125cf1a30Sjl /*
225cf1a30Sjl  * CDDL HEADER START
325cf1a30Sjl  *
425cf1a30Sjl  * The contents of this file are subject to the terms of the
525cf1a30Sjl  * Common Development and Distribution License (the "License").
625cf1a30Sjl  * You may not use this file except in compliance with the License.
725cf1a30Sjl  *
825cf1a30Sjl  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
925cf1a30Sjl  * or http://www.opensolaris.org/os/licensing.
1025cf1a30Sjl  * See the License for the specific language governing permissions
1125cf1a30Sjl  * and limitations under the License.
1225cf1a30Sjl  *
1325cf1a30Sjl  * When distributing Covered Code, include this CDDL HEADER in each
1425cf1a30Sjl  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1525cf1a30Sjl  * If applicable, add the following below this CDDL HEADER, with the
1625cf1a30Sjl  * fields enclosed by brackets "[]" replaced with your own identifying
1725cf1a30Sjl  * information: Portions Copyright [yyyy] [name of copyright owner]
1825cf1a30Sjl  *
1925cf1a30Sjl  * CDDL HEADER END
2025cf1a30Sjl  */
2125cf1a30Sjl /*
22*116f7629Sjfrank  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
2325cf1a30Sjl  * Use is subject to license terms.
2425cf1a30Sjl  */
2625cf1a30Sjl #ifndef	_SYS_PCMU_IB_H
2725cf1a30Sjl #define	_SYS_PCMU_IB_H
2925cf1a30Sjl #pragma ident	"%Z%%M%	%I%	%E% SMI"
3125cf1a30Sjl #ifdef	__cplusplus
3225cf1a30Sjl extern "C" {
3325cf1a30Sjl #endif
3525cf1a30Sjl #include <sys/ddi_subrdefs.h>
3725cf1a30Sjl typedef uint8_t pcmu_ib_ino_t;
3825cf1a30Sjl typedef uint16_t pcmu_ib_mondo_t;
4025cf1a30Sjl /*
4125cf1a30Sjl  * The following structure represents an interrupt entry for an INO.
4225cf1a30Sjl  */
4325cf1a30Sjl typedef struct ih {
4425cf1a30Sjl 	dev_info_t *ih_dip;		/* devinfo structure */
4525cf1a30Sjl 	uint32_t ih_inum;		/* interrupt number for this device */
4625cf1a30Sjl 	uint_t	ih_intr_state;		/* Only used for fixed interrupts */
4725cf1a30Sjl 	uint_t (*ih_handler)();		/* interrupt handler */
4825cf1a30Sjl 	caddr_t ih_handler_arg1;	/* interrupt handler argument #1 */
4925cf1a30Sjl 	caddr_t ih_handler_arg2;	/* interrupt handler argument #2 */
5025cf1a30Sjl 	ddi_acc_handle_t ih_config_handle; /* config space reg map handle */
5125cf1a30Sjl 	struct ih *ih_next;		/* next entry in list */
5225cf1a30Sjl } ih_t;
5425cf1a30Sjl /*
5525cf1a30Sjl  * ino structure : one per CMU-CH ino with interrupt registered
5625cf1a30Sjl  */
5725cf1a30Sjl typedef struct pcmu_ib_ino_info {
5825cf1a30Sjl 	struct pcmu_ib_ino_info *pino_next;
5925cf1a30Sjl 	pcmu_ib_ino_t pino_ino;		/* INO number - 8 bit */
6025cf1a30Sjl 	uint8_t pino_slot_no;		/* PCI slot number 0-8 */
6125cf1a30Sjl 	uint16_t pino_ih_size;		/* size of the pci intrspec list */
6225cf1a30Sjl 	ih_t *pino_ih_head;		/* intr spec (part of ppd) list head */
6325cf1a30Sjl 	ih_t *pino_ih_tail;		/* intr spec (part of ppd) list tail */
6425cf1a30Sjl 	ih_t *pino_ih_start;		/* starting point in intr spec list  */
6525cf1a30Sjl 	pcmu_ib_t *pino_ib_p;		/* link back to interrupt block state */
6625cf1a30Sjl 	volatile uint64_t *pino_clr_reg; /* ino interrupt clear register */
6725cf1a30Sjl 	volatile uint64_t *pino_map_reg; /* ino interrupt mapping register */
6825cf1a30Sjl 	uint64_t pino_map_reg_save;	/* = *pino_map_reg if saved */
6925cf1a30Sjl 	uint32_t pino_pil;		/* PIL for this ino */
7025cf1a30Sjl 	volatile uint_t pino_unclaimed;	/* number of unclaimed interrupts */
7125cf1a30Sjl 	clock_t pino_spurintr_begin;	/* begin time of spurious intr series */
7225cf1a30Sjl 	int pino_established;		/* ino has been associated with a cpu */
7325cf1a30Sjl 	uint32_t pino_cpuid;		/* cpu that ino is targeting */
7425cf1a30Sjl 	int32_t pino_intr_weight;	/* intr weight of devices sharing ino */
7525cf1a30Sjl } pcmu_ib_ino_info_t;
7725cf1a30Sjl /*
7825cf1a30Sjl  * interrupt block soft state structure:
7925cf1a30Sjl  */
8025cf1a30Sjl struct pcmu_ib {
8125cf1a30Sjl 	pcmu_t *pib_pcmu_p;	/* link back to pci soft state */
8225cf1a30Sjl 	pcmu_ign_t pib_ign;	/* interrupt group # */
8325cf1a30Sjl 	uintptr_t pib_obio_intr_map_regs;	/* onboard intr map register */
8425cf1a30Sjl 	uintptr_t pib_obio_clear_intr_regs;	/* onboard intr clear reg */
8525cf1a30Sjl 	volatile uint64_t *pib_upa_imr[2]; /* UPA expansion intr map register */
8625cf1a30Sjl 	uint64_t pib_upa_imr_state[2];	   /* UPA intr map state */ /* RAGS */
8725cf1a30Sjl 	volatile uint64_t *pib_intr_retry_timer_reg; /* intr retry register */
8825cf1a30Sjl 	volatile uint64_t *pib_obio_intr_state_diag_reg; /* onboard intr st. */
8925cf1a30Sjl 	uint_t pib_max_ino;			/* largest supported INO */
9025cf1a30Sjl 	pcmu_ib_ino_info_t *pib_ino_lst;	/* ino link list */
9125cf1a30Sjl 	kmutex_t pib_ino_lst_mutex;		/* mutex for ino link list */
9225cf1a30Sjl 	kmutex_t pib_intr_lock;			/* lock for internal intr  */
9325cf1a30Sjl };
9525cf1a30Sjl #define	PCMU_MAX_INO		0x3f
9625cf1a30Sjl #define	PCMU_INO_BITS		6		/* INO#s are 6 bits long */
9825cf1a30Sjl /*
9925cf1a30Sjl  * Only used for fixed or legacy interrupts
10025cf1a30Sjl  */
10125cf1a30Sjl #define	PCMU_INTR_STATE_DISABLE	0		/* disabled */
10225cf1a30Sjl #define	PCMU_INTR_STATE_ENABLE	1		/* enabled */
10425cf1a30Sjl #define	PCMU_IB_INTR_WAIT	1		/* wait for inter completion */
10525cf1a30Sjl #define	PCMU_IB_INTR_NOWAIT	0		/* handling intr, no wait */
10725cf1a30Sjl #define	PCMU_IB2CB(pib_p)	((pib_p)->pib_pcmu_p->pcmu_cb_p)
10925cf1a30Sjl #define	PCMU_IB_MONDO_TO_INO(mondo)	((pcmu_ib_ino_t)((mondo) & 0x3f))
11025cf1a30Sjl #define	PCMU_IB_INO_INTR_ON(reg_p)	*(reg_p) |= PCMU_INTR_MAP_REG_VALID
11125cf1a30Sjl #define	PCMU_IB_INO_INTR_OFF(reg_p)	*(reg_p) &= ~PCMU_INTR_MAP_REG_VALID
11225cf1a30Sjl #define	PCMU_IB_INO_INTR_STATE_REG(pib_p, ino)		\
11325cf1a30Sjl 	    (pib_p->pib_obio_intr_state_diag_reg)
11525cf1a30Sjl #define	PCMU_IB_INO_INTR_PENDING(reg_p, ino)		\
11625cf1a30Sjl 	    (((*(reg_p) >> (((ino) & 0x1f) << 1)) &	\
11925cf1a30Sjl #define	PCMU_IB_INO_INTR_CLEAR(reg_p)	*(reg_p) = PCMU_CLEAR_INTR_REG_IDLE
12025cf1a30Sjl #define	PCMU_IB_INO_INTR_PEND(reg_p)	*(reg_p) = PCMU_CLEAR_INTR_REG_PENDING
12125cf1a30Sjl #define	PCMU_IB_INO_INTR_ISON(imr)	((imr) >> 31)
12325cf1a30Sjl #define	PCMU_IB_IMR2MONDO(imr)	((imr) &		\
12625cf1a30Sjl #define	PCMU_IB_IS_OBIO_INO(ino) (ino & 0x20)
12825cf1a30Sjl #define	PCMU_IB_IGN_TO_MONDO(ign, ino)	(((ign) << PCMU_INO_BITS) | (ino))
12925cf1a30Sjl #define	PCMU_IB_INO_TO_MONDO(pib_p, ino)	\
13025cf1a30Sjl     PCMU_IB_IGN_TO_MONDO((pib_p)->pib_ign, ino)
13325cf1a30Sjl extern int pcmu_pil[];
13525cf1a30Sjl /*
13625cf1a30Sjl  * Prototypes
13725cf1a30Sjl  */
13825cf1a30Sjl extern void pcmu_ib_create(pcmu_t *pcmu_p);
13925cf1a30Sjl extern void pcmu_ib_destroy(pcmu_t *pcmu_p);
14025cf1a30Sjl extern void pcmu_ib_configure(pcmu_ib_t *pib_p);
14125cf1a30Sjl extern uint64_t ib_get_map_reg(pcmu_ib_mondo_t mondo, uint32_t cpu_id);
14225cf1a30Sjl extern void pcmu_ib_intr_enable(pcmu_t *pcmu_p, pcmu_ib_ino_t ino);
14325cf1a30Sjl extern void pcmu_ib_intr_disable(pcmu_ib_t *pib_p, pcmu_ib_ino_t ino, int wait);
14425cf1a30Sjl extern void pcmu_ib_nintr_clear(pcmu_ib_t *pib_p, pcmu_ib_ino_t ino);
14525cf1a30Sjl extern void pcmu_ib_suspend(pcmu_ib_t *pib_p);
14625cf1a30Sjl extern void pcmu_ib_resume(pcmu_ib_t *pib_p);
14725cf1a30Sjl extern pcmu_ib_ino_info_t *pcmu_ib_locate_ino(pcmu_ib_t *pib_p,
14825cf1a30Sjl     pcmu_ib_ino_t ino_num);
14925cf1a30Sjl extern pcmu_ib_ino_info_t *pcmu_ib_new_ino(pcmu_ib_t *pib_p,
15025cf1a30Sjl     pcmu_ib_ino_t ino_num, ih_t *ih_p);
15125cf1a30Sjl extern void pcmu_ib_delete_ino(pcmu_ib_t *pib_p, pcmu_ib_ino_info_t *ino_p);
15225cf1a30Sjl extern void pcmu_ib_free_ino_all(pcmu_ib_t *pib_p);
15325cf1a30Sjl extern int pcmu_ib_update_intr_state(pcmu_t *pcmu_p, dev_info_t *rdip,
15425cf1a30Sjl     ddi_intr_handle_impl_t *hdlp, uint_t new_intr_state);
15525cf1a30Sjl extern void pcmu_ib_ino_add_intr(pcmu_t *pcmu_p,
15625cf1a30Sjl     pcmu_ib_ino_info_t *ino_p, ih_t *ih_p);
157*116f7629Sjfrank extern int pcmu_ib_ino_rem_intr(pcmu_t *pcmu_p,
15825cf1a30Sjl     pcmu_ib_ino_info_t *ino_p, ih_t *ih_p);
15925cf1a30Sjl extern ih_t *pcmu_ib_ino_locate_intr(pcmu_ib_ino_info_t *ino_p,
16025cf1a30Sjl     dev_info_t *dip, uint32_t inum);
16125cf1a30Sjl extern ih_t *pcmu_ib_alloc_ih(dev_info_t *dip, uint32_t inum,
16225cf1a30Sjl     uint_t (*int_handler)(caddr_t int_handler_arg1, caddr_t int_handler_arg2),
16325cf1a30Sjl     caddr_t int_handler_arg1, caddr_t int_handler_arg2);
16425cf1a30Sjl extern void pcmu_ib_intr_dist_nintr(pcmu_ib_t *pib_p, pcmu_ib_ino_t ino,
16525cf1a30Sjl     volatile uint64_t *imr_p);
16625cf1a30Sjl extern void pcmu_ib_intr_dist_all(void *arg,
16725cf1a30Sjl     int32_t max_weight, int32_t weight);
16925cf1a30Sjl #ifdef	__cplusplus
17025cf1a30Sjl }
17125cf1a30Sjl #endif
17325cf1a30Sjl #endif	/* _SYS_PCMU_IB_H */