// ===========================================================================
// Include Files
// ---------------------------------------------------------------------------
#include "hal_dbg.h"
#include "hal_lmk.h"
#include "hal_spi.h"
#include "hal_timer.h"

// ===========================================================================
// External Data Definitions
// ---------------------------------------------------------------------------

// ===========================================================================
// Local Defines
// ---------------------------------------------------------------------------
#define LMK_DEFAULT_REGS_LENGTH						113

#define LMK_LOCK_TIMEOUT_US							3000
#define LMK_LOCK_TIMEOUT_MS							1000
//#define LMK_LOCK_TIMEOUT							(LMK_LOCK_TIMEOUT_US * HAL_TIMER_USEC_PRESCALAR)
#define LMK_LOCK_TIMEOUT							(LMK_LOCK_TIMEOUT_MS * HAL_TIMER_MSEC_PRESCALAR)

// ===========================================================================
// Local Structures
// ---------------------------------------------------------------------------

// ===========================================================================
// Local Data Definitions
// ---------------------------------------------------------------------------
SPI_HANDLE_Type	*lmk_spi_handle;


// Osc = 80 MHz & DAC
const u16 lmk_modem_default_cfg_regs[LMK_DEFAULT_REGS_LENGTH][2] = {
	{0x0000, 	0x90},		// RESET[b7]=1-Reset, SPI_3WIRE_DIS[b4]=1-4Wire
	{0x0000, 	0x10},		// RESET[b7]=0-Normal, SPI_3WIRE_DIS[b4]=1-4Wire
	{0x0002, 	0x00},		// POWER_DOWN[b0]=0-Disabled

	{0x0100, 	0x18}, 		// Clkout0_1_ODL[b6] = 0, Clkout0_1_IDL[b5] = 0, DCLKout0_DIV[b4:b0] = 24 (MGT_REFCLK0: 100 MHz / MGT_RX_SYSREF)
	{0x0101, 	0x55},		// DCLKout0_DDLY_CNTH[b7:b4] = 5, DCLKout0_DDLY_CNTL[b3:b0] = 5
	{0x0103, 	0x01},		// DCLKout0_ADLY[b7:b3] = 0 ps, DCLKout0_ADLY_MUX[b2] = 0, DCLKout0_MUX[b1:b0] = 1-Divider with DutyCycleCorr and HalfStep
	{0x0104, 	0x20},		// DCLKout0_HS[b6] = 0 cycle, SDCLKout1_MUX[b5] = 1-SYSREF, SDCLKout1_DDLY[b4:b1] = 0-Bypass, SDCLKout1_HS[b0] = 0 cycle
	{0x0105, 	0x00},		// SDCLKout1_ADLY_EN[b4] = 0-Disabled, SDCLKout1_ADLY[b3:b0] = 0 ps
	{0x0106, 	0xF0},		// DCLKout0_DDLY_PD[b7] = 1-PwrDwn, DCLKout0_HSg_PD[b6] = 1-PwrDwn, DCLKout0_ADLYg_PD[b5] = 1-PwrDwn, DCLKout0_ADLY_PD[b4] = 1-PwrDwn, CLKout0_1_PD[b3] = 0-Enabled, SDCLKout1_DIS_MODE[b2:b1] = 0-Active, SDCLKout1_PD[b0] = 0-Enabled
	{0x0107, 	0x55},		// SDCLKout1_POL[b7] = 0-Normal, SDCLKout1_FMT[b6:b4] = 5-LVPECL1600, DCLKout0_POL[b3] = 0-Normal, DCLKout0_FMT[b2:b0] = 5-LVPECL1600

	{0x0108, 	0x0C},		// Clkout2_3_ODL[b6] = 0, Clkout2_3_IDL[b5] = 0, DCLKout2_DIV[b4:b0] = 12 (JESD204B_TX_CORECLK/JESD204B_RX_CORECLK: 200 MHz)
	{0x0109, 	0x55},		// DCLKout2_DDLY_CNTH[b7:b4] = 5, DCLKout2_DDLY_CNTL[b3:b0] = 5
	{0x010B, 	0x01},		// DCLKout2_ADLY[b7:b3] = 0 ps, DCLKout2_ADLY_MUX[b2] = 0, DCLKout2_MUX[b1:b0] = 1-Divider with DutyCycleCorr and HalfStep
	{0x010C, 	0x20},		// DCLKout2_HS[b6] = 0 cycle, SDCLKout3_MUX[b5] = 1-SYSREF, SDCLKout3_DDLY[b4:b1] = 0-Bypass, SDCLKout3_HS[b0] = 0 cycle
	{0x010D, 	0x00},		// SDCLKout3_ADLY_EN[b4] = 0-Disabled, SDCLKout3_ADLY[b3:b0] = 0 ps
	{0x010E, 	0xF0},		// DCLKout2_DDLY_PD[b7] = 1-PwrDwn, DCLKout2_HSg_PD[b6] = 1-PwrDwn, DCLKout2_ADLYg_PD[b5] = 1-PwrDwn, DCLKout2_ADLY_PD[b4] = 1-PwrDwn, CLKout2_3_PD[b3] = 0-Enabled, SDCLKout3_DIS_MODE[b2:b1] = 0-Active, SDCLKout3_PD[b0] = 0-Enabled
	{0x010F, 	0x55},		// SDCLKout3_POL[b7] = 0-Normal, SDCLKout3_FMT[b6:b4] = 5-LVPECL1600, DCLKout2_POL[b3] = 0-Normal, DCLKout2_FMT[b2:b0] = 5-LVPECL1600

	{0x0110, 	0x18}, 		// Clkout4_5_ODL[b6] = 0, Clkout4_5_IDL[b5] = 0, DCLKout4_DIV[b4:b0] = 24 (MGT_REFCLK2_DAC: 100 MHz / MGT_TX_SYSREF)
	{0x0111, 	0x55},		// DCLKout4_DDLY_CNTH[b7:b4] = 5, DCLKout4_DDLY_CNTL[b3:b0] = 5
	{0x0113, 	0x01},		// DCLKout4_ADLY[b7:b3] = 0 ps, DCLKout4_ADLY_MUX[b2] = 0, DCLKout4_MUX[b1:b0] = 1-Divider with DutyCycleCorr and HalfStep
	{0x0114, 	0x20},		// DCLKout4_HS[b6] = 0 cycle, SDCLKout5_MUX[b5] = 1-SYSREF, SDCLKout5_DDLY[b4:b1] = 0-Bypass, SDCLKout5_HS[b0] = 0 cycle
	{0x0115, 	0x00},		// SDCLKout5_ADLY_EN[b4] = 0-Disabled, SDCLKout5_ADLY[b3:b0] = 0 ps
	{0x0116, 	0xF0},		// DCLKout4_DDLY_PD[b7] = 1-PwrDwn, DCLKout4_HSg_PD[b6] = 1-PwrDwn, DCLKout4_ADLYg_PD[b5] = 1-PwrDwn, DCLKout4_ADLY_PD[b4] = 1-PwrDwn, CLKout4_5_PD[b3] = 0-Enabled, SDCLKout5_DIS_MODE[b2:b1] = 0-Active, SDCLKout5_PD[b0] = 0-Enabled
{0x0117, 	0x15},//0x11},		// SDCLKout5_POL[b7] = 0-Normal, SDCLKout5_FMT[b6:b4] = 1-LVDS, DCLKout4_POL[b3] = 0-Normal, DCLKout4_FMT[b2:b0] = 1-LVDS

	{0x0118, 	0x06},		// Clkout6_7_ODL[b6] = 0, Clkout6_7_IDL[b5] = 0, DCLKout6_DIV[b4:b0] = 6 (DAC_TX_CLKIN: 400 MHz / DAC_TX_SYSREF)
	{0x0119, 	0x55},		// DCLKout6_DDLY_CNTH[b7:b4] = 5, DCLKout6_DDLY_CNTL[b3:b0] = 5
	{0x011B, 	0x01},		// DCLKout6_ADLY[b7:b3] = 0 ps, DCLKout6_ADLY_MUX[b2] = 0, DCLKout6_MUX[b1:b0] = 1-Divider with DutyCycleCorr and HalfStep
	{0x011C, 	0x20},		// DCLKout6_HS[b6] = 0 cycle, SDCLKout7_MUX[b5] = 1-SYSREF, SDCLKout7_DDLY[b4:b1] = 0-Bypass, SDCLKout7_HS[b0] = 0 cycle
	{0x011D, 	0x00},		// SDCLKout7_ADLY_EN[b4] = 0-Disabled, SDCLKout7_ADLY[b3:b0] = 0 ps
	{0x011E, 	0xF0},		// DCLKout6_DDLY_PD[b7] = 1-PwrDwn, DCLKout6_HSg_PD[b6] = 1-PwrDwn, DCLKout6_ADLYg_PD[b5] = 1-PwrDwn, DCLKout6_ADLY_PD[b4] = 1-PwrDwn, CLKout6_7_PD[b3] = 0-Enabled, SDCLKout7_DIS_MODE[b2:b1] = 0-Active, SDCLKout7_PD[b0] = 0-Enabled
	{0x011F, 	0x55},		// SDCLKout7_POL[b7] = 0-Normal, SDCLKout7_FMT[b6:b4] = 5-LVPECL1600, DCLKout6_POL[b3] = 0-Normal, DCLKout6_FMT[b2:b0] = 5-LVPECL1600

	{0x0120, 	0x0C}, 		// Clkout8_9_ODL[b6] = 0, Clkout8_9_IDL[b5] = 0, DCLKout8_DIV[b4:b0] = 12 (FPGA_CLK: 200 MHz)
	{0x0121, 	0x55},		// DCLKout8_DDLY_CNTH[b7:b4] = 5, DCLKout8_DDLY_CNTL[b3:b0] = 5
	{0x0123, 	0x01},		// DCLKout8_ADLY[b7:b3] = 0 ps, DCLKout8_ADLY_MUX[b2] = 0, DCLKout8_MUX[b1:b0] = 1-Divider with DutyCycleCorr and HalfStep
	{0x0124, 	0x20},		// DCLKout8_HS[b6] = 0 cycle, SDCLKout9_MUX[b5] = 1-SYSREF, SDCLKout9_DDLY[b4:b1] = 0-Bypass, SDCLKout9_HS[b0] = 0 cycle
	{0x0125, 	0x00},		// SDCLKout9_ADLY_EN[b4] = 0-Disabled, SDCLKout9_ADLY[b3:b0] = 0 ps
	{0x0126, 	0xF1},		// DCLKout8_DDLY_PD[b7] = 1-PwrDwn, DCLKout8_HSg_PD[b6] = 1-PwrDwn, DCLKout8_ADLYg_PD[b5] = 1-PwrDwn, DCLKout8_ADLY_PD[b4] = 1-PwrDwn, CLKout8_9_PD[b3] = 0-Enabled, SDCLKout9_DIS_MODE[b2:b1] = 0-Active, SDCLKout9_PD[b0] = 1-PwrDwn
{0x0127, 	0x05},//0x01},		// SDCLKout9_POL[b7] = 0-Normal, SDCLKout9_FMT[b6:b4] = 0-PwrDwn, DCLKout8_POL[b3] = 0-Normal, DCLKout8_FMT[b2:b0] = 1-LVDS

	{0x0128, 	0x00},		// Clkout10_11_ODL[b6] = 0, Clkout10_11_IDL[b5] = 0, DCLKout10_DIV[b4:b0] = 32
	{0x0129, 	0x55},		// DCLKout10_DDLY_CNTH[b7:b4] = 5, DCLKout0_DDLY_CNTL[b3:b0] = 5
	{0x012B, 	0x01},		// DCLKout10_ADLY[b7:b3] = 0 ps, DCLKout10_ADLY_MUX[b2] = 0, DCLKout10_MUX[b1:b0] = 1-Divider with DutyCycleCorr and HalfStep
	{0x012C, 	0x20},		// DCLKout10_HS[b6] = 0 cycle, SDCLKout11_MUX[b5] = 1-SYSREF, SDCLKout11_DDLY[b4:b1] = 0-Bypass, SDCLKout11_HS[b0] = 0 cycle
	{0x012D, 	0x00},		// SDCLKout11_ADLY_EN[b4] = 0-Disabled, SDCLKout11_ADLY[b3:b0] = 0 ps
	{0x012E, 	0xF9},		// DCLKout10_DDLY_PD[b7] = 1-PwrDwn, DCLKout10_HSg_PD[b6] = 1-PwrDwn, DCLKout10_ADLYg_PD[b5] = 1-PwrDwn, DCLKout10_ADLY_PD[b4] = 1-PwrDwn, CLKout10_11_PD[b3] = 1-PwrDwn, SDCLKout11_DIS_MODE[b2:b1] = 0-Active, SDCLKout11_PD[b0] = 1-PwrDwn
	{0x012F, 	0x00},		// SDCLKout11_POL[b7] = 0-Normal, SDCLKout11_FMT[b6:b4] = 0-PwrDwn, DCLKout10_POL[b3] = 0-Normal, DCLKout10_FMT[b2:b0] = 0-PwrDwn

	{0x0130, 	0x03}, 		// Clkout12_13_ODL[b6] = 0, Clkout12_13_IDL[b5] = 0, DCLKout12_DIV[b4:b0] = 3 (ADC_IF_CLKIN: 800 MHz / ADC_IF_SYSREF)
	{0x0131, 	0x55},		// DCLKout12_DDLY_CNTH[b7:b4] = 5, DCLKout12_DDLY_CNTL[b3:b0] = 5
	{0x0133, 	0x01},		// DCLKout12_ADLY[b7:b3] = 0 ps, DCLKout12_ADLY_MUX[b2] = 0, DCLKout12_MUX[b1:b0] = 1-Divider with DutyCycleCorr and HalfStep
	{0x0134, 	0x20},		// DCLKout12_HS[b6] = 0 cycle, SDCLKout13_MUX[b5] = 1-SYSREF, SDCLKout13_DDLY[b4:b1] = 0-Bypass, SDCLKout13_HS[b0] = 0 cycle
	{0x0135, 	0x00},		// SDCLKout13_ADLY_EN[b4] = 0-Disabled, SDCLKout13_ADLY[b3:b0] = 0 ps
	{0x0136, 	0xF0},		// DCLKout12_DDLY_PD[b7] = 1-PwrDwn, DCLKout12_HSg_PD[b6] = 1-PwrDwn, DCLKout12_ADLYg_PD[b5] = 1-PwrDwn, DCLKout12_ADLY_PD[b4] = 1-PwrDwn, CLKout12_13_PD[b3] = 0-Enabled, SDCLKout13_DIS_MODE[b2:b1] = 0-Active, SDCLKout13_PD[b0] = 0-Enabled
	{0x0137, 	0x55},		// SDCLKout13_POL[b7] = 0-Normal, SDCLKout13_FMT[b6:b4] = 5-LVPECL1600, DCLKout12_POL[b3] = 0-Normal, DCLKout12_FMT[b2:b0] = 5-LVPECL1600

	{0x0138, 	0x04},		// VCO_MUX[b6:b5] = 0-VCO0, OSCout_MUX[b4] = 0-Buffered OSCin, OSCout_FMT[b3:b0] = 4-LVPECL1600
{0x0139, 	0x02},//0x00},		// SYSREF_CLKin_MUX[b2] = 0-SYSREF Mux, SYSREF_Mux[b1:b0] = 0-NormalSync
	{0x013A, 	0x03}, 		// SYSREF_DIV_12_8[b4:b0] = Div-768 (F_LMFC_DAC=F_line/10/F/K=25 MHz, F_SYSREF=F_LMFC_DAC/n-integer=3.125 MHz for n-integer=8)
	{0x013B, 	0x00},		// SYSREF_DIV_7_0[b7:b0] = Div-768 (F_LMFC_ADC=F_line/10/F/K=50 MHz, F_SYSREF=F_LMFC_ADC/2^n-integer=3.125 MHz for n-integer=4)
	{0x013C, 	0x00},		// SYSREF_DDLY_12_8[b4:b0] = DDLY-8
	{0x013D, 	0x08},		// SYSREF_DDLY_7_0[b7:b0] = DDLY-8
	{0x013E, 	0x03},		// SYSREF_PULSE_CNT[b1:b0] = 3 - 8 pulses
	{0x013F, 	0x0B},		// PLL2_NCLK_MUX[b4] = 0-PLL2 Prescalar, PLL1_NCLK_MUX[b3] = 1-FeedbackMux, FB_MUX[b2:b1] = 1-DCLKout8(FPGA_CLK), FB_MUX_EN[b0] = 1-Enabled
	{0x0140, 	0x00},		// PLL1_PD[b7]=0-Normal, VCO_LDO_PD[b6]=0-Normal, VCO_PD[b5]=0-Normal, OSCin_PD[b4]=0-Normal, SYSREF_GLB_PD[b3]=0-Normal, SYSREF_PD[b2]=0-Normal, SYSREF_DDLY_PD[b1]=0-Normal, SYSREF_PLSR_PD[b7]=0-Normal
	{0x0141, 	0x00},		// DDLYd_SYSREF_EN[b7]=0-Disabled, DDLYd_12_EN[b6]=0-Disabled, DDLYd_10_EN[b5]=0-Disabled, DDLYd_8_EN[b4]=0-Disabled, DDLYd_6_EN[b3]=0-Disabled, DDLYd_4_EN[b2]=0-Disabled, DDLYd_2_EN[b1]=0-Disabled, DDLYd_0_EN[b0]=0-Disabled,
	{0x0142, 	0x00},		// DDLYd_STEP_CNT[b3:b0] = 0-No Adjust
{0x0143, 	0x92},//0x91},		// SYSREF_CLR[b7]=1, SYNC_1SHOT_EN[b6]=0-Disabled, SYNC_POL[b5]=0-Normal, SYNC_EN[b4]=1-Enabled, SYNC_PLL2_DLD[b3]=0-OFF, SYNC_PLL1_DLD[b2]=0-OFF, SYNC_MODE[b1:b0]=1-"SYNC event generated from SYNC pin"
	{0x0144, 	0xFF},		// SYNC_DISSYSREF[b7]=1-"Prevent the SYSREF clocks from becoming synchronized during a SYNC event", SYNC_12_DIS[b6]=1-SyncDisabled, SYNC_10_DIS[b5]=1-SyncDisabled, SYNC_8_DIS[b4]=1-SyncDisabled, SYNC_6_DIS[b3]=1-SyncDisabled, SYNC_4_DIS[b2]=1-SyncDisabled, SYNC_2_DIS[b1]=1-SyncDisabled, SYNC_0_DIS[b0]=1-SyncDisabled
	{0x0145, 	0x7F},		// Always 0x7F
	{0x0146, 	0x18},		// CLKin2_EN[b5]=0-DisableAutoMode, CLKin1_EN[b4]=1-EnableAutoMode, CLKin0_EN[b3]=1-EnableAutoMode, CLKin2_TYPE[b2]=0-Bipolar, CLKin1_TYPE[b1]=0-Bipolar, CLKin0_TYPE[b0]=0-Bipolar
	{0x0147, 	0x3A},		// CLKin_SEL_POL[b7]=0-ActiveHigh, CLKin_SEL_MODE[b6:b4]=3-PinSelect, CLKin1_OUT_MUX[b3:b2]=2-PLL1, CLKin0_OUT_MUX[b1:b0]=2-PLL1
	{0x0148, 	0x02},		// CLKin_SEL0_MUX[b5:b3]=0-LogicLow, CLKin_SEL0_TYPE[b2:b0]=2-Input/w pull-dwn
	{0x0149, 	0x73},		// SDIO_RDBK_TYPE[b6]=1-Output OpenDrain in 3-wire mode, CLKin_SEL1_MUX[b5:b3]=6-SPI Readback, CLKin_SEL1_TYPE[b2:b0]=3-Output pushpull
	{0x014A, 	0x02},		// RESET_MUX[b5:b3]=0-LogicLow, RESET_TYPE[b2:b0]=2-Input/w pull-dwn
	{0x014B, 	0x16},		// LOS_TIMEOUT[b7:b6]=0-370 kHz, LOS_EN[b5]=0-Disabled, TRACK_EN[b4]=1-Enabled, HOLDOVER_FORCE[b3]=0-Disabled, MAN_DAC_EN[b2]=1-Manual, MAN_DAC[b1:b0]= 512
	{0x014C, 	0x00},		// MAN_DAC[b7:b0] = 512
	{0x014D, 	0x00},		// DAC_TRIP_LOW[b5:b0]=0- 1/Vcc*64
	{0x014E, 	0xC0},		// DAC_CLK_MULT[b7:b6]=3-16384, DAC_TRIP_HIGH[b5:b0]=0-1/Vcc*64
	{0x014F, 	0x7F},		// DAC_CLK_CNTR[b7:b0]=127
	{0x0150, 	0x00},		// CLKin_OVERRIDE[b6]=0-No override, HOLDOVER_PLL1_DET[b4]=0, HOLDOVER_LOS_DET[b3]=0-Disabled, HOLDOVER_VTUNE_SET[b2]=0-Disabled, HOLDOVER_HITLESS_SWITCH[b1]=0-HardSwitch, HOLDOVER_EN[b0]=0-Disabled

	{0x0151, 	0x02},		// HOLDOVER_DLD_CNTR[b5:b0]=512
	{0x0152, 	0x00},		// HOLDOVER_DLD_CNTR[b7:b0]=512
	{0x0153, 	0x00},		// CLKin0_R[b5:b0]=80 (CLKin = 80 MHz, PLL1_Fpd = 1 MHz, max:40 MHz)
	{0x0154, 	0x50},		// CLKin0_R[b7:b0]=80
	{0x0155, 	0x00},		// CLKin1_R[b5:b0]=80 (CLKin = 80 MHz, PLL1_Fpd = 1 MHz, max:40 MHz)
	{0x0156, 	0x50},		// CLKin1_R[b7:b0]=80
	{0x0157, 	0x00},		// CLKin2_R[b5:b0]=80 (CLKin = 80 MHz, PLL1_Fpd = 1 MHz, max:40 MHz)
	{0x0158, 	0x50},		// CLKin2_R[b7:b0]=80
	{0x0159, 	0x00},		// PLL1_N[b5:b0]=200 (FB-FPGA_CLK=200 MHz)
	{0x015A, 	0xC8},		// PLL1_N[b7:b0]=200 (FB-FPGA_CLK=200 MHz)
	{0x015B, 	0xDF},		// PLL1_WND_SIZE[b7:b6]=3-43ns, PLL1_CP_TRI[b5]=0-PLL1 CPout active, PLL1_CP_POL[b4]=1-PositiveSLope, PLL1_CP_GAIN[b3:b0]=15-1550uA
	{0x015C, 	0x20},		// PLL1_DLD_CNT[b5:b0]= 8192
	{0x015D, 	0x00},		// PLL1_DLD_CNT[b7:b0]= 8192
	{0x015E, 	0x00},		// PLL1_R_DLY[b5:b3]=0-0ps, PLL1_N_DLY[b2:b0]=0-0ps
	{0x015F, 	0x0B},		// PLL1_LD_MUX[b7:b3]=1-PLL1 DLD, PLL1_LD_TYPE[b2:b0]=3-Output pushpull
	{0x0160, 	0x00},		// PLL2_R[b3:b0]=1 (OScin = 80 MHz, PLL2_Fpd = 80 MHz, max:155 MHz)
	{0x0161, 	0x01},		// PLL2_R[b7:b0]=1 (OScin = 80 MHz, PLL2_Fpd = 80 MHz, max:155 MHz)
	{0x0162, 	0x24},		// PLL2_P[b7:b5]=1-NPre=2, OSCin_FREQ[b4:b2]=1-67/127 MHz, PLL2_XTAL_EN[b1]=0-OSCAmp Disabled, PLL2_REF_2X_EN[b0]=0-Disabled
	{0x0163, 	0x00},		// PLL2_N_CAL[b1:b0]=12
	{0x0164, 	0x00},		// PLL2_N_CAL[b7:b0]=12
	{0x0165, 	0x0C},		// PLL2_N_CAL[b7:b0]=12

	//{0x0171, 	0xAA},		//
	//{0x0172, 	0x02},		//
	{0x017C, 	0x15},		// OPT_REG_1[b7:b0]=21-LMK04828
	{0x017D, 	0x33},		// OPT_REG_2[b7:b0]=51-LMK04828

	{0x0166, 	0x00},		// PLL2_FCAL_DIS[b2]=0-FCal Enabled, PLL2_N[b1:b0]=15 (PLL2_Fpd=80 MHz, max:155 MHz)
	{0x0167, 	0x00},		// PLL2_N[b7:b0]=15
	{0x0168, 	0x0F},		// PLL2_N[b7:b0]=15
	{0x0169, 	0x59},		// PLL2_WND_SIZE[b6:b5]=2-3.7ns, PLL2_CP_GAIN[b4:b3]=3-3.2 mA, PLL2_CP_POL[b2]=0-NegativeSlope, PLL2_CP_TRI[b1]=0-Disabled
	{0x016A, 	0x20},		// SYSREF_REQ_EN[b6]=0-Disabled, PLL2_DLD_CNT[b5:b0]=8192
	{0x016B, 	0x00},		// PLL2_DLD_CNT[b5:b0]=8192
	{0x016C, 	0x00},		// PLL2_LF_R4[b5:b3]=0-200 Ohm, PLL2_RF_R3[b2:b0]=0-200 Ohm
	{0x016D, 	0x00},		// PLL2_LF_C4[b7:b4]=0-10 pF, PLL2_RF_C3[b3:b0]=0-10 pF
	{0x016E, 	0x13},		// PLL2_LD_MUX[b7:b3]= 2-PLL2 DLD, PLL2_LD_TYPE[b2:b0]=3-Output pushpull
	//{0x0171, 	0xAA},
	//{0x0172, 	0x02},
	{0x0173, 	0x00},		// PLL2_PRE_PD[b6]=0-Normal, PLL2_PD[b5]=0-Normal
	//{0x017C, 	0x15},		// OPT_REG_1[b7:b0]=21-LMK04828
	//{0x017D, 	0x33},		// OPT_REG_2[b7:b0]=51-LMK04828
	//{0x0182, 	0x00},		//
	//{0x0183, 	0x00},		//
	//{0x0184, 	0x00},		//
	//{0x0185, 	0x00},		//
	//{0x0188, 	0x00},		//
	{0x1FFD, 	0x00},		// SPI Register Unlocked
	{0x1FFE, 	0x00},		// SPI Register Unlocked
	{0x1FFF, 	0x53}		// SPI Register Unlocked
};

u8 	lmk_lock_status;
u16 lmk_regs[LMK_DEFAULT_REGS_LENGTH];

// ===========================================================================
// Local Prototype Declarations
// ---------------------------------------------------------------------------

// ===========================================================================
// External Data Declarations
// ---------------------------------------------------------------------------

// ===========================================================================
// Module Body
// ---------------------------------------------------------------------------

//----------------------------------------------------------------------------
// Function Name		: hal_lmk_init()
//
// Function Description	:
//
// Input Argument(s)	: No input
//
// Return Argument		: void
//----------------------------------------------------------------------------
void hal_lmk_init(void) {

	u16 k;

	// Init parameters
	lmk_lock_status = FALSE;
	lmk_spi_handle = &spi_0_handle;

	// Init gpio
	hal_lmk_init_gpio();

	// Switch EMIO SPI to LMK SPI
	hal_spi_set_mux(SPI_MUX_LMK);

	// Set reference clock source
	hal_lmk_set_ref_clk_source(LMK_REF_CLK_MODEM);

	// Reset LMK device
	hal_lmk_set_gpio_reset(ENABLE);
	hal_timer_delay_usec(1000);
	hal_lmk_set_gpio_reset(DISABLE);

	// Wait for T_reset (min )
	hal_timer_delay_usec(1000);

	// Configure LMK
	for (k=0; k<LMK_DEFAULT_REGS_LENGTH; k++) {
		hal_lmk_write_reg(lmk_modem_default_cfg_regs[k][0], lmk_modem_default_cfg_regs[k][1]);
	}

	// Read back all registers
	for (k=0; k<LMK_DEFAULT_REGS_LENGTH; k++) {
		lmk_regs[k] = hal_lmk_read_reg(lmk_modem_default_cfg_regs[k][0]);
	}

	// Configure SYNC/SYSREF for JESD
	hal_lmk_cfg_sysref();

	// Wait for lock detect
	hal_timer_reload_start(LMK_LOCK_TIMEOUT);
	while(TRUE) {
		if (hal_lmk_get_gpio_lock_detect()) {
			lmk_lock_status = TRUE;
		} else if (hal_timer_check_timeout_flag()) {
			break;
		}
	}
}

//----------------------------------------------------------------------------
// Function Name		: hal_lmk_init_gpio()
//
// Function Description	:
//
// Input Argument(s)	: No input
//
// Return Argument		: void
//----------------------------------------------------------------------------
void hal_lmk_init_gpio(void) {

}

//----------------------------------------------------------------------------
// Function Name		: hal_lmk_set_ref_clk_source()
//
// Function Description	:
//
// Input Argument(s)	: No input
//
// Return Argument		: void
//----------------------------------------------------------------------------
void hal_lmk_set_ref_clk_source(u32 input_clk_select) {

	if (input_clk_select == LMK_REF_CLK_RF)
		hal_dbg_set_tps(HAL_DBG_TPS_LMK_CLKIN_SEL);
	else
		hal_dbg_reset_tps(HAL_DBG_TPS_LMK_CLKIN_SEL);
}

//----------------------------------------------------------------------------
// Function Name		: hal_lmk_set_gpio_reset()
//
// Function Description	:
//
// Input Argument(s)	: No input
//
// Return Argument		: void
//----------------------------------------------------------------------------
void hal_lmk_set_gpio_reset(u8 reset) {

	// Active High Signal
	if (reset)		hal_dbg_set_tps(HAL_DBG_TPS_LMK_RESET);
	else			hal_dbg_reset_tps(HAL_DBG_TPS_LMK_RESET);
}

//----------------------------------------------------------------------------
// Function Name		: hal_lmk_set_gpio_sync()
//
// Function Description	:
//
// Input Argument(s)	: No input
//
// Return Argument		: void
//----------------------------------------------------------------------------
void hal_lmk_set_gpio_sync(u8 status) {

	// Active High Signal
	if (status)		hal_dbg_set_tps(HAL_DBG_TPS_LMK_SYNC);
	else			hal_dbg_reset_tps(HAL_DBG_TPS_LMK_SYNC);
}

//----------------------------------------------------------------------------
// Function Name		: hal_lmk_get_gpio_lock_detect()
//
// Function Description	:
//
// Input Argument(s)	: No input
//
// Return Argument		: void
//----------------------------------------------------------------------------
u8 hal_lmk_get_gpio_lock_detect(void) {

	// TODO: Currently, Lock Detect (Status LD1/2) is not connected to PL/PS
	//       Lock status can be checked through SPI interface

	// Active High Signal

	return 0;
}

//----------------------------------------------------------------------------
// Function Name		: hal_lmk_read_reg()
//
// Function Description	:
//
// Input Argument(s)	: No input
//
// Return Argument		: void
//----------------------------------------------------------------------------
u8 hal_lmk_read_reg(u16 reg_adr) {

	u8  buf[3];

	// Clear R/W, W1, W0 fields (b.15, b.14, b.13)
	reg_adr &= 0x1FFF;

	// Set R/W field
	reg_adr |= 0x8000;

	// Set tx buffer (2 byte Address + 1 byte Dummy Data)
	buf[0] = reg_adr >> 8;
	buf[1] = reg_adr & 0xFF;
	buf[2] = 0;

	// Start xmit
	hal_spi_send_data(lmk_spi_handle, buf, buf, 3, HAL_SPI_BLOCK_DISABLE);

	return buf[2];
}

//----------------------------------------------------------------------------
// Function Name		: hal_lmk_write_reg()
//
// Function Description	:
//
// Input Argument(s)	: No input
//
// Return Argument		: void
//----------------------------------------------------------------------------
void hal_lmk_write_reg(u16 reg_adr, u8 reg_data) {

	u8  buf[3];

	// Clear R/W, W1, W0 fields (b.15, b.14, b.13)
	reg_adr &= 0x1FFF;

	// Set tx buffer (2 byte Address + 1 byte Data)
	buf[0] = reg_adr >> 8;
	buf[1] = reg_adr & 0xFF;
	buf[2] = reg_data;

	// Start xmit
	hal_spi_send_data(lmk_spi_handle, buf, buf, 3, HAL_SPI_BLOCK_DISABLE);
}

//----------------------------------------------------------------------------
// Function Name		: hal_lmk_cfg_sysref()
//
// Function Description	:
//
// Input Argument(s)	: No input
//
// Return Argument		: void
//----------------------------------------------------------------------------
void hal_lmk_cfg_sysref(void) {

	// REF[1]. LMK04828 DATASHEET "SECTION "9.3.2 JEDEC JESD204B", dac37j84.pdf

	// Switch EMIO SPI to LMK SPI
	hal_spi_set_mux(SPI_MUX_LMK);

	// SYNC_DISSYSREF[b7]=0-"Dont Prevent the SYSREF clocks from becoming synchronized during a SYNC event", SYNC_12_DIS[b6]=0-SyncEnabled, SYNC_10_DIS[b5]=0-SyncEnabled, SYNC_8_DIS[b4]=0-SyncEnabled, SYNC_6_DIS[b3]=0-SyncEnabled, SYNC_4_DIS[b2]=0-SyncEnabled, SYNC_2_DIS[b1]=0-SyncEnabled, SYNC_0_DIS[b0]=0-SyncEnabled
	hal_lmk_write_reg(0x0144, 0x00);

	// Toggle SYNC_POL[b5] or SYNC Pin
	hal_lmk_write_reg(0x0143, 0xB1);	// SYSREF_CLR[b7]=1, SYNC_1SHOT_EN[b6]=0-Disabled, SYNC_POL[b5]=1-Inverse, SYNC_EN[b4]=1-Enabled, SYNC_PLL2_DLD[b3]=0-OFF, SYNC_PLL1_DLD[b2]=0-OFF, SYNC_MODE[b1:b0]=1-"SYNC event generated from SYNC pin"
	hal_lmk_write_reg(0x0143, 0x91);	// SYSREF_CLR[b7]=1, SYNC_1SHOT_EN[b6]=0-Disabled, SYNC_POL[b5]=0-Normal, SYNC_EN[b4]=1-Enabled, SYNC_PLL2_DLD[b3]=0-OFF, SYNC_PLL1_DLD[b2]=0-OFF, SYNC_MODE[b1:b0]=1-"SYNC event generated from SYNC pin"
	//hal_lmk_set_gpio_sync(TRUE);
	//hal_timer_delay_usec(10);
	//hal_lmk_set_gpio_sync(FALSE);

	// SYNC_DISSYSREF[b7]=1-"Prevent the SYSREF clocks from becoming synchronized during a SYNC event", SYNC_12_DIS[b6]=1-NoSyncEnabled, SYNC_10_DIS[b5]=1-NoSyncEnabled, SYNC_8_DIS[b4]=1-NoSyncEnabled, SYNC_6_DIS[b3]=1-NoSyncEnabled, SYNC_4_DIS[b2]=1-NoSyncEnabled, SYNC_2_DIS[b1]=1-NoSyncEnabled, SYNC_0_DIS[b0]=1-NoSyncEnabled
	hal_lmk_write_reg(0x0144, 0xFF);

	// Release reset of local SYSREF digital delay (SYSREF_CLR[b7]=0)
	hal_lmk_write_reg(0x0143, 0x11);	// SYSREF_CLR[b7]=0, SYNC_1SHOT_EN[b6]=0-Disabled, SYNC_POL[b5]=0-Normal, SYNC_EN[b4]=1-Enabled, SYNC_PLL2_DLD[b3]=0-OFF, SYNC_PLL1_DLD[b2]=0-OFF, SYNC_MODE[b1:b0]=1-"SYNC event generated from SYNC pin"

	// Set SYSREF operation
	hal_lmk_write_reg(0x0139, 0x02);	// SYSREF_MUX[b1:b0]=2-SYSREF Pulser
	hal_lmk_write_reg(0x0143, 0x12);	// SYNC_MODE[b1:b0]=2-"SYNC/SYSREF pulses are generated by pulser block via SYNC Pin"
	//hal_lmk_write_reg(0x139, 0x03);	// SYSREF_MUX[b1:b0]=3-SYSREF Continuous
	//hal_lmk_write_reg(0x143, 0x11);	// SYNC_MODE[b1:b0]=1-"SYNC event generated from SYNC pin"

	// Trigger SYSREF Pulser by changing SYNC pin
	//hal_lmk_set_gpio_sync(TRUE);
	//hal_timer_delay_usec(10);
	//hal_lmk_set_gpio_sync(FALSE);
}

//----------------------------------------------------------------------------
// Function Name		: hal_lmk_trigger_sysref()
//
// Function Description	:
//
// Input Argument(s)	: No input
//
// Return Argument		: void
//----------------------------------------------------------------------------
void hal_lmk_trigger_sysref(void) {

#if 1
	// REFER TO THE SECTION "9.3.2 JEDEC JESD204B" OF LMK04828 DATASHEET

	// Switch EMIO SPI to LMK SPI
	hal_spi_set_mux(SPI_MUX_LMK);

	hal_lmk_write_reg(0x0139, 0x02);	// SYSREF_MUX[b1:b0]=2-SYSREF Pulser

	// Toggle SYNC_POL[b5] or SYNC Pin
	hal_lmk_write_reg(0x0143, 0x32);
	hal_lmk_write_reg(0x0143, 0x12);

	// Trigger SYSREF Pulser by changing SYNC pin
//	hal_lmk_set_gpio_sync(TRUE);
//	hal_timer_delay_usec(10);
//	hal_lmk_set_gpio_sync(FALSE);

#else
	// Switch EMIO SPI to LMK SPI
	hal_spi_set_mux(SPI_MUX_LMK);

	hal_lmk_write_reg(0x0139, 0x03);	// SYSREF_MUX[b1:b0]=3-SYSREF Continuous

	// Toggle SYNC_POL[b5] or SYNC Pin
	//hal_lmk_write_reg(0x0143, 0x32);
	//hal_lmk_write_reg(0x0143, 0x12);
	hal_lmk_set_gpio_sync(TRUE);
	hal_timer_delay_usec(10);
	hal_lmk_set_gpio_sync(FALSE);
#endif
}
