RTEMS 6.1-rc7
Loading...
Searching...
No Matches
apic.h
Go to the documentation of this file.
1/* SPDX-License-Identifier: BSD-2-Clause */
2
11/*
12 * Copyright (C) 2024 Matheus Pecoraro
13 * Copyright (c) 2018 Amaan Cheval <amaan.cheval@gmail.com>
14 *
15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions
17 * are met:
18 * 1. Redistributions of source code must retain the above copyright
19 * notice, this list of conditions and the following disclaimer.
20 * 2. Redistributions in binary form must reproduce the above copyright
21 * notice, this list of conditions and the following disclaimer in the
22 * documentation and/or other materials provided with the distribution.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 */
36
37#ifndef _AMD64_APIC_H
38#define _AMD64_APIC_H
39
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46/* The address of the MSR pointing to the APIC base physical address */
47#define APIC_BASE_MSR 0x1B
48/* Value to hardware-enable the APIC through the APIC_BASE_MSR */
49#define APIC_BASE_MSR_ENABLE 0x800
50
51#define xAPIC_MAX_APIC_ID 0xFE
52
53/*
54 * Since the LAPIC registers are contained in an array of 32-bit elements
55 * these byte-offsets need to be divided by 4 to index the array.
56 */
57#define LAPIC_OFFSET(val) (val >> 2)
58
59#define LAPIC_REGISTER_ID LAPIC_OFFSET(0x20)
60#define LAPIC_REGISTER_EOI LAPIC_OFFSET(0x0B0)
61#define LAPIC_REGISTER_SPURIOUS LAPIC_OFFSET(0x0F0)
62#define LAPIC_REGISTER_ICR_LOW LAPIC_OFFSET(0x300)
63#define LAPIC_REGISTER_ICR_HIGH LAPIC_OFFSET(0x310)
64#define LAPIC_REGISTER_LVT_TIMER LAPIC_OFFSET(0x320)
65#define LAPIC_REGISTER_TIMER_INITCNT LAPIC_OFFSET(0x380)
66#define LAPIC_REGISTER_TIMER_CURRCNT LAPIC_OFFSET(0x390)
67#define LAPIC_REGISTER_TIMER_DIV LAPIC_OFFSET(0x3E0)
68
69#define LAPIC_LVT_MASK 0x10000
70
71#define LAPIC_ICR_HIGH_MASK 0x00FFFFFF
72#define LAPIC_ICR_LOW_MASK 0xFFF32000
73#define LAPIC_ICR_DELIV_INIT 0x500
74#define LAPIC_ICR_DELIV_START 0x600
75#define LAPIC_ICR_DELIV_STAT_PEND 0x1000
76#define LAPIC_ICR_ASSERT 0x4000
77#define LAPIC_ICR_TRIG_LEVEL 0x8000
78
79#define LAPIC_EOI_ACK 0
80#define LAPIC_SELECT_TMR_PERIODIC 0x20000
81#define LAPIC_SPURIOUS_ENABLE 0x100
82
83/* Number of times to calibrate the LAPIC timer to average it out */
84#define LAPIC_TIMER_NUM_CALIBRATIONS 5
85/* Default divide value used by LAPIC timer */
86#define LAPIC_TIMER_DIVIDE_VALUE 16
87/* Value to set in register to pick the divide value above */
88#define LAPIC_TIMER_SELECT_DIVIDER 3
89
90/* PIT defines and macros used when calibrating the LAPIC timer and starting APs */
91#define PIT_FREQUENCY 1193180
92/*
93 * The PIT_FREQUENCY determines how many times the PIT counter is decremented
94 * per second - therefore, we can calculate how many ticks we set based on what
95 * fraction of a second we're okay with spending on calibration
96 */
97#define PIT_CALIBRATE_DIVIDER 20
98#define PIT_CALIBRATE_TICKS (PIT_FREQUENCY/PIT_CALIBRATE_DIVIDER)
99/*
100 * Since the PIT only has 2 one-byte registers, the maximum tick value is
101 * limited to 16-bits. We can set the PIT to use a frequency divider if
102 * needed.
103 */
105 PIT_CALIBRATE_TICKS <= 0xffff,
106 PIT_CALIBRATE_DIVIDER
107);
108
109/* I/O ports for the PIT */
110#define PIT_PORT_CHAN0 0x40
111#define PIT_PORT_CHAN1 0x41
112#define PIT_PORT_CHAN2 0x42
113/*
114 * The input to channel 2 can be gated through software, using bit 0 of port
115 * 0x61.
116 */
117#define PIT_PORT_CHAN2_GATE 0x61
118#define PIT_CHAN2_TIMER_BIT 1
119#define PIT_CHAN2_SPEAKER_BIT 2
120/* The PIT mode/command register */
121#define PIT_PORT_MCR 0x43
122
123/* PIT values to select channels, access, and operating modes */
124#define PIT_SELECT_CHAN0 0b00000000
125#define PIT_SELECT_CHAN1 0b01000000
126#define PIT_SELECT_CHAN2 0b10000000
127/*
128 * In the lo/hi mode, the low-byte is sent to the data port, followed by the
129 * high-byte; this makes it important that this be an atomic operation.
130 */
131#define PIT_SELECT_ACCESS_LOHI 0b00110000
132#define PIT_SELECT_ONE_SHOT_MODE 0b00000010
133#define PIT_SELECT_BINARY_MODE 0
134
135#define PIT_CHAN2_ENABLE(chan2_value) \
136 /* Enable the channel 2 timer gate and disable the speaker output */ \
137 chan2_value = (inport_byte(PIT_PORT_CHAN2_GATE) | PIT_CHAN2_TIMER_BIT) \
138 & ~PIT_CHAN2_SPEAKER_BIT; \
139 outport_byte(PIT_PORT_CHAN2_GATE, chan2_value); \
140 /* Initialize PIT in one-shot mode on Channel 2 */ \
141 outport_byte( \
142 PIT_PORT_MCR, \
143 PIT_SELECT_CHAN2 | PIT_SELECT_ACCESS_LOHI | \
144 PIT_SELECT_ONE_SHOT_MODE | PIT_SELECT_BINARY_MODE \
145 ); \
146
147#define PIT_CHAN2_WRITE_TICKS(pit_ticks) \
148 /* Set PIT reload value */ \
149 outport_byte(PIT_PORT_CHAN2, pit_ticks & 0xff); \
150 stub_io_wait(); \
151 outport_byte(PIT_PORT_CHAN2, (pit_ticks >> 8) & 0xff); \
152
153#define PIT_CHAN2_START_DELAY(chan2_value) \
154 /* Restart PIT by disabling the gated input and then re-enabling it */ \
155 chan2_value &= ~PIT_CHAN2_TIMER_BIT; \
156 outport_byte(PIT_PORT_CHAN2_GATE, chan2_value); \
157 chan2_value |= PIT_CHAN2_TIMER_BIT; \
158 outport_byte(PIT_PORT_CHAN2_GATE, chan2_value); \
159
160#define PIT_CHAN2_WAIT_DELAY(pit_ticks) \
161 do { \
162 uint32_t curr_ticks = pit_ticks; \
163 while ( curr_ticks <= pit_ticks ) { \
164 /* Send latch command to read multi-byte value atomically */ \
165 outport_byte(PIT_PORT_MCR, PIT_SELECT_CHAN2); \
166 curr_ticks = inport_byte(PIT_PORT_CHAN2); \
167 curr_ticks |= inport_byte(PIT_PORT_CHAN2) << 8; \
168 } \
169 } while(0); \
170
171extern volatile uint32_t* amd64_lapic_base;
172extern uint8_t amd64_lapic_to_cpu_map[xAPIC_MAX_APIC_ID + 1];
173
183bool lapic_initialize(void);
184
193uint32_t lapic_timer_calc_ticks(uint64_t desired_freq_hz);
194
200void lapic_timer_enable(uint32_t reload_value);
201
202#ifdef RTEMS_SMP
208uint32_t lapic_get_num_of_procesors(void);
209
216void lapic_send_ipi(uint32_t target_cpu_index, uint8_t isr_vector);
217
224void lapic_start_ap(uint32_t cpu_index, uint8_t page_vector);
225#endif
226
231uint8_t inline lapic_get_id(void)
232{
233 /* ID stored in highest 8 bits */
234 return amd64_lapic_base[LAPIC_REGISTER_ID]>>24;
235}
236
240void inline lapic_eoi(void)
241{
242 amd64_lapic_base[LAPIC_REGISTER_EOI] = LAPIC_EOI_ACK;
243}
244
245#ifdef __cplusplus
246}
247#endif
248
249#endif /* _AMD64_APIC_H */
This header file provides basic definitions used by the API and the implementation.
lpc176x_can_isr_vector isr_vector
Vector of isr for the can_driver .
Definition: can.c:37
#define RTEMS_STATIC_ASSERT(_cond, _msg)
It is defined if a static analysis run is performed.
Definition: basedefs.h:841
void lapic_eoi(void)
Signals an end of interrupt to the Local APIC.
Definition: apic.h:240
uint8_t lapic_get_id(void)
Retrieves the Local APIC ID.
Definition: apic.h:231
bool lapic_initialize(void)
Initializes the Local APIC by hardware and software enabling it.
Definition: apic.c:228
void lapic_timer_enable(uint32_t reload_value)
Enables the Local APIC timer.
Definition: apic.c:305
uint32_t lapic_timer_calc_ticks(uint64_t desired_freq_hz)
Calculates the number of Local APIC timer ticks which can be used with lapic_timer_enable to set up a...
Definition: apic.c:283