CCI: Adapt for specific product at run time
authorJeenu Viswambharan <jeenu.viswambharan@arm.com>
Wed, 19 Jul 2017 16:07:00 +0000 (17:07 +0100)
committerJeenu Viswambharan <jeenu.viswambharan@arm.com>
Tue, 1 Aug 2017 13:33:47 +0000 (14:33 +0100)
The current build system and driver requires the CCI product to be
specified at build time. The device constraints can be determined at run
time from its ID registers, obviating the need for specifying them
ahead.

This patch adds changes to identify and validate CCI at run time. Some
global variables are renamed to be in line with the rest of the code
base.

The build option ARM_CCI_PRODUCT_ID is now removed, and user guide is
updated.

Change-Id: Ibb765e349d3bc95ff3eb9a64bde1207ab710a93d
Signed-off-by: Jeenu Viswambharan <jeenu.viswambharan@arm.com>
Makefile
docs/user-guide.rst
drivers/arm/cci/cci.c
include/drivers/arm/cci.h
make_helpers/defaults.mk

index 23ebcaa92c6cfe4973100f99372920a8a5962844..b57b2129176c07d233d433cac198a6220f12a05b 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -465,7 +465,6 @@ $(eval $(call assert_numeric,ARM_ARCH_MINOR))
 # platform to overwrite the default options
 ################################################################################
 
-$(eval $(call add_define,ARM_CCI_PRODUCT_ID))
 $(eval $(call add_define,ARM_ARCH_MAJOR))
 $(eval $(call add_define,ARM_ARCH_MINOR))
 $(eval $(call add_define,ARM_GIC_ARCH))
index 9577269f7d1ba7fd31ec0f2f2b0fff69183d8b4b..99625e43855d99405e759ad028be0d64fa1b6b92 100644 (file)
@@ -213,10 +213,6 @@ Common build options
    It can take either ``aarch64`` or ``aarch32`` as values. By default, it is
    defined to ``aarch64``.
 
--  ``ARM_CCI_PRODUCT_ID``: Choice of ARM CCI product used by the platform. This
-   is used to determine the number of valid slave interfaces available in the
-   ARM CCI driver. Default is 400 (that is, CCI-400).
-
 -  ``ARM_ARCH_MAJOR``: The major version of ARM Architecture to target when
    compiling ARM Trusted Firmware. Its value must be numeric, and defaults to
    8 . See also, *ARMv8 Architecture Extensions* in `Firmware Design`_.
index 04530b01cb159c7cf96f03dc308ff6e0e4bdc3f6..e15683840dc00e2438f97f75548301ba13600a29 100644 (file)
 #include <mmio.h>
 #include <stdint.h>
 
-static uintptr_t g_cci_base;
-static unsigned int g_max_master_id;
-static const int *g_cci_slave_if_map;
+#define MAKE_CCI_PART_NUMBER(hi, lo)   ((hi << 8) | lo)
+#define CCI_PART_LO_MASK               0xff
+#define CCI_PART_HI_MASK               0xf
+
+/* CCI part number codes read from Peripheral ID registers 0 and 1 */
+#define CCI400_PART_NUM                0x420
+#define CCI500_PART_NUM                0x422
+#define CCI550_PART_NUM                0x423
+
+#define CCI400_SLAVE_PORTS     5
+#define CCI500_SLAVE_PORTS     7
+#define CCI550_SLAVE_PORTS     7
+
+static uintptr_t cci_base;
+static const int *cci_slave_if_map;
 
 #if ENABLE_ASSERTIONS
+static unsigned int max_master_id;
+static int cci_num_slave_ports;
+
 static int validate_cci_map(const int *map)
 {
        unsigned int valid_cci_map = 0;
@@ -23,13 +38,13 @@ static int validate_cci_map(const int *map)
        int i;
 
        /* Validate the map */
-       for (i = 0; i <= g_max_master_id; i++) {
+       for (i = 0; i <= max_master_id; i++) {
                slave_if_id = map[i];
 
                if (slave_if_id < 0)
                        continue;
 
-               if (slave_if_id >= CCI_SLAVE_INTERFACE_COUNT) {
+               if (slave_if_id >= cci_num_slave_ports) {
                        ERROR("Slave interface ID is invalid\n");
                        return 0;
                }
@@ -48,70 +63,105 @@ static int validate_cci_map(const int *map)
 
        return 1;
 }
+
+/*
+ * Read CCI part number from Peripheral ID registers
+ */
+static unsigned int read_cci_part_number(uintptr_t base)
+{
+       unsigned int part_lo, part_hi;
+
+       part_lo = mmio_read_32(base + PERIPHERAL_ID0) & CCI_PART_LO_MASK;
+       part_hi = mmio_read_32(base + PERIPHERAL_ID1) & CCI_PART_HI_MASK;
+
+       return MAKE_CCI_PART_NUMBER(part_hi, part_lo);
+}
+
+/*
+ * Identify a CCI device, and return the number of slaves. Return -1 for an
+ * unidentified device.
+ */
+static int get_slave_ports(unsigned int part_num)
+{
+       /* Macro to match CCI products */
+#define RET_ON_MATCH(product) \
+       case CCI ## product ## _PART_NUM: \
+               return CCI ## product ## _SLAVE_PORTS
+
+       switch (part_num) {
+
+       RET_ON_MATCH(400);
+       RET_ON_MATCH(500);
+       RET_ON_MATCH(550);
+
+       default:
+               return -1;
+       }
+
+#undef RET_ON_MATCH
+}
 #endif /* ENABLE_ASSERTIONS */
 
-void cci_init(uintptr_t cci_base,
-               const int *map,
-               unsigned int num_cci_masters)
+void cci_init(uintptr_t base, const int *map, unsigned int num_cci_masters)
 {
        assert(map);
-       assert(cci_base);
+       assert(base);
 
-       g_cci_base = cci_base;
+       cci_base = base;
+       cci_slave_if_map = map;
 
+#if ENABLE_ASSERTIONS
        /*
         * Master Id's are assigned from zero, So in an array of size n
         * the max master id is (n - 1).
         */
-       g_max_master_id = num_cci_masters - 1;
+       max_master_id = num_cci_masters - 1;
+       cci_num_slave_ports = get_slave_ports(read_cci_part_number(base));
+#endif
+       assert(cci_num_slave_ports >= 0);
 
        assert(validate_cci_map(map));
-       g_cci_slave_if_map = map;
 }
 
 void cci_enable_snoop_dvm_reqs(unsigned int master_id)
 {
-       int slave_if_id;
+       int slave_if_id = cci_slave_if_map[master_id];
 
-       assert(g_cci_base);
-       assert(master_id <= g_max_master_id);
-
-       slave_if_id = g_cci_slave_if_map[master_id];
-       assert((slave_if_id < CCI_SLAVE_INTERFACE_COUNT) && (slave_if_id >= 0));
+       assert(master_id <= max_master_id);
+       assert((slave_if_id < cci_num_slave_ports) && (slave_if_id >= 0));
+       assert(cci_base);
 
        /*
         * Enable Snoops and DVM messages, no need for Read/Modify/Write as
         * rest of bits are write ignore
         */
-       mmio_write_32(g_cci_base +
-                     SLAVE_IFACE_OFFSET(slave_if_id) +
-                     SNOOP_CTRL_REG, DVM_EN_BIT | SNOOP_EN_BIT);
+       mmio_write_32(cci_base +
+                     SLAVE_IFACE_OFFSET(slave_if_id) + SNOOP_CTRL_REG,
+                     DVM_EN_BIT | SNOOP_EN_BIT);
 
        /* Wait for the dust to settle down */
-       while (mmio_read_32(g_cci_base + STATUS_REG) & CHANGE_PENDING_BIT)
+       while (mmio_read_32(cci_base + STATUS_REG) & CHANGE_PENDING_BIT)
                ;
 }
 
 void cci_disable_snoop_dvm_reqs(unsigned int master_id)
 {
-       int slave_if_id;
-
-       assert(g_cci_base);
-       assert(master_id <= g_max_master_id);
+       int slave_if_id = cci_slave_if_map[master_id];
 
-       slave_if_id = g_cci_slave_if_map[master_id];
-       assert((slave_if_id < CCI_SLAVE_INTERFACE_COUNT) && (slave_if_id >= 0));
+       assert(master_id <= max_master_id);
+       assert((slave_if_id < cci_num_slave_ports) && (slave_if_id >= 0));
+       assert(cci_base);
 
        /*
         * Disable Snoops and DVM messages, no need for Read/Modify/Write as
         * rest of bits are write ignore.
         */
-       mmio_write_32(g_cci_base +
-                     SLAVE_IFACE_OFFSET(slave_if_id) +
-                     SNOOP_CTRL_REG, ~(DVM_EN_BIT | SNOOP_EN_BIT));
+       mmio_write_32(cci_base +
+                     SLAVE_IFACE_OFFSET(slave_if_id) + SNOOP_CTRL_REG,
+                     ~(DVM_EN_BIT | SNOOP_EN_BIT));
 
        /* Wait for the dust to settle down */
-       while (mmio_read_32(g_cci_base + STATUS_REG) & CHANGE_PENDING_BIT)
+       while (mmio_read_32(cci_base + STATUS_REG) & CHANGE_PENDING_BIT)
                ;
 }
 
index 5ac79c61fb107fbaa6f86dbcb5e7b10996be8048..1def6a8f23c82f31012a9e4611b058685c7541f8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
 #define SLAVE_IF_UNUSED                        -1
 
-#if ARM_CCI_PRODUCT_ID == 400
-       #define CCI_SLAVE_INTERFACE_COUNT       5
-#elif ARM_CCI_PRODUCT_ID == 500
-       #define CCI_SLAVE_INTERFACE_COUNT       7
-#else
-       #error "Invalid CCI product or CCI not supported"
-#endif
-
 #ifndef __ASSEMBLY__
 
 #include <stdint.h>
 
 /*
  * The ARM CCI driver needs the following:
- * 1. Base address of the CCI-500/CCI-400
+ * 1. Base address of the CCI product
  * 2. An array  of map between AMBA 4 master ids and ACE/ACE lite slave
  *    interfaces.
  * 3. Size of the array.
  * SLAVE_IF_UNUSED should be used in the map to represent no AMBA 4 master exists
  * for that interface.
  */
-void cci_init(uintptr_t cci_base,
-       const int *map,
-       unsigned int num_cci_masters);
+void cci_init(uintptr_t base, const int *map, unsigned int num_cci_masters);
 
 void cci_enable_snoop_dvm_reqs(unsigned int master_id);
 void cci_disable_snoop_dvm_reqs(unsigned int master_id);
index 9946fea109f6ddf397386a8e23607744074ed196..302d937f30fade7ab086c08ef659aab86adaeaf9 100644 (file)
@@ -16,10 +16,6 @@ AARCH32_SP                   := none
 # The Target build architecture. Supported values are: aarch64, aarch32.
 ARCH                           := aarch64
 
-# Determine the version of ARM CCI product used in the platform. The platform
-# port can change this value if needed.
-ARM_CCI_PRODUCT_ID             := 400
-
 # ARM Architecture major and minor versions: 8.0 by default.
 ARM_ARCH_MAJOR                 := 8
 ARM_ARCH_MINOR                 := 0