chen
2024-11-08 cc432b761c884a0bd8e9d83db0a4e26109fc08b1
keil/include/drivers/mk_calib.c
对比新文件
@@ -0,0 +1,262 @@
/*
 * Copyright (c) 2019-2023 Beijing Hanwei Innovation Technology Ltd. Co. and
 * its subsidiaries and affiliates (collectly called MKSEMI).
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form, except as embedded into an MKSEMI
 *    integrated circuit in a product or a software update for such product,
 *    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.
 *
 * 3. Neither the name of MKSEMI nor the names of its contributors may be used
 *    to endorse or promote products derived from this software without
 *    specific prior written permission.
 *
 * 4. This software, with or without modification, must only be used with a
 *    MKSEMI integrated circuit.
 *
 * 5. Any software provided in binary form under this license must not be
 *    reverse engineered, decompiled, modified and/or disassembled.
 *
 * THIS SOFTWARE IS PROVIDED BY MKSEMI "AS IS" AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL MKSEMI 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.
 */
#include "mk_calib.h"
#include "mk_clock.h"
#include "mk_reset.h"
#include "mk_trace.h"
#include "mk_misc.h"
#include "mk_rtc.h"
#include "board.h"
int calib_open(void)
{
    // enable CAL clock
    clock_enable(CLOCK_CALIB);
    reset_module(RESET_MODULE_CALIB);
    return DRV_OK;
}
int calib_close(void)
{
    // disable CAL clock
    clock_disable(CLOCK_CALIB);
    return DRV_OK;
}
void calib_start(uint32_t items)
{
    REG_WRITE(CALIB_BASE, items | CALIB_START);
}
void calib_check(uint32_t done)
{
    while ((REG_READ(CALIB_BASE + 0x4) & done) != done)
    {
    }
}
void calib_chip(void)
{
    uint32_t val;
    // load cap
    if (board_param.flag & (1 << BOARD_LOAD_CAP))
    {
        calib_xtal38m4_load_cap_set(board_param.load_cap);
    }
    if (board_param.flag & (1 << BOARD_X32K_LOAD_CAP))
    {
        calib_xtal32k_load_cap_set(board_param.x32k_load_cap);
    }
    clock_enable(CLOCK_CALIB);
    // fix DCDC_EN
    val = REG_READ(0x40000204) & ~0x3U;
    REG_WRITE(0x40000204, val | 0x2);
    // LO PLL configure
    REG_WRITE(0x4000060c, 0x0A106BAF);
#if HIGH_PERFORMANCE_MODE_EN
    // LPF_BM
    REG_WRITE(0x40000608, 0x03E80004);
    // increase Trim current to promote RF performance
    REG_WRITE_BYTE(0x40010072, 0x77);
#else
    // decrease Trim current
    // REG_WRITE_BYTE(0x40010072, 0x88); // lowest
    // clear Trim code
    REG_WRITE_BYTE(0x40010072, 0x00); // middle
    val = REG_READ_BYTE(0x40010071) & 0x1F;
    REG_WRITE_BYTE(0x40010071, (uint8_t)val);
#endif
#define LO_L (77 + (56 << 8) + (54 << 16) + (80 << 24))
#define LO_H (49 + (46 << 8) + (50 << 16) + (54 << 24))
#define WF (7 + (52 << 8))
    // patch for buck calibration voltage
    uint8_t x = REG_READ_BYTE(0x40010075);
    if ((READ_WORD(0x4001007C) == LO_L) && (READ_WORD(0x40010078) == LO_H) && (READ_SHORT(0x40010076) == WF) && (x >= 1) && (x <= 19))
    {
        REG_WRITE_BYTE(0x40010073, 0x20);
    }
    // patch for ADC trim code
    val = REG_READ_BYTE(0x4001006B);
    if ((val & 0x1F) == 0)
    {
        REG_WRITE_BYTE(0x4001006B, (uint8_t)(val | 0x10));
    }
    // Open RCO for calibration
    SYSCON->PMU_CTRL0 &= ~(1U << 5);
    // calibrate
    REG_WRITE(0x40006000, 0x80001cfe);
    while ((REG_READ(0x40006004) & 0x80000000) == 0)
    {
    }
    uint32_t id = mk_chip_id();
    LOG_INFO(TRACE_MODULE_DRIVER, "Chip ID: %08x\r\n", id);
    if (id == 0x0 || id == 0x400 || id == 0x800 || id == 0xC00)
    {
        LOG_INFO(TRACE_MODULE_DRIVER, "Old chip model is not supported by this SDK!!!\r\n");
        while (1)
        {
        }
    }
    // Reduce next PA calibration time
    val = REG_READ(0x400060d4) & ~0xfU;
    REG_WRITE(0x400060d4, val);
    val = REG_READ(0x400060c8) & ~((0xfU << 18) | (0x1));
    REG_WRITE(0x400060c8, val);
    // Reduce turnaround time
    REG_WRITE(0x40000410, 400);
    REG_WRITE(0x4000040c, 0x1f);
    // val = REG_READ(0x4000020c) & ~(0x1fU << 7);
    // REG_WRITE(0x4000020c, val | (0x18 << 7));
#if (LOW_POWER_EN) && (XTAL32K_EN == 0)
    rco32k_clk_calibrate(RCO32K_MEAS_TIME_64_CYCLES);
#endif
}
void calib_xtal38m4_load_cap_auto_tune(int32_t ppm)
{
    uint32_t tmp_val = REG_READ(0x40000048);
    uint8_t val = (tmp_val & 0x7FU);
    if (ppm > 2)
    {
        val += 1;
    }
    else if (ppm < -2)
    {
        val -= 1;
    }
    else
    {
        return;
    }
    tmp_val &= ~0x7FU;
    tmp_val |= (val & 0x7FU);
    REG_WRITE(0x40000048, tmp_val);
    LOG_INFO(TRACE_NO_REPORT_HOST | TRACE_MODULE_DRIVER, "XTAL load cap tune %d : %d\r\n", ppm, (tmp_val & 0x7FU));
}
void calib_xtal38m4_load_cap_set(uint8_t val)
{
    uint32_t tmp_val = REG_READ(0x40000048);
    tmp_val &= ~0x7FU;
    val &= 0x7FU;
    REG_WRITE(0x40000048, tmp_val | val);
    LOG_INFO(TRACE_MODULE_DRIVER, "XTAL load cap val %d\r\n", REG_READ(0x40000048) & 0x7FU);
}
void calib_xtal38m4_with_clock_out(uint8_t val)
{
    /* Setting GPIO17 output 38.4M clock. */
    uint32_t tmp_val = REG_READ(0x4000003C);
    tmp_val &= ~0x70U;
    tmp_val |= (0x1U << 4);
    REG_WRITE(0x4000003C, tmp_val);
    /* Setting internal load cap of MK8000, the valid value is from 0 ot 127. */
    tmp_val = REG_READ(0x40000048);
    tmp_val &= ~0x7FU;
    val &= 0x7FU;
    REG_WRITE(0x40000048, tmp_val | val);
    REG_WRITE(0x40000104, 0x3FFF);
    LOG_INFO(TRACE_MODULE_DRIVER, "XTAL load cap val %d\r\n", REG_READ(0x40000048) & 0x7FU);
}
void calib_xtal32k_load_cap_set(uint8_t val)
{
    uint32_t tmp_val = REG_READ(0x4000004C);
    tmp_val &= ~0x7FU;
    val &= 0x7FU;
    REG_WRITE(0x4000004C, tmp_val | val);
    LOG_INFO(TRACE_MODULE_DRIVER, "32K load cap val %d\r\n", REG_READ(0x4000004C) & 0x7FU);
}
void calib_xtal32k_with_clock_out(uint8_t val)
{
    /* Setting GPIO02 output 32K clock. */
    uint32_t tmp_val = REG_READ(0x40000234);
    tmp_val |= (0x1U << 10);
    REG_WRITE(0x40000234, tmp_val);
    /* Setting GPIO02 oupt 32K clock by pin mux. */
    tmp_val = REG_READ(0x40000034);
    tmp_val &= ~(0xFU << 8);
    tmp_val |= (0x4U << 8);
    REG_WRITE(0x40000034, tmp_val);
    /* Setting internal load cap of MK8000, the valid value is from 0 ot 127. */
    tmp_val = REG_READ(0x4000004C);
    tmp_val &= ~0x7FU;
    val &= 0x7FU;
    REG_WRITE(0x4000004C, tmp_val | val);
    LOG_INFO(TRACE_MODULE_DRIVER, "32K load cap val %d\r\n", REG_READ(0x4000004C) & 0x7FU);
}
void CALIB_IRQHandler(void)
{
}