SB800: Add IMC ROM and fan control.

Add configuration for AMD's IMC ROM and fan registers for cimx/sb800
platforms.

- Allows user to add the IMC rom to the build and to configure the
  location of the "signature" between the allowed positions.
- Allows for no fan control, manual setup of SB800 Fan registers, or
  setup of the IMC fan configuration registers.
- Register configuration is done through devicetree.cb. No files need
  to be added for new platform configuration.
- Initial setup is for Persimmon, but may be extended to any cimx/sb800
  platform.

Change-Id: Ib06408d794988cbb29eed6adbeeadea8b2629bae
Signed-off-by: Martin Roth <martin@se-eng.com>
Reviewed-on: http://review.coreboot.org/1977
Tested-by: build bot (Jenkins)
Reviewed-by: Patrick Georgi <patrick@georgi-clan.de>
Reviewed-by: Marc Jones <marcj303@gmail.com>
This commit is contained in:
Martin Roth 2012-12-05 16:07:11 -07:00 committed by Marc Jones
parent a17fd056d4
commit e899e518d8
10 changed files with 866 additions and 1 deletions

View File

@ -91,6 +91,55 @@ chip northbridge/amd/agesa/family14/root_complex
device pci 16.2 off end # EHCI USB3
register "gpp_configuration" = "0" #4:0:0:0 (really need to disable all 4 somehow)
register "boot_switch_sata_ide" = "0" # 0: boot from SATA. 1: IDE
#set up SB800 Fan control registers and IMC fan controls
register "imc_port_address" = "0x6E" # 0x2E and 0x6E are common
register "fan0_enabled" = "1"
register "fan1_enabled" = "1"
register "imc_fan_zone0_enabled" = "1"
register "imc_fan_zone1_enabled" = "1"
register "fan0_config_vals" = "{ \
FAN_INPUT_INTERNAL_DIODE, FAN_POLARITY_HIGH, \
FREQ_25KHZ, 0x08, 0x00, 0x00, 0x00, 0x00,\
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }"
register "fan1_config_vals" = "{ \
FAN_INPUT_INTERNAL_DIODE, FAN_POLARITY_HIGH, \
FREQ_25KHZ, 0x10, 0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }"
register "imc_zone0_mode1" = " \
IMC_MODE1_FAN_ENABLED | IMC_MODE1_FAN_IMC_CONTROLLED | \
IMC_MODE1_FAN_STEP_MODE | IMC_MODE1_FANOUT0"
register "imc_zone0_mode2" = " IMC_MODE2_TEMPIN_SB_TSI | \
IMC_MODE2_FANIN0 | IMC_MODE2_TEMP_AVERAGING_DISABLED"
register "imc_zone0_temp_offset" = "0x00" # No temp offset
register "imc_zone0_hysteresis" = "0x05" # Degrees C Hysteresis
register "imc_zone0_smbus_addr" = "0x98" # Temp Sensor SMBus address
register "imc_zone0_smbus_num" = "IMC_TEMP_SENSOR_ON_SMBUS_3" # SMBUS number
register "imc_zone0_pwm_step" = "0x01" # Fan PWM stepping rate
register "imc_zone0_ramping" = "0x00" # Disable Fan PWM ramping and stepping
register "imc_zone1_mode1" = " \
IMC_MODE1_FAN_ENABLED | IMC_MODE1_FAN_IMC_CONTROLLED | \
IMC_MODE1_FAN_STEP_MODE | IMC_MODE1_FANOUT1"
register "imc_zone1_mode2" = " IMC_MODE2_TEMPIN_SB_TSI | \
IMC_MODE2_FANIN1 | IMC_MODE2_TEMP_AVERAGING_DISABLED"
register "imc_zone1_temp_offset" = "0x00" # No temp offset
register "imc_zone1_hysteresis" = "0x05" # Degrees C Hysteresis
register "imc_zone1_smbus_addr" = "0x98" # Temp Sensor SMBus address
register "imc_zone1_smbus_num" = "IMC_TEMP_SENSOR_ON_SMBUS_3" # SMBUS number
register "imc_zone1_pwm_step" = "0x01" # Fan PWM stepping rate
register "imc_zone1_ramping" = "0x00" # Disable Fan PWM ramping and stepping
# T56N has a Maximum operating temperature of 90C
# ZONEX_THRESHOLDS - _AC0 - _AC7, _CRT - Temp Threshold in degrees C
# ZONEX_FANSPEEDS - Fan speeds as a "percentage"
register "imc_zone0_thresholds" = "{ 87, 82, 77, 72, 65, 1, 0, 0, 90 }"
register "imc_zone0_fanspeeds" = "{100, 7, 5, 4, 3, 2, 0, 0 }"
register "imc_zone1_thresholds" = "{ 85, 80, 75, 65, 1, 0, 0, 0, 90 }"
register "imc_zone1_fanspeeds" = "{100, 10, 6, 4, 3, 0, 0, 0 }"
end #southbridge/amd/cimx/sb800
# end # device pci 18.0
# These seem unnecessary

View File

@ -130,5 +130,100 @@ config S3_VOLATILE_POS
For a system with S3 feature, the BIOS needs to save some data to
non-volitile storage at cold boot stage.
config SB800_IMC_FWM
bool "Add IMC firmware"
default n
help
Add SB800 / Hudson 1 IMC Firmware to support the onboard fan control.
Please contact AMD to obtain the related firmware.
if SB800_IMC_FWM
config SB800_IMC_FWM_FILE
string "IMC firmware path and filename"
default "3rdparty/southbridge/amd/sb800/imc.bin"
choice
prompt "SB800 Firmware ROM Position"
config SB800_FWM_AT_FFFA0000
bool "0xFFFA0000"
help
The IMC and GEC ROMs requires a 'signature' located at one of several
fixed locations in memory. The location used shouldn't matter, just
select an area that doesn't conflict with anything else.
config SB800_FWM_AT_FFF20000
bool "0xFFF20000"
help
The IMC and GEC ROMs requires a 'signature' located at one of several
fixed locations in memory. The location used shouldn't matter, just
select an area that doesn't conflict with anything else.
config SB800_FWM_AT_FFE20000
depends on BOARD_ROMSIZE_KB_8192 || BOARD_ROMSIZE_KB_4096 || BOARD_ROMSIZE_KB_2048
bool "0xFFE20000"
help
The IMC and GEC ROMs requires a 'signature' located at one of several
fixed locations in memory. The location used shouldn't matter, just
select an area that doesn't conflict with anything else.
config SB800_FWM_AT_FFC20000
depends on BOARD_ROMSIZE_KB_8192 || BOARD_ROMSIZE_KB_4096
bool "0xFFC20000"
help
The IMC and GEC ROMs requires a 'signature' located at one of several
fixed locations in memory. The location used shouldn't matter, just
select an area that doesn't conflict with anything else.
config SB800_FWM_AT_FF820000
depends on BOARD_ROMSIZE_KB_8192
bool "0xFF820000"
help
The IMC and GEC ROMs requires a 'signature' located at one of several
fixed locations in memory. The location used shouldn't matter, just
select an area that doesn't conflict with anything else.
endchoice
config SB800_FWM_POSITION
hex
default 0xFFFA0000 if SB800_FWM_AT_FFFA0000
default 0xFFF20000 if SB800_FWM_AT_FFF20000
default 0xFFE20000 if SB800_FWM_AT_FFE20000
default 0xFFC20000 if SB800_FWM_AT_FFC20000
default 0xFF820000 if SB800_FWM_AT_FFE20000
endif #SB800_IMC_FWM
choice
prompt "Fan Control"
default SB800_NO_FAN_CONTROL
help
Select the method of SB800 fan control to be used. None would be
for either fixed maximum speed fans connected to the SB800 or for
an external chip controlling the fan speeds. Manual control sets
up the SB800 fan control registers. IMC fan control uses the SB800
IMC to actively control the fan speeds.
config SB800_NO_FAN_CONTROL
bool "None"
help
No SB800 Fan control - Do not set up the SB800 fan control registers.
config SB800_MANUAL_FAN_CONTROL
bool "Manual"
help
Configure the SB800 fan control registers in devicetree.cb.
config SB800_IMC_FAN_CONTROL
bool "IMC Based"
depends on SB800_IMC_FWM
help
Set up the SB800 to use the IMC based Fan controller. This requires
the IMC rom from AMD. Configure the registers in devicetree.cb.
endchoice
endif #SOUTHBRIDGE_AMD_CIMX_SB800

View File

@ -27,6 +27,8 @@ romstage-y += smbus.c
ramstage-y += cfg.c
ramstage-y += late.c
ramstage-$(CONFIG_SB800_MANUAL_FAN_CONTROL) += fan.c
ramstage-$(CONFIG_SB800_IMC_FAN_CONTROL) += fan.c
ramstage-$(CONFIG_HAVE_ACPI_RESUME) += spi.c
ramstage-$(CONFIG_GENERATE_ACPI_TABLES) += fadt.c
@ -53,3 +55,41 @@ ifeq ($(CONFIG_SB800_SATA_RAID), y)
raid/misc.bin-position := $(CONFIG_RAID_MISC_ROM_POSITION)
raid/misc.bin-type := raw
endif
ifeq ($(CONFIG_SB800_IMC_FWM), y)
# ROMSIG At ROMBASE + 0x20000:
# +-----------+---------------+----------------+------------+
# |0x55AA55AA |EC ROM Address |GEC ROM Address | |
# +-----------+---------------+----------------+------------+
# EC ROM should be 64K aligned.
SB800_FWM_POSITION=$(shell printf %u $(CONFIG_SB800_FWM_POSITION))
#assume the cbfs header is less than 128 bytes.
ROMSIG_SIZE=16
SB800_IMC_POSITION_UNALIGN=$(shell echo $(SB800_FWM_POSITION) $(ROMSIG_SIZE) 128 65535 | awk '{print $$1 + $$2 + $$3 + $$4}')
SB800_IMC_POSITION=$(shell echo $(SB800_IMC_POSITION_UNALIGN) | awk '{print $$1 - $$1 % 65536}')
$(obj)/coreboot_SB800_romsig.bin: \
$(call strip_quotes, $(CONFIG_SB800_IMC_FWM_FILE)) \
$(obj)/config.h \
$(obj)/mainboard/$(MAINBOARDDIR)/static.c
echo " SB800 FW $@"
for fwm in 1437226410 \
$(SB800_IMC_POSITION) \
0 \
0 ; do \
echo $$fwm | LC_ALL=C awk '{printf ("%c%c%c%c", $$1 % 256, int($$1/256) % 256, int($$1/65536) % 256, int($$1/16777216));}'; \
done > $@
cbfs-files-y += SB800/fwm
SB800/fwm-file := $(obj)/coreboot_SB800_romsig.bin
SB800/fwm-position := $(SB800_FWM_POSITION)
SB800/fwm-type := raw
cbfs-files-y += SB800/imc
SB800/imc-file := $(call strip_quotes, $(CONFIG_SB800_IMC_FWM_FILE))
SB800/imc-position := $(SB800_IMC_POSITION)
SB800/imc-type := raw
endif

View File

@ -57,6 +57,10 @@ typedef union _PCI_ADDR {
#endif
#define FIXUP_PTR(ptr) ptr
#if CONFIG_SB800_IMC_FWM
#define IMC_ENABLE_OVER_WRITE 0x01
#endif
#include <console/console.h>
#include "AmdSbLib.h"
#include "Amd.h"

View File

@ -112,6 +112,7 @@ void sb800_cimx_config(AMDSBCFG *sb_config)
sb_config->BuildParameters.PCIBSsid = PCIB_SSID;
sb_config->BuildParameters.SpreadSpectrumType = Spread_Spectrum_Type;
sb_config->BuildParameters.HpetBase = HPET_BASE_ADDRESS;
sb_config->BuildParameters.ImcEnableOverWrite = IMC_ENABLE_OVER_WRITE;
/* General */
sb_config->SpreadSpectrum = SPREAD_SPECTRUM;

View File

@ -19,6 +19,7 @@
#ifndef _CIMX_SB800_CHIP_H_
#define _CIMX_SB800_CHIP_H_
#include "fan.h" /* include for #defines used in devicetree.cb */
/*
* configuration set in mainboard/devicetree.cb
@ -35,6 +36,201 @@ struct southbridge_amd_cimx_sb800_config
{
u32 boot_switch_sata_ide : 1;
u8 gpp_configuration;
};
/*
* SB800 IMC and fan control
*/
u16 imc_port_address;
u32 fan0_enabled : 1;
u32 fan1_enabled : 1;
u32 fan2_enabled : 1;
u32 fan3_enabled : 1;
u32 fan4_enabled : 1;
u32 imc_fan_zone0_enabled : 1;
u32 imc_fan_zone1_enabled : 1;
u32 imc_fan_zone2_enabled : 1;
u32 imc_fan_zone3_enabled : 1;
u32 imc_tempin0_enabled : 1;
u32 imc_tempin1_enabled : 1;
u32 imc_tempin2_enabled : 1;
u32 imc_tempin3_enabled : 1;
union {
struct {
u8 fan0_control_reg_value;
u8 fan0_frequency_reg_value;
u8 fan0_low_duty_reg_value;
u8 fan0_med_duty_reg_value;
u8 fan0_multiplier_reg_value;
u8 fan0_low_temp_lo_reg_value;
u8 fan0_low_temp_hi_reg_value;
u8 fan0_med_temp_lo_reg_value;
u8 fan0_med_temp_hi_reg_value;
u8 fan0_high_temp_lo_reg_value;
u8 fan0_high_temp_hi_reg_value;
u8 fan0_linear_range_reg_value;
u8 fan0_linear_hold_reg_value;
};
u8 fan0_config_vals[FAN_REGISTER_COUNT];
};
union {
struct {
u8 fan1_control_reg_value;
u8 fan1_frequency_reg_value;
u8 fan1_low_duty_reg_value;
u8 fan1_med_duty_reg_value;
u8 fan1_multiplier_reg_value;
u8 fan1_low_temp_lo_reg_value;
u8 fan1_low_temp_hi_reg_value;
u8 fan1_med_temp_lo_reg_value;
u8 fan1_med_temp_hi_reg_value;
u8 fan1_high_temp_lo_reg_value;
u8 fan1_high_temp_hi_reg_value;
u8 fan1_linear_range_reg_value;
u8 fan1_linear_hold_reg_value;
};
u8 fan1_config_vals[FAN_REGISTER_COUNT];
};
union {
struct {
u8 fan2_control_reg_value;
u8 fan2_frequency_reg_value;
u8 fan2_low_duty_reg_value;
u8 fan2_med_duty_reg_value;
u8 fan2_multiplier_reg_value;
u8 fan2_low_temp_lo_reg_value;
u8 fan2_low_temp_hi_reg_value;
u8 fan2_med_temp_lo_reg_value;
u8 fan2_med_temp_hi_reg_value;
u8 fan2_high_temp_lo_reg_value;
u8 fan2_high_temp_hi_reg_value;
u8 fan2_linear_range_reg_value;
u8 fan2_linear_hold_reg_value;
};
u8 fan2_config_vals[FAN_REGISTER_COUNT];
};
union {
struct {
u8 fan3_control_reg_value;
u8 fan3_frequency_reg_value;
u8 fan3_low_duty_reg_value;
u8 fan3_med_duty_reg_value;
u8 fan3_multiplier_reg_value;
u8 fan3_low_temp_lo_reg_value;
u8 fan3_low_temp_hi_reg_value;
u8 fan3_med_temp_lo_reg_value;
u8 fan3_med_temp_hi_reg_value;
u8 fan3_high_temp_lo_reg_value;
u8 fan3_high_temp_hi_reg_value;
u8 fan3_linear_range_reg_value;
u8 fan3_linear_hold_reg_value;
};
u8 fan3_config_vals[FAN_REGISTER_COUNT];
};
union {
struct {
u8 fan4_control_reg_value;
u8 fan4_frequency_reg_value;
u8 fan4_low_duty_reg_value;
u8 fan4_med_duty_reg_value;
u8 fan4_multiplier_reg_value;
u8 fan4_low_temp_lo_reg_value;
u8 fan4_low_temp_hi_reg_value;
u8 fan4_med_temp_lo_reg_value;
u8 fan4_med_temp_hi_reg_value;
u8 fan4_high_temp_lo_reg_value;
u8 fan4_high_temp_hi_reg_value;
u8 fan4_linear_range_reg_value;
u8 fan4_linear_hold_reg_value;
};
u8 fan4_config_vals[FAN_REGISTER_COUNT];
};
union {
struct {
u8 imc_zone0_mode1;
u8 imc_zone0_mode2;
u8 imc_zone0_temp_offset;
u8 imc_zone0_hysteresis;
u8 imc_zone0_smbus_addr;
u8 imc_zone0_smbus_num;
u8 imc_zone0_pwm_step;
u8 imc_zone0_ramping;
};
u8 imc_zone0_config_vals[IMC_FAN_CONFIG_COUNT];
};
u8 imc_zone0_thresholds[IMC_FAN_THRESHOLD_COUNT];
u8 imc_zone0_fanspeeds[IMC_FAN_SPEED_COUNT];
union {
struct {
u8 imc_zone1_mode1;
u8 imc_zone1_mode2;
u8 imc_zone1_temp_offset;
u8 imc_zone1_hysteresis;
u8 imc_zone1_smbus_addr;
u8 imc_zone1_smbus_num;
u8 imc_zone1_pwm_step;
u8 imc_zone1_ramping;
};
u8 imc_zone1_config_vals[IMC_FAN_CONFIG_COUNT];
};
u8 imc_zone1_thresholds[IMC_FAN_THRESHOLD_COUNT];
u8 imc_zone1_fanspeeds[IMC_FAN_SPEED_COUNT];
union {
struct {
u8 imc_zone2_mode1;
u8 imc_zone2_mode2;
u8 imc_zone2_temp_offset;
u8 imc_zone2_hysteresis;
u8 imc_zone2_smbus_addr;
u8 imc_zone2_smbus_num;
u8 imc_zone2_pwm_step;
u8 imc_zone2_ramping;
};
u8 imc_zone2_config_vals[IMC_FAN_CONFIG_COUNT];
};
u8 imc_zone2_thresholds[IMC_FAN_THRESHOLD_COUNT];
u8 imc_zone2_fanspeeds[IMC_FAN_SPEED_COUNT];
union {
struct {
u8 imc_zone3_mode1;
u8 imc_zone3_mode2;
u8 imc_zone3_temp_offset;
u8 imc_zone3_hysteresis;
u8 imc_zone3_smbus_addr;
u8 imc_zone3_smbus_num;
u8 imc_zone3_pwm_step;
u8 imc_zone3_ramping;
};
u8 imc_zone3_config_vals[IMC_FAN_CONFIG_COUNT];
};
u8 imc_zone3_thresholds[IMC_FAN_THRESHOLD_COUNT];
u8 imc_zone3_fanspeeds[IMC_FAN_SPEED_COUNT];
u32 imc_tempin0_at;
u32 imc_tempin0_ct;
u8 imc_tempin0_tuning_param;
u32 imc_tempin1_at;
u32 imc_tempin1_ct;
u8 imc_tempin1_tuning_param;
u32 imc_tempin2_at;
u32 imc_tempin2_ct;
u8 imc_tempin2_tuning_param;
u32 imc_tempin3_at;
u32 imc_tempin3_ct;
u8 imc_tempin3_tuning_param;
};
#endif /* _CIMX_SB800_CHIP_H_ */

View File

@ -0,0 +1,311 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2012 Sage Electronic Engineering, LLC
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <southbridge/amd/cimx/cimx_util.h>
#include <device/device.h> /* device_t */
#include <device/pci.h> /* device_operations */
#include "SBPLATFORM.h"
#include "sb_cimx.h"
#include "chip.h" /* struct southbridge_amd_cimx_sb800_config */
#include "fan.h"
void init_sb800_MANUAL_fans(device_t dev)
{
int i;
struct southbridge_amd_cimx_sb800_config *sb_chip =
(struct southbridge_amd_cimx_sb800_config *)(dev->chip_info);
/* Init Fan 0 */
if (sb_chip->fan0_enabled)
for (i = 0; i < FAN_REGISTER_COUNT; i++)
pm2_iowrite(FAN_0_OFFSET + i, sb_chip->fan0_config_vals[i]);
/* Init Fan 1 */
if (sb_chip->fan1_enabled)
for (i = 0; i < FAN_REGISTER_COUNT; i++)
pm2_iowrite(FAN_1_OFFSET + i, sb_chip->fan1_config_vals[i]);
/* Init Fan 2 */
if (sb_chip->fan2_enabled)
for (i = 0; i < FAN_REGISTER_COUNT; i++)
pm2_iowrite(FAN_2_OFFSET + i, sb_chip->fan2_config_vals[i]);
/* Init Fan 3 */
if (sb_chip->fan3_enabled)
for (i = 0; i < FAN_REGISTER_COUNT; i++)
pm2_iowrite(FAN_3_OFFSET + i, sb_chip->fan3_config_vals[i]);
/* Init Fan 4 */
if (sb_chip->fan4_enabled)
for (i = 0; i < FAN_REGISTER_COUNT; i++)
pm2_iowrite(FAN_4_OFFSET + i, sb_chip->fan4_config_vals[i]);
}
void init_sb800_IMC_fans(device_t dev)
{
AMDSBCFG sb_config;
unsigned char *message_ptr;
int i;
struct southbridge_amd_cimx_sb800_config *sb_chip =
(struct southbridge_amd_cimx_sb800_config *)(dev->chip_info);
/*
* The default I/O address of the IMC configuration register index
* port is 0x6E. Change the IMC Config port I/O Address if it
* conflicts with other components in the system.
*
* Device 20, Function 3, Reg 0xA4
* [0]: if 1, the address specified in IMC_PortAddress is used.
* [15:1] IMC_PortAddress bits 15:1 (0x17 - address 0x2E )
*/
pci_write_config16(dev, 0xA4, sb_chip->imc_port_address | 0x01);
/*
* Do an initial manual setup of the fans for things like polarity
* and frequency.
*/
init_sb800_MANUAL_fans(dev);
/*
* FLAG for Func 81/83/85/89 support (1=On,0=Off)
* Bit0-3 = Func 81 Zone0-Zone3
* Bit4-7 = Func 83 Zone0-Zone3
* Bit8-11 = Func 85 Zone0-Zone3
* Bit12-15 = Func 89 Tempin Channel0-Channel3
*/
sb_config.Pecstruct.IMCFUNSupportBitMap = 0;
/*
********** Zone 0 **********
*/
if (sb_chip->imc_fan_zone0_enabled) {
sb_config.Pecstruct.IMCFUNSupportBitMap |= IMC_ENABLE_ZONE0;
/* EC LDN9 function 81 zone 0 */
sb_config.Pecstruct.MSGFun81zone0MSGREG0 = 0x00;
sb_config.Pecstruct.MSGFun81zone0MSGREG1 = IMC_ZONE0;
message_ptr = &sb_config.Pecstruct.MSGFun81zone0MSGREG2;
for (i = 0; i < IMC_FAN_CONFIG_COUNT ; i++ )
*(message_ptr + i) = sb_chip->imc_zone0_config_vals[i];
/* EC LDN9 function 83 zone 0 - Temperature Thresholds */
sb_config.Pecstruct.MSGFun83zone0MSGREG0 = 0x00;
sb_config.Pecstruct.MSGFun83zone0MSGREG1 = IMC_ZONE0;
sb_config.Pecstruct.MSGFun83zone0MSGREGB = 0x00;
message_ptr = &sb_config.Pecstruct.MSGFun83zone0MSGREG2;
for (i = 0; i < IMC_FAN_THRESHOLD_COUNT ; i++ )
*(message_ptr + i) = sb_chip->imc_zone0_thresholds[i];
/*EC LDN9 function 85 zone 0 - Fan Speeds */
sb_config.Pecstruct.MSGFun85zone0MSGREG0 = 0x00;
sb_config.Pecstruct.MSGFun85zone0MSGREG1 = IMC_ZONE0;
message_ptr = &sb_config.Pecstruct.MSGFun85zone0MSGREG2;
for (i = 0; i < IMC_FAN_SPEED_COUNT ; i++ )
*(message_ptr + i) = sb_chip->imc_zone0_fanspeeds[i];
}
/*
********** Zone 1 **********
*/
if (sb_chip->imc_fan_zone1_enabled) {
sb_config.Pecstruct.IMCFUNSupportBitMap |= IMC_ENABLE_ZONE1;
/* EC LDN9 function 81 zone 1 */
sb_config.Pecstruct.MSGFun81zone1MSGREG0 = 0x00;
sb_config.Pecstruct.MSGFun81zone1MSGREG1 = IMC_ZONE1;
message_ptr = &sb_config.Pecstruct.MSGFun81zone1MSGREG2;
for (i = 0; i < IMC_FAN_CONFIG_COUNT ; i++ )
*(message_ptr + i) = sb_chip->imc_zone1_config_vals[i];
/* EC LDN9 function 83 zone 1 - Temperature Thresholds */
sb_config.Pecstruct.MSGFun83zone1MSGREG0 = 0x00;
sb_config.Pecstruct.MSGFun83zone1MSGREG1 = IMC_ZONE1;
sb_config.Pecstruct.MSGFun83zone1MSGREGB = 0x00;
message_ptr = &sb_config.Pecstruct.MSGFun83zone1MSGREG2;
for (i = 0; i < IMC_FAN_THRESHOLD_COUNT ; i++ )
*(message_ptr + i) = sb_chip->imc_zone1_thresholds[i];
/* EC LDN9 function 85 zone 1 - Fan Speeds */
sb_config.Pecstruct.MSGFun85zone1MSGREG0 = 0x00;
sb_config.Pecstruct.MSGFun85zone1MSGREG1 = IMC_ZONE1;
message_ptr = &sb_config.Pecstruct.MSGFun85zone1MSGREG2;
for (i = 0; i < IMC_FAN_SPEED_COUNT ; i++ )
*(message_ptr + i) = sb_chip->imc_zone1_fanspeeds[i];
}
/*
********** Zone 2 **********
*/
if (sb_chip->imc_fan_zone2_enabled) {
sb_config.Pecstruct.IMCFUNSupportBitMap |= IMC_ENABLE_ZONE2;
/* EC LDN9 function 81 zone 2 */
sb_config.Pecstruct.MSGFun81zone2MSGREG0 = 0x00;
sb_config.Pecstruct.MSGFun81zone2MSGREG1 = IMC_ZONE2;
message_ptr = &sb_config.Pecstruct.MSGFun81zone2MSGREG2;
for (i = 0; i < IMC_FAN_CONFIG_COUNT ; i++ )
*(message_ptr + i) = sb_chip->imc_zone2_config_vals[i];
/* EC LDN9 function 83 zone 2 */
sb_config.Pecstruct.MSGFun83zone2MSGREG0 = 0x00;
sb_config.Pecstruct.MSGFun83zone2MSGREG1 = IMC_ZONE2;
sb_config.Pecstruct.MSGFun83zone2MSGREGB = 0x00;
message_ptr = &sb_config.Pecstruct.MSGFun83zone2MSGREG2;
for (i = 0; i < IMC_FAN_THRESHOLD_COUNT ; i++ )
*(message_ptr + i) = sb_chip->imc_zone2_thresholds[i];
/* EC LDN9 function 85 zone 2 */
sb_config.Pecstruct.MSGFun85zone2MSGREG0 = 0x00;
sb_config.Pecstruct.MSGFun85zone2MSGREG1 = IMC_ZONE2;
message_ptr = &sb_config.Pecstruct.MSGFun85zone2MSGREG2;
for (i = 0; i < IMC_FAN_SPEED_COUNT ; i++ )
*(message_ptr + i) = sb_chip->imc_zone2_fanspeeds[i];
}
/*
********** Zone 3 **********
*/
if (sb_chip->imc_fan_zone3_enabled) {
sb_config.Pecstruct.IMCFUNSupportBitMap |= IMC_ENABLE_ZONE3;
/* EC LDN9 function 81 zone 3 */
sb_config.Pecstruct.MSGFun81zone3MSGREG0 = 0x00;
sb_config.Pecstruct.MSGFun81zone3MSGREG1 = IMC_ZONE3;
message_ptr = &sb_config.Pecstruct.MSGFun81zone3MSGREG2;
for (i = 0; i < IMC_FAN_CONFIG_COUNT ; i++ )
*(message_ptr + i) = sb_chip->imc_zone3_config_vals[i];
/* EC LDN9 function 83 zone 3 */
sb_config.Pecstruct.MSGFun83zone3MSGREG0 = 0x00;
sb_config.Pecstruct.MSGFun83zone3MSGREG1 = IMC_ZONE3;
sb_config.Pecstruct.MSGFun83zone3MSGREGB = 0x00;
message_ptr = &sb_config.Pecstruct.MSGFun83zone3MSGREG2;
for (i = 0; i < IMC_FAN_THRESHOLD_COUNT ; i++ )
*(message_ptr + i) = sb_chip->imc_zone3_thresholds[i];
/* EC LDN9 function 85 zone 3 */
sb_config.Pecstruct.MSGFun85zone3MSGREG0 = 0x00;
sb_config.Pecstruct.MSGFun85zone3MSGREG1 = IMC_ZONE3;
message_ptr = &sb_config.Pecstruct.MSGFun85zone3MSGREG2;
for (i = 0; i < IMC_FAN_SPEED_COUNT ; i++ )
*(message_ptr + i) = sb_chip->imc_zone3_fanspeeds[i];
}
/*
* EC LDN9 funtion 89 - Set HWM TEMPIN Temperature Calculation Parameters
* This function provides the critical parameters of the HWM TempIn
* sensors, IMC would not perform temperature measurement using those
* sensors until the parameters are provided.
*/
if (sb_chip->imc_tempin0_enabled) {
sb_config.Pecstruct.IMCFUNSupportBitMap |= IMC_ENABLE_TEMPIN0;
/* EC LDN9 funtion 89 TEMPIN channel 0 */
sb_config.Pecstruct.MSGFun89zone0MSGREG0 = 0x00;
sb_config.Pecstruct.MSGFun89zone0MSGREG1 = 0x00;
sb_config.Pecstruct.MSGFun89zone0MSGREG2 = ( sb_chip->imc_tempin0_at & 0xff);
sb_config.Pecstruct.MSGFun89zone0MSGREG3 = ((sb_chip->imc_tempin0_at >> 8) & 0xff);
sb_config.Pecstruct.MSGFun89zone0MSGREG4 = ((sb_chip->imc_tempin0_at >> 16) & 0xff);
sb_config.Pecstruct.MSGFun89zone0MSGREG5 = ((sb_chip->imc_tempin0_at >> 24) & 0xff);
sb_config.Pecstruct.MSGFun89zone0MSGREG6 = ( sb_chip->imc_tempin0_ct & 0xff);
sb_config.Pecstruct.MSGFun89zone0MSGREG7 = ((sb_chip->imc_tempin0_ct >> 8) & 0xff);
sb_config.Pecstruct.MSGFun89zone0MSGREG8 = ((sb_chip->imc_tempin0_ct >> 16) & 0xff);
sb_config.Pecstruct.MSGFun89zone0MSGREG9 = ((sb_chip->imc_tempin0_ct >> 24) & 0xff);
sb_config.Pecstruct.MSGFun89zone0MSGREGA = sb_chip->imc_tempin0_tuning_param;
}
if (sb_chip->imc_tempin1_enabled) {
sb_config.Pecstruct.IMCFUNSupportBitMap |= IMC_ENABLE_TEMPIN1;
/* EC LDN9 funtion 89 TEMPIN channel 1 */
sb_config.Pecstruct.MSGFun89zone1MSGREG0 = 0x00;
sb_config.Pecstruct.MSGFun89zone1MSGREG1 = 0x01;
sb_config.Pecstruct.MSGFun89zone1MSGREG2 = ( sb_chip->imc_tempin1_at & 0xff);
sb_config.Pecstruct.MSGFun89zone1MSGREG3 = ((sb_chip->imc_tempin1_at >> 8) & 0xff);
sb_config.Pecstruct.MSGFun89zone1MSGREG4 = ((sb_chip->imc_tempin1_at >> 16) & 0xff);
sb_config.Pecstruct.MSGFun89zone1MSGREG5 = ((sb_chip->imc_tempin1_at >> 24) & 0xff);
sb_config.Pecstruct.MSGFun89zone1MSGREG6 = ( sb_chip->imc_tempin1_ct & 0xff);
sb_config.Pecstruct.MSGFun89zone1MSGREG7 = ((sb_chip->imc_tempin1_ct >> 8) & 0xff);
sb_config.Pecstruct.MSGFun89zone1MSGREG8 = ((sb_chip->imc_tempin1_ct >> 16) & 0xff);
sb_config.Pecstruct.MSGFun89zone1MSGREG9 = ((sb_chip->imc_tempin1_ct >> 24) & 0xff);
sb_config.Pecstruct.MSGFun89zone1MSGREGA = sb_chip->imc_tempin1_tuning_param;
}
if (sb_chip->imc_tempin2_enabled) {
sb_config.Pecstruct.IMCFUNSupportBitMap |= IMC_ENABLE_TEMPIN2;
/* EC LDN9 funtion 89 TEMPIN channel 2 */
sb_config.Pecstruct.MSGFun89zone2MSGREG0 = 0x00;
sb_config.Pecstruct.MSGFun89zone2MSGREG1 = 0x02;
sb_config.Pecstruct.MSGFun89zone2MSGREG2 = ( sb_chip->imc_tempin2_at & 0xff);
sb_config.Pecstruct.MSGFun89zone2MSGREG3 = ((sb_chip->imc_tempin2_at >> 8) & 0xff);
sb_config.Pecstruct.MSGFun89zone2MSGREG4 = ((sb_chip->imc_tempin2_at >> 16) & 0xff);
sb_config.Pecstruct.MSGFun89zone2MSGREG5 = ((sb_chip->imc_tempin2_at >> 24) & 0xff);
sb_config.Pecstruct.MSGFun89zone2MSGREG6 = ( sb_chip->imc_tempin2_ct & 0xff);
sb_config.Pecstruct.MSGFun89zone2MSGREG7 = ((sb_chip->imc_tempin2_ct >> 8) & 0xff);
sb_config.Pecstruct.MSGFun89zone2MSGREG8 = ((sb_chip->imc_tempin2_ct >> 16) & 0xff);
sb_config.Pecstruct.MSGFun89zone2MSGREG9 = ((sb_chip->imc_tempin2_ct >> 24) & 0xff);
sb_config.Pecstruct.MSGFun89zone2MSGREGA = sb_chip->imc_tempin2_tuning_param;
}
if (sb_chip->imc_tempin3_enabled) {
sb_config.Pecstruct.IMCFUNSupportBitMap |= IMC_ENABLE_TEMPIN3;
/* EC LDN9 funtion 89 TEMPIN channel 3 */
sb_config.Pecstruct.MSGFun89zone3MSGREG0 = 0x00;
sb_config.Pecstruct.MSGFun89zone3MSGREG1 = 0x03;
sb_config.Pecstruct.MSGFun89zone3MSGREG2 = ( sb_chip->imc_tempin3_at & 0xff);
sb_config.Pecstruct.MSGFun89zone3MSGREG3 = ((sb_chip->imc_tempin3_at >> 8) & 0xff);
sb_config.Pecstruct.MSGFun89zone3MSGREG4 = ((sb_chip->imc_tempin3_at >> 16) & 0xff);
sb_config.Pecstruct.MSGFun89zone3MSGREG5 = ((sb_chip->imc_tempin3_at >> 24) & 0xff);
sb_config.Pecstruct.MSGFun89zone3MSGREG6 = ( sb_chip->imc_tempin3_ct & 0xff);
sb_config.Pecstruct.MSGFun89zone3MSGREG7 = ((sb_chip->imc_tempin3_ct >> 8) & 0xff);
sb_config.Pecstruct.MSGFun89zone3MSGREG8 = ((sb_chip->imc_tempin3_ct >> 16) & 0xff);
sb_config.Pecstruct.MSGFun89zone3MSGREG9 = ((sb_chip->imc_tempin3_ct >> 24) & 0xff);
sb_config.Pecstruct.MSGFun89zone3MSGREGA = sb_chip->imc_tempin3_tuning_param;
}
/* Set up the sb_config structure for the fan control initialization */
sb_config.StdHeader.Func = SB_EC_FANCONTROL;
AmdSbDispatcher(&sb_config);
return;
}

View File

@ -0,0 +1,152 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2012 Sage Electronic Engineering, LLC
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _SB800_FAN_H_
#define _SB800_FAN_H_
#ifndef __PRE_RAM__
void init_sb800_IMC_fans(device_t dev);
void init_sb800_MANUAL_fans(device_t dev);
#endif
/* Fan Register Definitions */
#define FAN_0_OFFSET 0x00
#define FAN_1_OFFSET 0x10
#define FAN_2_OFFSET 0x20
#define FAN_3_OFFSET 0x30
#define FAN_4_OFFSET 0x40
#define FAN_INPUT_CONTROL_REG 0x00
#define FAN_CONTROL_REG 0x01
#define FAN_FREQUENCY_REG 0x02
#define FAN_LOW_DUTY_REG 0x03
#define FAN_MED_DUTY_REG 0x04
#define FAN_MULTIPLIER_REG 0x05
#define FAN_LOW_TEMP_LO_REG 0x06
#define FAN_LOW_TEMP_HI_REG 0x07
#define FAN_MED_TEMP_LO_REG 0x08
#define FAN_MED_TEMP_HI_REG 0x09
#define FAN_HIGH_TEMP_LO_REG 0x0A
#define FAN_HIGH_TEMP_HI_REG 0x0B
#define FAN_LINEAR_RANGE_REG 0x0C
#define FAN_LINEAR_HOLD_REG 0x0D
/* FanXInputControl Definitions */
#define FAN_INPUT_INTERNAL_DIODE 0
#define FAN_INPUT_TEMP0 1
#define FAN_INPUT_TEMP1 2
#define FAN_INPUT_TEMP2 3
#define FAN_INPUT_TEMP3 4
#define FAN_INPUT_TEMP0_FILTER 5
#define FAN_INPUT_ZERO 6
#define FAN_INPUT_DISABLED 7
/* FanXControl Definitions */
#define FAN_AUTOMODE (1 << 0)
#define FAN_LINEARMODE (1 << 1)
#define FAN_STEPMODE 0 /* ~(1 << 1) */
#define FAN_POLARITY_HIGH (1 << 2)
#define FAN_POLARITY_LOW 0 /*~(1 << 2) */
/* FanXLowDuty Definitions */
#define FAN_POLARITY_HIGH_MAX_SPEED 0xff
#define FAN_POLARITY_LOW_MAX_SPEED 0x00
/* FanXFreq Definitions */
/* Typically, fans run at 25KHz */
#define FREQ_28KHZ 0x0
#define FREQ_25KHZ 0x1
#define FREQ_23KHZ 0x2
#define FREQ_21KHZ 0x3
#define FREQ_29KHZ 0x4
#define FREQ_18KHZ 0x5
/* Any value > 05h and < F7: Freq = 1/(FreqDiv * 2048 * 15ns) */
#define FREQ_100HZ 0xF7
#define FREQ_87HZ 0xF8
#define FREQ_58HZ 0xF9
#define FREQ_44HZ 0xFA
#define FREQ_35HZ 0xFB
#define FREQ_29HZ 0xFC
#define FREQ_22HZ 0xFD
#define FREQ_14HZ 0xFE
#define FREQ_11HZ 0xFF
/* IMC Fan Control Definitions */
#define IMC_MODE1_FAN_ENABLED ( 1 << 0 )
#define IMC_MODE1_FAN_IMC_CONTROLLED ( 1 << 2 )
#define IMC_MODE1_FAN_LINEAR_MODE ( 1 << 4 )
#define IMC_MODE1_FAN_STEP_MODE 0 /* ~( 1 << 4 ) */
#define IMC_MODE1_NO_FANOUT 0 /* ~( 7 << 5 ) */
#define IMC_MODE1_FANOUT0 ( 1 << 5 )
#define IMC_MODE1_FANOUT1 ( 2 << 5 )
#define IMC_MODE1_FANOUT2 ( 3 << 5 )
#define IMC_MODE1_FANOUT3 ( 4 << 5 )
#define IMC_MODE1_FANOUT4 ( 5 << 5 )
#define IMC_MODE2_TEMPIN_NONE 0 /* ~( 7 << 0) */
#define IMC_MODE2_TEMPIN_0 1
#define IMC_MODE2_TEMPIN_1 2
#define IMC_MODE2_TEMPIN_2 3
#define IMC_MODE2_TEMPIN_3 4
#define IMC_MODE2_INT_TEMPIN 5
#define IMC_MODE2_TEMPIN_SB_TSI 6
#define IMC_MODE2_TEMPIN_OTHER 7
#define IMC_MODE2_FANIN_NONE 0 /* ~ (7 << 3) */
#define IMC_MODE2_FANIN0 ( 1 << 3 )
#define IMC_MODE2_FANIN1 ( 2 << 3 )
#define IMC_MODE2_FANIN2 ( 3 << 3 )
#define IMC_MODE2_FANIN3 ( 4 << 3 )
#define IMC_MODE2_FANIN4 ( 5 << 3 )
#define IMC_MODE2_TEMP_AVERAGING_ENABLED ( 1 << 6 )
#define IMC_MODE2_TEMP_AVERAGING_DISABLED 0 /* ~( 1 << 6 ) */
#define IMC_TEMP_SENSOR_ON_SMBUS_0 0
#define IMC_TEMP_SENSOR_ON_SMBUS_2 1
#define IMC_TEMP_SENSOR_ON_SMBUS_3 2
#define IMC_TEMP_SENSOR_ON_SMBUS_4 3
#define IMC_ZONE0 0
#define IMC_ZONE1 1
#define IMC_ZONE2 2
#define IMC_ZONE3 3
#define IMC_ZONE4 4
#define IMC_TEMPIN_TUNING_DEFAULT_MODE 0
#define IMC_TEMPIN_TUNING_HIGH_CURRENT_RATIO 1
#define IMC_TEMPIN_TUNING_HIGH_CURRENT 2
#define IMC_TEMPIN_TUNING_DISABLE_FILTERING ( 1 << 2 )
/* IMCFUNSupportBitMap - Zone enable values */
#define IMC_ENABLE_ZONE0 0x111
#define IMC_ENABLE_ZONE1 0x222
#define IMC_ENABLE_ZONE2 0x333
#define IMC_ENABLE_ZONE3 0x444
#define IMC_ENABLE_TEMPIN0 ( 1 << 12 )
#define IMC_ENABLE_TEMPIN1 ( 1 << 13 )
#define IMC_ENABLE_TEMPIN2 ( 1 << 14 )
#define IMC_ENABLE_TEMPIN3 ( 1 << 15 )
/* Array size settings */
#define IMC_FAN_THRESHOLD_COUNT 9
#define IMC_FAN_SPEED_COUNT 8
#define IMC_FAN_CONFIG_COUNT 8
#define FAN_REGISTER_COUNT 15
#endif

View File

@ -32,6 +32,7 @@
#include "chip.h" /* struct southbridge_amd_cimx_sb800_config */
#include "sb_cimx.h" /* AMD CIMX wrapper entries */
#include "smbus.h"
#include "fan.h"
/*implement in mainboard.c*/
void set_pcie_reset(void);
@ -418,6 +419,12 @@ static void sb800_enable(device_t dev)
case (0x14 << 3) | 3: /* 0:14:3 LPC */
/* Initialize the fans */
#if CONFIG_SB800_IMC_FAN_CONTROL
init_sb800_IMC_fans(dev);
#elif CONFIG_SB800_MANUAL_FAN_CONTROL
init_sb800_MANUAL_fans(dev);
#endif
break;
case (0x14 << 3) | 4: /* 0:14:4 PCI */

View File

@ -293,3 +293,13 @@
#ifndef Spread_Spectrum_Type
#define Spread_Spectrum_Type 0x00
#endif
/**
* Imc Enable OverWrite
* 2 - by default strapping
* 1 - On
* 0 - Off
*/
#ifndef IMC_ENABLE_OVER_WRITE
#define IMC_ENABLE_OVER_WRITE 0x02
#endif