Exemple #1
0
void add_core_attr(struct dt_node *cpu, uint32_t attr)
{
	if (attr & CPU_ATTR_UNIFIED_PL1)
		dt_add_property(cpu, "cache-unified", NULL, 0);
	if (attr & CPU_ATTR_SPLIT_TLB)
		dt_add_property(cpu, "tlb-split", NULL, 0);
	if (attr & CPU_ATTR_TLBIA)
		dt_add_property(cpu, "tlbia", NULL, 0);
	if (attr & CPU_ATTR_PERF_MONITOR)
		dt_add_property_cells(cpu, "performance-monitor", 0, 1);
	if (attr & CPU_ATTR_EXTERN_CONT)
		dt_add_property(cpu, "external-control", NULL, 0);
}
Exemple #2
0
void lxvpd_add_slot_properties(struct pci_slot *slot,
			       struct dt_node *np)
{
	struct phb *phb = slot->phb;
	struct lxvpd_pci_slot *s = slot->data;
	char loc_code[LOC_CODE_SIZE];
	size_t base_loc_code_len, slot_label_len;

	/* Check if we have platform specific slot */
	if (!s || !np)
		return;

	/* Check PHB base location code */
	if (!phb->base_loc_code)
		return;

	/* Check location length is valid */
	base_loc_code_len = strlen(phb->base_loc_code);
	slot_label_len = strlen(s->label);
	if ((base_loc_code_len + slot_label_len + 1) >= LOC_CODE_SIZE)
		return;

	/* Location code */
	strcpy(loc_code, phb->base_loc_code);
	strcat(loc_code, "-");
	strcat(loc_code, s->label);
	dt_add_property(np, "ibm,slot-location-code",
			loc_code, strlen(loc_code) + 1);
	dt_add_property_string(np, "ibm,slot-label",
			       s->label);
}
Exemple #3
0
void vpd_iohub_load(struct dt_node *hub_node)
{
	char record[4] = "LXR0";
	const void *valid_lx;
	uint8_t lx_size;
	int r;
	const uint32_t *p;
	const uint8_t *lx;
	unsigned int lxrn;

	p = dt_prop_get_def(hub_node, "ibm,vpd-lx-info", NULL);
	if (!p)
		return;

	lxrn = p[0];
        lx = (const char *)&p[1];

	/* verify the lid preload has started */
	if (!vpd_lid || !vpd_lid_no) {
		prlog(PR_WARNING, "VPD: WARNING: Unable to load VPD lid");
		return;
	}

	r = fsp_wait_lid_loaded(vpd_lid_no);

	if (r)
		goto fail;

	/* Validate it */
	if (lxrn < 9)
		record[3] = '0' + lxrn;
	else
		memcpy(record, "VINI", 4);

	valid_lx = vpd_find(vpd_lid, vpd_lid_size, record, "LX", &lx_size);
	if (!valid_lx || lx_size != 8) {
		prerror("VPD: Cannot find validation LX record\n");
		goto fail;
	}
	if (memcmp(valid_lx, lx, 8) != 0) {
		prerror("VPD: LX record mismatch !\n");
		goto fail;
	}

	printf("VPD: Loaded %zu bytes\n", vpd_lid_size);

	dt_add_property(hub_node, "ibm,io-vpd", vpd_lid, vpd_lid_size);
	free(vpd_lid);
	return;

fail:
	free(vpd_lid);
	vpd_lid = NULL;
	prerror("VPD: Failed to load VPD LID\n");
	return;
}
Exemple #4
0
void slca_vpd_add_loc_code(struct dt_node *node, uint16_t slca_index)
{
	const char *fru_loc_code;
	char loc_code[LOC_CODE_SIZE];

	memset(loc_code, 0, sizeof(loc_code));
	fru_loc_code = slca_get_loc_code_index(slca_index);
	if (!fru_loc_code)
		return;

	strncpy(loc_code, fru_loc_code, LOC_CODE_SIZE - 1);
	dt_add_property(node, "ibm,loc-code", loc_code, strlen(loc_code) + 1);
}
static void add_mem_node(uint64_t start, uint64_t len)
{
	struct dt_node *mem;
	u64 reg[2];
	char *name;

	name = (char*)malloc(sizeof("memory@") + STR_MAX_CHARS(reg[0]));
	assert(name);

	/* reg contains start and length */
	reg[0] = cpu_to_be64(start);
	reg[1] = cpu_to_be64(len);

	sprintf(name, "memory@%llx", (long long)start);

	mem = dt_new(dt_root, name);
	dt_add_property_string(mem, "device_type", "memory");
	dt_add_property(mem, "reg", reg, sizeof(reg));
	free(name);
}
Exemple #6
0
static void trace_add_dt_props(void)
{
	unsigned int i;
	u64 *prop, tmask;

	prop = malloc(sizeof(u64) * 2 * debug_descriptor.num_traces);

	for (i = 0; i < debug_descriptor.num_traces; i++) {
		prop[i * 2] = cpu_to_fdt64(debug_descriptor.trace_phys[i]);
		prop[i * 2 + 1] = cpu_to_fdt64(debug_descriptor.trace_size[i]);
	}

	dt_add_property(opal_node, "ibm,opal-traces",
			prop, sizeof(u64) * 2 * i);
	free(prop);

	tmask = (uint64_t)&debug_descriptor.trace_mask;
	dt_add_property_cells(opal_node, "ibm,opal-trace-mask",
			      hi32(tmask), lo32(tmask));
}
Exemple #7
0
void vpd_iohub_load(struct dt_node *hub_node)
{
    void *vpd;
    size_t sz;
    const uint32_t *p;
    unsigned int lx_idx;
    const char *lxr;

    p = dt_prop_get_def(hub_node, "ibm,vpd-lx-info", NULL);
    if (!p)
        return;

    lx_idx = p[0];
    lxr = (const char *)&p[1];

    vpd = vpd_lid_load(lxr, lx_idx, &sz);
    if (!vpd) {
        prerror("VPD: Failed to load VPD LID\n");
    } else {
        dt_add_property(hub_node, "ibm,io-vpd", vpd, sz);
        free(vpd);
    }
}
Exemple #8
0
static struct dt_node *create_cache_node(struct dt_node *cpus,
					 const struct sppcia_cpu_cache *cache,
					 const char *name, uint32_t unit_addr,
					 int okay)
{
	struct dt_node *node;

	node = dt_new_addr(cpus, name, unit_addr);
	assert(node);

	dt_add_property_string(node, "device_type", "cache");
	dt_add_property_cells(node, "reg", unit_addr);
	dt_add_property_string(node, "status", okay ? "okay" : "bad");
	dt_add_property(node, "cache-unified", NULL, 0);

	/* Assume cache associavitity sets is same for L2, L3 and L3.5 */
	dt_add_property_cells(node, "d-cache-sets",
			      be32_to_cpu(cache->l2_cache_assoc_sets));
	dt_add_property_cells(node, "i-cache-sets",
			      be32_to_cpu(cache->l2_cache_assoc_sets));

	return node;
}
Exemple #9
0
static struct dt_node *flash_add_dt_node(struct flash *flash, int id)
{
	int i;
	int rc;
	const char *name;
	bool ecc;
	struct ffs_handle *ffs;
	int ffs_part_num, ffs_part_start, ffs_part_size;
	struct dt_node *flash_node;
	struct dt_node *partition_container_node;
	struct dt_node *partition_node;

	flash_node = dt_new_addr(opal_node, "flash", id);
	dt_add_property_strings(flash_node, "compatible", "ibm,opal-flash");
	dt_add_property_cells(flash_node, "ibm,opal-id", id);
	dt_add_property_u64(flash_node, "reg", flash->size);
	dt_add_property_cells(flash_node, "ibm,flash-block-size",
			flash->block_size);
	if (flash->no_erase)
		dt_add_property(flash_node, "no-erase", NULL, 0);

	/* we fix to 32-bits */
	dt_add_property_cells(flash_node, "#address-cells", 1);
	dt_add_property_cells(flash_node, "#size-cells", 1);

	/* Add partition container node */
	partition_container_node = dt_new(flash_node, "partitions");
	dt_add_property_strings(partition_container_node, "compatible", "fixed-partitions");

	/* we fix to 32-bits */
	dt_add_property_cells(partition_container_node, "#address-cells", 1);
	dt_add_property_cells(partition_container_node, "#size-cells", 1);

	/* Add partitions */
	for (i = 0, name = NULL; i < ARRAY_SIZE(part_name_map); i++) {
		name = part_name_map[i].name;

		rc = ffs_init(0, flash->size, flash->bl, &ffs, 1);
		if (rc) {
			prerror("FLASH: Can't open ffs handle\n");
			continue;
		}

		rc = ffs_lookup_part(ffs, name, &ffs_part_num);
		if (rc) {
			/* This is not an error per-se, some partitions
			 * are purposefully absent, don't spam the logs
			 */
		        prlog(PR_DEBUG, "FLASH: No %s partition\n", name);
			continue;
		}
		rc = ffs_part_info(ffs, ffs_part_num, NULL,
				   &ffs_part_start, NULL, &ffs_part_size, &ecc);
		if (rc) {
			prerror("FLASH: Failed to get %s partition info\n", name);
			continue;
		}

		partition_node = dt_new_addr(partition_container_node, "partition", ffs_part_start);
		dt_add_property_strings(partition_node, "label", name);
		dt_add_property_cells(partition_node, "reg", ffs_part_start, ffs_part_size);
		if (part_name_map[i].id != RESOURCE_ID_KERNEL_FW) {
			/* Mark all partitions other than the full PNOR and the boot kernel
			 * firmware as read only.  These two partitions are the only partitions
			 * that are properly erase block aligned at this time.
			 */
			dt_add_property(partition_node, "read-only", NULL, 0);
		}
	}

	partition_node = dt_new_addr(partition_container_node, "partition", 0);
	dt_add_property_strings(partition_node, "label", "PNOR");
	dt_add_property_cells(partition_node, "reg", 0, flash->size);

	return flash_node;
}
Exemple #10
0
void force_dummy_console(void)
{
	if (!dummy_console_enabled())
		dt_add_property(dt_chosen, "sapphire,enable-dummy-console",
						NULL, 0);
}
Exemple #11
0
struct dt_node * add_core_common(struct dt_node *cpus,
				 const struct sppcia_cpu_cache *cache,
				 const struct sppaca_cpu_timebase *tb,
				 uint32_t int_server, bool okay)
{
	const char *name;
	struct dt_node *cpu;
	uint32_t version;
	uint64_t freq;
	const uint8_t pa_features[] = {
		6, 0, 0xf6, 0x3f, 0xc7, 0x00, 0x80, 0xc0 };

	printf("    Cache: I=%u D=%u/%u/%u/%u\n",
	       be32_to_cpu(cache->icache_size_kb),
	       be32_to_cpu(cache->l1_dcache_size_kb),
	       be32_to_cpu(cache->l2_dcache_size_kb),
	       be32_to_cpu(cache->l3_dcache_size_kb),
	       be32_to_cpu(cache->l35_dcache_size_kb));

	/* Use the boot CPU PVR to make up a CPU name in the device-tree
	 * since the HDAT doesn't seem to tell....
	 */
	version = mfspr(SPR_PVR);
	switch(PVR_TYPE(version)) {
	case PVR_TYPE_P7:
		name = "PowerPC,POWER7";
		break;
	case PVR_TYPE_P7P:
		name = "PowerPC,POWER7+";
		break;
	case PVR_TYPE_P8E:
	case PVR_TYPE_P8:
		name = "PowerPC,POWER8";
		break;
	default:
		name = "PowerPC,Unknown";
	}

	cpu = dt_new_addr(cpus, name, int_server);
	assert(cpu);
	dt_add_property_string(cpu, "device_type", "cpu");
	dt_add_property_string(cpu, "status", okay ? "okay" : "bad");
	dt_add_property_cells(cpu, "reg", int_server);
	dt_add_property_cells(cpu, "cpu-version", version);
	dt_add_property(cpu, "64-bit", NULL, 0);
	dt_add_property(cpu, "32-64-bridge", NULL, 0);
	dt_add_property(cpu, "graphics", NULL, 0);
	dt_add_property(cpu, "general-purpose", NULL, 0);
	dt_add_property_cells(cpu, "ibm,processor-segment-sizes",
			      0x1c, 0x28, 0xffffffff, 0xffffffff);
	dt_add_property_cells(cpu, "ibm,processor-page-sizes",
			      0xc, 0x10, 0x18, 0x22);

	/* Page size encodings appear to be the same for P7 and P8 */
	dt_add_property_cells(cpu, "ibm,segment-page-sizes",
		0x0c, 0x000, 3, 0x0c, 0x0000,  /*  4K seg  4k pages */
		                0x10, 0x0007,  /*  4K seg 64k pages */
		                0x18, 0x0038,  /*  4K seg 16M pages */
		0x10, 0x110, 2, 0x10, 0x0001,  /* 64K seg 64k pages */
		                0x18, 0x0008,  /* 64K seg 16M pages */
		0x18, 0x100, 1,	0x18, 0x0000,  /* 16M seg 16M pages */
		0x22, 0x120, 1, 0x22, 0x0003); /* 16G seg 16G pages */
			      
	dt_add_property(cpu, "ibm,pa-features",
			pa_features, sizeof(pa_features));
	dt_add_property_cells(cpu, "ibm,slb-size", 0x20);

	dt_add_property_cells(cpu, "ibm,vmx", 0x2);
	dt_add_property_cells(cpu, "ibm,dfp", 0x2);
	dt_add_property_cells(cpu, "ibm,purr", 0x1);
	dt_add_property_cells(cpu, "ibm,spurr", 0x1);

	/*
	 * Do not create "clock-frequency" if the frequency doesn't
	 * fit in a single cell
	 */
	freq = ((uint64_t)be32_to_cpu(tb->actual_clock_speed)) * 1000000ul;
	if (freq <= 0xfffffffful)
		dt_add_property_cells(cpu, "clock-frequency", freq);
	dt_add_property_cells(cpu, "ibm,extended-clock-frequency",
			      hi32(freq), lo32(freq));

	/* FIXME: Hardcoding is bad. */
	dt_add_property_cells(cpu, "timebase-frequency", 512000000);
	dt_add_property_cells(cpu, "ibm,extended-timebase-frequency",
			      0, 512000000);

	dt_add_property_cells(cpu, "reservation-granule-size",
			      be32_to_cpu(cache->reservation_size));

	dt_add_property_cells(cpu, "d-tlb-size",
			      be32_to_cpu(cache->dtlb_entries));
	dt_add_property_cells(cpu, "i-tlb-size",
			      be32_to_cpu(cache->itlb_entries));
	/* Assume unified TLB */
	dt_add_property_cells(cpu, "tlb-size",
			      be32_to_cpu(cache->dtlb_entries));
	dt_add_property_cells(cpu, "d-tlb-sets",
			      be32_to_cpu(cache->dtlb_assoc_sets));
	dt_add_property_cells(cpu, "i-tlb-sets",
			      be32_to_cpu(cache->itlb_assoc_sets));
	dt_add_property_cells(cpu, "tlb-sets",
			      be32_to_cpu(cache->dtlb_assoc_sets));

	dt_add_property_cells(cpu, "d-cache-block-size",
			      be32_to_cpu(cache->dcache_block_size));
	dt_add_property_cells(cpu, "i-cache-block-size",
			      be32_to_cpu(cache->icache_block_size));
	dt_add_property_cells(cpu, "d-cache-size",
			      be32_to_cpu(cache->l1_dcache_size_kb)*1024);
	dt_add_property_cells(cpu, "i-cache-size",
			      be32_to_cpu(cache->icache_size_kb)*1024);
	dt_add_property_cells(cpu, "i-cache-sets",
			      be32_to_cpu(cache->icache_assoc_sets));
	dt_add_property_cells(cpu, "d-cache-sets",
			      be32_to_cpu(cache->dcache_assoc_sets));

	if (cache->icache_line_size != cache->icache_block_size)
		dt_add_property_cells(cpu, "i-cache-line-size",
				      be32_to_cpu(cache->icache_line_size));
	if (cache->l1_dcache_line_size != cache->dcache_block_size)
		dt_add_property_cells(cpu, "d-cache-line-size",
				      be32_to_cpu(cache->l1_dcache_line_size));
	return cpu;
}
Exemple #12
0
struct dt_node * add_core_common(struct dt_node *cpus,
				 const struct sppcia_cpu_cache *cache,
				 const struct sppaca_cpu_timebase *tb,
				 uint32_t int_server, bool okay)
{
	const char *name;
	struct dt_node *cpu;
	uint32_t version;
	uint64_t freq;
	const uint8_t pa_features_p7[] = {
		6, 0,
		0xf6, 0x3f, 0xc7, 0x00, 0x80, 0xc0 };
	const uint8_t pa_features_p7p[] = {
		6, 0,
		0xf6, 0x3f, 0xc7, 0xc0, 0x80, 0xc0 };
	const uint8_t pa_features_p8[] = {
	       24, 0,
	       0xf6, 0x3f, 0xc7, 0xc0, 0x80, 0xd0, 0x80, 0x00,
	       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	       0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00,
	};
	const uint8_t pa_features_p9n_dd20[] = {
	       64, 0,
	       0xf6, 0x3f, 0xc7, 0xc0, 0x80, 0xd0, 0x80, 0x00, /*  0 ..  7 */
	       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*  8 .. 15 */
	       0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, /* 16 .. 23 */
	       0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, /* 24 .. 31 */
	       0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, /* 32 .. 39 */
	       0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 40 .. 47 */
	       0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 48 .. 55 */
	       0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 56 .. 63 */
	};
	const uint8_t pa_features_p9[] = {
	       64, 0,
	       0xf6, 0x3f, 0xc7, 0xc0, 0x80, 0xd0, 0x80, 0x00, /*  0 ..  7 */
	       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*  8 .. 15 */
	       0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, /* 16 .. 23 */
	       0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, /* 24 .. 31 */
	       0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, /* 32 .. 39 */
	       0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 40 .. 47 */
	       0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 48 .. 55 */
	       0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 56 .. 63 */
	};

	const uint8_t *pa_features;
	size_t pa_features_size;

	prlog(PR_INFO, "    Cache: I=%u D=%u/%u/%u/%u\n",
	      be32_to_cpu(cache->icache_size_kb),
	      be32_to_cpu(cache->l1_dcache_size_kb),
	      be32_to_cpu(cache->l2_dcache_size_kb),
	      be32_to_cpu(cache->l3_dcache_size_kb),
	      be32_to_cpu(cache->l35_dcache_size_kb));

	/* Use the boot CPU PVR to make up a CPU name in the device-tree
	 * since the HDAT doesn't seem to tell....
	 */
	version = mfspr(SPR_PVR);
	switch(PVR_TYPE(version)) {
	case PVR_TYPE_P7:
		name = "PowerPC,POWER7";
		pa_features = pa_features_p7;
		pa_features_size = sizeof(pa_features_p7);
		break;
	case PVR_TYPE_P7P:
		name = "PowerPC,POWER7+";
		pa_features = pa_features_p7p;
		pa_features_size = sizeof(pa_features_p7p);
		break;
	case PVR_TYPE_P8E:
	case PVR_TYPE_P8:
	case PVR_TYPE_P8NVL:
		name = "PowerPC,POWER8";
		pa_features = pa_features_p8;
		pa_features_size = sizeof(pa_features_p8);
		break;
	case PVR_TYPE_P9:
	case PVR_TYPE_P9P:
		name = "PowerPC,POWER9";
		if (is_power9n(version) &&
			   (PVR_VERS_MAJ(version) == 2) &&
			   (PVR_VERS_MIN(version) == 0)) {
			/* P9N DD2.0 */
			pa_features = pa_features_p9n_dd20;
			pa_features_size = sizeof(pa_features_p9n_dd20);
		} else {
			pa_features = pa_features_p9;
			pa_features_size = sizeof(pa_features_p9);
		}
		break;
	default:
		name = "PowerPC,Unknown";
		pa_features = NULL;
	}

	cpu = dt_new_addr(cpus, name, int_server);
	assert(cpu);
	dt_add_property_string(cpu, "device_type", "cpu");
	dt_add_property_string(cpu, "status", okay ? "okay" : "bad");
	dt_add_property_cells(cpu, "reg", int_server);
	dt_add_property_cells(cpu, "cpu-version", version);
	dt_add_property(cpu, "64-bit", NULL, 0);
	dt_add_property(cpu, "32-64-bridge", NULL, 0);
	dt_add_property(cpu, "graphics", NULL, 0);
	dt_add_property(cpu, "general-purpose", NULL, 0);
	dt_add_property_cells(cpu, "ibm,processor-segment-sizes",
			      0x1c, 0x28, 0xffffffff, 0xffffffff);
	dt_add_property_cells(cpu, "ibm,processor-page-sizes",
			      0xc, 0x10, 0x18, 0x22);

	if (proc_gen == proc_gen_p9)
		dt_add_property_cells(cpu, "ibm,processor-radix-AP-encodings",
			0x0000000c, 0xa0000010, 0x20000015, 0x4000001e);

	/* Page size encodings appear to be the same for P7 and P8 */
	dt_add_property_cells(cpu, "ibm,segment-page-sizes",
		0x0c, 0x000, 3, 0x0c, 0x0000,  /*  4K seg  4k pages */
		                0x10, 0x0007,  /*  4K seg 64k pages */
		                0x18, 0x0038,  /*  4K seg 16M pages */
		0x10, 0x110, 2, 0x10, 0x0001,  /* 64K seg 64k pages */
		                0x18, 0x0008,  /* 64K seg 16M pages */
		0x18, 0x100, 1,	0x18, 0x0000,  /* 16M seg 16M pages */
		0x22, 0x120, 1, 0x22, 0x0003); /* 16G seg 16G pages */


	if (pa_features) {
		dt_add_property(cpu, "ibm,pa-features",
				pa_features, pa_features_size);
	}
	dt_add_property_cells(cpu, "ibm,slb-size", 0x20);

	dt_add_property_cells(cpu, "ibm,vmx", 0x2);
	dt_add_property_cells(cpu, "ibm,dfp", 0x2);
	dt_add_property_cells(cpu, "ibm,purr", 0x1);
	dt_add_property_cells(cpu, "ibm,spurr", 0x1);

	/*
	 * Do not create "clock-frequency" if the frequency doesn't
	 * fit in a single cell
	 */
	freq = ((uint64_t)be32_to_cpu(tb->actual_clock_speed)) * 1000000ul;
	if (freq <= 0xfffffffful)
		dt_add_property_cells(cpu, "clock-frequency", freq);
	dt_add_property_u64(cpu, "ibm,extended-clock-frequency", freq);

	/* FIXME: Hardcoding is bad. */
	dt_add_property_cells(cpu, "timebase-frequency", 512000000);
	dt_add_property_cells(cpu, "ibm,extended-timebase-frequency",
			      0, 512000000);

	dt_add_property_cells(cpu, "reservation-granule-size",
			      be32_to_cpu(cache->reservation_size));

	dt_add_property_cells(cpu, "d-tlb-size",
			      be32_to_cpu(cache->dtlb_entries));
	dt_add_property_cells(cpu, "i-tlb-size",
			      be32_to_cpu(cache->itlb_entries));
	/* Assume unified TLB */
	dt_add_property_cells(cpu, "tlb-size",
			      be32_to_cpu(cache->dtlb_entries));
	dt_add_property_cells(cpu, "d-tlb-sets",
			      be32_to_cpu(cache->dtlb_assoc_sets));
	dt_add_property_cells(cpu, "i-tlb-sets",
			      be32_to_cpu(cache->itlb_assoc_sets));
	dt_add_property_cells(cpu, "tlb-sets",
			      be32_to_cpu(cache->dtlb_assoc_sets));

	dt_add_property_cells(cpu, "d-cache-block-size",
			      be32_to_cpu(cache->dcache_block_size));
	dt_add_property_cells(cpu, "i-cache-block-size",
			      be32_to_cpu(cache->icache_block_size));
	dt_add_property_cells(cpu, "d-cache-size",
			      be32_to_cpu(cache->l1_dcache_size_kb)*1024);
	dt_add_property_cells(cpu, "i-cache-size",
			      be32_to_cpu(cache->icache_size_kb)*1024);
	dt_add_property_cells(cpu, "i-cache-sets",
			      be32_to_cpu(cache->icache_assoc_sets));
	dt_add_property_cells(cpu, "d-cache-sets",
			      be32_to_cpu(cache->dcache_assoc_sets));

	if (cache->icache_line_size != cache->icache_block_size)
		dt_add_property_cells(cpu, "i-cache-line-size",
				      be32_to_cpu(cache->icache_line_size));
	if (cache->l1_dcache_line_size != cache->dcache_block_size)
		dt_add_property_cells(cpu, "d-cache-line-size",
				      be32_to_cpu(cache->l1_dcache_line_size));
	return cpu;
}