• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <asm/alternative-macros.h>
2 #include <asm/barrier.h>
3 #include <asm/kvm_mmu.h>
4 #include <asm/kvm_pkvm_module.h>
5 #include <asm/io.h>
6 
7 static unsigned long uart_addr;
8 
__hyp_readw(void * ioaddr)9 static inline unsigned int __hyp_readw(void *ioaddr)
10 {
11 	unsigned int val;
12 	asm volatile("ldr %w0, [%1]" : "=r" (val) : "r" (ioaddr));
13 	return val;
14 }
__hyp_writew(unsigned int val,void * ioaddr)15 static inline void __hyp_writew(unsigned int val, void *ioaddr)
16 {
17 	asm volatile("str %w0, [%1]" : : "r" (val), "r" (ioaddr));
18 }
19 
pl011_hyp_putc(char c)20 static void pl011_hyp_putc(char c)
21 {
22 	void *base = (void *)uart_addr;
23 	unsigned int val;
24 
25 	do {
26 		val = __hyp_readw(base + CONFIG_SERIAL_PKVM_PL011_UARTFR);
27 	} while (val & (1U <<CONFIG_SERIAL_PKVM_PL011_FULL));
28 	dmb(sy);
29 
30 	__hyp_writew(c, base + CONFIG_SERIAL_PKVM_PL011_UARTTX);
31 
32 	do {
33 		val = __hyp_readw(base + CONFIG_SERIAL_PKVM_PL011_UARTFR);
34 	} while (val & (1U << CONFIG_SERIAL_PKVM_PL011_BUSY));
35 	dmb(sy);
36 }
37 
pl011_hyp_init(const struct pkvm_module_ops * ops)38 int pl011_hyp_init(const struct pkvm_module_ops *ops)
39 {
40 	int ret;
41 
42 	ret = ops->create_private_mapping(CONFIG_SERIAL_PKVM_PL011_BASE_PHYS, PAGE_SIZE,
43 					  PAGE_HYP_DEVICE, &uart_addr);
44 	if (ret)
45 		return ret;
46 
47 	ret = ops->register_serial_driver(pl011_hyp_putc);
48 	if (ret)
49 		return ret;
50 
51 	ops->puts("pKVM pl011 UART driver loaded");
52 
53 	return 0;
54 }
55