1 /* SPDX-License-Identifier: MIT */
2 /*
3  * Copyright © 2023 Intel Corporation
4  */
5 
6 #ifndef __INTEL_UNCORE_H__
7 #define __INTEL_UNCORE_H__
8 
9 #include "xe_device.h"
10 #include "xe_device_types.h"
11 #include "xe_mmio.h"
12 
13 static inline struct xe_gt *__compat_uncore_to_gt(struct intel_uncore *uncore)
14 {
15 	struct xe_device *xe = container_of(uncore, struct xe_device, uncore);
16 
17 	return xe_root_mmio_gt(xe);
18 }
19 
20 static inline u32 intel_uncore_read(struct intel_uncore *uncore,
21 				    i915_reg_t i915_reg)
22 {
23 	struct xe_reg reg = XE_REG(i915_mmio_reg_offset(i915_reg));
24 
25 	return xe_mmio_read32(__compat_uncore_to_gt(uncore), reg);
26 }
27 
28 static inline u32 intel_uncore_read8(struct intel_uncore *uncore,
29 				     i915_reg_t i915_reg)
30 {
31 	struct xe_reg reg = XE_REG(i915_mmio_reg_offset(i915_reg));
32 
33 	return xe_mmio_read8(__compat_uncore_to_gt(uncore), reg);
34 }
35 
36 static inline u32 intel_uncore_read16(struct intel_uncore *uncore,
37 				      i915_reg_t i915_reg)
38 {
39 	struct xe_reg reg = XE_REG(i915_mmio_reg_offset(i915_reg));
40 
41 	return xe_mmio_read16(__compat_uncore_to_gt(uncore), reg);
42 }
43 
44 static inline u64
45 intel_uncore_read64_2x32(struct intel_uncore *uncore,
46 			 i915_reg_t i915_lower_reg, i915_reg_t i915_upper_reg)
47 {
48 	struct xe_reg lower_reg = XE_REG(i915_mmio_reg_offset(i915_lower_reg));
49 	struct xe_reg upper_reg = XE_REG(i915_mmio_reg_offset(i915_upper_reg));
50 	u32 upper, lower, old_upper;
51 	int loop = 0;
52 
53 	upper = xe_mmio_read32(__compat_uncore_to_gt(uncore), upper_reg);
54 	do {
55 		old_upper = upper;
56 		lower = xe_mmio_read32(__compat_uncore_to_gt(uncore), lower_reg);
57 		upper = xe_mmio_read32(__compat_uncore_to_gt(uncore), upper_reg);
58 	} while (upper != old_upper && loop++ < 2);
59 
60 	return (u64)upper << 32 | lower;
61 }
62 
63 static inline void intel_uncore_posting_read(struct intel_uncore *uncore,
64 					     i915_reg_t i915_reg)
65 {
66 	struct xe_reg reg = XE_REG(i915_mmio_reg_offset(i915_reg));
67 
68 	xe_mmio_read32(__compat_uncore_to_gt(uncore), reg);
69 }
70 
71 static inline void intel_uncore_write(struct intel_uncore *uncore,
72 				      i915_reg_t i915_reg, u32 val)
73 {
74 	struct xe_reg reg = XE_REG(i915_mmio_reg_offset(i915_reg));
75 
76 	xe_mmio_write32(__compat_uncore_to_gt(uncore), reg, val);
77 }
78 
79 static inline u32 intel_uncore_rmw(struct intel_uncore *uncore,
80 				   i915_reg_t i915_reg, u32 clear, u32 set)
81 {
82 	struct xe_reg reg = XE_REG(i915_mmio_reg_offset(i915_reg));
83 
84 	return xe_mmio_rmw32(__compat_uncore_to_gt(uncore), reg, clear, set);
85 }
86 
87 static inline int intel_wait_for_register(struct intel_uncore *uncore,
88 					  i915_reg_t i915_reg, u32 mask,
89 					  u32 value, unsigned int timeout)
90 {
91 	struct xe_reg reg = XE_REG(i915_mmio_reg_offset(i915_reg));
92 
93 	return xe_mmio_wait32(__compat_uncore_to_gt(uncore), reg, mask, value,
94 			      timeout * USEC_PER_MSEC, NULL, false);
95 }
96 
97 static inline int intel_wait_for_register_fw(struct intel_uncore *uncore,
98 					     i915_reg_t i915_reg, u32 mask,
99 					     u32 value, unsigned int timeout)
100 {
101 	struct xe_reg reg = XE_REG(i915_mmio_reg_offset(i915_reg));
102 
103 	return xe_mmio_wait32(__compat_uncore_to_gt(uncore), reg, mask, value,
104 			      timeout * USEC_PER_MSEC, NULL, false);
105 }
106 
107 static inline int
108 __intel_wait_for_register(struct intel_uncore *uncore, i915_reg_t i915_reg,
109 			  u32 mask, u32 value, unsigned int fast_timeout_us,
110 			  unsigned int slow_timeout_ms, u32 *out_value)
111 {
112 	struct xe_reg reg = XE_REG(i915_mmio_reg_offset(i915_reg));
113 
114 	return xe_mmio_wait32(__compat_uncore_to_gt(uncore), reg, mask, value,
115 			      fast_timeout_us + 1000 * slow_timeout_ms,
116 			      out_value, false);
117 }
118 
119 static inline u32 intel_uncore_read_fw(struct intel_uncore *uncore,
120 				       i915_reg_t i915_reg)
121 {
122 	struct xe_reg reg = XE_REG(i915_mmio_reg_offset(i915_reg));
123 
124 	return xe_mmio_read32(__compat_uncore_to_gt(uncore), reg);
125 }
126 
127 static inline void intel_uncore_write_fw(struct intel_uncore *uncore,
128 					 i915_reg_t i915_reg, u32 val)
129 {
130 	struct xe_reg reg = XE_REG(i915_mmio_reg_offset(i915_reg));
131 
132 	xe_mmio_write32(__compat_uncore_to_gt(uncore), reg, val);
133 }
134 
135 static inline u32 intel_uncore_read_notrace(struct intel_uncore *uncore,
136 					    i915_reg_t i915_reg)
137 {
138 	struct xe_reg reg = XE_REG(i915_mmio_reg_offset(i915_reg));
139 
140 	return xe_mmio_read32(__compat_uncore_to_gt(uncore), reg);
141 }
142 
143 static inline void intel_uncore_write_notrace(struct intel_uncore *uncore,
144 					      i915_reg_t i915_reg, u32 val)
145 {
146 	struct xe_reg reg = XE_REG(i915_mmio_reg_offset(i915_reg));
147 
148 	xe_mmio_write32(__compat_uncore_to_gt(uncore), reg, val);
149 }
150 
151 static inline void __iomem *intel_uncore_regs(struct intel_uncore *uncore)
152 {
153 	struct xe_device *xe = container_of(uncore, struct xe_device, uncore);
154 
155 	return xe_device_get_root_tile(xe)->mmio.regs;
156 }
157 
158 /*
159  * The raw_reg_{read,write} macros are intended as a micro-optimization for
160  * interrupt handlers so that the pointer indirection on uncore->regs can
161  * be computed once (and presumably cached in a register) instead of generating
162  * extra load instructions for each MMIO access.
163  *
164  * Given that these macros are only intended for non-GSI interrupt registers
165  * (and the goal is to avoid extra instructions generated by the compiler),
166  * these macros do not account for uncore->gsi_offset.  Any caller that needs
167  * to use these macros on a GSI register is responsible for adding the
168  * appropriate GSI offset to the 'base' parameter.
169  */
170 #define raw_reg_read(base, reg) \
171 	readl(base + i915_mmio_reg_offset(reg))
172 #define raw_reg_write(base, reg, value) \
173 	writel(value, base + i915_mmio_reg_offset(reg))
174 
175 #endif /* __INTEL_UNCORE_H__ */
176