common/block/cse: Add Kconfig to support ME specification version 21
[coreboot.git] / src / soc / intel / common / block / systemagent-server / common.c
bloba564f3be1d7bd4b4d82496af8dc87facde113d06
1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #define __SIMPLE_DEVICE__
5 #include <device/pci_ops.h>
6 #include <intelblocks/systemagent_server.h>
8 static uint32_t pci_moving_config32(pci_devfn_t dev, unsigned int reg)
10 uint32_t value, ones, zeroes;
12 value = pci_read_config32(dev, reg);
14 pci_write_config32(dev, reg, 0xffffffff);
15 ones = pci_read_config32(dev, reg);
17 pci_write_config32(dev, reg, 0x00000000);
18 zeroes = pci_read_config32(dev, reg);
20 pci_write_config32(dev, reg, value);
22 return ones ^ zeroes;
25 uint64_t sa_server_read_map_entry(pci_devfn_t dev,
26 const struct sa_server_mem_map_descriptor *entry)
28 uint64_t value = 0;
29 uint32_t alignment = entry->alignment;
31 if (entry->is_64_bit) {
32 value = pci_s_read_config32(dev, entry->reg_offset + 4);
33 value <<= 32;
36 value |= pci_s_read_config32(dev, entry->reg_offset);
38 /**
39 * Probe the alignment if not provided, promising the lower bits are read only, otherwise
40 * SoC should give a initial value.
42 if (!alignment)
43 alignment = ~pci_moving_config32(dev, entry->reg_offset) + 1;
45 /**
46 * If register stores the limit address, where lower bits are read as 0s but treated as 1s,
47 * restore the lower bits and align it up.
49 if (entry->is_limit)
50 value = ALIGN_UP(value + alignment - 1, alignment);
51 else
52 value = ALIGN_DOWN(value, alignment);
54 return value;