summaryrefslogtreecommitdiff
path: root/util
diff options
context:
space:
mode:
authorMaxim Polyakov <max.senia.poliak@gmail.com>2024-06-28 09:13:50 +0300
committerFelix Held <felix-coreboot@felixheld.de>2024-07-31 14:28:06 +0000
commitdc2ee2096ac629ba01c6734b1a9b318d79e7382e (patch)
tree5fb321579dd45e2a719091fb3ade079dd27ca98b /util
parentfa66d33336fcf4358c1bacd84ae9427f8dfb59ba (diff)
util/superiotool: Add extra selectors support
Some chips (fintek [1,2]) have registers with specific selector-fields that can affect the address space of the device (for example, switch the register bank). At the same time, these registers contain fields that should not change after they are configured in BIOS (for example, set the port to 2E/2F or 4E/4F). In this case, the selector should take into account the mask of the register fields and there is no convenient and easy way to add this in the code in the utility. The selector-fields should be set manually before the dump and this action is done several times. This patch adds an extra-selector mechanism that allows superiotool to make a correct dump in automatic mode. Just add a structure with an index, mask, and value for the selector inside the superio_registers chip for the corresponding LDN to switch the register bank: {FINTEK_F81966_DID, "F81962/F81964/F81966/F81967", { * * * {NOLDN, "Global", {0x28,0x2a,0x2b,0x2c,EOT}, {0x00,0x00,0x00,0x00,EOT}, {.idx = 0x27, .mask = 0xd, .val = 0x1} /* update extra selector */ }, {0x03, "LPT", {0x30,0x60,0x61,0x70,0x74,0xf0,EOT}, {NANA,0x03,0x78,0x07,0x03,0xc2,EOT} /* without extra selector */ }, * * * Tested with Fintek F81966 on Asrock IMB-1222: - run superiotool on Ubuntu and dump the registers for the board with the vendor's firmware; - add the superio chip initialization code to the board configuration in coreboot and build the project; - boot Ubuntu on the board with coreboot and re-dump the registers; - the register values from the board configuration code are the same in both dumps. Found Fintek F81962/F81964/F81966/F81967 (vid=0x3419, id=0x0215) at 0x2e (Global) -- ESEL[27h] 0x00 (Port Select Register) -- idx 02 07 20 21 23 24 25 26 27 28 29 2a 2b 2c 2d val 00 0b 15 02 19 34 5a 23 80 a0 f0 45 02 e3 2e def NA 00 15 02 19 34 00 23 02 a0 00 00 02 0c 28 * * * The changes do not affect the configuration of existing chips, which was tested on the Asrock H110-STX motherboard with Nuvoton NCT5539D (the dump before and after the changes are the same). [1] CB:83004 [2] CB:83019 Change-Id: If56af9f977381e637245bdd26563f5ba7e6cbead Signed-off-by: Maxim Polyakov <max.senia.poliak@gmail.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/83196 Reviewed-by: Angel Pons <th3fanbus@gmail.com> Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Diffstat (limited to 'util')
-rw-r--r--util/superiotool/superiotool.c24
-rw-r--r--util/superiotool/superiotool.h9
2 files changed, 33 insertions, 0 deletions
diff --git a/util/superiotool/superiotool.c b/util/superiotool/superiotool.c
index aee5026189..a62f49a084 100644
--- a/util/superiotool/superiotool.c
+++ b/util/superiotool/superiotool.c
@@ -84,6 +84,28 @@ const char *get_superio_name(const struct superio_registers reg_table[],
return "<unknown>";
}
+static void set_extra_selector(uint16_t port, const struct extra_selector *esel)
+{
+ if (esel->idx == 0) /* entry without extra selector */
+ return;
+
+ uint8_t reg_val = regval(port, esel->idx);
+ reg_val &= ~esel->mask;
+ reg_val |= esel->val;
+ regwrite(port, esel->idx, reg_val);
+
+ reg_val = regval(port, esel->idx) & esel->mask;
+
+ printf(" -- ESEL[%02xh] 0x%02x", esel->idx, reg_val);
+ if (esel->name != NULL)
+ printf(" (%s)", esel->name);
+ printf(" --");
+
+ if (verbose)
+ printf(" config: idx=%02xh, mask=%02xh, val=%02xh --", esel->idx, esel->mask,
+ esel->val);
+}
+
static void dump_regs(const struct superio_registers reg_table[],
int i, int j, uint16_t port, uint8_t ldn_sel)
{
@@ -102,6 +124,8 @@ static void dump_regs(const struct superio_registers reg_table[],
printf("(%s)", reg_table[i].ldn[j].name);
}
+ set_extra_selector(port, &reg_table[i].ldn[j].esel);
+
idx = reg_table[i].ldn[j].idx;
def = reg_table[i].ldn[j].def;
diff --git a/util/superiotool/superiotool.h b/util/superiotool/superiotool.h
index 14090309ee..ef2bfd6685 100644
--- a/util/superiotool/superiotool.h
+++ b/util/superiotool/superiotool.h
@@ -136,6 +136,14 @@ extern int dump, verbose, extra_dump;
extern int chip_found;
+/* Extra selector structure (see fintek.c) */
+struct extra_selector {
+ const char *name;
+ uint8_t idx;
+ uint8_t mask;
+ uint8_t val;
+};
+
struct superio_registers {
int32_t superio_id; /* Signed, as we need EOT. */
const char *name; /* Super I/O name */
@@ -144,6 +152,7 @@ struct superio_registers {
const char *name; /* LDN name */
int16_t idx[IDXSIZE];
int16_t def[IDXSIZE];
+ struct extra_selector esel;
} ldn[LDNSIZE];
};