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 
bcm_elog_putchar(char ch)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 
bcm_elog_init(uintptr_t pa_base,uint32_t size)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