xref: /illumos-gate/usr/src/uts/sun4u/taco/os/taco.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <sys/param.h>
30 #include <sys/systm.h>
31 #include <sys/sysmacros.h>
32 #include <sys/sunddi.h>
33 #include <sys/esunddi.h>
34 #include <sys/platform_module.h>
35 #include <sys/errno.h>
36 
37 /*
38  * 1535D+ IDE Interface Control Register Index
39  */
40 #define	IDEIC_RINDEX	(0x58)
41 
42 int (*p2get_mem_unum)(int, uint64_t, char *, int, int *);
43 
44 void
startup_platform(void)45 startup_platform(void)
46 {
47 }
48 
49 int
set_platform_tsb_spares(void)50 set_platform_tsb_spares(void)
51 {
52 	return (0);
53 }
54 
55 void
set_platform_defaults(void)56 set_platform_defaults(void)
57 {
58 }
59 
60 /*
61  * Definitions for accessing the pci config space of the ISA node
62  * of Southbridge.
63  */
64 #define	TACO_ISA_PATHNAME	"/pci@1e,600000/isa@7"
65 static ddi_acc_handle_t isa_handle;		/* handle for ISA pci space */
66 
67 
68 void
load_platform_drivers(void)69 load_platform_drivers(void)
70 {
71 	dev_info_t 		*dip;		/* dip of the ISA driver */
72 
73 	/*
74 	 * Install power driver which handles the power button.
75 	 */
76 	if (i_ddi_attach_hw_nodes("power") != DDI_SUCCESS)
77 		cmn_err(CE_WARN, "Failed to install \"power\" driver.");
78 	(void) ddi_hold_driver(ddi_name_to_major("power"));
79 
80 	/*
81 	 * It is OK to return error because 'us' driver is not available
82 	 * in all clusters (e.g. missing in Core cluster).
83 	 */
84 	(void) i_ddi_attach_hw_nodes("us");
85 
86 	if (i_ddi_attach_hw_nodes("grbeep") != DDI_SUCCESS)
87 		cmn_err(CE_WARN, "Failed to install \"beep\" driver.");
88 
89 
90 	/*
91 	 * mc-us3i must stay loaded for plat_get_mem_unum()
92 	 */
93 	if (i_ddi_attach_hw_nodes("mc-us3i") != DDI_SUCCESS)
94 		cmn_err(CE_WARN, "mc-us3i driver failed to install");
95 	(void) ddi_hold_driver(ddi_name_to_major("mc-us3i"));
96 
97 	/*
98 	 * Install ISA driver. This is required for the southbridge IDE
99 	 * workaround - to reset the IDE channel during IDE bus reset.
100 	 * Panic the system in case ISA driver could not be loaded or
101 	 * any problem in accessing its pci config space. Since the register
102 	 * to reset the channel for IDE is in ISA config space!.
103 	 */
104 
105 	dip = e_ddi_hold_devi_by_path(TACO_ISA_PATHNAME, 0);
106 	if (dip == NULL) {
107 		cmn_err(CE_PANIC, "Could not install the ISA driver\n");
108 		return;
109 	}
110 
111 	if (pci_config_setup(dip, &isa_handle) != DDI_SUCCESS) {
112 		cmn_err(CE_PANIC, "Could not get the config space of ISA\n");
113 		return;
114 	}
115 }
116 
117 /*
118  * This routine provides a workaround for a bug in the SB chip which
119  * can cause data corruption. Will be invoked from the IDE HBA driver for
120  * Acer SouthBridge at the time of IDE bus reset.
121  */
122 /*ARGSUSED*/
123 int
plat_ide_chipreset(dev_info_t * dip,int chno)124 plat_ide_chipreset(dev_info_t *dip, int chno)
125 {
126 	uint8_t	val;
127 	int	ret = DDI_SUCCESS;
128 
129 	if (isa_handle == NULL) {
130 		return (DDI_FAILURE);
131 	}
132 
133 	val = pci_config_get8(isa_handle, IDEIC_RINDEX);
134 	/*
135 	 * The dip passed as the argument is not used here.
136 	 * This will be needed for platforms which have multiple on-board SB,
137 	 * The dip passed will be used to match the corresponding ISA node.
138 	 */
139 	switch (chno) {
140 		case 0:
141 			/*
142 			 * First disable the primary channel then re-enable it.
143 			 * As per ALI no wait should be required in between have
144 			 * given 1ms delay in between to be on safer side.
145 			 * bit 2 of register 0x58 when 0 disable the channel 0.
146 			 * bit 2 of register 0x58 when 1 enables the channel 0.
147 			 */
148 			pci_config_put8(isa_handle, IDEIC_RINDEX, val & 0xFB);
149 			drv_usecwait(1000);
150 			pci_config_put8(isa_handle, IDEIC_RINDEX, val);
151 			break;
152 		case 1:
153 			/*
154 			 * bit 3 of register 0x58 when 0 disable the channel 1.
155 			 * bit 3 of register 0x58 when 1 enables the channel 1.
156 			 */
157 			pci_config_put8(isa_handle, IDEIC_RINDEX, val & 0xF7);
158 			drv_usecwait(1000);
159 			pci_config_put8(isa_handle, IDEIC_RINDEX, val);
160 			break;
161 		default:
162 			/*
163 			 * Unknown channel number passed. Return failure.
164 			 */
165 			ret = DDI_FAILURE;
166 	}
167 
168 	return (ret);
169 }
170 
171 
172 /*ARGSUSED*/
173 int
plat_cpu_poweron(struct cpu * cp)174 plat_cpu_poweron(struct cpu *cp)
175 {
176 	return (ENOTSUP);	/* not supported on this platform */
177 }
178 
179 /*ARGSUSED*/
180 int
plat_cpu_poweroff(struct cpu * cp)181 plat_cpu_poweroff(struct cpu *cp)
182 {
183 	return (ENOTSUP);	/* not supported on this platform */
184 }
185 
186 /*ARGSUSED*/
187 void
plat_freelist_process(int mnode)188 plat_freelist_process(int mnode)
189 {
190 }
191 
192 char *platform_module_list[] = {
193 	"m1535ppm",
194 	"jbusppm",
195 	"ics951601",
196 	"ppm",
197 	(char *)0
198 };
199 
200 /*ARGSUSED*/
201 void
plat_tod_fault(enum tod_fault_type tod_bad)202 plat_tod_fault(enum tod_fault_type tod_bad)
203 {
204 }
205 
206 /*ARGSUSED*/
207 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)208 plat_get_mem_unum(int synd_code, uint64_t flt_addr, int flt_bus_id,
209     int flt_in_memory, ushort_t flt_status, char *buf, int buflen, int *lenp)
210 {
211 	if (flt_in_memory && (p2get_mem_unum != NULL))
212 		return (p2get_mem_unum(synd_code, P2ALIGN(flt_addr, 8),
213 			buf, buflen, lenp));
214 	else
215 		return (ENOTSUP);
216 }
217 
218 /*ARGSUSED*/
219 int
plat_get_cpu_unum(int cpuid,char * buf,int buflen,int * lenp)220 plat_get_cpu_unum(int cpuid, char *buf, int buflen, int *lenp)
221 {
222 	if (snprintf(buf, buflen, "MB") >= buflen) {
223 		return (ENOSPC);
224 	} else {
225 		*lenp = strlen(buf);
226 		return (0);
227 	}
228 }
229