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 #include <machine/bus.h> 70 71 /* Prototypes for all the bus_space structure functions */ 72 uint8_t generic_bs_r_1(bus_space_tag_t t, bus_space_handle_t bsh, 73 bus_size_t offset); 74 75 uint16_t generic_bs_r_2(bus_space_tag_t t, bus_space_handle_t bsh, 76 bus_size_t offset); 77 78 uint32_t generic_bs_r_4(bus_space_tag_t t, bus_space_handle_t bsh, 79 bus_size_t offset); 80 81 void generic_bs_w_1(bus_space_tag_t t, bus_space_handle_t bsh, 82 bus_size_t offset, uint8_t value); 83 84 void generic_bs_w_2(bus_space_tag_t t, bus_space_handle_t bsh, 85 bus_size_t offset, uint16_t value); 86 87 void generic_bs_w_4(bus_space_tag_t t, bus_space_handle_t bsh, 88 bus_size_t offset, uint32_t value); 89 90 void generic_bs_w_8(bus_space_tag_t t, bus_space_handle_t bsh, 91 bus_size_t offset, uint64_t value); 92 93 #define __UNUSED __attribute__((unused)) 94 95 /* *INDENT-OFF* */ 96 #ifdef __cplusplus 97 extern "C" { 98 #endif 99 /* *INDENT-ON* */ 100 101 /** 102 * Make sure data will be visible by other masters (other CPUS and DMA). 103 * usually this is achieved by the ARM DMB instruction. 104 */ 105 static void al_data_memory_barrier(void); 106 static void al_smp_data_memory_barrier(void); 107 108 /** 109 * Make sure data will be visible by DMA masters, no restriction for other cpus 110 */ 111 static inline void 112 al_data_memory_barrier(void) 113 { 114 #ifndef __aarch64__ 115 dsb(); 116 #else 117 dsb(sy); 118 #endif 119 } 120 121 /** 122 * Make sure data will be visible in order by other cpus masters. 123 */ 124 static inline void 125 al_smp_data_memory_barrier(void) 126 { 127 #ifndef __aarch64__ 128 dmb(); 129 #else 130 dmb(ish); 131 #endif 132 } 133 134 /** 135 * Make sure write data will be visible in order by other cpus masters. 136 */ 137 static inline void 138 al_local_data_memory_barrier(void) 139 { 140 #ifndef __aarch64__ 141 dsb(); 142 #else 143 dsb(sy); 144 #endif 145 } 146 147 /* 148 * WMA: This is a hack which allows not modifying the __iomem accessing HAL code. 149 * On ARMv7, bus_handle holds the information about VA of accessed memory. It 150 * is possible to use direct load/store instruction instead of bus_dma machinery. 151 * WARNING: This is not guaranteed to stay that way forever, nor that 152 * on other architectures these variables behave similarly. Keep that 153 * in mind during porting to other systems. 154 */ 155 /** 156 * Read MMIO 8 bits register 157 * @param offset register offset 158 * 159 * @return register value 160 */ 161 static uint8_t al_reg_read8(uint8_t * offset); 162 163 /** 164 * Read MMIO 16 bits register 165 * @param offset register offset 166 * 167 * @return register value 168 */ 169 static uint16_t al_reg_read16(uint16_t * offset); 170 171 /** 172 * Read MMIO 32 bits register 173 * @param offset register offset 174 * 175 * @return register value 176 */ 177 static uint32_t al_reg_read32(uint32_t * offset); 178 179 /** 180 * Read MMIO 64 bits register 181 * @param offset register offset 182 * 183 * @return register value 184 */ 185 uint64_t al_reg_read64(uint64_t * offset); 186 187 /** 188 * Relaxed read MMIO 32 bits register 189 * 190 * Relaxed register read/write functions don't involve cpu instructions that 191 * force syncronization, nor ordering between the register access and memory 192 * data access. 193 * These instructions are used in performance critical code to avoid the 194 * overhead of the synchronization instructions. 195 * 196 * @param offset register offset 197 * 198 * @return register value 199 */ 200 #define al_bus_dma_to_va(bus_tag, bus_handle) ((void*)bus_handle) 201 202 /** 203 * Relaxed read MMIO 32 bits register 204 * 205 * Relaxed register read/write functions don't involve cpu instructions that 206 * force syncronization, nor ordering between the register access and memory 207 * data access. 208 * These instructions are used in performance critical code to avoid the 209 * overhead of the synchronization instructions. 210 * 211 * @param offset register offset 212 * 213 * @return register value 214 */ 215 #define al_reg_read32_relaxed(l) generic_bs_r_4(NULL, (bus_space_handle_t)l, 0) 216 217 /** 218 * Relaxed write to MMIO 32 bits register 219 * 220 * Relaxed register read/write functions don't involve cpu instructions that 221 * force syncronization, nor ordering between the register access and memory 222 * data access. 223 * These instructions are used in performance critical code to avoid the 224 * overhead of the synchronization instructions. 225 * 226 * @param offset register offset 227 * @param val value to write to the register 228 */ 229 #define al_reg_write32_relaxed(l,v) generic_bs_w_4(NULL, (bus_space_handle_t)l, 0, v) 230 231 /** 232 * Write to MMIO 8 bits register 233 * @param offset register offset 234 * @param val value to write to the register 235 */ 236 #define al_reg_write8(l, v) do { \ 237 al_data_memory_barrier(); \ 238 generic_bs_w_1(NULL, (bus_space_handle_t)l, 0, v); \ 239 al_smp_data_memory_barrier(); \ 240 } while (0) 241 242 /** 243 * Write to MMIO 16 bits register 244 * @param offset register offset 245 * @param val value to write to the register 246 */ 247 #define al_reg_write16(l, v) do { \ 248 al_data_memory_barrier(); \ 249 generic_bs_w_2(NULL, (bus_space_handle_t)l, 0, v); \ 250 al_smp_data_memory_barrier(); \ 251 } while (0) 252 253 /** 254 * Write to MMIO 32 bits register 255 * @param offset register offset 256 * @param val value to write to the register 257 */ 258 #define al_reg_write32(l, v) do { \ 259 al_data_memory_barrier(); \ 260 generic_bs_w_4(NULL, (bus_space_handle_t)l, 0, v); \ 261 al_smp_data_memory_barrier(); \ 262 } while (0) 263 264 /** 265 * Write to MMIO 64 bits register 266 * @param offset register offset 267 * @param val value to write to the register 268 */ 269 #define al_reg_write64(l, v) do { \ 270 al_data_memory_barrier(); \ 271 generic_bs_w_8(NULL, (bus_space_handle_t)l, 0, v); \ 272 al_smp_data_memory_barrier(); \ 273 } while (0) 274 275 static inline uint8_t 276 al_reg_read8(uint8_t *l) 277 { 278 279 al_data_memory_barrier(); 280 return (generic_bs_r_1(NULL, (bus_space_handle_t)l, 0)); 281 } 282 283 static inline uint16_t 284 al_reg_read16(uint16_t *l) 285 { 286 287 al_data_memory_barrier(); 288 return (generic_bs_r_2(NULL, (bus_space_handle_t)l, 0)); 289 } 290 291 static inline uint32_t 292 al_reg_read32(uint32_t *l) 293 { 294 295 al_data_memory_barrier(); 296 return (generic_bs_r_4(NULL, (bus_space_handle_t)l, 0)); 297 } 298 299 #define AL_DBG_LEVEL_NONE 0 300 #define AL_DBG_LEVEL_ERR 1 301 #define AL_DBG_LEVEL_WARN 2 302 #define AL_DBG_LEVEL_INFO 3 303 #define AL_DBG_LEVEL_DBG 4 304 305 #define AL_DBG_LEVEL AL_DBG_LEVEL_ERR 306 307 #define AL_DBG_LOCK() 308 #define AL_DBG_UNLOCK() 309 310 /** 311 * print message 312 * 313 * @param format The format string 314 * @param ... Additional arguments 315 */ 316 #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) 317 318 /** 319 * print error message 320 * 321 * @param format 322 */ 323 #define al_err(...) do { if (AL_DBG_LEVEL >= AL_DBG_LEVEL_ERR) { AL_DBG_LOCK(); printf(__VA_ARGS__); AL_DBG_UNLOCK(); } } while(0) 324 325 /** 326 * print warning message 327 * 328 * @param format 329 */ 330 #define al_warn(...) do { if (AL_DBG_LEVEL >= AL_DBG_LEVEL_WARN) { AL_DBG_LOCK(); printf(__VA_ARGS__); AL_DBG_UNLOCK(); } } while(0) 331 332 /** 333 * print info message 334 * 335 * @param format 336 */ 337 #define al_info(...) do { if (AL_DBG_LEVEL >= AL_DBG_LEVEL_INFO) { AL_DBG_LOCK(); printf(__VA_ARGS__); AL_DBG_UNLOCK(); } } while(0) 338 339 /** 340 * print debug message 341 * 342 * @param format 343 */ 344 #define al_dbg(...) do { if (AL_DBG_LEVEL >= AL_DBG_LEVEL_DBG) { AL_DBG_LOCK(); printf(__VA_ARGS__); AL_DBG_UNLOCK(); } } while(0) 345 346 /** 347 * Assertion 348 * 349 * @param condition 350 */ 351 #define al_assert(COND) \ 352 do { \ 353 if (!(COND)) \ 354 al_err( \ 355 "%s:%d:%s: Assertion failed! (%s)\n", \ 356 __FILE__, __LINE__, __func__, #COND); \ 357 } while(AL_FALSE) 358 359 /** 360 * al_udelay - micro sec delay 361 */ 362 #define al_udelay(u) DELAY(u) 363 364 /** 365 * al_msleep - mili sec delay 366 */ 367 #define al_msleep(m) DELAY((m) * 1000) 368 369 /** 370 * swap half word to little endian 371 * 372 * @param x 16 bit value 373 * 374 * @return the value in little endian 375 */ 376 #define swap16_to_le(x) htole16(x) 377 /** 378 * swap word to little endian 379 * 380 * @param x 32 bit value 381 * 382 * @return the value in little endian 383 */ 384 #define swap32_to_le(x) htole32(x) 385 386 /** 387 * swap 8 bytes to little endian 388 * 389 * @param x 64 bit value 390 * 391 * @return the value in little endian 392 */ 393 #define swap64_to_le(x) htole64(x) 394 395 /** 396 * swap half word from little endian 397 * 398 * @param x 16 bit value 399 * 400 * @return the value in the cpu endianess 401 */ 402 #define swap16_from_le(x) le16toh(x) 403 404 /** 405 * swap word from little endian 406 * 407 * @param x 32 bit value 408 * 409 * @return the value in the cpu endianess 410 */ 411 #define swap32_from_le(x) le32toh(x) 412 413 /** 414 * swap 8 bytes from little endian 415 * 416 * @param x 64 bit value 417 * 418 * @return the value in the cpu endianess 419 */ 420 #define swap64_from_le(x) le64toh(x) 421 422 /** 423 * Memory set 424 * 425 * @param p memory pointer 426 * @param val value for setting 427 * @param cnt number of bytes to set 428 */ 429 #define al_memset(p, val, cnt) memset(p, val, cnt) 430 431 /** 432 * Memory copy 433 * 434 * @param p1 memory pointer 435 * @param p2 memory pointer 436 * @param cnt number of bytes to copy 437 */ 438 #define al_memcpy(p1, p2, cnt) memcpy(p1, p2, cnt) 439 440 /** 441 * Memory compare 442 * 443 * @param p1 memory pointer 444 * @param p2 memory pointer 445 * @param cnt number of bytes to compare 446 */ 447 #define al_memcmp(p1, p2, cnt) memcmp(p1, p2, cnt) 448 449 /** 450 * String compare 451 * 452 * @param s1 string pointer 453 * @param s2 string pointer 454 */ 455 #define al_strcmp(s1, s2) strcmp(s1, s2) 456 457 #define al_get_cpu_id() 0 458 459 /* *INDENT-OFF* */ 460 #ifdef __cplusplus 461 } 462 #endif 463 /* *INDENT-ON* */ 464 /** @} end of Platform Services API group */ 465 #endif /* __PLAT_SERVICES_H__ */ 466