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