1 /*
2  * Copyright (c) 2023 Intel Corporation
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #ifndef _SEDI_DRIVER_CORE_H_
8 #define _SEDI_DRIVER_CORE_H_
9 #include <stdint.h>
10 #include "sedi_driver_common.h"
11 
12 #define SEDI_DCACHE_LINE_SIZE ((uint32_t)16)
13 
14 /*!
15  * \brief   Clean & Invalidate D-Cache
16  * \details Cleans and Invalidates D-Cache
17  */
sedi_core_inv_clean_dcache(void)18 static inline void sedi_core_inv_clean_dcache(void)
19 {
20 	__asm__ volatile("wbinvd;\n\t");
21 
22 	__asm__ volatile("lock; addl $0,-4(%%esp);\n\t" ::: "memory", "cc");
23 }
24 
25 /*!
26  * \brief   D-Cache Clean and Invalidate by address
27  * \details Cleans and invalidates D_Cache for the given address
28  * \param[in]   addr    address (aligned to 32-byte boundary)
29  * \param[in]   dsize   size of memory block (in number of bytes)
30  */
sedi_core_inv_clean_dcache_by_addr(uint32_t * addr,int32_t dsize)31 static inline int sedi_core_inv_clean_dcache_by_addr(uint32_t *addr, int32_t dsize)
32 {
33 	DBG_CHECK((!addr || dsize <= 0), SEDI_DRIVER_ERROR);
34 	uint32_t start = (uint32_t)addr;
35 	uint32_t end = start + dsize;
36 
37 	end = (end + (SEDI_DCACHE_LINE_SIZE - 1)) & ~(SEDI_DCACHE_LINE_SIZE - 1);
38 
39 	for (; start < end; start += SEDI_DCACHE_LINE_SIZE) {
40 		__asm__ volatile("clflush %0;\n\t" : "+m"(*(volatile char *)start));
41 	}
42 
43 	__asm__ volatile("lock; addl $0,-4(%%esp);\n\t" ::: "memory", "cc");
44 
45 	return SEDI_DRIVER_OK;
46 }
47 
48 /*!
49  * \brief   D-Cache Clean by address
50  * \details Cleans D-Cache for the given address
51  * \param[in]   addr    address (aligned to 32-byte boundary)
52  * \param[in]   dsize   size of memory block (in number of bytes)
53  */
sedi_core_clean_dcache_by_addr(uint32_t * addr,int32_t dsize)54 static inline int sedi_core_clean_dcache_by_addr(uint32_t *addr, int32_t dsize)
55 {
56 	return sedi_core_inv_clean_dcache_by_addr(addr, dsize);
57 }
58 
write_ioapic_reg(const uint32_t reg,const uint32_t val)59 static inline void write_ioapic_reg(const uint32_t reg, const uint32_t val)
60 {
61 	write32(SEDI_IOAPIC_IDX, (unsigned char)reg);
62 	write32(SEDI_IOAPIC_WDW, val);
63 }
64 
read_ioapic_reg(const uint32_t reg)65 static inline unsigned int read_ioapic_reg(const uint32_t reg)
66 {
67 	write32(SEDI_IOAPIC_IDX, (unsigned char)reg);
68 	return read32(SEDI_IOAPIC_WDW);
69 }
70 
update_ioapic_redtbl_raw_lo(const unsigned int irq,const unsigned int val)71 static inline void update_ioapic_redtbl_raw_lo(const unsigned int irq, const unsigned int val)
72 {
73 	/* [IOAPIC], 3.2.4. "IOREDTBL[23:0] I/O REDIRECTION TABLE REGISTERS" */
74 	const uint32_t redtbl_lo = SEDI_IOAPIC_IOREDTBL + 2 * irq;
75 
76 	write_ioapic_reg(redtbl_lo, val);
77 }
78 
sedi_core_irq_enable(unsigned int irq)79 static inline void sedi_core_irq_enable(unsigned int irq)
80 {
81 	const uint32_t redtbl_lo = SEDI_IOAPIC_IOREDTBL + 2 * irq;
82 	unsigned int val = read_ioapic_reg(redtbl_lo);
83 
84 	val &= ~SEDI_IOAPIC_REDTBL_MASK;
85 	update_ioapic_redtbl_raw_lo(irq, val);
86 }
87 
sedi_core_irq_disable(unsigned int irq)88 static inline void sedi_core_irq_disable(unsigned int irq)
89 {
90 	const uint32_t redtbl_lo = SEDI_IOAPIC_IOREDTBL + 2 * irq;
91 	unsigned int val = read_ioapic_reg(redtbl_lo);
92 
93 	val |= SEDI_IOAPIC_REDTBL_MASK;
94 	update_ioapic_redtbl_raw_lo(irq, val);
95 }
96 
sedi_core_irq_lock(void)97 static inline unsigned int sedi_core_irq_lock(void)
98 {
99 	unsigned int key;
100 
101 	__asm__ volatile("pushfl; cli; popl %0" : "=g"(key)::"memory");
102 
103 	return key;
104 }
105 
sedi_core_irq_unlock(unsigned int key)106 static inline void sedi_core_irq_unlock(unsigned int key)
107 {
108 	if ((key & 0x00000200U) != 0U) { /* 'IF' bit */
109 		__asm__ volatile("sti" ::: "memory");
110 	}
111 }
112 
sedi_core_get_irq_map(void)113 static inline uint64_t sedi_core_get_irq_map(void)
114 {
115 	uint64_t irq_map = 0;
116 
117 	for (int pin = 0; pin < 30; pin++) {
118 		write32(SEDI_IOAPIC_IDX, SEDI_IOAPIC_IOREDTBL + pin * 2);
119 		if (!(read32(SEDI_IOAPIC_WDW) & SEDI_IOAPIC_REDTBL_MASK)) {
120 			irq_map |= ((uint64_t)0x1) << pin;
121 		}
122 	}
123 
124 	return irq_map;
125 }
126 
127 #endif
128