1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright 2022 NXP
4  */
5 
6 #include <compiler.h>
7 #include <io.h>
8 #include <kernel/spinlock.h>
9 #include <stdint.h>
10 #include <util.h>
11 
12 #include "htif.h"
13 
14 static unsigned int htif_global_lock __nex_bss = SPINLOCK_UNLOCK;
15 
16 #ifdef HTIF_BASE
17 register_phys_mem(MEM_AREA_IO_NSEC, HTIF_BASE,
18 		  ROUNDUP(HTIF_REG_SIZE, CORE_MMU_PGDIR_SIZE));
19 #endif
20 
htif_lock_global(void)21 void htif_lock_global(void)
22 {
23 	cpu_spin_lock(&htif_global_lock);
24 }
25 
htif_unlock_global(void)26 void htif_unlock_global(void)
27 {
28 	cpu_spin_unlock(&htif_global_lock);
29 }
30 
chip_to_base(struct serial_chip * chip)31 static vaddr_t chip_to_base(struct serial_chip *chip)
32 {
33 	struct htif_console_data *pd =
34 		container_of(chip, struct htif_console_data, chip);
35 
36 	return io_pa_or_va(&pd->base, HTIF_REG_SIZE);
37 }
38 
tohost_cmd(vaddr_t base,uint64_t dev,uint64_t cmd,uint64_t data)39 static void __maybe_unused tohost_cmd(vaddr_t base, uint64_t dev,
40 				      uint64_t cmd, uint64_t data)
41 {
42 	while (io_read64(base))
43 		barrier();
44 
45 	io_write64(base, SHIFT_U64(dev, 56) | SHIFT_U64(cmd, 48) | data);
46 }
47 
htif_console_putc(struct serial_chip * chip,int ch __maybe_unused)48 static void htif_console_putc(struct serial_chip *chip,
49 			      int ch __maybe_unused)
50 {
51 #ifdef RV64
52 	vaddr_t base = 0;
53 
54 	htif_lock_global();
55 	base = chip_to_base(chip);
56 	tohost_cmd(base, HTIF_DEV_CONSOLE, HTIF_CMD_WRITE, ch);
57 	htif_unlock_global();
58 #else
59 #warning HTIF is not supported on RV32
60 #endif
61 }
62 
htif_console_flush(struct serial_chip * chip __unused)63 static void htif_console_flush(struct serial_chip *chip __unused)
64 {
65 }
66 
67 static const struct serial_ops htif_console_ops = {
68 	.flush = htif_console_flush,
69 	.putc = htif_console_putc,
70 };
71 DECLARE_KEEP_PAGER(htif_console_ops);
72 
htif_console_init(struct htif_console_data * pd,paddr_t pbase)73 void htif_console_init(struct htif_console_data *pd, paddr_t pbase)
74 {
75 	pd->base.pa = pbase;
76 	pd->chip.ops = &htif_console_ops;
77 }
78