Aaron Durbin (adurbin@google.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/4951
-gerrit
commit 364bcfaf0b8062656c7ca542afbc6879813d3c8a Author: Duncan Laurie dlaurie@chromium.org Date: Fri Nov 8 23:00:24 2013 -0800
regscript: Add support for MSR type
This required changing value/mask types to uint64_t.
Another option would be to use id field to select low or high 32 bits of the MSR and set them independently.
BUG=chrome-os-partner:23505 BRANCH=none TEST=build and boot on rambi
Change-Id: Ied9998058a8035bf3f003185236f3be3e0df7fc9 Signed-off-by: Duncan Laurie dlaurie@chromium.org Reviewed-on: https://chromium-review.googlesource.com/176304 Reviewed-by: Aaron Durbin adurbin@chromium.org Commit-Queue: Aaron Durbin adurbin@chromium.org Signed-off-by: Aaron Durbin adurbin@chromium.org --- src/include/reg_script.h | 26 ++++++++++- src/lib/reg_script.c | 114 ++++++++++++++++++++++++++++++++--------------- 2 files changed, 101 insertions(+), 39 deletions(-)
diff --git a/src/include/reg_script.h b/src/include/reg_script.h index 18eda0c..81a4648 100644 --- a/src/include/reg_script.h +++ b/src/include/reg_script.h @@ -59,12 +59,14 @@ enum { REG_SCRIPT_TYPE_MMIO, REG_SCRIPT_TYPE_RES, REG_SCRIPT_TYPE_IOSF, + REG_SCRIPT_TYPE_MSR, };
enum { REG_SCRIPT_SIZE_8, REG_SCRIPT_SIZE_16, REG_SCRIPT_SIZE_32, + REG_SCRIPT_SIZE_64, };
struct reg_script { @@ -72,8 +74,8 @@ struct reg_script { uint32_t type; uint32_t size; uint32_t reg; - uint32_t mask; - uint32_t value; + uint64_t mask; + uint64_t value; uint32_t timeout; union { uint32_t id; @@ -290,6 +292,26 @@ struct reg_script { REG_SCRIPT_IOSF(POLL, unit_, reg_, mask_, value_, timeout_)
/* + * CPU Model Specific Register + */ + +#define REG_SCRIPT_MSR(cmd_, reg_, mask_, value_, timeout_) \ + _REG_SCRIPT_ENCODE_RAW(REG_SCRIPT_COMMAND_##cmd_, \ + REG_SCRIPT_TYPE_MSR, \ + REG_SCRIPT_SIZE_64, \ + reg_, mask_, value_, timeout_, 0) +#define REG_MSR_READ(reg_) \ + REG_SCRIPT_MSR(READ, reg_, 0, 0, 0) +#define REG_MSR_WRITE(reg_, value_) \ + REG_SCRIPT_MSR(WRITE, reg_, 0, value_, 0) +#define REG_MSR_RMW(reg_, mask_, value_) \ + REG_SCRIPT_MSR(RMW, reg_, mask_, value_, 0) +#define REG_MSR_OR(reg_, value_) \ + REG_MSR_RMW(reg_, -1ULL, value_) +#define REG_MSR_POLL(reg_, mask_, value_, timeout_) \ + REG_SCRIPT_MSR(POLL, reg_, mask_, value_, timeout_) + +/* * Chain to another table. */ #define REG_SCRIPT_NEXT(next_) \ diff --git a/src/lib/reg_script.c b/src/lib/reg_script.c index 252aa12..c9200ab 100644 --- a/src/lib/reg_script.c +++ b/src/lib/reg_script.c @@ -26,6 +26,10 @@ #include <stdint.h> #include <reg_script.h>
+#if CONFIG_ARCH_X86 +#include <cpu/x86/msr.h> +#endif + #if CONFIG_SOC_INTEL_BAYTRAIL #include <baytrail/iosf.h> #endif @@ -285,7 +289,31 @@ static void reg_script_write_iosf(struct reg_script_context *ctx) #endif }
-static uint32_t reg_script_read(struct reg_script_context *ctx) +static uint64_t reg_script_read_msr(struct reg_script_context *ctx) +{ +#if CONFIG_ARCH_X86 + const struct reg_script *step = reg_script_get_step(ctx); + msr_t msr = rdmsr(step->reg); + uint64_t value = msr.hi; + value = msr.hi; + value <<= 32; + value |= msr.lo; + return value; +#endif +} + +static void reg_script_write_msr(struct reg_script_context *ctx) +{ +#if CONFIG_ARCH_X86 + const struct reg_script *step = reg_script_get_step(ctx); + msr_t msr; + msr.hi = step->value >> 32; + msr.lo = step->value & 0xffffffff; + wrmsr(step->reg, msr); +#endif +} + +static uint64_t reg_script_read(struct reg_script_context *ctx) { const struct reg_script *step = reg_script_get_step(ctx);
@@ -300,6 +328,8 @@ static uint32_t reg_script_read(struct reg_script_context *ctx) return reg_script_read_res(ctx); case REG_SCRIPT_TYPE_IOSF: return reg_script_read_iosf(ctx); + case REG_SCRIPT_TYPE_MSR: + return reg_script_read_msr(ctx); } return 0; } @@ -324,6 +354,9 @@ static void reg_script_write(struct reg_script_context *ctx) case REG_SCRIPT_TYPE_IOSF: reg_script_write_iosf(ctx); break; + case REG_SCRIPT_TYPE_MSR: + reg_script_write_msr(ctx); + break; } }
@@ -349,50 +382,57 @@ static void reg_script_rmw(struct reg_script_context *ctx) static void reg_script_run_next(struct reg_script_context *ctx, const struct reg_script *step);
-static void reg_script_run_with_context(struct reg_script_context *ctx) + +static void reg_script_run_step(struct reg_script_context *ctx, + const struct reg_script *step) { - uint32_t value = 0, try; + uint64_t value = 0, try;
+ switch (step->command) { + case REG_SCRIPT_COMMAND_READ: + (void)reg_script_read(ctx); + break; + case REG_SCRIPT_COMMAND_WRITE: + reg_script_write(ctx); + break; + case REG_SCRIPT_COMMAND_RMW: + reg_script_rmw(ctx); + break; + case REG_SCRIPT_COMMAND_POLL: + for (try = 0; try < step->timeout; try += POLL_DELAY) { + value = reg_script_read(ctx) & step->mask; + if (value == step->value) + break; + udelay(POLL_DELAY); + } + if (try >= step->timeout) + printk(BIOS_WARNING, "%s: POLL timeout waiting for " + "0x%x to be 0x%lx, got 0x%lx\n", __func__, + step->reg, (unsigned long)step->value, + (unsigned long)value); + break; + case REG_SCRIPT_COMMAND_SET_DEV: + reg_script_set_dev(ctx, step->dev); + break; + case REG_SCRIPT_COMMAND_NEXT: + reg_script_run_next(ctx, step->next); + break; + default: + printk(BIOS_WARNING, "Invalid command: %08x\n", + step->command); + break; + } +} + +static void reg_script_run_with_context(struct reg_script_context *ctx) +{ while (1) { const struct reg_script *step = reg_script_get_step(ctx);
if (step->command == REG_SCRIPT_COMMAND_END) break;
- switch (step->command) { - case REG_SCRIPT_COMMAND_READ: - (void)reg_script_read(ctx); - break; - case REG_SCRIPT_COMMAND_WRITE: - reg_script_write(ctx); - break; - case REG_SCRIPT_COMMAND_RMW: - reg_script_rmw(ctx); - break; - case REG_SCRIPT_COMMAND_POLL: - for (try = 0; try < step->timeout; try += POLL_DELAY) { - value = reg_script_read(ctx) & step->mask; - if (value == step->value) - break; - udelay(POLL_DELAY); - } - if (try >= step->timeout) - printk(BIOS_WARNING, "%s: POLL timeout waiting " - "for 0x%08x to be 0x%08x, got 0x%08x\n", - __func__, step->reg, step->value, value); - break; - case REG_SCRIPT_COMMAND_SET_DEV: - reg_script_set_dev(ctx, step->dev); - break; - case REG_SCRIPT_COMMAND_NEXT: - reg_script_run_next(ctx, step->next); - break; - default: - printk(BIOS_WARNING, "Invalid command: %08x\n", - step->command); - break; - } - + reg_script_run_step(ctx, step); reg_script_set_step(ctx, step + 1); } }