1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright 2019 Google LLC
4  * Written by Simon Glass <sjg@chromium.org>
5  */
6 
7 #include <common.h>
8 #include <binman.h>
9 #include <bootstage.h>
10 #include <dm.h>
11 #include <init.h>
12 #include <irq.h>
13 #include <log.h>
14 #include <malloc.h>
15 #include <p2sb.h>
16 #include <acpi/acpi_s3.h>
17 #include <asm/global_data.h>
18 #include <asm/intel_pinctrl.h>
19 #include <asm/io.h>
20 #include <asm/intel_regs.h>
21 #include <asm/msr.h>
22 #include <asm/msr-index.h>
23 #include <asm/pci.h>
24 #include <asm/arch/cpu.h>
25 #include <asm/arch/systemagent.h>
26 #include <asm/arch/fsp_bindings.h>
27 #include <asm/arch/fsp/fsp_configs.h>
28 #include <asm/arch/fsp/fsp_s_upd.h>
29 #include <dm/uclass-internal.h>
30 #include <linux/bitops.h>
31 
32 #define PCH_P2SB_E0		0xe0
33 #define HIDE_BIT		BIT(0)
34 
fsps_update_config(struct udevice * dev,ulong rom_offset,struct fsps_upd * upd)35 int fsps_update_config(struct udevice *dev, ulong rom_offset,
36 		       struct fsps_upd *upd)
37 {
38 	struct fsp_s_config *cfg = &upd->config;
39 	ofnode node;
40 
41 	if (IS_ENABLED(CONFIG_HAVE_VBT)) {
42 		void *buf;
43 		int ret;
44 
45 		ret = binman_entry_map(ofnode_null(), "intel-vbt", &buf, NULL);
46 		if (ret)
47 			return log_msg_ret("Cannot find VBT", ret);
48 		if (*(u32 *)buf != VBT_SIGNATURE)
49 			return log_msg_ret("VBT signature", -EINVAL);
50 
51 		/*
52 		 * Load VBT before devicetree-specific config. This only
53 		 * supports memory-mapped SPI at present.
54 		 */
55 		cfg->graphics_config_ptr = (ulong)buf;
56 	}
57 
58 	node = dev_read_subnode(dev, "fsp-s");
59 	if (!ofnode_valid(node))
60 		return log_msg_ret("fsp-s settings", -ENOENT);
61 
62 	return fsp_s_update_config_from_dtb(node, cfg);
63 }
64 
65 /* Configure package power limits */
set_power_limits(struct udevice * dev)66 static int set_power_limits(struct udevice *dev)
67 {
68 	msr_t rapl_msr_reg, limit;
69 	u32 power_unit;
70 	u32 tdp, min_power, max_power;
71 	u32 pl2_val;
72 	u32 override_tdp[2];
73 	int ret;
74 
75 	/* Get units */
76 	rapl_msr_reg = msr_read(MSR_PKG_POWER_SKU_UNIT);
77 	power_unit = 1 << (rapl_msr_reg.lo & 0xf);
78 
79 	/* Get power defaults for this SKU */
80 	rapl_msr_reg = msr_read(MSR_PKG_POWER_SKU);
81 	tdp = rapl_msr_reg.lo & PKG_POWER_LIMIT_MASK;
82 	pl2_val = rapl_msr_reg.hi & PKG_POWER_LIMIT_MASK;
83 	min_power = (rapl_msr_reg.lo >> 16) & PKG_POWER_LIMIT_MASK;
84 	max_power = rapl_msr_reg.hi & PKG_POWER_LIMIT_MASK;
85 
86 	if (min_power > 0 && tdp < min_power)
87 		tdp = min_power;
88 
89 	if (max_power > 0 && tdp > max_power)
90 		tdp = max_power;
91 
92 	ret = dev_read_u32_array(dev, "tdp-pl-override-mw", override_tdp,
93 				 ARRAY_SIZE(override_tdp));
94 	if (ret)
95 		return log_msg_ret("tdp-pl-override-mw", ret);
96 
97 	/* Set PL1 override value */
98 	if (override_tdp[0])
99 		tdp = override_tdp[0] * power_unit / 1000;
100 
101 	/* Set PL2 override value */
102 	if (override_tdp[1])
103 		pl2_val = override_tdp[1] * power_unit / 1000;
104 
105 	/* Set long term power limit to TDP */
106 	limit.lo = tdp & PKG_POWER_LIMIT_MASK;
107 	/* Set PL1 Pkg Power clamp bit */
108 	limit.lo |= PKG_POWER_LIMIT_CLAMP;
109 
110 	limit.lo |= PKG_POWER_LIMIT_EN;
111 	limit.lo |= (MB_POWER_LIMIT1_TIME_DEFAULT &
112 		PKG_POWER_LIMIT_TIME_MASK) << PKG_POWER_LIMIT_TIME_SHIFT;
113 
114 	/* Set short term power limit PL2 */
115 	limit.hi = pl2_val & PKG_POWER_LIMIT_MASK;
116 	limit.hi |= PKG_POWER_LIMIT_EN;
117 
118 	/* Program package power limits in RAPL MSR */
119 	msr_write(MSR_PKG_POWER_LIMIT, limit);
120 	log_debug("RAPL PL1 %d.%dW\n", tdp / power_unit,
121 		  100 * (tdp % power_unit) / power_unit);
122 	log_debug("RAPL PL2 %d.%dW\n", pl2_val / power_unit,
123 		  100 * (pl2_val % power_unit) / power_unit);
124 
125 	/*
126 	 * Sett RAPL MMIO register for Power limits. RAPL driver is using MSR
127 	 * instead of MMIO, so disable LIMIT_EN bit for MMIO
128 	 */
129 	writel(limit.lo & ~PKG_POWER_LIMIT_EN, MCHBAR_REG(MCHBAR_RAPL_PPL));
130 	writel(limit.hi & ~PKG_POWER_LIMIT_EN, MCHBAR_REG(MCHBAR_RAPL_PPL + 4));
131 
132 	return 0;
133 }
134 
p2sb_unhide(void)135 int p2sb_unhide(void)
136 {
137 	struct udevice *dev;
138 	int ret;
139 
140 	ret = uclass_find_first_device(UCLASS_P2SB, &dev);
141 	if (ret)
142 		return log_msg_ret("p2sb", ret);
143 	ret = p2sb_set_hide(dev, false);
144 	if (ret)
145 		return log_msg_ret("hide", ret);
146 
147 	return 0;
148 }
149 
150 /* Overwrites the SCI IRQ if another IRQ number is given by device tree */
set_sci_irq(void)151 static void set_sci_irq(void)
152 {
153 	/* Skip this for now */
154 }
155 
arch_fsps_preinit(void)156 int arch_fsps_preinit(void)
157 {
158 	struct udevice *itss;
159 	int ret;
160 
161 	if (!ll_boot_init())
162 		return 0;
163 	ret = irq_first_device_type(X86_IRQT_ITSS, &itss);
164 	if (ret)
165 		return log_msg_ret("no itss", ret);
166 
167 	/*
168 	 * Clear the GPI interrupt status and enable registers. These
169 	 * registers do not get reset to default state when booting from S5.
170 	 */
171 	ret = pinctrl_gpi_clear_int_cfg();
172 	if (ret)
173 		return log_msg_ret("gpi_clear", ret);
174 
175 	return 0;
176 }
177 
arch_fsp_init_r(void)178 int arch_fsp_init_r(void)
179 {
180 	bool s3wake;
181 	struct udevice *dev, *itss;
182 	int ret;
183 
184 	if (!ll_boot_init())
185 		return 0;
186 
187 	s3wake = IS_ENABLED(CONFIG_HAVE_ACPI_RESUME) &&
188 		gd->arch.prev_sleep_state == ACPI_S3;
189 
190 	/*
191 	 * This must be called before any devices are probed. Put any probing
192 	 * into arch_fsps_preinit() above.
193 	 *
194 	 * We don't use CONFIG_APL_BOOT_FROM_FAST_SPI_FLASH here since it will
195 	 * force PCI to be probed.
196 	 */
197 	ret = fsp_silicon_init(s3wake, false);
198 	if (ret)
199 		return ret;
200 
201 	ret = irq_first_device_type(X86_IRQT_ITSS, &itss);
202 	if (ret)
203 		return log_msg_ret("no itss", ret);
204 
205 	/*
206 	 * Restore GPIO IRQ polarities back to previous settings. This was
207 	 * stored in reserve_arch() - see X86_IRQT_ITSS
208 	 */
209 	irq_restore_polarities(itss);
210 
211 	/* soc_init() */
212 	ret = p2sb_unhide();
213 	if (ret)
214 		return log_msg_ret("unhide p2sb", ret);
215 
216 	/* Set RAPL MSR for Package power limits*/
217 	ret = uclass_first_device_err(UCLASS_NORTHBRIDGE, &dev);
218 	if (ret)
219 		return log_msg_ret("Cannot get northbridge", ret);
220 	set_power_limits(dev);
221 
222 	/*
223 	 * FSP-S routes SCI to IRQ 9. With the help of this function you can
224 	 * select another IRQ for SCI.
225 	 */
226 	set_sci_irq();
227 
228 	return 0;
229 }
230