1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
|
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef AMD_BLOCK_ESPI_H
#define AMD_BLOCK_ESPI_H
#include <stdint.h>
#include <stddef.h>
/* eSPI MMIO base lives at an offset of 0x10000 from the address in SPI BAR. */
#define ESPI_OFFSET_FROM_BAR 0x10000
#define ESPI_DECODE 0x40
#define ESPI_DECODE_MMIO_RANGE_EN(range) (1 << (((range) & 3) + 12))
#define ESPI_DECODE_IO_RANGE_EN(range) (1 << (((range) & 3) + 8))
#define ESPI_DECODE_IO_0x80_EN (1 << 2)
#define ESPI_DECODE_IO_0X60_0X64_EN (1 << 1)
#define ESPI_DECODE_IO_0X2E_0X2F_EN (1 << 0)
#define ESPI_IO_BASE_OFFSET_REG0 0x44
#define ESPI_IO_BASE_OFFSET_REG1 0x48
#define ESPI_IO_RANGE_SIZE_OFFSET 0x4c
#define ESPI_MMIO_BASE_OFFSET_REG0 0x50
#define ESPI_MMIO_BASE_OFFSET_REG1 0x54
#define ESPI_MMIO_BASE_OFFSET_REG2 0x58
#define ESPI_MMIO_BASE_OFFSET_REG3 0x5C
#define ESPI_MMIO_OFFSET_SIZE_REG0 0x60
#define ESPI_MMIO_OFFSET_SIZE_REG1 0x64
#define ESPI_IO_RANGE_BASE(range) (ESPI_IO_BASE_OFFSET_REG0 + ((range) & 3) * 2)
#define ESPI_IO_RANGE_SIZE(range) (ESPI_IO_RANGE_SIZE_OFFSET + ((range) & 3))
#define ESPI_MMIO_RANGE_BASE(range) (ESPI_MMIO_BASE_OFFSET_REG0 + ((range) & 3) * 4)
#define ESPI_MMIO_RANGE_SIZE(range) (ESPI_MMIO_OFFSET_SIZE_REG0 + ((range) & 3) * 2)
#define ESPI_GENERIC_IO_WIN_COUNT 4
#define ESPI_GENERIC_IO_MAX_WIN_SIZE 0x100
#define ESPI_GENERIC_MMIO_WIN_COUNT 4
#define ESPI_GENERIC_MMIO_MAX_WIN_SIZE 0x10000
#define ESPI_SLAVE0_CONFIG 0x68
#define ESPI_CRC_CHECKING_EN (1 << 31)
#define ESPI_ALERT_MODE (1 << 30)
#define ESPI_IO_MODE_SHIFT 28
#define ESPI_IO_MODE_MASK (0x3 << ESPI_IO_MODE_SHIFT)
#define ESPI_IO_MODE_VALUE(x) ((x) << ESPI_IO_MODE_SHIFT)
#define ESPI_OP_FREQ_SHIFT 25
#define ESPI_OP_FREQ_MASK (0x7 << ESPI_OP_FREQ_SHIFT)
#define ESPI_OP_FREQ_VALUE(x) ((x) << ESPI_OP_FREQ_SHIFT)
#define ESPI_PERIPH_CH_EN (1 << 3)
#define ESPI_VW_CH_EN (1 << 2)
#define ESPI_OOB_CH_EN (1 << 1)
#define ESPI_FLASH_CH_EN (1 << 0)
/* Virtual wire interrupt polarity. eSPI interrupts are active level high signals. The
polarity register inverts the incoming signal if the associated bit with the irq is
0. */
#define ESPI_VW_IRQ_LEVEL_HIGH(x) (1 << (x))
#define ESPI_VW_IRQ_LEVEL_LOW(x) (0 << (x))
#define ESPI_VW_IRQ_EDGE_HIGH(x) (1 << (x))
#define ESPI_VW_IRQ_EDGE_LOW(x) (0 << (x))
enum espi_io_mode {
ESPI_IO_MODE_SINGLE = ESPI_IO_MODE_VALUE(0),
ESPI_IO_MODE_DUAL = ESPI_IO_MODE_VALUE(1),
ESPI_IO_MODE_QUAD = ESPI_IO_MODE_VALUE(2),
};
enum espi_op_freq {
ESPI_OP_FREQ_16_MHZ = ESPI_OP_FREQ_VALUE(0),
ESPI_OP_FREQ_33_MHZ = ESPI_OP_FREQ_VALUE(1),
ESPI_OP_FREQ_66_MHZ = ESPI_OP_FREQ_VALUE(2),
};
enum espi_alert_pin {
ESPI_ALERT_PIN_IN_BAND,
ESPI_ALERT_PIN_PUSH_PULL,
ESPI_ALERT_PIN_OPEN_DRAIN,
};
struct espi_config {
/* Bitmap for standard IO decodes. Use ESPI_DECODE_IO_* above. */
uint32_t std_io_decode_bitmap;
struct {
uint16_t base;
size_t size;
} generic_io_range[ESPI_GENERIC_IO_WIN_COUNT];
/* Slave configuration parameters */
enum espi_io_mode io_mode;
enum espi_op_freq op_freq_mhz;
enum espi_alert_pin alert_pin;
uint32_t crc_check_enable:1;
uint32_t periph_ch_en:1;
uint32_t vw_ch_en:1;
uint32_t oob_ch_en:1;
uint32_t flash_ch_en:1;
uint32_t subtractive_decode:1;
/* Use ESPI_VW_IRQ_* above */
uint32_t vw_irq_polarity;
};
/*
* Open I/O window using the provided base and size.
* Return value: 0 = success, -1 = error.
*/
int espi_open_io_window(uint16_t base, size_t size);
/*
* Open MMIO window using the provided base and size.
* Return value: 0 = success, -1 = error.
*/
int espi_open_mmio_window(uint32_t base, size_t size);
/*
* In cases where eSPI BAR is statically provided by SoC, use that BAR instead of reading
* SPIBASE. This is required for cases where verstage runs on PSP.
*/
void espi_update_static_bar(uintptr_t bar);
/*
* Perform eSPI connection setup to the slave. Currently, this supports slave0 only.
* Returns 0 on success and -1 on error.
*/
int espi_setup(void);
/* Run mainboard configuration needed to set up eSPI */
void mb_set_up_early_espi(void);
/* Setup eSPI with any mainboard specific initialization. */
static inline void configure_espi(void)
{
/* If eSPI is setup in PSP Verstage, continue with that. Else setup eSPI to perform
port80h routing as early as possible. */
if (!CONFIG(VBOOT_STARTS_BEFORE_BOOTBLOCK) && CONFIG(SOC_AMD_COMMON_BLOCK_USE_ESPI)) {
mb_set_up_early_espi();
espi_setup();
}
}
#endif /* AMD_BLOCK_ESPI_H */
|