blob: 656a63263954ff740f74e7f1eed9e62f2941dfd3 [file] [log] [blame]
Angel Pons4b429832020-04-02 23:48:50 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Patrick Georgi2efc8802012-11-06 11:03:53 +01002
3#include <stdint.h>
Patrick Georgi2efc8802012-11-06 11:03:53 +01004#include <device/pci_def.h>
Patrick Georgi2efc8802012-11-06 11:03:53 +01005#include <cpu/x86/msr.h>
Elyes HAOUASf33e8352018-10-24 16:24:44 +02006#include <cpu/intel/speedstep.h>
Patrick Georgi2efc8802012-11-06 11:03:53 +01007
8#include "gm45.h"
9
10static 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}
27static void init_freq_scaling(const gmch_gfx_t sku, const int low_power_mode)
28{
29 int i;
30
Angel Pons3f1f8ef2021-03-27 13:52:43 +010031 mchbar_clrsetbits32(0x11cc, 0x1f, 0x17);
Patrick Georgi2efc8802012-11-06 11:03:53 +010032 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;
Angel Pons3f1f8ef2021-03-27 13:52:43 +010046 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);
Patrick Georgi2efc8802012-11-06 11:03:53 +010054
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)
Angel Pons3f1f8ef2021-03-27 13:52:43 +010085 mchbar_write8(0x1110 + 3, 0x1b);
Patrick Georgi2efc8802012-11-06 11:03:53 +010086 else
Angel Pons3f1f8ef2021-03-27 13:52:43 +010087 mchbar_write8(0x1110 + 3, 0x17);
88 mchbar_write8(0x1110 + 1, 0x17);
Patrick Georgi2efc8802012-11-06 11:03:53 +010089 if (!low_power_mode) {
Angel Pons3f1f8ef2021-03-27 13:52:43 +010090 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);
Patrick Georgi2efc8802012-11-06 11:03:53 +010096 }
97 for (i = 0; i < reg_limit; ++i) {
98 const int mchbar = 0x1110 + (i * 4);
Angel Pons3f1f8ef2021-03-27 13:52:43 +010099 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]);
Patrick Georgi2efc8802012-11-06 11:03:53 +0100103 }
104
105 if (low_power_mode) {
Angel Pons3f1f8ef2021-03-27 13:52:43 +0100106 mchbar_clrsetbits16(0x1190, 7 << 8 | 7 << 4 | 7, 1 << 8 | 1 << 4 | 1);
Patrick Georgi2efc8802012-11-06 11:03:53 +0100107 } else {
Angel Pons3f1f8ef2021-03-27 13:52:43 +0100108 mchbar_clrsetbits16(0x1190, 7 << 8 | 7 << 4, 7);
Patrick Georgi2efc8802012-11-06 11:03:53 +0100109 if (sku == GMCH_GS45) /* performance mode */
Angel Pons3f1f8ef2021-03-27 13:52:43 +0100110 mchbar_clrbits32(0x0ffc, 1 << 31);
Patrick Georgi2efc8802012-11-06 11:03:53 +0100111 }
112
Angel Pons3f1f8ef2021-03-27 13:52:43 +0100113 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);
Patrick Georgi2efc8802012-11-06 11:03:53 +0100119}
120
Vladimir Serbinenko020dc0e2014-08-12 22:50:40 +0200121void init_pm(const sysinfo_t *const sysinfo, int do_freq_scaling_cfg)
Patrick Georgi2efc8802012-11-06 11:03:53 +0100122{
123 const stepping_t stepping = sysinfo->stepping;
124 const fsb_clock_t fsb = sysinfo->selected_timings.fsb_clock;
125 const mem_clock_t memclk = sysinfo->selected_timings.mem_clock;
126
Angel Pons3f1f8ef2021-03-27 13:52:43 +0100127 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);
Patrick Georgi2efc8802012-11-06 11:03:53 +0100134 if (fsb == FSB_CLOCK_667MHz) {
Angel Pons3f1f8ef2021-03-27 13:52:43 +0100135 mchbar_write16(0xc3a, 0x0ea6);
136 mchbar_clrsetbits8(0xc16, 0x7f, 0x0e);
Patrick Georgi2efc8802012-11-06 11:03:53 +0100137 } else if (fsb == FSB_CLOCK_800MHz) {
Angel Pons3f1f8ef2021-03-27 13:52:43 +0100138 mchbar_write16(0xc3a, 0x1194);
139 mchbar_clrsetbits8(0xc16, 0x7f, 0x10);
Patrick Georgi2efc8802012-11-06 11:03:53 +0100140 } else if (fsb == FSB_CLOCK_1067MHz) {
Angel Pons3f1f8ef2021-03-27 13:52:43 +0100141 mchbar_write16(0xc3a, 0x1777);
142 mchbar_clrsetbits8(0xc16, 0x7f, 0x15);
Patrick Georgi2efc8802012-11-06 11:03:53 +0100143 }
Angel Pons3f1f8ef2021-03-27 13:52:43 +0100144 mchbar_write8(0xfb8, 3);
Patrick Georgi2efc8802012-11-06 11:03:53 +0100145 if (fsb == FSB_CLOCK_667MHz)
Angel Pons3f1f8ef2021-03-27 13:52:43 +0100146 mchbar_write16(0xc38, 0x0ea6);
Patrick Georgi2efc8802012-11-06 11:03:53 +0100147 else if (fsb == FSB_CLOCK_800MHz)
Angel Pons3f1f8ef2021-03-27 13:52:43 +0100148 mchbar_write16(0xc38, 0x1194);
Patrick Georgi2efc8802012-11-06 11:03:53 +0100149 else if (fsb == FSB_CLOCK_1067MHz)
Angel Pons3f1f8ef2021-03-27 13:52:43 +0100150 mchbar_write16(0xc38, 0x1777);
151 mchbar_setbits8(0xf10, 1 << 5);
152 mchbar_setbits16(0xc16, 3 << 12);
153 mchbar_write32(0xf60, 0x01030419);
Patrick Georgi2efc8802012-11-06 11:03:53 +0100154 if (fsb == FSB_CLOCK_667MHz) {
Angel Pons3f1f8ef2021-03-27 13:52:43 +0100155 mchbar_write32(0xf00, 0x00000600);
156 mchbar_write32(0xf04, 0x00001d80);
Patrick Georgi2efc8802012-11-06 11:03:53 +0100157 } else if (fsb == FSB_CLOCK_800MHz) {
Angel Pons3f1f8ef2021-03-27 13:52:43 +0100158 mchbar_write32(0xf00, 0x00000700);
159 mchbar_write32(0xf04, 0x00002380);
Patrick Georgi2efc8802012-11-06 11:03:53 +0100160 } else if (fsb == FSB_CLOCK_1067MHz) {
Angel Pons3f1f8ef2021-03-27 13:52:43 +0100161 mchbar_write32(0xf00, 0x00000900);
162 mchbar_write32(0xf04, 0x00002e80);
Patrick Georgi2efc8802012-11-06 11:03:53 +0100163 }
Angel Pons3f1f8ef2021-03-27 13:52:43 +0100164 mchbar_write16(0xf08, 0x730f);
Patrick Georgi2efc8802012-11-06 11:03:53 +0100165 if (fsb == FSB_CLOCK_667MHz)
Angel Pons3f1f8ef2021-03-27 13:52:43 +0100166 mchbar_write16(0xf0c, 0x0b96);
Patrick Georgi2efc8802012-11-06 11:03:53 +0100167 else if (fsb == FSB_CLOCK_800MHz)
Angel Pons3f1f8ef2021-03-27 13:52:43 +0100168 mchbar_write16(0xf0c, 0x0c99);
Patrick Georgi2efc8802012-11-06 11:03:53 +0100169 else if (fsb == FSB_CLOCK_1067MHz)
Angel Pons3f1f8ef2021-03-27 13:52:43 +0100170 mchbar_write16(0xf0c, 0x10a4);
171 mchbar_setbits32(0xf80, 1 << 31);
Patrick Georgi2efc8802012-11-06 11:03:53 +0100172
Angel Pons3f1f8ef2021-03-27 13:52:43 +0100173 mchbar_write32(0x40, (mchbar_read32(0x40) & ~(0x3f << 24)) |
Arthur Heymanscdad9922022-02-16 07:00:29 +0100174 ((sysinfo->cores == 4) ? (1 << 24) : 0));
Patrick Georgi2efc8802012-11-06 11:03:53 +0100175
Angel Pons3f1f8ef2021-03-27 13:52:43 +0100176 mchbar_clrbits32(0x40, 1 << 19);
177 mchbar_setbits32(0x40, 1 << 13);
178 mchbar_setbits32(0x40, 1 << 21);
179 mchbar_setbits32(0x40, 1 << 9);
Patrick Georgi2efc8802012-11-06 11:03:53 +0100180 if (stepping > STEPPING_B1) {
181 if (fsb != FSB_CLOCK_1067MHz) {
Angel Pons3f1f8ef2021-03-27 13:52:43 +0100182 mchbar_setbits32(0x70, 1 << 30);
Patrick Georgi2efc8802012-11-06 11:03:53 +0100183 } else {
Angel Pons3f1f8ef2021-03-27 13:52:43 +0100184 mchbar_clrbits32(0x70, 1 << 30);
Patrick Georgi2efc8802012-11-06 11:03:53 +0100185 }
186 }
187 if (stepping < STEPPING_B1)
Angel Pons3f1f8ef2021-03-27 13:52:43 +0100188 mchbar_setbits32(0x70, 1 << 29);
Patrick Georgi2efc8802012-11-06 11:03:53 +0100189 else
Angel Pons3f1f8ef2021-03-27 13:52:43 +0100190 mchbar_clrbits32(0x70, 1 << 29);
Patrick Georgi2efc8802012-11-06 11:03:53 +0100191 if (stepping > STEPPING_B1) {
Angel Pons3f1f8ef2021-03-27 13:52:43 +0100192 mchbar_setbits32(0x70, 1 << 28);
193 mchbar_setbits32(0x70, 1 << 25);
Patrick Georgi2efc8802012-11-06 11:03:53 +0100194 }
195 if (stepping > STEPPING_B0) {
196 if (fsb != FSB_CLOCK_667MHz)
Angel Pons3f1f8ef2021-03-27 13:52:43 +0100197 mchbar_clrsetbits32(0x70, 3 << 21, 1 << 21);
Patrick Georgi2efc8802012-11-06 11:03:53 +0100198 else
Angel Pons3f1f8ef2021-03-27 13:52:43 +0100199 mchbar_clrbits32(0x70, 3 << 21);
Patrick Georgi2efc8802012-11-06 11:03:53 +0100200 }
201 if (stepping > STEPPING_B2)
Angel Pons3f1f8ef2021-03-27 13:52:43 +0100202 mchbar_setbits32(0x44, 1 << 30);
203 mchbar_setbits32(0x44, 1 << 31);
Patrick Georgi2efc8802012-11-06 11:03:53 +0100204 if (sysinfo->cores == 2)
Angel Pons3f1f8ef2021-03-27 13:52:43 +0100205 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);
Patrick Georgi2efc8802012-11-06 11:03:53 +0100213 if (stepping < STEPPING_B0)
Angel Pons3f1f8ef2021-03-27 13:52:43 +0100214 mchbar_clrsetbits32(0x94, 3 << 19, 2 << 19);
Patrick Georgi2efc8802012-11-06 11:03:53 +0100215 if (stepping > STEPPING_B2)
Angel Pons3f1f8ef2021-03-27 13:52:43 +0100216 mchbar_setbits32(0x94, 1 << 21);
217 mchbar_clrbits8(0xb00, 1 << 0);
218 mchbar_setbits8(0xb00, 1 << 7);
Patrick Georgi2efc8802012-11-06 11:03:53 +0100219 if (fsb != FSB_CLOCK_1067MHz)
Angel Pons3f1f8ef2021-03-27 13:52:43 +0100220 mchbar_setbits8(0x75, 1 << 6);
Patrick Georgi2efc8802012-11-06 11:03:53 +0100221 else
Angel Pons3f1f8ef2021-03-27 13:52:43 +0100222 mchbar_clrbits8(0x75, ~(1 << 1));
223 mchbar_setbits8(0x77, 3);
Patrick Georgi2efc8802012-11-06 11:03:53 +0100224 if (stepping >= STEPPING_B1)
Angel Pons3f1f8ef2021-03-27 13:52:43 +0100225 mchbar_setbits8(0x77, 1 << 2);
Patrick Georgi2efc8802012-11-06 11:03:53 +0100226 if (stepping > STEPPING_B2)
Angel Pons3f1f8ef2021-03-27 13:52:43 +0100227 mchbar_setbits8(0x77, 1 << 4);
228 if (mchbar_read16(0x90) & (1 << 8))
229 mchbar_clrbits8(0x90, 7 << 4);
Patrick Georgi2efc8802012-11-06 11:03:53 +0100230 if (stepping >= STEPPING_B0)
Angel Pons3f1f8ef2021-03-27 13:52:43 +0100231 mchbar_setbits8(0xd0, 1 << 1);
232 mchbar_setbits8(0xbd8, 3 << 2);
Patrick Georgi2efc8802012-11-06 11:03:53 +0100233 if (stepping >= STEPPING_B3)
Angel Pons3f1f8ef2021-03-27 13:52:43 +0100234 mchbar_setbits32(0x70, 1 << 0);
235 mchbar_setbits32(0x70, 1 << 3);
Patrick Georgi2efc8802012-11-06 11:03:53 +0100236 if (stepping >= STEPPING_B0)
Angel Pons3f1f8ef2021-03-27 13:52:43 +0100237 mchbar_clrbits32(0x70, 1 << 16);
Patrick Georgi2efc8802012-11-06 11:03:53 +0100238 else
Angel Pons3f1f8ef2021-03-27 13:52:43 +0100239 mchbar_setbits32(0x70, 1 << 16);
Patrick Georgi2efc8802012-11-06 11:03:53 +0100240 if (stepping >= STEPPING_B3)
Angel Pons3f1f8ef2021-03-27 13:52:43 +0100241 mchbar_setbits8(0xc14, 1 << 1);
Patrick Georgi2efc8802012-11-06 11:03:53 +0100242 if (stepping >= STEPPING_B1)
Angel Pons3f1f8ef2021-03-27 13:52:43 +0100243 mchbar_clrsetbits16(0xffc, 0x7ff, 0x7c0);
244 mchbar_clrsetbits16(0x48, 0xff << 2, 0xaa << 2);
Patrick Georgi2efc8802012-11-06 11:03:53 +0100245 if (stepping == STEPPING_CONVERSION_A1) {
Angel Pons3f1f8ef2021-03-27 13:52:43 +0100246 mchbar_setbits16(0x40, 1 << 12);
247 mchbar_setbits32(0x94, 3 << 22);
Patrick Georgi2efc8802012-11-06 11:03:53 +0100248 }
249
Elyes HAOUASf33e8352018-10-24 16:24:44 +0200250 const int cpu_supports_super_lfm =
251 rdmsr(MSR_EXTENDED_CONFIG).lo & (1 << 27);
Patrick Georgi2efc8802012-11-06 11:03:53 +0100252 if ((stepping >= STEPPING_B0) && cpu_supports_super_lfm) {
Angel Pons3f1f8ef2021-03-27 13:52:43 +0100253 mchbar_clrbits16(CLKCFG_MCHBAR, 1 << 7);
254 mchbar_setbits16(CLKCFG_MCHBAR, 1 << 14);
Patrick Georgi2efc8802012-11-06 11:03:53 +0100255 } else {
Angel Pons3f1f8ef2021-03-27 13:52:43 +0100256 mchbar_clrbits16(CLKCFG_MCHBAR, 1 << 14);
257 mchbar_setbits16(CLKCFG_MCHBAR, 1 << 7);
258 mchbar_clrbits32(0x44, 1 << 31); /* Was set above. */
Patrick Georgi2efc8802012-11-06 11:03:53 +0100259 }
260
Vladimir Serbinenko020dc0e2014-08-12 22:50:40 +0200261 if ((sysinfo->gfx_type != GMCH_PM45) && do_freq_scaling_cfg &&
Patrick Georgi2efc8802012-11-06 11:03:53 +0100262 (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))
Angel Pons3f1f8ef2021-03-27 13:52:43 +0100268 mchbar_clrbits32(CLKCFG_MCHBAR, 1 << 17);
Patrick Georgi2efc8802012-11-06 11:03:53 +0100269}