diff options
author | Lee Leahy <leroy.p.leahy@intel.com> | 2014-08-29 13:38:59 -0700 |
---|---|---|
committer | Patrick Georgi <pgeorgi@google.com> | 2015-04-04 12:40:29 +0200 |
commit | 9f5a5c532343fe72753fc507b0f2ef1a26afabd3 (patch) | |
tree | be1f1b955ce316f24871ec2da4785a2d6e988e9b | |
parent | a19a4e1d64ab0dbf531a3fbeb7cdda331a3ed6ca (diff) |
Add table driven way to add platform specific reg_script routines
Extend lib/reg_script.c to use a platform table to declare
additional platform specific register access routine functions.
REG_SCRIPT_TYPE_PLATFORM_BASE is the starting value for platform
specific register types. Additional register access types may be
defined above this value. The type and access routines are placed
into reg_script_type_table.
The Baytrail type value for IOSF was left the enumeration since it
was already defined and is being used for Braswell.
BRANCH=none
BUG=None
TEST=Use the following steps to test:
1. Build for a Baytrail platform
2. Build for the Samus platform
3. Add a platform_bus_table routine to a platform which returns the
address of an array of reg_script_bus_entry structures and the
number of entries in the array.
Change-Id: Ic99d345c4b067c52b4e9c47e59ed4472a05bc1a5
Signed-off-by: Stefan Reinauer <reinauer@chromium.org>
Original-Commit-Id: 2d9fecf4287dff6311a81d818603212248f1a248
Original-Signed-off-by: Lee Leahy <leroy.p.leahy@intel.com>
Original-Reviewed-on: https://chromium-review.googlesource.com/215645
Original-Reviewed-by: Aaron Durbin <adurbin@chromium.org>
Original-Change-Id: I7cd37abc5a08cadb3166d4048f65b919b86ab5db
Original-Reviewed-on: https://chromium-review.googlesource.com/229612
Original-Reviewed-by: Duncan Laurie <dlaurie@chromium.org>
Reviewed-on: http://review.coreboot.org/9279
Tested-by: build bot (Jenkins)
Reviewed-by: Patrick Georgi <pgeorgi@google.com>
-rw-r--r-- | src/include/reg_script.h | 25 | ||||
-rw-r--r-- | src/lib/reg_script.c | 87 |
2 files changed, 98 insertions, 14 deletions
diff --git a/src/include/reg_script.h b/src/include/reg_script.h index 97b4fb00dc..0c0ea01ce5 100644 --- a/src/include/reg_script.h +++ b/src/include/reg_script.h @@ -60,6 +60,10 @@ enum { REG_SCRIPT_TYPE_RES, REG_SCRIPT_TYPE_IOSF, REG_SCRIPT_TYPE_MSR, + + /* Insert other platform independent values above this comment */ + + REG_SCRIPT_TYPE_PLATFORM_BASE = 0x10000 }; enum { @@ -85,6 +89,24 @@ struct reg_script { }; }; +struct reg_script_context { + device_t dev; + struct resource *res; + const struct reg_script *step; +}; + +#ifndef __PRE_RAM__ +struct reg_script_bus_entry { + int type; + uint64_t (*reg_script_read)(struct reg_script_context *ctx); + void (*reg_script_write)(struct reg_script_context *ctx); +}; + +/* Get the address and length of the platform bus table */ +const struct reg_script_bus_entry *platform_bus_table(size_t *table_entries); + +#endif /* __PRE_RAM */ + /* Internal helper Macros. */ #define _REG_SCRIPT_ENCODE_RAW(cmd_, type_, size_, reg_, \ @@ -271,6 +293,8 @@ struct reg_script { #define REG_RES_POLL32(bar_, reg_, mask_, value_, timeout_) \ REG_SCRIPT_RES(POLL, 32, bar_, reg_, mask_, value_, timeout_) + +#if CONFIG_SOC_INTEL_BAYTRAIL /* * IO Sideband Function */ @@ -290,6 +314,7 @@ struct reg_script { REG_IOSF_RMW(unit_, reg_, 0xffffffff, value_) #define REG_IOSF_POLL(unit_, reg_, mask_, value_, timeout_) \ REG_SCRIPT_IOSF(POLL, unit_, reg_, mask_, value_, timeout_) +#endif /* CONFIG_SOC_INTEL_BAYTRAIL */ /* * CPU Model Specific Register diff --git a/src/lib/reg_script.c b/src/lib/reg_script.c index 2fd943e3a1..3f7ddaf3da 100644 --- a/src/lib/reg_script.c +++ b/src/lib/reg_script.c @@ -41,12 +41,6 @@ #define EMPTY_DEV NULL #endif -struct reg_script_context { - device_t dev; - struct resource *res; - const struct reg_script *step; -}; - static inline void reg_script_set_dev(struct reg_script_context *ctx, device_t dev) { @@ -243,9 +237,9 @@ static void reg_script_write_res(struct reg_script_context *ctx) reg_script_set_step(ctx, step); } +#if CONFIG_SOC_INTEL_BAYTRAIL static uint32_t reg_script_read_iosf(struct reg_script_context *ctx) { -#if CONFIG_SOC_INTEL_BAYTRAIL const struct reg_script *step = reg_script_get_step(ctx); switch (step->id) { @@ -296,13 +290,11 @@ static uint32_t reg_script_read_iosf(struct reg_script_context *ctx) step->id); break; } -#endif return 0; } static void reg_script_write_iosf(struct reg_script_context *ctx) { -#if CONFIG_SOC_INTEL_BAYTRAIL const struct reg_script *step = reg_script_get_step(ctx); switch (step->id) { @@ -374,8 +366,9 @@ static void reg_script_write_iosf(struct reg_script_context *ctx) step->id); break; } -#endif } +#endif + static uint64_t reg_script_read_msr(struct reg_script_context *ctx) { @@ -401,6 +394,36 @@ static void reg_script_write_msr(struct reg_script_context *ctx) #endif } +#ifndef __PRE_RAM__ +/* Default routine provided for systems without platform specific busses */ +const struct reg_script_bus_entry *__attribute__((weak)) + platform_bus_table(size_t *table_entries) +{ + /* No platform bus type table supplied */ + *table_entries = 0; + return NULL; +} + +/* Locate the structure containing the platform specific bus access routines */ +static const struct reg_script_bus_entry + *find_bus(const struct reg_script *step) +{ + const struct reg_script_bus_entry *bus; + size_t table_entries; + size_t i; + + /* Locate the platform specific bus */ + bus = platform_bus_table(&table_entries); + for (i = 0; i < table_entries; i++) { + if (bus[i].type == step->type) + return &bus[i]; + } + + /* Bus not found */ + return NULL; +} +#endif + static uint64_t reg_script_read(struct reg_script_context *ctx) { const struct reg_script *step = reg_script_get_step(ctx); @@ -414,10 +437,27 @@ static uint64_t reg_script_read(struct reg_script_context *ctx) return reg_script_read_mmio(ctx); case REG_SCRIPT_TYPE_RES: 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); +#if CONFIG_SOC_INTEL_BAYTRAIL + case REG_SCRIPT_TYPE_IOSF: + return reg_script_read_iosf(ctx); +#endif + default: +#ifndef __PRE_RAM__ + { + const struct reg_script_bus_entry *bus; + + /* Read from the platform specific bus */ + bus = find_bus(step); + if (NULL != bus) + return bus->reg_script_read(ctx); + } +#endif + printk(BIOS_ERR, + "Unsupported read type (0x%x) for this device!\n", + step->type); + break; } return 0; } @@ -439,11 +479,30 @@ static void reg_script_write(struct reg_script_context *ctx) case REG_SCRIPT_TYPE_RES: reg_script_write_res(ctx); break; + case REG_SCRIPT_TYPE_MSR: + reg_script_write_msr(ctx); + break; +#if CONFIG_SOC_INTEL_BAYTRAIL case REG_SCRIPT_TYPE_IOSF: reg_script_write_iosf(ctx); break; - case REG_SCRIPT_TYPE_MSR: - reg_script_write_msr(ctx); +#endif + default: +#ifndef __PRE_RAM__ + { + const struct reg_script_bus_entry *bus; + + /* Write to the platform specific bus */ + bus = find_bus(step); + if (NULL != bus) { + bus->reg_script_write(ctx); + return; + } + } +#endif + printk(BIOS_ERR, + "Unsupported write type (0x%x) for this device!\n", + step->type); break; } } |