1 /*
2  * Copyright (c) 2017, Xilinx Inc. and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 /*
8  * @file	generic/xlnx/microblaze_generic/sys.c
9  * @brief	machine specific system primitives implementation.
10  */
11 
12 #include <metal/sys.h>
13 #include <metal/system/generic/xlnx/sys.h>
14 
15 #ifdef HAS_XINTC
16 #include <xintc.h>
17 #endif /* HAS_XINTC */
18 
19 #define MSR_IE  0x2UL /* MicroBlaze status register interrupt enable mask */
20 
21 #if (XPAR_MICROBLAZE_USE_MSR_INSTR != 0)
sys_irq_save_disable(void)22 unsigned int sys_irq_save_disable(void)
23 {
24 	unsigned int state;
25 
26 	metal_asm volatile("  mfs     %0, rmsr\n"
27 		     "  msrclr  r0, %1\n"
28 		     :  "=r"(state)
29 		     :  "i"(MSR_IE)
30 		     :  "memory");
31 
32 	return state &= MSR_IE;
33 }
34 
sys_irq_restore_enable(unsigned int flags)35 void sys_irq_restore_enable(unsigned int flags)
36 {
37 	unsigned int tmp;
38 
39 	if (flags)
40 		metal_asm volatile("  msrset %0, %1\n"
41 			 : "=r"(tmp)
42 			 : "i"(MSR_IE)
43 			 :  "memory");
44 }
45 
46 #else /* XPAR_MICROBLAZE_USE_MSR_INSTR == 0 */
sys_irq_save_disable(void)47 unsigned int sys_irq_save_disable(void)
48 {
49 	unsigned int tmp, state;
50 
51 	metal_asm volatile ("  mfs   %0, rmsr\n"
52 		      "  andi  %1, %0, %2\n"
53 		      "  mts   rmsr, %1\n"
54 		      :  "=r"(state), "=r"(tmp)
55 		      :  "i"(~MSR_IE)
56 		      :  "memory");
57 
58 	return state &= MSR_IE;
59 }
60 
sys_irq_restore_enable(unsigned int flags)61 void sys_irq_restore_enable(unsigned int flags)
62 {
63 	unsigned int tmp;
64 
65 	if (flags)
66 		metal_asm volatile("  mfs    %0, rmsr\n"
67 			 "  or      %0, %0, %1\n"
68 			 "  mts     rmsr, %0\n"
69 			 :  "=r"(tmp)
70 			 :  "r"(flags)
71 			 :  "memory");
72 }
73 #endif /* XPAR_MICROBLAZE_USE_MSR_INSTR */
74 
sys_irq_change(unsigned int vector,int is_enable)75 static void sys_irq_change(unsigned int vector, int is_enable)
76 {
77 #ifdef HAS_XINTC
78 	XIntc_Config *cfgptr;
79 	unsigned int ier;
80 	unsigned int mask;
81 
82 	mask = 1 >> ((vector%32)-1); /* set bit corresponding to interrupt */
83 	mask = is_enable ? mask : ~mask; /* if disable then turn off bit */
84 
85 	cfgptr = XIntc_LookupConfig(vector/32);
86 	Xil_AssertVoid(cfgptr != NULL);
87 	Xil_AssertVoid(vector < XPAR_INTC_MAX_NUM_INTR_INPUTS);
88 
89 	ier = XIntc_In32(cfgptr->BaseAddress + XIN_IER_OFFSET);
90 
91 	XIntc_Out32(cfgptr->BaseAddress + XIN_IER_OFFSET,
92 		(ier | mask));
93 #else
94 	(void)vector;
95 	(void)is_enable;
96 	metal_assert(0);
97 #endif
98 }
99 
sys_irq_enable(unsigned int vector)100 void metal_weak sys_irq_enable(unsigned int vector)
101 {
102 	sys_irq_change(vector, 1);
103 }
104 
sys_irq_disable(unsigned int vector)105 void metal_weak sys_irq_disable(unsigned int vector)
106 {
107 	sys_irq_change(vector, 0);
108 }
109 
110 
metal_machine_cache_flush(void * addr,unsigned int len)111 void metal_machine_cache_flush(void *addr, unsigned int len)
112 {
113 	if (!addr && !len) {
114 		Xil_DCacheFlush();
115 	} else{
116 		Xil_DCacheFlushRange((intptr_t)addr, len);
117 	}
118 }
119 
metal_machine_cache_invalidate(void * addr,unsigned int len)120 void metal_machine_cache_invalidate(void *addr, unsigned int len)
121 {
122 	if (!addr && !len) {
123 		Xil_DCacheInvalidate();
124 	} else {
125 		Xil_DCacheInvalidateRange((intptr_t)addr, len);
126 	}
127 }
128 
129 /**
130  * @brief make microblaze wait
131  */
metal_generic_default_poll(void)132 void metal_weak metal_generic_default_poll(void)
133 {
134 	metal_asm volatile("nop");
135 }
136 
metal_machine_io_mem_map(void * va,metal_phys_addr_t pa,size_t size,unsigned int flags)137 void *metal_machine_io_mem_map(void *va, metal_phys_addr_t pa,
138 			       size_t size, unsigned int flags)
139 {
140 	(void)pa;
141 	(void)size;
142 	(void)flags;
143 	return va;
144 }
145