coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
pm.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <stdint.h>
4 #include <device/pci_def.h>
5 #include <cpu/x86/msr.h>
6 #include <cpu/intel/speedstep.h>
7 
8 #include "gm45.h"
9 
10 static int sku_freq_index(const gmch_gfx_t sku, const int low_power_mode)
11 {
12  if (low_power_mode)
13  return 1;
14  switch (sku) {
15  case GMCH_GM45:
16  case GMCH_GE45:
17  case GMCH_GS45:
18  return 0;
19  case GMCH_GM47:
20  return 2;
21  case GMCH_GM49:
22  return 3;
23  default:
24  return 0;
25  }
26 }
27 static void init_freq_scaling(const gmch_gfx_t sku, const int low_power_mode)
28 {
29  int i;
30 
31  mchbar_clrsetbits32(0x11cc, 0x1f, 0x17);
32  switch (sku) {
33  case GMCH_GM45:
34  case GMCH_GE45:
35  case GMCH_GS45:
36  case GMCH_GM47:
37  case GMCH_GM49:
38  break;
39  default:
40  /* No more to be done for the others. */
41  return;
42  }
43 
44  static const u32 voltage_mask =
45  (0x1f << 24) | (0x1f << 16) | (0x1f << 8) | 0x1f;
46  mchbar_clrsetbits32(0x1120, voltage_mask, 0x10111213);
47  mchbar_clrsetbits32(0x1124, voltage_mask, 0x14151617);
48  mchbar_clrsetbits32(0x1128, voltage_mask, 0x18191a1b);
49  mchbar_clrsetbits32(0x112c, voltage_mask, 0x1c1d1e1f);
50  mchbar_clrsetbits32(0x1130, voltage_mask, 0x00010203);
51  mchbar_clrsetbits32(0x1134, voltage_mask, 0x04050607);
52  mchbar_clrsetbits32(0x1138, voltage_mask, 0x08090a0b);
53  mchbar_clrsetbits32(0x113c, voltage_mask, 0x0c0d0e0f);
54 
55  /* Program frequencies. */
56  static const u32 frequencies_from_sku_vco[][4][8] = {
57  /* GM45/GE45/GS45_perf */ {
58  /* VCO 2666 */ { 0xcd, 0xbc, 0x9b, 0x8a, 0x79, 0x78, 0x67, 0x56 },
59  /* VCO 3200 */ { 0xcd, 0xac, 0x9b, 0x8a, 0x89, 0x78, 0x67, 0x56 },
60  /* VCO 4000 */ { 0xac, 0x9b, 0x9a, 0x89, 0x89, 0x68, 0x56, 0x45 },
61  /* VCO 5333 */ { 0xab, 0x9a, 0x79, 0x68, 0x57, 0x56, 0x45, 0x34 },
62  },
63  /* GS45_low_power */ {
64  /* VCO 2666 */ { 0xcd, 0x8a },
65  /* VCO 3200 */ { 0xcd, 0x89 },
66  /* VCO 4000 */ { 0xac, 0x89 },
67  /* VCO 5333 */ { 0xab, 0x68 },
68  },
69  /* GM47 */ {
70  /* VCO 2666 */ { 0xcd, 0xcd, 0xbc, 0x9b, 0x79, 0x78, 0x67, 0x56 },
71  /* VCO 3200 */ { 0xde, 0xcd, 0xac, 0x9b, 0x89, 0x78, 0x67, 0x56 },
72  /* VCO 4000 */ { 0xcd, 0xac, 0x9b, 0x9a, 0x89, 0x68, 0x56, 0x45 },
73  /* VCO 5333 */ { 0xac, 0xab, 0x9a, 0x79, 0x68, 0x56, 0x45, 0x34 },
74  },
75  /* GM49 */ {
76  /* VCO 2666 */ { },
77  /* VCO 3200 */ { 0xef, 0xde, 0xcd, 0xac, 0x89, 0x78, 0x67, 0x56 },
78  /* VCO 4000 */ { 0xef, 0xde, 0xac, 0x9b, 0x89, 0x68, 0x56, 0x45 },
79  /* VCO 5333 */ { 0xce, 0xbd, 0xab, 0x9a, 0x68, 0x57, 0x45, 0x34 },
80  }};
81  const int sku_index = sku_freq_index(sku, low_power_mode);
82  const int vco_index = raminit_read_vco_index();
83  const int reg_limit = low_power_mode ? 1 : 4;
84  if (sku == GMCH_GM49)
85  mchbar_write8(0x1110 + 3, 0x1b);
86  else
87  mchbar_write8(0x1110 + 3, 0x17);
88  mchbar_write8(0x1110 + 1, 0x17);
89  if (!low_power_mode) {
90  mchbar_write8(0x1114 + 3, 0x17);
91  mchbar_write8(0x1114 + 1, 0x17);
92  mchbar_write8(0x1118 + 3, 0x17);
93  mchbar_write8(0x1118 + 1, 0x17);
94  mchbar_write8(0x111c + 3, 0x17);
95  mchbar_write8(0x111c + 1, 0x17);
96  }
97  for (i = 0; i < reg_limit; ++i) {
98  const int mchbar = 0x1110 + (i * 4);
99  mchbar_write8(mchbar + 2, frequencies_from_sku_vco
100  [sku_index][vco_index][i * 2 + 0]);
101  mchbar_write8(mchbar + 0, frequencies_from_sku_vco
102  [sku_index][vco_index][i * 2 + 1]);
103  }
104 
105  if (low_power_mode) {
106  mchbar_clrsetbits16(0x1190, 7 << 8 | 7 << 4 | 7, 1 << 8 | 1 << 4 | 1);
107  } else {
108  mchbar_clrsetbits16(0x1190, 7 << 8 | 7 << 4, 7);
109  if (sku == GMCH_GS45) /* performance mode */
110  mchbar_clrbits32(0x0ffc, 1 << 31);
111  }
112 
113  mchbar_setbits16(0x0fc0, 1 << 11);
114  mchbar_write16(0x11b8, 0x333c);
115  mchbar_write16(0x11c0 + 2, 0x0303);
116  mchbar_write32(0x11c4, 0x0a030a03);
117  mchbar_clrsetbits16(0x1100, 0x1f << 8, 3 << 8);
118  mchbar_write16(0x11b8 + 2, 0x4000);
119 }
120 
121 void init_pm(const sysinfo_t *const sysinfo, int do_freq_scaling_cfg)
122 {
123  const stepping_t stepping = sysinfo->stepping;
126 
127  mchbar_write16(0xc14, 0);
128  mchbar_write16(0xc20, 0);
129  mchbar_write32(0xfc0, 0x001f00fd);
130  mchbar_setbits32(0xfc0, 3 << 25);
131  mchbar_setbits32(0xfc0, 1 << 11);
132  mchbar_write8(0xfb0, 3);
133  mchbar_setbits8(0xf10, 1 << 1);
134  if (fsb == FSB_CLOCK_667MHz) {
135  mchbar_write16(0xc3a, 0x0ea6);
136  mchbar_clrsetbits8(0xc16, 0x7f, 0x0e);
137  } else if (fsb == FSB_CLOCK_800MHz) {
138  mchbar_write16(0xc3a, 0x1194);
139  mchbar_clrsetbits8(0xc16, 0x7f, 0x10);
140  } else if (fsb == FSB_CLOCK_1067MHz) {
141  mchbar_write16(0xc3a, 0x1777);
142  mchbar_clrsetbits8(0xc16, 0x7f, 0x15);
143  }
144  mchbar_write8(0xfb8, 3);
145  if (fsb == FSB_CLOCK_667MHz)
146  mchbar_write16(0xc38, 0x0ea6);
147  else if (fsb == FSB_CLOCK_800MHz)
148  mchbar_write16(0xc38, 0x1194);
149  else if (fsb == FSB_CLOCK_1067MHz)
150  mchbar_write16(0xc38, 0x1777);
151  mchbar_setbits8(0xf10, 1 << 5);
152  mchbar_setbits16(0xc16, 3 << 12);
153  mchbar_write32(0xf60, 0x01030419);
154  if (fsb == FSB_CLOCK_667MHz) {
155  mchbar_write32(0xf00, 0x00000600);
156  mchbar_write32(0xf04, 0x00001d80);
157  } else if (fsb == FSB_CLOCK_800MHz) {
158  mchbar_write32(0xf00, 0x00000700);
159  mchbar_write32(0xf04, 0x00002380);
160  } else if (fsb == FSB_CLOCK_1067MHz) {
161  mchbar_write32(0xf00, 0x00000900);
162  mchbar_write32(0xf04, 0x00002e80);
163  }
164  mchbar_write16(0xf08, 0x730f);
165  if (fsb == FSB_CLOCK_667MHz)
166  mchbar_write16(0xf0c, 0x0b96);
167  else if (fsb == FSB_CLOCK_800MHz)
168  mchbar_write16(0xf0c, 0x0c99);
169  else if (fsb == FSB_CLOCK_1067MHz)
170  mchbar_write16(0xf0c, 0x10a4);
171  mchbar_setbits32(0xf80, 1 << 31);
172 
173  mchbar_write32(0x40, (mchbar_read32(0x40) & ~(0x3f << 24)) |
174  ((sysinfo->cores == 4) ? (1 << 24) : 0));
175 
176  mchbar_clrbits32(0x40, 1 << 19);
177  mchbar_setbits32(0x40, 1 << 13);
178  mchbar_setbits32(0x40, 1 << 21);
179  mchbar_setbits32(0x40, 1 << 9);
180  if (stepping > STEPPING_B1) {
181  if (fsb != FSB_CLOCK_1067MHz) {
182  mchbar_setbits32(0x70, 1 << 30);
183  } else {
184  mchbar_clrbits32(0x70, 1 << 30);
185  }
186  }
187  if (stepping < STEPPING_B1)
188  mchbar_setbits32(0x70, 1 << 29);
189  else
190  mchbar_clrbits32(0x70, 1 << 29);
191  if (stepping > STEPPING_B1) {
192  mchbar_setbits32(0x70, 1 << 28);
193  mchbar_setbits32(0x70, 1 << 25);
194  }
195  if (stepping > STEPPING_B0) {
196  if (fsb != FSB_CLOCK_667MHz)
197  mchbar_clrsetbits32(0x70, 3 << 21, 1 << 21);
198  else
199  mchbar_clrbits32(0x70, 3 << 21);
200  }
201  if (stepping > STEPPING_B2)
202  mchbar_setbits32(0x44, 1 << 30);
203  mchbar_setbits32(0x44, 1 << 31);
204  if (sysinfo->cores == 2)
205  mchbar_setbits32(0x44, 1 << 26);
206  mchbar_setbits32(0x44, 1 << 21);
207  mchbar_clrsetbits32(0x44, 3 << 24, 2 << 24);
208  mchbar_setbits32(0x44, 1 << 5);
209  mchbar_setbits32(0x44, 1 << 4);
210  mchbar_clrsetbits32(0x90, 7, 4);
211  mchbar_setbits32(0x94, 1 << 29);
212  mchbar_setbits32(0x94, 1 << 11);
213  if (stepping < STEPPING_B0)
214  mchbar_clrsetbits32(0x94, 3 << 19, 2 << 19);
215  if (stepping > STEPPING_B2)
216  mchbar_setbits32(0x94, 1 << 21);
217  mchbar_clrbits8(0xb00, 1 << 0);
218  mchbar_setbits8(0xb00, 1 << 7);
219  if (fsb != FSB_CLOCK_1067MHz)
220  mchbar_setbits8(0x75, 1 << 6);
221  else
222  mchbar_clrbits8(0x75, ~(1 << 1));
223  mchbar_setbits8(0x77, 3);
224  if (stepping >= STEPPING_B1)
225  mchbar_setbits8(0x77, 1 << 2);
226  if (stepping > STEPPING_B2)
227  mchbar_setbits8(0x77, 1 << 4);
228  if (mchbar_read16(0x90) & (1 << 8))
229  mchbar_clrbits8(0x90, 7 << 4);
230  if (stepping >= STEPPING_B0)
231  mchbar_setbits8(0xd0, 1 << 1);
232  mchbar_setbits8(0xbd8, 3 << 2);
233  if (stepping >= STEPPING_B3)
234  mchbar_setbits32(0x70, 1 << 0);
235  mchbar_setbits32(0x70, 1 << 3);
236  if (stepping >= STEPPING_B0)
237  mchbar_clrbits32(0x70, 1 << 16);
238  else
239  mchbar_setbits32(0x70, 1 << 16);
240  if (stepping >= STEPPING_B3)
241  mchbar_setbits8(0xc14, 1 << 1);
242  if (stepping >= STEPPING_B1)
243  mchbar_clrsetbits16(0xffc, 0x7ff, 0x7c0);
244  mchbar_clrsetbits16(0x48, 0xff << 2, 0xaa << 2);
246  mchbar_setbits16(0x40, 1 << 12);
247  mchbar_setbits32(0x94, 3 << 22);
248  }
249 
250  const int cpu_supports_super_lfm =
251  rdmsr(MSR_EXTENDED_CONFIG).lo & (1 << 27);
252  if ((stepping >= STEPPING_B0) && cpu_supports_super_lfm) {
255  } else {
258  mchbar_clrbits32(0x44, 1 << 31); /* Was set above. */
259  }
260 
261  if ((sysinfo->gfx_type != GMCH_PM45) && do_freq_scaling_cfg &&
262  (sysinfo->gfx_type != GMCH_UNKNOWN))
263  init_freq_scaling(sysinfo->gfx_type,
264  sysinfo->gs45_low_power_mode);
265 
266  /* This has to be the last write to CLKCFG. */
267  if ((fsb == FSB_CLOCK_1067MHz) && (memclk == MEM_CLOCK_667MT))
269 }
#define mchbar_setbits32(addr, set)
Definition: fixed_bars.h:58
static __always_inline void mchbar_write16(const uintptr_t offset, const uint16_t value)
Definition: fixed_bars.h:31
static __always_inline void mchbar_write8(const uintptr_t offset, const uint8_t value)
Definition: fixed_bars.h:26
static __always_inline void mchbar_clrsetbits8(uintptr_t offset, uint8_t clear, uint8_t set)
Definition: fixed_bars.h:41
static __always_inline void mchbar_write32(const uintptr_t offset, const uint32_t value)
Definition: fixed_bars.h:36
#define mchbar_clrbits8(addr, clear)
Definition: fixed_bars.h:60
#define mchbar_clrbits16(addr, clear)
Definition: fixed_bars.h:61
#define mchbar_setbits8(addr, set)
Definition: fixed_bars.h:56
static __always_inline void mchbar_clrsetbits32(uintptr_t offset, uint32_t clear, uint32_t set)
Definition: fixed_bars.h:51
static __always_inline uint32_t mchbar_read32(const uintptr_t offset)
Definition: fixed_bars.h:21
#define mchbar_clrbits32(addr, clear)
Definition: fixed_bars.h:62
static __always_inline void mchbar_clrsetbits16(uintptr_t offset, uint16_t clear, uint16_t set)
Definition: fixed_bars.h:46
static __always_inline uint16_t mchbar_read16(const uintptr_t offset)
Definition: fixed_bars.h:16
#define mchbar_setbits16(addr, set)
Definition: fixed_bars.h:57
int raminit_read_vco_index(void)
Definition: raminit.c:733
#define CLKCFG_MCHBAR
Definition: gm45.h:229
stepping_t
Definition: gm45.h:14
@ STEPPING_B1
Definition: gm45.h:22
@ STEPPING_B3
Definition: gm45.h:24
@ STEPPING_B0
Definition: gm45.h:21
@ STEPPING_B2
Definition: gm45.h:23
@ STEPPING_CONVERSION_A1
Definition: gm45.h:25
fsb_clock_t
Definition: gm45.h:8
@ FSB_CLOCK_800MHz
Definition: gm45.h:10
@ FSB_CLOCK_667MHz
Definition: gm45.h:11
@ FSB_CLOCK_1067MHz
Definition: gm45.h:9
gmch_gfx_t
Definition: gm45.h:28
@ GMCH_GM47
Definition: gm45.h:30
@ GMCH_PM45
Definition: gm45.h:37
@ GMCH_GM45
Definition: gm45.h:29
@ GMCH_GS45
Definition: gm45.h:36
@ GMCH_UNKNOWN
Definition: gm45.h:38
@ GMCH_GE45
Definition: gm45.h:32
@ GMCH_GM49
Definition: gm45.h:31
mem_clock_t
Definition: gm45.h:41
@ MEM_CLOCK_667MT
Definition: gm45.h:47
enum project_sku sku
Definition: mainboard.c:51
static __always_inline msr_t rdmsr(unsigned int index)
Definition: msr.h:146
static int memclk(void)
Definition: raminit.c:92
void init_pm(const sysinfo_t *const sysinfo, int do_freq_scaling_cfg)
Definition: pm.c:121
static int sku_freq_index(const gmch_gfx_t sku, const int low_power_mode)
Definition: pm.c:10
static void init_freq_scaling(const gmch_gfx_t sku, const int low_power_mode)
Definition: pm.c:27
const char * stepping
#define MSR_EXTENDED_CONFIG
Definition: speedstep.h:29
uint32_t u32
Definition: stdint.h:51
unsigned int lo
Definition: msr.h:111
int cores
Definition: raminit.h:99
struct timings selected_timings
Definition: raminit.h:113
enum fsb_clk fsb_clock
Definition: raminit.h:46
enum mem_clk mem_clock
Definition: raminit.h:47