1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * From Coreboot northbridge/intel/sandybridge/northbridge.c
4  *
5  * Copyright (C) 2007-2009 coresystems GmbH
6  * Copyright (C) 2011 The Chromium Authors
7  */
8 
9 #include <common.h>
10 #include <dm.h>
11 #include <asm/msr.h>
12 #include <asm/cpu.h>
13 #include <asm/intel_regs.h>
14 #include <asm/io.h>
15 #include <asm/pci.h>
16 #include <asm/processor.h>
17 #include <asm/arch/pch.h>
18 #include <asm/arch/model_206ax.h>
19 #include <asm/arch/sandybridge.h>
20 
21 DECLARE_GLOBAL_DATA_PTR;
22 
23 int bridge_silicon_revision(struct udevice *dev)
24 {
25 	struct cpuid_result result;
26 	u16 bridge_id;
27 	u8 stepping;
28 
29 	result = cpuid(1);
30 	stepping = result.eax & 0xf;
31 	dm_pci_read_config16(dev, PCI_DEVICE_ID, &bridge_id);
32 	bridge_id &= 0xf0;
33 	return bridge_id | stepping;
34 }
35 
36 static int get_pcie_bar(struct udevice *dev, u32 *base, u32 *len)
37 {
38 	u32 pciexbar_reg;
39 
40 	*base = 0;
41 	*len = 0;
42 
43 	dm_pci_read_config32(dev, PCIEXBAR, &pciexbar_reg);
44 
45 	if (!(pciexbar_reg & (1 << 0)))
46 		return 0;
47 
48 	switch ((pciexbar_reg >> 1) & 3) {
49 	case 0: /* 256MB */
50 		*base = pciexbar_reg & ((1 << 31) | (1 << 30) | (1 << 29) |
51 				(1 << 28));
52 		*len = 256 * 1024 * 1024;
53 		return 1;
54 	case 1: /* 128M */
55 		*base = pciexbar_reg & ((1 << 31) | (1 << 30) | (1 << 29) |
56 				(1 << 28) | (1 << 27));
57 		*len = 128 * 1024 * 1024;
58 		return 1;
59 	case 2: /* 64M */
60 		*base = pciexbar_reg & ((1 << 31) | (1 << 30) | (1 << 29) |
61 				(1 << 28) | (1 << 27) | (1 << 26));
62 		*len = 64 * 1024 * 1024;
63 		return 1;
64 	}
65 
66 	return 0;
67 }
68 
69 static void add_fixed_resources(struct udevice *dev, int index)
70 {
71 	u32 pcie_config_base, pcie_config_size;
72 
73 	if (get_pcie_bar(dev, &pcie_config_base, &pcie_config_size)) {
74 		debug("Adding PCIe config bar base=0x%08x size=0x%x\n",
75 		      pcie_config_base, pcie_config_size);
76 	}
77 }
78 
79 static void northbridge_dmi_init(struct udevice *dev, int rev)
80 {
81 	/* Clear error status bits */
82 	writel(0xffffffff, DMIBAR_REG(0x1c4));
83 	writel(0xffffffff, DMIBAR_REG(0x1d0));
84 
85 	/* Steps prior to DMI ASPM */
86 	if ((rev & BASE_REV_MASK) == BASE_REV_SNB) {
87 		clrsetbits_le32(DMIBAR_REG(0x250), (1 << 22) | (1 << 20),
88 				1 << 21);
89 	}
90 
91 	setbits_le32(DMIBAR_REG(0x238), 1 << 29);
92 
93 	if (rev >= SNB_STEP_D0) {
94 		setbits_le32(DMIBAR_REG(0x1f8), 1 << 16);
95 	} else if (rev >= SNB_STEP_D1) {
96 		clrsetbits_le32(DMIBAR_REG(0x1f8), 1 << 26, 1 << 16);
97 		setbits_le32(DMIBAR_REG(0x1fc), (1 << 12) | (1 << 23));
98 	}
99 
100 	/* Enable ASPM on SNB link, should happen before PCH link */
101 	if ((rev & BASE_REV_MASK) == BASE_REV_SNB)
102 		setbits_le32(DMIBAR_REG(0xd04), 1 << 4);
103 
104 	setbits_le32(DMIBAR_REG(0x88), (1 << 1) | (1 << 0));
105 }
106 
107 static void northbridge_init(struct udevice *dev, int rev)
108 {
109 	u32 bridge_type;
110 
111 	add_fixed_resources(dev, 6);
112 	northbridge_dmi_init(dev, rev);
113 
114 	bridge_type = readl(MCHBAR_REG(0x5f10));
115 	bridge_type &= ~0xff;
116 
117 	if ((rev & BASE_REV_MASK) == BASE_REV_IVB) {
118 		/* Enable Power Aware Interrupt Routing - fixed priority */
119 		clrsetbits_8(MCHBAR_REG(0x5418), 0xf, 0x4);
120 
121 		/* 30h for IvyBridge */
122 		bridge_type |= 0x30;
123 	} else {
124 		/* 20h for Sandybridge */
125 		bridge_type |= 0x20;
126 	}
127 	writel(bridge_type, MCHBAR_REG(0x5f10));
128 
129 	/*
130 	 * Set bit 0 of BIOS_RESET_CPL to indicate to the CPU
131 	 * that BIOS has initialized memory and power management
132 	 */
133 	setbits_8(MCHBAR_REG(BIOS_RESET_CPL), 1);
134 	debug("Set BIOS_RESET_CPL\n");
135 
136 	/* Configure turbo power limits 1ms after reset complete bit */
137 	mdelay(1);
138 	set_power_limits(28);
139 
140 	/*
141 	 * CPUs with configurable TDP also need power limits set
142 	 * in MCHBAR.  Use same values from MSR_PKG_POWER_LIMIT.
143 	 */
144 	if (cpu_config_tdp_levels()) {
145 		msr_t msr = msr_read(MSR_PKG_POWER_LIMIT);
146 
147 		writel(msr.lo, MCHBAR_REG(0x59A0));
148 		writel(msr.hi, MCHBAR_REG(0x59A4));
149 	}
150 
151 	/* Set here before graphics PM init */
152 	writel(0x00100001, MCHBAR_REG(0x5500));
153 }
154 
155 static void sandybridge_setup_northbridge_bars(struct udevice *dev)
156 {
157 	/* Set up all hardcoded northbridge BARs */
158 	debug("Setting up static registers\n");
159 	dm_pci_write_config32(dev, EPBAR, DEFAULT_EPBAR | 1);
160 	dm_pci_write_config32(dev, EPBAR + 4, (0LL + DEFAULT_EPBAR) >> 32);
161 	dm_pci_write_config32(dev, MCHBAR, MCH_BASE_ADDRESS | 1);
162 	dm_pci_write_config32(dev, MCHBAR + 4, (0LL + MCH_BASE_ADDRESS) >> 32);
163 	/* 64MB - busses 0-63 */
164 	dm_pci_write_config32(dev, PCIEXBAR, DEFAULT_PCIEXBAR | 5);
165 	dm_pci_write_config32(dev, PCIEXBAR + 4,
166 			      (0LL + DEFAULT_PCIEXBAR) >> 32);
167 	dm_pci_write_config32(dev, DMIBAR, DEFAULT_DMIBAR | 1);
168 	dm_pci_write_config32(dev, DMIBAR + 4, (0LL + DEFAULT_DMIBAR) >> 32);
169 
170 	/* Set C0000-FFFFF to access RAM on both reads and writes */
171 	dm_pci_write_config8(dev, PAM0, 0x30);
172 	dm_pci_write_config8(dev, PAM1, 0x33);
173 	dm_pci_write_config8(dev, PAM2, 0x33);
174 	dm_pci_write_config8(dev, PAM3, 0x33);
175 	dm_pci_write_config8(dev, PAM4, 0x33);
176 	dm_pci_write_config8(dev, PAM5, 0x33);
177 	dm_pci_write_config8(dev, PAM6, 0x33);
178 }
179 
180 /**
181  * sandybridge_init_iommu() - Set up IOMMU so that azalia can be used
182  *
183  * It is not obvious where these values come from. They may be undocumented.
184  */
185 static void sandybridge_init_iommu(struct udevice *dev)
186 {
187 	u32 capid0_a;
188 
189 	dm_pci_read_config32(dev, 0xe4, &capid0_a);
190 	if (capid0_a & (1 << 23)) {
191 		log_debug("capid0_a not needed\n");
192 		return;
193 	}
194 
195 	/* setup BARs */
196 	writel(IOMMU_BASE1 >> 32, MCHBAR_REG(0x5404));
197 	writel(IOMMU_BASE1 | 1, MCHBAR_REG(0x5400));
198 	writel(IOMMU_BASE2 >> 32, MCHBAR_REG(0x5414));
199 	writel(IOMMU_BASE2 | 1, MCHBAR_REG(0x5410));
200 
201 	/* lock policies */
202 	writel(0x80000000, IOMMU_BASE1 + 0xff0);
203 
204 	/* Enable azalia sound */
205 	writel(0x20000000, IOMMU_BASE2 + 0xff0);
206 	writel(0xa0000000, IOMMU_BASE2 + 0xff0);
207 }
208 
209 static int bd82x6x_northbridge_early_init(struct udevice *dev)
210 {
211 	const int chipset_type = SANDYBRIDGE_MOBILE;
212 	u32 capid0_a;
213 	u8 reg8;
214 
215 	/* Device ID Override Enable should be done very early */
216 	dm_pci_read_config32(dev, 0xe4, &capid0_a);
217 	if (capid0_a & (1 << 10)) {
218 		dm_pci_read_config8(dev, 0xf3, &reg8);
219 		reg8 &= ~7; /* Clear 2:0 */
220 
221 		if (chipset_type == SANDYBRIDGE_MOBILE)
222 			reg8 |= 1; /* Set bit 0 */
223 
224 		dm_pci_write_config8(dev, 0xf3, reg8);
225 	}
226 
227 	sandybridge_setup_northbridge_bars(dev);
228 
229 	/* Setup IOMMU BARs */
230 	sandybridge_init_iommu(dev);
231 
232 	/* Device Enable */
233 	dm_pci_write_config32(dev, DEVEN, DEVEN_HOST | DEVEN_IGD);
234 
235 	return 0;
236 }
237 
238 static int bd82x6x_northbridge_probe(struct udevice *dev)
239 {
240 	int rev;
241 
242 	if (!(gd->flags & GD_FLG_RELOC))
243 		return bd82x6x_northbridge_early_init(dev);
244 
245 	rev = bridge_silicon_revision(dev);
246 	northbridge_init(dev, rev);
247 
248 	return 0;
249 }
250 
251 static const struct udevice_id bd82x6x_northbridge_ids[] = {
252 	{ .compatible = "intel,bd82x6x-northbridge" },
253 	{ }
254 };
255 
256 U_BOOT_DRIVER(bd82x6x_northbridge_drv) = {
257 	.name		= "bd82x6x_northbridge",
258 	.id		= UCLASS_NORTHBRIDGE,
259 	.of_match	= bd82x6x_northbridge_ids,
260 	.probe		= bd82x6x_northbridge_probe,
261 };
262