From 63e3dff02f5b66b32b32fd1497f820532af25a07 Mon Sep 17 00:00:00 2001 From: Lee Leahy Date: Sat, 30 Apr 2016 08:48:52 -0700 Subject: soc/intel/quark: Add temperature sensor support Migrate the temperature sensor support from QuarkFspPkg into coreboot. TEST=Build and run on Galileo Gen2 Change-Id: I6dc68c735375c9d1777693264674521f67397556 Signed-off-by: Lee Leahy Reviewed-on: https://review.coreboot.org/14565 Tested-by: build bot (Jenkins) Reviewed-by: Martin Roth --- src/soc/intel/quark/chip.c | 95 ++++++++++++++++++++++++++++ src/soc/intel/quark/include/soc/reg_access.h | 48 ++++++++++++++ src/soc/intel/quark/reg_access.c | 54 ++++++++++++++++ 3 files changed, 197 insertions(+) (limited to 'src/soc/intel/quark') diff --git a/src/soc/intel/quark/chip.c b/src/soc/intel/quark/chip.c index 7ea8a062a1..30ab48ac10 100644 --- a/src/soc/intel/quark/chip.c +++ b/src/soc/intel/quark/chip.c @@ -17,9 +17,104 @@ #include #include #include +#include + +/* Cat Trip Clear value must be less than Cat Trip Set value */ +#define PLATFORM_CATASTROPHIC_TRIP_CELSIUS 105 +#define PLATFORM_CATASTROPHIC_CLEAR_CELSIUS 65 + +static const struct reg_script thermal_init_script[] = { + + /* Setup RMU Thermal sensor registers for Ratiometric mode. */ + REG_SOC_UNIT_RMW(QUARK_SCSS_SOC_UNIT_TSCGF1_CONFIG, + ~(B_TSCGF1_CONFIG_ISNSCURRENTSEL_MASK + | B_TSCGF1_CONFIG_ISNSCHOPSEL_MASK + | B_TSCGF1_CONFIG_ISNSINTERNALVREFEN + | B_TSCGF1_CONFIG_IBGEN + | B_TSCGF1_CONFIG_IBGCHOPEN), + ((V_TSCGF1_CONFIG_ISNSCURRENTSEL_RATIO_MODE + << B_TSCGF1_CONFIG_ISNSCURRENTSEL_BP) + | (V_TSCGF1_CONFIG_ISNSCHOPSEL_RATIO_MODE + << B_TSCGF1_CONFIG_ISNSCHOPSEL_BP) + | (V_TSCGF1_CONFIG_ISNSINTERNALVREFEN_RATIO_MODE + << B_TSCGF1_CONFIG_ISNSINTERNALVREFEN_BP) + | (V_TSCGF1_CONFIG_IBGEN_RATIO_MODE + << B_TSCGF1_CONFIG_IBGEN_BP) + | (V_TSCGF1_CONFIG_IBGCHOPEN_RATIO_MODE + << B_TSCGF1_CONFIG_IBGCHOPEN_BP))), + + REG_SOC_UNIT_RMW(QUARK_SCSS_SOC_UNIT_TSCGF2_CONFIG2, + ~(B_TSCGF2_CONFIG2_ICALCONFIGSEL_MASK + | B_TSCGF2_CONFIG2_ISPARECTRL_MASK + | B_TSCGF2_CONFIG2_ICALCOARSETUNE_MASK), + ((V_TSCGF2_CONFIG2_ICALCONFIGSEL_RATIO_MODE + << B_TSCGF2_CONFIG2_ICALCONFIGSEL_BP) + | (V_TSCGF2_CONFIG2_ISPARECTRL_RATIO_MODE + << B_TSCGF2_CONFIG2_ISPARECTRL_BP) + | (V_TSCGF2_CONFIG2_ICALCOARSETUNE_RATIO_MODE + << B_TSCGF2_CONFIG2_ICALCOARSETUNE_BP))), + + REG_SOC_UNIT_RMW(QUARK_SCSS_SOC_UNIT_TSCGF2_CONFIG, + ~(B_TSCGF2_CONFIG_IDSCONTROL_MASK + | B_TSCGF2_CONFIG_IDSTIMING_MASK), + ((V_TSCGF2_CONFIG_IDSCONTROL_RATIO_MODE + << B_TSCGF2_CONFIG_IDSCONTROL_BP) + | (V_TSCGF2_CONFIG_IDSTIMING_RATIO_MODE + << B_TSCGF2_CONFIG_IDSTIMING_BP))), + + REG_SOC_UNIT_RMW(QUARK_SCSS_SOC_UNIT_TSCGF3_CONFIG, + ~B_TSCGF3_CONFIG_ITSGAMMACOEFF_MASK, + V_TSCGF3_CONFIG_ITSGAMMACOEFF_RATIO_MODE + << B_TSCGF3_CONFIG_ITSGAMMACOEFF_BP), + + /* Enable RMU Thermal sensor with a Catastrophic Trip point. */ + + /* Set up Catastrophic Trip point. + * + * Trip Register fields are 8-bit temperature values of granularity 1 + * degree C where 0x00 corresponds to -50 degrees C and 0xFF corresponds + * to 205 degrees C. + * + * Add 50 to Celsius values to get values for register fields. + */ + REG_RMU_TEMP_RMW(QUARK_NC_RMU_REG_TS_TRIP, + ~(TS_CAT_TRIP_SET_THOLD_MASK | TS_CAT_TRIP_CLEAR_THOLD_MASK), + (((PLATFORM_CATASTROPHIC_TRIP_CELSIUS + 50) + << TS_CAT_TRIP_SET_THOLD_BP) + | ((PLATFORM_CATASTROPHIC_CLEAR_CELSIUS + 50) + << TS_CAT_TRIP_CLEAR_THOLD_BP))), + + /* To enable the TS do the following: + * 1) Take the TS out of reset by setting itsrst to 0x0. + * 2) Enable the TS using RMU Thermal sensor mode register. + */ + REG_SOC_UNIT_AND(QUARK_SCSS_SOC_UNIT_TSCGF3_CONFIG, + ~B_TSCGF3_CONFIG_ITSRST), + REG_RMU_TEMP_OR(QUARK_NC_RMU_REG_TS_MODE, TS_ENABLE), + + /* Lock all RMU Thermal sensor control & trip point registers. */ + REG_RMU_TEMP_OR(QUARK_NC_RMU_REG_CONFIG, TS_LOCK_THRM_CTRL_REGS_ENABLE + | TS_LOCK_AUX_TRIP_PT_REGS_ENABLE), + REG_SCRIPT_END +}; static void chip_init(void *chip_info) { + /* Validate the temperature settings */ + ASSERT(PLATFORM_CATASTROPHIC_TRIP_CELSIUS <= 255); + ASSERT(PLATFORM_CATASTROPHIC_TRIP_CELSIUS + > PLATFORM_CATASTROPHIC_CLEAR_CELSIUS); + + /* Set the temperature settings */ + reg_script_run(thermal_init_script); + + /* Verify that the thermal configuration is locked */ + ASSERT((reg_rmu_temp_read(QUARK_NC_RMU_REG_CONFIG) + & (TS_LOCK_THRM_CTRL_REGS_ENABLE + | TS_LOCK_AUX_TRIP_PT_REGS_ENABLE)) + == (TS_LOCK_THRM_CTRL_REGS_ENABLE + | TS_LOCK_AUX_TRIP_PT_REGS_ENABLE)); + /* Perform silicon specific init. */ if (IS_ENABLED(CONFIG_RELOCATE_FSP_INTO_DRAM)) intel_silicon_init(); diff --git a/src/soc/intel/quark/include/soc/reg_access.h b/src/soc/intel/quark/include/soc/reg_access.h index 934c75d0e5..ddca6682cd 100644 --- a/src/soc/intel/quark/include/soc/reg_access.h +++ b/src/soc/intel/quark/include/soc/reg_access.h @@ -18,10 +18,13 @@ #include #include +#include #include enum { USB_PHY_REGS = 1, + SOC_UNIT_REGS, + RMU_TEMP_REGS, }; enum { @@ -32,6 +35,50 @@ enum { #define SOC_ACCESS(cmd_, reg_, size_, mask_, value_, timeout_, reg_set_) \ _REG_SCRIPT_ENCODE_RAW(REG_SCRIPT_COMMAND_##cmd_, SOC_TYPE, \ size_, reg_, mask_, value_, timeout_, reg_set_) + +/* RMU temperature register access macros */ +#define REG_RMU_TEMP_ACCESS(cmd_, reg_, mask_, value_, timeout_) \ + SOC_ACCESS(cmd_, reg_, REG_SCRIPT_SIZE_32, mask_, value_, timeout_, \ + RMU_TEMP_REGS) +#define REG_RMU_TEMP_READ(reg_) \ + REG_RMU_TEMP_ACCESS(READ, reg_, 0, 0, 0) +#define REG_RMU_TEMP_WRITE(reg_, value_) \ + REG_RMU_TEMP_ACCESS(WRITE, reg_, 0, value_, 0) +#define REG_RMU_TEMP_AND(reg_, value_) \ + REG_RMU_TEMP_RMW(reg_, value_, 0) +#define REG_RMU_TEMP_RMW(reg_, mask_, value_) \ + REG_RMU_TEMP_ACCESS(RMW, reg_, mask_, value_, 0) +#define REG_RMU_TEMP_RXW(reg_, mask_, value_) \ + REG_RMU_TEMP_ACCESS(RXW, reg_, mask_, value_, 0) +#define REG_RMU_TEMP_OR(reg_, value_) \ + REG_RMU_TEMP_RMW(reg_, 0xffffffff, value_) +#define REG_RMU_TEMP_POLL(reg_, mask_, value_, timeout_) \ + REG_RMU_TEMP_ACCESS(POLL, reg_, mask_, value_, timeout_) +#define REG_RMU_TEMP_XOR(reg_, value_) \ + REG_RMU_TEMP_RXW(reg_, 0xffffffff, value_) + +/* Temperature sensor access macros */ +#define REG_SOC_UNIT_ACCESS(cmd_, reg_, mask_, value_, timeout_) \ + SOC_ACCESS(cmd_, reg_, REG_SCRIPT_SIZE_32, mask_, value_, timeout_, \ + SOC_UNIT_REGS) +#define REG_SOC_UNIT_READ(reg_) \ + REG_SOC_UNIT_ACCESS(READ, reg_, 0, 0, 0) +#define REG_SOC_UNIT_WRITE(reg_, value_) \ + REG_SOC_UNIT_ACCESS(WRITE, reg_, 0, value_, 0) +#define REG_SOC_UNIT_AND(reg_, value_) \ + REG_SOC_UNIT_RMW(reg_, value_, 0) +#define REG_SOC_UNIT_RMW(reg_, mask_, value_) \ + REG_SOC_UNIT_ACCESS(RMW, reg_, mask_, value_, 0) +#define REG_SOC_UNIT_RXW(reg_, mask_, value_) \ + REG_SOC_UNIT_ACCESS(RXW, reg_, mask_, value_, 0) +#define REG_SOC_UNIT_OR(reg_, value_) \ + REG_SOC_UNIT_RMW(reg_, 0xffffffff, value_) +#define REG_SOC_UNIT_POLL(reg_, mask_, value_, timeout_) \ + REG_SOC_UNIT_ACCESS(POLL, reg_, mask_, value_, timeout_) +#define REG_SOC_UNIT_XOR(reg_, value_) \ + REG_SOC_UNIT_RXW(reg_, 0xffffffff, value_) + +/* USB register access macros */ #define REG_USB_ACCESS(cmd_, reg_, mask_, value_, timeout_) \ SOC_ACCESS(cmd_, reg_, REG_SCRIPT_SIZE_32, mask_, value_, timeout_, \ USB_PHY_REGS) @@ -56,5 +103,6 @@ void mcr_write(uint8_t opcode, uint8_t port, uint32_t reg_address); uint32_t mdr_read(void); void mdr_write(uint32_t value); void mea_write(uint32_t reg_address); +uint32_t reg_rmu_temp_read(uint32_t reg_address); #endif /* _QUARK_REG_ACCESS_H_ */ diff --git a/src/soc/intel/quark/reg_access.c b/src/soc/intel/quark/reg_access.c index 278fc7e47d..fb80f3df0b 100644 --- a/src/soc/intel/quark/reg_access.c +++ b/src/soc/intel/quark/reg_access.c @@ -45,6 +45,40 @@ void mea_write(uint32_t reg_address) & QNC_MEA_MASK); } +uint32_t reg_rmu_temp_read(uint32_t reg_address) +{ + /* Read the RMU temperature register */ + mea_write(reg_address); + mcr_write(QUARK_OPCODE_READ, QUARK_NC_RMU_SB_PORT_ID, reg_address); + return mdr_read(); +} + +static void reg_rmu_temp_write(uint32_t reg_address, uint32_t value) +{ + /* Write the RMU temperature register */ + mea_write(reg_address); + mdr_write(value); + mcr_write(QUARK_OPCODE_WRITE, QUARK_NC_RMU_SB_PORT_ID, reg_address); +} + +static uint32_t reg_soc_unit_read(uint32_t reg_address) +{ + /* Read the temperature sensor register */ + mea_write(reg_address); + mcr_write(QUARK_ALT_OPCODE_READ, QUARK_SCSS_SOC_UNIT_SB_PORT_ID, + reg_address); + return mdr_read(); +} + +static void reg_soc_unit_write(uint32_t reg_address, uint32_t value) +{ + /* Write the temperature sensor register */ + mea_write(reg_address); + mdr_write(value); + mcr_write(QUARK_ALT_OPCODE_WRITE, QUARK_SCSS_SOC_UNIT_SB_PORT_ID, + reg_address); +} + static uint32_t reg_usb_read(uint32_t reg_address) { /* Read the USB register */ @@ -76,6 +110,16 @@ static uint64_t reg_read(struct reg_script_context *ctx) ctx->display_features = REG_SCRIPT_DISPLAY_NOTHING; return 0; + case RMU_TEMP_REGS: + ctx->display_prefix = "RMU TEMP"; + value = reg_rmu_temp_read(step->reg); + break; + + case SOC_UNIT_REGS: + ctx->display_prefix = "SOC Unit"; + value = reg_soc_unit_read(step->reg); + break; + case USB_PHY_REGS: ctx->display_prefix = "USB PHY"; value = reg_usb_read(step->reg); @@ -96,6 +140,16 @@ static void reg_write(struct reg_script_context *ctx) ctx->display_features = REG_SCRIPT_DISPLAY_NOTHING; return; + case RMU_TEMP_REGS: + ctx->display_prefix = "RMU TEMP"; + reg_rmu_temp_write(step->reg, (uint32_t)step->value); + break; + + case SOC_UNIT_REGS: + ctx->display_prefix = "SOC Unit"; + reg_soc_unit_write(step->reg, (uint32_t)step->value); + break; + case USB_PHY_REGS: ctx->display_prefix = "USB PHY"; reg_usb_write(step->reg, (uint32_t)step->value); -- cgit v1.2.3