Browse Source
This patch introduces dynamic configuration for SDEI setup and is supported when the new build flag SDEI_IN_FCONF is enabled. Instead of using C arrays and processing the configuration at compile time, the config is moved to dts files. It will be retrieved at runtime during SDEI init, using the fconf layer. Change-Id: If5c35a7517ba00a9f258d7f3e7c8c20cee169a31 Signed-off-by: Balint Dobszay <balint.dobszay@arm.com> Co-authored-by: Madhukar Pappireddy <madhukar.pappireddy@arm.com>pull/1979/head
Balint Dobszay
5 years ago
committed by
Madhukar Pappireddy
14 changed files with 303 additions and 52 deletions
@ -0,0 +1,31 @@ |
|||
/*
|
|||
* Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved. |
|||
* |
|||
* SPDX-License-Identifier: BSD-3-Clause |
|||
*/ |
|||
|
|||
#ifndef FCONF_SDEI_GETTER_H |
|||
#define FCONF_SDEI_GETTER_H |
|||
|
|||
#include <lib/fconf/fconf.h> |
|||
|
|||
#include <platform_def.h> |
|||
|
|||
#define sdei__dyn_config_getter(id) sdei_dyn_config.id |
|||
|
|||
struct sdei_dyn_config_t { |
|||
uint32_t private_ev_cnt; |
|||
int32_t private_ev_nums[PLAT_SDEI_DP_EVENT_MAX_CNT]; |
|||
unsigned int private_ev_intrs[PLAT_SDEI_DP_EVENT_MAX_CNT]; |
|||
unsigned int private_ev_flags[PLAT_SDEI_DP_EVENT_MAX_CNT]; |
|||
uint32_t shared_ev_cnt; |
|||
int32_t shared_ev_nums[PLAT_SDEI_DS_EVENT_MAX_CNT]; |
|||
unsigned int shared_ev_intrs[PLAT_SDEI_DS_EVENT_MAX_CNT]; |
|||
unsigned int shared_ev_flags[PLAT_SDEI_DS_EVENT_MAX_CNT]; |
|||
}; |
|||
|
|||
int fconf_populate_sdei_dyn_config(uintptr_t config); |
|||
|
|||
extern struct sdei_dyn_config_t sdei_dyn_config; |
|||
|
|||
#endif /* FCONF_SDEI_GETTER_H */ |
@ -0,0 +1,56 @@ |
|||
/*
|
|||
* Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. |
|||
* |
|||
* SPDX-License-Identifier: BSD-3-Clause |
|||
*/ |
|||
|
|||
#ifndef SDEI_FLAGS_H |
|||
#define SDEI_FLAGS_H |
|||
|
|||
#include <lib/utils_def.h> |
|||
|
|||
/* Internal: SDEI flag bit positions */ |
|||
#define SDEI_MAPF_DYNAMIC_SHIFT_ 1U |
|||
#define SDEI_MAPF_BOUND_SHIFT_ 2U |
|||
#define SDEI_MAPF_SIGNALABLE_SHIFT_ 3U |
|||
#define SDEI_MAPF_PRIVATE_SHIFT_ 4U |
|||
#define SDEI_MAPF_CRITICAL_SHIFT_ 5U |
|||
#define SDEI_MAPF_EXPLICIT_SHIFT_ 6U |
|||
|
|||
/* SDEI event 0 */ |
|||
#define SDEI_EVENT_0 0 |
|||
|
|||
/* Placeholder interrupt for dynamic mapping */ |
|||
#define SDEI_DYN_IRQ 0U |
|||
|
|||
/* SDEI flags */ |
|||
|
|||
/*
|
|||
* These flags determine whether or not an event can be associated with an |
|||
* interrupt. Static events are permanently associated with an interrupt, and |
|||
* can't be changed at runtime. Association of dynamic events with interrupts |
|||
* can be changed at run time using the SDEI_INTERRUPT_BIND and |
|||
* SDEI_INTERRUPT_RELEASE calls. |
|||
* |
|||
* SDEI_MAPF_DYNAMIC only indicates run time configurability, where as |
|||
* SDEI_MAPF_BOUND indicates interrupt association. For example: |
|||
* |
|||
* - Calling SDEI_INTERRUPT_BIND on a dynamic event will have both |
|||
* SDEI_MAPF_DYNAMIC and SDEI_MAPF_BOUND set. |
|||
* |
|||
* - Statically-bound events will always have SDEI_MAPF_BOUND set, and neither |
|||
* SDEI_INTERRUPT_BIND nor SDEI_INTERRUPT_RELEASE can be called on them. |
|||
* |
|||
* See also the is_map_bound() macro. |
|||
*/ |
|||
#define SDEI_MAPF_DYNAMIC BIT(SDEI_MAPF_DYNAMIC_SHIFT_) |
|||
#define SDEI_MAPF_BOUND BIT(SDEI_MAPF_BOUND_SHIFT_) |
|||
#define SDEI_MAPF_EXPLICIT BIT(SDEI_MAPF_EXPLICIT_SHIFT_) |
|||
|
|||
#define SDEI_MAPF_SIGNALABLE BIT(SDEI_MAPF_SIGNALABLE_SHIFT_) |
|||
#define SDEI_MAPF_PRIVATE BIT(SDEI_MAPF_PRIVATE_SHIFT_) |
|||
|
|||
#define SDEI_MAPF_NORMAL 0 |
|||
#define SDEI_MAPF_CRITICAL BIT(SDEI_MAPF_CRITICAL_SHIFT_) |
|||
|
|||
#endif /* SDEI_FLAGS_H */ |
@ -0,0 +1,103 @@ |
|||
/*
|
|||
* Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved. |
|||
* |
|||
* SPDX-License-Identifier: BSD-3-Clause |
|||
*/ |
|||
#include <assert.h> |
|||
|
|||
#include <common/debug.h> |
|||
#include <common/fdt_wrappers.h> |
|||
#include <libfdt.h> |
|||
#include <plat/arm/common/fconf_sdei_getter.h> |
|||
|
|||
#define PRIVATE_EVENT_NUM(i) private_events[3 * (i)] |
|||
#define PRIVATE_EVENT_INTR(i) private_events[3 * (i) + 1] |
|||
#define PRIVATE_EVENT_FLAGS(i) private_events[3 * (i) + 2] |
|||
|
|||
#define SHARED_EVENT_NUM(i) shared_events[3 * (i)] |
|||
#define SHARED_EVENT_INTR(i) shared_events[3 * (i) + 1] |
|||
#define SHARED_EVENT_FLAGS(i) shared_events[3 * (i) + 2] |
|||
|
|||
struct sdei_dyn_config_t sdei_dyn_config; |
|||
|
|||
int fconf_populate_sdei_dyn_config(uintptr_t config) |
|||
{ |
|||
uint32_t i; |
|||
int node, err; |
|||
uint32_t private_events[PLAT_SDEI_DP_EVENT_MAX_CNT * 3]; |
|||
uint32_t shared_events[PLAT_SDEI_DS_EVENT_MAX_CNT * 3]; |
|||
|
|||
const void *dtb = (void *)config; |
|||
|
|||
/* Check that the node offset points to compatible property */ |
|||
node = fdt_node_offset_by_compatible(dtb, -1, "arm,sdei-1.0"); |
|||
if (node < 0) { |
|||
ERROR("FCONF: Can't find 'arm,sdei-1.0' compatible node in dtb\n"); |
|||
return node; |
|||
} |
|||
|
|||
/* Read number of private mappings */ |
|||
err = fdt_read_uint32(dtb, node, "private_event_count", |
|||
&sdei_dyn_config.private_ev_cnt); |
|||
if (err < 0) { |
|||
ERROR("FCONF: Read cell failed for 'private_event_count': %u\n", |
|||
sdei_dyn_config.private_ev_cnt); |
|||
return err; |
|||
} |
|||
|
|||
/* Check if the value is in range */ |
|||
if (sdei_dyn_config.private_ev_cnt > PLAT_SDEI_DP_EVENT_MAX_CNT) { |
|||
ERROR("FCONF: Invalid value for 'private_event_count': %u\n", |
|||
sdei_dyn_config.private_ev_cnt); |
|||
return -1; |
|||
} |
|||
|
|||
/* Read private mappings */ |
|||
err = fdt_read_uint32_array(dtb, node, "private_events", |
|||
sdei_dyn_config.private_ev_cnt * 3, private_events); |
|||
if (err < 0) { |
|||
ERROR("FCONF: Read cell failed for 'private_events': %d\n", err); |
|||
return err; |
|||
} |
|||
|
|||
/* Move data to fconf struct */ |
|||
for (i = 0; i < sdei_dyn_config.private_ev_cnt; i++) { |
|||
sdei_dyn_config.private_ev_nums[i] = PRIVATE_EVENT_NUM(i); |
|||
sdei_dyn_config.private_ev_intrs[i] = PRIVATE_EVENT_INTR(i); |
|||
sdei_dyn_config.private_ev_flags[i] = PRIVATE_EVENT_FLAGS(i); |
|||
} |
|||
|
|||
/* Read number of shared mappings */ |
|||
err = fdt_read_uint32(dtb, node, "shared_event_count", |
|||
&sdei_dyn_config.shared_ev_cnt); |
|||
if (err < 0) { |
|||
ERROR("FCONF: Read cell failed for 'shared_event_count'\n"); |
|||
return err; |
|||
} |
|||
|
|||
/* Check if the value is in range */ |
|||
if (sdei_dyn_config.shared_ev_cnt > PLAT_SDEI_DS_EVENT_MAX_CNT) { |
|||
ERROR("FCONF: Invalid value for 'shared_event_count': %u\n", |
|||
sdei_dyn_config.shared_ev_cnt); |
|||
return -1; |
|||
} |
|||
|
|||
/* Read shared mappings */ |
|||
err = fdt_read_uint32_array(dtb, node, "shared_events", |
|||
sdei_dyn_config.shared_ev_cnt * 3, shared_events); |
|||
if (err < 0) { |
|||
ERROR("FCONF: Read cell failed for 'shared_events': %d\n", err); |
|||
return err; |
|||
} |
|||
|
|||
/* Move data to fconf struct */ |
|||
for (i = 0; i < sdei_dyn_config.shared_ev_cnt; i++) { |
|||
sdei_dyn_config.shared_ev_nums[i] = SHARED_EVENT_NUM(i); |
|||
sdei_dyn_config.shared_ev_intrs[i] = SHARED_EVENT_INTR(i); |
|||
sdei_dyn_config.shared_ev_flags[i] = SHARED_EVENT_FLAGS(i); |
|||
} |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
FCONF_REGISTER_POPULATOR(HW_CONFIG, sdei, fconf_populate_sdei_dyn_config); |
Loading…
Reference in new issue