xref: /aosp_15_r20/external/coreboot/util/intelmetool/rcba.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
3 #include <stdio.h>
4 #include <inttypes.h>
5 
6 #include "intelmetool.h"
7 #include "mmap.h"
8 #include "rcba.h"
9 
10 static const int size = 0x4000;
11 
12 /* Returns the physical RCBA base address or zero on error. */
get_rcba_phys(void)13 u32 get_rcba_phys(void)
14 {
15 	struct pci_access *pacc;
16 	struct pci_dev *sb;
17 	uint32_t rcba_phys;
18 
19 	pacc = pci_alloc();
20 	pacc->method = PCI_ACCESS_I386_TYPE1;
21 
22 	pci_init(pacc);
23 	pci_scan_bus(pacc);
24 
25 	sb = pci_get_dev(pacc, 0, 0, 0x1f, 0);
26 	if (!sb) {
27 		printf("Uh oh, southbridge not on BDF(0:31:0), please report "
28 		       "this error, exiting.\n");
29 		pci_cleanup(pacc);
30 		return 0;
31 	}
32 	pci_fill_info(sb, PCI_FILL_IDENT | PCI_FILL_BASES | PCI_FILL_SIZES |
33 			  PCI_FILL_CLASS);
34 
35 	rcba_phys = pci_read_long(sb, 0xf0) & 0xfffffffe;
36 
37 	pci_free_dev(sb);
38 	pci_cleanup(pacc);
39 
40 	return rcba_phys;
41 }
42 
43 /*
44  * Writes 'val' to RCBA register at address 'addr'.
45  * Returns 1 on error and 0 on success.
46  */
write_rcba32(uint32_t addr,uint32_t val)47 int write_rcba32(uint32_t addr, uint32_t val)
48 {
49 	volatile uint8_t *rcba;
50 	const uint32_t rcba_phys = get_rcba_phys();
51 
52 	if (!rcba_phys) {
53 		printf("Could not get RCBA address\n");
54 		return 1;
55 	}
56 
57 	rcba = map_physical((off_t)rcba_phys, size);
58 	if (rcba == NULL) {
59 		printf("Could not map RCBA\n"
60 		       "Do you have kernel cmdline argument 'iomem=relaxed' set ?\n");
61 		return 1;
62 	}
63 	*(uint32_t *)(rcba + addr) = val;
64 
65 	munmap((void *)rcba, size);
66 	return 0;
67 }
68 
69 /*
70  * Reads RCBA register at address 'addr' and stores it in 'val'.
71  * Returns 1 on error and 0 on success.
72  */
read_rcba32(uint32_t addr,uint32_t * val)73 int read_rcba32(uint32_t addr, uint32_t *val)
74 {
75 	volatile uint8_t *rcba;
76 	const uint32_t rcba_phys = get_rcba_phys();
77 
78 	if (!rcba_phys) {
79 		printf("Could not get RCBA address\n");
80 		return 1;
81 	}
82 
83 	rcba = map_physical((off_t)rcba_phys, size);
84 	if (rcba == NULL) {
85 		printf("Could not map RCBA\n"
86 		       "Do you have kernel cmdline argument 'iomem=relaxed' set ?\n");
87 		return 1;
88 	}
89 
90 	*val = *(uint32_t *)(rcba + addr);
91 
92 	munmap((void *)rcba, size);
93 	return 0;
94 }
95