xref: /illumos-gate/usr/src/uts/sun4u/io/gptwo_cpu.c (revision 88294e09)
11c42de6dSgd /*
21c42de6dSgd  * CDDL HEADER START
31c42de6dSgd  *
41c42de6dSgd  * The contents of this file are subject to the terms of the
51c42de6dSgd  * Common Development and Distribution License (the "License").
61c42de6dSgd  * You may not use this file except in compliance with the License.
71c42de6dSgd  *
81c42de6dSgd  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
91c42de6dSgd  * or http://www.opensolaris.org/os/licensing.
101c42de6dSgd  * See the License for the specific language governing permissions
111c42de6dSgd  * and limitations under the License.
121c42de6dSgd  *
131c42de6dSgd  * When distributing Covered Code, include this CDDL HEADER in each
141c42de6dSgd  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
151c42de6dSgd  * If applicable, add the following below this CDDL HEADER, with the
161c42de6dSgd  * fields enclosed by brackets "[]" replaced with your own identifying
171c42de6dSgd  * information: Portions Copyright [yyyy] [name of copyright owner]
181c42de6dSgd  *
191c42de6dSgd  * CDDL HEADER END
201c42de6dSgd  */
211c42de6dSgd /*
22*88294e09SRichard Bean  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
231c42de6dSgd  * Use is subject to license terms.
241c42de6dSgd  */
251c42de6dSgd 
261c42de6dSgd /*
271c42de6dSgd  * CPU functions to the Safari Configurator  (gptwo_cpu)
281c42de6dSgd  */
291c42de6dSgd 
301c42de6dSgd #include <sys/types.h>
311c42de6dSgd #include <sys/cred.h>
321c42de6dSgd #include <sys/mman.h>
331c42de6dSgd #include <sys/kmem.h>
341c42de6dSgd #include <sys/conf.h>
351c42de6dSgd #include <sys/ddi.h>
361c42de6dSgd #include <sys/sunddi.h>
371c42de6dSgd #include <sys/sunndi.h>
381c42de6dSgd #include <sys/modctl.h>
391c42de6dSgd #include <sys/stat.h>
401c42de6dSgd #include <sys/param.h>
411c42de6dSgd #include <sys/autoconf.h>
421c42de6dSgd #include <sys/ksynch.h>
431c42de6dSgd #include <sys/promif.h>
441c42de6dSgd #include <sys/ndi_impldefs.h>
451c42de6dSgd #include <sys/ddi_impldefs.h>
461c42de6dSgd #include <sys/machsystm.h>
471c42de6dSgd #include <sys/gp2cfg.h>
481c42de6dSgd #include <sys/gptwo_cpu.h>
491c42de6dSgd #include <sys/cheetahregs.h>
501c42de6dSgd 
511c42de6dSgd #ifdef DEBUG
521c42de6dSgd int gptwo_cpu_debug = 0;
531c42de6dSgd 
541c42de6dSgd static void debug(char *, uintptr_t, uintptr_t,
551c42de6dSgd     uintptr_t, uintptr_t, uintptr_t);
561c42de6dSgd 
571c42de6dSgd #define	GPTWO_DEBUG0(level, flag, s) if (gptwo_cpu_debug >= level) \
581c42de6dSgd     cmn_err(flag, s)
591c42de6dSgd #define	GPTWO_DEBUG1(level, flag, fmt, a1) if (gptwo_cpu_debug >= level) \
601c42de6dSgd     debug(fmt, (uintptr_t)(a1), 0, 0, 0, 0);
611c42de6dSgd #define	GPTWO_DEBUG2(level, flag, fmt, a1, a2) if (gptwo_cpu_debug >= level) \
621c42de6dSgd     debug(fmt, (uintptr_t)(a1), (uintptr_t)(a2), 0, 0, 0);
631c42de6dSgd #define	GPTWO_DEBUG3(level, flag, fmt, a1, a2, a3) \
641c42de6dSgd     if (gptwo_cpu_debug >= level) \
651c42de6dSgd     debug(fmt, (uintptr_t)(a1), (uintptr_t)(a2), (uintptr_t)(a3), 0, 0);
661c42de6dSgd #else
671c42de6dSgd #define	GPTWO_DEBUG0(level, flag, s)
681c42de6dSgd #define	GPTWO_DEBUG1(level, flag, fmt, a1)
691c42de6dSgd #define	GPTWO_DEBUG2(level, flag, fmt, a1, a2)
701c42de6dSgd #define	GPTWO_DEBUG3(level, flag, fmt, a1, a2, a3)
711c42de6dSgd #endif
721c42de6dSgd 
731c42de6dSgd /*
741c42de6dSgd  * Devinfo branch create arg
751c42de6dSgd  */
761c42de6dSgd struct bca {
771c42de6dSgd 	spcd_t *pcd;
781c42de6dSgd 	uint_t portid;
791c42de6dSgd 	uint_t cpuid;
801c42de6dSgd 	uint_t coreid;
811c42de6dSgd 	uint_t impl;
821c42de6dSgd 	dev_info_t *new_child;
831c42de6dSgd };
841c42de6dSgd 
851c42de6dSgd static dev_info_t *gptwocfg_create_cpu_node(dev_info_t *, spcd_t *,
861c42de6dSgd     uint_t, uint_t, uint_t, uint_t);
871c42de6dSgd static dev_info_t *gptwocfg_create_mc_node(dev_info_t *, spcd_t *, uint_t);
881c42de6dSgd static dev_info_t *gptwocfg_create_cmp_node(dev_info_t *, spcd_t *, uint_t);
891c42de6dSgd static int gptwocfg_create_core_node(dev_info_t *, spcd_t *, uint_t, uint_t);
901c42de6dSgd static int set_mc_props(dev_info_t *new_child, void *arg, uint_t flags);
911c42de6dSgd static int set_cmp_props(dev_info_t *new_child, void *arg, uint_t flags);
921c42de6dSgd static int set_cpu_props(dev_info_t *new_child, void *arg, uint_t flags);
931c42de6dSgd static int set_cpu_common_props(dev_info_t *new_child, struct bca *bcp);
941c42de6dSgd static int set_cpu_us3_props(dev_info_t *new_child, struct bca *bcp);
951c42de6dSgd static int set_cpu_us4_props(dev_info_t *new_child, struct bca *bcp);
961c42de6dSgd static void get_new_child(dev_info_t *rdip, void *arg, uint_t flags);
971c42de6dSgd 
981c42de6dSgd 
991c42de6dSgd /*
1001c42de6dSgd  * Module linkage information for the kernel.
1011c42de6dSgd  */
1021c42de6dSgd 
1031c42de6dSgd extern struct mod_ops mod_miscops;
1041c42de6dSgd 
1051c42de6dSgd static struct modlmisc modlmisc = {
1061c42de6dSgd 	&mod_miscops, /* Type of module */
107*88294e09SRichard Bean 	"gptwo->cpu configurator",
1081c42de6dSgd };
1091c42de6dSgd 
1101c42de6dSgd static struct modlinkage modlinkage = {
1111c42de6dSgd 	MODREV_1, (void *)&modlmisc, NULL
1121c42de6dSgd };
1131c42de6dSgd 
1141c42de6dSgd int
_init(void)1151c42de6dSgd _init(void)
1161c42de6dSgd {
1171c42de6dSgd 	int err = 0;
1181c42de6dSgd 
1191c42de6dSgd 	/* register device with the configurator */
1201c42de6dSgd 	gptwocfg_register_ops(SAFPTYPE_CPU, gptwocfg_configure_cpu, NULL);
1211c42de6dSgd 
1221c42de6dSgd 	if ((err = mod_install(&modlinkage)) != 0) {
1231c42de6dSgd 		GPTWO_DEBUG1(1, CE_WARN, "gptwo_cpu (CPU/MC Functions) "
1241c42de6dSgd 		"failed to load, error=%d\n", err);
1251c42de6dSgd 		gptwocfg_unregister_ops(SAFPTYPE_CPU);
1261c42de6dSgd 	} else {
1271c42de6dSgd 		GPTWO_DEBUG0(1, CE_WARN, "gptwo_cpu (CPU/MC Functions) "
1281c42de6dSgd 		"has been loaded.\n");
1291c42de6dSgd 	}
1301c42de6dSgd 	return (err);
1311c42de6dSgd }
1321c42de6dSgd 
1331c42de6dSgd int
_fini(void)1341c42de6dSgd _fini(void)
1351c42de6dSgd {
1361c42de6dSgd 	/* cleanup/freeup structs with configurator */
1371c42de6dSgd 	gptwocfg_unregister_ops(SAFPTYPE_CPU);
1381c42de6dSgd 	return (mod_remove(&modlinkage));
1391c42de6dSgd }
1401c42de6dSgd 
1411c42de6dSgd int
_info(struct modinfo * modinfop)1421c42de6dSgd _info(struct modinfo *modinfop)
1431c42de6dSgd {
1441c42de6dSgd 	return (mod_info(&modlinkage, modinfop));
1451c42de6dSgd }
1461c42de6dSgd 
1471c42de6dSgd gptwo_new_nodes_t *
gptwocfg_configure_cpu(dev_info_t * ap,spcd_t * pcd,uint_t portid)1481c42de6dSgd gptwocfg_configure_cpu(dev_info_t *ap, spcd_t *pcd, uint_t portid)
1491c42de6dSgd {
1501c42de6dSgd 	dev_info_t *cpu_node[AGENTS_PER_PORT], *mc_node[AGENTS_PER_PORT];
1511c42de6dSgd 	dev_info_t *cmp_node = NULL;
1521c42de6dSgd 	gptwo_new_nodes_t *new_nodes;
1531c42de6dSgd 	int nodes = 0;
1541c42de6dSgd 	int i, j = 0;
1551c42de6dSgd 	uint_t implementation;
1561c42de6dSgd 
1571c42de6dSgd 	GPTWO_DEBUG2(1, CE_CONT, "gptwocfg_configure_cpu: portid=%x pcd=%lx\n",
1581c42de6dSgd 	    portid, pcd);
1591c42de6dSgd 
1601c42de6dSgd 	for (i = 0; i < AGENTS_PER_PORT; i++) {
1611c42de6dSgd 		cpu_node[i] = NULL;
1621c42de6dSgd 		mc_node[i] = NULL;
1631c42de6dSgd 	}
1641c42de6dSgd 
1651c42de6dSgd 	implementation = (pcd->spcd_ver_reg >> 32) & 0x000000000000ffff;
1661c42de6dSgd 
1671c42de6dSgd 	switch (implementation) {
1681c42de6dSgd 	case CHEETAH_IMPL:
1691c42de6dSgd 	case CHEETAH_PLUS_IMPL:
1701c42de6dSgd 	case JAGUAR_IMPL:
1711c42de6dSgd 	case PANTHER_IMPL:
1721c42de6dSgd 		break;
1731c42de6dSgd 	default:
1741c42de6dSgd 		cmn_err(CE_WARN, "Unsupported cpu implementation=0x%x : "
1751c42de6dSgd 		    "skipping configure of portid=0x%x", implementation,
1761c42de6dSgd 		    portid);
1771c42de6dSgd 		ASSERT(0);
1781c42de6dSgd 		return (NULL);
1791c42de6dSgd 	}
1801c42de6dSgd 
1811c42de6dSgd 	if (CPU_IMPL_IS_CMP(implementation)) {
1821c42de6dSgd 		if (cmp_node = gptwocfg_create_cmp_node(ap, pcd, portid))
1831c42de6dSgd 			nodes++;
1841c42de6dSgd 		else
1851c42de6dSgd 			return (NULL);
1861c42de6dSgd 	}
1871c42de6dSgd 
1881c42de6dSgd 	for (i = 0; i < AGENTS_PER_PORT; i++) {
1891c42de6dSgd 		if (pcd->spcd_agent[i] != SPCD_RSV_PASS)
1901c42de6dSgd 			continue;
1911c42de6dSgd 
1921c42de6dSgd 		if (cpu_node[i] = gptwocfg_create_cpu_node(cmp_node ?
1931c42de6dSgd 		    cmp_node : ap, pcd, portid, pcd->spcd_cpuid[i], i,
1941c42de6dSgd 		    implementation)) {
1951c42de6dSgd 			/*
1961c42de6dSgd 			 * If the CPU is a CMP, the entire branch is
1971c42de6dSgd 			 * manipulated using just the top node. Thus,
1981c42de6dSgd 			 * the dips of the individual cores do not need
1991c42de6dSgd 			 * to be held or stored in the new node list.
2001c42de6dSgd 			 */
2011c42de6dSgd 			if (cmp_node) {
2021c42de6dSgd 				e_ddi_branch_rele(cpu_node[i]);
2031c42de6dSgd 			} else {
2041c42de6dSgd 				nodes++;
2051c42de6dSgd 			}
2061c42de6dSgd 		}
2071c42de6dSgd 	}
2081c42de6dSgd 
2091c42de6dSgd 	/* current implementations have 1 MC node per Safari port */
2101c42de6dSgd 	if (pcd->spcd_prsv == SPCD_RSV_PASS &&
2111c42de6dSgd 	    (mc_node[0] = gptwocfg_create_mc_node(ap, pcd, portid)))
2121c42de6dSgd 		nodes++;
2131c42de6dSgd 
2141c42de6dSgd 	new_nodes = gptwocfg_allocate_node_list(nodes);
2151c42de6dSgd 
2161c42de6dSgd 	j = 0;
2171c42de6dSgd 	for (i = 0; i < AGENTS_PER_PORT; i++) {
2181c42de6dSgd 		if ((cpu_node[i] != NULL) && (!CPU_IMPL_IS_CMP(implementation)))
2191c42de6dSgd 			new_nodes->gptwo_nodes[j++] = cpu_node[i];
2201c42de6dSgd 		if (mc_node[i] != NULL)
2211c42de6dSgd 			new_nodes->gptwo_nodes[j++] = mc_node[i];
2221c42de6dSgd 	}
2231c42de6dSgd 
2241c42de6dSgd 	if (cmp_node)
2251c42de6dSgd 		new_nodes->gptwo_nodes[j++] = cmp_node;
2261c42de6dSgd 
2271c42de6dSgd 	return (new_nodes);
2281c42de6dSgd }
2291c42de6dSgd 
2301c42de6dSgd 
2311c42de6dSgd static dev_info_t *
gptwocfg_create_cmp_node(dev_info_t * ap,spcd_t * pcd,uint_t portid)2321c42de6dSgd gptwocfg_create_cmp_node(dev_info_t *ap, spcd_t *pcd, uint_t portid)
2331c42de6dSgd {
2341c42de6dSgd 	struct bca arg;
2351c42de6dSgd 	devi_branch_t b;
2361c42de6dSgd 
2371c42de6dSgd 	arg.pcd = pcd;
2381c42de6dSgd 	arg.portid = portid;
2391c42de6dSgd 	arg.cpuid = 0;
2401c42de6dSgd 	arg.coreid = 0;
2411c42de6dSgd 	arg.new_child = NULL;
2421c42de6dSgd 
2431c42de6dSgd 	b.arg = &arg;
2441c42de6dSgd 	b.type = DEVI_BRANCH_SID;
2451c42de6dSgd 	b.create.sid_branch_create = set_cmp_props;
2461c42de6dSgd 	b.devi_branch_callback = get_new_child;
2471c42de6dSgd 
2481c42de6dSgd 	if (e_ddi_branch_create(ap, &b, NULL, 0))
2491c42de6dSgd 		return (NULL);
2501c42de6dSgd 
2511c42de6dSgd 	return (arg.new_child);
2521c42de6dSgd }
2531c42de6dSgd 
2541c42de6dSgd /*ARGSUSED*/
2551c42de6dSgd static int
set_cmp_props(dev_info_t * new_child,void * arg,uint_t flags)2561c42de6dSgd set_cmp_props(dev_info_t *new_child, void *arg, uint_t flags)
2571c42de6dSgd {
2581c42de6dSgd 	struct bca *bap = (struct bca *)arg;
2591c42de6dSgd 	gptwo_regspec_t	reg;
2601c42de6dSgd 	spcd_t *pcd;
2611c42de6dSgd 	uint_t portid;
2621c42de6dSgd 
2631c42de6dSgd 	pcd = bap->pcd;
2641c42de6dSgd 	portid = bap->portid;
2651c42de6dSgd 
2661c42de6dSgd 	GPTWO_DEBUG2(1, CE_CONT, "set_cmp_props: portid=%x pcd=%lx\n",
2671c42de6dSgd 	    portid, pcd);
2681c42de6dSgd 
2691c42de6dSgd 	if (ndi_prop_update_string(DDI_DEV_T_NONE, new_child,
2701c42de6dSgd 	    "name", "cmp") != DDI_SUCCESS) {
2711c42de6dSgd 		GPTWO_DEBUG0(1, CE_CONT, "set_cmp_props: failed to "
2721c42de6dSgd 		    "create name property\n");
2731c42de6dSgd 		return (DDI_WALK_ERROR);
2741c42de6dSgd 	}
2751c42de6dSgd 
2761c42de6dSgd 	if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child,
2771c42de6dSgd 	    "portid", portid) != DDI_SUCCESS) {
2781c42de6dSgd 		GPTWO_DEBUG0(1, CE_CONT, "set_cmp_props: failed to "
2791c42de6dSgd 		    "create portid property\n");
2801c42de6dSgd 		return (DDI_WALK_ERROR);
2811c42de6dSgd 	}
2821c42de6dSgd 
2831c42de6dSgd 	reg.gptwo_phys_hi = 0x400 | (portid >> 9);
2841c42de6dSgd 	reg.gptwo_phys_low = (portid << 23);
2851c42de6dSgd 	reg.gptwo_size_hi = 0;
2861c42de6dSgd 	reg.gptwo_size_low = 0x10000;
2871c42de6dSgd 
2881c42de6dSgd 	if (ndi_prop_update_int_array(DDI_DEV_T_NONE,
2891c42de6dSgd 	    new_child, "reg", (int *)&reg,
2901c42de6dSgd 	    sizeof (gptwo_regspec_t) / sizeof (int)) != DDI_SUCCESS) {
2911c42de6dSgd 		GPTWO_DEBUG0(1, CE_CONT, "set_cmp_props: failed to "
2921c42de6dSgd 		    "create reg property\n");
2931c42de6dSgd 		return (DDI_WALK_ERROR);
2941c42de6dSgd 	}
2951c42de6dSgd 
2961c42de6dSgd 	return (DDI_WALK_TERMINATE);
2971c42de6dSgd }
2981c42de6dSgd 
2991c42de6dSgd static dev_info_t *
gptwocfg_create_cpu_node(dev_info_t * ap,spcd_t * pcd,uint_t portid,uint_t cpuid,uint_t coreid,uint_t impl)3001c42de6dSgd gptwocfg_create_cpu_node(dev_info_t *ap, spcd_t *pcd, uint_t portid,
3011c42de6dSgd     uint_t cpuid, uint_t coreid, uint_t impl)
3021c42de6dSgd {
3031c42de6dSgd 	struct bca arg;
3041c42de6dSgd 	devi_branch_t b = {0};
3051c42de6dSgd 
3061c42de6dSgd 	arg.pcd = pcd;
3071c42de6dSgd 	arg.portid = portid;
3081c42de6dSgd 	arg.cpuid = cpuid;
3091c42de6dSgd 	arg.coreid = coreid;
3101c42de6dSgd 	arg.impl = impl;
3111c42de6dSgd 	arg.new_child = NULL;
3121c42de6dSgd 
3131c42de6dSgd 	b.arg = &arg;
3141c42de6dSgd 	b.type = DEVI_BRANCH_SID;
3151c42de6dSgd 	b.create.sid_branch_create = set_cpu_props;
3161c42de6dSgd 	b.devi_branch_callback = get_new_child;
3171c42de6dSgd 
3181c42de6dSgd 	if (e_ddi_branch_create(ap, &b, NULL, 0))
3191c42de6dSgd 		return (NULL);
3201c42de6dSgd 
3211c42de6dSgd 	return (arg.new_child);
3221c42de6dSgd }
3231c42de6dSgd 
3241c42de6dSgd /*ARGSUSED*/
3251c42de6dSgd static int
set_cpu_props(dev_info_t * new_child,void * arg,uint_t flags)3261c42de6dSgd set_cpu_props(dev_info_t *new_child, void *arg, uint_t flags)
3271c42de6dSgd {
3281c42de6dSgd 	struct bca *bcp = arg;
3291c42de6dSgd 	uint_t impl = bcp->impl;
3301c42de6dSgd 	int rc;
3311c42de6dSgd 
3321c42de6dSgd 	if (set_cpu_common_props(new_child, bcp) != DDI_WALK_CONTINUE)
3331c42de6dSgd 		return (DDI_WALK_ERROR);
3341c42de6dSgd 
3351c42de6dSgd 	switch (impl) {
3361c42de6dSgd 	case CHEETAH_IMPL:
3371c42de6dSgd 	case CHEETAH_PLUS_IMPL:
3381c42de6dSgd 		rc = set_cpu_us3_props(new_child, bcp);
3391c42de6dSgd 		break;
3401c42de6dSgd 	case JAGUAR_IMPL:
3411c42de6dSgd 	case PANTHER_IMPL:
3421c42de6dSgd 		rc = set_cpu_us4_props(new_child, bcp);
3431c42de6dSgd 		break;
3441c42de6dSgd 	default:
3451c42de6dSgd 		ASSERT(0);
3461c42de6dSgd 		return (DDI_WALK_ERROR);
3471c42de6dSgd 	}
3481c42de6dSgd 
3491c42de6dSgd 	return (rc);
3501c42de6dSgd }
3511c42de6dSgd 
3521c42de6dSgd /*
3531c42de6dSgd  * Set properties common to cpu (non-CMP) and core (CMP) nodes.
3541c42de6dSgd  *
3551c42de6dSgd  *	cpuid
3561c42de6dSgd  * 	device_type
3571c42de6dSgd  *	manufacturer#
3581c42de6dSgd  * 	implementation#
3591c42de6dSgd  *	mask#
3601c42de6dSgd  *	sparc-version
3611c42de6dSgd  * 	clock-frequency
3621c42de6dSgd  *	#dtlb-entries
3631c42de6dSgd  *	#itlb-entries
3641c42de6dSgd  */
3651c42de6dSgd static int
set_cpu_common_props(dev_info_t * new_child,struct bca * bcp)3661c42de6dSgd set_cpu_common_props(dev_info_t *new_child, struct bca *bcp)
3671c42de6dSgd {
3681c42de6dSgd 	uint_t	cpuid, impl;
3691c42de6dSgd 	spcd_t	*pcd;
3701c42de6dSgd 	int	mask, manufacturer;
3711c42de6dSgd 
3721c42de6dSgd 	cpuid = bcp->cpuid;
3731c42de6dSgd 	pcd = bcp->pcd;
3741c42de6dSgd 	impl = bcp->impl;
3751c42de6dSgd 
3761c42de6dSgd 	mask = (pcd->spcd_ver_reg >> 24) & 0x00000000000000ff;
3771c42de6dSgd 	manufacturer = (pcd->spcd_ver_reg >> 48) & 0x000000000000ffff;
3781c42de6dSgd 
3791c42de6dSgd 	if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child,
3801c42de6dSgd 	    "cpuid", cpuid) != DDI_SUCCESS) {
3811c42de6dSgd 		GPTWO_DEBUG0(1, CE_CONT, "set_cpu_common_props: failed "
3821c42de6dSgd 		    "to create cpuid property\n");
3831c42de6dSgd 		return (DDI_WALK_ERROR);
3841c42de6dSgd 	}
3851c42de6dSgd 
3861c42de6dSgd 	if (ndi_prop_update_string(DDI_DEV_T_NONE, new_child,
3871c42de6dSgd 	    "device_type", "cpu") != DDI_SUCCESS) {
3881c42de6dSgd 		GPTWO_DEBUG0(1, CE_CONT, "set_cpu_common_props: failed "
3891c42de6dSgd 		    "to create device_type property\n");
3901c42de6dSgd 		return (DDI_WALK_ERROR);
3911c42de6dSgd 	}
3921c42de6dSgd 
3931c42de6dSgd 	if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child, "manufacturer#",
3941c42de6dSgd 	    manufacturer) != DDI_SUCCESS) {
3951c42de6dSgd 		GPTWO_DEBUG0(1, CE_CONT, "set_cpu_common_props: failed "
3961c42de6dSgd 		    "to create manufacturer# property\n");
3971c42de6dSgd 		return (DDI_WALK_ERROR);
3981c42de6dSgd 	}
3991c42de6dSgd 
4001c42de6dSgd 	if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child, "implementation#",
4011c42de6dSgd 	    impl) != DDI_SUCCESS) {
4021c42de6dSgd 		GPTWO_DEBUG0(1, CE_CONT, "set_cpu_common_props: failed "
4031c42de6dSgd 		    "to create implementation# property\n");
4041c42de6dSgd 		return (DDI_WALK_ERROR);
4051c42de6dSgd 	}
4061c42de6dSgd 
4071c42de6dSgd 	if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child, "mask#",
4081c42de6dSgd 	    mask) != DDI_SUCCESS) {
4091c42de6dSgd 		GPTWO_DEBUG0(1, CE_CONT, "set_cpu_common_props: failed "
4101c42de6dSgd 		    "to create mask# property\n");
4111c42de6dSgd 		return (DDI_WALK_ERROR);
4121c42de6dSgd 	}
4131c42de6dSgd 
4141c42de6dSgd 	if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child,
4151c42de6dSgd 	    "sparc-version", 9) != DDI_SUCCESS) {
4161c42de6dSgd 		GPTWO_DEBUG0(1, CE_CONT, "set_cpu_common_props: failed "
4171c42de6dSgd 		    "to create sparc-version property\n");
4181c42de6dSgd 		return (DDI_WALK_ERROR);
4191c42de6dSgd 	}
4201c42de6dSgd 
4211c42de6dSgd 	if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child,
4221c42de6dSgd 	    "clock-frequency", (pcd->spcd_afreq * 1000000)) != DDI_SUCCESS) {
4231c42de6dSgd 		GPTWO_DEBUG0(1, CE_CONT, "set_cpu_common_props: failed "
4241c42de6dSgd 		    "to create clock-frequency property\n");
4251c42de6dSgd 		return (DDI_WALK_ERROR);
4261c42de6dSgd 	}
4271c42de6dSgd 
4281c42de6dSgd 	if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child,
4291c42de6dSgd 	    "#dtlb-entries", 0x10) != DDI_SUCCESS) {
4301c42de6dSgd 		GPTWO_DEBUG0(1, CE_CONT, "set_cpu_common_props: failed "
4311c42de6dSgd 		    "to create #dtlb-entries property\n");
4321c42de6dSgd 		return (DDI_WALK_ERROR);
4331c42de6dSgd 	}
4341c42de6dSgd 
4351c42de6dSgd 	if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child,
4361c42de6dSgd 	    "#itlb-entries", 0x10) != DDI_SUCCESS) {
4371c42de6dSgd 		GPTWO_DEBUG0(1, CE_CONT, "set_cpu_common_props: failed "
4381c42de6dSgd 		    "to create #itlb-entries property\n");
4391c42de6dSgd 		return (DDI_WALK_ERROR);
4401c42de6dSgd 	}
4411c42de6dSgd 
4421c42de6dSgd 	return (DDI_WALK_CONTINUE);
4431c42de6dSgd }
4441c42de6dSgd 
4451c42de6dSgd /*
4461c42de6dSgd  * Set cpu node properties for Cheetah and Cheetah+.
4471c42de6dSgd  *
4481c42de6dSgd  *	name
4491c42de6dSgd  * 	portid
4501c42de6dSgd  * 	reg
4511c42de6dSgd  * 	icache-size
4521c42de6dSgd  * 	icache-line-size
4531c42de6dSgd  *	icache-associativity
4541c42de6dSgd  *	dcache-size
4551c42de6dSgd  *	dcache-line-size
4561c42de6dSgd  *	dcache-associativity
4571c42de6dSgd  *	ecache-size
4581c42de6dSgd  *	ecache-line-size
4591c42de6dSgd  *	ecache-associativity
4601c42de6dSgd  */
4611c42de6dSgd static int
set_cpu_us3_props(dev_info_t * new_child,struct bca * bcp)4621c42de6dSgd set_cpu_us3_props(dev_info_t *new_child, struct bca *bcp)
4631c42de6dSgd {
4641c42de6dSgd 	char *node_name;
4651c42de6dSgd 	gptwo_regspec_t	reg;
4661c42de6dSgd 	int ecache_size, ecache_line_size;
4671c42de6dSgd 	int dimms, ecache_assoc;
4681c42de6dSgd 	spcd_t *pcd;
4691c42de6dSgd 	uint_t portid, impl;
4701c42de6dSgd 
4711c42de6dSgd 	pcd = bcp->pcd;
4721c42de6dSgd 	portid = bcp->portid;
4731c42de6dSgd 	impl = bcp->impl;
4741c42de6dSgd 
4751c42de6dSgd 	ASSERT(IS_CHEETAH(impl) || IS_CHEETAH_PLUS(impl));
4761c42de6dSgd 
4771c42de6dSgd 	switch (impl) {
4781c42de6dSgd 	case CHEETAH_IMPL:
4791c42de6dSgd 		ecache_assoc = CH_ECACHE_NWAY;
4801c42de6dSgd 		node_name = "SUNW,UltraSPARC-III";
4811c42de6dSgd 		break;
4821c42de6dSgd 	case CHEETAH_PLUS_IMPL:
4831c42de6dSgd 		/*
4841c42de6dSgd 		 * Hard coding the ecache-associativity to 2 for Cheetah+.
4851c42de6dSgd 		 * We probably should add this to the PCD.
4861c42de6dSgd 		 */
4871c42de6dSgd 		ecache_assoc = CHP_ECACHE_NWAY;
4881c42de6dSgd 		node_name = "SUNW,UltraSPARC-III+";
4891c42de6dSgd 		break;
4901c42de6dSgd 	default:
4911c42de6dSgd 		GPTWO_DEBUG1(1, CE_CONT, "set_cpu_us3_props: invalid "
4921c42de6dSgd 		    "implementation=0x%x\n", impl);
4931c42de6dSgd 		return (DDI_WALK_ERROR);
4941c42de6dSgd 	}
4951c42de6dSgd 
4961c42de6dSgd 	if (ndi_prop_update_string(DDI_DEV_T_NONE, new_child,
4971c42de6dSgd 	    "name", node_name) != DDI_SUCCESS) {
4981c42de6dSgd 		GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us3_props: failed "
4991c42de6dSgd 		    "to create name property\n");
5001c42de6dSgd 		return (DDI_WALK_ERROR);
5011c42de6dSgd 	}
5021c42de6dSgd 
5031c42de6dSgd 	if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child,
5041c42de6dSgd 	    "portid", portid) != DDI_SUCCESS) {
5051c42de6dSgd 		GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us3_props: failed "
5061c42de6dSgd 		    "to create portid property\n");
5071c42de6dSgd 		return (DDI_WALK_ERROR);
5081c42de6dSgd 	}
5091c42de6dSgd 
5101c42de6dSgd 	reg.gptwo_phys_hi = 0x400 | (portid >> 9);
5111c42de6dSgd 	reg.gptwo_phys_low = (portid << 23);
5121c42de6dSgd 	reg.gptwo_size_hi = 0;
5131c42de6dSgd 	reg.gptwo_size_low = 0x10000;
5141c42de6dSgd 
5151c42de6dSgd 	if (ndi_prop_update_int_array(DDI_DEV_T_NONE,
5161c42de6dSgd 	    new_child, "reg", (int *)&reg,
5171c42de6dSgd 	    sizeof (gptwo_regspec_t) / sizeof (int)) != DDI_SUCCESS) {
5181c42de6dSgd 		GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us3_props: failed "
5191c42de6dSgd 		    "to create reg property\n");
5201c42de6dSgd 		return (DDI_WALK_ERROR);
5211c42de6dSgd 	}
5221c42de6dSgd 
5231c42de6dSgd 	if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child,
5241c42de6dSgd 	    "icache-size", CH_ICACHE_SIZE) != DDI_SUCCESS) {
5251c42de6dSgd 		GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us3_props: failed "
5261c42de6dSgd 		    "to create icache-size property\n");
5271c42de6dSgd 		return (DDI_WALK_ERROR);
5281c42de6dSgd 	}
5291c42de6dSgd 
5301c42de6dSgd 	if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child,
5311c42de6dSgd 	    "icache-line-size", CH_ICACHE_LSIZE) != DDI_SUCCESS) {
5321c42de6dSgd 		GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us3_props: failed "
5331c42de6dSgd 		    "to create icache-line-size property\n");
5341c42de6dSgd 		return (DDI_WALK_ERROR);
5351c42de6dSgd 	}
5361c42de6dSgd 
5371c42de6dSgd 	if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child,
5381c42de6dSgd 	    "icache-associativity", CH_ICACHE_NWAY) != DDI_SUCCESS) {
5391c42de6dSgd 		GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us3_props: failed "
5401c42de6dSgd 		    "to create icache-associativity property\n");
5411c42de6dSgd 		return (DDI_WALK_ERROR);
5421c42de6dSgd 	}
5431c42de6dSgd 
5441c42de6dSgd 	if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child,
5451c42de6dSgd 	    "dcache-size", CH_DCACHE_SIZE) != DDI_SUCCESS) {
5461c42de6dSgd 		GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us3_props: failed "
5471c42de6dSgd 		    "to create dcache-size property\n");
5481c42de6dSgd 		return (DDI_WALK_ERROR);
5491c42de6dSgd 	}
5501c42de6dSgd 
5511c42de6dSgd 	if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child,
5521c42de6dSgd 	    "dcache-line-size", CH_DCACHE_LSIZE) != DDI_SUCCESS) {
5531c42de6dSgd 		GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us3_props: failed "
5541c42de6dSgd 		    "to create dcache-line-size property\n");
5551c42de6dSgd 		return (DDI_WALK_ERROR);
5561c42de6dSgd 	}
5571c42de6dSgd 
5581c42de6dSgd 	if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child,
5591c42de6dSgd 	    "dcache-associativity", CH_DCACHE_NWAY) != DDI_SUCCESS) {
5601c42de6dSgd 		GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us3_props: failed "
5611c42de6dSgd 		    "to create dcache-associativity property\n");
5621c42de6dSgd 		return (DDI_WALK_ERROR);
5631c42de6dSgd 	}
5641c42de6dSgd 
5651c42de6dSgd 	/*
5661c42de6dSgd 	 * Get the External Cache Size from the Common PCD.
5671c42de6dSgd 	 */
5681c42de6dSgd 	ecache_size = pcd->spcd_cache * 0x100000;
5691c42de6dSgd 
5701c42de6dSgd 	if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child,
5711c42de6dSgd 	    "ecache-size", ecache_size) != DDI_SUCCESS) {
5721c42de6dSgd 		GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us3_props: failed "
5731c42de6dSgd 		    "to create ecache-line-size property\n");
5741c42de6dSgd 		return (DDI_WALK_ERROR);
5751c42de6dSgd 	}
5761c42de6dSgd 
5771c42de6dSgd 	switch (ecache_size) {
5781c42de6dSgd 	case CH_ECACHE_1M_SIZE:
5791c42de6dSgd 		ecache_line_size = 64;
5801c42de6dSgd 		break;
5811c42de6dSgd 	case CH_ECACHE_4M_SIZE:
5821c42de6dSgd 		ecache_line_size = 256;
5831c42de6dSgd 		break;
5841c42de6dSgd 	case CH_ECACHE_8M_SIZE:
5851c42de6dSgd 		ecache_line_size = 512;
5861c42de6dSgd 		break;
5871c42de6dSgd 	default:
5881c42de6dSgd 		GPTWO_DEBUG1(1, CE_CONT, "set_cpu_us3_props: invalid "
5891c42de6dSgd 		    "ecache-size 0x%x\b", ecache_size);
5901c42de6dSgd 		return (DDI_WALK_ERROR);
5911c42de6dSgd 	}
5921c42de6dSgd 
5931c42de6dSgd 	if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child,
5941c42de6dSgd 	    "ecache-line-size", ecache_line_size) != DDI_SUCCESS) {
5951c42de6dSgd 		GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us3_props: failed "
5961c42de6dSgd 		    "to create ecache-line-size property\n");
5971c42de6dSgd 		return (DDI_WALK_ERROR);
5981c42de6dSgd 	}
5991c42de6dSgd 
6001c42de6dSgd 	if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child,
6011c42de6dSgd 	    "ecache-associativity", ecache_assoc) != DDI_SUCCESS) {
6021c42de6dSgd 		GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us3_props: failed "
6031c42de6dSgd 		    "to create ecache-associativity property\n");
6041c42de6dSgd 		return (DDI_WALK_ERROR);
6051c42de6dSgd 	}
6061c42de6dSgd 
6071c42de6dSgd 	/*
6081c42de6dSgd 	 * Create the ecache-dimm-label property.
6091c42de6dSgd 	 */
6101c42de6dSgd 	dimms = 0;
6111c42de6dSgd 
6121c42de6dSgd 	while ((pcd->sprd_ecache_dimm_label[dimms] != NULL) &&
6131c42de6dSgd 	    (dimms < MAX_DIMMS_PER_PORT))
6141c42de6dSgd 		dimms++;
6151c42de6dSgd 
6161c42de6dSgd 	if (dimms) {
6171c42de6dSgd 		(void) ndi_prop_update_string_array(DDI_DEV_T_NONE, new_child,
6181c42de6dSgd 		    "ecache-dimm-label", (char **)pcd->sprd_ecache_dimm_label,
6191c42de6dSgd 		    dimms);
6201c42de6dSgd 	}
6211c42de6dSgd 
6221c42de6dSgd 	return (DDI_WALK_TERMINATE);
6231c42de6dSgd }
6241c42de6dSgd 
6251c42de6dSgd /*
6261c42de6dSgd  * Set cmp core node properties for Jaguar and Panther.
6271c42de6dSgd  *
6281c42de6dSgd  * 	name
6291c42de6dSgd  * 	compatible
6301c42de6dSgd  * 	reg
6311c42de6dSgd  *	l1-icache-size
6321c42de6dSgd  *	l1-icache-line-size
6331c42de6dSgd  *	l1-icache-associativity
6341c42de6dSgd  *	l1-dcache-size
6351c42de6dSgd  *	l1-dcache-line-size
6361c42de6dSgd  *	l1-dcache-associativity
6371c42de6dSgd  *	l2-cache-size
6381c42de6dSgd  *	l2-cache-line-size
6391c42de6dSgd  *	l2-cache-associativity
6401c42de6dSgd  *	l2-cache-sharing
6411c42de6dSgd  *	l3-cache-size
6421c42de6dSgd  *	l3-cache-line-size
6431c42de6dSgd  *	l3-cache-associativity
6441c42de6dSgd  *	l3-cache-sharing
6451c42de6dSgd  */
6461c42de6dSgd static int
set_cpu_us4_props(dev_info_t * new_child,struct bca * bcp)6471c42de6dSgd set_cpu_us4_props(dev_info_t *new_child, struct bca *bcp)
6481c42de6dSgd {
6491c42de6dSgd 	uint_t l1_icache_size, l1_icache_line_size;
6501c42de6dSgd 	uint_t l2_cache_size, l2_cache_line_size, l2_cache_assoc;
6511c42de6dSgd 	uint_t l2_cache_share;
6521c42de6dSgd 	uint_t pcd_cache_size;
6531c42de6dSgd 	uint_t coreid, impl;
6541c42de6dSgd 	spcd_t *pcd;
6551c42de6dSgd 	char *compatible;
6561c42de6dSgd 	int dimms;
6571c42de6dSgd 	int i;
6581c42de6dSgd 
6591c42de6dSgd 	pcd = bcp->pcd;
6601c42de6dSgd 	coreid = bcp->coreid;
6611c42de6dSgd 	impl = bcp->impl;
6621c42de6dSgd 
6631c42de6dSgd 	ASSERT(IS_JAGUAR(impl) || IS_PANTHER(impl));
6641c42de6dSgd 
6651c42de6dSgd 	/*
6661c42de6dSgd 	 * Get the External Cache Size from the Common PCD.
6671c42de6dSgd 	 */
6681c42de6dSgd 	pcd_cache_size = pcd->spcd_cache * 0x100000;
6691c42de6dSgd 
6701c42de6dSgd 	switch (impl) {
6711c42de6dSgd 	case JAGUAR_IMPL:
6721c42de6dSgd 		compatible = "SUNW,UltraSPARC-IV";
6731c42de6dSgd 		l1_icache_size = CH_ICACHE_SIZE;
6741c42de6dSgd 		l1_icache_line_size = CH_ICACHE_LSIZE;
6751c42de6dSgd 		l2_cache_assoc = CHP_ECACHE_NWAY;
6761c42de6dSgd 
6771c42de6dSgd 		/*
6781c42de6dSgd 		 * Jaguar has no logical sharing of L2 cache, so the sharing
6791c42de6dSgd 		 * bit-map will represent this core only.
6801c42de6dSgd 		 */
6811c42de6dSgd 		l2_cache_share = coreid ? 0x2 : 0x1;
6821c42de6dSgd 
6831c42de6dSgd 		/*
6841c42de6dSgd 		 * Jaguar has a split ecache, so the total ecache must be
6851c42de6dSgd 		 * divided in half to get the ecache for the individual core.
6861c42de6dSgd 		 */
6871c42de6dSgd 		l2_cache_size = pcd_cache_size / 2;
6881c42de6dSgd 
6891c42de6dSgd 		switch (l2_cache_size) {
6901c42de6dSgd 		case JG_ECACHE_4M_SIZE:
6911c42de6dSgd 			l2_cache_line_size = 64;
6921c42de6dSgd 			break;
6931c42de6dSgd 		case JG_ECACHE_8M_SIZE:
6941c42de6dSgd 			l2_cache_line_size = 128;
6951c42de6dSgd 			break;
6961c42de6dSgd 		default:
6971c42de6dSgd 			GPTWO_DEBUG1(1, CE_CONT, "set_cpu_us4_props: "
6981c42de6dSgd 			    "invalid l2_cache-size 0x%x\n", l2_cache_size);
6991c42de6dSgd 			return (DDI_WALK_ERROR);
7001c42de6dSgd 		}
7011c42de6dSgd 		break;
7021c42de6dSgd 	case PANTHER_IMPL:
7031c42de6dSgd 		ASSERT(pcd_cache_size == PN_L3_SIZE);
7041c42de6dSgd 		compatible = "SUNW,UltraSPARC-IV+";
7051c42de6dSgd 		l1_icache_size = PN_ICACHE_SIZE;
7061c42de6dSgd 		l1_icache_line_size = PN_ICACHE_LSIZE;
7071c42de6dSgd 		l2_cache_size = PN_L2_SIZE;
7081c42de6dSgd 		l2_cache_line_size = PN_L2_LINESIZE;
7091c42de6dSgd 		l2_cache_assoc = PN_ECACHE_NWAY;
7101c42de6dSgd 
7111c42de6dSgd 		/*
7121c42de6dSgd 		 * For Panther, the L2 and L3 caches are logically shared by
7131c42de6dSgd 		 * all enabled cores, so the sharing bit-map will represent
7141c42de6dSgd 		 * all enabled cores.  Panther split-mode is still considered
7151c42de6dSgd 		 * shared.
7161c42de6dSgd 		 *
7171c42de6dSgd 		 * Check the PCD status to determine enabled cores.
7181c42de6dSgd 		 */
7191c42de6dSgd 		ASSERT(pcd->spcd_ptype == SAFPTYPE_CPU);
7201c42de6dSgd 		l2_cache_share = 0;
7211c42de6dSgd 		for (i = 0; i < AGENTS_PER_PORT; i++) {
7221c42de6dSgd 			if (pcd->spcd_agent[i] == SPCD_RSV_PASS) {
7231c42de6dSgd 				l2_cache_share |= (1 << i);
7241c42de6dSgd 			}
7251c42de6dSgd 		}
7261c42de6dSgd 
7271c42de6dSgd 		break;
7281c42de6dSgd 	default:
7291c42de6dSgd 		GPTWO_DEBUG1(1, CE_CONT, "set_cpu_us4_props: invalid "
7301c42de6dSgd 		    "implementation=0x%x\n", impl);
7311c42de6dSgd 		return (DDI_WALK_ERROR);
7321c42de6dSgd 	}
7331c42de6dSgd 
7341c42de6dSgd 	if (ndi_prop_update_string(DDI_DEV_T_NONE, new_child,
7351c42de6dSgd 	    "name", "cpu") != DDI_SUCCESS) {
7361c42de6dSgd 		GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us4_props: failed "
7371c42de6dSgd 		    "to create name property\n");
7381c42de6dSgd 		return (DDI_WALK_ERROR);
7391c42de6dSgd 	}
7401c42de6dSgd 
7411c42de6dSgd 	if (ndi_prop_update_string(DDI_DEV_T_NONE, new_child,
7421c42de6dSgd 	    "compatible", compatible) != DDI_SUCCESS) {
7431c42de6dSgd 		GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us4_props: failed "
7441c42de6dSgd 		    "to create compatible property\n");
7451c42de6dSgd 		return (DDI_WALK_ERROR);
7461c42de6dSgd 	}
7471c42de6dSgd 
7481c42de6dSgd 	if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child,
7491c42de6dSgd 	    "reg", coreid) != DDI_SUCCESS) {
7501c42de6dSgd 		GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us4_props: failed "
7511c42de6dSgd 		    "to create reg property\n");
7521c42de6dSgd 		return (DDI_WALK_ERROR);
7531c42de6dSgd 	}
7541c42de6dSgd 
7551c42de6dSgd 	if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child,
7561c42de6dSgd 	    "l1-icache-size", l1_icache_size) != DDI_SUCCESS) {
7571c42de6dSgd 		GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us4_props: failed "
7581c42de6dSgd 		    "to create l1-icache-size property\n");
7591c42de6dSgd 		return (DDI_WALK_ERROR);
7601c42de6dSgd 	}
7611c42de6dSgd 
7621c42de6dSgd 	if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child,
7631c42de6dSgd 	    "l1-icache-line-size", l1_icache_line_size) != DDI_SUCCESS) {
7641c42de6dSgd 		GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us4_props: failed "
7651c42de6dSgd 		    "to create icache-line-size property\n");
7661c42de6dSgd 		return (DDI_WALK_ERROR);
7671c42de6dSgd 	}
7681c42de6dSgd 
7691c42de6dSgd 	if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child,
7701c42de6dSgd 	    "l1-icache-associativity", CH_ICACHE_NWAY) != DDI_SUCCESS) {
7711c42de6dSgd 		GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us4_props: failed "
7721c42de6dSgd 		    "to create l1-icache-associativity property\n");
7731c42de6dSgd 		return (DDI_WALK_ERROR);
7741c42de6dSgd 	}
7751c42de6dSgd 
7761c42de6dSgd 	if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child,
7771c42de6dSgd 	    "l1-dcache-size", CH_DCACHE_SIZE) != DDI_SUCCESS) {
7781c42de6dSgd 		GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us4_props: failed "
7791c42de6dSgd 		    "to create l1-dcache-size property\n");
7801c42de6dSgd 		return (DDI_WALK_ERROR);
7811c42de6dSgd 	}
7821c42de6dSgd 
7831c42de6dSgd 	if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child,
7841c42de6dSgd 	    "l1-dcache-line-size", CH_DCACHE_LSIZE) != DDI_SUCCESS) {
7851c42de6dSgd 		GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us4_props: failed "
7861c42de6dSgd 		    "to create dcache-line-size property\n");
7871c42de6dSgd 		return (DDI_WALK_ERROR);
7881c42de6dSgd 	}
7891c42de6dSgd 
7901c42de6dSgd 	if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child,
7911c42de6dSgd 	    "l1-dcache-associativity", CH_DCACHE_NWAY) != DDI_SUCCESS) {
7921c42de6dSgd 		GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us4_props: failed "
7931c42de6dSgd 		    "to create l1-dcache-associativity property\n");
7941c42de6dSgd 		return (DDI_WALK_ERROR);
7951c42de6dSgd 	}
7961c42de6dSgd 
7971c42de6dSgd 	if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child,
7981c42de6dSgd 	    "l2-cache-size", l2_cache_size) != DDI_SUCCESS) {
7991c42de6dSgd 		GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us4_props: failed "
8001c42de6dSgd 		    "to create l2-cache-size property\n");
8011c42de6dSgd 		return (DDI_WALK_ERROR);
8021c42de6dSgd 	}
8031c42de6dSgd 
8041c42de6dSgd 	if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child,
8051c42de6dSgd 	    "l2-cache-line-size", l2_cache_line_size) != DDI_SUCCESS) {
8061c42de6dSgd 		GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us4_props: failed "
8071c42de6dSgd 		    "to create l2_cache-line-size property\n");
8081c42de6dSgd 		return (DDI_WALK_ERROR);
8091c42de6dSgd 	}
8101c42de6dSgd 
8111c42de6dSgd 	if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child,
8121c42de6dSgd 	    "l2-cache-associativity", l2_cache_assoc) != DDI_SUCCESS) {
8131c42de6dSgd 		GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us4_props: failed "
8141c42de6dSgd 		    "to create l2-cache-associativity property\n");
8151c42de6dSgd 		return (DDI_WALK_ERROR);
8161c42de6dSgd 	}
8171c42de6dSgd 
8181c42de6dSgd 	if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child,
8191c42de6dSgd 	    "l2-cache-sharing", l2_cache_share) != DDI_SUCCESS) {
8201c42de6dSgd 		GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us4_props: failed "
8211c42de6dSgd 		    "to create l2-cache-sharing property\n");
8221c42de6dSgd 		return (DDI_WALK_ERROR);
8231c42de6dSgd 	}
8241c42de6dSgd 
8251c42de6dSgd 	/*
8261c42de6dSgd 	 * Create the ecache-dimm-label property.
8271c42de6dSgd 	 */
8281c42de6dSgd 	dimms = 0;
8291c42de6dSgd 
8301c42de6dSgd 	while ((pcd->sprd_ecache_dimm_label[dimms] != NULL) &&
8311c42de6dSgd 	    (dimms < MAX_DIMMS_PER_PORT))
8321c42de6dSgd 		dimms++;
8331c42de6dSgd 
8341c42de6dSgd 	if (dimms) {
8351c42de6dSgd 		(void) ndi_prop_update_string_array(DDI_DEV_T_NONE, new_child,
8361c42de6dSgd 		    "ecache-dimm-label", (char **)pcd->sprd_ecache_dimm_label,
8371c42de6dSgd 		    dimms);
8381c42de6dSgd 	}
8391c42de6dSgd 
8401c42de6dSgd 	if (IS_PANTHER(impl)) {
8411c42de6dSgd 		int l3_cache_share = l2_cache_share;
8421c42de6dSgd 
8431c42de6dSgd 		if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child,
8441c42de6dSgd 		    "l3-cache-size", PN_L3_SIZE) != DDI_SUCCESS) {
8451c42de6dSgd 			GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us4_props: "
8461c42de6dSgd 			    "failed to create l3-cache-size property\n");
8471c42de6dSgd 			return (DDI_WALK_ERROR);
8481c42de6dSgd 		}
8491c42de6dSgd 
8501c42de6dSgd 		if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child,
8511c42de6dSgd 		    "l3-cache-line-size", PN_L3_LINESIZE) != DDI_SUCCESS) {
8521c42de6dSgd 			GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us4_props: "
8531c42de6dSgd 			    "failed to create l3-cache-line-size property\n");
8541c42de6dSgd 			return (DDI_WALK_ERROR);
8551c42de6dSgd 		}
8561c42de6dSgd 
8571c42de6dSgd 		if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child,
8581c42de6dSgd 		    "l3-cache-associativity", PN_ECACHE_NWAY) != DDI_SUCCESS) {
8591c42de6dSgd 			GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us4_props: "
8601c42de6dSgd 			    "failed to create l3-cache-associativity "
8611c42de6dSgd 			    "property\n");
8621c42de6dSgd 			return (DDI_WALK_ERROR);
8631c42de6dSgd 		}
8641c42de6dSgd 
8651c42de6dSgd 		if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child,
8661c42de6dSgd 		    "l3-cache-sharing", l3_cache_share) != DDI_SUCCESS) {
8671c42de6dSgd 			GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us4_props: "
8681c42de6dSgd 			    "failed to create l3-cache-sharing property\n");
8691c42de6dSgd 			return (DDI_WALK_ERROR);
8701c42de6dSgd 		}
8711c42de6dSgd 	}
8721c42de6dSgd 
8731c42de6dSgd 	return (DDI_WALK_TERMINATE);
8741c42de6dSgd }
8751c42de6dSgd 
8761c42de6dSgd static dev_info_t *
gptwocfg_create_mc_node(dev_info_t * ap,spcd_t * pcd,uint_t portid)8771c42de6dSgd gptwocfg_create_mc_node(dev_info_t *ap, spcd_t *pcd, uint_t portid)
8781c42de6dSgd {
8791c42de6dSgd 	struct bca arg;
8801c42de6dSgd 	devi_branch_t b = {0};
8811c42de6dSgd 
8821c42de6dSgd 	arg.pcd = pcd;
8831c42de6dSgd 	arg.portid = portid;
8841c42de6dSgd 	arg.cpuid = portid;
8851c42de6dSgd 	arg.new_child = NULL;
8861c42de6dSgd 
8871c42de6dSgd 	b.arg = &arg;
8881c42de6dSgd 	b.type = DEVI_BRANCH_SID;
8891c42de6dSgd 	b.create.sid_branch_create = set_mc_props;
8901c42de6dSgd 	b.devi_branch_callback = get_new_child;
8911c42de6dSgd 
8921c42de6dSgd 	if (e_ddi_branch_create(ap, &b, NULL, 0))
8931c42de6dSgd 		return (NULL);
8941c42de6dSgd 
8951c42de6dSgd 	return (arg.new_child);
8961c42de6dSgd }
8971c42de6dSgd 
8981c42de6dSgd /*ARGSUSED*/
8991c42de6dSgd static int
set_mc_props(dev_info_t * new_child,void * arg,uint_t flags)9001c42de6dSgd set_mc_props(dev_info_t *new_child, void *arg, uint_t flags)
9011c42de6dSgd {
9021c42de6dSgd 	struct bca *bcp = arg;
9031c42de6dSgd 	gptwo_regspec_t	reg;
9041c42de6dSgd 	int banks, dimms;
9051c42de6dSgd 	spcd_t *pcd = bcp->pcd;
9061c42de6dSgd 	uint_t portid = bcp->portid;
9071c42de6dSgd 	uint_t cpuid = bcp->cpuid;
9081c42de6dSgd 
9091c42de6dSgd 	GPTWO_DEBUG3(1, CE_CONT, "set_mc_props: ap=0x%lx portid=0x%x "
9101c42de6dSgd 	    "cpuid=0x%x\n", ddi_get_parent(new_child), portid, cpuid);
9111c42de6dSgd 
9121c42de6dSgd 	if (ndi_prop_update_string(DDI_DEV_T_NONE, new_child,
9131c42de6dSgd 	    "name", "memory-controller") != DDI_SUCCESS) {
9141c42de6dSgd 		GPTWO_DEBUG0(1, CE_CONT, "set_mc_props: failed "
9151c42de6dSgd 		    "to create name property\n");
9161c42de6dSgd 		return (DDI_WALK_ERROR);
9171c42de6dSgd 	}
9181c42de6dSgd 
9191c42de6dSgd 	if (ndi_prop_update_string(DDI_DEV_T_NONE, new_child,
9201c42de6dSgd 	    "compatible", "SUNW,UltraSPARC-III,mc") != DDI_SUCCESS) {
9211c42de6dSgd 		GPTWO_DEBUG0(1, CE_CONT, "set_mc_props: failed "
9221c42de6dSgd 		    "to create compatible property\n");
9231c42de6dSgd 		return (DDI_WALK_ERROR);
9241c42de6dSgd 	}
9251c42de6dSgd 
9261c42de6dSgd 	if (ndi_prop_update_string(DDI_DEV_T_NONE, new_child,
9271c42de6dSgd 	    "device_type", "memory-controller") != DDI_SUCCESS) {
9281c42de6dSgd 		GPTWO_DEBUG0(1, CE_CONT, "set_mc_props: failed "
9291c42de6dSgd 		    "to create device_type property\n");
9301c42de6dSgd 		return (DDI_WALK_ERROR);
9311c42de6dSgd 	}
9321c42de6dSgd 
9331c42de6dSgd 	if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child,
9341c42de6dSgd 	    "portid", portid) != DDI_SUCCESS) {
9351c42de6dSgd 		GPTWO_DEBUG0(1, CE_CONT, "set_mc_props: failed "
9361c42de6dSgd 		    "to create portid property\n");
9371c42de6dSgd 		return (DDI_WALK_ERROR);
9381c42de6dSgd 	}
9391c42de6dSgd 
9401c42de6dSgd 	if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child,
9411c42de6dSgd 	    "cpuid", cpuid) != DDI_SUCCESS) {
9421c42de6dSgd 		GPTWO_DEBUG0(1, CE_CONT, "set_mc_props: failed "
9431c42de6dSgd 		    "to create cpuid property\n");
9441c42de6dSgd 		return (DDI_WALK_ERROR);
9451c42de6dSgd 	}
9461c42de6dSgd 
9471c42de6dSgd 	reg.gptwo_phys_hi = 0x400 | (portid >> 9);
9481c42de6dSgd 	reg.gptwo_phys_low = (portid << 23) | 0x400000;
9491c42de6dSgd 	reg.gptwo_size_hi = 0;
9501c42de6dSgd 	reg.gptwo_size_low = 0x48;
9511c42de6dSgd 
9521c42de6dSgd 	if (ndi_prop_update_int_array(DDI_DEV_T_NONE,
9531c42de6dSgd 	    new_child, "reg", (int *)&reg,
9541c42de6dSgd 	    sizeof (gptwo_regspec_t) / sizeof (int)) != DDI_SUCCESS) {
9551c42de6dSgd 		GPTWO_DEBUG0(1, CE_CONT, "set_mc_props: failed "
9561c42de6dSgd 		    "to create reg property\n");
9571c42de6dSgd 		return (DDI_WALK_ERROR);
9581c42de6dSgd 	}
9591c42de6dSgd 
9601c42de6dSgd 	if (pcd->memory_layout) {
9611c42de6dSgd 		if (ndi_prop_update_byte_array(DDI_DEV_T_NONE,
9621c42de6dSgd 		    new_child, "memory-layout", (uchar_t *)pcd->memory_layout,
9631c42de6dSgd 		    pcd->memory_layout_size) != DDI_SUCCESS) {
9641c42de6dSgd 
9651c42de6dSgd 			GPTWO_DEBUG0(1, CE_CONT, "set_mc_props: failed "
9661c42de6dSgd 			    "to create memory-layout property\n");
9671c42de6dSgd 
9681c42de6dSgd 			return (DDI_WALK_ERROR);
9691c42de6dSgd 		}
9701c42de6dSgd 	}
9711c42de6dSgd 
9721c42de6dSgd 	/*
9731c42de6dSgd 	 * Create the bank-status property.
9741c42de6dSgd 	 */
9751c42de6dSgd 	banks = 0;
9761c42de6dSgd 
9771c42de6dSgd 	while ((pcd->sprd_bank_rsv[banks] != NULL) &&
9781c42de6dSgd 	    (banks < MAX_BANKS_PER_PORT))
9791c42de6dSgd 		banks++;
9801c42de6dSgd 
9811c42de6dSgd 	if (banks) {
9821c42de6dSgd 		(void) ndi_prop_update_string_array(DDI_DEV_T_NONE, new_child,
9831c42de6dSgd 		    "bank-status", (char **)pcd->sprd_bank_rsv, banks);
9841c42de6dSgd 	}
9851c42de6dSgd 
9861c42de6dSgd 	/*
9871c42de6dSgd 	 * Create the dimm-status property.
9881c42de6dSgd 	 */
9891c42de6dSgd 	dimms = 0;
9901c42de6dSgd 
9911c42de6dSgd 	while ((pcd->sprd_dimm[dimms] != NULL) &&
9921c42de6dSgd 	    (dimms < MAX_DIMMS_PER_PORT))
9931c42de6dSgd 		dimms++;
9941c42de6dSgd 
9951c42de6dSgd 	if (dimms) {
9961c42de6dSgd 		(void) ndi_prop_update_string_array(DDI_DEV_T_NONE, new_child,
9971c42de6dSgd 		    "dimm-status", (char **)pcd->sprd_dimm, dimms);
9981c42de6dSgd 	}
9991c42de6dSgd 
10001c42de6dSgd 
10011c42de6dSgd 	return (DDI_WALK_TERMINATE);
10021c42de6dSgd }
10031c42de6dSgd 
10041c42de6dSgd /*ARGSUSED*/
10051c42de6dSgd static void
get_new_child(dev_info_t * rdip,void * arg,uint_t flags)10061c42de6dSgd get_new_child(dev_info_t *rdip, void *arg, uint_t flags)
10071c42de6dSgd {
10081c42de6dSgd 	struct bca *bcp = arg;
10091c42de6dSgd 
10101c42de6dSgd 	bcp->new_child = rdip;
10111c42de6dSgd 
10121c42de6dSgd }
10131c42de6dSgd 
10141c42de6dSgd #ifdef DEBUG
10151c42de6dSgd static void
debug(char * fmt,uintptr_t a1,uintptr_t a2,uintptr_t a3,uintptr_t a4,uintptr_t a5)10161c42de6dSgd debug(char *fmt, uintptr_t a1, uintptr_t a2, uintptr_t a3,
10171c42de6dSgd 	uintptr_t a4, uintptr_t a5)
10181c42de6dSgd {
10191c42de6dSgd 	cmn_err(CE_CONT, fmt, a1, a2, a3, a4, a5);
10201c42de6dSgd }
10211c42de6dSgd #endif
1022