212 lines
5.3 KiB
C
212 lines
5.3 KiB
C
|
/***************************************************************************
|
||
|
*
|
||
|
* Copyright 2015-2019 BES.
|
||
|
* All rights reserved. All unpublished rights reserved.
|
||
|
*
|
||
|
* No part of this work may be used or reproduced in any form or by any
|
||
|
* means, or stored in a database or retrieval system, without prior written
|
||
|
* permission of BES.
|
||
|
*
|
||
|
* Use of this work is governed by a license granted by BES.
|
||
|
* This work contains confidential and proprietary information of
|
||
|
* BES. which is protected by copyright, trade secret,
|
||
|
* trademark and other intellectual property rights.
|
||
|
*
|
||
|
****************************************************************************/
|
||
|
#include "plat_types.h"
|
||
|
#include "cmsis.h"
|
||
|
#include "hal_analogif.h"
|
||
|
#include "hal_location.h"
|
||
|
#include "hal_spi.h"
|
||
|
|
||
|
#define ANA_REG_CHIP_ID 0x00
|
||
|
|
||
|
#define ANA_CHIP_ID_SHIFT (4)
|
||
|
#define ANA_CHIP_ID_MASK (0xFFF << ANA_CHIP_ID_SHIFT)
|
||
|
#define ANA_CHIP_ID(n) BITFIELD_VAL(ANA_CHIP_ID, n)
|
||
|
#define ANA_VAL_CHIP_ID 0x18E
|
||
|
|
||
|
// ISPI_ARBITRATOR_ENABLE should be defined when:
|
||
|
// 1) BT and MCU will access RF register at the same time; or
|
||
|
// 2) BT can access PMU/ANA, and BT will access RF register at the same time
|
||
|
// when MCU is accessing PMU/ANA register
|
||
|
|
||
|
#ifdef ISPI_ARBITRATOR_ENABLE
|
||
|
// Min padding OSC cycles needed: BT=0 MCU=6
|
||
|
// When OSC=26M and SPI=6.5M, min padding SPI cycles is BT=0 MCU=2
|
||
|
#define PADDING_CYCLES 2
|
||
|
#else
|
||
|
#define PADDING_CYCLES 0
|
||
|
#endif
|
||
|
|
||
|
#define ANA_READ_CMD(r) (((1 << 24) | (((r) & 0xFF) << 16)) << PADDING_CYCLES)
|
||
|
#define ANA_WRITE_CMD(r, v) (((((r) & 0xFF) << 16) | ((v) & 0xFFFF)) << PADDING_CYCLES)
|
||
|
#define ANA_READ_VAL(v) (((v) >> PADDING_CYCLES) & 0xFFFF)
|
||
|
|
||
|
#define ANA_PAGE_1 0xA010
|
||
|
#define ANA_PAGE_0 0xA000
|
||
|
|
||
|
static const BOOT_RODATA_SRAM_LOC uint8_t page_reg[3] = {
|
||
|
0x00, 0x60, 0x80,
|
||
|
};
|
||
|
|
||
|
static const BOOT_RODATA_FLASH_LOC struct HAL_SPI_CFG_T spi_cfg = {
|
||
|
.clk_delay_half = false,
|
||
|
.clk_polarity = false,
|
||
|
.slave = false,
|
||
|
.dma_rx = false,
|
||
|
.dma_tx = false,
|
||
|
.rx_sep_line = false,
|
||
|
.cs = 0,
|
||
|
.rate = 6500000,
|
||
|
.tx_bits = 25 + PADDING_CYCLES,
|
||
|
.rx_bits = 25 + PADDING_CYCLES,
|
||
|
.rx_frame_bits = 0,
|
||
|
};
|
||
|
|
||
|
static bool BOOT_BSS_LOC analogif_inited = false;
|
||
|
|
||
|
static int BOOT_TEXT_SRAM_LOC hal_analogif_rawread(unsigned short reg, unsigned short *val)
|
||
|
{
|
||
|
int ret;
|
||
|
unsigned int data;
|
||
|
unsigned int cmd;
|
||
|
|
||
|
data = 0;
|
||
|
cmd = ANA_READ_CMD(reg);
|
||
|
ret = hal_ispi_recv(&cmd, &data, 4);
|
||
|
if (ret) {
|
||
|
return ret;
|
||
|
}
|
||
|
*val = ANA_READ_VAL(data);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static int BOOT_TEXT_SRAM_LOC hal_analogif_rawwrite(unsigned short reg, unsigned short val)
|
||
|
{
|
||
|
int ret;
|
||
|
unsigned int cmd;
|
||
|
|
||
|
cmd = ANA_WRITE_CMD(reg, val);
|
||
|
ret = hal_ispi_send(&cmd, 4);
|
||
|
if (ret) {
|
||
|
return ret;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int BOOT_TEXT_SRAM_LOC hal_analogif_reg_read(unsigned short reg, unsigned short *val)
|
||
|
{
|
||
|
uint32_t lock;
|
||
|
uint32_t idx;
|
||
|
int ret;
|
||
|
|
||
|
#if defined(USE_CYBERON)
|
||
|
extern int cyb_efuse_check_status(void);
|
||
|
|
||
|
if (cyb_efuse_check_status()) {
|
||
|
if (reg == 0x5e) {
|
||
|
*val = 49185;
|
||
|
return 0;
|
||
|
}
|
||
|
if (reg == 0x00) {
|
||
|
*val = 0x20e0;
|
||
|
return 0;
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
if (reg < 0x100) {
|
||
|
lock = int_lock();
|
||
|
ret = hal_analogif_rawread(reg, val);
|
||
|
int_unlock(lock);
|
||
|
return ret;
|
||
|
} else if (reg >= 0x100 && reg <= 0x15F) {
|
||
|
idx = 0;
|
||
|
} else if (reg >= 0x160 && reg <= 0x17F) {
|
||
|
idx = 1;
|
||
|
} else if (reg >= 0x180 && reg <= 0x1FF) {
|
||
|
idx = 2;
|
||
|
} else {
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
reg &= 0xFF;
|
||
|
|
||
|
lock = int_lock();
|
||
|
hal_analogif_rawwrite(page_reg[idx], ANA_PAGE_1);
|
||
|
ret = hal_analogif_rawread(reg, val);
|
||
|
hal_analogif_rawwrite(page_reg[idx], ANA_PAGE_0);
|
||
|
int_unlock(lock);
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
int BOOT_TEXT_SRAM_LOC hal_analogif_reg_write(unsigned short reg, unsigned short val)
|
||
|
{
|
||
|
uint32_t lock;
|
||
|
uint32_t idx;
|
||
|
int ret;
|
||
|
|
||
|
if (reg < 0x100) {
|
||
|
lock = int_lock();
|
||
|
ret = hal_analogif_rawwrite(reg, val);
|
||
|
int_unlock(lock);
|
||
|
return ret;
|
||
|
} else if (reg >= 0x100 && reg <= 0x15F) {
|
||
|
idx = 0;
|
||
|
} else if (reg >= 0x160 && reg <= 0x17F) {
|
||
|
idx = 1;
|
||
|
} else if (reg >= 0x180 && reg <= 0x1FF) {
|
||
|
idx = 2;
|
||
|
} else {
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
reg &= 0xFF;
|
||
|
|
||
|
lock = int_lock();
|
||
|
hal_analogif_rawwrite(page_reg[idx], ANA_PAGE_1);
|
||
|
ret = hal_analogif_rawwrite(reg, val);
|
||
|
hal_analogif_rawwrite(page_reg[idx], ANA_PAGE_0);
|
||
|
int_unlock(lock);
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
int BOOT_TEXT_FLASH_LOC hal_analogif_open(void)
|
||
|
{
|
||
|
int ret;
|
||
|
unsigned short chip_id;
|
||
|
const struct HAL_SPI_CFG_T *cfg_ptr;
|
||
|
struct HAL_SPI_CFG_T cfg;
|
||
|
|
||
|
if (analogif_inited) {
|
||
|
// Restore the nominal rate
|
||
|
cfg_ptr = &spi_cfg;
|
||
|
} else {
|
||
|
analogif_inited = true;
|
||
|
// Crystal freq is unknown yet. Let SPI run on half of the nominal rate
|
||
|
cfg = spi_cfg;
|
||
|
cfg.rate /= 2;
|
||
|
cfg_ptr = &cfg;
|
||
|
}
|
||
|
|
||
|
ret = hal_ispi_open(cfg_ptr);
|
||
|
if (ret) {
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
ret = hal_analogif_rawread(ANA_REG_CHIP_ID, &chip_id);
|
||
|
if (ret) {
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
if (GET_BITFIELD(chip_id, ANA_CHIP_ID) != ANA_VAL_CHIP_ID) {
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|