17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate /*
237c478bd9Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate #include <sys/param.h>
287c478bd9Sstevel@tonic-gate #include <sys/systm.h>
297c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
307c478bd9Sstevel@tonic-gate #include <sys/sunndi.h>
317c478bd9Sstevel@tonic-gate #include <sys/modctl.h>
327c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
337c478bd9Sstevel@tonic-gate #include <sys/platform_module.h>
347c478bd9Sstevel@tonic-gate #include <sys/errno.h>
357c478bd9Sstevel@tonic-gate 
367c478bd9Sstevel@tonic-gate /*
377c478bd9Sstevel@tonic-gate  * This platmod is used by both SUNW,Sun-Fire-280R (a.k.a littleneck) and
387c478bd9Sstevel@tonic-gate  * SUNW,Netra-T4 (a.k.a. lw2plus) platforms.
397c478bd9Sstevel@tonic-gate  */
407c478bd9Sstevel@tonic-gate 
417c478bd9Sstevel@tonic-gate #define	LITTLENECK_NVRAM_PATH	"/pci@8,700000/ebus@5/i2c@1,2e/nvram@0,a0"
427c478bd9Sstevel@tonic-gate #define	LW2PLUS_NVRAM_PATH	"/pci@8,700000/ebus@5/i2c@1,30/nvram@0,e0"
437c478bd9Sstevel@tonic-gate 
447c478bd9Sstevel@tonic-gate static dev_info_t *shared_pcf8584_dip = NULL;
457c478bd9Sstevel@tonic-gate static kmutex_t lneck_pcf8584_mutex;
467c478bd9Sstevel@tonic-gate 
477c478bd9Sstevel@tonic-gate int (*p2get_mem_unum)(int, uint64_t, char *, int, int *);
487c478bd9Sstevel@tonic-gate 
497c478bd9Sstevel@tonic-gate void
startup_platform(void)507c478bd9Sstevel@tonic-gate startup_platform(void)
517c478bd9Sstevel@tonic-gate {
52*f23a396bSToomas Soome 	mutex_init(&lneck_pcf8584_mutex, NULL, MUTEX_ADAPTIVE, NULL);
537c478bd9Sstevel@tonic-gate }
547c478bd9Sstevel@tonic-gate 
557c478bd9Sstevel@tonic-gate int
set_platform_tsb_spares()567c478bd9Sstevel@tonic-gate set_platform_tsb_spares()
577c478bd9Sstevel@tonic-gate {
587c478bd9Sstevel@tonic-gate 	return (0);
597c478bd9Sstevel@tonic-gate }
607c478bd9Sstevel@tonic-gate 
617c478bd9Sstevel@tonic-gate void
set_platform_defaults(void)627c478bd9Sstevel@tonic-gate set_platform_defaults(void)
637c478bd9Sstevel@tonic-gate {
647c478bd9Sstevel@tonic-gate }
657c478bd9Sstevel@tonic-gate 
667c478bd9Sstevel@tonic-gate void
load_platform_drivers(void)677c478bd9Sstevel@tonic-gate load_platform_drivers(void)
687c478bd9Sstevel@tonic-gate {
697c478bd9Sstevel@tonic-gate 	char		**drv;
707c478bd9Sstevel@tonic-gate 	dev_info_t	*nvram_dip;
717c478bd9Sstevel@tonic-gate 	static char	*boot_time_drivers[] = {
727c478bd9Sstevel@tonic-gate 		"todds1287",
737c478bd9Sstevel@tonic-gate 		"pcf8574",
747c478bd9Sstevel@tonic-gate 		"mc-us3",
757c478bd9Sstevel@tonic-gate 		NULL
767c478bd9Sstevel@tonic-gate 	};
777c478bd9Sstevel@tonic-gate 
787c478bd9Sstevel@tonic-gate 	for (drv = boot_time_drivers; *drv; drv++) {
797c478bd9Sstevel@tonic-gate 		if (i_ddi_attach_hw_nodes(*drv) != DDI_SUCCESS)
807c478bd9Sstevel@tonic-gate 			cmn_err(CE_WARN, "Failed to install \"%s\" driver.",
817c478bd9Sstevel@tonic-gate 			    *drv);
827c478bd9Sstevel@tonic-gate 	}
837c478bd9Sstevel@tonic-gate 
847c478bd9Sstevel@tonic-gate 	/* hold modules for keyswitch polling and plat_get_mem_unum() */
857c478bd9Sstevel@tonic-gate 	(void) ddi_hold_driver(ddi_name_to_major("pcf8574"));
867c478bd9Sstevel@tonic-gate 	(void) ddi_hold_driver(ddi_name_to_major("mc-us3"));
877c478bd9Sstevel@tonic-gate 
887c478bd9Sstevel@tonic-gate 	/*
897c478bd9Sstevel@tonic-gate 	 * For littleneck we figure out which pcf8584 dip is shared with
907c478bd9Sstevel@tonic-gate 	 * OBP for the nvram device, so the lock can be acquired.
917c478bd9Sstevel@tonic-gate 	 * If this fails see if we're running on a Netra 20.
927c478bd9Sstevel@tonic-gate 	 * The Netra 20 nvram node is the SCC and is also shared by
937c478bd9Sstevel@tonic-gate 	 * Solaris and OBP.
947c478bd9Sstevel@tonic-gate 	 */
957c478bd9Sstevel@tonic-gate 
967c478bd9Sstevel@tonic-gate 	nvram_dip = e_ddi_hold_devi_by_path(LITTLENECK_NVRAM_PATH, 0);
977c478bd9Sstevel@tonic-gate 
987c478bd9Sstevel@tonic-gate 	if (nvram_dip == NULL)
997c478bd9Sstevel@tonic-gate 		nvram_dip = e_ddi_hold_devi_by_path(LW2PLUS_NVRAM_PATH, 0);
1007c478bd9Sstevel@tonic-gate 	if (nvram_dip == NULL)
1017c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN, "Failed to hold pcf8584");
1027c478bd9Sstevel@tonic-gate 	else {
1037c478bd9Sstevel@tonic-gate 		shared_pcf8584_dip = ddi_get_parent(nvram_dip);
1047c478bd9Sstevel@tonic-gate 
1057c478bd9Sstevel@tonic-gate 		ndi_hold_devi(shared_pcf8584_dip);
1067c478bd9Sstevel@tonic-gate 		ndi_rele_devi(nvram_dip);
1077c478bd9Sstevel@tonic-gate 	}
1087c478bd9Sstevel@tonic-gate }
1097c478bd9Sstevel@tonic-gate 
1107c478bd9Sstevel@tonic-gate /*ARGSUSED*/
1117c478bd9Sstevel@tonic-gate int
plat_cpu_poweron(struct cpu * cp)1127c478bd9Sstevel@tonic-gate plat_cpu_poweron(struct cpu *cp)
1137c478bd9Sstevel@tonic-gate {
1147c478bd9Sstevel@tonic-gate 	return (ENOTSUP);	/* not supported on this platform */
1157c478bd9Sstevel@tonic-gate }
1167c478bd9Sstevel@tonic-gate 
1177c478bd9Sstevel@tonic-gate /*ARGSUSED*/
1187c478bd9Sstevel@tonic-gate int
plat_cpu_poweroff(struct cpu * cp)1197c478bd9Sstevel@tonic-gate plat_cpu_poweroff(struct cpu *cp)
1207c478bd9Sstevel@tonic-gate {
1217c478bd9Sstevel@tonic-gate 	return (ENOTSUP);	/* not supported on this platform */
1227c478bd9Sstevel@tonic-gate }
1237c478bd9Sstevel@tonic-gate 
1247c478bd9Sstevel@tonic-gate /*ARGSUSED*/
1257c478bd9Sstevel@tonic-gate void
plat_freelist_process(int mnode)1267c478bd9Sstevel@tonic-gate plat_freelist_process(int mnode)
1277c478bd9Sstevel@tonic-gate {
1287c478bd9Sstevel@tonic-gate }
1297c478bd9Sstevel@tonic-gate 
1307c478bd9Sstevel@tonic-gate /*
1317c478bd9Sstevel@tonic-gate  * No platform drivers on this platform
1327c478bd9Sstevel@tonic-gate  */
1337c478bd9Sstevel@tonic-gate char *platform_module_list[] = {
1347c478bd9Sstevel@tonic-gate 	(char *)0
1357c478bd9Sstevel@tonic-gate };
1367c478bd9Sstevel@tonic-gate 
1377c478bd9Sstevel@tonic-gate /*ARGSUSED*/
1387c478bd9Sstevel@tonic-gate void
plat_tod_fault(enum tod_fault_type tod_bad)1397c478bd9Sstevel@tonic-gate plat_tod_fault(enum tod_fault_type tod_bad)
1407c478bd9Sstevel@tonic-gate {
1417c478bd9Sstevel@tonic-gate }
1427c478bd9Sstevel@tonic-gate 
1437c478bd9Sstevel@tonic-gate /*ARGSUSED*/
1447c478bd9Sstevel@tonic-gate int
plat_get_mem_unum(int synd_code,uint64_t flt_addr,int flt_bus_id,int flt_in_memory,ushort_t flt_status,char * buf,int buflen,int * lenp)1457c478bd9Sstevel@tonic-gate plat_get_mem_unum(int synd_code, uint64_t flt_addr, int flt_bus_id,
1467c478bd9Sstevel@tonic-gate     int flt_in_memory, ushort_t flt_status, char *buf, int buflen, int *lenp)
1477c478bd9Sstevel@tonic-gate {
1487c478bd9Sstevel@tonic-gate 	if (flt_in_memory && (p2get_mem_unum != NULL))
1497c478bd9Sstevel@tonic-gate 		return (p2get_mem_unum(synd_code, P2ALIGN(flt_addr, 8),
150*f23a396bSToomas Soome 		    buf, buflen, lenp));
1517c478bd9Sstevel@tonic-gate 	else
1527c478bd9Sstevel@tonic-gate 		return (ENOTSUP);
1537c478bd9Sstevel@tonic-gate }
1547c478bd9Sstevel@tonic-gate 
1557c478bd9Sstevel@tonic-gate int
plat_get_cpu_unum(int cpuid,char * buf,int buflen,int * lenp)1567c478bd9Sstevel@tonic-gate plat_get_cpu_unum(int cpuid, char *buf, int buflen, int *lenp)
1577c478bd9Sstevel@tonic-gate {
1587c478bd9Sstevel@tonic-gate 	if (snprintf(buf, buflen, "Slot %d", cpuid) >= buflen) {
1597c478bd9Sstevel@tonic-gate 		return (ENOSPC);
1607c478bd9Sstevel@tonic-gate 	} else {
1617c478bd9Sstevel@tonic-gate 		*lenp = strlen(buf);
1627c478bd9Sstevel@tonic-gate 		return (0);
1637c478bd9Sstevel@tonic-gate 	}
1647c478bd9Sstevel@tonic-gate }
1657c478bd9Sstevel@tonic-gate 
1667c478bd9Sstevel@tonic-gate /*
1677c478bd9Sstevel@tonic-gate  * Littleneck's BBC pcf8584 controller is used by both OBP and the OS's i2c
1687c478bd9Sstevel@tonic-gate  * drivers.  The 'eeprom' command executes OBP code to handle property requests.
1697c478bd9Sstevel@tonic-gate  * If eeprom didn't do this, or if the controllers were partitioned so that all
1707c478bd9Sstevel@tonic-gate  * devices on a given controller were driven by either OBP or the OS, this
1717c478bd9Sstevel@tonic-gate  * wouldn't be necessary.
1727c478bd9Sstevel@tonic-gate  *
1737c478bd9Sstevel@tonic-gate  * Note that getprop doesn't have the same issue as it reads from cached
1747c478bd9Sstevel@tonic-gate  * memory in OBP.
1757c478bd9Sstevel@tonic-gate  */
1767c478bd9Sstevel@tonic-gate 
1777c478bd9Sstevel@tonic-gate /*
1787c478bd9Sstevel@tonic-gate  * Common locking enter code
1797c478bd9Sstevel@tonic-gate  */
1807c478bd9Sstevel@tonic-gate void
plat_setprop_enter(void)1817c478bd9Sstevel@tonic-gate plat_setprop_enter(void)
1827c478bd9Sstevel@tonic-gate {
1837c478bd9Sstevel@tonic-gate 	mutex_enter(&lneck_pcf8584_mutex);
1847c478bd9Sstevel@tonic-gate }
1857c478bd9Sstevel@tonic-gate 
1867c478bd9Sstevel@tonic-gate /*
1877c478bd9Sstevel@tonic-gate  * Common locking exit code
1887c478bd9Sstevel@tonic-gate  */
1897c478bd9Sstevel@tonic-gate void
plat_setprop_exit(void)1907c478bd9Sstevel@tonic-gate plat_setprop_exit(void)
1917c478bd9Sstevel@tonic-gate {
1927c478bd9Sstevel@tonic-gate 	mutex_exit(&lneck_pcf8584_mutex);
1937c478bd9Sstevel@tonic-gate }
1947c478bd9Sstevel@tonic-gate 
1957c478bd9Sstevel@tonic-gate /*
1967c478bd9Sstevel@tonic-gate  * Called by pcf8584 driver
1977c478bd9Sstevel@tonic-gate  */
1987c478bd9Sstevel@tonic-gate void
plat_shared_i2c_enter(dev_info_t * i2cnexus_dip)1997c478bd9Sstevel@tonic-gate plat_shared_i2c_enter(dev_info_t *i2cnexus_dip)
2007c478bd9Sstevel@tonic-gate {
2017c478bd9Sstevel@tonic-gate 	if (i2cnexus_dip == shared_pcf8584_dip) {
2027c478bd9Sstevel@tonic-gate 		plat_setprop_enter();
2037c478bd9Sstevel@tonic-gate 	}
2047c478bd9Sstevel@tonic-gate }
2057c478bd9Sstevel@tonic-gate 
2067c478bd9Sstevel@tonic-gate /*
2077c478bd9Sstevel@tonic-gate  * Called by pcf8584 driver
2087c478bd9Sstevel@tonic-gate  */
2097c478bd9Sstevel@tonic-gate void
plat_shared_i2c_exit(dev_info_t * i2cnexus_dip)2107c478bd9Sstevel@tonic-gate plat_shared_i2c_exit(dev_info_t *i2cnexus_dip)
2117c478bd9Sstevel@tonic-gate {
2127c478bd9Sstevel@tonic-gate 	if (i2cnexus_dip == shared_pcf8584_dip) {
2137c478bd9Sstevel@tonic-gate 		plat_setprop_exit();
2147c478bd9Sstevel@tonic-gate 	}
2157c478bd9Sstevel@tonic-gate }
216