mbed-os/targets/TARGET_Samsung/TARGET_SIDK_S5JS100/s5js100_dcxo.cpp

778 lines
24 KiB
C++

/****************************************************************************
*
* Copyright 2020 Samsung Electronics All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the License.
*
****************************************************************************/
#include "mbed.h"
#include "s5js100_dcxo.h"
#include "s5js100_type.h"
#include "mbed_trace.h"
#define TRACE_GROUP "DCXO"
#ifndef S5JS100_DCXO_DBG_ON
#define S5JS100_DCXO_DBG_ON 0
#endif
#define S5JS100_DCXO_DBG if (S5JS100_DCXO_DBG_ON) tr_info
#define DCXO_TEMPERATURE_RANGE 126 /* -40 ~ 85 */
#define DCXO_TSU_TABLE_MIN_TEMPERATURE (-40)
#define DCXO_TSU_TABLE_MAX_TEMPERATURE 85
#define DCXO_TSU_TABLE_MIN 10000
#define DCXO_TSU_TABLE_LENGTH 35
#define DCXO_TSU_TABLE_UNIT 5000
Thread *g_dcxo_tid;
static Semaphore dcxo_tbl_sem(1, 1);
static unsigned int tsu_code_to_temperature(unsigned int tsu_code);
static unsigned int tsu_temperature_to_code(unsigned int temp_celcius);
// table for KDS 9pF and SIDK board
// B constant : 3,380, T0 : 25'C
static const unsigned short g_dcxo_tsu_table[] = {
49690, //-40'C, 10,000
48942,
48194, //-30'C, 20,000
47446,
46698, //-20'C, 30,000
45639,
44316, //-10'C, 40,000
42776,
41063, //0'C, 50,000
39214,
37269, //10'C, 60,000
35261,
33221, //20'C, 70,000
31177,
29156, //30'C, 80,000
27180,
25267, //40'C, 90,000
23436,
21700, //50'C, 100,000
20069,
18553, //60'C, 110,000
17155,
15878, //70'C, 120,000
14721,
13681, //80'C, 130,000
12751,
11922, //90'C, 140,000
11181,
10513, //100'C, 150,000
9899,
9319, //110'C, 160,000
8749,
8162, //120'C, 170,000
7527,
6813, //130'C, 180,000
};
static volatile int tsu_interrupt_flag;
static int dcxo_init_flag;
static Full_set_table_t *dcxo_tbl;
// return value : (celcius temperature)*1000 + 50,000
static unsigned int tsu_code_to_temperature(unsigned int tsu_code)
{
unsigned int temp_code;
int index, base, ratio;
index = 0;
while (index < DCXO_TSU_TABLE_LENGTH) {
if (g_dcxo_tsu_table[index] <= tsu_code) {
break;
} else {
index++;
}
}
if (index <= 0) {
index = 1;
} else if (index >= DCXO_TSU_TABLE_LENGTH) {
index = DCXO_TSU_TABLE_LENGTH - 1;
}
base = (index - 1) * DCXO_TSU_TABLE_UNIT + DCXO_TSU_TABLE_MIN;
ratio = ((int)(g_dcxo_tsu_table[index - 1] - tsu_code) * DCXO_TSU_TABLE_UNIT)
/ (int)(g_dcxo_tsu_table[index - 1] - g_dcxo_tsu_table[index]);
temp_code = base + ratio;
return temp_code;
}
// temp_celcius : (celcius temperature)*1000 + 50,000
static unsigned int tsu_temperature_to_code(unsigned int temp_celcius)
{
int index, ratio;
index = (temp_celcius - DCXO_TSU_TABLE_MIN) / DCXO_TSU_TABLE_UNIT;
if (temp_celcius <= DCXO_TSU_TABLE_MIN) {
index = 0;
ratio = (int)(DCXO_TSU_TABLE_MIN + DCXO_TSU_TABLE_UNIT * index - temp_celcius) * (int)(g_dcxo_tsu_table[index] - g_dcxo_tsu_table[index + 1]) / DCXO_TSU_TABLE_UNIT;
} else if (index >= DCXO_TSU_TABLE_LENGTH - 1) {
index = DCXO_TSU_TABLE_LENGTH - 1;
ratio = (int)(DCXO_TSU_TABLE_MIN + DCXO_TSU_TABLE_UNIT * index - temp_celcius) * (int)(g_dcxo_tsu_table[index - 1] - g_dcxo_tsu_table[index]) / DCXO_TSU_TABLE_UNIT;
} else {
ratio = (int)(DCXO_TSU_TABLE_MIN + DCXO_TSU_TABLE_UNIT * index - temp_celcius) * (int)(g_dcxo_tsu_table[index] - g_dcxo_tsu_table[index + 1]) / DCXO_TSU_TABLE_UNIT;
}
//dbg("\nindex : %d , base : %d , ratio : %d\n", index, g_dcxo_tsu_table[index], ratio);
return g_dcxo_tsu_table[index] + ratio;
}
/****************************************************************************
* Function: up_timerisr
*
* Description:
* The timer ISR will perform a variety of services for various portions
* of the systems.
*
****************************************************************************/
int dcxo_tsu_isr(int irq, void *context, void *arg)
{
NVIC_DisableIRQ((IRQn_Type)irq);
tsu_interrupt_flag = 1;
if (irq == S5JS100_IRQ_TSU0) {
modifyreg32(S5JS100_DCXO_CFG + DCXO_CFG_IRQ_CFG1, 1, 1);
modifyreg32(S5JS100_DCXO_CFG + DCXO_CFG_IRQ_CFG1, 0x10, 0x10);
modifyreg32(S5JS100_DCXO_CFG + DCXO_CFG_IRQ_CFG0, 0xFFFF, 0x0);
//dbg("TSU0 interrupt\n");
} else if (irq == S5JS100_IRQ_TSU1) {
modifyreg32(S5JS100_DCXO_CFG + DCXO_CFG_IRQ_CFG1, 2, 2);
modifyreg32(S5JS100_DCXO_CFG + DCXO_CFG_IRQ_CFG1, 0x20, 0x20);
modifyreg32(S5JS100_DCXO_CFG + DCXO_CFG_IRQ_CFG0, 0xFFFF0000, 0xFFFF0000);
//dbg("TSU1 interrupt\n");
}
return 0;
}
/****************************************************************************
* Private Data
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: s5js100_dcxo_ctb_loop
*
* Description:
* update DCXO value in every ms by parameter freq
*
* Returned Value:
* a NULL on failure
*
****************************************************************************/
int s5js100_dcxo_tbl_dump(void)
{
int i;
for (i = 0; i < DCXO_TEMPERATURE_RANGE; i++) {
S5JS100_DCXO_DBG("%d : CTB[%d]", i - 40, (dcxo_tbl + i)->ctb);
}
return 0;
}
void dcxo_ctb_sem_wait(void)
{
dcxo_tbl_sem.try_acquire();
}
void dcxo_ctb_sem_release(void)
{
dcxo_tbl_sem.release();
}
void s5js100_dcxo_ctb_loop(void)
{
int tsu, index, ctb, ctb_prev;
int ctb_gap;
int loop_started = 0;
//s5js100_dcxo_tbl_dump();
while (1) {
// refer dcxo table
// read TSU
tsu = (int) s5js100_tsu_get_temperature();
index = (tsu - 10000) / 1000;
dcxo_ctb_sem_wait();
if (tsu < (50000 + DCXO_TSU_TABLE_MIN_TEMPERATURE * 1000)) {
index = 0;
ctb_gap = dcxo_tbl[index + 1].ctb - dcxo_tbl[index].ctb;
ctb = dcxo_tbl[index].ctb + (ctb_gap * (tsu - (50000 + DCXO_TSU_TABLE_MIN_TEMPERATURE * 1000))) / 1000;
} else if (tsu > (50000 + DCXO_TSU_TABLE_MAX_TEMPERATURE * 1000)) {
index = DCXO_TEMPERATURE_RANGE - 1;
ctb_gap = dcxo_tbl[index].ctb - dcxo_tbl[index - 1].ctb;
ctb = dcxo_tbl[index].ctb + (ctb_gap * (tsu - (50000 + DCXO_TSU_TABLE_MAX_TEMPERATURE * 1000))) / 1000;
} else {
ctb_gap = dcxo_tbl[index + 1].ctb - dcxo_tbl[index].ctb;
ctb = dcxo_tbl[index].ctb + ctb_gap * (tsu % 1000) / 1000;
}
if (ctb < 0) {
ctb = 0;
} else if (ctb > 16383) {
ctb = 16383;
}
if (!loop_started) {
S5JS100_DCXO_DBG("s5js100_dcxo_ctb_loop FIRST update temp(%d) coarse(%d -> %d)", tsu - 50000, s5js100_dcxo_get_coarse_tune_value, ctb);
s5js100_dcxo_set_tune_value(ctb, 4096);
} else {
ctb_prev = s5js100_dcxo_get_coarse_tune_value();
if (ctb > ctb_prev) {
ctb_prev++;
} else if (ctb < ctb_prev) {
ctb_prev--;
}
s5js100_dcxo_set_tune_value(ctb_prev, 4096);
}
if (ctb == 0) {
S5JS100_DCXO_DBG("[ERROR]CTB was 0x0[temp:%d]!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n", tsu);
}
loop_started = 1;
dcxo_ctb_sem_release();
osDelay(50);
}
}
int s5js100_tsu_get_code(void)
{
return (getreg32(S5JS100_DCXO_CFG + DCXO_CFG_IRQ_STA0) & 0xFFFF);
}
int s5js100_dcxo_force_update_ctb(void)
{
int tsu, index, ctb, code;
int ctb_gap;
// read TSU
code = s5js100_tsu_get_code();
tsu = (int) tsu_code_to_temperature(code);
index = (tsu - 10000) / 1000;
if (tsu < (50000 + DCXO_TSU_TABLE_MIN_TEMPERATURE * 1000)) {
index = 0;
ctb_gap = dcxo_tbl[index + 1].ctb - dcxo_tbl[index].ctb;
ctb = dcxo_tbl[index].ctb + (ctb_gap * (tsu - (50000 + DCXO_TSU_TABLE_MIN_TEMPERATURE * 1000))) / 1000;
} else if (tsu > (50000 + DCXO_TSU_TABLE_MAX_TEMPERATURE * 1000)) {
index = DCXO_TEMPERATURE_RANGE - 1;
ctb_gap = dcxo_tbl[index].ctb - dcxo_tbl[index - 1].ctb;
ctb = dcxo_tbl[index].ctb + (ctb_gap * (tsu - (50000 + DCXO_TSU_TABLE_MAX_TEMPERATURE * 1000))) / 1000;
} else {
ctb_gap = dcxo_tbl[index + 1].ctb - dcxo_tbl[index].ctb;
ctb = dcxo_tbl[index].ctb + ctb_gap * (tsu % 1000) / 1000;
}
if (ctb < 0) {
ctb = 0;
} else if (ctb > 16383) {
ctb = 16383;
}
s5js100_dcxo_set_tune_value(ctb, 4096);
if (ctb == 0) {
S5JS100_DCXO_DBG("Force CTB was 0x0[temp:%d, code:%d]!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n", tsu, code);
//asm("b .");
}
if ((tsu - 50000) > 0) {
//dcxollvdbg("TSU : %d.%03d 'C, CTB : %d ( %d )\n", (tsu - 50000) / 1000, (tsu) % 1000, ctb, tsu);
} else if ((tsu - 50000) > -1000) {
//dcxollvdbg("TSU : -%d.%03d 'C, CTB : %d ( %d )\n", (tsu - 50000) / 1000, (1000 - (tsu) % 1000) % 1000, ctb, tsu);
} else {
//dcxollvdbg("TSU : %d.%03d 'C, CTB : %d ( %d )\n", (tsu - 50000) / 1000, (1000 - (tsu) % 1000) % 1000, ctb, tsu);
}
return 0;
}
/****************************************************************************
* Name: s5js100_dcxo_initialize
*
* Description:
* Initialize the DCXO.
*
* Returned Value:
* a NULL on failure
*
****************************************************************************/
int s5js100_dcxo_initialize(void)
{
if (dcxo_init_flag == 0) {
// initialize DOTSU, clk:100kHz
//putreg32(0x3E5, S5JS100_DCXO_CFG + DCXO_CFG_ADC_CFG);
//putreg32(0x1BE7, S5JS100_DCXO_CFG + DCXO_CFG_ADC_CFG); //ATE setting value
putreg32(0x13FE5, S5JS100_DCXO_CFG + DCXO_CFG_ADC_CFG); //Final setting value
putreg32(0x3A, S5JS100_DCXO_CFG + DCXO_CFG_DIV_CFG);
putreg32(0x30, S5JS100_DCXO_CFG + DCXO_CFG_IRQ_CFG1);
putreg32(0xFFFF0000, S5JS100_DCXO_CFG + DCXO_CFG_IRQ_CFG0);
// tsu sensing time by average unit
// 0:10us, 1:40us, 2:160us, 3:640us, 4:2.56ms, 5:10.24ms, 6:81.92ms, 7:327.68 ms
putreg32(0x3, S5JS100_DCXO_CFG + DCXO_CFG_AVR_CFG);
//putreg32(0x7, S5JS100_DCXO_CFG + DCXO_CFG_AVR_CFG);
// wait till update temperature
while (!(getreg32(S5JS100_DCXO_CFG + DCXO_CFG_IRQ_STA1) & 0xFFFF0000)) {
}
// initialize DCXO
// IDAC_SEL = 1
modifyreg32(S5JS100_PMU_ALIVE + 0x520, 1 << 3, 1 << 3);
#if 0
// IDAC_EX = 0xa0
modifyreg32(S5JS100_PMU_ALIVE + 0x524, 0xff << 5, 0xa0 << 5);
#else
// change tune parameter
// IDAC_EX = 100
modifyreg32(S5JS100_PMU_ALIVE + 0x524, 0xff << 5, 100 << 5);
// BUF_SEL = 8
modifyreg32(S5JS100_PMU_ALIVE + 0x528, 0xf << 3, 8 << 3);
#endif
#if defined(DCXO_FINE_PMU_COARSE_DCXO)
// Fine=FTUNE2, Coarse=DcxoFTune
// FuneMuxSel = 1
modifyreg32(S5JS100_DCXO_CFG + DCXO_CFG_DSM_CFG0, 1, 1);
// FTSEL = 1
modifyreg32(S5JS100_PMU_ALIVE + 0x528, 1 << 16, 1 << 16);
// FTSWP = 1
modifyreg32(S5JS100_PMU_ALIVE + 0x528, 1 << 15, 1 << 15);
#elif defined(DCXO_FINE_PMU_COARSE_PMU)
// Fine=FTUNE2, Coarse=FTUNE
// FuneMuxSel = 0
modifyreg32(S5JS100_DCXO_CFG + DCXO_CFG_DSM_CFG0, 1, 0);
// FTSEL = 1
modifyreg32(S5JS100_PMU_ALIVE + 0x528, 1 << 16, 1 << 16);
// FTSWP = 1
modifyreg32(S5JS100_PMU_ALIVE + 0x528, 1 << 15, 1 << 15);
#elif defined(DCXO_FINE_DCXO_COARSE_PMU)
// Fine=DcxoFTune, Coarse=FTUNE2
// FuneMuxSel = 1
modifyreg32(S5JS100_DCXO_CFG + DCXO_CFG_DSM_CFG0, 1, 1);
// FTSEL = 1
modifyreg32(S5JS100_PMU_ALIVE + 0x528, 1 << 16, 1 << 16);
// FTSWP = 0
modifyreg32(S5JS100_PMU_ALIVE + 0x528, 1 << 15, 0);
#endif
dcxo_init_flag = 1;
}
return 1;
}
int s5js100_dcxo_start_ctb_loop(Full_set_table_t tbl[])
{
dcxo_tbl = tbl;
g_dcxo_tid = new rtos::Thread(osPriorityNormal, 2048, NULL, "ctbloop");
g_dcxo_tid->start(s5js100_dcxo_ctb_loop);
if (!g_dcxo_tid) {
return -ESRCH;
}
return 0;
}
/****************************************************************************
* Name: s5js100_tsu_get_temperature
*
* Description:
* Read temperature of TSX.
*
* Returned Value:
* celcius temperature
*
****************************************************************************/
int s5js100_tsu_calculate_temperature(unsigned int code)
{
return tsu_code_to_temperature(code);
}
int s5js100_tsu_convert_code(unsigned int temperature)
{
return tsu_temperature_to_code(temperature);
}
int s5js100_tsu_get_temperature(void)
{
return tsu_code_to_temperature(s5js100_tsu_get_code());
}
int s5js100_tsu_set_interrupt(int high_interrupt, int temp)
{
unsigned int tsu_code, irq_no;
if (temp < DCXO_TSU_TABLE_MIN_TEMPERATURE) {
temp = DCXO_TSU_TABLE_MIN_TEMPERATURE;
} else if (temp > DCXO_TSU_TABLE_MIN_TEMPERATURE + DCXO_TSU_TABLE_LENGTH - 1) {
temp = DCXO_TSU_TABLE_MIN_TEMPERATURE + DCXO_TSU_TABLE_LENGTH - 1;
}
if (high_interrupt) {
tsu_code = tsu_temperature_to_code(temp - 1);
modifyreg32(S5JS100_DCXO_CFG + DCXO_CFG_IRQ_CFG1, 1, 1);
modifyreg32(S5JS100_DCXO_CFG + DCXO_CFG_IRQ_CFG1, 1, 0);
modifyreg32(S5JS100_DCXO_CFG + DCXO_CFG_IRQ_CFG0, 0xFFFF, tsu_code);
modifyreg32(S5JS100_DCXO_CFG + DCXO_CFG_IRQ_CFG1, (1 << 4), 0);
irq_no = S5JS100_IRQ_TSU0;
} else {
tsu_code = tsu_temperature_to_code(temp);
modifyreg32(S5JS100_DCXO_CFG + DCXO_CFG_IRQ_CFG1, 2, 2);
modifyreg32(S5JS100_DCXO_CFG + DCXO_CFG_IRQ_CFG1, 2, 0);
modifyreg32(S5JS100_DCXO_CFG + DCXO_CFG_IRQ_CFG0, 0xFFFF0000, tsu_code << 16);
modifyreg32(S5JS100_DCXO_CFG + DCXO_CFG_IRQ_CFG1, (1 << 5), 0);
irq_no = S5JS100_IRQ_TSU1;
}
//dbg("\ns5js100_tsu_set_interrupt(%d), tsu_code : 0x%x", high_interrupt, tsu_code);
NVIC_SetVector((IRQn_Type)irq_no, (uint32_t)dcxo_tsu_isr);
#if defined (__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U)
SCB_InvalidateICache();
#endif
NVIC_EnableIRQ((IRQn_Type)irq_no);
modifyreg32(S5JS100_DCXO_CFG + DCXO_CFG_IRQ_CFG1, (1 << 2), (1 << 2));
modifyreg32(S5JS100_DCXO_CFG + DCXO_CFG_IRQ_CFG1, (1 << 2), 0);
return 1;
}
int s5js100_tsu_set_interrupt_code(int high_interrupt, int tsu_code, int check)
{
unsigned int irq_no;
int ret = 1;
//dbg("s5js100_tsu_set_interrupt(%d), tsu_code : 0x%x\n", high_interrupt, tsu_code);
if (check) {
tsu_interrupt_flag = 0;
}
if (!high_interrupt) {
modifyreg32(S5JS100_DCXO_CFG + DCXO_CFG_IRQ_CFG1, 1, 1);
modifyreg32(S5JS100_DCXO_CFG + DCXO_CFG_IRQ_CFG1, 1, 0);
modifyreg32(S5JS100_DCXO_CFG + DCXO_CFG_IRQ_CFG0, 0xFFFF, tsu_code);
modifyreg32(S5JS100_DCXO_CFG + DCXO_CFG_IRQ_CFG1, (1 << 4), 0);
irq_no = S5JS100_IRQ_TSU0;
} else {
modifyreg32(S5JS100_DCXO_CFG + DCXO_CFG_IRQ_CFG1, 2, 2);
modifyreg32(S5JS100_DCXO_CFG + DCXO_CFG_IRQ_CFG1, 2, 0);
modifyreg32(S5JS100_DCXO_CFG + DCXO_CFG_IRQ_CFG0, 0xFFFF0000, tsu_code << 16);
modifyreg32(S5JS100_DCXO_CFG + DCXO_CFG_IRQ_CFG1, (1 << 5), 0);
irq_no = S5JS100_IRQ_TSU1;
}
NVIC_SetVector((IRQn_Type)irq_no, (uint32_t)dcxo_tsu_isr);
#if defined (__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U)
SCB_InvalidateICache();
#endif
NVIC_EnableIRQ((IRQn_Type)irq_no);
modifyreg32(S5JS100_DCXO_CFG + DCXO_CFG_IRQ_CFG1, (1 << 2), (1 << 2));
modifyreg32(S5JS100_DCXO_CFG + DCXO_CFG_IRQ_CFG1, (1 << 2), 0);
if (check) {
//sleep(1);
if (!tsu_interrupt_flag) {
ret = 0;
}
}
return ret;
}
int s5js100_dcxo_get_coarse_tune_value(void)
{
int coarse_tune;
#if defined(DCXO_FINE_PMU_COARSE_DCXO)
// Fine=DcxoFTune, Coarse=FTUNE2
coarse_tune = (getreg32(S5JS100_DCXO_CFG + DCXO_CFG_DSM_CFG0) >> 1) & 0xFFFFF;
coarse_tune >>= 6;
#elif defined(DCXO_FINE_PMU_COARSE_PMU)
// Fine=FTUNE2, Coarse=FTUNE
// Coarse=FTUNE 14bit
// EVT0 : 0x81000524[26:13], EVT1 : 0x8100000C[13:0]
if (is_evt0()) {
coarse_tune = (getreg32(S5JS100_PMU_ALIVE + 0x524) >> 13) & 0x3FFF;
} else {
coarse_tune = (getreg32(S5JS100_PMU_ALIVE + 0xC) >> 0) & 0x3FFF;
}
#elif defined(DCXO_FINE_DCXO_COARSE_PMU)
// Fine=DcxoFTune, Coarse=FTUNE2
// Coarse=FTUNE2 14bit
// EVT0 : 0x81000528[31:17], EVT1 : 0x8100000C[28:14]
if (is_evt0()) {
coarse_tune = (getreg32(S5JS100_PMU_ALIVE + 0x528) >> 17) & 0x3FFF;
} else {
coarse_tune = (getreg32(S5JS100_PMU_ALIVE + 0xC) >> 14) & 0x3FFF;
}
#endif
return coarse_tune;
}
int s5js100_dcxo_set_tune_value(unsigned int coarse_value, unsigned int fine_value)
{
#if defined(DCXO_FINE_PMU_COARSE_DCXO)
// Fine=DcxoFTune, Coarse=FTUNE2
coarse_value <<= 6;
// Coarse = DcxoFTune 20bit
modifyreg32(S5JS100_DCXO_CFG + DCXO_CFG_DSM_CFG0, 0xFFFFF << 1, coarse_value << 1);
// Fine=FTUNE2 14bit
// EVT0 : 0x81000528[31:17], EVT1 : 0x8100000C[28:14]
if (is_evt0()) {
modifyreg32(S5JS100_PMU_ALIVE + 0x528, 0x3FFF << 17, fine_value << 17);
} else {
modifyreg32(S5JS100_PMU_ALIVE + 0xC, 0x3FFF << 14, fine_value << 14);
}
#elif defined(DCXO_FINE_PMU_COARSE_PMU)
// Fine=FTUNE2, Coarse=FTUNE
// Fine = FTUNE2 13bit
// EVT0 : 0x81000528[31:17], EVT1 : 0x8100000C[28:14]
if (is_evt0()) {
modifyreg32(S5JS100_PMU_ALIVE + 0x528, 0x3FFF << 17, fine_value << 17);
} else {
modifyreg32(S5JS100_PMU_ALIVE + 0xC, 0x3FFF << 14, fine_value << 14);
}
// Coarse=FTUNE 14bit
// EVT0 : 0x81000524[26:13], EVT1 : 0x8100000C[13:0]
if (is_evt0()) {
modifyreg32(S5JS100_PMU_ALIVE + 0x524, (0x3FFF << 13), (coarse_value << 13));
} else {
modifyreg32(S5JS100_PMU_ALIVE + 0xC, 0x3FFF << 0, coarse_value << 0);
}
#elif defined(DCXO_FINE_DCXO_COARSE_PMU)
// Fine=DcxoFTune, Coarse=FTUNE2
fine_value <<= 6;
// Fine = DcxoFTune 20bit
modifyreg32(S5JS100_DCXO_CFG + DCXO_CFG_DSM_CFG0, 0xFFFFF << 1, fine_value << 1);
// Coarse=FTUNE2 14bit
// EVT0 : 0x81000528[31:17], EVT1 : 0x8100000C[28:14]
if (is_evt0()) {
modifyreg32(S5JS100_PMU_ALIVE + 0x528, 0x3FFF << 17, coarse_value << 17);
} else {
modifyreg32(S5JS100_PMU_ALIVE + 0xC, 0x3FFF << 14, coarse_value << 14);
}
#endif
return 1;
}
int s5js100_dcxo_set_tune_value_20bit(unsigned int coarse_value, unsigned int fine_value)
{
#if defined(DCXO_FINE_PMU_COARSE_DCXO)
// Coarse=DcxoFTune, Fine=FTUNE2
// Coarse = DcxoFTune 20bit
modifyreg32(S5JS100_DCXO_CFG + DCXO_CFG_DSM_CFG0, 0xFFFFF << 1, coarse_value << 1);
// Fine=FTUNE2 14bit
// EVT0 : 0x81000528[31:17], EVT1 : 0x8100000C[28:14]
if (is_evt0()) {
modifyreg32(S5JS100_PMU_ALIVE + 0x528, 0x3FFF << 17, fine_value << 17);
} else {
modifyreg32(S5JS100_PMU_ALIVE + 0xC, 0x3FFF << 14, fine_value << 14);
}
// toggle oSwRstDSM
//modifyreg32(S5JS100_DCXO_CFG + DCXO_CFG_SW_RESETN, (1<<3), 0);
//modifyreg32(S5JS100_DCXO_CFG + DCXO_CFG_SW_RESETN, (1<<3), (1<<3));
#elif defined(DCXO_FINE_PMU_COARSE_PMU)
// Fine=FTUNE2, Coarse=FTUNE
coarse_value >>= 6;
// Fine = FTUNE2 13bit
// EVT0 : 0x81000528[31:17], EVT1 : 0x8100000C[28:14]
if (is_evt0()) {
modifyreg32(S5JS100_PMU_ALIVE + 0x528, 0x3FFF << 17, fine_value << 17);
} else {
modifyreg32(S5JS100_PMU_ALIVE + 0xC, 0x3FFF << 14, fine_value << 14);
}
// Coarse=FTUNE 14bit
// EVT0 : 0x81000524[26:13], EVT1 : 0x8100000C[13:0]
if (is_evt0()) {
modifyreg32(S5JS100_PMU_ALIVE + 0x524, (0x3FFF << 13), (coarse_value << 13));
} else {
modifyreg32(S5JS100_PMU_ALIVE + 0xC, 0x3FFF << 0, coarse_value << 0);
}
#elif defined(DCXO_FINE_DCXO_COARSE_PMU)
// Fine=DcxoFTune, Coarse=FTUNE2
coarse_value >>= 6;
// Fine = DcxoFTune 20bit
modifyreg32(S5JS100_DCXO_CFG + DCXO_CFG_DSM_CFG0, 0xFFFFF << 1, fine_value << 1);
// Coarse=FTUNE2 14bit
// EVT0 : 0x81000528[31:17], EVT1 : 0x8100000C[28:14]
if (is_evt0()) {
modifyreg32(S5JS100_PMU_ALIVE + 0x528, 0x3FFF << 17, coarse_value << 17);
} else {
modifyreg32(S5JS100_PMU_ALIVE + 0xC, 0x3FFF << 14, coarse_value << 14);
}
#endif
return 1;
}
int s5js100_dcxo_set_idac_ex(int value)
{
modifyreg32(S5JS100_PMU_ALIVE + 0x524, 0xff << 5, value << 5);
return 1;
}
int s5js100_dcxo_set_fb_res(int value)
{
modifyreg32(S5JS100_PMU_ALIVE + 0x528, 0x7 << 0, value << 0);
return 1;
}
int s5js100_dcxo_set_buf_sel(int value)
{
modifyreg32(S5JS100_PMU_ALIVE + 0x528, 0xf << 3, value << 3);
return 1;
}
int s5js100_dcxo_set_dsmdither(unsigned int dither_bit_sel)
{
#if defined(DCXO_FINE_PMU_COARSE_DCXO)
// set dither_bit_sel, iDsmType=1, iEnDsmDither=0, iPrbsSel=0, iEnDsm=1
modifyreg32(S5JS100_DCXO_CFG + DCXO_CFG_DSM_CFG1, 0x7F, (1 << 6) + (dither_bit_sel << 2) + 1);
// toggle oSwRstDSM
modifyreg32(S5JS100_DCXO_CFG + DCXO_CFG_SW_RESETN, (1 << 3), 0);
modifyreg32(S5JS100_DCXO_CFG + DCXO_CFG_SW_RESETN, (1 << 3), (1 << 3));
#else
#endif
return 1;
}
int s5js100_dcxo_set_dither_bit_sel(unsigned int dither_bit_sel)
{
#if defined(DCXO_FINE_PMU_COARSE_DCXO)
modifyreg32(S5JS100_DCXO_CFG + DCXO_CFG_DSM_CFG1, (7 << 2), (dither_bit_sel << 2));
// toggle oSwRstDSM
modifyreg32(S5JS100_DCXO_CFG + DCXO_CFG_SW_RESETN, (1 << 3), 0);
modifyreg32(S5JS100_DCXO_CFG + DCXO_CFG_SW_RESETN, (1 << 3), (1 << 3));
#else
#endif
return 1;
}
int s5js100_dcxo_set_dsm_type(unsigned int dsm_type)
{
#if defined(DCXO_FINE_PMU_COARSE_DCXO)
modifyreg32(S5JS100_DCXO_CFG + DCXO_CFG_DSM_CFG1, (1 << 6), (dsm_type << 6));
// toggle oSwRstDSM
modifyreg32(S5JS100_DCXO_CFG + DCXO_CFG_SW_RESETN, (1 << 3), 0);
modifyreg32(S5JS100_DCXO_CFG + DCXO_CFG_SW_RESETN, (1 << 3), (1 << 3));
#else
#endif
return 1;
}
int s5js100_dcxo_set_en_dsm_dither(unsigned int en_dsm_dither)
{
#if defined(DCXO_FINE_PMU_COARSE_DCXO)
modifyreg32(S5JS100_DCXO_CFG + DCXO_CFG_DSM_CFG1, (1 << 5), (en_dsm_dither << 5));
// toggle oSwRstDSM
modifyreg32(S5JS100_DCXO_CFG + DCXO_CFG_SW_RESETN, (1 << 3), 0);
modifyreg32(S5JS100_DCXO_CFG + DCXO_CFG_SW_RESETN, (1 << 3), (1 << 3));
#else
#endif
return 1;
}
int s5js100_dcxo_set_prbs_sel(unsigned int prbs_sel)
{
#if defined(DCXO_FINE_PMU_COARSE_DCXO)
modifyreg32(S5JS100_DCXO_CFG + DCXO_CFG_DSM_CFG1, (1 << 1), (prbs_sel << 1));
// toggle oSwRstDSM
modifyreg32(S5JS100_DCXO_CFG + DCXO_CFG_SW_RESETN, (1 << 3), 0);
modifyreg32(S5JS100_DCXO_CFG + DCXO_CFG_SW_RESETN, (1 << 3), (1 << 3));
#else
#endif
return 1;
}
int s5js100_dcxo_en_dsm(unsigned int en_dsm)
{
#if defined(DCXO_FINE_PMU_COARSE_DCXO)
modifyreg32(S5JS100_DCXO_CFG + DCXO_CFG_DSM_CFG1, (1 << 0), (en_dsm << 0));
// toggle oSwRstDSM
modifyreg32(S5JS100_DCXO_CFG + DCXO_CFG_SW_RESETN, (1 << 3), 0);
modifyreg32(S5JS100_DCXO_CFG + DCXO_CFG_SW_RESETN, (1 << 3), (1 << 3));
#else
#endif
return 1;
}
extern "C" {
int s5js100_dcxo_force_initialize(void)
{
dcxo_init_flag = 0;
s5js100_dcxo_initialize();
s5js100_dcxo_force_update_ctb();
return 0;
}
}