1285431Szbb/*- 2285431Szbb******************************************************************************* 3285431SzbbCopyright (C) 2015 Annapurna Labs Ltd. 4285431Szbb 5285431SzbbThis file may be licensed under the terms of the Annapurna Labs Commercial 6285431SzbbLicense Agreement. 7285431Szbb 8285431SzbbAlternatively, this file can be distributed under the terms of the GNU General 9285431SzbbPublic License V2 as published by the Free Software Foundation and can be 10285431Szbbfound at http://www.gnu.org/licenses/gpl-2.0.html 11285431Szbb 12285431SzbbAlternatively, redistribution and use in source and binary forms, with or 13285431Szbbwithout modification, are permitted provided that the following conditions are 14285431Szbbmet: 15285431Szbb 16285431Szbb * Redistributions of source code must retain the above copyright notice, 17285431Szbbthis list of conditions and the following disclaimer. 18285431Szbb 19285431Szbb * Redistributions in binary form must reproduce the above copyright 20285431Szbbnotice, this list of conditions and the following disclaimer in 21285431Szbbthe documentation and/or other materials provided with the 22285431Szbbdistribution. 23285431Szbb 24285431SzbbTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 25285431SzbbANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 26285431SzbbWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 27285431SzbbDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 28285431SzbbANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 29285431Szbb(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 30285431SzbbLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 31285431SzbbANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 32285431Szbb(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33285431SzbbSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34285431Szbb 35285431Szbb*******************************************************************************/ 36285431Szbb 37285431Szbb/** 38285431Szbb * @defgroup group_services Platform Services API 39285431Szbb * @{ 40285431Szbb * The Platform Services API provides miscellaneous system services to HAL 41285431Szbb * drivers, such as: 42285431Szbb * - Registers read/write 43285431Szbb * - Assertions 44285431Szbb * - Memory barriers 45285431Szbb * - Endianness conversions 46285431Szbb * 47285431Szbb * And more. 48285431Szbb * @file plat_api/sample/al_hal_plat_services.h 49285431Szbb * 50285431Szbb * @brief API for Platform services provided for to HAL drivers 51285431Szbb * 52285431Szbb * 53285431Szbb */ 54285431Szbb 55285431Szbb#ifndef __PLAT_SERVICES_H__ 56285431Szbb#define __PLAT_SERVICES_H__ 57285431Szbb 58285431Szbb#include <machine/atomic.h> 59285431Szbb#include <sys/cdefs.h> 60285431Szbb__FBSDID("$FreeBSD: releng/11.0/sys/contrib/alpine-hal/al_hal_plat_services.h 285431 2015-07-12 21:35:45Z zbb $"); 61285431Szbb 62285431Szbb#include <sys/param.h> 63285431Szbb#include <sys/systm.h> 64285431Szbb#include <sys/kernel.h> 65285431Szbb#include <sys/endian.h> 66285431Szbb#include <sys/errno.h> 67285431Szbb#include <sys/lock.h> 68285431Szbb#include <sys/mutex.h> 69285431Szbb 70285431Szbb/* Prototypes for all the bus_space structure functions */ 71285431Szbbbs_protos(generic); 72285431Szbbbs_protos(generic_armv4); 73285431Szbb 74285431Szbb#define __UNUSED __attribute__((unused)) 75285431Szbb 76285431Szbb/* *INDENT-OFF* */ 77285431Szbb#ifdef __cplusplus 78285431Szbbextern "C" { 79285431Szbb#endif 80285431Szbb/* *INDENT-ON* */ 81285431Szbb 82285431Szbb/* 83285431Szbb * WMA: This is a hack which allows not modifying the __iomem accessing HAL code. 84285431Szbb * On ARMv7, bus_handle holds the information about VA of accessed memory. It 85285431Szbb * is possible to use direct load/store instruction instead of bus_dma machinery. 86285431Szbb * WARNING: This is not guaranteed to stay that way forever, nor that 87285431Szbb * on other architectures these variables behave similarly. Keep that 88285431Szbb * in mind during porting to other systems. 89285431Szbb */ 90285431Szbb/** 91285431Szbb * Read MMIO 8 bits register 92285431Szbb * @param offset register offset 93285431Szbb * 94285431Szbb * @return register value 95285431Szbb */ 96285431Szbbstatic uint8_t al_reg_read8(uint8_t * offset); 97285431Szbb 98285431Szbb/** 99285431Szbb * Read MMIO 16 bits register 100285431Szbb * @param offset register offset 101285431Szbb * 102285431Szbb * @return register value 103285431Szbb */ 104285431Szbbstatic uint16_t al_reg_read16(uint16_t * offset); 105285431Szbb 106285431Szbb/** 107285431Szbb * Read MMIO 32 bits register 108285431Szbb * @param offset register offset 109285431Szbb * 110285431Szbb * @return register value 111285431Szbb */ 112285431Szbbstatic uint32_t al_reg_read32(uint32_t * offset); 113285431Szbb 114285431Szbb/** 115285431Szbb * Read MMIO 64 bits register 116285431Szbb * @param offset register offset 117285431Szbb * 118285431Szbb * @return register value 119285431Szbb */ 120285431Szbbuint64_t al_reg_read64(uint64_t * offset); 121285431Szbb 122285431Szbb/** 123285431Szbb * Relaxed read MMIO 32 bits register 124285431Szbb * 125285431Szbb * Relaxed register read/write functions don't involve cpu instructions that 126285431Szbb * force syncronization, nor ordering between the register access and memory 127285431Szbb * data access. 128285431Szbb * These instructions are used in performance critical code to avoid the 129285431Szbb * overhead of the synchronization instructions. 130285431Szbb * 131285431Szbb * @param offset register offset 132285431Szbb * 133285431Szbb * @return register value 134285431Szbb */ 135285431Szbb#define al_bus_dma_to_va(bus_tag, bus_handle) ((void*)bus_handle) 136285431Szbb 137285431Szbb/** 138285431Szbb * Relaxed read MMIO 32 bits register 139285431Szbb * 140285431Szbb * Relaxed register read/write functions don't involve cpu instructions that 141285431Szbb * force syncronization, nor ordering between the register access and memory 142285431Szbb * data access. 143285431Szbb * These instructions are used in performance critical code to avoid the 144285431Szbb * overhead of the synchronization instructions. 145285431Szbb * 146285431Szbb * @param offset register offset 147285431Szbb * 148285431Szbb * @return register value 149285431Szbb */ 150285431Szbb#define al_reg_read32_relaxed(l) generic_bs_r_4(NULL, (bus_space_handle_t)l, 0) 151285431Szbb 152285431Szbb/** 153285431Szbb * Relaxed write to MMIO 32 bits register 154285431Szbb * 155285431Szbb * Relaxed register read/write functions don't involve cpu instructions that 156285431Szbb * force syncronization, nor ordering between the register access and memory 157285431Szbb * data access. 158285431Szbb * These instructions are used in performance critical code to avoid the 159285431Szbb * overhead of the synchronization instructions. 160285431Szbb * 161285431Szbb * @param offset register offset 162285431Szbb * @param val value to write to the register 163285431Szbb */ 164285431Szbb#define al_reg_write32_relaxed(l,v) generic_bs_w_4(NULL, (bus_space_handle_t)l, 0, v) 165285431Szbb 166285431Szbb/** 167285431Szbb * Write to MMIO 8 bits register 168285431Szbb * @param offset register offset 169285431Szbb * @param val value to write to the register 170285431Szbb */ 171285431Szbb#define al_reg_write8(l,v) do { dsb(); generic_bs_w_1(NULL, (bus_space_handle_t)l, 0, v); dmb(); } while (0) 172285431Szbb 173285431Szbb/** 174285431Szbb * Write to MMIO 16 bits register 175285431Szbb * @param offset register offset 176285431Szbb * @param val value to write to the register 177285431Szbb */ 178285431Szbb#define al_reg_write16(l,v) do { dsb(); generic_bs_w_2(NULL, (bus_space_handle_t)l, 0, v); dmb(); } while (0) 179285431Szbb 180285431Szbb/** 181285431Szbb * Write to MMIO 32 bits register 182285431Szbb * @param offset register offset 183285431Szbb * @param val value to write to the register 184285431Szbb */ 185285431Szbb#define al_reg_write32(l,v) do { dsb(); generic_bs_w_4(NULL, (bus_space_handle_t)l, 0, v); dmb(); } while (0) 186285431Szbb 187285431Szbb/** 188285431Szbb * Write to MMIO 64 bits register 189285431Szbb * @param offset register offset 190285431Szbb * @param val value to write to the register 191285431Szbb */ 192285431Szbb#define al_reg_write64(l,v) do { dsb(); generic_bs_w_8(NULL, (bus_space_handle_t)l, 0, v); dmb(); } while (0) 193285431Szbb 194285431Szbbstatic inline uint8_t 195285431Szbbal_reg_read8(uint8_t *l) 196285431Szbb{ 197285431Szbb dsb(); 198285431Szbb 199285431Szbb return (generic_bs_r_1(NULL, (bus_space_handle_t)l, 0)); 200285431Szbb} 201285431Szbb 202285431Szbbstatic inline uint16_t 203285431Szbbal_reg_read16(uint16_t *l) 204285431Szbb{ 205285431Szbb dsb(); 206285431Szbb 207285431Szbb return (generic_bs_r_2(NULL, (bus_space_handle_t)l, 0)); 208285431Szbb} 209285431Szbb 210285431Szbbstatic inline uint32_t 211285431Szbbal_reg_read32(uint32_t *l) 212285431Szbb{ 213285431Szbb dsb(); 214285431Szbb 215285431Szbb return (generic_bs_r_4(NULL, (bus_space_handle_t)l, 0)); 216285431Szbb} 217285431Szbb 218285431Szbb#define AL_DBG_LEVEL_NONE 0 219285431Szbb#define AL_DBG_LEVEL_ERR 1 220285431Szbb#define AL_DBG_LEVEL_WARN 2 221285431Szbb#define AL_DBG_LEVEL_INFO 3 222285431Szbb#define AL_DBG_LEVEL_DBG 4 223285431Szbb 224285431Szbb#define AL_DBG_LEVEL AL_DBG_LEVEL_ERR 225285431Szbb 226285431Szbbextern struct mtx al_dbg_lock; 227285431Szbb 228285431Szbb#define AL_DBG_LOCK() mtx_lock_spin(&al_dbg_lock) 229285431Szbb#define AL_DBG_UNLOCK() mtx_unlock_spin(&al_dbg_lock) 230285431Szbb 231285431Szbb/** 232285431Szbb * print message 233285431Szbb * 234285431Szbb * @param format The format string 235285431Szbb * @param ... Additional arguments 236285431Szbb */ 237285431Szbb#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) 238285431Szbb 239285431Szbb/** 240285431Szbb * print error message 241285431Szbb * 242285431Szbb * @param format 243285431Szbb */ 244285431Szbb#define al_err(...) do { if (AL_DBG_LEVEL >= AL_DBG_LEVEL_ERR) { AL_DBG_LOCK(); printf(__VA_ARGS__); AL_DBG_UNLOCK(); } } while(0) 245285431Szbb 246285431Szbb/** 247285431Szbb * print warning message 248285431Szbb * 249285431Szbb * @param format 250285431Szbb */ 251285431Szbb#define al_warn(...) do { if (AL_DBG_LEVEL >= AL_DBG_LEVEL_WARN) { AL_DBG_LOCK(); printf(__VA_ARGS__); AL_DBG_UNLOCK(); } } while(0) 252285431Szbb 253285431Szbb/** 254285431Szbb * print info message 255285431Szbb * 256285431Szbb * @param format 257285431Szbb */ 258285431Szbb#define al_info(...) do { if (AL_DBG_LEVEL >= AL_DBG_LEVEL_INFO) { AL_DBG_LOCK(); printf(__VA_ARGS__); AL_DBG_UNLOCK(); } } while(0) 259285431Szbb 260285431Szbb/** 261285431Szbb * print debug message 262285431Szbb * 263285431Szbb * @param format 264285431Szbb */ 265285431Szbb#define al_dbg(...) do { if (AL_DBG_LEVEL >= AL_DBG_LEVEL_DBG) { AL_DBG_LOCK(); printf(__VA_ARGS__); AL_DBG_UNLOCK(); } } while(0) 266285431Szbb 267285431Szbb/** 268285431Szbb * Assertion 269285431Szbb * 270285431Szbb * @param condition 271285431Szbb */ 272285431Szbb#define al_assert(COND) \ 273285431Szbb do { \ 274285431Szbb if (!(COND)) \ 275285431Szbb al_err( \ 276285431Szbb "%s:%d:%s: Assertion failed! (%s)\n", \ 277285431Szbb __FILE__, __LINE__, __func__, #COND); \ 278285431Szbb } while(AL_FALSE) 279285431Szbb 280285431Szbb/** 281285431Szbb * Make sure data will be visible by other masters (other CPUS and DMA). 282285431Szbb * usually this is achieved by the ARM DMB instruction. 283285431Szbb */ 284285431Szbbstatic void al_data_memory_barrier(void); 285285431Szbb 286285431Szbb/** 287285431Szbb * Make sure data will be visible by DMA masters, no restriction for other cpus 288285431Szbb */ 289285431Szbbstatic inline void 290285431Szbbal_data_memory_barrier(void) 291285431Szbb{ 292285431Szbb dsb(); 293285431Szbb} 294285431Szbb 295285431Szbb/** 296285431Szbb * Make sure data will be visible in order by other cpus masters. 297285431Szbb */ 298285431Szbbstatic inline void 299285431Szbbal_smp_data_memory_barrier(void) 300285431Szbb{ 301285431Szbb dsb(); 302285431Szbb} 303285431Szbb 304285431Szbb/** 305285431Szbb * Make sure write data will be visible in order by other cpus masters. 306285431Szbb */ 307285431Szbbstatic inline void 308285431Szbbal_local_data_memory_barrier(void) 309285431Szbb{ 310285431Szbb dsb(); 311285431Szbb} 312285431Szbb 313285431Szbb/** 314285431Szbb * al_udelay - micro sec delay 315285431Szbb */ 316285431Szbb#define al_udelay(u) DELAY(u) 317285431Szbb 318285431Szbb/** 319285431Szbb * al_msleep - mili sec delay 320285431Szbb */ 321285431Szbb#define al_msleep(m) DELAY((m) * 1000) 322285431Szbb 323285431Szbb/** 324285431Szbb * swap half word to little endian 325285431Szbb * 326285431Szbb * @param x 16 bit value 327285431Szbb * 328285431Szbb * @return the value in little endian 329285431Szbb */ 330285431Szbb#define swap16_to_le(x) htole16(x) 331285431Szbb/** 332285431Szbb * swap word to little endian 333285431Szbb * 334285431Szbb * @param x 32 bit value 335285431Szbb * 336285431Szbb * @return the value in little endian 337285431Szbb */ 338285431Szbb#define swap32_to_le(x) htole32(x) 339285431Szbb 340285431Szbb/** 341285431Szbb * swap 8 bytes to little endian 342285431Szbb * 343285431Szbb * @param x 64 bit value 344285431Szbb * 345285431Szbb * @return the value in little endian 346285431Szbb */ 347285431Szbb#define swap64_to_le(x) htole64(x) 348285431Szbb 349285431Szbb/** 350285431Szbb * swap half word from little endian 351285431Szbb * 352285431Szbb * @param x 16 bit value 353285431Szbb * 354285431Szbb * @return the value in the cpu endianess 355285431Szbb */ 356285431Szbb#define swap16_from_le(x) le16toh(x) 357285431Szbb 358285431Szbb/** 359285431Szbb * swap word from little endian 360285431Szbb * 361285431Szbb * @param x 32 bit value 362285431Szbb * 363285431Szbb * @return the value in the cpu endianess 364285431Szbb */ 365285431Szbb#define swap32_from_le(x) le32toh(x) 366285431Szbb 367285431Szbb/** 368285431Szbb * swap 8 bytes from little endian 369285431Szbb * 370285431Szbb * @param x 64 bit value 371285431Szbb * 372285431Szbb * @return the value in the cpu endianess 373285431Szbb */ 374285431Szbb#define swap64_from_le(x) le64toh(x) 375285431Szbb 376285431Szbb/** 377285431Szbb * Memory set 378285431Szbb * 379285431Szbb * @param p memory pointer 380285431Szbb * @param val value for setting 381285431Szbb * @param cnt number of bytes to set 382285431Szbb */ 383285431Szbb#define al_memset(p, val, cnt) memset(p, val, cnt) 384285431Szbb 385285431Szbb/** 386285431Szbb * Memory copy 387285431Szbb * 388285431Szbb * @param p1 memory pointer 389285431Szbb * @param p2 memory pointer 390285431Szbb * @param cnt number of bytes to copy 391285431Szbb */ 392285431Szbb#define al_memcpy(p1, p2, cnt) memcpy(p1, p2, cnt) 393285431Szbb 394285431Szbb/** 395285431Szbb * Memory compare 396285431Szbb * 397285431Szbb * @param p1 memory pointer 398285431Szbb * @param p2 memory pointer 399285431Szbb * @param cnt number of bytes to compare 400285431Szbb */ 401285431Szbb#define al_memcmp(p1, p2, cnt) memcmp(p1, p2, cnt) 402285431Szbb 403285431Szbb/** 404285431Szbb * String compare 405285431Szbb * 406285431Szbb * @param s1 string pointer 407285431Szbb * @param s2 string pointer 408285431Szbb */ 409285431Szbb#define al_strcmp(s1, s2) strcmp(s1, s2) 410285431Szbb 411285431Szbb#define al_get_cpu_id() 0 412285431Szbb 413285431Szbb/* *INDENT-OFF* */ 414285431Szbb#ifdef __cplusplus 415285431Szbb} 416285431Szbb#endif 417285431Szbb/* *INDENT-ON* */ 418285431Szbb/** @} end of Platform Services API group */ 419285431Szbb#endif /* __PLAT_SERVICES_H__ */ 420