xref: /illumos-gate/usr/src/uts/sun4u/sys/sysiosbus.h (revision 2aeafac3612e19716bf8164f89c3c9196342979c)
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  * Copyright 2019 Peter Tribble.
28  */
29 
30 #ifndef _SYS_SYSIOSBUS_H
31 #define	_SYS_SYSIOSBUS_H
32 
33 #ifndef _ASM
34 #include <sys/avintr.h>
35 #include <sys/vmem.h>
36 #include <sys/ontrap.h>
37 #include <sys/machsystm.h>
38 #endif
39 
40 #ifdef	__cplusplus
41 extern "C" {
42 #endif
43 
44 /* Things for debugging */
45 #ifdef SYSIO_MEM_DEBUG
46 #define	IO_MEMUSAGE
47 #endif /* SYSIO_MEM_DEBUG */
48 
49 /*
50  * sysio sbus constant definitions.
51  */
52 #define	NATURAL_REG_SIZE	0x8	/* 8 Bytes is Fusion reg size */
53 #define	MIN_REG_SIZE		0x4	/* Smallest Fusion reg size */
54 #define	OFF_SYSIO_CTRL_REG	0x10
55 #define	SYSIO_CTRL_REG_SIZE	(NATURAL_REG_SIZE)
56 #define	OFF_SBUS_CTRL_REG	0x2000
57 #define	SBUS_CTRL_REG_SIZE	(NATURAL_REG_SIZE)
58 #define	OFF_SBUS_SLOT_CONFIG	0x2020
59 #define	SBUS_SLOT_CONFIG_SIZE	(NATURAL_REG_SIZE * 7)
60 #define	OFF_INTR_MAPPING_REG	0x2c00
61 /* #define	INTR_MAPPING_REG_SIZE	(NATURAL_REG_SIZE * 16 * 8)  */
62 #define	INTR_MAPPING_REG_SIZE	0x490
63 #define	OFF_CLR_INTR_REG	0x3408
64 /* #define	CLR_INTR_REG_SIZE	(NATURAL_REG_SIZE * 16 * 8) */
65 #define	CLR_INTR_REG_SIZE	0x488
66 #define	OFF_INTR_RETRY_REG	0x2c20
67 #define	INTR_RETRY_REG_SIZE	(MIN_REG_SIZE)
68 #define	OFF_SBUS_INTR_STATE_REG	0x4800
69 #define	SBUS_INTR_STATE_REG_SIZE (NATURAL_REG_SIZE * 2)
70 #define	SYSIO_IGN		46
71 #define	SBUS_ARBIT_ALL		0x3full
72 #define	SYSIO_VER_SHIFT		56
73 
74 /* Error registers */
75 #define	OFF_SYSIO_ECC_REGS	0x20
76 #define	SYSIO_ECC_REGS_SIZE	NATURAL_REG_SIZE
77 #define	OFF_SYSIO_UE_REGS	0x30
78 #define	SYSIO_UE_REGS_SIZE	(NATURAL_REG_SIZE * 2)
79 #define	OFF_SYSIO_CE_REGS	0x40
80 #define	SYSIO_CE_REGS_SIZE	(NATURAL_REG_SIZE * 2)
81 #define	OFF_SBUS_ERR_REGS	0x2010
82 #define	SBUS_ERR_REGS_SIZE	(NATURAL_REG_SIZE * 2)
83 
84 /* Interrupts */
85 #define	INTERRUPT_CPU_FIELD	26	/* Bit shift for mondo TID field */
86 #define	INTERRUPT_GROUP_NUMBER	6	/* Bit shift for mondo IGN field */
87 #define	INTERRUPT_VALID		0x80000000ull /* Mondo valid bit */
88 #define	SBUS_INTR_IDLE		0ull
89 #define	INT_PENDING 		3	/* state of the interrupt dispatch */
90 /*
91  * Fix these (RAZ)
92  * Interrupt Mapping Register defines
93  */
94 #define	IMR_VALID		0x80000000ull	/* Valid bit */
95 #define	IMR_TID			0x7C000000ull	/* TID bits */
96 #define	IMR_IGN			0x000007C0ull	/* IGN bits */
97 #define	IMR_INO			0x0000003Full	/* INO bits */
98 #define	IMR_TID_SHIFT		26		/* Bit shift for TID field */
99 #define	IMR_IGN_SHIFT		6		/* Bit shift for IGN field */
100 
101 #define	MAX_SBUS		(30)
102 #define	MAX_SBUS_LEVEL		(7)
103 #define	MAX_SBUS_SLOTS	(7)		/* 4 external slots + 3 internal */
104 #define	EXT_SBUS_SLOTS		4	/* Number of external sbus slots */
105 #define	MAX_SBUS_SLOT_ADDR	0x10	/* Max slot address on SYSIO */
106 #define	SYSIO_BURST_RANGE	(0x7f)	/* 32 bit: 64 Byte to 1 Byte burst */
107 #define	SYSIO64_BURST_RANGE	(0x78)	/* 64 bit: 64 Byte to 8 Byte burst */
108 #define	SYSIO_BURST_MASK	0xffff
109 #define	SYSIO64_BURST_MASK	0xffff0000
110 #define	SYSIO64_BURST_SHIFT	16
111 #define	MAX_PIL			16
112 
113 /* Slot config register defines */
114 #define	SBUS_ETM		0x4000ull
115 #define	SYSIO_SLAVEBURST_MASK	0x1e	/* Mask for hardware register */
116 #define	SYSIO_SLAVEBURST_RANGE	(0x78)	/* 32 bit: 64 Byte to 8 Byte burst */
117 #define	SYSIO64_SLAVEBURST_RANGE (0x78)	/* 64 bit: 64 Byte to 8 Byte burst */
118 #define	SYSIO_SLAVEBURST_REGSHIFT 2	/* Convert bit positions 2**8 to 2**1 */
119 
120 /*
121  * Offsets of sysio, sbus, registers
122  */
123 /* Slot configuration register mapping offsets */
124 #define	SBUS_SLOT0_CONFIG	0x0
125 #define	SBUS_SLOT1_CONFIG	0x1
126 #define	SBUS_SLOT2_CONFIG	0x2
127 #define	SBUS_SLOT3_CONFIG	0x3
128 #define	SBUS_SLOT4_CONFIG	0x4
129 #define	SBUS_SLOT5_CONFIG	0x5
130 #define	SBUS_SLOT6_CONFIG	0x6
131 
132 /* Interrupt mapping register mapping offsets */
133 #define	SBUS_SLOT0_MAPREG	0x0
134 #define	SBUS_SLOT1_MAPREG	0x1
135 #define	SBUS_SLOT2_MAPREG	0x2
136 #define	SBUS_SLOT3_MAPREG	0x3
137 #define	ESP_MAPREG		0x80
138 #define	ETHER_MAPREG		0x81
139 #define	PP_MAPREG		0x82
140 #define	AUDIO_MAPREG		0x83
141 #define	KBDMOUSE_MAPREG		0x85
142 #define	FLOPPY_MAPREG		0x86
143 #define	THERMAL_MAPREG		0x87
144 #define	TIMER0_MAPREG		0x8C
145 #define	TIMER1_MAPREG		0x8D
146 #define	UE_ECC_MAPREG		0x8E
147 #define	CE_ECC_MAPREG		0x8F
148 #define	SBUS_ERR_MAPREG		0x90
149 #define	PM_WAKEUP_MAPREG	0x91
150 #define	FFB_MAPPING_REG		0x92
151 #define	EXP_MAPPING_REG		0x93
152 
153 /* Interrupt clear register mapping offsets */
154 #define	SBUS_SLOT0_L1_CLEAR	0x0
155 #define	SBUS_SLOT0_L2_CLEAR	0x1
156 #define	SBUS_SLOT0_L3_CLEAR	0x2
157 #define	SBUS_SLOT0_L4_CLEAR	0x3
158 #define	SBUS_SLOT0_L5_CLEAR	0x4
159 #define	SBUS_SLOT0_L6_CLEAR	0x5
160 #define	SBUS_SLOT0_L7_CLEAR	0x6
161 #define	SBUS_SLOT1_L1_CLEAR	0x8
162 #define	SBUS_SLOT1_L2_CLEAR	0x9
163 #define	SBUS_SLOT1_L3_CLEAR	0xa
164 #define	SBUS_SLOT1_L4_CLEAR	0xb
165 #define	SBUS_SLOT1_L5_CLEAR	0xc
166 #define	SBUS_SLOT1_L6_CLEAR	0xd
167 #define	SBUS_SLOT1_L7_CLEAR	0xe
168 #define	SBUS_SLOT2_L1_CLEAR	0x10
169 #define	SBUS_SLOT2_L2_CLEAR	0x11
170 #define	SBUS_SLOT2_L3_CLEAR	0x12
171 #define	SBUS_SLOT2_L4_CLEAR	0x13
172 #define	SBUS_SLOT2_L5_CLEAR	0x14
173 #define	SBUS_SLOT2_L6_CLEAR	0x15
174 #define	SBUS_SLOT2_L7_CLEAR	0x16
175 #define	SBUS_SLOT3_L1_CLEAR	0x18
176 #define	SBUS_SLOT3_L2_CLEAR	0x19
177 #define	SBUS_SLOT3_L3_CLEAR	0x1a
178 #define	SBUS_SLOT3_L4_CLEAR	0x1b
179 #define	SBUS_SLOT3_L5_CLEAR	0x1c
180 #define	SBUS_SLOT3_L6_CLEAR	0x1d
181 #define	SBUS_SLOT3_L7_CLEAR	0x1e
182 #define	ESP_CLEAR		0x7f
183 #define	ETHER_CLEAR		0x80
184 #define	PP_CLEAR		0x81
185 #define	AUDIO_CLEAR		0x82
186 #define	KBDMOUSE_CLEAR		0x84
187 #define	FLOPPY_CLEAR		0x85
188 #define	THERMAL_CLEAR		0x86
189 #define	TIMER0_CLEAR		0x8B
190 #define	TIMER1_CLEAR		0x8C
191 #define	UE_ECC_CLEAR		0x8D
192 #define	CE_ECC_CLEAR		0x8E
193 #define	SBUS_ERR_CLEAR		0x8F
194 #define	PM_WAKEUP_CLEAR		0x90
195 
196 /*
197  * Bit shift for accessing the keyboard mouse interrupt state reg.
198  * note - The external devices are the only other devices where
199  * we need to check the interrupt state before adding or removing
200  * interrupts.  There is an algorithm to calculate their bit shift.
201  */
202 #define	ESP_INTR_STATE_SHIFT		0
203 #define	ETHER_INTR_STATE_SHIFT		2
204 #define	PP_INTR_STATE_SHIFT		4
205 #define	AUDIO_INTR_STATE_SHIFT		6
206 #define	KBDMOUSE_INTR_STATE_SHIFT	10
207 #define	FLOPPY_INTR_STATE_SHIFT		12
208 #define	THERMAL_INTR_STATE_SHIFT	14
209 #define	TIMER0_INTR_STATE_SHIFT		22
210 #define	TIMER1_INTR_STATE_SHIFT		24
211 #define	UE_INTR_STATE_SHIFT		26
212 #define	CE_INTR_STATE_SHIFT		28
213 #define	SERR_INTR_STATE_SHIFT		30
214 #define	PM_INTR_STATE_SHIFT		32
215 
216 #define	MAX_INO_TABLE_SIZE	58	/* Max num of sbus devices on sysio */
217 #define	MAX_MONDO_EXTERNAL	0x1f
218 #define	SBUS_MAX_INO		0x3f
219 #define	THERMAL_MONDO		0x2a
220 #define	UE_ECC_MONDO		0x34
221 #define	CE_ECC_MONDO		0x35
222 #define	SBUS_ERR_MONDO		0x36
223 
224 /* used for the picN kstats */
225 #define	SBUS_NUM_PICS	2
226 #define	SBUS_NUM_EVENTS	14
227 #define	SBUS_PIC0_MASK	0x00000000FFFFFFFFULL	/* pic0 bits of %pic */
228 
229 /* Offsets for Performance registers */
230 #define	OFF_SBUS_PCR	0x100
231 #define	OFF_SBUS_PIC	0x108
232 
233 /*
234  * used to build array of event-names and pcr-mask values
235  */
236 typedef	struct	sbus_event_mask {
237 	char	*event_name;
238 	uint64_t pcr_mask;
239 } sbus_event_mask_t;
240 
241 /*
242  * This type is used to describe addresses that we expect a device
243  * to place on a bus i.e. addresses from the iommu address space.
244  */
245 typedef	uint32_t	ioaddr_t;
246 
247 
248 /*
249  * sysio sbus soft state data structure.
250  * We use the sbus_ctrl_reg to flush hardware store buffers because
251  * there is very little hardware contention on this register.
252  */
253 struct sbus_soft_state {
254 	dev_info_t *dip;		/* dev info of myself */
255 	int upa_id;			/* UPA ID of this SYSIO */
256 
257 	/*
258 	 * device node address property:
259 	 */
260 	caddr_t address;
261 
262 	/*
263 	 * access handles in case we need to map the registers ourself:
264 	 */
265 	ddi_acc_handle_t ac;
266 
267 	volatile uint64_t *iommu_flush_reg; /* IOMMU regs */
268 	volatile uint64_t *iommu_ctrl_reg;
269 	volatile uint64_t *tsb_base_addr;  /* Hardware reg for phys TSB base */
270 	volatile uint64_t *soft_tsb_base_addr; /* virtual address of TSB base */
271 	volatile uint64_t *iommu_tlb_tag;
272 	volatile uint64_t *iommu_tlb_data;
273 
274 	size_t iommu_dvma_size;
275 	ioaddr_t iommu_dvma_base;
276 	uint16_t iommu_tsb_cookie;
277 
278 
279 	volatile uint64_t *sysio_ctrl_reg;	/* sysio regs */
280 	volatile uint64_t *sbus_ctrl_reg;   /* also used to flush store bufs */
281 	volatile uint64_t *sbus_slot_config_reg;
282 	uint_t sbus_slave_burstsizes[MAX_SBUS_SLOTS];
283 
284 	volatile uint64_t *intr_mapping_reg;	/* Interrupt regs */
285 	volatile uint64_t *clr_intr_reg;
286 	volatile uint64_t *intr_retry_reg;
287 	volatile uint64_t *sbus_intr_state;
288 	volatile uint64_t *obio_intr_state;
289 	int8_t intr_hndlr_cnt[MAX_SBUS_SLOT_ADDR]; /* intmapreg cntr by slot */
290 	uchar_t spurious_cntrs[MAX_PIL + 1];	/* Spurious intr counter */
291 
292 	volatile uint64_t *sysio_ecc_reg;	/* sysio ecc control reg */
293 	volatile uint64_t *sysio_ue_reg;	/* sysio ue ecc error regs */
294 	volatile uint64_t *sysio_ce_reg;	/* sysio ce ecc error regs */
295 	volatile uint64_t *sbus_err_reg;	/* sbus async error regs */
296 
297 	volatile uint64_t *str_buf_ctrl_reg;	/* streaming buffer regs */
298 	volatile uint64_t *str_buf_flush_reg;
299 	volatile uint64_t *str_buf_sync_reg;
300 	volatile uint64_t *str_buf_pg_tag_diag;
301 	kmutex_t sync_reg_lock;			/* lock around sync flush reg */
302 	int stream_buf_off;
303 
304 	uint_t sbus_burst_sizes;
305 	uint_t sbus64_burst_sizes;
306 
307 	vmem_t *dvma_arena;		/* DVMA arena for this IOMMU */
308 	uintptr_t dvma_call_list_id;	/* DVMA callback list */
309 	kmutex_t dma_pool_lock;
310 	caddr_t dmaimplbase;		/* dma_pool_lock protects this */
311 	int	dma_reserve;		/* Size reserved for fast DVMA */
312 
313 	struct sbus_wrapper_arg *intr_list[MAX_INO_TABLE_SIZE];
314 	kmutex_t intr_poll_list_lock;	/* to add/rem to intr poll list */
315 	kmutex_t pokefault_mutex;	/* mutex for pokefaults */
316 	on_trap_data_t *ontrap_data;	/* Data used to handle poke faults */
317 	hrtime_t bto_timestamp;		/* time of first timeout */
318 	int bto_ctr;			/* counter for timeouts thereafter */
319 	pfn_t sbus_io_lo_pfn;
320 	pfn_t sbus_io_hi_pfn;
321 	struct iophyslist *sbus_io_ranges;
322 	int intr_mapping_ign;		/* placeholder for the IGN */
323 #ifdef	DEBUG
324 	kmutex_t iomemlock;		/* Memory usage lock (debug only) */
325 	struct io_mem_list *iomem;	/* Memory usage list (debug only) */
326 #endif /* DEBUG */
327 	/*
328 	 * Performance registers and kstat.
329 	 */
330 	volatile uint64_t *sbus_pcr;	/* perf counter control */
331 	volatile uint64_t *sbus_pic; 	/* perf counter register */
332 	kstat_t	*sbus_counters_ksp;	/* perf counter kstat */
333 };
334 
335 
336 /*
337  * Ugly interrupt cruft due to sysio inconsistencies.
338  */
339 struct sbus_slot_entry {
340 	uint64_t slot_config;
341 	uint64_t mapping_reg;
342 	uint64_t clear_reg;
343 	int diagreg_shift;
344 };
345 
346 struct sbus_intr_handler {
347 	dev_info_t *dip;
348 	uint32_t inum;
349 	uint_t (*funcp)();
350 	caddr_t arg1;
351 	caddr_t arg2;
352 	uint_t	intr_state;
353 	struct sbus_intr_handler *next;
354 };
355 
356 /* sbus Interrupt routine wrapper structure */
357 struct sbus_wrapper_arg {
358 	struct sbus_soft_state *softsp;
359 	volatile uint64_t *clear_reg;
360 	uint32_t pil;
361 	struct sbus_intr_handler *handler_list;
362 };
363 
364 
365 /*
366  * SYSIO parent private data structure contains register, interrupt, property
367  * and range information.
368  * Note: the only thing different from the "generic" sbus parent private
369  * data is the interrupt specification.
370  */
371 struct sysio_parent_private_data {
372 	int par_nreg;			/* number of regs */
373 	struct regspec *par_reg;	/* array of regs */
374 	int par_nintr;			/* number of interrupts */
375 	struct sysiointrspec *par_intr;	/* array of possible interrupts */
376 	int par_nrng;			/* number of ranges */
377 	struct rangespec *par_rng;	/* array of ranges */
378 	uint_t slot;			/* Slot number, on this sbus */
379 	uint_t offset;			/* Offset of first real "reg" */
380 };
381 #define	SYSIO_PD(d)	\
382 	((struct sysio_parent_private_data *)DEVI((d))->devi_parent_data)
383 
384 #define	sysio_pd_getnreg(dev)		(SYSIO_PD(dev)->par_nreg)
385 #define	sysio_pd_getnintr(dev)		(SYSIO_PD(dev)->par_nintr)
386 #define	sysio_pd_getnrng(dev)		(SYSIO_PD(dev)->par_nrng)
387 #define	sysio_pd_getslot(dev)		(SYSIO_PD(dev)->slot)
388 #define	sysio_pd_getoffset(dev)		(SYSIO_PD(dev)->offset)
389 
390 #define	sysio_pd_getreg(dev, n)		(&SYSIO_PD(dev)->par_reg[(n)])
391 #define	sysio_pd_getintr(dev, n)	(&SYSIO_PD(dev)->par_intr[(n)])
392 #define	sysio_pd_getrng(dev, n)		(&SYSIO_PD(dev)->par_rng[(n)])
393 
394 #define	IS_INTRA_SBUS(softsp, pfn)	(pfn >= softsp->sbus_io_lo_pfn && \
395 					    pfn <= softsp->sbus_io_hi_pfn)
396 
397 /* Used for legacy interrupts */
398 #define	SBUS_INTR_STATE_DISABLE		0	/* disabled */
399 #define	SBUS_INTR_STATE_ENABLE		1	/* enabled */
400 
401 struct io_mem_list {
402 	dev_info_t *rdip;
403 	ulong_t	ioaddr;
404 	ulong_t	addr;
405 	pgcnt_t npages;
406 	pfn_t *pfn;
407 	struct io_mem_list *next;
408 };
409 
410 /*
411  * Function prototypes.
412  */
413 
414 
415 #ifdef	__cplusplus
416 }
417 #endif
418 
419 #endif	/* _SYS_SYSIOSBUS_H */
420