[OpenBIOS] [PATCH 04/10] pci: property encoding helpers

Igor V. Kovalenko igor.v.kovalenko at gmail.com
Tue May 25 14:38:11 CEST 2010


From: Igor V. Kovalenko <igor.v.kovalenko at gmail.com>

Signed-off-by: Igor V. Kovalenko <igor.v.kovalenko at gmail.com>
---
 drivers/pci.c |  127 +++++++++++++++++++++++++++++++++++++++++----------------
 1 files changed, 92 insertions(+), 35 deletions(-)

diff --git a/drivers/pci.c b/drivers/pci.c
index 7df418e..c080372 100644
--- a/drivers/pci.c
+++ b/drivers/pci.c
@@ -52,7 +52,21 @@ enum {
 	MEMORY_SPACE_64 = 3,
 };
 
-static inline void pci_encode_phys_addr(u32 *phys, int flags, int space_code,
+static int encode_int32_cells(int num_cells, u32 *prop, ucell val)
+{
+    int i = 0;
+
+    /* hi ... lo */
+    for (i=0; i < num_cells; ++i) {
+        prop[num_cells - i - 1] = val;
+        val >>= 16;
+        val >>= 16;
+    }
+
+    return num_cells;
+}
+
+static inline int pci_encode_phys_addr(u32 *phys, int flags, int space_code,
 				 pci_addr dev, uint8_t reg, uint64_t addr)
 {
 
@@ -67,8 +81,44 @@ static inline void pci_encode_phys_addr(u32 *phys, int flags, int space_code,
 	/* phys.lo */
 
 	phys[2] = addr;
+
+	return 3;
 }
 
+static inline int pci_encode_size(u32 *prop, uint64_t size)
+{
+    return encode_int32_cells(2, prop, size);
+}
+
+static int host_address_cells(void)
+{
+    return get_int_property(find_dev("/"), "#address-cells", NULL);
+}
+
+static int host_encode_phys_addr(u32 *prop, ucell addr)
+{
+    return encode_int32_cells(host_address_cells(), prop, addr);
+}
+
+static int host_size_cells(void)
+{
+    return get_int_property(find_dev("/"), "#size-cells", NULL);
+}
+
+/*
+static int parent_address_cells(void)
+{
+    phandle_t parent_ph = ih_to_phandle(my_parent());
+    return get_int_property(parent_ph, "#address-cells", NULL);
+}
+
+static int parent_size_cells(void)
+{
+    phandle_t parent_ph = ih_to_phandle(my_parent());
+    return get_int_property(parent_ph, "#size-cells", NULL);
+}
+*/
+
 static void
 ob_pci_open(int *idx)
 {
@@ -318,14 +368,23 @@ static void pci_host_set_interrupt_map(const pci_config_t *config)
 
 static void pci_host_set_reg(const pci_config_t *config)
 {
-	phandle_t dev = get_cur_dev();
-	u32 props[2];
+    phandle_t dev = get_cur_dev();
+    /* at most 2 integers for address and size */
+    u32 props[4];
+    int ncells = 0;
+
+    ncells += encode_int32_cells(host_address_cells(), props + ncells,
+            arch->cfg_base);
+
+    ncells += encode_int32_cells(host_size_cells(), props + ncells,
+            arch->cfg_len);
 
-	props[0] = arch->cfg_base;
-	props[1] = arch->cfg_len;
-	set_property(dev, "reg", (char *)props, 2 * sizeof(props[0]));
+    set_property(dev, "reg", (char *)props, ncells * sizeof(props[0]));
 }
 
+/* child-phys : parent-phys : size */
+/* 3 cells for PCI : 2 cells for 64bit parent : 2 cells for PCI */
+
 static void pci_host_set_ranges(const pci_config_t *config)
 {
 	phandle_t dev = get_cur_dev();
@@ -333,29 +392,31 @@ static void pci_host_set_ranges(const pci_config_t *config)
 	int ncells;
 
 	ncells = 0;
+	/* first encode PCI configuration space */
+	{
+	    ncells += pci_encode_phys_addr(props + ncells, 0, CONFIGURATION_SPACE,
+                     config->dev, 0, 0);
+        ncells += host_encode_phys_addr(props + ncells, arch->cfg_addr);
+        ncells += pci_encode_size(props + ncells, arch->cfg_len);
+	}
+
 	if (arch->io_base) {
-		pci_encode_phys_addr(props + ncells, 0, IO_SPACE,
+	    ncells += pci_encode_phys_addr(props + ncells, 0, IO_SPACE,
 				     config->dev, 0, 0);
-		ncells += 3;
-		props[ncells++] = arch->io_base;
-		props[ncells++] = 0x00000000;
-		props[ncells++] = arch->io_len;
+        ncells += host_encode_phys_addr(props + ncells, arch->io_base);
+        ncells += pci_encode_size(props + ncells, arch->io_len);
 	}
 	if (arch->rbase) {
-		pci_encode_phys_addr(props + ncells, 0, MEMORY_SPACE_32,
+	    ncells += pci_encode_phys_addr(props + ncells, 0, MEMORY_SPACE_32,
 				     config->dev, 0, 0);
-		ncells += 3;
-		props[ncells++] = arch->rbase;
-		props[ncells++] = 0x00000000;
-		props[ncells++] = arch->rlen;
+        ncells += host_encode_phys_addr(props + ncells, arch->rbase);
+        ncells += pci_encode_size(props + ncells, arch->rlen);
 	}
 	if (arch->mem_base) {
-		pci_encode_phys_addr(props + ncells, 0, MEMORY_SPACE_32,
+	    ncells += pci_encode_phys_addr(props + ncells, 0, MEMORY_SPACE_32,
 				     config->dev, 0, arch->mem_base);
-		ncells += 3;
-		props[ncells++] = arch->mem_base;
-		props[ncells++] = 0x00000000;
-		props[ncells++] = arch->mem_len;
+        ncells += host_encode_phys_addr(props + ncells, arch->mem_base);
+        ncells += pci_encode_size(props + ncells, arch->mem_len);
 	}
 	set_property(dev, "ranges", (char *)props, ncells * sizeof(props[0]));
 }
@@ -548,11 +609,10 @@ static void pci_set_assigned_addresses(const pci_config_t *config, int num_bars)
 		pci_decode_pci_addr(config->assigned[i],
 				    &flags, &space_code, &mask);
 
-		pci_encode_phys_addr(props + ncells,
+		ncells += pci_encode_phys_addr(props + ncells,
 				     flags, space_code, config->dev,
 				     PCI_BASE_ADDR_0 + (i * sizeof(uint32_t)),
 				     config->assigned[i] & ~mask);
-		ncells += 3;
 
 		props[ncells++] = 0x00000000;
 		props[ncells++] = config->sizes[i];
@@ -571,13 +631,13 @@ static void pci_set_reg(const pci_config_t *config, int num_bars)
 	uint32_t mask;
 	int space_code, flags;
 
-	ncells = 0;
-	pci_encode_phys_addr(props + ncells, 0, CONFIGURATION_SPACE,
+    ncells = 0;
+
+    /* first (addr, size) pair is the beginning of configuration address space */
+	ncells += pci_encode_phys_addr(props + ncells, 0, CONFIGURATION_SPACE,
 			     config->dev, 0, 0);
-	ncells += 3;
 
-	props[ncells++] = 0x00000000;
-	props[ncells++] = 0x00000000;
+	ncells += pci_encode_size(props + ncells, 0);
 
 	for (i = 0; i < num_bars; i++) {
 		if (!config->assigned[i] || !config->sizes[i])
@@ -586,17 +646,15 @@ static void pci_set_reg(const pci_config_t *config, int num_bars)
 		pci_decode_pci_addr(config->regions[i],
 				    &flags, &space_code, &mask);
 
-		pci_encode_phys_addr(props + ncells,
+		ncells += pci_encode_phys_addr(props + ncells,
 				     flags, space_code, config->dev,
 				     PCI_BASE_ADDR_0 + (i * sizeof(uint32_t)),
 				     config->regions[i] & ~mask);
-		ncells += 3;
 
 		/* set size */
-
-		props[ncells++] = 0x00000000;
-		props[ncells++] = config->sizes[i];
+		ncells += pci_encode_size(props + ncells, config->sizes[i]);
 	}
+
 	set_property(dev, "reg", (char *)props, ncells * sizeof(props[0]));
 }
 
@@ -624,10 +682,9 @@ static void pci_set_ranges(const pci_config_t *config)
 
 		pci_decode_pci_addr(config->assigned[i],
 				    &flags, &space_code, &mask);
-		pci_encode_phys_addr(props + ncells, flags, space_code,
+		ncells += pci_encode_phys_addr(props + ncells, flags, space_code,
 				     config->dev, 0x10 + i * 4,
 				     config->assigned[i] & ~mask);
-		ncells += 3;
 
 		/* size */
 




More information about the OpenBIOS mailing list