LOCAL &function &args
ENTRY &function %LINE &args
// --  J721E_OBSCLK.GEL 
// --  Copyright (c) 2019, Texas Instruments Incorporated
// --  * All rights reserved.
// --  *
// --  * Redistribution and use in source and binary forms, with or without
// --  * modification, are permitted provided that the following conditions
// --  * are met:
// --  *
// --  * *  Redistributions of source code must retain the above copyright
// --  *    notice, this list of conditions and the following disclaimer.
// --  *
// --  * *  Redistributions in binary form must reproduce the above copyright
// --  *    notice, this list of conditions and the following disclaimer in the
// --  *    documentation and/or other materials provided with the distribution.
// --  *
// --  * *  Neither the name of Texas Instruments Incorporated nor the names of
// --  *    its contributors may be used to endorse or promote products derived
// --  *    from this software without specific prior written permission.
// --  *
// --  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// --  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
// --  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// --  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// --  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// --  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// --  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
// --  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
// --  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
// --  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
// --  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
LOCAL &__CSL_MAIN_CTRL_MMR_CFG0_OBSCLK_CTRL
&__CSL_MAIN_CTRL_MMR_CFG0_OBSCLK_CTRL=(0x00008000)
LOCAL &__CSL_WKUP_CTRL_MMR_CFG0_MCU_OBSCLK_CTRL
&__CSL_WKUP_CTRL_MMR_CFG0_MCU_OBSCLK_CTRL=(0x00008000)
LOCAL &__WAKEUP_PSC_BASE
&__WAKEUP_PSC_BASE=(0x42000000)
LOCAL &__PSC_PID
&__PSC_PID=(0x44827A00)
LOCAL &__CSL_MAIN_CTRL_MMR0_CFG0_BASE
&__CSL_MAIN_CTRL_MMR0_CFG0_BASE=(0x100000)
LOCAL &__CSL_WKUP_CTRL_MMR0_CFG0_BASE
&__CSL_WKUP_CTRL_MMR0_CFG0_BASE=(0x43000000)
// -- Main Control MMR Lock Registers
LOCAL &__CSL_MAIN_CTRL_MMR_CFG0_LOCK2_KICK0
&__CSL_MAIN_CTRL_MMR_CFG0_LOCK2_KICK0=(0x00009008)
LOCAL &__CSL_MAIN_CTRL_MMR_CFG0_LOCK2_KICK1
&__CSL_MAIN_CTRL_MMR_CFG0_LOCK2_KICK1=(0x0000900C)
LOCAL &__CSL_WKUP_CTRL_MMR_CFG0_LOCK2_KICK0
&__CSL_WKUP_CTRL_MMR_CFG0_LOCK2_KICK0=(0x00009008)
LOCAL &__CSL_WKUP_CTRL_MMR_CFG0_LOCK2_KICK1
&__CSL_WKUP_CTRL_MMR_CFG0_LOCK2_KICK1=(0x0000900C)
// -- MMR unlock keys
LOCAL &__KICK0_UNLOCK_VAL
&__KICK0_UNLOCK_VAL=(0x68EF3490)
LOCAL &__KICK1_UNLOCK_VAL
&__KICK1_UNLOCK_VAL=(0xD172BC5A)
LOCAL &__KICK_LOCK_VAL
&__KICK_LOCK_VAL=(0x00000000)

GLOBAL &path_J721E_OBSCLK_cmm
&path_J721E_OBSCLK_cmm=OS.PPF()
IF "&function"!=""
(
	GOSUB &function &args
)
ELSE
(
	GOSUB __GeL_MeNu_CrEaTe
)
ENDDO
// --  Global Helper Functions 
// --  ************************************************************************* 
// --  Read from an MMR. 

Read_MMR:
(
	PRIVATE &__VF0
	ENTRY &__VF0
	
	&__VF0=&__VF0 // evaluation of passed expression 
	
	Var.NEWLOCAL unsigned int \mmr_address=&__VF0
	Var.NEWLOCAL unsigned int * \p_mmr
	Var.Assign \p_mmr=((unsigned int *)\mmr_address)
	&__FUNCTION_RETURN_VALUE=Var.Value(*\p_mmr)
	RETURN &__FUNCTION_RETURN_VALUE
	RETURN
)
// --  Write to an MMR. 

Write_MMR:
(
	PRIVATE &__VF0 &__VF1
	ENTRY &__VF0 &__VF1
	
	&__VF0=&__VF0 // evaluation of passed expressions 
	&__VF1=&__VF1
	
	Var.NEWLOCAL unsigned int \mmr_address=&__VF0
	Var.NEWLOCAL unsigned int \mmr_value=&__VF1
	Var.NEWLOCAL unsigned int * \p_mmr
	Var.Assign \p_mmr=((unsigned int *)\mmr_address)
	Data.Set D:(Var.VALUE(\p_mmr)) %Long Var.VALUE(\mmr_value)
	RETURN
)
// --  Write to a specific field in an MMR. 
// -- TODO: Don't use this function yet

Write_MMR_Field:
(
	PRIVATE &__VF0 &__VF1 &__VF2 &__VF3
	ENTRY &__VF0 &__VF1 &__VF2 &__VF3
	
	&__VF0=&__VF0 // evaluation of passed expressions 
	&__VF1=&__VF1
	&__VF2=&__VF2
	&__VF3=&__VF3
	
	Var.NEWLOCAL unsigned int \mmr_address=&__VF0
	Var.NEWLOCAL unsigned int \value=&__VF1
	Var.NEWLOCAL unsigned int \mask=&__VF2
	Var.NEWLOCAL unsigned int \leftshift=&__VF3
	Var.NEWLOCAL unsigned int * \p_mmr
	Var.Assign \p_mmr=((unsigned int *)\mmr_address)
	Var.Assign \value=(\value<<\leftshift)
	Var.Assign (*\p_mmr|=\value)
	Data.Set D:(Var.VALUE(\p_mmr)) %Long Var.VALUE(mmr_value)
	RETURN
)

__GeL_MeNu_CrEaTe:
(
	MENU.ReProgram
	(
		ADD
		MENU
		(
			POPUP "GEL"
			(
				POPUP "Observation Clock"
				(
					MENUITEM "Configure_OBSCLK" 
					(
						DO "&path_J721E_OBSCLK_cmm" Configure_OBSCLK_dialog
					)
					MENUITEM "Configure_MCU_OBSCLK" 
					(
						DO "&path_J721E_OBSCLK_cmm" Configure_MCU_OBSCLK_dialog
					)
				)
			)
		)
	)
	RETURN
)

Configure_OBSCLK_dialog:
(
	Var.NEW unsigned long long \Clock_mux_index
	VAR.ASSIGN \Clock_mux_index=0
	
	Var.NEW unsigned long long \divider_value
	VAR.ASSIGN \divider_value=0

        DIALOG
	(
		HEADER "Configure_OBSCLK"
		POS 0. 0. 49.
		TEXT "Observation Clock Multiplexer Index: "
		POS 0. 1. 49.
		TEXT "Output Divider Value (+1 factored in already): "
		POS 49. 0. 10.
		EDIT "" "&Clock_mux_index=*"
		POS 49. 1. 10.
		EDIT "" "&divider_value=*"
		POS 0. 2. 59.
		BUTTON "Execute" 
		(
			DO &path_J721E_OBSCLK_cmm Configure_OBSCLK &Clock_mux_index &divider_value
		)
	)
	RETURN
)

Configure_OBSCLK:
(
	ENTRY &__VF0 &__VF1
	
	Var.NEW unsigned long long \Clock_mux_index
	VAR.ASSIGN \Clock_mux_index=&__VF0
	
	Var.NEW unsigned long long \divider_value
	VAR.ASSIGN \divider_value=&__VF1
	
	
	Var.NEW unsigned int \temp_val
	Var.NEW unsigned int \temp_val2
	Var.NEW unsigned int \temp_val3
	Var.NEW unsigned int \reg_val
	Var.NEW unsigned int \LOAD
	Var.NEW unsigned int \address_offset
	Var.Assign \temp_val=0x0
	Var.Assign \temp_val2=0x0
	Var.Assign \temp_val3=0x0
	Var.Assign \reg_val=0x0
	Var.Assign \LOAD=0x10000
	IF (Data.Long(D:(&__WAKEUP_PSC_BASE))!=&__PSC_PID)
	(
		Var.Assign \address_offset=0x80000000
	)
	// -- Main Control MMRs use the offset of 0x8000_0000.
	// -- Error checking against user input. This should be taken care of anyhow.
	Var.IF ((\divider_value)>0xFF)
	(
		PRINT "********ERROR: Divider Value is too large."
		PRINT ""
		RETURN
	)
	Var.IF ((\Clock_mux_index)>=0x20)
	(
		PRINT "********ERROR: Invalid observation clock multiplexer selection."
		PRINT ""
		RETURN
	)
	// -- Unlock Main CTRL MMR Partition 2
	GOSUB Write_MMR ((&__CSL_MAIN_CTRL_MMR0_CFG0_BASE+&__CSL_MAIN_CTRL_MMR_CFG0_LOCK2_KICK0)+Var.Value(\address_offset)) &__KICK0_UNLOCK_VAL
	GOSUB Write_MMR ((&__CSL_MAIN_CTRL_MMR0_CFG0_BASE+&__CSL_MAIN_CTRL_MMR_CFG0_LOCK2_KICK1)+Var.Value(\address_offset)) &__KICK1_UNLOCK_VAL
	GOSUB Read_MMR ((&__CSL_MAIN_CTRL_MMR0_CFG0_BASE+&__CSL_MAIN_CTRL_MMR_CFG0_OBSCLK_CTRL)+Var.Value(\address_offset))
	ENTRY &__V2
	Var.Assign \temp_val=&__V2
	AREA.Select
	PRINT "OBSCLK control MMR value: " %HEX Var.VALUE(\temp_val) ""
	PRINT ""
	Var.Assign \reg_val=\Clock_mux_index
	Var.Assign \temp_val=(\divider_value<<0x8)
	Var.Assign (\reg_val|=\temp_val)
	GOSUB Write_MMR ((&__CSL_MAIN_CTRL_MMR0_CFG0_BASE+&__CSL_MAIN_CTRL_MMR_CFG0_OBSCLK_CTRL)+Var.Value(\address_offset)) Var.VALUE(\reg_val)
	Var.Assign (\reg_val|=\LOAD)
	GOSUB Write_MMR ((&__CSL_MAIN_CTRL_MMR0_CFG0_BASE+&__CSL_MAIN_CTRL_MMR_CFG0_OBSCLK_CTRL)+Var.Value(\address_offset)) Var.VALUE(\reg_val)
	GOSUB Read_MMR ((&__CSL_MAIN_CTRL_MMR0_CFG0_BASE+&__CSL_MAIN_CTRL_MMR_CFG0_OBSCLK_CTRL)+Var.Value(\address_offset))
	ENTRY &__V5
	Var.Assign \temp_val=&__V5
	AREA.Select
	PRINT "OBSCLK control MMR value: " %HEX Var.VALUE(\temp_val) ""
	PRINT ""
	PRINT "Main OBSCLK successfully programmed."
	PRINT ""
	RETURN
)

Configure_MCU_OBSCLK_dialog:
(
	Var.NEW unsigned long long \Clock_mux_index
	VAR.ASSIGN \Clock_mux_index=0
	
	Var.NEW unsigned long long \divider_value
	VAR.ASSIGN \divider_value=0
	
	DIALOG
	(
		HEADER "Configure_MCU_OBSCLK"
		POS 0. 0. 49.
		TEXT "Observation Clock Multiplexer Index: "
		POS 0. 1. 49.
		TEXT "Output Divider Value (+1 factored in already): "
		POS 49. 0. 10.
		EDIT "" "&Clock_mux_index=*"
		POS 49. 1. 10.
		EDIT "" "&divider_value=*"
		POS 0. 2. 59.
		BUTTON "Execute" 
		(
			DO &path_J721E_OBSCLK_cmm Configure_MCU_OBSCLK &Clock_mux_index &divider_value
		)
	)
	RETURN
)

Configure_MCU_OBSCLK:
(
	ENTRY &__VF0 &__VF1
	
	Var.NEW unsigned long long \Clock_mux_index
	VAR.ASSIGN \Clock_mux_index=&__VF0
	
	Var.NEW unsigned long long \divider_value
	VAR.ASSIGN \divider_value=&__VF1
	
	
	Var.NEW unsigned int \temp_val
	Var.NEW unsigned int \temp_val2
	Var.NEW unsigned int \temp_val3
	Var.NEW unsigned int \reg_val
	Var.NEW unsigned int \LOAD
	Var.NEW unsigned int \address_offset
	Var.Assign \temp_val=0x0
	Var.Assign \temp_val2=0x0
	Var.Assign \temp_val3=0x0
	Var.Assign \reg_val=0x0
	Var.Assign \LOAD=0x10000
	IF (Data.Long(D:(&__WAKEUP_PSC_BASE))!=&__PSC_PID)
	(
		Var.Assign \address_offset=0x20000000
	)
	// -- WKUP Control MMRs use the offset of 0x8000_0000.
	// -- Error checking against user input. This should be taken care of anyhow.
	Var.IF ((\divider_value)>0xF)
	(
		PRINT "********ERROR: Divider Value is too large."
		PRINT ""
		RETURN
	)
	Var.IF ((\Clock_mux_index)>=0x10)
	(
		PRINT "********ERROR: Invalid observation clock multiplexer selection."
		PRINT ""
		RETURN
	)
	// -- Unlock WKUP CTRL MMR Partition 2
	GOSUB Write_MMR ((&__CSL_WKUP_CTRL_MMR0_CFG0_BASE+&__CSL_WKUP_CTRL_MMR_CFG0_LOCK2_KICK0)+Var.Value(\address_offset)) &__KICK0_UNLOCK_VAL
	GOSUB Write_MMR ((&__CSL_WKUP_CTRL_MMR0_CFG0_BASE+&__CSL_WKUP_CTRL_MMR_CFG0_LOCK2_KICK1)+Var.Value(\address_offset)) &__KICK1_UNLOCK_VAL
	GOSUB Read_MMR ((&__CSL_WKUP_CTRL_MMR0_CFG0_BASE+&__CSL_WKUP_CTRL_MMR_CFG0_MCU_OBSCLK_CTRL)+Var.Value(\address_offset))
	ENTRY &__V8
	Var.Assign \temp_val=&__V8
	AREA.Select
	PRINT "MCU OBSCLK control MMR value: " %HEX Var.VALUE(\temp_val) ""
	PRINT ""
	Var.Assign \reg_val=\Clock_mux_index
	Var.Assign \temp_val=(\divider_value<<0x8)
	Var.Assign (\reg_val|=\temp_val)
	GOSUB Write_MMR ((&__CSL_WKUP_CTRL_MMR0_CFG0_BASE+&__CSL_WKUP_CTRL_MMR_CFG0_MCU_OBSCLK_CTRL)+Var.Value(\address_offset)) Var.VALUE(\reg_val)
	Var.Assign (\reg_val|=\LOAD)
	GOSUB Write_MMR ((&__CSL_WKUP_CTRL_MMR0_CFG0_BASE+&__CSL_WKUP_CTRL_MMR_CFG0_MCU_OBSCLK_CTRL)+Var.Value(\address_offset)) Var.VALUE(\reg_val)
	GOSUB Read_MMR ((&__CSL_WKUP_CTRL_MMR0_CFG0_BASE+&__CSL_WKUP_CTRL_MMR_CFG0_MCU_OBSCLK_CTRL)+Var.Value(\address_offset))
	ENTRY &__V11
	Var.Assign \temp_val=&__V11
	AREA.Select
	PRINT "MCU OBSCLK control MMR value: " %HEX Var.VALUE(\temp_val) ""
	PRINT ""
	PRINT "MCU OBSCLK successfully programmed."
	PRINT ""
	RETURN
)
