2023-09-04 17:20:36 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								/*
 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-12 16:50:26 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								 *  SPDX - FileCopyrightText :  2022 - 2024  Espressif  Systems  ( Shanghai )  CO  LTD 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-04 17:20:36 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  SPDX - License - Identifier :  Apache - 2.0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-10-19 22:21:53 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# include  <sys/queue.h> 
 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-04 17:20:36 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								# include  "sdkconfig.h" 
 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-26 18:01:30 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# include  "freertos/FreeRTOS.h" 
 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-04 17:20:36 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								# include  "driver/gpio.h" 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  "esp_clock_output.h" 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  "esp_check.h" 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  "esp_rom_gpio.h" 
 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-15 14:12:47 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# include  "soc/clkout_channel.h" 
 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-04 17:20:36 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								# include  "hal/gpio_hal.h" 
 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-15 14:12:47 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# include  "hal/clk_tree_hal.h" 
 
							 
						 
					
						
							
								
									
										
										
										
											2023-12-14 18:12:09 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# include  "hal/clk_tree_ll.h" 
 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-04 17:20:36 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								# include  "soc/soc_caps.h" 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  "soc/io_mux_reg.h" 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-10-19 22:21:53 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								typedef  struct  clkout_channel_handle  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-04 17:20:36 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    bool  is_mapped ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-19 22:21:53 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    soc_clkout_sig_id_t  mapped_clock ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-01-22 21:48:12 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    clock_out_channel_t  channel_id ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-04 17:20:36 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    uint8_t  ref_cnt ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-19 22:21:53 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    uint64_t  mapped_io_bmap ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    portMUX_TYPE  clkout_channel_lock ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								}  clkout_channel_handle_t ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								typedef  struct  esp_clock_output_mapping  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-04 17:20:36 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    gpio_num_t  mapped_io ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-19 22:21:53 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    clkout_channel_handle_t *  clkout_channel_hdl ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    uint8_t  ref_cnt ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    portMUX_TYPE  clkout_mapping_lock ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    SLIST_ENTRY ( esp_clock_output_mapping )  next ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								}  esp_clock_output_mapping_t ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-04 17:20:36 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-10-19 22:21:53 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								static  const  char  * TAG  =  " esp_clock_output " ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-04 17:20:36 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-10-19 22:21:53 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								static  SLIST_HEAD ( esp_clock_output_mapping_head ,  esp_clock_output_mapping )  s_mapping_list  =  SLIST_HEAD_INITIALIZER ( s_mapping_list_head ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  portMUX_TYPE  s_mapping_list_lock  =  portMUX_INITIALIZER_UNLOCKED ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  portMUX_TYPE  s_clkout_lock  =  portMUX_INITIALIZER_UNLOCKED ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-04 17:20:36 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-10-19 22:21:53 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								static  clkout_channel_handle_t  s_clkout_handle [ CLKOUT_CHANNEL_MAX ]  =  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-04 17:20:36 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    [ 0  . . .  CLKOUT_CHANNEL_MAX  -  1 ]  =  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        . is_mapped  =  false , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        . ref_cnt  =  0 , 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-19 22:21:53 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        . mapped_io_bmap  =  0 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        . clkout_channel_lock  =  portMUX_INITIALIZER_UNLOCKED , 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-04 17:20:36 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-10-19 22:21:53 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								static  clkout_channel_handle_t *  clkout_channel_alloc ( soc_clkout_sig_id_t  clk_sig ,  gpio_num_t  gpio_num ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-04 17:20:36 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-19 22:21:53 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    clkout_channel_handle_t  * allocated_channel  =  NULL ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-04 17:20:36 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# if SOC_GPIO_CLOCKOUT_BY_IO_MUX 
 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-19 22:21:53 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    portENTER_CRITICAL ( & s_clkout_handle [ IONUM_TO_CLKOUT_CHANNEL ( gpio_num ) ] . clkout_channel_lock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ! s_clkout_handle [ IONUM_TO_CLKOUT_CHANNEL ( gpio_num ) ] . is_mapped )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        s_clkout_handle [ IONUM_TO_CLKOUT_CHANNEL ( gpio_num ) ] . is_mapped  =  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        allocated_channel  =  & s_clkout_handle [ IONUM_TO_CLKOUT_CHANNEL ( gpio_num ) ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    }  else  if  ( ( s_clkout_handle [ IONUM_TO_CLKOUT_CHANNEL ( gpio_num ) ] . mapped_io_bmap  &  BIT ( gpio_num ) )  & & 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-26 18:01:30 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								               ( s_clkout_handle [ IONUM_TO_CLKOUT_CHANNEL ( gpio_num ) ] . mapped_clock  = =  clk_sig ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-19 22:21:53 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        allocated_channel  =  & s_clkout_handle [ IONUM_TO_CLKOUT_CHANNEL ( gpio_num ) ] ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-04 17:20:36 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-19 22:21:53 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    allocated_channel - > channel_id  =  ( clock_out_channel_t ) IONUM_TO_CLKOUT_CHANNEL ( gpio_num ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    portEXIT_CRITICAL ( & s_clkout_handle [ IONUM_TO_CLKOUT_CHANNEL ( gpio_num ) ] . clkout_channel_lock ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-04 17:20:36 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								# elif SOC_GPIO_CLOCKOUT_BY_GPIO_MATRIX 
 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-26 18:01:30 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    for  ( uint32_t  channel  =  0 ;  channel  <  CLKOUT_CHANNEL_MAX ;  channel + + )  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-19 22:21:53 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        portENTER_CRITICAL ( & s_clkout_handle [ channel ] . clkout_channel_lock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( ! s_clkout_handle [ channel ] . is_mapped )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            s_clkout_handle [ channel ] . is_mapped  =  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            allocated_channel  =  & s_clkout_handle [ channel ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            allocated_channel - > channel_id  =  ( clock_out_channel_t ) channel ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            portEXIT_CRITICAL ( & s_clkout_handle [ channel ] . clkout_channel_lock ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-04 17:20:36 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								            break ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-19 22:21:53 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        }  else  if  ( s_clkout_handle [ channel ] . mapped_clock  = =  clk_sig )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            allocated_channel  =  & s_clkout_handle [ channel ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            portEXIT_CRITICAL ( & s_clkout_handle [ channel ] . clkout_channel_lock ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-04 17:20:36 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								            break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-19 22:21:53 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        portEXIT_CRITICAL ( & s_clkout_handle [ channel ] . clkout_channel_lock ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-04 17:20:36 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# endif 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-10-19 22:21:53 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( allocated_channel  ! =  NULL )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        portENTER_CRITICAL ( & allocated_channel - > clkout_channel_lock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        allocated_channel - > mapped_io_bmap  | =  BIT ( gpio_num ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        allocated_channel - > mapped_clock  =  clk_sig ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        allocated_channel - > ref_cnt + + ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( allocated_channel - > ref_cnt  = =  1 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            portENTER_CRITICAL ( & s_clkout_lock ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-12-14 18:12:09 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# if SOC_CLOCKOUT_HAS_SOURCE_GATE 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            clk_ll_enable_clkout_source ( clk_sig ,  true ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# endif 
 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-15 14:12:47 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            clk_hal_clock_output_setup ( clk_sig ,  allocated_channel - > channel_id ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-19 22:21:53 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            portEXIT_CRITICAL ( & s_clkout_lock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        portEXIT_CRITICAL ( & allocated_channel - > clkout_channel_lock ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-04 17:20:36 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-10-19 22:21:53 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    return  allocated_channel ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-04 17:20:36 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-10-19 22:21:53 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								static  esp_clock_output_mapping_t *  clkout_mapping_alloc ( clkout_channel_handle_t *  channel_hdl ,  gpio_num_t  gpio_num ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-04 17:20:36 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-19 22:21:53 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    esp_clock_output_mapping_t  * allocated_mapping  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    portENTER_CRITICAL ( & s_mapping_list_lock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    esp_clock_output_mapping_t  * hdl ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    SLIST_FOREACH ( hdl ,  & s_mapping_list ,  next )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( ( hdl - > clkout_channel_hdl  = =  channel_hdl )  & &  ( hdl - > mapped_io  = =  gpio_num ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            allocated_mapping  =  hdl ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    portEXIT_CRITICAL ( & s_mapping_list_lock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( allocated_mapping  = =  NULL )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        allocated_mapping  =  ( esp_clock_output_mapping_t  * ) malloc ( sizeof ( esp_clock_output_mapping_t ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        allocated_mapping - > mapped_io  =  gpio_num ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        allocated_mapping - > clkout_channel_hdl  =  channel_hdl ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        allocated_mapping - > ref_cnt  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        portMUX_INITIALIZE ( & allocated_mapping - > clkout_mapping_lock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        portENTER_CRITICAL ( & s_mapping_list_lock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        SLIST_INSERT_HEAD ( & s_mapping_list ,  allocated_mapping ,  next ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        portEXIT_CRITICAL ( & s_mapping_list_lock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    portENTER_CRITICAL ( & allocated_mapping - > clkout_mapping_lock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    allocated_mapping - > ref_cnt + + ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( allocated_mapping - > ref_cnt  = =  1 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# if SOC_GPIO_CLOCKOUT_BY_IO_MUX 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        gpio_hal_iomux_func_sel ( GPIO_PIN_MUX_REG [ gpio_num ] ,  CLKOUT_CHANNEL_TO_IOMUX_FUNC ( allocated_mapping - > clkout_channel_hdl - > channel_id ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# elif SOC_GPIO_CLOCKOUT_BY_GPIO_MATRIX 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        gpio_set_pull_mode ( gpio_num ,  GPIO_FLOATING ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        gpio_hal_iomux_func_sel ( GPIO_PIN_MUX_REG [ gpio_num ] ,  PIN_FUNC_GPIO ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        gpio_set_direction ( gpio_num ,  GPIO_MODE_OUTPUT ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        esp_rom_gpio_connect_out_signal ( gpio_num ,  CLKOUT_CHANNEL_TO_GPIO_SIG_ID ( allocated_mapping - > clkout_channel_hdl - > channel_id ) ,  false ,  false ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# endif 
 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-04 17:20:36 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-19 22:21:53 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    portEXIT_CRITICAL ( & allocated_mapping - > clkout_mapping_lock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  allocated_mapping ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-04 17:20:36 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-10-19 22:21:53 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								static  void  clkout_channel_free ( clkout_channel_handle_t  * channel_hdl ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-04 17:20:36 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-19 22:21:53 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    portENTER_CRITICAL ( & channel_hdl - > clkout_channel_lock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( - - channel_hdl - > ref_cnt  = =  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        portENTER_CRITICAL ( & s_clkout_lock ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-12-14 18:12:09 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# if SOC_CLOCKOUT_HAS_SOURCE_GATE 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        clk_ll_enable_clkout_source ( channel_hdl - > mapped_clock ,  false ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# endif 
 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-15 14:12:47 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        clk_hal_clock_output_teardown ( channel_hdl - > channel_id ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-19 22:21:53 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        portEXIT_CRITICAL ( & s_clkout_lock ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-12-14 18:12:09 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        channel_hdl - > mapped_clock  =  CLKOUT_SIG_INVALID ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-19 22:21:53 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        channel_hdl - > is_mapped  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    portEXIT_CRITICAL ( & channel_hdl - > clkout_channel_lock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-04 17:20:36 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-10-19 22:21:53 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								static  void  clkout_mapping_free ( esp_clock_output_mapping_t  * mapping_hdl ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    portENTER_CRITICAL ( & mapping_hdl - > clkout_mapping_lock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    clkout_channel_free ( mapping_hdl - > clkout_channel_hdl ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    bool  do_free_mapping_hdl  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( - - mapping_hdl - > ref_cnt  = =  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        gpio_hal_iomux_func_sel ( GPIO_PIN_MUX_REG [ mapping_hdl - > mapped_io ] ,  PIN_FUNC_GPIO ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        esp_rom_gpio_connect_out_signal ( mapping_hdl - > mapped_io ,  SIG_GPIO_OUT_IDX ,  false ,  false ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        gpio_set_direction ( mapping_hdl - > mapped_io ,  GPIO_MODE_DISABLE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        portENTER_CRITICAL ( & mapping_hdl - > clkout_channel_hdl - > clkout_channel_lock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        mapping_hdl - > clkout_channel_hdl - > mapped_io_bmap  & =  ~ BIT ( mapping_hdl - > mapped_io ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        portEXIT_CRITICAL ( & mapping_hdl - > clkout_channel_hdl - > clkout_channel_lock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        portENTER_CRITICAL ( & s_mapping_list_lock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        SLIST_REMOVE ( & s_mapping_list ,  mapping_hdl ,  esp_clock_output_mapping ,  next ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        portEXIT_CRITICAL ( & s_mapping_list_lock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        do_free_mapping_hdl  =  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    portEXIT_CRITICAL ( & mapping_hdl - > clkout_mapping_lock ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-04 17:20:36 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-10-19 22:21:53 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( do_free_mapping_hdl )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        free ( mapping_hdl ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-04 17:20:36 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-10-19 22:21:53 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								esp_err_t  esp_clock_output_start ( soc_clkout_sig_id_t  clk_sig ,  gpio_num_t  gpio_num ,  esp_clock_output_mapping_handle_t  * clkout_mapping_ret_hdl ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ESP_RETURN_ON_FALSE ( ( clkout_mapping_ret_hdl  ! =  NULL ) ,  ESP_ERR_INVALID_ARG ,  TAG ,  " Clock out mapping handle passed in is invalid " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-15 14:12:47 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# if SOC_GPIO_CLOCKOUT_BY_GPIO_MATRIX 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ESP_RETURN_ON_FALSE ( GPIO_IS_VALID_GPIO ( gpio_num ) ,  ESP_ERR_INVALID_ARG ,  TAG ,  " %s " ,  " Output GPIO number error " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# else 
 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-19 22:21:53 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    ESP_RETURN_ON_FALSE ( IS_VALID_CLKOUT_IO ( gpio_num ) ,  ESP_ERR_INVALID_ARG ,  TAG ,  " %s " ,  " Output GPIO number error " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-15 14:12:47 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# endif 
 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-04 17:20:36 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-10-19 22:21:53 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    esp_clock_output_mapping_t  * hdl ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    SLIST_FOREACH ( hdl ,  & s_mapping_list ,  next )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ESP_RETURN_ON_FALSE ( ! ( ( hdl - > mapped_io  = =  gpio_num )  & &  ( hdl - > clkout_channel_hdl - > mapped_clock  ! =  clk_sig ) ) ,  ESP_ERR_INVALID_ARG ,  TAG ,  " Selected io is already mapped by another signal " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-04 17:20:36 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-10-19 22:21:53 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    clkout_channel_handle_t  * channel_hdl  =  clkout_channel_alloc ( clk_sig ,  gpio_num ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-04 17:20:36 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								# if SOC_GPIO_CLOCKOUT_BY_IO_MUX 
 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-19 22:21:53 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    ESP_RETURN_ON_FALSE ( ( channel_hdl  ! =  NULL ) ,  ESP_ERR_INVALID_ARG ,  TAG ,  " Selected clock out IO is already mapped to other internal clock source " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-04 17:20:36 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								# elif SOC_GPIO_CLOCKOUT_BY_GPIO_MATRIX 
 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-19 22:21:53 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    ESP_RETURN_ON_FALSE ( ( channel_hdl  ! =  NULL ) ,  ESP_FAIL ,  TAG ,  " Maximum support for %d output clock signals, no available clock_out channel for assignment " ,  CLKOUT_CHANNEL_MAX ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-04 17:20:36 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								# endif 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-10-19 22:21:53 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    * clkout_mapping_ret_hdl  =  clkout_mapping_alloc ( channel_hdl ,  gpio_num ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-09-04 17:20:36 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    return  ESP_OK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-10-19 22:21:53 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								esp_err_t  esp_clock_output_stop ( esp_clock_output_mapping_handle_t  clkout_mapping_hdl ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-04 17:20:36 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-19 22:21:53 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    ESP_RETURN_ON_FALSE ( ( clkout_mapping_hdl  ! =  NULL ) ,  ESP_ERR_INVALID_ARG ,  TAG ,  " Clock out mapping handle passed in is invalid " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ESP_RETURN_ON_FALSE ( clkout_mapping_hdl - > ref_cnt  >  0 ,  ESP_ERR_INVALID_STATE ,  TAG ,  " %s " ,  " Clock outputting is already disabled " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    clkout_mapping_free ( clkout_mapping_hdl ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-04 17:20:36 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    return  ESP_OK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-04-12 16:50:26 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# if SOC_CLOCKOUT_SUPPORT_CHANNEL_DIVIDER 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								esp_err_t  esp_clock_output_set_divider ( esp_clock_output_mapping_handle_t  clkout_mapping_hdl ,  uint32_t  div_num ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ESP_RETURN_ON_FALSE ( ( ( div_num  >  0 )  & &  ( div_num  < =  256 ) ) ,  ESP_ERR_INVALID_ARG ,  TAG ,  " Divider number must be in the range of [1,  256] " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ESP_RETURN_ON_FALSE ( ( clkout_mapping_hdl  ! =  NULL ) ,  ESP_ERR_INVALID_ARG ,  TAG ,  " Clock out mapping handle passed in is invalid " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    portENTER_CRITICAL ( & clkout_mapping_hdl - > clkout_mapping_lock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    clk_hal_clock_output_set_divider ( clkout_mapping_hdl - > clkout_channel_hdl - > channel_id ,  div_num ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    portEXIT_CRITICAL ( & clkout_mapping_hdl - > clkout_mapping_lock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  ESP_OK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# endif 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-09-04 17:20:36 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								# if CONFIG_IDF_TARGET_ESP32 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// Due to a hardware bug, PIN_CTRL cannot select 0xf output, whereas 0xf is the default value.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								__attribute__ ( ( constructor ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  void  esp_clock_output_pin_ctrl_init ( void ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    gpio_ll_set_pin_ctrl ( 0 ,  CLK_OUT1 ,  CLK_OUT1_S ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    gpio_ll_set_pin_ctrl ( 0 ,  CLK_OUT2 ,  CLK_OUT2_S ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    gpio_ll_set_pin_ctrl ( 0 ,  CLK_OUT3 ,  CLK_OUT3_S ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# endif