Files
banban/ql-config/soc_platform/preboot_boot2/boards/libarom-common/pmu.c
T

180 lines
5.3 KiB
C

/* -*- C -*- */
/*
* Copyright (c) 2020, ASR microelectronics
* All rights reserved.
*/
/*---------------------------------------------------------------------------*/
#if defined(BOARD_CRANE) || defined(BOARD_CRANEW_MCU)
#include <stdbool.h>
#include "contiki.h"
#include "pmu.h"
#include "reg.h"
#include "cpu.h"
/* Log configuration */
#include "log.h"
#define LOG_MODULE "PMU"
#define LOG_LEVEL LOG_LEVEL_MAIN
/*---------------------------------------------------------------------------*/
#define PMU_BASE 0xD4282800
/* usb detect*/
#define PMU_SD_ROT_WAKE_CLR (PMU_BASE + 0x7C)
#define USB_VBUS_WK_SRC_SEL (1 << 8)
#define VBUS_DETECT (1 << 15)
#ifdef BOARD_CRANEW_MCU
/* WatchOne, WatchTwo */
#define VBUS_DETECT_MUX (1 << 27)
#else
#define VBUS_DETECT_MUX (1 << 17)
#endif
/*---------------------------------------------------------------------------*/
static bool
usb_support_phy_vbus_detect(void)
{
#if (AROM_VERSION < AROM_VER_2022_03_31_SC2_A0)
return false;
#else
uint32_t chip_id = hw_chip_id();
switch(chip_id) {
case CHIP_ID_CRANELS:
case CHIP_ID_CRANEW:
case CHIP_ID_CRANELR:
case CHIP_ID_CRANEGT:
case CHIP_ID_CRANELG:
case CHIP_ID_CRANELRH:
case CHIP_ID_LAPWING:
return false;
}
return true;
#endif
}
/*---------------------------------------------------------------------------*/
/*
* if USB_VBUS is connected(R1101(12K) and R1104(6.8K) is connected,
* USB_DETECT is connected to USB_VBUS),
* if USB_VBUS is unconnected, bit VBUS_DETECT always 0.
*/
int
usb_connect_with_usb_detect(void)
{
uint32_t val = readl(PMU_SD_ROT_WAKE_CLR);
uint32_t det_mask;
if(usb_support_phy_vbus_detect()) {
if((val & USB_VBUS_WK_SRC_SEL) == 0x0) {
writel(USB_VBUS_WK_SRC_SEL | val, PMU_SD_ROT_WAKE_CLR);
}
}
val = readl(PMU_SD_ROT_WAKE_CLR);
LOG_DBG("PMU_SD_ROT_WAKE_CLR(0x%x) = 0x%" PRIx32 "\n", PMU_SD_ROT_WAKE_CLR, val);
/**
* Those chips (CraneLB and later) have 2 schemes for VBUS detection:
* 1. VBUS valid form GPIO(legacy).
* 2. VBUS valid from PHY(newly added).
* Apply the PHY scheme by default, and the free GPIO can be used
* for another purpose.
*/
/* Compatible with new mux bit and legacy vbus detect bit */
det_mask = VBUS_DETECT_MUX | VBUS_DETECT;
return (val & det_mask) ? 1 : 0;
}
/*---------------------------------------------------------------------------*/
#define USB_BASE 0xD4208000
#define USB_PORT_SC (USB_BASE + 0x184)
#define SUSP_DETECT (1 << 7)
/*---------------------------------------------------------------------------*/
/*
* if USB_VBUS is unconnected(R1101(12K) and R1104(6.8K) is unconnected,
* USB_DETECT is unconnected to USB_VBUS),
* USB_DETECT always be 0 no matter usb connect or unconnect.
* PMU_SD_ROT_WAKE_CLR can not be use,
* need read USB_PORT_SC, if SUSP_DETECT[bit7] = 1 means usb is unconnected.
*
* if downloading, bit7 = 0. if usb pull out when download over, bit7 = 1
* Note:
* before try download, USB_PORT_SC always is 0x0, no matter USB_VBUS connected or not.
* so usb_connect_without_usb_detect cannot be used before received uuuu(preamble),
* it only can be used when downloading, to check whether usb is pulled out.
*/
int
usb_connect_without_usb_detect(void)
{
unsigned val = readl(USB_PORT_SC);
LOG_DBG("USB_PORT_SC(0x%x) = 0x%x\n", USB_PORT_SC, val);
return (val & SUSP_DETECT) ? 0 : 1;
}
/*---------------------------------------------------------------------------*/
/*
* if usb-vbus not connected, customer use at+qdownload = 1 to enter force download mode,
* not support wait 1s to try download mode.
*
* cr5 should not invoke usb_connect(). it is for mcu.
*/
int
usb_connect(void)
{
if(hw_platform_type() == HW_PLATFORM_TYPE_FPGA) {
/* HW_PLATFORM_TYPE_FPGA can not detect usb, return connected */
return 1;
} else if(hw_platform_type() == HW_PLATFORM_TYPE_ZEBU_Z1) {
return 0;
}
return usb_connect_with_usb_detect();
}
/*---------------------------------------------------------------------------*/
/*
* move geu clk enable to pmu.c instead of geu.c
* to support preboot enable gen clock, boot2 disable geu clock
* register is diff for cranew, refer to cpu.h
*/
static void
_geu_clk_enable(bool en)
{
#ifdef MCU_SYS_PMU_CTRL
/* cranew CR5 */
uint32_t pum_ctrl = readl(MCU_SYS_PMU_CTRL);
if(en) {
writel(pum_ctrl | AEU_CG_EN, MCU_SYS_PMU_CTRL);
} else {
writel(pum_ctrl & (~AEU_CG_EN), MCU_SYS_PMU_CTRL);
}
#else
pmu_aes_clk_res_ctrl_t pmu_aes_clk_res_ctrl;
pmu_aes_clk_res_ctrl.value = readl(PMU_AES_CLK_RES_CTRL);
if(en) {
pmu_aes_clk_res_ctrl.s.aes_axi_clk_en = 1;
} else {
pmu_aes_clk_res_ctrl.s.aes_axi_clk_en = 0;
}
pmu_aes_clk_res_ctrl.s.aes_axi_reset = 1;
writel(pmu_aes_clk_res_ctrl.value, PMU_AES_CLK_RES_CTRL);
#endif
}
/*---------------------------------------------------------------------------*/
void
geu_clk_enable(void)
{
unsigned int val = readl(ACGR);
val |= (1 << APMU_104M_BIT);
writel(val, ACGR);
_geu_clk_enable(1);
}
/*---------------------------------------------------------------------------*/
void
geu_clk_disable(void)
{
_geu_clk_enable(0);
}
#endif