blob: 3716bcb353288b23f089dd7124e9b3ee05d0f66f [file] [log] [blame]
Patrick Georgiac959032020-05-05 22:49:26 +02001/* SPDX-License-Identifier: GPL-2.0-or-later */
Patrick Rudolph5e9dc372017-11-19 09:11:58 +01002
3#include <stdio.h>
4#include <inttypes.h>
5
6#include "intelmetool.h"
7#include "mmap.h"
8#include "rcba.h"
9
10static const int size = 0x4000;
11
12/* Returns the physical RCBA base address or zero on error. */
Patrick Rudolph0391d0b2018-02-01 16:14:19 +010013u32 get_rcba_phys(void)
Patrick Rudolph5e9dc372017-11-19 09:11:58 +010014{
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 */
47int 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) {
Patrick Rudolphad4ddfc2018-02-02 15:07:09 +010059 printf("Could not map RCBA\n"
Jonathan Neuschäfer5be7bb32018-04-17 13:06:49 +020060 "Do you have kernel cmdline argument 'iomem=relaxed' set ?\n");
Patrick Rudolph5e9dc372017-11-19 09:11:58 +010061 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 */
73int 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) {
Patrick Rudolphad4ddfc2018-02-02 15:07:09 +010085 printf("Could not map RCBA\n"
Jonathan Neuschäfer5be7bb32018-04-17 13:06:49 +020086 "Do you have kernel cmdline argument 'iomem=relaxed' set ?\n");
Patrick Rudolph5e9dc372017-11-19 09:11:58 +010087 return 1;
88 }
89
90 *val = *(uint32_t *)(rcba + addr);
91
92 munmap((void *)rcba, size);
93 return 0;
94}