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 <leroy.p.leahy@intel.com>
Reviewed-on: https://review.coreboot.org/14565
Tested-by: build bot (Jenkins)
Reviewed-by: Martin Roth <martinroth@google.com>
This commit is contained in:
Lee Leahy 2016-04-30 08:48:52 -07:00 committed by Leroy P Leahy
parent 4dd34eee09
commit 63e3dff02f
3 changed files with 197 additions and 0 deletions

View File

@ -17,9 +17,104 @@
#include <console/console.h> #include <console/console.h>
#include <device/device.h> #include <device/device.h>
#include <soc/ramstage.h> #include <soc/ramstage.h>
#include <soc/reg_access.h>
/* 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) 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. */ /* Perform silicon specific init. */
if (IS_ENABLED(CONFIG_RELOCATE_FSP_INTO_DRAM)) if (IS_ENABLED(CONFIG_RELOCATE_FSP_INTO_DRAM))
intel_silicon_init(); intel_silicon_init();

View File

@ -18,10 +18,13 @@
#include <fsp/util.h> #include <fsp/util.h>
#include <reg_script.h> #include <reg_script.h>
#include <soc/IntelQNCConfig.h>
#include <soc/QuarkNcSocId.h> #include <soc/QuarkNcSocId.h>
enum { enum {
USB_PHY_REGS = 1, USB_PHY_REGS = 1,
SOC_UNIT_REGS,
RMU_TEMP_REGS,
}; };
enum { enum {
@ -32,6 +35,50 @@ enum {
#define SOC_ACCESS(cmd_, reg_, size_, mask_, value_, timeout_, reg_set_) \ #define SOC_ACCESS(cmd_, reg_, size_, mask_, value_, timeout_, reg_set_) \
_REG_SCRIPT_ENCODE_RAW(REG_SCRIPT_COMMAND_##cmd_, SOC_TYPE, \ _REG_SCRIPT_ENCODE_RAW(REG_SCRIPT_COMMAND_##cmd_, SOC_TYPE, \
size_, reg_, mask_, value_, timeout_, reg_set_) 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_) \ #define REG_USB_ACCESS(cmd_, reg_, mask_, value_, timeout_) \
SOC_ACCESS(cmd_, reg_, REG_SCRIPT_SIZE_32, mask_, value_, timeout_, \ SOC_ACCESS(cmd_, reg_, REG_SCRIPT_SIZE_32, mask_, value_, timeout_, \
USB_PHY_REGS) 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); uint32_t mdr_read(void);
void mdr_write(uint32_t value); void mdr_write(uint32_t value);
void mea_write(uint32_t reg_address); void mea_write(uint32_t reg_address);
uint32_t reg_rmu_temp_read(uint32_t reg_address);
#endif /* _QUARK_REG_ACCESS_H_ */ #endif /* _QUARK_REG_ACCESS_H_ */

View File

@ -45,6 +45,40 @@ void mea_write(uint32_t reg_address)
& QNC_MEA_MASK); & 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) static uint32_t reg_usb_read(uint32_t reg_address)
{ {
/* Read the USB register */ /* 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; ctx->display_features = REG_SCRIPT_DISPLAY_NOTHING;
return 0; 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: case USB_PHY_REGS:
ctx->display_prefix = "USB PHY"; ctx->display_prefix = "USB PHY";
value = reg_usb_read(step->reg); 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; ctx->display_features = REG_SCRIPT_DISPLAY_NOTHING;
return; 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: case USB_PHY_REGS:
ctx->display_prefix = "USB PHY"; ctx->display_prefix = "USB PHY";
reg_usb_write(step->reg, (uint32_t)step->value); reg_usb_write(step->reg, (uint32_t)step->value);