ccn: Introduce API to set and read value of node register
authorPankaj Gupta <pankaj.gupta@nxp.com>
Thu, 15 Nov 2018 06:12:50 +0000 (11:42 +0530)
committerPankaj Gupta <pankaj.gupta@nxp.com>
Fri, 23 Nov 2018 11:08:43 +0000 (16:38 +0530)
Signed-off-by: Pankaj Gupta <pankaj.gupta@nxp.com>
drivers/arm/ccn/ccn.c
include/drivers/arm/ccn.h

index 910cd7cd27b2845bb2c6145bace59b8bbc33af93..59a7576cfe29a295840592cc74f89bf6f9076d6e 100644 (file)
@@ -11,6 +11,7 @@
 #include <debug.h>
 #include <errno.h>
 #include <mmio.h>
+#include <stdbool.h>
 #include "ccn_private.h"
 
 static const ccn_desc_t *ccn_plat_desc;
@@ -490,3 +491,123 @@ int ccn_get_part0_id(uintptr_t periphbase)
        return (int)(mmio_read_64(periphbase
                        + MN_PERIPH_ID_0_1_OFFSET) & 0xFF);
 }
+
+/*******************************************************************************
+ * This function returns the region id corresponding to a node_id of node_type.
+ ******************************************************************************/
+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;
+       }
+       /*
+        * RN-I, HN-F, HN-I, SN node registers in the MN region
+        * occupy contiguous 16 byte apart offsets.
+        *
+        * RN-F and RN-D node are not supported as
+        * none of them exposes any memory map to
+        * configure any of their offset registers.
+        */
+
+       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;
+       }
+
+       region_id += node_pos_in_map;
+
+       return region_id;
+}
+
+/*******************************************************************************
+ * This function sets the value 'val' to the register at register_offset from
+ * the base address pointed to by the region_id.
+ * where, region id is mapped to a node_id of node_type.
+ ******************************************************************************/
+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;
+       }
+
+       /* Setting the value of Auxilary Control Register of the Node */
+       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);
+}
+
+/*******************************************************************************
+ * This function read the value 'val' stored in the register at register_offset
+ * from the base address pointed to by the region_id.
+ * where, region id is mapped to a node_id of node_type.
+ ******************************************************************************/
+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);
+       }
+
+       /* Setting the value of Auxilary Control Register of the Node */
+       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;
+}
index eba974d2f3a72837dd8252c96505e931abebfe5c..9c3abac6b17f58af898c276486129b82f9e74605 100644 (file)
@@ -76,6 +76,16 @@ typedef struct ccn_desc {
        uintptr_t periphbase;
 } ccn_desc_t;
 
+/* Enum used to loop through all types of nodes in CCN*/
+typedef enum node_types {
+       NODE_TYPE_RNF = 0,
+       NODE_TYPE_RNI,
+       NODE_TYPE_RND,
+       NODE_TYPE_HNF,
+       NODE_TYPE_HNI,
+       NODE_TYPE_SN,
+       NUM_NODE_TYPES
+} node_types_t;
 
 void ccn_init(const ccn_desc_t *plat_ccn_desc);
 void ccn_enter_snoop_dvm_domain(unsigned long long master_iface_map);
@@ -92,5 +102,12 @@ void ccn_program_sys_addrmap(unsigned int sn0_id,
 unsigned int ccn_get_l3_run_mode(void);
 int ccn_get_part0_id(uintptr_t periphbase);
 
+void ccn_write_node_reg(node_types_t node_type, unsigned int node_id,
+                               unsigned int reg_offset,
+                               unsigned long long val);
+unsigned long long ccn_read_node_reg(node_types_t node_type,
+                                       unsigned int node_id,
+                                       unsigned int reg_offset);
+
 #endif /* __ASSEMBLY__ */
 #endif /* CCN_H */