xref: /illumos-gate/usr/src/uts/sun4u/sys/opl_cfg.h (revision e98fafb9)
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 (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #ifndef	_SYS_OPL_CFG_H
27 #define	_SYS_OPL_CFG_H
28 
29 #pragma ident	"%Z%%M%	%I%	%E% SMI"
30 
31 #ifdef	__cplusplus
32 extern "C" {
33 #endif
34 
35 /*
36  * Hardware Descriptor.
37  */
38 
39 #include <sys/opl_hwdesc.h>
40 
41 #define	OPL_PSB_MODE	0x0
42 #define	OPL_XSB_MODE	0x1
43 
44 #define	OPL_LSBID_MASK	0x1f
45 
46 /*
47  * CPU device portid:
48  *
49  *	  1  0  0  0  0  0  0  0   0  0    0
50  *	  0  9  8  7  6  5  4  3   2  1    0
51  *      ---------------------------------------
52  *	| 1 |   LSB ID    | CHIP | CORE | CPU |
53  * 	---------------------------------------
54  */
55 #define	OPL_CPUID_TO_LSB(devid)	((devid >> 5) & OPL_LSBID_MASK)
56 #define	OPL_CPU_CHIP(devid)	((devid >> 3) & 0x3)
57 #define	OPL_CORE(devid)		((devid >> 1) & 0x3)
58 #define	OPL_CPU(devid)		((devid & 0x001))
59 
60 #define	OPL_PORTID(board, chip)		((1 << 10) | (board << 5) | (chip << 3))
61 
62 #define	OPL_CPUID(board, chip, core, cpu)				\
63 									\
64 	((board << 5) | (chip << 3) | (core << 1) | (cpu))
65 
66 /*
67  * Dummy address space for a chip.
68  */
69 #define	OPL_PROC_AS(board, chip)					\
70 									\
71 	((1ULL << 46) | ((uint64_t)board << 40) | (1ULL << 39) | 	\
72 		(1ULL << 33) | ((uint64_t)chip << 4))
73 
74 /*
75  * pseudo-mc portid:
76  *
77  *	  1   0   0  0  0  0  0   0  0  0  0
78  *	  0   9   8  7  6  5  4   3  2  1  0
79  *      -------------------------------------
80  *	| 0 | 1 |     LSB ID    |    0      |
81  * 	-------------------------------------
82  */
83 #define	OPL_LSB_TO_PSEUDOMC_PORTID(board)	((1 << 9) | (board << 4))
84 
85 /*
86  * Dummy address space for a pseudo memory node
87  */
88 #define	OPL_MC_AS(board)						\
89 									\
90 	((1ULL << 46) | ((uint64_t)board << 40) | (1ULL << 39) | 	\
91 		(1ULL << 33))
92 
93 /*
94  * Defines used by the Jupiter bus-specific library (lfc_jupiter.so).
95  * This library gets loaded into the user-level fcode interpreter
96  * and provides bus-specific methods that are used by the Oberon
97  * and the CMU-channel fcode drivers.
98  */
99 /*
100  *
101  * IO port id:
102  *
103  *	  1  0  0  0  0  0  0  0   0  0    0
104  *	  0  9  8  7  6  5  4  3   2  1    0
105  *      ---------------------------------------
106  *	| 0  0 |   LSB ID    | IO CHAN | LEAF |
107  * 	---------------------------------------
108  */
109 #define	OPL_PORTID_MASK			0x7FF
110 #define	OPL_IO_PORTID_TO_LSB(portid)	(((portid) >> 4) & OPL_LSBID_MASK)
111 #define	OPL_PORTID_TO_CHANNEL(portid)	(((portid) >> 1) & 0x7)
112 #define	OPL_PORTID_TO_LEAF(portid)	((portid) & 0x1)
113 #define	OPL_IO_PORTID(lsb, ch, leaf)	\
114 	(((lsb & OPL_LSBID_MASK) << 4) | ((ch & 0x7) << 1) | (leaf & 0x1))
115 
116 #define	OPL_ADDR_TO_LSB(hi)		(((hi) >> 8) & OPL_LSBID_MASK)
117 #define	OPL_ADDR_TO_CHANNEL(hi)		(((hi) >> 5) & 0x7)
118 #define	OPL_ADDR_TO_LEAF(hi, lo)	\
119 		(!(((hi) >> 7) & 0x1) && (((lo) >> 20) == 0x7))
120 
121 #define	OPL_ADDR_HI(lsb, ch)		\
122 		((1 << 14) | ((lsb & OPL_LSBID_MASK) << 8) | ((ch & 0x7) << 5))
123 
124 #define	OPL_CMU_CHANNEL	4
125 #define	OPL_OBERON_CHANNEL(ch)	((ch >= 0) && (ch <= 3))
126 #define	OPL_VALID_CHANNEL(ch)	((ch >= 0) && (ch <= 4))
127 #define	OPL_VALID_LEAF(leaf)	((leaf == 0) || (leaf == 1))
128 
129 #if defined(_KERNEL)
130 
131 /*
132  * We store the pointers to the following device nodes in this structure:
133  *	"pseudo-mc"
134  *	"cmp"
135  *	"pci"
136  *
137  * These nodes represent the different branches we create in the device
138  * tree for each board during probe. We store them so that when a board
139  * is unprobed, we can easily locate the branches and destroy them.
140  */
141 typedef struct {
142 	dev_info_t		*cfg_pseudo_mc;
143 	dev_info_t		*cfg_cpu_chips[HWD_CPU_CHIPS_PER_CMU];
144 	dev_info_t		*cfg_cmuch_leaf;
145 	fco_handle_t		cfg_cmuch_handle;
146 	char			*cfg_cmuch_probe_str;
147 	dev_info_t		*cfg_pcich_leaf[HWD_PCI_CHANNELS_PER_SB]
148 						[HWD_LEAVES_PER_PCI_CHANNEL];
149 	fco_handle_t		cfg_pcich_handle[HWD_PCI_CHANNELS_PER_SB]
150 						[HWD_LEAVES_PER_PCI_CHANNEL];
151 	char			*cfg_pcich_probe_str[HWD_PCI_CHANNELS_PER_SB]
152 						[HWD_LEAVES_PER_PCI_CHANNEL];
153 	void			*cfg_hwd;
154 } opl_board_cfg_t;
155 
156 /*
157  * Prototypes for the callback functions used in the DDI functions
158  * used to perform device tree operations.
159  *
160  * init functions are used to find device nodes that are created
161  * by Solaris during boot.
162  *
163  * create functions are used to initialize device nodes during DR.
164  */
165 typedef int	(*opl_init_func_t)(dev_info_t *, char *, int);
166 typedef int	(*opl_create_func_t)(dev_info_t *, void *, uint_t);
167 
168 /*
169  * The following probe structure carries all the information required
170  * at various points during probe. This structure serves two purposes:
171  *
172  *	1. It allows us to streamline functions and have them accept just
173  *	   a single argument.
174  *
175  *	2. It allows us to pass information to the DDI callbacks. DDI
176  *	   callbacks are allowed only one argument. It also allows
177  *	   us to return information from those callbacks.
178  *
179  * The probe structure carries a snapshot of the hardware descriptor
180  * taken at the beginning of a probe.
181  */
182 typedef struct {
183 	hwd_header_t		*pr_hdr;
184 	hwd_sb_status_t		*pr_sb_status;
185 	hwd_domain_info_t	*pr_dinfo;
186 	hwd_sb_t		*pr_sb;
187 
188 	int			pr_board;
189 	int			pr_cpu_chip;
190 	int			pr_core;
191 	int			pr_cpu;
192 	int			pr_channel;
193 	int			pr_channel_status;
194 	int			pr_leaf;
195 	int			pr_leaf_status;
196 
197 	opl_create_func_t	pr_create;
198 	dev_info_t		*pr_parent;
199 	dev_info_t		*pr_node;
200 	int			pr_hold;
201 	unsigned		pr_cpu_impl;
202 } opl_probe_t;
203 
204 #define	OPL_STR_LEN	256
205 
206 #define	OPL_HI(value)	((uint32_t)((uint64_t)(value) >> 32))
207 #define	OPL_LO(value)	((uint32_t)(value))
208 
209 typedef struct {
210 	uint32_t	addr_hi;
211 	uint32_t	addr_lo;
212 } opl_addr_t;
213 
214 typedef struct {
215 	uint32_t	rg_addr_hi;
216 	uint32_t	rg_addr_lo;
217 	uint32_t	rg_size_hi;
218 	uint32_t	rg_size_lo;
219 } opl_range_t;
220 
221 typedef struct {
222 	int		mc_bank;
223 	uint32_t	mc_hi;
224 	uint32_t	mc_lo;
225 } opl_mc_addr_t;
226 
227 /*
228  * Convenience macros for DDI property operations. The functions that
229  * DDI provides for getting and updating properties are not symmetric
230  * either in their names or in the number of arguments. These macros
231  * hide the gory details and provide a symmetric way to get and
232  * set properties.
233  */
234 #define	opl_prop_get_string(dip, name, bufp, lenp)			\
235 	ddi_getlongprop(DDI_DEV_T_ANY, dip,				\
236 			DDI_PROP_DONTPASS, name, (caddr_t)bufp, lenp)
237 
238 #define	opl_prop_get_int(dip, name, value, defvalue)			\
239 (									\
240 	*(value) = ddi_getprop(DDI_DEV_T_ANY, dip,			\
241 			DDI_PROP_DONTPASS, name, defvalue),		\
242 	(*(value) == defvalue) ? DDI_PROP_NOT_FOUND : DDI_PROP_SUCCESS	\
243 )
244 
245 #define	opl_prop_get_int_array(dip, name, data, nelems)			\
246 	ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip,			\
247 	DDI_PROP_DONTPASS, name, (int **)&data, (uint_t *)&nelems)
248 
249 #define	OPL_GET_PROP(type, dip, name, value, arg)			\
250 	opl_prop_get_##type(dip, name, value, arg)
251 
252 #define	OPL_GET_PROP_ARRAY(type, dip, name, values, nvalues)		\
253 	opl_prop_get_##type##_array(dip, name, values, nvalues)
254 
255 #define	OPL_FREE_PROP(data)						\
256 	ddi_prop_free((void *)data)
257 
258 #define	OPL_UPDATE_PROP_ERR(ret, name)					\
259 	if (ret != DDI_PROP_SUCCESS) {					\
260 		cmn_err(CE_WARN, "%s (%d): %s update property error (%d)",\
261 			__FILE__, __LINE__, name, ret);			\
262 		return (DDI_WALK_ERROR);				\
263 	}
264 
265 #define	OPL_UPDATE_PROP(type, dip, name, value)				\
266 	ret = ndi_prop_update_##type(DDI_DEV_T_NONE, dip, name, value);	\
267 	OPL_UPDATE_PROP_ERR(ret, name)
268 
269 
270 #define	OPL_UPDATE_PROP_ARRAY(type, dip, name, values, nvalues)		\
271 	ret = ndi_prop_update_##type##_array(DDI_DEV_T_NONE, dip,	\
272 						name, values, nvalues);	\
273 	OPL_UPDATE_PROP_ERR(ret, name)
274 
275 /*
276  * Node names for the different nodes supported in OPL.
277  */
278 #define	OPL_PSEUDO_MC_NODE	"pseudo-mc"
279 #define	OPL_CPU_CHIP_NODE	"cmp"
280 #define	OPL_CORE_NODE		"core"
281 #define	OPL_CPU_NODE		"cpu"
282 #define	OPL_PCI_LEAF_NODE	"pci"
283 
284 typedef struct {
285 	char		*fc_service;
286 	fc_ops_t	*fc_op;
287 } opl_fc_ops_t;
288 
289 /*
290  * Functions used by drmach
291  */
292 extern int	opl_probe_sb(int, unsigned *);
293 extern int	opl_unprobe_sb(int);
294 extern int	opl_read_hwd(int, hwd_header_t **, hwd_sb_status_t **,
295 				hwd_domain_info_t **, hwd_sb_t **);
296 extern void	opl_hold_devtree(void);
297 extern void	opl_release_devtree(void);
298 extern int	oplcfg_pa_swap(int from, int to);
299 extern int	opl_init_cfg();
300 
301 #endif /* _KERNEL */
302 
303 #ifdef	__cplusplus
304 }
305 #endif
306 
307 #endif	/* _SYS_OPL_CFG_H */
308