xref: /optee_os/core/arch/arm/plat-bcm/bcm_elog.c (revision c2e4eb43b7b7211345cd38ceceac97773bd78d2c)
19348a85aSSheetal Tigadoli // SPDX-License-Identifier: BSD-2-Clause
29348a85aSSheetal Tigadoli /*
39348a85aSSheetal Tigadoli  * Copyright 2019 Broadcom.
49348a85aSSheetal Tigadoli  */
59348a85aSSheetal Tigadoli 
69348a85aSSheetal Tigadoli #include <bcm_elog.h>
79348a85aSSheetal Tigadoli #include <io.h>
89348a85aSSheetal Tigadoli 
99348a85aSSheetal Tigadoli static struct bcm_elog global_elog;
109348a85aSSheetal Tigadoli 
bcm_elog_putchar(char ch)119348a85aSSheetal Tigadoli void bcm_elog_putchar(char ch)
129348a85aSSheetal Tigadoli {
139348a85aSSheetal Tigadoli 	struct bcm_elog *elog = &global_elog;
149348a85aSSheetal Tigadoli 	uint32_t offset = 0, len = 0;
159348a85aSSheetal Tigadoli 	vaddr_t base = 0;
169348a85aSSheetal Tigadoli 
17*c2e4eb43SAnton Rybakov 	base = io_pa_or_va(&elog->base, elog->max_size);
189348a85aSSheetal Tigadoli 
199348a85aSSheetal Tigadoli 	offset = io_read32(base + BCM_ELOG_OFF_OFFSET);
209348a85aSSheetal Tigadoli 	len = io_read32(base + BCM_ELOG_LEN_OFFSET);
219348a85aSSheetal Tigadoli 	io_write8(base + offset, ch);
229348a85aSSheetal Tigadoli 	offset++;
239348a85aSSheetal Tigadoli 
249348a85aSSheetal Tigadoli 	/* Log buffer is now full and need to wrap around */
259348a85aSSheetal Tigadoli 	if (offset >= elog->max_size)
269348a85aSSheetal Tigadoli 		offset = BCM_ELOG_HEADER_LEN;
279348a85aSSheetal Tigadoli 
289348a85aSSheetal Tigadoli 	/* Only increment length when log buffer is not full */
299348a85aSSheetal Tigadoli 	if (len < elog->max_size - BCM_ELOG_HEADER_LEN)
309348a85aSSheetal Tigadoli 		len++;
319348a85aSSheetal Tigadoli 
329348a85aSSheetal Tigadoli 	io_write32(base + BCM_ELOG_OFF_OFFSET, offset);
339348a85aSSheetal Tigadoli 	io_write32(base + BCM_ELOG_LEN_OFFSET, len);
349348a85aSSheetal Tigadoli }
359348a85aSSheetal Tigadoli 
bcm_elog_init(uintptr_t pa_base,uint32_t size)369348a85aSSheetal Tigadoli void bcm_elog_init(uintptr_t pa_base, uint32_t size)
379348a85aSSheetal Tigadoli {
389348a85aSSheetal Tigadoli 	struct bcm_elog *elog = &global_elog;
399348a85aSSheetal Tigadoli 	uint32_t val = 0;
409348a85aSSheetal Tigadoli 	vaddr_t base = 0;
419348a85aSSheetal Tigadoli 
429348a85aSSheetal Tigadoli 	elog->base.pa = pa_base;
439348a85aSSheetal Tigadoli 	elog->max_size = size;
449348a85aSSheetal Tigadoli 
45*c2e4eb43SAnton Rybakov 	base = io_pa_or_va(&elog->base, BCM_ELOG_HEADER_LEN);
469348a85aSSheetal Tigadoli 
479348a85aSSheetal Tigadoli 	/*
489348a85aSSheetal Tigadoli 	 * If a valid signature is found, it means logging is already
499348a85aSSheetal Tigadoli 	 * initialized. In this case, we should not re-initialize the entry
509348a85aSSheetal Tigadoli 	 * header in the designated memory
519348a85aSSheetal Tigadoli 	 */
529348a85aSSheetal Tigadoli 	val = io_read32(base + BCM_ELOG_SIG_OFFSET);
539348a85aSSheetal Tigadoli 	if (val != BCM_ELOG_SIG_VAL) {
549348a85aSSheetal Tigadoli 		io_write32(base + BCM_ELOG_SIG_OFFSET, BCM_ELOG_SIG_VAL);
559348a85aSSheetal Tigadoli 		io_write32(base + BCM_ELOG_OFF_OFFSET, BCM_ELOG_HEADER_LEN);
569348a85aSSheetal Tigadoli 		io_write32(base + BCM_ELOG_LEN_OFFSET, 0);
579348a85aSSheetal Tigadoli 	}
589348a85aSSheetal Tigadoli }
59