time.c (503021B)
1 /* 2 * 3 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 4 * 5 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 6 * 7 * File: time.c 8 * 9 * Remarks: Broadcom StrataSwitch Time BroadSync API 10 * 11 * Functions: 12 * Private Interface functions 13 * 14 * _bcm_esw_time_hw_clear 15 * _bcm_esw_time_deinit 16 * _bcm_esw_time_reinit 17 * _bcm_esw_time_interface_id_validate 18 * _bcm_esw_time_interface_input_validate 19 * _bcm_esw_time_interface_allocate_id 20 * _bcm_esw_time_interface_heartbeat_install 21 * _bcm_esw_time_interface_accuracy_time2hw 22 * _bcm_esw_time_interface_drift_install 23 * _bcm_esw_time_interface_offset_install 24 * _bcm_esw_time_interface_ref_clock_install 25 * _bcm_esw_time_interface_install 26 * _bcm_esw_time_interface_dual_bs_install 27 * _bcm_time_interface_free 28 * _bcm_esw_time_accuracy_parse 29 * _bcm_esw_time_input_parse 30 * _bcm_esw_time_capture_counter_read 31 * _bcm_esw_time_capture_get 32 * _bcm_esw_time_interface_offset_get 33 * _bcm_esw_time_interface_drift_get 34 * _bcm_esw_time_interface_ref_clock_get 35 * _bcm_esw_time_interface_accuracy_get 36 * _bcm_esw_time_interface_get 37 * _bcm_esw_time_interface_dual_bs_get 38 * _bcm_esw_time_hw_interrupt_dflt 39 * _bcm_esw_time_hw_interrupt 40 * _bcm_esw_time_trigger_to_timestamp_mode 41 * _bcm_esw_time_trigger_from_timestamp_mode 42 * _bcm_esw_time_bs_init 43 * _bcm_time_sw_dump 44 * 45 * Public Interface functions 46 * 47 * bcm_esw_time_init 48 * bcm_esw_time_deinit 49 * bcm_esw_time_interface_add 50 * bcm_esw_time_interface_delete 51 * bcm_esw_time_interface_get 52 * bcm_esw_time_interface_delete_all 53 * bcm_esw_time_interface_traverse 54 * bcm_esw_time_capture_get 55 * bcm_esw_time_heartbeat_enable_set 56 * bcm_esw_time_heartbeat_enable_get 57 * bcm_esw_time_trigger_enable_set 58 * bcm_esw_time_trigger_enable_get 59 * bcm_esw_time_heartbeat_register 60 * bcm_esw_time_heartbeat_unregister 61 */ 62 63 #include <shared/util.h> 64 #include <shared/bsl.h> 65 #include <bcm/time.h> 66 #include <bcm/error.h> 67 68 #include <soc/defs.h> 69 #include <soc/mem.h> 70 #include <soc/iproc.h> 71 #include <soc/drv.h> 72 #include <soc/cmicm.h> 73 74 #include <bcm/port.h> 75 76 #include <bcm_int/common/time.h> 77 #include <bcm_int/common/time-mbox.h> 78 #include <bcm_int/common/mbox.h> 79 80 #include <bcm_int/esw/mbcm.h> 81 #include <bcm_int/esw_dispatch.h> 82 #include <bcm_int/common/ptp.h> 83 #ifdef BCM_CMICX_SUPPORT 84 #include <soc/intr_cmicx.h> 85 #endif 86 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 87 #include <soc/trident2.h> 88 #endif /* BCM_TRIDENT2PLUS_SUPPORT */ 89 #if defined(BCM_GREYHOUND2_SUPPORT) 90 #include <soc/phy/phyctrl.h> 91 #endif /* BCM_GREYHOUND2_SUPPORT */ 92 #ifdef PORTMOD_SUPPORT 93 #include <soc/esw/portctrl.h> 94 #include <soc/portmod/portmod.h> 95 #include <soc/portmod/portmod_internal.h> 96 #endif 97 #ifdef BCM_WARM_BOOT_SUPPORT 98 #include <soc/scache.h> 99 #endif 100 #include <bcm_int/esw/switch.h> 101 102 #ifdef BCM_ESMC_EXTDPLL_SUPPORT 103 #include <bcm_int/common/esmc.h> 104 #endif /* BCM_ESMC_EXTDPLL_SUPPORT */ 105 106 #define BROAD_SYNC_TIME_CAPTURE_TIMEOUT (10) /* useconds */ 107 #define BROAD_SYNC_OUTPUT_TOGGLE_TIME_DELAY (3) /* seconds */ 108 109 #define SYNT_TIME_SECONDS(unit, id) \ 110 TIME_INTERFACE_CONFIG(unit, id).time_capture.syntonous.seconds 111 #define SYNT_TIME_NANOSECONDS(unit, id) \ 112 TIME_INTERFACE_CONFIG(unit, id).time_capture.syntonous.nanoseconds 113 114 #define HX5_PORT_BLOCK_FIRST_PORT(port) \ 115 SOC_INFO(unit).port_l2p_mapping[port] <= 48 ? \ 116 (1 + ((SOC_INFO(unit).port_l2p_mapping[port] - 1) & ~0xF)) :\ 117 (1 + ((SOC_INFO(unit).port_l2p_mapping[port] - 1) & ~0x3)); 118 119 #if defined(BCM_HITLESS_RESET_SUPPORT) 120 #define HITLESS_REG(cmicd_reg_write) \ 121 do { \ 122 /* Double-writes per CMICD-110 WAR. */ \ 123 cmicd_reg_write; \ 124 cmicd_reg_write; \ 125 } while (0) 126 127 #else 128 #define HITLESS_REG(cmicd_reg_write) \ 129 do { \ 130 cmicd_reg_write; \ 131 } while (0) 132 133 #endif /* defined(BCM_HITLESS_RESET_SUPPORT) */ 134 135 #if (defined(BCM_TIME_V3_SUPPORT) || \ 136 defined(BCM_KATANA2_SUPPORT) || defined(BCM_HELIX4_SUPPORT) || \ 137 defined(BCM_HURRICANE2_SUPPORT) || defined(BCM_GREYHOUND_SUPPORT) || \ 138 defined(BCM_SABER2_SUPPORT) || defined(BCM_TOMAHAWK_SUPPORT) || \ 139 defined(BCM_HURRICANE3_SUPPORT) || defined(BCM_MONTEREY_SUPPORT)) 140 #define BCM_TIME_V3_OR_IPROC_MANAGED_BROADSYNC (1) 141 #endif 142 143 #define SOC_HAS_TIME_V3_OR_IPROC_MANAGED_BROADSYNC(unit) \ 144 ((soc_feature(unit, soc_feature_time_v3)) || \ 145 (SOC_IS_KATANA2(unit)) || (SOC_IS_HELIX4(unit)) || \ 146 (SOC_IS_HURRICANE2(unit)) || (SOC_IS_GREYHOUND(unit)) || \ 147 (SOC_IS_SABER2(unit)) || (SOC_IS_TOMAHAWKX(unit)) || \ 148 (SOC_IS_HURRICANE3(unit)) || (SOC_IS_GREYHOUND2(unit)) || (SOC_IS_MONTEREY(unit))) 149 150 #if (defined(BCM_TIME_V3_OR_IPROC_MANAGED_BROADSYNC) || \ 151 defined(BCM_KATANA_SUPPORT) || \ 152 defined(BCM_TRIUMPH3_SUPPORT) || \ 153 defined(BCM_TRIDENT2_SUPPORT)) 154 #define BCM_TIME_MANAGED_BROADSYNC (1) 155 #endif 156 157 #define SOC_HAS_MANAGED_BROADSYNC(unit) \ 158 (SOC_HAS_TIME_V3_OR_IPROC_MANAGED_BROADSYNC(unit) || \ 159 SOC_IS_KATANA(unit) || \ 160 SOC_IS_TRIUMPH3(unit) || \ 161 SOC_IS_TD2_TT2(unit)) 162 163 #ifdef BCM_WARM_BOOT_SUPPORT 164 #define BCM_WB_VERSION_1_0 SOC_SCACHE_VERSION(1,0) 165 #define BCM_WB_DEFAULT_VERSION BCM_WB_VERSION_1_0 166 #endif /* BCM_WARM_BOOT_SUPPORT */ 167 168 /****************************************************************************/ 169 /* LOCAL VARIABLES DECLARATION */ 170 /****************************************************************************/ 171 /* 8 TSC (TSC0~6, TSCF0) */ 172 static const int gh2_tsc_phy_port[] = {58, 62, 66, 70, 74, 78, 82, 86}; 173 174 static _bcm_time_config_p _bcm_time_config[BCM_MAX_NUM_UNITS] = {NULL}; 175 176 static bcm_time_spec_t _bcm_time_accuracy_arr[TIME_ACCURACY_CLK_MAX] = { 177 {0, COMPILER_64_INIT(0,0), 25}, /* HW value = 32, accuracy up tp 25 nanosec */ 178 {0, COMPILER_64_INIT(0,0), 100}, /* HW value = 33, accuracy up to 100 nanosec */ 179 {0, COMPILER_64_INIT(0,0), 250}, /* HW value = 34, accuracy up to 250 nanosec */ 180 {0, COMPILER_64_INIT(0,0), 1000}, /* HW value = 35, accuracy up to 1 microsec */ 181 {0, COMPILER_64_INIT(0,0), 2500}, /* HW value = 36, accuracy up to 2.5 microsec */ 182 {0, COMPILER_64_INIT(0,0), 10000}, /* HW value = 37, accuracy up to 10 microsec */ 183 {0, COMPILER_64_INIT(0,0), 25000}, /* HW value = 38, accuracy up to 25 microsec */ 184 {0, COMPILER_64_INIT(0,0), 100000}, /* HW value = 39, accuracy up to 100 microsec */ 185 {0, COMPILER_64_INIT(0,0), 250000}, /* HW value = 40, accuracy up to 250 microsec */ 186 {0, COMPILER_64_INIT(0,0), 1000000}, /* HW value = 41, accuracy up to 1 milisec */ 187 {0, COMPILER_64_INIT(0,0), 2500000}, /* HW value = 42, accuracy up to 2.5 milisec */ 188 {0, COMPILER_64_INIT(0,0), 10000000}, /* HW value = 43, accuracy up to 10 milisec */ 189 {0, COMPILER_64_INIT(0,0), 25000000}, /* HW value = 44, accuracy up to 25 milisec */ 190 {0, COMPILER_64_INIT(0,0), 100000000}, /* HW value = 45, accuracy up to 100 milisec */ 191 {0, COMPILER_64_INIT(0,0), 250000000}, /* HW value = 46, accuracy up to 250 milisec */ 192 {0, COMPILER_64_INIT(0,1), 0}, /* HW value = 47, accuracy up to 1 sec */ 193 {0, COMPILER_64_INIT(0,10), 0}, /* HW value = 48, accuracy up to 10 sec */ 194 /* HW value = 49, accuracy greater than 10 sec */ 195 {0, COMPILER_64_INIT(0,TIME_ACCURACY_INFINITE), TIME_ACCURACY_INFINITE}, 196 /* HW value = 254 accuracy unknown */ 197 {0, COMPILER_64_INIT(0,TIME_ACCURACY_UNKNOWN), TIME_ACCURACY_UNKNOWN} 198 }; 199 200 #if defined(BCM_MONTEREY_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT) 201 STATIC 202 soc_reg_t _bcm_time_gpio_regs[TS_GPIO_COUNT] = { NS_TIMESYNC_GPIO_0_CTRLr, 203 NS_TIMESYNC_GPIO_1_CTRLr, 204 NS_TIMESYNC_GPIO_2_CTRLr, 205 NS_TIMESYNC_GPIO_3_CTRLr, 206 NS_TIMESYNC_GPIO_4_CTRLr, 207 NS_TIMESYNC_GPIO_5_CTRLr }; 208 209 STATIC 210 soc_reg_t _bcm_time_bs_pll_regs[2] = { NS_BROADSYNC0_CLK_EVENT_CTRLr, 211 NS_BROADSYNC1_CLK_EVENT_CTRLr }; 212 STATIC 213 soc_reg_t __bcm_time_mapper_port_enable_regs[4] = { NS_TIMESYNC_MAPPER_PORT_ENABLE_0r, 214 NS_TIMESYNC_MAPPER_PORT_ENABLE_1r, 215 NS_TIMESYNC_MAPPER_PORT_ENABLE_2r, 216 NS_TIMESYNC_MAPPER_PORT_ENABLE_3r 217 }; 218 219 STATIC 220 soc_reg_t _bcm_time_mapper_port_enable[32] = { PORT0_TS_ENABLEf, PORT1_TS_ENABLEf, 221 PORT2_TS_ENABLEf, PORT3_TS_ENABLEf, 222 PORT4_TS_ENABLEf, PORT5_TS_ENABLEf, 223 PORT6_TS_ENABLEf, PORT7_TS_ENABLEf, 224 225 PORT8_TS_ENABLEf, PORT9_TS_ENABLEf, 226 PORT10_TS_ENABLEf, PORT11_TS_ENABLEf, 227 PORT12_TS_ENABLEf, PORT13_TS_ENABLEf, 228 PORT14_TS_ENABLEf, PORT15_TS_ENABLEf, 229 230 PORT16_TS_ENABLEf, PORT17_TS_ENABLEf, 231 PORT18_TS_ENABLEf, PORT19_TS_ENABLEf, 232 PORT20_TS_ENABLEf, PORT21_TS_ENABLEf, 233 PORT22_TS_ENABLEf, PORT23_TS_ENABLEf, 234 235 PORT24_TS_ENABLEf, PORT25_TS_ENABLEf, 236 PORT26_TS_ENABLEf, PORT27_TS_ENABLEf, 237 PORT28_TS_ENABLEf, PORT29_TS_ENABLEf, 238 PORT30_TS_ENABLEf, PORT31_TS_ENABLEf 239 }; 240 241 242 STATIC 243 uint8 _bcm_time_capture_event_state[BCM_TIME_CAPTURE_MAX_EVENT_ID]; 244 STATIC uint8 tsfifo_flag = 0; 245 #endif 246 247 /****************************************************************************/ 248 /* Internal functions implementation */ 249 /****************************************************************************/ 250 STATIC int 251 _bcm_esw_time_capture_get (int unit, bcm_time_if_t id, bcm_time_capture_t *time, uint32 flags); 252 STATIC int 253 _bcm_esw_time_interface_offset_get(int unit, bcm_time_if_t id, bcm_time_spec_t *offset); 254 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || \ 255 defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_HELIX4_SUPPORT) || \ 256 defined(BCM_HURRICANE2_SUPPORT) || defined(BCM_GREYHOUND_SUPPORT) || \ 257 defined(BCM_SABER2_SUPPORT) || defined(BCM_TOMAHAWK_SUPPORT) 258 STATIC int 259 _bcm_esw_time_bs_init(int unit, bcm_time_interface_t *intf); 260 STATIC int 261 _bcm_esw_time_hw_clear(int unit, bcm_time_if_t intf_id); 262 STATIC int 263 _bcm_esw_time_hitless_reset(int unit, bcm_time_if_t intf_id); 264 #endif 265 266 #if defined(INCLUDE_GDPLL) 267 extern void gdpll_intr(int unit, uint32 int_status, uint32 int_enable); 268 #endif 269 270 STATIC int 271 _bcm_esw_time_synce_clock_source_squelch_set(int unit, bcm_time_synce_clock_src_type_t clk_src, 272 int squelch); 273 STATIC int 274 _bcm_esw_time_synce_clock_source_squelch_get(int unit, bcm_time_synce_clock_src_type_t clk_src, 275 int *squelch); 276 277 STATIC int 278 _bcm_esw_time_synce_clock_source_frequency_set(int unit, bcm_time_synce_clock_source_config_t *clk_src_config, 279 int frequency); 280 STATIC int 281 _bcm_esw_time_synce_clock_source_frequency_get(int unit, bcm_time_synce_clock_source_config_t *clk_src_config, 282 int *frequency); 283 284 /* 285 * Function: 286 * _bcm_esw_time_hw_clear 287 * Purpose: 288 * Internal routine used to clear all HW registers and table to default values 289 * Parameters: 290 * unit - (IN) BCM device number. 291 * intf_id - (IN) Time interface identifier 292 * Returns: 293 * BCM_E_XXX 294 */ 295 STATIC int 296 _bcm_esw_time_hw_clear(int unit, bcm_time_if_t intf_id) 297 { 298 uint32 regval; 299 #if defined(BCM_TIME_V3_OR_IPROC_MANAGED_BROADSYNC) 300 /*****************************************************************************/ 301 /* Perform KATANA2, HELIX4, HURRICANE2, GREYHOUND, SABER2 IPROC HW configuration */ 302 /*****************************************************************************/ 303 304 /* Reset Config register */ 305 if (SOC_HAS_TIME_V3_OR_IPROC_MANAGED_BROADSYNC(unit)) { 306 if (!soc_feature(unit, soc_feature_time_v3_no_bs)) { 307 if(SOC_IS_TOMAHAWK3(unit) || SOC_IS_MONTEREY(unit)) { 308 READ_NS_BS0_BS_CONFIGr(unit, ®val); 309 soc_reg_field_set(unit, NS_BS0_BS_CONFIGr, ®val, MODEf, TIME_MODE_OUTPUT); 310 soc_reg_field_set(unit, NS_BS0_BS_CONFIGr, ®val, BS_TC_OUTPUT_ENABLEf, 0); 311 soc_reg_field_set(unit, NS_BS0_BS_CONFIGr, ®val, BS_CLK_OUTPUT_ENABLEf, 0); 312 HITLESS_REG(WRITE_NS_BS0_BS_CONFIGr(unit, regval)); 313 314 READ_NS_BS1_BS_CONFIGr(unit, ®val); 315 soc_reg_field_set(unit, NS_BS1_BS_CONFIGr, ®val, MODEf, TIME_MODE_OUTPUT); 316 soc_reg_field_set(unit, NS_BS1_BS_CONFIGr, ®val, BS_TC_OUTPUT_ENABLEf, 0); 317 soc_reg_field_set(unit, NS_BS1_BS_CONFIGr, ®val, BS_CLK_OUTPUT_ENABLEf, 0); 318 HITLESS_REG(WRITE_NS_BS1_BS_CONFIGr(unit, regval)); 319 320 READ_NS_BS0_BS_OUTPUT_TIME_0r(unit, ®val); 321 soc_reg_field_set(unit, NS_BS0_BS_OUTPUT_TIME_0r, ®val, ACCURACYf, 0); 322 soc_reg_field_set(unit, NS_BS0_BS_OUTPUT_TIME_0r, ®val, LOCKf, 0); 323 soc_reg_field_set(unit, NS_BS0_BS_OUTPUT_TIME_0r, ®val, EPOCHf, 0); 324 WRITE_NS_BS0_BS_OUTPUT_TIME_0r(unit, regval); 325 326 READ_NS_BS1_BS_OUTPUT_TIME_0r(unit, ®val); 327 soc_reg_field_set(unit, NS_BS1_BS_OUTPUT_TIME_0r, ®val, ACCURACYf, 0); 328 soc_reg_field_set(unit, NS_BS1_BS_OUTPUT_TIME_0r, ®val, LOCKf, 0); 329 soc_reg_field_set(unit, NS_BS1_BS_OUTPUT_TIME_0r, ®val, EPOCHf, 0); 330 WRITE_NS_BS1_BS_OUTPUT_TIME_0r(unit, regval); 331 332 /* Reset Clock Control */ 333 READ_NS_BS0_BS_CLK_CTRLr(unit, ®val); 334 soc_reg_field_set(unit, NS_BS0_BS_CLK_CTRLr, ®val, ENABLEf, 0); 335 HITLESS_REG(WRITE_NS_BS0_BS_CLK_CTRLr(unit, regval)); 336 337 READ_NS_BS1_BS_CLK_CTRLr(unit, ®val); 338 soc_reg_field_set(unit, NS_BS1_BS_CLK_CTRLr, ®val, ENABLEf, 0); 339 HITLESS_REG(WRITE_NS_BS1_BS_CLK_CTRLr(unit, regval)); 340 341 /* Reset HeartBeat */ 342 READ_NS_BS0_BS_HEARTBEAT_CTRLr(unit, ®val); 343 soc_reg_field_set(unit, NS_BS0_BS_HEARTBEAT_CTRLr, ®val, ENABLEf, 0); 344 HITLESS_REG(WRITE_NS_BS0_BS_HEARTBEAT_CTRLr(unit, regval)); 345 346 READ_NS_BS1_BS_HEARTBEAT_CTRLr(unit, ®val); 347 soc_reg_field_set(unit, NS_BS1_BS_HEARTBEAT_CTRLr, ®val, ENABLEf, 0); 348 HITLESS_REG(WRITE_NS_BS1_BS_HEARTBEAT_CTRLr(unit, regval)); 349 } else { 350 351 READ_CMIC_BS0_CONFIGr(unit, ®val); 352 soc_reg_field_set(unit, CMIC_BS0_CONFIGr, ®val, MODEf, TIME_MODE_OUTPUT); 353 soc_reg_field_set(unit, CMIC_BS0_CONFIGr, ®val, BS_TC_OUTPUT_ENABLEf, 0); 354 soc_reg_field_set(unit, CMIC_BS0_CONFIGr, ®val, BS_CLK_OUTPUT_ENABLEf, 0); 355 HITLESS_REG(WRITE_CMIC_BS0_CONFIGr(unit, regval)); 356 357 READ_CMIC_BS1_CONFIGr(unit, ®val); 358 soc_reg_field_set(unit, CMIC_BS1_CONFIGr, ®val, MODEf, TIME_MODE_OUTPUT); 359 soc_reg_field_set(unit, CMIC_BS1_CONFIGr, ®val, BS_TC_OUTPUT_ENABLEf, 0); 360 soc_reg_field_set(unit, CMIC_BS1_CONFIGr, ®val, BS_CLK_OUTPUT_ENABLEf, 0); 361 HITLESS_REG(WRITE_CMIC_BS1_CONFIGr(unit, regval)); 362 363 READ_CMIC_BS0_OUTPUT_TIME_0r(unit, ®val); 364 soc_reg_field_set(unit, CMIC_BS0_OUTPUT_TIME_0r, ®val, ACCURACYf, 0); 365 soc_reg_field_set(unit, CMIC_BS0_OUTPUT_TIME_0r, ®val, LOCKf, 0); 366 soc_reg_field_set(unit, CMIC_BS0_OUTPUT_TIME_0r, ®val, EPOCHf, 0); 367 WRITE_CMIC_BS0_OUTPUT_TIME_0r(unit, regval); 368 369 READ_CMIC_BS1_OUTPUT_TIME_0r(unit, ®val); 370 soc_reg_field_set(unit, CMIC_BS1_OUTPUT_TIME_0r, ®val, ACCURACYf, 0); 371 soc_reg_field_set(unit, CMIC_BS1_OUTPUT_TIME_0r, ®val, LOCKf, 0); 372 soc_reg_field_set(unit, CMIC_BS1_OUTPUT_TIME_0r, ®val, EPOCHf, 0); 373 WRITE_CMIC_BS1_OUTPUT_TIME_0r(unit, regval); 374 375 /* Reset Clock Control */ 376 READ_CMIC_BS0_CLK_CTRLr(unit, ®val); 377 soc_reg_field_set(unit, CMIC_BS0_CLK_CTRLr, ®val, ENABLEf, 0); 378 HITLESS_REG(WRITE_CMIC_BS0_CLK_CTRLr(unit, regval)); 379 380 READ_CMIC_BS1_CLK_CTRLr(unit, ®val); 381 soc_reg_field_set(unit, CMIC_BS1_CLK_CTRLr, ®val, ENABLEf, 0); 382 HITLESS_REG(WRITE_CMIC_BS1_CLK_CTRLr(unit, regval)); 383 384 /* Reset HeartBeat */ 385 READ_CMIC_BS0_HEARTBEAT_CTRLr(unit, ®val); 386 soc_reg_field_set(unit, CMIC_BS0_HEARTBEAT_CTRLr, ®val, ENABLEf, 0); 387 HITLESS_REG(WRITE_CMIC_BS0_HEARTBEAT_CTRLr(unit, regval)); 388 389 READ_CMIC_BS1_HEARTBEAT_CTRLr(unit, ®val); 390 soc_reg_field_set(unit, CMIC_BS1_HEARTBEAT_CTRLr, ®val, ENABLEf, 0); 391 HITLESS_REG(WRITE_CMIC_BS1_HEARTBEAT_CTRLr(unit, regval)); 392 } 393 } 394 395 /* Reset Capture */ 396 if (SOC_IS_TOMAHAWK3(unit) || SOC_IS_MONTEREY(unit)){ 397 READ_NS_ROE_TS_INT_ENABLEr(unit, ®val); 398 soc_reg_field_set(unit, NS_ROE_TS_INT_ENABLEr, ®val, INTENf, 0); 399 WRITE_NS_ROE_TS_INT_ENABLEr(unit, regval); 400 401 READ_NS_MISC_CLK_EVENT_CTRLr(unit, ®val); 402 soc_reg_field_set(unit, NS_MISC_CLK_EVENT_CTRLr, ®val, TIME_CAPTURE_ENABLEf, 0); 403 soc_reg_field_set(unit, NS_MISC_CLK_EVENT_CTRLr, ®val, BS0_TX_HB_STATUS_ENABLEf, 0); 404 soc_reg_field_set(unit, NS_MISC_CLK_EVENT_CTRLr, ®val, BS0_RX_HB_STATUS_ENABLEf, 0); 405 soc_reg_field_set(unit, NS_MISC_CLK_EVENT_CTRLr, ®val, BS1_TX_HB_STATUS_ENABLEf, 0); 406 soc_reg_field_set(unit, NS_MISC_CLK_EVENT_CTRLr, ®val, BS1_RX_HB_STATUS_ENABLEf, 0); 407 WRITE_NS_MISC_CLK_EVENT_CTRLr(unit, regval); 408 409 READ_NS_MISC_CLK_EVENT_CTRLr(unit, ®val); 410 soc_reg_field_set(unit, NS_MISC_CLK_EVENT_CTRLr, ®val, ENABLEf, TIME_CAPTURE_MODE_DISABLE); 411 WRITE_NS_MISC_CLK_EVENT_CTRLr(unit, regval); 412 } else 413 #ifdef BCM_TRIDENT3_SUPPORT 414 if (soc_feature(unit, soc_feature_timesync_block_iproc)) { 415 soc_iproc_getreg(unit, soc_reg_addr(unit, 416 CMIC_TIMESYNC_INTERRUPT_ENABLEr, REG_PORT_ANY, 0), ®val); 417 soc_reg_field_set(unit, CMIC_TIMESYNC_INTERRUPT_ENABLEr, ®val, 418 INT_ENABLEf, 0); 419 soc_iproc_setreg(unit, soc_reg_addr(unit, 420 CMIC_TIMESYNC_INTERRUPT_ENABLEr, REG_PORT_ANY, 0), regval); 421 422 soc_iproc_getreg(unit, soc_reg_addr(unit, 423 CMIC_TIMESYNC_TIME_CAPTURE_CONTROLr, REG_PORT_ANY, 0), ®val); 424 soc_reg_field_set(unit, CMIC_TIMESYNC_TIME_CAPTURE_CONTROLr, 425 ®val, TIME_CAPTURE_ENABLEf, 0); 426 soc_reg_field_set(unit, CMIC_TIMESYNC_TIME_CAPTURE_CONTROLr, 427 ®val, BSYNC0_TX_HB_STATUS_ENABLEf, 0); 428 soc_reg_field_set(unit, CMIC_TIMESYNC_TIME_CAPTURE_CONTROLr, 429 ®val, BSYNC0_RX_HB_STATUS_ENABLEf, 0); 430 soc_reg_field_set(unit, CMIC_TIMESYNC_TIME_CAPTURE_CONTROLr, 431 ®val, BSYNC1_TX_HB_STATUS_ENABLEf, 0); 432 soc_reg_field_set(unit, CMIC_TIMESYNC_TIME_CAPTURE_CONTROLr, 433 ®val, BSYNC1_RX_HB_STATUS_ENABLEf, 0); 434 soc_iproc_setreg(unit, soc_reg_addr(unit, 435 CMIC_TIMESYNC_TIME_CAPTURE_CONTROLr, REG_PORT_ANY, 0), regval); 436 437 soc_iproc_getreg(unit, soc_reg_addr(unit, 438 CMIC_TIMESYNC_TIME_CAPTURE_MODEr, REG_PORT_ANY, 0), ®val); 439 soc_reg_field_set(unit, CMIC_TIMESYNC_TIME_CAPTURE_MODEr, ®val, 440 TIME_CAPTURE_MODEf, TIME_CAPTURE_MODE_DISABLE); 441 soc_iproc_setreg(unit, soc_reg_addr(unit, 442 CMIC_TIMESYNC_TIME_CAPTURE_MODEr, REG_PORT_ANY, 0), regval); 443 444 } else 445 #endif 446 { 447 READ_CMIC_TIMESYNC_INTERRUPT_ENABLEr(unit, ®val); 448 soc_reg_field_set(unit, CMIC_TIMESYNC_INTERRUPT_ENABLEr, ®val, INT_ENABLEf, 0); 449 WRITE_CMIC_TIMESYNC_INTERRUPT_ENABLEr(unit, regval); 450 451 READ_CMIC_TIMESYNC_TIME_CAPTURE_CONTROLr(unit, ®val); 452 soc_reg_field_set(unit, CMIC_TIMESYNC_TIME_CAPTURE_CONTROLr, ®val, TIME_CAPTURE_ENABLEf, 0); 453 soc_reg_field_set(unit, CMIC_TIMESYNC_TIME_CAPTURE_CONTROLr, ®val, BSYNC0_TX_HB_STATUS_ENABLEf, 0); 454 soc_reg_field_set(unit, CMIC_TIMESYNC_TIME_CAPTURE_CONTROLr, ®val, BSYNC0_RX_HB_STATUS_ENABLEf, 0); 455 soc_reg_field_set(unit, CMIC_TIMESYNC_TIME_CAPTURE_CONTROLr, ®val, BSYNC1_TX_HB_STATUS_ENABLEf, 0); 456 soc_reg_field_set(unit, CMIC_TIMESYNC_TIME_CAPTURE_CONTROLr, ®val, BSYNC1_RX_HB_STATUS_ENABLEf, 0); 457 WRITE_CMIC_TIMESYNC_TIME_CAPTURE_CONTROLr(unit, regval); 458 459 READ_CMIC_TIMESYNC_TIME_CAPTURE_MODEr(unit, ®val); 460 soc_reg_field_set(unit, CMIC_TIMESYNC_TIME_CAPTURE_MODEr, ®val, TIME_CAPTURE_MODEf, TIME_CAPTURE_MODE_DISABLE); 461 WRITE_CMIC_TIMESYNC_TIME_CAPTURE_MODEr(unit, regval); 462 } 463 464 } else 465 #endif /* BCM_TIME_V3_OR_IPROC_MANAGED_BROADSYNC */ 466 467 /*****************************************************************************/ 468 /* Non-KATANA2, HELIX4, HURRICANE2, GREYHOUND HW configuration */ 469 /*****************************************************************************/ 470 { 471 if (SOC_REG_IS_VALID(unit, CMIC_BS_DRIFT_RATEr)) { 472 /* Reset Drift Rate */ 473 READ_CMIC_BS_DRIFT_RATEr(unit, ®val); 474 soc_reg_field_set(unit, CMIC_BS_DRIFT_RATEr, ®val, SIGNf, 0); 475 soc_reg_field_set(unit, CMIC_BS_DRIFT_RATEr, ®val, FRAC_NSf, 0); 476 WRITE_CMIC_BS_DRIFT_RATEr(unit, regval); 477 } 478 479 if (SOC_REG_IS_VALID(unit, CMIC_BS_OFFSET_ADJUST_0r)) { 480 /* Reset Offset Adjust */ 481 READ_CMIC_BS_OFFSET_ADJUST_0r(unit, ®val); 482 soc_reg_field_set(unit, CMIC_BS_OFFSET_ADJUST_0r, ®val, SECONDf, 0); 483 WRITE_CMIC_BS_OFFSET_ADJUST_0r(unit, regval); 484 READ_CMIC_BS_OFFSET_ADJUST_1r(unit, ®val); 485 soc_reg_field_set(unit, CMIC_BS_OFFSET_ADJUST_1r, ®val, SIGN_BITf, 0); 486 soc_reg_field_set(unit, CMIC_BS_OFFSET_ADJUST_1r, ®val, NSf, 0); 487 WRITE_CMIC_BS_OFFSET_ADJUST_1r(unit, regval); 488 } 489 490 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_TRIDENT2_SUPPORT) 491 if (SOC_IS_KATANA(unit) || SOC_IS_TRIUMPH3(unit) || SOC_IS_TD2_TT2(unit)) { 492 READ_CMIC_BS_CONFIGr(unit, ®val); 493 /* Configure Broadsync in output mode */ 494 soc_reg_field_set(unit, CMIC_BS_CONFIGr, ®val, MODEf, TIME_MODE_OUTPUT); 495 soc_reg_field_set(unit, CMIC_BS_CONFIGr, ®val, BS_TC_OUTPUT_ENABLEf, 0); 496 soc_reg_field_set(unit, CMIC_BS_CONFIGr, ®val, BS_CLK_OUTPUT_ENABLEf, 0); 497 WRITE_CMIC_BS_CONFIGr(unit, regval); 498 499 READ_CMIC_BS_OUTPUT_TIME_0r(unit, ®val); 500 soc_reg_field_set(unit, CMIC_BS_OUTPUT_TIME_0r, ®val, ACCURACYf, 0); 501 soc_reg_field_set(unit, CMIC_BS_OUTPUT_TIME_0r, ®val, LOCKf, 0); 502 soc_reg_field_set(unit, CMIC_BS_OUTPUT_TIME_0r, ®val, EPOCHf, 0); 503 WRITE_CMIC_BS_OUTPUT_TIME_0r(unit, regval); 504 } else 505 #endif /* defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_TRIDENT2_SUPPORT) */ 506 { 507 READ_CMIC_BS_CONFIGr(unit, ®val); 508 soc_reg_field_set(unit, CMIC_BS_CONFIGr, ®val, ENABLEf, 0); 509 soc_reg_field_set(unit, CMIC_BS_CONFIGr, ®val, MODEf, TIME_MODE_OUTPUT); 510 soc_reg_field_set(unit, CMIC_BS_CONFIGr, ®val, TIME_CODE_ENABLEf, 0); 511 soc_reg_field_set(unit, CMIC_BS_CONFIGr, ®val, LOCKf, 0); 512 soc_reg_field_set(unit, CMIC_BS_CONFIGr, ®val, ACCURACYf, TIME_ACCURACY_UNKNOWN_HW_VAL); 513 soc_reg_field_set(unit, CMIC_BS_CONFIGr, ®val, EPOCHf, 0); 514 WRITE_CMIC_BS_CONFIGr(unit, regval); 515 } 516 517 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_TRIDENT2_SUPPORT) 518 if (SOC_IS_KATANA(unit) || SOC_IS_TRIUMPH3(unit) || SOC_IS_TD2_TT2(unit)) { 519 READ_CMIC_BS_CLK_CTRLr(unit, ®val); 520 soc_reg_field_set(unit, CMIC_BS_CLK_CTRLr, ®val, ENABLEf, 0); 521 WRITE_CMIC_BS_CLK_CTRLr(unit, regval); 522 } else 523 #endif /* defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_TRIDENT2_SUPPORT) */ 524 { 525 READ_CMIC_BS_CLK_CTRL_0r(unit, ®val); 526 soc_reg_field_set(unit, CMIC_BS_CLK_CTRL_0r, ®val, ENABLEf, 0); 527 soc_reg_field_set(unit, CMIC_BS_CLK_CTRL_0r, ®val, NSf, 0); 528 WRITE_CMIC_BS_CLK_CTRL_0r(unit, regval); 529 } 530 531 if (SOC_REG_IS_VALID(unit, CMIC_BS_CLK_CTRL_1r)) { 532 READ_CMIC_BS_CLK_CTRL_1r(unit, ®val); 533 soc_reg_field_set(unit, CMIC_BS_CLK_CTRL_1r, ®val, FRAC_NSf, 0); 534 WRITE_CMIC_BS_CLK_CTRL_1r(unit, regval); 535 } 536 537 /* Reset Clock Toggle */ 538 if (SOC_REG_IS_VALID(unit, CMIC_BS_CLK_TOGGLE_TIME_0r)) { 539 READ_CMIC_BS_CLK_TOGGLE_TIME_0r(unit, ®val); 540 soc_reg_field_set(unit, CMIC_BS_CLK_TOGGLE_TIME_0r, ®val, SECf, 0); 541 WRITE_CMIC_BS_CLK_TOGGLE_TIME_0r(unit, regval); 542 } 543 544 if (SOC_REG_IS_VALID(unit, CMIC_BS_CLK_TOGGLE_TIME_1r)) { 545 READ_CMIC_BS_CLK_TOGGLE_TIME_1r(unit, ®val); 546 soc_reg_field_set(unit, CMIC_BS_CLK_TOGGLE_TIME_1r, ®val, NSf, 0); 547 WRITE_CMIC_BS_CLK_TOGGLE_TIME_1r(unit, regval); 548 } 549 550 if (SOC_REG_IS_VALID(unit, CMIC_BS_CLK_TOGGLE_TIME_2r)) { 551 READ_CMIC_BS_CLK_TOGGLE_TIME_2r(unit, ®val); 552 soc_reg_field_set(unit, CMIC_BS_CLK_TOGGLE_TIME_2r, ®val, FRAC_NSf, 0); 553 WRITE_CMIC_BS_CLK_TOGGLE_TIME_2r(unit, regval); 554 } 555 556 READ_CMIC_BS_HEARTBEAT_CTRLr(unit, ®val); 557 soc_reg_field_set(unit, CMIC_BS_HEARTBEAT_CTRLr, ®val, ENABLEf, 0); 558 if (!(SOC_IS_KATANAX(unit) || SOC_IS_TRIUMPH3(unit) || 559 SOC_IS_TD2_TT2(unit))) { 560 soc_reg_field_set(unit, CMIC_BS_HEARTBEAT_CTRLr, ®val, THRESHOLDf, 0); 561 } 562 WRITE_CMIC_BS_HEARTBEAT_CTRLr(unit, regval); 563 564 #if (defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_TRIDENT2_SUPPORT)) 565 if (SOC_IS_KATANA(unit) || SOC_IS_TRIUMPH3(unit) || SOC_IS_TD2_TT2(unit)) { 566 READ_CMIC_TS_TIME_CAPTURE_CTRLr(unit, ®val); 567 soc_reg_field_set(unit, CMIC_TS_TIME_CAPTURE_CTRLr, ®val, 568 INT_ENABLEf, 0); 569 if(SOC_IS_TD2P_TT2P(unit)) { 570 soc_reg_field_set(unit, CMIC_TS_TIME_CAPTURE_CTRLr, ®val, 571 TIME_CAPTURE_MODEf, TIME_CAPTURE_MODE_DISABLE); 572 } else { 573 /* Configure the HW to capture time on every heartbeat */ 574 soc_reg_field_set(unit, CMIC_TS_TIME_CAPTURE_CTRLr, ®val, 575 TIME_CAPTURE_MODEf, TIME_CAPTURE_MODE_HEARTBEAT); 576 } 577 WRITE_CMIC_TS_TIME_CAPTURE_CTRLr(unit, regval); 578 } else 579 #endif /* defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_TRIDENT2_SUPPORT) */ 580 { 581 READ_CMIC_BS_CAPTURE_CTRLr(unit, ®val); 582 soc_reg_field_set(unit, CMIC_BS_CAPTURE_CTRLr, ®val, INT_ENf, 0); 583 soc_reg_field_set(unit, CMIC_BS_CAPTURE_CTRLr, ®val, TIME_CAPTURE_MODEf, 584 TIME_CAPTURE_MODE_DISABLE); 585 WRITE_CMIC_BS_CAPTURE_CTRLr(unit, regval); 586 } 587 } 588 589 return BCM_E_NONE; 590 } 591 592 /* 593 * Function: 594 * _bcm_esw_time_hitless_reset 595 * Purpose: 596 * Internal routine used to check if hitless reset is present in 597 * the hardware, and is active. 598 * If present, hitless reset preserves the BroadSync operation 599 * and registers through a chip reset. 600 * Parameters: 601 * unit - (IN) BCM device number. 602 * intf_id - (IN) Time interface identifier 603 * Returns: 604 * BCM_E_NONE if hitless reset is active 605 * BCM_E_UNAVAIL if it is not. 606 */ 607 int _bcm_esw_time_hitless_reset(int unit, bcm_time_if_t intf_id) 608 { 609 #if defined(BCM_HITLESS_RESET_SUPPORT) 610 if (SOC_IS_KATANA2(unit) || SOC_IS_SABER2(unit)) { 611 /* if BS0 has its output enabled, this indicates that 612 * drv.c determined that hitless reset was in effect 613 * and so did not clear the output. 614 */ 615 uint32 regval; 616 READ_CMIC_BS0_CONFIGr(unit, ®val); 617 if (soc_reg_field_get(unit, CMIC_BS0_CONFIGr, 618 regval, BS_CLK_OUTPUT_ENABLEf) != 0) { 619 return BCM_E_NONE; 620 } 621 } 622 #endif 623 624 return BCM_E_UNAVAIL; 625 } 626 627 /* 628 * Function: 629 * _bcm_esw_time_deinit 630 * Purpose: 631 * Internal routine used to free time software module 632 * control structures. 633 * Parameters: 634 * unit - (IN) BCM device number. 635 * time_cfg_pptr - (IN) Pointer to pointer to time config structure. 636 * Returns: 637 * BCM_E_XXX 638 */ 639 STATIC int 640 _bcm_esw_time_deinit(int unit, _bcm_time_config_p *time_cfg_pptr) 641 { 642 int idx; 643 _bcm_time_config_p time_cfg_ptr; 644 soc_control_t *soc = SOC_CONTROL(unit); 645 646 /* Sanity checks. */ 647 if (NULL == time_cfg_pptr) { 648 return (BCM_E_PARAM); 649 } 650 651 time_cfg_ptr = *time_cfg_pptr; 652 /* If time config was not allocated we are done. */ 653 if (NULL == time_cfg_ptr) { 654 return (BCM_E_NONE); 655 } 656 657 /* Free time interface */ 658 if (NULL != time_cfg_ptr->intf_arr) { 659 for (idx = 0; idx < NUM_TIME_INTERFACE(unit); idx++) { 660 if (NULL != time_cfg_ptr->intf_arr[idx].user_cb) { 661 sal_free(time_cfg_ptr->intf_arr[idx].user_cb); 662 } 663 } 664 sal_free(time_cfg_ptr->intf_arr); 665 } 666 667 /* Destroy protection mutex. */ 668 if (NULL != time_cfg_ptr->mutex) { 669 sal_mutex_destroy(time_cfg_ptr->mutex); 670 } 671 672 /* If any registered function - deregister */ 673 soc->time_call_ref_count = 0; 674 soc->soc_time_callout = NULL; 675 676 /* Free module configuration structue. */ 677 sal_free(time_cfg_ptr); 678 *time_cfg_pptr = NULL; 679 return (BCM_E_NONE); 680 } 681 682 #ifdef BCM_WARM_BOOT_SUPPORT 683 684 /* 685 * Function: 686 * _bcm_time_scache_alloc 687 * Purpose: 688 * Internal routine used to allocate scache memory for TIME module 689 * Parameters: 690 * unit - (IN) BCM device number. 691 * Returns: 692 * BCM_E_XXX 693 */ 694 STATIC int 695 _bcm_time_scache_alloc(int unit) 696 { 697 soc_scache_handle_t scache_handle; 698 uint8 *time_scache; 699 int alloc_size = 0; 700 701 alloc_size = ( sizeof(bcm_time_interface_t) + sizeof(int)) * NUM_TIME_INTERFACE(unit); 702 703 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_TIME, 0); 704 BCM_IF_ERROR_RETURN(_bcm_esw_scache_ptr_get(unit, scache_handle, 1, 705 alloc_size, &time_scache, BCM_WB_DEFAULT_VERSION, NULL)); 706 return BCM_E_NONE; 707 } 708 709 /* 710 * Function: 711 * _bcm_time_scache_sync 712 * Purpose: 713 * Routine to sync the time module to scache 714 * Parameters: 715 * unit - (IN) BCM device number. 716 * Returns: 717 * BCM_E_XXX 718 */ 719 int 720 _bcm_time_scache_sync(int unit) 721 { 722 int rv = BCM_E_NONE; 723 soc_scache_handle_t scache_handle; 724 uint8 *time_scache; 725 int alloc_size = 0; 726 int idx; 727 728 alloc_size = ( sizeof(bcm_time_interface_t) + sizeof(int)) * NUM_TIME_INTERFACE(unit); 729 730 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_TIME, 0); 731 rv = _bcm_esw_scache_ptr_get(unit, 732 scache_handle, 733 0, 734 alloc_size, 735 &time_scache, 736 BCM_WB_DEFAULT_VERSION, 737 NULL 738 ); 739 740 if (!BCM_FAILURE(rv)) { 741 for (idx = 0; idx < NUM_TIME_INTERFACE(unit); idx++) { 742 sal_memcpy(time_scache, (TIME_INTERFACE(unit, idx)), 743 sizeof(bcm_time_interface_t)); 744 time_scache += sizeof(bcm_time_interface_t); 745 sal_memcpy(time_scache, &TIME_INTERFACE_CONFIG_REF_COUNT(unit, idx), 746 sizeof(int)); 747 time_scache += sizeof(int); 748 } 749 } 750 751 return rv; 752 } 753 754 /* 755 * Function: 756 * _bcm_esw_time_reinit 757 * Purpose: 758 * Internal routine used to reinitialize time module based on HW settings 759 * during Warm boot 760 * Parameters: 761 * unit - (IN) BCM device number. 762 * intf_id - (IN) Time interface identifier 763 * Returns: 764 * BCM_E_XXX 765 */ 766 STATIC int 767 _bcm_esw_time_reinit(int unit, bcm_time_if_t intf_id) 768 { 769 soc_scache_handle_t scache_handle; 770 uint16 recovered_ver = 0; 771 uint8 *time_scache; 772 int rv = BCM_E_NONE; 773 774 if(SOC_WARM_BOOT(unit)) { 775 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_TIME, 0); 776 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, 0, 0, 777 &time_scache, BCM_WB_DEFAULT_VERSION, 778 &recovered_ver); 779 if (!BCM_FAILURE(rv)) { 780 time_scache += sizeof(bcm_time_interface_t) * intf_id; 781 sal_memcpy((TIME_INTERFACE(unit, intf_id)), time_scache, 782 sizeof(bcm_time_interface_t)); 783 time_scache += sizeof(bcm_time_interface_t); 784 time_scache += sizeof(int) * intf_id; 785 sal_memcpy(&(TIME_INTERFACE_CONFIG_REF_COUNT(unit, intf_id)), time_scache, 786 sizeof(int)); 787 time_scache += sizeof(int); 788 789 #if defined(BCM_TIME_MANAGED_BROADSYNC) 790 if ((TIME_INTERFACE(unit, intf_id))->flags & BCM_TIME_SYNC_STAMPER) { 791 /* Broadsync was initialised. Hence reattach */ 792 (void)_bcm_mbox_comm_init(unit, MOS_MSG_MBOX_APPL_BS); 793 } 794 #endif 795 } 796 } 797 798 if (!soc_feature(unit, soc_feature_time_v3_no_bs)) { 799 int hb_enable; 800 801 /* Read the status of heartbeat interrupt */ 802 BCM_IF_ERROR_RETURN( 803 bcm_esw_time_heartbeat_enable_get(unit, intf_id, &hb_enable)); 804 805 /* If heartbeat was enabled, restore handling functionality */ 806 if (hb_enable) { 807 BCM_IF_ERROR_RETURN( 808 bcm_esw_time_heartbeat_enable_set(unit, intf_id, hb_enable)); 809 } 810 } 811 812 return (BCM_E_NONE); 813 } 814 #endif /* BCM_WARM_BOOT_SUPPORT */ 815 816 /* 817 * Function: 818 * _bcm_esw_time_interface_id_validate 819 * Purpose: 820 * Internal routine used to validate interface identifier 821 * Parameters: 822 * unit - (IN) BCM device number. 823 * id - (IN) Interface id to validate 824 * Returns: 825 * BCM_E_XXX 826 */ 827 STATIC int 828 _bcm_esw_time_interface_id_validate(int unit, bcm_time_if_t id) 829 { 830 if (0 == TIME_INIT(unit)) { 831 return (BCM_E_INIT); 832 } 833 if (id < 0 || id > TIME_INTERFACE_ID_MAX(unit)) { 834 return (BCM_E_PARAM); 835 } 836 if (NULL == TIME_INTERFACE(unit, id)) { 837 return (BCM_E_NOT_FOUND); 838 } 839 840 return (BCM_E_NONE); 841 } 842 843 844 /* 845 * Function: 846 * _bcm_esw_time_interface_input_validate 847 * Purpose: 848 * Internal routine used to validate interface input 849 * Parameters: 850 * unit - (IN) BCM device number. 851 * intf - (IN) Interface to validate 852 * Returns: 853 * BCM_E_XXX 854 */ 855 STATIC int 856 _bcm_esw_time_interface_input_validate(int unit, bcm_time_interface_t *intf) 857 { 858 /* Sanity checks. */ 859 if (NULL == intf) { 860 return (BCM_E_PARAM); 861 } 862 if (intf->flags & BCM_TIME_WITH_ID) { 863 if (intf->id < 0 || intf->id > TIME_INTERFACE_ID_MAX(unit) ) { 864 return (BCM_E_PARAM); 865 } 866 } 867 868 #if defined(BCM_TIME_V3_OR_IPROC_MANAGED_BROADSYNC) 869 if (soc_feature(unit, soc_feature_time_v3_no_bs) && 870 (intf->flags & BCM_TIME_SYNC_STAMPER)) { 871 return BCM_E_UNAVAIL; 872 } 873 #endif 874 875 #if defined(BCM_TIME_MANAGED_BROADSYNC) 876 if (intf->flags & BCM_TIME_SYNC_STAMPER) { 877 if (intf->heartbeat_hz <= 0 || intf->bitclock_hz <= 0) { 878 return (BCM_E_PARAM); 879 } 880 } 881 #endif 882 883 #if defined(BCM_TIME_V3_SUPPORT) 884 if (soc_feature(unit, soc_feature_time_v3) && 885 !SOC_IS_HURRICANE2(unit) && !SOC_IS_GREYHOUND(unit) && 886 !SOC_IS_TOMAHAWKX(unit) && !SOC_IS_HURRICANE3(unit) && 887 !SOC_IS_GREYHOUND2(unit) && !SOC_IS_TRIDENT3(unit) && 888 !(intf->flags & BCM_TIME_SYNC_STAMPER)) { 889 /* 890 * Drift/Offset is not supported by 3rd generation time architecture 891 * NB: Hurricane2 (56150) enables v3 time feature. BroadSync FW APIs 892 * support time offset functionality. !SOC_IS_HURRICANE2() logic 893 * added to conditional to enable phase offset on HR2 similar to 894 * other platforms. 895 */ 896 if (intf->flags & BCM_TIME_DRIFT || intf->flags & BCM_TIME_OFFSET) { 897 return BCM_E_UNAVAIL; 898 } 899 } 900 #endif /* defined(BCM_TIME_V3_SUPPORT) */ 901 902 if (intf->flags & BCM_TIME_DRIFT) { 903 if (intf->drift.nanoseconds > TIME_DRIFT_MAX) { 904 return BCM_E_PARAM; 905 } 906 } 907 908 if (intf->flags & BCM_TIME_OFFSET) { 909 if (intf->offset.nanoseconds > TIME_NANOSEC_MAX) { 910 return BCM_E_PARAM; 911 } 912 } 913 914 return (BCM_E_NONE); 915 } 916 917 918 /* 919 * Function: 920 * _bcm_esw_time_interface_allocate_id 921 * Purpose: 922 * Internal routine used to allocate time interface id 923 * Parameters: 924 * unit - (IN) BCM device number. 925 * id - (OUT) Interface id to be allocated 926 * Returns: 927 * BCM_E_XXX 928 */ 929 STATIC int 930 _bcm_esw_time_interface_allocate_id(int unit, bcm_time_if_t *id) 931 { 932 int idx; /* Time interfaces iteration index.*/ 933 _bcm_time_interface_config_p intf; /* Time interface description. */ 934 935 /* Input parameters check. */ 936 if (NULL == id) { 937 return (BCM_E_PARAM); 938 } 939 940 /* Find & allocate time interface. */ 941 for (idx = 0; idx < TIME_CONFIG(unit)->intf_count; idx++) { 942 intf = TIME_CONFIG(unit)->intf_arr + idx; 943 if (intf->ref_count) { /* In use interface */ 944 continue; 945 } 946 intf->ref_count++; /* If founf mark interface as in use */ 947 *id = intf->time_interface.id; /* Assign ID */ 948 return (BCM_E_NONE); 949 } 950 951 /* No available interfaces */ 952 return (BCM_E_FULL); 953 } 954 955 956 957 /* 958 * Function: 959 * _bcm_esw_time_interface_heartbeat_install 960 * Purpose: 961 * Internal routine used to install interface heartbeat rate into a HW 962 * Parameters: 963 * unit - (IN) BCM device number. 964 * id - (IN) Interface id to be installed into a HW 965 * Returns: 966 * BCM_E_XXX 967 */ 968 STATIC int 969 _bcm_esw_time_interface_heartbeat_install(int unit, bcm_time_if_t id) 970 { 971 uint32 regval; 972 uint32 hb_hz; /* Number of heartbeats in HZ */ 973 uint32 ns_hp; /* Number of nanosec per half clock cycle*/ 974 uint32 threshold; /* Heartbeat threshold */ 975 976 bcm_time_interface_t *intf; 977 978 intf = TIME_INTERFACE(unit, id); 979 980 hb_hz = (intf->heartbeat_hz > TIME_HEARTBEAT_HZ_MAX) ? 981 TIME_HEARTBEAT_HZ_MAX : intf->heartbeat_hz; 982 hb_hz = (intf->heartbeat_hz < TIME_HEARTBEAT_HZ_MIN) ? 983 TIME_HEARTBEAT_HZ_MIN : hb_hz; 984 985 threshold = intf->bitclock_hz / hb_hz; 986 987 if (threshold < 100) { 988 /* BitClock must have a frequency at least 100 times that of heartbeat. */ 989 return BCM_E_PARAM; 990 } 991 992 /* Calculate nanoseconds per half period of cycle */ 993 ns_hp = TIME_HEARTBEAT_NS_HZ / intf->bitclock_hz / 2; 994 995 /* program the half period of broadsync clock */ 996 #if defined(BCM_TIME_V3_OR_IPROC_MANAGED_BROADSYNC) 997 if (SOC_HAS_TIME_V3_OR_IPROC_MANAGED_BROADSYNC(unit)) { 998 uint32 interval = 0; 999 if (SOC_IS_TOMAHAWK3(unit) || SOC_IS_MONTEREY(unit)) { 1000 READ_NS_BS0_BS_CLK_CTRLr(unit, ®val); 1001 soc_reg_field_set(unit, NS_BS0_BS_CLK_CTRLr, ®val, ENABLEf, 1); 1002 WRITE_NS_BS0_BS_CLK_CTRLr(unit, regval); 1003 1004 READ_NS_BS1_BS_CLK_CTRLr(unit, ®val); 1005 soc_reg_field_set(unit, NS_BS1_BS_CLK_CTRLr, ®val, ENABLEf, 1); 1006 WRITE_NS_BS1_BS_CLK_CTRLr(unit, regval); 1007 1008 /* enable Heartbeat generation */ 1009 READ_NS_BS0_BS_HEARTBEAT_CTRLr(unit, ®val); 1010 soc_reg_field_set(unit, NS_BS0_BS_HEARTBEAT_CTRLr, ®val, ENABLEf, 1); 1011 WRITE_NS_BS0_BS_HEARTBEAT_CTRLr(unit, regval); 1012 1013 /* Install heartbeat up and down interval */ 1014 READ_NS_BS0_BS_HEARTBEAT_UP_DURATIONr(unit, ®val); 1015 soc_reg_field_set(unit, NS_BS0_BS_HEARTBEAT_UP_DURATIONr, ®val, UP_DURATIONf, threshold); 1016 WRITE_NS_BS0_BS_HEARTBEAT_UP_DURATIONr(unit, regval); 1017 1018 READ_NS_BS0_BS_HEARTBEAT_DOWN_DURATIONr(unit, ®val); 1019 soc_reg_field_set(unit, NS_BS0_BS_HEARTBEAT_DOWN_DURATIONr, ®val, DOWN_DURATIONf, threshold); 1020 WRITE_NS_BS0_BS_HEARTBEAT_DOWN_DURATIONr(unit, regval); 1021 1022 READ_NS_BS1_BS_HEARTBEAT_UP_DURATIONr(unit, ®val); 1023 soc_reg_field_set(unit, NS_BS1_BS_HEARTBEAT_UP_DURATIONr, ®val, UP_DURATIONf, threshold); 1024 WRITE_NS_BS1_BS_HEARTBEAT_UP_DURATIONr(unit, regval); 1025 1026 READ_NS_BS1_BS_HEARTBEAT_DOWN_DURATIONr(unit, ®val); 1027 soc_reg_field_set(unit, NS_BS1_BS_HEARTBEAT_DOWN_DURATIONr, ®val, DOWN_DURATIONf, threshold); 1028 WRITE_NS_BS1_BS_HEARTBEAT_DOWN_DURATIONr(unit, regval); 1029 1030 /* Enable heartbeat output */ 1031 READ_NS_BS0_BS_HEARTBEAT_CTRLr(unit, ®val); 1032 soc_reg_field_set(unit, NS_BS0_BS_HEARTBEAT_CTRLr, ®val, ENABLEf, 1); 1033 WRITE_NS_BS0_BS_HEARTBEAT_CTRLr(unit, regval); 1034 1035 READ_NS_BS1_BS_HEARTBEAT_CTRLr(unit, ®val); 1036 soc_reg_field_set(unit, NS_BS1_BS_HEARTBEAT_CTRLr, ®val, ENABLEf, 1); 1037 WRITE_NS_BS1_BS_HEARTBEAT_CTRLr(unit, regval); 1038 1039 /* 1040 * KT-1381 : 1041 * TS_GPIO_LOW = (UP_EVENT_INTERVAL x 4) + 1 TS_REF_CLK_time_period 1042 * TS_GPIO_HIGH = (DOWN_EVENT_INTERVAL x 4) + 1 TS_REF_CLK_time_period 1043 */ 1044 threshold = (threshold * 4) + SOC_TIMESYNC_PLL_CLOCK_NS(unit); 1045 1046 /* Install GPIO timesync trigger interval */ 1047 /* GPIO_EVENT_1 */ 1048 READ_NS_TIMESYNC_GPIO_0_DOWN_EVENT_CTRLr(unit, &interval); 1049 soc_reg_field_set(unit, NS_TIMESYNC_GPIO_0_DOWN_EVENT_CTRLr, &interval, INTERVAL_LENGTHf, threshold); 1050 WRITE_NS_TIMESYNC_GPIO_0_DOWN_EVENT_CTRLr(unit, interval); 1051 1052 READ_NS_TIMESYNC_GPIO_0_UP_EVENT_CTRLr(unit, &interval); 1053 soc_reg_field_set(unit, NS_TIMESYNC_GPIO_0_UP_EVENT_CTRLr, &interval, INTERVAL_LENGTHf, threshold); 1054 WRITE_NS_TIMESYNC_GPIO_0_UP_EVENT_CTRLr(unit, interval); 1055 1056 /* GPIO_EVENT_2 */ 1057 READ_NS_TIMESYNC_GPIO_1_DOWN_EVENT_CTRLr(unit, &interval); 1058 soc_reg_field_set(unit, NS_TIMESYNC_GPIO_1_DOWN_EVENT_CTRLr, &interval, INTERVAL_LENGTHf, threshold); 1059 WRITE_NS_TIMESYNC_GPIO_1_DOWN_EVENT_CTRLr(unit, interval); 1060 1061 READ_NS_TIMESYNC_GPIO_1_UP_EVENT_CTRLr(unit, &interval); 1062 soc_reg_field_set(unit, NS_TIMESYNC_GPIO_1_UP_EVENT_CTRLr, &interval, INTERVAL_LENGTHf, threshold); 1063 WRITE_NS_TIMESYNC_GPIO_1_UP_EVENT_CTRLr(unit, interval); 1064 1065 /* GPIO_EVENT_3 */ 1066 READ_NS_TIMESYNC_GPIO_2_DOWN_EVENT_CTRLr(unit, &interval); 1067 soc_reg_field_set(unit, NS_TIMESYNC_GPIO_2_DOWN_EVENT_CTRLr, &interval, INTERVAL_LENGTHf, threshold); 1068 WRITE_NS_TIMESYNC_GPIO_2_DOWN_EVENT_CTRLr(unit, interval); 1069 1070 READ_NS_TIMESYNC_GPIO_2_UP_EVENT_CTRLr(unit, &interval); 1071 soc_reg_field_set(unit, NS_TIMESYNC_GPIO_2_UP_EVENT_CTRLr, &interval, INTERVAL_LENGTHf, threshold); 1072 WRITE_NS_TIMESYNC_GPIO_2_UP_EVENT_CTRLr(unit, interval); 1073 1074 /* GPIO_EVENT_4 */ 1075 READ_NS_TIMESYNC_GPIO_3_DOWN_EVENT_CTRLr(unit, &interval); 1076 soc_reg_field_set(unit, NS_TIMESYNC_GPIO_3_DOWN_EVENT_CTRLr, &interval, INTERVAL_LENGTHf, threshold); 1077 WRITE_NS_TIMESYNC_GPIO_3_DOWN_EVENT_CTRLr(unit, interval); 1078 1079 READ_NS_TIMESYNC_GPIO_3_UP_EVENT_CTRLr(unit, &interval); 1080 soc_reg_field_set(unit, NS_TIMESYNC_GPIO_3_UP_EVENT_CTRLr, &interval, INTERVAL_LENGTHf, threshold); 1081 WRITE_NS_TIMESYNC_GPIO_3_UP_EVENT_CTRLr(unit, interval); 1082 1083 /* GPIO_EVENT_5 */ 1084 READ_NS_TIMESYNC_GPIO_4_DOWN_EVENT_CTRLr(unit, &interval); 1085 soc_reg_field_set(unit, NS_TIMESYNC_GPIO_4_DOWN_EVENT_CTRLr, &interval, INTERVAL_LENGTHf, threshold); 1086 WRITE_NS_TIMESYNC_GPIO_4_DOWN_EVENT_CTRLr(unit, interval); 1087 1088 READ_NS_TIMESYNC_GPIO_4_UP_EVENT_CTRLr(unit, &interval); 1089 soc_reg_field_set(unit, NS_TIMESYNC_GPIO_4_UP_EVENT_CTRLr, &interval, INTERVAL_LENGTHf, threshold); 1090 WRITE_NS_TIMESYNC_GPIO_4_UP_EVENT_CTRLr(unit, interval); 1091 1092 /* GPIO_EVENT_6 */ 1093 READ_NS_TIMESYNC_GPIO_5_DOWN_EVENT_CTRLr(unit, &interval); 1094 soc_reg_field_set(unit, NS_TIMESYNC_GPIO_5_DOWN_EVENT_CTRLr, &interval, INTERVAL_LENGTHf, threshold); 1095 WRITE_NS_TIMESYNC_GPIO_5_DOWN_EVENT_CTRLr(unit, interval); 1096 1097 READ_NS_TIMESYNC_GPIO_5_UP_EVENT_CTRLr(unit, &interval); 1098 soc_reg_field_set(unit, NS_TIMESYNC_GPIO_5_UP_EVENT_CTRLr, &interval, INTERVAL_LENGTHf, threshold); 1099 WRITE_NS_TIMESYNC_GPIO_5_UP_EVENT_CTRLr(unit, interval); 1100 1101 } else { 1102 READ_CMIC_BS0_CLK_CTRLr(unit, ®val); 1103 soc_reg_field_set(unit, CMIC_BS0_CLK_CTRLr, ®val, ENABLEf, 1); 1104 WRITE_CMIC_BS0_CLK_CTRLr(unit, regval); 1105 1106 READ_CMIC_BS1_CLK_CTRLr(unit, ®val); 1107 soc_reg_field_set(unit, CMIC_BS1_CLK_CTRLr, ®val, ENABLEf, 1); 1108 WRITE_CMIC_BS1_CLK_CTRLr(unit, regval); 1109 1110 /* enable Heartbeat generation */ 1111 READ_CMIC_BS0_HEARTBEAT_CTRLr(unit, ®val); 1112 soc_reg_field_set(unit, CMIC_BS0_HEARTBEAT_CTRLr, ®val, ENABLEf, 1); 1113 WRITE_CMIC_BS0_HEARTBEAT_CTRLr(unit, regval); 1114 1115 /* Install heartbeat up and down interval */ 1116 READ_CMIC_BS0_HEARTBEAT_UP_DURATIONr(unit, ®val); 1117 soc_reg_field_set(unit, CMIC_BS0_HEARTBEAT_UP_DURATIONr, ®val, UP_DURATIONf, threshold); 1118 WRITE_CMIC_BS0_HEARTBEAT_UP_DURATIONr(unit, regval); 1119 1120 READ_CMIC_BS0_HEARTBEAT_DOWN_DURATIONr(unit, ®val); 1121 soc_reg_field_set(unit, CMIC_BS0_HEARTBEAT_DOWN_DURATIONr, ®val, DOWN_DURATIONf, threshold); 1122 WRITE_CMIC_BS0_HEARTBEAT_DOWN_DURATIONr(unit, regval); 1123 1124 READ_CMIC_BS1_HEARTBEAT_UP_DURATIONr(unit, ®val); 1125 soc_reg_field_set(unit, CMIC_BS1_HEARTBEAT_UP_DURATIONr, ®val, UP_DURATIONf, threshold); 1126 WRITE_CMIC_BS1_HEARTBEAT_UP_DURATIONr(unit, regval); 1127 1128 READ_CMIC_BS1_HEARTBEAT_DOWN_DURATIONr(unit, ®val); 1129 soc_reg_field_set(unit, CMIC_BS1_HEARTBEAT_DOWN_DURATIONr, ®val, DOWN_DURATIONf, threshold); 1130 WRITE_CMIC_BS1_HEARTBEAT_DOWN_DURATIONr(unit, regval); 1131 1132 /* Enable heartbeat output */ 1133 READ_CMIC_BS0_HEARTBEAT_CTRLr(unit, ®val); 1134 soc_reg_field_set(unit, CMIC_BS0_HEARTBEAT_CTRLr, ®val, ENABLEf, 1); 1135 WRITE_CMIC_BS0_HEARTBEAT_CTRLr(unit, regval); 1136 1137 READ_CMIC_BS1_HEARTBEAT_CTRLr(unit, ®val); 1138 soc_reg_field_set(unit, CMIC_BS1_HEARTBEAT_CTRLr, ®val, ENABLEf, 1); 1139 WRITE_CMIC_BS1_HEARTBEAT_CTRLr(unit, regval); 1140 1141 /* 1142 * KT-1381 : 1143 * TS_GPIO_LOW = (UP_EVENT_INTERVAL x 4) + 1 TS_REF_CLK_time_period 1144 * TS_GPIO_HIGH = (DOWN_EVENT_INTERVAL x 4) + 1 TS_REF_CLK_time_period 1145 */ 1146 threshold = (threshold * 4) + SOC_TIMESYNC_PLL_CLOCK_NS(unit); 1147 1148 /* Install GPIO timesync trigger interval */ 1149 /* GPIO_EVENT_1 */ 1150 READ_CMIC_TIMESYNC_GPIO_0_DOWN_EVENT_CTRLr(unit, &interval); 1151 soc_reg_field_set(unit, CMIC_TIMESYNC_GPIO_0_DOWN_EVENT_CTRLr, &interval, INTERVAL_LENGTHf, threshold); 1152 WRITE_CMIC_TIMESYNC_GPIO_0_DOWN_EVENT_CTRLr(unit, interval); 1153 1154 READ_CMIC_TIMESYNC_GPIO_0_UP_EVENT_CTRLr(unit, &interval); 1155 soc_reg_field_set(unit, CMIC_TIMESYNC_GPIO_0_UP_EVENT_CTRLr, &interval, INTERVAL_LENGTHf, threshold); 1156 WRITE_CMIC_TIMESYNC_GPIO_0_UP_EVENT_CTRLr(unit, interval); 1157 1158 /* GPIO_EVENT_2 */ 1159 READ_CMIC_TIMESYNC_GPIO_1_DOWN_EVENT_CTRLr(unit, &interval); 1160 soc_reg_field_set(unit, CMIC_TIMESYNC_GPIO_1_DOWN_EVENT_CTRLr, &interval, INTERVAL_LENGTHf, threshold); 1161 WRITE_CMIC_TIMESYNC_GPIO_1_DOWN_EVENT_CTRLr(unit, interval); 1162 1163 READ_CMIC_TIMESYNC_GPIO_1_UP_EVENT_CTRLr(unit, &interval); 1164 soc_reg_field_set(unit, CMIC_TIMESYNC_GPIO_1_UP_EVENT_CTRLr, &interval, INTERVAL_LENGTHf, threshold); 1165 WRITE_CMIC_TIMESYNC_GPIO_1_UP_EVENT_CTRLr(unit, interval); 1166 1167 /* GPIO_EVENT_3 */ 1168 READ_CMIC_TIMESYNC_GPIO_2_DOWN_EVENT_CTRLr(unit, &interval); 1169 soc_reg_field_set(unit, CMIC_TIMESYNC_GPIO_2_DOWN_EVENT_CTRLr, &interval, INTERVAL_LENGTHf, threshold); 1170 WRITE_CMIC_TIMESYNC_GPIO_2_DOWN_EVENT_CTRLr(unit, interval); 1171 1172 READ_CMIC_TIMESYNC_GPIO_2_UP_EVENT_CTRLr(unit, &interval); 1173 soc_reg_field_set(unit, CMIC_TIMESYNC_GPIO_2_UP_EVENT_CTRLr, &interval, INTERVAL_LENGTHf, threshold); 1174 WRITE_CMIC_TIMESYNC_GPIO_2_UP_EVENT_CTRLr(unit, interval); 1175 1176 /* GPIO_EVENT_4 */ 1177 READ_CMIC_TIMESYNC_GPIO_3_DOWN_EVENT_CTRLr(unit, &interval); 1178 soc_reg_field_set(unit, CMIC_TIMESYNC_GPIO_3_DOWN_EVENT_CTRLr, &interval, INTERVAL_LENGTHf, threshold); 1179 WRITE_CMIC_TIMESYNC_GPIO_3_DOWN_EVENT_CTRLr(unit, interval); 1180 1181 READ_CMIC_TIMESYNC_GPIO_3_UP_EVENT_CTRLr(unit, &interval); 1182 soc_reg_field_set(unit, CMIC_TIMESYNC_GPIO_3_UP_EVENT_CTRLr, &interval, INTERVAL_LENGTHf, threshold); 1183 WRITE_CMIC_TIMESYNC_GPIO_3_UP_EVENT_CTRLr(unit, interval); 1184 1185 /* GPIO_EVENT_5 */ 1186 READ_CMIC_TIMESYNC_GPIO_4_DOWN_EVENT_CTRLr(unit, &interval); 1187 soc_reg_field_set(unit, CMIC_TIMESYNC_GPIO_4_DOWN_EVENT_CTRLr, &interval, INTERVAL_LENGTHf, threshold); 1188 WRITE_CMIC_TIMESYNC_GPIO_4_DOWN_EVENT_CTRLr(unit, interval); 1189 1190 READ_CMIC_TIMESYNC_GPIO_4_UP_EVENT_CTRLr(unit, &interval); 1191 soc_reg_field_set(unit, CMIC_TIMESYNC_GPIO_4_UP_EVENT_CTRLr, &interval, INTERVAL_LENGTHf, threshold); 1192 WRITE_CMIC_TIMESYNC_GPIO_4_UP_EVENT_CTRLr(unit, interval); 1193 } 1194 1195 } else 1196 #endif /* BCM_TIME_V3_OR_IPROC_MANAGED_BROADSYNC */ 1197 { 1198 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_TRIDENT2_SUPPORT) 1199 if (SOC_IS_KATANAX(unit) || SOC_IS_TRIUMPH3(unit) || 1200 SOC_IS_TD2_TT2(unit)) { 1201 1202 READ_CMIC_BS_CLK_CTRLr(unit, ®val); 1203 soc_reg_field_set(unit, CMIC_BS_CLK_CTRLr, ®val, ENABLEf, 1); 1204 WRITE_CMIC_BS_CLK_CTRLr(unit, regval); 1205 1206 READ_CMIC_BS_HEARTBEAT_CTRLr(unit, ®val); 1207 soc_reg_field_set(unit, CMIC_BS_HEARTBEAT_CTRLr, ®val, ENABLEf, 1); 1208 WRITE_CMIC_BS_HEARTBEAT_CTRLr(unit, regval); 1209 } else 1210 #endif /* defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_TRIDENT2_SUPPORT) */ 1211 { 1212 READ_CMIC_BS_CLK_CTRL_0r(unit, ®val); 1213 soc_reg_field_set(unit, CMIC_BS_CLK_CTRL_0r, ®val, ENABLEf, 1); 1214 soc_reg_field_set(unit, CMIC_BS_CLK_CTRL_0r, ®val, NSf, ns_hp); 1215 WRITE_CMIC_BS_CLK_CTRL_0r(unit, regval); 1216 1217 READ_CMIC_BS_HEARTBEAT_CTRLr(unit, ®val); 1218 soc_reg_field_set(unit, CMIC_BS_HEARTBEAT_CTRLr, ®val, ENABLEf, 1); 1219 soc_reg_field_set(unit, CMIC_BS_HEARTBEAT_CTRLr, ®val, 1220 THRESHOLDf, threshold); 1221 WRITE_CMIC_BS_HEARTBEAT_CTRLr(unit, regval); 1222 } 1223 1224 #if (defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_TRIDENT2_SUPPORT)) 1225 /* Install heartbeat and external trigger clock interval */ 1226 if (SOC_IS_KATANAX(unit) || SOC_IS_TRIUMPH3(unit) || 1227 SOC_IS_TD2_TT2(unit)) { 1228 uint32 interval = 0; 1229 1230 /* Install heartbeat up and down interval */ 1231 READ_CMIC_BS_HEARTBEAT_UP_DURATIONr(unit, &interval); 1232 soc_reg_field_set(unit, CMIC_BS_HEARTBEAT_UP_DURATIONr, 1233 &interval, UP_DURATIONf, threshold); 1234 WRITE_CMIC_BS_HEARTBEAT_UP_DURATIONr(unit, interval); 1235 1236 READ_CMIC_BS_HEARTBEAT_DOWN_DURATIONr(unit, &interval); 1237 soc_reg_field_set(unit, CMIC_BS_HEARTBEAT_DOWN_DURATIONr, 1238 &interval, DOWN_DURATIONf, threshold); 1239 WRITE_CMIC_BS_HEARTBEAT_DOWN_DURATIONr(unit, interval); 1240 1241 /* Install divisor for LCPLL trigger interval */ 1242 READ_CMIC_TS_LCPLL_CLK_COUNT_CTRLr(unit, &interval); 1243 soc_reg_field_set(unit, 1244 CMIC_TS_LCPLL_CLK_COUNT_CTRLr, 1245 &interval, DIVISORf, threshold); 1246 WRITE_CMIC_TS_LCPLL_CLK_COUNT_CTRLr(unit, interval); 1247 1248 /* Install divisor for Primary L1 trigger interval */ 1249 READ_CMIC_TS_L1_CLK_RECOVERED_CLK_COUNT_CTRLr(unit, &interval); 1250 soc_reg_field_set(unit, 1251 CMIC_TS_L1_CLK_RECOVERED_CLK_COUNT_CTRLr, 1252 &interval, DIVISORf, threshold); 1253 WRITE_CMIC_TS_L1_CLK_RECOVERED_CLK_COUNT_CTRLr(unit, interval); 1254 1255 /* Install divisor for backup L1 trigger interval */ 1256 READ_CMIC_TS_L1_CLK_RECOVERED_CLK_BKUP_COUNT_CTRLr(unit, &interval); 1257 soc_reg_field_set(unit, 1258 CMIC_TS_L1_CLK_RECOVERED_CLK_BKUP_COUNT_CTRLr, 1259 &interval, DIVISORf, threshold); 1260 WRITE_CMIC_TS_L1_CLK_RECOVERED_CLK_BKUP_COUNT_CTRLr(unit, interval); 1261 1262 /* 1263 * KT-1381 : 1264 * TS_GPIO_LOW = 1265 (UP_EVENT_INTERVAL x 4) + 1 TS_REF_CLK_time_period 1266 * TS_GPIO_HIGH = 1267 (DOWN_EVENT_INTERVAL x 4) + 1 TS_REF_CLK_time_period 1268 */ 1269 threshold = (threshold * 4) + SOC_TIMESYNC_PLL_CLOCK_NS(unit); 1270 1271 /* Install GPIO timesync trigger interval */ 1272 /* GPIO_EVENT_1 */ 1273 READ_CMIC_TS_GPIO_1_DOWN_EVENT_CTRLr(unit, &interval); 1274 soc_reg_field_set(unit, CMIC_TS_GPIO_1_DOWN_EVENT_CTRLr, &interval, 1275 INTERVAL_LENGTHf, threshold); 1276 WRITE_CMIC_TS_GPIO_1_DOWN_EVENT_CTRLr(unit, interval); 1277 READ_CMIC_TS_GPIO_1_UP_EVENT_CTRLr(unit, &interval); 1278 soc_reg_field_set(unit, CMIC_TS_GPIO_1_UP_EVENT_CTRLr, &interval, 1279 INTERVAL_LENGTHf, threshold); 1280 WRITE_CMIC_TS_GPIO_1_UP_EVENT_CTRLr(unit, interval); 1281 1282 /* GPIO_EVENT_2 */ 1283 READ_CMIC_TS_GPIO_2_DOWN_EVENT_CTRLr(unit, &interval); 1284 soc_reg_field_set(unit, CMIC_TS_GPIO_2_DOWN_EVENT_CTRLr, &interval, 1285 INTERVAL_LENGTHf, threshold); 1286 WRITE_CMIC_TS_GPIO_2_DOWN_EVENT_CTRLr(unit, interval); 1287 READ_CMIC_TS_GPIO_2_UP_EVENT_CTRLr(unit, &interval); 1288 soc_reg_field_set(unit, CMIC_TS_GPIO_2_UP_EVENT_CTRLr, &interval, 1289 INTERVAL_LENGTHf, threshold); 1290 WRITE_CMIC_TS_GPIO_2_UP_EVENT_CTRLr(unit, interval); 1291 1292 /* GPIO_EVENT_3 */ 1293 READ_CMIC_TS_GPIO_3_DOWN_EVENT_CTRLr(unit, &interval); 1294 soc_reg_field_set(unit, CMIC_TS_GPIO_3_DOWN_EVENT_CTRLr, &interval, 1295 INTERVAL_LENGTHf, threshold); 1296 WRITE_CMIC_TS_GPIO_3_DOWN_EVENT_CTRLr(unit, interval); 1297 READ_CMIC_TS_GPIO_3_UP_EVENT_CTRLr(unit, &interval); 1298 soc_reg_field_set(unit, CMIC_TS_GPIO_3_UP_EVENT_CTRLr, &interval, 1299 INTERVAL_LENGTHf, threshold); 1300 WRITE_CMIC_TS_GPIO_3_UP_EVENT_CTRLr(unit, interval); 1301 1302 /* GPIO_EVENT_4 */ 1303 READ_CMIC_TS_GPIO_4_DOWN_EVENT_CTRLr(unit, &interval); 1304 soc_reg_field_set(unit, CMIC_TS_GPIO_4_DOWN_EVENT_CTRLr, &interval, 1305 INTERVAL_LENGTHf, threshold); 1306 WRITE_CMIC_TS_GPIO_4_DOWN_EVENT_CTRLr(unit, interval); 1307 READ_CMIC_TS_GPIO_4_UP_EVENT_CTRLr(unit, &interval); 1308 soc_reg_field_set(unit, CMIC_TS_GPIO_4_UP_EVENT_CTRLr, &interval, 1309 INTERVAL_LENGTHf, threshold); 1310 WRITE_CMIC_TS_GPIO_4_UP_EVENT_CTRLr(unit, interval); 1311 1312 /* GPIO_EVENT_5 */ 1313 READ_CMIC_TS_GPIO_5_DOWN_EVENT_CTRLr(unit, &interval); 1314 soc_reg_field_set(unit, 1315 CMIC_TS_GPIO_5_DOWN_EVENT_CTRLr, 1316 &interval, INTERVAL_LENGTHf, threshold); 1317 WRITE_CMIC_TS_GPIO_5_DOWN_EVENT_CTRLr(unit, interval); 1318 READ_CMIC_TS_GPIO_5_UP_EVENT_CTRLr(unit, &interval); 1319 soc_reg_field_set(unit, 1320 CMIC_TS_GPIO_5_UP_EVENT_CTRLr, 1321 &interval, INTERVAL_LENGTHf, threshold); 1322 WRITE_CMIC_TS_GPIO_5_UP_EVENT_CTRLr(unit, interval); 1323 } 1324 #endif /* defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_TRIDENT2_SUPPORT) */ 1325 } 1326 1327 return (BCM_E_NONE); 1328 } 1329 1330 1331 /* 1332 * Function: 1333 * _bcm_esw_time_interface_accuracy_time2hw 1334 * Purpose: 1335 * Internal routine used to compute HW accuracy value from interface 1336 * Parameters: 1337 * unit - (IN) BCM device number. 1338 * id - (IN) Interface id 1339 * accuracy - (OUT) HW value to be programmed 1340 * Returns: 1341 * BCM_E_XXX 1342 */ 1343 STATIC int 1344 _bcm_esw_time_interface_accuracy_time2hw(int unit, bcm_time_if_t id, 1345 uint32 *accuracy) 1346 { 1347 int idx; /* accuracy itterator */ 1348 bcm_time_interface_t *intf; 1349 1350 if (NULL == accuracy) { 1351 return BCM_E_PARAM; 1352 } 1353 1354 intf = TIME_INTERFACE(unit, id); 1355 1356 /* Find the right accuracy */ 1357 for (idx = 0; idx < TIME_ACCURACY_CLK_MAX; idx++) { 1358 if (intf->accuracy.nanoseconds <= _bcm_time_accuracy_arr[idx].nanoseconds && 1359 COMPILER_64_LO(intf->accuracy.seconds) <= COMPILER_64_LO(_bcm_time_accuracy_arr[idx].seconds) ) { 1360 break; 1361 } 1362 } 1363 /* if no match - return error */ 1364 if (idx == TIME_ACCURACY_CLK_MAX) { 1365 return BCM_E_NOT_FOUND; 1366 } 1367 1368 /* Return the correct HW value */ 1369 1370 *accuracy = TIME_ACCURACY_SW_IDX_2_HW(idx); 1371 1372 return (BCM_E_NONE); 1373 } 1374 1375 /* 1376 * Function: 1377 * _bcm_esw_time_interface_drift_install 1378 * Purpose: 1379 * Internal routine used to install interface drift into a HW 1380 * Parameters: 1381 * unit - (IN) BCM device number. 1382 * id - (IN) Interface id to be installed into a HW 1383 * Returns: 1384 * BCM_E_XXX 1385 */ 1386 STATIC int 1387 _bcm_esw_time_interface_drift_install(int unit, bcm_time_if_t id) 1388 { 1389 uint32 regval, hw_val, sign; 1390 bcm_time_interface_t *intf; 1391 1392 #if defined(BCM_TIME_V3_SUPPORT) 1393 /* Not supported in 3rd generation time arch */ 1394 if (soc_feature(unit, soc_feature_time_v3)) { 1395 return BCM_E_UNAVAIL; 1396 } 1397 #endif /* defined(BCM_TIME_V3_SUPPORT) */ 1398 1399 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_TRIDENT2_SUPPORT) 1400 /* Katana does not support clock drift */ 1401 if (SOC_IS_KATANAX(unit) || SOC_IS_TRIUMPH3(unit) || 1402 SOC_IS_TD2_TT2(unit)) { 1403 return BCM_E_UNAVAIL; 1404 } 1405 #endif /* defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_TRIDENT2_SUPPORT) */ 1406 1407 intf = TIME_INTERFACE(unit, id); 1408 sign = intf->drift.isnegative; 1409 1410 /* Requested drift value should not be more then 1/8 of drift denominator */ 1411 if (intf->drift.nanoseconds <= TIME_DRIFT_MAX) { 1412 hw_val = 8 * intf->drift.nanoseconds; 1413 } else { 1414 return (BCM_E_PARAM); 1415 } 1416 READ_CMIC_BS_DRIFT_RATEr(unit, ®val); 1417 soc_reg_field_set(unit, CMIC_BS_DRIFT_RATEr, ®val, SIGNf, sign); 1418 soc_reg_field_set(unit, CMIC_BS_DRIFT_RATEr, ®val, FRAC_NSf, hw_val); 1419 WRITE_CMIC_BS_DRIFT_RATEr(unit, regval); 1420 1421 return (BCM_E_NONE); 1422 } 1423 1424 /* 1425 * Function: 1426 * _bcm_esw_time_interface_offset_install 1427 * Purpose: 1428 * Internal routine used to install interface offset into a HW 1429 * Parameters: 1430 * unit - (IN) BCM device number. 1431 * id - (IN) Interface id to be installed into a HW 1432 * Returns: 1433 * BCM_E_XXX 1434 */ 1435 STATIC int 1436 _bcm_esw_time_interface_offset_install(int unit, bcm_time_if_t id) 1437 { 1438 uint32 regval, sign, hw_val; 1439 bcm_time_interface_t *intf; 1440 1441 #if defined(BCM_TIME_V3_SUPPORT) 1442 /* Not supported in 3rd generation time arch */ 1443 if (soc_feature(unit, soc_feature_time_v3)) { 1444 return BCM_E_UNAVAIL; 1445 } 1446 #endif /* defined(BCM_TIME_V3_SUPPORT) */ 1447 1448 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_HELIX4_SUPPORT) 1449 /* Katana does not support clock offset */ 1450 if (SOC_IS_KATANAX(unit) || SOC_IS_TRIUMPH3(unit) || 1451 SOC_IS_TD2_TT2(unit) || SOC_IS_HELIX4(unit)) { 1452 return BCM_E_UNAVAIL; 1453 } 1454 #endif /* defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_HELIX4_SUPPORT) */ 1455 1456 intf = TIME_INTERFACE(unit, id); 1457 1458 /* Negative value if local clock is faster and need negative adjustment */ 1459 sign = intf->offset.isnegative; 1460 /* Write second's values into the HW */ 1461 READ_CMIC_BS_OFFSET_ADJUST_0r(unit, ®val); 1462 hw_val = COMPILER_64_LO(intf->offset.seconds); 1463 soc_reg_field_set(unit, CMIC_BS_OFFSET_ADJUST_0r, ®val, SECONDf, hw_val); 1464 WRITE_CMIC_BS_OFFSET_ADJUST_0r(unit, regval); 1465 /* Write sign and nansecond's values into the HW */ 1466 READ_CMIC_BS_OFFSET_ADJUST_1r(unit, ®val); 1467 soc_reg_field_set(unit, CMIC_BS_OFFSET_ADJUST_1r, ®val, 1468 SIGN_BITf, sign); 1469 soc_reg_field_set(unit, CMIC_BS_OFFSET_ADJUST_1r, ®val, NSf, 1470 intf->offset.nanoseconds); 1471 WRITE_CMIC_BS_OFFSET_ADJUST_1r(unit, regval); 1472 1473 /* If necessary install the epoch */ 1474 if (COMPILER_64_HI(intf->offset.seconds) > 0) { 1475 READ_CMIC_BS_CONFIGr(unit, ®val); 1476 hw_val = COMPILER_64_HI(intf->offset.seconds); 1477 if (hw_val > TIME_EPOCH_MAX) { 1478 hw_val = TIME_EPOCH_MAX; 1479 } 1480 soc_reg_field_set(unit, CMIC_BS_CONFIGr, ®val, EPOCHf, hw_val); 1481 WRITE_CMIC_BS_CONFIGr(unit, regval); 1482 } 1483 1484 return (BCM_E_NONE); 1485 } 1486 1487 #if defined(BCM_TIME_MANAGED_BROADSYNC) 1488 /* 1489 * Function: 1490 * _bcm_esw_time_interface_ref_clock_install 1491 * Purpose: 1492 * Internal routine to install timesync clock divisor to 1493 * enable broadsync reference clock. 1494 * Parameters: 1495 * unit - (IN) BCM device number. 1496 * id - (IN) Interface id to be installed into a HW 1497 * Returns: 1498 * BCM_E_XXX 1499 */ 1500 STATIC int 1501 _bcm_esw_time_interface_ref_clock_install(int unit, bcm_time_if_t id) 1502 { 1503 uint32 regval, ndiv, hdiv, ref_clk; 1504 bcm_time_interface_t *intf; 1505 1506 intf = TIME_INTERFACE(unit, id); 1507 1508 /* Validate and calculate ts_clk divisor to generate reference clock */ 1509 if (intf->clk_resolution <= 0) { 1510 return BCM_E_PARAM; 1511 } 1512 1513 /* Maximum ts_clk frequency is of 25Mhz(40ns) */ 1514 ref_clk = (intf->clk_resolution > TIME_TS_CLK_FREQUENCY_40NS) ? 1515 TIME_TS_CLK_FREQUENCY_40NS : intf->clk_resolution; 1516 1517 /* Divisor is half period for reference clock */ 1518 ndiv = TIME_TS_CLK_FREQUENCY_40NS / ref_clk; 1519 1520 /* Divisor is ceiling of half period */ 1521 hdiv = (ndiv + 1)/2 ? ndiv : 1; 1522 1523 /* Enable Broadsync reference clock */ 1524 #if defined(BCM_TIME_V3_OR_IPROC_MANAGED_BROADSYNC) 1525 if (SOC_HAS_TIME_V3_OR_IPROC_MANAGED_BROADSYNC(unit)) { 1526 if (SOC_IS_TOMAHAWK3(unit) || SOC_IS_MONTEREY(unit)) { 1527 READ_NS_BROADSYNC_REF_CLK_GEN_CTRLr(unit, ®val); 1528 soc_reg_field_set(unit, NS_BROADSYNC_REF_CLK_GEN_CTRLr, ®val, 1529 ENABLEf, 1); 1530 soc_reg_field_set(unit, NS_BROADSYNC_REF_CLK_GEN_CTRLr, ®val, 1531 DIVISORf, hdiv); 1532 WRITE_NS_BROADSYNC_REF_CLK_GEN_CTRLr(unit, regval); 1533 } else { 1534 READ_CMIC_BROADSYNC_REF_CLK_GEN_CTRLr(unit, ®val); 1535 soc_reg_field_set(unit, CMIC_BROADSYNC_REF_CLK_GEN_CTRLr, ®val, 1536 ENABLEf, 1); 1537 soc_reg_field_set(unit, CMIC_BROADSYNC_REF_CLK_GEN_CTRLr, ®val, 1538 DIVISORf, hdiv); 1539 WRITE_CMIC_BROADSYNC_REF_CLK_GEN_CTRLr(unit, regval); 1540 } 1541 } else 1542 #endif /* BCM_TIME_V3_OR_IPROC_MANAGED_BROADSYNC */ 1543 { 1544 READ_CMIC_BS_REF_CLK_GEN_CTRLr(unit, ®val); 1545 soc_reg_field_set(unit, CMIC_BS_REF_CLK_GEN_CTRLr, ®val, 1546 ENABLEf, 1); 1547 soc_reg_field_set(unit, CMIC_BS_REF_CLK_GEN_CTRLr, ®val, 1548 DIVISORf, hdiv); 1549 WRITE_CMIC_BS_REF_CLK_GEN_CTRLr(unit, regval); 1550 } 1551 1552 return (BCM_E_NONE); 1553 } 1554 #endif /* BCM_TIME_MANAGED_BROADSYNC */ 1555 1556 /* 1557 * Function: 1558 * _bcm_esw_time_interface_install 1559 * Purpose: 1560 * Internal routine used to install interface settings into a HW 1561 * Parameters: 1562 * unit - (IN) BCM device number. 1563 * intf_id - (IN) Interface id to be installed into a HW 1564 * Returns: 1565 * BCM_E_XXX 1566 */ 1567 STATIC int 1568 _bcm_esw_time_interface_install(int unit, bcm_time_if_t intf_id) 1569 { 1570 bcm_time_interface_t *intf; /* Time interface */ 1571 uint32 regval; /* For register read and write operations */ 1572 uint32 hw_val; /* Value to program into a HW */ 1573 uint32 second, diff, delay = BROAD_SYNC_OUTPUT_TOGGLE_TIME_DELAY; 1574 int enable = 0; 1575 soc_reg_t reg; 1576 bcm_time_spec_t toggle_time; 1577 1578 if (NULL == TIME_INTERFACE(unit, intf_id)) { 1579 return BCM_E_PARAM; 1580 } 1581 1582 intf = TIME_INTERFACE(unit, intf_id); 1583 1584 READ_CMIC_BS_CONFIGr(unit, ®val); 1585 1586 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_TRIDENT2_SUPPORT) 1587 if (SOC_IS_KATANAX(unit) || SOC_IS_TRIUMPH3(unit) || 1588 SOC_IS_TD2_TT2(unit)) { 1589 if ((intf->flags & BCM_TIME_ENABLE)) { 1590 /* Enable all three broadsync pins: 1591 * Bit clock, HeartBeat and Timecode 1592 */ 1593 soc_reg_field_set( 1594 unit, CMIC_BS_CONFIGr, ®val, BS_CLK_OUTPUT_ENABLEf, 1); 1595 soc_reg_field_set( 1596 unit, CMIC_BS_CONFIGr, ®val, BS_HB_OUTPUT_ENABLEf, 1); 1597 soc_reg_field_set( 1598 unit, CMIC_BS_CONFIGr, ®val, BS_TC_OUTPUT_ENABLEf, 1); 1599 } else { 1600 soc_reg_field_set( 1601 unit, CMIC_BS_CONFIGr, ®val, BS_CLK_OUTPUT_ENABLEf, 0); 1602 soc_reg_field_set( 1603 unit, CMIC_BS_CONFIGr, ®val, BS_TC_OUTPUT_ENABLEf, 0); 1604 } 1605 1606 if ((intf->flags & BCM_TIME_LOCKED)) { 1607 soc_reg_field32_modify( 1608 unit, CMIC_BS_OUTPUT_TIME_0r, REG_PORT_ANY, LOCKf, 1); 1609 } else { 1610 soc_reg_field32_modify( 1611 unit, CMIC_BS_OUTPUT_TIME_0r, REG_PORT_ANY, LOCKf, 0); 1612 } 1613 1614 } else 1615 #endif /* defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_TRIDENT2_SUPPORT) */ 1616 { 1617 if (intf->flags & BCM_TIME_ENABLE) { 1618 soc_reg_field_set(unit, CMIC_BS_CONFIGr, ®val, ENABLEf, 1); 1619 soc_reg_field_set( 1620 unit, CMIC_BS_CONFIGr, ®val, TIME_CODE_ENABLEf, 1); 1621 } else { 1622 soc_reg_field_set(unit, CMIC_BS_CONFIGr, ®val, ENABLEf, 0); 1623 soc_reg_field_set( 1624 unit, CMIC_BS_CONFIGr, ®val, TIME_CODE_ENABLEf, 0); 1625 } 1626 1627 if ((intf->flags & BCM_TIME_LOCKED)) { 1628 soc_reg_field_set(unit, CMIC_BS_CONFIGr, ®val, LOCKf, 1); 1629 } else { 1630 soc_reg_field_set(unit, CMIC_BS_CONFIGr, ®val, LOCKf, 0); 1631 } 1632 } 1633 1634 if (intf->flags & BCM_TIME_INPUT) { 1635 /* Set Broadsync in Input mode */ 1636 soc_reg_field_set(unit, CMIC_BS_CONFIGr, ®val, MODEf, 1637 TIME_MODE_INPUT); 1638 } else { 1639 /* Configure Accuracy, offset and drift for broadsync output mode */ 1640 soc_reg_field_set(unit, CMIC_BS_CONFIGr, ®val, MODEf, 1641 TIME_MODE_OUTPUT); 1642 if (intf->flags & BCM_TIME_ACCURACY) { 1643 BCM_IF_ERROR_RETURN( 1644 _bcm_esw_time_interface_accuracy_time2hw(unit, intf_id, &hw_val)); 1645 if (SOC_IS_KATANAX(unit) || SOC_IS_TRIUMPH3(unit) || 1646 SOC_IS_TD2_TT2(unit)) { 1647 soc_reg_field32_modify(unit, CMIC_BS_OUTPUT_TIME_0r, 1648 REG_PORT_ANY, ACCURACYf, hw_val); 1649 } else { 1650 soc_reg_field_set(unit, CMIC_BS_CONFIGr, ®val, ACCURACYf, hw_val); 1651 } 1652 } 1653 if (intf->flags & BCM_TIME_HEARTBEAT) { 1654 BCM_IF_ERROR_RETURN( 1655 _bcm_esw_time_interface_heartbeat_install(unit, intf_id)); 1656 1657 if (!(intf->flags & BCM_TIME_OFFSET)) { 1658 BCM_IF_ERROR_RETURN( 1659 _bcm_esw_time_capture_get(unit, intf_id, TIME_CAPTURE(unit, intf_id), 0)); 1660 if (!(SOC_IS_KATANAX(unit) || SOC_IS_TRIUMPH3(unit) || 1661 SOC_IS_TD2_TT2(unit))) { 1662 second = COMPILER_64_LO(SYNT_TIME_SECONDS(unit, intf_id)); 1663 second += delay; 1664 WRITE_CMIC_BS_CLK_TOGGLE_TIME_0r(unit, second); 1665 WRITE_CMIC_BS_CLK_TOGGLE_TIME_1r( 1666 unit, SYNT_TIME_NANOSECONDS(unit, intf_id)); 1667 } 1668 } 1669 } 1670 } 1671 WRITE_CMIC_BS_CONFIGr(unit, regval); 1672 1673 if (intf->flags & BCM_TIME_OFFSET) { 1674 if(SOC_REG_IS_VALID(unit, CMIC_BS_CLK_CTRL_0r)) { 1675 reg = CMIC_BS_CLK_CTRL_0r; 1676 READ_CMIC_BS_CLK_CTRL_0r(unit, ®val); 1677 } else { 1678 reg = CMIC_BS_CLK_CTRLr; 1679 READ_CMIC_BS_CLK_CTRLr(unit, ®val); 1680 } 1681 1682 /* Stop broadsync output if already enabled */ 1683 enable = soc_reg_field_get(unit, reg, regval, ENABLEf); 1684 if (1 == enable) { 1685 soc_reg_field_set(unit, reg, ®val, ENABLEf, 0); 1686 if (SOC_REG_IS_VALID(unit, CMIC_BS_CLK_CTRL_0r)) { 1687 WRITE_CMIC_BS_CLK_CTRL_0r(unit, regval); 1688 } else { 1689 WRITE_CMIC_BS_CLK_CTRLr(unit, regval); 1690 } 1691 BCM_IF_ERROR_RETURN( 1692 _bcm_esw_time_capture_get(unit, intf_id, TIME_CAPTURE(unit, intf_id), 0)); 1693 } 1694 1695 BCM_IF_ERROR_RETURN( 1696 _bcm_esw_time_interface_offset_install(unit, intf_id)); 1697 1698 if (intf->offset.isnegative) { 1699 second = COMPILER_64_LO(SYNT_TIME_SECONDS(unit, intf_id)) - 1700 COMPILER_64_LO(intf->offset.seconds); 1701 1702 if (intf->offset.nanoseconds <= SYNT_TIME_NANOSECONDS(unit, intf_id)) { 1703 toggle_time.nanoseconds = SYNT_TIME_NANOSECONDS(unit, intf_id) - 1704 intf->offset.nanoseconds; 1705 } else { 1706 /* Wrapped */ 1707 diff = intf->offset.nanoseconds - SYNT_TIME_NANOSECONDS(unit, intf_id); 1708 toggle_time.nanoseconds = TIME_NANOSEC_MAX - diff; 1709 second--; 1710 } 1711 COMPILER_64_SET(toggle_time.seconds, 0, second); 1712 } else { 1713 second = COMPILER_64_LO(SYNT_TIME_SECONDS(unit, intf_id)) + 1714 COMPILER_64_LO(intf->offset.seconds); 1715 toggle_time.nanoseconds = 1716 SYNT_TIME_NANOSECONDS(unit, intf_id) + intf->offset.nanoseconds; 1717 if (toggle_time.nanoseconds >= TIME_NANOSEC_MAX) { 1718 toggle_time.nanoseconds -= TIME_NANOSEC_MAX; 1719 second++; 1720 } 1721 COMPILER_64_SET(toggle_time.seconds, 0, second); 1722 } 1723 1724 if (1 == enable) { 1725 /* Reenable broadsync output */ 1726 COMPILER_64_TO_32_LO(second, toggle_time.seconds); 1727 second += delay; 1728 if (SOC_REG_IS_VALID(unit, CMIC_BS_CLK_TOGGLE_TIME_0r)) { 1729 WRITE_CMIC_BS_CLK_TOGGLE_TIME_0r(unit, second); 1730 } 1731 1732 if (SOC_REG_IS_VALID(unit, CMIC_BS_CLK_TOGGLE_TIME_1r)) { 1733 WRITE_CMIC_BS_CLK_TOGGLE_TIME_1r(unit, toggle_time.nanoseconds); 1734 } 1735 1736 if (SOC_REG_IS_VALID(unit, CMIC_BS_CLK_TOGGLE_TIME_1r)) { 1737 READ_CMIC_BS_CLK_CTRL_0r(unit, ®val); 1738 soc_reg_field_set(unit, CMIC_BS_CLK_CTRL_0r, ®val, ENABLEf, 1); 1739 WRITE_CMIC_BS_CLK_CTRL_0r(unit, regval); 1740 } else { 1741 READ_CMIC_BS_CLK_CTRLr(unit, ®val); 1742 soc_reg_field_set(unit, CMIC_BS_CLK_CTRLr, ®val, ENABLEf, 1); 1743 WRITE_CMIC_BS_CLK_CTRLr(unit, regval); 1744 } 1745 } 1746 } 1747 1748 if (intf->flags & BCM_TIME_DRIFT) { 1749 BCM_IF_ERROR_RETURN( 1750 _bcm_esw_time_interface_drift_install(unit, intf_id)); 1751 } 1752 1753 return (BCM_E_NONE); 1754 } 1755 1756 #if defined(BCM_TIME_V3_OR_IPROC_MANAGED_BROADSYNC) 1757 STATIC int 1758 _bcm_esw_time_interface_dual_bs_install(int unit, bcm_time_if_t intf_id) 1759 { 1760 bcm_time_interface_t *intf; /* Time interface */ 1761 uint32 regval; /* For register read and write operations */ 1762 uint32 hw_val; /* Value to program into a HW */ 1763 1764 /* Feature unavailable on devices without BroadSync support. */ 1765 if (soc_feature(unit, soc_feature_time_v3_no_bs)) { 1766 return BCM_E_UNAVAIL; 1767 } 1768 1769 if (NULL == TIME_INTERFACE(unit, intf_id)) { 1770 return BCM_E_PARAM; 1771 } 1772 1773 intf = TIME_INTERFACE(unit, intf_id); 1774 1775 if (SOC_IS_TOMAHAWK3(unit) || SOC_IS_MONTEREY(unit)) { 1776 READ_NS_BS0_BS_CONFIGr(unit, ®val); 1777 1778 if ((intf->flags & BCM_TIME_LOCKED)) { 1779 soc_reg_field32_modify(unit, NS_BS0_BS_OUTPUT_TIME_0r, REG_PORT_ANY, LOCKf, 1); 1780 } else { 1781 soc_reg_field32_modify(unit, NS_BS0_BS_OUTPUT_TIME_0r, REG_PORT_ANY, LOCKf, 0); 1782 } 1783 1784 if (intf->flags & BCM_TIME_INPUT) { 1785 /* Set Broadsync in Input mode */ 1786 soc_reg_field_set(unit, NS_BS0_BS_CONFIGr, ®val, MODEf, TIME_MODE_INPUT); 1787 1788 /* ensure all output controls are disabled in input mode */ 1789 soc_reg_field_set(unit, NS_BS0_BS_CONFIGr, ®val, BS_CLK_OUTPUT_ENABLEf, 0); 1790 soc_reg_field_set(unit, NS_BS0_BS_CONFIGr, ®val, BS_TC_OUTPUT_ENABLEf, 0); 1791 soc_reg_field_set(unit, NS_BS0_BS_CONFIGr, ®val, BS_HB_OUTPUT_ENABLEf, 0); 1792 } else { 1793 /* Configure Accuracy, offset and drift for broadsync output mode */ 1794 soc_reg_field_set(unit, NS_BS0_BS_CONFIGr, ®val, MODEf, TIME_MODE_OUTPUT); 1795 1796 if ((intf->flags & BCM_TIME_ENABLE)) { 1797 /* Enable all three broadsync pins: Bit clock, HeartBeat and Timecode */ 1798 soc_reg_field_set(unit, NS_BS0_BS_CONFIGr, ®val, BS_CLK_OUTPUT_ENABLEf, 1); 1799 soc_reg_field_set(unit, NS_BS0_BS_CONFIGr, ®val, BS_TC_OUTPUT_ENABLEf, 1); 1800 soc_reg_field_set(unit, NS_BS0_BS_CONFIGr, ®val, BS_HB_OUTPUT_ENABLEf, 1); 1801 } else { 1802 /* ensure all output controls are disabled */ 1803 soc_reg_field_set(unit, NS_BS0_BS_CONFIGr, ®val, BS_CLK_OUTPUT_ENABLEf, 0); 1804 soc_reg_field_set(unit, NS_BS0_BS_CONFIGr, ®val, BS_TC_OUTPUT_ENABLEf, 0); 1805 soc_reg_field_set(unit, NS_BS0_BS_CONFIGr, ®val, BS_HB_OUTPUT_ENABLEf, 0); 1806 } 1807 1808 if (intf->flags & BCM_TIME_ACCURACY) { 1809 BCM_IF_ERROR_RETURN( 1810 _bcm_esw_time_interface_accuracy_time2hw(unit, intf_id, &hw_val)); 1811 soc_reg_field32_modify(unit, NS_BS0_BS_OUTPUT_TIME_0r, REG_PORT_ANY, ACCURACYf, hw_val); 1812 } 1813 1814 if (intf->flags & BCM_TIME_HEARTBEAT) { 1815 BCM_IF_ERROR_RETURN( 1816 _bcm_esw_time_interface_heartbeat_install(unit, intf_id)); 1817 } 1818 } 1819 1820 WRITE_NS_BS0_BS_CONFIGr(unit, regval); 1821 1822 } else { 1823 1824 READ_CMIC_BS0_CONFIGr(unit, ®val); 1825 1826 if ((intf->flags & BCM_TIME_LOCKED)) { 1827 soc_reg_field32_modify(unit, CMIC_BS0_OUTPUT_TIME_0r, REG_PORT_ANY, LOCKf, 1); 1828 } else { 1829 soc_reg_field32_modify(unit, CMIC_BS0_OUTPUT_TIME_0r, REG_PORT_ANY, LOCKf, 0); 1830 } 1831 1832 if (intf->flags & BCM_TIME_INPUT) { 1833 /* Set Broadsync in Input mode */ 1834 soc_reg_field_set(unit, CMIC_BS0_CONFIGr, ®val, MODEf, TIME_MODE_INPUT); 1835 1836 /* ensure all output controls are disabled in input mode */ 1837 soc_reg_field_set(unit, CMIC_BS0_CONFIGr, ®val, BS_CLK_OUTPUT_ENABLEf, 0); 1838 soc_reg_field_set(unit, CMIC_BS0_CONFIGr, ®val, BS_TC_OUTPUT_ENABLEf, 0); 1839 soc_reg_field_set(unit, CMIC_BS0_CONFIGr, ®val, BS_HB_OUTPUT_ENABLEf, 0); 1840 } else { 1841 /* Configure Accuracy, offset and drift for broadsync output mode */ 1842 soc_reg_field_set(unit, CMIC_BS0_CONFIGr, ®val, MODEf, TIME_MODE_OUTPUT); 1843 1844 if ((intf->flags & BCM_TIME_ENABLE)) { 1845 /* Enable all three broadsync pins: Bit clock, HeartBeat and Timecode */ 1846 soc_reg_field_set(unit, CMIC_BS0_CONFIGr, ®val, BS_CLK_OUTPUT_ENABLEf, 1); 1847 soc_reg_field_set(unit, CMIC_BS0_CONFIGr, ®val, BS_TC_OUTPUT_ENABLEf, 1); 1848 soc_reg_field_set(unit, CMIC_BS0_CONFIGr, ®val, BS_HB_OUTPUT_ENABLEf, 1); 1849 } else { 1850 /* ensure all output controls are disabled */ 1851 soc_reg_field_set(unit, CMIC_BS0_CONFIGr, ®val, BS_CLK_OUTPUT_ENABLEf, 0); 1852 soc_reg_field_set(unit, CMIC_BS0_CONFIGr, ®val, BS_TC_OUTPUT_ENABLEf, 0); 1853 soc_reg_field_set(unit, CMIC_BS0_CONFIGr, ®val, BS_HB_OUTPUT_ENABLEf, 0); 1854 } 1855 1856 if (intf->flags & BCM_TIME_ACCURACY) { 1857 BCM_IF_ERROR_RETURN( 1858 _bcm_esw_time_interface_accuracy_time2hw(unit, intf_id, &hw_val)); 1859 soc_reg_field32_modify(unit, CMIC_BS0_OUTPUT_TIME_0r, REG_PORT_ANY, ACCURACYf, hw_val); 1860 } 1861 1862 if (intf->flags & BCM_TIME_HEARTBEAT) { 1863 BCM_IF_ERROR_RETURN( 1864 _bcm_esw_time_interface_heartbeat_install(unit, intf_id)); 1865 } 1866 } 1867 1868 WRITE_CMIC_BS0_CONFIGr(unit, regval); 1869 } 1870 return (BCM_E_NONE); 1871 } 1872 #endif /* BCM_TIME_V3_OR_IPROC_MANAGED_BROADSYNC */ 1873 1874 1875 /* 1876 * Function: 1877 * _bcm_time_interface_free 1878 * Purpose: 1879 * Free time interface. 1880 * Parameters: 1881 * unit - (IN) BCM device number. 1882 * intf_id - (IN) time interface id. 1883 * Returns: 1884 * BCM_X_XXX 1885 */ 1886 1887 STATIC int 1888 _bcm_time_interface_free(int unit, bcm_time_if_t intf_id) 1889 { 1890 _bcm_time_interface_config_p intf_cfg; /* Time interface config.*/ 1891 1892 intf_cfg = &TIME_INTERFACE_CONFIG(unit, intf_id); 1893 1894 if (intf_cfg->ref_count > 0) { 1895 intf_cfg->ref_count--; 1896 } 1897 1898 if (0 == intf_cfg->ref_count) { 1899 sal_memset(&intf_cfg->time_interface, 0, sizeof(bcm_time_interface_t)); 1900 intf_cfg->time_interface.id = intf_id; 1901 } 1902 1903 return (BCM_E_NONE); 1904 } 1905 1906 /* 1907 * Function: 1908 * _bcm_esw_time_accuracy_parse 1909 * Purpose: 1910 * Internal routine to parse accuracy hw value into bcm_time_spec_t format 1911 * Parameters: 1912 * unit - (IN) StrataSwitch Unit #. 1913 * accuracy - (IN) Accuracy HW value 1914 * time - (OUT) bcm_time_spec_t structure to contain accuracy 1915 * Returns: 1916 * BCM_E_NONE 1917 * BCM_E_XXX 1918 */ 1919 STATIC int 1920 _bcm_esw_time_accuracy_parse(int unit, uint32 accuracy, bcm_time_spec_t *time) 1921 { 1922 if (accuracy < TIME_ACCURACY_LOW_HW_VAL || 1923 (accuracy > TIME_ACCURACY_HIGH_HW_VAL && 1924 accuracy != TIME_ACCURACY_UNKNOWN_HW_VAL)) { 1925 return (BCM_E_PARAM); 1926 } 1927 1928 time->isnegative = 1929 _bcm_time_accuracy_arr[TIME_ACCURACY_HW_2_SW_IDX(accuracy)].isnegative; 1930 time->nanoseconds = 1931 _bcm_time_accuracy_arr[TIME_ACCURACY_HW_2_SW_IDX(accuracy)].nanoseconds; 1932 time->seconds = 1933 _bcm_time_accuracy_arr[TIME_ACCURACY_HW_2_SW_IDX(accuracy)].seconds; 1934 time->isnegative = 0; /* Can't be negative */ 1935 1936 return (BCM_E_NONE); 1937 } 1938 1939 1940 /* 1941 * Function: 1942 * _bcm_esw_time_input_parse 1943 * Purpose: 1944 * Internal routine to parse input time information stored in 3 registeres 1945 * Parameters: 1946 * unit - (IN) StrataSwitch Unit #. 1947 * data0 - (IN) Data stored in register 0 conrain input time information 1948 * data1 - (IN) Data stored in register 1 conrain input time information 1949 * data2 - (IN) Data stored in register 2 conrain input time information 1950 * time - (OUT) Structure to contain input time information 1951 * Returns: 1952 * BCM_E_NONE 1953 * BCM_E_XXX 1954 */ 1955 STATIC int 1956 _bcm_esw_time_input_parse(int unit, uint32 data0, uint32 data1, uint32 data2, 1957 bcm_time_capture_t *time) 1958 { 1959 uint32 accuracy, sec_hi, sec_lo; 1960 1961 if (data0 >> 31) { 1962 time->flags |= BCM_TIME_CAPTURE_LOCKED; 1963 } 1964 time->received.isnegative = 0; 1965 sec_hi = ((data0 << 1) >> 1); 1966 sec_lo = (data1 >> 14); 1967 COMPILER_64_SET(time->received.seconds, sec_hi, sec_lo); 1968 time->received.nanoseconds = (data1 << 16); 1969 time->received.nanoseconds |= (data2 >> 8); 1970 1971 accuracy = ((data2 << 24) >> 24); 1972 1973 return _bcm_esw_time_accuracy_parse(unit,accuracy, 1974 &(time->received_accuracy)); 1975 } 1976 1977 /* 1978 * Function: 1979 * _bcm_esw_time_capture_counter_read 1980 * Purpose: 1981 * Internal routine to read HW clocks 1982 * Parameters: 1983 * unit - (IN) StrataSwitch Unit #. 1984 * id - (IN) Time interface identifier 1985 * time - (OUT) Structure to contain HW clocks values 1986 * Returns: 1987 * BCM_E_NONE 1988 * BCM_E_XXX 1989 */ 1990 1991 STATIC int 1992 _bcm_esw_time_capture_counter_read(int unit, bcm_time_if_t id, 1993 bcm_time_capture_t *time) 1994 { 1995 uint32 regval; 1996 bcm_time_interface_t *intf; 1997 1998 #if defined(BCM_TIME_V3_OR_IPROC_MANAGED_BROADSYNC) 1999 if (SOC_HAS_TIME_V3_OR_IPROC_MANAGED_BROADSYNC(unit)) { 2000 uint32 regval2, event_id, lower; 2001 uint32 upper; 2002 sal_memset(time, 0, sizeof(bcm_time_capture_t)); 2003 2004 if (SOC_IS_TOMAHAWK3(unit) || SOC_IS_MONTEREY(unit)) { 2005 /* Read timestamp from FIFO */ 2006 uint32 regval1, regval3; 2007 READ_NS_TS_INT_STATUSr(unit, ®val); 2008 if (0 == soc_reg_field_get(unit, NS_TS_INT_STATUSr, 2009 regval, TS_FIFO_NOT_EMPTYf)) { 2010 return (BCM_E_EMPTY); 2011 } 2012 2013 /* Must read LOWER regiser first */ 2014 /* Read to this register POPs the FIFO */ 2015 READ_NS_TIMESYNC_INPUT_TIME_FIFO_TS_0r(unit, ®val); 2016 READ_NS_TIMESYNC_INPUT_TIME_FIFO_TS_1r(unit, ®val1); 2017 READ_NS_TIMESYNC_INPUT_TIME_FIFO_TS_2r(unit, ®val2); 2018 READ_NS_TIMESYNC_INPUT_TIME_FIFO_TS_3r(unit, ®val3); 2019 2020 /* If it's not valid, something is wrong (since FIFO is not empty) */ 2021 if (0 == soc_reg_field_get( 2022 unit, NS_TIMESYNC_INPUT_TIME_FIFO_TS_3r, regval3, 2023 TS_VALIDf)) { 2024 return (BCM_E_FAIL); 2025 } 2026 /* Check capture event id */ 2027 event_id = soc_reg_field_get( 2028 unit, NS_TIMESYNC_INPUT_TIME_FIFO_TS_3r, 2029 regval3, TS_EVENT_IDf); 2030 2031 if (event_id == 0) { 2032 time->flags |= BCM_TIME_CAPTURE_IMMEDIATE; 2033 } 2034 /* Calculate seconds/nanoseconds from the timestamp value */ 2035 lower = soc_reg_field_get( 2036 unit, NS_TIMESYNC_INPUT_TIME_FIFO_TS_0r, 2037 regval, TS0_Lf); 2038 2039 upper = soc_reg_field_get( 2040 unit, NS_TIMESYNC_INPUT_TIME_FIFO_TS_1r, 2041 regval1, TS0_Uf); 2042 /* Discard 4bits from lower*/ 2043 lower = (lower >> 4); 2044 lower = (lower & 0x0FFFFFFF) | ((upper & 0xF) << 28); 2045 upper = (upper >> 4); 2046 2047 } else { 2048 /* Read timestamp from FIFO */ 2049 READ_CMIC_TIMESYNC_CAPTURE_STATUS_1r(unit, ®val); 2050 if (0 == soc_reg_field_get(unit, CMIC_TIMESYNC_CAPTURE_STATUS_1r, 2051 regval, FIFO_DEPTHf)) { 2052 return (BCM_E_EMPTY); 2053 } 2054 2055 /* Must read LOWER regiser first */ 2056 READ_CMIC_TIMESYNC_INPUT_TIME_FIFO_TS_LOWERr(unit, ®val2); 2057 2058 /* Then read UPPER register */ 2059 READ_CMIC_TIMESYNC_INPUT_TIME_FIFO_TS_UPPERr(unit, ®val); 2060 /* If it's not valid, something is wrong (since FIFO is not empty) */ 2061 if (0 == soc_reg_field_get( 2062 unit, CMIC_TIMESYNC_INPUT_TIME_FIFO_TS_UPPERr, regval, 2063 VALIDf)) { 2064 return (BCM_E_FAIL); 2065 } 2066 /* Check capture event id */ 2067 event_id = soc_reg_field_get( 2068 unit, CMIC_TIMESYNC_INPUT_TIME_FIFO_TS_UPPERr, 2069 regval, EVENT_IDf); 2070 if (event_id == 0) { 2071 time->flags |= BCM_TIME_CAPTURE_IMMEDIATE; 2072 } 2073 /* Calculate seconds/nanoseconds from the timestamp value */ 2074 lower = soc_reg_field_get( 2075 unit, CMIC_TIMESYNC_INPUT_TIME_FIFO_TS_LOWERr, 2076 regval2, TIMESTAMPf); 2077 2078 upper = soc_reg_field_get( 2079 unit, CMIC_TIMESYNC_INPUT_TIME_FIFO_TS_UPPERr, 2080 regval, TIMESTAMPf); 2081 2082 } 2083 2084 if (soc_feature(unit, soc_feature_timesync_timestampingmode)) { 2085 /* 48-bit timestamping supported */ 2086 uint64 time_val, secs, nano_secs; 2087 uint64 div; 2088 /* Get the 48-bit timestamp value */ 2089 COMPILER_64_SET(time_val, upper, lower); 2090 2091 /* Get seconds from the timestamp value */ 2092 secs = time_val; 2093 COMPILER_64_SET(div, 0, 1000000000); 2094 COMPILER_64_UDIV_64(secs, div); 2095 time->synchronous.seconds = secs; 2096 2097 /* Get nanoseconds from the timestamp value */ 2098 nano_secs = time_val; 2099 COMPILER_64_UMUL_32(secs, 1000000000); 2100 COMPILER_64_SUB_64(nano_secs, secs); 2101 time->synchronous.nanoseconds = COMPILER_64_LO(nano_secs); 2102 } else { 2103 COMPILER_64_SET(time->synchronous.seconds, 0, lower / 1000000000); 2104 time->synchronous.nanoseconds = lower % 1000000000; 2105 } 2106 2107 /* For backward compatibility */ 2108 time->free = time->synchronous; 2109 time->syntonous = time->synchronous; 2110 2111 } else 2112 #endif /* BCM_TIME_V3_OR_IPROC_MANAGED_BROADSYNC */ 2113 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_TRIDENT2_SUPPORT) 2114 if (SOC_IS_KATANA(unit) || SOC_IS_TRIUMPH3(unit) || 2115 SOC_IS_TD2_TT2(unit)) { 2116 uint32 event_id; 2117 2118 /* Check FIFO depth */ 2119 sal_memset(time, 0, sizeof(bcm_time_capture_t)); 2120 READ_CMIC_TS_CAPTURE_STATUSr(unit, ®val); 2121 if (0 == soc_reg_field_get(unit, CMIC_TS_CAPTURE_STATUSr, 2122 regval, FIFO_DEPTHf)) { 2123 return (BCM_E_EMPTY); 2124 } 2125 2126 /* Read timestamp from FIFO */ 2127 READ_CMIC_TS_INPUT_TIME_FIFO_TSr(unit, ®val); 2128 time->synchronous.nanoseconds = soc_reg_field_get(unit, 2129 CMIC_TS_INPUT_TIME_FIFO_TSr, regval, 2130 TIMESTAMPf); 2131 2132 /* If it's not valid, something is wrong (since FIFO is not empty) */ 2133 READ_CMIC_TS_INPUT_TIME_FIFO_IDr(unit, ®val); 2134 if (0 == soc_reg_field_get( 2135 unit, CMIC_TS_INPUT_TIME_FIFO_IDr, regval, 2136 VALIDf)) { 2137 return (BCM_E_FAIL); 2138 } 2139 2140 /* Check capture event id */ 2141 event_id = soc_reg_field_get( 2142 unit, CMIC_TS_INPUT_TIME_FIFO_IDr, 2143 regval, EVENT_IDf); 2144 2145 if (event_id == 0) { 2146 time->flags |= BCM_TIME_CAPTURE_IMMEDIATE; 2147 } 2148 2149 /* For backward compatibility */ 2150 time->free = time->synchronous; 2151 time->syntonous = time->synchronous; 2152 2153 } else 2154 #endif /* defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_TRIDENT2_SUPPORT) */ 2155 { 2156 /* Read free running time capture */ 2157 READ_CMIC_BS_CAPTURE_FREE_RUN_TIME_0r(unit, ®val); 2158 COMPILER_64_SET(time->free.seconds, 0, 2159 soc_reg_field_get(unit, CMIC_BS_CAPTURE_FREE_RUN_TIME_0r, 2160 regval, SECONDf)); 2161 READ_CMIC_BS_CAPTURE_FREE_RUN_TIME_1r(unit, ®val); 2162 time->free.nanoseconds = 2163 soc_reg_field_get(unit, CMIC_BS_CAPTURE_FREE_RUN_TIME_1r, regval, NSf); 2164 /* Read syntonous time capture */ 2165 READ_CMIC_BS_CAPTURE_SYNT_TIME_0r(unit, ®val); 2166 COMPILER_64_SET(time->syntonous.seconds, 0, 2167 soc_reg_field_get(unit, CMIC_BS_CAPTURE_SYNT_TIME_0r, regval, SECONDf)); 2168 READ_CMIC_BS_CAPTURE_SYNT_TIME_1r(unit, ®val); 2169 time->syntonous.nanoseconds = 2170 soc_reg_field_get(unit, CMIC_BS_CAPTURE_SYNT_TIME_1r, regval, NSf); 2171 /* Read synchronous time capture */ 2172 READ_CMIC_BS_CAPTURE_SYNC_TIME_0r(unit, ®val); 2173 COMPILER_64_SET(time->synchronous.seconds, 0, 2174 soc_reg_field_get(unit, CMIC_BS_CAPTURE_SYNC_TIME_0r, regval, SECONDf)); 2175 READ_CMIC_BS_CAPTURE_SYNC_TIME_1r(unit, ®val); 2176 time->synchronous.nanoseconds = 2177 soc_reg_field_get(unit, CMIC_BS_CAPTURE_SYNC_TIME_1r, regval, NSf); 2178 } 2179 2180 time->free.isnegative = time->synchronous.isnegative = 2181 time->syntonous.isnegative = 0; 2182 2183 /* If interface is in input mode read time provided by the master */ 2184 intf = TIME_INTERFACE(unit, id); 2185 if (intf->flags & BCM_TIME_INPUT) { 2186 uint32 data0 = 0, data1 = 0, data2 = 0; 2187 2188 #if defined(BCM_TIME_V3_OR_IPROC_MANAGED_BROADSYNC) 2189 if (SOC_HAS_TIME_V3_OR_IPROC_MANAGED_BROADSYNC(unit)) { 2190 if (!soc_feature(unit, soc_feature_time_v3_no_bs)) { 2191 if (SOC_IS_TOMAHAWK3(unit) || SOC_IS_MONTEREY(unit)) { 2192 READ_NS_BS0_BS_INPUT_TIME_2r(unit, ®val); 2193 if (soc_reg_field_get(unit, NS_BS0_BS_INPUT_TIME_2r, regval, 2194 CHECKSUM_ERRORf)) { 2195 return BCM_E_INTERNAL; 2196 } 2197 data2 = soc_reg_field_get( 2198 unit, NS_BS0_BS_INPUT_TIME_2r, regval, DATAf); 2199 READ_NS_BS0_BS_INPUT_TIME_1r(unit, ®val); 2200 data1 = soc_reg_field_get( 2201 unit, NS_BS0_BS_INPUT_TIME_1r, regval, DATAf); 2202 READ_NS_BS0_BS_INPUT_TIME_0r(unit, ®val); 2203 data0 = soc_reg_field_get( 2204 unit, NS_BS0_BS_INPUT_TIME_0r, regval, DATAf); 2205 } else { 2206 READ_CMIC_BS0_INPUT_TIME_2r(unit, ®val); 2207 if (soc_reg_field_get(unit, CMIC_BS0_INPUT_TIME_2r, regval, 2208 CHECKSUM_ERRORf)) { 2209 return BCM_E_INTERNAL; 2210 } 2211 data2 = soc_reg_field_get( 2212 unit, CMIC_BS0_INPUT_TIME_2r, regval, DATAf); 2213 READ_CMIC_BS0_INPUT_TIME_1r(unit, ®val); 2214 data1 = soc_reg_field_get( 2215 unit, CMIC_BS0_INPUT_TIME_1r, regval, DATAf); 2216 READ_CMIC_BS0_INPUT_TIME_0r(unit, ®val); 2217 data0 = soc_reg_field_get( 2218 unit, CMIC_BS0_INPUT_TIME_0r, regval, DATAf); 2219 } 2220 } 2221 } else 2222 #endif /* BCM_TIME_V3_OR_IPROC_MANAGED_BROADSYNC */ 2223 { 2224 READ_CMIC_BS_INPUT_TIME_2r(unit, ®val); 2225 if (soc_reg_field_get(unit, CMIC_BS_INPUT_TIME_2r, regval, 2226 CHECKSUM_ERRORf)) { 2227 return BCM_E_INTERNAL; 2228 } 2229 data2 = soc_reg_field_get(unit, CMIC_BS_INPUT_TIME_2r, regval, DATAf); 2230 READ_CMIC_BS_INPUT_TIME_1r(unit, ®val); 2231 data1 = soc_reg_field_get(unit, CMIC_BS_INPUT_TIME_1r, regval, DATAf); 2232 READ_CMIC_BS_INPUT_TIME_0r(unit, ®val); 2233 data0 = soc_reg_field_get(unit, CMIC_BS_INPUT_TIME_0r, regval, DATAf); 2234 } 2235 2236 BCM_IF_ERROR_RETURN( 2237 _bcm_esw_time_input_parse(unit, data0, data1, data2, time)); 2238 } 2239 2240 return (BCM_E_NONE); 2241 } 2242 2243 /* 2244 * Function: 2245 * _bcm_esw_time_capture_get 2246 * Purpose: 2247 * Internal routine to read HW clocks 2248 * Parameters: 2249 * unit - (IN) StrataSwitch Unit #. 2250 * id - (IN) Time interface identifier 2251 * time - (OUT) Structure to contain HW clocks values 2252 * flags - (IN) Flags BCM_TIME_CAPTURE_ 2253 * Returns: 2254 * BCM_E_NONE 2255 * BCM_E_XXX 2256 */ 2257 STATIC int 2258 _bcm_esw_time_capture_get (int unit, bcm_time_if_t id, bcm_time_capture_t *time, uint32 flags) 2259 { 2260 uint32 regval, orgval; /* To keep register value */ 2261 int hw_complete; /* HW read completion indicator*/ 2262 soc_timeout_t timeout; /* Timeout in case of HW error */ 2263 #if defined(BCM_GREYHOUND_SUPPORT) 2264 uint32 lower, upper; 2265 #endif 2266 2267 #if defined(BCM_TIME_V3_OR_IPROC_MANAGED_BROADSYNC) 2268 if (SOC_HAS_TIME_V3_OR_IPROC_MANAGED_BROADSYNC(unit)) { 2269 /* Read capture mode */ 2270 if (SOC_IS_TOMAHAWK3(unit) || SOC_IS_MONTEREY(unit)) { 2271 uint32 lower, upper; 2272 READ_NS_MISC_CLK_EVENT_CTRLr(unit, ®val); 2273 orgval = soc_reg_field_get(unit, NS_MISC_CLK_EVENT_CTRLr, 2274 regval, ENABLEf); 2275 if (flags == BCM_TIME_CAPTURE_IMMEDIATE || orgval == TIME_CAPTURE_MODE_DISABLE || 2276 orgval == TIME_CAPTURE_MODE_IMMEDIATE) { 2277 /* do an immediate capture */ 2278 READ_NS_TIMESYNC_TS0_TIMESTAMP_UPPER_STATUSr(unit, ®val); 2279 upper = regval; 2280 READ_NS_TIMESYNC_TS0_TIMESTAMP_LOWER_STATUSr(unit, ®val); 2281 lower = regval; 2282 /* Discard 4bits from lower*/ 2283 lower = (lower >> 4); 2284 lower = (lower & 0x0FFFFFFF) | ((upper & 0xF) << 28); 2285 upper = (upper >> 4); 2286 2287 if (soc_feature(unit, soc_feature_timesync_timestampingmode)) { 2288 /* 48-bit timestamping supported */ 2289 uint64 time_val, secs, nano_secs; 2290 uint64 div; 2291 /* Get the 48-bit timestamp value */ 2292 COMPILER_64_SET(time_val, upper, lower); 2293 /* Get seconds from the timestamp value */ 2294 secs = time_val; 2295 COMPILER_64_SET(div, 0, 1000000000); 2296 COMPILER_64_UDIV_64(secs, div); 2297 time->synchronous.seconds = secs; 2298 2299 /* Get nanoseconds from the timestamp value */ 2300 nano_secs = time_val; 2301 COMPILER_64_UMUL_32(secs, 1000000000); 2302 COMPILER_64_SUB_64(nano_secs, secs); 2303 time->synchronous.nanoseconds = COMPILER_64_LO(nano_secs); 2304 } else { 2305 COMPILER_64_SET(time->synchronous.seconds, 0, lower / 1000000000); 2306 time->synchronous.nanoseconds = lower % 1000000000; 2307 } 2308 2309 /* For backward compatibility */ 2310 time->free = time->synchronous; 2311 time->syntonous = time->synchronous; 2312 time->flags |= BCM_TIME_CAPTURE_IMMEDIATE; 2313 return BCM_E_NONE; 2314 } else { 2315 2316 /* If any trigger condition is set, get the timestamp from FIFO */ 2317 return _bcm_esw_time_capture_counter_read(unit, id, time); 2318 } 2319 } 2320 #if defined(BCM_GREYHOUND_SUPPORT) 2321 if (flags == BCM_TIME_CAPTURE_IMMEDIATE) { 2322 /* do an immediate capture */ 2323 READ_CMIC_TIMESYNC_TS0_FREQ_CTRL_LOWERr(unit, ®val); 2324 lower = regval; 2325 READ_CMIC_TIMESYNC_TS0_FREQ_CTRL_UPPERr(unit, ®val); 2326 upper = regval; 2327 if (soc_feature(unit, soc_feature_timesync_timestampingmode)) { 2328 /* 48-bit timestamping supported */ 2329 uint64 time_val, secs, nano_secs; 2330 uint64 div; 2331 /* Get the 48-bit timestamp value */ 2332 COMPILER_64_SET(time_val, upper, lower); 2333 /* Get seconds from the timestamp value */ 2334 secs = time_val; 2335 COMPILER_64_SET(div, 0, 1000000000); 2336 COMPILER_64_UDIV_64(secs, div); 2337 time->synchronous.seconds = secs; 2338 2339 /* Get nanoseconds from the timestamp value */ 2340 nano_secs = time_val; 2341 COMPILER_64_UMUL_32(secs, 1000000000); 2342 COMPILER_64_SUB_64(nano_secs, secs); 2343 time->synchronous.nanoseconds = COMPILER_64_LO(nano_secs); 2344 } else { 2345 COMPILER_64_SET(time->synchronous.seconds, 0, lower / 1000000000); 2346 time->synchronous.nanoseconds = lower % 1000000000; 2347 } 2348 2349 /* For backward compatibility */ 2350 time->free = time->synchronous; 2351 time->syntonous = time->synchronous; 2352 return BCM_E_NONE; 2353 } 2354 #endif 2355 READ_CMIC_TIMESYNC_TIME_CAPTURE_MODEr(unit, ®val); 2356 orgval = soc_reg_field_get(unit, CMIC_TIMESYNC_TIME_CAPTURE_MODEr, 2357 regval, TIME_CAPTURE_MODEf); 2358 2359 /* If any trigger condition is set, get the timestamp from FIFO */ 2360 if ((orgval != TIME_CAPTURE_MODE_DISABLE) && 2361 (orgval != TIME_CAPTURE_MODE_IMMEDIATE)) { 2362 return _bcm_esw_time_capture_counter_read(unit, id, time); 2363 } 2364 /* Make sure timestamp capture is enabled */ 2365 READ_CMIC_TIMESYNC_TIME_CAPTURE_CONTROLr(unit, ®val); 2366 if (0 == soc_reg_field_get(unit, CMIC_TIMESYNC_TIME_CAPTURE_CONTROLr, 2367 regval, TIME_CAPTURE_ENABLEf)) { 2368 soc_reg_field_set(unit, CMIC_TIMESYNC_TIME_CAPTURE_CONTROLr, 2369 ®val, TIME_CAPTURE_ENABLEf, 1 ); 2370 WRITE_CMIC_TIMESYNC_TIME_CAPTURE_CONTROLr(unit, regval); 2371 } 2372 2373 /* Clear the FIFO if not empty */ 2374 for(;;) { 2375 READ_CMIC_TIMESYNC_CAPTURE_STATUS_1r(unit, ®val); 2376 if (0 == soc_reg_field_get(unit, CMIC_TIMESYNC_CAPTURE_STATUS_1r, 2377 regval, FIFO_DEPTHf)) { 2378 break; 2379 } 2380 /* There is still something in the FIFO, pop it */ 2381 READ_CMIC_TIMESYNC_INPUT_TIME_FIFO_TS_LOWERr(unit, ®val); 2382 READ_CMIC_TIMESYNC_INPUT_TIME_FIFO_TS_UPPERr(unit, ®val); 2383 } 2384 2385 /* Make sure the capture status is cleared */ 2386 READ_CMIC_TIMESYNC_CAPTURE_STATUS_1r(unit, ®val); 2387 if (regval != 0) { 2388 soc_reg_field_set(unit, CMIC_TIMESYNC_CAPTURE_STATUS_CLR_1r, 2389 ®val, TIME_CAPTURE_COMPLETE_CLRf, 1); 2390 soc_reg_field_set(unit, CMIC_TIMESYNC_CAPTURE_STATUS_CLR_1r, 2391 ®val, FIFO_WRITE_COMPLETE_CLRf, 1); 2392 WRITE_CMIC_TIMESYNC_CAPTURE_STATUS_CLR_1r(unit, regval); 2393 } 2394 2395 /* Program HW to capture time immediately */ 2396 READ_CMIC_TIMESYNC_TIME_CAPTURE_MODEr(unit, ®val); 2397 soc_reg_field_set(unit, CMIC_TIMESYNC_TIME_CAPTURE_MODEr, ®val, 2398 TIME_CAPTURE_MODEf, TIME_CAPTURE_MODE_IMMEDIATE); 2399 WRITE_CMIC_TIMESYNC_TIME_CAPTURE_MODEr(unit, regval); 2400 2401 /* Wait for HW time capture completion */ 2402 hw_complete = 0; 2403 soc_timeout_init(&timeout, BROAD_SYNC_TIME_CAPTURE_TIMEOUT, 0); 2404 while (!hw_complete) { 2405 READ_CMIC_TIMESYNC_CAPTURE_STATUS_1r(unit, ®val); 2406 hw_complete = soc_reg_field_get(unit, CMIC_TIMESYNC_CAPTURE_STATUS_1r, 2407 regval, TIME_CAPTURE_COMPLETEf); 2408 if (soc_timeout_check(&timeout)) { 2409 return (BCM_E_TIMEOUT); 2410 } 2411 } 2412 2413 /* Program HW to disable time capture */ 2414 READ_CMIC_TIMESYNC_TIME_CAPTURE_MODEr(unit, ®val); 2415 soc_reg_field_set(unit, CMIC_TIMESYNC_TIME_CAPTURE_MODEr, ®val, 2416 TIME_CAPTURE_MODEf, TIME_CAPTURE_MODE_DISABLE); 2417 WRITE_CMIC_TIMESYNC_TIME_CAPTURE_MODEr(unit, regval); 2418 2419 /* Read the HW time */ 2420 BCM_IF_ERROR_RETURN( 2421 _bcm_esw_time_capture_counter_read(unit, id, time)); 2422 2423 } else 2424 #endif /* BCM_TIME_V3_OR_IPROC_MANAGED_BROADSYNC */ 2425 #if (defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_TRIDENT2_SUPPORT)) 2426 if (SOC_IS_KATANA(unit) || SOC_IS_TRIUMPH3(unit) || 2427 SOC_IS_TD2_TT2(unit)) { 2428 /* Read capture mode */ 2429 READ_CMIC_TS_TIME_CAPTURE_CTRLr(unit, ®val); 2430 /* If any trigger condition is set, get the timestamp from FIFO */ 2431 if (TIME_CAPTURE_MODE_DISABLE != soc_reg_field_get(unit, 2432 CMIC_TS_TIME_CAPTURE_CTRLr, regval, TIME_CAPTURE_MODEf) ) { 2433 return _bcm_esw_time_capture_counter_read(unit, id, time); 2434 } 2435 2436 /* if different than interrupt remember original capture mode */ 2437 orgval = regval; 2438 2439 /* Program HW to disable time capture */ 2440 soc_reg_field_set(unit, CMIC_TS_TIME_CAPTURE_CTRLr, ®val, 2441 TIME_CAPTURE_MODEf, TIME_CAPTURE_MODE_DISABLE); 2442 if (orgval != regval) { 2443 WRITE_CMIC_TS_TIME_CAPTURE_CTRLr(unit, regval); 2444 } 2445 2446 /* Make sure timestamp capture is enabled */ 2447 READ_CMIC_TS_TIME_CAPTURE_CTRLr(unit, ®val); 2448 if (0 == soc_reg_field_get(unit, CMIC_TS_TIME_CAPTURE_CTRLr, 2449 regval, TIME_CAPTURE_ENABLEf)) { 2450 soc_reg_field_set(unit, CMIC_TS_TIME_CAPTURE_CTRLr, 2451 ®val, TIME_CAPTURE_ENABLEf, 1 ); 2452 WRITE_CMIC_TS_TIME_CAPTURE_CTRLr(unit, regval); 2453 } 2454 2455 /* Clear the FIFO if not empty */ 2456 for(;;) { 2457 READ_CMIC_TS_CAPTURE_STATUSr(unit, ®val); 2458 if (0 == soc_reg_field_get(unit, CMIC_TS_CAPTURE_STATUSr, 2459 regval, FIFO_DEPTHf)) { 2460 break; 2461 } 2462 /* There is still something in the FIFO, pop it */ 2463 READ_CMIC_TS_INPUT_TIME_FIFO_TSr(unit, ®val); 2464 } 2465 2466 /* Make sure the capture status is cleared */ 2467 READ_CMIC_TS_CAPTURE_STATUSr(unit, ®val); 2468 if (regval != 0) { 2469 soc_reg_field_set(unit, CMIC_TS_CAPTURE_STATUS_CLRr, 2470 ®val, TIME_CAPTURE_COMPLETE_CLRf, 1); 2471 soc_reg_field_set(unit, CMIC_TS_CAPTURE_STATUS_CLRr, 2472 ®val, FIFO_WRITE_COMPLETE_CLRf, 1); 2473 WRITE_CMIC_TS_CAPTURE_STATUS_CLRr(unit, regval); 2474 } 2475 2476 /* Program HW to capture time immediately */ 2477 READ_CMIC_TS_TIME_CAPTURE_CTRLr(unit, ®val); 2478 soc_reg_field_set(unit, CMIC_TS_TIME_CAPTURE_CTRLr, ®val, 2479 TIME_CAPTURE_MODEf,TIME_CAPTURE_MODE_IMMEDIATE); 2480 WRITE_CMIC_TS_TIME_CAPTURE_CTRLr(unit, regval); 2481 2482 /* Wait for HW time capture completion */ 2483 hw_complete = 0; 2484 soc_timeout_init(&timeout, BROAD_SYNC_TIME_CAPTURE_TIMEOUT, 0); 2485 2486 while (!hw_complete) { 2487 READ_CMIC_TS_CAPTURE_STATUSr(unit, ®val); 2488 hw_complete = soc_reg_field_get(unit, CMIC_TS_CAPTURE_STATUSr, 2489 regval, TIME_CAPTURE_COMPLETEf); 2490 if (soc_timeout_check(&timeout)) { 2491 return (BCM_E_TIMEOUT); 2492 } 2493 } 2494 2495 /* Read the HW time */ 2496 BCM_IF_ERROR_RETURN( 2497 _bcm_esw_time_capture_counter_read(unit, id, time)); 2498 2499 /* Program HW to original time capture value */ 2500 WRITE_CMIC_TS_TIME_CAPTURE_CTRLr(unit, orgval); 2501 2502 } else 2503 #endif /* defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_TRIDENT2_SUPPORT) */ 2504 { 2505 /* Read capture mode */ 2506 READ_CMIC_BS_CAPTURE_CTRLr(unit, ®val); 2507 /* If in interrupt mode, return time captured on last interrupt */ 2508 if (TIME_CAPTURE_MODE_HEARTBEAT == soc_reg_field_get(unit, 2509 CMIC_BS_CAPTURE_CTRLr, regval, TIME_CAPTURE_MODEf)) { 2510 return _bcm_esw_time_capture_counter_read(unit, id, time); 2511 } 2512 /* if different than interrupt remember original capture mode */ 2513 orgval = regval; 2514 2515 /* Program HW to disable time capture */ 2516 soc_reg_field_set(unit, CMIC_BS_CAPTURE_CTRLr, ®val, TIME_CAPTURE_MODEf, 2517 TIME_CAPTURE_MODE_DISABLE); 2518 if (orgval != regval) { 2519 WRITE_CMIC_BS_CAPTURE_CTRLr(unit, regval); 2520 } 2521 2522 /* Program HW to capture time immediately */ 2523 soc_reg_field_set(unit, CMIC_BS_CAPTURE_CTRLr, ®val, TIME_CAPTURE_MODEf, 2524 TIME_CAPTURE_MODE_IMMEDIATE); 2525 WRITE_CMIC_BS_CAPTURE_CTRLr(unit, regval); 2526 2527 /* Wait for HW time capture completion */ 2528 hw_complete = 0; 2529 soc_timeout_init(&timeout, BROAD_SYNC_TIME_CAPTURE_TIMEOUT, 0); 2530 2531 while (!hw_complete) { 2532 READ_CMIC_BS_CAPTURE_STATUSr(unit, ®val); 2533 hw_complete = soc_reg_field_get(unit, CMIC_BS_CAPTURE_STATUSr, regval, 2534 TIME_CAPTURE_COMPLETEf); 2535 if (soc_timeout_check(&timeout)) { 2536 return (BCM_E_TIMEOUT); 2537 } 2538 } 2539 /* Read the HW time */ 2540 BCM_IF_ERROR_RETURN( 2541 _bcm_esw_time_capture_counter_read(unit, id, time)); 2542 2543 /* Program HW to original time capture value */ 2544 WRITE_CMIC_BS_CAPTURE_CTRLr(unit, orgval); 2545 } 2546 2547 return BCM_E_NONE; 2548 } 2549 2550 /* 2551 * Function: 2552 * _bcm_esw_time_interface_offset_get 2553 * Purpose: 2554 * Internal routine to read HW offset value and convert it into 2555 * bcm_time_spec_t structure 2556 * Parameters: 2557 * unit - (IN) StrataSwitch Unit #. 2558 * id - (IN) Time interface identifier 2559 * offset - (OUT) Time interface offset 2560 * Returns: 2561 * BCM_E_NONE 2562 * BCM_E_XXX 2563 */ 2564 STATIC int 2565 _bcm_esw_time_interface_offset_get(int unit, bcm_time_if_t id, 2566 bcm_time_spec_t *offset) 2567 { 2568 uint32 regval, sec, epoch; 2569 2570 #if defined(BCM_TIME_V3_SUPPORT) 2571 /* Not supported in 3rd generation time arch */ 2572 if (soc_feature(unit, soc_feature_time_v3)) { 2573 return BCM_E_UNAVAIL; 2574 } 2575 #endif /* defined(BCM_TIME_V3_SUPPORT) */ 2576 2577 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_TRIDENT2_SUPPORT) 2578 /* Katana does not support clock offset */ 2579 if (SOC_IS_KATANAX(unit) || SOC_IS_TRIUMPH3(unit) || 2580 SOC_IS_TD2_TT2(unit)) { 2581 return BCM_E_UNAVAIL; 2582 } 2583 #endif /* defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_TRIDENT2_SUPPORT) */ 2584 2585 READ_CMIC_BS_OFFSET_ADJUST_0r(unit, ®val); 2586 sec = soc_reg_field_get(unit, CMIC_BS_OFFSET_ADJUST_0r, regval, SECONDf); 2587 READ_CMIC_BS_OFFSET_ADJUST_1r(unit, ®val); 2588 offset->nanoseconds= soc_reg_field_get(unit, CMIC_BS_OFFSET_ADJUST_1r, 2589 regval, NSf); 2590 offset->isnegative = soc_reg_field_get(unit, CMIC_BS_OFFSET_ADJUST_1r, 2591 regval, SIGN_BITf); 2592 /* If the epoch was installed read it */ 2593 READ_CMIC_BS_CONFIGr(unit, ®val); 2594 epoch = soc_reg_field_get(unit,CMIC_BS_CONFIGr, regval, EPOCHf); 2595 2596 COMPILER_64_SET(offset->seconds, epoch, sec); 2597 2598 return (BCM_E_NONE); 2599 } 2600 2601 /* 2602 * Function: 2603 * _bcm_esw_time_interface_drift_get 2604 * Purpose: 2605 * Internal routine to read HW drift value and convert it into 2606 * bcm_time_spec_t structure 2607 * Parameters: 2608 * unit - (IN) StrataSwitch Unit #. 2609 * id - (IN) Time interface identifier 2610 * drift - (OUT) Time interface drift 2611 * Returns: 2612 * BCM_E_NONE 2613 * BCM_E_XXX 2614 */ 2615 STATIC int 2616 _bcm_esw_time_interface_drift_get(int unit, bcm_time_if_t id, 2617 bcm_time_spec_t *drift) 2618 { 2619 uint32 regval, val, ns; 2620 2621 #if defined(BCM_TIME_V3_SUPPORT) 2622 /* Not supported in 3rd generation time arch */ 2623 if (soc_feature(unit, soc_feature_time_v3)) { 2624 return BCM_E_UNAVAIL; 2625 } 2626 #endif /* defined(BCM_TIME_V3_SUPPORT) */ 2627 2628 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_TRIDENT2_SUPPORT) 2629 /* Katana does not support clock drift */ 2630 if (SOC_IS_KATANAX(unit) || SOC_IS_TRIUMPH3(unit) || 2631 SOC_IS_TD2_TT2(unit)) { 2632 return BCM_E_UNAVAIL; 2633 } 2634 #endif /* defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_TRIDENT2_SUPPORT) */ 2635 2636 2637 READ_CMIC_BS_DRIFT_RATEr(unit, ®val); 2638 val = soc_reg_field_get(unit, CMIC_BS_DRIFT_RATEr, regval, FRAC_NSf); 2639 2640 ns = (val / 8); 2641 2642 drift->nanoseconds = (ns > TIME_DRIFT_MAX) ? TIME_DRIFT_MAX : ns; 2643 2644 drift->isnegative = soc_reg_field_get(unit, CMIC_BS_DRIFT_RATEr, 2645 regval, SIGNf); 2646 return (BCM_E_NONE); 2647 } 2648 2649 #if defined(BCM_TIME_MANAGED_BROADSYNC) 2650 /* 2651 * Function: 2652 * _bcm_esw_time_interface_ref_clock_get 2653 * Purpose: 2654 * Internal routine to read ref clock divisor 2655 * Parameters: 2656 * unit - (IN) StrataSwitch Unit #. 2657 * id - (IN) Time interface identifier 2658 * divisor - (OUT) Time interface ref clock resolution 2659 * Returns: 2660 * BCM_E_NONE 2661 * BCM_E_XXX 2662 */ 2663 STATIC int 2664 _bcm_esw_time_interface_ref_clock_get(int unit, bcm_time_if_t id, 2665 int *clk_resolution) 2666 { 2667 uint32 regval, val, hdiv = 0; 2668 2669 #if defined(BCM_TIME_V3_OR_IPROC_MANAGED_BROADSYNC) 2670 if (SOC_HAS_TIME_V3_OR_IPROC_MANAGED_BROADSYNC(unit)) { 2671 if (SOC_IS_TOMAHAWK3(unit) || SOC_IS_MONTEREY(unit)) { 2672 READ_NS_BROADSYNC_REF_CLK_GEN_CTRLr(unit, ®val); 2673 val = soc_reg_field_get(unit, NS_BROADSYNC_REF_CLK_GEN_CTRLr, 2674 regval, ENABLEf); 2675 hdiv = soc_reg_field_get(unit, NS_BROADSYNC_REF_CLK_GEN_CTRLr, 2676 regval, DIVISORf); 2677 } else { 2678 READ_CMIC_BROADSYNC_REF_CLK_GEN_CTRLr(unit, ®val); 2679 val = soc_reg_field_get(unit, CMIC_BROADSYNC_REF_CLK_GEN_CTRLr, 2680 regval, ENABLEf); 2681 hdiv = soc_reg_field_get(unit, CMIC_BROADSYNC_REF_CLK_GEN_CTRLr, 2682 regval, DIVISORf); 2683 } 2684 } else 2685 #endif /* BCM_TIME_V3_OR_IPROC_MANAGED_BROADSYNC */ 2686 { 2687 READ_CMIC_BS_REF_CLK_GEN_CTRLr(unit, ®val); 2688 val = soc_reg_field_get(unit, CMIC_BS_REF_CLK_GEN_CTRLr, regval, 2689 ENABLEf); 2690 hdiv = soc_reg_field_get(unit, CMIC_BS_REF_CLK_GEN_CTRLr, regval, 2691 DIVISORf); 2692 } 2693 2694 if (val) { 2695 /* Divisor is half period for reference clock */ 2696 *clk_resolution = TIME_TS_CLK_FREQUENCY_40NS / (hdiv * 2); 2697 } else { 2698 *clk_resolution = 0; 2699 } 2700 2701 return (BCM_E_NONE); 2702 } 2703 #endif /*BCM_TIME_MANAGED_BROADSYNC */ 2704 2705 /* 2706 * Function: 2707 * _bcm_esw_time_interface_accuracy_get 2708 * Purpose: 2709 * Internal routine to read HW accuracy value and convert it into 2710 * bcm_time_spec_t structure 2711 * Parameters: 2712 * unit - (IN) StrataSwitch Unit #. 2713 * id - (IN) Time interface identifier 2714 * accuracy - (OUT) Time interface accuracy 2715 * Returns: 2716 * BCM_E_NONE 2717 * BCM_E_XXX 2718 */ 2719 STATIC int 2720 _bcm_esw_time_interface_accuracy_get(int unit, bcm_time_if_t id, 2721 bcm_time_spec_t *accuracy) 2722 { 2723 uint32 regval, val; 2724 2725 #if defined(BCM_TIME_V3_OR_IPROC_MANAGED_BROADSYNC) 2726 if (SOC_HAS_TIME_V3_OR_IPROC_MANAGED_BROADSYNC(unit)) { 2727 if (SOC_IS_TOMAHAWK3(unit) || SOC_IS_MONTEREY(unit)) { 2728 READ_NS_BS0_BS_OUTPUT_TIME_0r(unit, ®val); 2729 val = soc_reg_field_get(unit, NS_BS0_BS_OUTPUT_TIME_0r, regval, ACCURACYf); 2730 } else { 2731 READ_CMIC_BS0_OUTPUT_TIME_0r(unit, ®val); 2732 val = soc_reg_field_get(unit, CMIC_BS0_OUTPUT_TIME_0r, regval, ACCURACYf); 2733 } 2734 } else 2735 #endif /* BCM_TIME_V3_OR_IPROC_MANAGED_BROADSYNC */ 2736 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_TRIDENT2_SUPPORT) 2737 if (SOC_IS_KATANAX(unit) || SOC_IS_TRIUMPH3(unit) || 2738 SOC_IS_TD2_TT2(unit)) { 2739 READ_CMIC_BS_OUTPUT_TIME_0r(unit, ®val); 2740 val = soc_reg_field_get(unit, CMIC_BS_OUTPUT_TIME_0r, regval, ACCURACYf); 2741 } else 2742 #endif /* defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_TRIDENT2_SUPPORT) */ 2743 { 2744 READ_CMIC_BS_CONFIGr(unit, ®val); 2745 val = soc_reg_field_get(unit, CMIC_BS_CONFIGr, regval, ACCURACYf); 2746 } 2747 2748 return _bcm_esw_time_accuracy_parse(unit, val, accuracy); 2749 } 2750 2751 /* 2752 * Function: 2753 * _bcm_esw_time_interface_get 2754 * Purpose: 2755 * Internal routine to get a time sync interface by id 2756 * Parameters: 2757 * unit - (IN) StrataSwitch Unit #. 2758 * id - (IN) Time interface identifier 2759 * intf - (IN/OUT) Time Sync Interface to get 2760 * Returns: 2761 * BCM_E_NONE 2762 * BCM_E_XXX 2763 */ 2764 STATIC int 2765 _bcm_esw_time_interface_get(int unit, bcm_time_if_t id, bcm_time_interface_t *intf) 2766 { 2767 uint32 regval; 2768 bcm_time_interface_t *intf_ptr; 2769 uint32 orig_flags; 2770 2771 intf_ptr = TIME_INTERFACE(unit, id); 2772 orig_flags = intf_ptr->flags; 2773 2774 intf_ptr->flags = intf->flags; 2775 intf_ptr->id = id; 2776 if (SOC_IS_TOMAHAWK3(unit) || SOC_IS_MONTEREY(unit)) { 2777 READ_NS_BS0_BS_CONFIGr(unit, ®val); 2778 /* Update output flags */ 2779 if (TIME_MODE_INPUT == soc_reg_field_get(unit, NS_BS0_BS_CONFIGr, 2780 regval, MODEf)) { 2781 intf_ptr->flags |= BCM_TIME_INPUT; 2782 } else { 2783 intf_ptr->flags &= ~BCM_TIME_INPUT; 2784 } 2785 } else { 2786 READ_CMIC_BS_CONFIGr(unit, ®val); 2787 2788 /* Update output flags */ 2789 if (TIME_MODE_INPUT == soc_reg_field_get(unit, CMIC_BS_CONFIGr, 2790 regval, MODEf)) { 2791 intf_ptr->flags |= BCM_TIME_INPUT; 2792 } else { 2793 intf_ptr->flags &= ~BCM_TIME_INPUT; 2794 } 2795 } 2796 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_TRIDENT2_SUPPORT) 2797 if (SOC_IS_KATANAX(unit) || SOC_IS_TRIUMPH3(unit) || 2798 SOC_IS_TD2_TT2(unit)) { 2799 if (soc_reg_field_get(unit, CMIC_BS_CONFIGr, 2800 regval, BS_CLK_OUTPUT_ENABLEf)) { 2801 intf_ptr->flags |= BCM_TIME_ENABLE; 2802 } else { 2803 intf_ptr->flags &= ~BCM_TIME_ENABLE; 2804 } 2805 2806 READ_CMIC_BS_OUTPUT_TIME_0r(unit, ®val); 2807 if (soc_reg_field_get(unit, CMIC_BS_OUTPUT_TIME_0r, 2808 regval, LOCKf)) { 2809 intf_ptr->flags |= BCM_TIME_LOCKED; 2810 } else { 2811 intf_ptr->flags &= ~BCM_TIME_LOCKED; 2812 } 2813 } else 2814 #endif /* defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_TRIDENT2_SUPPORT) */ 2815 { 2816 if (SOC_IS_TOMAHAWK3(unit) || SOC_IS_MONTEREY(unit)) { 2817 if (soc_reg_field_get(unit, NS_BS0_BS_CONFIGr, regval, ENABLEf)) { 2818 intf_ptr->flags |= BCM_TIME_ENABLE; 2819 } else { 2820 intf_ptr->flags &= ~BCM_TIME_ENABLE; 2821 } 2822 if (soc_reg_field_get(unit, NS_BS0_BS_CONFIGr, regval, LOCKf)) { 2823 intf_ptr->flags |= BCM_TIME_LOCKED; 2824 } else { 2825 intf_ptr->flags &= ~BCM_TIME_LOCKED; 2826 } 2827 } else { 2828 if (soc_reg_field_get(unit, CMIC_BS_CONFIGr, regval, ENABLEf)) { 2829 intf_ptr->flags |= BCM_TIME_ENABLE; 2830 } else { 2831 intf_ptr->flags &= ~BCM_TIME_ENABLE; 2832 } 2833 if (soc_reg_field_get(unit, CMIC_BS_CONFIGr, regval, LOCKf)) { 2834 intf_ptr->flags |= BCM_TIME_LOCKED; 2835 } else { 2836 intf_ptr->flags &= ~BCM_TIME_LOCKED; 2837 } 2838 } 2839 } 2840 2841 #if defined(INCLUDE_PTP) 2842 if ((orig_flags & BCM_TIME_SYNC_STAMPER) && 2843 (_bcm_ptp_running(unit) == BCM_E_NONE)) { 2844 intf_ptr->flags = orig_flags; 2845 *intf = *intf_ptr; 2846 return BCM_E_NONE; 2847 } 2848 #endif /* INCLUDE_PTP */ 2849 2850 if (intf->flags & BCM_TIME_ACCURACY) { 2851 BCM_IF_ERROR_RETURN( 2852 _bcm_esw_time_interface_accuracy_get(unit, id, 2853 &(intf_ptr->accuracy))); 2854 } 2855 2856 if (intf->flags & BCM_TIME_OFFSET) { 2857 if (orig_flags & BCM_TIME_SYNC_STAMPER) { 2858 2859 } else { 2860 /* Get value from hardware */ 2861 BCM_IF_ERROR_RETURN( 2862 _bcm_esw_time_interface_offset_get(unit, id, &(intf_ptr->offset))); 2863 } 2864 } 2865 2866 if (intf->flags & BCM_TIME_DRIFT) { 2867 if (orig_flags & BCM_TIME_SYNC_STAMPER) { 2868 2869 } else { 2870 /* Get value from hardware */ 2871 BCM_IF_ERROR_RETURN( 2872 _bcm_esw_time_interface_drift_get(unit, id, &(intf_ptr->drift))); 2873 } 2874 } 2875 2876 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_TRIDENT2_SUPPORT) 2877 if (SOC_IS_KATANAX(unit) || SOC_IS_TRIUMPH3(unit) || 2878 SOC_IS_TD2_TT2(unit)) { 2879 if (intf->flags & BCM_TIME_REF_CLOCK) { 2880 BCM_IF_ERROR_RETURN( 2881 _bcm_esw_time_interface_ref_clock_get(unit, id, 2882 &(intf_ptr->clk_resolution))); 2883 } 2884 } 2885 #endif /* defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_TRIDENT2_SUPPORT) */ 2886 2887 if (orig_flags & BCM_TIME_SYNC_STAMPER) { 2888 intf_ptr->flags = orig_flags; 2889 } 2890 2891 *intf = *(TIME_INTERFACE(unit, id)); 2892 2893 return (BCM_E_NONE); 2894 } 2895 2896 #if defined(BCM_TIME_V3_OR_IPROC_MANAGED_BROADSYNC) 2897 STATIC int 2898 _bcm_esw_time_interface_dual_bs_get(int unit, bcm_time_if_t id, bcm_time_interface_t *intf) 2899 { 2900 uint32 regval; 2901 bcm_time_interface_t *intf_ptr; 2902 uint32 orig_flags; 2903 2904 /* Feature unavailable on devices without BroadSync support. */ 2905 if (soc_feature(unit, soc_feature_time_v3_no_bs)) { 2906 return BCM_E_UNAVAIL; 2907 } 2908 2909 intf_ptr = TIME_INTERFACE(unit, id); 2910 orig_flags = intf_ptr->flags; 2911 intf_ptr->flags = intf->flags; 2912 intf_ptr->id = id; 2913 if (SOC_IS_TOMAHAWK3(unit) || SOC_IS_MONTEREY(unit)) { 2914 READ_NS_BS0_BS_CONFIGr(unit, ®val); 2915 2916 /* Update output flags */ 2917 if (TIME_MODE_INPUT == soc_reg_field_get(unit, NS_BS0_BS_CONFIGr, 2918 regval, MODEf)) { 2919 intf_ptr->flags |= BCM_TIME_INPUT; 2920 } else { 2921 intf_ptr->flags &= ~BCM_TIME_INPUT; 2922 } 2923 2924 if (soc_reg_field_get(unit, NS_BS0_BS_CONFIGr, 2925 regval, BS_CLK_OUTPUT_ENABLEf)) { 2926 intf_ptr->flags |= BCM_TIME_ENABLE; 2927 } else { 2928 intf_ptr->flags &= ~BCM_TIME_ENABLE; 2929 } 2930 2931 READ_NS_BS0_BS_OUTPUT_TIME_0r(unit, ®val); 2932 if (soc_reg_field_get(unit, NS_BS0_BS_OUTPUT_TIME_0r, 2933 regval, LOCKf)) { 2934 intf_ptr->flags |= BCM_TIME_LOCKED; 2935 } else { 2936 intf_ptr->flags &= ~BCM_TIME_LOCKED; 2937 } 2938 } else { 2939 READ_CMIC_BS0_CONFIGr(unit, ®val); 2940 2941 /* Update output flags */ 2942 if (TIME_MODE_INPUT == soc_reg_field_get(unit, CMIC_BS0_CONFIGr, 2943 regval, MODEf)) { 2944 intf_ptr->flags |= BCM_TIME_INPUT; 2945 } else { 2946 intf_ptr->flags &= ~BCM_TIME_INPUT; 2947 } 2948 2949 if (soc_reg_field_get(unit, CMIC_BS0_CONFIGr, 2950 regval, BS_CLK_OUTPUT_ENABLEf)) { 2951 intf_ptr->flags |= BCM_TIME_ENABLE; 2952 } else { 2953 intf_ptr->flags &= ~BCM_TIME_ENABLE; 2954 } 2955 2956 READ_CMIC_BS0_OUTPUT_TIME_0r(unit, ®val); 2957 if (soc_reg_field_get(unit, CMIC_BS0_OUTPUT_TIME_0r, 2958 regval, LOCKf)) { 2959 intf_ptr->flags |= BCM_TIME_LOCKED; 2960 } else { 2961 intf_ptr->flags &= ~BCM_TIME_LOCKED; 2962 } 2963 } 2964 2965 2966 #if defined(INCLUDE_PTP) 2967 if (_bcm_ptp_running(unit) == BCM_E_NONE) { 2968 intf_ptr->flags = orig_flags; 2969 *intf = *intf_ptr; 2970 return BCM_E_NONE; 2971 } 2972 #endif /* INCLUDE_PTP */ 2973 2974 if (intf->flags & BCM_TIME_ACCURACY) { 2975 BCM_IF_ERROR_RETURN( 2976 _bcm_esw_time_interface_accuracy_get(unit, id, 2977 &(intf_ptr->accuracy))); 2978 } 2979 2980 if (intf->flags & BCM_TIME_OFFSET) { 2981 if (orig_flags & BCM_TIME_SYNC_STAMPER) { 2982 2983 } else { 2984 /* Get value from hardware */ 2985 BCM_IF_ERROR_RETURN( 2986 _bcm_esw_time_interface_offset_get(unit, id, &(intf_ptr->offset))); 2987 } 2988 } 2989 2990 if (intf->flags & BCM_TIME_DRIFT) { 2991 if (orig_flags & BCM_TIME_SYNC_STAMPER) { 2992 2993 } else { 2994 /* Get value from hardware */ 2995 BCM_IF_ERROR_RETURN( 2996 _bcm_esw_time_interface_drift_get(unit, id, &(intf_ptr->drift))); 2997 } 2998 } 2999 3000 if (intf->flags & BCM_TIME_REF_CLOCK) { 3001 BCM_IF_ERROR_RETURN( 3002 _bcm_esw_time_interface_ref_clock_get(unit, id, 3003 &(intf_ptr->clk_resolution))); 3004 } 3005 3006 if (orig_flags & BCM_TIME_SYNC_STAMPER) { 3007 intf_ptr->flags = orig_flags; 3008 } 3009 3010 *intf = *(TIME_INTERFACE(unit, id)); 3011 3012 return (BCM_E_NONE); 3013 } 3014 #endif /* BCM_TIME_V3_OR_IPROC_MANAGED_BROADSYNC */ 3015 3016 /* 3017 * Function: 3018 * _bcm_esw_time_hw_interrupt_dflt 3019 * Purpose: 3020 * Default handler for broadsync heartbeat interrupt 3021 * Parameters: 3022 * unit - StrataSwitch unit #. 3023 * Returns: 3024 * Nothing 3025 */ 3026 3027 STATIC void 3028 _bcm_esw_time_hw_interrupt_dflt(int unit) 3029 { 3030 uint32 regval; 3031 3032 /* Due to HW constrains we need to reinable the interrupt on every rising */ 3033 /* edge and update the capture mode */ 3034 3035 #if defined(BCM_TIME_V3_OR_IPROC_MANAGED_BROADSYNC) 3036 uint32 intr, mode; 3037 3038 if (soc_feature(unit, soc_feature_time_v3)) { 3039 if (SOC_IS_TOMAHAWK3(unit) || SOC_IS_MONTEREY(unit)) { 3040 3041 return; 3042 } else { 3043 /* Read original values */ 3044 READ_CMIC_TIMESYNC_TIME_CAPTURE_MODEr(unit, &mode); 3045 READ_CMIC_TIMESYNC_TIME_CAPTURE_CONTROLr(unit, ®val); 3046 READ_CMIC_TIMESYNC_INTERRUPT_ENABLEr(unit, &intr); 3047 3048 /* Disable all */ 3049 WRITE_CMIC_TIMESYNC_INTERRUPT_ENABLEr(unit, 0); 3050 WRITE_CMIC_TIMESYNC_TIME_CAPTURE_CONTROLr(unit, 0); 3051 WRITE_CMIC_TIMESYNC_TIME_CAPTURE_MODEr(unit, 0); 3052 3053 /* Enable with the original settings */ 3054 WRITE_CMIC_TIMESYNC_INTERRUPT_ENABLEr(unit, intr); 3055 WRITE_CMIC_TIMESYNC_TIME_CAPTURE_CONTROLr(unit, regval); 3056 WRITE_CMIC_TIMESYNC_TIME_CAPTURE_MODEr(unit, mode); 3057 } 3058 3059 } else 3060 #endif /* BCM_TIME_V3_OR_IPROC_MANAGED_BROADSYNC */ 3061 #if (defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_TRIDENT2_SUPPORT)) 3062 if (SOC_IS_KATANAX(unit) || SOC_IS_TRIUMPH3(unit) || 3063 SOC_IS_TD2_TT2(unit)) { 3064 READ_CMIC_TS_TIME_CAPTURE_CTRLr(unit, ®val); 3065 WRITE_CMIC_TS_TIME_CAPTURE_CTRLr(unit, 0); 3066 WRITE_CMIC_TS_TIME_CAPTURE_CTRLr(unit, regval); 3067 } else 3068 #endif /* defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_TRIDENT2_SUPPORT) */ 3069 { 3070 READ_CMIC_BS_CAPTURE_CTRLr(unit, ®val); 3071 WRITE_CMIC_BS_CAPTURE_CTRLr(unit, 0); 3072 WRITE_CMIC_BS_CAPTURE_CTRLr(unit, regval); 3073 } 3074 return; 3075 } 3076 3077 /* 3078 * Function: 3079 * _bcm_esw_time_hw_interrupt 3080 * Purpose: 3081 * Handles broadsync heartbeat interrupt 3082 * Parameters: 3083 * unit - StrataSwitch unit #. 3084 * Returns: 3085 * Nothing 3086 */ 3087 STATIC void 3088 _bcm_esw_time_hw_interrupt(int unit) 3089 { 3090 void *u_data; 3091 bcm_time_heartbeat_cb u_cb; 3092 int idx; /* interface itterator */ 3093 bcm_time_capture_t time; 3094 3095 for (idx = 0; idx < NUM_TIME_INTERFACE(unit); idx++) { 3096 if (NULL != TIME_INTERFACE(unit, idx) && 3097 NULL != TIME_INTERFACE_CONFIG(unit,idx).user_cb) { 3098 u_cb = TIME_INTERFACE_CONFIG(unit,idx).user_cb->heartbeat_cb; 3099 u_data = TIME_INTERFACE_CONFIG(unit,idx).user_cb->user_data; 3100 _bcm_esw_time_capture_counter_read(unit, idx, &time); 3101 if (NULL != u_cb) { 3102 u_cb(unit, idx, &time, u_data); 3103 } 3104 } 3105 } 3106 3107 _bcm_esw_time_hw_interrupt_dflt(unit); 3108 3109 return; 3110 } 3111 3112 /****************************************************************************/ 3113 /* API functions implementation */ 3114 /****************************************************************************/ 3115 3116 /* 3117 * Function: 3118 * bcm_esw_time_init 3119 * Purpose: 3120 * Initialize time module 3121 * Parameters: 3122 * unit - (IN) StrataSwitch Unit #. 3123 * Returns: 3124 * BCM_E_NONE 3125 * BCM_E_XXX 3126 */ 3127 int 3128 bcm_esw_time_init (int unit) 3129 { 3130 _bcm_time_config_p time_cfg_ptr; /* Pointer to Time module config */ 3131 bcm_time_interface_t *intf; /* Time interfaces iterator. */ 3132 int alloc_sz; /* Memory allocation size. */ 3133 int idx; /* Time interface array iterator */ 3134 int rv; /* Return Value */ 3135 soc_control_t *soc = SOC_CONTROL(unit); /* Soc control structure */ 3136 #if defined(BCM_MONTEREY_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT) 3137 uint32_t regVal = 0; 3138 uint32_t eventId; 3139 #endif 3140 3141 /* Check if time feature is supported on a device */ 3142 if (!soc_feature(unit, soc_feature_time_support)) { 3143 return (BCM_E_UNAVAIL); 3144 } 3145 3146 /* If already initialized then deinitialize time module */ 3147 if (TIME_INIT(unit)) { 3148 _bcm_esw_time_deinit(unit, &TIME_CONFIG(unit)); 3149 } 3150 3151 /* Allocate time config structure. */ 3152 alloc_sz = sizeof(_bcm_time_config_t); 3153 time_cfg_ptr = sal_alloc(alloc_sz, "Time module"); 3154 if (NULL == time_cfg_ptr) { 3155 return (BCM_E_MEMORY); 3156 } 3157 sal_memset(time_cfg_ptr, 0, alloc_sz); 3158 3159 /* Currently only one interface per unit */ 3160 time_cfg_ptr->intf_count = NUM_TIME_INTERFACE(unit); 3161 3162 /* Allocate memory for all time interfaces, supported */ 3163 alloc_sz = time_cfg_ptr->intf_count * sizeof(_bcm_time_interface_config_t); 3164 time_cfg_ptr->intf_arr = sal_alloc(alloc_sz, "Time Interfaces"); 3165 if (NULL == time_cfg_ptr->intf_arr) { 3166 _bcm_esw_time_deinit(unit, &time_cfg_ptr); 3167 return (BCM_E_MEMORY); 3168 } 3169 sal_memset(time_cfg_ptr->intf_arr, 0, alloc_sz); 3170 for (idx = 0; idx < time_cfg_ptr->intf_count; idx++) { 3171 intf = &time_cfg_ptr->intf_arr[idx].time_interface; 3172 intf->id = idx; 3173 } 3174 3175 /* For each time interface allocate memory for tuser_cb */ 3176 alloc_sz = sizeof(_bcm_time_user_cb_t); 3177 for (idx = 0; idx < NUM_TIME_INTERFACE(unit); idx++) { 3178 time_cfg_ptr->intf_arr[idx].user_cb = 3179 sal_alloc(alloc_sz, "Time Interface User Callback"); 3180 if (NULL == time_cfg_ptr->intf_arr[idx].user_cb) { 3181 _bcm_esw_time_deinit(unit, &time_cfg_ptr); 3182 return (BCM_E_MEMORY); 3183 } 3184 sal_memset(time_cfg_ptr->intf_arr[idx].user_cb, 0, alloc_sz); 3185 } 3186 3187 /* Interrupt handling function initialization */ 3188 soc->time_call_ref_count = 0; 3189 soc->soc_time_callout = NULL; 3190 3191 /* Create protection mutex. */ 3192 time_cfg_ptr->mutex = sal_mutex_create("Time mutex"); 3193 if (NULL == time_cfg_ptr->mutex) { 3194 _bcm_esw_time_deinit(unit, &time_cfg_ptr); 3195 return (BCM_E_MEMORY); 3196 } 3197 3198 sal_mutex_take(time_cfg_ptr->mutex, sal_mutex_FOREVER); 3199 3200 TIME_CONFIG(unit) = time_cfg_ptr; 3201 3202 #ifdef BCM_WARM_BOOT_SUPPORT 3203 _bcm_time_scache_alloc(unit); 3204 #endif 3205 3206 /* Clear memories/registers on Cold boot only */ 3207 if (!SOC_WARM_BOOT(unit) && 3208 _bcm_esw_time_hitless_reset(unit, idx) != BCM_E_NONE) { 3209 for (idx = 0; idx < NUM_TIME_INTERFACE(unit); idx++) { 3210 rv = _bcm_esw_time_hw_clear(unit, idx); 3211 if (BCM_FAILURE(rv)) { 3212 TIME_UNLOCK(unit); 3213 _bcm_esw_time_deinit(unit, &time_cfg_ptr); 3214 TIME_CONFIG(unit) = NULL; 3215 return (BCM_E_MEMORY); 3216 } 3217 } 3218 } else { 3219 /* If Warm boot reinitialize module based on HW state */ 3220 #ifdef BCM_WARM_BOOT_SUPPORT 3221 for (idx = 0; idx < NUM_TIME_INTERFACE(unit); idx++) { 3222 rv = _bcm_esw_time_reinit(unit, idx); 3223 if (BCM_FAILURE(rv)) { 3224 TIME_UNLOCK(unit); 3225 _bcm_esw_time_deinit(unit, &time_cfg_ptr); 3226 TIME_CONFIG(unit) = NULL; 3227 return (rv); 3228 } 3229 } 3230 3231 #endif /* BCM_WARM_BOOT_SUPPORT */ 3232 } 3233 #if defined(BCM_MONTEREY_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT) 3234 if (SOC_IS_TOMAHAWK3(unit) || SOC_IS_MONTEREY(unit)) { 3235 /* Set the event ids for Nanosync, both miscellaneous and port events 3236 * i.e, NS_TIMESYNC_TS_EVENT_FWD_CFG - 150 Numels 3237 * NS_TIMESYNC_MAPPER_FWD_CFG - 128 Numels 3238 * 3239 * EventId 0 to 191 for port events for 64-ports 3240 * Events could be RXCDR/RXSOF, ROE, TXSOF/TXPI 3241 * 0, 2, 4...126 -> RXCDR/RXSOF 3242 * 1, 3, 5...127 -> ROE 3243 * 128, 129, 130..191 -> TXSOF/TXPI 3244 */ 3245 3246 /* Set the Miscellaneous event id's */ 3247 eventId = 192; 3248 for (idx = 128; idx < 150; idx++) { 3249 BCM_TIME_READ_NS_REGr(unit, NS_TIMESYNC_TS_EVENT_FWD_CFGr, idx, ®Val); 3250 soc_reg_field_set(unit, NS_TIMESYNC_TS_EVENT_FWD_CFGr, ®Val, EVENT_IDf, eventId); 3251 BCM_TIME_WRITE_NS_REGr(unit, NS_TIMESYNC_TS_EVENT_FWD_CFGr, idx, regVal); 3252 eventId++; 3253 } 3254 3255 3256 } 3257 3258 /* Check availability of TS FIFO to host */ 3259 tsfifo_flag = soc_property_get(unit, "tsfifo_available_flag", 0); 3260 #endif 3261 3262 TIME_UNLOCK(unit); 3263 3264 return (BCM_E_NONE); 3265 } 3266 3267 /* 3268 * Function: 3269 * bcm_esw_time_deinit 3270 * Purpose: 3271 * Uninitialize time module 3272 * Parameters: 3273 * unit - (IN) StrataSwitch Unit #. 3274 * Returns: 3275 * BCM_E_NONE 3276 * BCM_E_XXX 3277 */ 3278 int 3279 bcm_esw_time_deinit (int unit) 3280 { 3281 /* Chek if time feature is supported on a device */ 3282 if (!soc_feature(unit, soc_feature_time_support)) { 3283 return (BCM_E_UNAVAIL); 3284 } 3285 3286 if (0 == TIME_INIT(unit)) { 3287 return (BCM_E_INIT); 3288 } 3289 3290 return _bcm_esw_time_deinit(unit, &TIME_CONFIG(unit)); 3291 } 3292 3293 static int _bcm_time_interface_traverse_cb(int unit, 3294 bcm_time_interface_t *intf, void *user_data) 3295 { 3296 uint8 *ptr = (uint8 *)user_data; 3297 if (intf->flags & BCM_TIME_SYNC_STAMPER) { 3298 *ptr = 1; 3299 } else { 3300 *ptr = 0; 3301 } 3302 return BCM_E_NONE; 3303 } 3304 3305 /* 3306 * Function: 3307 * bcm_esw_time_bs_log_config_set 3308 * Purpose: 3309 * Configure Broadsync logging 3310 * Parameters: 3311 * unit - (IN) StrataSwitch Unit #. 3312 * Returns: 3313 * BCM_E_NONE 3314 * BCM_E_XXX 3315 */ 3316 int 3317 bcm_esw_time_bs_log_configure_set (int unit, bcm_time_bs_log_cfg_t bs_log_cfg) 3318 { 3319 uint8 bs_initialized=0; 3320 3321 /* Chek if time feature is supported on a device */ 3322 if (!soc_feature(unit, soc_feature_time_support)) { 3323 return (BCM_E_UNAVAIL); 3324 } 3325 3326 if (!SOC_UNIT_VALID(unit)) { 3327 return BCM_E_UNIT; 3328 } 3329 3330 bcm_esw_time_interface_traverse(unit, _bcm_time_interface_traverse_cb, 3331 (void*)&bs_initialized); 3332 if (!bs_initialized) { 3333 return BCM_E_INIT; 3334 } 3335 3336 _bcm_time_bs_debug(bs_log_cfg.debug_mask); 3337 3338 return _bcm_time_bs_log_configure(unit, bs_log_cfg.debug_mask, 3339 bs_log_cfg.udp_log_mask, bs_log_cfg.src_mac, 3340 bs_log_cfg.dest_mac, bs_log_cfg.tpid, bs_log_cfg.vid, 3341 bs_log_cfg.ttl, bs_log_cfg.src_addr, bs_log_cfg.dest_addr, 3342 bs_log_cfg.udp_port); 3343 } 3344 3345 /* 3346 * Function: 3347 * bcm_esw_time_bs_log_config_get 3348 * Purpose: 3349 * Configure Broadsync logging 3350 * Parameters: 3351 * unit - (IN) StrataSwitch Unit #. 3352 * Returns: 3353 * BCM_E_NONE 3354 * BCM_E_XXX 3355 */ 3356 int 3357 bcm_esw_time_bs_log_configure_get (int unit, bcm_time_bs_log_cfg_t *bs_log_cfg) 3358 { 3359 uint8 bs_initialized=0; 3360 3361 /* Chek if time feature is supported on a device */ 3362 if (!soc_feature(unit, soc_feature_time_support)) { 3363 return (BCM_E_UNAVAIL); 3364 } 3365 3366 if (!SOC_UNIT_VALID(unit)) { 3367 return BCM_E_UNIT; 3368 } 3369 3370 bcm_esw_time_interface_traverse(unit, _bcm_time_interface_traverse_cb, 3371 (void*)&bs_initialized); 3372 if (!bs_initialized) { 3373 return BCM_E_INIT; 3374 } 3375 3376 return _bcm_time_bs_log_configure_get(unit, bs_log_cfg); 3377 3378 } 3379 3380 /* 3381 * Function: 3382 * bcm_esw_time_interface_add 3383 * Purpose: 3384 * Adding a time sync interface to a specified unit 3385 * Parameters: 3386 * unit - (IN) StrataSwitch Unit #. 3387 * intf - (IN/OUT) Time Sync Interface 3388 * Returns: 3389 * BCM_E_NONE 3390 * BCM_E_XXX 3391 */ 3392 int 3393 bcm_esw_time_interface_add (int unit, bcm_time_interface_t *intf) 3394 { 3395 int rv = BCM_E_NONE; /* Return value */ 3396 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_TRIDENT2_SUPPORT) || \ 3397 defined(BCM_HELIX4_SUPPORT) || defined(BCM_KATANA2_SUPPORT) || defined(BCM_HURRICANE2_SUPPORT) || \ 3398 defined(BCM_GREYHOUND_SUPPORT) || defined(BCM_SABER2_SUPPORT) || defined(BCM_TOMAHAWK_SUPPORT) 3399 int replacing = 0; 3400 int reset_hardware = 0; 3401 #endif 3402 3403 if (!SOC_UNIT_VALID(unit)) { 3404 return BCM_E_UNIT; 3405 } 3406 3407 /* Check if time feature is supported on a device */ 3408 if (!soc_feature(unit, soc_feature_time_support)) { 3409 return (BCM_E_UNAVAIL); 3410 } 3411 3412 BCM_IF_ERROR_RETURN( 3413 _bcm_esw_time_interface_input_validate(unit, intf)); 3414 3415 if (TIME_CONFIG(unit) == NULL) { 3416 return (BCM_E_INIT); 3417 } 3418 3419 TIME_LOCK(unit); 3420 if (intf->flags & BCM_TIME_WITH_ID) { 3421 /* If interface already been in use */ 3422 if (0 != TIME_INTERFACE_CONFIG_REF_COUNT(unit, intf->id)) { 3423 if (0 == (intf->flags & BCM_TIME_REPLACE)) { 3424 TIME_UNLOCK(unit); 3425 return BCM_E_EXISTS; 3426 } 3427 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_TRIDENT2_SUPPORT) || \ 3428 defined(BCM_HELIX4_SUPPORT) || defined(BCM_KATANA2_SUPPORT) || defined(BCM_HURRICANE2_SUPPORT) || \ 3429 defined(BCM_GREYHOUND_SUPPORT) || defined(BCM_SABER2_SUPPORT) || defined(BCM_TOMAHAWK_SUPPORT) 3430 replacing = 1; 3431 #endif 3432 } else { 3433 TIME_INTERFACE_CONFIG_REF_COUNT(unit, intf->id) = 1; 3434 } 3435 } else { 3436 rv = _bcm_esw_time_interface_allocate_id(unit, &(intf->id)); 3437 if (BCM_FAILURE(rv)) { 3438 TIME_UNLOCK(unit); 3439 return rv; 3440 } 3441 } 3442 3443 #if defined(BCM_TIME_MANAGED_BROADSYNC) 3444 if (intf->flags & BCM_TIME_SYNC_STAMPER) { 3445 #if defined(INCLUDE_PTP) 3446 if (_bcm_ptp_running(unit) == BCM_E_NONE) { 3447 /* Unit is running PTP, so let PTP firmware know if timecodes should be output */ 3448 int tc_output_enable = 0; 3449 int locked = 0; 3450 int include_servo_offset = 0; 3451 int needs_restart = 1; 3452 /* if either enable or "ref_clock" is changed, we'll need to stop and/or restart */ 3453 uint32 restart_mask = (BCM_TIME_ENABLE | BCM_TIME_INPUT | BCM_TIME_REF_CLOCK); 3454 unsigned two_cycle_delay_usec = 500; /* two cycles @ 4KHz */ 3455 3456 if ((intf->flags & BCM_TIME_ENABLE) && 3457 !(intf->flags & BCM_TIME_INPUT)) { 3458 tc_output_enable = 1; 3459 } 3460 if (intf->flags & BCM_TIME_REF_CLOCK) { 3461 include_servo_offset = 1; 3462 } 3463 if (intf->flags & BCM_TIME_LOCKED) { 3464 locked = 1; 3465 } 3466 3467 if (replacing) { 3468 /* clear 'needs_restart' if the only change is to the LOCK status */ 3469 needs_restart = ((intf->flags & restart_mask) != 3470 ((TIME_INTERFACE(unit, intf->id))->flags & restart_mask)); 3471 } 3472 3473 #if defined(BCM_CMICM_SUPPORT) 3474 if (soc_feature(unit, soc_feature_cmicm) && /* CMICM, not iProc */ 3475 !soc_feature(unit, soc_feature_iproc)) { 3476 if (needs_restart) { 3477 soc_reg_field32_modify(unit, CMIC_BS_CONFIGr, REG_PORT_ANY, BS_TC_OUTPUT_ENABLEf, 0); 3478 /* use "lock" field as a signal on startup that the servo offset should be included */ 3479 soc_reg_field32_modify(unit, CMIC_BS_OUTPUT_TIME_0r, REG_PORT_ANY, LOCKf, include_servo_offset); 3480 3481 sal_usleep(two_cycle_delay_usec); 3482 3483 soc_reg_field32_modify(unit, CMIC_BS_CONFIGr, REG_PORT_ANY, BS_TC_OUTPUT_ENABLEf, tc_output_enable); 3484 3485 sal_usleep(two_cycle_delay_usec); 3486 } 3487 soc_reg_field32_modify(unit, CMIC_BS_OUTPUT_TIME_0r, REG_PORT_ANY, LOCKf, locked); 3488 } else 3489 #endif /* BCM_CMICM_SUPPORT */ 3490 #if defined (BCM_IPROC_SUPPORT) 3491 { 3492 if (soc_feature(unit, soc_feature_iproc)) { /* IPROC/CMICD */ 3493 if (needs_restart) { 3494 soc_reg_field32_modify(unit, CMIC_BS0_CONFIGr, 3495 REG_PORT_ANY, 3496 BS_TC_OUTPUT_ENABLEf, 0); 3497 /* use "lock" field as a signal on startup that the servo offset should be included */ 3498 soc_reg_field32_modify(unit, CMIC_BS0_OUTPUT_TIME_0r, 3499 REG_PORT_ANY, 3500 LOCKf, include_servo_offset); 3501 3502 sal_usleep(two_cycle_delay_usec); 3503 3504 soc_reg_field32_modify(unit, CMIC_BS0_CONFIGr, 3505 REG_PORT_ANY, 3506 BS_TC_OUTPUT_ENABLEf, tc_output_enable); 3507 3508 sal_usleep(two_cycle_delay_usec); 3509 } 3510 soc_reg_field32_modify(unit, CMIC_BS0_OUTPUT_TIME_0r, 3511 REG_PORT_ANY, 3512 LOCKf, locked); 3513 } 3514 } 3515 #endif /* BCM_IPROC_SUPPORT */ 3516 #if defined(BCM_TOMAHAWK3_SUPPORT) 3517 { 3518 if (SOC_IS_TOMAHAWK3(unit) || SOC_IS_MONTEREY(unit)) { /* IPROC/CMICD */ 3519 if (needs_restart) { 3520 soc_reg_field32_modify(unit, NS_BS0_BS_CONFIGr, 3521 REG_PORT_ANY, 3522 BS_TC_OUTPUT_ENABLEf, 0); 3523 /* use "lock" field as a signal on startup that the servo offset should be included */ 3524 soc_reg_field32_modify(unit, NS_BS0_BS_OUTPUT_TIME_0r, 3525 REG_PORT_ANY, 3526 LOCKf, include_servo_offset); 3527 3528 sal_usleep(two_cycle_delay_usec); 3529 3530 soc_reg_field32_modify(unit, NS_BS0_BS_CONFIGr, 3531 REG_PORT_ANY, 3532 BS_TC_OUTPUT_ENABLEf, tc_output_enable); 3533 3534 sal_usleep(two_cycle_delay_usec); 3535 } 3536 soc_reg_field32_modify(unit, NS_BS0_BS_OUTPUT_TIME_0r, 3537 REG_PORT_ANY, 3538 LOCKf, locked); 3539 } 3540 3541 } 3542 #endif 3543 /* copy the used flags */ 3544 (TIME_INTERFACE(unit, intf->id))->flags &= ~(BCM_TIME_ENABLE | BCM_TIME_INPUT | BCM_TIME_REF_CLOCK | BCM_TIME_LOCKED); 3545 (TIME_INTERFACE(unit, intf->id))->flags |= 3546 intf->flags & (BCM_TIME_ENABLE | BCM_TIME_INPUT | BCM_TIME_REF_CLOCK | BCM_TIME_LOCKED); 3547 3548 TIME_UNLOCK(unit); 3549 return (BCM_E_NONE); 3550 } 3551 #endif /* INCLUDE_PTP */ 3552 3553 /* Set time interface configuration. */ 3554 if (replacing) { 3555 if (((TIME_INTERFACE(unit, intf->id))->flags & 3556 (BCM_TIME_ENABLE | BCM_TIME_INPUT)) != 3557 (intf->flags & (BCM_TIME_ENABLE | BCM_TIME_INPUT))) { 3558 /* either master or enabled state changed, so copy those bits in flags */ 3559 (TIME_INTERFACE(unit, intf->id))->flags &= ~(BCM_TIME_ENABLE | BCM_TIME_INPUT); 3560 (TIME_INTERFACE(unit, intf->id))->flags |= 3561 intf->flags & (BCM_TIME_ENABLE | BCM_TIME_INPUT); 3562 /* either master or enabled state changed, so re-init */ 3563 reset_hardware = 1; 3564 } 3565 if (intf->flags & BCM_TIME_DRIFT) { 3566 (TIME_INTERFACE(unit, intf->id))->drift = intf->drift; 3567 } 3568 if (intf->flags & BCM_TIME_OFFSET) { 3569 (TIME_INTERFACE(unit, intf->id))->offset = intf->offset; 3570 } 3571 if (intf->flags & BCM_TIME_ACCURACY) { 3572 (TIME_INTERFACE(unit, intf->id))->accuracy = intf->accuracy; 3573 } 3574 if (intf->flags & BCM_TIME_HEARTBEAT) { 3575 if ((TIME_INTERFACE(unit, intf->id))->heartbeat_hz != intf->heartbeat_hz) { 3576 (TIME_INTERFACE(unit, intf->id))->heartbeat_hz = intf->heartbeat_hz; 3577 /* Also use heartbeat flag to indicate whether to replace bitclock freq */ 3578 (TIME_INTERFACE(unit, intf->id))->bitclock_hz = intf->bitclock_hz; 3579 reset_hardware = 1; 3580 } 3581 } 3582 if (intf->flags & BCM_TIME_BS_TIME) { 3583 (TIME_INTERFACE(unit, intf->id))->bs_time = intf->bs_time; 3584 } 3585 } else { 3586 /* Is new, so just copy wholesale */ 3587 *(TIME_INTERFACE(unit, intf->id)) = *intf; 3588 reset_hardware = 1; 3589 } 3590 3591 #if defined(BCM_TIME_V3_OR_IPROC_MANAGED_BROADSYNC) 3592 if (SOC_IS_TOMAHAWK3(unit) || SOC_IS_MONTEREY(unit)) { 3593 uint32 regval; 3594 /* in case of broadsync, enable common control for both counters */ 3595 READ_NS_TIMESYNC_COUNTER_CONFIG_SELECTr(unit, ®val); 3596 soc_reg_field_set(unit, NS_TIMESYNC_COUNTER_CONFIG_SELECTr, ®val, 3597 ENABLE_COMMON_CONTROLf, 1); 3598 WRITE_NS_TIMESYNC_COUNTER_CONFIG_SELECTr(unit, regval); 3599 3600 } else if (SOC_HAS_TIME_V3_OR_IPROC_MANAGED_BROADSYNC(unit)) { 3601 uint32 regval; 3602 /* in case of broadsync, enable common control for both counters */ 3603 READ_CMIC_TIMESYNC_COUNTER_CONFIG_SELECTr(unit, ®val); 3604 soc_reg_field_set(unit, CMIC_TIMESYNC_COUNTER_CONFIG_SELECTr, ®val, 3605 ENABLE_COMMON_CONTROLf, 1); 3606 WRITE_CMIC_TIMESYNC_COUNTER_CONFIG_SELECTr(unit, regval); 3607 } 3608 #endif /* defined(BCM_TIME_V3_OR_IPROC_MANAGED_BROADSYNC) */ 3609 3610 3611 if (reset_hardware) { 3612 /* Enable/Setup TIME API BroadSync on the unit */ 3613 rv = _bcm_esw_time_bs_init(unit, TIME_INTERFACE(unit, intf->id)); 3614 if (BCM_FAILURE(rv)) { 3615 TIME_UNLOCK(unit); 3616 return rv; 3617 } 3618 } 3619 3620 if (!replacing) { 3621 /* Enable BS firmware on the unit */ 3622 rv = _bcm_mbox_comm_init(unit, MOS_MSG_MBOX_APPL_BS); 3623 if (BCM_FAILURE(rv)) { 3624 TIME_UNLOCK(unit); 3625 return rv; 3626 } 3627 } 3628 3629 /* Set BroadSync time */ 3630 if (intf->flags & BCM_TIME_BS_TIME) { 3631 rv = _bcm_time_bs_time_set(unit, intf->bs_time); 3632 if (BCM_FAILURE(rv)) { 3633 TIME_UNLOCK(unit); 3634 return rv; 3635 } 3636 } 3637 3638 /* Set specified offsets */ 3639 if (intf->flags & BCM_TIME_DRIFT) { 3640 rv = _bcm_time_bs_frequency_offset_set(unit, intf->drift); 3641 if (BCM_FAILURE(rv)) { 3642 TIME_UNLOCK(unit); 3643 return rv; 3644 } 3645 } 3646 3647 if (intf->flags & BCM_TIME_OFFSET) { 3648 rv = _bcm_time_bs_phase_offset_set(unit, intf->offset); 3649 if (BCM_FAILURE(rv)) { 3650 TIME_UNLOCK(unit); 3651 return rv; 3652 } 3653 } 3654 3655 TIME_UNLOCK(unit); 3656 3657 #ifdef BCM_WARM_BOOT_SUPPORT 3658 SOC_CONTROL_LOCK(unit); 3659 SOC_CONTROL(unit)->scache_dirty = 1; 3660 SOC_CONTROL_UNLOCK(unit); 3661 #endif 3662 3663 return (BCM_E_NONE); 3664 } 3665 3666 3667 if (SOC_HAS_MANAGED_BROADSYNC(unit)) { 3668 uint32 regval = 0; 3669 3670 if (SOC_IS_TOMAHAWK3(unit) || SOC_IS_MONTEREY(unit)) { 3671 /* Enable Timestamp Generation */ 3672 READ_NS_TIMESYNC_TS0_FREQ_CTRL_FRAC_UPPERr(unit, ®val); 3673 /* 500 Mhz NCO - 2.000 ns */ 3674 soc_reg_field_set(unit, NS_TIMESYNC_TS0_FREQ_CTRL_FRAC_UPPERr, ®val, UINCf, 3675 0x2000); 3676 WRITE_NS_TIMESYNC_TS0_FREQ_CTRL_FRAC_UPPERr(unit, regval); 3677 3678 READ_NS_TIMESYNC_TS0_FREQ_CTRL_FRAC_LOWERr(unit, ®val); 3679 soc_reg_field_set(unit, NS_TIMESYNC_TS0_FREQ_CTRL_FRAC_LOWERr, ®val, LINCf, 0); 3680 WRITE_NS_TIMESYNC_TS0_FREQ_CTRL_FRAC_LOWERr(unit, regval); 3681 3682 READ_NS_TIMESYNC_TS0_COUNTER_ENABLEr(unit, ®val); 3683 soc_reg_field_set(unit, NS_TIMESYNC_TS0_COUNTER_ENABLEr, ®val, ENABLEf, 1); 3684 WRITE_NS_TIMESYNC_TS0_COUNTER_ENABLEr(unit, regval); 3685 3686 } else 3687 #if defined (BCM_IPROC_SUPPORT) 3688 if (soc_feature(unit, soc_feature_iproc)) { 3689 /* Enable Timestamp Generation */ 3690 READ_CMIC_TIMESYNC_TS0_FREQ_CTRL_FRACr(unit, ®val); 3691 /* 250 Mhz - 4.000 ns */ 3692 soc_reg_field_set(unit, CMIC_TIMESYNC_TS0_FREQ_CTRL_FRACr, ®val, FRACf, 3693 ((soc_property_get(unit, spn_PTP_TS_PLL_FREF, 0) 3694 == 12800000 ) ? 0x40842108 : 0x40000000)); 3695 WRITE_CMIC_TIMESYNC_TS0_FREQ_CTRL_FRACr(unit, regval); 3696 3697 READ_CMIC_TIMESYNC_TS0_FREQ_CTRL_UPPERr(unit, ®val); 3698 soc_reg_field_set(unit, CMIC_TIMESYNC_TS0_FREQ_CTRL_UPPERr, ®val, NSf, 0); 3699 WRITE_CMIC_TIMESYNC_TS0_FREQ_CTRL_UPPERr(unit, regval); 3700 3701 READ_CMIC_TIMESYNC_TS0_COUNTER_ENABLEr(unit, ®val); 3702 soc_reg_field_set(unit, CMIC_TIMESYNC_TS0_COUNTER_ENABLEr, ®val, ENABLEf, 1); 3703 WRITE_CMIC_TIMESYNC_TS0_COUNTER_ENABLEr(unit, regval); 3704 } else 3705 #endif 3706 { 3707 /* Enable Timestamp Generation */ 3708 READ_CMIC_TS_FREQ_CTRL_LOWERr(unit, ®val); 3709 /* 250 Mhz - 4.000 ns */ 3710 soc_reg_field_set(unit, CMIC_TS_FREQ_CTRL_LOWERr, ®val, FRACf, 3711 ((soc_property_get(unit, spn_PTP_TS_PLL_FREF, 0) 3712 == 12800000 ) ? 0x40842108 : 0x40000000)); 3713 WRITE_CMIC_TS_FREQ_CTRL_LOWERr(unit, regval); 3714 3715 READ_CMIC_TS_FREQ_CTRL_UPPERr(unit, ®val); 3716 soc_reg_field_set(unit, CMIC_TS_FREQ_CTRL_UPPERr, ®val, NSf, 0); 3717 soc_reg_field_set(unit, CMIC_TS_FREQ_CTRL_UPPERr, ®val, ENABLEf, 1); 3718 WRITE_CMIC_TS_FREQ_CTRL_UPPERr(unit, regval); 3719 } 3720 3721 if (intf->flags & BCM_TIME_REF_CLOCK) { 3722 rv = _bcm_esw_time_interface_ref_clock_install(unit, intf->id); 3723 if (BCM_FAILURE(rv)) { 3724 TIME_INTERFACE_CONFIG_REF_COUNT(unit, intf->id) -= 1; 3725 TIME_UNLOCK(unit); 3726 return rv; 3727 } 3728 } 3729 } 3730 #endif /* BCM_TIME_MANAGED_BROADSYNC */ 3731 3732 #if defined(BCM_TIME_V3_OR_IPROC_MANAGED_BROADSYNC) 3733 if (SOC_HAS_TIME_V3_OR_IPROC_MANAGED_BROADSYNC(unit)) { 3734 uint32 regval; 3735 3736 if (SOC_IS_TOMAHAWK3(unit) || SOC_IS_MONTEREY(unit)) { 3737 /* Enable common control for both counters */ 3738 READ_NS_TIMESYNC_COUNTER_CONFIG_SELECTr(unit, ®val); 3739 soc_reg_field_set(unit, NS_TIMESYNC_COUNTER_CONFIG_SELECTr, ®val, 3740 ENABLE_COMMON_CONTROLf, 1); 3741 WRITE_NS_TIMESYNC_COUNTER_CONFIG_SELECTr(unit, regval); 3742 3743 /* Enable Timestamp Generation */ 3744 READ_NS_TIMESYNC_TS0_FREQ_CTRL_FRAC_UPPERr(unit, ®val); 3745 3746 /* TH3 1GHz input to iProc 2.000 ns */ 3747 soc_reg_field_set(unit, NS_TIMESYNC_TS0_FREQ_CTRL_FRAC_UPPERr, ®val, UINCf, 3748 0x2000); 3749 WRITE_NS_TIMESYNC_TS0_FREQ_CTRL_FRAC_UPPERr(unit, regval); 3750 3751 READ_NS_TIMESYNC_TS0_FREQ_CTRL_FRAC_LOWERr(unit, ®val); 3752 soc_reg_field_set(unit, NS_TIMESYNC_TS0_FREQ_CTRL_FRAC_LOWERr, ®val, LINCf, 0); 3753 WRITE_NS_TIMESYNC_TS0_FREQ_CTRL_FRAC_LOWERr(unit, regval); 3754 3755 READ_NS_TIMESYNC_TS0_COUNTER_ENABLEr(unit, ®val); 3756 soc_reg_field_set(unit, NS_TIMESYNC_TS0_COUNTER_ENABLEr, ®val, ENABLEf, 1); 3757 WRITE_NS_TIMESYNC_TS0_COUNTER_ENABLEr(unit, regval); 3758 } else { 3759 /* Enable common control for both counters */ 3760 READ_CMIC_TIMESYNC_COUNTER_CONFIG_SELECTr(unit, ®val); 3761 soc_reg_field_set(unit, CMIC_TIMESYNC_COUNTER_CONFIG_SELECTr, ®val, 3762 ENABLE_COMMON_CONTROLf, 1); 3763 WRITE_CMIC_TIMESYNC_COUNTER_CONFIG_SELECTr(unit, regval); 3764 3765 /* 250 Mhz - 4.000 ns */ 3766 READ_CMIC_TIMESYNC_TS0_FREQ_CTRL_FRACr(unit, ®val); 3767 soc_reg_field_set(unit, CMIC_TIMESYNC_TS0_FREQ_CTRL_FRACr, ®val, 3768 FRACf, 3769 ((soc_property_get(unit, spn_PTP_TS_PLL_FREF, 0) 3770 == 12800000 ) ? 0x40842108 : 0x40000000)); 3771 WRITE_CMIC_TIMESYNC_TS0_FREQ_CTRL_FRACr(unit, regval); 3772 3773 READ_CMIC_TIMESYNC_TS0_FREQ_CTRL_UPPERr(unit, ®val); 3774 soc_reg_field_set(unit, CMIC_TIMESYNC_TS0_FREQ_CTRL_UPPERr, ®val, 3775 NSf, 0); 3776 WRITE_CMIC_TIMESYNC_TS0_FREQ_CTRL_UPPERr(unit, regval); 3777 3778 READ_CMIC_TIMESYNC_TS0_FREQ_CTRL_LOWERr(unit, ®val); 3779 soc_reg_field_set(unit, CMIC_TIMESYNC_TS0_FREQ_CTRL_LOWERr, ®val, 3780 NSf, 0); 3781 WRITE_CMIC_TIMESYNC_TS0_FREQ_CTRL_LOWERr(unit, regval); 3782 3783 /* Enable Timestamp Generation */ 3784 READ_CMIC_TIMESYNC_TS0_COUNTER_ENABLEr(unit, ®val); 3785 soc_reg_field_set(unit, CMIC_TIMESYNC_TS0_COUNTER_ENABLEr, ®val, 3786 ENABLEf, 1); 3787 WRITE_CMIC_TIMESYNC_TS0_COUNTER_ENABLEr(unit, regval); 3788 } 3789 if (intf->flags & BCM_TIME_REF_CLOCK) { 3790 rv = _bcm_esw_time_interface_ref_clock_install(unit, intf->id); 3791 if (BCM_FAILURE(rv)) { 3792 TIME_INTERFACE_CONFIG_REF_COUNT(unit, intf->id) -= 1; 3793 TIME_UNLOCK(unit); 3794 return rv; 3795 } 3796 } 3797 } 3798 #endif /* BCM_TIME_V3_OR_IPROC_MANAGED_BROADSYNC */ 3799 3800 /* Set time interface configuration. */ 3801 *(TIME_INTERFACE(unit, intf->id)) = *intf; 3802 3803 /* Install the interface into the HW */ 3804 #if defined(BCM_TIME_V3_OR_IPROC_MANAGED_BROADSYNC) 3805 if (SOC_HAS_TIME_V3_OR_IPROC_MANAGED_BROADSYNC(unit)) { 3806 if (!soc_feature(unit, soc_feature_time_v3_no_bs)) { 3807 rv = _bcm_esw_time_interface_dual_bs_install(unit, intf->id); 3808 } 3809 } else 3810 #endif /* BCM_TIME_V3_OR_IPROC_MANAGED_BROADSYNC */ 3811 { 3812 rv = _bcm_esw_time_interface_install(unit, intf->id); 3813 } 3814 3815 if (BCM_FAILURE(rv)) { 3816 TIME_INTERFACE_CONFIG_REF_COUNT(unit, intf->id) -= 1; 3817 TIME_UNLOCK(unit); 3818 return rv; 3819 } 3820 3821 TIME_UNLOCK(unit); 3822 3823 #ifdef BCM_WARM_BOOT_SUPPORT 3824 SOC_CONTROL_LOCK(unit); 3825 SOC_CONTROL(unit)->scache_dirty = 1; 3826 SOC_CONTROL_UNLOCK(unit); 3827 #endif 3828 3829 return (BCM_E_NONE); 3830 } 3831 3832 /* 3833 * Function: 3834 * bcm_esw_time_interface_delete 3835 * Purpose: 3836 * Deleting a time sync interface from unit 3837 * Parameters: 3838 * unit - (IN) StrataSwitch Unit #. 3839 * intf_id - (IN) Time Sync Interface id to remove 3840 * Returns: 3841 * BCM_E_NONE 3842 * BCM_E_XXX 3843 */ 3844 int 3845 bcm_esw_time_interface_delete (int unit, bcm_time_if_t intf_id) 3846 { 3847 int rv; 3848 3849 /* Chek if time feature is supported on a device */ 3850 if (!soc_feature(unit, soc_feature_time_support)) { 3851 return (BCM_E_UNAVAIL); 3852 } 3853 3854 /* Initialization check. */ 3855 BCM_IF_ERROR_RETURN( 3856 _bcm_esw_time_interface_id_validate(unit, intf_id)); 3857 3858 TIME_LOCK(unit); 3859 3860 /* If interface still in use return an Error */ 3861 if (1 < TIME_INTERFACE_CONFIG_REF_COUNT(unit, intf_id)) { 3862 TIME_UNLOCK(unit); 3863 return (BCM_E_BUSY); 3864 } 3865 3866 /* Free the interface */ 3867 rv = _bcm_time_interface_free(unit, intf_id); 3868 if (BCM_FAILURE(rv)) { 3869 TIME_UNLOCK(unit); 3870 return (rv); 3871 } 3872 3873 rv = _bcm_esw_time_hw_clear(unit, intf_id); 3874 3875 #ifdef BCM_WARM_BOOT_SUPPORT 3876 SOC_CONTROL_LOCK(unit); 3877 SOC_CONTROL(unit)->scache_dirty = 1; 3878 SOC_CONTROL_UNLOCK(unit); 3879 #endif 3880 3881 TIME_UNLOCK(unit); 3882 return (rv); 3883 } 3884 3885 /* 3886 * Function: 3887 * bcm_esw_time_interface_get 3888 * Purpose: 3889 * Get a time sync interface on a specified unit 3890 * Parameters: 3891 * unit - (IN) StrataSwitch Unit #. 3892 * intf - (IN/OUT) Time Sync Interface to get 3893 * Returns: 3894 * BCM_E_NONE 3895 * BCM_E_XXX 3896 */ 3897 int 3898 bcm_esw_time_interface_get (int unit, bcm_time_interface_t *intf) 3899 { 3900 int rv; 3901 /* Chek if time feature is supported on a device */ 3902 if (!soc_feature(unit, soc_feature_time_support)) { 3903 return (BCM_E_UNAVAIL); 3904 } 3905 3906 /* Validation checks */ 3907 if (NULL == intf) { 3908 return BCM_E_PARAM; 3909 } 3910 3911 BCM_IF_ERROR_RETURN( 3912 _bcm_esw_time_interface_id_validate(unit, intf->id)); 3913 3914 TIME_LOCK(unit); 3915 #if defined(BCM_TIME_V3_OR_IPROC_MANAGED_BROADSYNC) 3916 if (SOC_HAS_TIME_V3_OR_IPROC_MANAGED_BROADSYNC(unit)) { 3917 rv = _bcm_esw_time_interface_dual_bs_get(unit, intf->id, intf); 3918 } else 3919 #endif /* BCM_TIME_V3_OR_IPROC_MANAGED_BROADSYNC */ 3920 { 3921 rv = _bcm_esw_time_interface_get(unit, intf->id, intf); 3922 } 3923 3924 if (intf->flags & BCM_TIME_SYNC_STAMPER) { 3925 if (!soc_feature(unit, soc_feature_time_v3_no_bs)) { 3926 BCM_IF_ERROR_RETURN(_bcm_time_bs_status_get(unit, 3927 (int *)(&(intf->status)))); 3928 } 3929 } 3930 TIME_UNLOCK(unit); 3931 3932 return (rv); 3933 } 3934 3935 /* 3936 * Function: 3937 * bcm_esw_time_interface_delete_all 3938 * Purpose: 3939 * Deleting all time sync interfaces on a unit 3940 * Parameters: 3941 * unit - (IN) StrataSwitch Unit #. 3942 * Returns: 3943 * BCM_E_NONE 3944 * BCM_E_XXX 3945 */ 3946 int 3947 bcm_esw_time_interface_delete_all (int unit) 3948 { 3949 bcm_time_if_t intf; 3950 3951 /* Chek if time feature is supported on a device */ 3952 if (!soc_feature(unit, soc_feature_time_support)) { 3953 return (BCM_E_UNAVAIL); 3954 } 3955 3956 /* Initialization check */ 3957 if (0 == TIME_INIT(unit)) { 3958 return BCM_E_INIT; 3959 } 3960 3961 for (intf = 0; intf < NUM_TIME_INTERFACE(unit); intf++ ) { 3962 BCM_IF_ERROR_RETURN( 3963 bcm_esw_time_interface_delete(unit, intf)); 3964 } 3965 3966 return (BCM_E_NONE); 3967 } 3968 3969 /* 3970 * Function: 3971 * bcm_esw_time_interface_traverse 3972 * Purpose: 3973 * Itterates over all time sync interfaces and calls given callback 3974 * Parameters: 3975 * unit - (IN) StrataSwitch Unit #. 3976 * cb - (IN) Call back function 3977 * user_data - (IN) void pointer to store any user information 3978 * Returns: 3979 * BCM_E_NONE 3980 * BCM_E_XXX 3981 */ 3982 int 3983 bcm_esw_time_interface_traverse (int unit, bcm_time_interface_traverse_cb cb, 3984 void *user_data) 3985 { 3986 bcm_time_if_t intf; 3987 3988 /* Chek if time feature is supported on a device */ 3989 if (!soc_feature(unit, soc_feature_time_support)) { 3990 return (BCM_E_UNAVAIL); 3991 } 3992 3993 /* Initialization check. */ 3994 if (0 == TIME_INIT(unit)) { 3995 return BCM_E_INIT; 3996 } 3997 3998 if (NULL == cb) { 3999 return (BCM_E_PARAM); 4000 } 4001 4002 for (intf = 0; intf < NUM_TIME_INTERFACE(unit); intf++ ) { 4003 if (NULL != TIME_INTERFACE(unit, intf)) { 4004 BCM_IF_ERROR_RETURN(cb(unit, TIME_INTERFACE(unit, intf), user_data)); 4005 } 4006 } 4007 return (BCM_E_NONE); 4008 } 4009 4010 /* 4011 * Function: 4012 * bcm_esw_time_capture_get 4013 * Purpose: 4014 * Gets a time captured by HW clock 4015 * Parameters: 4016 * unit - (IN) StrataSwitch Unit #. 4017 * id - (IN) Time interface identifier 4018 * time - (OUT) Structure to contain HW clocks values 4019 * Returns: 4020 * BCM_E_NONE 4021 * BCM_E_XXX 4022 */ 4023 int 4024 bcm_esw_time_capture_get (int unit, bcm_time_if_t id, bcm_time_capture_t *time) 4025 { 4026 int rv; /* Operation return status. */ 4027 4028 /* Chek if time feature is supported on a device */ 4029 if (!soc_feature(unit, soc_feature_time_support)) { 4030 return (BCM_E_UNAVAIL); 4031 } 4032 4033 /* Initialization check. */ 4034 BCM_IF_ERROR_RETURN( 4035 _bcm_esw_time_interface_id_validate(unit, id)); 4036 4037 if (NULL == time) { 4038 return (BCM_E_PARAM); 4039 } 4040 if (NULL == TIME_CAPTURE(unit, id)) { 4041 return (BCM_E_NOT_FOUND); 4042 } 4043 4044 TIME_LOCK(unit); 4045 rv = _bcm_esw_time_capture_get(unit, id, TIME_CAPTURE(unit, id), time->flags); 4046 if (BCM_FAILURE(rv)) { 4047 TIME_UNLOCK(unit); 4048 return (rv); 4049 } 4050 4051 *time = *(TIME_CAPTURE(unit, id)); 4052 4053 TIME_UNLOCK(unit); 4054 4055 return (BCM_E_NONE); 4056 } 4057 4058 /* 4059 * Function: 4060 * bcm_esw_time_heartbeat_enable_set 4061 * Purpose: 4062 * Enables/Disables interrupt handling for each heartbeat provided by a 4063 * HW clock 4064 * Parameters: 4065 * unit - (IN) StrataSwitch Unit #. 4066 * id - (IN) Time Sync Interface Id 4067 * enable - (IN) Enable/Disable parameter 4068 * Returns: 4069 * BCM_E_NONE 4070 * BCM_E_XXX 4071 */ 4072 int 4073 bcm_esw_time_heartbeat_enable_set (int unit, bcm_time_if_t id, int enable) 4074 { 4075 uint32 regval; 4076 soc_control_t *soc = SOC_CONTROL(unit); 4077 4078 /* Check if time feature is supported on a device */ 4079 if (!soc_feature(unit, soc_feature_time_support)) { 4080 return (BCM_E_UNAVAIL); 4081 } 4082 4083 /* Feature unavailable on devices without BroadSync support. */ 4084 if (soc_feature(unit, soc_feature_time_v3_no_bs)) { 4085 return BCM_E_UNAVAIL; 4086 } 4087 4088 /* Param validation check. */ 4089 BCM_IF_ERROR_RETURN( 4090 _bcm_esw_time_interface_id_validate(unit, id)); 4091 4092 TIME_LOCK(unit); 4093 4094 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || \ 4095 defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_HURRICANE2_SUPPORT) || \ 4096 defined(BCM_GREYHOUND_SUPPORT) || defined(BCM_TOMAHAWK_SUPPORT) 4097 if ((TIME_INTERFACE(unit, id))->flags & BCM_TIME_SYNC_STAMPER) { 4098 int rv = _bcm_time_bs_debug_1pps_set(unit, enable); 4099 if (BCM_FAILURE(rv)) { 4100 TIME_UNLOCK(unit); 4101 return rv; 4102 } 4103 4104 TIME_UNLOCK(unit); 4105 return BCM_E_NONE; 4106 } 4107 #endif /* defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || 4108 defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_HURRICANE2_SUPPORT) || 4109 defined(BCM_GREYHOUND_SUPPORT) || defined(BCM_TOMAHAWK_SUPPORT) */ 4110 4111 /* Install heartbeat and external trigger clock interval */ 4112 #if defined(BCM_TIME_V3_OR_IPROC_MANAGED_BROADSYNC) 4113 if (SOC_HAS_TIME_V3_OR_IPROC_MANAGED_BROADSYNC(unit)) { 4114 if (SOC_IS_TOMAHAWK3(unit) || SOC_IS_MONTEREY(unit)) { 4115 READ_NS_MISC_CLK_EVENT_CTRLr(unit, ®val); 4116 soc_reg_field_set(unit, NS_MISC_CLK_EVENT_CTRLr, ®val, ENABLEf, 4117 (enable) ? IPROC_TIME_CAPTURE_MODE_HB_BS_0 : IPROC_TIME_CAPTURE_MODE_DISABLE); 4118 WRITE_NS_MISC_CLK_EVENT_CTRLr(unit, regval); 4119 4120 if (enable) { 4121 /* Configure the HW to raise interrupt on every heartbeat */ 4122 READ_NS_MISC_CLK_EVENT_CTRLr(unit, ®val); 4123 soc_reg_field_set(unit, NS_MISC_CLK_EVENT_CTRLr, ®val, ENABLEf, 1); 4124 soc_reg_field_set(unit, NS_MISC_CLK_EVENT_CTRLr, ®val, BS0_TX_HB_STATUS_ENABLEf, 1); 4125 soc_reg_field_set(unit, NS_MISC_CLK_EVENT_CTRLr, ®val, BS0_RX_HB_STATUS_ENABLEf, 1); 4126 WRITE_NS_MISC_CLK_EVENT_CTRLr(unit, regval); 4127 } else { 4128 /* Leave TIME_CAPTURE_ENABLEf for other trigger sources */ 4129 READ_NS_MISC_CLK_EVENT_CTRLr(unit, ®val); 4130 soc_reg_field_set(unit, NS_MISC_CLK_EVENT_CTRLr, ®val, BS0_RX_HB_STATUS_ENABLEf, 0); 4131 soc_reg_field_set(unit, NS_MISC_CLK_EVENT_CTRLr, ®val, BS0_TX_HB_STATUS_ENABLEf, 0); 4132 WRITE_NS_MISC_CLK_EVENT_CTRLr(unit, regval); 4133 } 4134 } else { 4135 READ_CMIC_TIMESYNC_INTERRUPT_ENABLEr(unit, ®val); 4136 soc_reg_field_set(unit, CMIC_TIMESYNC_INTERRUPT_ENABLEr, ®val, INT_ENABLEf, 4137 (enable) ? IPROC_TIME_CAPTURE_MODE_HB_BS_0 : IPROC_TIME_CAPTURE_MODE_DISABLE); 4138 WRITE_CMIC_TIMESYNC_INTERRUPT_ENABLEr(unit, regval); 4139 4140 if (enable) { 4141 /* Configure the HW to raise interrupt on every heartbeat */ 4142 READ_CMIC_TIMESYNC_TIME_CAPTURE_CONTROLr(unit, ®val); 4143 soc_reg_field_set(unit, CMIC_TIMESYNC_TIME_CAPTURE_CONTROLr, ®val, TIME_CAPTURE_ENABLEf, 1); 4144 soc_reg_field_set(unit, CMIC_TIMESYNC_TIME_CAPTURE_CONTROLr, ®val, BSYNC0_TX_HB_STATUS_ENABLEf, 1); 4145 soc_reg_field_set(unit, CMIC_TIMESYNC_TIME_CAPTURE_CONTROLr, ®val, BSYNC0_RX_HB_STATUS_ENABLEf, 1); 4146 WRITE_CMIC_TIMESYNC_TIME_CAPTURE_CONTROLr(unit, regval); 4147 } else { 4148 /* Leave TIME_CAPTURE_ENABLEf for other trigger sources */ 4149 READ_CMIC_TIMESYNC_TIME_CAPTURE_CONTROLr(unit, ®val); 4150 soc_reg_field_set(unit, CMIC_TIMESYNC_TIME_CAPTURE_CONTROLr, ®val, BSYNC0_RX_HB_STATUS_ENABLEf, 0); 4151 soc_reg_field_set(unit, CMIC_TIMESYNC_TIME_CAPTURE_CONTROLr, ®val, BSYNC0_TX_HB_STATUS_ENABLEf, 0); 4152 WRITE_CMIC_TIMESYNC_TIME_CAPTURE_CONTROLr(unit, regval); 4153 } 4154 4155 /* Configure the HW to capture time on every heartbeat */ 4156 READ_CMIC_TIMESYNC_TIME_CAPTURE_MODEr(unit, ®val); 4157 soc_reg_field_set(unit, CMIC_TIMESYNC_TIME_CAPTURE_MODEr, ®val, TIME_CAPTURE_MODEf, 4158 (enable) ? IPROC_TIME_CAPTURE_MODE_HB_BS_0 : IPROC_TIME_CAPTURE_MODE_DISABLE); 4159 4160 WRITE_CMIC_TIMESYNC_TIME_CAPTURE_MODEr(unit, regval); 4161 4162 /* set interrupt enables to match the mode */ 4163 WRITE_CMIC_TIMESYNC_INTERRUPT_ENABLEr(unit, regval); 4164 } 4165 4166 4167 } else 4168 4169 #endif /* BCM_TIME_V3_OR_IPROC_MANAGED_BROADSYNC */ 4170 #if (defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_TRIDENT2_SUPPORT)) 4171 if (SOC_IS_KATANAX(unit) || SOC_IS_TRIUMPH3(unit) || SOC_IS_TD2_TT2(unit)) { 4172 READ_CMIC_TS_TIME_CAPTURE_CTRLr(unit, ®val); 4173 /* Configure the HW to raise interrupt on every heartbeat */ 4174 soc_reg_field_set(unit, CMIC_TS_TIME_CAPTURE_CTRLr, ®val, INT_ENABLEf, 4175 (enable) ? TIME_CAPTURE_MODE_HEARTBEAT : 0); 4176 soc_reg_field_set(unit, CMIC_TS_TIME_CAPTURE_CTRLr, ®val, TIME_CAPTURE_ENABLEf, 1); 4177 soc_reg_field_set(unit, CMIC_TS_TIME_CAPTURE_CTRLr, ®val, TX_HB_STATUS_ENABLEf, 1); 4178 soc_reg_field_set(unit, CMIC_TS_TIME_CAPTURE_CTRLr, ®val, RX_HB_STATUS_ENABLEf, 1); 4179 4180 /* Configure the HW to capture time on every heartbeat */ 4181 soc_reg_field_set(unit, CMIC_TS_TIME_CAPTURE_CTRLr, ®val, TIME_CAPTURE_MODEf, 4182 (enable) ? TIME_CAPTURE_MODE_HEARTBEAT : TIME_CAPTURE_MODE_DISABLE); 4183 WRITE_CMIC_TS_TIME_CAPTURE_CTRLr(unit, regval); 4184 } else 4185 #endif /* defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_TRIDENT2_SUPPORT) */ 4186 { 4187 READ_CMIC_BS_CAPTURE_CTRLr(unit, ®val); 4188 /* Configure the HW to give interrupt on every heartbeat */ 4189 soc_reg_field_set(unit, CMIC_BS_CAPTURE_CTRLr, ®val, INT_ENf, (enable) ? 1: 0); 4190 /* Configure the HW to capture time on every heartbeat */ 4191 soc_reg_field_set(unit, CMIC_BS_CAPTURE_CTRLr, ®val, TIME_CAPTURE_MODEf, 4192 (enable) ? TIME_CAPTURE_MODE_HEARTBEAT : TIME_CAPTURE_MODE_DISABLE); 4193 WRITE_CMIC_BS_CAPTURE_CTRLr(unit, regval); 4194 } 4195 4196 TIME_UNLOCK(unit); 4197 4198 /* Enable/disable broadsync interrupt */ 4199 if (enable) { 4200 soc_intr_enable(unit, IRQ_BROADSYNC_INTR); 4201 if (!soc->time_call_ref_count) { 4202 soc->soc_time_callout = _bcm_esw_time_hw_interrupt_dflt; 4203 } 4204 4205 } else { 4206 soc_intr_disable(unit, IRQ_BROADSYNC_INTR); 4207 if (!soc->time_call_ref_count) { 4208 soc->soc_time_callout = NULL; 4209 } 4210 } 4211 4212 return (BCM_E_NONE); 4213 } 4214 4215 /* 4216 * Function: 4217 * bcm_esw_time_heartbeat_enable_get 4218 * Purpose: 4219 * Gets interrupt handling status for each heartbeat provided by a 4220 * HW clock 4221 * Parameters: 4222 * unit - (IN) StrataSwitch Unit #. 4223 * id - (IN) Time Sync Interface Id 4224 * enable - (OUT) Enable status of interrupt handling 4225 * Returns: 4226 * BCM_E_NONE 4227 * BCM_E_XXX 4228 */ 4229 int 4230 bcm_esw_time_heartbeat_enable_get (int unit, bcm_time_if_t id, int *enable) 4231 { 4232 uint32 regval; 4233 4234 /* Check if time feature is supported on a device */ 4235 if (!soc_feature(unit, soc_feature_time_support)) { 4236 return (BCM_E_UNAVAIL); 4237 } 4238 4239 /* Feature unavailable on devices without BroadSync support. */ 4240 if (soc_feature(unit, soc_feature_time_v3_no_bs)) { 4241 return BCM_E_UNAVAIL; 4242 } 4243 4244 /* Param validation check. */ 4245 if (enable == NULL) { 4246 return (BCM_E_PARAM); 4247 } 4248 BCM_IF_ERROR_RETURN( 4249 _bcm_esw_time_interface_id_validate(unit, id)); 4250 4251 /* Read HW Configuration */ 4252 #if defined(BCM_TIME_V3_OR_IPROC_MANAGED_BROADSYNC) 4253 if (SOC_HAS_TIME_V3_OR_IPROC_MANAGED_BROADSYNC(unit)) { 4254 if (SOC_IS_TOMAHAWK3(unit) || SOC_IS_MONTEREY(unit)) { 4255 READ_NS_MISC_CLK_EVENT_CTRLr(unit, ®val); 4256 *enable = soc_reg_field_get(unit, NS_MISC_CLK_EVENT_CTRLr, regval, ENABLEf) & 4257 soc_reg_field_get(unit, NS_MISC_CLK_EVENT_CTRLr, regval, BS0_TX_HB_STATUS_ENABLEf) & 4258 soc_reg_field_get(unit, NS_MISC_CLK_EVENT_CTRLr, regval, BS0_RX_HB_STATUS_ENABLEf); 4259 } else { 4260 READ_CMIC_TIMESYNC_TIME_CAPTURE_MODEr(unit, ®val); 4261 *enable = (regval & TIME_CAPTURE_MODE_HEARTBEAT)? 1 : 0; 4262 } 4263 } else 4264 #endif /* BCM_TIME_V3_OR_IPROC_MANAGED_BROADSYNC */ 4265 #if (defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_TRIDENT2_SUPPORT)) 4266 if (SOC_IS_KATANA(unit) || SOC_IS_TRIUMPH3(unit) || 4267 SOC_IS_TD2_TT2(unit)) { 4268 READ_CMIC_TS_TIME_CAPTURE_CTRLr(unit, ®val); 4269 *enable = soc_reg_field_get(unit, CMIC_TS_TIME_CAPTURE_CTRLr, 4270 regval, INT_ENABLEf); 4271 *enable = (*enable == TIME_CAPTURE_MODE_HEARTBEAT) ? 1 : 0; 4272 } else 4273 #endif /* defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_TRIDENT2_SUPPORT) */ 4274 { 4275 READ_CMIC_BS_CAPTURE_CTRLr(unit, ®val); 4276 *enable = soc_reg_field_get(unit, CMIC_BS_CAPTURE_CTRLr, regval, INT_ENf); 4277 } 4278 4279 return (BCM_E_NONE); 4280 } 4281 4282 4283 #if (defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_TRIDENT2_SUPPORT)) 4284 /* 4285 * Function: 4286 * _bcm_esw_time_trigger_to_timestamp_mode 4287 * Purpose: 4288 * Convert capture mode flags to time control capture modes 4289 * 4290 * Parameters: 4291 * unit - (IN) mode_flags 4292 * 4293 * Returns: 4294 * Timesync captude modes 4295 * Notes: 4296 */ 4297 STATIC uint32 4298 _bcm_esw_time_trigger_to_timestamp_mode(int unit, uint32 mode_flags) 4299 { 4300 uint32 capture_mode = 0; 4301 uint32 regval; 4302 int bit_cnt; 4303 4304 /* processing on user mode flags reduces the dependencies on 4305 * hardware bit maps, byte shift of mode flags 4306 * should have been efficient 4307 */ 4308 for (bit_cnt = 0; bit_cnt < sizeof(uint32); bit_cnt++) 4309 { 4310 switch (mode_flags & (1 << bit_cnt)) 4311 { 4312 case BCM_TIME_CAPTURE_GPIO_0: 4313 capture_mode |= TIME_CAPTURE_MODE_GPIO_0; 4314 if (soc_reg_field_valid(unit, CMIC_TS_GPIO_1_DOWN_EVENT_CTRLr, ENABLEf)) { 4315 READ_CMIC_TS_GPIO_1_DOWN_EVENT_CTRLr(unit, ®val); 4316 soc_reg_field_set(unit, CMIC_TS_GPIO_1_DOWN_EVENT_CTRLr, ®val, ENABLEf, 1); 4317 WRITE_CMIC_TS_GPIO_1_DOWN_EVENT_CTRLr(unit, regval); 4318 } 4319 if (soc_reg_field_valid(unit, CMIC_TS_GPIO_1_UP_EVENT_CTRLr, ENABLEf)) { 4320 READ_CMIC_TS_GPIO_1_UP_EVENT_CTRLr(unit, ®val); 4321 soc_reg_field_set(unit, CMIC_TS_GPIO_1_UP_EVENT_CTRLr, ®val, ENABLEf, 1); 4322 WRITE_CMIC_TS_GPIO_1_UP_EVENT_CTRLr(unit, regval); 4323 } 4324 if (soc_reg_field_valid(unit, CMIC_TS_GPIO_1_CTRLr, ENABLEf)) { 4325 READ_CMIC_TS_GPIO_1_CTRLr(unit, ®val); 4326 soc_reg_field_set(unit, CMIC_TS_GPIO_1_CTRLr, ®val, ENABLEf, 1); 4327 WRITE_CMIC_TS_GPIO_1_CTRLr(unit, regval); 4328 } 4329 break; 4330 4331 case BCM_TIME_CAPTURE_GPIO_1: 4332 capture_mode |= TIME_CAPTURE_MODE_GPIO_1; 4333 if (soc_reg_field_valid(unit, CMIC_TS_GPIO_1_DOWN_EVENT_CTRLr, ENABLEf)) { 4334 READ_CMIC_TS_GPIO_1_DOWN_EVENT_CTRLr(unit, ®val); 4335 soc_reg_field_set(unit, CMIC_TS_GPIO_1_DOWN_EVENT_CTRLr, ®val, ENABLEf, 1); 4336 WRITE_CMIC_TS_GPIO_1_DOWN_EVENT_CTRLr(unit, regval); 4337 } 4338 if (soc_reg_field_valid(unit, CMIC_TS_GPIO_1_UP_EVENT_CTRLr, ENABLEf)) { 4339 READ_CMIC_TS_GPIO_1_UP_EVENT_CTRLr(unit, ®val); 4340 soc_reg_field_set(unit, CMIC_TS_GPIO_1_UP_EVENT_CTRLr, ®val, ENABLEf, 1); 4341 WRITE_CMIC_TS_GPIO_1_UP_EVENT_CTRLr(unit, regval); 4342 } 4343 if (soc_reg_field_valid(unit, CMIC_TS_GPIO_1_CTRLr, ENABLEf)) { 4344 READ_CMIC_TS_GPIO_1_CTRLr(unit, ®val); 4345 soc_reg_field_set(unit, CMIC_TS_GPIO_1_CTRLr, ®val, ENABLEf, 1); 4346 WRITE_CMIC_TS_GPIO_1_CTRLr(unit, regval); 4347 } 4348 break; 4349 4350 case BCM_TIME_CAPTURE_GPIO_2: 4351 capture_mode |= TIME_CAPTURE_MODE_GPIO_2; 4352 if (soc_reg_field_valid(unit, CMIC_TS_GPIO_2_DOWN_EVENT_CTRLr, ENABLEf)) { 4353 READ_CMIC_TS_GPIO_2_DOWN_EVENT_CTRLr(unit, ®val); 4354 soc_reg_field_set(unit, CMIC_TS_GPIO_2_DOWN_EVENT_CTRLr, ®val, ENABLEf, 1); 4355 WRITE_CMIC_TS_GPIO_2_DOWN_EVENT_CTRLr(unit, regval); 4356 } 4357 if (soc_reg_field_valid(unit, CMIC_TS_GPIO_2_UP_EVENT_CTRLr, ENABLEf)) { 4358 READ_CMIC_TS_GPIO_2_UP_EVENT_CTRLr(unit, ®val); 4359 soc_reg_field_set(unit, CMIC_TS_GPIO_2_UP_EVENT_CTRLr, ®val, ENABLEf, 1); 4360 WRITE_CMIC_TS_GPIO_2_UP_EVENT_CTRLr(unit, regval); 4361 } 4362 if (soc_reg_field_valid(unit, CMIC_TS_GPIO_2_CTRLr, ENABLEf)) { 4363 READ_CMIC_TS_GPIO_2_CTRLr(unit, ®val); 4364 soc_reg_field_set(unit, CMIC_TS_GPIO_2_CTRLr, ®val, ENABLEf, 1); 4365 WRITE_CMIC_TS_GPIO_2_CTRLr(unit, regval); 4366 } 4367 break; 4368 4369 case BCM_TIME_CAPTURE_GPIO_3: 4370 capture_mode |= TIME_CAPTURE_MODE_GPIO_3; 4371 if (soc_reg_field_valid(unit, CMIC_TS_GPIO_3_DOWN_EVENT_CTRLr, ENABLEf)) { 4372 READ_CMIC_TS_GPIO_3_DOWN_EVENT_CTRLr(unit, ®val); 4373 soc_reg_field_set(unit, CMIC_TS_GPIO_3_DOWN_EVENT_CTRLr, ®val, ENABLEf, 1); 4374 WRITE_CMIC_TS_GPIO_3_DOWN_EVENT_CTRLr(unit, regval); 4375 } 4376 if (soc_reg_field_valid(unit, CMIC_TS_GPIO_3_UP_EVENT_CTRLr, ENABLEf)) { 4377 READ_CMIC_TS_GPIO_3_UP_EVENT_CTRLr(unit, ®val); 4378 soc_reg_field_set(unit, CMIC_TS_GPIO_3_UP_EVENT_CTRLr, ®val, ENABLEf, 1); 4379 WRITE_CMIC_TS_GPIO_3_UP_EVENT_CTRLr(unit, regval); 4380 } 4381 if (soc_reg_field_valid(unit, CMIC_TS_GPIO_3_CTRLr, ENABLEf)) { 4382 READ_CMIC_TS_GPIO_3_CTRLr(unit, ®val); 4383 soc_reg_field_set(unit, CMIC_TS_GPIO_3_CTRLr, ®val, ENABLEf, 1); 4384 WRITE_CMIC_TS_GPIO_3_CTRLr(unit, regval); 4385 } 4386 break; 4387 4388 case BCM_TIME_CAPTURE_GPIO_4: 4389 capture_mode |= TIME_CAPTURE_MODE_GPIO_4; 4390 if (soc_reg_field_valid(unit, CMIC_TS_GPIO_4_DOWN_EVENT_CTRLr, ENABLEf)) { 4391 READ_CMIC_TS_GPIO_4_DOWN_EVENT_CTRLr(unit, ®val); 4392 soc_reg_field_set(unit, CMIC_TS_GPIO_4_DOWN_EVENT_CTRLr, ®val, ENABLEf, 1); 4393 WRITE_CMIC_TS_GPIO_4_DOWN_EVENT_CTRLr(unit, regval); 4394 } 4395 if (soc_reg_field_valid(unit, CMIC_TS_GPIO_4_UP_EVENT_CTRLr, ENABLEf)) { 4396 READ_CMIC_TS_GPIO_4_UP_EVENT_CTRLr(unit, ®val); 4397 soc_reg_field_set(unit, CMIC_TS_GPIO_4_UP_EVENT_CTRLr, ®val, ENABLEf, 1); 4398 WRITE_CMIC_TS_GPIO_4_UP_EVENT_CTRLr(unit, regval); 4399 } 4400 if (soc_reg_field_valid(unit, CMIC_TS_GPIO_4_CTRLr, ENABLEf)) { 4401 READ_CMIC_TS_GPIO_4_CTRLr(unit, ®val); 4402 soc_reg_field_set(unit, CMIC_TS_GPIO_4_CTRLr, ®val, ENABLEf, 1); 4403 WRITE_CMIC_TS_GPIO_4_CTRLr(unit, regval); 4404 } 4405 break; 4406 4407 case BCM_TIME_CAPTURE_GPIO_5: 4408 capture_mode |= TIME_CAPTURE_MODE_GPIO_5; 4409 if (soc_reg_field_valid(unit, CMIC_TS_GPIO_5_DOWN_EVENT_CTRLr, ENABLEf)) { 4410 READ_CMIC_TS_GPIO_5_DOWN_EVENT_CTRLr(unit, ®val); 4411 soc_reg_field_set(unit, CMIC_TS_GPIO_5_DOWN_EVENT_CTRLr, ®val, ENABLEf, 1); 4412 WRITE_CMIC_TS_GPIO_5_DOWN_EVENT_CTRLr(unit, regval); 4413 } 4414 if (soc_reg_field_valid(unit, CMIC_TS_GPIO_5_UP_EVENT_CTRLr, ENABLEf)) { 4415 READ_CMIC_TS_GPIO_5_UP_EVENT_CTRLr(unit, ®val); 4416 soc_reg_field_set(unit, CMIC_TS_GPIO_5_UP_EVENT_CTRLr, ®val, ENABLEf, 1); 4417 WRITE_CMIC_TS_GPIO_5_UP_EVENT_CTRLr(unit, regval); 4418 } 4419 if (soc_reg_field_valid(unit, CMIC_TS_GPIO_5_CTRLr, ENABLEf)) { 4420 READ_CMIC_TS_GPIO_5_CTRLr(unit, ®val); 4421 soc_reg_field_set(unit, CMIC_TS_GPIO_5_CTRLr, ®val, ENABLEf, 1); 4422 WRITE_CMIC_TS_GPIO_5_CTRLr(unit, regval); 4423 } 4424 break; 4425 4426 case BCM_TIME_CAPTURE_L1_CLOCK_PRIMARY: 4427 capture_mode |= TIME_CAPTURE_MODE_L1_CLOCK_PRIMARY; 4428 READ_CMIC_TS_L1_CLK_RECOVERED_CLK_COUNT_CTRLr(unit, ®val); 4429 soc_reg_field_set(unit, CMIC_TS_L1_CLK_RECOVERED_CLK_COUNT_CTRLr, ®val, ENABLEf, 1); 4430 WRITE_CMIC_TS_L1_CLK_RECOVERED_CLK_COUNT_CTRLr(unit, regval); 4431 break; 4432 4433 case BCM_TIME_CAPTURE_L1_CLOCK_SECONDARY: 4434 capture_mode |= TIME_CAPTURE_MODE_L1_CLOCK_SECONDARY; 4435 READ_CMIC_TS_L1_CLK_RECOVERED_CLK_BKUP_COUNT_CTRLr(unit, ®val); 4436 soc_reg_field_set(unit, CMIC_TS_L1_CLK_RECOVERED_CLK_BKUP_COUNT_CTRLr, ®val, ENABLEf, 1); 4437 WRITE_CMIC_TS_L1_CLK_RECOVERED_CLK_BKUP_COUNT_CTRLr(unit, regval); 4438 break; 4439 4440 case BCM_TIME_CAPTURE_LCPLL: 4441 capture_mode |= TIME_CAPTURE_MODE_LCPLL; 4442 READ_CMIC_TS_LCPLL_CLK_COUNT_CTRLr(unit, ®val); 4443 soc_reg_field_set(unit, CMIC_TS_LCPLL_CLK_COUNT_CTRLr, ®val, ENABLEf, 1); 4444 WRITE_CMIC_TS_LCPLL_CLK_COUNT_CTRLr(unit, regval); 4445 break; 4446 4447 case BCM_TIME_CAPTURE_IP_DM_0: 4448 capture_mode |= TIME_CAPTURE_MODE_IP_DM_0; 4449 break; 4450 4451 case BCM_TIME_CAPTURE_IP_DM_1: 4452 capture_mode |= TIME_CAPTURE_MODE_IP_DM_1; 4453 break; 4454 4455 default: 4456 break; 4457 } 4458 } 4459 4460 return capture_mode; 4461 } 4462 4463 /* 4464 * Function: 4465 * _bcm_esw_time_trigger_from_timestamp_mode 4466 * Purpose: 4467 * Convert Timesync capture modes to mode flags 4468 * 4469 * Parameters: 4470 * unit - (IN) capture_mode 4471 * 4472 * Returns: 4473 * Capture mode flags 4474 * Notes: 4475 */ 4476 4477 STATIC uint32 4478 _bcm_esw_time_trigger_from_timestamp_mode (uint32 capture_mode) 4479 { 4480 uint32 user_flags = 0; 4481 int bit_cnt; 4482 4483 /* processing on user mode flags reduces the dependencies on 4484 * hardware bit maps, byte shift of mode flags 4485 * should have been efficient 4486 */ 4487 for (bit_cnt = 0; bit_cnt < sizeof(uint32); bit_cnt++) 4488 { 4489 switch (capture_mode & (1 << bit_cnt)) 4490 { 4491 case TIME_CAPTURE_MODE_GPIO_0: 4492 user_flags |= BCM_TIME_CAPTURE_GPIO_0; 4493 break; 4494 case TIME_CAPTURE_MODE_GPIO_1: 4495 user_flags |= BCM_TIME_CAPTURE_GPIO_1; 4496 break; 4497 case TIME_CAPTURE_MODE_GPIO_2: 4498 user_flags |= BCM_TIME_CAPTURE_GPIO_2; 4499 break; 4500 case TIME_CAPTURE_MODE_GPIO_3: 4501 user_flags |= BCM_TIME_CAPTURE_GPIO_3; 4502 break; 4503 case TIME_CAPTURE_MODE_GPIO_4: 4504 user_flags |= BCM_TIME_CAPTURE_GPIO_4; 4505 break; 4506 case TIME_CAPTURE_MODE_GPIO_5: 4507 user_flags |= BCM_TIME_CAPTURE_GPIO_5; 4508 break; 4509 case TIME_CAPTURE_MODE_L1_CLOCK_PRIMARY: 4510 user_flags |= BCM_TIME_CAPTURE_L1_CLOCK_PRIMARY; 4511 break; 4512 case TIME_CAPTURE_MODE_L1_CLOCK_SECONDARY: 4513 user_flags |= BCM_TIME_CAPTURE_L1_CLOCK_SECONDARY; 4514 break; 4515 case TIME_CAPTURE_MODE_LCPLL: 4516 user_flags |= BCM_TIME_CAPTURE_LCPLL; 4517 break; 4518 case TIME_CAPTURE_MODE_IP_DM_0: 4519 user_flags |= BCM_TIME_CAPTURE_IP_DM_0; 4520 break; 4521 case TIME_CAPTURE_MODE_IP_DM_1: 4522 user_flags |= BCM_TIME_CAPTURE_IP_DM_1; 4523 break; 4524 default: 4525 break; 4526 } 4527 } 4528 4529 return user_flags; 4530 } 4531 4532 #endif /* (defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_TRIDENT2_SUPPORT)) */ 4533 4534 /* 4535 * Function: 4536 * bcm_esw_time_trigger_enable_set 4537 * Purpose: 4538 * Enables/Disables interrupt handling for external triggers 4539 * Parameters: 4540 * unit - (IN) StrataSwitch Unit #. 4541 * id - (IN) Time Sync Interface Id 4542 * mode_flags - (IN) Enable/Disable parameter 4543 * Returns: 4544 * BCM_E_NONE 4545 * BCM_E_XXX 4546 */ 4547 int 4548 bcm_esw_time_trigger_enable_set(int unit, bcm_time_if_t id, uint32 mode_flags) 4549 { 4550 #if (defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_TRIDENT2_SUPPORT)) 4551 uint32 regval, capture_mode = 0; 4552 soc_control_t *soc = SOC_CONTROL(unit); 4553 #endif 4554 4555 /* Check if time feature is supported on a device */ 4556 if (!(soc_feature(unit, soc_feature_time_support) && 4557 (SOC_IS_KATANAX(unit) || SOC_IS_TRIUMPH3(unit) || 4558 SOC_IS_TD2_TT2(unit)))) { 4559 return (BCM_E_UNAVAIL); 4560 } 4561 #if defined(BCM_TIME_V3_SUPPORT) 4562 /* Not supported in 3rd generation time arch */ 4563 if (soc_feature(unit, soc_feature_time_v3)) { 4564 return BCM_E_UNAVAIL; 4565 } 4566 #endif /* defined(BCM_TIME_V3_SUPPORT) */ 4567 4568 4569 /* Param validation check. */ 4570 BCM_IF_ERROR_RETURN( 4571 _bcm_esw_time_interface_id_validate(unit, id)); 4572 4573 TIME_LOCK(unit); 4574 4575 #if (defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_TRIDENT2_SUPPORT)) 4576 /* 4577 * Read time capture control capture modes and 4578 * Convert to hardware cature mode bitmap. 4579 * Enable interrupt for all capture mode bitmap and 4580 * Write time capture mode. 4581 * 4582 * If for ALL capture mode, ignore individual capture modes and 4583 * Enable Interrupts. 4584 */ 4585 READ_CMIC_TS_TIME_CAPTURE_CTRLr(unit, ®val); 4586 4587 if (mode_flags & BCM_TIME_CAPTURE_ALL) { 4588 /* Enable all Time capture mechanisms */ 4589 soc_reg_field_set(unit, CMIC_TS_TIME_CAPTURE_CTRLr, ®val, 4590 TIME_CAPTURE_ENABLEf, 1 ); 4591 4592 /* Return and ignore setting of individual capture modes */ 4593 return BCM_E_NONE; 4594 } 4595 4596 /* Set time capture modes */ 4597 capture_mode = _bcm_esw_time_trigger_to_timestamp_mode (unit, mode_flags); 4598 4599 /* Configure the HW with capture modes */ 4600 soc_reg_field_set(unit, CMIC_TS_TIME_CAPTURE_CTRLr, ®val, 4601 TIME_CAPTURE_MODEf, (capture_mode) ? capture_mode : 4602 TIME_CAPTURE_MODE_DISABLE); 4603 4604 /* Configure the HW to trigger interrupt for capture events */ 4605 soc_reg_field_set(unit, CMIC_TS_TIME_CAPTURE_CTRLr, ®val, INT_ENABLEf, 4606 (capture_mode) ? capture_mode : 0); 4607 4608 WRITE_CMIC_TS_TIME_CAPTURE_CTRLr(unit, regval); 4609 4610 TIME_UNLOCK(unit); 4611 4612 /* Enable/disable broadsync interrupt */ 4613 if (capture_mode) { 4614 /* Enable Interrupt */ 4615 soc_intr_enable(unit, IRQ_BROADSYNC_INTR); 4616 if (!soc->time_call_ref_count) { 4617 soc->soc_time_callout = _bcm_esw_time_hw_interrupt_dflt; 4618 } 4619 4620 } else { 4621 /* Check on the references and disable interrupt and handler */ 4622 soc_intr_disable(unit, IRQ_BROADSYNC_INTR); 4623 if (!soc->time_call_ref_count) { 4624 soc->soc_time_callout = NULL; 4625 } 4626 } 4627 #endif /* defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_TRIDENT2_SUPPORT) */ 4628 4629 return (BCM_E_NONE); 4630 } 4631 4632 /* 4633 * Function: 4634 * bcm_esw_time_trigger_enable_get 4635 * Purpose: 4636 * Gets interrupt handling status for each heartbeat provided by a 4637 * HW clock 4638 * Parameters: 4639 * unit - (IN) StrataSwitch Unit #. 4640 * id - (IN) Time Sync Interface Id 4641 * enable - (OUT) Enable status of interrupt handling 4642 * Returns: 4643 * BCM_E_NONE 4644 * BCM_E_XXX 4645 */ 4646 int 4647 bcm_esw_time_trigger_enable_get(int unit, bcm_time_if_t id, uint32 *mode_flags) 4648 { 4649 #if (defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_TRIDENT2_SUPPORT)) 4650 uint32 regval, capture_mode = 0; 4651 #endif 4652 4653 /* Chek if time feature is supported on a device */ 4654 if (!(soc_feature(unit, soc_feature_time_support) && 4655 (SOC_IS_KATANAX(unit) || SOC_IS_TRIUMPH3(unit) || 4656 SOC_IS_TD2_TT2(unit)))) { 4657 return (BCM_E_UNAVAIL); 4658 } 4659 4660 /* Param validation check. */ 4661 BCM_IF_ERROR_RETURN( 4662 _bcm_esw_time_interface_id_validate(unit, id)); 4663 4664 #ifdef BCM_TOMAHAWK_SUPPORT 4665 if (SOC_IS_TOMAHAWKX(unit)) { 4666 return BCM_E_UNAVAIL; 4667 } 4668 #endif /* BCM_TOMAHAWK_SUPPORT */ 4669 4670 #if defined(BCM_TIME_V3_SUPPORT) 4671 /* Not supported in 3rd generation time arch */ 4672 if (soc_feature(unit, soc_feature_time_v3)) { 4673 return BCM_E_UNAVAIL; 4674 } 4675 #endif /* defined(BCM_TIME_V3_SUPPORT) */ 4676 4677 4678 #if (defined(BCM_KATANA2_SUPPORT) || defined(BCM_HELIX4_SUPPORT)) 4679 /* Install heartbeat and external trigger clock interval */ 4680 if (SOC_IS_KATANA2(unit) || SOC_IS_HELIX4(unit)) { 4681 /* Read HW Configuration */ 4682 READ_CMIC_TIMESYNC_INTERRUPT_ENABLEr(unit, ®val); 4683 4684 /* Get interrupt enabled capture modes */ 4685 capture_mode = soc_reg_field_get(unit, CMIC_TIMESYNC_INTERRUPT_ENABLEr, regval, INT_ENABLEf); 4686 *mode_flags = _bcm_esw_time_trigger_from_timestamp_mode (capture_mode); 4687 } else 4688 #endif 4689 { 4690 #if (defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_TRIDENT2_SUPPORT)) 4691 /* Read HW Configuration */ 4692 READ_CMIC_TS_TIME_CAPTURE_CTRLr(unit, ®val); 4693 4694 /* Get interrupt enabled capture modes */ 4695 capture_mode = soc_reg_field_get(unit, CMIC_TS_TIME_CAPTURE_CTRLr, regval, INT_ENABLEf); 4696 4697 *mode_flags = _bcm_esw_time_trigger_from_timestamp_mode (capture_mode); 4698 #endif /* (defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_TRIDENT2_SUPPORT)) */ 4699 } 4700 4701 return (BCM_E_NONE); 4702 } 4703 4704 4705 /* 4706 * Function: 4707 * bcm_esw_time_heartbeat_register 4708 * Purpose: 4709 * Registers a call back function to be called on each heartbeat 4710 * Parameters: 4711 * unit - (IN) StrataSwitch Unit #. 4712 * id - (IN) Time Sync Interface Id 4713 * f - (IN) Function to register 4714 * user_data - (IN) void pointer to store any user information 4715 * Returns: 4716 * BCM_E_NONE 4717 * BCM_E_XXX 4718 */ 4719 int 4720 bcm_esw_time_heartbeat_register (int unit, bcm_time_if_t id, bcm_time_heartbeat_cb f, 4721 void *user_data) 4722 { 4723 soc_control_t *soc = SOC_CONTROL(unit); 4724 4725 /* Chek if time feature is supported on a device */ 4726 if (!soc_feature(unit, soc_feature_time_support)) { 4727 return (BCM_E_UNAVAIL); 4728 } 4729 4730 /* Param validation check. */ 4731 BCM_IF_ERROR_RETURN( 4732 _bcm_esw_time_interface_id_validate(unit, id)); 4733 if (NULL == f) { 4734 return (BCM_E_PARAM); 4735 } 4736 4737 TIME_LOCK(unit); 4738 /* If HW interrupt handler been registered protect from race condition */ 4739 if (soc->time_call_ref_count) { 4740 soc->soc_time_callout = _bcm_esw_time_hw_interrupt_dflt; 4741 } 4742 4743 /* Register user call back */ 4744 TIME_INTERFACE_CONFIG(unit, id).user_cb->heartbeat_cb = f; 4745 TIME_INTERFACE_CONFIG(unit, id).user_cb->user_data = user_data; 4746 4747 /* After registering user cb function and user_data turn on 4748 HW interrupt handler */ 4749 soc->soc_time_callout = _bcm_esw_time_hw_interrupt; 4750 /* Only single call back at a time is currently supported */ 4751 soc->time_call_ref_count = 1; 4752 4753 TIME_UNLOCK(unit); 4754 4755 return (BCM_E_NONE); 4756 } 4757 4758 /* 4759 * Function: 4760 * bcm_esw_time_heartbeat_unregister 4761 * Purpose: 4762 * Unregisters a call back function to be called on each heartbeat 4763 * Parameters: 4764 * unit - (IN) StrataSwitch Unit #. 4765 * id - (IN) Time Sync Interface Id 4766 * Returns: 4767 * BCM_E_NONE 4768 * BCM_E_XXX 4769 */ 4770 int 4771 bcm_esw_time_heartbeat_unregister (int unit, bcm_time_if_t id) 4772 { 4773 soc_control_t *soc = SOC_CONTROL(unit); 4774 4775 /* Chek if time feature is supported on a device */ 4776 if (!soc_feature(unit, soc_feature_time_support)) { 4777 return (BCM_E_UNAVAIL); 4778 } 4779 4780 /* Param validation check. */ 4781 BCM_IF_ERROR_RETURN( 4782 _bcm_esw_time_interface_id_validate(unit, id)); 4783 4784 TIME_LOCK(unit); 4785 4786 if (--soc->time_call_ref_count <= 0) { 4787 soc->time_call_ref_count = 0; 4788 soc->soc_time_callout = _bcm_esw_time_hw_interrupt_dflt; 4789 } 4790 TIME_INTERFACE_CONFIG(unit, id).user_cb->heartbeat_cb = NULL; 4791 TIME_INTERFACE_CONFIG(unit, id).user_cb->user_data = NULL; 4792 4793 TIME_UNLOCK(unit); 4794 4795 return (BCM_E_NONE); 4796 } 4797 4798 4799 #ifdef BCM_WARM_BOOT_SUPPORT_SW_DUMP 4800 /* 4801 * Function: 4802 * _bcm_time_sw_dump 4803 * Purpose: 4804 * Displays time information maintained by software. 4805 * Parameters: 4806 * unit - Device unit number 4807 * Returns: 4808 * None 4809 */ 4810 void 4811 _bcm_time_sw_dump(int unit) 4812 { 4813 soc_control_t *soc = SOC_CONTROL(unit); 4814 4815 LOG_CLI((BSL_META_U(unit, 4816 "\nSW Information TIME - Unit %d\n"), unit)); 4817 LOG_CLI((BSL_META_U(unit, 4818 " Time call reference counter = %d\n"), soc->time_call_ref_count)); 4819 if (NULL != soc->soc_time_callout) { 4820 LOG_CLI((BSL_META_U(unit, 4821 " Time interrupt handler address is = %p\n"), 4822 (void *)(unsigned long)soc->soc_time_callout)); 4823 } else { 4824 LOG_CLI((BSL_META_U(unit, 4825 " Time interrupt handler is NULL \n"))); 4826 } 4827 } 4828 #endif /* BCM_WARM_BOOT_SUPPORT_SW_DUMP */ 4829 4830 4831 /********************************** ESW BroadSync Time Support ***********************************/ 4832 4833 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || \ 4834 defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_HELIX4_SUPPORT) || \ 4835 defined(BCM_KATANA2_SUPPORT) || defined(BCM_TOMAHAWK_SUPPORT) || \ 4836 defined(BCM_HURRICANE2_SUPPORT) || defined(BCM_GREYHOUND_SUPPORT) || \ 4837 defined(BCM_SABER2_SUPPORT) 4838 STATIC 4839 int 4840 _bcm_esw_time_bs_init(int unit, bcm_time_interface_t *intf) 4841 { 4842 const int bspll_freq = 20000000; /* 20 MHz */ 4843 4844 uint32 regval = 0; 4845 4846 int master = ((intf->flags & BCM_TIME_INPUT) == 0); 4847 int output_enable = master && ((intf->flags & BCM_TIME_ENABLE) != 0); 4848 4849 int bitclk_divisor = bspll_freq / intf->bitclock_hz; 4850 int bitclk_high = bitclk_divisor / 2; 4851 int bitclk_low = bitclk_divisor - bitclk_high; 4852 int hb_divisor = intf->bitclock_hz / intf->heartbeat_hz; 4853 int hb_up = (hb_divisor > 200) ? 100 : (hb_divisor / 2); 4854 int hb_down = hb_divisor - hb_up; 4855 int bs_ndiv_int = 0; 4856 4857 uint32 freq_ctrl_lower = 0x40000000; /* 4ns increment, for 250MHz TSPLL output */ 4858 4859 4860 #if defined(BCM_TIME_V3_OR_IPROC_MANAGED_BROADSYNC) 4861 /*****************************************************************************/ 4862 /* Perform KATANA2, HELIX4, HURRICANE2, GREYHOUND, SABER2, APACHE IPROC HW configuration */ 4863 /*****************************************************************************/ 4864 if (SOC_HAS_TIME_V3_OR_IPROC_MANAGED_BROADSYNC(unit)) { 4865 freq_ctrl_lower = 4; /* 4ns increment, for 250MHz TSPLL output */ 4866 4867 if (SOC_IS_GREYHOUND(unit) || SOC_IS_SABER2(unit) || 4868 SOC_IS_HURRICANE3(unit)) { 4869 /* Feature unavailable on devices without BroadSync support. */ 4870 if (soc_feature(unit, soc_feature_time_v3_no_bs)) { 4871 return BCM_E_UNAVAIL; 4872 } 4873 } 4874 if (SOC_IS_TOMAHAWK3(unit)) { 4875 /* configure BS0/BS1 Clock control registers (HIGH_DURATION / LOW_DURATION) */ 4876 READ_NS_BS0_BS_CLK_CTRLr(unit, ®val); 4877 soc_reg_field_set(unit, NS_BS0_BS_CLK_CTRLr, ®val, LOW_DURATIONf, bitclk_low); 4878 soc_reg_field_set(unit, NS_BS0_BS_CLK_CTRLr, ®val, HIGH_DURATIONf, bitclk_high); 4879 WRITE_NS_BS0_BS_CLK_CTRLr(unit, regval); 4880 4881 READ_NS_BS0_BS_CLK_CTRLr(unit, ®val); 4882 soc_reg_field_set(unit, NS_BS0_BS_CLK_CTRLr, ®val, ENABLEf, 1); 4883 WRITE_NS_BS0_BS_CLK_CTRLr(unit, regval); 4884 4885 READ_NS_BS1_BS_CLK_CTRLr(unit, ®val); 4886 soc_reg_field_set(unit, NS_BS1_BS_CLK_CTRLr, ®val, LOW_DURATIONf, bitclk_low); 4887 soc_reg_field_set(unit, NS_BS1_BS_CLK_CTRLr, ®val, HIGH_DURATIONf, bitclk_high); 4888 WRITE_NS_BS1_BS_CLK_CTRLr(unit, regval); 4889 4890 READ_NS_BS1_BS_CLK_CTRLr(unit, ®val); 4891 soc_reg_field_set(unit, NS_BS1_BS_CLK_CTRLr, ®val, ENABLEf, 1); 4892 WRITE_NS_BS1_BS_CLK_CTRLr(unit, regval); 4893 4894 /* configure BS0/BS1 Clock configuration registers */ 4895 READ_NS_BS0_BS_CONFIGr(unit, ®val); 4896 soc_reg_field_set(unit, NS_BS0_BS_CONFIGr, ®val, MODEf, master ? TIME_MODE_OUTPUT : TIME_MODE_INPUT); 4897 soc_reg_field_set(unit, NS_BS0_BS_CONFIGr, ®val, BS_CLK_OUTPUT_ENABLEf, output_enable); 4898 soc_reg_field_set(unit, NS_BS0_BS_CONFIGr, ®val, BS_HB_OUTPUT_ENABLEf, output_enable); 4899 soc_reg_field_set(unit, NS_BS0_BS_CONFIGr, ®val, BS_TC_OUTPUT_ENABLEf, output_enable); 4900 WRITE_NS_BS0_BS_CONFIGr(unit, regval); 4901 4902 READ_NS_BS1_BS_CONFIGr(unit, ®val); 4903 soc_reg_field_set(unit, NS_BS1_BS_CONFIGr, ®val, MODEf, master ? TIME_MODE_OUTPUT : TIME_MODE_INPUT); 4904 soc_reg_field_set(unit, NS_BS1_BS_CONFIGr, ®val, BS_CLK_OUTPUT_ENABLEf, output_enable); 4905 soc_reg_field_set(unit, NS_BS1_BS_CONFIGr, ®val, BS_HB_OUTPUT_ENABLEf, output_enable); 4906 soc_reg_field_set(unit, NS_BS1_BS_CONFIGr, ®val, BS_TC_OUTPUT_ENABLEf, output_enable); 4907 WRITE_NS_BS1_BS_CONFIGr(unit, regval); 4908 4909 READ_NS_TIMESYNC_TS0_FREQ_CTRL_FRAC_LOWERr(unit, ®val); 4910 soc_reg_field_set(unit, NS_TIMESYNC_TS0_FREQ_CTRL_FRAC_LOWERr, ®val, LINCf, freq_ctrl_lower); 4911 WRITE_NS_TIMESYNC_TS0_FREQ_CTRL_FRAC_LOWERr(unit, regval); 4912 4913 READ_NS_TIMESYNC_TS0_CURRENT_FREQ_CTRL_LOWERr(unit, ®val); 4914 soc_reg_field_set(unit, NS_TIMESYNC_TS0_CURRENT_FREQ_CTRL_LOWERr, ®val, FCLf, 0); 4915 WRITE_NS_TIMESYNC_TS0_CURRENT_FREQ_CTRL_LOWERr(unit, regval); 4916 4917 READ_NS_TIMESYNC_TS0_CURRENT_FREQ_CTRL_UPPERr(unit, ®val); 4918 soc_reg_field_set(unit, NS_TIMESYNC_TS0_CURRENT_FREQ_CTRL_UPPERr, ®val, FCUf, 0); 4919 WRITE_NS_TIMESYNC_TS0_CURRENT_FREQ_CTRL_UPPERr(unit, regval); 4920 4921 READ_NS_TIMESYNC_TS0_COUNTER_ENABLEr(unit, ®val); 4922 soc_reg_field_set(unit, NS_TIMESYNC_TS0_COUNTER_ENABLEr, ®val, ENABLEf, 1); 4923 WRITE_NS_TIMESYNC_TS0_COUNTER_ENABLEr(unit, regval); 4924 4925 /* Setup BS0/BS1 HeartBeat Control registers */ 4926 READ_NS_BS0_BS_HEARTBEAT_CTRLr(unit, ®val); 4927 soc_reg_field_set(unit, NS_BS0_BS_HEARTBEAT_CTRLr, ®val, ENABLEf, 1); 4928 WRITE_NS_BS0_BS_HEARTBEAT_CTRLr(unit, regval); 4929 4930 READ_NS_BS1_BS_HEARTBEAT_CTRLr(unit, ®val); 4931 soc_reg_field_set(unit, NS_BS1_BS_HEARTBEAT_CTRLr, ®val, ENABLEf, 1); 4932 WRITE_NS_BS1_BS_HEARTBEAT_CTRLr(unit, regval); 4933 4934 READ_NS_BS0_BS_HEARTBEAT_DOWN_DURATIONr(unit, ®val); 4935 soc_reg_field_set(unit, NS_BS0_BS_HEARTBEAT_DOWN_DURATIONr, ®val, DOWN_DURATIONf, hb_down); 4936 WRITE_NS_BS0_BS_HEARTBEAT_DOWN_DURATIONr(unit, regval); 4937 4938 READ_NS_BS1_BS_HEARTBEAT_DOWN_DURATIONr(unit, ®val); 4939 soc_reg_field_set(unit, NS_BS1_BS_HEARTBEAT_DOWN_DURATIONr, ®val, DOWN_DURATIONf, hb_down); 4940 WRITE_NS_BS1_BS_HEARTBEAT_DOWN_DURATIONr(unit, regval); 4941 4942 READ_NS_BS0_BS_HEARTBEAT_UP_DURATIONr(unit, ®val); 4943 soc_reg_field_set(unit, NS_BS0_BS_HEARTBEAT_UP_DURATIONr, ®val, UP_DURATIONf, hb_up); 4944 WRITE_NS_BS0_BS_HEARTBEAT_UP_DURATIONr(unit, regval); 4945 4946 READ_NS_BS1_BS_HEARTBEAT_UP_DURATIONr(unit, ®val); 4947 soc_reg_field_set(unit, NS_BS1_BS_HEARTBEAT_UP_DURATIONr, ®val, UP_DURATIONf, hb_up); 4948 WRITE_NS_BS1_BS_HEARTBEAT_UP_DURATIONr(unit, regval); 4949 4950 READ_NS_BS0_BS_CLK_CTRLr(unit, ®val); 4951 soc_reg_field_set(unit, NS_BS0_BS_CLK_CTRLr, ®val, ENABLEf, 0); 4952 WRITE_NS_BS0_BS_CLK_CTRLr(unit, regval); 4953 4954 READ_NS_BS1_BS_CLK_CTRLr(unit, ®val); 4955 soc_reg_field_set(unit, NS_BS1_BS_CLK_CTRLr, ®val, ENABLEf, 0); 4956 WRITE_NS_BS1_BS_CLK_CTRLr(unit, regval); 4957 4958 READ_NS_BROADSYNC_REF_CLK_GEN_CTRLr(unit, ®val); 4959 soc_reg_field_set(unit, NS_BROADSYNC_REF_CLK_GEN_CTRLr, ®val, ENABLEf, 0); 4960 WRITE_NS_BROADSYNC_REF_CLK_GEN_CTRLr(unit, regval); 4961 4962 /* configure BS0/BS1 Clock control registers (HIGH_DURATION / LOW_DURATION) */ 4963 READ_NS_BS0_BS_CLK_CTRLr(unit, ®val); 4964 soc_reg_field_set(unit, NS_BS0_BS_CLK_CTRLr, ®val, LOW_DURATIONf, bitclk_low); 4965 soc_reg_field_set(unit, NS_BS0_BS_CLK_CTRLr, ®val, HIGH_DURATIONf, bitclk_high); 4966 WRITE_NS_BS0_BS_CLK_CTRLr(unit, regval); 4967 4968 READ_NS_BS0_BS_CLK_CTRLr(unit, ®val); 4969 soc_reg_field_set(unit, NS_BS0_BS_CLK_CTRLr, ®val, ENABLEf, 1); 4970 WRITE_NS_BS0_BS_CLK_CTRLr(unit, regval); 4971 4972 READ_NS_BS1_BS_CLK_CTRLr(unit, ®val); 4973 soc_reg_field_set(unit, NS_BS1_BS_CLK_CTRLr, ®val, LOW_DURATIONf, bitclk_low); 4974 soc_reg_field_set(unit, NS_BS1_BS_CLK_CTRLr, ®val, HIGH_DURATIONf, bitclk_high); 4975 WRITE_NS_BS1_BS_CLK_CTRLr(unit, regval); 4976 4977 READ_NS_BS1_BS_CLK_CTRLr(unit, ®val); 4978 soc_reg_field_set(unit, NS_BS1_BS_CLK_CTRLr, ®val, ENABLEf, 1); 4979 WRITE_NS_BS1_BS_CLK_CTRLr(unit, regval); 4980 4981 /* configure BS0/BS1 Clock configuration registers */ 4982 READ_NS_BS0_BS_CONFIGr(unit, ®val); 4983 soc_reg_field_set(unit, NS_BS0_BS_CONFIGr, ®val, MODEf, master ? TIME_MODE_OUTPUT : TIME_MODE_INPUT); 4984 soc_reg_field_set(unit, NS_BS0_BS_CONFIGr, ®val, BS_CLK_OUTPUT_ENABLEf, output_enable); 4985 soc_reg_field_set(unit, NS_BS0_BS_CONFIGr, ®val, BS_HB_OUTPUT_ENABLEf, output_enable); 4986 soc_reg_field_set(unit, NS_BS0_BS_CONFIGr, ®val, BS_TC_OUTPUT_ENABLEf, output_enable); 4987 WRITE_NS_BS0_BS_CONFIGr(unit, regval); 4988 4989 READ_NS_BS1_BS_CONFIGr(unit, ®val); 4990 soc_reg_field_set(unit, NS_BS1_BS_CONFIGr, ®val, MODEf, master ? TIME_MODE_OUTPUT : TIME_MODE_INPUT); 4991 soc_reg_field_set(unit, NS_BS1_BS_CONFIGr, ®val, BS_CLK_OUTPUT_ENABLEf, output_enable); 4992 soc_reg_field_set(unit, NS_BS1_BS_CONFIGr, ®val, BS_HB_OUTPUT_ENABLEf, output_enable); 4993 soc_reg_field_set(unit, NS_BS1_BS_CONFIGr, ®val, BS_TC_OUTPUT_ENABLEf, output_enable); 4994 WRITE_NS_BS1_BS_CONFIGr(unit, regval); 4995 } else { 4996 4997 /* configure BS0/BS1 Clock control registers (HIGH_DURATION / LOW_DURATION) */ 4998 READ_CMIC_BS0_CLK_CTRLr(unit, ®val); 4999 soc_reg_field_set(unit, CMIC_BS0_CLK_CTRLr, ®val, LOW_DURATIONf, bitclk_low); 5000 soc_reg_field_set(unit, CMIC_BS0_CLK_CTRLr, ®val, HIGH_DURATIONf, bitclk_high); 5001 WRITE_CMIC_BS0_CLK_CTRLr(unit, regval); 5002 5003 READ_CMIC_BS0_CLK_CTRLr(unit, ®val); 5004 soc_reg_field_set(unit, CMIC_BS0_CLK_CTRLr, ®val, ENABLEf, 1); 5005 WRITE_CMIC_BS0_CLK_CTRLr(unit, regval); 5006 5007 READ_CMIC_BS1_CLK_CTRLr(unit, ®val); 5008 soc_reg_field_set(unit, CMIC_BS1_CLK_CTRLr, ®val, LOW_DURATIONf, bitclk_low); 5009 soc_reg_field_set(unit, CMIC_BS1_CLK_CTRLr, ®val, HIGH_DURATIONf, bitclk_high); 5010 WRITE_CMIC_BS1_CLK_CTRLr(unit, regval); 5011 5012 READ_CMIC_BS1_CLK_CTRLr(unit, ®val); 5013 soc_reg_field_set(unit, CMIC_BS1_CLK_CTRLr, ®val, ENABLEf, 1); 5014 WRITE_CMIC_BS1_CLK_CTRLr(unit, regval); 5015 5016 /* configure BS0/BS1 Clock configuration registers */ 5017 READ_CMIC_BS0_CONFIGr(unit, ®val); 5018 soc_reg_field_set(unit, CMIC_BS0_CONFIGr, ®val, MODEf, master ? TIME_MODE_OUTPUT : TIME_MODE_INPUT); 5019 soc_reg_field_set(unit, CMIC_BS0_CONFIGr, ®val, BS_CLK_OUTPUT_ENABLEf, output_enable); 5020 soc_reg_field_set(unit, CMIC_BS0_CONFIGr, ®val, BS_HB_OUTPUT_ENABLEf, output_enable); 5021 soc_reg_field_set(unit, CMIC_BS0_CONFIGr, ®val, BS_TC_OUTPUT_ENABLEf, output_enable); 5022 WRITE_CMIC_BS0_CONFIGr(unit, regval); 5023 5024 READ_CMIC_BS1_CONFIGr(unit, ®val); 5025 soc_reg_field_set(unit, CMIC_BS1_CONFIGr, ®val, MODEf, master ? TIME_MODE_OUTPUT : TIME_MODE_INPUT); 5026 soc_reg_field_set(unit, CMIC_BS1_CONFIGr, ®val, BS_CLK_OUTPUT_ENABLEf, output_enable); 5027 soc_reg_field_set(unit, CMIC_BS1_CONFIGr, ®val, BS_HB_OUTPUT_ENABLEf, output_enable); 5028 soc_reg_field_set(unit, CMIC_BS1_CONFIGr, ®val, BS_TC_OUTPUT_ENABLEf, output_enable); 5029 WRITE_CMIC_BS1_CONFIGr(unit, regval); 5030 5031 READ_CMIC_TIMESYNC_TS0_FREQ_CTRL_FRACr(unit, ®val); 5032 soc_reg_field_set(unit, CMIC_TIMESYNC_TS0_FREQ_CTRL_FRACr, ®val, FRACf, freq_ctrl_lower); 5033 WRITE_CMIC_TIMESYNC_TS0_FREQ_CTRL_FRACr(unit, regval); 5034 5035 READ_CMIC_TIMESYNC_TS0_FREQ_CTRL_LOWERr(unit, ®val); 5036 soc_reg_field_set(unit, CMIC_TIMESYNC_TS0_FREQ_CTRL_LOWERr, ®val, NSf, 0); 5037 WRITE_CMIC_TIMESYNC_TS0_FREQ_CTRL_LOWERr(unit, regval); 5038 5039 READ_CMIC_TIMESYNC_TS0_FREQ_CTRL_UPPERr(unit, ®val); 5040 soc_reg_field_set(unit, CMIC_TIMESYNC_TS0_FREQ_CTRL_UPPERr, ®val, NSf, 0); 5041 WRITE_CMIC_TIMESYNC_TS0_FREQ_CTRL_UPPERr(unit, regval); 5042 5043 READ_CMIC_TIMESYNC_TS0_COUNTER_ENABLEr(unit, ®val); 5044 soc_reg_field_set(unit, CMIC_TIMESYNC_TS0_COUNTER_ENABLEr, ®val, ENABLEf, 1); 5045 WRITE_CMIC_TIMESYNC_TS0_COUNTER_ENABLEr(unit, regval); 5046 5047 /* Setup BS0/BS1 HeartBeat Control registers */ 5048 READ_CMIC_BS0_HEARTBEAT_CTRLr(unit, ®val); 5049 soc_reg_field_set(unit, CMIC_BS0_HEARTBEAT_CTRLr, ®val, ENABLEf, 1); 5050 WRITE_CMIC_BS0_HEARTBEAT_CTRLr(unit, regval); 5051 5052 READ_CMIC_BS1_HEARTBEAT_CTRLr(unit, ®val); 5053 soc_reg_field_set(unit, CMIC_BS1_HEARTBEAT_CTRLr, ®val, ENABLEf, 1); 5054 WRITE_CMIC_BS1_HEARTBEAT_CTRLr(unit, regval); 5055 5056 READ_CMIC_BS0_HEARTBEAT_DOWN_DURATIONr(unit, ®val); 5057 soc_reg_field_set(unit, CMIC_BS0_HEARTBEAT_DOWN_DURATIONr, ®val, DOWN_DURATIONf, hb_down); 5058 WRITE_CMIC_BS0_HEARTBEAT_DOWN_DURATIONr(unit, regval); 5059 5060 READ_CMIC_BS1_HEARTBEAT_DOWN_DURATIONr(unit, ®val); 5061 soc_reg_field_set(unit, CMIC_BS1_HEARTBEAT_DOWN_DURATIONr, ®val, DOWN_DURATIONf, hb_down); 5062 WRITE_CMIC_BS1_HEARTBEAT_DOWN_DURATIONr(unit, regval); 5063 5064 READ_CMIC_BS0_HEARTBEAT_UP_DURATIONr(unit, ®val); 5065 soc_reg_field_set(unit, CMIC_BS0_HEARTBEAT_UP_DURATIONr, ®val, UP_DURATIONf, hb_up); 5066 WRITE_CMIC_BS0_HEARTBEAT_UP_DURATIONr(unit, regval); 5067 5068 READ_CMIC_BS1_HEARTBEAT_UP_DURATIONr(unit, ®val); 5069 soc_reg_field_set(unit, CMIC_BS1_HEARTBEAT_UP_DURATIONr, ®val, UP_DURATIONf, hb_up); 5070 WRITE_CMIC_BS1_HEARTBEAT_UP_DURATIONr(unit, regval); 5071 5072 READ_CMIC_BS0_CLK_CTRLr(unit, ®val); 5073 soc_reg_field_set(unit, CMIC_BS0_CLK_CTRLr, ®val, ENABLEf, 0); 5074 WRITE_CMIC_BS0_CLK_CTRLr(unit, regval); 5075 5076 READ_CMIC_BS1_CLK_CTRLr(unit, ®val); 5077 soc_reg_field_set(unit, CMIC_BS1_CLK_CTRLr, ®val, ENABLEf, 0); 5078 WRITE_CMIC_BS1_CLK_CTRLr(unit, regval); 5079 5080 READ_CMIC_BROADSYNC_REF_CLK_GEN_CTRLr(unit, ®val); 5081 soc_reg_field_set(unit, CMIC_BROADSYNC_REF_CLK_GEN_CTRLr, ®val, ENABLEf, 0); 5082 WRITE_CMIC_BROADSYNC_REF_CLK_GEN_CTRLr(unit, regval); 5083 5084 /* configure BS0/BS1 Clock control registers (HIGH_DURATION / LOW_DURATION) */ 5085 READ_CMIC_BS0_CLK_CTRLr(unit, ®val); 5086 soc_reg_field_set(unit, CMIC_BS0_CLK_CTRLr, ®val, LOW_DURATIONf, bitclk_low); 5087 soc_reg_field_set(unit, CMIC_BS0_CLK_CTRLr, ®val, HIGH_DURATIONf, bitclk_high); 5088 WRITE_CMIC_BS0_CLK_CTRLr(unit, regval); 5089 5090 READ_CMIC_BS0_CLK_CTRLr(unit, ®val); 5091 soc_reg_field_set(unit, CMIC_BS0_CLK_CTRLr, ®val, ENABLEf, 1); 5092 WRITE_CMIC_BS0_CLK_CTRLr(unit, regval); 5093 5094 READ_CMIC_BS1_CLK_CTRLr(unit, ®val); 5095 soc_reg_field_set(unit, CMIC_BS1_CLK_CTRLr, ®val, LOW_DURATIONf, bitclk_low); 5096 soc_reg_field_set(unit, CMIC_BS1_CLK_CTRLr, ®val, HIGH_DURATIONf, bitclk_high); 5097 WRITE_CMIC_BS1_CLK_CTRLr(unit, regval); 5098 5099 READ_CMIC_BS1_CLK_CTRLr(unit, ®val); 5100 soc_reg_field_set(unit, CMIC_BS1_CLK_CTRLr, ®val, ENABLEf, 1); 5101 WRITE_CMIC_BS1_CLK_CTRLr(unit, regval); 5102 5103 /* configure BS0/BS1 Clock configuration registers */ 5104 READ_CMIC_BS0_CONFIGr(unit, ®val); 5105 soc_reg_field_set(unit, CMIC_BS0_CONFIGr, ®val, MODEf, master ? TIME_MODE_OUTPUT : TIME_MODE_INPUT); 5106 soc_reg_field_set(unit, CMIC_BS0_CONFIGr, ®val, BS_CLK_OUTPUT_ENABLEf, output_enable); 5107 soc_reg_field_set(unit, CMIC_BS0_CONFIGr, ®val, BS_HB_OUTPUT_ENABLEf, output_enable); 5108 soc_reg_field_set(unit, CMIC_BS0_CONFIGr, ®val, BS_TC_OUTPUT_ENABLEf, output_enable); 5109 WRITE_CMIC_BS0_CONFIGr(unit, regval); 5110 5111 READ_CMIC_BS1_CONFIGr(unit, ®val); 5112 soc_reg_field_set(unit, CMIC_BS1_CONFIGr, ®val, MODEf, master ? TIME_MODE_OUTPUT : TIME_MODE_INPUT); 5113 soc_reg_field_set(unit, CMIC_BS1_CONFIGr, ®val, BS_CLK_OUTPUT_ENABLEf, output_enable); 5114 soc_reg_field_set(unit, CMIC_BS1_CONFIGr, ®val, BS_HB_OUTPUT_ENABLEf, output_enable); 5115 soc_reg_field_set(unit, CMIC_BS1_CONFIGr, ®val, BS_TC_OUTPUT_ENABLEf, output_enable); 5116 WRITE_CMIC_BS1_CONFIGr(unit, regval); 5117 } 5118 } else 5119 #endif /* BCM_TIME_V3_OR_IPROC_MANAGED_BROADSYNC */ 5120 /*****************************************************************************/ 5121 /* Non-KATANA2, HELIX4, HURRICANE2, GREYHOUND HW configuration */ 5122 /*****************************************************************************/ 5123 { 5124 #if defined(BCM_KATANA_SUPPORT) 5125 if (SOC_IS_KATANA(unit)) { 5126 READ_TOP_BROAD_SYNC_PLL_CTRL_REGISTER_3r(unit, ®val); 5127 bs_ndiv_int = soc_reg_field_get(unit, TOP_BROAD_SYNC_PLL_CTRL_REGISTER_3r, 5128 regval, NDIV_INTf); 5129 } 5130 #endif /* defined(BCM_KATANA_SUPPORT) */ 5131 5132 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_TRIDENT2_SUPPORT) 5133 if (SOC_IS_TRIUMPH3(unit) && !SOC_IS_TD2P_TT2P(unit)) { 5134 READ_TOP_BS_PLL_CTRL_3r(unit, ®val); 5135 bs_ndiv_int = soc_reg_field_get(unit, TOP_BS_PLL_CTRL_3r, 5136 regval, NDIV_INTf); 5137 bs_ndiv_int = (regval & 0x3ff); 5138 } else if (SOC_IS_TD2P_TT2P(unit)) { 5139 READ_TOP_BS_PLL_CTRL_4r(unit, ®val); 5140 bs_ndiv_int = soc_reg_field_get(unit, TOP_BS_PLL_CTRL_4r, 5141 regval, NDIV_INTf); 5142 bs_ndiv_int = (regval & 0x3ff); 5143 } 5144 #endif /* defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_TRIDENT2_SUPPORT) */ 5145 5146 if (bs_ndiv_int == 300) { 5147 /* Take a BroadSync NDIV_INT value of 0 as a signal that the input 5148 * reference frequency is 12.8 MHz, so TSPLL will produce 248MHz, 5149 * not 250MHz 5150 */ 5151 freq_ctrl_lower = 0x40842108; 5152 } 5153 5154 #if defined(BCM_TRIDENT2_SUPPORT) 5155 if (SOC_IS_TD2_TT2(unit)) { 5156 /* m top_soft_reset_reg_2 top_bs_pll_rst_l=0 top_bs_pll_post_rst_l=0 */ 5157 READ_TOP_SOFT_RESET_REG_2r(unit, ®val); 5158 soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, ®val, TOP_BS_PLL_RST_Lf, 0); 5159 soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, ®val, TOP_BS_PLL_POST_RST_Lf, 0); 5160 WRITE_TOP_SOFT_RESET_REG_2r(unit, regval); 5161 5162 if (!SOC_IS_TD2P_TT2P(unit)) { 5163 /* m TOP_BS_PLL_CTRL_0 VCO_DIV2=1 */ 5164 READ_TOP_BS_PLL_CTRL_0r(unit, ®val); 5165 soc_reg_field_set(unit, TOP_BS_PLL_CTRL_0r, ®val, VCO_DIV2f, 1); 5166 WRITE_TOP_BS_PLL_CTRL_0r(unit, regval); 5167 5168 /* m TOP_BS_PLL_CTRL_2 PDIV=1 CH0_MDIV=175 */ 5169 READ_TOP_BS_PLL_CTRL_2r(unit, ®val); 5170 soc_reg_field_set(unit, TOP_BS_PLL_CTRL_2r, ®val, PDIVf, 1); 5171 soc_reg_field_set(unit, TOP_BS_PLL_CTRL_2r, ®val, CH0_MDIVf, 175); 5172 WRITE_TOP_BS_PLL_CTRL_2r(unit, regval); 5173 } else { 5174 5175 READ_TOP_BS_PLL_CTRL_0r(unit, ®val); 5176 soc_reg_field_set(unit, TOP_BS_PLL_CTRL_0r, ®val, VCO_FB_DIV2f, 1); 5177 WRITE_TOP_BS_PLL_CTRL_0r(unit, regval); 5178 5179 /* TD2+: Keeping default for VCO_DIV2(=1), NDIV(=140.0), PDIV(=1) */ 5180 READ_TOP_BS_PLL_CTRL_3r(unit, ®val); 5181 soc_reg_field_set(unit, TOP_BS_PLL_CTRL_3r, ®val, PDIVf, 1); 5182 soc_reg_field_set(unit, TOP_BS_PLL_CTRL_3r, ®val, CH0_MDIVf, 175); 5183 WRITE_TOP_BS_PLL_CTRL_3r(unit, regval); 5184 } 5185 5186 /* m top_soft_reset_reg_2 top_bs_pll_rst_l=1 */ 5187 READ_TOP_SOFT_RESET_REG_2r(unit, ®val); 5188 soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, ®val, TOP_BS_PLL_RST_Lf, 1); 5189 WRITE_TOP_SOFT_RESET_REG_2r(unit, regval); 5190 5191 /* m top_soft_reset_reg_2 top_bs_pll_post_rst_l=1 */ 5192 READ_TOP_SOFT_RESET_REG_2r(unit, ®val); 5193 soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, ®val, TOP_BS_PLL_POST_RST_Lf, 1); 5194 WRITE_TOP_SOFT_RESET_REG_2r(unit, regval); 5195 } 5196 #endif /* defined(BCM_TRIDENT2_SUPPORT) */ 5197 5198 if (SOC_IS_KATANA(unit) || SOC_IS_TRIUMPH3(unit) || SOC_IS_TD2_TT2(unit)) { 5199 5200 /* Validate calculated output based on bitclock_hz */ 5201 if(SOC_FAILURE(soc_reg_field_validate(unit, CMIC_BS_CLK_CTRLr, 5202 LOW_DURATIONf, bitclk_low))) { 5203 return BCM_E_PARAM; 5204 } 5205 if(SOC_FAILURE(soc_reg_field_validate(unit, CMIC_BS_CLK_CTRLr, 5206 HIGH_DURATIONf, bitclk_high))) { 5207 return BCM_E_PARAM; 5208 } 5209 5210 /* m CMIC_BS_CLK_CTRL LOW_DURATION=1 HIGH_DURATION=1 */ 5211 READ_CMIC_BS_CLK_CTRLr(unit, ®val); 5212 soc_reg_field_set(unit, CMIC_BS_CLK_CTRLr, ®val, LOW_DURATIONf, bitclk_low); 5213 soc_reg_field_set(unit, CMIC_BS_CLK_CTRLr, ®val, HIGH_DURATIONf, bitclk_high); 5214 WRITE_CMIC_BS_CLK_CTRLr(unit, regval); 5215 5216 /* m CMIC_BS_CLK_CTRL ENABLE=1 */ 5217 READ_CMIC_BS_CLK_CTRLr(unit, ®val); 5218 soc_reg_field_set(unit, CMIC_BS_CLK_CTRLr, ®val, ENABLEf, 1); 5219 WRITE_CMIC_BS_CLK_CTRLr(unit, regval); 5220 5221 /* m CMIC_BS_CONFIG BS_CLK_OUTPUT_ENABLE=1 BS_HB_OUTPUT_ENABLE=1 BS_TC_OUTPUT_ENABLE=1 */ 5222 READ_CMIC_BS_CONFIGr(unit, ®val); 5223 soc_reg_field_set(unit, CMIC_BS_CONFIGr, ®val, BS_CLK_OUTPUT_ENABLEf, output_enable); 5224 soc_reg_field_set(unit, CMIC_BS_CONFIGr, ®val, BS_HB_OUTPUT_ENABLEf, output_enable); 5225 soc_reg_field_set(unit, CMIC_BS_CONFIGr, ®val, BS_TC_OUTPUT_ENABLEf, output_enable); 5226 WRITE_CMIC_BS_CONFIGr(unit, regval); 5227 5228 READ_CMIC_TS_FREQ_CTRL_LOWERr(unit, ®val); 5229 soc_reg_field_set(unit, CMIC_TS_FREQ_CTRL_LOWERr, ®val, FRACf, freq_ctrl_lower); 5230 WRITE_CMIC_TS_FREQ_CTRL_LOWERr(unit, regval); 5231 5232 /* m CMIC_TS_FREQ_CTRL_UPPER ENABLE=1 */ 5233 READ_CMIC_TS_FREQ_CTRL_UPPERr(unit, ®val); 5234 soc_reg_field_set(unit, CMIC_TS_FREQ_CTRL_UPPERr, ®val, ENABLEf, 1); 5235 WRITE_CMIC_TS_FREQ_CTRL_UPPERr(unit, regval); 5236 5237 /* m CMIC_BS_HEARTBEAT_CTRL ENABLE=1 */ 5238 READ_CMIC_BS_HEARTBEAT_CTRLr(unit, ®val); 5239 soc_reg_field_set(unit, CMIC_BS_HEARTBEAT_CTRLr, ®val, ENABLEf, 1); 5240 WRITE_CMIC_BS_HEARTBEAT_CTRLr(unit, regval); 5241 5242 /* m CMIC_BS_HEARTBEAT_DOWN_DURATION DOWN_DURATION=2400 */ 5243 /* Validate calculated hb_down based on heartbeat_hz */ 5244 if(SOC_FAILURE(soc_reg_field_validate(unit, 5245 CMIC_BS_HEARTBEAT_DOWN_DURATIONr, 5246 DOWN_DURATIONf, hb_down))) { 5247 return BCM_E_PARAM; 5248 } 5249 READ_CMIC_BS_HEARTBEAT_DOWN_DURATIONr(unit, ®val); 5250 soc_reg_field_set(unit, CMIC_BS_HEARTBEAT_DOWN_DURATIONr, ®val, DOWN_DURATIONf, hb_down); 5251 WRITE_CMIC_BS_HEARTBEAT_DOWN_DURATIONr(unit, regval); 5252 5253 /* m CMIC_BS_HEARTBEAT_UP_DURATION UP_DURATION=100 */ 5254 READ_CMIC_BS_HEARTBEAT_UP_DURATIONr(unit, ®val); 5255 soc_reg_field_set(unit, CMIC_BS_HEARTBEAT_UP_DURATIONr, ®val, UP_DURATIONf, hb_up); 5256 WRITE_CMIC_BS_HEARTBEAT_UP_DURATIONr(unit, regval); 5257 5258 /* m CMIC_BS_CLK_CTRL ENABLE=0 */ 5259 READ_CMIC_BS_CLK_CTRLr(unit, ®val); 5260 soc_reg_field_set(unit, CMIC_BS_CLK_CTRLr, ®val, ENABLEf, 0); 5261 WRITE_CMIC_BS_CLK_CTRLr(unit, regval); 5262 5263 /* m CMIC_BS_REF_CLK_GEN_CTRL ENABLE=0 */ 5264 /* BS_REF_CLK from BS_PLL_CLK rather than BS_REF_CLK_generated */ 5265 5266 READ_CMIC_BS_REF_CLK_GEN_CTRLr(unit, ®val); 5267 soc_reg_field_set(unit, CMIC_BS_REF_CLK_GEN_CTRLr, ®val, ENABLEf, 0); 5268 WRITE_CMIC_BS_REF_CLK_GEN_CTRLr(unit, regval); 5269 5270 /* m CMIC_BS_CLK_CTRL ENABLE=1 LOW_DURATION=1 HIGH_DURATION=1 */ 5271 READ_CMIC_BS_CLK_CTRLr(unit, ®val); 5272 soc_reg_field_set(unit, CMIC_BS_CLK_CTRLr, ®val, ENABLEf, 1); 5273 soc_reg_field_set(unit, CMIC_BS_CLK_CTRLr, ®val, LOW_DURATIONf, bitclk_low); 5274 soc_reg_field_set(unit, CMIC_BS_CLK_CTRLr, ®val, HIGH_DURATIONf, bitclk_high); 5275 WRITE_CMIC_BS_CLK_CTRLr(unit, regval); 5276 5277 /* m CMIC_BS_CONFIG MODE=1 BS_CLK_OUTPUT_ENABLE=1 BS_HB_OUTPUT_ENABLE=1 */ 5278 READ_CMIC_BS_CONFIGr(unit, ®val); 5279 soc_reg_field_set(unit, CMIC_BS_CONFIGr, ®val, MODEf, master ? TIME_MODE_OUTPUT : TIME_MODE_INPUT); 5280 soc_reg_field_set(unit, CMIC_BS_CONFIGr, ®val, BS_CLK_OUTPUT_ENABLEf, output_enable); 5281 soc_reg_field_set(unit, CMIC_BS_CONFIGr, ®val, BS_HB_OUTPUT_ENABLEf, output_enable); 5282 WRITE_CMIC_BS_CONFIGr(unit, regval); 5283 } 5284 } 5285 5286 return BCM_E_NONE; 5287 } 5288 #endif /* defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || 5289 defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_HELIX4_SUPPORT) || 5290 defined(BCM_KATANA2_SUPPORT) || defined(BCM_TOMAHAWK_SUPPORT) || 5291 defined(BCM_HURRICANE2_SUPPORT) || defined(BCM_GREYHOUND_SUPPORT) || 5292 defiend(BCM_SABER2_SUPPORT) */ 5293 #if defined(BCM_HELIX4_SUPPORT) 5294 #define BCM_TIME_HX4_L1_FREQ_SEL_MODE(x) (((x) >= 0) && ((x) <= 3)) 5295 #define BCM_TIME_HX4_PORT_VALID(x) (((x) >= 1 && (x) <= 48 ) || ((x)>=65 && (x) <= 66)) 5296 #define BCM_TIME_HX4_CLK_SRC_VALID(x) \ 5297 (((x) == bcmTimeSynceClockSourcePrimary) || \ 5298 ((x) == bcmTimeSynceClockSourceSecondary) ) 5299 5300 /* 5301 * Function: 5302 * _bcm_esw_time_hx4_synce_clock_set 5303 * Purpose: 5304 * Set syncE divisor setting 5305 * Parameters: 5306 * unit - (IN) Unit number. 5307 * clk_src - (IN) clock source type (Primary, Secondary) 5308 * input_src - (IN) input source type (PORT) 5309 * index - (IN) if input_src is PORT, specify port number 1..48(physical port) or 65..66(LCPLL ports) 5310 * divisor - (IN) divisor setting. 5311 * Returns: 5312 * BCM_E_xxx 5313 * Notes: 5314 */ 5315 STATIC int 5316 _bcm_esw_time_hx4_synce_clock_set(int unit, 5317 bcm_time_synce_clock_src_type_t clk_src, 5318 bcm_time_synce_divisor_setting_t *divisor) 5319 { 5320 /* Assumes input index is logical port number */ 5321 int phy_port = divisor->index; 5322 int port_sel; 5323 5324 if (!BCM_TIME_HX4_PORT_VALID(phy_port) || 5325 !BCM_TIME_HX4_CLK_SRC_VALID(clk_src) || 5326 (phy_port == -1)) { 5327 return BCM_E_PARAM; 5328 } 5329 5330 port_sel = phy_port - 1; 5331 if ( clk_src == bcmTimeSynceClockSourcePrimary ) { 5332 /* TOP_MISC_CONTROL_1 */ 5333 SOC_IF_ERROR_RETURN 5334 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_1r, REG_PORT_ANY, 5335 L1_RCVD_CLK_RSTNf, 0)); 5336 /* TOP_MISC_CONTROL_1 */ 5337 SOC_IF_ERROR_RETURN 5338 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_1r, REG_PORT_ANY, 5339 L1_RCVD_FREQ_SELf, divisor->stage0_mode)); 5340 /* EGR_L1_CLK_RECOVERY_CTRL */ 5341 SOC_IF_ERROR_RETURN 5342 (soc_reg_field32_modify(unit, EGR_L1_CLK_RECOVERY_CTRLr, 5343 REG_PORT_ANY, PRI_PORT_SELf, port_sel)); 5344 5345 /* Enable L1 prim recov clk as valid,default it is invalid */ 5346 SOC_IF_ERROR_RETURN 5347 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_1r, REG_PORT_ANY, 5348 L1_RCVD_SW_OVWR_VALIDf, 1)); 5349 SOC_IF_ERROR_RETURN 5350 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_1r, REG_PORT_ANY, 5351 L1_RCVD_SW_OVWR_ENf, 1)); 5352 5353 /* TOP_MISC_CONTROL_1 */ 5354 SOC_IF_ERROR_RETURN 5355 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_1r, REG_PORT_ANY, 5356 L1_RCVD_CLK_RSTNf, 1)); 5357 } else { /* Secondary/Backup SyncE source */ 5358 /* TOP_MISC_CONTROL_1 */ 5359 SOC_IF_ERROR_RETURN 5360 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_1r, REG_PORT_ANY, 5361 L1_RCVD_CLK_BKUP_RSTNf, 0)); 5362 /* TOP_MISC_CONTROL_1 */ 5363 SOC_IF_ERROR_RETURN 5364 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_1r, REG_PORT_ANY, 5365 L1_RCVD_BKUP_FREQ_SELf, divisor->stage0_mode)); 5366 /* EGR_L1_CLK_RECOVERY_CTRL */ 5367 SOC_IF_ERROR_RETURN 5368 (soc_reg_field32_modify(unit, EGR_L1_CLK_RECOVERY_CTRLr, 5369 REG_PORT_ANY, BKUP_PORT_SELf, port_sel)); 5370 5371 /* Enable L1 sec/bkp recov clk as valid,default it is invalid */ 5372 SOC_IF_ERROR_RETURN 5373 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_1r, REG_PORT_ANY, 5374 L1_RCVD_SW_OVWR_BKUP_VALIDf, 1)); 5375 SOC_IF_ERROR_RETURN 5376 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_1r, REG_PORT_ANY, 5377 L1_RCVD_SW_OVWR_ENf, 1)); 5378 5379 /* TOP_MISC_CONTROL_1 */ 5380 SOC_IF_ERROR_RETURN 5381 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_1r, REG_PORT_ANY, 5382 L1_RCVD_CLK_BKUP_RSTNf, 1)); 5383 } 5384 return BCM_E_NONE; 5385 } 5386 5387 /* 5388 * Function: 5389 * _bcm_esw_time_hx4_synce_clock_get 5390 * Purpose: 5391 * Get current setting of syncE clock divisor 5392 * Parameters: 5393 * unit - (IN) Unit number. 5394 divisor - (OUT) Divisor setting 5395 * Returns: 5396 * BCM_E_xxx 5397 * Notes: 5398 */ 5399 STATIC int 5400 _bcm_esw_time_hx4_synce_clock_get(int unit, 5401 bcm_time_synce_clock_src_type_t clk_src, 5402 bcm_time_synce_divisor_setting_t *divisor) 5403 { 5404 uint32 val, phy_port, rval; 5405 5406 switch(clk_src) { 5407 case bcmTimeSynceClockSourcePrimary: 5408 /* input source */ 5409 SOC_IF_ERROR_RETURN( 5410 READ_EGR_L1_CLK_RECOVERY_CTRLr(unit, &rval)); 5411 val = soc_reg_field_get(unit, EGR_L1_CLK_RECOVERY_CTRLr, rval, 5412 PRI_PORT_SELf); 5413 phy_port = val+ 1; 5414 divisor->input_src = bcmTimeSynceInputSourceTypePort; 5415 divisor->index = phy_port; 5416 5417 SOC_IF_ERROR_RETURN(READ_TOP_MISC_CONTROL_1r(unit, &rval)); 5418 /* Freq div mode */ 5419 divisor->stage0_mode = soc_reg_field_get(unit, TOP_MISC_CONTROL_1r, 5420 rval, L1_RCVD_FREQ_SELf); 5421 break; 5422 case bcmTimeSynceClockSourceSecondary: 5423 /* input source */ 5424 SOC_IF_ERROR_RETURN( 5425 READ_EGR_L1_CLK_RECOVERY_CTRLr(unit, &rval)); 5426 val= soc_reg_field_get(unit, EGR_L1_CLK_RECOVERY_CTRLr, rval, 5427 BKUP_PORT_SELf); 5428 phy_port = val+ 1; 5429 divisor->input_src = bcmTimeSynceInputSourceTypePort; 5430 divisor->index = phy_port; 5431 5432 SOC_IF_ERROR_RETURN(READ_TOP_MISC_CONTROL_1r(unit, &rval)); 5433 /* Freq div mode */ 5434 divisor->stage0_mode = soc_reg_field_get(unit, TOP_MISC_CONTROL_1r, 5435 rval, L1_RCVD_BKUP_FREQ_SELf); 5436 break; 5437 default: 5438 return BCM_E_PARAM; 5439 } 5440 5441 return BCM_E_NONE; 5442 } 5443 5444 #endif /* defined(BCM_HELIX4_SUPPORT */ 5445 5446 #if defined(BCM_GREYHOUND_SUPPORT) 5447 #define BCM_TIME_GH_L1_FREQ_SEL_MODE(x) (((x) >= 0) && ((x) <= 3)) 5448 #define BCM_TIME_GH_PORT_VALID(x) (((x) >= 1 && (x) <= 48 ) || ((x)>=65 && (x) <= 66)) 5449 #define BCM_TIME_GH_CLK_SRC_VALID(x) \ 5450 (((x) == bcmTimeSynceClockSourcePrimary) || \ 5451 ((x) == bcmTimeSynceClockSourceSecondary) ) 5452 5453 /* 5454 * Function: 5455 * _bcm_esw_time_gh_synce_clock_set 5456 * Purpose: 5457 * Set syncE divisor setting 5458 * Parameters: 5459 * unit - (IN) Unit number. 5460 * clk_src - (IN) clock source type (Primary, Secondary) 5461 * input_src - (IN) input source type (PORT) 5462 * index - (IN) if input_src is PORT, specify port number 1..48(physical port) or 65..66(LCPLL ports) 5463 * divisor - (IN) divisor setting. 5464 * Returns: 5465 * BCM_E_xxx 5466 * Notes: 5467 */ 5468 STATIC int 5469 _bcm_esw_time_gh_synce_clock_set(int unit, 5470 bcm_time_synce_clock_src_type_t clk_src, 5471 bcm_time_synce_divisor_setting_t *divisor) 5472 { 5473 /* Assumes input index is logical port number */ 5474 int phy_port = divisor->index; 5475 int port_sel; 5476 5477 if (!BCM_TIME_GH_PORT_VALID(phy_port) || 5478 !BCM_TIME_GH_CLK_SRC_VALID(clk_src) || 5479 (phy_port == -1)) { 5480 return BCM_E_PARAM; 5481 } 5482 5483 if (!SOC_PORT_VALID(unit,phy_port)) 5484 { 5485 return BCM_E_PARAM; 5486 } 5487 5488 port_sel = phy_port - 1; 5489 if ( clk_src == bcmTimeSynceClockSourcePrimary ) { 5490 /* TOP_MISC_CONTROL_2 */ 5491 SOC_IF_ERROR_RETURN 5492 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_2r, REG_PORT_ANY, 5493 L1_RCVD_CLK_RSTNf, 0)); 5494 /* TOP_MISC_CONTROL_2 */ 5495 SOC_IF_ERROR_RETURN 5496 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_2r, REG_PORT_ANY, 5497 L1_RCVD_FREQ_SELf, divisor->stage0_mode)); 5498 /* TOP_MISC_CONTROL_2 */ 5499 SOC_IF_ERROR_RETURN 5500 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_2r, 5501 REG_PORT_ANY, L1_RCVD_PRI_CLK_PORT_SELf, port_sel)); 5502 5503 /* Enable L1 prim recov clk as valid,default it is invalid */ 5504 SOC_IF_ERROR_RETURN 5505 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_2r, REG_PORT_ANY, 5506 L1_RCVD_SW_OVWR_VALIDf, 1)); 5507 SOC_IF_ERROR_RETURN 5508 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_2r, REG_PORT_ANY, 5509 L1_RCVD_SW_OVWR_ENf, 1)); 5510 5511 /* TOP_MISC_CONTROL_2 */ 5512 SOC_IF_ERROR_RETURN 5513 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_2r, REG_PORT_ANY, 5514 L1_RCVD_CLK_RSTNf, 1)); 5515 } else { /* Secondary/Backup SyncE source */ 5516 /* TOP_MISC_CONTROL_2 */ 5517 SOC_IF_ERROR_RETURN 5518 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_2r, REG_PORT_ANY, 5519 L1_RCVD_CLK_BKUP_RSTNf, 0)); 5520 /* TOP_MISC_CONTROL_2 */ 5521 SOC_IF_ERROR_RETURN 5522 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_2r, REG_PORT_ANY, 5523 L1_RCVD_BKUP_FREQ_SELf, divisor->stage0_mode)); 5524 /* TOP_MISC_CONTROL_2 */ 5525 SOC_IF_ERROR_RETURN 5526 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_2r, 5527 REG_PORT_ANY, L1_RCVD_BKUP_CLK_PORT_SELf, port_sel)); 5528 5529 /* Enable L1 sec/bkp recov clk as valid,default it is invalid */ 5530 SOC_IF_ERROR_RETURN 5531 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_2r, REG_PORT_ANY, 5532 L1_RCVD_SW_OVWR_BKUP_VALIDf, 1)); 5533 SOC_IF_ERROR_RETURN 5534 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_2r, REG_PORT_ANY, 5535 L1_RCVD_SW_OVWR_ENf, 1)); 5536 5537 /* TOP_MISC_CONTROL_2 */ 5538 SOC_IF_ERROR_RETURN 5539 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_2r, REG_PORT_ANY, 5540 L1_RCVD_CLK_BKUP_RSTNf, 1)); 5541 } 5542 return BCM_E_NONE; 5543 } 5544 5545 /* 5546 * Function: 5547 * _bcm_esw_time_gh_synce_clock_get 5548 * Purpose: 5549 * Get current setting of syncE clock divisor 5550 * Parameters: 5551 * unit - (IN) Unit number. 5552 divisor - (OUT) Divisor setting 5553 * Returns: 5554 * BCM_E_xxx 5555 * Notes: 5556 */ 5557 STATIC int 5558 _bcm_esw_time_gh_synce_clock_get(int unit, 5559 bcm_time_synce_clock_src_type_t clk_src, 5560 bcm_time_synce_divisor_setting_t *divisor) 5561 { 5562 uint32 val, phy_port, rval; 5563 5564 switch(clk_src) { 5565 case bcmTimeSynceClockSourcePrimary: 5566 /* input source */ 5567 SOC_IF_ERROR_RETURN( 5568 READ_TOP_MISC_CONTROL_2r(unit, &rval)); 5569 val = soc_reg_field_get(unit, TOP_MISC_CONTROL_2r, rval, 5570 L1_RCVD_PRI_CLK_PORT_SELf); 5571 phy_port = val+ 1; 5572 divisor->input_src = bcmTimeSynceInputSourceTypePort; 5573 divisor->index = phy_port; 5574 5575 SOC_IF_ERROR_RETURN(READ_TOP_MISC_CONTROL_2r(unit, &rval)); 5576 /* Freq div mode */ 5577 divisor->stage0_mode = soc_reg_field_get(unit, TOP_MISC_CONTROL_2r, 5578 rval, L1_RCVD_FREQ_SELf); 5579 break; 5580 case bcmTimeSynceClockSourceSecondary: 5581 /* input source */ 5582 SOC_IF_ERROR_RETURN( 5583 READ_TOP_MISC_CONTROL_2r(unit, &rval)); 5584 val = soc_reg_field_get(unit, TOP_MISC_CONTROL_2r, rval, 5585 L1_RCVD_BKUP_CLK_PORT_SELf); 5586 phy_port = val+ 1; 5587 divisor->input_src = bcmTimeSynceInputSourceTypePort; 5588 divisor->index = phy_port; 5589 5590 SOC_IF_ERROR_RETURN(READ_TOP_MISC_CONTROL_2r(unit, &rval)); 5591 /* Freq div mode */ 5592 divisor->stage0_mode = soc_reg_field_get(unit, TOP_MISC_CONTROL_2r, 5593 rval, L1_RCVD_BKUP_FREQ_SELf); 5594 break; 5595 default: 5596 return BCM_E_PARAM; 5597 } 5598 5599 return BCM_E_NONE; 5600 } 5601 5602 #endif /* defined(BCM_GREYHOUND_SUPPORT) */ 5603 5604 #if defined(BCM_KATANA_SUPPORT) 5605 /* 5606 * Function: 5607 * _bcm_esw_time_katana_synce_clock_set 5608 * Purpose: 5609 * Set syncE divisor setting 5610 * Parameters: 5611 * unit - (IN) Unit number. 5612 * clk_src - (IN) clock source type (Primary, Secondary) 5613 * input_src - (IN) input source type (PORT) 5614 * index - (IN) port no 5615 * divisor - (IN) divisor setting. 5616 * Returns: 5617 * BCM_E_xxx 5618 * Notes: 5619 */ 5620 STATIC int 5621 _bcm_esw_time_katana_synce_clock_set(int unit, 5622 bcm_time_synce_clock_src_type_t clk_src, 5623 bcm_time_synce_divisor_setting_t *divisor) 5624 { 5625 /* Assumes input index is logical port number */ 5626 int phy_port = divisor->index; 5627 int port_sel; 5628 uint32 rval; 5629 5630 port_sel = phy_port - 1; 5631 if ( clk_src == bcmTimeSynceClockSourcePrimary ) { 5632 BCM_IF_ERROR_RETURN( 5633 READ_TOP_MISC_CONTROLr(unit, &rval)); 5634 soc_reg_field_set(unit, TOP_MISC_CONTROLr, &rval, 5635 L1_CLK0_RECOVERY_MUX_SELf, port_sel); 5636 BCM_IF_ERROR_RETURN( 5637 WRITE_TOP_MISC_CONTROLr(unit, rval)); 5638 } else { /* Secondary/Backup SyncE source */ 5639 BCM_IF_ERROR_RETURN( 5640 READ_TOP_MISC_CONTROLr(unit, &rval)); 5641 soc_reg_field_set(unit, TOP_MISC_CONTROLr, &rval, 5642 L1_CLK1_RECOVERY_MUX_SELf, port_sel); 5643 BCM_IF_ERROR_RETURN( 5644 WRITE_TOP_MISC_CONTROLr(unit, rval)); 5645 } 5646 return BCM_E_NONE; 5647 } 5648 5649 /* 5650 * Function: 5651 * _bcm_esw_time_katana_synce_clock_get 5652 * Purpose: 5653 * Get current setting of syncE clock divisor 5654 * Parameters: 5655 * unit - (IN) Unit number. 5656 divisor - (OUT) Divisor setting 5657 * Returns: 5658 * BCM_E_xxx 5659 * Notes: 5660 */ 5661 STATIC int 5662 _bcm_esw_time_katana_synce_clock_get(int unit, 5663 bcm_time_synce_clock_src_type_t clk_src, 5664 bcm_time_synce_divisor_setting_t *divisor) 5665 { 5666 uint32 val, phy_port, rval; 5667 5668 switch(clk_src) { 5669 case bcmTimeSynceClockSourcePrimary: 5670 BCM_IF_ERROR_RETURN( READ_TOP_MISC_CONTROLr(unit, &rval)); 5671 val = soc_reg_field_get(unit, TOP_MISC_CONTROLr, rval, 5672 L1_CLK0_RECOVERY_MUX_SELf); 5673 break; 5674 case bcmTimeSynceClockSourceSecondary: 5675 BCM_IF_ERROR_RETURN( READ_TOP_MISC_CONTROLr(unit, &rval)); 5676 val = soc_reg_field_get(unit, TOP_MISC_CONTROLr, rval, 5677 L1_CLK1_RECOVERY_MUX_SELf); 5678 break; 5679 default: 5680 return BCM_E_PARAM; 5681 } 5682 5683 phy_port = val+ 1; 5684 divisor->input_src = bcmTimeSynceInputSourceTypePort; 5685 divisor->index = phy_port; 5686 5687 return BCM_E_NONE; 5688 } 5689 #endif /* BCM_KATANA_SUPPORT */ 5690 5691 #define BCM_TIME_SYNCE_CLK_SRC_VALID(x) \ 5692 (((x) == bcmTimeSynceClockSourcePrimary) || \ 5693 ((x) == bcmTimeSynceClockSourceSecondary) ) 5694 5695 #if defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_TOMAHAWK_SUPPORT) || defined(BCM_APACHE_SUPPORT) || defined(BCM_GREYHOUND2_SUPPORT) 5696 5697 /* Synchronous Ethernet(SyncE) */ 5698 /* static definition and functions */ 5699 5700 #define BCM_TIME_TD2P_PLL_VALID(x) (((x) >= 0) && ((x) <= 3)) 5701 #define BCM_TIME_TOMAHAWK_PLL_VALID(x) (((x) >= 0) && ((x) <= 3)) 5702 5703 5704 #define BCM_TIME_TD2P_PORT_VALID(x) ((x) >= 1 && (x) <= 105 ) 5705 #define BCM_TIME_TOMAHAWK_PORT_VALID(x) ((x) >= 1 && (x) <= 132 ) 5706 5707 STATIC int 5708 _bcm_time_td2p_divctrl_reg_modify_primary(int unit, 5709 bcm_time_synce_divisor_setting_t *divisor) 5710 { 5711 uint32 rval; 5712 SOC_IF_ERROR_RETURN(READ_TOP_L1_RCVD_CLK_CTRLr(unit, &rval)); 5713 soc_reg_field_set(unit, TOP_L1_RCVD_CLK_CTRLr, &rval, 5714 STAGE0_MODEf, divisor->stage0_mode); 5715 /* STAGE1_MODEf "DON'T CARE" in SDM mode. */ 5716 if (divisor->stage0_mode != bcmTimeSynceModeSDMFracDiv) { 5717 soc_reg_field_set(unit, TOP_L1_RCVD_CLK_CTRLr, &rval, 5718 STAGE1_MODEf, divisor->stage1_div); 5719 } 5720 if ((divisor->stage0_mode == bcmTimeSynceModeBypass) || 5721 (divisor->stage0_mode == bcmTimeSynceModeSDMFracDiv)) { 5722 uint16 sdm_val; 5723 sdm_val = ((divisor->stage0_sdm_whole & 0xff) << 8 | 5724 (divisor->stage0_sdm_frac & 0xff)); 5725 soc_reg_field_set(unit, TOP_L1_RCVD_CLK_CTRLr, &rval, 5726 SDM_DIVISORf, sdm_val); 5727 } 5728 WRITE_TOP_L1_RCVD_CLK_CTRLr(unit, rval); 5729 return BCM_E_NONE; 5730 } 5731 5732 STATIC int 5733 _bcm_time_td2p_divctrl_reg_modify_secondary(int unit, 5734 bcm_time_synce_divisor_setting_t *divisor) 5735 { 5736 uint32 rval; 5737 SOC_IF_ERROR_RETURN(READ_TOP_L1_RCVD_CLK_BKUP_CTRLr(unit, &rval)); 5738 soc_reg_field_set(unit, TOP_L1_RCVD_CLK_BKUP_CTRLr, &rval, 5739 STAGE0_MODEf, divisor->stage0_mode); 5740 /* STAGE1_MODEf "DON'T CARE" in SDM mode. */ 5741 if (divisor->stage0_mode != bcmTimeSynceModeSDMFracDiv) { 5742 soc_reg_field_set(unit, TOP_L1_RCVD_CLK_BKUP_CTRLr, &rval, 5743 STAGE1_MODEf, divisor->stage1_div); 5744 } 5745 if ((divisor->stage0_mode == bcmTimeSynceModeBypass) || 5746 (divisor->stage0_mode == bcmTimeSynceModeSDMFracDiv)) { 5747 uint16 sdm_val; 5748 sdm_val = ((divisor->stage0_sdm_whole & 0xff) << 8 | 5749 (divisor->stage0_sdm_frac & 0xff)); 5750 soc_reg_field_set(unit, TOP_L1_RCVD_CLK_BKUP_CTRLr, &rval, 5751 SDM_DIVISORf, sdm_val); 5752 } 5753 WRITE_TOP_L1_RCVD_CLK_BKUP_CTRLr(unit, rval); 5754 return BCM_E_NONE; 5755 } 5756 5757 #ifdef PORTMOD_SUPPORT 5758 STATIC phymod_dispatch_type_t 5759 _bcm_time_synce_tsc_phymod_dispatch_type_get(int unit, int port) 5760 { 5761 phymod_dispatch_type_t rv = phymodDispatchTypeInvalid; 5762 int nof_cores = 0; 5763 5764 if (soc_feature(unit, soc_feature_portmod)) { 5765 phymod_core_access_t core_acc; 5766 phymod_core_access_t_init(&core_acc); 5767 portmod_port_main_core_access_get(unit, port, 0, &core_acc, &nof_cores); 5768 if (nof_cores <= 0) { 5769 LOG_ERROR(BSL_LS_BCM_TIME, 5770 (BSL_META_U(unit, 5771 "Cannot get phy address\n"))); 5772 return BCM_E_PARAM; 5773 } 5774 5775 rv= core_acc.type; 5776 5777 } else 5778 { 5779 return phymodDispatchTypeInvalid; 5780 } 5781 5782 return rv; 5783 } 5784 #endif 5785 5786 5787 STATIC int 5788 _bcm_esw_time_synce_phy_port_lane_adjust(int unit, 5789 int phy_port, 5790 int *adjusted_lane, 5791 int *adjusted_phy_port) 5792 { 5793 int first_phy_port, first_log_port, port, lane = 0; 5794 uint32 flags = 0; 5795 int num_lanes = 4; 5796 5797 port = SOC_INFO(unit).port_p2l_mapping[phy_port]; 5798 #ifdef PORTMOD_SUPPORT 5799 if (soc_feature(unit, soc_feature_portmod)) { 5800 phymod_dispatch_type_t dispatch_type = phymodDispatchTypeInvalid; 5801 dispatch_type = _bcm_time_synce_tsc_phymod_dispatch_type_get(unit, port); 5802 if (dispatch_type == phymodDispatchTypeTscbh) 5803 { 5804 num_lanes = 8; 5805 } 5806 } 5807 #endif 5808 5809 if (SOC_IS_HELIX5(unit)) { 5810 first_phy_port = HX5_PORT_BLOCK_FIRST_PORT(port); 5811 } else if (SOC_IS_GREYHOUND2(unit)){ 5812 first_phy_port = gh2_tsc_phy_port[((phy_port - 58) / 4)]; /* Eagle and Falcon*/ 5813 } else { 5814 first_phy_port = (SOC_INFO(unit).port_serdes[port] * num_lanes) + 1; 5815 } 5816 5817 first_log_port = SOC_INFO(unit).port_p2l_mapping[first_phy_port]; 5818 #ifdef PORTMOD_SUPPORT 5819 if (soc_feature(unit, soc_feature_portmod)) { 5820 phymod_lane_map_t lane_map; 5821 if (!SOC_PORT_VALID(unit,first_log_port)) 5822 { 5823 return BCM_E_PARAM; 5824 } 5825 SOC_IF_ERROR_RETURN(portmod_port_lane_map_get(unit, first_log_port, flags, &lane_map)); 5826 lane = lane_map.lane_map_rx[(phy_port - 1) % num_lanes]; 5827 } else 5828 #endif 5829 { 5830 uint32_t lane_swap = 0; 5831 BCM_IF_ERROR_RETURN(bcm_esw_port_phy_control_get(unit, first_log_port, 5832 BCM_PORT_PHY_CONTROL_LANE_SWAP, &lane_swap)); 5833 if (SOC_IS_GREYHOUND2(unit)){ 5834 lane = (lane_swap >> (((phy_port - 2) % num_lanes) * num_lanes)) & 0xf; 5835 } else { 5836 lane = (lane_swap >> (((phy_port - 1) % num_lanes) * num_lanes)) & 0xf; 5837 } 5838 } 5839 5840 phy_port = first_phy_port + lane; 5841 5842 if (adjusted_lane) { 5843 *adjusted_lane = lane; 5844 } 5845 if (adjusted_phy_port) { 5846 *adjusted_phy_port = phy_port; 5847 } 5848 5849 return BCM_E_NONE; 5850 } 5851 5852 STATIC int 5853 _bcm_esw_time_synce_phy_port_get(int unit, 5854 int adjusted_phy_port, 5855 uint32 *phy_port) 5856 { 5857 int first_phy_port, first_log_port, lane_indx = 0; 5858 int adjusted_lane = 0; 5859 int tmp_phy_port = adjusted_phy_port; 5860 int num_lanes = 4; 5861 uint32 flags = 0; 5862 5863 #ifdef PORTMOD_SUPPORT 5864 { 5865 5866 if (SOC_IS_TOMAHAWK3(unit)) 5867 num_lanes = 8; 5868 } 5869 #endif 5870 if (SOC_IS_GREYHOUND2(unit)) { /* Eagle and Falcon */ 5871 first_phy_port = gh2_tsc_phy_port[((adjusted_phy_port - 58) / 4)]; 5872 } else { 5873 first_phy_port = (((adjusted_phy_port - 1)/num_lanes) * num_lanes) + 1; 5874 } 5875 adjusted_lane = adjusted_phy_port - first_phy_port; 5876 first_log_port = SOC_INFO(unit).port_p2l_mapping[first_phy_port]; 5877 #ifdef PORTMOD_SUPPORT 5878 if (soc_feature(unit, soc_feature_portmod)) { 5879 phymod_lane_map_t lane_map; 5880 if (!SOC_PORT_VALID(unit,first_log_port)) 5881 { 5882 return BCM_E_PARAM; 5883 } 5884 SOC_IF_ERROR_RETURN(portmod_port_lane_map_get(unit, first_log_port, flags, &lane_map)); 5885 for (lane_indx = 0; lane_indx < num_lanes; lane_indx++) { 5886 if (lane_map.lane_map_rx[lane_indx] == adjusted_lane) { 5887 break; 5888 } 5889 } 5890 } else 5891 #endif 5892 { 5893 uint32_t lane_swap = 0; 5894 BCM_IF_ERROR_RETURN(bcm_esw_port_phy_control_get(unit, first_log_port, 5895 BCM_PORT_PHY_CONTROL_LANE_SWAP, &lane_swap)); 5896 for (lane_indx = 0; lane_indx < num_lanes; lane_indx++) { 5897 if ( ((lane_swap >> (lane_indx * num_lanes)) & 0xf) == adjusted_lane) { 5898 break; 5899 } 5900 } 5901 } 5902 tmp_phy_port = first_phy_port + lane_indx; 5903 if (phy_port) { 5904 *phy_port = (uint32)tmp_phy_port; 5905 } 5906 return BCM_E_NONE; 5907 } 5908 5909 /* 5910 * Function: 5911 * _tsc_synce_phy_register_set 5912 * Purpose: 5913 * SyncE mode register(0x9002:PCS register) set. 5914 * This function is equivalent with 5915 * 5916 * phy raw sbus <phy_address> 0.<phy_lane> 0x9002 value 5917 * 5918 * phy_address, phy_lane will be calculated based on input logical port. 5919 * Parameters: 5920 * port - (IN) logical port number 5921 * value - (IN) the value to be written to register. 5922 * Returns: 5923 * BCM_E_xxx 5924 * Notes: 5925 */ 5926 /* TSC eagle phy registers address */ 5927 #define BCM_TIME_TSCE_MAIN0_SYNCE_CTL_STAGE0_REG 0x9002 /* TSC eagle synce mode register stage 0 */ 5928 5929 /* TSC falcon phy registers address */ 5930 #define BCM_TIME_TSCF_MAIN0_SYNCE_CTL_REG 0x9001 /* TSC falcon synce mode register stage 1 */ 5931 #define BCM_TIME_TSCF_MAIN0_SYNCE_CTL_STAGE0_REG 0x9002 /* TSC falcon synce mode register stage 0 */ 5932 #define BCM_TIME_TSCF_RX_X4_SYNCE_FRACTIONAL_DIV_REG 0xc13d /* TSC falcon synce fractional divisor register */ 5933 5934 STATIC int 5935 _bcm_time_synce_phy_register_set(int unit, int port, int value, uint32 phy_reg) 5936 { 5937 uint32 phy_devad = 0; /* devad = 0 means PCS access */ 5938 uint32 phy_aer; 5939 uint16 phy_addr; 5940 int phy_lane; 5941 int phy_port; 5942 int nof_cores = 0; 5943 uint32 val; 5944 /* get internal phy address */ 5945 #ifdef PORTMOD_SUPPORT 5946 if (soc_feature(unit, soc_feature_portmod)) { 5947 phymod_core_access_t core_acc; 5948 phymod_core_access_t_init(&core_acc); 5949 portmod_port_main_core_access_get(unit, port, 0, &core_acc, &nof_cores); 5950 if (nof_cores <= 0) { 5951 LOG_ERROR(BSL_LS_BCM_TIME, 5952 (BSL_META_U(unit, 5953 "Cannot get phy address\n"))); 5954 return BCM_E_PARAM; 5955 } 5956 phy_addr = core_acc.access.addr; 5957 } else 5958 #endif 5959 { 5960 phy_addr = PORT_TO_PHY_ADDR(unit, port); 5961 if (phy_addr == 0xff) { 5962 LOG_ERROR(BSL_LS_BCM_TIME, 5963 (BSL_META_U(unit, 5964 "Cannot get phy address\n"))); 5965 return BCM_E_PARAM; 5966 } 5967 } 5968 5969 /* calculate lane index based on logical port */ 5970 phy_port = SOC_INFO(unit).port_l2p_mapping[port]; 5971 5972 BCM_IF_ERROR_RETURN(_bcm_esw_time_synce_phy_port_lane_adjust(unit, phy_port, 5973 &phy_lane, NULL)); 5974 phy_aer = (phy_devad << 11) | phy_lane; 5975 5976 if (phy_reg != BCM_TIME_TSCF_RX_X4_SYNCE_FRACTIONAL_DIV_REG) { 5977 soc_sbus_mdio_read(unit, phy_addr, phy_reg, &val); 5978 value = (val & ~(0x3 << (phy_lane *2))) | ((value & 0x3) << phy_lane * 2); 5979 } else { 5980 phy_reg = (phy_aer << 16) | phy_reg; 5981 } 5982 5983 SOC_IF_ERROR_RETURN( 5984 soc_sbus_mdio_write(unit, phy_addr, phy_reg, value)); 5985 5986 LOG_VERBOSE(BSL_LS_BCM_TIME, (BSL_META_U(unit, 5987 "logical port (%d)\n" 5988 "physical port (%d)\n" 5989 "phy addr (%x) lane (%d)\n") 5990 , port, phy_port 5991 , phy_addr, phy_lane)); 5992 return BCM_E_NONE; 5993 } 5994 5995 STATIC int 5996 _bcm_time_synce_phy_register_get(int unit, int port, uint32 phy_reg, uint32 *value) 5997 { 5998 uint32 phy_devad = 0; /* devad = 0 means PCS access */ 5999 uint32 phy_aer; 6000 uint16 phy_addr; 6001 int phy_lane; 6002 int phy_port; 6003 int nof_cores = 0; 6004 6005 /* get internal phy address */ 6006 #ifdef PORTMOD_SUPPORT 6007 if (soc_feature(unit, soc_feature_portmod)) { 6008 phymod_core_access_t core_acc; 6009 phymod_core_access_t_init(&core_acc); 6010 portmod_port_main_core_access_get(unit, port, 0, &core_acc, &nof_cores); 6011 if (nof_cores <= 0) { 6012 LOG_ERROR(BSL_LS_BCM_TIME, 6013 (BSL_META_U(unit, 6014 "Cannot get phy address\n"))); 6015 return BCM_E_PARAM; 6016 } 6017 phy_addr = core_acc.access.addr; 6018 } else 6019 #endif 6020 { 6021 phy_addr = PORT_TO_PHY_ADDR(unit, port); 6022 if (phy_addr == 0xff) { 6023 LOG_ERROR(BSL_LS_BCM_TIME, 6024 (BSL_META_U(unit, 6025 "Cannot get phy address\n"))); 6026 return BCM_E_PARAM; 6027 } 6028 } 6029 6030 /* calculate lane index based on logical port */ 6031 phy_port = SOC_INFO(unit).port_l2p_mapping[port]; 6032 6033 BCM_IF_ERROR_RETURN(_bcm_esw_time_synce_phy_port_lane_adjust(unit, phy_port, 6034 &phy_lane, NULL)); 6035 6036 phy_aer = (phy_devad << 11) | phy_lane; 6037 if (phy_reg == BCM_TIME_TSCF_RX_X4_SYNCE_FRACTIONAL_DIV_REG) { 6038 phy_reg = (phy_aer << 16) | phy_reg; 6039 } 6040 6041 6042 SOC_IF_ERROR_RETURN( 6043 soc_sbus_mdio_read(unit, phy_addr, phy_reg, value)); 6044 6045 if (phy_reg == BCM_TIME_TSCF_MAIN0_SYNCE_CTL_REG || phy_reg == BCM_TIME_TSCF_MAIN0_SYNCE_CTL_STAGE0_REG) { 6046 soc_sbus_mdio_read(unit, phy_addr, phy_reg, value); 6047 *value = (*value >> phy_lane *2) & 0x3; 6048 } 6049 6050 LOG_VERBOSE(BSL_LS_BCM_TIME, (BSL_META_U(unit, 6051 "logical port (%d)\n" 6052 "physical port (%d)\n" 6053 "phy addr (%x) lane (%d)\n") 6054 , port, phy_port 6055 , phy_addr, phy_lane)); 6056 return BCM_E_NONE; 6057 } 6058 6059 6060 6061 STATIC int 6062 _bcm_time_synce_tsc_divisor_turn_off(int unit, int port) 6063 { 6064 int rv = BCM_E_NONE; 6065 int nof_cores = 0; 6066 6067 #ifdef PORTMOD_SUPPORT 6068 if (soc_feature(unit, soc_feature_portmod)) { 6069 phymod_core_access_t core_acc; 6070 phymod_core_access_t_init(&core_acc); 6071 portmod_port_main_core_access_get(unit, port, 0, &core_acc, &nof_cores); 6072 if (nof_cores <= 0) { 6073 LOG_ERROR(BSL_LS_BCM_TIME, 6074 (BSL_META_U(unit, 6075 "Cannot get phy address\n"))); 6076 return BCM_E_PARAM; 6077 } 6078 6079 if (core_acc.type == phymodDispatchTypeTsce) { 6080 rv = _bcm_time_synce_phy_register_set(unit, port, 0x0, BCM_TIME_TSCE_MAIN0_SYNCE_CTL_STAGE0_REG); 6081 } 6082 6083 } else 6084 #endif 6085 { 6086 return BCM_E_PARAM; 6087 } 6088 6089 return rv; 6090 } 6091 6092 6093 /* NOTES : this function takes care of TD2Plus only */ 6094 STATIC int 6095 _bcm_esw_time_td2p_synce_clock_set_by_port(int unit, 6096 bcm_time_synce_clock_src_type_t clk_src, 6097 bcm_time_synce_divisor_setting_t *divisor) 6098 { 6099 /* Assumes input index is logical port number */ 6100 int lport = divisor->index; 6101 int phy_port = SOC_INFO(unit).port_l2p_mapping[lport]; 6102 int port_sel; 6103 6104 if (!BCM_TIME_TD2P_PORT_VALID(lport) || 6105 !BCM_TIME_SYNCE_CLK_SRC_VALID(clk_src) || 6106 (phy_port == -1)) { 6107 return BCM_E_PARAM; 6108 } 6109 6110 BCM_IF_ERROR_RETURN(_bcm_esw_time_synce_phy_port_lane_adjust(unit, phy_port, 6111 NULL, &phy_port)); 6112 6113 6114 port_sel = phy_port - 1; 6115 if ( clk_src == bcmTimeSynceClockSourcePrimary ) { 6116 /* TOP_MISC_CONTROL */ 6117 SOC_IF_ERROR_RETURN 6118 (soc_reg_field32_modify(unit, TOP_MISC_CONTROLr, REG_PORT_ANY, 6119 L1_RCVD_CLK_RSTNf, 0)); 6120 /* TOP_MISC_CONTROL_2 */ 6121 SOC_IF_ERROR_RETURN 6122 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_2r, REG_PORT_ANY, 6123 L1_RCVD_FREQ_DIV_SELf, 0)); 6124 /* _TOP_L1_RCVD_CLK_CTRL */ 6125 SOC_IF_ERROR_RETURN(_bcm_time_td2p_divctrl_reg_modify_primary(unit, divisor)); 6126 /* TOP_MISC_CONTROL_2 */ 6127 SOC_IF_ERROR_RETURN 6128 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_2r, REG_PORT_ANY, 6129 XG_RCVD_PRI_SELf, 0)); 6130 /* EGR_L1_CLK_RECOVERY_CTRL */ 6131 SOC_IF_ERROR_RETURN 6132 (soc_reg_field32_modify(unit, EGR_L1_CLK_RECOVERY_CTRLr, 6133 REG_PORT_ANY, PRI_PORT_SELf, port_sel)); 6134 /* Turn off TSC div11 */ 6135 BCM_IF_ERROR_RETURN( 6136 _bcm_time_synce_tsc_divisor_turn_off(unit, lport)); 6137 6138 /* Enable SW L1 prim recov clk as valid,default it is invalid*/ 6139 SOC_IF_ERROR_RETURN 6140 (soc_reg_field32_modify(unit, TOP_MISC_CONTROLr, REG_PORT_ANY, 6141 L1_RCVD_SW_OVWR_VALIDf, 1)); 6142 SOC_IF_ERROR_RETURN 6143 (soc_reg_field32_modify(unit, TOP_MISC_CONTROLr, REG_PORT_ANY, 6144 L1_RCVD_SW_OVWR_ENf, 1)); 6145 6146 /* TOP_MISC_CONTROL */ 6147 SOC_IF_ERROR_RETURN 6148 (soc_reg_field32_modify(unit, TOP_MISC_CONTROLr, REG_PORT_ANY, 6149 L1_RCVD_CLK_RSTNf, 1)); 6150 } else { 6151 /* TOP_MISC_CONTROL */ 6152 SOC_IF_ERROR_RETURN 6153 (soc_reg_field32_modify(unit, TOP_MISC_CONTROLr, REG_PORT_ANY, 6154 L1_RCVD_CLK_BKUP_RSTNf, 0)); 6155 /* TOP_MISC_CONTROL_2 */ 6156 SOC_IF_ERROR_RETURN 6157 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_2r, REG_PORT_ANY, 6158 L1_RCVD_BKUP_FREQ_DIV_SELf, 0)); 6159 /* _TOP_L1_RCVD_CLK_BKUP_CTRL */ 6160 SOC_IF_ERROR_RETURN 6161 (_bcm_time_td2p_divctrl_reg_modify_secondary(unit, divisor)); 6162 /* TOP_MISC_CONTROL_2 */ 6163 SOC_IF_ERROR_RETURN 6164 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_2r, REG_PORT_ANY, 6165 XG_RCVD_BKUP_SELf, 0)); 6166 /* EGR_L1_CLK_RECOVERY_CTRL */ 6167 SOC_IF_ERROR_RETURN 6168 (soc_reg_field32_modify(unit, EGR_L1_CLK_RECOVERY_CTRLr, 6169 REG_PORT_ANY, BKUP_PORT_SELf, port_sel)); 6170 /* Turn off TSC div11 */ 6171 BCM_IF_ERROR_RETURN( 6172 _bcm_time_synce_tsc_divisor_turn_off(unit, lport)); 6173 6174 /* Enable SW L1 sec recov clk as valid,default it is invalid*/ 6175 SOC_IF_ERROR_RETURN 6176 (soc_reg_field32_modify(unit, TOP_MISC_CONTROLr, REG_PORT_ANY, 6177 L1_RCVD_SW_OVWR_BKUP_VALIDf, 1)); 6178 SOC_IF_ERROR_RETURN 6179 (soc_reg_field32_modify(unit, TOP_MISC_CONTROLr, REG_PORT_ANY, 6180 L1_RCVD_SW_OVWR_ENf, 1)); 6181 6182 /* TOP_MISC_CONTROL */ 6183 SOC_IF_ERROR_RETURN 6184 (soc_reg_field32_modify(unit, TOP_MISC_CONTROLr, REG_PORT_ANY, 6185 L1_RCVD_CLK_BKUP_RSTNf, 1)); 6186 } 6187 return BCM_E_NONE; 6188 } 6189 6190 /* NOTES : this function takes care of TD2Plus only */ 6191 STATIC int 6192 _bcm_esw_time_td2p_synce_clock_set_by_pll(int unit, 6193 bcm_time_synce_clock_src_type_t clk_src, 6194 bcm_time_synce_divisor_setting_t *divisor) 6195 { 6196 uint32 pll_index = divisor->index; 6197 6198 /* coverity[unsigned_compare] */ 6199 if (!BCM_TIME_TD2P_PLL_VALID(pll_index) || 6200 !BCM_TIME_SYNCE_CLK_SRC_VALID(clk_src)) { 6201 return BCM_E_PARAM; 6202 } 6203 if (clk_src == bcmTimeSynceClockSourcePrimary) { 6204 /* TOP_MISC_CONTROL */ 6205 SOC_IF_ERROR_RETURN 6206 (soc_reg_field32_modify(unit, TOP_MISC_CONTROLr, REG_PORT_ANY, 6207 L1_RCVD_CLK_RSTNf, 0)); 6208 /* TOP_MISC_CONTROL_2 */ 6209 SOC_IF_ERROR_RETURN 6210 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_2r, REG_PORT_ANY, 6211 L1_RCVD_FREQ_DIV_SELf, 0)); 6212 /* _TOP_L1_RCVD_CLK_CTRL */ 6213 SOC_IF_ERROR_RETURN(_bcm_time_td2p_divctrl_reg_modify_primary(unit, divisor)); 6214 /* TOP_MISC_CONTROL_2 */ 6215 SOC_IF_ERROR_RETURN 6216 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_2r, REG_PORT_ANY, 6217 XG_RCVD_PRI_SELf, pll_index+1)); 6218 /* EGR_L1_CLK_RECOVERY_CTRL */ 6219 SOC_IF_ERROR_RETURN 6220 (soc_reg_field32_modify(unit, EGR_L1_CLK_RECOVERY_CTRLr, 6221 REG_PORT_ANY, PRI_PORT_SELf, 0)); 6222 6223 /* Enable SW L1 prim recov clk as valid,default it is invalid*/ 6224 SOC_IF_ERROR_RETURN 6225 (soc_reg_field32_modify(unit, TOP_MISC_CONTROLr, REG_PORT_ANY, 6226 L1_RCVD_SW_OVWR_VALIDf, 1)); 6227 SOC_IF_ERROR_RETURN 6228 (soc_reg_field32_modify(unit, TOP_MISC_CONTROLr, REG_PORT_ANY, 6229 L1_RCVD_SW_OVWR_ENf, 1)); 6230 6231 /* TOP_MISC_CONTROL */ 6232 SOC_IF_ERROR_RETURN 6233 (soc_reg_field32_modify(unit, TOP_MISC_CONTROLr, REG_PORT_ANY, 6234 L1_RCVD_CLK_RSTNf, 1)); 6235 } else { 6236 /* TOP_MISC_CONTROL */ 6237 SOC_IF_ERROR_RETURN 6238 (soc_reg_field32_modify(unit, TOP_MISC_CONTROLr, REG_PORT_ANY, 6239 L1_RCVD_CLK_BKUP_RSTNf, 0)); 6240 /* TOP_MISC_CONTROL_2 */ 6241 SOC_IF_ERROR_RETURN 6242 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_2r, REG_PORT_ANY, 6243 L1_RCVD_BKUP_FREQ_DIV_SELf, 0)); 6244 /* _TOP_L1_RCVD_CLK_BKUP_CTRL */ 6245 SOC_IF_ERROR_RETURN 6246 (_bcm_time_td2p_divctrl_reg_modify_secondary(unit, divisor)); 6247 /* TOP_MISC_CONTROL_2 */ 6248 SOC_IF_ERROR_RETURN 6249 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_2r, REG_PORT_ANY, 6250 XG_RCVD_BKUP_SELf, pll_index+1)); 6251 /* EGR_L1_CLK_RECOVERY_CTRL */ 6252 SOC_IF_ERROR_RETURN 6253 (soc_reg_field32_modify(unit, EGR_L1_CLK_RECOVERY_CTRLr, 6254 REG_PORT_ANY, BKUP_PORT_SELf, 0)); 6255 6256 /* Enable SW L1 sec recov clk as valid,default it is invalid*/ 6257 SOC_IF_ERROR_RETURN 6258 (soc_reg_field32_modify(unit, TOP_MISC_CONTROLr, REG_PORT_ANY, 6259 L1_RCVD_SW_OVWR_BKUP_VALIDf, 1)); 6260 SOC_IF_ERROR_RETURN 6261 (soc_reg_field32_modify(unit, TOP_MISC_CONTROLr, REG_PORT_ANY, 6262 L1_RCVD_SW_OVWR_ENf, 1)); 6263 6264 /* TOP_MISC_CONTROL */ 6265 SOC_IF_ERROR_RETURN 6266 (soc_reg_field32_modify(unit, TOP_MISC_CONTROLr, REG_PORT_ANY, 6267 L1_RCVD_CLK_BKUP_RSTNf, 1)); 6268 } 6269 return BCM_E_NONE; 6270 } 6271 6272 /* 6273 * Function: 6274 * _bcm_esw_time_td2p_synce_clock_set 6275 * Purpose: 6276 * Set syncE divisor setting 6277 * Parameters: 6278 * unit - (IN) Unit number. 6279 * clk_src - (IN) clock source type (Primary, Secondary) 6280 * input_src - (IN) input source type (PORT, PLL) 6281 * index - (IN) if input_src is PORT, specify logical port number 0..105 6282 * if input_src is PLL, specify PLL index 0..3 6283 * divisor - (IN) divisor setting. 6284 * Returns: 6285 * BCM_E_xxx 6286 * Notes: This function only configures for td2plus 6287 */ 6288 STATIC int 6289 _bcm_esw_time_td2p_synce_clock_set(int unit, 6290 bcm_time_synce_clock_src_type_t clk_src, 6291 bcm_time_synce_divisor_setting_t *divisor) 6292 { 6293 int rv; 6294 6295 switch(divisor->input_src) { 6296 case bcmTimeSynceInputSourceTypePort: 6297 rv = _bcm_esw_time_td2p_synce_clock_set_by_port(unit, clk_src, divisor); 6298 break; 6299 case bcmTimeSynceInputSourceTypePLL: 6300 rv = _bcm_esw_time_td2p_synce_clock_set_by_pll(unit, clk_src, divisor); 6301 break; 6302 default: 6303 rv = BCM_E_PARAM; 6304 break; 6305 } 6306 6307 return rv; 6308 } 6309 6310 /* 6311 * Function: 6312 * _bcm_esw_time_td2p_synce_clock_get 6313 * Purpose: 6314 * Get current setting of syncE clock divisor 6315 * Parameters: 6316 * unit - (IN) Unit number. 6317 divisor - (OUT) Divisor setting 6318 * Returns: 6319 * BCM_E_xxx 6320 * Notes: This function takes care of TD2Plus only 6321 */ 6322 STATIC int 6323 _bcm_esw_time_td2p_synce_clock_get(int unit, 6324 bcm_time_synce_clock_src_type_t clk_src, 6325 bcm_time_synce_divisor_setting_t *divisor) 6326 { 6327 uint32 val, val2, rval; 6328 uint16 sdm_val; 6329 6330 switch(clk_src) { 6331 case bcmTimeSynceClockSourcePrimary: 6332 /* input source */ 6333 SOC_IF_ERROR_RETURN( 6334 READ_TOP_MISC_CONTROL_2r(unit, &rval)); 6335 val = soc_reg_field_get(unit, TOP_MISC_CONTROL_2r, rval, 6336 XG_RCVD_PRI_SELf); 6337 SOC_IF_ERROR_RETURN( 6338 READ_EGR_L1_CLK_RECOVERY_CTRLr(unit, &rval)); 6339 val2 = soc_reg_field_get(unit, EGR_L1_CLK_RECOVERY_CTRLr, rval, 6340 PRI_PORT_SELf); 6341 if (val == 0) { /* source is Port */ 6342 uint32 phy_port; 6343 phy_port = val2 + 1; 6344 _bcm_esw_time_synce_phy_port_get(unit, phy_port, &phy_port); 6345 divisor->input_src = bcmTimeSynceInputSourceTypePort; 6346 divisor->index = SOC_INFO(unit).port_p2l_mapping[phy_port]; 6347 } else { /* source is PLL */ 6348 /* EGR_L1_CLK_RECOVERY_CTRLr.PRI_PORT_SELf needs to be 0 6349 * Otherwise, there's no clock output */ 6350 if (val2 != 0) { 6351 LOG_ERROR(BSL_LS_BCM_TIME, (BSL_META_U(unit, 6352 "No clock output\n"))); 6353 return BCM_E_FAIL; 6354 } 6355 divisor->input_src = bcmTimeSynceInputSourceTypePLL; 6356 divisor->index = val - 1; 6357 } 6358 6359 SOC_IF_ERROR_RETURN(READ_TOP_L1_RCVD_CLK_CTRLr(unit, &rval)); 6360 /* stage0_mode */ 6361 divisor->stage0_mode = soc_reg_field_get(unit, TOP_L1_RCVD_CLK_CTRLr, 6362 rval, STAGE0_MODEf); 6363 sdm_val = soc_reg_field_get(unit, TOP_L1_RCVD_CLK_CTRLr, rval, 6364 SDM_DIVISORf); 6365 /* stage0_whole */ 6366 divisor->stage0_sdm_whole = ((sdm_val & 0xff00) >> 8); 6367 /* stage0_frac */ 6368 divisor->stage0_sdm_frac = sdm_val & 0xff ; 6369 /* stage1_div */ 6370 divisor->stage1_div = soc_reg_field_get(unit, TOP_L1_RCVD_CLK_CTRLr, 6371 rval, STAGE1_MODEf); 6372 break; 6373 case bcmTimeSynceClockSourceSecondary: 6374 /* input source */ 6375 SOC_IF_ERROR_RETURN( 6376 READ_TOP_MISC_CONTROL_2r(unit, &rval)); 6377 val = soc_reg_field_get(unit, TOP_MISC_CONTROL_2r, rval, 6378 XG_RCVD_BKUP_SELf); 6379 SOC_IF_ERROR_RETURN( 6380 READ_EGR_L1_CLK_RECOVERY_CTRLr(unit, &rval)); 6381 val2 = soc_reg_field_get(unit, EGR_L1_CLK_RECOVERY_CTRLr, rval, 6382 BKUP_PORT_SELf); 6383 if (val == 0) { /* source is Port */ 6384 uint32 phy_port; 6385 phy_port = val2 + 1; 6386 _bcm_esw_time_synce_phy_port_get(unit, phy_port, &phy_port); 6387 divisor->input_src = bcmTimeSynceInputSourceTypePort; 6388 divisor->index = SOC_INFO(unit).port_p2l_mapping[phy_port]; 6389 } else { /* source is PLL */ 6390 /* EGR_L1_CLK_RECOVERY_CTRLr.BKUP_PORT_SELf needs to be 0 6391 * Otherwise, there's no clock output */ 6392 if (val2 != 0) { 6393 LOG_ERROR(BSL_LS_BCM_TIME, (BSL_META_U(unit, 6394 "No clock output\n"))); 6395 return BCM_E_FAIL; 6396 } 6397 divisor->input_src = bcmTimeSynceInputSourceTypePLL; 6398 divisor->index = val - 1; 6399 } 6400 6401 SOC_IF_ERROR_RETURN(READ_TOP_L1_RCVD_CLK_BKUP_CTRLr(unit, &rval)); 6402 /* stage0_mode */ 6403 divisor->stage0_mode = soc_reg_field_get(unit, TOP_L1_RCVD_CLK_BKUP_CTRLr, 6404 rval, STAGE0_MODEf); 6405 sdm_val = soc_reg_field_get(unit, TOP_L1_RCVD_CLK_BKUP_CTRLr, rval, 6406 SDM_DIVISORf); 6407 /* stage0_whole */ 6408 divisor->stage0_sdm_whole = ((sdm_val & 0xff00) >> 8); 6409 /* stage0_frac */ 6410 divisor->stage0_sdm_frac = sdm_val & 0xff ; 6411 /* stage1_div */ 6412 divisor->stage1_div = soc_reg_field_get(unit, TOP_L1_RCVD_CLK_BKUP_CTRLr, 6413 rval, STAGE1_MODEf); 6414 break; 6415 default: 6416 return BCM_E_PARAM; 6417 } 6418 6419 6420 6421 return BCM_E_NONE; 6422 } 6423 6424 STATIC int 6425 _bcm_esw_time_tomahawkx_synce_clock_set_by_port(int unit, 6426 bcm_time_synce_clock_src_type_t clk_src, 6427 bcm_time_synce_divisor_setting_t *divisor) 6428 { 6429 soc_reg_t synce_ctrl = TOP_MISC_CONTROLr; 6430 soc_reg_t synce_ctrl_2 = TOP_MISC_CONTROL_2r; 6431 /* Assumes input index is logical port number */ 6432 int lport = divisor->index; 6433 int phy_port = SOC_INFO(unit).port_l2p_mapping[lport]; 6434 int port_sel; 6435 uint16 sdm_val; 6436 portmod_port_synce_clk_ctrl_t config; 6437 soc_field_t xg_rcvd_sel = XG_RCVD_SELf; 6438 soc_field_t l1_rcvd_port_sel = L1_RCVD_PORT_SELf; 6439 soc_field_t l1_rcvd_clk_rstn = L1_RCVD_CLK_RSTNf; 6440 soc_field_t l1_rcvd_freq_sel = L1_RCVD_FREQ_SELf; 6441 6442 if (clk_src == bcmTimeSynceClockSourceSecondary) { 6443 l1_rcvd_port_sel = L1_RCVD_BKUP_PORT_SELf; 6444 xg_rcvd_sel = XG_RCVD_BKUP_SELf; 6445 l1_rcvd_clk_rstn = L1_RCVD_CLK_BKUP_RSTNf; 6446 l1_rcvd_freq_sel = L1_RCVD_BKUP_FREQ_SELf; 6447 } 6448 /* Set Registers for TOMAHAWK3 */ 6449 if (SOC_IS_TOMAHAWK3(unit)) { 6450 synce_ctrl = TOP_SYNCE_CTRLr; 6451 synce_ctrl_2 = TOP_SYNCE_CTRLr; 6452 } 6453 6454 if (!BCM_TIME_SYNCE_CLK_SRC_VALID(clk_src) || 6455 !BCM_TIME_TOMAHAWK_PORT_VALID(lport) || 6456 (phy_port == -1)) { 6457 return BCM_E_PARAM; 6458 } 6459 6460 BCM_IF_ERROR_RETURN(_bcm_esw_time_synce_phy_port_lane_adjust(unit, phy_port, 6461 NULL, &phy_port)); 6462 port_sel = phy_port - 1; 6463 6464 /* TOP_MISC_CONTROL */ 6465 SOC_IF_ERROR_RETURN 6466 (soc_reg_field32_modify(unit, synce_ctrl, REG_PORT_ANY, 6467 l1_rcvd_clk_rstn, 0)); 6468 6469 /* TOP_MISC_CONTROL_2 - post divisors set to 0 */ 6470 SOC_IF_ERROR_RETURN 6471 (soc_reg_field32_modify(unit, synce_ctrl_2, REG_PORT_ANY, 6472 l1_rcvd_freq_sel, 0)); 6473 sdm_val = ((divisor->stage0_sdm_whole & 0xff) << 8 | 6474 (divisor->stage0_sdm_frac & 0xff)); 6475 #ifdef PORTMOD_SUPPORT 6476 if (soc_feature(unit, soc_feature_portmod)) { 6477 portmod_port_synce_clk_ctrl_t_init(unit, &config); 6478 config.stg0_mode = divisor->stage0_mode; 6479 config.stg1_mode = 0x0; 6480 config.sdm_val = sdm_val; 6481 if (!SOC_PORT_VALID(unit,lport)) 6482 { 6483 return BCM_E_PARAM; 6484 } 6485 SOC_IF_ERROR_RETURN(portmod_port_synce_clk_ctrl_set(unit, lport, &config)); 6486 } else 6487 #endif 6488 { 6489 /* Set TSCF SDM divisors */ 6490 /* Set SDM stage 1 mode to bypass */ 6491 BCM_IF_ERROR_RETURN(_bcm_time_synce_phy_register_set(unit, lport, divisor->stage1_div, 6492 BCM_TIME_TSCF_MAIN0_SYNCE_CTL_REG)); 6493 6494 /* Set stage 0 mode to SDM mode */ 6495 BCM_IF_ERROR_RETURN(_bcm_time_synce_phy_register_set(unit, lport, 6496 divisor->stage0_mode, BCM_TIME_TSCF_MAIN0_SYNCE_CTL_STAGE0_REG)); 6497 6498 BCM_IF_ERROR_RETURN(_bcm_time_synce_phy_register_set(unit, lport, sdm_val, 6499 BCM_TIME_TSCF_RX_X4_SYNCE_FRACTIONAL_DIV_REG)); 6500 } 6501 /* TOP_MISC_CONTROL_2 - set sg pll port sel 0 */ 6502 if (!SOC_IS_TOMAHAWK3(unit)) { 6503 SOC_IF_ERROR_RETURN 6504 (soc_reg_field32_modify(unit, synce_ctrl_2, REG_PORT_ANY, 6505 xg_rcvd_sel, 0)); 6506 } 6507 /* serdes port configuration */ 6508 SOC_IF_ERROR_RETURN 6509 (soc_reg_field32_modify(unit, synce_ctrl_2, 6510 REG_PORT_ANY, l1_rcvd_port_sel, port_sel)); 6511 /* TOP_MISC_CONTROL */ 6512 SOC_IF_ERROR_RETURN 6513 (soc_reg_field32_modify(unit, synce_ctrl, REG_PORT_ANY, 6514 l1_rcvd_clk_rstn, 1)); 6515 6516 return BCM_E_NONE; 6517 } 6518 6519 /* 6520 * Function: 6521 * _bcm_esw_time_tomahawkx_synce_clock_get 6522 * Purpose: 6523 * Get current setting of syncE clock divisor 6524 * Parameters: 6525 * unit - (IN) Unit number. 6526 divisor - (OUT) Divisor setting 6527 * Returns: 6528 * BCM_E_xxx 6529 * Notes: This function takes care of tomahawk only 6530 */ 6531 STATIC int 6532 _bcm_esw_time_tomahawkx_synce_clock_get(int unit, 6533 bcm_time_synce_clock_src_type_t clk_src, 6534 bcm_time_synce_divisor_setting_t *divisor) 6535 { 6536 uint32 val, val2, rval; 6537 int lport; 6538 uint32 sdm_val; 6539 soc_reg_t synce_ctrl_2 = TOP_MISC_CONTROL_2r; 6540 soc_field_t xg_rcvd_sel = XG_RCVD_SELf; 6541 soc_field_t l1_rcvd_port_sel = L1_RCVD_PORT_SELf; 6542 portmod_port_synce_clk_ctrl_t config; 6543 6544 if (SOC_IS_TOMAHAWK3(unit)) { 6545 synce_ctrl_2 = TOP_SYNCE_CTRLr; 6546 } 6547 6548 portmod_port_synce_clk_ctrl_t_init(unit, &config); 6549 6550 if (clk_src == bcmTimeSynceClockSourceSecondary) { 6551 l1_rcvd_port_sel = L1_RCVD_BKUP_PORT_SELf; 6552 xg_rcvd_sel = XG_RCVD_BKUP_SELf; 6553 } 6554 /* input source port */ 6555 val = 0; 6556 soc_reg32_get(unit, synce_ctrl_2, REG_PORT_ANY, 0, &rval); 6557 6558 if (!SOC_IS_TOMAHAWK3(unit)) { 6559 val = soc_reg_field_get(unit, synce_ctrl_2, rval, xg_rcvd_sel); 6560 } 6561 val2 = soc_reg_field_get(unit, synce_ctrl_2, rval, l1_rcvd_port_sel); 6562 if (val == 0) { /* source is Port */ 6563 uint32 phy_port; 6564 phy_port = val2 + 1; 6565 _bcm_esw_time_synce_phy_port_get(unit, phy_port, &phy_port); 6566 divisor->input_src = bcmTimeSynceInputSourceTypePort; 6567 divisor->index = SOC_INFO(unit).port_p2l_mapping[phy_port]; 6568 } else { /* source is PLL */ 6569 /* TOP_MISC_CONTROL_2.L1_RCVD_PORT_SELf needs to be 0 6570 * Otherwise, there's no clock output */ 6571 if (val2 != 0) { 6572 LOG_ERROR(BSL_LS_BCM_TIME, (BSL_META_U(unit, 6573 "No clock output\n"))); 6574 return BCM_E_FAIL; 6575 } 6576 divisor->input_src = bcmTimeSynceInputSourceTypePLL; 6577 divisor->index = val - 1; 6578 } 6579 6580 /* READ the SDM divisors from TSC */ 6581 lport = divisor->index; 6582 6583 if (!SOC_PORT_VALID(unit,lport)) 6584 { 6585 return BCM_E_PARAM; 6586 } 6587 6588 #ifdef PORTMOD_SUPPORT 6589 if (soc_feature(unit, soc_feature_portmod)) { 6590 SOC_IF_ERROR_RETURN(portmod_port_synce_clk_ctrl_get(unit, lport, &config)); 6591 /* stage0_mode */ 6592 divisor->stage0_mode = config.stg0_mode; 6593 sdm_val = config.sdm_val; 6594 /* stage0_whole */ 6595 divisor->stage0_sdm_whole = ((sdm_val & 0xff00) >> 8); 6596 /* stage0_frac */ 6597 divisor->stage0_sdm_frac = sdm_val & 0xff ; 6598 /* stage1_div */ 6599 divisor->stage1_div = config.stg1_mode; 6600 } else 6601 #endif 6602 { 6603 /* stage0_mode */ 6604 BCM_IF_ERROR_RETURN(_bcm_time_synce_phy_register_get(unit, lport, 6605 BCM_TIME_TSCF_MAIN0_SYNCE_CTL_STAGE0_REG, &divisor->stage0_mode)); 6606 BCM_IF_ERROR_RETURN(_bcm_time_synce_phy_register_get(unit, lport, 6607 BCM_TIME_TSCF_RX_X4_SYNCE_FRACTIONAL_DIV_REG, &sdm_val)); 6608 /* stage0_whole */ 6609 divisor->stage0_sdm_whole = ((sdm_val & 0xff00) >> 8); 6610 /* stage0_frac */ 6611 divisor->stage0_sdm_frac = sdm_val & 0xff ; 6612 /* stage1_div */ 6613 BCM_IF_ERROR_RETURN(_bcm_time_synce_phy_register_get(unit, lport, 6614 BCM_TIME_TSCF_MAIN0_SYNCE_CTL_REG, &divisor->stage1_div)); 6615 } 6616 6617 return BCM_E_NONE; 6618 } 6619 6620 #define BCM_TIME_APACHEX_PLL_VALID(x) (((x) >= 0) && ((x) <= 3)) 6621 #define BCM_TIME_APACHEX_PORT_VALID(x) ((x) >= 1 && (x) <= 72 ) 6622 #define BCM_TIME_APACHEX_LCPLL_PORT_BASE (73) 6623 6624 STATIC int 6625 _bcm_esw_time_apachex_synce_clock_set_by_port(int unit, 6626 bcm_time_synce_clock_src_type_t clk_src, 6627 bcm_time_synce_divisor_setting_t *divisor) 6628 { 6629 /* Assumes input index is logical port number */ 6630 int lport = divisor->index; 6631 int phy_port = SOC_INFO(unit).port_l2p_mapping[lport]; 6632 int port_sel; 6633 uint16 sdm_val; 6634 uint32 rval; 6635 phymod_dispatch_type_t dispatch_type = phymodDispatchTypeInvalid; 6636 6637 if (!BCM_TIME_SYNCE_CLK_SRC_VALID(clk_src) || 6638 !BCM_TIME_APACHEX_PORT_VALID(lport) || 6639 (phy_port == -1)) { 6640 return BCM_E_PARAM; 6641 } 6642 6643 BCM_IF_ERROR_RETURN(_bcm_esw_time_synce_phy_port_lane_adjust(unit, phy_port, 6644 NULL, &phy_port)); 6645 6646 port_sel = phy_port - 1; 6647 switch (clk_src) { 6648 case bcmTimeSynceClockSourcePrimary: 6649 /* TOP_MISC_CONTROL */ 6650 SOC_IF_ERROR_RETURN 6651 (soc_reg_field32_modify(unit, TOP_MISC_CONTROLr, REG_PORT_ANY, 6652 L1_RCVD_CLK_RSTNf, 0)); 6653 6654 /* TOP_MISC_CONTROL_2 - post divisors set to 0 */ 6655 SOC_IF_ERROR_RETURN 6656 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_2r, REG_PORT_ANY, 6657 L1_RCVD_FREQ_SELf, 0)); 6658 6659 dispatch_type = _bcm_time_synce_tsc_phymod_dispatch_type_get(unit, lport); 6660 6661 if (dispatch_type == phymodDispatchTypeTsce) { 6662 6663 /* register is similar to TD2+ */ 6664 _bcm_time_td2p_divctrl_reg_modify_primary(unit, divisor); 6665 6666 /* Turn off TSC div11 */ 6667 BCM_IF_ERROR_RETURN(_bcm_time_synce_phy_register_set(unit, lport, 0x0, 6668 BCM_TIME_TSCE_MAIN0_SYNCE_CTL_STAGE0_REG)); 6669 6670 6671 } else if (dispatch_type == phymodDispatchTypeTscf) { 6672 /* reset chip level SDM config before phy SDM config*/ 6673 SOC_IF_ERROR_RETURN(READ_TOP_L1_RCVD_CLK_CTRLr(unit, &rval)); 6674 soc_reg_field_set(unit, TOP_L1_RCVD_CLK_CTRLr, &rval, 6675 STAGE0_MODEf, 0x0); 6676 soc_reg_field_set(unit, TOP_L1_RCVD_CLK_CTRLr, &rval, 6677 STAGE1_MODEf, 0x0); 6678 soc_reg_field_set(unit, TOP_L1_RCVD_CLK_CTRLr, &rval, 6679 SDM_DIVISORf, 0x0); 6680 WRITE_TOP_L1_RCVD_CLK_CTRLr(unit, rval); 6681 6682 6683 /* Set TSCF SDM divisors */ 6684 /* Set SDM stage 1 mode to bypass */ 6685 BCM_IF_ERROR_RETURN(_bcm_time_synce_phy_register_set(unit, lport, 0x0, 6686 BCM_TIME_TSCF_MAIN0_SYNCE_CTL_REG)); 6687 6688 /* Set stage 0 mode to SDM mode */ 6689 BCM_IF_ERROR_RETURN(_bcm_time_synce_phy_register_set(unit, lport, 6690 divisor->stage0_mode, BCM_TIME_TSCF_MAIN0_SYNCE_CTL_STAGE0_REG)); 6691 6692 sdm_val = ((divisor->stage0_sdm_whole & 0xff) << 8 | 6693 (divisor->stage0_sdm_frac & 0xff)); 6694 6695 BCM_IF_ERROR_RETURN(_bcm_time_synce_phy_register_set(unit, lport, sdm_val, 6696 BCM_TIME_TSCF_RX_X4_SYNCE_FRACTIONAL_DIV_REG)); 6697 } 6698 6699 /* TOP_MISC_CONTROL_2 */ 6700 SOC_IF_ERROR_RETURN 6701 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_2r, REG_PORT_ANY, 6702 XG_RCVD_PRI_SELf, 0)); 6703 /* EGR_L1_CLK_RECOVERY_CTRL */ 6704 SOC_IF_ERROR_RETURN 6705 (soc_reg_field32_modify(unit, EGR_L1_CLK_RECOVERY_CTRLr, 6706 REG_PORT_ANY, PRI_PORT_SELf, port_sel)); 6707 6708 /* TOP_MISC_CONTROL */ 6709 SOC_IF_ERROR_RETURN 6710 (soc_reg_field32_modify(unit, TOP_MISC_CONTROLr, REG_PORT_ANY, 6711 L1_RCVD_CLK_RSTNf, 1)); 6712 break; 6713 case bcmTimeSynceClockSourceSecondary: 6714 /* TOP_MISC_CONTROL */ 6715 SOC_IF_ERROR_RETURN 6716 (soc_reg_field32_modify(unit, TOP_MISC_CONTROLr, REG_PORT_ANY, 6717 L1_RCVD_CLK_BKUP_RSTNf, 0)); 6718 6719 /* TOP_MISC_CONTROL_2 - post divisors set to 0 */ 6720 SOC_IF_ERROR_RETURN 6721 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_2r, REG_PORT_ANY, 6722 L1_RCVD_BKUP_FREQ_SELf, 0)); 6723 6724 dispatch_type = _bcm_time_synce_tsc_phymod_dispatch_type_get(unit, lport); 6725 6726 if (dispatch_type == phymodDispatchTypeTsce) { 6727 /* register is similar to TD2+ */ 6728 _bcm_time_td2p_divctrl_reg_modify_secondary(unit, divisor); 6729 6730 /* Turn off TSC div11 */ 6731 BCM_IF_ERROR_RETURN(_bcm_time_synce_phy_register_set(unit, lport, 0x0, 6732 BCM_TIME_TSCE_MAIN0_SYNCE_CTL_STAGE0_REG)); 6733 6734 } else if (dispatch_type == phymodDispatchTypeTscf) { 6735 /* reset chip level SDM config before phy SDM config*/ 6736 SOC_IF_ERROR_RETURN(READ_TOP_L1_RCVD_CLK_BKUP_CTRLr(unit, &rval)); 6737 soc_reg_field_set(unit, TOP_L1_RCVD_CLK_BKUP_CTRLr, &rval, 6738 STAGE0_MODEf, 0x0); 6739 soc_reg_field_set(unit, TOP_L1_RCVD_CLK_BKUP_CTRLr, &rval, 6740 STAGE1_MODEf, 0x0); 6741 soc_reg_field_set(unit, TOP_L1_RCVD_CLK_BKUP_CTRLr, &rval, 6742 SDM_DIVISORf, 0x0); 6743 WRITE_TOP_L1_RCVD_CLK_BKUP_CTRLr(unit, rval); 6744 6745 6746 /* Set TSCF SDM divisors */ 6747 /* Set SDM stage 1 mode to bypass */ 6748 BCM_IF_ERROR_RETURN(_bcm_time_synce_phy_register_set(unit, lport, 0x0, 6749 BCM_TIME_TSCF_MAIN0_SYNCE_CTL_REG)); 6750 6751 /* Set stage 0 mode to SDM mode */ 6752 BCM_IF_ERROR_RETURN(_bcm_time_synce_phy_register_set(unit, lport, 6753 divisor->stage0_mode, BCM_TIME_TSCF_MAIN0_SYNCE_CTL_STAGE0_REG)); 6754 6755 sdm_val = ((divisor->stage0_sdm_whole & 0xff) << 8 | 6756 (divisor->stage0_sdm_frac & 0xff)); 6757 6758 BCM_IF_ERROR_RETURN(_bcm_time_synce_phy_register_set(unit, lport, sdm_val, 6759 BCM_TIME_TSCF_RX_X4_SYNCE_FRACTIONAL_DIV_REG)); 6760 } 6761 6762 /* TOP_MISC_CONTROL_2 */ 6763 SOC_IF_ERROR_RETURN 6764 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_2r, REG_PORT_ANY, 6765 XG_RCVD_BKUP_SELf, 0)); 6766 /* EGR_L1_CLK_RECOVERY_CTRL */ 6767 SOC_IF_ERROR_RETURN 6768 (soc_reg_field32_modify(unit, EGR_L1_CLK_RECOVERY_CTRLr, 6769 REG_PORT_ANY, BKUP_PORT_SELf, port_sel)); 6770 6771 /* TOP_MISC_CONTROL */ 6772 SOC_IF_ERROR_RETURN 6773 (soc_reg_field32_modify(unit, TOP_MISC_CONTROLr, REG_PORT_ANY, 6774 L1_RCVD_CLK_BKUP_RSTNf, 1)); 6775 break; 6776 /* coverity[dead_error_begin:FALSE] */ 6777 default: 6778 return BCM_E_PARAM; 6779 6780 } 6781 return BCM_E_NONE; 6782 } 6783 6784 /* NOTES : this function takes care of Apache/ Maverick only */ 6785 STATIC int 6786 _bcm_esw_time_apachex_synce_clock_set_by_pll(int unit, 6787 bcm_time_synce_clock_src_type_t clk_src, 6788 bcm_time_synce_divisor_setting_t *divisor) 6789 { 6790 uint32 pll_index = divisor->index; 6791 6792 /* coverity[unsigned_compare] */ 6793 if (!BCM_TIME_APACHEX_PLL_VALID(pll_index) || 6794 !BCM_TIME_SYNCE_CLK_SRC_VALID(clk_src)) { 6795 return BCM_E_PARAM; 6796 } 6797 pll_index = pll_index + BCM_TIME_APACHEX_LCPLL_PORT_BASE; /* serdes LCPLL base */ 6798 if (clk_src == bcmTimeSynceClockSourcePrimary) { 6799 /* TOP_MISC_CONTROL */ 6800 SOC_IF_ERROR_RETURN 6801 (soc_reg_field32_modify(unit, TOP_MISC_CONTROLr, REG_PORT_ANY, 6802 L1_RCVD_CLK_RSTNf, 0)); 6803 /* TOP_MISC_CONTROL_2 */ 6804 SOC_IF_ERROR_RETURN 6805 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_2r, REG_PORT_ANY, 6806 L1_RCVD_FREQ_DIV_SELf, 0)); 6807 /* _TOP_L1_RCVD_CLK_CTRL */ 6808 SOC_IF_ERROR_RETURN(_bcm_time_td2p_divctrl_reg_modify_primary(unit, divisor)); 6809 /* TOP_MISC_CONTROL_2 */ 6810 SOC_IF_ERROR_RETURN 6811 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_2r, REG_PORT_ANY, 6812 XG_RCVD_PRI_SELf, pll_index)); 6813 /* EGR_L1_CLK_RECOVERY_CTRL */ 6814 SOC_IF_ERROR_RETURN 6815 (soc_reg_field32_modify(unit, EGR_L1_CLK_RECOVERY_CTRLr, 6816 REG_PORT_ANY, PRI_PORT_SELf, 0)); 6817 /* TOP_MISC_CONTROL */ 6818 SOC_IF_ERROR_RETURN 6819 (soc_reg_field32_modify(unit, TOP_MISC_CONTROLr, REG_PORT_ANY, 6820 L1_RCVD_CLK_RSTNf, 1)); 6821 } else { 6822 /* TOP_MISC_CONTROL */ 6823 SOC_IF_ERROR_RETURN 6824 (soc_reg_field32_modify(unit, TOP_MISC_CONTROLr, REG_PORT_ANY, 6825 L1_RCVD_CLK_BKUP_RSTNf, 0)); 6826 /* TOP_MISC_CONTROL_2 */ 6827 SOC_IF_ERROR_RETURN 6828 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_2r, REG_PORT_ANY, 6829 L1_RCVD_BKUP_FREQ_DIV_SELf, 0)); 6830 /* _TOP_L1_RCVD_CLK_BKUP_CTRL */ 6831 SOC_IF_ERROR_RETURN 6832 (_bcm_time_td2p_divctrl_reg_modify_secondary(unit, divisor)); 6833 /* TOP_MISC_CONTROL_2 */ 6834 SOC_IF_ERROR_RETURN 6835 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_2r, REG_PORT_ANY, 6836 XG_RCVD_BKUP_SELf, pll_index)); 6837 /* EGR_L1_CLK_RECOVERY_CTRL */ 6838 SOC_IF_ERROR_RETURN 6839 (soc_reg_field32_modify(unit, EGR_L1_CLK_RECOVERY_CTRLr, 6840 REG_PORT_ANY, BKUP_PORT_SELf, 0)); 6841 /* TOP_MISC_CONTROL */ 6842 SOC_IF_ERROR_RETURN 6843 (soc_reg_field32_modify(unit, TOP_MISC_CONTROLr, REG_PORT_ANY, 6844 L1_RCVD_CLK_BKUP_RSTNf, 1)); 6845 } 6846 return BCM_E_NONE; 6847 } 6848 6849 6850 6851 /* 6852 * Function: 6853 * _bcm_esw_time_apachex_synce_clock_set 6854 * Purpose: 6855 * Set syncE divisor setting 6856 * Parameters: 6857 * unit - (IN) Unit number. 6858 * clk_src - (IN) clock source type (Primary, Secondary) 6859 * input_src - (IN) input source type (PORT, PLL) 6860 * index - (IN) if input_src is PORT, specify logical port number 0..30 6861 * if input_src is PLL, specify PLL index 0..2 6862 * divisor - (IN) divisor setting. 6863 * Returns: 6864 * BCM_E_xxx 6865 * Notes: This function only configures for SB2 6866 */ 6867 STATIC int 6868 _bcm_esw_time_apachex_synce_clock_set(int unit, 6869 bcm_time_synce_clock_src_type_t clk_src, 6870 bcm_time_synce_divisor_setting_t *divisor) 6871 { 6872 int rv; 6873 switch(divisor->input_src) { 6874 case bcmTimeSynceInputSourceTypePort: 6875 rv = _bcm_esw_time_apachex_synce_clock_set_by_port(unit, clk_src, divisor); 6876 break; 6877 case bcmTimeSynceInputSourceTypePLL: 6878 rv = _bcm_esw_time_apachex_synce_clock_set_by_pll(unit, clk_src, divisor); 6879 break; 6880 default: 6881 rv = BCM_E_PARAM; 6882 break; 6883 } 6884 6885 return rv; 6886 } 6887 6888 6889 /* 6890 * Function: 6891 * _bcm_esw_time_apachex_synce_clock_get 6892 * Purpose: 6893 * Get current setting of syncE clock divisor 6894 * Parameters: 6895 * unit - (IN) Unit number. 6896 divisor - (OUT) Divisor setting 6897 * Returns: 6898 * BCM_E_xxx 6899 * Notes: This function takes care of tomahawk only 6900 */ 6901 STATIC int 6902 _bcm_esw_time_apachex_synce_clock_get(int unit, 6903 bcm_time_synce_clock_src_type_t clk_src, 6904 bcm_time_synce_divisor_setting_t *divisor) 6905 { 6906 uint32 val, val2, rval, lport; 6907 uint32 sdm_val; 6908 phymod_dispatch_type_t dispatch_type = phymodDispatchTypeInvalid; 6909 6910 switch(clk_src) { 6911 case bcmTimeSynceClockSourcePrimary: 6912 /* input source port */ 6913 SOC_IF_ERROR_RETURN( 6914 READ_TOP_MISC_CONTROL_2r(unit, &rval)); 6915 val = soc_reg_field_get(unit, TOP_MISC_CONTROL_2r, rval, 6916 XG_RCVD_PRI_SELf); 6917 SOC_IF_ERROR_RETURN( 6918 READ_EGR_L1_CLK_RECOVERY_CTRLr(unit, &rval)); 6919 val2 = soc_reg_field_get(unit, EGR_L1_CLK_RECOVERY_CTRLr, rval, 6920 PRI_PORT_SELf); 6921 6922 if (val == 0) { /* source is Port */ 6923 uint32 phy_port; 6924 phy_port = val2 + 1; 6925 _bcm_esw_time_synce_phy_port_get(unit, phy_port, &phy_port); 6926 divisor->input_src = bcmTimeSynceInputSourceTypePort; 6927 divisor->index = SOC_INFO(unit).port_p2l_mapping[phy_port]; 6928 } else { /* source is PLL */ 6929 /* TOP_MISC_CONTROL_2.L1_RCVD_PORT_SELf needs to be 0 6930 * Otherwise, there's no clock output */ 6931 if (val2 != 0) { 6932 LOG_ERROR(BSL_LS_BCM_TIME, (BSL_META_U(unit, 6933 "No clock output\n"))); 6934 return BCM_E_FAIL; 6935 } 6936 divisor->input_src = bcmTimeSynceInputSourceTypePLL; 6937 divisor->index = BCM_TIME_APACHEX_LCPLL_PORT_BASE - val; 6938 } 6939 6940 /* READ the SDM divisors from TSC */ 6941 if (divisor->input_src == bcmTimeSynceInputSourceTypePort) { 6942 6943 /* input source type port */ 6944 lport = divisor->index; 6945 6946 dispatch_type = _bcm_time_synce_tsc_phymod_dispatch_type_get(unit, lport); 6947 6948 if (dispatch_type == phymodDispatchTypeTsce) { 6949 SOC_IF_ERROR_RETURN(READ_TOP_L1_RCVD_CLK_CTRLr(unit, &rval)); 6950 /* stage0_mode */ 6951 divisor->stage0_mode = soc_reg_field_get(unit, TOP_L1_RCVD_CLK_CTRLr, 6952 rval, STAGE0_MODEf); 6953 sdm_val = soc_reg_field_get(unit, TOP_L1_RCVD_CLK_CTRLr, rval, 6954 SDM_DIVISORf); 6955 /* stage0_whole */ 6956 divisor->stage0_sdm_whole = ((sdm_val & 0xff00) >> 8); 6957 /* stage0_frac */ 6958 divisor->stage0_sdm_frac = sdm_val & 0xff ; 6959 /* stage1_div */ 6960 divisor->stage1_div = soc_reg_field_get(unit, TOP_L1_RCVD_CLK_CTRLr, 6961 rval, STAGE1_MODEf); 6962 6963 } else if (dispatch_type == phymodDispatchTypeTscf) { 6964 /* stage0_mode */ 6965 BCM_IF_ERROR_RETURN(_bcm_time_synce_phy_register_get(unit, lport, 6966 BCM_TIME_TSCF_MAIN0_SYNCE_CTL_STAGE0_REG, &divisor->stage0_mode)); 6967 6968 BCM_IF_ERROR_RETURN(_bcm_time_synce_phy_register_get(unit, lport, 6969 BCM_TIME_TSCF_RX_X4_SYNCE_FRACTIONAL_DIV_REG, &sdm_val)); 6970 6971 /* stage0_whole */ 6972 divisor->stage0_sdm_whole = ((sdm_val & 0xff00) >> 8); 6973 /* stage0_frac */ 6974 divisor->stage0_sdm_frac = sdm_val & 0xff ; 6975 6976 /* stage1_div */ 6977 BCM_IF_ERROR_RETURN(_bcm_time_synce_phy_register_get(unit, lport, 6978 BCM_TIME_TSCF_MAIN0_SYNCE_CTL_REG, &divisor->stage1_div)); 6979 6980 } 6981 } else { 6982 /* input source type pll */ 6983 SOC_IF_ERROR_RETURN(READ_TOP_L1_RCVD_CLK_CTRLr(unit, &rval)); 6984 /* stage0_mode */ 6985 divisor->stage0_mode = soc_reg_field_get(unit, TOP_L1_RCVD_CLK_CTRLr, 6986 rval, STAGE0_MODEf); 6987 sdm_val = soc_reg_field_get(unit, TOP_L1_RCVD_CLK_CTRLr, rval, 6988 SDM_DIVISORf); 6989 /* stage0_whole */ 6990 divisor->stage0_sdm_whole = ((sdm_val & 0xff00) >> 8); 6991 /* stage0_frac */ 6992 divisor->stage0_sdm_frac = sdm_val & 0xff ; 6993 /* stage1_div */ 6994 divisor->stage1_div = soc_reg_field_get(unit, TOP_L1_RCVD_CLK_CTRLr, 6995 rval, STAGE1_MODEf); 6996 } 6997 6998 break; 6999 case bcmTimeSynceClockSourceSecondary: 7000 /* input source port */ 7001 SOC_IF_ERROR_RETURN( 7002 READ_TOP_MISC_CONTROL_2r(unit, &rval)); 7003 val = soc_reg_field_get(unit, TOP_MISC_CONTROL_2r, rval, 7004 XG_RCVD_BKUP_SELf); 7005 SOC_IF_ERROR_RETURN( 7006 READ_EGR_L1_CLK_RECOVERY_CTRLr(unit, &rval)); 7007 val2 = soc_reg_field_get(unit, EGR_L1_CLK_RECOVERY_CTRLr, rval, 7008 BKUP_PORT_SELf); 7009 7010 if (val == 0) { /* source is Port */ 7011 uint32 phy_port; 7012 phy_port = val2 + 1; 7013 _bcm_esw_time_synce_phy_port_get(unit, phy_port, &phy_port); 7014 divisor->input_src = bcmTimeSynceInputSourceTypePort; 7015 divisor->index = SOC_INFO(unit).port_p2l_mapping[phy_port]; 7016 } else { /* source is PLL */ 7017 /* TOP_MISC_CONTROL_2.L1_RCVD_BKUP_PORT_SELf needs to be 0 7018 * Otherwise, there's no clock output */ 7019 if (val2 != 0) { 7020 LOG_ERROR(BSL_LS_BCM_TIME, (BSL_META_U(unit, 7021 "No clock output\n"))); 7022 return BCM_E_FAIL; 7023 } 7024 divisor->input_src = bcmTimeSynceInputSourceTypePLL; 7025 divisor->index = BCM_TIME_APACHEX_LCPLL_PORT_BASE- val; 7026 } 7027 7028 /* READ the SDM divisors from TSC */ 7029 if (divisor->input_src == bcmTimeSynceInputSourceTypePort) { 7030 lport = divisor->index; 7031 7032 dispatch_type = _bcm_time_synce_tsc_phymod_dispatch_type_get(unit, lport); 7033 7034 if (dispatch_type == phymodDispatchTypeTsce) { 7035 SOC_IF_ERROR_RETURN(READ_TOP_L1_RCVD_CLK_BKUP_CTRLr(unit, &rval)); 7036 /* stage0_mode */ 7037 divisor->stage0_mode = soc_reg_field_get(unit, TOP_L1_RCVD_CLK_BKUP_CTRLr, 7038 rval, STAGE0_MODEf); 7039 sdm_val = soc_reg_field_get(unit, TOP_L1_RCVD_CLK_BKUP_CTRLr, rval, 7040 SDM_DIVISORf); 7041 /* stage0_whole */ 7042 divisor->stage0_sdm_whole = ((sdm_val & 0xff00) >> 8); 7043 /* stage0_frac */ 7044 divisor->stage0_sdm_frac = sdm_val & 0xff ; 7045 /* stage1_div */ 7046 divisor->stage1_div = soc_reg_field_get(unit, TOP_L1_RCVD_CLK_BKUP_CTRLr, 7047 rval, STAGE1_MODEf); 7048 } else if (dispatch_type == phymodDispatchTypeTscf) { 7049 /* stage0_mode */ 7050 BCM_IF_ERROR_RETURN(_bcm_time_synce_phy_register_get(unit, lport, 7051 BCM_TIME_TSCF_MAIN0_SYNCE_CTL_STAGE0_REG, &divisor->stage0_mode)); 7052 7053 BCM_IF_ERROR_RETURN(_bcm_time_synce_phy_register_get(unit, lport, 7054 BCM_TIME_TSCF_RX_X4_SYNCE_FRACTIONAL_DIV_REG, &sdm_val)); 7055 7056 /* stage0_whole */ 7057 divisor->stage0_sdm_whole = ((sdm_val & 0xff00) >> 8); 7058 /* stage0_frac */ 7059 divisor->stage0_sdm_frac = sdm_val & 0xff ; 7060 7061 /* stage1_div */ 7062 BCM_IF_ERROR_RETURN(_bcm_time_synce_phy_register_get(unit, lport, 7063 BCM_TIME_TSCF_MAIN0_SYNCE_CTL_REG, &divisor->stage1_div)); 7064 } 7065 } else { 7066 SOC_IF_ERROR_RETURN(READ_TOP_L1_RCVD_CLK_BKUP_CTRLr(unit, &rval)); 7067 /* stage0_mode */ 7068 divisor->stage0_mode = soc_reg_field_get(unit, TOP_L1_RCVD_CLK_BKUP_CTRLr, 7069 rval, STAGE0_MODEf); 7070 sdm_val = soc_reg_field_get(unit, TOP_L1_RCVD_CLK_BKUP_CTRLr, rval, 7071 SDM_DIVISORf); 7072 /* stage0_whole */ 7073 divisor->stage0_sdm_whole = ((sdm_val & 0xff00) >> 8); 7074 /* stage0_frac */ 7075 divisor->stage0_sdm_frac = sdm_val & 0xff ; 7076 /* stage1_div */ 7077 divisor->stage1_div = soc_reg_field_get(unit, TOP_L1_RCVD_CLK_BKUP_CTRLr, 7078 rval, STAGE1_MODEf); 7079 } 7080 break; 7081 /* coverity[dead_error_begin:FALSE] */ 7082 default: 7083 return BCM_E_PARAM; 7084 } 7085 7086 return BCM_E_NONE; 7087 } 7088 7089 7090 #endif /* defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_TOMAHAWK_SUPPORT) || defined(BCM_APACHE_SUPPORT)*/ 7091 7092 #if defined(BCM_SABER2_SUPPORT) 7093 7094 #define BCM_TIME_SB2_PORT_VALID(x) ((x) >= 1 && (x) <= 28) 7095 #define BCM_TIME_SB2_PLL_VALID(x) (((x) >= 0) && ((x) <= 2)) 7096 7097 /* NOTES : this function takes care of Saber2 only */ 7098 STATIC int 7099 _bcm_esw_time_saber2_synce_clock_set_by_port(int unit, 7100 bcm_time_synce_clock_src_type_t clk_src, 7101 bcm_time_synce_divisor_setting_t *divisor) 7102 { 7103 /* Assumes input index is logical port number */ 7104 int lport = divisor->index; 7105 int phy_port = SOC_INFO(unit).port_l2p_mapping[lport]; 7106 int mux_index; 7107 uint32 phy_reg = 0x9002; 7108 if (!BCM_TIME_SB2_PORT_VALID(lport) || 7109 !BCM_TIME_SYNCE_CLK_SRC_VALID(clk_src) || 7110 (phy_port == -1)) { 7111 return BCM_E_PARAM; 7112 } 7113 7114 mux_index = lport - 1; 7115 7116 if ((mux_index >= 24 && mux_index <= 27) && 7117 divisor->stage0_mode == bcmTimeSynceModeBypass) { 7118 return BCM_E_PARAM; 7119 } 7120 7121 7122 if ( clk_src == bcmTimeSynceClockSourcePrimary ) { 7123 /* TOP_MISC_CONTROL */ 7124 SOC_IF_ERROR_RETURN 7125 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_0r, REG_PORT_ANY, 7126 L1_CLK0_RECOVERY_DIV_CTRLf, 0x0)); 7127 SOC_IF_ERROR_RETURN 7128 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_0r, REG_PORT_ANY, 7129 L1_CLK0_RECOVERY_MUX_SELf, mux_index)); 7130 if ((mux_index >= 24 && mux_index <= 27) ) { 7131 /* Egal Ports */ 7132 SOC_IF_ERROR_RETURN 7133 (soc_reg_field32_modify(unit, TOP_TSCE_CONFIGr, REG_PORT_ANY, 7134 SYNCE_STAGE0_MODEf, 0x2)); 7135 SOC_IF_ERROR_RETURN 7136 (soc_reg_field32_modify(unit, TOP_TSCE_CONFIGr, REG_PORT_ANY, 7137 SDM_DIVISORf, 0x14a0)); 7138 SOC_IF_ERROR_RETURN 7139 (soc_reg_field32_modify(unit, TOP_TSCE_CONFIGr, REG_PORT_ANY, 7140 SYNCE_MODEf, 0x0)); 7141 phy_port = _bcm_switch_port_to_phyaddr(unit, lport); 7142 if (phy_port == 0xff) { 7143 /* no phy address assigned */ 7144 return BCM_E_PARAM; 7145 } 7146 /* all lanes divisor configured 0 7147 * by default, eagle phy does /11, setting this configuration is 7148 * mandatory to get correct frequency... 7149 * Q: do we need to implement per lane reset .. not seen any 7150 * scenerio though currently 7151 */ 7152 BCM_IF_ERROR_RETURN( 7153 soc_sbus_mdio_write(unit, phy_port, phy_reg, 0)); 7154 } else { 7155 if (divisor->stage0_mode == bcmTimeSynceModeSDMFracDiv) { 7156 SOC_IF_ERROR_RETURN 7157 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_0r, REG_PORT_ANY, 7158 L1_CLK0_RECOVERY_DIV_CTRLf, 0x3)); 7159 } 7160 } 7161 7162 /* enable prim recov clk as VALID indication from invalid status */ 7163 SOC_IF_ERROR_RETURN 7164 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_1r, REG_PORT_ANY, 7165 L1_RCVD_CLK0_SW_OVWR_VALIDf, 1)); 7166 SOC_IF_ERROR_RETURN 7167 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_1r, REG_PORT_ANY, 7168 L1_RCVD_SW_OVWR_ENf, 1 )); 7169 7170 } else { 7171 /* TOP_MISC_CONTROL */ 7172 SOC_IF_ERROR_RETURN 7173 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_0r, REG_PORT_ANY, 7174 L1_CLK1_RECOVERY_DIV_CTRLf, 0x0)); 7175 SOC_IF_ERROR_RETURN 7176 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_0r, REG_PORT_ANY, 7177 L1_CLK1_RECOVERY_MUX_SELf, mux_index)); 7178 if ((mux_index >= 24 && mux_index <= 27) ) { 7179 /* Egal Ports */ 7180 SOC_IF_ERROR_RETURN 7181 (soc_reg_field32_modify(unit, TOP_TSCE_CONFIGr, REG_PORT_ANY, 7182 SYNCE_STAGE0_MODEf, 0x2)); 7183 SOC_IF_ERROR_RETURN 7184 (soc_reg_field32_modify(unit, TOP_TSCE_CONFIGr, REG_PORT_ANY, 7185 SDM_DIVISORf, 0x14a0)); 7186 SOC_IF_ERROR_RETURN 7187 (soc_reg_field32_modify(unit, TOP_TSCE_CONFIGr, REG_PORT_ANY, 7188 SYNCE_MODEf, 0x0)); 7189 phy_port = _bcm_switch_port_to_phyaddr(unit, lport); 7190 if (phy_port == 0xff) { 7191 /* no phy address assigned */ 7192 return BCM_E_PARAM; 7193 } 7194 /* all lanes divisor configured 0 7195 * by default, eagle phy does /11, setting this configuration is 7196 * mandatory to get correct frequency... 7197 * Q: do we need to implement per lane reset .. not seen any 7198 * scenerio though currently 7199 */ 7200 BCM_IF_ERROR_RETURN( 7201 soc_sbus_mdio_write(unit, phy_port, phy_reg, 0)); 7202 } else { 7203 if (divisor->stage0_mode == bcmTimeSynceModeSDMFracDiv) { 7204 SOC_IF_ERROR_RETURN 7205 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_0r, REG_PORT_ANY, 7206 L1_CLK1_RECOVERY_DIV_CTRLf, 0x3)); 7207 } 7208 } 7209 7210 /* enable secondary recov clk as VALID indication from invalid status */ 7211 SOC_IF_ERROR_RETURN 7212 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_1r, REG_PORT_ANY, 7213 L1_RCVD_CLK1_SW_OVWR_VALIDf, 1)); 7214 SOC_IF_ERROR_RETURN 7215 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_1r, REG_PORT_ANY, 7216 L1_RCVD_SW_OVWR_ENf, 1 )); 7217 7218 7219 } 7220 return BCM_E_NONE; 7221 } 7222 7223 /* NOTES : this function takes care of Saber2 only */ 7224 STATIC int 7225 _bcm_esw_time_saber2_synce_clock_set_by_pll(int unit, 7226 bcm_time_synce_clock_src_type_t clk_src, 7227 bcm_time_synce_divisor_setting_t *divisor) 7228 { 7229 uint32 pll_index = divisor->index; 7230 uint32 mux_index; 7231 /* coverity[unsigned_compare] */ 7232 if (!BCM_TIME_SB2_PLL_VALID(pll_index) || 7233 !BCM_TIME_SYNCE_CLK_SRC_VALID(clk_src)) { 7234 return BCM_E_PARAM; 7235 } 7236 7237 /* PLL we support only 125MHz */ 7238 if (pll_index < 2 && divisor->stage0_mode == bcmTimeSynceModeSDMFracDiv) { 7239 return BCM_E_PARAM; 7240 } 7241 7242 mux_index = pll_index + 28; /* SERDES LCPLL Base for Mux */ 7243 7244 if (clk_src == bcmTimeSynceClockSourcePrimary) { 7245 /* TOP_MISC_CONTROL */ 7246 SOC_IF_ERROR_RETURN 7247 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_0r, REG_PORT_ANY, 7248 L1_CLK0_RECOVERY_DIV_CTRLf, 0x0)); 7249 SOC_IF_ERROR_RETURN 7250 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_0r, REG_PORT_ANY, 7251 L1_CLK0_RECOVERY_MUX_SELf, mux_index)); 7252 7253 /* enable prim recov clk as VALID indication from invalid status */ 7254 SOC_IF_ERROR_RETURN 7255 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_1r, REG_PORT_ANY, 7256 L1_RCVD_CLK0_SW_OVWR_VALIDf, 1)); 7257 SOC_IF_ERROR_RETURN 7258 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_1r, REG_PORT_ANY, 7259 L1_RCVD_SW_OVWR_ENf, 1 )); 7260 7261 } else { 7262 /* TOP_MISC_CONTROL */ 7263 SOC_IF_ERROR_RETURN 7264 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_0r, REG_PORT_ANY, 7265 L1_CLK1_RECOVERY_DIV_CTRLf, 0x0)); 7266 SOC_IF_ERROR_RETURN 7267 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_0r, REG_PORT_ANY, 7268 L1_CLK1_RECOVERY_MUX_SELf, mux_index)); 7269 7270 /* enable secondary recov clk as VALID indication from invalid status */ 7271 SOC_IF_ERROR_RETURN 7272 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_1r, REG_PORT_ANY, 7273 L1_RCVD_CLK1_SW_OVWR_VALIDf, 1)); 7274 SOC_IF_ERROR_RETURN 7275 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_1r, REG_PORT_ANY, 7276 L1_RCVD_SW_OVWR_ENf, 1 )); 7277 7278 } 7279 return BCM_E_NONE; 7280 } 7281 7282 /* 7283 * Function: 7284 * _bcm_esw_time_saber2_synce_clock_set 7285 * Purpose: 7286 * Set syncE divisor setting 7287 * Parameters: 7288 * unit - (IN) Unit number. 7289 * clk_src - (IN) clock source type (Primary, Secondary) 7290 * input_src - (IN) input source type (PORT, PLL) 7291 * index - (IN) if input_src is PORT, specify logical port number 0..30 7292 * if input_src is PLL, specify PLL index 0..2 7293 * divisor - (IN) divisor setting. 7294 * Returns: 7295 * BCM_E_xxx 7296 * Notes: This function only configures for SB2 7297 */ 7298 STATIC int 7299 _bcm_esw_time_saber2_synce_clock_set(int unit, 7300 bcm_time_synce_clock_src_type_t clk_src, 7301 bcm_time_synce_divisor_setting_t *divisor) 7302 { 7303 int rv; 7304 switch(divisor->input_src) { 7305 case bcmTimeSynceInputSourceTypePort: 7306 rv = _bcm_esw_time_saber2_synce_clock_set_by_port(unit, clk_src, divisor); 7307 break; 7308 case bcmTimeSynceInputSourceTypePLL: 7309 rv = _bcm_esw_time_saber2_synce_clock_set_by_pll(unit, clk_src, divisor); 7310 break; 7311 default: 7312 rv = BCM_E_PARAM; 7313 break; 7314 } 7315 7316 return rv; 7317 } 7318 7319 /* 7320 * Function: 7321 * _bcm_esw_time_saber2_synce_clock_get 7322 * Purpose: 7323 * Get current setting of syncE clock divisor 7324 * Parameters: 7325 * unit - (IN) Unit number. 7326 divisor - (OUT) Divisor setting 7327 * Returns: 7328 * BCM_E_xxx 7329 * Notes: This function takes care of Saber2 only 7330 */ 7331 STATIC int 7332 _bcm_esw_time_saber2_synce_clock_get(int unit, 7333 bcm_time_synce_clock_src_type_t clk_src, 7334 bcm_time_synce_divisor_setting_t *divisor) 7335 { 7336 uint32 mux_val, div_val, rval; 7337 uint16 phy_port; 7338 7339 switch(clk_src) { 7340 case bcmTimeSynceClockSourcePrimary: 7341 /* input source */ 7342 SOC_IF_ERROR_RETURN( 7343 READ_TOP_MISC_CONTROL_0r(unit, &rval)); 7344 mux_val = soc_reg_field_get(unit, TOP_MISC_CONTROL_0r, rval, 7345 L1_CLK0_RECOVERY_MUX_SELf); 7346 div_val = soc_reg_field_get(unit, TOP_MISC_CONTROL_0r, rval, 7347 L1_CLK0_RECOVERY_DIV_CTRLf); 7348 if (mux_val <= 27) { /* source is Port */ 7349 divisor->input_src = bcmTimeSynceInputSourceTypePort; 7350 phy_port = mux_val + 1; 7351 divisor->index = phy_port; 7352 /* stage0_mode */ 7353 if ((div_val & 0x3) && (mux_val <=23)) 7354 divisor->stage0_mode = bcmTimeSynceModeSDMFracDiv; 7355 else if (mux_val >= 24 && mux_val <=27) 7356 divisor->stage0_mode = bcmTimeSynceModeSDMFracDiv; 7357 else 7358 divisor->stage0_mode = bcmTimeSynceModeBypass; 7359 7360 } else { /* source is PLL */ 7361 if (mux_val > 30) { 7362 LOG_ERROR(BSL_LS_BCM_TIME, (BSL_META_U(unit, 7363 "No clock output\n"))); 7364 return BCM_E_FAIL; 7365 } 7366 divisor->stage0_mode = bcmTimeSynceModeBypass; 7367 divisor->input_src = bcmTimeSynceInputSourceTypePLL; 7368 divisor->index = mux_val - 28; 7369 } 7370 7371 break; 7372 case bcmTimeSynceClockSourceSecondary: 7373 /* input source */ 7374 SOC_IF_ERROR_RETURN( 7375 READ_TOP_MISC_CONTROL_0r(unit, &rval)); 7376 mux_val = soc_reg_field_get(unit, TOP_MISC_CONTROL_0r, rval, 7377 L1_CLK1_RECOVERY_MUX_SELf); 7378 div_val = soc_reg_field_get(unit, TOP_MISC_CONTROL_0r, rval, 7379 L1_CLK1_RECOVERY_DIV_CTRLf); 7380 if (mux_val <= 27) { 7381 /* source is Port */ 7382 divisor->input_src = bcmTimeSynceInputSourceTypePort; 7383 phy_port = mux_val + 1; 7384 divisor->index = phy_port; 7385 /* stage0_mode */ 7386 if ((div_val & 0x3) && (mux_val <=23)) 7387 divisor->stage0_mode = bcmTimeSynceModeSDMFracDiv; 7388 else if (mux_val >= 24 && mux_val <=27) 7389 divisor->stage0_mode = bcmTimeSynceModeSDMFracDiv; 7390 else 7391 divisor->stage0_mode = bcmTimeSynceModeBypass; 7392 } else { 7393 /* source is PLL */ 7394 if (mux_val > 30) { 7395 LOG_ERROR(BSL_LS_BCM_TIME, (BSL_META_U(unit, 7396 "No clock output\n"))); 7397 return BCM_E_FAIL; 7398 } 7399 divisor->stage0_mode = bcmTimeSynceModeBypass; 7400 divisor->input_src = bcmTimeSynceInputSourceTypePLL; 7401 divisor->index = mux_val - 28; 7402 } 7403 break; 7404 default: 7405 return BCM_E_PARAM; 7406 } 7407 return BCM_E_NONE; 7408 } 7409 #endif 7410 7411 #if defined(BCM_METROLITE_SUPPORT) 7412 7413 #define BCM_TIME_ML_PORT_VALID(x) ((x) >= 1 && (x) <= 12) /* Table23, ML top spec(ver0p1) */ 7414 #define BCM_TIME_ML_PLL_VALID(x) ((x) <= 1) /* Table23, ML top spec(verop1) */ 7415 7416 STATIC int 7417 _bcm_esw_time_metrolite_synce_clock_set_by_port(int unit, 7418 bcm_time_synce_clock_src_type_t clk_src, 7419 bcm_time_synce_divisor_setting_t *divisor) 7420 { 7421 /* Assumes input index is logical port number */ 7422 int lport = divisor->index; 7423 int phy_port = SOC_INFO(unit).port_l2p_mapping[lport]; 7424 int mux_index; 7425 uint32 phy_reg = 0x9002; 7426 if (!BCM_TIME_ML_PORT_VALID(lport) || 7427 !BCM_TIME_SYNCE_CLK_SRC_VALID(clk_src) || 7428 (phy_port == -1)) { 7429 return BCM_E_PARAM; 7430 } 7431 7432 mux_index = lport - 1; 7433 7434 /* For eagle TSCE synce div logic handled by portmacro */ 7435 if ((mux_index >= 4 && mux_index <= 11) && 7436 divisor->stage0_mode == bcmTimeSynceModeBypass) { 7437 return BCM_E_PARAM; 7438 } 7439 7440 7441 if ( clk_src == bcmTimeSynceClockSourcePrimary ) { 7442 /* TOP_MISC_CONTROL */ 7443 SOC_IF_ERROR_RETURN 7444 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_0r, REG_PORT_ANY, 7445 L1_CLK0_RECOVERY_DIV_CTRLf, 0x5)); /* Table25 ML top spec ::enable active_reset 7446 * and TSCE synce div logic 7447 */ 7448 SOC_IF_ERROR_RETURN 7449 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_0r, REG_PORT_ANY, 7450 L1_CLK0_RECOVERY_MUX_SELf, mux_index)); 7451 if ((mux_index >= 4 && mux_index <= 11) ) { 7452 /* Eagle Ports */ 7453 SOC_IF_ERROR_RETURN 7454 (soc_reg_field32_modify(unit, TOP_TSC_SYNCE_DIV_CONFIG_0r, REG_PORT_ANY, 7455 SYNCE_STAGE0_MODEf, 0x2)); /* TSCE stage0 divisor(SDM mode choosen) */ 7456 SOC_IF_ERROR_RETURN 7457 (soc_reg_field32_modify(unit, TOP_TSC_SYNCE_DIV_CONFIG_0r, REG_PORT_ANY, 7458 SDM_DIVISORf, 0x14a0)); /* TSCE SDM divisor */ 7459 SOC_IF_ERROR_RETURN 7460 (soc_reg_field32_modify(unit, TOP_TSC_SYNCE_DIV_CONFIG_0r, REG_PORT_ANY, 7461 SYNCE_MODEf, 0x0)); /* TSCE stage1 divisor(div1 choosen) */ 7462 phy_port = _bcm_switch_port_to_phyaddr(unit, lport); 7463 if (phy_port == 0xff) { 7464 /* no phy address assigned */ 7465 return BCM_E_PARAM; 7466 } 7467 /* all lanes divisor configured 0 7468 * by default, eagle phy does /11, setting this configuration is 7469 * mandatory to get correct frequency... 7470 * Q: do we need to implement per lane reset .. not seen any 7471 * scenerio though currently 7472 */ 7473 BCM_IF_ERROR_RETURN( 7474 soc_sbus_mdio_write(unit, phy_port, phy_reg, 0)); 7475 } else { /* for viper ports : 25MHz/125MHz L1 recovery */ 7476 if (divisor->stage0_mode == bcmTimeSynceModeSDMFracDiv) { /* 25MHz L1 recovery from viper ports */ 7477 SOC_IF_ERROR_RETURN 7478 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_0r, REG_PORT_ANY, 7479 L1_CLK0_RECOVERY_DIV_CTRLf, 0x3)); /* enable active_reset and default div5 logic */ 7480 } else { /* 125MHz L1 recovery from viper ports*/ 7481 SOC_IF_ERROR_RETURN 7482 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_0r, REG_PORT_ANY, 7483 L1_CLK0_RECOVERY_DIV_CTRLf, 0x1)); 7484 } 7485 } 7486 7487 /* enable prim recov clk as VALID indication from invalid status */ 7488 SOC_IF_ERROR_RETURN 7489 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_1r, REG_PORT_ANY, 7490 L1_RCVD_CLK0_SW_OVWR_VALIDf, 1)); 7491 SOC_IF_ERROR_RETURN 7492 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_1r, REG_PORT_ANY, 7493 L1_RCVD_SW_OVWR_ENf, 1 )); 7494 7495 } else { 7496 /* TOP_MISC_CONTROL */ 7497 SOC_IF_ERROR_RETURN 7498 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_0r, REG_PORT_ANY, 7499 L1_CLK1_RECOVERY_DIV_CTRLf, 0x5));/* Table25 ML top spec ::enable active_reset 7500 * and TSCE synce div logic 7501 */ 7502 SOC_IF_ERROR_RETURN 7503 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_0r, REG_PORT_ANY, 7504 L1_CLK1_RECOVERY_MUX_SELf, mux_index)); 7505 if ((mux_index >= 4 && mux_index <= 11) ) { 7506 /* Eagle Ports */ 7507 SOC_IF_ERROR_RETURN 7508 (soc_reg_field32_modify(unit, TOP_TSC_SYNCE_DIV_CONFIG_1r, REG_PORT_ANY, 7509 SYNCE_STAGE0_MODEf, 0x2)); /* TSCE stage0 divisor(SDM mode choosen) */ 7510 SOC_IF_ERROR_RETURN 7511 (soc_reg_field32_modify(unit, TOP_TSC_SYNCE_DIV_CONFIG_1r, REG_PORT_ANY, 7512 SDM_DIVISORf, 0x14a0)); /* TSCE SDM divisor */ 7513 SOC_IF_ERROR_RETURN 7514 (soc_reg_field32_modify(unit, TOP_TSC_SYNCE_DIV_CONFIG_1r, REG_PORT_ANY, 7515 SYNCE_MODEf, 0x0)); /* TSCE stage1 divisor(div1 choosen) */ 7516 7517 phy_port = _bcm_switch_port_to_phyaddr(unit, lport); 7518 if (phy_port == 0xff) { 7519 /* no phy address assigned */ 7520 return BCM_E_PARAM; 7521 } 7522 /* all lanes divisor configured 0 7523 * by default, eagle phy does /11, setting this configuration is 7524 * mandatory to get correct frequency... 7525 * Q: do we need to implement per lane reset .. not seen any 7526 * scenerio though currently 7527 */ 7528 BCM_IF_ERROR_RETURN( 7529 soc_sbus_mdio_write(unit, phy_port, phy_reg, 0)); 7530 } else { /* for viper ports : 25MHz/125MHz L1 recovery */ 7531 if (divisor->stage0_mode == bcmTimeSynceModeSDMFracDiv) { /* 25MHz L1 recovery from viper ports */ 7532 SOC_IF_ERROR_RETURN 7533 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_0r, REG_PORT_ANY, 7534 L1_CLK1_RECOVERY_DIV_CTRLf, 0x3)); /* enable active_reset and default div5 logic */ 7535 } else { /* 125MHz L1 recovery from viper ports */ 7536 SOC_IF_ERROR_RETURN 7537 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_0r, REG_PORT_ANY, 7538 L1_CLK1_RECOVERY_DIV_CTRLf, 0x1)); /* enable only active_reset */ 7539 } 7540 } 7541 /* enable secondary recov clk as VALID indication from invalid status */ 7542 SOC_IF_ERROR_RETURN 7543 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_1r, REG_PORT_ANY, 7544 L1_RCVD_CLK1_SW_OVWR_VALIDf, 1)); 7545 SOC_IF_ERROR_RETURN 7546 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_1r, REG_PORT_ANY, 7547 L1_RCVD_SW_OVWR_ENf, 1 )); 7548 7549 } 7550 return BCM_E_NONE; 7551 } 7552 7553 STATIC int 7554 _bcm_esw_time_metrolite_synce_clock_set_by_pll(int unit, 7555 bcm_time_synce_clock_src_type_t clk_src, 7556 bcm_time_synce_divisor_setting_t *divisor) 7557 { 7558 uint32 pll_index = divisor->index; 7559 uint32 mux_index; 7560 7561 if (!BCM_TIME_ML_PLL_VALID(pll_index) || 7562 !BCM_TIME_SYNCE_CLK_SRC_VALID(clk_src)) { 7563 return BCM_E_PARAM; 7564 } 7565 7566 /* MasterLCPLL we support only 125MHz */ 7567 if (pll_index < 1 && divisor->stage0_mode == bcmTimeSynceModeSDMFracDiv) { 7568 return BCM_E_PARAM; 7569 } 7570 7571 mux_index = pll_index + 12; /* Master LCPLL Base for Mux */ 7572 7573 if (clk_src == bcmTimeSynceClockSourcePrimary) { 7574 /* TOP_MISC_CONTROL */ 7575 SOC_IF_ERROR_RETURN 7576 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_0r, REG_PORT_ANY, 7577 L1_CLK0_RECOVERY_DIV_CTRLf, 0x1)); /*Table22, ML top spec::enable active_reset only*/ 7578 SOC_IF_ERROR_RETURN 7579 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_0r, REG_PORT_ANY, 7580 L1_CLK0_RECOVERY_MUX_SELf, mux_index)); 7581 7582 /* enable prim recov clk as VALID indication from invalid status */ 7583 SOC_IF_ERROR_RETURN 7584 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_1r, REG_PORT_ANY, 7585 L1_RCVD_CLK0_SW_OVWR_VALIDf, 1)); 7586 SOC_IF_ERROR_RETURN 7587 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_1r, REG_PORT_ANY, 7588 L1_RCVD_SW_OVWR_ENf, 1 )); 7589 7590 } else { 7591 /* TOP_MISC_CONTROL */ 7592 SOC_IF_ERROR_RETURN 7593 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_0r, REG_PORT_ANY, 7594 L1_CLK1_RECOVERY_DIV_CTRLf, 0x1));/*Table22, ML top spec::enable active_reset only*/ 7595 SOC_IF_ERROR_RETURN 7596 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_0r, REG_PORT_ANY, 7597 L1_CLK1_RECOVERY_MUX_SELf, mux_index)); 7598 7599 /* enable secondary recov clk as VALID indication from invalid status */ 7600 SOC_IF_ERROR_RETURN 7601 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_1r, REG_PORT_ANY, 7602 L1_RCVD_CLK1_SW_OVWR_VALIDf, 1)); 7603 SOC_IF_ERROR_RETURN 7604 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_1r, REG_PORT_ANY, 7605 L1_RCVD_SW_OVWR_ENf, 1 )); 7606 7607 } 7608 return BCM_E_NONE; 7609 } 7610 7611 /* 7612 * Function: 7613 * _bcm_esw_time_metrolite_synce_clock_set 7614 * Purpose: 7615 * Set syncE divisor setting 7616 * Parameters: 7617 * unit - (IN) Unit number. 7618 * clk_src - (IN) clock source type (Primary, Secondary) 7619 * input_src - (IN) input source type (PORT, PLL) 7620 * index - (IN) if input_src is PORT, specify logical port number 0..30 7621 * if input_src is PLL, specify PLL index 0..2 7622 * divisor - (IN) divisor setting. 7623 * Returns: 7624 * BCM_E_xxx 7625 * Notes: ML specific function 7626 */ 7627 STATIC int 7628 _bcm_esw_time_metrolite_synce_clock_set(int unit, 7629 bcm_time_synce_clock_src_type_t clk_src, 7630 bcm_time_synce_divisor_setting_t *divisor) 7631 { 7632 int rv; 7633 switch(divisor->input_src) { 7634 case bcmTimeSynceInputSourceTypePort: 7635 rv = _bcm_esw_time_metrolite_synce_clock_set_by_port(unit, clk_src, divisor); 7636 break; 7637 case bcmTimeSynceInputSourceTypePLL: 7638 rv = _bcm_esw_time_metrolite_synce_clock_set_by_pll(unit, clk_src, divisor); 7639 break; 7640 default: 7641 rv = BCM_E_PARAM; 7642 break; 7643 } 7644 7645 return rv; 7646 } 7647 7648 /* 7649 * Function: 7650 * _bcm_esw_time_metrolite_synce_clock_get 7651 * Purpose: 7652 * Get current setting of syncE clock divisor 7653 * Parameters: 7654 * unit - (IN) Unit number. 7655 divisor - (OUT) Divisor setting 7656 * Returns: 7657 * BCM_E_xxx 7658 * Notes: This function takes care of Saber2 only 7659 */ 7660 STATIC int 7661 _bcm_esw_time_metrolite_synce_clock_get(int unit, 7662 bcm_time_synce_clock_src_type_t clk_src, 7663 bcm_time_synce_divisor_setting_t *divisor) 7664 { 7665 uint32 mux_val, div_val, rval; 7666 uint16 phy_port; 7667 7668 switch(clk_src) { 7669 case bcmTimeSynceClockSourcePrimary: 7670 /* input source */ 7671 SOC_IF_ERROR_RETURN( 7672 READ_TOP_MISC_CONTROL_0r(unit, &rval)); 7673 mux_val = soc_reg_field_get(unit, TOP_MISC_CONTROL_0r, rval, 7674 L1_CLK0_RECOVERY_MUX_SELf); 7675 div_val = soc_reg_field_get(unit, TOP_MISC_CONTROL_0r, rval, 7676 L1_CLK0_RECOVERY_DIV_CTRLf); 7677 if (mux_val <= 11) { /* source is Port */ 7678 divisor->input_src = bcmTimeSynceInputSourceTypePort; 7679 phy_port = mux_val + 1; 7680 divisor->index = phy_port; 7681 /* stage0_mode */ 7682 if ((div_val & 0x3) && (mux_val <=3)) 7683 divisor->stage0_mode = bcmTimeSynceModeSDMFracDiv; 7684 else if ((div_val & 0x5) && (mux_val >= 4 && mux_val <=11)) 7685 divisor->stage0_mode = bcmTimeSynceModeSDMFracDiv; 7686 else 7687 divisor->stage0_mode = bcmTimeSynceModeBypass; 7688 7689 } else { /* source is PLL */ 7690 if (mux_val > 13) { 7691 LOG_ERROR(BSL_LS_BCM_TIME, (BSL_META_U(unit, 7692 "No clock output\n"))); 7693 return BCM_E_FAIL; 7694 } 7695 divisor->stage0_mode = bcmTimeSynceModeBypass; 7696 divisor->input_src = bcmTimeSynceInputSourceTypePLL; 7697 divisor->index = mux_val - 12; 7698 } 7699 7700 break; 7701 case bcmTimeSynceClockSourceSecondary: 7702 /* input source */ 7703 SOC_IF_ERROR_RETURN( 7704 READ_TOP_MISC_CONTROL_0r(unit, &rval)); 7705 mux_val = soc_reg_field_get(unit, TOP_MISC_CONTROL_0r, rval, 7706 L1_CLK1_RECOVERY_MUX_SELf); 7707 div_val = soc_reg_field_get(unit, TOP_MISC_CONTROL_0r, rval, 7708 L1_CLK1_RECOVERY_DIV_CTRLf); 7709 if (mux_val <= 11) { 7710 /* source is Port */ 7711 divisor->input_src = bcmTimeSynceInputSourceTypePort; 7712 phy_port = mux_val + 1; 7713 divisor->index = phy_port; 7714 /* stage0_mode */ 7715 if ((div_val & 0x3) && (mux_val <=3)) 7716 divisor->stage0_mode = bcmTimeSynceModeSDMFracDiv; 7717 else if ((div_val & 0x5) && (mux_val >= 4 && mux_val <=11)) 7718 divisor->stage0_mode = bcmTimeSynceModeSDMFracDiv; 7719 else 7720 divisor->stage0_mode = bcmTimeSynceModeBypass; 7721 } else { 7722 /* source is PLL */ 7723 if (mux_val > 13) { 7724 LOG_ERROR(BSL_LS_BCM_TIME, (BSL_META_U(unit, 7725 "No clock output\n"))); 7726 return BCM_E_FAIL; 7727 } 7728 divisor->stage0_mode = bcmTimeSynceModeBypass; 7729 divisor->input_src = bcmTimeSynceInputSourceTypePLL; 7730 divisor->index = mux_val - 12; 7731 } 7732 break; 7733 default: 7734 return BCM_E_PARAM; 7735 } 7736 return BCM_E_NONE; 7737 } 7738 #endif /* defined(BCM_METROLITE_SUPPORT) */ 7739 7740 #if defined(BCM_TRIDENT3_SUPPORT) 7741 7742 #define BCM_TIME_TD3_PHY_PORT_VALID(x) ((x) >= 1 && (x) <= 128) /* Section 10.2.4, TD3 top spec */ 7743 #define BCM_TIME_TD3_PLL_VALID(x) ((x) <= 3) /* Section 10.2.4 Top spec */ 7744 7745 STATIC int 7746 _bcm_esw_time_trident3_synce_clock_set_by_port(int unit, 7747 bcm_time_synce_clock_src_type_t clk_src, 7748 bcm_time_synce_divisor_setting_t *divisor) 7749 { 7750 /* Assumes input index is logical port number */ 7751 int lport = divisor->index; 7752 int phy_port = SOC_INFO(unit).port_l2p_mapping[lport]; 7753 int port_sel; 7754 uint16 sdm_val; 7755 portmod_port_synce_clk_ctrl_t config; 7756 if(!IS_CL_PORT(unit, lport)) 7757 return BCM_E_PARAM; 7758 7759 if (!BCM_TIME_SYNCE_CLK_SRC_VALID(clk_src) || 7760 !BCM_TIME_TD3_PHY_PORT_VALID(phy_port)) { 7761 return BCM_E_PARAM; 7762 } 7763 7764 BCM_IF_ERROR_RETURN(_bcm_esw_time_synce_phy_port_lane_adjust(unit, phy_port, 7765 NULL, &phy_port)); 7766 7767 port_sel = phy_port - 1; 7768 7769 portmod_port_synce_clk_ctrl_t_init(unit, &config); 7770 7771 switch (clk_src) { 7772 case bcmTimeSynceClockSourcePrimary: 7773 /* TOP_MISC_CONTROL */ 7774 SOC_IF_ERROR_RETURN 7775 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_2r, REG_PORT_ANY, 7776 L1_RCVD_CLK_RSTNf, 0)); 7777 7778 /* TOP_MISC_CONTROL_2 - post divisors set to 0 */ 7779 SOC_IF_ERROR_RETURN 7780 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_2r, REG_PORT_ANY, 7781 L1_RCVD_FREQ_SELf, 0)); 7782 7783 /* Set TSCF SDM divisors */ 7784 /* Set SDM stage 1 mode to bypass */ 7785 7786 sdm_val = ((divisor->stage0_sdm_whole & 0xff) << 8 | 7787 (divisor->stage0_sdm_frac & 0xff)); 7788 7789 config.stg0_mode = divisor->stage0_mode; 7790 config.stg1_mode = 0x0; 7791 config.sdm_val = sdm_val; 7792 if (!SOC_PORT_VALID(unit,lport)) 7793 { 7794 return BCM_E_PARAM; 7795 } 7796 SOC_IF_ERROR_RETURN(portmod_port_synce_clk_ctrl_set(unit, lport, &config)); 7797 7798 /* TOP_MISC_CONTROL_2 - set sg pll port sel 0 */ 7799 SOC_IF_ERROR_RETURN 7800 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_2r, REG_PORT_ANY, 7801 XG_RCVD_SELf, 0)); 7802 7803 /* serdes port configuration */ 7804 SOC_IF_ERROR_RETURN 7805 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_2r, 7806 REG_PORT_ANY, L1_RCVD_PORT_SELf, port_sel)); 7807 7808 /* TOP_MISC_CONTROL */ 7809 SOC_IF_ERROR_RETURN 7810 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_2r, REG_PORT_ANY, 7811 L1_RCVD_CLK_RSTNf, 1)); 7812 break; 7813 case bcmTimeSynceClockSourceSecondary: 7814 /* TOP_MISC_CONTROL */ 7815 SOC_IF_ERROR_RETURN 7816 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_2r, REG_PORT_ANY, 7817 L1_RCVD_CLK_BKUP_RSTNf, 0)); 7818 7819 /* TOP_MISC_CONTROL_2 - post divisors set to 0 */ 7820 SOC_IF_ERROR_RETURN 7821 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_2r, REG_PORT_ANY, 7822 L1_RCVD_BKUP_FREQ_SELf, 0)); 7823 7824 /* Set TSCF SDM divisors */ 7825 /* Set SDM stage 1 mode to bypass */ 7826 sdm_val = ((divisor->stage0_sdm_whole & 0xff) << 8 | 7827 (divisor->stage0_sdm_frac & 0xff)); 7828 7829 config.stg0_mode = divisor->stage0_mode; 7830 config.stg1_mode = 0x0; 7831 config.sdm_val = sdm_val; 7832 if (!SOC_PORT_VALID(unit,lport)) 7833 { 7834 return BCM_E_PARAM; 7835 } 7836 SOC_IF_ERROR_RETURN(portmod_port_synce_clk_ctrl_set(unit, lport, &config)); 7837 7838 /* TOP_MISC_CONTROL_2 - set sg pll port sel 0*/ 7839 SOC_IF_ERROR_RETURN 7840 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_2r, REG_PORT_ANY, 7841 XG_RCVD_BKUP_SELf, 0)); 7842 7843 /* serdes port configuration */ 7844 SOC_IF_ERROR_RETURN 7845 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_2r, 7846 REG_PORT_ANY, L1_RCVD_BKUP_PORT_SELf, port_sel)); 7847 7848 /* TOP_MISC_CONTROL */ 7849 SOC_IF_ERROR_RETURN 7850 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_2r, REG_PORT_ANY, 7851 L1_RCVD_CLK_BKUP_RSTNf, 1)); 7852 break; 7853 /* coverity[dead_error_begin:FALSE] */ 7854 default: 7855 return BCM_E_PARAM; 7856 7857 } 7858 return BCM_E_NONE; 7859 } 7860 7861 /* 7862 * Function: 7863 * _bcm_esw_time_trident3_synce_clock_get 7864 * Purpose: 7865 * Get current setting of syncE clock divisor 7866 * Parameters: 7867 * unit - (IN) Unit number. 7868 divisor - (OUT) Divisor setting 7869 * Returns: 7870 * BCM_E_xxx 7871 * Notes: This function takes care of trident3 only 7872 */ 7873 STATIC int 7874 _bcm_esw_time_trident3_synce_clock_get(int unit, 7875 bcm_time_synce_clock_src_type_t clk_src, 7876 bcm_time_synce_divisor_setting_t *divisor) 7877 { 7878 uint32 val, val2, rval; 7879 int lport; 7880 uint32 sdm_val; 7881 portmod_port_synce_clk_ctrl_t config; 7882 portmod_port_synce_clk_ctrl_t_init(unit, &config); 7883 7884 switch(clk_src) { 7885 case bcmTimeSynceClockSourcePrimary: 7886 /* input source port */ 7887 SOC_IF_ERROR_RETURN( READ_TOP_MISC_CONTROL_2r(unit, &rval)); 7888 7889 val = soc_reg_field_get(unit, TOP_MISC_CONTROL_2r, rval, XG_RCVD_SELf); 7890 val2 = soc_reg_field_get(unit, TOP_MISC_CONTROL_2r, rval, L1_RCVD_PORT_SELf); 7891 7892 if (val == 0) { /* source is Port */ 7893 uint32 phy_port; 7894 phy_port = val2 + 1; 7895 _bcm_esw_time_synce_phy_port_get(unit, phy_port, &phy_port); 7896 divisor->input_src = bcmTimeSynceInputSourceTypePort; 7897 divisor->index = SOC_INFO(unit).port_p2l_mapping[phy_port]; 7898 } else { /* source is PLL */ 7899 /* TOP_MISC_CONTROL_2.L1_RCVD_PORT_SELf needs to be 0 7900 * Otherwise, there's no clock output */ 7901 if (val2 != 0) { 7902 LOG_ERROR(BSL_LS_BCM_TIME, (BSL_META_U(unit, 7903 "No clock output\n"))); 7904 return BCM_E_FAIL; 7905 } 7906 divisor->input_src = bcmTimeSynceInputSourceTypePLL; 7907 divisor->index = val - 1; 7908 } 7909 7910 /* READ the SDM divisors from TSC */ 7911 lport = divisor->index; 7912 if (!SOC_PORT_VALID(unit,lport)) 7913 { 7914 return BCM_E_PARAM; 7915 } 7916 SOC_IF_ERROR_RETURN(portmod_port_synce_clk_ctrl_get(unit, lport, &config)); 7917 7918 /* stage0_mode */ 7919 divisor->stage0_mode = config.stg0_mode; 7920 7921 sdm_val = config.sdm_val; 7922 7923 /* stage0_whole */ 7924 divisor->stage0_sdm_whole = ((sdm_val & 0xff00) >> 8); 7925 /* stage0_frac */ 7926 divisor->stage0_sdm_frac = sdm_val & 0xff ; 7927 7928 /* stage1_div */ 7929 divisor->stage1_div = config.stg1_mode; 7930 7931 break; 7932 case bcmTimeSynceClockSourceSecondary: 7933 /* input source port */ 7934 SOC_IF_ERROR_RETURN( READ_TOP_MISC_CONTROL_2r(unit, &rval)); 7935 7936 val = soc_reg_field_get(unit, TOP_MISC_CONTROL_2r, rval, XG_RCVD_BKUP_SELf); 7937 val2 = soc_reg_field_get(unit, TOP_MISC_CONTROL_2r, rval, L1_RCVD_BKUP_PORT_SELf); 7938 7939 if (val == 0) { /* source is Port */ 7940 uint32 phy_port; 7941 phy_port = val2 + 1; 7942 _bcm_esw_time_synce_phy_port_get(unit, phy_port, &phy_port); 7943 divisor->input_src = bcmTimeSynceInputSourceTypePort; 7944 divisor->index = SOC_INFO(unit).port_p2l_mapping[phy_port]; 7945 } else { /* source is PLL */ 7946 /* TOP_MISC_CONTROL_2.L1_RCVD_BKUP_PORT_SELf needs to be 0 7947 * Otherwise, there's no clock output */ 7948 if (val2 != 0) { 7949 LOG_ERROR(BSL_LS_BCM_TIME, (BSL_META_U(unit, 7950 "No clock output\n"))); 7951 return BCM_E_FAIL; 7952 } 7953 divisor->input_src = bcmTimeSynceInputSourceTypePLL; 7954 divisor->index = val - 1; 7955 } 7956 7957 /* READ the SDM divisors from TSC */ 7958 lport = divisor->index; 7959 if (!SOC_PORT_VALID(unit,lport)) 7960 { 7961 return BCM_E_PARAM; 7962 } 7963 7964 SOC_IF_ERROR_RETURN(portmod_port_synce_clk_ctrl_get(unit, lport, &config)); 7965 7966 /* stage0_mode */ 7967 divisor->stage0_mode = config.stg0_mode; 7968 7969 sdm_val = config.sdm_val; 7970 7971 /* stage0_whole */ 7972 divisor->stage0_sdm_whole = ((sdm_val & 0xff00) >> 8); 7973 /* stage0_frac */ 7974 divisor->stage0_sdm_frac = sdm_val & 0xff ; 7975 7976 /* stage1_div */ 7977 divisor->stage1_div = config.stg1_mode; 7978 7979 7980 break; 7981 /* coverity[dead_error_begin:FALSE] */ 7982 default: 7983 return BCM_E_PARAM; 7984 } 7985 7986 return BCM_E_NONE; 7987 } 7988 7989 7990 STATIC int 7991 _bcm_esw_time_trident3_synce_clock_set_by_pll(int unit, 7992 bcm_time_synce_clock_src_type_t clk_src, 7993 bcm_time_synce_divisor_setting_t *divisor) 7994 { 7995 uint32 pll_index = divisor->index; 7996 7997 if (!BCM_TIME_TD3_PLL_VALID(pll_index) || 7998 !BCM_TIME_SYNCE_CLK_SRC_VALID(clk_src)) { 7999 return BCM_E_PARAM; 8000 } 8001 switch (clk_src) { 8002 case bcmTimeSynceClockSourcePrimary: 8003 /* TOP_MISC_CONTROL */ 8004 SOC_IF_ERROR_RETURN 8005 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_2r, REG_PORT_ANY, 8006 L1_RCVD_CLK_RSTNf, 0)); 8007 8008 /* TOP_MISC_CONTROL_2 - post divisors set to 0 */ 8009 SOC_IF_ERROR_RETURN 8010 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_2r, REG_PORT_ANY, 8011 L1_RCVD_FREQ_SELf, 0)); 8012 8013 /* TOP_MISC_CONTROL_2 - set sg pll port sel 0 */ 8014 SOC_IF_ERROR_RETURN 8015 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_2r, REG_PORT_ANY, 8016 XG_RCVD_SELf, pll_index)); 8017 8018 /* TOP_MISC_CONTROL */ 8019 SOC_IF_ERROR_RETURN 8020 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_2r, REG_PORT_ANY, 8021 L1_RCVD_CLK_RSTNf, 1)); 8022 break; 8023 8024 case bcmTimeSynceClockSourceSecondary: 8025 /* TOP_MISC_CONTROL */ 8026 SOC_IF_ERROR_RETURN 8027 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_2r, REG_PORT_ANY, 8028 L1_RCVD_CLK_BKUP_RSTNf, 0)); 8029 8030 /* TOP_MISC_CONTROL_2 - post divisors set to 0 */ 8031 SOC_IF_ERROR_RETURN 8032 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_2r, REG_PORT_ANY, 8033 L1_RCVD_BKUP_FREQ_SELf, 0)); 8034 8035 /* TOP_MISC_CONTROL_2 - set sg pll port sel 0*/ 8036 SOC_IF_ERROR_RETURN 8037 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_2r, REG_PORT_ANY, 8038 XG_RCVD_BKUP_SELf, pll_index)); 8039 8040 /* TOP_MISC_CONTROL */ 8041 SOC_IF_ERROR_RETURN 8042 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_2r, REG_PORT_ANY, 8043 L1_RCVD_CLK_BKUP_RSTNf, 1)); 8044 break; 8045 } 8046 return BCM_E_NONE; 8047 } 8048 8049 /* 8050 * Function: 8051 * _bcm_esw_time_trident3_synce_clock_set 8052 * Purpose: 8053 * Set syncE divisor setting 8054 * Parameters: 8055 * unit - (IN) Unit number. 8056 * clk_src - (IN) clock source type (Primary, Secondary) 8057 * input_src - (IN) input source type (PORT, PLL) 8058 * index - (IN) if input_src is PORT, specify logical port number 0..105 8059 * if input_src is PLL, specify PLL index 0..3 8060 * divisor - (IN) divisor setting. 8061 * Returns: 8062 * BCM_E_xxx 8063 * Notes: This function only configures for td2plus 8064 */ 8065 STATIC int 8066 _bcm_esw_time_trident3_synce_clock_set(int unit, 8067 bcm_time_synce_clock_src_type_t clk_src, 8068 bcm_time_synce_divisor_setting_t *divisor) 8069 { 8070 int rv; 8071 8072 switch(divisor->input_src) { 8073 case bcmTimeSynceInputSourceTypePort: 8074 rv = _bcm_esw_time_trident3_synce_clock_set_by_port(unit, clk_src, divisor); 8075 break; 8076 case bcmTimeSynceInputSourceTypePLL: 8077 rv = _bcm_esw_time_trident3_synce_clock_set_by_pll(unit, clk_src, divisor); 8078 break; 8079 default: 8080 rv = BCM_E_PARAM; 8081 break; 8082 } 8083 8084 return rv; 8085 } 8086 8087 8088 #endif /* defined(BCM_TRIDENT3_SUPPORT) */ 8089 8090 #if defined(BCM_MAVERICK2_SUPPORT) 8091 8092 #define BCM_TIME_MV2_PHY_PORT_VALID(x) ((x) >= 0 && (x) <= 80) /* Section 10.2.2 and 5.2, MV2 top spec */ 8093 STATIC int 8094 _bcm_esw_time_maverick2_synce_clock_set_by_port(int unit, 8095 bcm_time_synce_clock_src_type_t clk_src, 8096 bcm_time_synce_divisor_setting_t *divisor) 8097 { 8098 /* Assumes input index is logical port number */ 8099 int lport = divisor->index; 8100 int phy_port = SOC_INFO(unit).port_l2p_mapping[lport]; 8101 int port_sel; 8102 uint16 sdm_val; 8103 portmod_port_synce_clk_ctrl_t config; 8104 8105 soc_reg_t synce_ctrl_2 = TOP_MISC_CONTROL_2r; 8106 soc_field_t l1_rcvd_clk_rstn = L1_RCVD_CLK_RSTNf; 8107 soc_field_t l1_rcvd_freq_sel = L1_RCVD_FREQ_SELf; 8108 soc_field_t l1_rcvd_port_sel = L1_RCVD_PORT_SELf; 8109 8110 if (clk_src == bcmTimeSynceClockSourceSecondary) { 8111 l1_rcvd_clk_rstn = L1_RCVD_CLK_BKUP_RSTNf; 8112 l1_rcvd_freq_sel = L1_RCVD_BKUP_FREQ_SELf; 8113 l1_rcvd_port_sel = L1_RCVD_BKUP_PORT_SELf; 8114 } 8115 8116 if(!IS_CL_PORT(unit, lport)) 8117 return BCM_E_PARAM; 8118 8119 if (!BCM_TIME_SYNCE_CLK_SRC_VALID(clk_src) || 8120 !BCM_TIME_MV2_PHY_PORT_VALID(phy_port)) { 8121 return BCM_E_PARAM; 8122 } 8123 8124 BCM_IF_ERROR_RETURN(_bcm_esw_time_synce_phy_port_lane_adjust(unit, phy_port, 8125 NULL, &phy_port)); 8126 8127 port_sel = phy_port - 1; 8128 8129 portmod_port_synce_clk_ctrl_t_init(unit, &config); 8130 8131 /* TOP_MISC_CONTROL_2 */ 8132 SOC_IF_ERROR_RETURN 8133 (soc_reg_field32_modify(unit, synce_ctrl_2, REG_PORT_ANY, 8134 l1_rcvd_clk_rstn, 0)); 8135 8136 /* TOP_MISC_CONTROL_2 - post divisors set to 0 */ 8137 SOC_IF_ERROR_RETURN 8138 (soc_reg_field32_modify(unit, synce_ctrl_2, REG_PORT_ANY, 8139 l1_rcvd_freq_sel, 0)); 8140 8141 /* Set TSCF SDM divisors */ 8142 /* Set SDM stage 1 mode to bypass */ 8143 8144 sdm_val = ((divisor->stage0_sdm_whole & 0xff) << 8 | 8145 (divisor->stage0_sdm_frac & 0xff)); 8146 8147 config.stg0_mode = divisor->stage0_mode; 8148 config.stg1_mode = 0x0; 8149 config.sdm_val = sdm_val; 8150 if (!SOC_PORT_VALID(unit,lport)) 8151 { 8152 return BCM_E_PARAM; 8153 } 8154 SOC_IF_ERROR_RETURN(portmod_port_synce_clk_ctrl_set(unit, lport, &config)); 8155 8156 /* serdes port configuration */ 8157 SOC_IF_ERROR_RETURN 8158 (soc_reg_field32_modify(unit, synce_ctrl_2, 8159 REG_PORT_ANY, l1_rcvd_port_sel, port_sel)); 8160 8161 /* TOP_MISC_CONTROL_2 */ 8162 SOC_IF_ERROR_RETURN 8163 (soc_reg_field32_modify(unit, synce_ctrl_2, REG_PORT_ANY, 8164 l1_rcvd_clk_rstn, 1)); 8165 return BCM_E_NONE; 8166 } 8167 8168 /* 8169 * Function: 8170 * _bcm_esw_time_maverick2_synce_clock_get 8171 * Purpose: 8172 * Get current setting of syncE clock divisor 8173 * Parameters: 8174 * unit - (IN) Unit number. 8175 divisor - (OUT) Divisor setting 8176 * Returns: 8177 * BCM_E_xxx 8178 * Notes: This function takes care of maverick2 only 8179 */ 8180 STATIC int 8181 _bcm_esw_time_maverick2_synce_clock_get(int unit, 8182 bcm_time_synce_clock_src_type_t clk_src, 8183 bcm_time_synce_divisor_setting_t *divisor) 8184 { 8185 uint32 val, rval; 8186 int lport; 8187 uint32 sdm_val; 8188 uint32 phy_port; 8189 8190 soc_reg_t synce_ctrl_2 = TOP_MISC_CONTROL_2r; 8191 soc_field_t l1_rcvd_port_sel = L1_RCVD_PORT_SELf; 8192 8193 portmod_port_synce_clk_ctrl_t config; 8194 portmod_port_synce_clk_ctrl_t_init(unit, &config); 8195 8196 if (clk_src == bcmTimeSynceClockSourceSecondary) { 8197 l1_rcvd_port_sel = L1_RCVD_BKUP_PORT_SELf; 8198 } 8199 8200 /* input source port */ 8201 SOC_IF_ERROR_RETURN( READ_TOP_MISC_CONTROL_2r(unit, &rval)); 8202 8203 val = soc_reg_field_get(unit, synce_ctrl_2, rval, l1_rcvd_port_sel); 8204 8205 phy_port = val + 1; 8206 _bcm_esw_time_synce_phy_port_get(unit, phy_port, &phy_port); 8207 divisor->input_src = bcmTimeSynceInputSourceTypePort; 8208 divisor->index = SOC_INFO(unit).port_p2l_mapping[phy_port]; 8209 8210 /* READ the SDM divisors from TSC */ 8211 lport = divisor->index; 8212 if (!SOC_PORT_VALID(unit,lport)) 8213 { 8214 return BCM_E_PARAM; 8215 } 8216 8217 SOC_IF_ERROR_RETURN(portmod_port_synce_clk_ctrl_get(unit, lport, &config)); 8218 /* stage0_mode */ 8219 divisor->stage0_mode = config.stg0_mode; 8220 sdm_val = config.sdm_val; 8221 /* stage0_whole */ 8222 divisor->stage0_sdm_whole = ((sdm_val & 0xff00) >> 8); 8223 /* stage0_frac */ 8224 divisor->stage0_sdm_frac = sdm_val & 0xff ; 8225 /* stage1_div */ 8226 divisor->stage1_div = config.stg1_mode; 8227 return BCM_E_NONE; 8228 } 8229 8230 /* 8231 * Function: 8232 * _bcm_esw_time_maverick2_synce_clock_set 8233 * Purpose: 8234 * Set syncE divisor setting 8235 * Parameters: 8236 * unit - (IN) Unit number. 8237 * clk_src - (IN) clock source type (Primary, Secondary) 8238 * input_src - (IN) input source type (PORT, PLL) 8239 * index - (IN) if input_src is PORT, specify logical port number 0..105 8240 * if input_src is PLL, specify PLL index 0..3 8241 * divisor - (IN) divisor setting. 8242 * Returns: 8243 * BCM_E_xxx 8244 * Notes: This function only configures for maverick2 8245 */ 8246 STATIC int 8247 _bcm_esw_time_maverick2_synce_clock_set(int unit, 8248 bcm_time_synce_clock_src_type_t clk_src, 8249 bcm_time_synce_divisor_setting_t *divisor) 8250 { 8251 int rv; 8252 8253 switch(divisor->input_src) { 8254 case bcmTimeSynceInputSourceTypePort: 8255 rv = _bcm_esw_time_maverick2_synce_clock_set_by_port(unit, clk_src, divisor); 8256 break; 8257 default: 8258 rv = BCM_E_PARAM; 8259 break; 8260 } 8261 return rv; 8262 } 8263 8264 #endif /* defined(BCM_MAVERICK2_SUPPORT) */ 8265 8266 #if defined(BCM_HELIX5_SUPPORT) 8267 #define BCM_TIME_HX5_PHY_PORT_VALID(x) ((x) >= 1 && (x) <= 76) /* Section 9.2, HX5 top spec */ 8268 8269 STATIC int 8270 _bcm_esw_time_hx5_synce_L1_rcvd_clk_port_get(int phy_port) 8271 { 8272 if (phy_port >=1 && phy_port <= 4) { 8273 return (phy_port - 1); 8274 } 8275 else if (phy_port >= 17 && phy_port <=20) { 8276 return (phy_port - 12 - 1); 8277 } 8278 else if (phy_port >= 33 && phy_port <=36) { 8279 return (phy_port - 24 - 1); 8280 } 8281 else if (phy_port >= 49 && phy_port <=76) { 8282 return (phy_port - 36 - 1); 8283 } 8284 else { 8285 return BCM_E_PARAM; 8286 } 8287 } 8288 8289 STATIC int 8290 _bcm_esw_time_hx5_phy_port_get(int port_sel) 8291 { 8292 if (port_sel < 4) { 8293 return (port_sel + 1); 8294 } 8295 else if (port_sel < 8) { 8296 return (port_sel + 1 + 12); 8297 } 8298 else if (port_sel < 12) { 8299 return (port_sel + 1 + 24); 8300 } 8301 else if (port_sel < 40){ 8302 return (port_sel + 1 + 36); 8303 } 8304 else { 8305 return BCM_E_PARAM; 8306 } 8307 } 8308 8309 STATIC int 8310 _bcm_esw_time_hx5_synce_clock_set_by_port(int unit, 8311 bcm_time_synce_clock_src_type_t clk_src, 8312 bcm_time_synce_divisor_setting_t *divisor) 8313 { 8314 /* Assumes input index is logical port number */ 8315 int lport = divisor->index; 8316 int phy_port = SOC_INFO(unit).port_l2p_mapping[lport]; 8317 int port_sel; 8318 uint16 sdm_val; 8319 portmod_port_synce_clk_ctrl_t config; 8320 8321 soc_reg_t synce_ctrl_2 = TOP_MISC_CONTROL_2r; 8322 soc_field_t l1_rcvd_clk_rstn = L1_RCVD_CLK_RSTNf; 8323 soc_field_t l1_rcvd_freq_sel = L1_RCVD_FREQ_SELf; 8324 soc_field_t l1_rcvd_port_sel = L1_RCVD_PORT_SELf; 8325 8326 if (clk_src == bcmTimeSynceClockSourceSecondary) { 8327 l1_rcvd_clk_rstn = L1_RCVD_CLK_BKUP_RSTNf; 8328 l1_rcvd_freq_sel = L1_RCVD_BKUP_FREQ_SELf; 8329 l1_rcvd_port_sel = L1_RCVD_BKUP_PORT_SELf; 8330 } 8331 8332 if (!BCM_TIME_SYNCE_CLK_SRC_VALID(clk_src) || 8333 !BCM_TIME_HX5_PHY_PORT_VALID(phy_port)) { 8334 return BCM_E_PARAM; 8335 } 8336 8337 BCM_IF_ERROR_RETURN(_bcm_esw_time_synce_phy_port_lane_adjust(unit, phy_port, 8338 NULL, &phy_port)); 8339 8340 8341 port_sel = _bcm_esw_time_hx5_synce_L1_rcvd_clk_port_get(phy_port); 8342 8343 portmod_port_synce_clk_ctrl_t_init(unit, &config); 8344 8345 /* TOP_MISC_CONTROL_2 */ 8346 SOC_IF_ERROR_RETURN 8347 (soc_reg_field32_modify(unit, synce_ctrl_2, REG_PORT_ANY, 8348 l1_rcvd_clk_rstn, 0)); 8349 8350 /* TOP_MISC_CONTROL_2 - post divisors set to 0 */ 8351 SOC_IF_ERROR_RETURN 8352 (soc_reg_field32_modify(unit, synce_ctrl_2, REG_PORT_ANY, 8353 l1_rcvd_freq_sel, 0)); 8354 8355 /* Set TSCF SDM divisors */ 8356 /* Set SDM stage 1 mode to bypass */ 8357 8358 sdm_val = ((divisor->stage0_sdm_whole & 0xff) << 8 | 8359 (divisor->stage0_sdm_frac & 0xff)); 8360 8361 config.stg0_mode = divisor->stage0_mode; 8362 config.stg1_mode = 0x0; 8363 config.sdm_val = sdm_val; 8364 if (!SOC_PORT_VALID(unit,lport)) 8365 { 8366 return BCM_E_PARAM; 8367 } 8368 SOC_IF_ERROR_RETURN(portmod_port_synce_clk_ctrl_set(unit, lport, &config)); 8369 8370 /* serdes port configuration */ 8371 SOC_IF_ERROR_RETURN 8372 (soc_reg_field32_modify(unit, synce_ctrl_2, 8373 REG_PORT_ANY, l1_rcvd_port_sel, port_sel)); 8374 8375 /* TOP_MISC_CONTROL_2 */ 8376 SOC_IF_ERROR_RETURN 8377 (soc_reg_field32_modify(unit, synce_ctrl_2, REG_PORT_ANY, 8378 l1_rcvd_clk_rstn, 1)); 8379 return BCM_E_NONE; 8380 } 8381 8382 #define BCM_TIME_HX5_PLL_VALID(x) ((x) < 2) 8383 STATIC int 8384 _bcm_esw_time_hx5_synce_clock_set_by_pll(int unit, 8385 bcm_time_synce_clock_src_type_t clk_src, 8386 bcm_time_synce_divisor_setting_t *divisor) 8387 { 8388 uint32 pll_index = divisor->index; 8389 int port_sel; 8390 8391 soc_reg_t synce_ctrl_2 = TOP_MISC_CONTROL_2r; 8392 soc_field_t l1_rcvd_clk_rstn = L1_RCVD_CLK_RSTNf; 8393 soc_field_t l1_rcvd_freq_sel = L1_RCVD_FREQ_SELf; 8394 soc_field_t l1_rcvd_port_sel = L1_RCVD_PORT_SELf; 8395 8396 if (!BCM_TIME_HX5_PLL_VALID(pll_index) || 8397 !BCM_TIME_SYNCE_CLK_SRC_VALID(clk_src)) { 8398 return BCM_E_PARAM; 8399 } 8400 8401 if (clk_src == bcmTimeSynceClockSourceSecondary) { 8402 l1_rcvd_clk_rstn = L1_RCVD_CLK_BKUP_RSTNf; 8403 l1_rcvd_freq_sel = L1_RCVD_BKUP_FREQ_SELf; 8404 l1_rcvd_port_sel = L1_RCVD_BKUP_PORT_SELf; 8405 } 8406 8407 /* TOP_MISC_CONTROL */ 8408 SOC_IF_ERROR_RETURN 8409 (soc_reg_field32_modify(unit, synce_ctrl_2, REG_PORT_ANY, 8410 l1_rcvd_clk_rstn, 0)); 8411 8412 /* TOP_MISC_CONTROL_2 - post divisors set to 0 */ 8413 SOC_IF_ERROR_RETURN 8414 (soc_reg_field32_modify(unit, synce_ctrl_2, REG_PORT_ANY, 8415 l1_rcvd_freq_sel, 0)); 8416 port_sel = pll_index + 40; 8417 /* TOP_MISC_CONTROL_2 - set pll port sel */ 8418 SOC_IF_ERROR_RETURN 8419 (soc_reg_field32_modify(unit, synce_ctrl_2, 8420 REG_PORT_ANY, l1_rcvd_port_sel, port_sel)); 8421 8422 /* TOP_MISC_CONTROL */ 8423 SOC_IF_ERROR_RETURN 8424 (soc_reg_field32_modify(unit, synce_ctrl_2, REG_PORT_ANY, 8425 l1_rcvd_clk_rstn, 1)); 8426 8427 return BCM_E_NONE; 8428 } 8429 8430 /* 8431 * Function: 8432 * _bcm_esw_time_hx5_synce_clock_get 8433 * Purpose: 8434 * Get current setting of syncE clock divisor 8435 * Parameters: 8436 * unit - (IN) Unit number. 8437 divisor - (OUT) Divisor setting 8438 * Returns: 8439 * BCM_E_xxx 8440 * Notes: This function takes care of helix5 only 8441 */ 8442 STATIC int 8443 _bcm_esw_time_hx5_synce_clock_get(int unit, 8444 bcm_time_synce_clock_src_type_t clk_src, 8445 bcm_time_synce_divisor_setting_t *divisor) 8446 { 8447 uint32 val, rval; 8448 int lport; 8449 uint32 sdm_val; 8450 uint32 phy_port; 8451 8452 soc_reg_t synce_ctrl_2 = TOP_MISC_CONTROL_2r; 8453 soc_field_t l1_rcvd_port_sel = L1_RCVD_PORT_SELf; 8454 8455 portmod_port_synce_clk_ctrl_t config; 8456 portmod_port_synce_clk_ctrl_t_init(unit, &config); 8457 8458 if (clk_src == bcmTimeSynceClockSourceSecondary) { 8459 l1_rcvd_port_sel = L1_RCVD_BKUP_PORT_SELf; 8460 } 8461 8462 /* input source port */ 8463 SOC_IF_ERROR_RETURN( READ_TOP_MISC_CONTROL_2r(unit, &rval)); 8464 8465 val = soc_reg_field_get(unit, synce_ctrl_2, rval, l1_rcvd_port_sel); 8466 8467 if (val < 40) { 8468 8469 phy_port = _bcm_esw_time_hx5_phy_port_get(val); 8470 _bcm_esw_time_synce_phy_port_get(unit, phy_port, &phy_port); 8471 divisor->input_src = bcmTimeSynceInputSourceTypePort; 8472 divisor->index = SOC_INFO(unit).port_p2l_mapping[phy_port]; 8473 } else { 8474 divisor->input_src = bcmTimeSynceInputSourceTypePLL; 8475 divisor->index = val - 40; 8476 } 8477 8478 if (divisor->input_src == bcmTimeSynceInputSourceTypePort) { 8479 /* READ the SDM divisors from TSC */ 8480 lport = divisor->index; 8481 if (!SOC_PORT_VALID(unit,lport)) 8482 { 8483 return BCM_E_PARAM; 8484 } 8485 8486 SOC_IF_ERROR_RETURN(portmod_port_synce_clk_ctrl_get(unit, lport, &config)); 8487 /* stage0_mode */ 8488 divisor->stage0_mode = config.stg0_mode; 8489 sdm_val = config.sdm_val; 8490 /* stage0_whole */ 8491 divisor->stage0_sdm_whole = ((sdm_val & 0xff00) >> 8); 8492 /* stage0_frac */ 8493 divisor->stage0_sdm_frac = sdm_val & 0xff ; 8494 /* stage1_div */ 8495 divisor->stage1_div = config.stg1_mode; 8496 } 8497 return BCM_E_NONE; 8498 } 8499 8500 /* 8501 * Function: 8502 * _bcm_esw_time_hx5_synce_clock_set 8503 * Purpose: 8504 * Set syncE divisor setting 8505 * Parameters: 8506 * unit - (IN) Unit number. 8507 * clk_src - (IN) clock source type (Primary, Secondary) 8508 * input_src - (IN) input source type (PORT, PLL) 8509 * index - (IN) if input_src is PORT, specify logical port number 0..105 8510 * if input_src is PLL, specify PLL index 0..3 8511 * divisor - (IN) divisor setting. 8512 * Returns: 8513 * BCM_E_xxx 8514 * Notes: This function only configures for helix5 8515 */ 8516 STATIC int 8517 _bcm_esw_time_hx5_synce_clock_set(int unit, 8518 bcm_time_synce_clock_src_type_t clk_src, 8519 bcm_time_synce_divisor_setting_t *divisor) 8520 { 8521 int rv; 8522 8523 switch(divisor->input_src) { 8524 case bcmTimeSynceInputSourceTypePort: 8525 rv = _bcm_esw_time_hx5_synce_clock_set_by_port(unit, clk_src, divisor); 8526 break; 8527 default: 8528 rv = _bcm_esw_time_hx5_synce_clock_set_by_pll(unit, clk_src, divisor); 8529 break; 8530 } 8531 return rv; 8532 } 8533 8534 #endif /* defined(BCM_HELIX5_SUPPORT) */ 8535 8536 #if defined(BCM_GREYHOUND2_SUPPORT) 8537 #define BCM_TIME_GH2_PHY_PORT_VALID(x) ((x) >= 2 && (x) <= 89) /* Section 7.1.3, GH2 top design spec */ 8538 8539 STATIC int 8540 _bcm_esw_time_gh2_synce_clock_set_by_port(int unit, 8541 bcm_time_synce_clock_src_type_t clk_src, 8542 bcm_time_synce_divisor_setting_t *divisor) 8543 { 8544 /* Assumes input index is logical port number */ 8545 int lport = divisor->index; 8546 int phy_port; 8547 int port_sel; 8548 uint16 sdm_val; 8549 8550 soc_reg_t synce_ctrl_2 = TOP_MISC_CONTROL_2r; 8551 soc_field_t l1_rcvd_port_sel = L1_RCVD_PRI_CLK_PORT_SELf; 8552 soc_field_t l1_rcvd_lnksts_sel = L1_RCVD_PRI_LNKSTS_PORT_SELf; 8553 8554 soc_reg_t l1_rcvd_clk_ctrl = TOP_L1_RCVD_CLK_CONTROLr; 8555 soc_field_t l1_rcvd_clk_rstn = L1_RCVD_CLK_RSTNf; 8556 8557 if (clk_src == bcmTimeSynceClockSourceSecondary) { 8558 l1_rcvd_port_sel = L1_RCVD_BKUP_CLK_PORT_SELf; 8559 l1_rcvd_clk_rstn = L1_RCVD_CLK_BKUP_RSTNf; 8560 l1_rcvd_lnksts_sel = L1_RCVD_BKUP_LNKSTS_PORT_SELf; 8561 } 8562 8563 if (!SOC_PORT_VALID(unit,lport)) 8564 { 8565 return BCM_E_PARAM; 8566 } 8567 phy_port = SOC_INFO(unit).port_l2p_mapping[lport]; 8568 8569 if (!BCM_TIME_SYNCE_CLK_SRC_VALID(clk_src) || 8570 !BCM_TIME_GH2_PHY_PORT_VALID(phy_port)) { 8571 return BCM_E_PARAM; 8572 } 8573 8574 /* lane adjust for eagle and falcon */ 8575 if (phy_port >= 58) { 8576 BCM_IF_ERROR_RETURN(_bcm_esw_time_synce_phy_port_lane_adjust(unit, phy_port, 8577 NULL, &phy_port)); 8578 } 8579 8580 /* Section 7.1.3, table 19, GH2 top design spec */ 8581 if (phy_port > 1 && phy_port < 26) { /* Viper */ 8582 port_sel = phy_port + 6; 8583 } else if (phy_port >= 58) { /*Eagle and Falcon */ 8584 port_sel = phy_port - 18; 8585 } else { 8586 return BCM_E_PARAM; 8587 } 8588 8589 if (phy_port >= 58) { /*Eagle and Falcon */ 8590 /* Set TSCF SDM divisors */ 8591 /* Set SDM stage 1 mode to bypass */ 8592 8593 sdm_val = ((divisor->stage0_sdm_whole & 0xff) << 8 | 8594 (divisor->stage0_sdm_frac & 0xff)); 8595 8596 SOC_IF_ERROR_RETURN(soc_phyctrl_synce_clock_set(unit, divisor->index, divisor->stage0_mode, 0, sdm_val)); 8597 } 8598 /* serdes port configuration */ 8599 SOC_IF_ERROR_RETURN 8600 (soc_reg_field32_modify(unit, synce_ctrl_2, 8601 REG_PORT_ANY, l1_rcvd_port_sel, port_sel)); 8602 SOC_IF_ERROR_RETURN 8603 (soc_reg_field32_modify(unit, synce_ctrl_2, 8604 REG_PORT_ANY, l1_rcvd_lnksts_sel, port_sel)); 8605 8606 SOC_IF_ERROR_RETURN 8607 (soc_reg_field32_modify(unit, l1_rcvd_clk_ctrl, REG_PORT_ANY, 8608 l1_rcvd_clk_rstn, 1)); 8609 return BCM_E_NONE; 8610 } 8611 8612 #define BCM_TIME_GH2_PLL_VALID(x) ((x) < 2) 8613 STATIC int 8614 _bcm_esw_time_gh2_synce_clock_set_by_pll(int unit, 8615 bcm_time_synce_clock_src_type_t clk_src, 8616 bcm_time_synce_divisor_setting_t *divisor) 8617 { 8618 return BCM_E_PARAM; 8619 #if 0 8620 8621 8622 uint32 pll_index = divisor->index; 8623 int port_sel; 8624 8625 if (!BCM_TIME_GH2_PLL_VALID(pll_index) || 8626 !BCM_TIME_SYNCE_CLK_SRC_VALID(clk_src)) { 8627 return BCM_E_PARAM; 8628 } 8629 8630 soc_reg_t synce_ctrl_2 = TOP_MISC_CONTROL_2r; 8631 soc_field_t l1_rcvd_port_sel = L1_RCVD_PRI_CLK_PORT_SELf; 8632 8633 soc_reg_t l1_rcvd_clk_ctrl = TOP_L1_RCVD_CLK_CONTROLr; 8634 soc_field_t l1_rcvd_clk_rstn = L1_RCVD_CLK_RSTNf; 8635 soc_field_t l1_rcvd_freq_sel = L1_RCVD_FREQ_SELf; 8636 8637 if (clk_src == bcmTimeSynceClockSourceSecondary) { 8638 l1_rcvd_port_sel = L1_RCVD_BKUP_CLK_PORT_SELf; 8639 l1_rcvd_clk_rstn = L1_RCVD_CLK_BKUP_RSTNf; 8640 l1_rcvd_freq_sel = L1_RCVD_BKUP_FREQ_SELf; 8641 } 8642 8643 /* TOP_MISC_CONTROL */ 8644 SOC_IF_ERROR_RETURN 8645 (soc_reg_field32_modify(unit, l1_rcvd_clk_ctrl, REG_PORT_ANY, 8646 l1_rcvd_clk_rstn, 0)); 8647 8648 /* TOP_MISC_CONTROL_2 - post divisors set to 0 */ 8649 SOC_IF_ERROR_RETURN 8650 (soc_reg_field32_modify(unit, l1_rcvd_clk_ctrl, REG_PORT_ANY, 8651 l1_rcvd_freq_sel, 0)); 8652 port_sel = pll_index; 8653 /* TOP_MISC_CONTROL_2 - set pll port sel */ 8654 SOC_IF_ERROR_RETURN 8655 (soc_reg_field32_modify(unit, synce_ctrl_2, 8656 REG_PORT_ANY, l1_rcvd_port_sel, port_sel)); 8657 8658 /* TOP_MISC_CONTROL */ 8659 SOC_IF_ERROR_RETURN 8660 (soc_reg_field32_modify(unit, l1_rcvd_clk_ctrl, REG_PORT_ANY, 8661 l1_rcvd_clk_rstn, 1)); 8662 8663 return BCM_E_NONE; 8664 #endif 8665 } 8666 8667 STATIC int 8668 _bcm_esw_time_gh2_synce_clock_get(int unit, 8669 bcm_time_synce_clock_src_type_t clk_src, 8670 bcm_time_synce_divisor_setting_t *divisor) 8671 { 8672 uint32 val, rval; 8673 int lport; 8674 uint32 sdm_val; 8675 uint32 phy_port; 8676 uint32 mode0, mode1; 8677 8678 soc_reg_t synce_ctrl_2 = TOP_MISC_CONTROL_2r; 8679 soc_field_t l1_rcvd_port_sel = L1_RCVD_PRI_CLK_PORT_SELf; 8680 8681 if (clk_src == bcmTimeSynceClockSourceSecondary) { 8682 l1_rcvd_port_sel = L1_RCVD_BKUP_CLK_PORT_SELf; 8683 } 8684 8685 /* input source port */ 8686 SOC_IF_ERROR_RETURN( READ_TOP_MISC_CONTROL_2r(unit, &rval)); 8687 8688 val = soc_reg_field_get(unit, synce_ctrl_2, rval, l1_rcvd_port_sel); 8689 8690 if (val >= 8 && val <= 31) { /* viper */ 8691 phy_port = val - 6; 8692 } else if (val >= 40) { /*Eagle or Falcon */ 8693 phy_port = val + 18; 8694 _bcm_esw_time_synce_phy_port_get(unit, phy_port, &phy_port); 8695 } 8696 8697 divisor->input_src = bcmTimeSynceInputSourceTypePort; 8698 divisor->index = SOC_INFO(unit).port_p2l_mapping[phy_port]; 8699 8700 if (divisor->input_src == bcmTimeSynceInputSourceTypePort) { 8701 /* READ the SDM divisors from TSC */ 8702 lport = divisor->index; 8703 if (!SOC_PORT_VALID(unit,lport)) { 8704 return BCM_E_PARAM; 8705 } 8706 if (phy_port >= 58) { 8707 SOC_IF_ERROR_RETURN(soc_phyctrl_synce_clock_get(unit, divisor->index, &mode0, &mode1, &sdm_val)); 8708 /* stage0_whole */ 8709 divisor->stage0_sdm_whole = ((sdm_val & 0xff00) >> 8); 8710 /* stage0_frac */ 8711 divisor->stage0_sdm_frac = sdm_val & 0xff ; 8712 /* stage0_mode */ 8713 divisor->stage0_mode = mode0; 8714 /* stage1_div */ 8715 divisor->stage1_div = mode1; 8716 } 8717 } 8718 return BCM_E_NONE; 8719 } 8720 8721 STATIC int 8722 _bcm_esw_time_gh2_synce_clock_set(int unit, 8723 bcm_time_synce_clock_src_type_t clk_src, 8724 bcm_time_synce_divisor_setting_t *divisor) 8725 { 8726 int rv; 8727 8728 switch(divisor->input_src) { 8729 case bcmTimeSynceInputSourceTypePort: 8730 rv = _bcm_esw_time_gh2_synce_clock_set_by_port(unit, clk_src, divisor); 8731 break; 8732 default: 8733 rv = _bcm_esw_time_gh2_synce_clock_set_by_pll(unit, clk_src, divisor); 8734 break; 8735 } 8736 return rv; 8737 } 8738 #endif /* defined(BCM_GREYHOUND2_SUPPORT) */ 8739 8740 #if defined(BCM_MONTEREY_SUPPORT) 8741 #define BCM_TIME_MO_PHY_PORT_VALID(x) ((x) >= 1 && (x) <= 64) /* Section 7, MO top design spec */ 8742 8743 STATIC int 8744 _bcm_esw_time_monterey_synce_clock_set_by_port(int unit, 8745 bcm_time_synce_clock_src_type_t clk_src, 8746 bcm_time_synce_divisor_setting_t *divisor) 8747 { 8748 /* Assumes input index is logical port number */ 8749 int lport = divisor->index; 8750 int phy_port; 8751 int port_sel; 8752 uint16 sdm_val; 8753 portmod_port_synce_clk_ctrl_t config; 8754 8755 soc_reg_t synce_ctrl = TOP_MISC_CONTROLr; 8756 soc_reg_t synce_ctrl_2 = TOP_MISC_CONTROL_2r; 8757 soc_field_t l1_rcvd_clk_rstn = L1_RCVD_CLK_RSTNf; 8758 soc_field_t l1_rcvd_freq_sel_2 = L1_RCVD_FREQ_SELf; 8759 soc_field_t l1_rcvd_port_sel_2 = L1_CLK_RECOVERY_PRI_PORT_SELf; 8760 soc_field_t l1_rcvd_sw_ovwr_valid = L1_RCVD_SW_OVWR_VALIDf; 8761 soc_field_t l1_rcvd_sw_ovwr_enable = L1_RCVD_SW_OVWR_ENf; 8762 8763 if (clk_src == bcmTimeSynceClockSourceSecondary) { 8764 l1_rcvd_clk_rstn = L1_RCVD_CLK_BKUP_RSTNf; 8765 l1_rcvd_freq_sel_2 = L1_RCVD_BKUP_FREQ_SELf; 8766 l1_rcvd_port_sel_2 = L1_CLK_RECOVERY_BKUP_PORT_SELf; 8767 l1_rcvd_sw_ovwr_valid = L1_RCVD_SW_OVWR_BKUP_VALIDf; 8768 } 8769 8770 if (!SOC_PORT_VALID(unit,lport)) { 8771 return BCM_E_PARAM; 8772 } 8773 phy_port = SOC_INFO(unit).port_l2p_mapping[lport]; 8774 8775 if (!BCM_TIME_SYNCE_CLK_SRC_VALID(clk_src) || 8776 !BCM_TIME_MO_PHY_PORT_VALID(phy_port)) { 8777 return BCM_E_PARAM; 8778 } 8779 8780 BCM_IF_ERROR_RETURN(_bcm_esw_time_synce_phy_port_lane_adjust(unit, phy_port, 8781 NULL, &phy_port)); 8782 8783 port_sel = phy_port - 1; 8784 8785 portmod_port_synce_clk_ctrl_t_init(unit, &config); 8786 8787 /* TOP_MISC_CONTROL_2 */ 8788 SOC_IF_ERROR_RETURN 8789 (soc_reg_field32_modify(unit, synce_ctrl, REG_PORT_ANY, 8790 l1_rcvd_clk_rstn, 0)); 8791 8792 /* TOP_MISC_CONTROL_2 - post divisors set to 0 */ 8793 SOC_IF_ERROR_RETURN 8794 (soc_reg_field32_modify(unit, synce_ctrl_2, REG_PORT_ANY, 8795 l1_rcvd_freq_sel_2, 1)); 8796 8797 /* Set SDM stage 1 mode to bypass */ 8798 sdm_val = ((divisor->stage0_sdm_whole & 0xff) << 8 | 8799 (divisor->stage0_sdm_frac & 0xff)); 8800 8801 config.stg0_mode = divisor->stage0_mode; 8802 config.stg1_mode = 0x0; 8803 config.sdm_val = sdm_val; 8804 SOC_IF_ERROR_RETURN(portmod_port_synce_clk_ctrl_set(unit, lport, &config)); 8805 8806 /* serdes port configuration */ 8807 SOC_IF_ERROR_RETURN 8808 (soc_reg_field32_modify(unit, synce_ctrl_2, 8809 REG_PORT_ANY, l1_rcvd_port_sel_2, port_sel)); 8810 8811 SOC_IF_ERROR_RETURN 8812 (soc_reg_field32_modify(unit, synce_ctrl, REG_PORT_ANY, 8813 l1_rcvd_sw_ovwr_valid, 1)); 8814 SOC_IF_ERROR_RETURN 8815 (soc_reg_field32_modify(unit, synce_ctrl, REG_PORT_ANY, 8816 l1_rcvd_sw_ovwr_enable, 1 )); 8817 /* TOP_MISC_CONTROL_2 */ 8818 SOC_IF_ERROR_RETURN 8819 (soc_reg_field32_modify(unit, synce_ctrl, REG_PORT_ANY, 8820 l1_rcvd_clk_rstn, 1)); 8821 return BCM_E_NONE; 8822 } 8823 8824 #define BCM_TIME_MO_PLL_VALID(x) ((x) < 4) 8825 STATIC int 8826 _bcm_esw_time_monterey_synce_clock_set_by_pll(int unit, 8827 bcm_time_synce_clock_src_type_t clk_src, 8828 bcm_time_synce_divisor_setting_t *divisor) 8829 { 8830 uint32 pll_index = divisor->index; 8831 int port_sel; 8832 8833 soc_reg_t synce_ctrl = TOP_MISC_CONTROLr; 8834 soc_reg_t synce_ctrl_2 = TOP_MISC_CONTROL_2r; 8835 8836 soc_field_t l1_rcvd_clk_rstn = L1_RCVD_CLK_RSTNf; 8837 soc_field_t l1_rcvd_freq_sel_2 = L1_RCVD_FREQ_SELf; 8838 soc_field_t l1_rcvd_port_sel_2 = L1_CLK_RECOVERY_PRI_PORT_SELf; 8839 soc_field_t xg_rcvd_pri_sel_2 = XG_RCVD_PRI_SELf; 8840 soc_field_t l1_rcvd_sw_ovwr_valid = L1_RCVD_SW_OVWR_VALIDf; 8841 soc_field_t l1_rcvd_sw_ovwr_enable = L1_RCVD_SW_OVWR_ENf; 8842 8843 if (clk_src == bcmTimeSynceClockSourceSecondary) { 8844 l1_rcvd_clk_rstn = L1_RCVD_CLK_BKUP_RSTNf; 8845 l1_rcvd_freq_sel_2 = L1_RCVD_BKUP_FREQ_SELf; 8846 l1_rcvd_port_sel_2 = L1_CLK_RECOVERY_BKUP_PORT_SELf; 8847 xg_rcvd_pri_sel_2 = XG_RCVD_BKUP_SELf; 8848 l1_rcvd_sw_ovwr_valid = L1_RCVD_SW_OVWR_BKUP_VALIDf; 8849 } 8850 8851 if (!BCM_TIME_SYNCE_CLK_SRC_VALID(clk_src) || 8852 !BCM_TIME_MO_PLL_VALID(pll_index)) { 8853 return BCM_E_PARAM; 8854 } 8855 8856 port_sel = pll_index + 64; 8857 8858 /* TOP_MISC_CONTROL_2 */ 8859 SOC_IF_ERROR_RETURN 8860 (soc_reg_field32_modify(unit, synce_ctrl, REG_PORT_ANY, 8861 l1_rcvd_clk_rstn, 0)); 8862 8863 /* TOP_MISC_CONTROL_2 - post divisors set to 1 */ 8864 SOC_IF_ERROR_RETURN 8865 (soc_reg_field32_modify(unit, synce_ctrl_2, REG_PORT_ANY, 8866 l1_rcvd_freq_sel_2, 1)); 8867 8868 /* pll index-mux configuration */ 8869 SOC_IF_ERROR_RETURN 8870 (soc_reg_field32_modify(unit, synce_ctrl_2, 8871 REG_PORT_ANY, l1_rcvd_port_sel_2, port_sel)); 8872 SOC_IF_ERROR_RETURN 8873 (soc_reg_field32_modify(unit, synce_ctrl_2, 8874 REG_PORT_ANY, xg_rcvd_pri_sel_2, pll_index+1)); 8875 /* EGR_L1_CLK_RECOVERY_CTRL */ 8876 SOC_IF_ERROR_RETURN 8877 (soc_reg_field32_modify(unit, EGR_L1_CLK_RECOVERY_CTRLr, 8878 REG_PORT_ANY, PRI_PORT_SELf, 0)); 8879 8880 SOC_IF_ERROR_RETURN 8881 (soc_reg_field32_modify(unit, synce_ctrl, REG_PORT_ANY, 8882 l1_rcvd_sw_ovwr_valid, 1)); 8883 SOC_IF_ERROR_RETURN 8884 (soc_reg_field32_modify(unit, synce_ctrl, REG_PORT_ANY, 8885 l1_rcvd_sw_ovwr_enable, 1 )); 8886 8887 /* TOP_MISC_CONTROL_2 */ 8888 SOC_IF_ERROR_RETURN 8889 (soc_reg_field32_modify(unit, synce_ctrl, REG_PORT_ANY, 8890 l1_rcvd_clk_rstn, 1)); 8891 8892 return BCM_E_NONE; 8893 } 8894 /* 8895 * Function: 8896 * _bcm_esw_time_monterey_synce_clock_get 8897 * Purpose: 8898 * Get current setting of syncE clock divisor 8899 * Parameters: 8900 * unit - (IN) Unit number. 8901 divisor - (OUT) Divisor setting 8902 * Returns: 8903 * BCM_E_xxx 8904 * Notes: This function takes care of monterey only 8905 */ 8906 STATIC int 8907 _bcm_esw_time_monterey_synce_clock_get(int unit, 8908 bcm_time_synce_clock_src_type_t clk_src, 8909 bcm_time_synce_divisor_setting_t *divisor) 8910 { 8911 uint32 val, val2, rval; 8912 int lport; 8913 uint32 sdm_val; 8914 uint32 phy_port; 8915 portmod_port_synce_clk_ctrl_t config; 8916 8917 soc_reg_t synce_ctrl_2 = TOP_MISC_CONTROL_2r; 8918 soc_field_t l1_rcvd_port_sel_2 = L1_CLK_RECOVERY_PRI_PORT_SELf; 8919 soc_field_t xg_rcvd_pri_sel_2 = XG_RCVD_PRI_SELf; 8920 8921 portmod_port_synce_clk_ctrl_t_init(unit, &config); 8922 8923 if (clk_src == bcmTimeSynceClockSourceSecondary) { 8924 l1_rcvd_port_sel_2 = L1_CLK_RECOVERY_BKUP_PORT_SELf; 8925 } 8926 8927 /* input source port */ 8928 SOC_IF_ERROR_RETURN( READ_TOP_MISC_CONTROL_2r(unit, &rval)); 8929 8930 val = soc_reg_field_get(unit, synce_ctrl_2, rval, l1_rcvd_port_sel_2); 8931 val2 = soc_reg_field_get(unit, synce_ctrl_2, rval, xg_rcvd_pri_sel_2); 8932 8933 if (val2 == 0) { 8934 if (val < 64) { 8935 phy_port = val + 1; 8936 _bcm_esw_time_synce_phy_port_get(unit, phy_port, &phy_port); 8937 divisor->input_src = bcmTimeSynceInputSourceTypePort; 8938 divisor->index = SOC_INFO(unit).port_p2l_mapping[phy_port]; 8939 8940 lport = divisor->index; 8941 if (!SOC_PORT_VALID(unit,lport)) { 8942 return BCM_E_PARAM; 8943 } 8944 8945 /* READ the SDM divisors from TSC */ 8946 SOC_IF_ERROR_RETURN(portmod_port_synce_clk_ctrl_get(unit, lport, &config)); 8947 /* stage0_mode */ 8948 divisor->stage0_mode = config.stg0_mode; 8949 sdm_val = config.sdm_val; 8950 /* stage0_whole */ 8951 divisor->stage0_sdm_whole = ((sdm_val & 0xff00) >> 8); 8952 /* stage0_frac */ 8953 divisor->stage0_sdm_frac = sdm_val & 0xff; 8954 /* stage1_div */ 8955 divisor->stage1_div = config.stg1_mode; 8956 } else { 8957 return BCM_E_FAIL; 8958 } 8959 } else { 8960 divisor->input_src = bcmTimeSynceInputSourceTypePLL; 8961 divisor->index = val2 - 1; 8962 } 8963 return BCM_E_NONE; 8964 } 8965 8966 STATIC int 8967 _bcm_esw_time_monterey_synce_clock_set(int unit, 8968 bcm_time_synce_clock_src_type_t clk_src, 8969 bcm_time_synce_divisor_setting_t *divisor) 8970 { 8971 int rv; 8972 8973 switch(divisor->input_src) { 8974 case bcmTimeSynceInputSourceTypePort: 8975 rv = _bcm_esw_time_monterey_synce_clock_set_by_port(unit, clk_src, divisor); 8976 break; 8977 case bcmTimeSynceInputSourceTypePLL: 8978 rv = _bcm_esw_time_monterey_synce_clock_set_by_pll(unit, clk_src, divisor); 8979 break; 8980 default: 8981 return BCM_E_PARAM; 8982 } 8983 return rv; 8984 } 8985 8986 #endif /*defined(BCM_MONTEREY_SUPPORT)*/ 8987 /* 8988 * Function: 8989 * bcm_esw_time_synce_clock_get 8990 * Purpose: 8991 * Get current setting of syncE clock divisor 8992 * Parameters: 8993 * unit - (IN) Unit number. 8994 * clk_src - (IN) clock source type (Primary, Secondary) 8995 * divisor - (OUT) Divisor setting 8996 * Returns: 8997 * BCM_E_xxx 8998 * Notes: 8999 */ 9000 int 9001 bcm_esw_time_synce_clock_get(int unit, 9002 bcm_time_synce_clock_src_type_t clk_src, 9003 bcm_time_synce_divisor_setting_t *divisor) 9004 { 9005 int rv = BCM_E_UNAVAIL; 9006 9007 if (soc_feature(unit, soc_feature_time_synce_divisor_setting)) { 9008 #ifdef BCM_TRIDENT2PLUS_SUPPORT 9009 if (SOC_IS_TD2P_TT2P(unit) && !SOC_IS_TOMAHAWKX(unit) && !SOC_IS_APACHE(unit)) { 9010 rv = _bcm_esw_time_td2p_synce_clock_get(unit, clk_src, divisor); 9011 } 9012 #endif 9013 9014 #ifdef BCM_HELIX4_SUPPORT 9015 if (SOC_IS_HELIX4(unit)) { 9016 rv = _bcm_esw_time_hx4_synce_clock_get(unit, clk_src, divisor); 9017 } 9018 #endif 9019 9020 #ifdef BCM_GREYHOUND_SUPPORT 9021 if (SOC_IS_GREYHOUND(unit)) { 9022 rv = _bcm_esw_time_gh_synce_clock_get(unit, clk_src, divisor); 9023 } 9024 #endif 9025 9026 } 9027 9028 #ifdef BCM_KATANA_SUPPORT 9029 if (SOC_IS_KATANA(unit)) { 9030 rv = _bcm_esw_time_katana_synce_clock_get(unit, clk_src, divisor); 9031 } 9032 #endif 9033 9034 #ifdef BCM_TOMAHAWK_SUPPORT 9035 if (SOC_IS_TOMAHAWKX(unit)) { 9036 rv = _bcm_esw_time_tomahawkx_synce_clock_get(unit, clk_src, divisor); 9037 } 9038 #endif 9039 9040 #ifdef BCM_METROLITE_SUPPORT 9041 if (SOC_IS_METROLITE(unit)) { 9042 rv = _bcm_esw_time_metrolite_synce_clock_get(unit, clk_src, divisor); 9043 } 9044 #endif 9045 9046 #ifdef BCM_TRIDENT3_SUPPORT 9047 if (SOC_IS_TRIDENT3(unit)) { 9048 rv = _bcm_esw_time_trident3_synce_clock_get(unit, clk_src, divisor); 9049 } 9050 #endif 9051 9052 #ifdef BCM_APACHE_SUPPORT 9053 if (SOC_IS_APACHE(unit) && !SOC_IS_MONTEREY(unit)) { 9054 rv = _bcm_esw_time_apachex_synce_clock_get(unit, clk_src, divisor); 9055 } 9056 #endif 9057 9058 #ifdef BCM_MAVERICK2_SUPPORT 9059 if (SOC_IS_MAVERICK2(unit)) { 9060 rv = _bcm_esw_time_maverick2_synce_clock_get(unit, clk_src, divisor); 9061 } 9062 #endif 9063 9064 #ifdef BCM_HELIX5_SUPPORT 9065 if (SOC_IS_HELIX5(unit)) { 9066 rv = _bcm_esw_time_hx5_synce_clock_get(unit, clk_src, divisor); 9067 } 9068 #endif 9069 9070 #ifdef BCM_GREYHOUND2_SUPPORT 9071 if (SOC_IS_GREYHOUND2(unit)) { 9072 rv = _bcm_esw_time_gh2_synce_clock_get(unit, clk_src, divisor); 9073 } 9074 #endif 9075 9076 #ifdef BCM_MONTEREY_SUPPORT 9077 if (SOC_IS_MONTEREY(unit)) { 9078 rv = _bcm_esw_time_monterey_synce_clock_get(unit, clk_src, divisor); 9079 } 9080 #endif 9081 return rv; 9082 } 9083 9084 /* 9085 * Function: 9086 * bcm_esw_time_synce_clock_set 9087 * Purpose: 9088 * Set syncE divisor setting 9089 * Parameters: 9090 * unit - (IN) Unit number. 9091 * clk_src - (IN) clock source type (Primary, Secondary) 9092 * divisor - (IN) divisor setting. 9093 * Returns: 9094 * BCM_E_xxx 9095 * Notes: 9096 */ 9097 int 9098 bcm_esw_time_synce_clock_set(int unit, 9099 bcm_time_synce_clock_src_type_t clk_src, 9100 bcm_time_synce_divisor_setting_t *divisor) 9101 { 9102 int rv = BCM_E_UNAVAIL; 9103 9104 if (soc_feature(unit, soc_feature_time_synce_divisor_setting)) { 9105 #ifdef BCM_TRIDENT2PLUS_SUPPORT 9106 if (SOC_IS_TD2P_TT2P(unit) && !SOC_IS_TOMAHAWKX(unit) && !SOC_IS_APACHE(unit)) { 9107 rv = _bcm_esw_time_td2p_synce_clock_set(unit, clk_src, divisor); 9108 } 9109 #endif 9110 9111 #ifdef BCM_GREYHOUND_SUPPORT 9112 if (SOC_IS_GREYHOUND(unit)) { 9113 rv = _bcm_esw_time_gh_synce_clock_set(unit, clk_src, divisor); 9114 } 9115 #endif 9116 9117 #ifdef BCM_HELIX4_SUPPORT 9118 if (SOC_IS_HELIX4(unit)) { 9119 rv = _bcm_esw_time_hx4_synce_clock_set(unit, clk_src, divisor); 9120 } 9121 #endif 9122 9123 } 9124 #ifdef BCM_KATANA_SUPPORT 9125 if (SOC_IS_KATANA(unit)) { 9126 rv = _bcm_esw_time_katana_synce_clock_set(unit, clk_src, divisor); 9127 } 9128 #endif 9129 9130 #ifdef BCM_TOMAHAWK_SUPPORT 9131 if (SOC_IS_TOMAHAWKX(unit)) { 9132 rv = _bcm_esw_time_tomahawkx_synce_clock_set_by_port(unit, clk_src, divisor); 9133 } 9134 #endif 9135 9136 #ifdef BCM_SABER2_SUPPORT 9137 if (SOC_IS_SABER2(unit)) { 9138 rv = _bcm_esw_time_saber2_synce_clock_set(unit, clk_src, divisor); 9139 } 9140 #endif 9141 9142 #ifdef BCM_METROLITE_SUPPORT 9143 if (SOC_IS_METROLITE(unit)) { 9144 rv = _bcm_esw_time_metrolite_synce_clock_set(unit, clk_src, divisor); 9145 } 9146 #endif 9147 9148 #ifdef BCM_TRIDENT3_SUPPORT 9149 if (SOC_IS_TRIDENT3(unit)) { 9150 rv = _bcm_esw_time_trident3_synce_clock_set(unit, clk_src, divisor); 9151 } 9152 #endif 9153 9154 #ifdef BCM_APACHE_SUPPORT 9155 if (SOC_IS_APACHE(unit) && !SOC_IS_MONTEREY(unit)) { 9156 rv = _bcm_esw_time_apachex_synce_clock_set(unit, clk_src, divisor); 9157 } 9158 #endif /* BCM_APACHE_SUPPORT */ 9159 9160 #ifdef BCM_MAVERICK2_SUPPORT 9161 if (SOC_IS_MAVERICK2(unit)) { 9162 rv = _bcm_esw_time_maverick2_synce_clock_set(unit, clk_src, divisor); 9163 } 9164 #endif 9165 9166 #ifdef BCM_HELIX5_SUPPORT 9167 if (SOC_IS_HELIX5(unit)) { 9168 rv = _bcm_esw_time_hx5_synce_clock_set(unit, clk_src, divisor); 9169 } 9170 #endif 9171 9172 #ifdef BCM_GREYHOUND2_SUPPORT 9173 if (SOC_IS_GREYHOUND2(unit)) { 9174 rv = _bcm_esw_time_gh2_synce_clock_set(unit, clk_src, divisor); 9175 } 9176 #endif 9177 9178 #ifdef BCM_MONTEREY_SUPPORT 9179 if (SOC_IS_MONTEREY(unit)) { 9180 rv = _bcm_esw_time_monterey_synce_clock_set(unit, clk_src, divisor); 9181 } 9182 #endif 9183 9184 #ifdef BCM_ESMC_EXTDPLL_SUPPORT 9185 if (rv == BCM_E_NONE) { 9186 rv = bcm_extdpll_esmc_select_port_set(unit, divisor->index, clk_src); 9187 /* Unsquelch the CDR MUX output, if it was squelched earlier */ 9188 rv = _bcm_esw_time_synce_clock_source_squelch_set(unit, clk_src, 0); 9189 } 9190 #endif /* BCM_ESMC_EXTDPLL_SUPPORT */ 9191 9192 return rv; 9193 } 9194 9195 /* 9196 * Function: 9197 * _bcm_esw_time_synce_clock_source_control_get 9198 * Purpose: 9199 * Get syncE clock source control option 9200 * Parameters: 9201 * unit - (IN) Unit number. 9202 * clk_src - (IN) clock source 9203 * squelch - (OUT) squelch value 9204 * Returns: 9205 * BCM_E_xxx 9206 * Notes: 9207 */ 9208 STATIC int 9209 _bcm_esw_time_synce_clock_source_squelch_get(int unit, 9210 bcm_time_synce_clock_src_type_t clk_src, 9211 int *squelch) 9212 { 9213 int rv = BCM_E_NONE; 9214 uint32 regval; 9215 9216 COMPILER_REFERENCE(regval); 9217 COMPILER_REFERENCE(rv); 9218 9219 if (!squelch) return rv; 9220 #if defined(BCM_TOMAHAWK3_SUPPORT) 9221 if (SOC_IS_TOMAHAWK3(unit) || SOC_IS_TOMAHAWK(unit)) { 9222 soc_reg_t synce_ctrl = TOP_SYNCE_CTRLr; 9223 soc_field_t l1_rcvd_sw_ovwr_valid = L1_RCVD_SW_OVWR_VALIDf; 9224 soc_field_t l1_rcvd_sw_ovwr_enable = L1_RCVD_SW_OVWR_ENf; 9225 9226 if (SOC_IS_TOMAHAWK(unit)) { 9227 synce_ctrl = TOP_MISC_CONTROLr; 9228 } 9229 9230 if (clk_src == bcmTimeSynceClockSourceSecondary) { 9231 l1_rcvd_sw_ovwr_valid = L1_RCVD_SW_OVWR_BKUP_VALIDf; 9232 l1_rcvd_sw_ovwr_enable = L1_RCVD_SW_OVWR_ENf; 9233 } 9234 soc_reg32_get(unit, synce_ctrl, REG_PORT_ANY, 0, ®val); 9235 9236 /* check if software overwrite enabled or not */ 9237 if(soc_reg_field_get(unit, synce_ctrl, regval, l1_rcvd_sw_ovwr_enable)) { 9238 /* check if we have squelch or supressed */ 9239 *squelch = soc_reg_field_get(unit, synce_ctrl, regval, l1_rcvd_sw_ovwr_valid) ? 0 : 1; 9240 } else { 9241 *squelch = 0; 9242 } 9243 return rv; 9244 } 9245 #endif 9246 9247 switch(clk_src) { 9248 case bcmTimeSynceClockSourcePrimary: 9249 #if defined(BCM_SABER2_SUPPORT) 9250 if (SOC_IS_SABER2(unit)) { 9251 READ_TOP_MISC_CONTROL_1r(unit, ®val); 9252 *squelch = soc_reg_field_get(unit, TOP_MISC_CONTROL_1r, regval, 9253 L1_RCVD_SW_OVWR_ENf); 9254 } 9255 #endif /* defined(BCM_SABER2_SUPPORT) */ 9256 9257 #if defined(BCM_METROLITE_SUPPORT) 9258 if (SOC_IS_METROLITE(unit)) { 9259 READ_TOP_MISC_CONTROL_1r(unit, ®val); 9260 *squelch = soc_reg_field_get(unit, TOP_MISC_CONTROL_1r, regval, 9261 L1_RCVD_SW_OVWR_ENf); 9262 } 9263 #endif /* defined(BCM_METROLITE_SUPPORT) */ 9264 9265 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 9266 if (SOC_IS_TD2P_TT2P(unit)) { 9267 READ_TOP_MISC_CONTROLr(unit, ®val); 9268 *squelch = !soc_reg_field_get(unit, TOP_MISC_CONTROLr, regval, 9269 L1_RCVD_CLK_RSTNf); 9270 } 9271 #endif 9272 9273 #if defined(BCM_GREYHOUND_SUPPORT) 9274 if (SOC_IS_GREYHOUND(unit)) { 9275 READ_TOP_MISC_CONTROL_2r(unit, ®val); 9276 *squelch = soc_reg_field_get(unit, TOP_MISC_CONTROL_2r, regval, 9277 L1_RCVD_SW_OVWR_ENf); 9278 } 9279 #endif /* defined(BCM_GREYHOUND_SUPPORT) */ 9280 9281 9282 #if defined(BCM_HELIX4_SUPPORT) 9283 if (SOC_IS_HELIX4(unit)) { 9284 READ_TOP_MISC_CONTROL_1r(unit, ®val); 9285 *squelch = soc_reg_field_get(unit, TOP_MISC_CONTROL_1r, regval, 9286 L1_RCVD_SW_OVWR_ENf); 9287 } 9288 #endif /* defined(BCM_HELIX4_SUPPORT) */ 9289 9290 #if defined(BCM_TRIDENT3_SUPPORT) 9291 if (SOC_IS_TRIDENT3(unit)) { 9292 READ_TOP_MISC_CONTROL_2r(unit, ®val); 9293 *squelch = soc_reg_field_get(unit, TOP_MISC_CONTROL_2r, regval, 9294 L1_RCVD_SW_OVWR_ENf); 9295 } 9296 #endif /* defined(BCM_TRIDENT3_SUPPORT) */ 9297 9298 #if defined(BCM_APACHE_SUPPORT) 9299 if (SOC_IS_APACHE(unit)) { /* Apache and Monterey */ 9300 READ_TOP_MISC_CONTROLr(unit, ®val); 9301 *squelch = soc_reg_field_get(unit, TOP_MISC_CONTROLr, regval, 9302 L1_RCVD_SW_OVWR_ENf); 9303 } 9304 #endif /* defined(BCM_APACHE_SUPPORT) */ 9305 9306 9307 #if defined(BCM_TOMAHAWK2_SUPPORT) 9308 if (SOC_IS_TOMAHAWK2(unit)) { 9309 READ_TOP_MISC_CONTROLr(unit, ®val); 9310 *squelch = soc_reg_field_get(unit, TOP_MISC_CONTROLr, regval, 9311 L1_RCVD_SW_OVWR_ENf); 9312 } 9313 #endif /* defined(BCM_TOMAHAWK2_SUPPORT) */ 9314 9315 #if defined(BCM_MAVERICK2_SUPPORT) 9316 if (SOC_IS_MAVERICK2(unit)) { 9317 READ_TOP_MISC_CONTROL_2r(unit, ®val); 9318 *squelch = soc_reg_field_get(unit, TOP_MISC_CONTROL_2r, regval, 9319 L1_RCVD_SW_OVWR_ENf); 9320 } 9321 #endif /* defined(BCM_MAVERICK2_SUPPORT) */ 9322 9323 #if defined(BCM_HELIX5_SUPPORT) 9324 if (SOC_IS_HELIX5(unit)) { 9325 READ_TOP_MISC_CONTROL_2r(unit, ®val); 9326 *squelch = soc_reg_field_get(unit, TOP_MISC_CONTROL_2r, regval, 9327 L1_RCVD_SW_OVWR_ENf); 9328 } 9329 #endif /* defined(BCM_HELIX5_SUPPORT) */ 9330 9331 #if defined(BCM_GREYHOUND2_SUPPORT) 9332 if (SOC_IS_GREYHOUND2(unit)) { 9333 READ_TOP_L1_RCVD_CLK_CONTROLr(unit, ®val); 9334 *squelch = soc_reg_field_get(unit, TOP_L1_RCVD_CLK_CONTROLr, regval, 9335 L1_RCVD_SW_OVWR_ENf); 9336 } 9337 #endif /* defined(BCM_GREYHOUND2_SUPPORT) */ 9338 break; 9339 9340 case bcmTimeSynceClockSourceSecondary: 9341 #if defined(BCM_SABER2_SUPPORT) 9342 if (SOC_IS_SABER2(unit)) { 9343 READ_TOP_MISC_CONTROL_1r(unit, ®val); 9344 *squelch = soc_reg_field_get(unit, TOP_MISC_CONTROL_1r, regval, 9345 L1_RCVD_SW_OVWR_ENf); 9346 } 9347 #endif /* defined(BCM_SABER2_SUPPORT) */ 9348 9349 #if defined(BCM_METROLITE_SUPPORT) 9350 if (SOC_IS_METROLITE(unit)) { 9351 READ_TOP_MISC_CONTROL_1r(unit, ®val); 9352 *squelch = soc_reg_field_get(unit, TOP_MISC_CONTROL_1r, regval, 9353 L1_RCVD_SW_OVWR_ENf); 9354 } 9355 #endif /* defined(BCM_METROLITE_SUPPORT) */ 9356 9357 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 9358 if (SOC_IS_TD2P_TT2P(unit) && !SOC_IS_APACHE(unit)) { 9359 READ_TOP_MISC_CONTROLr(unit, ®val); 9360 *squelch = !soc_reg_field_get(unit, TOP_MISC_CONTROLr, regval, 9361 L1_RCVD_CLK_BKUP_RSTNf); 9362 } 9363 #endif 9364 9365 #if defined(BCM_GREYHOUND_SUPPORT) 9366 if (SOC_IS_GREYHOUND(unit)) { 9367 READ_TOP_MISC_CONTROL_2r(unit, ®val); 9368 *squelch = soc_reg_field_get(unit, TOP_MISC_CONTROL_2r, regval, 9369 L1_RCVD_SW_OVWR_ENf); 9370 } 9371 #endif /* defined(BCM_HELIX4_SUPPORT) */ 9372 9373 #if defined(BCM_HELIX4_SUPPORT) 9374 if (SOC_IS_HELIX4(unit)) { 9375 READ_TOP_MISC_CONTROL_1r(unit, ®val); 9376 *squelch = soc_reg_field_get(unit, TOP_MISC_CONTROL_1r, regval, 9377 L1_RCVD_SW_OVWR_ENf); 9378 } 9379 #endif /* defined(BCM_HELIX4_SUPPORT) */ 9380 9381 #if defined(BCM_TRIDENT3_SUPPORT) 9382 if (SOC_IS_TRIDENT3(unit)) { 9383 READ_TOP_MISC_CONTROL_2r(unit, ®val); 9384 *squelch = soc_reg_field_get(unit, TOP_MISC_CONTROL_2r, regval, 9385 L1_RCVD_SW_OVWR_ENf); 9386 } 9387 #endif /* defined(BCM_TRIDENT3_SUPPORT) */ 9388 9389 #if defined(BCM_APACHE_SUPPORT) 9390 if (SOC_IS_APACHE(unit)) { 9391 READ_TOP_MISC_CONTROLr(unit, ®val); 9392 *squelch = soc_reg_field_get(unit, TOP_MISC_CONTROLr, regval, 9393 L1_RCVD_SW_OVWR_ENf); 9394 } 9395 #endif /* defined(BCM_APACHE_SUPPORT) */ 9396 9397 #if defined(BCM_TOMAHAWK2_SUPPORT) 9398 if (SOC_IS_TOMAHAWK2(unit)) { 9399 READ_TOP_MISC_CONTROLr(unit, ®val); 9400 *squelch = soc_reg_field_get(unit, TOP_MISC_CONTROLr, regval, 9401 L1_RCVD_SW_OVWR_ENf); 9402 } 9403 #endif /* defined(BCM_TOMAHAWK2_SUPPORT) */ 9404 9405 #if defined(BCM_MAVERICK2_SUPPORT) 9406 if (SOC_IS_MAVERICK2(unit)) { 9407 READ_TOP_MISC_CONTROL_2r(unit, ®val); 9408 *squelch = soc_reg_field_get(unit, TOP_MISC_CONTROL_2r, regval, 9409 L1_RCVD_SW_OVWR_ENf); 9410 } 9411 #endif /* defined(BCM_MAVERICK2_SUPPORT) */ 9412 9413 #if defined(BCM_HELIX5_SUPPORT) 9414 if (SOC_IS_HELIX5(unit)) { 9415 READ_TOP_MISC_CONTROL_2r(unit, ®val); 9416 *squelch = soc_reg_field_get(unit, TOP_MISC_CONTROL_2r, regval, 9417 L1_RCVD_SW_OVWR_ENf); 9418 } 9419 #endif /* defined(BCM_HELIX5_SUPPORT) */ 9420 9421 #if defined(BCM_GREYHOUND2_SUPPORT) 9422 if (SOC_IS_GREYHOUND2(unit)) { 9423 READ_TOP_L1_RCVD_CLK_CONTROLr(unit, ®val); 9424 *squelch = soc_reg_field_get(unit, TOP_L1_RCVD_CLK_CONTROLr, regval, 9425 L1_RCVD_SW_OVWR_ENf); 9426 } 9427 #endif /* defined(BCM_GREYHOUND2_SUPPORT) */ 9428 break; 9429 default: 9430 return BCM_E_PARAM; 9431 } 9432 9433 return rv; 9434 } 9435 9436 9437 /* 9438 * Function: 9439 * _bcm_esw_time_synce_clock_source_frequency_get 9440 * Purpose: 9441 * Get syncE clock source squelch option 9442 * Parameters: 9443 * unit - (IN) Unit number. 9444 * clk_src - (IN) clock source type (Primary, Secondary) 9445 * frequency - (OUT) synce clock source frequency. 9446 * Returns: 9447 * BCM_E_xxx 9448 * Notes: 9449 */ 9450 STATIC int 9451 _bcm_esw_time_synce_clock_source_frequency_get(int unit, 9452 bcm_time_synce_clock_source_config_t *clk_src_config, 9453 int *frequency) 9454 9455 { 9456 int rv = BCM_E_NONE; 9457 bcm_time_synce_divisor_setting_t div_out; 9458 bcm_time_synce_divisor_setting_t_init(&div_out); 9459 9460 COMPILER_REFERENCE(rv); 9461 rv = bcm_esw_time_synce_clock_get(unit, clk_src_config->clk_src, &div_out); 9462 if (div_out.input_src == bcmTimeSynceInputSourceTypePort) { 9463 clk_src_config->port = div_out.index; 9464 } else { 9465 clk_src_config->pll_index = div_out.index; 9466 } 9467 9468 if (IS_MANAGEMENT_PORT(unit, clk_src_config->port) && clk_src_config->input_src == bcmTimeSynceInputSourceTypePort) { 9469 return BCM_E_PARAM; 9470 } 9471 9472 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 9473 if(SOC_IS_TD2P_TT2P(unit) && !SOC_IS_TOMAHAWK(unit) && !SOC_IS_APACHE(unit)) { 9474 if(div_out.stage0_mode == bcmTimeSynceModeSDMFracDiv && div_out.stage0_sdm_whole == 20 && 9475 div_out.stage0_sdm_frac == 160) { 9476 *frequency = bcmTimeSyncE25MHz; 9477 } else if (div_out.stage0_mode == bcmTimeSynceModeBypass && div_out.stage1_div == bcmTimeSynceStage1Div11) { 9478 if (div_out.stage0_sdm_whole == 23) { 9479 *frequency = bcmTimeSyncE23MHz; 9480 } else if (div_out.stage0_sdm_whole == 28) { 9481 *frequency = bcmTimeSyncE28MHz; 9482 } else if (div_out.stage0_sdm_whole == 46) { 9483 *frequency = bcmTimeSyncE46MHz; 9484 } else { 9485 return BCM_E_PARAM; 9486 } 9487 } else { 9488 return BCM_E_PARAM; 9489 } 9490 } 9491 #endif /* BCM_TRIDENT2PLUS_SUPPORT */ 9492 9493 #if defined(BCM_GREYHOUND_SUPPORT) 9494 if (SOC_IS_GREYHOUND(unit)) { 9495 /* Helix4 : 9496 stage0_mode=0 -> pass-through mode 9497 stage0_mode=1 -> Div_by_5(25MHz) mode 9498 stage0_mode=2 -> Div_by_10(31.25MHz) mode 9499 stage0_mode=3 -> Div_by_2(156.25MHz) mode 9500 */ 9501 *frequency = div_out.stage0_mode; 9502 } 9503 #endif /* BCM_GREYHOUND_SUPPORT */ 9504 9505 #if defined(BCM_HELIX4_SUPPORT) 9506 if (SOC_IS_HELIX4(unit)) { 9507 /* Helix4 : 9508 stage0_mode=0 -> pass-through mode 9509 stage0_mode=1 -> Div_by_5(25MHz) mode 9510 stage0_mode=2 -> Div_by_10(31.25MHz) mode 9511 stage0_mode=3 -> Div_by_2(156.25MHz) mode 9512 */ 9513 *frequency = div_out.stage0_mode; 9514 } 9515 #endif /* BCM_HELIX4_SUPPORT */ 9516 9517 #if defined(BCM_KATANA_SUPPORT) 9518 if (SOC_IS_KATANA(unit)) { 9519 /* Katana */ 9520 *frequency = bcmTimeSyncE125MHz; 9521 } 9522 #endif /* BCM_KATANA_SUPPORT */ 9523 9524 #if defined(BCM_GREYHOUND2_SUPPORT) 9525 if (SOC_IS_GREYHOUND2(unit)) { 9526 /* GH2 */ 9527 if (div_out.input_src == bcmTimeSynceInputSourceTypePort) { 9528 phy_ctrl_t *pc; 9529 phymod_dispatch_type_t dispatch_type = phymodDispatchTypeInvalid; 9530 9531 pc = INT_PHY_SW_STATE(unit, clk_src_config->port); 9532 if (pc == NULL) { 9533 return BCM_E_FAIL; 9534 } 9535 dispatch_type = pc->phymod_ctrl.phy[0]->pm_phy.type; 9536 9537 if ((div_out.stage0_mode == bcmTimeSynceModeSDMFracDiv) && 9538 (div_out.stage1_div == bcmTimeSynceStage1Div1)) { 9539 if (dispatch_type == phymodDispatchTypeTsce_dpll || dispatch_type == phymodDispatchTypeTscf ) { 9540 *frequency = bcmTimeSyncE25MHz; 9541 } 9542 } else { 9543 if (dispatch_type == phymodDispatchTypeViper) { 9544 *frequency = bcmTimeSyncE125MHz; 9545 } 9546 } 9547 } else { 9548 return BCM_E_PARAM; 9549 } 9550 } 9551 #endif /* BCM_GREYHOUND2_SUPPORT */ 9552 9553 #if defined(BCM_SABER2_SUPPORT) 9554 if (SOC_IS_SABER2(unit)) { 9555 rv = _bcm_esw_time_saber2_synce_clock_get(unit, clk_src_config->clk_src, &div_out); 9556 if (rv == BCM_E_NONE) { 9557 if (div_out.input_src == bcmTimeSynceInputSourceTypePort) { 9558 clk_src_config->port = div_out.index; 9559 if (div_out.stage0_mode == bcmTimeSynceModeBypass) 9560 *frequency = bcmTimeSyncE125MHz; 9561 else 9562 *frequency = bcmTimeSyncE25MHz; 9563 } else { 9564 clk_src_config->pll_index = div_out.index; 9565 *frequency = bcmTimeSyncE125MHz; 9566 } 9567 } 9568 } 9569 #endif /* BCM_SABER2_SUPPORT */ 9570 9571 #if defined(BCM_METROLITE_SUPPORT) 9572 if (SOC_IS_METROLITE(unit)) { 9573 rv = _bcm_esw_time_metrolite_synce_clock_get(unit, clk_src_config->clk_src, &div_out); 9574 if (rv == BCM_E_NONE) { 9575 if (div_out.input_src == bcmTimeSynceInputSourceTypePort) { 9576 clk_src_config->port = div_out.index; 9577 if (div_out.stage0_mode == bcmTimeSynceModeBypass) 9578 *frequency = bcmTimeSyncE125MHz; 9579 else 9580 *frequency = bcmTimeSyncE25MHz; 9581 } else { 9582 clk_src_config->pll_index = div_out.index; 9583 *frequency = bcmTimeSyncE125MHz; 9584 } 9585 } 9586 } 9587 #endif /* BCM_METROLITE_SUPPORT */ 9588 9589 #if defined(BCM_HELIX5_SUPPORT) 9590 if (SOC_IS_HELIX5(unit)) { 9591 /* HELIX5 */ 9592 if (div_out.input_src == bcmTimeSynceInputSourceTypePLL) { 9593 *frequency = bcmTimeSyncE125MHz; 9594 clk_src_config->input_src = div_out.input_src; 9595 } 9596 } 9597 #endif /* BCM_HELIX5_SUPPORT*/ 9598 9599 #if defined(BCM_MONTEREY_SUPPORT) 9600 if (SOC_IS_MONTEREY(unit)) { 9601 if (div_out.input_src == bcmTimeSynceInputSourceTypePLL) { 9602 *frequency = bcmTimeSyncE125MHz; 9603 clk_src_config->pll_index = div_out.index; 9604 clk_src_config->input_src = div_out.input_src; 9605 } 9606 } 9607 #endif /* BCM_MONTEREY_SUPPORT */ 9608 9609 #if defined(BCM_TOMAHAWK_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_APACHE_SUPPORT) || defined(BCM_MAVERICK2_SUPPORT) || defined(BCM_HELIX5_SUPPORT) || \ 9610 defined(BCM_MONTEREY_SUPPORT) 9611 9612 if (div_out.input_src == bcmTimeSynceInputSourceTypePort) { 9613 9614 if (SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT3(unit) || SOC_IS_APACHE(unit) || SOC_IS_MAVERICK2(unit) || SOC_IS_HELIX5(unit) || SOC_IS_MONTEREY(unit)) { 9615 /* tomahawk & TD3 */ 9616 if ((div_out.stage0_mode == bcmTimeSynceModeSDMFracDiv) && 9617 (div_out.stage1_div == bcmTimeSynceStage1Div1)) { 9618 9619 int port_speed = 0; /* speed specified in mbps*/ 9620 uint32 sdm_divisor = 0; 9621 phymod_dispatch_type_t dispatch_type = phymodDispatchTypeInvalid; 9622 9623 BCM_IF_ERROR_RETURN(bcm_esw_port_speed_get(unit, clk_src_config->port, &port_speed)); 9624 sdm_divisor = (div_out.stage0_sdm_whole <<8) | div_out.stage0_sdm_frac; 9625 9626 dispatch_type = _bcm_time_synce_tsc_phymod_dispatch_type_get(unit, clk_src_config->port); 9627 9628 if ((dispatch_type == phymodDispatchTypeTsce) || 9629 (dispatch_type == phymodDispatchTypeTsce16)) { 9630 if (!IS_HG_PORT(unit, clk_src_config->port)) { 9631 /* regular port */ 9632 if (sdm_divisor == 0x14a0) { 9633 *frequency = bcmTimeSyncE25MHz; 9634 } 9635 } else { 9636 /* hi gig port */ 9637 if (sdm_divisor == 0x15e0) { 9638 *frequency = bcmTimeSyncE25MHz; 9639 } 9640 } 9641 } else if (dispatch_type == phymodDispatchTypeTscf) { 9642 switch (port_speed) { 9643 case 100: 9644 /* 1G ports - VCO 25.78125 */ 9645 if (sdm_divisor == 0x19c8) { 9646 *frequency = bcmTimeSyncE25MHz; 9647 } else { 9648 return BCM_E_PARAM; 9649 } 9650 break; 9651 case 10000: 9652 case 40000: 9653 /* 10G or 40G ports - VCO 20.625 */ 9654 if (sdm_divisor == 0xa50) { 9655 *frequency = bcmTimeSyncE25MHz; 9656 } else { 9657 return BCM_E_PARAM; 9658 } 9659 break; 9660 case 25000: 9661 case 100000: 9662 /* 100G ports - VCO 25.78125*/ 9663 if (sdm_divisor == 0x19c8) { 9664 *frequency = bcmTimeSyncE25MHz; 9665 } else { 9666 return BCM_E_PARAM; 9667 } 9668 break; 9669 case 11000: 9670 /* 11G HG ports -VCO 21.875 */ 9671 if (sdm_divisor == 0xaf0) { 9672 *frequency = bcmTimeSyncE25MHz; 9673 } else { 9674 return BCM_E_PARAM; 9675 } 9676 break; 9677 case 106000: 9678 /* 106G HG ports -VCO 21.875 */ 9679 if (sdm_divisor == 0x1b58) { 9680 *frequency = bcmTimeSyncE25MHz; 9681 } else { 9682 return BCM_E_PARAM; 9683 } 9684 break; 9685 default: 9686 return BCM_E_PARAM; 9687 break; 9688 } 9689 } else if (dispatch_type == phymodDispatchTypeTscf16) { 9690 switch (port_speed) { 9691 case 100: 9692 /* 1G ports - VCO 25.78125 */ 9693 if (sdm_divisor == 0x19c8) { 9694 *frequency = bcmTimeSyncE25MHz; 9695 } else { 9696 return BCM_E_PARAM; 9697 } 9698 break; 9699 case 10000: 9700 case 40000: 9701 /* 10G or 40G ports - VCO 20.625 */ 9702 if (sdm_divisor == 0xa50) { 9703 *frequency = bcmTimeSyncE25MHz; 9704 } else { 9705 return BCM_E_PARAM; 9706 } 9707 break; 9708 case 25000: 9709 case 100000: 9710 /* 100G ports - VCO 25.78125*/ 9711 if (sdm_divisor == 0x19c8) { 9712 *frequency = bcmTimeSyncE25MHz; 9713 } else { 9714 return BCM_E_PARAM; 9715 } 9716 break; 9717 case 11000: 9718 /* 11G HG ports -VCO 21.875 */ 9719 if (sdm_divisor == 0xaf0) { 9720 *frequency = bcmTimeSyncE25MHz; 9721 } else { 9722 return BCM_E_PARAM; 9723 } 9724 break; 9725 case 106000: 9726 /* 106G HG ports -VCO 21.875 */ 9727 if (sdm_divisor == 0x1b58) { 9728 *frequency = bcmTimeSyncE25MHz; 9729 } else { 9730 return BCM_E_PARAM; 9731 } 9732 break; 9733 default: 9734 return BCM_E_PARAM; 9735 break; 9736 } 9737 } else if (dispatch_type == phymodDispatchTypeTscbh) { 9738 #ifdef PORTMOD_SUPPORT 9739 if (SOC_USE_PORTCTRL(unit)) { 9740 portmod_port_synce_clk_ctrl_t config; 9741 portmod_port_synce_clk_ctrl_t_init(unit, &config); 9742 9743 SOC_IF_ERROR_RETURN(portmod_port_synce_clk_ctrl_get(unit, clk_src_config->port, &config)); 9744 if ((config.stg0_mode == 0x2) && (config.stg1_mode == 0x0)) { 9745 *frequency = bcmTimeSyncE25MHz; 9746 } 9747 } 9748 #endif 9749 } else if (dispatch_type == phymodDispatchTypeTsce_dpll) { 9750 switch (port_speed) { 9751 case 1000: 9752 case 10000: 9753 case 20000: 9754 case 40000: 9755 if (sdm_divisor == 0x14a0) { 9756 *frequency = bcmTimeSyncE25MHz; 9757 } else if (sdm_divisor == 0x4200) { 9758 *frequency = bcmTimeSyncE7MHz; 9759 } else if (sdm_divisor == 0x2940) { 9760 *frequency = bcmTimeSyncE12MHz; 9761 } else if (sdm_divisor == 0x1080) { 9762 *frequency = bcmTimeSyncE31MHz; 9763 } else if (sdm_divisor == 0xDC0) { 9764 *frequency = bcmTimeSyncE37MHz; 9765 } else { 9766 return BCM_E_PARAM; 9767 } 9768 break; 9769 default: 9770 return BCM_E_PARAM; 9771 } 9772 } else if (dispatch_type == phymodDispatchTypeTscf_gen3) { 9773 switch (port_speed) { 9774 case 1000: 9775 if (sdm_divisor == 0x14A0) { 9776 *frequency = bcmTimeSyncE25MHz; 9777 } else if (sdm_divisor == 0x4200) { 9778 *frequency = bcmTimeSyncE7MHz; 9779 } else if (sdm_divisor == 0x2940) { 9780 *frequency = bcmTimeSyncE12MHz; 9781 } else if (sdm_divisor == 0x1080) { 9782 *frequency = bcmTimeSyncE31MHz; 9783 } else if (sdm_divisor == 0xDC0) { 9784 *frequency = bcmTimeSyncE37MHz; 9785 } else { 9786 return BCM_E_PARAM; 9787 } 9788 break; 9789 case 10000: 9790 case 20000: 9791 case 40000: 9792 if (sdm_divisor == 0xA50) { 9793 *frequency = bcmTimeSyncE25MHz; 9794 } else if (sdm_divisor == 0x2100) { 9795 *frequency = bcmTimeSyncE7MHz; 9796 } else if (sdm_divisor == 0x14A0) { 9797 *frequency = bcmTimeSyncE12MHz; 9798 } else if (sdm_divisor == 0x840) { 9799 *frequency = bcmTimeSyncE31MHz; 9800 } else if (sdm_divisor == 0x6E0) { 9801 *frequency = bcmTimeSyncE37MHz; 9802 } else { 9803 return BCM_E_PARAM; 9804 } 9805 break; 9806 case 25000: 9807 case 50000: 9808 case 100000: 9809 if (sdm_divisor == 0x19C8) { 9810 *frequency = bcmTimeSyncE25MHz; 9811 } else if (sdm_divisor == 0x5280) { 9812 *frequency = bcmTimeSyncE7MHz; 9813 } else if (sdm_divisor == 0x3390) { 9814 *frequency = bcmTimeSyncE12MHz; 9815 } else if (sdm_divisor == 0x14A0) { 9816 *frequency = bcmTimeSyncE31MHz; 9817 } else if (sdm_divisor == 0x1130) { 9818 *frequency = bcmTimeSyncE37MHz; 9819 } else { 9820 return BCM_E_PARAM; 9821 } 9822 break; 9823 default: 9824 cli_out("not supported port_speed:%d\n", (int)port_speed); 9825 return BCM_E_PARAM; 9826 } 9827 } 9828 } else { 9829 return BCM_E_PARAM; 9830 } 9831 } 9832 } 9833 #endif /* BCM_TOMAHAWK_SUPPORT || BCM_TRIDENT3_SUPPORT */ 9834 9835 return rv; 9836 } 9837 9838 /* 9839 * Function: 9840 * bcm_esw_time_synce_clock_source_control_get 9841 * Purpose: 9842 * Get syncE clock source control option 9843 * Parameters: 9844 * unit - (IN) Unit number. 9845 * clk_src - (IN) clock source 9846 * vlaue - (OUT) control value 9847 * Returns: 9848 * BCM_E_xxx 9849 * Notes: New wrapper API to support synce operation 9850 */ 9851 int 9852 bcm_esw_time_synce_clock_source_control_get(int unit, 9853 bcm_time_synce_clock_source_config_t *clk_src_config, 9854 bcm_time_synce_clock_source_control_t control, 9855 int *value) 9856 { 9857 int rv = BCM_E_UNAVAIL; 9858 9859 switch (control) { 9860 case bcmTimeSynceClockSourceControlSquelch: 9861 rv = _bcm_esw_time_synce_clock_source_squelch_get(unit, clk_src_config->clk_src, value); 9862 break; 9863 case bcmTimeSynceClockSourceControlFrequency: 9864 rv = _bcm_esw_time_synce_clock_source_frequency_get(unit, clk_src_config, value); 9865 break; 9866 default: 9867 return BCM_E_PARAM; 9868 } 9869 9870 return rv; 9871 9872 } 9873 9874 /* 9875 * Function: 9876 * _bcm_esw_time_synce_clock_source_squelch_set 9877 * Purpose: 9878 * Set syncE clock source squelch option 9879 * Parameters: 9880 * unit - (IN) Unit number. 9881 * clk_src - (IN) clock source type (Primary, Secondary) 9882 * squelch - (IN) synce clock source squelch setting 1 to enable , 0 to disable. 9883 * Returns: 9884 * BCM_E_xxx 9885 * Notes: 9886 */ 9887 STATIC int 9888 _bcm_esw_time_synce_clock_source_squelch_set(int unit, 9889 bcm_time_synce_clock_src_type_t clk_src, 9890 int squelch) 9891 9892 { 9893 int rv = BCM_E_NONE; 9894 9895 COMPILER_REFERENCE(rv); 9896 #if defined(BCM_TOMAHAWK3_SUPPORT) 9897 if (SOC_IS_TOMAHAWK3(unit) || SOC_IS_TOMAHAWK(unit)) { 9898 soc_reg_t synce_ctrl = TOP_SYNCE_CTRLr; 9899 soc_field_t l1_rcvd_sw_ovwr_valid = L1_RCVD_SW_OVWR_VALIDf; 9900 soc_field_t l1_rcvd_sw_ovwr_enable = L1_RCVD_SW_OVWR_ENf; 9901 9902 if (SOC_IS_TOMAHAWK(unit)) { 9903 synce_ctrl = TOP_MISC_CONTROLr; 9904 } 9905 9906 if (clk_src == bcmTimeSynceClockSourceSecondary) { 9907 l1_rcvd_sw_ovwr_valid = L1_RCVD_SW_OVWR_BKUP_VALIDf; 9908 l1_rcvd_sw_ovwr_enable = L1_RCVD_SW_OVWR_ENf; 9909 } 9910 SOC_IF_ERROR_RETURN 9911 (soc_reg_field32_modify(unit, synce_ctrl, REG_PORT_ANY, 9912 l1_rcvd_sw_ovwr_valid, ((squelch) ? 0 : 1))); 9913 SOC_IF_ERROR_RETURN 9914 (soc_reg_field32_modify(unit, synce_ctrl, REG_PORT_ANY, 9915 l1_rcvd_sw_ovwr_enable, ((squelch) ? 1 : 0))); 9916 return rv; 9917 } 9918 #endif 9919 9920 switch(clk_src) { 9921 case bcmTimeSynceClockSourcePrimary: 9922 #if defined(BCM_TOMAHAWK2_SUPPORT) 9923 if (SOC_IS_TOMAHAWK2(unit)) { 9924 SOC_IF_ERROR_RETURN 9925 (soc_reg_field32_modify(unit, TOP_MISC_CONTROLr, REG_PORT_ANY, 9926 L1_RCVD_SW_OVWR_VALIDf, ((squelch) ? 0 : 1))); 9927 SOC_IF_ERROR_RETURN 9928 (soc_reg_field32_modify(unit, TOP_MISC_CONTROLr, REG_PORT_ANY, 9929 L1_RCVD_SW_OVWR_ENf, ((squelch) ? 1 : 0))); 9930 } 9931 #endif /* defined(BCM_TOMAHAWK2_SUPPORT) */ 9932 9933 #if defined(BCM_SABER2_SUPPORT) 9934 if (SOC_IS_SABER2(unit)) { 9935 SOC_IF_ERROR_RETURN 9936 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_1r, REG_PORT_ANY, 9937 L1_RCVD_CLK0_SW_OVWR_VALIDf, ((squelch) ? 0 : 1))); 9938 SOC_IF_ERROR_RETURN 9939 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_1r, REG_PORT_ANY, 9940 L1_RCVD_SW_OVWR_ENf, ((squelch) ? 1 : 0))); 9941 } 9942 #endif /* defined(BCM_SABER2_SUPPORT) */ 9943 9944 #if defined(BCM_METROLITE_SUPPORT) 9945 if (SOC_IS_METROLITE(unit)) { 9946 SOC_IF_ERROR_RETURN 9947 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_1r, REG_PORT_ANY, 9948 L1_RCVD_CLK0_SW_OVWR_VALIDf, ((squelch) ? 0 : 1))); 9949 SOC_IF_ERROR_RETURN 9950 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_1r, REG_PORT_ANY, 9951 L1_RCVD_SW_OVWR_ENf, ((squelch) ? 1 : 0))); 9952 } 9953 #endif /* defined(BCM_METROLITE_SUPPORT) */ 9954 9955 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 9956 if (SOC_IS_TD2P_TT2P(unit)) { 9957 SOC_IF_ERROR_RETURN 9958 (soc_reg_field32_modify(unit, TOP_MISC_CONTROLr, REG_PORT_ANY, 9959 L1_RCVD_CLK_RSTNf, ((squelch) ? 0 : 1))); 9960 } 9961 #endif 9962 9963 #if defined(BCM_GREYHOUND_SUPPORT) 9964 if (SOC_IS_GREYHOUND(unit) ) { 9965 SOC_IF_ERROR_RETURN 9966 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_2r, REG_PORT_ANY, 9967 L1_RCVD_SW_OVWR_VALIDf, ((squelch) ? 0 : 1))); 9968 SOC_IF_ERROR_RETURN 9969 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_2r, REG_PORT_ANY, 9970 L1_RCVD_SW_OVWR_ENf, ((squelch) ? 1 : 0))); 9971 } 9972 #endif /* defined(BCM_GREYHOUND_SUPPORT) */ 9973 9974 #if defined(BCM_HELIX4_SUPPORT) 9975 if (SOC_IS_HELIX4(unit) ) { 9976 SOC_IF_ERROR_RETURN 9977 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_1r, REG_PORT_ANY, 9978 L1_RCVD_SW_OVWR_VALIDf, ((squelch) ? 0 : 1))); 9979 SOC_IF_ERROR_RETURN 9980 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_1r, REG_PORT_ANY, 9981 L1_RCVD_SW_OVWR_ENf, ((squelch) ? 1 : 0))); 9982 } 9983 #endif /* defined(BCM_HELIX4_SUPPORT) */ 9984 9985 #if defined(BCM_APACHE_SUPPORT) 9986 if (SOC_IS_APACHE(unit)) { /* Both Apache and Monterey */ 9987 SOC_IF_ERROR_RETURN 9988 (soc_reg_field32_modify(unit, TOP_MISC_CONTROLr, REG_PORT_ANY, 9989 L1_RCVD_SW_OVWR_VALIDf, ((squelch) ? 0 : 1))); 9990 SOC_IF_ERROR_RETURN 9991 (soc_reg_field32_modify(unit, TOP_MISC_CONTROLr, REG_PORT_ANY, 9992 L1_RCVD_SW_OVWR_ENf, ((squelch) ? 1 : 0))); 9993 } 9994 #endif /* defined(BCM_APACHE_SUPPORT) */ 9995 9996 #if defined(BCM_TRIDENT3_SUPPORT) 9997 if (SOC_IS_TRIDENT3(unit)) { 9998 SOC_IF_ERROR_RETURN 9999 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_2r, REG_PORT_ANY, 10000 L1_RCVD_SW_OVWR_VALIDf, ((squelch) ? 0 : 1))); 10001 SOC_IF_ERROR_RETURN 10002 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_2r, REG_PORT_ANY, 10003 L1_RCVD_SW_OVWR_ENf, ((squelch) ? 1 : 0))); 10004 } 10005 #endif /* defined(BCM_TRIDENT3_SUPPORT) */ 10006 10007 #if defined(BCM_MAVERICK2_SUPPORT) 10008 if (SOC_IS_MAVERICK2(unit)) { 10009 SOC_IF_ERROR_RETURN 10010 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_2r, REG_PORT_ANY, 10011 L1_RCVD_SW_OVWR_VALIDf, ((squelch) ? 0 : 1))); 10012 SOC_IF_ERROR_RETURN 10013 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_2r, REG_PORT_ANY, 10014 L1_RCVD_SW_OVWR_ENf, ((squelch) ? 1 : 0))); 10015 } 10016 #endif /* defined(BCM_MAVERICK2_SUPPORT) */ 10017 10018 #if defined(BCM_HELIX5_SUPPORT) 10019 if (SOC_IS_HELIX5(unit)) { 10020 SOC_IF_ERROR_RETURN 10021 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_2r, REG_PORT_ANY, 10022 L1_RCVD_SW_OVWR_VALIDf, ((squelch) ? 0 : 1))); 10023 SOC_IF_ERROR_RETURN 10024 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_2r, REG_PORT_ANY, 10025 L1_RCVD_SW_OVWR_ENf, ((squelch) ? 1 : 0))); 10026 } 10027 #endif /* defined(BCM_HELIX5_SUPPORT) */ 10028 10029 #if defined(BCM_GREYHOUND2_SUPPORT) 10030 if (SOC_IS_GREYHOUND2(unit)) { 10031 SOC_IF_ERROR_RETURN 10032 (soc_reg_field32_modify(unit, TOP_L1_RCVD_CLK_CONTROLr, REG_PORT_ANY, 10033 L1_RCVD_SW_OVWR_VALIDf, ((squelch) ? 0 : 1))); 10034 SOC_IF_ERROR_RETURN 10035 (soc_reg_field32_modify(unit, TOP_L1_RCVD_CLK_CONTROLr, REG_PORT_ANY, 10036 L1_RCVD_SW_OVWR_ENf, ((squelch) ? 1 : 0))); 10037 } 10038 #endif /* defined(BCM_GREYHOUND2_SUPPORT) */ 10039 break; 10040 10041 case bcmTimeSynceClockSourceSecondary: 10042 #if defined(BCM_TOMAHAWK2_SUPPORT) 10043 if (SOC_IS_TOMAHAWK2(unit)) { 10044 SOC_IF_ERROR_RETURN 10045 (soc_reg_field32_modify(unit, TOP_MISC_CONTROLr, REG_PORT_ANY, 10046 L1_RCVD_SW_OVWR_BKUP_VALIDf, ((squelch) ? 0 : 1))); 10047 SOC_IF_ERROR_RETURN 10048 (soc_reg_field32_modify(unit, TOP_MISC_CONTROLr, REG_PORT_ANY, 10049 L1_RCVD_SW_OVWR_ENf, ((squelch) ? 1 : 0))); 10050 } 10051 #endif /* defined(BCM_TOMAHAWK2_SUPPORT) */ 10052 10053 #if defined(BCM_SABER2_SUPPORT) 10054 if (SOC_IS_SABER2(unit)) { 10055 SOC_IF_ERROR_RETURN 10056 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_1r, REG_PORT_ANY, 10057 L1_RCVD_CLK1_SW_OVWR_VALIDf, ((squelch) ? 0 : 1))); 10058 SOC_IF_ERROR_RETURN 10059 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_1r, REG_PORT_ANY, 10060 L1_RCVD_SW_OVWR_ENf, ((squelch) ? 1: 0))); 10061 } 10062 #endif /* defined(BCM_SABER2_SUPPORT) */ 10063 10064 #if defined(BCM_METROLITE_SUPPORT) 10065 if (SOC_IS_METROLITE(unit)) { 10066 SOC_IF_ERROR_RETURN 10067 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_1r, REG_PORT_ANY, 10068 L1_RCVD_CLK1_SW_OVWR_VALIDf, ((squelch) ? 0 : 1))); 10069 SOC_IF_ERROR_RETURN 10070 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_1r, REG_PORT_ANY, 10071 L1_RCVD_SW_OVWR_ENf, ((squelch) ? 1: 0))); 10072 } 10073 #endif /* defined(BCM_METROLITE_SUPPORT) */ 10074 10075 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 10076 if (SOC_IS_TD2P_TT2P(unit)) { 10077 SOC_IF_ERROR_RETURN 10078 (soc_reg_field32_modify(unit, TOP_MISC_CONTROLr, REG_PORT_ANY, 10079 L1_RCVD_CLK_BKUP_RSTNf, ((squelch) ? 0: 1))); 10080 } 10081 #endif 10082 10083 #if defined(BCM_GREYHOUND_SUPPORT) 10084 if (SOC_IS_GREYHOUND(unit) ) { 10085 SOC_IF_ERROR_RETURN 10086 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_2r, REG_PORT_ANY, 10087 L1_RCVD_SW_OVWR_BKUP_VALIDf, ((squelch) ? 0 : 1))); 10088 SOC_IF_ERROR_RETURN 10089 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_2r, REG_PORT_ANY, 10090 L1_RCVD_SW_OVWR_ENf, ((squelch) ? 1 : 0))); 10091 } 10092 #endif /* defined(BCM_GREYHOUND_SUPPORT) */ 10093 10094 10095 #if defined(BCM_HELIX4_SUPPORT) 10096 if (SOC_IS_HELIX4(unit)) { 10097 SOC_IF_ERROR_RETURN 10098 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_1r, REG_PORT_ANY, 10099 L1_RCVD_SW_OVWR_BKUP_VALIDf, ((squelch) ? 0 : 1))); 10100 SOC_IF_ERROR_RETURN 10101 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_1r, REG_PORT_ANY, 10102 L1_RCVD_SW_OVWR_ENf, ((squelch) ? 1 : 0))); 10103 } 10104 #endif /* defined(BCM_HELIX4_SUPPORT) */ 10105 10106 #if defined(BCM_TRIDENT3_SUPPORT) 10107 if (SOC_IS_TRIDENT3(unit)) { 10108 SOC_IF_ERROR_RETURN 10109 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_2r, REG_PORT_ANY, 10110 L1_RCVD_SW_OVWR_BKUP_VALIDf, ((squelch) ? 0 : 1))); 10111 SOC_IF_ERROR_RETURN 10112 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_2r, REG_PORT_ANY, 10113 L1_RCVD_SW_OVWR_ENf, ((squelch) ? 1 : 0))); 10114 } 10115 #endif /* defined(BCM_TRIDENT3_SUPPORT) */ 10116 10117 #if defined(BCM_APACHE_SUPPORT) 10118 if (SOC_IS_APACHE(unit)) { /* Both Apache and Monterey */ 10119 SOC_IF_ERROR_RETURN 10120 (soc_reg_field32_modify(unit, TOP_MISC_CONTROLr, REG_PORT_ANY, 10121 L1_RCVD_SW_OVWR_BKUP_VALIDf, ((squelch) ? 0 : 1))); 10122 SOC_IF_ERROR_RETURN 10123 (soc_reg_field32_modify(unit, TOP_MISC_CONTROLr, REG_PORT_ANY, 10124 L1_RCVD_SW_OVWR_ENf, ((squelch) ? 1 : 0))); 10125 } 10126 #endif /* defined(BCM_APACHE_SUPPORT) */ 10127 10128 #if defined(BCM_MAVERICK2_SUPPORT) 10129 if (SOC_IS_MAVERICK2(unit)) { 10130 SOC_IF_ERROR_RETURN 10131 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_2r, REG_PORT_ANY, 10132 L1_RCVD_SW_OVWR_BKUP_VALIDf, ((squelch) ? 0 : 1))); 10133 SOC_IF_ERROR_RETURN 10134 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_2r, REG_PORT_ANY, 10135 L1_RCVD_SW_OVWR_ENf, ((squelch) ? 1 : 0))); 10136 } 10137 #endif /* defined(BCM_MAVERICK2_SUPPORT) */ 10138 10139 #if defined(BCM_HELIX5_SUPPORT) 10140 if (SOC_IS_HELIX5(unit)) { 10141 SOC_IF_ERROR_RETURN 10142 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_2r, REG_PORT_ANY, 10143 L1_RCVD_SW_OVWR_BKUP_VALIDf, ((squelch) ? 0 : 1))); 10144 SOC_IF_ERROR_RETURN 10145 (soc_reg_field32_modify(unit, TOP_MISC_CONTROL_2r, REG_PORT_ANY, 10146 L1_RCVD_SW_OVWR_ENf, ((squelch) ? 1 : 0))); 10147 } 10148 #endif /* defined(BCM_HELIX5_SUPPORT) */ 10149 10150 #if defined(BCM_GREYHOUND2_SUPPORT) 10151 if (SOC_IS_GREYHOUND2(unit)) { 10152 SOC_IF_ERROR_RETURN 10153 (soc_reg_field32_modify(unit, TOP_L1_RCVD_CLK_CONTROLr, REG_PORT_ANY, 10154 L1_RCVD_SW_OVWR_BKUP_VALIDf, ((squelch) ? 0 : 1))); 10155 SOC_IF_ERROR_RETURN 10156 (soc_reg_field32_modify(unit, TOP_L1_RCVD_CLK_CONTROLr, REG_PORT_ANY, 10157 L1_RCVD_SW_OVWR_ENf, ((squelch) ? 1 : 0))); 10158 } 10159 #endif /* defined(BCM_GREYHOUND2_SUPPORT) */ 10160 break; 10161 default: 10162 return BCM_E_PARAM; 10163 } 10164 return rv; 10165 } 10166 10167 /* 10168 * Function: 10169 * _bcm_esw_time_synce_clock_source_frequency_set 10170 * Purpose: 10171 * Set syncE clock source squelch option 10172 * Parameters: 10173 * unit - (IN) Unit number. 10174 * clk_src - (IN) clock source type (Primary, Secondary) 10175 * frequency - (IN) synce clock source frequency. 10176 * Returns: 10177 * BCM_E_xxx 10178 * Notes: 10179 */ 10180 STATIC int 10181 _bcm_esw_time_synce_clock_source_frequency_set(int unit, 10182 bcm_time_synce_clock_source_config_t *clk_src_config, 10183 int frequency) 10184 10185 { 10186 int rv = BCM_E_NONE; 10187 bcm_time_synce_divisor_setting_t div_in; 10188 bcm_time_synce_divisor_setting_t_init(&div_in); 10189 COMPILER_REFERENCE(rv); 10190 10191 if (clk_src_config->input_src == bcmTimeSynceInputSourceTypePort) { 10192 div_in.index = clk_src_config->port; 10193 } else if(clk_src_config->input_src == bcmTimeSynceInputSourceTypePLL ) { 10194 div_in.index = clk_src_config->pll_index; 10195 } else { 10196 return BCM_E_PARAM; 10197 } 10198 10199 if (IS_MANAGEMENT_PORT(unit, clk_src_config->port) && clk_src_config->input_src == bcmTimeSynceInputSourceTypePort) { 10200 return BCM_E_PARAM; 10201 } 10202 10203 10204 #if defined(BCM_HELIX5_SUPPORT) 10205 /* port_gmii_mode_1/_17/_33 not supported */ 10206 if (SOC_IS_HELIX5(unit)) { 10207 int phy_port = SOC_INFO(unit).port_l2p_mapping[clk_src_config->port]; 10208 if ((clk_src_config->input_src == bcmTimeSynceInputSourceTypePort) && (phy_port <= 48)) { 10209 if (soc_property_phys_port_get(unit, 1, spn_PORT_GMII_MODE, 0)) { 10210 return BCM_E_CONFIG; 10211 } 10212 if (soc_property_phys_port_get(unit, 17, spn_PORT_GMII_MODE, 0)) { 10213 return BCM_E_CONFIG; 10214 } 10215 if (soc_property_phys_port_get(unit, 33, spn_PORT_GMII_MODE, 0)) { 10216 return BCM_E_CONFIG; 10217 } 10218 } 10219 } 10220 #endif /* defined(BCM_HELIX5_SUPPORT) */ 10221 10222 div_in.input_src = clk_src_config->input_src; 10223 10224 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 10225 if(SOC_IS_TD2_TT2(unit) && !SOC_IS_TOMAHAWKX(unit) && !SOC_IS_APACHE(unit)) { 10226 /* 10227 * output_freq = (rx_clk) * stage0_sdm * stage1_div 10228 * rx_clk = (VCO/20) 10229 * stage0_sdm = (stage0_sdm_whole) + (stage0_sdm_frac)/256 10230 * stage1_div = 1 10231 * (0 <= stage0_sdm_whole <= 255, 10232 * 0 <= stage0_sdm_frac <= 255, 10233 * stage1_div is always locked to bypass in SDM mode. Div7,Div11 is not allowed.) 10234 * 10235 * For example, 10236 * stage0_sdm_whole = 20 10237 * stage0_sdm_frac = 160 10238 * stage0_sdm = 20 + 160/256 = 20.625 10239 * Port speed |VCO |VCO/20 |stage0 |stage1 |output freq(MHz) 10240 * 10/40/100G |10.3125 |515.625 |20.625 |1 |25 10241 */ 10242 10243 switch(frequency) { 10244 case bcmTimeSyncE23MHz: 10245 div_in.stage0_mode = bcmTimeSynceModeBypass; 10246 div_in.stage0_sdm_whole = 23; 10247 div_in.stage1_div = bcmTimeSynceStage1Div11; 10248 break; 10249 case bcmTimeSyncE25MHz: 10250 div_in.stage0_mode = bcmTimeSynceModeSDMFracDiv; 10251 div_in.stage0_sdm_whole = 20; 10252 div_in.stage0_sdm_frac = 160; 10253 break; 10254 case bcmTimeSyncE28MHz: 10255 div_in.stage0_mode = bcmTimeSynceModeBypass; 10256 div_in.stage0_sdm_whole = 28; 10257 div_in.stage1_div = bcmTimeSynceStage1Div11; 10258 break; 10259 case bcmTimeSyncE46MHz: 10260 div_in.stage0_mode = bcmTimeSynceModeBypass; 10261 div_in.stage0_sdm_whole = 46; 10262 div_in.stage1_div = bcmTimeSynceStage1Div11; 10263 break; 10264 default: 10265 return BCM_E_PARAM; 10266 } 10267 } 10268 #endif /* BCM_TRIDENT2PLUS_SUPPORT */ 10269 10270 #ifdef BCM_GREYHOUND_SUPPORT 10271 if (SOC_IS_GREYHOUND(unit)) { /* GREYHOUND SyncE Freq Divisor*/ 10272 if(!BCM_TIME_GH_L1_FREQ_SEL_MODE(frequency)) { 10273 return BCM_E_PARAM; 10274 } 10275 /* In Greyhound raw recovered clock from port will be based on below 10276 pass-through mode :: freq = 0(00b) 10277 Div by 5mode(25MHz) :: freq = 1(01b) 10278 Div by 10mode(31.25MHz) :: freq = 2(10b) 10279 Div by 2mode(156.25MHz) :: freq = 3(11b) 10280 */ 10281 /* raw recovered clock div val */ 10282 switch(frequency) { 10283 case 0:/* pass-through mode */ 10284 div_in.stage0_mode = 0; 10285 break; 10286 case 1: /* Div by 5mode(25MHz) */ 10287 div_in.stage0_mode = 1; 10288 break; 10289 case 2: /* Div by 10mode(31.25MHz) */ 10290 div_in.stage0_mode = 2; 10291 break; 10292 default: /* Div by 2mode(156.25MHz)*/ 10293 div_in.stage0_mode = 3; 10294 } 10295 } 10296 #endif /* BCM_GREYHOUND_SUPPORT */ 10297 10298 #ifdef BCM_HELIX4_SUPPORT 10299 if (SOC_IS_HELIX4(unit)) { /* HELIX4 SyncE Freq Divisor*/ 10300 if(!BCM_TIME_HX4_L1_FREQ_SEL_MODE(frequency)) { 10301 return BCM_E_PARAM; 10302 } 10303 /* In Helix4 raw recovered clock from port will be based on below 10304 pass-through mode :: freq = 0(00b) 10305 Div by 5mode(25MHz) :: freq = 1(01b) 10306 Div by 10mode(31.25MHz) :: freq = 2(10b) 10307 Div by 2mode(156.25MHz) :: freq = 3(11b) 10308 */ 10309 /* raw recovered clock div val */ 10310 switch(frequency) { 10311 case 0:/* pass-through mode */ 10312 div_in.stage0_mode = 0; 10313 break; 10314 case 1: /* Div by 5mode(25MHz) */ 10315 div_in.stage0_mode = 1; 10316 break; 10317 case 2: /* Div by 10mode(31.25MHz) */ 10318 div_in.stage0_mode = 2; 10319 break; 10320 default: /* Div by 2mode(156.25MHz)*/ 10321 div_in.stage0_mode = 3; 10322 } 10323 } 10324 #endif /* BCM_HELIX4_SUPPORT */ 10325 10326 #if defined(BCM_KATANA_SUPPORT) 10327 if (SOC_IS_KATANA(unit)) { 10328 switch (frequency) { 10329 case bcmTimeSyncE125MHz: 10330 /* KT do not have SDM */ 10331 break; 10332 default: 10333 return BCM_E_FAIL; 10334 break; 10335 } 10336 } 10337 #endif /* defined(BCM_KATANA_SUPPORT) */ 10338 10339 #if defined(BCM_SABER2_SUPPORT) 10340 if (SOC_IS_SABER2(unit)) { 10341 switch (frequency) { 10342 case bcmTimeSyncE25MHz: 10343 div_in.stage0_mode = bcmTimeSynceModeSDMFracDiv; 10344 break; 10345 case bcmTimeSyncE125MHz: 10346 div_in.stage0_mode = bcmTimeSynceModeBypass; 10347 break; 10348 default: 10349 return BCM_E_FAIL; 10350 break; 10351 } 10352 } 10353 #endif /* defined(BCM_SABER2_SUPPORT) */ 10354 10355 #if defined (BCM_GREYHOUND2_SUPPORT) 10356 if (SOC_IS_GREYHOUND2(unit)) { 10357 if (clk_src_config->input_src == bcmTimeSynceInputSourceTypePort) { 10358 phy_ctrl_t *pc; 10359 phymod_dispatch_type_t type = phymodDispatchTypeInvalid; 10360 int speed = 0; 10361 10362 pc = INT_PHY_SW_STATE(unit, clk_src_config->port); 10363 if (pc == NULL) { 10364 return BCM_E_FAIL; 10365 } 10366 type = pc->phymod_ctrl.phy[0]->pm_phy.type; 10367 10368 BCM_IF_ERROR_RETURN(bcm_esw_port_speed_get(unit, clk_src_config->port, &speed)); 10369 10370 switch (frequency) { 10371 case bcmTimeSyncE25MHz: /* 25MHz using SDM mode */ 10372 if (type == phymodDispatchTypeTsce_dpll) { 10373 div_in.stage0_mode = bcmTimeSynceModeSDMFracDiv; 10374 div_in.stage1_div = bcmTimeSynceStage1Div1; 10375 if (speed == 10606 || speed == 21000 || speed == 42000) { 10376 div_in.stage0_sdm_whole = 0x15; 10377 div_in.stage0_sdm_frac = 0xe0; 10378 } else { 10379 div_in.stage0_sdm_whole = 0x14; 10380 div_in.stage0_sdm_frac = 0xa0; 10381 } 10382 } else if (type == phymodDispatchTypeTscf) { 10383 div_in.stage0_mode = bcmTimeSynceModeSDMFracDiv; 10384 div_in.stage1_div = bcmTimeSynceStage1Div1; 10385 /* falcon ports */ 10386 if (speed == 100 || speed == 10000 || speed== 40000) { 10387 /* 1G or 10G or 40G ports - */ 10388 div_in.stage0_sdm_whole = 0xa; 10389 div_in.stage0_sdm_frac = 0x50; 10390 } else if (speed == 25000 || speed == 50000) { 10391 /* 25G or 50G ports - VCO 25.78125*/ 10392 div_in.stage0_sdm_whole = 0x19; 10393 div_in.stage0_sdm_frac = 0xc8; 10394 } 10395 if (IS_HG_PORT(unit, clk_src_config->port) && (speed == 10000 || speed == 21000 || speed == 42000)) { 10396 /* 10G/21G/42G HG ports -VCO 21.875 */ 10397 div_in.stage0_sdm_whole = 0xa; 10398 div_in.stage0_sdm_frac = 0xf0; 10399 } else if (IS_HG_PORT(unit, clk_src_config->port) && speed == 25000) { 10400 /* 25G HG ports */ 10401 div_in.stage0_sdm_whole = 0x1b; 10402 div_in.stage0_sdm_frac = 0x58; 10403 } 10404 } 10405 break; 10406 case bcmTimeSyncE125MHz: /* 125MHz viper */ 10407 if (type == phymodDispatchTypeViper) { 10408 break; 10409 } 10410 default: 10411 return BCM_E_PARAM; 10412 } 10413 } 10414 } 10415 #endif /* defined (BCM_GREYHOUND2_SUPPORT) */ 10416 10417 #if defined(BCM_TOMAHAWK_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_APACHE_SUPPORT) || defined(BCM_MAVERICK2_SUPPORT) || defined(BCM_HELIX5_SUPPORT) || \ 10418 defined(BCM_MONTEREY_SUPPORT) 10419 if (clk_src_config->input_src == bcmTimeSynceInputSourceTypePort) { 10420 #ifdef PORTMOD_SUPPORT 10421 if ((SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT3(unit) || SOC_IS_APACHE(unit) || SOC_IS_MAVERICK2(unit) || SOC_IS_HELIX5(unit) || SOC_IS_MONTEREY(unit)) && 10422 soc_feature(unit, soc_feature_portmod)) { 10423 10424 int port_speed = 0; /* speed specified in mbps*/ 10425 phymod_dispatch_type_t dispatch_type = phymodDispatchTypeInvalid; 10426 10427 BCM_IF_ERROR_RETURN(bcm_esw_port_speed_get(unit, clk_src_config->port, &port_speed)); 10428 10429 dispatch_type = _bcm_time_synce_tsc_phymod_dispatch_type_get(unit, clk_src_config->port); 10430 10431 /* as per top spec 25MHz recovered clock is suggested from all falcon ports 10432 * using SDM mode configuration 10433 * Tomahawk has 4 LCPLL ports , 1 - LCPLL1, 2 - LCPLL2, 3 - LCPLL3, 4 - LCPLL4 10434 * TD3 has 4 XGPLL XGPLL0-XGPLL3 10435 */ 10436 switch (frequency) { 10437 case bcmTimeSyncE25MHz: /* 25MHz using SDM mode */ 10438 div_in.stage0_mode = bcmTimeSynceModeSDMFracDiv; 10439 div_in.stage1_div = bcmTimeSynceStage1Div1; 10440 10441 if((dispatch_type == phymodDispatchTypeTsce) || 10442 (dispatch_type == phymodDispatchTypeTsce16)) { 10443 /* eagle port */ 10444 if (!IS_HG_PORT(unit, clk_src_config->port)) { 10445 /* regular port */ 10446 div_in.stage0_sdm_whole = 0x14; 10447 div_in.stage0_sdm_frac = 0xa0; 10448 } else { 10449 /* hi gig port */ 10450 div_in.stage0_sdm_whole = 0x15; 10451 div_in.stage0_sdm_frac = 0xe0; 10452 } 10453 } else if (dispatch_type == phymodDispatchTypeTscf) { 10454 /* falcon ports */ 10455 if (port_speed == 100) { 10456 /* 1G ports - VCO 25.78125 */ 10457 div_in.stage0_sdm_whole = 0x19; 10458 div_in.stage0_sdm_frac = 0xc8; 10459 } else if (port_speed == 10000 || port_speed == 40000) { 10460 /* 10G or 40G ports - VCO 20.625 */ 10461 div_in.stage0_sdm_whole = 0xa; 10462 div_in.stage0_sdm_frac = 0x50; 10463 } else if (port_speed == 100000 || port_speed == 25000) { 10464 /* 100G ports - VCO 25.78125*/ 10465 div_in.stage0_sdm_whole = 0x19; 10466 div_in.stage0_sdm_frac = 0xc8; 10467 } else if (IS_HG_PORT(unit, clk_src_config->port) && port_speed == 11000) { 10468 /* 11G HG ports -VCO 21.875 */ 10469 div_in.stage0_sdm_whole = 0xa; 10470 div_in.stage0_sdm_frac = 0xf0; 10471 } else if (IS_HG_PORT(unit, clk_src_config->port) && port_speed == 106000) { 10472 /* 106G HG ports -VCO 21.875 */ 10473 div_in.stage0_sdm_whole = 0x1b; 10474 div_in.stage0_sdm_frac = 0x58; 10475 } 10476 } else if (dispatch_type == phymodDispatchTypeTscf16) { 10477 /* falcon ports */ 10478 if (port_speed == 100) { 10479 /* 1G ports - VCO 25.78125 */ 10480 div_in.stage0_sdm_whole = 0x19; 10481 div_in.stage0_sdm_frac = 0xc8; 10482 } else if (port_speed == 10000 || port_speed == 40000) { 10483 /* 10G or 40G ports - VCO 20.625 */ 10484 div_in.stage0_sdm_whole = 0xa; 10485 div_in.stage0_sdm_frac = 0x50; 10486 } else if (port_speed == 100000 || port_speed == 25000) { 10487 /* 100G ports - VCO 25.78125*/ 10488 div_in.stage0_sdm_whole = 0x19; 10489 div_in.stage0_sdm_frac = 0xc8; 10490 } else if (IS_HG_PORT(unit, clk_src_config->port) && port_speed == 11000) { 10491 /* 11G HG ports -VCO 21.875 */ 10492 div_in.stage0_sdm_whole = 0xa; 10493 div_in.stage0_sdm_frac = 0xf0; 10494 } else if (IS_HG_PORT(unit, clk_src_config->port) && port_speed == 106000) { 10495 /* 106G HG ports -VCO 21.875 */ 10496 div_in.stage0_sdm_whole = 0x1b; 10497 div_in.stage0_sdm_frac = 0x58; 10498 } 10499 } else if (dispatch_type == phymodDispatchTypeTscbh) { 10500 /* DO NOTHING: portmod API will program the proper settings for SDM mode. */ 10501 } else if (dispatch_type == phymodDispatchTypeTsce_dpll) { 10502 if (port_speed == 1000 || port_speed == 10000 || port_speed == 40000 || port_speed == 20000) { 10503 div_in.stage0_sdm_whole = 0x14; 10504 div_in.stage0_sdm_frac = 0xa0; 10505 } else { 10506 div_in.stage0_sdm_whole = 0x15; 10507 div_in.stage0_sdm_frac = 0xE0; 10508 } 10509 } else if (dispatch_type == phymodDispatchTypeTscf_gen3) { 10510 if (port_speed == 25000 || port_speed == 100000 || port_speed == 50000) { 10511 div_in.stage0_sdm_whole = 0x19; 10512 div_in.stage0_sdm_frac = 0xC8; 10513 } else if (port_speed == 1000) { 10514 div_in.stage0_sdm_whole = 0x14; 10515 div_in.stage0_sdm_frac = 0xA0; 10516 } else { 10517 div_in.stage0_sdm_whole = 0x0A; 10518 div_in.stage0_sdm_frac = 0x50; 10519 } 10520 } else { 10521 cli_out("unknown port dispatch type ... %d\n", (int)dispatch_type); 10522 return BCM_E_FAIL; 10523 } 10524 break; 10525 case bcmTimeSyncE7MHz: 10526 div_in.stage0_mode = bcmTimeSynceModeSDMFracDiv; 10527 div_in.stage1_div = bcmTimeSynceStage1Div1; 10528 10529 if (dispatch_type == phymodDispatchTypeTsce_dpll) { 10530 if (port_speed == 1000 || port_speed == 10000 || port_speed == 40000 || port_speed == 20000) { 10531 div_in.stage0_sdm_whole = 0x42; 10532 div_in.stage0_sdm_frac = 0x00; 10533 } 10534 } else if (dispatch_type == phymodDispatchTypeTscf_gen3) { 10535 if (port_speed == 25000 || port_speed == 100000 || port_speed == 50000) { 10536 div_in.stage0_sdm_whole = 0x52; 10537 div_in.stage0_sdm_frac = 0x80; 10538 } else if (port_speed == 1000) { 10539 div_in.stage0_sdm_whole = 0x42; 10540 div_in.stage0_sdm_frac = 0x00; 10541 } else { 10542 div_in.stage0_sdm_whole = 0x21; 10543 div_in.stage0_sdm_frac = 0x00; 10544 } 10545 } 10546 break; 10547 case bcmTimeSyncE12MHz: 10548 div_in.stage0_mode = bcmTimeSynceModeSDMFracDiv; 10549 div_in.stage1_div = bcmTimeSynceStage1Div1; 10550 10551 if (dispatch_type == phymodDispatchTypeTsce_dpll) { 10552 if (port_speed == 1000 || port_speed == 10000 || port_speed == 40000 || port_speed == 20000) { 10553 div_in.stage0_sdm_whole = 0x29; 10554 div_in.stage0_sdm_frac = 0x40; 10555 } 10556 } else if (dispatch_type == phymodDispatchTypeTscf_gen3) { 10557 if (port_speed == 25000 || port_speed == 100000 || port_speed == 50000) { 10558 div_in.stage0_sdm_whole = 0x33; 10559 div_in.stage0_sdm_frac = 0x90; 10560 } else if (port_speed == 1000) { 10561 div_in.stage0_sdm_whole = 0x29; 10562 div_in.stage0_sdm_frac = 0x40; 10563 } else { 10564 div_in.stage0_sdm_whole = 0x14; 10565 div_in.stage0_sdm_frac = 0xa0; 10566 } 10567 } 10568 break; 10569 case bcmTimeSyncE31MHz: 10570 div_in.stage0_mode = bcmTimeSynceModeSDMFracDiv; 10571 div_in.stage1_div = bcmTimeSynceStage1Div1; 10572 10573 if (dispatch_type == phymodDispatchTypeTsce_dpll) { 10574 if (port_speed == 1000 || port_speed == 10000 || port_speed == 40000 || port_speed == 20000) { 10575 div_in.stage0_sdm_whole = 0x10; 10576 div_in.stage0_sdm_frac = 0x80; 10577 } 10578 } else if (dispatch_type == phymodDispatchTypeTscf_gen3) { 10579 if (port_speed == 25000 || port_speed == 100000 || port_speed == 50000) { 10580 div_in.stage0_sdm_whole = 0x14; 10581 div_in.stage0_sdm_frac = 0xa0; 10582 } else if (port_speed == 1000) { 10583 div_in.stage0_sdm_whole = 0x10; 10584 div_in.stage0_sdm_frac = 0x80; 10585 } else { 10586 div_in.stage0_sdm_whole = 0x08; 10587 div_in.stage0_sdm_frac = 0x40; 10588 } 10589 } 10590 break; 10591 case bcmTimeSyncE37MHz: 10592 div_in.stage0_mode = bcmTimeSynceModeSDMFracDiv; 10593 div_in.stage1_div = bcmTimeSynceStage1Div1; 10594 10595 if (dispatch_type == phymodDispatchTypeTsce_dpll) { 10596 if (port_speed == 1000 || port_speed == 10000 || port_speed == 40000 || port_speed == 20000) { 10597 div_in.stage0_sdm_whole = 0x0D; 10598 div_in.stage0_sdm_frac = 0xC0; 10599 } 10600 } else if (dispatch_type == phymodDispatchTypeTscf_gen3) { 10601 if (port_speed == 25000 || port_speed == 100000 || port_speed == 50000) { 10602 div_in.stage0_sdm_whole = 0x11; 10603 div_in.stage0_sdm_frac = 0x30; 10604 } else if (port_speed == 1000) { 10605 div_in.stage0_sdm_whole = 0x0D; 10606 div_in.stage0_sdm_frac = 0xC0; 10607 } else { 10608 div_in.stage0_sdm_whole = 0x06; 10609 div_in.stage0_sdm_frac = 0xE0; 10610 } 10611 } 10612 break; 10613 default: 10614 /* not supported */ 10615 return BCM_E_FAIL; 10616 break; 10617 } 10618 } 10619 else 10620 #endif /* PORTMOD_SUPPORT */ 10621 { 10622 if (SOC_IS_TOMAHAWK(unit)) { 10623 switch (frequency) { 10624 case bcmTimeSyncE25MHz: 10625 div_in.stage0_mode = bcmTimeSynceModeSDMFracDiv; 10626 div_in.stage0_sdm_whole = 20; 10627 div_in.stage0_sdm_frac = 160; 10628 break; 10629 default: 10630 return BCM_E_FAIL; 10631 break; 10632 } 10633 10634 } 10635 } 10636 } 10637 #endif /* TH TD3 AP MV2 HX5 support */ 10638 10639 #if defined(BCM_METROLITE_SUPPORT) 10640 if (SOC_IS_METROLITE(unit)) { 10641 switch (frequency) { 10642 /* For Viper: div5 logic at Mux1 gives 25MHz 10643 * For Eagle: default SDM logic choosen TSCE synce div gives 25MHz 10644 * make sure portmacro side stage1 is not in default 10645 * div11(for SDM stage1 should be in div1) 10646 */ 10647 case bcmTimeSyncE25MHz: 10648 div_in.stage0_mode = bcmTimeSynceModeSDMFracDiv; 10649 break; 10650 /* For Viper only : 125MHz bypassed L1 recov_clock */ 10651 case bcmTimeSyncE125MHz: 10652 div_in.stage0_mode = bcmTimeSynceModeBypass; 10653 break; 10654 default: 10655 return BCM_E_FAIL; 10656 break; 10657 } 10658 } 10659 #endif /* defined(BCM_METROLITE_SUPPORT) */ 10660 10661 rv = bcm_esw_time_synce_clock_set(unit, clk_src_config->clk_src, &div_in); 10662 return rv; 10663 } 10664 10665 10666 /* 10667 * Function: 10668 * bcm_esw_time_synce_clock_source_control_set 10669 * Purpose: 10670 * Set syncE clock source control option 10671 * Parameters: 10672 * unit - (IN) Unit number. 10673 * clk_src_config - (IN) clock source config 10674 * value - (IN) control value 10675 * Returns: 10676 * BCM_E_xxx 10677 * Notes: NEW API to support SYNCE configuration 10678 */ 10679 int 10680 bcm_esw_time_synce_clock_source_control_set(int unit, 10681 bcm_time_synce_clock_source_config_t *clk_src_config, 10682 bcm_time_synce_clock_source_control_t control, 10683 int value) 10684 { 10685 int rv = BCM_E_UNAVAIL; 10686 10687 switch (control) { 10688 case bcmTimeSynceClockSourceControlSquelch: 10689 rv = _bcm_esw_time_synce_clock_source_squelch_set(unit, clk_src_config->clk_src, value); 10690 break; 10691 case bcmTimeSynceClockSourceControlFrequency: 10692 rv = _bcm_esw_time_synce_clock_source_frequency_set(unit, clk_src_config, value); 10693 break; 10694 default: 10695 return BCM_E_PARAM; 10696 } 10697 10698 return rv; 10699 } 10700 10701 /* 10702 * Function: 10703 * bcm_esw_time_bs_time_get 10704 * Purpose: 10705 * Get the broadsync time on the specified unit 10706 * Parameters: 10707 * unit - (IN) StrataSwitch Unit #. 10708 * bs_time - (OUT) broadsync time in seconds and nanoseconds 10709 * Returns: 10710 * BCM_E_NONE 10711 * BCM_E_XXX 10712 */ 10713 10714 int 10715 bcm_esw_time_bs_time_get (int unit, bcm_time_spec_t *bs_time) 10716 { 10717 int rv; /* Operation return status. */ 10718 uint8 bs_initialized=0; 10719 10720 /* Chek if time feature is supported on a device */ 10721 if (!soc_feature(unit, soc_feature_time_support)) { 10722 return (BCM_E_UNAVAIL); 10723 } 10724 10725 bcm_esw_time_interface_traverse(unit, _bcm_time_interface_traverse_cb, 10726 (void*)&bs_initialized); 10727 if (!bs_initialized) { 10728 return BCM_E_INIT; 10729 } 10730 10731 if (NULL == bs_time) { 10732 return (BCM_E_PARAM); 10733 } 10734 10735 TIME_LOCK(unit); 10736 rv = _bcm_time_bs_time_get(unit, bs_time); 10737 if (BCM_FAILURE(rv)) { 10738 TIME_UNLOCK(unit); 10739 return (rv); 10740 } 10741 TIME_UNLOCK(unit); 10742 10743 return (BCM_E_NONE); 10744 } 10745 10746 #if defined(BCM_MONTEREY_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT) 10747 int 10748 _bcm_esw_time_counter_get(int unit, int ts_counter, uint64 *pTS_val) 10749 { 10750 int rv = BCM_E_NONE; 10751 uint64 ts; 10752 uint32 upper; 10753 uint32 lower; 10754 10755 if (ts_counter == 1) { 10756 READ_NS_TIMESYNC_TS1_TIMESTAMP_UPPER_STATUSr(unit, &upper); 10757 READ_NS_TIMESYNC_TS1_TIMESTAMP_LOWER_STATUSr(unit, &lower); 10758 } else if(ts_counter == 0) { 10759 READ_NS_TIMESYNC_TS0_TIMESTAMP_UPPER_STATUSr(unit, &upper); 10760 READ_NS_TIMESYNC_TS0_TIMESTAMP_LOWER_STATUSr(unit, &lower); 10761 } else { 10762 return BCM_E_FAIL; 10763 } 10764 10765 u64_H(ts) = upper; 10766 u64_L(ts) = lower; 10767 10768 if (SOC_IS_TOMAHAWK3(unit)) { 10769 COMPILER_64_SHR(ts, 4); 10770 } 10771 10772 *pTS_val = ts; 10773 10774 return rv; 10775 } 10776 10777 int 10778 _bcm_esw_time_counter_set(int unit, int ts_counter, uint64 ts_val) 10779 { 10780 uint32 rval; 10781 int rv = BCM_E_NONE; 10782 10783 /* 52b format frpom 48b ns */ 10784 if(SOC_IS_MONTEREY(unit) || SOC_IS_TOMAHAWK3(unit)) { 10785 COMPILER_64_SHL(ts_val, 4); 10786 } 10787 10788 if (ts_counter == 1) { 10789 SOC_IF_ERROR_RETURN(READ_NS_TIMESYNC_TS1_INIT_ACCUMULATOR_2r(unit, &rval)); 10790 soc_reg_field_set(unit, NS_TIMESYNC_TS1_INIT_ACCUMULATOR_2r, &rval, ACC2f, u64_H(ts_val) << 8 | u64_L(ts_val) >> 24); 10791 SOC_IF_ERROR_RETURN(WRITE_NS_TIMESYNC_TS1_INIT_ACCUMULATOR_2r(unit, rval)); 10792 10793 SOC_IF_ERROR_RETURN(READ_NS_TIMESYNC_TS1_INIT_ACCUMULATOR_1r(unit, &rval)); 10794 soc_reg_field_set(unit, NS_TIMESYNC_TS1_INIT_ACCUMULATOR_1r, &rval, ACC1f, u64_L(ts_val) << 8); 10795 SOC_IF_ERROR_RETURN(WRITE_NS_TIMESYNC_TS1_INIT_ACCUMULATOR_1r(unit, rval)); 10796 10797 SOC_IF_ERROR_RETURN(READ_NS_TIMESYNC_TS1_INIT_ACCUMULATOR_0r(unit, &rval)); 10798 soc_reg_field_set(unit, NS_TIMESYNC_TS1_INIT_ACCUMULATOR_0r, &rval, ACC0f, 0); 10799 SOC_IF_ERROR_RETURN(WRITE_NS_TIMESYNC_TS1_INIT_ACCUMULATOR_0r(unit, rval)); 10800 10801 } else if (ts_counter == 0) { 10802 SOC_IF_ERROR_RETURN(READ_NS_TIMESYNC_TS0_INIT_ACCUMULATOR_2r(unit, &rval)); 10803 soc_reg_field_set(unit, NS_TIMESYNC_TS0_INIT_ACCUMULATOR_2r, &rval, ACC2f, u64_H(ts_val) << 8 | u64_L(ts_val) >> 24); 10804 SOC_IF_ERROR_RETURN(WRITE_NS_TIMESYNC_TS0_INIT_ACCUMULATOR_2r(unit, rval)); 10805 10806 SOC_IF_ERROR_RETURN(READ_NS_TIMESYNC_TS0_INIT_ACCUMULATOR_1r(unit, &rval)); 10807 soc_reg_field_set(unit, NS_TIMESYNC_TS0_INIT_ACCUMULATOR_1r, &rval, ACC1f, u64_L(ts_val) << 8); 10808 SOC_IF_ERROR_RETURN(WRITE_NS_TIMESYNC_TS0_INIT_ACCUMULATOR_1r(unit, rval)); 10809 10810 SOC_IF_ERROR_RETURN(READ_NS_TIMESYNC_TS0_INIT_ACCUMULATOR_0r(unit, &rval)); 10811 soc_reg_field_set(unit, NS_TIMESYNC_TS0_INIT_ACCUMULATOR_0r, &rval, ACC0f, 0); 10812 SOC_IF_ERROR_RETURN(WRITE_NS_TIMESYNC_TS0_INIT_ACCUMULATOR_0r(unit, rval)); 10813 } else { 10814 rv = BCM_E_FAIL; 10815 } 10816 10817 return rv; 10818 } 10819 10820 int 10821 _bcm_esw_time_counter_enable(int unit, int ts_counter, int enable) 10822 { 10823 uint32 rval; 10824 int rv = BCM_E_NONE; 10825 10826 if (ts_counter == 1) { 10827 SOC_IF_ERROR_RETURN(READ_NS_TIMESYNC_TS1_COUNTER_ENABLEr(unit, &rval)); 10828 soc_reg_field_set(unit, NS_TIMESYNC_TS1_COUNTER_ENABLEr, &rval, ENABLEf, enable?1:0); 10829 SOC_IF_ERROR_RETURN(WRITE_NS_TIMESYNC_TS1_COUNTER_ENABLEr(unit, rval)); 10830 } else if (ts_counter == 0) { 10831 SOC_IF_ERROR_RETURN(READ_NS_TIMESYNC_TS0_COUNTER_ENABLEr(unit, &rval)); 10832 soc_reg_field_set(unit, NS_TIMESYNC_TS0_COUNTER_ENABLEr, &rval, ENABLEf, enable?1:0); 10833 SOC_IF_ERROR_RETURN(WRITE_NS_TIMESYNC_TS0_COUNTER_ENABLEr(unit, rval)); 10834 } else { 10835 rv = BCM_E_FAIL; 10836 } 10837 10838 return rv; 10839 } 10840 10841 int 10842 _bcm_esw_time_counter_freq_frac_set(int unit, int ts_counter) 10843 { 10844 uint32 rval; 10845 int rv = BCM_E_NONE; 10846 10847 if (ts_counter == 1) { 10848 /* Disable the common control of TS0 and TS1 */ 10849 SOC_IF_ERROR_RETURN(READ_NS_TIMESYNC_COUNTER_CONFIG_SELECTr(unit, &rval)); 10850 soc_reg_field_set(unit, NS_TIMESYNC_COUNTER_CONFIG_SELECTr, &rval, ENABLE_COMMON_CONTROLf, 0); 10851 SOC_IF_ERROR_RETURN(WRITE_NS_TIMESYNC_COUNTER_CONFIG_SELECTr(unit, rval)); 10852 10853 SOC_IF_ERROR_RETURN(READ_NS_TIMESYNC_TS1_FREQ_CTRL_FRAC_UPPERr(unit, &rval)); 10854 soc_reg_field_set(unit, NS_TIMESYNC_TS1_FREQ_CTRL_FRAC_UPPERr, &rval, UINCf, 0x2000); 10855 SOC_IF_ERROR_RETURN(WRITE_NS_TIMESYNC_TS1_FREQ_CTRL_FRAC_UPPERr(unit, rval)); 10856 10857 SOC_IF_ERROR_RETURN(READ_NS_TIMESYNC_TS1_FREQ_CTRL_FRAC_LOWERr(unit, &rval)); 10858 soc_reg_field_set(unit, NS_TIMESYNC_TS1_FREQ_CTRL_FRAC_LOWERr, &rval, LINCf, 0x0); 10859 SOC_IF_ERROR_RETURN(WRITE_NS_TIMESYNC_TS1_FREQ_CTRL_FRAC_LOWERr(unit, rval)); 10860 10861 } else if (ts_counter == 0) { 10862 SOC_IF_ERROR_RETURN(READ_NS_TIMESYNC_TS0_FREQ_CTRL_FRAC_UPPERr(unit, &rval)); 10863 soc_reg_field_set(unit, NS_TIMESYNC_TS0_FREQ_CTRL_FRAC_UPPERr, &rval, UINCf, 0x2000); 10864 SOC_IF_ERROR_RETURN(WRITE_NS_TIMESYNC_TS0_FREQ_CTRL_FRAC_UPPERr(unit, rval)); 10865 10866 SOC_IF_ERROR_RETURN(READ_NS_TIMESYNC_TS0_FREQ_CTRL_FRAC_LOWERr(unit, &rval)); 10867 soc_reg_field_set(unit, NS_TIMESYNC_TS0_FREQ_CTRL_FRAC_LOWERr, &rval, LINCf, 0x0); 10868 SOC_IF_ERROR_RETURN(WRITE_NS_TIMESYNC_TS0_FREQ_CTRL_FRAC_LOWERr(unit, rval)); 10869 } else { 10870 rv = BCM_E_FAIL; 10871 } 10872 10873 return rv; 10874 } 10875 10876 #endif 10877 10878 /* 10879 * Function: 10880 * bcm_esw_time_ts_counter_set 10881 * Purpose: 10882 * Set timestamper counter 10883 * Parameters: 10884 * unit - (IN) Unit number. 10885 * counter - (IN) counter values 10886 * Returns: 10887 * BCM_E_xxx 10888 */ 10889 int 10890 bcm_esw_time_ts_counter_set( 10891 int unit, 10892 bcm_time_ts_counter_t *counter) 10893 { 10894 int rv = BCM_E_UNAVAIL; 10895 #if (defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT) || \ 10896 defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_MONTEREY_SUPPORT)) 10897 uint32 freq_ctrl = 0; 10898 uint64 check; 10899 uint32 u64_hi = 0xffff, u64_low = 0xffffffff; 10900 10901 if (counter == NULL) { 10902 return BCM_E_PARAM; 10903 } 10904 10905 COMPILER_64_SET(check, u64_hi, u64_low); 10906 10907 if (COMPILER_64_GT(counter->ts_counter_ns, check)) { 10908 return BCM_E_PARAM; 10909 } 10910 10911 #if defined(BCM_MONTEREY_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT) 10912 if(SOC_IS_MONTEREY(unit) || SOC_IS_TOMAHAWK3(unit)) { 10913 int ts_counter; 10914 10915 10916 ts_counter = counter->ts_counter; 10917 10918 SOC_IF_ERROR_RETURN(_bcm_esw_time_counter_enable(unit, ts_counter, 0)); 10919 if(SOC_IS_MONTEREY(unit)) { 10920 SOC_IF_ERROR_RETURN(_bcm_esw_time_counter_freq_frac_set(unit, ts_counter)); 10921 } else if (SOC_IS_TOMAHAWK3(unit)) { 10922 SOC_IF_ERROR_RETURN(_bcm_esw_time_counter_set(unit, ts_counter, counter->ts_counter_ns)); 10923 } 10924 SOC_IF_ERROR_RETURN(_bcm_esw_time_counter_enable(unit, ts_counter, counter->enable)); 10925 10926 rv = BCM_E_NONE; 10927 } else 10928 #endif 10929 { 10930 freq_ctrl = (counter->time_format == bcmTimeFormatPTP) ? 10931 0x40000000 : 0x44B82FA1; 10932 10933 rv = soc_reg_field32_modify(unit, CMIC_TIMESYNC_TS1_FREQ_CTRL_FRACr, 10934 REG_PORT_ANY, 10935 FRACf, freq_ctrl); 10936 10937 if (BCM_FAILURE(rv)) { 10938 return rv; 10939 } 10940 10941 /* 10942 * Adding 64bit upper 32 bits into 32 bit container. 10943 * then extracting only 16 bits. 10944 */ 10945 COMPILER_64_TO_32_HI(u64_hi, counter->ts_counter_ns); 10946 rv = soc_reg_field32_modify(unit, CMIC_TIMESYNC_TS1_FREQ_CTRL_UPPERr, 10947 REG_PORT_ANY, 10948 NSf, (u64_hi & 0xffff)); 10949 10950 if (BCM_FAILURE(rv)) { 10951 return rv; 10952 } 10953 10954 /* Adding 64bit lower 32 bits into 32 bit container. */ 10955 COMPILER_64_TO_32_LO(u64_low, counter->ts_counter_ns); 10956 rv = soc_reg_field32_modify(unit, CMIC_TIMESYNC_TS1_FREQ_CTRL_LOWERr, 10957 REG_PORT_ANY, 10958 NSf, u64_low); 10959 10960 if (BCM_FAILURE(rv)) { 10961 return rv; 10962 } 10963 10964 /* Set the enable and disable control. */ 10965 rv = soc_reg_field32_modify(unit, CMIC_TIMESYNC_TS1_COUNTER_ENABLEr, 10966 REG_PORT_ANY, 10967 ENABLEf, counter->enable); 10968 } 10969 #endif 10970 10971 return rv; 10972 } 10973 10974 /* 10975 * Function: 10976 * bcm_esw_time_ts_counter_get 10977 * Purpose: 10978 * Get timestamper counter 10979 * Parameters: 10980 * unit - (IN) Unit number. 10981 * counter - (OUT) counter values 10982 * Returns: 10983 * BCM_E_xxx 10984 */ 10985 int 10986 bcm_esw_time_ts_counter_get( 10987 int unit, 10988 bcm_time_ts_counter_t *counter) 10989 { 10990 int rv = BCM_E_UNAVAIL; 10991 #if (defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT) || \ 10992 defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_MONTEREY_SUPPORT)) 10993 uint32 val_hi = 0, val_lo = 0; 10994 10995 if (counter == NULL) { 10996 return BCM_E_PARAM; 10997 } 10998 10999 #if defined(BCM_MONTEREY_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT) 11000 if(SOC_IS_MONTEREY(unit) || SOC_IS_TOMAHAWK3(unit)) { 11001 int ts_counter; 11002 uint32 regval; 11003 11004 11005 ts_counter = counter->ts_counter; 11006 11007 SOC_IF_ERROR_RETURN(_bcm_esw_time_counter_get(unit, ts_counter, &counter->ts_counter_ns)); 11008 11009 /* Read the enable status */ 11010 if (ts_counter == 1) { 11011 SOC_IF_ERROR_RETURN(READ_NS_TIMESYNC_TS1_COUNTER_ENABLEr(unit, ®val)); 11012 counter->enable = soc_reg_field_get(unit, NS_TIMESYNC_TS1_COUNTER_ENABLEr, regval, ENABLEf); 11013 } else if(ts_counter == 0) { 11014 SOC_IF_ERROR_RETURN(READ_NS_TIMESYNC_TS0_COUNTER_ENABLEr(unit, ®val)); 11015 counter->enable = soc_reg_field_get(unit, NS_TIMESYNC_TS0_COUNTER_ENABLEr, regval, ENABLEf); 11016 } else { 11017 return BCM_E_FAIL; 11018 } 11019 11020 if (SOC_IS_TOMAHAWK3(unit)) { 11021 uint32 freq_ctrl = 0, freq_ctrl_2 = 0; 11022 READ_NS_TIMESYNC_TS1_FREQ_CTRL_FRAC_UPPERr(unit, &freq_ctrl); 11023 READ_NS_TIMESYNC_TS1_FREQ_CTRL_FRAC_LOWERr(unit, &freq_ctrl_2); 11024 11025 if ((freq_ctrl == 0x2000) && (freq_ctrl_2 == 0)) { 11026 counter->time_format = bcmTimeFormatPTP; 11027 } else { 11028 counter->time_format = bcmTimeFormatNTP; 11029 } 11030 } else { 11031 counter->time_format = bcmTimeFormatPTP; 11032 } 11033 rv = BCM_E_NONE; 11034 } else 11035 #endif 11036 { 11037 uint32 freq_ctrl = 0; 11038 rv = READ_CMIC_TIMESYNC_TS1_FREQ_CTRL_FRACr(unit, &freq_ctrl); 11039 if(BCM_FAILURE(rv)) { 11040 return rv; 11041 } 11042 11043 if (freq_ctrl == 0x40000000) { 11044 counter->time_format = bcmTimeFormatPTP; 11045 } else { 11046 counter->time_format = bcmTimeFormatNTP; 11047 } 11048 11049 rv = READ_CMIC_TIMESYNC_TS1_FREQ_CTRL_UPPERr(unit, &val_hi); 11050 if(BCM_FAILURE(rv)) { 11051 return rv; 11052 } 11053 11054 rv = READ_CMIC_TIMESYNC_TS1_FREQ_CTRL_LOWERr(unit, &val_lo); 11055 if(BCM_FAILURE(rv)) { 11056 return rv; 11057 } 11058 11059 COMPILER_64_SET(counter->ts_counter_ns, val_hi, val_lo); 11060 11061 val_lo = 0; 11062 rv = READ_CMIC_TIMESYNC_TS1_COUNTER_ENABLEr(unit, &val_lo); 11063 11064 counter->enable = ((val_lo) ? 1 : 0); 11065 } 11066 #endif 11067 11068 return rv; 11069 } 11070 11071 11072 11073 /* 11074 * Function: 11075 * bcmi_time_tod_set 11076 * Purpose: 11077 * Internal function to update tod values. 11078 * Parameters: 11079 * unit - (IN) Unit number. 11080 * tod - (IN) Time of the day values. 11081 * stage - (IN) Stage where time needs to be updated. 11082 * Returns: 11083 * BCM_E_xxx 11084 */ 11085 int 11086 bcmi_time_tod_set( 11087 int unit, 11088 bcm_time_tod_t *tod, 11089 int stage) 11090 11091 { 11092 soc_mem_t mem = INVALIDm; 11093 #if defined(BCM_FLOWTRACKER_SUPPORT) 11094 bsc_ts_utc_conversion_entry_t ts_entry; 11095 #else 11096 egr_ts_utc_conversion_entry_t ts_entry; 11097 #endif /* BCM_FLOWTRACKER_SUPPORT */ 11098 uint64 check; 11099 uint32 u64_hi = 0xffff, u64_low = 0xffffffff; 11100 uint32 data_sec[2], data_nsec[2]; 11101 int rv = 0; 11102 11103 if (stage == 1 ) { 11104 mem = EGR_TS_UTC_CONVERSIONm; 11105 } 11106 #if defined(BCM_FLOWTRACKER_SUPPORT) 11107 else { 11108 mem = BSC_TS_UTC_CONVERSIONm; 11109 } 11110 #endif /* BCM_FLOWTRACKER_SUPPORT */ 11111 11112 /* coverity[dead_error_line] */ 11113 if(mem == INVALIDm) { 11114 return BCM_E_NONE; 11115 } 11116 11117 #if defined(BCM_FLOWTRACKER_SUPPORT) 11118 sal_memset(&ts_entry, 0, sizeof(bsc_ts_utc_conversion_entry_t)); 11119 #else 11120 sal_memset(&ts_entry, 0, sizeof(egr_ts_utc_conversion_entry_t)); 11121 #endif /* BCM_FLOWTRACKER_SUPPORT */ 11122 COMPILER_64_SET(check, u64_hi, u64_low); 11123 11124 if (COMPILER_64_GT(tod->ts.seconds, check)) { 11125 return BCM_E_PARAM; 11126 } 11127 if (COMPILER_64_GT(tod->ts_adjustment_counter_ns, check)) { 11128 return BCM_E_PARAM; 11129 } 11130 #if defined(BCM_FLOWTRACKER_SUPPORT) 11131 /* Set timestamp format. */ 11132 if (soc_mem_field_valid(unit, mem, TIMESTAMP_FORMATf)) { 11133 soc_mem_field32_set(unit, mem, (uint32 *)&ts_entry, TIMESTAMP_FORMATf, 11134 tod->time_format); 11135 } 11136 #endif /* BCM_FLOWTRACKER_SUPPORT */ 11137 /* Set Nanoseconds. */ 11138 if (soc_mem_field_valid(unit, mem, TIMESTAMP_TOD_NSECf)) { 11139 soc_mem_field32_set(unit, mem, (uint32 *)&ts_entry, TIMESTAMP_TOD_NSECf, 11140 tod->ts.nanoseconds); 11141 } 11142 11143 sal_memset(data_sec, 0, 2*sizeof(uint32)); 11144 COMPILER_64_TO_32_LO(data_sec[0], tod->ts.seconds); 11145 COMPILER_64_TO_32_HI(data_sec[1], tod->ts.seconds); 11146 11147 if (soc_mem_field_valid(unit, mem, TIMESTAMP_TOD_SECf)) { 11148 soc_mem_field_set(unit, mem, (uint32 *)&ts_entry, TIMESTAMP_TOD_SECf, 11149 data_sec); 11150 } 11151 11152 sal_memset(data_nsec, 0, 2*sizeof(uint32)); 11153 COMPILER_64_TO_32_LO(data_nsec[0], tod->ts_adjustment_counter_ns); 11154 COMPILER_64_TO_32_HI(data_nsec[1], tod->ts_adjustment_counter_ns); 11155 11156 if (soc_mem_field_valid(unit, mem, TIMESTAMP_TA_NSECf)) { 11157 soc_mem_field_set(unit, mem, (uint32 *)&ts_entry, TIMESTAMP_TA_NSECf, 11158 data_nsec); 11159 } 11160 11161 rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, 0, &ts_entry); 11162 11163 #if defined(BCM_TOMAHAWK3_SUPPORT) 11164 if ((SOC_IS_TOMAHAWK3(unit)) && (!BCM_FAILURE(rv))) { 11165 soc_mem_t mem_2 = EGR_TS_UTC_CONVERSION_2m; 11166 11167 if (soc_mem_field_valid(unit, mem_2, TIMESTAMP_TOD_NSECf)) { 11168 soc_mem_field32_set(unit, mem_2, (uint32 *)&ts_entry, TIMESTAMP_TOD_NSECf, 11169 tod->ts.nanoseconds); 11170 } 11171 if (soc_mem_field_valid(unit, mem_2, TIMESTAMP_TOD_SECf)) { 11172 soc_mem_field_set(unit, mem_2, (uint32 *)&ts_entry, TIMESTAMP_TOD_SECf, 11173 data_sec); 11174 } 11175 if (soc_mem_field_valid(unit, mem_2, TIMESTAMP_TA_NSECf)) { 11176 soc_mem_field_set(unit, mem_2, (uint32 *)&ts_entry, TIMESTAMP_TA_NSECf, 11177 data_nsec); 11178 } 11179 11180 rv = soc_mem_write(unit, mem_2, MEM_BLOCK_ALL, 0, &ts_entry); 11181 } 11182 #endif /* BCM_TOMAHAWK3_SUPPORT */ 11183 11184 return rv; 11185 } 11186 11187 /* 11188 * Function: 11189 * bcmi_time_tod_get 11190 * Purpose: 11191 * Internal function to get tod values for stage. 11192 * Parameters: 11193 * unit - (IN) Unit number. 11194 * tod - (OUT) Time of the day values. 11195 * stage - (IN) Stage where time needs to be updated. 11196 * Returns: 11197 * BCM_E_xxx 11198 */ 11199 int 11200 bcmi_time_tod_get( 11201 int unit, 11202 bcm_time_tod_t *tod, 11203 int stage) 11204 11205 { 11206 soc_mem_t mem = INVALIDm; 11207 #if defined(BCM_FLOWTRACKER_SUPPORT) 11208 bsc_ts_utc_conversion_entry_t ts_entry; 11209 #else 11210 egr_ts_utc_conversion_entry_t ts_entry; 11211 #endif /* BCM_FLOWTRACKER_SUPPORT */ 11212 uint32 data[2]; 11213 int rv = 0; 11214 11215 if (stage == 1 ) { 11216 mem = EGR_TS_UTC_CONVERSIONm; 11217 } 11218 #if defined(BCM_FLOWTRACKER_SUPPORT) 11219 else { 11220 mem = BSC_TS_UTC_CONVERSIONm; 11221 } 11222 #endif /* BCM_FLOWTRACKER_SUPPORT */ 11223 11224 /* coverity[dead_error_line] */ 11225 if(mem == INVALIDm) { 11226 return BCM_E_NONE; 11227 } 11228 #if defined(BCM_FLOWTRACKER_SUPPORT) 11229 sal_memset(&ts_entry, 0, sizeof(bsc_ts_utc_conversion_entry_t)); 11230 #else 11231 sal_memset(&ts_entry, 0, sizeof(egr_ts_utc_conversion_entry_t)); 11232 #endif 11233 rv = soc_mem_read(unit, mem, MEM_BLOCK_ALL, 0, &ts_entry); 11234 11235 if (BCM_FAILURE(rv)) { 11236 return rv; 11237 } 11238 #if defined(BCM_FLOWTRACKER_SUPPORT) 11239 /* Set timestamp format. */ 11240 if (soc_mem_field_valid(unit, mem, TIMESTAMP_FORMATf)) { 11241 tod->time_format = soc_mem_field32_get(unit, mem, (uint32 *)&ts_entry, 11242 TIMESTAMP_FORMATf); 11243 } 11244 #endif /* BCM_FLOWTRACKER_SUPPORT */ 11245 /* Set Nanoseconds. */ 11246 if (soc_mem_field_valid(unit, mem, TIMESTAMP_TOD_NSECf)) { 11247 tod->ts.nanoseconds = soc_mem_field32_get(unit, mem, (uint32 *)&ts_entry, 11248 TIMESTAMP_TOD_NSECf); 11249 } 11250 11251 sal_memset(data, 0, 2*sizeof(uint32)); 11252 11253 if (soc_mem_field_valid(unit, mem, TIMESTAMP_TOD_SECf)) { 11254 soc_mem_field_get(unit, mem, (uint32 *)&ts_entry, TIMESTAMP_TOD_SECf, 11255 data); 11256 } 11257 11258 COMPILER_64_SET(tod->ts.seconds, data[1], data[0]); 11259 11260 sal_memset(data, 0, 2*sizeof(uint32)); 11261 11262 if (soc_mem_field_valid(unit, mem, TIMESTAMP_TA_NSECf)) { 11263 soc_mem_field_get(unit, mem, (uint32 *)&ts_entry, TIMESTAMP_TA_NSECf, 11264 (uint32 *)&data); 11265 } 11266 11267 COMPILER_64_SET(tod->ts_adjustment_counter_ns, data[1], data[0]); 11268 11269 return BCM_E_NONE; 11270 } 11271 11272 /* 11273 * Function: 11274 * bcm_esw_time_tod_set 11275 * Purpose: 11276 * API to update tod values for stage. 11277 * Parameters: 11278 * unit - (IN) Unit number. 11279 * stages - (IN) Stage where time needs to be updated. 11280 * tod - (IN) Time of the day values. 11281 * Returns: 11282 * BCM_E_xxx 11283 */ 11284 int 11285 bcm_esw_time_tod_set( 11286 int unit, 11287 uint32 stages, 11288 bcm_time_tod_t *tod) 11289 { 11290 11291 int rv = BCM_E_UNAVAIL; 11292 11293 if (tod == NULL) { 11294 return BCM_E_PARAM; 11295 } 11296 11297 #if (defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT) || \ 11298 defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_MAVERICK2_SUPPORT)) 11299 if (stages & BCM_TIME_STAGE_ALL) { 11300 rv = bcmi_time_tod_set(unit, tod, 1); 11301 if (rv) { 11302 return rv; 11303 } 11304 11305 rv = bcmi_time_tod_set(unit, tod, 0); 11306 } else if (stages & BCM_TIME_STAGE_EGRESS) { 11307 rv = bcmi_time_tod_set(unit, tod, 1); 11308 } else if (stages & BCM_TIME_STAGE_INGRESS_FLOWTRACKER) { 11309 rv = bcmi_time_tod_set(unit, tod, 0); 11310 } else { 11311 return BCM_E_PARAM; 11312 } 11313 #endif 11314 11315 return rv; 11316 } 11317 11318 /* 11319 * Function: 11320 * bcm_esw_time_tod_get 11321 * Purpose: 11322 * API to get tod values for stage. 11323 * Parameters: 11324 * unit - (IN) Unit number. 11325 * stages - (IN) Stage where time needs to be updated. 11326 * tod - (IN) Time of the day values. 11327 * Returns: 11328 * BCM_E_xxx 11329 */ 11330 int 11331 bcm_esw_time_tod_get( 11332 int unit, 11333 uint32 stages, 11334 bcm_time_tod_t *tod) 11335 { 11336 int rv = BCM_E_UNAVAIL; 11337 11338 if (tod == NULL) { 11339 return BCM_E_PARAM; 11340 } 11341 11342 #if (defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT) || \ 11343 defined(BCM_TOMAHAWK2_SUPPORT)|| defined(BCM_MAVERICK2_SUPPORT)) 11344 if (stages & BCM_TIME_STAGE_ALL) { 11345 rv = bcmi_time_tod_get(unit, tod, 1); 11346 } else if (stages & BCM_TIME_STAGE_EGRESS) { 11347 rv = bcmi_time_tod_get(unit, tod, 1); 11348 } else if (stages & BCM_TIME_STAGE_INGRESS_FLOWTRACKER) { 11349 rv = bcmi_time_tod_get(unit, tod, 0); 11350 } else { 11351 return BCM_E_PARAM; 11352 } 11353 #endif 11354 11355 return rv; 11356 } 11357 11358 #if defined(BCM_MONTEREY_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT) 11359 int _bcm_esw_get_event_config_from_time_capture( 11360 int unit, 11361 bcm_time_capture_t *time_capture, 11362 _bcm_time_capture_input_t *time_capture_input) 11363 { 11364 time_capture_input->event_dest = _bcmTimeCaptureDestCPU; 11365 time_capture_input->event_divisor = time_capture->event_divisor; 11366 time_capture_input->port = time_capture->port; 11367 time_capture_input->port_event_type = time_capture->port_event_type; 11368 time_capture_input->ppm_check_enable = 0; /* Not valid for FIFO timestamp capture */ 11369 time_capture_input->ts_counter = time_capture->ts_counter; 11370 11371 switch (time_capture->flags){ 11372 case BCM_TIME_CAPTURE_LOCKED: 11373 case BCM_TIME_CAPTURE_L1_CLOCK_PRIMARY: 11374 case BCM_TIME_CAPTURE_L1_CLOCK_SECONDARY: 11375 case BCM_TIME_CAPTURE_IMMEDIATE: 11376 bsl_printf("Unable to find mapping for flag set in time_capture\n"); 11377 return BCM_E_NOT_FOUND; 11378 case BCM_TIME_CAPTURE_GPIO_0: 11379 time_capture_input->input_event = _bcmTimeCaptureEventGPIO0; 11380 break; 11381 case BCM_TIME_CAPTURE_GPIO_1: 11382 time_capture_input->input_event = _bcmTimeCaptureEventGPIO1; 11383 break; 11384 case BCM_TIME_CAPTURE_GPIO_2: 11385 time_capture_input->input_event = _bcmTimeCaptureEventGPIO2; 11386 break; 11387 case BCM_TIME_CAPTURE_GPIO_3: 11388 time_capture_input->input_event = _bcmTimeCaptureEventGPIO3; 11389 break; 11390 case BCM_TIME_CAPTURE_GPIO_4: 11391 time_capture_input->input_event = _bcmTimeCaptureEventGPIO4; 11392 break; 11393 case BCM_TIME_CAPTURE_GPIO_5: 11394 time_capture_input->input_event = _bcmTimeCaptureEventGPIO5; 11395 break; 11396 case BCM_TIME_CAPTURE_LCPLL: 11397 time_capture_input->input_event = _bcmTimeCaptureEventLCPLL0; 11398 break; 11399 case BCM_TIME_CAPTURE_IP_DM_0: 11400 time_capture_input->input_event = _bcmTimeCaptureEventIPDM0; 11401 break; 11402 case BCM_TIME_CAPTURE_IP_DM_1: 11403 time_capture_input->input_event = _bcmTimeCaptureEventIPDM1; 11404 break; 11405 case BCM_TIME_CAPTURE_BS0HB: 11406 time_capture_input->input_event = _bcmTimeCaptureEventBS0HB; 11407 break; 11408 case BCM_TIME_CAPTURE_BS1HB: 11409 time_capture_input->input_event = _bcmTimeCaptureEventBS1HB; 11410 break; 11411 case BCM_TIME_CAPTURE_TS1TS: 11412 time_capture_input->input_event = _bcmTimeCaptureEventTS1TS; 11413 break; 11414 case BCM_TIME_CAPTURE_BS0PLL: 11415 time_capture_input->input_event = _bcmTimeCaptureEventBS0PLL; 11416 break; 11417 case BCM_TIME_CAPTURE_BS1PLL: 11418 time_capture_input->input_event = _bcmTimeCaptureEventBS1PLL; 11419 break; 11420 case BCM_TIME_CAPTURE_RSVD1IF: 11421 if (SOC_IS_TOMAHAWK3(unit)){ 11422 bsl_printf("Unable to find mapping for flag set in time_capture\n"); 11423 return BCM_E_NOT_FOUND; 11424 } else if (SOC_IS_MONTEREY(unit)){ 11425 time_capture_input->input_event = _bcmTimeCaptureEventRSVD1IF; 11426 } 11427 break; 11428 case BCM_TIME_CAPTURE_RSVD1RF: 11429 if (SOC_IS_TOMAHAWK3(unit)){ 11430 bsl_printf("Unable to find mapping for flag set in time_capture\n"); 11431 return BCM_E_NOT_FOUND; 11432 } else if (SOC_IS_MONTEREY(unit)){ 11433 time_capture_input->input_event = _bcmTimeCaptureEventRSVD1RF; 11434 } 11435 break; 11436 case BCM_TIME_CAPTURE_BS0CONVTC: 11437 time_capture_input->input_event = _bcmTimeCaptureEventBS0ConvTC; 11438 break; 11439 case BCM_TIME_CAPTURE_BS1CONVTC: 11440 time_capture_input->input_event = _bcmTimeCaptureEventBS1ConvTC; 11441 break; 11442 case BCM_TIME_CAPTURE_LCPLL1: 11443 time_capture_input->input_event = _bcmTimeCaptureEventLCPLL1; 11444 break; 11445 case BCM_TIME_CAPTURE_LCPLL2: 11446 time_capture_input->input_event = _bcmTimeCaptureEventLCPLL2; 11447 break; 11448 case BCM_TIME_CAPTURE_LCPLL3: 11449 time_capture_input->input_event = _bcmTimeCaptureEventLCPLL3; 11450 break; 11451 case BCM_TIME_CAPTURE_PORT: 11452 if (SOC_IS_TOMAHAWK3(unit)){ 11453 bsl_printf("Unable to find mapping for flag set in time_capture\n"); 11454 return BCM_E_NOT_FOUND; 11455 } else if (SOC_IS_MONTEREY(unit)){ 11456 time_capture_input->input_event = _bcmTimeCaptureEventPORT; 11457 } 11458 break; 11459 } 11460 return BCM_E_NONE; 11461 } 11462 11463 11464 STATIC int _bcm_esw_time_portmap_get(int unit, bcm_port_t port, int *pTimePort) 11465 { 11466 int rv = BCM_E_NONE; 11467 11468 /* Following is the mapping in Monterey */ 11469 if ((port >= 1) && (port <= BCM_TIME_CAPTURE_NUM_PORTS)) { 11470 *pTimePort = port - 1; 11471 } else { 11472 LOG_ERROR(BSL_LS_SOC_COMMON, 11473 (BSL_META_U(unit, 11474 "_bcm_esw_time_portmap_get: Error !! Invalid port\n"))); 11475 *pTimePort = BCM_TIME_CAPTURE_NUM_PORTS; 11476 rv = BCM_E_PARAM; 11477 } 11478 11479 return rv; 11480 } 11481 11482 STATIC int 11483 _bcm_esw_time_input_eventId_get(int unit, 11484 _bcm_time_capture_input_t *pInputEvent, 11485 uint32 *pEventId) 11486 { 11487 int rv = BCM_E_NONE; 11488 int idx = 0; 11489 11490 if ((pEventId==NULL) || 11491 (pInputEvent->input_event < _bcmTimeCaptureEventCpu) || 11492 (pInputEvent->input_event >= _bcmTimeCaptureEventMax)) { 11493 LOG_ERROR(BSL_LS_SOC_COMMON, 11494 (BSL_META_U(unit, 11495 "input_eventId_get: Error !! Wrong event\n"))); 11496 rv = BCM_E_PARAM; 11497 goto exit; 11498 } 11499 11500 /* EventId 0 to 191 for port events, 11501 * EventId 192 to 213 for EventCpu to EventLCPLL3 11502 * EventId 214 for R5 11503 */ 11504 switch ((int)pInputEvent->input_event) { 11505 case _bcmTimeCaptureEventPORT: 11506 if (pInputEvent->port < 0 || pInputEvent->port > BCM_TIME_CAPTURE_NUM_PORTS){ 11507 LOG_ERROR(BSL_LS_SOC_COMMON, 11508 (BSL_META_U(unit, 11509 "input_eventId_get: Error !! Wrong port\n"))); 11510 rv = BCM_E_PARAM; 11511 goto exit; 11512 } 11513 11514 if ((pInputEvent->port_event_type == bcmTimePortEventRXCDR) || 11515 (pInputEvent->port_event_type == bcmTimePortEventRXSOF)){ 11516 /* Event could be TXSOF or TXPI based on port type */ 11517 idx = pInputEvent->port*2; 11518 } else if (pInputEvent->port_event_type == bcmTimePortEventROE) { 11519 idx = pInputEvent->port*2 + 1; 11520 } else if ((pInputEvent->port_event_type == bcmTimePortEventTXSOF) || 11521 (pInputEvent->port_event_type == bcmTimePortEventTXPI)){ 11522 /* Event could be TXSOF or TXPI based on port type */ 11523 idx = BCM_TIME_CAPTURE_IA_START_TXPI_TXSOF + pInputEvent->port; 11524 } else { 11525 LOG_ERROR(BSL_LS_SOC_COMMON, 11526 (BSL_META_U(unit, 11527 "input_eventId_get: Error !! Wrong param\n"))); 11528 rv = BCM_E_PARAM; 11529 goto exit; 11530 } 11531 break; 11532 11533 case _bcmTimeCaptureEventR5: 11534 idx = BCM_TIME_CAPTURE_IA_START_R5; 11535 break; 11536 11537 default: 11538 idx = BCM_TIME_CAPTURE_IA_START_MISC + pInputEvent->input_event; 11539 } 11540 11541 *pEventId = idx; 11542 11543 exit: 11544 return rv; 11545 } 11546 11547 STATIC int 11548 _bcm_esw_time_event_divisor_misc_set(int unit, _bcm_time_capture_event_t event_misc, 11549 uint32 divisor) 11550 { 11551 int rv = BCM_E_NONE; 11552 int idx = 0; 11553 uint32 regVal = 0; 11554 11555 switch (event_misc) { 11556 case _bcmTimeCaptureEventCpu: 11557 case _bcmTimeCaptureEventBS0HB: 11558 case _bcmTimeCaptureEventBS1HB: 11559 case _bcmTimeCaptureEventIPDM0: 11560 case _bcmTimeCaptureEventIPDM1: 11561 case _bcmTimeCaptureEventTS1TS: 11562 case _bcmTimeCaptureEventRSVD1IF: 11563 case _bcmTimeCaptureEventRSVD1RF: 11564 case _bcmTimeCaptureEventBS0ConvTC: 11565 case _bcmTimeCaptureEventBS1ConvTC: 11566 /* No divider */ 11567 bsl_printf("BCM_TIME: event_divisor_misc_set: No divider for event:%d \n", event_misc); 11568 break; 11569 11570 case _bcmTimeCaptureEventGPIO0: 11571 case _bcmTimeCaptureEventGPIO1: 11572 case _bcmTimeCaptureEventGPIO2: 11573 case _bcmTimeCaptureEventGPIO3: 11574 case _bcmTimeCaptureEventGPIO4: 11575 case _bcmTimeCaptureEventGPIO5: 11576 idx = event_misc - _bcmTimeCaptureEventGPIO0; 11577 BCM_TIME_READ_NS_REGr(unit, _bcm_time_gpio_regs[idx], 0, ®Val); 11578 soc_reg_field_set(unit, _bcm_time_gpio_regs[idx], ®Val, 11579 DIVISORf, divisor); 11580 BCM_TIME_WRITE_NS_REGr(unit, _bcm_time_gpio_regs[idx], 0, regVal); 11581 break; 11582 11583 case _bcmTimeCaptureEventBS0PLL: 11584 case _bcmTimeCaptureEventBS1PLL: 11585 idx = event_misc - _bcmTimeCaptureEventBS0PLL; 11586 BCM_TIME_READ_NS_REGr(unit, _bcm_time_bs_pll_regs[idx], 0, ®Val); 11587 soc_reg_field_set(unit, _bcm_time_bs_pll_regs[idx], ®Val, 11588 DIVISORf, divisor); 11589 BCM_TIME_WRITE_NS_REGr(unit, _bcm_time_bs_pll_regs[idx], 0, regVal); 11590 break; 11591 11592 case _bcmTimeCaptureEventLCPLL0: 11593 case _bcmTimeCaptureEventLCPLL1: 11594 case _bcmTimeCaptureEventLCPLL2: 11595 case _bcmTimeCaptureEventLCPLL3: 11596 idx = event_misc - _bcmTimeCaptureEventLCPLL0; 11597 BCM_TIME_READ_NS_REGr(unit, NS_TIMESYNC_SERDES_LCPLL_EVENT_CTRLr, idx, ®Val); 11598 soc_reg_field_set(unit, NS_TIMESYNC_SERDES_LCPLL_EVENT_CTRLr, ®Val, 11599 DIVISORf, divisor); 11600 BCM_TIME_WRITE_NS_REGr(unit, NS_TIMESYNC_SERDES_LCPLL_EVENT_CTRLr, idx, regVal); 11601 break; 11602 11603 default: 11604 LOG_ERROR(BSL_LS_SOC_COMMON, 11605 (BSL_META_U(unit, 11606 "event_divisor_misc_set: Error !! wrong param\n"))); 11607 rv = BCM_E_PARAM; 11608 goto exit; 11609 } 11610 11611 exit: 11612 return (rv); 11613 } 11614 11615 STATIC int 11616 _bcm_esw_time_event_dest_misc_set(int unit, _bcm_time_capture_event_t event_misc, 11617 _bcm_time_capture_dest_cfg_t *pEventDest, 11618 uint32 eventId) 11619 { 11620 int rv = BCM_E_NONE; 11621 int idx = 0; 11622 uint32 regVal = 0; 11623 uint32 dest; 11624 uint32 chkProfile; 11625 11626 if (event_misc < _bcmTimeCaptureEventCpu || 11627 event_misc > _bcmTimeCaptureEventLCPLL3) { 11628 LOG_ERROR(BSL_LS_SOC_COMMON, 11629 (BSL_META_U(unit, 11630 "event_dest_misc_set: Error !! Wrong param\n"))); 11631 rv = BCM_E_PARAM; 11632 goto exit; 11633 } 11634 11635 /* Since we have 150 numels of NS_TIMESYNC_TS_EVENT_FWD_CFG, 11636 * the miscellaneous events starts from index 128 per table 6.4 in uArch 11637 */ 11638 idx = 128 + event_misc; 11639 11640 if (pEventDest->event_dest == _bcmTimeCaptureDestCPU) { 11641 dest = 0; 11642 }else if (pEventDest->event_dest == _bcmTimeCaptureDestM7) { 11643 dest = 1; 11644 }else if (pEventDest->event_dest == _bcmTimeCaptureDestALL) { 11645 dest = 2; 11646 }else { 11647 LOG_ERROR(BSL_LS_SOC_COMMON, 11648 (BSL_META_U(unit, 11649 "event_dest_misc_set: Error !! wrong event dest\n"))); 11650 rv = BCM_E_PARAM; 11651 goto exit; 11652 } 11653 11654 11655 chkProfile = 0; 11656 11657 BCM_TIME_READ_NS_REGr(unit, NS_TIMESYNC_TS_EVENT_FWD_CFGr, idx, ®Val); 11658 11659 soc_reg_field_set(unit, NS_TIMESYNC_TS_EVENT_FWD_CFGr, ®Val, 11660 EVENT_IDf, eventId); 11661 11662 dest |= soc_reg_field_get(unit, NS_TIMESYNC_TS_EVENT_FWD_CFGr, 11663 regVal, DESTf); 11664 soc_reg_field_set(unit, NS_TIMESYNC_TS_EVENT_FWD_CFGr, ®Val, 11665 DESTf, dest); 11666 /*soc_reg_field_set(unit, NS_TIMESYNC_TS_EVENT_FWD_CFGr, ®Val, 11667 DPLL_ADDRf, *eventId);*/ 11668 soc_reg_field_set(unit, NS_TIMESYNC_TS_EVENT_FWD_CFGr, ®Val, 11669 GDPLL_TSf, pEventDest->ts_counter ? 1:0); 11670 soc_reg_field_set(unit, NS_TIMESYNC_TS_EVENT_FWD_CFGr, ®Val, 11671 PPM_CHECK_ENABLEf, pEventDest->ppm_check_enable ? 1:0); 11672 soc_reg_field_set(unit, NS_TIMESYNC_TS_EVENT_FWD_CFGr, ®Val, 11673 SRC_TS_COUNTERf, pEventDest->ts_counter ? 1:0); 11674 soc_reg_field_set(unit, NS_TIMESYNC_TS_EVENT_FWD_CFGr, ®Val, 11675 CHK_PROFILEf, chkProfile); 11676 BCM_TIME_WRITE_NS_REGr(unit, NS_TIMESYNC_TS_EVENT_FWD_CFGr, idx, regVal); 11677 11678 exit: 11679 return (rv); 11680 } 11681 11682 STATIC int 11683 _bcm_esw_time_event_divisor_port_set(int unit, bcm_port_t port, 11684 bcm_time_port_event_t port_event_type, uint32 divisor) 11685 { 11686 int rv = BCM_E_NONE; 11687 int idx = 0; 11688 uint32 regVal = 0; 11689 11690 if (port > BCM_TIME_CAPTURE_NUM_PORTS) { 11691 LOG_ERROR(BSL_LS_SOC_COMMON, 11692 (BSL_META_U(unit, 11693 "event_divisor_port_set: Error !! wrong port \n"))); 11694 rv = BCM_E_PARAM; 11695 goto exit; 11696 } 11697 11698 idx = port; 11699 switch (port_event_type) { 11700 case bcmTimePortEventRXSOF: 11701 case bcmTimePortEventTXSOF: 11702 case bcmTimePortEventROE: 11703 LOG_ERROR(BSL_LS_SOC_COMMON, 11704 (BSL_META_U(unit, 11705 "event_divisor_port_set: Error !! No divisor\n"))); 11706 rv = BCM_E_UNAVAIL; 11707 break; 11708 11709 case bcmTimePortEventRXCDR: 11710 BCM_TIME_READ_NS_REGr(unit, NS_TIMESYNC_RX_CDR_EVENT_CTRLr, idx, ®Val); 11711 soc_reg_field_set(unit, NS_TIMESYNC_RX_CDR_EVENT_CTRLr, ®Val, 11712 DIVISORf, divisor); 11713 BCM_TIME_WRITE_NS_REGr(unit, NS_TIMESYNC_RX_CDR_EVENT_CTRLr, idx, regVal); 11714 break; 11715 11716 case bcmTimePortEventTXPI: 11717 BCM_TIME_READ_NS_REGr(unit, NS_TIMESYNC_TX_PI_CLK_EVENT_CTRLr, idx, ®Val); 11718 soc_reg_field_set(unit, NS_TIMESYNC_TX_PI_CLK_EVENT_CTRLr, ®Val, 11719 DIVISORf, divisor); 11720 BCM_TIME_WRITE_NS_REGr(unit, NS_TIMESYNC_TX_PI_CLK_EVENT_CTRLr, idx, regVal); 11721 break; 11722 11723 default: 11724 LOG_ERROR(BSL_LS_SOC_COMMON, 11725 (BSL_META_U(unit, 11726 "event_divisor_port_set: Error !! Wrong param\n"))); 11727 rv = BCM_E_PARAM; 11728 } 11729 11730 exit: 11731 return (rv); 11732 } 11733 11734 STATIC int 11735 _bcm_esw_time_event_dest_port_set (int unit, bcm_port_t port, 11736 bcm_time_port_event_t port_event_type, 11737 _bcm_time_capture_dest_cfg_t *pEventDest, 11738 uint32 eventId) 11739 { 11740 int rv = BCM_E_NONE; 11741 int idx = 0; 11742 uint32 regVal = 0; 11743 uint32 dest; 11744 uint32 chkProfile; 11745 11746 if (port >= BCM_TIME_CAPTURE_NUM_PORTS) { 11747 LOG_ERROR(BSL_LS_SOC_COMMON, 11748 (BSL_META_U(unit, 11749 "event_dest_port_set: Error !! wrong param\n"))); 11750 rv = BCM_E_PARAM; 11751 goto exit; 11752 } 11753 11754 11755 if (pEventDest->event_dest == _bcmTimeCaptureDestCPU) { 11756 dest = 0; 11757 }else if (pEventDest->event_dest == _bcmTimeCaptureDestM7) { 11758 dest = 1; 11759 }else if (pEventDest->event_dest == _bcmTimeCaptureDestALL) { 11760 dest = 2; 11761 }else { 11762 LOG_ERROR(BSL_LS_SOC_COMMON, 11763 (BSL_META_U(unit, 11764 "event_dest_port_set: Error !! wrong event dest\n"))); 11765 rv = BCM_E_PARAM; 11766 goto exit; 11767 } 11768 11769 11770 chkProfile = 0; 11771 11772 switch(port_event_type) { 11773 case bcmTimePortEventRXCDR: 11774 case bcmTimePortEventTXPI: 11775 if (port_event_type == bcmTimePortEventRXCDR){ 11776 idx = port; 11777 }else if (port_event_type == bcmTimePortEventTXPI) { 11778 idx = port + BCM_TIME_CAPTURE_NUM_PORTS; 11779 } 11780 11781 bsl_printf("BCM_TIME: Setting NS_TIMESYNC_TS_EVENT_FWD_CFG idx:%d\n", 11782 idx); 11783 11784 BCM_TIME_READ_NS_REGr(unit, NS_TIMESYNC_TS_EVENT_FWD_CFGr, idx, ®Val); 11785 soc_reg_field_set(unit, NS_TIMESYNC_TS_EVENT_FWD_CFGr, ®Val, 11786 EVENT_IDf, eventId); 11787 dest |= soc_reg_field_get(unit, NS_TIMESYNC_TS_EVENT_FWD_CFGr, 11788 regVal, DESTf); 11789 soc_reg_field_set(unit, NS_TIMESYNC_TS_EVENT_FWD_CFGr, ®Val, 11790 DESTf, dest); 11791 /*soc_reg_field_set(unit, NS_TIMESYNC_TS_EVENT_FWD_CFGr, ®Val, 11792 DPLL_ADDRf, *pIaAddr);*/ 11793 soc_reg_field_set(unit, NS_TIMESYNC_TS_EVENT_FWD_CFGr, ®Val, 11794 GDPLL_TSf, pEventDest->ts_counter ? 1:0); 11795 soc_reg_field_set(unit, NS_TIMESYNC_TS_EVENT_FWD_CFGr, ®Val, 11796 PPM_CHECK_ENABLEf, pEventDest->ppm_check_enable ? 1:0); 11797 soc_reg_field_set(unit, NS_TIMESYNC_TS_EVENT_FWD_CFGr, ®Val, 11798 SRC_TS_COUNTERf, pEventDest->ts_counter ? 1:0); 11799 soc_reg_field_set(unit, NS_TIMESYNC_TS_EVENT_FWD_CFGr, ®Val, 11800 CHK_PROFILEf, chkProfile); 11801 BCM_TIME_WRITE_NS_REGr(unit, NS_TIMESYNC_TS_EVENT_FWD_CFGr, idx, regVal); 11802 11803 break; 11804 11805 case bcmTimePortEventRXSOF: /* Type-0 */ 11806 case bcmTimePortEventTXSOF: /* Type-1 */ 11807 case bcmTimePortEventROE: /* Type-2 */ 11808 /* 11809 * Having 128 Numels, register map is 11810 * Port-0: type-0, type-1, type-2, unused 11811 * Port-1: type-0, type-1, type-2, unused 11812 */ 11813 if ((port >= BCM_TIME_CAPTURE_NUM_CPRI_PORTS) || (port < 0)) { 11814 LOG_ERROR(BSL_LS_SOC_COMMON, 11815 (BSL_META_U(unit, 11816 "event_dest_port_set: Error !! Invalid CPRI port\n"))); 11817 rv = BCM_E_PARAM; 11818 goto exit; 11819 } 11820 11821 idx = port*4; 11822 if (port_event_type == bcmTimePortEventTXSOF) { 11823 idx = idx + 1; 11824 }else if (port_event_type == bcmTimePortEventROE) { 11825 idx = idx + 2; 11826 } 11827 11828 bsl_printf("BCM_TIME: Setting NS_TIMESYNC_MAPPER_FWD_CFG idx:%d\n", 11829 idx); 11830 BCM_TIME_READ_NS_REGr(unit, NS_TIMESYNC_MAPPER_FWD_CFGr, idx, ®Val); 11831 soc_reg_field_set(unit, NS_TIMESYNC_MAPPER_FWD_CFGr, ®Val, 11832 EVENT_IDf, eventId); 11833 dest |= soc_reg_field_get(unit, NS_TIMESYNC_MAPPER_FWD_CFGr, 11834 regVal, DESTf); 11835 soc_reg_field_set(unit, NS_TIMESYNC_MAPPER_FWD_CFGr, ®Val, 11836 DESTf, dest); 11837 /*soc_reg_field_set(unit, NS_TIMESYNC_MAPPER_FWD_CFGr, ®Val, 11838 DPLL_ADDRf, *pIaAddr);*/ 11839 soc_reg_field_set(unit, NS_TIMESYNC_MAPPER_FWD_CFGr, ®Val, 11840 PPM_CHECK_ENABLEf, pEventDest->ppm_check_enable ? 1:0); 11841 soc_reg_field_set(unit, NS_TIMESYNC_MAPPER_FWD_CFGr, ®Val, 11842 SRC_TS_COUNTERf, 1); /* It is TS1 counter */ 11843 soc_reg_field_set(unit, NS_TIMESYNC_MAPPER_FWD_CFGr, ®Val, 11844 CHK_PROFILEf, chkProfile); 11845 BCM_TIME_WRITE_NS_REGr(unit, NS_TIMESYNC_MAPPER_FWD_CFGr, idx, regVal); 11846 break; 11847 11848 default: 11849 LOG_ERROR(BSL_LS_SOC_COMMON, 11850 (BSL_META_U(unit, 11851 "event_dest_port_set: Error !! wrong event\n"))); 11852 rv = BCM_E_PARAM; 11853 goto exit; 11854 } 11855 11856 exit: 11857 return (rv); 11858 } 11859 11860 STATIC int 11861 _bcm_esw_time_event_roe_52b_set(int unit, bcm_port_t port, int enable) 11862 { 11863 int rv = BCM_E_NONE; 11864 uint32 enable_field = 0; 11865 uint32 regVal = 0; 11866 uint32 reg_enable = 0; 11867 11868 /* Program NS_TIMESYNC_MAPPER_TYPE2_FORMAT */ 11869 11870 enable_field = 1 << port; 11871 11872 BCM_TIME_READ_NS_REGr(unit, NS_TIMESYNC_MAPPER_TYPE2_FORMATr, port, ®Val); 11873 reg_enable = soc_reg_field_get(unit, NS_TIMESYNC_MAPPER_TYPE2_FORMATr, regVal, CONV_ENf); 11874 11875 reg_enable = enable ? (reg_enable | enable_field) : (reg_enable & (~enable_field)); 11876 11877 soc_reg_field_set(unit, NS_TIMESYNC_MAPPER_TYPE2_FORMATr, ®Val, CONV_ENf, reg_enable); 11878 BCM_TIME_WRITE_NS_REGr(unit, NS_TIMESYNC_MAPPER_TYPE2_FORMATr, port, regVal); 11879 11880 return (rv); 11881 } 11882 11883 STATIC int 11884 _bcm_esw_time_capture_enable_misc_set(int unit, _bcm_time_capture_event_t event_misc, 11885 int enable) 11886 { 11887 int rv = BCM_E_NONE; 11888 uint32 idx = 0; 11889 uint32 enable_field = 0; 11890 uint32 regVal = 0; 11891 uint32 reg_enable; 11892 11893 /* 11894 NS_MISC_CLK_EVENT_CTRL 11895 NS_TIMESYNC_SERDES_LCPLL_EVENT_CTRL 11896 NS_BROADSYNC0_CLK_EVENT_CTRL 11897 NS_BROADSYNC1_CLK_EVENT_CTRL 11898 NS_TIMESYNC_GPIO_x_CTRL 11899 */ 11900 switch (event_misc){ 11901 case _bcmTimeCaptureEventCpu: 11902 if (event_misc == _bcmTimeCaptureEventCpu) { 11903 enable_field = BCM_TIME_CAPTURE_MISC_EVENT_EN_CPU; 11904 } 11905 case _bcmTimeCaptureEventBS0HB: 11906 if (event_misc == _bcmTimeCaptureEventBS0HB) { 11907 enable_field = BCM_TIME_CAPTURE_MISC_EVENT_EN_BS0HB; 11908 } 11909 case _bcmTimeCaptureEventBS1HB: 11910 if (event_misc == _bcmTimeCaptureEventBS1HB) { 11911 enable_field = BCM_TIME_CAPTURE_MISC_EVENT_EN_BS1HB; 11912 } 11913 case _bcmTimeCaptureEventIPDM0: 11914 if (event_misc == _bcmTimeCaptureEventIPDM0) { 11915 enable_field = BCM_TIME_CAPTURE_MISC_EVENT_EN_IPDM0; 11916 } 11917 case _bcmTimeCaptureEventIPDM1: 11918 if (event_misc == _bcmTimeCaptureEventIPDM1) { 11919 enable_field = BCM_TIME_CAPTURE_MISC_EVENT_EN_IPDM1; 11920 } 11921 case _bcmTimeCaptureEventTS1TS: 11922 if (event_misc == _bcmTimeCaptureEventTS1TS) { 11923 enable_field = BCM_TIME_CAPTURE_MISC_EVENT_EN_TS1; 11924 } 11925 case _bcmTimeCaptureEventRSVD1IF: 11926 if (event_misc == _bcmTimeCaptureEventRSVD1IF) { 11927 enable_field = BCM_TIME_CAPTURE_MISC_EVENT_EN_RSVD1IF; 11928 } 11929 case _bcmTimeCaptureEventRSVD1RF: 11930 if (event_misc == _bcmTimeCaptureEventRSVD1RF) { 11931 enable_field = BCM_TIME_CAPTURE_MISC_EVENT_EN_RSVD1RF; 11932 } 11933 case _bcmTimeCaptureEventBS0ConvTC: 11934 if (event_misc == _bcmTimeCaptureEventBS0ConvTC) { 11935 enable_field = BCM_TIME_CAPTURE_MISC_EVENT_EN_BS0CONV; 11936 } 11937 case _bcmTimeCaptureEventBS1ConvTC: 11938 if (event_misc == _bcmTimeCaptureEventBS1ConvTC) { 11939 enable_field = BCM_TIME_CAPTURE_MISC_EVENT_EN_BS1CONV; 11940 } 11941 11942 /* Write the enable flag */ 11943 BCM_TIME_READ_NS_REGr(unit, NS_MISC_CLK_EVENT_CTRLr, 0, ®Val); 11944 reg_enable = soc_reg_field_get(unit, NS_MISC_CLK_EVENT_CTRLr, regVal, ENABLEf); 11945 11946 reg_enable = enable ? (reg_enable | enable_field) : (reg_enable & (~enable_field)); 11947 11948 soc_reg_field_set(unit, NS_MISC_CLK_EVENT_CTRLr, ®Val, 11949 ENABLEf, reg_enable); 11950 BCM_TIME_WRITE_NS_REGr(unit, NS_MISC_CLK_EVENT_CTRLr, 0, regVal); 11951 break; 11952 11953 case _bcmTimeCaptureEventGPIO0: 11954 case _bcmTimeCaptureEventGPIO1: 11955 case _bcmTimeCaptureEventGPIO2: 11956 case _bcmTimeCaptureEventGPIO3: 11957 case _bcmTimeCaptureEventGPIO4: 11958 case _bcmTimeCaptureEventGPIO5: 11959 idx = event_misc - _bcmTimeCaptureEventGPIO0; 11960 BCM_TIME_READ_NS_REGr(unit, _bcm_time_gpio_regs[idx], 0, ®Val); 11961 #ifndef INCLUDE_GDPLL 11962 soc_reg_field_set(unit, _bcm_time_gpio_regs[idx], ®Val, 11963 CAPTURE_ENABLEf, enable ? 1:0); 11964 #endif 11965 BCM_TIME_WRITE_NS_REGr(unit, _bcm_time_gpio_regs[idx], 0, regVal); 11966 break; 11967 11968 case _bcmTimeCaptureEventBS0PLL: 11969 case _bcmTimeCaptureEventBS1PLL: 11970 idx = event_misc - _bcmTimeCaptureEventBS0PLL; 11971 BCM_TIME_READ_NS_REGr(unit, _bcm_time_bs_pll_regs[idx], 0, ®Val); 11972 soc_reg_field_set(unit, _bcm_time_bs_pll_regs[idx], ®Val, 11973 ENABLEf, enable ? 1:0); 11974 BCM_TIME_WRITE_NS_REGr(unit, _bcm_time_bs_pll_regs[idx], 0, regVal); 11975 break; 11976 11977 case _bcmTimeCaptureEventLCPLL0: 11978 case _bcmTimeCaptureEventLCPLL1: 11979 case _bcmTimeCaptureEventLCPLL2: 11980 case _bcmTimeCaptureEventLCPLL3: 11981 idx = event_misc - _bcmTimeCaptureEventLCPLL0; 11982 BCM_TIME_READ_NS_REGr(unit, NS_TIMESYNC_SERDES_LCPLL_EVENT_CTRLr, idx, ®Val); 11983 soc_reg_field_set(unit, NS_TIMESYNC_SERDES_LCPLL_EVENT_CTRLr, ®Val, 11984 ENABLEf, enable ? 1:0); 11985 BCM_TIME_WRITE_NS_REGr(unit, NS_TIMESYNC_SERDES_LCPLL_EVENT_CTRLr, idx, regVal); 11986 break; 11987 11988 case _bcmTimeCaptureEventPORT: 11989 default: 11990 LOG_ERROR(BSL_LS_SOC_COMMON, 11991 (BSL_META_U(unit, 11992 "event_enable_misc_set: Error !! wrong event\n"))); 11993 rv = BCM_E_PARAM; 11994 goto exit; 11995 } 11996 11997 exit: 11998 return (rv); 11999 } 12000 12001 STATIC int 12002 _bcm_esw_time_capture_enable_port_set(int unit, bcm_port_t port, bcm_time_port_event_t port_event_type, 12003 int enable) 12004 { 12005 int rv = BCM_E_NONE; 12006 uint32 mapper_reg; 12007 uint32 regVal = 0; 12008 uint32 enable_field = 0; 12009 uint32 reg_enable = 0; 12010 12011 if (port >= BCM_TIME_CAPTURE_NUM_PORTS) { 12012 LOG_ERROR(BSL_LS_SOC_COMMON, 12013 (BSL_META_U(unit, 12014 "event_enable_port_set: Error !! wrong port\n"))); 12015 rv = BCM_E_PARAM; 12016 goto exit; 12017 } 12018 12019 switch (port_event_type) { 12020 case bcmTimePortEventRXSOF: 12021 case bcmTimePortEventTXSOF: 12022 case bcmTimePortEventROE: 12023 /* NS has support to 32 CPRI ports */ 12024 if ((port >= BCM_TIME_CAPTURE_NUM_CPRI_PORTS) || (port < 0)) { 12025 LOG_ERROR(BSL_LS_SOC_COMMON, 12026 (BSL_META_U(unit, 12027 "event_enable_port_set: Error !! wrong port or non-cpri\n"))); 12028 rv = BCM_E_PARAM; 12029 goto exit; 12030 } 12031 12032 /* Program NS_TIMESYNC_MAPPER_PORT_ENABLE_x */ 12033 enable_field = 1 << (port_event_type - bcmTimePortEventRXSOF); 12034 mapper_reg = port/8; 12035 12036 BCM_TIME_READ_NS_REGr(unit, __bcm_time_mapper_port_enable_regs[mapper_reg], 0, ®Val); 12037 reg_enable = soc_reg_field_get(unit, __bcm_time_mapper_port_enable_regs[mapper_reg], regVal, _bcm_time_mapper_port_enable[port]); 12038 12039 reg_enable = enable ? (reg_enable | enable_field) : (reg_enable & (~enable_field)); 12040 12041 soc_reg_field_set(unit, __bcm_time_mapper_port_enable_regs[mapper_reg], ®Val, _bcm_time_mapper_port_enable[port], reg_enable); 12042 BCM_TIME_WRITE_NS_REGr(unit, __bcm_time_mapper_port_enable_regs[mapper_reg], 0, regVal); 12043 12044 break; 12045 12046 case bcmTimePortEventRXCDR: 12047 /* Program NS_TIMESYNC_RX_CDR_EVENT_CTRL */ 12048 BCM_TIME_READ_NS_REGr(unit, NS_TIMESYNC_RX_CDR_EVENT_CTRLr, port, ®Val); 12049 soc_reg_field_set(unit, NS_TIMESYNC_RX_CDR_EVENT_CTRLr, ®Val, ENABLEf, enable ? 1:0); 12050 BCM_TIME_WRITE_NS_REGr(unit, NS_TIMESYNC_RX_CDR_EVENT_CTRLr, port, regVal); 12051 break; 12052 12053 case bcmTimePortEventTXPI: 12054 /* Program NS_TIMESYNC_TX_PI_CLK_EVENT_CTRL */ 12055 BCM_TIME_READ_NS_REGr(unit, NS_TIMESYNC_TX_PI_CLK_EVENT_CTRLr, port, ®Val); 12056 soc_reg_field_set(unit, NS_TIMESYNC_TX_PI_CLK_EVENT_CTRLr, ®Val, ENABLEf, enable ? 1:0); 12057 BCM_TIME_WRITE_NS_REGr(unit, NS_TIMESYNC_TX_PI_CLK_EVENT_CTRLr, port, regVal); 12058 break; 12059 12060 default: 12061 LOG_ERROR(BSL_LS_SOC_COMMON, 12062 (BSL_META_U(unit, 12063 "event_enable_port_set: Error !! wrong port event\n"))); 12064 rv = BCM_E_PARAM; 12065 goto exit; 12066 } 12067 12068 exit: 12069 return (rv); 12070 } 12071 12072 STATIC int 12073 _bcm_esw_time_capture_enable_cpu_set(int unit, int enable) 12074 { 12075 int rv = BCM_E_NONE; 12076 uint32 regVal = 0; 12077 12078 BCM_TIME_READ_NS_REGr(unit, NS_MISC_CLK_EVENT_CTRLr, 0, ®Val); 12079 soc_reg_field_set(unit, NS_MISC_CLK_EVENT_CTRLr, ®Val, TIME_CAPTURE_ENABLEf, enable ? 1:0); 12080 BCM_TIME_WRITE_NS_REGr(unit, NS_MISC_CLK_EVENT_CTRLr, 0, regVal); 12081 12082 return (rv); 12083 } 12084 12085 STATIC int 12086 bcm_esw_time_capture_enable(int unit, _bcm_time_capture_input_t event_misc, int enable) 12087 { 12088 int rv = BCM_E_NONE; 12089 12090 bsl_printf("BCM TIME: Set enable for time capture event\n"); 12091 if (event_misc.input_event == _bcmTimeCaptureEventPORT) { 12092 _bcm_esw_time_capture_enable_port_set(unit, event_misc.port, event_misc.port_event_type, enable); 12093 } else { 12094 _bcm_esw_time_capture_enable_misc_set(unit, event_misc.input_event, enable); 12095 } 12096 12097 _bcm_esw_time_capture_enable_cpu_set(unit,enable); 12098 return (rv); 12099 } 12100 12101 STATIC int 12102 _bcm_esw_time_event_config_set(int unit, _bcm_time_capture_input_t *pTimeCapture, uint32 eventId) 12103 { 12104 int rv = BCM_E_NONE; 12105 _bcm_time_capture_dest_cfg_t eventDest; 12106 12107 /* Configure the event */ 12108 eventDest.event_dest = pTimeCapture->event_dest; 12109 eventDest.ts_counter = pTimeCapture->ts_counter; 12110 eventDest.ppm_check_enable = pTimeCapture->ppm_check_enable; 12111 12112 if ((pTimeCapture->input_event >= _bcmTimeCaptureEventCpu) && 12113 (pTimeCapture->input_event <= _bcmTimeCaptureEventLCPLL3)) { 12114 BCM_IF_ERROR_RETURN(_bcm_esw_time_event_divisor_misc_set(unit, 12115 pTimeCapture->input_event, 12116 pTimeCapture->event_divisor)); 12117 BCM_IF_ERROR_RETURN(_bcm_esw_time_event_dest_misc_set(unit, 12118 pTimeCapture->input_event, 12119 &eventDest, eventId)); 12120 12121 } else if(pTimeCapture->input_event == _bcmTimeCaptureEventPORT) { 12122 if ((pTimeCapture->port_event_type == bcmTimePortEventRXCDR) || 12123 (pTimeCapture->port_event_type == bcmTimePortEventTXPI)) { 12124 BCM_IF_ERROR_RETURN(_bcm_esw_time_event_divisor_port_set(unit, 12125 pTimeCapture->port, pTimeCapture->port_event_type, 12126 pTimeCapture->event_divisor)); 12127 } 12128 BCM_IF_ERROR_RETURN(_bcm_esw_time_event_dest_port_set(unit, pTimeCapture->port, 12129 pTimeCapture->port_event_type, 12130 &eventDest, eventId)); 12131 12132 /* ROE event, disable the 52b conversion SWIPROC-591 */ 12133 if (pTimeCapture->port_event_type == bcmTimePortEventROE) 12134 BCM_IF_ERROR_RETURN(_bcm_esw_time_event_roe_52b_set(unit, 12135 pTimeCapture->port, 0)); 12136 12137 } /*else if(pTimeCapture->input_event == _bcmTimeCaptureEventR5) {*/ 12138 12139 /*pIaAddr = 214; 12140 } */else { 12141 LOG_ERROR(BSL_LS_SOC_COMMON, 12142 (BSL_META_U(unit, 12143 "event_config_set: Error !! invalid input event\n"))); 12144 rv = BCM_E_PARAM; 12145 } 12146 12147 return (rv); 12148 } 12149 12150 #endif /* BCM_MONTEREY_SUPPORT || defined(BCM_TOMAHAWK3_SUPPORT)*/ 12151 12152 int bcm_esw_time_capture_enable_set( 12153 int unit, 12154 bcm_time_if_t id, 12155 bcm_time_capture_t *time_capture, 12156 int enable, 12157 int *capture_handle) 12158 { 12159 int rv = BCM_E_UNAVAIL; 12160 12161 #if defined(BCM_MONTEREY_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT) 12162 _bcm_time_capture_input_t time_capture_input; 12163 int ts_port; 12164 uint32 eventId = BCM_TIME_CAPTURE_HANDLE_INVALID; 12165 12166 if (_bcm_esw_get_event_config_from_time_capture(unit, 12167 time_capture, 12168 &time_capture_input) != BCM_E_NONE) { 12169 rv = BCM_E_INTERNAL; 12170 goto exit; 12171 } 12172 12173 if (time_capture_input.input_event == _bcmTimeCaptureEventPORT) { 12174 _bcm_esw_time_portmap_get(unit, time_capture_input.port, &ts_port); 12175 time_capture_input.port = ts_port; 12176 } 12177 12178 if (_bcm_esw_time_input_eventId_get(unit, 12179 &time_capture_input, 12180 &eventId) != BCM_E_NONE) { 12181 rv = BCM_E_INTERNAL; 12182 goto exit; 12183 } 12184 12185 if (eventId >= BCM_TIME_CAPTURE_MAX_EVENT_ID){ 12186 bsl_printf("BCM TIME: Internal error. Invalid capture_handle: %d", eventId); 12187 rv = BCM_E_INTERNAL; 12188 goto exit; 12189 } 12190 12191 if (_bcm_time_capture_event_state[eventId] == BCM_TIME_CAPTURE_EVENT_STATE_NOT_IN_USE && 12192 enable == 0) { 12193 bsl_printf("BCM_TIME: Error! Trying to disable a capture handle that is not enabled"); 12194 rv = BCM_E_PARAM; 12195 goto exit; 12196 } else if (_bcm_time_capture_event_state[eventId] == BCM_TIME_CAPTURE_EVENT_STATE_IN_USE && 12197 enable == 1) { 12198 bsl_printf("BCM_TIME: Error! Trying to enable a capture handle that is in use"); 12199 rv = BCM_E_PARAM; 12200 goto exit; 12201 } 12202 12203 _bcm_time_capture_event_state[eventId] = (enable)?BCM_TIME_CAPTURE_EVENT_STATE_IN_USE:BCM_TIME_CAPTURE_EVENT_STATE_NOT_IN_USE; 12204 12205 bsl_printf("Capture handle generated:%d\n", eventId); 12206 /*bsl_printf("event_dest: %d, event_divisor: %d, input_event: %d, port: %d, port_event_type: %d, ppm_check_enable: %d, ts_counter: %d\n",time_capture.event_dest, 12207 time_capture.event_divisor, 12208 time_capture.input_event, 12209 time_capture.port, 12210 time_capture.port_event_type, 12211 time_capture.ppm_check_enable, 12212 time_capture.ts_counter);*/ 12213 12214 /* Configure the input event and get iaAddr_ref */ 12215 if(_bcm_esw_time_event_config_set(unit, 12216 &time_capture_input, 12217 eventId) != BCM_E_NONE) { 12218 rv = BCM_E_INTERNAL; 12219 goto exit; 12220 } 12221 12222 rv = bcm_esw_time_capture_enable(unit, time_capture_input, enable); 12223 12224 exit: 12225 *capture_handle = eventId; 12226 #endif /*BCM_MONTEREY_SUPPORT || defined(BCM_TOMAHAWK3_SUPPORT)*/ 12227 return (rv); 12228 } 12229 12230 #if defined(BCM_MONTEREY_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT) || defined (BCM_TIMESYNC_TIME_CAPTURE_SUPPORT) 12231 typedef struct bcm_time_cb_context_s { 12232 bcm_time_capture_cb cb; 12233 bcm_time_capture_cb_type_t cb_type; 12234 void *user_data_ptr; 12235 }bcm_time_cb_context_t; 12236 12237 bcm_time_cb_context_t cb_overflow,cb_fill,cb_all; 12238 12239 #endif /* #if defined(BCM_MONTEREY_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT)*/ 12240 12241 #if defined(BCM_MONTEREY_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT) 12242 uint32 g_int_status = 0; /* Interrupt status */ 12243 uint8 g_fifo_data_fill[BCM_TIME_CAPTURE_MAX_FIFO_DATA_SIZE]; 12244 uint8 g_fifo_data_overflow[2]; 12245 sal_sem_t g_fifo_sem; 12246 #endif /* #if defined(BCM_MONTEREY_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT) */ 12247 12248 12249 #if defined(BCM_TIMESYNC_TIME_CAPTURE_SUPPORT) 12250 typedef struct bcm_esw_time_ts_capture_info_s { 12251 int time_capture_ts_enable; 12252 int time_capture_ts_active; 12253 sal_thread_t thread_id_time_capture_ts; 12254 sal_sem_t ts_fifo_sem; 12255 uint32 ts_fifo_wr_index; 12256 uint32 ts_fifo_rd_index; 12257 uint8 ts_fifo_data_fill[BCM_TIME_TS_CAPTURE_BUF_SIZE]; 12258 } bcm_esw_time_ts_capture_info_t; 12259 12260 STATIC bcm_esw_time_ts_capture_info_t *ts_capture_info[BCM_UNITS_MAX] = {0}; 12261 #endif /* BCM_TIMESYNC_TIME_CAPTURE_SUPPORT */ 12262 12263 12264 12265 int bcm_esw_time_capture_cb_register( 12266 int unit, 12267 bcm_time_if_t id, 12268 bcm_time_capture_cb_type_t cb_type, 12269 bcm_time_capture_cb cb, 12270 void *user_data) 12271 { 12272 int rv = BCM_E_NONE; 12273 #if defined(BCM_MONTEREY_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT) || defined(BCM_TIMESYNC_TIME_CAPTURE_SUPPORT) 12274 if (cb_overflow.cb == NULL && cb_fill.cb == NULL && cb_all.cb == NULL){ 12275 /* At least one callback is registered. Enable the interrupt */ 12276 #if defined(BCM_MONTEREY_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT) 12277 if (SOC_IS_MONTEREY(unit) || SOC_IS_TOMAHAWK3(unit)) { 12278 BCM_TIME_WRITE_NS_REGr(unit, NS_TS_INT_ENABLEr, 0, INTR_NS_TIME_CAPTURE); 12279 } 12280 #ifdef BCM_CMICX_SUPPORT 12281 if (soc_feature(unit, soc_feature_cmicx)) { 12282 soc_cmic_intr_enable(unit, TS_INTR); 12283 } 12284 #endif 12285 #endif 12286 #if defined (BCM_TIMESYNC_TIME_CAPTURE_SUPPORT) 12287 if (soc_feature(unit, soc_feature_timesync_time_capture)) { 12288 (void)soc_cmicm_intr1_enable(unit, IRQ_CMCx_TIMESYNC_INTR); 12289 } 12290 12291 if (soc_feature(unit, soc_feature_timesync_time_capture)) { 12292 ts_capture_info[unit]->ts_fifo_rd_index = 0; 12293 ts_capture_info[unit]->ts_fifo_wr_index = 0; 12294 sal_memset(ts_capture_info[unit]->ts_fifo_data_fill, 0, BCM_TIME_TS_CAPTURE_BUF_SIZE); 12295 } 12296 #endif 12297 } 12298 switch (cb_type){ 12299 case bcmTimeCaptureOverflow: 12300 if (cb_overflow.cb != NULL){ 12301 bsl_printf("BCM TIME: Error! Callback function already registered for bcmTimeCaptureOverflow"); 12302 rv = BCM_E_PARAM; 12303 goto exit; 12304 } 12305 cb_overflow.cb_type = bcmTimeCaptureOverflow; 12306 cb_overflow.cb = cb; 12307 cb_overflow.user_data_ptr = user_data; 12308 break; 12309 case bcmTimeCapturetFill: 12310 if (cb_fill.cb != NULL){ 12311 bsl_printf("BCM TIME: Error! Callback function already registered for bcmTimeCapturetFill"); 12312 rv = BCM_E_PARAM; 12313 goto exit; 12314 } 12315 cb_fill.cb_type = bcmTimeCapturetFill; 12316 cb_fill.cb = cb; 12317 cb_fill.user_data_ptr = user_data; 12318 break; 12319 case bcmTimeCaptureAll: 12320 if (cb_all.cb != NULL){ 12321 bsl_printf("BCM TIME: Error! Callback function already registered for bcmTimeCaptureAll"); 12322 rv = BCM_E_PARAM; 12323 goto exit; 12324 } 12325 cb_all.cb_type = bcmTimeCaptureAll; 12326 cb_all.cb = cb; 12327 cb_all.user_data_ptr = user_data; 12328 break; 12329 } 12330 exit: 12331 #endif /* #if defined(BCM_MONTEREY_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT) */ 12332 return rv; 12333 } 12334 12335 12336 int bcm_esw_time_capture_cb_unregister( 12337 int unit, 12338 bcm_time_if_t id, 12339 bcm_time_capture_cb_type_t cb_type) 12340 { 12341 #if defined(BCM_MONTEREY_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT) || defined (BCM_TIMESYNC_TIME_CAPTURE_SUPPORT) 12342 switch (cb_type){ 12343 case bcmTimeCaptureOverflow: 12344 cb_overflow.cb_type = bcmTimeCaptureOverflow; 12345 cb_overflow.cb = NULL; 12346 cb_overflow.user_data_ptr = NULL; 12347 break; 12348 case bcmTimeCapturetFill: 12349 cb_fill.cb_type = bcmTimeCapturetFill; 12350 cb_fill.cb = NULL; 12351 cb_fill.user_data_ptr = NULL; 12352 break; 12353 case bcmTimeCaptureAll: 12354 cb_all.cb_type = bcmTimeCaptureAll; 12355 cb_all.cb = NULL; 12356 cb_all.user_data_ptr = NULL; 12357 break; 12358 } 12359 12360 if (cb_overflow.cb == NULL && cb_fill.cb == NULL && cb_all.cb == NULL){ 12361 /* No callbacks are registered anymore. Disable interrupts */ 12362 #if defined(BCM_MONTEREY_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT) 12363 if (SOC_IS_MONTEREY(unit) || SOC_IS_TOMAHAWK3(unit)) { 12364 BCM_TIME_WRITE_NS_REGr(unit, NS_TS_INT_ENABLEr, 0, 0); 12365 } 12366 #endif 12367 } 12368 if (cb_overflow.cb == NULL && cb_fill.cb == NULL && cb_all.cb == NULL){ 12369 /* At least one callback is registered. Enable the interrupt */ 12370 #if defined(BCM_TIMESYNC_TIME_CAPTURE_SUPPORT) 12371 if (soc_feature(unit, soc_feature_timesync_time_capture)) { 12372 (void)soc_cmicm_intr1_disable(unit, IRQ_CMCx_TIMESYNC_INTR); 12373 } 12374 #endif 12375 } 12376 #endif /* #if defined(BCM_MONTEREY_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT) */ 12377 12378 return BCM_E_NONE; 12379 } 12380 12381 void 12382 soc_nanosync_intr(void *unit_vp, void *d1, void *d2, 12383 void *d3, void *d4) 12384 { 12385 #if defined(BCM_MONTEREY_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT) 12386 int unit = PTR_TO_INT(unit_vp); 12387 int valid = 0; 12388 12389 uint32 int_status_clear = 0; /* Interrupt status clear */ 12390 uint32 int_enable = 0; /* Interrupt enable */ 12391 uint32 regval,regval1,regval2,regval3,lower, middle, upper,event_id, fifo_depth, capture_status; 12392 12393 uint16 g_fifo_data_index = 0; 12394 12395 /* Read the GDPLL interrupt */ 12396 BCM_TIME_READ_NS_REGr(unit, NS_TS_INT_STATUSr, 0, &g_int_status); 12397 BCM_TIME_READ_NS_REGr(unit, NS_TS_INT_ENABLEr, 0, &int_enable); 12398 12399 /* Process only enabled interrupts */ 12400 g_int_status &= int_enable; 12401 12402 /* TS_FIFO_NOT_EMPTY interrupt */ 12403 if (tsfifo_flag && soc_reg_field_get(unit, NS_TS_INT_STATUSr, g_int_status, TS_FIFO_NOT_EMPTYf)) { 12404 12405 /* Set W1TC to clear the flag */ 12406 soc_reg_field_set(unit, NS_TS_INT_STATUSr, &int_status_clear, TS_FIFO_NOT_EMPTYf, 1); 12407 /* Write W1TC to clear the flags in NS_TS_INT_STATUS */ 12408 BCM_TIME_WRITE_NS_REGr(unit, NS_TS_INT_STATUSr, 0, int_status_clear); 12409 12410 BCM_TIME_READ_NS_REGr(unit, NS_TS_CAPTURE_STATUSr, 0, &capture_status); 12411 fifo_depth = soc_reg_field_get(unit, NS_TS_CAPTURE_STATUSr, capture_status, FIFO_DEPTHf); 12412 g_fifo_data_fill[g_fifo_data_index++] = 0xFF & fifo_depth; 12413 g_fifo_data_fill[g_fifo_data_index++] = 0xFF & (fifo_depth >> 8); 12414 /*bsl_printf("FIFO_Depth: %d\n", fifo_depth);*/ 12415 12416 while (fifo_depth != 0) { 12417 /* Must read LOWER regiser first */ 12418 /* Read to this register POPs the FIFO */ 12419 READ_NS_TIMESYNC_INPUT_TIME_FIFO_TS_3r(unit, ®val3); 12420 READ_NS_TIMESYNC_INPUT_TIME_FIFO_TS_2r(unit, ®val2); 12421 READ_NS_TIMESYNC_INPUT_TIME_FIFO_TS_1r(unit, ®val1); 12422 READ_NS_TIMESYNC_INPUT_TIME_FIFO_TS_0r(unit, ®val); 12423 12424 12425 12426 /* Check capture event id */ 12427 event_id = soc_reg_field_get( 12428 unit, NS_TIMESYNC_INPUT_TIME_FIFO_TS_3r, 12429 regval3, TS_EVENT_IDf); 12430 12431 valid = (regval3 >> 20) & 1; 12432 12433 if (!valid){ 12434 continue; 12435 } 12436 12437 #if 0 12438 /* Calculate seconds/nanoseconds from the timestamp value */ 12439 lower = soc_reg_field_get( 12440 unit, NS_TIMESYNC_INPUT_TIME_FIFO_TS_0r, 12441 regval, TS0_Lf); 12442 12443 upper = soc_reg_field_get( 12444 unit, NS_TIMESYNC_INPUT_TIME_FIFO_TS_1r, 12445 regval1, TS0_Uf); 12446 12447 bsl_printf("FIFO timestamp popped. EventId: %d, TS0: %x%x\n", event_id, upper, lower); 12448 12449 g_fifo_data_fill[g_fifo_data_index++] = 0xFF & event_id; 12450 g_fifo_data_fill[g_fifo_data_index++] = 0x0; 12451 g_fifo_data_fill[g_fifo_data_index++] = 0xFF & lower; 12452 g_fifo_data_fill[g_fifo_data_index++] = 0xFF & (lower >> 8); 12453 g_fifo_data_fill[g_fifo_data_index++] = 0xFF & (lower >> 16); 12454 g_fifo_data_fill[g_fifo_data_index++] = 0xFF & (lower >> 24); 12455 g_fifo_data_fill[g_fifo_data_index++] = 0xFF & upper; 12456 g_fifo_data_fill[g_fifo_data_index++] = 0xFF & (upper >> 8); 12457 g_fifo_data_fill[g_fifo_data_index++] = 0xFF & (upper >> 16); 12458 #endif 12459 12460 /* Calculate seconds/nanoseconds from the timestamp value */ 12461 lower = soc_reg_field_get( 12462 unit, NS_TIMESYNC_INPUT_TIME_FIFO_TS_1r, 12463 regval1, TS1_Lf); 12464 12465 middle = soc_reg_field_get( 12466 unit, NS_TIMESYNC_INPUT_TIME_FIFO_TS_2r, 12467 regval2, TS1_Mf); 12468 12469 upper = soc_reg_field_get( 12470 unit, NS_TIMESYNC_INPUT_TIME_FIFO_TS_3r, 12471 regval3, TS1_Uf); 12472 12473 lower = (lower & 0xFFF) | ((middle & 0xFFFFF) << 12); 12474 upper = ((upper & 0xF) << 12) | ((middle >> 20) & 0xFFF); 12475 12476 12477 /*bsl_printf("FIFO timestamp popped. EventId: %d, TS1: %x%x\n", event_id, upper, lower);*/ 12478 12479 g_fifo_data_fill[g_fifo_data_index++] = 0xFF & event_id; 12480 g_fifo_data_fill[g_fifo_data_index++] = 0x0; 12481 g_fifo_data_fill[g_fifo_data_index++] = 0xFF & lower; 12482 g_fifo_data_fill[g_fifo_data_index++] = 0xFF & (lower >> 8); 12483 g_fifo_data_fill[g_fifo_data_index++] = 0xFF & (lower >> 16); 12484 g_fifo_data_fill[g_fifo_data_index++] = 0xFF & (lower >> 24); 12485 g_fifo_data_fill[g_fifo_data_index++] = 0xFF & upper; 12486 g_fifo_data_fill[g_fifo_data_index++] = 0xFF & (upper >> 8); 12487 g_fifo_data_fill[g_fifo_data_index++] = 0xFF & (upper >> 16); 12488 fifo_depth--; 12489 } 12490 } 12491 12492 /* TS_FIFO_OVERFLOW interrupt */ 12493 if (tsfifo_flag && soc_reg_field_get(unit, NS_TS_INT_STATUSr, g_int_status, TS_FIFO_OVERFLOWf)) { 12494 g_fifo_data_index = 0; 12495 12496 /* Set W1TC to clear the flag */ 12497 soc_reg_field_set(unit, NS_TS_INT_STATUSr, &int_status_clear, TS_FIFO_OVERFLOWf, 1); 12498 /* Write W1TC to clear the flags in NS_TS_INT_STATUS */ 12499 BCM_TIME_WRITE_NS_REGr(unit, NS_TS_INT_STATUSr, 0, int_status_clear); 12500 12501 BCM_TIME_READ_NS_REGr(unit, NS_TIMESYNC_INPUT_TIME_FIFO_STATUSr, 0, &capture_status); 12502 event_id = soc_reg_field_get(unit, NS_TIMESYNC_INPUT_TIME_FIFO_STATUSr, 12503 capture_status, SOURCE_OVERFLOW_TYPEf); 12504 g_fifo_data_overflow[g_fifo_data_index++] = 0xFF & event_id; 12505 12506 } 12507 12508 #if defined(INCLUDE_GDPLL) 12509 gdpll_intr(unit, g_int_status, int_enable); 12510 #endif 12511 12512 /* Signal the thread for buffer read */ 12513 if (tsfifo_flag && g_fifo_sem) { 12514 sal_sem_give(g_fifo_sem); 12515 } 12516 /* Re-enable TS NS IRQ */ 12517 /* soc_cmicm_intr2_enable(unit, SOC_TIME_NS_INTR_POS); */ 12518 soc_cmicm_intr2_enable(unit, (1<<24) | (1<<25));/* SOC_GDPLL_NS_INTR_POS | SOC_GDPLL_NS_INTR_DEBUG_POS */ 12519 12520 #endif /* #if defined(BCM_MONTEREY_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT) */ 12521 } 12522 12523 12524 #if defined (BCM_TIMESYNC_TIME_CAPTURE_SUPPORT) 12525 void 12526 soc_esw_timesync_ts_intr(int unit) 12527 { 12528 12529 uint32 int_enable = 0; /* Interrupt enable */ 12530 uint32 regval1=0, lower=0, upper=0, event_id=0; 12531 uint32 fifo_depth=0, capture_status=0, fifo_status=0; 12532 uint32 intr=0, over_flow=0; 12533 uint16 notify=0; 12534 uint32 int_status = 0; /* Interrupt status */ 12535 int buf_full=0, buf_idx=0; 12536 12537 READ_CMIC_TIMESYNC_INTERRUPT_STATUSr(unit, &int_status); 12538 12539 READ_CMIC_TIMESYNC_CAPTURE_STATUS_1r(unit, &capture_status); 12540 12541 /* TS_FIFO_NOT_EMPTY interrupt */ 12542 intr = soc_reg_field_get(unit, CMIC_TIMESYNC_INTERRUPT_STATUSr, int_status, INTERRUPTf); 12543 if (intr) 12544 { 12545 12546 READ_CMIC_TIMESYNC_FIFO_STATUSr(unit, &fifo_status); 12547 over_flow = soc_reg_field_get(unit, CMIC_TIMESYNC_FIFO_STATUSr, 12548 fifo_status, SOURCE_OVERFLOWf); 12549 if(over_flow) { 12550 LOG_ERROR(BSL_LS_SOC_COMMON, (BSL_META_U(unit, "TS FIFO status source overflow \n"))); 12551 soc_reg_field_set(unit, CMIC_TIMESYNC_FIFO_STATUSr, &fifo_status, SOURCE_OVERFLOWf, 0); 12552 WRITE_CMIC_TIMESYNC_FIFO_STATUSr(unit, fifo_status); 12553 } 12554 12555 fifo_depth = soc_reg_field_get(unit, CMIC_TIMESYNC_CAPTURE_STATUS_1r, capture_status, FIFO_DEPTHf); 12556 LOG_INFO(BSL_LS_SOC_COMMON, (BSL_META_U(unit, "FIFO depth[%d]\n"),fifo_depth)); 12557 12558 while (fifo_depth != 0) { 12559 notify = 1; 12560 /* Must read LOWER regiser first */ 12561 READ_CMIC_TIMESYNC_INPUT_TIME_FIFO_TS_LOWERr(unit, &lower); 12562 READ_CMIC_TIMESYNC_INPUT_TIME_FIFO_TS_UPPERr(unit, ®val1); 12563 12564 /* Check capture event id */ 12565 event_id = soc_reg_field_get( 12566 unit, CMIC_TIMESYNC_INPUT_TIME_FIFO_TS_UPPERr, 12567 regval1, EVENT_IDf); 12568 12569 /* Calculate seconds/nanoseconds from the timestamp value */ 12570 upper = soc_reg_field_get( 12571 unit, CMIC_TIMESYNC_INPUT_TIME_FIFO_TS_UPPERr, 12572 regval1, TIMESTAMPf); 12573 12574 /* LOG_INFO(BSL_LS_SOC_COMMON, (BSL_META_U(unit, "[%d]:%d:%x%x\n"),fifo_depth, event_id, upper, lower));*/ 12575 12576 buf_idx = (ts_capture_info[unit]->ts_fifo_wr_index); 12577 buf_full = ((buf_idx + 12) >= BCM_TIME_TS_CAPTURE_BUF_SIZE); 12578 if (!buf_full) { 12579 12580 ts_capture_info[unit]->ts_fifo_data_fill[buf_idx++] = 0x0; 12581 ts_capture_info[unit]->ts_fifo_data_fill[buf_idx++] = 0x0; 12582 ts_capture_info[unit]->ts_fifo_data_fill[buf_idx++] = 0x0; 12583 ts_capture_info[unit]->ts_fifo_data_fill[buf_idx++] = 0x1; 12584 12585 ts_capture_info[unit]->ts_fifo_data_fill[buf_idx++] = 0x0; 12586 ts_capture_info[unit]->ts_fifo_data_fill[buf_idx++] = 0xFF & event_id; 12587 ts_capture_info[unit]->ts_fifo_data_fill[buf_idx++] = 0xFF & (upper >> 8); 12588 ts_capture_info[unit]->ts_fifo_data_fill[buf_idx++] = 0xFF & upper; 12589 ts_capture_info[unit]->ts_fifo_data_fill[buf_idx++] = 0xFF & (lower >> 24); 12590 ts_capture_info[unit]->ts_fifo_data_fill[buf_idx++] = 0xFF & (lower >> 16); 12591 ts_capture_info[unit]->ts_fifo_data_fill[buf_idx++] = 0xFF & (lower >> 8); 12592 ts_capture_info[unit]->ts_fifo_data_fill[buf_idx++] = 0xFF & lower; 12593 12594 ts_capture_info[unit]->ts_fifo_wr_index = buf_idx; 12595 } 12596 fifo_depth--; 12597 } 12598 12599 if(over_flow) { 12600 LOG_ERROR(BSL_LS_SOC_COMMON, (BSL_META_U(unit, "[%d]:%d:%x%x \n"),fifo_depth, event_id, upper, lower)); 12601 } 12602 12603 /* Clear status */ 12604 WRITE_CMIC_TIMESYNC_CAPTURE_STATUS_CLR_1r(unit, capture_status); 12605 12606 READ_CMIC_TIMESYNC_INTERRUPT_ENABLEr(unit, &int_enable); 12607 12608 /* Clear interrupts */ 12609 WRITE_CMIC_TIMESYNC_INTERRUPT_CLRr(unit, int_status); 12610 WRITE_CMIC_TIMESYNC_INTERRUPT_CLRr(unit, 0); 12611 12612 /* Enable interrupts */ 12613 WRITE_CMIC_TIMESYNC_INTERRUPT_ENABLEr(unit, int_enable); 12614 12615 } 12616 12617 if (notify && !over_flow && (ts_capture_info[unit]->ts_fifo_sem)) { 12618 sal_sem_give(ts_capture_info[unit]->ts_fifo_sem); 12619 } 12620 12621 } 12622 12623 #ifdef BCM_CMICX_SUPPORT 12624 void 12625 soc_esw_timesync_ts_cmicx_intr(int unit, void *data) 12626 { 12627 soc_esw_timesync_ts_intr(unit); 12628 } 12629 #endif 12630 12631 #endif 12632 12633 12634 #if defined(BCM_MONTEREY_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT) 12635 void 12636 time_capture_cb_thread(void *unit_vp) 12637 { 12638 int unit = PTR_TO_INT(unit_vp); 12639 uint8 cb_data_fill[BCM_TIME_CAPTURE_MAX_FIFO_DATA_SIZE]; 12640 uint8 cb_data_overflow[2]; 12641 uint32 int_status = 0; 12642 12643 while(1) { 12644 /* Wait on the signal from the ISR */ 12645 (void)sal_sem_take(g_fifo_sem, sal_sem_FOREVER); 12646 12647 int_status = g_int_status; 12648 12649 if (soc_reg_field_get(unit, NS_TS_INT_STATUSr, int_status, TS_FIFO_NOT_EMPTYf)) { 12650 sal_memcpy(cb_data_fill, g_fifo_data_fill, BCM_TIME_CAPTURE_MAX_FIFO_DATA_SIZE); 12651 } 12652 12653 /* TS_FIFO_OVERFLOW interrupt */ 12654 if (soc_reg_field_get(unit, NS_TS_INT_STATUSr, int_status, TS_FIFO_OVERFLOWf)) { 12655 sal_memcpy(cb_data_overflow, g_fifo_data_overflow, 2); 12656 } 12657 12658 if (soc_reg_field_get(unit, NS_TS_INT_STATUSr, int_status, TS_FIFO_NOT_EMPTYf)) { 12659 if (cb_fill.cb != NULL) 12660 cb_fill.cb(unit, cb_fill.user_data_ptr, (uint32 *)cb_data_fill, bcmTimeCapturetFill); 12661 if (cb_all.cb != NULL) 12662 cb_all.cb(unit, cb_all.user_data_ptr, (uint32 *)cb_data_fill, bcmTimeCapturetFill); 12663 } 12664 12665 /* TS_FIFO_OVERFLOW interrupt */ 12666 if (soc_reg_field_get(unit, NS_TS_INT_STATUSr, int_status, TS_FIFO_OVERFLOWf)) { 12667 if (cb_overflow.cb != NULL) 12668 cb_overflow.cb(unit, cb_overflow.user_data_ptr, (uint32 *)cb_data_overflow, bcmTimeCaptureOverflow); 12669 if (cb_all.cb != NULL) 12670 cb_all.cb(unit, cb_all.user_data_ptr, (uint32 *)cb_data_overflow, bcmTimeCaptureOverflow); 12671 } 12672 } 12673 } 12674 12675 #if defined(BCM_TOMAHAWK3_SUPPORT) 12676 void 12677 soc_esw_nanosync_ts_cmicx_intr(int unit, void *data) 12678 { 12679 int valid = 0; 12680 uint32 int_status = 0; /* Interrupt status */ 12681 uint32 int_status_clear = 0; /* Interrupt status clear */ 12682 uint32 int_enable = 0; /* Interrupt enable */ 12683 uint32 regval,regval1,regval2,regval3,lower, middle, upper,event_id, fifo_depth, capture_status; 12684 12685 int buf_full=0, buf_idx=0; 12686 12687 /* Read the GDPLL interrupt */ 12688 BCM_TIME_READ_NS_REGr(unit, NS_TS_INT_STATUSr, 0, &int_status); 12689 BCM_TIME_READ_NS_REGr(unit, NS_TS_INT_ENABLEr, 0, &int_enable); 12690 12691 /* Process only enabled interrupts */ 12692 int_status &= int_enable; 12693 12694 /* TS_FIFO_NOT_EMPTY interrupt */ 12695 if (soc_reg_field_get(unit, NS_TS_INT_STATUSr, int_status, TS_FIFO_NOT_EMPTYf)) { 12696 12697 /* Set W1TC to clear the flag */ 12698 soc_reg_field_set(unit, NS_TS_INT_STATUSr, &int_status_clear, TS_FIFO_NOT_EMPTYf, 1); 12699 12700 /* Write W1TC to clear the flags in NS_TS_INT_STATUS */ 12701 BCM_TIME_WRITE_NS_REGr(unit, NS_TS_INT_STATUSr, 0, int_status_clear); 12702 12703 BCM_TIME_READ_NS_REGr(unit, NS_TS_CAPTURE_STATUSr, 0, &capture_status); 12704 12705 fifo_depth = soc_reg_field_get(unit, NS_TS_CAPTURE_STATUSr, capture_status, FIFO_DEPTHf); 12706 12707 /*bsl_printf("FIFO_Depth: %d\n", fifo_depth);*/ 12708 12709 while (fifo_depth != 0) { 12710 /* Must read LOWER regiser first */ 12711 /* Read to this register POPs the FIFO */ 12712 READ_NS_TIMESYNC_INPUT_TIME_FIFO_TS_3r(unit, ®val3); 12713 READ_NS_TIMESYNC_INPUT_TIME_FIFO_TS_2r(unit, ®val2); 12714 READ_NS_TIMESYNC_INPUT_TIME_FIFO_TS_1r(unit, ®val1); 12715 READ_NS_TIMESYNC_INPUT_TIME_FIFO_TS_0r(unit, ®val); 12716 12717 12718 /* Check capture event id */ 12719 event_id = soc_reg_field_get( 12720 unit, NS_TIMESYNC_INPUT_TIME_FIFO_TS_3r, 12721 regval3, TS_EVENT_IDf); 12722 valid = soc_reg_field_get( 12723 unit, NS_TIMESYNC_INPUT_TIME_FIFO_TS_3r, 12724 regval3, TS_VALIDf); 12725 12726 if (!valid){ 12727 continue; 12728 } 12729 12730 /* Calculate seconds/nanoseconds from the timestamp value */ 12731 lower = soc_reg_field_get( 12732 unit, NS_TIMESYNC_INPUT_TIME_FIFO_TS_1r, 12733 regval1, TS1_Lf); 12734 12735 middle = soc_reg_field_get( 12736 unit, NS_TIMESYNC_INPUT_TIME_FIFO_TS_2r, 12737 regval2, TS1_Mf); 12738 12739 upper = soc_reg_field_get( 12740 unit, NS_TIMESYNC_INPUT_TIME_FIFO_TS_3r, 12741 regval3, TS1_Uf); 12742 12743 lower = (lower & 0xFFF) | ((middle & 0xFFFFF) << 12); 12744 upper = ((upper & 0xF) << 12) | ((middle >> 20) & 0xFFF); 12745 12746 12747 /*bsl_printf("FIFO timestamp popped. EventId: %d, TS1: %x%x\n", event_id, upper, lower);*/ 12748 12749 buf_idx = (ts_capture_info[unit]->ts_fifo_wr_index); 12750 buf_full = ((buf_idx + 12) >= BCM_TIME_TS_CAPTURE_BUF_SIZE); 12751 if (!buf_full) { 12752 12753 ts_capture_info[unit]->ts_fifo_data_fill[buf_idx++] = 0x0; 12754 ts_capture_info[unit]->ts_fifo_data_fill[buf_idx++] = 0x0; 12755 ts_capture_info[unit]->ts_fifo_data_fill[buf_idx++] = 0x0; 12756 ts_capture_info[unit]->ts_fifo_data_fill[buf_idx++] = 0x1; 12757 12758 ts_capture_info[unit]->ts_fifo_data_fill[buf_idx++] = 0x0; 12759 ts_capture_info[unit]->ts_fifo_data_fill[buf_idx++] = 0xFF & event_id; 12760 ts_capture_info[unit]->ts_fifo_data_fill[buf_idx++] = 0xFF & (upper >> 8); 12761 ts_capture_info[unit]->ts_fifo_data_fill[buf_idx++] = 0xFF & upper; 12762 ts_capture_info[unit]->ts_fifo_data_fill[buf_idx++] = 0xFF & (lower >> 24); 12763 ts_capture_info[unit]->ts_fifo_data_fill[buf_idx++] = 0xFF & (lower >> 16); 12764 ts_capture_info[unit]->ts_fifo_data_fill[buf_idx++] = 0xFF & (lower >> 8); 12765 ts_capture_info[unit]->ts_fifo_data_fill[buf_idx++] = 0xFF & lower; 12766 12767 ts_capture_info[unit]->ts_fifo_wr_index = buf_idx; 12768 } 12769 fifo_depth--; 12770 12771 } 12772 } 12773 12774 /* TS_FIFO_OVERFLOW interrupt */ 12775 if (soc_reg_field_get(unit, NS_TS_INT_STATUSr, int_status, TS_FIFO_OVERFLOWf)) { 12776 12777 /* Set W1TC to clear the flag */ 12778 soc_reg_field_set(unit, NS_TS_INT_STATUSr, &int_status_clear, TS_FIFO_OVERFLOWf, 1); 12779 /* Write W1TC to clear the flags in NS_TS_INT_STATUS */ 12780 BCM_TIME_WRITE_NS_REGr(unit, NS_TS_INT_STATUSr, 0, int_status_clear); 12781 12782 BCM_TIME_READ_NS_REGr(unit, NS_TIMESYNC_INPUT_TIME_FIFO_STATUSr, 0, &capture_status); 12783 12784 } else if ((ts_capture_info[unit]->ts_fifo_sem)) { 12785 /* Signal the thread for buffer read */ 12786 sal_sem_give(ts_capture_info[unit]->ts_fifo_sem); 12787 } 12788 12789 /* Re-enable TS NS IRQ */ 12790 #ifdef BCM_CMICX_SUPPORT 12791 if (soc_feature(unit, soc_feature_cmicx)) { 12792 soc_cmic_intr_enable(unit, TS_INTR); 12793 } 12794 #endif 12795 12796 12797 } 12798 #endif /* defined(BCM_TOMAHAWK3_SUPPORT) */ 12799 12800 12801 int 12802 _bcm_esw_time_capture_init(int unit) 12803 { 12804 sal_thread_t thread_id_time_capture_cb; 12805 12806 /* Create the time capture semaphore */ 12807 g_fifo_sem = sal_sem_create("fifo_time_capture", sal_sem_COUNTING, 0); 12808 if (g_fifo_sem == NULL) { 12809 LOG_ERROR(BSL_LS_SOC_COMMON, 12810 (BSL_META_U(unit, 12811 "BCM TIME: Error !! failed to create the sem\n"))); 12812 return (SOC_E_MEMORY); 12813 } 12814 12815 /* Create the time capture callback thread */ 12816 thread_id_time_capture_cb = sal_thread_create("Time capture cb thread", SAL_THREAD_STKSZ, 100, 12817 time_capture_cb_thread, INT_TO_PTR(unit)); 12818 if (thread_id_time_capture_cb == SAL_THREAD_ERROR) { 12819 LOG_ERROR(BSL_LS_SOC_COMMON, (BSL_META_U(unit, "BCM TIME: Error !! callback thread create failed\n"))); 12820 return SOC_E_INTERNAL; 12821 } 12822 12823 return BCM_E_NONE; 12824 } 12825 #endif /*#if defined(BCM_MONTEREY_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT)*/ 12826 12827 #if defined(BCM_TIMESYNC_TIME_CAPTURE_SUPPORT) 12828 12829 void 12830 time_capture_ts_cb_thread(void *unit_vp) 12831 { 12832 int num_entries; 12833 int unit = PTR_TO_INT(unit_vp); 12834 uint8 cb_data_fill[12] = {0}; 12835 12836 ts_capture_info[unit]->time_capture_ts_active = 1; 12837 12838 while (ts_capture_info[unit]->time_capture_ts_enable) { 12839 12840 /* Wait on the signal from the ISR */ 12841 (void)sal_sem_take(ts_capture_info[unit]->ts_fifo_sem, sal_sem_FOREVER); 12842 if ((ts_capture_info[unit] != NULL) && 12843 (ts_capture_info[unit]->time_capture_ts_enable == 0)) { 12844 break; 12845 } 12846 12847 num_entries = ((ts_capture_info[unit]->ts_fifo_wr_index - ts_capture_info[unit]->ts_fifo_rd_index) / 12); 12848 while (num_entries) { 12849 sal_memcpy(cb_data_fill, &(ts_capture_info[unit]->ts_fifo_data_fill[ts_capture_info[unit]->ts_fifo_rd_index]), 12); 12850 ts_capture_info[unit]->ts_fifo_rd_index += 12; 12851 12852 if (cb_fill.cb != NULL) { 12853 cb_fill.cb(unit, cb_fill.user_data_ptr, (uint32 *)cb_data_fill, bcmTimeCapturetFill); 12854 } 12855 num_entries--; 12856 } 12857 } 12858 12859 ts_capture_info[unit]->time_capture_ts_active = 0; 12860 12861 return; 12862 } 12863 12864 int 12865 bcm_esw_time_capture_ts_init(int unit) 12866 { 12867 #ifdef BCM_CMICX_SUPPORT 12868 soc_cmic_intr_handler_t handle; 12869 #endif 12870 12871 if (ts_capture_info[unit] != NULL) { 12872 return BCM_E_NONE; 12873 } 12874 12875 ts_capture_info[unit] = sal_alloc(sizeof(bcm_esw_time_ts_capture_info_t), "ts capture info"); 12876 if (ts_capture_info[unit] == NULL) { 12877 LOG_ERROR(BSL_LS_SOC_COMMON, 12878 (BSL_META_U(unit, 12879 "BCM TIME: Error !! failed to allocate memory for time capture info\n"))); 12880 return (SOC_E_MEMORY); 12881 } 12882 sal_memset(ts_capture_info[unit], 0, sizeof(bcm_esw_time_ts_capture_info_t)); 12883 12884 /* Create the time capture semaphore */ 12885 ts_capture_info[unit]->ts_fifo_sem = sal_sem_create("fifo_time_capture", sal_sem_COUNTING, 0); 12886 if (ts_capture_info[unit]->ts_fifo_sem == NULL) { 12887 LOG_ERROR(BSL_LS_SOC_COMMON, 12888 (BSL_META_U(unit, 12889 "BCM TIME: Error !! failed to create semaphore\n"))); 12890 return (SOC_E_MEMORY); 12891 } 12892 12893 #ifdef BCM_CMICX_SUPPORT 12894 if (soc_feature(unit, soc_feature_cmicx)) { 12895 12896 handle.num = TS_INTR; 12897 #ifdef BCM_TOMAHAWK3_SUPPORT 12898 if (SOC_IS_TOMAHAWK3(unit)) { 12899 handle.intr_fn = soc_esw_nanosync_ts_cmicx_intr; 12900 } else 12901 #endif 12902 { 12903 handle.intr_fn = soc_esw_timesync_ts_cmicx_intr; 12904 } 12905 handle.intr_data = NULL; 12906 soc_cmic_intr_register(unit, &handle, 1); 12907 12908 soc_cmic_intr_enable(unit, TS_INTR); 12909 } 12910 #endif 12911 12912 /* Create the time capture callback thread */ 12913 ts_capture_info[unit]->time_capture_ts_enable = 1; 12914 ts_capture_info[unit]->thread_id_time_capture_ts = 12915 sal_thread_create("Time capture cb thread", SAL_THREAD_STKSZ, 100, 12916 time_capture_ts_cb_thread, INT_TO_PTR(unit)); 12917 12918 if (ts_capture_info[unit]->thread_id_time_capture_ts == SAL_THREAD_ERROR) { 12919 LOG_ERROR(BSL_LS_SOC_COMMON, 12920 (BSL_META_U(unit, 12921 "BCM TIME: Error !! callback thread create failed\n"))); 12922 return SOC_E_INTERNAL; 12923 } 12924 12925 return BCM_E_NONE; 12926 } 12927 12928 int 12929 bcm_esw_time_capture_ts_deinit(int unit) 12930 { 12931 soc_timeout_t to; 12932 12933 if (ts_capture_info[unit] == NULL) { 12934 return BCM_E_NONE; 12935 } 12936 12937 ts_capture_info[unit]->time_capture_ts_enable = 0; 12938 sal_sem_give(ts_capture_info[unit]->ts_fifo_sem); 12939 12940 soc_timeout_init(&to, 50000, 0); 12941 12942 do { 12943 if (soc_timeout_check(&to)) { 12944 LOG_WARN(BSL_LS_SOC_COMMON, 12945 (BSL_META_U(unit, "TS Thread exit timed out\n"))); 12946 } 12947 } while (ts_capture_info[unit]->time_capture_ts_active != 0); 12948 12949 /* Destroy the time capture semaphore */ 12950 sal_sem_destroy(ts_capture_info[unit]->ts_fifo_sem); 12951 12952 /* Free ts_capture info */ 12953 sal_free(ts_capture_info[unit]); 12954 ts_capture_info[unit] = NULL; 12955 12956 return BCM_E_NONE; 12957 } 12958 12959 #endif /* BCM_TIMESYNC_TIME_CAPTURE_SUPPORT */