[U-Boot] [PATCH v5 2/7] ppc/p4080: Add support for CoreNet style platform LAWs

Kumar Gala galak at kernel.crashing.org
Wed Sep 23 22:51:16 CEST 2009


On CoreNet based platforms the LAW address is split between an high &
low register and we no longer shift the address.  Also, the target IDs
on CoreNet platforms have been completely re-assigned.

Additionally, added a new find_law() API to which LAW an address hits in.
This is need for the CoreNet style boot release code since it will need
to determine what the target ID should be set to for boot window
translation.

Finally, enamed LAWAR_EN to LAW_EN and moved to header so we can use
it elsewhere.

Signed-off-by: Kumar Gala <galak at kernel.crashing.org>
---
* Split out set_law & disable_law between pq3 & corenet versions
* Added get_law_entry helper for find_law
* fixed for loop format

 drivers/misc/fsl_law.c    |  126 +++++++++++++++++++++++++++++++++++++++++----
 include/asm-ppc/fsl_law.h |   31 +++++++++++
 2 files changed, 146 insertions(+), 11 deletions(-)

diff --git a/drivers/misc/fsl_law.c b/drivers/misc/fsl_law.c
index aa877c6..7c59c88 100644
--- a/drivers/misc/fsl_law.c
+++ b/drivers/misc/fsl_law.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2008 Freescale Semiconductor, Inc.
+ * Copyright 2008-2009 Freescale Semiconductor, Inc.
  *
  * (C) Copyright 2000
  * Wolfgang Denk, DENX Software Engineering, wd at denx.de.
@@ -29,7 +29,6 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
-#define LAWAR_EN	0x80000000
 /* number of LAWs in the hw implementation */
 #if defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || \
     defined(CONFIG_MPC8560) || defined(CONFIG_MPC8555)
@@ -46,6 +45,56 @@ DECLARE_GLOBAL_DATA_PTR;
 #error FSL_HW_NUM_LAWS not defined for this platform
 #endif
 
+#ifdef CONFIG_FSL_CORENET
+void set_law(u8 idx, phys_addr_t addr, enum law_size sz, enum law_trgt_if id)
+{
+	volatile ccsr_local_t *ccm = (void *)(CONFIG_SYS_FSL_CORENET_CCM_ADDR);
+
+	gd->used_laws |= (1 << idx);
+
+	out_be32(&ccm->law[idx].lawar, 0);
+	out_be32(&ccm->law[idx].lawbarh, ((u64)addr >> 32));
+	out_be32(&ccm->law[idx].lawbarl, addr & 0xffffffff);
+	out_be32(&ccm->law[idx].lawar, LAW_EN | ((u32)id << 20) | (u32)sz);
+
+	/* Read back so that we sync the writes */
+	in_be32(&ccm->law[idx].lawar);
+}
+
+void disable_law(u8 idx)
+{
+	volatile ccsr_local_t *ccm = (void *)(CONFIG_SYS_FSL_CORENET_CCM_ADDR);
+
+	gd->used_laws &= ~(1 << idx);
+
+	out_be32(&ccm->law[idx].lawar, 0);
+	out_be32(&ccm->law[idx].lawbarh, 0);
+	out_be32(&ccm->law[idx].lawbarl, 0);
+
+	/* Read back so that we sync the writes */
+	in_be32(&ccm->law[idx].lawar);
+
+	return;
+}
+
+static int get_law_entry(u8 i, struct law_entry *e)
+{
+	volatile ccsr_local_t *ccm = (void *)(CONFIG_SYS_FSL_CORENET_CCM_ADDR);
+	u32 lawar;
+
+	lawar = in_be32(&ccm->law[i].lawar);
+
+	if (!(lawar & LAW_EN))
+		return 0;
+
+	e->addr = ((u64)in_be32(&ccm->law[i].lawbarh) << 32) |
+			in_be32(&ccm->law[i].lawbarl);
+	e->size = lawar & 0x3f;
+	e->trgt_id = (lawar >> 20) & 0xff;
+
+	return 1;
+}
+#else
 void set_law(u8 idx, phys_addr_t addr, enum law_size sz, enum law_trgt_if id)
 {
 	volatile u32 *base = (volatile u32 *)(CONFIG_SYS_IMMR + 0xc08);
@@ -56,12 +105,49 @@ void set_law(u8 idx, phys_addr_t addr, enum law_size sz, enum law_trgt_if id)
 
 	out_be32(lawar, 0);
 	out_be32(lawbar, addr >> 12);
-	out_be32(lawar, LAWAR_EN | ((u32)id << 20) | (u32)sz);
+	out_be32(lawar, LAW_EN | ((u32)id << 20) | (u32)sz);
 
 	/* Read back so that we sync the writes */
 	in_be32(lawar);
 }
 
+void disable_law(u8 idx)
+{
+	volatile u32 *base = (volatile u32 *)(CONFIG_SYS_IMMR + 0xc08);
+	volatile u32 *lawbar = base + 8 * idx;
+	volatile u32 *lawar = base + 8 * idx + 2;
+
+	gd->used_laws &= ~(1 << idx);
+
+	out_be32(lawar, 0);
+	out_be32(lawbar, 0);
+
+	/* Read back so that we sync the writes */
+	in_be32(lawar);
+
+	return;
+}
+
+static int get_law_entry(u8 i, struct law_entry *e)
+{
+	volatile u32 *base = (volatile u32 *)(CONFIG_SYS_IMMR + 0xc08);
+	volatile u32 *lawbar = base + 8 * i;
+	volatile u32 *lawar = base + 8 * i + 2;
+	u32 temp;
+
+	temp = in_be32(lawar);
+
+	if (!(temp & LAW_EN))
+		return 0;
+
+	e->addr = (u64)in_be32(lawbar) << 12;
+	e->size = temp & 0x3f;
+	e->trgt_id = (temp >> 20) & 0xff;
+
+	return 1;
+}
+#endif
+
 int set_next_law(phys_addr_t addr, enum law_size sz, enum law_trgt_if id)
 {
 	u32 idx = ffz(gd->used_laws);
@@ -94,18 +180,30 @@ int set_last_law(phys_addr_t addr, enum law_size sz, enum law_trgt_if id)
 	return idx;
 }
 
-void disable_law(u8 idx)
+struct law_entry find_law(phys_addr_t addr)
 {
-	volatile u32 *base = (volatile u32 *)(CONFIG_SYS_IMMR + 0xc08);
-	volatile u32 *lawbar = base + 8 * idx;
-	volatile u32 *lawar = base + 8 * idx + 2;
+	struct law_entry entry;
+	int i;
 
-	gd->used_laws &= ~(1 << idx);
+	entry.index = -1;
+	entry.addr = 0;
+	entry.size = 0;
+	entry.trgt_id = 0;
 
-	out_be32(lawar, 0);
-	out_be32(lawbar, 0);
+	for (i = 0; i < FSL_HW_NUM_LAWS; i++) {
+		u64 upper;
 
-	return;
+		if (!get_law_entry(i, &entry))
+			continue;
+
+		upper = entry.addr + (2ull << entry.size);
+		if ((addr >= entry.addr) && (addr < upper)) {
+			entry.index = i;
+			break;
+		}
+	}
+
+	return entry;
 }
 
 void print_laws(void)
@@ -173,7 +271,13 @@ void init_laws(void)
 {
 	int i;
 
+#if FSL_HW_NUM_LAWS < 32
 	gd->used_laws = ~((1 << FSL_HW_NUM_LAWS) - 1);
+#elif FSL_HW_NUM_LAWS == 32
+	gd->used_laws = 0;
+#else
+#error FSL_HW_NUM_LAWS can not be greater than 32 w/o code changes
+#endif
 
 	for (i = 0; i < num_law_entries; i++) {
 		if (law_table[i].index == -1)
diff --git a/include/asm-ppc/fsl_law.h b/include/asm-ppc/fsl_law.h
index e06a1a6..31bb754 100644
--- a/include/asm-ppc/fsl_law.h
+++ b/include/asm-ppc/fsl_law.h
@@ -1,8 +1,18 @@
+/*
+ * Copyright 2008-2009 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * Version 2 as published by the Free Software Foundation.
+ */
+
 #ifndef _FSL_LAW_H_
 #define _FSL_LAW_H_
 
 #include <asm/io.h>
 
+#define LAW_EN	0x80000000
+
 #define SET_LAW_ENTRY(idx, a, sz, trgt) \
 	{ .index = idx, .addr = a, .size = sz, .trgt_id = trgt }
 
@@ -36,6 +46,25 @@ enum law_size {
 	LAW_SIZE_32G,
 };
 
+#ifdef CONFIG_FSL_CORENET
+enum law_trgt_if {
+	LAW_TRGT_IF_PCIE_1 = 0x00,
+	LAW_TRGT_IF_PCIE_2 = 0x01,
+	LAW_TRGT_IF_PCIE_3 = 0x02,
+	LAW_TRGT_IF_RIO_1 = 0x08,
+	LAW_TRGT_IF_RIO_2 = 0x09,
+
+	LAW_TRGT_IF_DDR_1 = 0x10,
+	LAW_TRGT_IF_DDR_2 = 0x11,	/* 2nd controller */
+	LAW_TRGT_IF_DDR_INTRLV = 0x14,
+
+	LAW_TRGT_IF_BMAN = 0x18,
+	LAW_TRGT_IF_DCSR = 0x1d,
+	LAW_TRGT_IF_LBC = 0x1f,
+	LAW_TRGT_IF_QMAN = 0x3c,
+};
+#define LAW_TRGT_IF_DDR		LAW_TRGT_IF_DDR_1
+#else
 enum law_trgt_if {
 	LAW_TRGT_IF_PCI = 0x00,
 	LAW_TRGT_IF_PCI_2 = 0x01,
@@ -64,6 +93,7 @@ enum law_trgt_if {
 #if defined(CONFIG_MPC8572) || defined(CONFIG_P2020)
 #define LAW_TRGT_IF_PCIE_3	LAW_TRGT_IF_PCI
 #endif
+#endif /* CONFIG_FSL_CORENET */
 
 struct law_entry {
 	int index;
@@ -76,6 +106,7 @@ extern void set_law(u8 idx, phys_addr_t addr, enum law_size sz, enum law_trgt_if
 extern int set_next_law(phys_addr_t addr, enum law_size sz, enum law_trgt_if id);
 extern int set_last_law(phys_addr_t addr, enum law_size sz, enum law_trgt_if id);
 extern int set_ddr_laws(u64 start, u64 sz, enum law_trgt_if id);
+extern struct law_entry find_law(phys_addr_t addr);
 extern void disable_law(u8 idx);
 extern void init_laws(void);
 extern void print_laws(void);
-- 
1.6.0.6



More information about the U-Boot mailing list