coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
fan.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <amdblocks/acpimmio.h>
4 #include <device/device.h>
5 #include <device/pci.h> /* device_operations */
6 #include <device/pci_ops.h>
7 #include "SBPLATFORM.h"
8 #include "sb_cimx.h"
9 #include "chip.h" /* struct southbridge_amd_cimx_sb800_config */
10 #include "fan.h"
11 
12 void init_sb800_MANUAL_fans(struct device *dev)
13 {
14  int i;
15  struct southbridge_amd_cimx_sb800_config *sb_chip =
17 
18  /* Init Fan 0 */
19  if (sb_chip->fan0_enabled)
20  for (i = 0; i < FAN_REGISTER_COUNT; i++)
21  pm2_write8(FAN_0_OFFSET + i, sb_chip->fan0_config_vals[i]);
22 
23  /* Init Fan 1 */
24  if (sb_chip->fan1_enabled)
25  for (i = 0; i < FAN_REGISTER_COUNT; i++)
26  pm2_write8(FAN_1_OFFSET + i, sb_chip->fan1_config_vals[i]);
27 
28  /* Init Fan 2 */
29  if (sb_chip->fan2_enabled)
30  for (i = 0; i < FAN_REGISTER_COUNT; i++)
31  pm2_write8(FAN_2_OFFSET + i, sb_chip->fan2_config_vals[i]);
32 
33  /* Init Fan 3 */
34  if (sb_chip->fan3_enabled)
35  for (i = 0; i < FAN_REGISTER_COUNT; i++)
36  pm2_write8(FAN_3_OFFSET + i, sb_chip->fan3_config_vals[i]);
37 
38  /* Init Fan 4 */
39  if (sb_chip->fan4_enabled)
40  for (i = 0; i < FAN_REGISTER_COUNT; i++)
41  pm2_write8(FAN_4_OFFSET + i, sb_chip->fan4_config_vals[i]);
42 }
43 
44 void init_sb800_IMC_fans(struct device *dev)
45 {
46  AMDSBCFG sb_config;
47  unsigned char *message_ptr;
48  int i;
49  struct southbridge_amd_cimx_sb800_config *sb_chip =
51 
52  /*
53  * The default I/O address of the IMC configuration register index
54  * port is 0x6E. Change the IMC Config port I/O Address if it
55  * conflicts with other components in the system.
56  *
57  * Device 20, Function 3, Reg 0xA4
58  * [0]: if 1, the address specified in IMC_PortAddress is used.
59  * [15:1] IMC_PortAddress bits 15:1 (0x17 - address 0x2E)
60  */
61 
62  pci_write_config16(dev, 0xA4, sb_chip->imc_port_address | 0x01);
63 
64  /*
65  * Do an initial manual setup of the fans for things like polarity
66  * and frequency.
67  */
69 
70  /*
71  * FLAG for Func 81/83/85/89 support (1=On,0=Off)
72  * Bit0-3 = Func 81 Zone0-Zone3
73  * Bit4-7 = Func 83 Zone0-Zone3
74  * Bit8-11 = Func 85 Zone0-Zone3
75  * Bit12-15 = Func 89 Tempin Channel0-Channel3
76  */
77  sb_config.Pecstruct.IMCFUNSupportBitMap = 0;
78 
79 /*
80  ********** Zone 0 **********
81  */
82 if (sb_chip->imc_fan_zone0_enabled) {
83 
84  sb_config.Pecstruct.IMCFUNSupportBitMap |= IMC_ENABLE_ZONE0;
85 
86  /* EC LDN9 function 81 zone 0 */
87  sb_config.Pecstruct.MSGFun81zone0MSGREG0 = 0x00;
88  sb_config.Pecstruct.MSGFun81zone0MSGREG1 = IMC_ZONE0;
89  message_ptr = &sb_config.Pecstruct.MSGFun81zone0MSGREG2;
90  for (i = 0; i < IMC_FAN_CONFIG_COUNT; i++)
91  *(message_ptr + i) = sb_chip->imc_zone0_config_vals[i];
92 
93  /* EC LDN9 function 83 zone 0 - Temperature Thresholds */
94  sb_config.Pecstruct.MSGFun83zone0MSGREG0 = 0x00;
95  sb_config.Pecstruct.MSGFun83zone0MSGREG1 = IMC_ZONE0;
96  sb_config.Pecstruct.MSGFun83zone0MSGREGB = 0x00;
97  message_ptr = &sb_config.Pecstruct.MSGFun83zone0MSGREG2;
98  for (i = 0; i < IMC_FAN_THRESHOLD_COUNT; i++)
99  *(message_ptr + i) = sb_chip->imc_zone0_thresholds[i];
100 
101  /*EC LDN9 function 85 zone 0 - Fan Speeds */
102  sb_config.Pecstruct.MSGFun85zone0MSGREG0 = 0x00;
103  sb_config.Pecstruct.MSGFun85zone0MSGREG1 = IMC_ZONE0;
104  message_ptr = &sb_config.Pecstruct.MSGFun85zone0MSGREG2;
105  for (i = 0; i < IMC_FAN_SPEED_COUNT; i++)
106  *(message_ptr + i) = sb_chip->imc_zone0_fanspeeds[i];
107 }
108 
109 /*
110  ********** Zone 1 **********
111  */
112 if (sb_chip->imc_fan_zone1_enabled) {
113 
114  sb_config.Pecstruct.IMCFUNSupportBitMap |= IMC_ENABLE_ZONE1;
115 
116  /* EC LDN9 function 81 zone 1 */
117  sb_config.Pecstruct.MSGFun81zone1MSGREG0 = 0x00;
118  sb_config.Pecstruct.MSGFun81zone1MSGREG1 = IMC_ZONE1;
119  message_ptr = &sb_config.Pecstruct.MSGFun81zone1MSGREG2;
120  for (i = 0; i < IMC_FAN_CONFIG_COUNT; i++)
121  *(message_ptr + i) = sb_chip->imc_zone1_config_vals[i];
122 
123  /* EC LDN9 function 83 zone 1 - Temperature Thresholds */
124  sb_config.Pecstruct.MSGFun83zone1MSGREG0 = 0x00;
125  sb_config.Pecstruct.MSGFun83zone1MSGREG1 = IMC_ZONE1;
126  sb_config.Pecstruct.MSGFun83zone1MSGREGB = 0x00;
127  message_ptr = &sb_config.Pecstruct.MSGFun83zone1MSGREG2;
128  for (i = 0; i < IMC_FAN_THRESHOLD_COUNT; i++)
129  *(message_ptr + i) = sb_chip->imc_zone1_thresholds[i];
130 
131  /* EC LDN9 function 85 zone 1 - Fan Speeds */
132  sb_config.Pecstruct.MSGFun85zone1MSGREG0 = 0x00;
133  sb_config.Pecstruct.MSGFun85zone1MSGREG1 = IMC_ZONE1;
134  message_ptr = &sb_config.Pecstruct.MSGFun85zone1MSGREG2;
135  for (i = 0; i < IMC_FAN_SPEED_COUNT; i++)
136  *(message_ptr + i) = sb_chip->imc_zone1_fanspeeds[i];
137 }
138 
139 /*
140  ********** Zone 2 **********
141  */
142 if (sb_chip->imc_fan_zone2_enabled) {
143 
144  sb_config.Pecstruct.IMCFUNSupportBitMap |= IMC_ENABLE_ZONE2;
145 
146  /* EC LDN9 function 81 zone 2 */
147  sb_config.Pecstruct.MSGFun81zone2MSGREG0 = 0x00;
148  sb_config.Pecstruct.MSGFun81zone2MSGREG1 = IMC_ZONE2;
149  message_ptr = &sb_config.Pecstruct.MSGFun81zone2MSGREG2;
150  for (i = 0; i < IMC_FAN_CONFIG_COUNT; i++)
151  *(message_ptr + i) = sb_chip->imc_zone2_config_vals[i];
152 
153  /* EC LDN9 function 83 zone 2 */
154  sb_config.Pecstruct.MSGFun83zone2MSGREG0 = 0x00;
155  sb_config.Pecstruct.MSGFun83zone2MSGREG1 = IMC_ZONE2;
156  sb_config.Pecstruct.MSGFun83zone2MSGREGB = 0x00;
157  message_ptr = &sb_config.Pecstruct.MSGFun83zone2MSGREG2;
158  for (i = 0; i < IMC_FAN_THRESHOLD_COUNT; i++)
159  *(message_ptr + i) = sb_chip->imc_zone2_thresholds[i];
160 
161  /* EC LDN9 function 85 zone 2 */
162  sb_config.Pecstruct.MSGFun85zone2MSGREG0 = 0x00;
163  sb_config.Pecstruct.MSGFun85zone2MSGREG1 = IMC_ZONE2;
164  message_ptr = &sb_config.Pecstruct.MSGFun85zone2MSGREG2;
165  for (i = 0; i < IMC_FAN_SPEED_COUNT; i++)
166  *(message_ptr + i) = sb_chip->imc_zone2_fanspeeds[i];
167 }
168 
169 /*
170  ********** Zone 3 **********
171  */
172 
173 if (sb_chip->imc_fan_zone3_enabled) {
174 
175  sb_config.Pecstruct.IMCFUNSupportBitMap |= IMC_ENABLE_ZONE3;
176 
177  /* EC LDN9 function 81 zone 3 */
178  sb_config.Pecstruct.MSGFun81zone3MSGREG0 = 0x00;
179  sb_config.Pecstruct.MSGFun81zone3MSGREG1 = IMC_ZONE3;
180  message_ptr = &sb_config.Pecstruct.MSGFun81zone3MSGREG2;
181  for (i = 0; i < IMC_FAN_CONFIG_COUNT; i++)
182  *(message_ptr + i) = sb_chip->imc_zone3_config_vals[i];
183 
184  /* EC LDN9 function 83 zone 3 */
185  sb_config.Pecstruct.MSGFun83zone3MSGREG0 = 0x00;
186  sb_config.Pecstruct.MSGFun83zone3MSGREG1 = IMC_ZONE3;
187  sb_config.Pecstruct.MSGFun83zone3MSGREGB = 0x00;
188  message_ptr = &sb_config.Pecstruct.MSGFun83zone3MSGREG2;
189  for (i = 0; i < IMC_FAN_THRESHOLD_COUNT; i++)
190  *(message_ptr + i) = sb_chip->imc_zone3_thresholds[i];
191 
192  /* EC LDN9 function 85 zone 3 */
193  sb_config.Pecstruct.MSGFun85zone3MSGREG0 = 0x00;
194  sb_config.Pecstruct.MSGFun85zone3MSGREG1 = IMC_ZONE3;
195  message_ptr = &sb_config.Pecstruct.MSGFun85zone3MSGREG2;
196  for (i = 0; i < IMC_FAN_SPEED_COUNT; i++)
197  *(message_ptr + i) = sb_chip->imc_zone3_fanspeeds[i];
198 }
199 
200  /*
201  * EC LDN9 function 89 - Set HWM TEMPIN Temperature Calculation Parameters
202  * This function provides the critical parameters of the HWM TempIn
203  * sensors, IMC would not perform temperature measurement using those
204  * sensors until the parameters are provided.
205  */
206 
207 if (sb_chip->imc_tempin0_enabled) {
208 
209  sb_config.Pecstruct.IMCFUNSupportBitMap |= IMC_ENABLE_TEMPIN0;
210 
211  /* EC LDN9 function 89 TEMPIN channel 0 */
212  sb_config.Pecstruct.MSGFun89zone0MSGREG0 = 0x00;
213  sb_config.Pecstruct.MSGFun89zone0MSGREG1 = 0x00;
214  sb_config.Pecstruct.MSGFun89zone0MSGREG2 = (sb_chip->imc_tempin0_at & 0xff);
215  sb_config.Pecstruct.MSGFun89zone0MSGREG3 = ((sb_chip->imc_tempin0_at >> 8) & 0xff);
216  sb_config.Pecstruct.MSGFun89zone0MSGREG4 = ((sb_chip->imc_tempin0_at >> 16) & 0xff);
217  sb_config.Pecstruct.MSGFun89zone0MSGREG5 = ((sb_chip->imc_tempin0_at >> 24) & 0xff);
218  sb_config.Pecstruct.MSGFun89zone0MSGREG6 = (sb_chip->imc_tempin0_ct & 0xff);
219  sb_config.Pecstruct.MSGFun89zone0MSGREG7 = ((sb_chip->imc_tempin0_ct >> 8) & 0xff);
220  sb_config.Pecstruct.MSGFun89zone0MSGREG8 = ((sb_chip->imc_tempin0_ct >> 16) & 0xff);
221  sb_config.Pecstruct.MSGFun89zone0MSGREG9 = ((sb_chip->imc_tempin0_ct >> 24) & 0xff);
222  sb_config.Pecstruct.MSGFun89zone0MSGREGA = sb_chip->imc_tempin0_tuning_param;
223 }
224 
225 if (sb_chip->imc_tempin1_enabled) {
226 
227  sb_config.Pecstruct.IMCFUNSupportBitMap |= IMC_ENABLE_TEMPIN1;
228 
229  /* EC LDN9 function 89 TEMPIN channel 1 */
230  sb_config.Pecstruct.MSGFun89zone1MSGREG0 = 0x00;
231  sb_config.Pecstruct.MSGFun89zone1MSGREG1 = 0x01;
232  sb_config.Pecstruct.MSGFun89zone1MSGREG2 = (sb_chip->imc_tempin1_at & 0xff);
233  sb_config.Pecstruct.MSGFun89zone1MSGREG3 = ((sb_chip->imc_tempin1_at >> 8) & 0xff);
234  sb_config.Pecstruct.MSGFun89zone1MSGREG4 = ((sb_chip->imc_tempin1_at >> 16) & 0xff);
235  sb_config.Pecstruct.MSGFun89zone1MSGREG5 = ((sb_chip->imc_tempin1_at >> 24) & 0xff);
236  sb_config.Pecstruct.MSGFun89zone1MSGREG6 = (sb_chip->imc_tempin1_ct & 0xff);
237  sb_config.Pecstruct.MSGFun89zone1MSGREG7 = ((sb_chip->imc_tempin1_ct >> 8) & 0xff);
238  sb_config.Pecstruct.MSGFun89zone1MSGREG8 = ((sb_chip->imc_tempin1_ct >> 16) & 0xff);
239  sb_config.Pecstruct.MSGFun89zone1MSGREG9 = ((sb_chip->imc_tempin1_ct >> 24) & 0xff);
240  sb_config.Pecstruct.MSGFun89zone1MSGREGA = sb_chip->imc_tempin1_tuning_param;
241 }
242 
243 if (sb_chip->imc_tempin2_enabled) {
244 
245  sb_config.Pecstruct.IMCFUNSupportBitMap |= IMC_ENABLE_TEMPIN2;
246 
247  /* EC LDN9 function 89 TEMPIN channel 2 */
248  sb_config.Pecstruct.MSGFun89zone2MSGREG0 = 0x00;
249  sb_config.Pecstruct.MSGFun89zone2MSGREG1 = 0x02;
250  sb_config.Pecstruct.MSGFun89zone2MSGREG2 = (sb_chip->imc_tempin2_at & 0xff);
251  sb_config.Pecstruct.MSGFun89zone2MSGREG3 = ((sb_chip->imc_tempin2_at >> 8) & 0xff);
252  sb_config.Pecstruct.MSGFun89zone2MSGREG4 = ((sb_chip->imc_tempin2_at >> 16) & 0xff);
253  sb_config.Pecstruct.MSGFun89zone2MSGREG5 = ((sb_chip->imc_tempin2_at >> 24) & 0xff);
254  sb_config.Pecstruct.MSGFun89zone2MSGREG6 = (sb_chip->imc_tempin2_ct & 0xff);
255  sb_config.Pecstruct.MSGFun89zone2MSGREG7 = ((sb_chip->imc_tempin2_ct >> 8) & 0xff);
256  sb_config.Pecstruct.MSGFun89zone2MSGREG8 = ((sb_chip->imc_tempin2_ct >> 16) & 0xff);
257  sb_config.Pecstruct.MSGFun89zone2MSGREG9 = ((sb_chip->imc_tempin2_ct >> 24) & 0xff);
258  sb_config.Pecstruct.MSGFun89zone2MSGREGA = sb_chip->imc_tempin2_tuning_param;
259 }
260 
261 if (sb_chip->imc_tempin3_enabled) {
262 
263  sb_config.Pecstruct.IMCFUNSupportBitMap |= IMC_ENABLE_TEMPIN3;
264 
265  /* EC LDN9 function 89 TEMPIN channel 3 */
266  sb_config.Pecstruct.MSGFun89zone3MSGREG0 = 0x00;
267  sb_config.Pecstruct.MSGFun89zone3MSGREG1 = 0x03;
268  sb_config.Pecstruct.MSGFun89zone3MSGREG2 = (sb_chip->imc_tempin3_at & 0xff);
269  sb_config.Pecstruct.MSGFun89zone3MSGREG3 = ((sb_chip->imc_tempin3_at >> 8) & 0xff);
270  sb_config.Pecstruct.MSGFun89zone3MSGREG4 = ((sb_chip->imc_tempin3_at >> 16) & 0xff);
271  sb_config.Pecstruct.MSGFun89zone3MSGREG5 = ((sb_chip->imc_tempin3_at >> 24) & 0xff);
272  sb_config.Pecstruct.MSGFun89zone3MSGREG6 = (sb_chip->imc_tempin3_ct & 0xff);
273  sb_config.Pecstruct.MSGFun89zone3MSGREG7 = ((sb_chip->imc_tempin3_ct >> 8) & 0xff);
274  sb_config.Pecstruct.MSGFun89zone3MSGREG8 = ((sb_chip->imc_tempin3_ct >> 16) & 0xff);
275  sb_config.Pecstruct.MSGFun89zone3MSGREG9 = ((sb_chip->imc_tempin3_ct >> 24) & 0xff);
276  sb_config.Pecstruct.MSGFun89zone3MSGREGA = sb_chip->imc_tempin3_tuning_param;
277 }
278 
279  /* Set up the sb_config structure for the fan control initialization */
280  sb_config.StdHeader.Func = SB_EC_FANCONTROL;
281 
282  AmdSbDispatcher(&sb_config);
283 }
static void pm2_write8(uint8_t reg, uint8_t value)
Definition: acpimmio.h:201
void init_sb800_IMC_fans(struct device *dev)
Definition: fan.c:44
void init_sb800_MANUAL_fans(struct device *dev)
Definition: fan.c:12
#define IMC_ENABLE_TEMPIN1
Definition: fan.h:124
#define IMC_ZONE0
Definition: fan.h:107
#define IMC_ENABLE_TEMPIN3
Definition: fan.h:126
#define IMC_ENABLE_TEMPIN0
Definition: fan.h:123
#define IMC_FAN_CONFIG_COUNT
Definition: fan.h:131
#define IMC_FAN_SPEED_COUNT
Definition: fan.h:130
#define FAN_1_OFFSET
Definition: fan.h:13
#define IMC_ENABLE_ZONE3
Definition: fan.h:122
#define IMC_ENABLE_TEMPIN2
Definition: fan.h:125
#define IMC_ZONE2
Definition: fan.h:109
#define FAN_2_OFFSET
Definition: fan.h:14
#define IMC_ENABLE_ZONE1
Definition: fan.h:120
#define IMC_ZONE1
Definition: fan.h:108
#define FAN_0_OFFSET
Definition: fan.h:12
#define IMC_ENABLE_ZONE2
Definition: fan.h:121
#define FAN_REGISTER_COUNT
Definition: fan.h:132
#define IMC_ENABLE_ZONE0
Definition: fan.h:119
#define IMC_FAN_THRESHOLD_COUNT
Definition: fan.h:129
#define FAN_3_OFFSET
Definition: fan.h:15
#define FAN_4_OFFSET
Definition: fan.h:16
#define IMC_ZONE3
Definition: fan.h:110
static __always_inline void pci_write_config16(const struct device *dev, u16 reg, u16 val)
Definition: pci_ops.h:70
static AMDSBCFG * sb_config
Definition: late.c:29
Definition: device.h:107
DEVTREE_CONST void * chip_info
Definition: device.h:164
u8 imc_zone2_config_vals[IMC_FAN_CONFIG_COUNT]
Definition: chip.h:182
u8 fan0_config_vals[FAN_REGISTER_COUNT]
Definition: chip.h:60
u8 imc_zone1_fanspeeds[IMC_FAN_SPEED_COUNT]
Definition: chip.h:169
u8 fan4_config_vals[FAN_REGISTER_COUNT]
Definition: chip.h:136
u8 imc_zone0_thresholds[IMC_FAN_THRESHOLD_COUNT]
Definition: chip.h:152
u8 fan2_config_vals[FAN_REGISTER_COUNT]
Definition: chip.h:98
u8 imc_zone1_config_vals[IMC_FAN_CONFIG_COUNT]
Definition: chip.h:166
u8 imc_zone0_config_vals[IMC_FAN_CONFIG_COUNT]
Definition: chip.h:150
u8 imc_zone0_fanspeeds[IMC_FAN_SPEED_COUNT]
Definition: chip.h:153
u8 imc_zone3_config_vals[IMC_FAN_CONFIG_COUNT]
Definition: chip.h:198
u8 imc_zone2_thresholds[IMC_FAN_THRESHOLD_COUNT]
Definition: chip.h:184
u8 imc_zone3_thresholds[IMC_FAN_THRESHOLD_COUNT]
Definition: chip.h:200
u8 fan1_config_vals[FAN_REGISTER_COUNT]
Definition: chip.h:79
u8 imc_zone2_fanspeeds[IMC_FAN_SPEED_COUNT]
Definition: chip.h:185
u8 imc_zone1_thresholds[IMC_FAN_THRESHOLD_COUNT]
Definition: chip.h:168
u8 imc_zone3_fanspeeds[IMC_FAN_SPEED_COUNT]
Definition: chip.h:201
u8 fan3_config_vals[FAN_REGISTER_COUNT]
Definition: chip.h:117