feat(imx8ulp): add i.MX8ULP basic support

Add the basic support for i.MX8ULP.

The i.MX 8ULP family of processors features NXP’s advanced
implementation of the dual Arm Cortex-A35 cores alongside
an Arm Cortex-M33. This combined architecture enables the
device to run a rich operating system (such as Linux) on
the Cortex-A35 core and an RTOS (such as FreeRTOS) on the
Cortex-M33 core. It also includes a Cadence Tensilica Fusion
DSP for low-power audio and a HiFi4 DSP for advanced audio
and machine learning applications.

Signed-off-by: Peng Fan <peng.fan@nxp.com>
Signed-off-by: Ye Li <ye.li@nxp.com>
Signed-off-by: Jacky Bai <ping.bai@nxp.com>
Change-Id: I12df622b95960bcdf7da52e4c66470a700690e36
This commit is contained in:
Jacky Bai 2020-07-02 14:39:58 +08:00
parent 0d6b4cdb23
commit fcd41e8692
20 changed files with 8281 additions and 3 deletions

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2015-2024, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@ -86,6 +86,31 @@ func plat_calc_core_pos
ret
endfunc plat_calc_core_pos
/* ----------------------------------------------
* function to handle platform specific reset.
* ----------------------------------------------
*/
func plat_reset_handler
#if defined(PLAT_imx8ulp)
mrs x0, CORTEX_A35_CPUECTLR_EL1
orr x0, x0, #(0x1 << 0)
orr x0, x0, #(0x1 << 3)
msr CORTEX_A35_CPUECTLR_EL1, x0
mrs x0, CORTEX_A35_L2ECTLR_EL1
orr x0, x0, #(0x1 << 0)
msr CORTEX_A35_L2ECTLR_EL1, x0
isb
#endif
/* enable EL2 cpuectlr RW access */
mov x0, #0x73
msr actlr_el3, x0
msr actlr_el2, x0
isb
ret
endfunc plat_reset_handler
/* ---------------------------------------------
* function to get the entrypoint.
* ---------------------------------------------

View file

@ -0,0 +1,23 @@
/*
* Copyright 2023-2024 NXP
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <imx_plat_common.h>
uint32_t plat_get_spsr_for_bl33_entry(void)
{
unsigned long el_status;
unsigned long mode;
uint32_t spsr;
/* figure out what mode we enter the non-secure world */
el_status = read_id_aa64pfr0_el1() >> ID_AA64PFR0_EL2_SHIFT;
el_status &= ID_AA64PFR0_ELX_MASK;
mode = (el_status) ? MODE_EL2 : MODE_EL1;
spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
return spsr;
}

View file

@ -1,14 +1,17 @@
/*
* Copyright (c) 2015-2023, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2015-2024, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stdint.h>
#include <common/debug.h>
#include <common/runtime_svc.h>
#include <drivers/scmi-msg.h>
#include <lib/pmf/pmf.h>
#include <tools_share/uuid.h>
#include <imx_sip_svc.h>
static int32_t imx_sip_setup(void)
@ -29,6 +32,12 @@ static uintptr_t imx_sip_handler(unsigned int smc_fid,
case IMX_SIP_AARCH32:
SMC_RET1(handle, imx_kernel_entry_handler(smc_fid, x1, x2, x3, x4));
break;
#if defined(PLAT_imx8ulp)
case IMX_SIP_SCMI:
scmi_smt_fastcall_smc_entry(0);
SMC_RET1(handle, 0);
break;
#endif
#if defined(PLAT_imx8mq)
case IMX_SIP_GET_SOC_INFO:
SMC_RET1(handle, imx_soc_info_handler(smc_fid, x1, x2, x3));

View file

@ -0,0 +1,16 @@
/*
* Copyright 2023-2024 NXP
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef IMX_PLAT_COMMON_H
#define IMX_PLAT_COMMON_H
#include <stdint.h>
#include <arch_helpers.h>
uint32_t plat_get_spsr_for_bl33_entry(void);
#endif /*IMX_PLAT_COMMON_H */

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015-2023, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2015-2024, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@ -52,6 +52,9 @@
int imx_kernel_entry_handler(uint32_t smc_fid, u_register_t x1,
u_register_t x2, u_register_t x3,
u_register_t x4);
#define IMX_SIP_SCMI 0xC20000FE
#if defined(PLAT_imx8mq)
int imx_soc_info_handler(uint32_t smc_fid, u_register_t x1,
u_register_t x2, u_register_t x3);
@ -96,5 +99,6 @@ int imx_misc_set_temp_handler(uint32_t smc_fid, u_register_t x1,
uint64_t imx_buildinfo_handler(uint32_t smc_fid, u_register_t x1,
u_register_t x2, u_register_t x3,
u_register_t x4);
int scmi_handler(uint32_t smc_fid, u_register_t x1, u_register_t x2, u_register_t x3);
#endif /* __IMX_SIP_SVC_H__ */

View file

@ -0,0 +1,133 @@
/*
* Copyright 2021-2024 NXP
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <assert.h>
#include <stdbool.h>
#include <arch_helpers.h>
#include <common/bl_common.h>
#include <common/debug.h>
#include <context.h>
#include <drivers/console.h>
#include <drivers/generic_delay_timer.h>
#include <lib/el3_runtime/context_mgmt.h>
#include <lib/mmio.h>
#include <lib/xlat_tables/xlat_tables_v2.h>
#include <plat/common/platform.h>
#include <platform_def.h>
#include <imx8_lpuart.h>
#include <imx_plat_common.h>
#include <plat_imx8.h>
#include <upower_api.h>
#define MAP_BL31_TOTAL \
MAP_REGION_FLAT(BL31_BASE, BL31_LIMIT - BL31_BASE, MT_MEMORY | MT_RW | MT_SECURE)
#define MAP_BL31_RO \
MAP_REGION_FLAT(BL_CODE_BASE, BL_CODE_END - BL_CODE_BASE, MT_MEMORY | MT_RO | MT_SECURE)
#define MAP_COHERENT_MEM \
MAP_REGION_FLAT(BL_COHERENT_RAM_BASE, (BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE), \
MT_DEVICE | MT_RW | MT_SECURE)
static const mmap_region_t imx_mmap[] = {
DEVICE0_MAP, DEVICE1_MAP, ELE_MAP,
SEC_SIM_MAP, SRAM0_MAP,
{0}
};
extern uint32_t upower_init(void);
extern void imx8ulp_init_scmi_server(void);
static entry_point_info_t bl32_image_ep_info;
static entry_point_info_t bl33_image_ep_info;
void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
u_register_t arg2, u_register_t arg3)
{
static console_t console;
/* enable the GPIO D,E,F non-secure access by default */
mmio_write_32(IMX_PCC4_BASE + 0x78, 0xc0000000);
mmio_write_32(IMX_PCC4_BASE + 0x7c, 0xc0000000);
mmio_write_32(IMX_PCC5_BASE + 0x114, 0xc0000000);
mmio_write_32(IMX_GPIOE_BASE + 0x10, 0xffffffff);
mmio_write_32(IMX_GPIOE_BASE + 0x14, 0x3);
mmio_write_32(IMX_GPIOE_BASE + 0x18, 0xffffffff);
mmio_write_32(IMX_GPIOE_BASE + 0x1c, 0x3);
mmio_write_32(IMX_GPIOF_BASE + 0x10, 0xffffffff);
mmio_write_32(IMX_GPIOF_BASE + 0x14, 0x3);
mmio_write_32(IMX_GPIOF_BASE + 0x18, 0xffffffff);
mmio_write_32(IMX_GPIOF_BASE + 0x1c, 0x3);
mmio_write_32(IMX_GPIOD_BASE + 0x10, 0xffffffff);
mmio_write_32(IMX_GPIOD_BASE + 0x14, 0x3);
mmio_write_32(IMX_GPIOD_BASE + 0x18, 0xffffffff);
mmio_write_32(IMX_GPIOD_BASE + 0x1c, 0x3);
console_lpuart_register(IMX_LPUART_BASE, IMX_BOOT_UART_CLK_IN_HZ,
IMX_CONSOLE_BAUDRATE, &console);
/* This console is only used for boot stage */
console_set_scope(&console, CONSOLE_FLAG_BOOT | CONSOLE_FLAG_RUNTIME);
bl33_image_ep_info.pc = PLAT_NS_IMAGE_OFFSET;
bl33_image_ep_info.spsr = plat_get_spsr_for_bl33_entry();
SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
}
void bl31_plat_arch_setup(void)
{
const mmap_region_t bl_regions[] = {
MAP_BL31_TOTAL,
MAP_BL31_RO,
#if USE_COHERENT_MEM
MAP_COHERENT_MEM,
#endif
{0},
};
setup_page_tables(bl_regions, imx_mmap);
enable_mmu_el3(0);
/* TODO: Hack, refine this piece, scmi channel free */
mmio_write_32(SRAM0_BASE + 0x4, 1);
}
void bl31_platform_setup(void)
{
/* select the arch timer source */
mmio_setbits_32(IMX_SIM1_BASE + 0x30, 0x8000000);
generic_delay_timer_init();
plat_gic_driver_init();
plat_gic_init();
imx8ulp_init_scmi_server();
upower_init();
}
entry_point_info_t *bl31_plat_get_next_image_ep_info(unsigned int type)
{
if (type == NON_SECURE) {
return &bl33_image_ep_info;
} else {
return &bl32_image_ep_info;
}
}
unsigned int plat_get_syscnt_freq2(void)
{
return COUNTER_FREQUENCY;
}
void bl31_plat_runtime_setup(void)
{
}

View file

@ -0,0 +1,124 @@
/*
* Copyright 2021-2024 NXP
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stdbool.h>
#include <arch.h>
#include <arch_helpers.h>
#include <common/debug.h>
#include <drivers/arm/gicv3.h>
#include <lib/mmio.h>
#include <lib/psci/psci.h>
#include <plat_imx8.h>
static uintptr_t secure_entrypoint;
#define CORE_PWR_STATE(state) ((state)->pwr_domain_state[MPIDR_AFFLVL0])
#define CLUSTER_PWR_STATE(state) ((state)->pwr_domain_state[MPIDR_AFFLVL1])
#define SYSTEM_PWR_STATE(state) ((state)->pwr_domain_state[PLAT_MAX_PWR_LVL])
#define RVBARADDRx(c) (IMX_SIM1_BASE + 0x5c + 0x4 * (c))
#define WKPUx(c) (IMX_SIM1_BASE + 0x3c + 0x4 * (c))
#define AD_COREx_LPMODE(c) (IMX_CMC1_BASE + 0x50 + 0x4 * (c))
static int imx_pwr_set_cpu_entry(unsigned int cpu, unsigned int entry)
{
mmio_write_32(RVBARADDRx(cpu), entry);
/* set update bit */
mmio_write_32(IMX_SIM1_BASE + 0x8, mmio_read_32(IMX_SIM1_BASE + 0x8) | BIT_32(24 + cpu));
/* wait for ack */
while (!(mmio_read_32(IMX_SIM1_BASE + 0x8) & BIT_32(26 + cpu))) {
}
/* clear update bit */
mmio_write_32(IMX_SIM1_BASE + 0x8, mmio_read_32(IMX_SIM1_BASE + 0x8) & ~BIT_32(24 + cpu));
/* clear ack bit */
mmio_write_32(IMX_SIM1_BASE + 0x8, mmio_read_32(IMX_SIM1_BASE + 0x8) | BIT_32(26 + cpu));
return 0;
}
int imx_pwr_domain_on(u_register_t mpidr)
{
unsigned int cpu = MPIDR_AFFLVL0_VAL(mpidr);
imx_pwr_set_cpu_entry(cpu, secure_entrypoint);
mmio_write_32(IMX_CMC1_BASE + 0x18, 0x3f);
mmio_write_32(IMX_CMC1_BASE + 0x50 + 0x4 * cpu, 0);
/* enable wku wakeup for idle */
mmio_write_32(IMX_SIM1_BASE + 0x3c + 0x4 * cpu, 0xffffffff);
return PSCI_E_SUCCESS;
}
void imx_pwr_domain_on_finish(const psci_power_state_t *target_state)
{
imx_pwr_set_cpu_entry(0, IMX_ROM_ENTRY);
plat_gic_pcpu_init();
plat_gic_cpuif_enable();
}
int imx_validate_ns_entrypoint(uintptr_t ns_entrypoint)
{
return PSCI_E_SUCCESS;
}
void imx_pwr_domain_off(const psci_power_state_t *target_state)
{
unsigned int cpu = MPIDR_AFFLVL0_VAL(read_mpidr_el1());
plat_gic_cpuif_disable();
/* disable wakeup */
mmio_write_32(WKPUx(cpu), 0);
mmio_write_32(AD_COREx_LPMODE(cpu), 0x3);
}
void __dead2 imx8ulp_pwr_domain_pwr_down_wfi(const psci_power_state_t *target_state)
{
while (1) {
wfi();
}
}
void __dead2 imx8ulp_system_reset(void)
{
imx_pwr_set_cpu_entry(0, IMX_ROM_ENTRY);
/* Write invalid command to WDOG CNT to trigger reset */
mmio_write_32(IMX_WDOG3_BASE + 0x4, 0x12345678);
while (true) {
wfi();
}
}
static const plat_psci_ops_t imx_plat_psci_ops = {
.pwr_domain_on = imx_pwr_domain_on,
.pwr_domain_on_finish = imx_pwr_domain_on_finish,
.validate_ns_entrypoint = imx_validate_ns_entrypoint,
.system_reset = imx8ulp_system_reset,
.pwr_domain_off = imx_pwr_domain_off,
.pwr_domain_pwr_down_wfi = imx8ulp_pwr_domain_pwr_down_wfi,
};
int plat_setup_psci_ops(uintptr_t sec_entrypoint,
const plat_psci_ops_t **psci_ops)
{
secure_entrypoint = sec_entrypoint;
imx_pwr_set_cpu_entry(0, sec_entrypoint);
*psci_ops = &imx_plat_psci_ops;
mmio_write_32(IMX_CMC1_BASE + 0x18, 0x3f);
mmio_write_32(IMX_SIM1_BASE + 0x3c, 0xffffffff);
return 0;
}

View file

@ -0,0 +1,93 @@
/*
* Copyright 2021-2024 NXP
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef PLATFORM_DEF_H
#define PLATFORM_DEF_H
#include <lib/utils_def.h>
#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64"
#define PLATFORM_LINKER_ARCH aarch64
#define PLATFORM_STACK_SIZE 0x400
#define CACHE_WRITEBACK_GRANULE 64
#define PLAT_PRIMARY_CPU 0x0
#define PLATFORM_MAX_CPU_PER_CLUSTER 2
#define PLATFORM_CLUSTER_COUNT 1
#define PLATFORM_CORE_COUNT 2
#define PLATFORM_CLUSTER0_CORE_COUNT 2
#define PLATFORM_CLUSTER1_CORE_COUNT 0
#define IMX_PWR_LVL0 MPIDR_AFFLVL0
#define IMX_PWR_LVL1 MPIDR_AFFLVL1
#define IMX_PWR_LVL2 MPIDR_AFFLVL2
#define PWR_DOMAIN_AT_MAX_LVL U(1)
#define PLAT_MAX_PWR_LVL U(2)
#define PLAT_MAX_OFF_STATE U(4)
#define PLAT_MAX_RET_STATE U(2)
#define PLAT_WAIT_RET_STATE U(1)
#define PLAT_STOP_OFF_STATE U(3)
#define BL31_BASE 0x20040000
#define BL31_LIMIT 0x20070000
#define PLAT_VIRT_ADDR_SPACE_SIZE (1ull << 32)
#define PLAT_PHY_ADDR_SPACE_SIZE (1ull << 32)
#define MAX_XLAT_TABLES 8
#define MAX_MMAP_REGIONS 9
#define PLAT_GICD_BASE U(0x2d400000)
#define PLAT_GICR_BASE U(0x2d440000)
#define DEVICE0_BASE U(0x20000000)
#define DEVICE0_SIZE U(0x10000000)
#define DEVICE1_BASE U(0x30000000)
#define DEVICE1_SIZE U(0x10000000)
#define IMX_LPUART4_BASE U(0x29390000)
#define IMX_LPUART5_BASE U(0x293a0000)
#define IMX_LPUART_BASE IMX_LPUART5_BASE
#define IMX_BOOT_UART_CLK_IN_HZ 24000000
#define IMX_CONSOLE_BAUDRATE 115200
#define IMX_CGC1_BASE U(0x292c0000)
#define IMX_PCC3_BASE U(0x292d0000)
#define IMX_PCC4_BASE U(0x29800000)
#define IMX_SIM2_BASE U(0x2da50000)
#define IMX_CGC2_BASE U(0x2da60000)
#define IMX_PCC5_BASE U(0x2da70000)
#define IMX_CMC1_BASE U(0x29240000)
#define IMX_SIM1_BASE U(0x29290000)
#define IMX_WDOG3_BASE U(0x292a0000)
#define IMX_GPIOE_BASE U(0x2D000000)
#define IMX_GPIOD_BASE U(0x2E200000)
#define IMX_GPIOF_BASE U(0x2D010000)
#define SRAM0_BASE U(0x2201F000)
#define IMX_ROM_ENTRY U(0x1000)
#define COUNTER_FREQUENCY 1000000
#define PLAT_NS_IMAGE_OFFSET 0x80200000
#define BL31_NOBITS_BASE 0x20058000
#define BL31_NOBITS_LIMIT 0x2006d000
#define BL31_RWDATA_BASE 0x2006d000
#define BL31_RWDATA_LIMIT 0x20070000
/* system memory map define */
#define DEVICE0_MAP MAP_REGION_FLAT(DEVICE0_BASE, DEVICE0_SIZE, MT_DEVICE | MT_RW)
#define DEVICE1_MAP MAP_REGION_FLAT(DEVICE1_BASE, DEVICE1_SIZE, MT_DEVICE | MT_RW)
/* MU and FSB */
#define ELE_MAP MAP_REGION_FLAT(0x27010000, 0x20000, MT_DEVICE | MT_RW | MT_NS)
#define SEC_SIM_MAP MAP_REGION_FLAT(0x2802B000, 0x1000, MT_DEVICE | MT_RW | MT_NS) /* SEC SIM */
/* For SCMI shared memory region */
#define SRAM0_MAP MAP_REGION_FLAT(SRAM0_BASE, 0x1000, MT_RW | MT_DEVICE)
#endif /* PLATFORM_DEF_H */

View file

@ -0,0 +1,100 @@
/*
* Copyright 2021-2024 NXP
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef IMX8_SCMI_H
#define IMX8_SCMI_H
#include <stdint.h>
#define SCMI_SHMEM_CHANNEL_ERROR BIT_32(1)
#define SCMI_SHMEM_CHANNEL_FREE BIT_32(0)
#define SCMI_SHMEM_FLAG_INTR_ENABLED BIT_32(0)
enum scmi_std_protocol {
SCMI_PROTOCOL_BASE = 0x10,
SCMI_PROTOCOL_POWER_DOMAIN = 0x11,
SCMI_PROTOCOL_SYS_POWER = 0x12,
SCMI_PROTOCOL_PERF_DOMAIN = 0x13,
SCMI_PROTOCOL_CLK = 0x14,
SCMI_PROTOCOL_SENSOR = 0x15,
SCMI_PROTOCOL_RESET_DOMAIN = 0x16,
};
#define MSG_ID(m) ((m) & 0xff)
#define MSG_TYPE(m) (((m) >> 8) & 0x3)
#define MSG_PRO_ID(m) (((m) >> 10) & 0xff)
#define MSG_TOKEN(m) (((m) >> 18) & 0x3ff)
enum {
SCMI_POWER_DOMAIN_PROTOCOL = 0x11,
SCMI_SYS_PWR_DOMAIN_PROTOCOL = 0x12,
SCMI_PER_DOMAIN_PROTOCOL = 0x13,
SCMI_CLK_DOMAIN_PROTOCOL = 0x14,
SCMI_SENSOR_PROTOCOL = 0x15,
};
#define PROTOCOL_VERSION 0
#define PROTOCOL_ATTRIBUTES 1
#define PROTOCOL_MESSAGE_ATTRIBUTES 2
#define BASE_DISCOVER_VENDOR 3
#define BASE_DISCOVER_SUB_VENDOR 4
#define BASE_DISCOVER_IMPLEMENTATION_VERSION 5
#define BASE_DISCOVER_LIST_PROTOCOLS 6
#define BASE_DISCOVER_AGENT 7
#define BASE_NOTIFY_ERRORS 8
#define BASE_SET_DEVICE_PERMISSIONS 9
#define BASE_SET_PROTOCOL_PERMISSIONS 0xA
#define BASE_RESET_AGENT_CONFIGURATION 0xB
enum {
SCMI_RET_SUCCESS = 0,
SCMI_RET_NOT_SUPPORTED = -1,
SCMI_RET_INVALID_PARAMETERS = -2,
SCMI_RET_DENIED = -3,
SCMI_RET_NOT_FOUND = -4,
SCMI_RET_OUT_OF_RANGE = -5,
SCMI_RET_BUSY = -6,
SCMI_RET_COMMS_ERROR = -7,
SCMI_RET_GENERIC_ERROR = -8,
SCMI_RET_HARDWARE_ERROR = -9,
SCMI_RET_PROTOCOL_ERROR = -10,
};
#define POWER_DOMAIN_ATTRIBUTES 3
#define POWER_DOMAIN_SUPPORT_NOTIFICATION BIT(31)
#define POWER_DOMAIN_SUPPORT_ASYNCHRONOUS BIT(30)
#define POWER_DOMAIN_SUPPORT_SYNCHRONOUS BIT(29)
#define POWER_STATE_SET 4
#define POWER_STATE_GET 5
#define POWER_STATE_NOTIFY 6
#define POWER_STATE_CHANGE_REQUESTED_NOTIFY 7
int scmi_power_domain_handler(uint32_t msg_id, void *shmem);
#define PERFORMANCE_DOMAIN_ATTRIBUTES 3
#define PERFORMANCE_DESCRIBE_LEVELS 4
#define PERFORMANCE_LIMITS_SET 5
#define PERFORMANCE_LIMITS_GET 6
#define PERFORMANCE_LEVEL_SET 7
#define PERFORMANCE_LEVEL_GET 8
#define PERFORMANCE_NOTIFY_LIMITS 9
#define PERFORMANCE_NOTIFY_LEVEL 0xA
#define PERFORMANCE_DESCRIBE_FAST_CHANNEL 0xB
int scmi_perf_domain_handler(uint32_t msg_id, void *shmem);
#define SENSOR_DESCRIPTION_GET 0x003
#define SENSOR_CONFIG_SET 0x004
#define SENSOR_TRIP_POINT_SET 0x005
#define SENSOR_READING_GET 0x006
int scmi_sensor_handler(uint32_t msg_id, void *shmem);
#define SMC_SHMEM_BASE 0x2201f000
#endif /* IMX8_SCMI_H */

View file

@ -0,0 +1,139 @@
/*
* Copyright (c) 2015-2024, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
* Description:
* System Control and Management Interface (SCMI) support.
*/
#ifndef INTERNAL_SCMI_SENSOR_H
#define INTERNAL_SCMI_SENSOR_H
#include <stdint.h>
#define SCMI_PROTOCOL_VERSION_SENSOR UINT32_C(0x10000)
/*
* PROTOCOL_ATTRIBUTES
*/
struct scmi_sensor_protocol_attributes_p2a {
int32_t status;
uint32_t attributes;
uint32_t sensor_reg_address_low;
uint32_t sensor_reg_address_high;
uint32_t sensor_reg_len;
};
/*
* SENSOR_READING_GET
*/
#define SCMI_SENSOR_PROTOCOL_READING_GET_ASYNC_FLAG_MASK (1 << 0)
struct scmi_sensor_protocol_reading_get_a2p {
uint32_t sensor_id;
uint32_t flags;
};
struct scmi_sensor_protocol_reading_get_p2a {
int32_t status;
uint32_t sensor_value_low;
uint32_t sensor_value_high;
};
/*
* SENSOR_DESCRIPTION_GET
*/
#define SCMI_SENSOR_DESCS_MAX(MAILBOX_SIZE) \
((sizeof(struct scmi_sensor_protocol_description_get_p2a) < MAILBOX_SIZE) \
? ((MAILBOX_SIZE - \
sizeof(struct scmi_sensor_protocol_description_get_p2a)) \
/ sizeof(struct scmi_sensor_desc)) \
: 0)
#define SCMI_SENSOR_DESC_ATTRS_HIGH_SENSOR_TYPE_POS 0
#define SCMI_SENSOR_DESC_ATTRS_HIGH_SENSOR_UNIT_MULTIPLIER_POS 11
#define SCMI_SENSOR_DESC_ATTRS_HIGH_SENSOR_UPDATE_MULTIPLIER_POS 22
#define SCMI_SENSOR_DESC_ATTRS_HIGH_SENSOR_UPDATE_INTERVAL_POS 27
#define SCMI_SENSOR_DESC_ATTRS_HIGH_SENSOR_TYPE_MASK \
(UINT32_C(0xFF) << SCMI_SENSOR_DESC_ATTRS_HIGH_SENSOR_TYPE_POS)
#define SCMI_SENSOR_DESC_ATTRS_HIGH_SENSOR_UNIT_MULTIPLIER_MASK \
(UINT32_C(0x1F) << SCMI_SENSOR_DESC_ATTRS_HIGH_SENSOR_UNIT_MULTIPLIER_POS)
#define SCMI_SENSOR_DESC_ATTRS_HIGH_SENSOR_UPDATE_MULTIPLIER_MASK \
(UINT32_C(0x1F) << \
SCMI_SENSOR_DESC_ATTRS_HIGH_SENSOR_UPDATE_MULTIPLIER_POS)
#define SCMI_SENSOR_DESC_ATTRS_HIGH_SENSOR_UPDATE_INTERVAL_MASK \
(UINT32_C(0x1F) << SCMI_SENSOR_DESC_ATTRS_HIGH_SENSOR_UPDATE_INTERVAL_POS)
#define SCMI_SENSOR_DESC_ATTRS_HIGH_SENSOR_UNIT_MULTIPLIER_MAX \
(int32_t)(SCMI_SENSOR_DESC_ATTRS_HIGH_SENSOR_UNIT_MULTIPLIER_MASK >> 1)
#define SCMI_SENSOR_DESC_ATTRS_HIGH_SENSOR_UNIT_MULTIPLIER_MIN \
(-(SCMI_SENSOR_DESC_ATTRS_HIGH_SENSOR_UNIT_MULTIPLIER_MAX + 1))
#define SCMI_SENSOR_DESC_ATTRS_HIGH_SENSOR_UPDATE_MULTIPLIER_MAX \
(int32_t)(SCMI_SENSOR_DESC_ATTRS_HIGH_SENSOR_UPDATE_INTERVAL_MASK >> 1)
#define SCMI_SENSOR_DESC_ATTRS_HIGH_SENSOR_UPDATE_MULTIPLIER_MIN \
(-(SCMI_SENSOR_DESC_ATTRS_HIGH_SENSOR_UPDATE_MULTIPLIER_MAX + 1))
#define SCMI_SENSOR_DESC_ATTRIBUTES_HIGH(SENSOR_TYPE, UNIT_MULTIPLIER, \
UPDATE_MULTIPLIER, UPDATE_INTERVAL) \
( \
(((SENSOR_TYPE) << \
SCMI_SENSOR_DESC_ATTRS_HIGH_SENSOR_TYPE_POS) & \
SCMI_SENSOR_DESC_ATTRS_HIGH_SENSOR_TYPE_MASK) | \
(((UNIT_MULTIPLIER) << \
SCMI_SENSOR_DESC_ATTRS_HIGH_SENSOR_UNIT_MULTIPLIER_POS) & \
SCMI_SENSOR_DESC_ATTRS_HIGH_SENSOR_UNIT_MULTIPLIER_MASK) | \
(((UPDATE_MULTIPLIER) << \
SCMI_SENSOR_DESC_ATTRS_HIGH_SENSOR_UPDATE_MULTIPLIER_POS) & \
SCMI_SENSOR_DESC_ATTRS_HIGH_SENSOR_UPDATE_MULTIPLIER_MASK) | \
(((UPDATE_INTERVAL) << \
SCMI_SENSOR_DESC_ATTRS_HIGH_SENSOR_UPDATE_INTERVAL_POS) & \
SCMI_SENSOR_DESC_ATTRS_HIGH_SENSOR_UPDATE_INTERVAL_MASK) \
)
#define SCMI_SENSOR_NUM_SENSOR_FLAGS_NUM_DESCS_POS 0
#define SCMI_SENSOR_NUM_SENSOR_FLAGS_NUM_REMAINING_DESCS_POS 16
#define SCMI_SENSOR_NUM_SENSOR_FLAGS_NUM_DESCS_MASK \
(UINT32_C(0xFFF) << SCMI_SENSOR_NUM_SENSOR_FLAGS_NUM_DESCS_POS)
#define SCMI_SENSOR_NUM_SENSOR_FLAGS_NUM_REMAINING_DESCS_MASK \
(UINT32_C(0xFFFF) << SCMI_SENSOR_NUM_SENSOR_FLAGS_NUM_REMAINING_DESCS_POS)
#define SCMI_SENSOR_NUM_SENSOR_FLAGS(NUM_DESCS, NUM_REMAINING_DESCS) \
( \
(((NUM_DESCS) << \
SCMI_SENSOR_NUM_SENSOR_FLAGS_NUM_DESCS_POS) & \
SCMI_SENSOR_NUM_SENSOR_FLAGS_NUM_DESCS_MASK) | \
(((NUM_REMAINING_DESCS) << \
SCMI_SENSOR_NUM_SENSOR_FLAGS_NUM_REMAINING_DESCS_POS) & \
SCMI_SENSOR_NUM_SENSOR_FLAGS_NUM_REMAINING_DESCS_MASK) \
)
#define SCMI_SENSOR_NAME_LEN 16
struct scmi_sensor_desc {
uint32_t sensor_id;
uint32_t sensor_attributes_low;
uint32_t sensor_attributes_high;
char sensor_name[SCMI_SENSOR_NAME_LEN];
};
struct scmi_sensor_protocol_description_get_a2p {
uint32_t desc_index;
};
struct scmi_sensor_protocol_description_get_p2a {
int32_t status;
uint32_t num_sensor_flags;
struct scmi_sensor_desc sensor_desc[];
};
/* Event indices */
enum scmi_sensor_api_idx {
SCMI_SENSOR_EVENT_IDX_REQUEST,
SCMI_SENSOR_EVENT_IDX_COUNT,
};
#endif /* INTERNAL_SCMI_SENSOR_H */

View file

@ -0,0 +1,60 @@
#
# Copyright 2021-2024 NXP
#
# SPDX-License-Identifier: BSD-3-Clause
#
# Translation tables library
include lib/xlat_tables_v2/xlat_tables.mk
# Include GICv3 driver files
include drivers/arm/gic/v3/gicv3.mk
PLAT_INCLUDES := -Iplat/imx/imx8ulp/include \
-Iplat/imx/common/include \
-Iplat/imx/imx8ulp/upower
IMX_GIC_SOURCES := ${GICV3_SOURCES} \
plat/common/plat_gicv3.c \
plat/common/plat_psci_common.c \
plat/imx/common/plat_imx8_gic.c
BL31_SOURCES += plat/imx/common/lpuart_console.S \
plat/imx/common/imx8_helpers.S \
plat/imx/imx8ulp/imx8ulp_bl31_setup.c \
plat/imx/imx8ulp/imx8ulp_psci.c \
plat/imx/common/imx8_topology.c \
plat/imx/common/imx_sip_svc.c \
plat/imx/common/imx_sip_handler.c \
plat/imx/common/imx_bl31_common.c \
plat/common/plat_psci_common.c \
lib/cpus/aarch64/cortex_a35.S \
drivers/delay_timer/delay_timer.c \
drivers/delay_timer/generic_delay_timer.c \
drivers/scmi-msg/base.c \
drivers/scmi-msg/entry.c \
drivers/scmi-msg/smt.c \
drivers/scmi-msg/power_domain.c \
drivers/scmi-msg/sensor.c \
plat/imx/imx8ulp/scmi/scmi.c \
plat/imx/imx8ulp/scmi/scmi_pd.c \
plat/imx/imx8ulp/scmi/scmi_sensor.c \
plat/imx/imx8ulp/upower/upower_api.c \
plat/imx/imx8ulp/upower/upower_hal.c \
${XLAT_TABLES_LIB_SRCS} \
${IMX_GIC_SOURCES}
ifeq ($(findstring clang,$(notdir $(CC))),)
TF_CFLAGS_aarch64 += -fno-strict-aliasing
endif
USE_COHERENT_MEM := 1
RESET_TO_BL31 := 1
SEPARATE_NOBITS_REGION := 1
SEPARATE_RWDATA_REGION := 1
PROGRAMMABLE_RESET_ADDRESS := 1
COLD_BOOT_SINGLE_CPU := 1
BL32_BASE ?= 0xa6000000
BL32_SIZE ?= 0x2000000
$(eval $(call add_define,BL32_BASE))
$(eval $(call add_define,BL32_SIZE))

View file

@ -0,0 +1,69 @@
/*
* Copyright 2021-2024 NXP
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <assert.h>
#include <stdint.h>
#include <drivers/scmi-msg.h>
#include <drivers/scmi.h>
#include <platform_def.h>
#define SMT_BUFFER_BASE 0x2201f000
#define SMT_BUFFER0_BASE SMT_BUFFER_BASE
#define SMT_BUFFER1_BASE (SMT_BUFFER_BASE + 0x200)
static struct scmi_msg_channel scmi_channel[] = {
[0] = {
.shm_addr = SMT_BUFFER0_BASE,
.shm_size = SMT_BUF_SLOT_SIZE,
},
};
struct scmi_msg_channel *plat_scmi_get_channel(unsigned int agent_id)
{
assert(agent_id < ARRAY_SIZE(scmi_channel));
return &scmi_channel[agent_id];
}
static const char vendor[] = "NXP";
static const char sub_vendor[] = "";
const char *plat_scmi_vendor_name(void)
{
return vendor;
}
const char *plat_scmi_sub_vendor_name(void)
{
return sub_vendor;
}
/* Currently supporting Clocks and Reset Domains */
static const uint8_t plat_protocol_list[] = {
SCMI_PROTOCOL_ID_POWER_DOMAIN,
SCMI_PROTOCOL_ID_SENSOR,
0U /* Null termination */
};
size_t plat_scmi_protocol_count(void)
{
return ARRAY_SIZE(plat_protocol_list) - 1U;
}
const uint8_t *plat_scmi_protocol_list(unsigned int agent_id __unused)
{
return plat_protocol_list;
}
void imx8ulp_init_scmi_server(void)
{
size_t i;
for (i = 0U; i < ARRAY_SIZE(scmi_channel); i++) {
scmi_smt_init_agent_channel(&scmi_channel[i]);
}
}

View file

@ -0,0 +1,352 @@
/*
* Copyright 2021-2024 NXP
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <inttypes.h>
#include <lib/libc/errno.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <common/debug.h>
#include <drivers/scmi.h>
#include <lib/mmio.h>
#include <lib/utils_def.h>
#include <platform_def.h>
#include <scmi.h>
#include <upower_api.h>
#define POWER_STATE_ON (0 << 30)
#define POWER_STATE_OFF (1 << 30)
enum {
PS0 = 0,
PS1 = 1,
PS2 = 2,
PS3 = 3,
PS4 = 4,
PS5 = 5,
PS6 = 6,
PS7 = 7,
PS8 = 8,
PS9 = 9,
PS10 = 10,
PS11 = 11,
PS12 = 12,
PS13 = 13,
PS14 = 14,
PS15 = 15,
PS16 = 16,
PS17 = 17,
PS18 = 18,
PS19 = 19,
};
#define SRAM_DMA1 BIT(6)
#define SRAM_FLEXSPI2 BIT(7)
#define SRAM_USB0 BIT(10)
#define SRAM_USDHC0 BIT(11)
#define SRAM_USDHC1 BIT(12)
#define SRAM_USDHC2_USB1 BIT(13)
#define SRAM_DCNANO GENMASK_32(18, 17)
#define SRAM_EPDC GENMASK_32(20, 19)
#define SRAM_DMA2 BIT(21)
#define SRAM_GPU2D GENMASK_32(23, 22)
#define SRAM_GPU3D GENMASK_32(25, 24)
#define SRAM_HIFI4 BIT(26)
#define SRAM_ISI_BUFFER BIT(27)
#define SRAM_MIPI_CSI_FIFO BIT(28)
#define SRAM_MIPI_DSI_FIFO BIT(29)
#define SRAM_PXP BIT(30)
#define SRAM_DMA0 BIT_64(33)
#define SRAM_FLEXCAN BIT_64(34)
#define SRAM_FLEXSPI0 BIT_64(35)
#define SRAM_FLEXSPI1 BIT_64(36)
struct psw {
char *name;
uint32_t reg;
int power_state;
uint32_t count;
int flags;
};
#define ALWAYS_ON BIT(0)
static struct psw imx8ulp_psw[] = {
[PS6] = { .name = "PS6", .reg = PS6, .flags = ALWAYS_ON, .power_state = POWER_STATE_ON },
[PS7] = { .name = "PS7", .reg = PS7, .power_state = POWER_STATE_OFF },
[PS8] = { .name = "PS8", .reg = PS8, .power_state = POWER_STATE_OFF },
[PS13] = { .name = "PS13", .reg = PS13, .power_state = POWER_STATE_OFF },
[PS14] = { .name = "PS14", .reg = PS14, .flags = ALWAYS_ON, .power_state = POWER_STATE_OFF },
[PS15] = { .name = "PS15", .reg = PS15, .power_state = POWER_STATE_OFF },
[PS16] = { .name = "PS16", .reg = PS16, .flags = ALWAYS_ON, .power_state = POWER_STATE_ON },
};
struct power_domain {
char *name;
uint32_t reg;
uint32_t psw_parent;
uint32_t sram_parent;
uint64_t bits;
uint32_t power_state;
uint32_t sw_rst_reg; /* pcc sw reset reg offset */
};
/* The Rich OS need flow the macro */
#define IMX8ULP_PD_DMA1 0
#define IMX8ULP_PD_FLEXSPI2 1
#define IMX8ULP_PD_USB0 2
#define IMX8ULP_PD_USDHC0 3
#define IMX8ULP_PD_USDHC1 4
#define IMX8ULP_PD_USDHC2_USB1 5
#define IMX8ULP_PD_DCNANO 6
#define IMX8ULP_PD_EPDC 7
#define IMX8ULP_PD_DMA2 8
#define IMX8ULP_PD_GPU2D 9
#define IMX8ULP_PD_GPU3D 10
#define IMX8ULP_PD_HIFI4 11
#define IMX8ULP_PD_ISI 12
#define IMX8ULP_PD_MIPI_CSI 13
#define IMX8ULP_PD_MIPI_DSI 14
#define IMX8ULP_PD_PXP 15
#define IMX8ULP_PD_PS6 16
#define IMX8ULP_PD_PS7 17
#define IMX8ULP_PD_PS8 18
#define IMX8ULP_PD_PS13 19
#define IMX8ULP_PD_PS14 20
#define IMX8ULP_PD_PS15 21
#define IMX8ULP_PD_PS16 22
#define IMX8ULP_PD_MAX 23
/* LPAV peripheral PCC */
#define PCC_GPU2D (IMX_PCC5_BASE + 0xf0)
#define PCC_GPU3D (IMX_PCC5_BASE + 0xf4)
#define PCC_EPDC (IMX_PCC5_BASE + 0xcc)
#define PCC_CSI (IMX_PCC5_BASE + 0xbc)
#define PCC_PXP (IMX_PCC5_BASE + 0xd0)
#define PCC_SW_RST BIT(28)
#define PWR_DOMAIN(_name, _reg, _psw_parent, _sram_parent, \
_bits, _state, _rst_reg) \
{ \
.name = _name, \
.reg = _reg, \
.psw_parent = _psw_parent, \
.sram_parent = _sram_parent, \
.bits = _bits, \
.power_state = _state, \
.sw_rst_reg = _rst_reg, \
}
static struct power_domain scmi_power_domains[] = {
PWR_DOMAIN("DMA1", IMX8ULP_PD_DMA1, PS6, PS6, SRAM_DMA1, POWER_STATE_OFF, 0U),
PWR_DOMAIN("FLEXSPI2", IMX8ULP_PD_FLEXSPI2, PS6, PS6, SRAM_FLEXSPI2, POWER_STATE_OFF, 0U),
PWR_DOMAIN("USB0", IMX8ULP_PD_USB0, PS6, PS6, SRAM_USB0, POWER_STATE_OFF, 0U),
PWR_DOMAIN("USDHC0", IMX8ULP_PD_USDHC0, PS6, PS6, SRAM_USDHC0, POWER_STATE_OFF, 0U),
PWR_DOMAIN("USDHC1", IMX8ULP_PD_USDHC1, PS6, PS6, SRAM_USDHC1, POWER_STATE_OFF, 0U),
PWR_DOMAIN("USDHC2_USB1", IMX8ULP_PD_USDHC2_USB1, PS6, PS6, SRAM_USDHC2_USB1, POWER_STATE_OFF, 0U),
PWR_DOMAIN("DCNano", IMX8ULP_PD_DCNANO, PS16, PS16, SRAM_DCNANO, POWER_STATE_OFF, 0U),
PWR_DOMAIN("EPDC", IMX8ULP_PD_EPDC, PS13, PS13, SRAM_EPDC, POWER_STATE_OFF, PCC_EPDC),
PWR_DOMAIN("DMA2", IMX8ULP_PD_DMA2, PS16, PS16, SRAM_DMA2, POWER_STATE_OFF, 0U),
PWR_DOMAIN("GPU2D", IMX8ULP_PD_GPU2D, PS16, PS16, SRAM_GPU2D, POWER_STATE_OFF, PCC_GPU2D),
PWR_DOMAIN("GPU3D", IMX8ULP_PD_GPU3D, PS7, PS7, SRAM_GPU3D, POWER_STATE_OFF, PCC_GPU3D),
PWR_DOMAIN("HIFI4", IMX8ULP_PD_HIFI4, PS8, PS8, SRAM_HIFI4, POWER_STATE_OFF, 0U),
PWR_DOMAIN("ISI", IMX8ULP_PD_ISI, PS16, PS16, SRAM_ISI_BUFFER, POWER_STATE_OFF, 0U),
PWR_DOMAIN("MIPI_CSI", IMX8ULP_PD_MIPI_CSI, PS15, PS16, SRAM_MIPI_CSI_FIFO, POWER_STATE_OFF, PCC_CSI),
PWR_DOMAIN("MIPI_DSI", IMX8ULP_PD_MIPI_DSI, PS14, PS16, SRAM_MIPI_DSI_FIFO, POWER_STATE_OFF, 0U),
PWR_DOMAIN("PXP", IMX8ULP_PD_PXP, PS13, PS13, SRAM_PXP | SRAM_EPDC, POWER_STATE_OFF, PCC_PXP)
};
size_t plat_scmi_pd_count(unsigned int agent_id __unused)
{
return ARRAY_SIZE(scmi_power_domains);
}
const char *plat_scmi_pd_get_name(unsigned int agent_id __unused,
unsigned int pd_id)
{
if (pd_id >= IMX8ULP_PD_PS6) {
return imx8ulp_psw[pd_id - IMX8ULP_PD_PS6].name;
}
return scmi_power_domains[pd_id].name;
}
unsigned int plat_scmi_pd_get_state(unsigned int agent_id __unused,
unsigned int pd_id __unused)
{
if (pd_id >= IMX8ULP_PD_PS6) {
return imx8ulp_psw[pd_id - IMX8ULP_PD_PS6].power_state;
}
return scmi_power_domains[pd_id].power_state;
}
extern void upower_wait_resp(void);
int upwr_pwm_power(const uint32_t swton[], const uint32_t memon[], bool on)
{
int ret_val;
int ret;
if (on == true) {
ret = upwr_pwm_power_on(swton, memon, NULL);
} else {
ret = upwr_pwm_power_off(swton, memon, NULL);
}
if (ret != 0U) {
WARN("%s failed: ret: %d, state: %x\n", __func__, ret, on);
return ret;
}
upower_wait_resp();
ret = upwr_poll_req_status(UPWR_SG_PWRMGMT, NULL, NULL, &ret_val, 1000);
if (ret != UPWR_REQ_OK) {
WARN("Failure %d, %s\n", ret, __func__);
if (ret == UPWR_REQ_BUSY) {
return -EBUSY;
} else {
return -EINVAL;
}
}
return 0;
}
int32_t plat_scmi_pd_psw(unsigned int index, unsigned int state)
{
uint32_t psw_parent = scmi_power_domains[index].psw_parent;
uint32_t sram_parent = scmi_power_domains[index].sram_parent;
uint64_t swt;
bool on;
int ret = 0;
if ((imx8ulp_psw[psw_parent].flags & ALWAYS_ON) != 0U &&
(imx8ulp_psw[sram_parent].flags & ALWAYS_ON) != 0U) {
return 0;
}
on = (state == POWER_STATE_ON) ? true : false;
if ((imx8ulp_psw[psw_parent].flags & ALWAYS_ON) == 0U) {
swt = 1 << imx8ulp_psw[psw_parent].reg;
if (imx8ulp_psw[psw_parent].count == 0U) {
if (on == false) {
WARN("off PSW[%d] that already in off state\n", psw_parent);
ret = -EACCES;
} else {
ret = upwr_pwm_power((const uint32_t *)&swt, NULL, on);
imx8ulp_psw[psw_parent].count++;
}
} else {
if (on == true) {
imx8ulp_psw[psw_parent].count++;
} else {
imx8ulp_psw[psw_parent].count--;
}
if (imx8ulp_psw[psw_parent].count == 0U) {
ret = upwr_pwm_power((const uint32_t *)&swt, NULL, on);
}
}
}
if (!(imx8ulp_psw[sram_parent].flags & ALWAYS_ON) && (psw_parent != sram_parent)) {
swt = 1 << imx8ulp_psw[sram_parent].reg;
if (imx8ulp_psw[sram_parent].count == 0U) {
if (on == false) {
WARN("off PSW[%d] that already in off state\n", sram_parent);
ret = -EACCES;
} else {
ret = upwr_pwm_power((const uint32_t *)&swt, NULL, on);
imx8ulp_psw[sram_parent].count++;
}
} else {
if (on == true) {
imx8ulp_psw[sram_parent].count++;
} else {
imx8ulp_psw[sram_parent].count--;
}
if (imx8ulp_psw[sram_parent].count == 0U) {
ret = upwr_pwm_power((const uint32_t *)&swt, NULL, on);
}
}
}
return ret;
}
void assert_pcc_reset(unsigned int pcc)
{
/* if sw_rst_reg is valid, assert the pcc reset */
if (pcc != 0U) {
mmio_clrbits_32(pcc, PCC_SW_RST);
}
}
int32_t plat_scmi_pd_set_state(unsigned int agent_id __unused,
unsigned int flags,
unsigned int pd_id,
unsigned int state)
{
unsigned int ps_idx;
uint64_t mem;
bool on;
int ret;
if (flags != 0U || pd_id >= IMX8ULP_PD_PS6) {
return SCMI_NOT_SUPPORTED;
}
ps_idx = 0;
while (ps_idx < IMX8ULP_PD_PS6 && scmi_power_domains[ps_idx].reg != pd_id) {
ps_idx++;
}
if (ps_idx == IMX8ULP_PD_PS6) {
return SCMI_NOT_FOUND;
}
if (state == scmi_power_domains[ps_idx].power_state) {
return SCMI_SUCCESS;
}
mem = scmi_power_domains[ps_idx].bits;
on = (state == POWER_STATE_ON ? true : false);
if (on == true) {
/* Assert pcc sw reset if necessary */
assert_pcc_reset(scmi_power_domains[ps_idx].sw_rst_reg);
ret = plat_scmi_pd_psw(ps_idx, state);
if (ret != 0U) {
return SCMI_DENIED;
}
ret = upwr_pwm_power(NULL, (const uint32_t *)&mem, on);
if (ret != 0U) {
return SCMI_DENIED;
}
} else {
ret = upwr_pwm_power(NULL, (const uint32_t *)&mem, on);
if (ret != 0U) {
return SCMI_DENIED;
}
ret = plat_scmi_pd_psw(ps_idx, state);
if (ret != 0U) {
return SCMI_DENIED;
}
}
scmi_power_domains[pd_id].power_state = state;
return SCMI_SUCCESS;
}

View file

@ -0,0 +1,85 @@
/*
* Copyright 2021-2024 NXP
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <lib/libc/errno.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "../../../drivers/scmi-msg/sensor.h"
#include <common/debug.h>
#include <drivers/scmi.h>
#include <lib/mmio.h>
#include <lib/utils_def.h>
#include <scmi.h>
#include <upower_api.h>
/* Only Temperature now */
static uint16_t imx_scmi_sensor_count(unsigned int agent_id __unused)
{
return 1U;
}
uint8_t imx_scmi_sensor_max_requests(unsigned int agent_id __unused)
{
return 1U;
}
extern int upower_read_temperature(uint32_t sensor_id, int32_t *temperature);
int imx_scmi_sensor_reading_get(uint32_t agent_id __unused, uint16_t sensor_id __unused,
uint32_t *val)
{
int32_t temperature;
int ret;
ret = upower_read_temperature(1, &temperature);
if (ret != 0U) {
val[0] = 0xFFFFFFFF;
} else {
val[0] = temperature;
}
val[1] = 0;
val[2] = 0;
val[3] = 0;
return ret;
}
#define SCMI_SENSOR_NAME_LENGTH_MAX 16U
uint32_t imx_scmi_sensor_state(uint32_t agent_id __unused, uint16_t sensor_id __unused)
{
return 1U;
}
uint32_t imx_scmi_sensor_description_get(uint32_t agent_id __unused, uint16_t desc_index __unused,
struct scmi_sensor_desc *desc __unused)
{
desc->id = 0;
desc->attr_low = 0;
desc->attr_high = 2;
strlcpy((char *)desc->name, "UPOWER-TEMP", 12);
desc->power = 0;
desc->resolution = 0;
desc->min_range_low = 0;
desc->min_range_high = 0x80000000;
desc->max_range_low = 0xffffffff;
desc->max_range_high = 0x7fffffff;
return 1U;
}
REGISTER_SCMI_SENSOR_OPS(imx_scmi_sensor_count,
imx_scmi_sensor_max_requests,
NULL,
imx_scmi_sensor_reading_get,
imx_scmi_sensor_description_get,
NULL,
imx_scmi_sensor_state,
NULL);

View file

@ -0,0 +1,279 @@
/*
* Copyright 2021-2024 NXP
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef MU_H
#define MU_H
#include <stdint.h>
typedef volatile unsigned int vuint32_t;
/****************************************************************************/
/* MODULE: Message Unit */
/****************************************************************************/
/* VER Register */
typedef union {
vuint32_t R;
struct {
vuint32_t FEATURE : 16;
vuint32_t MINOR : 8;
vuint32_t MAJOR : 8;
} B;
} MU_VER_t;
/* PAR Register */
typedef union {
vuint32_t R;
struct {
vuint32_t TR_NUM : 8;
vuint32_t RR_NUM : 8;
vuint32_t GIR_NUM : 8;
vuint32_t FLAG_WIDTH : 8;
} B;
} MU_PAR_t;
/* CR Register */
typedef union {
vuint32_t R;
struct {
vuint32_t MUR : 1;
vuint32_t MURIE : 1;
vuint32_t rsrv_1 : 30;
} B;
} MU_CR_t;
/* SR Register */
typedef union {
vuint32_t R;
struct {
vuint32_t MURS : 1;
vuint32_t MURIP : 1;
vuint32_t EP : 1;
vuint32_t FUP : 1;
vuint32_t GIRP : 1;
vuint32_t TEP : 1;
vuint32_t RFP : 1;
vuint32_t CEP : 1;
vuint32_t rsrv_1 : 24;
} B;
} MU_SR_t;
/* CCR0 Register */
typedef union {
vuint32_t R;
struct {
vuint32_t NMI : 1;
vuint32_t HR : 1;
vuint32_t HRM : 1;
vuint32_t CLKE : 1;
vuint32_t RSTH : 1;
vuint32_t BOOT : 2;
vuint32_t rsrv_1 : 25;
} B;
} MU_CCR0_t;
/* CIER0 Register */
typedef union {
vuint32_t R;
struct {
vuint32_t rsrv_1 : 1;
vuint32_t HRIE : 1;
vuint32_t RUNIE : 1;
vuint32_t RAIE : 1;
vuint32_t HALTIE : 1;
vuint32_t WAITIE : 1;
vuint32_t STOPIE : 1;
vuint32_t PDIE : 1;
vuint32_t rsrv_2 : 24;
} B;
} MU_CIER0_t;
/* CSSR0 Register */
typedef union {
vuint32_t R;
struct {
vuint32_t NMIC : 1;
vuint32_t HRIP : 1;
vuint32_t RUN : 1;
vuint32_t RAIP : 1;
vuint32_t HALT : 1;
vuint32_t WAIT : 1;
vuint32_t STOP : 1;
vuint32_t PD : 1;
vuint32_t rsrv_1 : 24;
} B;
} MU_CSSR0_t;
/* CSR0 Register */
typedef union {
vuint32_t R;
struct {
vuint32_t rsrv_1 : 1;
vuint32_t HRIP : 1;
vuint32_t RUN : 1;
vuint32_t RAIP : 1;
vuint32_t HALT : 1;
vuint32_t WAIT : 1;
vuint32_t STOP : 1;
vuint32_t PD : 1;
vuint32_t rsrv_2 : 24;
} B;
} MU_CSR0_t;
/* FCR Register */
typedef union {
vuint32_t R;
struct {
vuint32_t F0 : 1;
vuint32_t F1 : 1;
vuint32_t F2 : 1;
vuint32_t rsrv_1 : 29;
} B;
} MU_FCR_t;
/* FSR Register */
typedef union {
vuint32_t R;
struct {
vuint32_t F0 : 1;
vuint32_t F1 : 1;
vuint32_t F2 : 1;
vuint32_t rsrv_1 : 29;
} B;
} MU_FSR_t;
/* GIER Register */
typedef union {
vuint32_t R;
struct {
vuint32_t GIE0 : 1;
vuint32_t GIE1 : 1;
vuint32_t rsrv_1 : 30;
} B;
} MU_GIER_t;
/* GCR Register */
typedef union {
vuint32_t R;
struct {
vuint32_t GIR0 : 1;
vuint32_t GIR1 : 1;
vuint32_t rsrv_1 : 30;
} B;
} MU_GCR_t;
/* GSR Register */
typedef union {
vuint32_t R;
struct {
vuint32_t GIP0 : 1;
vuint32_t GIP1 : 1;
vuint32_t rsrv_1 : 30;
} B;
} MU_GSR_t;
/* TCR Register */
typedef union{
vuint32_t R;
struct {
vuint32_t TIE0 : 1;
vuint32_t TIE1 : 1;
vuint32_t rsrv_1 : 30;
} B;
} MU_TCR_t;
/* TSR Register */
typedef union {
vuint32_t R;
struct {
vuint32_t TE0 : 1;
vuint32_t TE1 : 1;
vuint32_t rsrv_1 : 30;
} B;
} MU_TSR_t;
/* RCR Register */
typedef union {
vuint32_t R;
struct {
vuint32_t RIE0 : 1;
vuint32_t RIE1 : 1;
vuint32_t rsrv_1 : 30;
} B;
} MU_RCR_t;
/* RSR Register */
typedef union {
vuint32_t R;
struct {
vuint32_t RF0 : 1;
vuint32_t RF1 : 1;
vuint32_t rsrv_1 : 30;
} B;
} MU_RSR_t;
/* TR0 Register */
typedef union {
vuint32_t R;
struct {
vuint32_t TR_DATA : 32;
} B;
} MU_TR0_t;
/* TR1 Register */
typedef union {
vuint32_t R;
struct {
vuint32_t TR_DATA : 32;
} B;
} MU_TR1_t;
/* RR0 Register */
typedef union {
vuint32_t R;
struct {
vuint32_t RR_DATA : 32;
} B;
} MU_RR0_t;
/* RR1 Register */
typedef union {
vuint32_t R;
struct {
vuint32_t RR_DATA : 32;
} B;
} MU_RR1_t;
struct MU_t {
MU_VER_t VER;
MU_PAR_t PAR;
MU_CR_t CR;
MU_SR_t SR;
MU_CCR0_t CCR0;
MU_CIER0_t CIER0;
MU_CSSR0_t CSSR0;
MU_CSR0_t CSR0;
uint8_t MU_reserved0[224];
MU_FCR_t FCR;
MU_FSR_t FSR;
uint8_t MU_reserved1[8];
MU_GIER_t GIER;
MU_GCR_t GCR;
MU_GSR_t GSR;
uint8_t MU_reserved2[4];
MU_TCR_t TCR;
MU_TSR_t TSR;
MU_RCR_t RCR;
MU_RSR_t RSR;
uint8_t MU_reserved3[208];
MU_TR0_t TR[2];
uint8_t MU_reserved4[120];
MU_RR0_t RR[2];
};
#endif /* MU_H */

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,742 @@
/* SPDX-License-Identifier: BSD-3-Clause */
/**
* Copyright 2019-2024 NXP
*
* KEYWORDS: micro-power uPower driver API
* -----------------------------------------------------------------------------
* PURPOSE: uPower driver API #defines and typedefs shared with the firmware
* -----------------------------------------------------------------------------
* PARAMETERS:
* PARAM NAME RANGE:DESCRIPTION: DEFAULTS: UNITS
* -----------------------------------------------------------------------------
* REUSE ISSUES: no reuse issues
*/
#ifndef UPWR_DEFS_H
#define UPWR_DEFS_H
#include <stdint.h>
#ifndef UPWR_PMC_SWT_WORDS
#define UPWR_PMC_SWT_WORDS (1U)
#endif
#ifndef UPWR_PMC_MEM_WORDS
#define UPWR_PMC_MEM_WORDS (2U)
#endif
/* ****************************************************************************
* DOWNSTREAM MESSAGES - COMMANDS/FUNCTIONS
* ****************************************************************************
*/
#define UPWR_SRVGROUP_BITS (4U)
#define UPWR_FUNCTION_BITS (4U)
#define UPWR_PWDOMAIN_BITS (4U)
#define UPWR_HEADER_BITS \
(UPWR_SRVGROUP_BITS + UPWR_FUNCTION_BITS + UPWR_PWDOMAIN_BITS)
#define UPWR_ARG_BITS (32U - UPWR_HEADER_BITS)
#if ((UPWR_ARG_BITS & 1U) > 0U)
#error "UPWR_ARG_BITS must be an even number"
#endif
#define UPWR_ARG64_BITS (64U - UPWR_HEADER_BITS)
#define UPWR_HALF_ARG_BITS (UPWR_ARG_BITS >> 1U)
#define UPWR_DUAL_OFFSET_BITS ((UPWR_ARG_BITS + 32U) >> 1U)
/*
* message header: header fields common to all downstream messages.
*/
struct upwr_msg_hdr {
uint32_t domain : UPWR_PWDOMAIN_BITS; /* power domain */
uint32_t srvgrp : UPWR_SRVGROUP_BITS; /* service group */
uint32_t function : UPWR_FUNCTION_BITS; /* function */
uint32_t arg : UPWR_ARG_BITS; /* function-specific argument */
};
/* generic 1-word downstream message format */
typedef union {
struct upwr_msg_hdr hdr;
uint32_t word; /* message first word */
} upwr_down_1w_msg;
/* generic 2-word downstream message format */
typedef struct {
struct upwr_msg_hdr hdr;
uint32_t word2; /* message second word */
} upwr_down_2w_msg;
/* message format for functions that receive a pointer/offset */
typedef struct {
struct upwr_msg_hdr hdr;
uint32_t ptr; /* config struct offset */
} upwr_pointer_msg;
/* message format for functions that receive 2 pointers/offsets */
typedef union {
struct upwr_msg_hdr hdr;
struct {
uint64_t rsv : UPWR_HEADER_BITS;
uint64_t ptr0 : UPWR_DUAL_OFFSET_BITS;
uint64_t ptr1 : UPWR_DUAL_OFFSET_BITS;
} ptrs;
} upwr_2pointer_msg;
#define UPWR_SG_EXCEPT (0U) /* 0 = exception */
#define UPWR_SG_PWRMGMT (1U) /* 1 = power management */
#define UPWR_SG_DELAYM (2U) /* 2 = delay measurement */
#define UPWR_SG_VOLTM (3U) /* 3 = voltage measurement */
#define UPWR_SG_CURRM (4U) /* 4 = current measurement */
#define UPWR_SG_TEMPM (5U) /* 5 = temperature measurement */
#define UPWR_SG_DIAG (6U) /* 6 = diagnostic */
#define UPWR_SG_COUNT (7U)
typedef uint32_t upwr_sg_t;
/* *************************************************************************
* Initialization - downstream
***************************************************************************/
typedef upwr_down_1w_msg upwr_start_msg; /* start command message */
typedef upwr_down_1w_msg upwr_power_on_msg; /* power on command message */
typedef upwr_down_1w_msg upwr_boot_start_msg; /* boot start command message */
typedef union {
struct upwr_msg_hdr hdr;
upwr_power_on_msg power_on;
upwr_boot_start_msg boot_start;
upwr_start_msg start;
} upwr_startup_down_msg;
/* *************************************************************************
* Service Group EXCEPTION - downstream
***************************************************************************/
#define UPWR_XCP_INIT (0U) /* 0 = init msg (not a service request itself) */
#define UPWR_XCP_PING (0U) /* 0 = also ping request, since its response isan init msg */
#define UPWR_XCP_START (1U) /* 1 = service start: upwr_start *(not a service request itself) */
#define UPWR_XCP_SHUTDOWN (2U) /* 2 = service shutdown: upwr_xcp_shutdown */
#define UPWR_XCP_CONFIG (3U) /* 3 = uPower configuration: upwr_xcp_config */
#define UPWR_XCP_SW_ALARM (4U) /* 4 = uPower software alarm: upwr_xcp_sw_alarm */
#define UPWR_XCP_I2C (5U) /* 5 = I2C access: upwr_xcp_i2c_access */
#define UPWR_XCP_SPARE_6 (6U) /* 6 = spare */
#define UPWR_XCP_SET_DDR_RETN (7U) /* 7 = set/clear ddr retention */
#define UPWR_XCP_SET_RTD_APD_LLWU (8U) /* 8 = set/clear rtd/apd llwu */
#define UPWR_XCP_SPARE_8 (8U) /* 8 = spare */
#define UPWR_XCP_SET_RTD_USE_DDR (9U) /* 9 = M33 core set it is using DDR or not */
#define UPWR_XCP_SPARE_9 (9U) /* 9 = spare */
#define UPWR_XCP_SPARE_10 (10U) /* 10 = spare */
#define UPWR_XCP_SET_MIPI_DSI_ENA (10U) /* 10 = set/clear mipi dsi ena */
#define UPWR_XCP_SPARE_11 (11U) /* 11 = spare */
#define UPWR_XCP_GET_MIPI_DSI_ENA (11U) /* 11 = get mipi dsi ena status */
#define UPWR_XCP_SPARE_12 (12U) /* 12 = spare */
#define UPWR_XCP_SET_OSC_MODE (12U) /* 12 = set uPower OSC mode, high or low */
#define UPWR_XCP_SPARE_13 (13U) /* 13 = spare */
#define UPWR_XCP_SPARE_14 (14U) /* 14 = spare */
#define UPWR_XCP_SPARE_15 (15U) /* 15 = spare */
#define UPWR_XCP_F_COUNT (16U)
typedef uint32_t upwr_xcp_f_t;
typedef upwr_down_1w_msg upwr_xcp_ping_msg;
typedef upwr_down_1w_msg upwr_xcp_shutdown_msg;
typedef upwr_power_on_msg upwr_xcp_power_on_msg;
typedef upwr_boot_start_msg upwr_xcp_boot_start_msg;
typedef upwr_start_msg upwr_xcp_start_msg;
typedef upwr_down_2w_msg upwr_xcp_config_msg;
typedef upwr_down_1w_msg upwr_xcp_swalarm_msg;
typedef upwr_down_1w_msg upwr_xcp_ddr_retn_msg;
typedef upwr_down_1w_msg upwr_xcp_set_mipi_dsi_ena_msg;
typedef upwr_down_1w_msg upwr_xcp_get_mipi_dsi_ena_msg;
typedef upwr_down_1w_msg upwr_xcp_rtd_use_ddr_msg;
typedef upwr_down_1w_msg upwr_xcp_rtd_apd_llwu_msg;
typedef upwr_down_1w_msg upwr_xcp_set_osc_mode_msg;
typedef upwr_pointer_msg upwr_xcp_i2c_msg;
/* structure pointed by message upwr_xcp_i2c_msg */
typedef struct {
uint16_t addr;
int8_t data_size;
uint8_t subaddr_size;
uint32_t subaddr;
uint32_t data;
} upwr_i2c_access;
/* Exception all messages */
typedef union {
struct upwr_msg_hdr hdr; /* message header */
upwr_xcp_ping_msg ping; /* ping */
upwr_xcp_start_msg start; /* service start */
upwr_xcp_shutdown_msg shutdown; /* shutdown */
upwr_xcp_boot_start_msg bootstart; /* boot start */
upwr_xcp_config_msg config; /* uPower configuration */
upwr_xcp_swalarm_msg swalarm; /* software alarm */
upwr_xcp_i2c_msg i2c; /* I2C access */
upwr_xcp_ddr_retn_msg set_ddr_retn; /* set ddr retention msg */
upwr_xcp_set_mipi_dsi_ena_msg set_mipi_dsi_ena; /* set mipi dsi ena msg */
upwr_xcp_get_mipi_dsi_ena_msg get_mipi_dsi_ena; /* get mipi dsi ena msg */
upwr_xcp_rtd_use_ddr_msg set_rtd_use_ddr; /* set rtd is using ddr msg */
upwr_xcp_rtd_apd_llwu_msg set_llwu; /* set rtd/apd llwu msg */
upwr_xcp_set_osc_mode_msg set_osc_mode; /* set osc_mode msg */
} upwr_xcp_msg;
/* structure pointed by message upwr_volt_dva_req_id_msg */
typedef struct {
uint32_t id_word0;
uint32_t id_word1;
uint32_t mode;
} upwr_dva_id_struct;
/**
* PMIC voltage accuracy is 12.5 mV, 12500 uV
*/
#define PMIC_VOLTAGE_MIN_STEP 12500U
/* *************************************************************************
* Service Group POWER MANAGEMENT - downstream
***************************************************************************/
#define UPWR_PWM_REGCFG (0U) /* 0 = regulator config: upwr_pwm_reg_config */
#define UPWR_PWM_DEVMODE (0U) /* deprecated, for old compile */
#define UPWR_PWM_VOLT (1U) /* 1 = voltage change: upwr_pwm_chng_reg_voltage */
#define UPWR_PWM_SWITCH (2U) /* 2 = switch control: upwr_pwm_chng_switch_mem */
#define UPWR_PWM_PWR_ON (3U) /* 3 = switch/RAM/ROM power on: upwr_pwm_power_on */
#define UPWR_PWM_PWR_OFF (4U) /* 4 = switch/RAM/ROM power off: upwr_pwm_power_off */
#define UPWR_PWM_RETAIN (5U) /* 5 = retain memory array: upwr_pwm_mem_retain */
#define UPWR_PWM_DOM_BIAS (6U) /* 6 = Domain bias control: upwr_pwm_chng_dom_bias */
#define UPWR_PWM_MEM_BIAS (7U) /* 7 = Memory bias control: upwr_pwm_chng_mem_bias */
#define UPWR_PWM_PMICCFG (8U) /* 8 = PMIC configuration: upwr_pwm_pmic_config */
#define UPWR_PWM_PMICMOD (8U) /* deprecated, for old compile */
#define UPWR_PWM_PES (9U) /* 9 so far, no use */
#define UPWR_PWM_CONFIG (10U) /* 10= apply power mode defined configuration */
#define UPWR_PWM_CFGPTR (11U) /* 11= configuration pointer */
#define UPWR_PWM_DOM_PWRON (12U) /* 12 = domain power on: upwr_pwm_dom_power_on */
#define UPWR_PWM_BOOT (13U) /* 13 = boot start: upwr_pwm_boot_start */
#define UPWR_PWM_FREQ (14U) /* 14 = domain frequency setup */
#define UPWR_PWM_PARAM (15U) /* 15 = power management parameters */
#define UPWR_PWM_F_COUNT (16U)
typedef uint32_t upwr_pwm_f_t;
#define MAX_PMETER_SSEL 7U
#define UPWR_VTM_CHNG_PMIC_RAIL_VOLT (0U) /* 0 = change pmic rail voltage */
#define UPWR_VTM_GET_PMIC_RAIL_VOLT (1U) /* 1 = get pmic rail voltage */
#define UPWR_VTM_PMIC_CONFIG (2U) /* 2 = configure PMIC IC */
#define UPWR_VTM_DVA_DUMP_INFO (3U) /* 3 = dump dva information */
#define UPWR_VTM_DVA_REQ_ID (4U) /* 4 = dva request ID array */
#define UPWR_VTM_DVA_REQ_DOMAIN (5U) /* 5 = dva request domain */
#define UPWR_VTM_DVA_REQ_SOC (6U) /* 6 = dva request the whole SOC */
#define UPWR_VTM_PMETER_MEAS (7U) /* 7 = pmeter measure */
#define UPWR_VTM_VMETER_MEAS (8U) /* 8 = vmeter measure */
#define UPWR_VTM_PMIC_COLD_RESET (9U) /* 9 = pmic cold reset */
#define UPWR_VTM_SET_DVFS_PMIC_RAIL (10U) /* 10 = set which domain use which pmic rail, for DVFS use */
#define UPWR_VTM_SET_PMIC_MODE (11U) /* 11 = set pmic mode */
#define UPWR_VTM_F_COUNT (16U)
typedef uint32_t upwr_volt_f_t;
#define VMETER_SEL_RTD 0U
#define VMETER_SEL_LDO 1U
#define VMETER_SEL_APD 2U
#define VMETER_SEL_AVD 3U
#define VMETER_SEL_MAX 3U
/**
* The total TSEL count is 256
*/
#define MAX_TEMP_TSEL 256U
/**
* Support 3 temperature sensor, sensor 0, 1, 2
*/
#define MAX_TEMP_SENSOR 2U
#define UPWR_TEMP_GET_CUR_TEMP (0U) /* 0 = get current temperature */
#define UPWR_TEMP_F_COUNT (1U)
typedef uint32_t upwr_temp_f_t;
#define UPWR_DMETER_GET_DELAY_MARGIN (0U) /* 0 = get delay margin */
#define UPWR_DMETER_SET_DELAY_MARGIN (1U) /* 1 = set delay margin */
#define UPWR_PMON_REQ (2U) /* 2 = process monitor service */
#define UPWR_DMETER_F_COUNT (3U)
typedef uint32_t upwr_dmeter_f_t;
typedef upwr_down_1w_msg upwr_volt_pmeter_meas_msg;
typedef upwr_down_1w_msg upwr_volt_pmic_set_mode_msg;
typedef upwr_down_1w_msg upwr_volt_vmeter_meas_msg;
struct upwr_reg_config_t {
uint32_t reg;
};
/* set of 32 switches */
struct upwr_switch_board_t {
uint32_t on; /* Switch on state,1 bit per instance */
uint32_t mask; /* actuation mask, 1 bit per instance */
};
/* set of 32 RAM/ROM switches */
struct upwr_mem_switches_t {
uint32_t array; /* RAM/ROM array state, 1 bit per instance */
uint32_t perif; /* RAM/ROM peripheral state, 1 bit per instance */
uint32_t mask; /* actuation mask, 1 bit per instance */
};
typedef upwr_down_1w_msg upwr_pwm_dom_pwron_msg; /* domain power on message */
typedef upwr_down_1w_msg upwr_pwm_boot_start_msg; /* boot start message */
/* functions with complex arguments use the pointer message formats: */
typedef upwr_pointer_msg upwr_pwm_retain_msg;
typedef upwr_pointer_msg upwr_pwm_pmode_cfg_msg;
#if (UPWR_ARG_BITS < UPWR_DOMBIAS_ARG_BITS)
#if ((UPWR_ARG_BITS + 32) < UPWR_DOMBIAS_ARG_BITS)
#error "too few message bits for domain bias argument"
#endif
#endif
/* service upwr_pwm_chng_dom_bias message argument fields */
#define UPWR_DOMBIAS_MODE_BITS (2U)
#define UPWR_DOMBIAS_RBB_BITS (8U)
#define UPWR_DOMBIAS_RSV_BITS (14U)
#define UPWR_DOMBIAS_ARG_BITS (UPWR_DOMBIAS_RSV_BITS + \
(2U * UPWR_DOMBIAS_MODE_BITS) + \
(4U * UPWR_DOMBIAS_RBB_BITS) + 2U)
/*
* upwr_pwm_dom_bias_args is an SoC-dependent message,
*/
typedef struct {
uint32_t: 12U; /* TODO: find a way to use UPWR_HEADER_BITS */
uint32_t dommode : UPWR_DOMBIAS_MODE_BITS;
uint32_t avdmode : UPWR_DOMBIAS_MODE_BITS;
uint32_t domapply : 1U;
uint32_t avdapply : 1U;
uint32_t rsv : UPWR_DOMBIAS_RSV_BITS;
uint32_t domrbbn : UPWR_DOMBIAS_RBB_BITS; /* RTD/APD back bias N-well */
uint32_t domrbbp : UPWR_DOMBIAS_RBB_BITS; /* RTD/APD back bias P-well */
uint32_t avdrbbn : UPWR_DOMBIAS_RBB_BITS; /* AVD back bias N-well */
uint32_t avdrbbp : UPWR_DOMBIAS_RBB_BITS; /* AVD back bias P-well */
} upwr_pwm_dom_bias_args;
typedef union {
struct upwr_msg_hdr hdr; /* message header */
struct {
upwr_pwm_dom_bias_args B;
} args;
} upwr_pwm_dom_bias_msg;
/* service upwr_pwm_chng_mem_bias message argument fields */
/*
* upwr_pwm_mem_bias_args is an SoC-dependent message,
* defined in upower_soc_defs.h
*/
typedef struct {
uint32_t: 12U; /* TODO: find a way to use UPWR_HEADER_BITS */
uint32_t en : 1U;
uint32_t rsv : 19U;
} upwr_pwm_mem_bias_args;
typedef union {
struct upwr_msg_hdr hdr; /* message header */
struct {
upwr_pwm_mem_bias_args B;
} args;
} upwr_pwm_mem_bias_msg;
typedef upwr_pointer_msg upwr_pwm_pes_seq_msg;
/* upwr_pwm_reg_config-specific message format */
typedef upwr_pointer_msg upwr_pwm_regcfg_msg;
/* upwr_volt_pmic_volt-specific message format */
typedef union {
struct upwr_msg_hdr hdr; /* message header */
struct {
uint32_t rsv : UPWR_HEADER_BITS;
uint32_t domain : 8U;
uint32_t rail : 8U;
} args;
} upwr_volt_dom_pmic_rail_msg;
typedef union {
struct upwr_msg_hdr hdr;
struct {
uint32_t rsv : UPWR_HEADER_BITS;
uint32_t rail : 4U; /* pmic rail id */
uint32_t volt : 12U; /* voltage value, accurate to mV, support 0~3.3V */
} args;
} upwr_volt_pmic_set_volt_msg;
typedef union {
struct upwr_msg_hdr hdr;
struct {
uint32_t rsv : UPWR_HEADER_BITS;
uint32_t rail : 16U; /* pmic rail id */
} args;
} upwr_volt_pmic_get_volt_msg;
typedef union {
struct upwr_msg_hdr hdr;
struct {
uint32_t rsv :UPWR_HEADER_BITS;
uint32_t domain : 8U;
uint32_t mode : 8U; /* work mode */
} args;
} upwr_volt_dva_req_domain_msg;
typedef union {
struct upwr_msg_hdr hdr;
struct {
uint32_t rsv : UPWR_HEADER_BITS;
uint32_t mode : 16U; /* work mode */
} args;
} upwr_volt_dva_req_soc_msg;
typedef union {
struct upwr_msg_hdr hdr;
struct {
uint32_t rsv : UPWR_HEADER_BITS;
uint32_t addr_offset : 16U; /* addr_offset to 0x28330000 */
} args;
} upwr_volt_dva_dump_info_msg;
typedef upwr_pointer_msg upwr_volt_pmiccfg_msg;
typedef upwr_pointer_msg upwr_volt_dva_req_id_msg;
typedef upwr_down_1w_msg upwr_volt_pmic_cold_reset_msg;
/* upwr_pwm_volt-specific message format */
typedef union {
struct upwr_msg_hdr hdr;
struct {
uint32_t rsv : UPWR_HEADER_BITS;
uint32_t reg : UPWR_HALF_ARG_BITS; /* regulator id */
uint32_t volt : UPWR_HALF_ARG_BITS; /* voltage value */
} args;
} upwr_pwm_volt_msg;
/* upwr_pwm_freq_setup-specific message format */
/**
* DVA adjust stage
*/
#define DVA_ADJUST_STAGE_INVALID 0U
/* first stage, gross adjust, for increase frequency use */
#define DVA_ADJUST_STAGE_ONE 1U
/* second stage, fine adjust for increase frequency use */
#define DVA_ADJUST_STAGE_TWO 2U
/* combine first + second stage, for descrese frequency use */
#define DVA_ADJUST_STAGE_FULL 3U
/**
* This message structure is used for DVFS feature
* 1. Because user may use different PMIC or different board,
* the pmic regulator of RTD/APD may change,
* so, user need to tell uPower the regulator number.
* The number must be matched with PMIC IC and board.
* use 4 bits for pmic regulator, support to 16 regulator.
*
* use 2 bits for DVA stage
*
* use 10 bits for target frequency, accurate to MHz, support to 1024 MHz
*/
typedef union {
struct upwr_msg_hdr hdr;
struct {
uint32_t rsv : UPWR_HEADER_BITS;
uint32_t rail : 4; /* pmic regulator */
uint32_t stage : 2; /* DVA stage */
uint32_t target_freq : 10; /* target frequency */
} args;
} upwr_pwm_freq_msg;
typedef upwr_down_2w_msg upwr_pwm_param_msg;
/* upwr_pwm_pmiccfg-specific message format */
typedef upwr_pointer_msg upwr_pwm_pmiccfg_msg;
/* functions that pass a pointer use message format upwr_pointer_msg */
typedef upwr_pointer_msg upwr_pwm_cfgptr_msg;
/* functions that pass 2 pointers use message format upwr_2pointer_msg
*/
typedef upwr_2pointer_msg upwr_pwm_switch_msg;
typedef upwr_2pointer_msg upwr_pwm_pwron_msg;
typedef upwr_2pointer_msg upwr_pwm_pwroff_msg;
/* Power Management all messages */
typedef union {
struct upwr_msg_hdr hdr; /* message header */
upwr_pwm_param_msg param; /* power management parameters */
upwr_pwm_dom_bias_msg dom_bias; /* domain bias message */
upwr_pwm_mem_bias_msg mem_bias; /* memory bias message */
upwr_pwm_pes_seq_msg pes; /* PE seq. message */
upwr_pwm_pmode_cfg_msg pmode; /* power mode config message */
upwr_pwm_regcfg_msg regcfg; /* regulator config message */
upwr_pwm_volt_msg volt; /* set voltage message */
upwr_pwm_freq_msg freq; /* set frequency message */
upwr_pwm_switch_msg switches; /* switch control message */
upwr_pwm_pwron_msg pwron; /* switch/RAM/ROM power on message */
upwr_pwm_pwroff_msg pwroff; /* switch/RAM/ROM power off message */
upwr_pwm_retain_msg retain; /* memory retain message */
upwr_pwm_cfgptr_msg cfgptr; /* configuration pointer message*/
upwr_pwm_dom_pwron_msg dompwron; /* domain power on message */
upwr_pwm_boot_start_msg boot; /* boot start message */
} upwr_pwm_msg;
typedef union {
struct upwr_msg_hdr hdr; /* message header */
upwr_volt_pmic_set_volt_msg set_pmic_volt; /* set pmic voltage message */
upwr_volt_pmic_get_volt_msg get_pmic_volt; /* set pmic voltage message */
upwr_volt_pmic_set_mode_msg set_pmic_mode; /* set pmic mode message */
upwr_volt_pmiccfg_msg pmiccfg; /* PMIC configuration message */
upwr_volt_dom_pmic_rail_msg dom_pmic_rail; /* domain bias message */
upwr_volt_dva_dump_info_msg dva_dump_info; /* dump dva info message */
upwr_volt_dva_req_id_msg dva_req_id; /* dump dva request id array message */
upwr_volt_dva_req_domain_msg dva_req_domain; /* dump dva request domain message */
upwr_volt_dva_req_soc_msg dva_req_soc; /* dump dva request whole soc message */
upwr_volt_pmeter_meas_msg pmeter_meas_msg; /* pmeter measure message */
upwr_volt_vmeter_meas_msg vmeter_meas_msg; /* vmeter measure message */
upwr_volt_pmic_cold_reset_msg cold_reset_msg; /* pmic cold reset message */
} upwr_volt_msg;
typedef union {
struct upwr_msg_hdr hdr;
struct {
uint32_t rsv : UPWR_HEADER_BITS;
uint32_t sensor_id : 16U; /* temperature sensor id */
} args;
} upwr_temp_get_cur_temp_msg;
typedef union {
struct upwr_msg_hdr hdr;
struct {
uint32_t rsv : UPWR_HEADER_BITS;
uint32_t index : 8U; /* the delay meter index */
uint32_t path : 8U; /* the critical path number */
} args;
} upwr_dmeter_get_delay_margin_msg;
#define MAX_DELAY_MARGIN 63U
#define MAX_DELAY_CRITICAL_PATH 7U
#define MAX_DELAY_METER_NUM 1U
typedef union {
struct upwr_msg_hdr hdr;
struct {
uint32_t rsv : UPWR_HEADER_BITS;
uint32_t index: 4U; /* the delay meter index */
uint32_t path: 4U; /* the critical path number */
uint32_t dm: 8U; /* the delay margin value of delay meter */
} args;
} upwr_dmeter_set_delay_margin_msg;
#define MAX_PMON_CHAIN_SEL 1U
typedef union {
struct upwr_msg_hdr hdr;
struct {
uint32_t rsv : UPWR_HEADER_BITS;
uint32_t chain_sel : 16U; /* the process monitor delay chain sel */
} args;
} upwr_pmon_msg;
typedef union {
struct upwr_msg_hdr hdr; /* message header */
upwr_temp_get_cur_temp_msg get_temp_msg; /* get current temperature message */
} upwr_temp_msg;
typedef union {
struct upwr_msg_hdr hdr; /* message header */
upwr_dmeter_get_delay_margin_msg get_margin_msg; /* get delay margin message */
upwr_dmeter_set_delay_margin_msg set_margin_msg; /* set delay margin message */
upwr_pmon_msg pmon_msg; /* process monitor message */
} upwr_dmeter_msg;
typedef upwr_down_2w_msg upwr_down_max_msg; /* longest downstream msg */
/*
* upwr_dom_bias_cfg_t and upwr_mem_bias_cfg_t are SoC-dependent structs,
* defined in upower_soc_defs.h
*/
/* Power and mem switches */
typedef struct {
volatile struct upwr_switch_board_t swt_board[UPWR_PMC_SWT_WORDS];
volatile struct upwr_mem_switches_t swt_mem[UPWR_PMC_MEM_WORDS];
} swt_config_t;
/* *************************************************************************
* Service Group DIAGNOSE - downstream
***************************************************************************/
/* Diagnose Functions */
#define UPWR_DGN_MODE (0U) /* 0 = diagnose mode: upwr_dgn_mode */
#define UPWR_DGN_F_COUNT (1U)
#define UPWR_DGN_BUFFER_EN (2U)
typedef uint32_t upwr_dgn_f_t;
#define UPWR_DGN_ALL2ERR (0U) /* record all until an error occurs, freeze recording on error */
#define UPWR_DGN_ALL2HLT (1U) /* record all until an error occurs, halt core on error */
#define UPWR_DGN_ALL (2U) /* trace, warnings, errors, task state recorded */
#define UPWR_DGN_MAX UPWR_DGN_ALL
#define UPWR_DGN_TRACE (3U) /* trace, warnings, errors recorded */
#define UPWR_DGN_SRVREQ (4U) /* service request activity recorded */
#define UPWR_DGN_WARN (5U) /* warnings and errors recorded */
#define UPWR_DGN_ERROR (6U) /* only errors recorded */
#define UPWR_DGN_NONE (7U) /* no diagnostic recorded */
#define UPWR_DGN_COUNT (8U)
typedef uint32_t upwr_dgn_mode_t;
typedef upwr_down_1w_msg upwr_dgn_mode_msg;
typedef union {
struct upwr_msg_hdr hdr;
upwr_dgn_mode_msg mode_msg;
} upwr_dgn_msg;
typedef struct {
struct upwr_msg_hdr hdr;
uint32_t buf_addr;
} upwr_dgn_v2_msg;
/* diagnostics log types in the shared RAM log buffer */
typedef enum {
DGN_LOG_NONE = 0x00000000,
DGN_LOG_INFO = 0x10000000,
DGN_LOG_ERROR = 0x20000000,
DGN_LOG_ASSERT = 0x30000000,
DGN_LOG_EXCEPT = 0x40000000,
DGN_LOG_EVENT = 0x50000000, // old event trace
DGN_LOG_EVENTNEW = 0x60000000, // new event trace
DGN_LOG_SERVICE = 0x70000000,
DGN_LOG_TASKDEF = 0x80000000,
DGN_LOG_TASKEXE = 0x90000000,
DGN_LOG_MUTEX = 0xA0000000,
DGN_LOG_SEMAPH = 0xB0000000,
DGN_LOG_TIMER = 0xC0000000,
DGN_LOG_CALLTRACE = 0xD0000000,
DGN_LOG_DATA = 0xE0000000,
DGN_LOG_PCTRACE = 0xF0000000
} upwr_dgn_log_t;
/* ****************************************************************************
* UPSTREAM MESSAGES - RESPONSES
* ****************************************************************************
*/
/* generic ok/ko response message */
#define UPWR_RESP_ERR_BITS (4U)
#define UPWR_RESP_HDR_BITS (UPWR_RESP_ERR_BITS+\
UPWR_SRVGROUP_BITS+UPWR_FUNCTION_BITS)
#define UPWR_RESP_RET_BITS (32U - UPWR_RESP_HDR_BITS)
#define UPWR_RESP_OK (0U) /* no error */
#define UPWR_RESP_SG_BUSY (1U) /* service group is busy */
#define UPWR_RESP_SHUTDOWN (2U) /* services not up or shutting down */
#define UPWR_RESP_BAD_REQ (3U) /* invalid request */
#define UPWR_RESP_BAD_STATE (4U) /* system state doesn't allow perform the request */
#define UPWR_RESP_UNINSTALLD (5U) /* service or function not installed */
#define UPWR_RESP_UNINSTALLED (5U) /* service or function not installed (alias) */
#define UPWR_RESP_RESOURCE (6U) /* resource not available */
#define UPWR_RESP_TIMEOUT (7U) /* service timeout */
#define UPWR_RESP_COUNT (8U)
typedef uint32_t upwr_resp_t;
struct upwr_resp_hdr {
uint32_t errcode : UPWR_RESP_ERR_BITS;
uint32_t srvgrp : UPWR_SRVGROUP_BITS; /* service group */
uint32_t function: UPWR_FUNCTION_BITS;
uint32_t ret : UPWR_RESP_RET_BITS; /* return value, if any */
};
/* generic 1-word upstream message format */
typedef union {
struct upwr_resp_hdr hdr;
uint32_t word;
} upwr_resp_msg;
/* generic 2-word upstream message format */
typedef struct {
struct upwr_resp_hdr hdr;
uint32_t word2; /* message second word */
} upwr_up_2w_msg;
typedef upwr_up_2w_msg upwr_up_max_msg;
/* *************************************************************************
* Exception/Initialization - upstream
***************************************************************************/
#define UPWR_SOC_BITS (7U)
#define UPWR_VMINOR_BITS (4U)
#define UPWR_VFIXES_BITS (4U)
#define UPWR_VMAJOR_BITS \
(32U - UPWR_HEADER_BITS - UPWR_SOC_BITS - UPWR_VMINOR_BITS - UPWR_VFIXES_BITS)
typedef struct {
uint32_t soc_id;
uint32_t vmajor;
uint32_t vminor;
uint32_t vfixes;
} upwr_code_vers_t;
/* message sent by firmware initialization, received by upwr_init */
typedef union {
struct upwr_resp_hdr hdr;
struct {
uint32_t rsv : UPWR_RESP_HDR_BITS;
uint32_t soc : UPWR_SOC_BITS; /* SoC identification */
uint32_t vmajor : UPWR_VMAJOR_BITS; /* firmware major version */
uint32_t vminor : UPWR_VMINOR_BITS; /* firmware minor version */
uint32_t vfixes : UPWR_VFIXES_BITS; /* firmware fixes version */
} args;
} upwr_init_msg;
/* message sent by firmware when the core platform is powered up */
typedef upwr_resp_msg upwr_power_up_msg;
/* message sent by firmware when the core reset is released for boot */
typedef upwr_resp_msg upwr_boot_up_msg;
/* message sent by firmware when ready for service requests */
#define UPWR_RAM_VMINOR_BITS (7)
#define UPWR_RAM_VFIXES_BITS (6)
#define UPWR_RAM_VMAJOR_BITS (32 - UPWR_HEADER_BITS \
- UPWR_RAM_VFIXES_BITS - UPWR_RAM_VMINOR_BITS)
typedef union {
struct upwr_resp_hdr hdr;
struct {
uint32_t rsv : UPWR_RESP_HDR_BITS;
uint32_t vmajor : UPWR_RAM_VMAJOR_BITS; /* RAM fw major version */
uint32_t vminor : UPWR_RAM_VMINOR_BITS; /* RAM fw minor version */
uint32_t vfixes : UPWR_RAM_VFIXES_BITS; /* RAM fw fixes version */
} args;
} upwr_ready_msg;
/* message sent by firmware when shutdown finishes */
typedef upwr_resp_msg upwr_shutdown_msg;
typedef union {
struct upwr_resp_hdr hdr;
upwr_init_msg init;
upwr_power_up_msg pwrup;
upwr_boot_up_msg booted;
upwr_ready_msg ready;
} upwr_startup_up_msg;
/* message sent by firmware for uPower config setting */
typedef upwr_resp_msg upwr_config_resp_msg;
/* message sent by firmware for uPower alarm */
typedef upwr_resp_msg upwr_alarm_resp_msg;
/* *************************************************************************
* Power Management - upstream
***************************************************************************/
typedef upwr_resp_msg upwr_param_resp_msg;
enum work_mode {
OVER_DRIVE,
NORMAL_DRIVE,
LOW_DRIVE
};
#define UTIMER3_MAX_COUNT 0xFFFFU
#endif /* UPWR_DEFS_H */

View file

@ -0,0 +1,147 @@
/*
* Copyright 2020-2024 NXP
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <errno.h>
#include <common/debug.h>
#include <drivers/delay_timer.h>
#include <lib/mmio.h>
#include "upower_api.h"
#include "upower_defs.h"
#define UPOWER_AP_MU1_ADDR U(0x29280000)
struct MU_t *muptr = (struct MU_t *)UPOWER_AP_MU1_ADDR;
void upower_apd_inst_isr(upwr_isr_callb txrx_isr,
upwr_isr_callb excp_isr)
{
/* Do nothing */
}
int upower_status(int status)
{
int ret = -1;
switch (status) {
case 0:
VERBOSE("finished successfully!\n");
ret = 0;
break;
case -1:
VERBOSE("memory allocation or resource failed!\n");
break;
case -2:
VERBOSE("invalid argument!\n");
break;
case -3:
VERBOSE("called in an invalid API state!\n");
break;
default:
VERBOSE("invalid return status\n");
break;
}
return ret;
}
void upower_wait_resp(void)
{
while (muptr->RSR.B.RF0 == 0) {
udelay(100);
}
upwr_txrx_isr();
}
static void user_upwr_rdy_callb(uint32_t soc, uint32_t vmajor, uint32_t vminor)
{
NOTICE("%s: soc=%x\n", __func__, soc);
NOTICE("%s: RAM version:%d.%d\n", __func__, vmajor, vminor);
}
int upower_init(void)
{
int status;
status = upwr_init(APD_DOMAIN, muptr, NULL, NULL, upower_apd_inst_isr, NULL);
if (upower_status(status)) {
ERROR("%s: upower init failure\n", __func__);
return -EINVAL;
}
NOTICE("%s: start uPower RAM service\n", __func__);
status = upwr_start(1, user_upwr_rdy_callb);
upower_wait_resp();
/* poll status */
if (upower_status(status)) {
NOTICE("%s: upower init failure\n", __func__);
return status;
}
return 0;
}
int upower_pwm(int domain_id, bool pwr_on)
{
int ret, ret_val;
uint32_t swt;
if (domain_id == 9U || domain_id == 11U || domain_id == 12U) {
swt = BIT_32(12) | BIT_32(11) | BIT_32(10) | BIT_32(9);
} else {
swt = BIT_32(domain_id);
}
if (pwr_on) {
ret = upwr_pwm_power_on(&swt, NULL, NULL);
} else {
ret = upwr_pwm_power_off(&swt, NULL, NULL);
}
if (ret) {
NOTICE("%s failed: ret: %d, pwr_on: %d\n", __func__, ret, pwr_on);
return ret;
}
upower_wait_resp();
ret = upwr_poll_req_status(UPWR_SG_PWRMGMT, NULL, NULL, &ret_val, 1000);
if (ret != UPWR_REQ_OK) {
NOTICE("Failure %d, %s\n", ret, __func__);
if (ret == UPWR_REQ_BUSY) {
return -EBUSY;
} else {
return -EINVAL;
}
}
return 0;
}
int upower_read_temperature(uint32_t sensor_id, int32_t *temperature)
{
int ret, ret_val;
upwr_resp_t err_code;
int64_t t;
ret = upwr_tpm_get_temperature(sensor_id, NULL);
if (ret) {
return ret;
}
upower_wait_resp();
ret = upwr_poll_req_status(UPWR_SG_TEMPM, NULL, &err_code, &ret_val, 1000);
if (ret > UPWR_REQ_OK) {
return ret;
}
t = ret_val & 0xff;
*temperature = (2673049 * t * t * t / 10000000 + 3734262 * t * t / 100000 +
4487042 * t / 100 - 4698694) / 100000;
return 0;
}

File diff suppressed because it is too large Load diff