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
32extern "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 */
141typedef 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 */
165typedef int	(*opl_init_func_t)(dev_info_t *, char *, int);
166typedef 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 */
182typedef 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
209typedef struct {
210	uint32_t	addr_hi;
211	uint32_t	addr_lo;
212} opl_addr_t;
213
214typedef 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
221typedef 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
284typedef struct {
285	char		*fc_service;
286	fc_ops_t	*fc_op;
287} opl_fc_ops_t;
288
289/*
290 * Functions used by drmach
291 */
292extern int	opl_probe_sb(int, unsigned *);
293extern int	opl_unprobe_sb(int);
294extern int	opl_read_hwd(int, hwd_header_t **, hwd_sb_status_t **,
295				hwd_domain_info_t **, hwd_sb_t **);
296extern void	opl_hold_devtree(void);
297extern void	opl_release_devtree(void);
298extern int	oplcfg_pa_swap(int from, int to);
299extern int	opl_init_cfg();
300
301#endif /* _KERNEL */
302
303#ifdef	__cplusplus
304}
305#endif
306
307#endif	/* _SYS_OPL_CFG_H */
308