xref: /freebsd/sys/contrib/alpine-hal/al_hal_plat_services.h (revision 3fe401a500cdfc73d8c066da3c577c4b9f0aa953)
1 /*-
2 *******************************************************************************
3 Copyright (C) 2015 Annapurna Labs Ltd.
4 
5 This file may be licensed under the terms of the Annapurna Labs Commercial
6 License Agreement.
7 
8 Alternatively, this file can be distributed under the terms of the GNU General
9 Public License V2 as published by the Free Software Foundation and can be
10 found at http://www.gnu.org/licenses/gpl-2.0.html
11 
12 Alternatively, redistribution and use in source and binary forms, with or
13 without modification, are permitted provided that the following conditions are
14 met:
15 
16     *     Redistributions of source code must retain the above copyright notice,
17 this list of conditions and the following disclaimer.
18 
19     *     Redistributions in binary form must reproduce the above copyright
20 notice, this list of conditions and the following disclaimer in
21 the documentation and/or other materials provided with the
22 distribution.
23 
24 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
25 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
28 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
31 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 
35 *******************************************************************************/
36 
37 /**
38  * @defgroup group_services Platform Services API
39  *  @{
40  * The Platform Services API provides miscellaneous system services to HAL
41  * drivers, such as:
42  * - Registers read/write
43  * - Assertions
44  * - Memory barriers
45  * - Endianness conversions
46  *
47  * And more.
48  * @file   plat_api/sample/al_hal_plat_services.h
49  *
50  * @brief  API for Platform services provided for to HAL drivers
51  *
52  *
53  */
54 
55 #ifndef __PLAT_SERVICES_H__
56 #define __PLAT_SERVICES_H__
57 
58 #include <machine/atomic.h>
59 #include <sys/cdefs.h>
60 __FBSDID("$FreeBSD$");
61 
62 #include <sys/param.h>
63 #include <sys/systm.h>
64 #include <sys/kernel.h>
65 #include <sys/endian.h>
66 #include <sys/errno.h>
67 #include <sys/lock.h>
68 #include <sys/mutex.h>
69 
70 /* Prototypes for all the bus_space structure functions */
71 bs_protos(generic);
72 bs_protos(generic_armv4);
73 
74 #define __UNUSED __attribute__((unused))
75 
76 /* *INDENT-OFF* */
77 #ifdef __cplusplus
78 extern "C" {
79 #endif
80 /* *INDENT-ON* */
81 
82 /*
83  * WMA: This is a hack which allows not modifying the __iomem accessing HAL code.
84  * On ARMv7, bus_handle holds the information about VA of accessed memory. It
85  * is possible to use direct load/store instruction instead of bus_dma machinery.
86  * WARNING: This is not guaranteed to stay that way forever, nor that
87  * on other architectures these variables behave similarly. Keep that
88  * in mind during porting to other systems.
89  */
90 /**
91  * Read MMIO 8 bits register
92  * @param  offset	register offset
93  *
94  * @return register value
95  */
96 static uint8_t al_reg_read8(uint8_t * offset);
97 
98 /**
99  * Read MMIO 16 bits register
100  * @param  offset	register offset
101  *
102  * @return register value
103  */
104 static uint16_t al_reg_read16(uint16_t * offset);
105 
106 /**
107  * Read MMIO 32 bits register
108  * @param  offset	register offset
109  *
110  * @return register value
111  */
112 static uint32_t al_reg_read32(uint32_t * offset);
113 
114 /**
115  * Read MMIO 64 bits register
116  * @param  offset	register offset
117  *
118  * @return register value
119  */
120 uint64_t al_reg_read64(uint64_t * offset);
121 
122 /**
123  * Relaxed read MMIO 32 bits register
124  *
125  * Relaxed register read/write functions don't involve cpu instructions that
126  * force syncronization, nor ordering between the register access and memory
127  * data access.
128  * These instructions are used in performance critical code to avoid the
129  * overhead of the synchronization instructions.
130  *
131  * @param  offset	register offset
132  *
133  * @return register value
134  */
135 #define al_bus_dma_to_va(bus_tag, bus_handle)	((void*)bus_handle)
136 
137 /**
138  * Relaxed read MMIO 32 bits register
139  *
140  * Relaxed register read/write functions don't involve cpu instructions that
141  * force syncronization, nor ordering between the register access and memory
142  * data access.
143  * These instructions are used in performance critical code to avoid the
144  * overhead of the synchronization instructions.
145  *
146  * @param  offset	register offset
147  *
148  * @return register value
149  */
150 #define al_reg_read32_relaxed(l)	generic_bs_r_4(NULL, (bus_space_handle_t)l, 0)
151 
152 /**
153  * Relaxed write to MMIO 32 bits register
154  *
155  * Relaxed register read/write functions don't involve cpu instructions that
156  * force syncronization, nor ordering between the register access and memory
157  * data access.
158  * These instructions are used in performance critical code to avoid the
159  * overhead of the synchronization instructions.
160  *
161  * @param  offset	register offset
162  * @param  val		value to write to the register
163  */
164 #define al_reg_write32_relaxed(l,v)	generic_bs_w_4(NULL, (bus_space_handle_t)l, 0, v)
165 
166 /**
167  * Write to MMIO 8 bits register
168  * @param  offset	register offset
169  * @param  val		value to write to the register
170  */
171 #define al_reg_write8(l,v)	do { dsb(); generic_bs_w_1(NULL, (bus_space_handle_t)l, 0, v); dmb(); } while (0)
172 
173 /**
174  * Write to MMIO 16 bits register
175  * @param  offset	register offset
176  * @param  val		value to write to the register
177  */
178 #define al_reg_write16(l,v)	do { dsb(); generic_bs_w_2(NULL, (bus_space_handle_t)l, 0, v); dmb(); } while (0)
179 
180 /**
181  * Write to MMIO 32 bits register
182  * @param  offset	register offset
183  * @param  val		value to write to the register
184  */
185 #define al_reg_write32(l,v)	do { dsb(); generic_bs_w_4(NULL, (bus_space_handle_t)l, 0, v); dmb(); } while (0)
186 
187 /**
188  * Write to MMIO 64 bits register
189  * @param  offset	register offset
190  * @param  val		value to write to the register
191  */
192 #define al_reg_write64(l,v)	do { dsb(); generic_bs_w_8(NULL, (bus_space_handle_t)l, 0, v); dmb(); } while (0)
193 
194 static inline uint8_t
195 al_reg_read8(uint8_t *l)
196 {
197 	dsb();
198 
199 	return (generic_bs_r_1(NULL, (bus_space_handle_t)l, 0));
200 }
201 
202 static inline uint16_t
203 al_reg_read16(uint16_t *l)
204 {
205 	dsb();
206 
207 	return (generic_bs_r_2(NULL, (bus_space_handle_t)l, 0));
208 }
209 
210 static inline uint32_t
211 al_reg_read32(uint32_t *l)
212 {
213 	dsb();
214 
215 	return (generic_bs_r_4(NULL, (bus_space_handle_t)l, 0));
216 }
217 
218 #define AL_DBG_LEVEL_NONE 0
219 #define AL_DBG_LEVEL_ERR 1
220 #define AL_DBG_LEVEL_WARN 2
221 #define AL_DBG_LEVEL_INFO 3
222 #define AL_DBG_LEVEL_DBG 4
223 
224 #define AL_DBG_LEVEL AL_DBG_LEVEL_ERR
225 
226 extern struct mtx al_dbg_lock;
227 
228 #define AL_DBG_LOCK()	mtx_lock_spin(&al_dbg_lock)
229 #define AL_DBG_UNLOCK()	mtx_unlock_spin(&al_dbg_lock)
230 
231 /**
232  * print message
233  *
234  * @param format The format string
235  * @param ... Additional arguments
236  */
237 #define al_print(type, fmt, ...) 		do { if (AL_DBG_LEVEL >= AL_DBG_LEVEL_NONE) { AL_DBG_LOCK(); printf(fmt, ##__VA_ARGS__); AL_DBG_UNLOCK(); } } while(0)
238 
239 /**
240  * print error message
241  *
242  * @param format
243  */
244 #define al_err(...)			do { if (AL_DBG_LEVEL >= AL_DBG_LEVEL_ERR) { AL_DBG_LOCK(); printf(__VA_ARGS__); AL_DBG_UNLOCK(); } } while(0)
245 
246 /**
247  * print warning message
248  *
249  * @param format
250  */
251 #define al_warn(...)			do { if (AL_DBG_LEVEL >= AL_DBG_LEVEL_WARN) { AL_DBG_LOCK(); printf(__VA_ARGS__); AL_DBG_UNLOCK(); } } while(0)
252 
253 /**
254  * print info message
255  *
256  * @param format
257  */
258 #define al_info(...)			do { if (AL_DBG_LEVEL >= AL_DBG_LEVEL_INFO) { AL_DBG_LOCK(); printf(__VA_ARGS__); AL_DBG_UNLOCK(); } } while(0)
259 
260 /**
261  * print debug message
262  *
263  * @param format
264  */
265 #define al_dbg(...)			do { if (AL_DBG_LEVEL >= AL_DBG_LEVEL_DBG) { AL_DBG_LOCK(); printf(__VA_ARGS__); AL_DBG_UNLOCK(); } } while(0)
266 
267 /**
268  * Assertion
269  *
270  * @param condition
271  */
272 #define al_assert(COND)		\
273 	do {			\
274 		if (!(COND))	\
275 			al_err(	\
276 			"%s:%d:%s: Assertion failed! (%s)\n",	\
277 			__FILE__, __LINE__, __func__, #COND);	\
278 	} while(AL_FALSE)
279 
280 /**
281   * Make sure data will be visible by other masters (other CPUS and DMA).
282   * usually this is achieved by the ARM DMB instruction.
283   */
284 static void al_data_memory_barrier(void);
285 
286 /**
287   * Make sure data will be visible by DMA masters, no restriction for other cpus
288   */
289 static inline void
290 al_data_memory_barrier(void)
291 {
292 	dsb();
293 }
294 
295 /**
296   * Make sure data will be visible in order by other cpus masters.
297   */
298 static inline void
299 al_smp_data_memory_barrier(void)
300 {
301 	dsb();
302 }
303 
304 /**
305   * Make sure write data will be visible in order by other cpus masters.
306   */
307 static inline void
308 al_local_data_memory_barrier(void)
309 {
310 	dsb();
311 }
312 
313 /**
314  * al_udelay - micro sec delay
315  */
316 #define al_udelay(u)		DELAY(u)
317 
318 /**
319  * al_msleep - mili sec delay
320  */
321 #define al_msleep(m)		DELAY((m) * 1000)
322 
323 /**
324  * swap half word to little endian
325  *
326  * @param x 16 bit value
327  *
328  * @return the value in little endian
329  */
330 #define swap16_to_le(x)		htole16(x)
331 /**
332  * swap word to little endian
333  *
334  * @param x 32 bit value
335  *
336  * @return the value in little endian
337  */
338 #define swap32_to_le(x)		htole32(x)
339 
340 /**
341  * swap 8 bytes to little endian
342  *
343  * @param x 64 bit value
344  *
345  * @return the value in little endian
346  */
347 #define swap64_to_le(x)		htole64(x)
348 
349 /**
350  * swap half word from little endian
351  *
352  * @param x 16 bit value
353  *
354  * @return the value in the cpu endianess
355  */
356 #define swap16_from_le(x)	le16toh(x)
357 
358 /**
359  * swap word from little endian
360  *
361  * @param x 32 bit value
362  *
363  * @return the value in the cpu endianess
364  */
365 #define swap32_from_le(x)	le32toh(x)
366 
367 /**
368  * swap 8 bytes from little endian
369  *
370  * @param x 64 bit value
371  *
372  * @return the value in the cpu endianess
373  */
374 #define swap64_from_le(x)	le64toh(x)
375 
376 /**
377  * Memory set
378  *
379  * @param p memory pointer
380  * @param val value for setting
381  * @param cnt number of bytes to set
382  */
383 #define al_memset(p, val, cnt)	memset(p, val, cnt)
384 
385 /**
386  * Memory copy
387  *
388  * @param p1 memory pointer
389  * @param p2 memory pointer
390  * @param cnt number of bytes to copy
391  */
392 #define al_memcpy(p1, p2, cnt)	memcpy(p1, p2, cnt)
393 
394 /**
395  * Memory compare
396  *
397  * @param p1 memory pointer
398  * @param p2 memory pointer
399  * @param cnt number of bytes to compare
400  */
401 #define al_memcmp(p1, p2, cnt)	memcmp(p1, p2, cnt)
402 
403 /**
404  * String compare
405  *
406  * @param s1 string pointer
407  * @param s2 string pointer
408  */
409 #define al_strcmp(s1, s2)	strcmp(s1, s2)
410 
411 #define al_get_cpu_id()		0
412 
413 /* *INDENT-OFF* */
414 #ifdef __cplusplus
415 }
416 #endif
417 /* *INDENT-ON* */
418 /** @} end of Platform Services API group */
419 #endif				/* __PLAT_SERVICES_H__ */
420