summaryrefslogtreecommitdiff
path: root/drivers/arm
diff options
context:
space:
mode:
authorJeenu Viswambharan <jeenu.viswambharan@arm.com>2017-07-19 17:07:00 +0100
committerJeenu Viswambharan <jeenu.viswambharan@arm.com>2017-08-01 14:33:47 +0100
commite33fd44548e41bcfa7bf697a36653e19e410e6c6 (patch)
treea713d900923ebca9e03277edc89e8f5c697af237 /drivers/arm
parenteeb9ff9990e67f363fb7ec4ae432a1c88af50339 (diff)
CCI: Adapt for specific product at run time
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>
Diffstat (limited to 'drivers/arm')
-rw-r--r--drivers/arm/cci/cci.c114
1 files changed, 82 insertions, 32 deletions
diff --git a/drivers/arm/cci/cci.c b/drivers/arm/cci/cci.c
index 04530b01..e1568384 100644
--- a/drivers/arm/cci/cci.c
+++ b/drivers/arm/cci/cci.c
@@ -11,11 +11,26 @@
#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)
;
}