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