| /* SPDX-License-Identifier: GPL-2.0-or-later */ |
| |
| #include <stdio.h> |
| #include <inttypes.h> |
| |
| #include "intelmetool.h" |
| #include "mmap.h" |
| #include "rcba.h" |
| |
| static const int size = 0x4000; |
| |
| /* Returns the physical RCBA base address or zero on error. */ |
| u32 get_rcba_phys(void) |
| { |
| struct pci_access *pacc; |
| struct pci_dev *sb; |
| uint32_t rcba_phys; |
| |
| pacc = pci_alloc(); |
| pacc->method = PCI_ACCESS_I386_TYPE1; |
| |
| pci_init(pacc); |
| pci_scan_bus(pacc); |
| |
| sb = pci_get_dev(pacc, 0, 0, 0x1f, 0); |
| if (!sb) { |
| printf("Uh oh, southbridge not on BDF(0:31:0), please report " |
| "this error, exiting.\n"); |
| pci_cleanup(pacc); |
| return 0; |
| } |
| pci_fill_info(sb, PCI_FILL_IDENT | PCI_FILL_BASES | PCI_FILL_SIZES | |
| PCI_FILL_CLASS); |
| |
| rcba_phys = pci_read_long(sb, 0xf0) & 0xfffffffe; |
| |
| pci_free_dev(sb); |
| pci_cleanup(pacc); |
| |
| return rcba_phys; |
| } |
| |
| /* |
| * Writes 'val' to RCBA register at address 'addr'. |
| * Returns 1 on error and 0 on success. |
| */ |
| int write_rcba32(uint32_t addr, uint32_t val) |
| { |
| volatile uint8_t *rcba; |
| const uint32_t rcba_phys = get_rcba_phys(); |
| |
| if (!rcba_phys) { |
| printf("Could not get RCBA address\n"); |
| return 1; |
| } |
| |
| rcba = map_physical((off_t)rcba_phys, size); |
| if (rcba == NULL) { |
| printf("Could not map RCBA\n" |
| "Do you have kernel cmdline argument 'iomem=relaxed' set ?\n"); |
| return 1; |
| } |
| *(uint32_t *)(rcba + addr) = val; |
| |
| munmap((void *)rcba, size); |
| return 0; |
| } |
| |
| /* |
| * Reads RCBA register at address 'addr' and stores it in 'val'. |
| * Returns 1 on error and 0 on success. |
| */ |
| int read_rcba32(uint32_t addr, uint32_t *val) |
| { |
| volatile uint8_t *rcba; |
| const uint32_t rcba_phys = get_rcba_phys(); |
| |
| if (!rcba_phys) { |
| printf("Could not get RCBA address\n"); |
| return 1; |
| } |
| |
| rcba = map_physical((off_t)rcba_phys, size); |
| if (rcba == NULL) { |
| printf("Could not map RCBA\n" |
| "Do you have kernel cmdline argument 'iomem=relaxed' set ?\n"); |
| return 1; |
| } |
| |
| *val = *(uint32_t *)(rcba + addr); |
| |
| munmap((void *)rcba, size); |
| return 0; |
| } |