1/*-
2 * Copyright (c) 2015 The FreeBSD Foundation
3 *
4 * This software was developed by Semihalf under
5 * the sponsorship of the FreeBSD Foundation.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29#ifndef _GIC_V3_VAR_H_
30#define _GIC_V3_VAR_H_
31
32#include <arm/arm/gic_common.h>
33
34#define	GIC_V3_DEVSTR	"ARM Generic Interrupt Controller v3.0"
35
36DECLARE_CLASS(gic_v3_driver);
37
38struct gic_v3_irqsrc;
39
40struct redist_pcpu {
41	struct resource		*res;		/* mem resource for redist */
42	vm_offset_t		pend_base;
43	bus_size_t		offset;
44	bool			lpi_enabled;	/* redist LPI configured? */
45};
46
47struct gic_redists {
48	/*
49	 * Re-Distributor region description.
50	 * We will have few of those depending
51	 * on the #redistributor-regions property in FDT.
52	 */
53	struct resource **	regions;
54	/* Number of Re-Distributor regions */
55	u_int			nregions;
56	/* Per-CPU Re-Distributor data */
57	struct redist_pcpu	*pcpu;
58};
59
60struct gic_v3_softc {
61	device_t		dev;
62	struct resource **	gic_res;
63	struct mtx		gic_mtx;
64	/* Distributor */
65	struct resource *	gic_dist;
66	/* Re-Distributors */
67	struct gic_redists	gic_redists;
68
69	/* Message Based Interrupts */
70	u_int			gic_mbi_start;
71	u_int			gic_mbi_end;
72	struct mtx		gic_mbi_mtx;
73
74	uint32_t		gic_pidr2;
75	u_int			gic_bus;
76
77	u_int			gic_nirqs;
78	u_int			gic_idbits;
79
80	boolean_t		gic_registered;
81
82	int			gic_nchildren;
83	device_t		*gic_children;
84	struct intr_pic		*gic_pic;
85	struct gic_v3_irqsrc	*gic_irqs;
86
87	int			nranges;
88	struct arm_gic_range *	ranges;
89};
90
91struct gic_v3_devinfo {
92	int gic_domain;
93	int msi_xref;
94	int is_vgic;
95};
96
97#define GIC_INTR_ISRC(sc, irq)	(&sc->gic_irqs[irq].gi_isrc)
98
99MALLOC_DECLARE(M_GIC_V3);
100
101/* ivars */
102#define	GICV3_IVAR_NIRQS	1000
103/* 1001 was GICV3_IVAR_REDIST_VADDR */
104#define	GICV3_IVAR_REDIST	1002
105#define	GICV3_IVAR_SUPPORT_LPIS	1003
106
107__BUS_ACCESSOR(gicv3, nirqs, GICV3, NIRQS, u_int);
108__BUS_ACCESSOR(gicv3, redist, GICV3, REDIST, void *);
109__BUS_ACCESSOR(gicv3, support_lpis, GICV3, SUPPORT_LPIS, bool);
110
111/* Device methods */
112int gic_v3_attach(device_t dev);
113int gic_v3_detach(device_t dev);
114int arm_gic_v3_intr(void *);
115
116uint32_t gic_r_read_4(device_t, bus_size_t);
117uint64_t gic_r_read_8(device_t, bus_size_t);
118void gic_r_write_4(device_t, bus_size_t, uint32_t var);
119void gic_r_write_8(device_t, bus_size_t, uint64_t var);
120
121/*
122 * GIC Distributor accessors.
123 * Notice that only GIC sofc can be passed.
124 */
125#define	gic_d_read(sc, len, reg)		\
126({						\
127	bus_read_##len(sc->gic_dist, reg);	\
128})
129
130#define	gic_d_write(sc, len, reg, val)		\
131({						\
132	bus_write_##len(sc->gic_dist, reg, val);\
133})
134
135/* GIC Re-Distributor accessors (per-CPU) */
136#define	gic_r_read(sc, len, reg)		\
137({						\
138	u_int cpu = PCPU_GET(cpuid);		\
139						\
140	bus_read_##len(				\
141	    (sc)->gic_redists.pcpu[cpu].res,	\
142	    (sc)->gic_redists.pcpu[cpu].offset + (reg)); \
143})
144
145#define	gic_r_write(sc, len, reg, val)		\
146({						\
147	u_int cpu = PCPU_GET(cpuid);		\
148						\
149	bus_write_##len(			\
150	    (sc)->gic_redists.pcpu[cpu].res,	\
151	    (sc)->gic_redists.pcpu[cpu].offset + (reg), \
152	    (val));				\
153})
154
155#endif /* _GIC_V3_VAR_H_ */
156