1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright 2019 Broadcom. 4 */ 5 6 #include <bcm_elog.h> 7 #include <io.h> 8 9 static struct bcm_elog global_elog; 10 11 void bcm_elog_putchar(char ch) 12 { 13 struct bcm_elog *elog = &global_elog; 14 uint32_t offset = 0, len = 0; 15 vaddr_t base = 0; 16 17 base = io_pa_or_va(&elog->base, elog->max_size); 18 19 offset = io_read32(base + BCM_ELOG_OFF_OFFSET); 20 len = io_read32(base + BCM_ELOG_LEN_OFFSET); 21 io_write8(base + offset, ch); 22 offset++; 23 24 /* Log buffer is now full and need to wrap around */ 25 if (offset >= elog->max_size) 26 offset = BCM_ELOG_HEADER_LEN; 27 28 /* Only increment length when log buffer is not full */ 29 if (len < elog->max_size - BCM_ELOG_HEADER_LEN) 30 len++; 31 32 io_write32(base + BCM_ELOG_OFF_OFFSET, offset); 33 io_write32(base + BCM_ELOG_LEN_OFFSET, len); 34 } 35 36 void bcm_elog_init(uintptr_t pa_base, uint32_t size) 37 { 38 struct bcm_elog *elog = &global_elog; 39 uint32_t val = 0; 40 vaddr_t base = 0; 41 42 elog->base.pa = pa_base; 43 elog->max_size = size; 44 45 base = io_pa_or_va(&elog->base, BCM_ELOG_HEADER_LEN); 46 47 /* 48 * If a valid signature is found, it means logging is already 49 * initialized. In this case, we should not re-initialize the entry 50 * header in the designated memory 51 */ 52 val = io_read32(base + BCM_ELOG_SIG_OFFSET); 53 if (val != BCM_ELOG_SIG_VAL) { 54 io_write32(base + BCM_ELOG_SIG_OFFSET, BCM_ELOG_SIG_VAL); 55 io_write32(base + BCM_ELOG_OFF_OFFSET, BCM_ELOG_HEADER_LEN); 56 io_write32(base + BCM_ELOG_LEN_OFFSET, 0); 57 } 58 } 59