123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621 |
- #include <assert.h>
- #include <stdbool.h>
- #include <arch.h>
- #include <common/debug.h>
- #include <drivers/arm/ccn.h>
- #include <lib/bakery_lock.h>
- #include <lib/mmio.h>
- #include "ccn_private.h"
- static const ccn_desc_t *ccn_plat_desc;
- #if defined(IMAGE_BL31) || (!defined(__aarch64__) && defined(IMAGE_BL32))
- DEFINE_BAKERY_LOCK(ccn_lock);
- #endif
- static inline unsigned long long ccn_reg_read(uintptr_t periphbase,
- unsigned int region_id,
- unsigned int register_offset)
- {
- uintptr_t region_base;
- assert(periphbase);
- assert(region_id < REGION_ID_LIMIT);
- region_base = periphbase + region_id_to_base(region_id);
- return mmio_read_64(region_base + register_offset);
- }
- static inline void ccn_reg_write(uintptr_t periphbase,
- unsigned int region_id,
- unsigned int register_offset,
- unsigned long long value)
- {
- uintptr_t region_base;
- assert(periphbase);
- assert(region_id < REGION_ID_LIMIT);
- region_base = periphbase + region_id_to_base(region_id);
- mmio_write_64(region_base + register_offset, value);
- }
- #if ENABLE_ASSERTIONS
- typedef struct rn_info {
- unsigned char node_desc[MAX_RN_NODES];
- } rn_info_t;
- static unsigned int ccn_get_rni_mcount(uintptr_t periphbase,
- unsigned int rn_id)
- {
- unsigned int rn_type_id;
-
- rn_type_id = get_node_type(ccn_reg_read(periphbase,
- rn_id + RNI_REGION_ID_START,
- REGION_ID_OFFSET));
-
- return rn_type_id_to_master_cnt(rn_type_id);
- }
- static unsigned int ccn_get_rn_master_info(uintptr_t periphbase,
- rn_info_t *info)
- {
- unsigned int num_masters = 0;
- rn_types_t rn_type;
- assert (info);
- for (rn_type = RN_TYPE_RNF; rn_type < NUM_RN_TYPES; rn_type++) {
- unsigned int mn_reg_off, node_id;
- unsigned long long rn_bitmap;
-
- mn_reg_off = MN_RNF_NODEID_OFFSET + (rn_type << 4);
- rn_bitmap = ccn_reg_read(periphbase, MN_REGION_ID, mn_reg_off);
- FOR_EACH_PRESENT_NODE_ID(node_id, rn_bitmap) {
- unsigned int node_mcount;
-
- node_mcount = (mn_reg_off == MN_RNF_NODEID_OFFSET ? 1 :
- ccn_get_rni_mcount(periphbase, node_id));
-
- num_masters += node_mcount;
-
- info->node_desc[node_id] = node_mcount;
- }
- }
- return num_masters;
- }
- static void __init ccn_validate_plat_params(const ccn_desc_t *plat_desc)
- {
- unsigned int master_id, num_rn_masters;
- rn_info_t info = { {0} };
- assert(plat_desc);
- assert(plat_desc->periphbase);
- assert(plat_desc->master_to_rn_id_map);
- assert(plat_desc->num_masters);
- assert(plat_desc->num_masters < CCN_MAX_RN_MASTERS);
-
- num_rn_masters = ccn_get_rn_master_info(plat_desc->periphbase, &info);
- assert(plat_desc->num_masters < num_rn_masters);
-
- for (master_id = 0; master_id < plat_desc->num_masters; master_id++) {
- unsigned int node_id;
- node_id = plat_desc->master_to_rn_id_map[master_id];
- assert(node_id < MAX_RN_NODES);
- assert(info.node_desc[node_id]);
- info.node_desc[node_id]--;
- }
- }
- #endif
- void __init ccn_init(const ccn_desc_t *plat_desc)
- {
- #if ENABLE_ASSERTIONS
- ccn_validate_plat_params(plat_desc);
- #endif
- ccn_plat_desc = plat_desc;
- }
- static unsigned long long ccn_master_to_rn_id_map(unsigned long long master_map)
- {
- unsigned long long rn_id_map = 0;
- unsigned int node_id, iface_id;
- assert(master_map);
- assert(ccn_plat_desc);
- FOR_EACH_PRESENT_MASTER_INTERFACE(iface_id, master_map) {
- assert(iface_id < ccn_plat_desc->num_masters);
-
- node_id = ccn_plat_desc->master_to_rn_id_map[iface_id];
-
- rn_id_map |= (1ULL << node_id);
- }
- return rn_id_map;
- }
- static void ccn_snoop_dvm_do_op(unsigned long long rn_id_map,
- unsigned long long hn_id_map,
- unsigned int region_id,
- unsigned int op_reg_offset,
- unsigned int stat_reg_offset)
- {
- unsigned int start_region_id;
- assert(ccn_plat_desc);
- assert(ccn_plat_desc->periphbase);
- #if defined(IMAGE_BL31) || (!defined(__aarch64__) && defined(IMAGE_BL32))
- bakery_lock_get(&ccn_lock);
- #endif
- start_region_id = region_id;
- FOR_EACH_PRESENT_REGION_ID(start_region_id, hn_id_map) {
- ccn_reg_write(ccn_plat_desc->periphbase,
- start_region_id,
- op_reg_offset,
- rn_id_map);
- }
- start_region_id = region_id;
- FOR_EACH_PRESENT_REGION_ID(start_region_id, hn_id_map) {
- WAIT_FOR_DOMAIN_CTRL_OP_COMPLETION(start_region_id,
- stat_reg_offset,
- op_reg_offset,
- rn_id_map);
- }
- #if defined(IMAGE_BL31) || (!defined(__aarch64__) && defined(IMAGE_BL32))
- bakery_lock_release(&ccn_lock);
- #endif
- }
- void ccn_enter_snoop_dvm_domain(unsigned long long master_iface_map)
- {
- unsigned long long rn_id_map;
- rn_id_map = ccn_master_to_rn_id_map(master_iface_map);
- ccn_snoop_dvm_do_op(rn_id_map,
- CCN_GET_HN_NODEID_MAP(ccn_plat_desc->periphbase,
- MN_HNF_NODEID_OFFSET),
- HNF_REGION_ID_START,
- HNF_SDC_SET_OFFSET,
- HNF_SDC_STAT_OFFSET);
- ccn_snoop_dvm_do_op(rn_id_map,
- CCN_GET_MN_NODEID_MAP(ccn_plat_desc->periphbase),
- MN_REGION_ID,
- MN_DDC_SET_OFFSET,
- MN_DDC_STAT_OFFSET);
- }
- void ccn_exit_snoop_dvm_domain(unsigned long long master_iface_map)
- {
- unsigned long long rn_id_map;
- rn_id_map = ccn_master_to_rn_id_map(master_iface_map);
- ccn_snoop_dvm_do_op(rn_id_map,
- CCN_GET_HN_NODEID_MAP(ccn_plat_desc->periphbase,
- MN_HNF_NODEID_OFFSET),
- HNF_REGION_ID_START,
- HNF_SDC_CLR_OFFSET,
- HNF_SDC_STAT_OFFSET);
- ccn_snoop_dvm_do_op(rn_id_map,
- CCN_GET_MN_NODEID_MAP(ccn_plat_desc->periphbase),
- MN_REGION_ID,
- MN_DDC_CLR_OFFSET,
- MN_DDC_STAT_OFFSET);
- }
- void ccn_enter_dvm_domain(unsigned long long master_iface_map)
- {
- unsigned long long rn_id_map;
- rn_id_map = ccn_master_to_rn_id_map(master_iface_map);
- ccn_snoop_dvm_do_op(rn_id_map,
- CCN_GET_MN_NODEID_MAP(ccn_plat_desc->periphbase),
- MN_REGION_ID,
- MN_DDC_SET_OFFSET,
- MN_DDC_STAT_OFFSET);
- }
- void ccn_exit_dvm_domain(unsigned long long master_iface_map)
- {
- unsigned long long rn_id_map;
- rn_id_map = ccn_master_to_rn_id_map(master_iface_map);
- ccn_snoop_dvm_do_op(rn_id_map,
- CCN_GET_MN_NODEID_MAP(ccn_plat_desc->periphbase),
- MN_REGION_ID,
- MN_DDC_CLR_OFFSET,
- MN_DDC_STAT_OFFSET);
- }
- unsigned int ccn_get_l3_run_mode(void)
- {
- unsigned long long hnf_pstate_stat;
- assert(ccn_plat_desc);
- assert(ccn_plat_desc->periphbase);
-
- do {
- hnf_pstate_stat = ccn_reg_read(ccn_plat_desc->periphbase,
- HNF_REGION_ID_START,
- HNF_PSTATE_STAT_OFFSET);
- } while (hnf_pstate_stat & 0x3);
- return PSTATE_TO_RUN_MODE(hnf_pstate_stat);
- }
- void ccn_set_l3_run_mode(unsigned int mode)
- {
- unsigned long long mn_hnf_id_map, hnf_pstate_stat;
- unsigned int region_id;
- assert(ccn_plat_desc);
- assert(ccn_plat_desc->periphbase);
- assert(mode <= CCN_L3_RUN_MODE_FAM);
- mn_hnf_id_map = ccn_reg_read(ccn_plat_desc->periphbase,
- MN_REGION_ID,
- MN_HNF_NODEID_OFFSET);
- region_id = HNF_REGION_ID_START;
-
- FOR_EACH_PRESENT_REGION_ID(region_id, mn_hnf_id_map) {
- ccn_reg_write(ccn_plat_desc->periphbase,
- region_id,
- HNF_PSTATE_REQ_OFFSET,
- mode);
- }
-
- region_id = HNF_REGION_ID_START;
- FOR_EACH_PRESENT_REGION_ID(region_id, mn_hnf_id_map) {
-
- do {
- hnf_pstate_stat = ccn_reg_read(ccn_plat_desc->periphbase,
- region_id,
- HNF_PSTATE_STAT_OFFSET);
- } while (((hnf_pstate_stat & HNF_PSTATE_MASK) >> 2) != mode);
- }
- }
- void ccn_program_sys_addrmap(unsigned int sn0_id,
- unsigned int sn1_id,
- unsigned int sn2_id,
- unsigned int top_addr_bit0,
- unsigned int top_addr_bit1,
- unsigned char three_sn_en)
- {
- unsigned long long mn_hnf_id_map, hnf_sam_ctrl_value;
- unsigned int region_id;
- assert(ccn_plat_desc);
- assert(ccn_plat_desc->periphbase);
- mn_hnf_id_map = ccn_reg_read(ccn_plat_desc->periphbase,
- MN_REGION_ID,
- MN_HNF_NODEID_OFFSET);
- region_id = HNF_REGION_ID_START;
- hnf_sam_ctrl_value = MAKE_HNF_SAM_CTRL_VALUE(sn0_id,
- sn1_id,
- sn2_id,
- top_addr_bit0,
- top_addr_bit1,
- three_sn_en);
- FOR_EACH_PRESENT_REGION_ID(region_id, mn_hnf_id_map) {
-
- ccn_reg_write(ccn_plat_desc->periphbase,
- region_id,
- HNF_SAM_CTRL_OFFSET,
- hnf_sam_ctrl_value);
- }
- }
- int ccn_get_part0_id(uintptr_t periphbase)
- {
- assert(periphbase);
- return (int)(mmio_read_64(periphbase
- + MN_PERIPH_ID_0_1_OFFSET) & 0xFF);
- }
- static unsigned int get_region_id_for_node(node_types_t node_type,
- unsigned int node_id)
- {
- unsigned int mn_reg_off, region_id;
- unsigned long long node_bitmap;
- unsigned int loc_node_id, node_pos_in_map = 0;
- assert(node_type < NUM_NODE_TYPES);
- assert(node_id < MAX_RN_NODES);
- switch (node_type) {
- case NODE_TYPE_RNI:
- region_id = RNI_REGION_ID_START;
- break;
- case NODE_TYPE_HNF:
- region_id = HNF_REGION_ID_START;
- break;
- case NODE_TYPE_HNI:
- region_id = HNI_REGION_ID_START;
- break;
- case NODE_TYPE_SN:
- region_id = SBSX_REGION_ID_START;
- break;
- default:
- ERROR("Un-supported Node Type = %d.\n", node_type);
- assert(false);
- return REGION_ID_LIMIT;
- }
-
- mn_reg_off = MN_RNF_NODEID_OFFSET + (node_type << 4);
- node_bitmap = ccn_reg_read(ccn_plat_desc->periphbase,
- MN_REGION_ID, mn_reg_off);
- assert((node_bitmap & (1ULL << (node_id))) != 0U);
- FOR_EACH_PRESENT_NODE_ID(loc_node_id, node_bitmap) {
- INFO("Index = %u with loc_nod=%u and input nod=%u\n",
- node_pos_in_map, loc_node_id, node_id);
- if (loc_node_id == node_id)
- break;
- node_pos_in_map++;
- }
- if (node_pos_in_map == CCN_MAX_RN_MASTERS) {
- ERROR("Node Id = %d, is not found.\n", node_id);
- assert(false);
- return REGION_ID_LIMIT;
- }
-
- if (node_type == NODE_TYPE_RNI)
- region_id += node_id;
- else
- region_id += node_pos_in_map;
- return region_id;
- }
- void ccn_write_node_reg(node_types_t node_type, unsigned int node_id,
- unsigned int reg_offset, unsigned long long val)
- {
- unsigned int region_id = get_region_id_for_node(node_type, node_id);
- if (reg_offset > REGION_ID_OFFSET) {
- ERROR("Invalid Register offset 0x%x is provided.\n",
- reg_offset);
- assert(false);
- return;
- }
-
- ccn_reg_write(ccn_plat_desc->periphbase, region_id, reg_offset, val);
- VERBOSE("Value is successfully written at address 0x%lx.\n",
- (ccn_plat_desc->periphbase
- + region_id_to_base(region_id))
- + reg_offset);
- }
- unsigned long long ccn_read_node_reg(node_types_t node_type,
- unsigned int node_id,
- unsigned int reg_offset)
- {
- unsigned long long val;
- unsigned int region_id = get_region_id_for_node(node_type, node_id);
- if (reg_offset > REGION_ID_OFFSET) {
- ERROR("Invalid Register offset 0x%x is provided.\n",
- reg_offset);
- assert(false);
- return ULL(0);
- }
-
- val = ccn_reg_read(ccn_plat_desc->periphbase, region_id, reg_offset);
- VERBOSE("Value is successfully read from address 0x%lx.\n",
- (ccn_plat_desc->periphbase
- + region_id_to_base(region_id))
- + reg_offset);
- return val;
- }
|