xref: /openbmc/u-boot/arch/x86/cpu/broadwell/pch.c (revision 1e6f4e58862088f31cae350d73f0b1162d0ceb46)
1*1e6f4e58SSimon Glass /*
2*1e6f4e58SSimon Glass  * Copyright (c) 2016 Google, Inc
3*1e6f4e58SSimon Glass  *
4*1e6f4e58SSimon Glass  * SPDX-License-Identifier:	GPL-2.0
5*1e6f4e58SSimon Glass  */
6*1e6f4e58SSimon Glass 
7*1e6f4e58SSimon Glass #include <common.h>
8*1e6f4e58SSimon Glass #include <dm.h>
9*1e6f4e58SSimon Glass #include <pch.h>
10*1e6f4e58SSimon Glass #include <asm/cpu.h>
11*1e6f4e58SSimon Glass #include <asm/gpio.h>
12*1e6f4e58SSimon Glass #include <asm/i8259.h>
13*1e6f4e58SSimon Glass #include <asm/intel_regs.h>
14*1e6f4e58SSimon Glass #include <asm/io.h>
15*1e6f4e58SSimon Glass #include <asm/ioapic.h>
16*1e6f4e58SSimon Glass #include <asm/lpc_common.h>
17*1e6f4e58SSimon Glass #include <asm/pch_common.h>
18*1e6f4e58SSimon Glass #include <asm/arch/cpu.h>
19*1e6f4e58SSimon Glass #include <asm/arch/gpio.h>
20*1e6f4e58SSimon Glass #include <asm/arch/iomap.h>
21*1e6f4e58SSimon Glass #include <asm/arch/pch.h>
22*1e6f4e58SSimon Glass #include <asm/arch/pm.h>
23*1e6f4e58SSimon Glass #include <asm/arch/rcb.h>
24*1e6f4e58SSimon Glass #include <asm/arch/spi.h>
25*1e6f4e58SSimon Glass 
26*1e6f4e58SSimon Glass #define BIOS_CTRL	0xdc
27*1e6f4e58SSimon Glass 
28*1e6f4e58SSimon Glass bool cpu_is_ult(void)
29*1e6f4e58SSimon Glass {
30*1e6f4e58SSimon Glass 	u32 fm = cpu_get_family_model();
31*1e6f4e58SSimon Glass 
32*1e6f4e58SSimon Glass 	return fm == BROADWELL_FAMILY_ULT || fm == HASWELL_FAMILY_ULT;
33*1e6f4e58SSimon Glass }
34*1e6f4e58SSimon Glass 
35*1e6f4e58SSimon Glass static int broadwell_pch_early_init(struct udevice *dev)
36*1e6f4e58SSimon Glass {
37*1e6f4e58SSimon Glass 	struct gpio_desc desc;
38*1e6f4e58SSimon Glass 	struct udevice *bus;
39*1e6f4e58SSimon Glass 	pci_dev_t bdf;
40*1e6f4e58SSimon Glass 	int ret;
41*1e6f4e58SSimon Glass 
42*1e6f4e58SSimon Glass 	dm_pci_write_config32(dev, PCH_RCBA, RCB_BASE_ADDRESS | 1);
43*1e6f4e58SSimon Glass 
44*1e6f4e58SSimon Glass 	dm_pci_write_config32(dev, PMBASE, ACPI_BASE_ADDRESS | 1);
45*1e6f4e58SSimon Glass 	dm_pci_write_config8(dev, ACPI_CNTL, ACPI_EN);
46*1e6f4e58SSimon Glass 	dm_pci_write_config32(dev, GPIO_BASE, GPIO_BASE_ADDRESS | 1);
47*1e6f4e58SSimon Glass 	dm_pci_write_config8(dev, GPIO_CNTL, GPIO_EN);
48*1e6f4e58SSimon Glass 
49*1e6f4e58SSimon Glass 	/* Enable IOAPIC */
50*1e6f4e58SSimon Glass 	writew(0x1000, RCB_REG(OIC));
51*1e6f4e58SSimon Glass 	/* Read back for posted write */
52*1e6f4e58SSimon Glass 	readw(RCB_REG(OIC));
53*1e6f4e58SSimon Glass 
54*1e6f4e58SSimon Glass 	/* Set HPET address and enable it */
55*1e6f4e58SSimon Glass 	clrsetbits_le32(RCB_REG(HPTC), 3, 1 << 7);
56*1e6f4e58SSimon Glass 	/* Read back for posted write */
57*1e6f4e58SSimon Glass 	readl(RCB_REG(HPTC));
58*1e6f4e58SSimon Glass 	/* Enable HPET to start counter */
59*1e6f4e58SSimon Glass 	setbits_le32(HPET_BASE_ADDRESS + 0x10, 1 << 0);
60*1e6f4e58SSimon Glass 
61*1e6f4e58SSimon Glass 	setbits_le32(RCB_REG(GCS), 1 << 5);
62*1e6f4e58SSimon Glass 
63*1e6f4e58SSimon Glass 	/*
64*1e6f4e58SSimon Glass 	 * Enable PP3300_AUTOBAHN_EN after initial GPIO setup
65*1e6f4e58SSimon Glass 	 * to prevent possible brownout. This will cause the GPIOs to be set
66*1e6f4e58SSimon Glass 	 * up if it has not been done already.
67*1e6f4e58SSimon Glass 	 */
68*1e6f4e58SSimon Glass 	ret = gpio_request_by_name(dev, "power-enable-gpio", 0, &desc,
69*1e6f4e58SSimon Glass 				   GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE);
70*1e6f4e58SSimon Glass 	if (ret)
71*1e6f4e58SSimon Glass 		return ret;
72*1e6f4e58SSimon Glass 
73*1e6f4e58SSimon Glass 	/* 8.14 Additional PCI Express Programming Steps, step #1 */
74*1e6f4e58SSimon Glass 	bdf = PCI_BDF(0, 0x1c, 0);
75*1e6f4e58SSimon Glass 	bus = pci_get_controller(dev);
76*1e6f4e58SSimon Glass 	pci_bus_clrset_config32(bus, bdf, 0xf4, 0x60, 0);
77*1e6f4e58SSimon Glass 	pci_bus_clrset_config32(bus, bdf, 0xf4, 0x80, 0x80);
78*1e6f4e58SSimon Glass 	pci_bus_clrset_config32(bus, bdf, 0xe2, 0x30, 0x30);
79*1e6f4e58SSimon Glass 
80*1e6f4e58SSimon Glass 	return 0;
81*1e6f4e58SSimon Glass }
82*1e6f4e58SSimon Glass 
83*1e6f4e58SSimon Glass static void pch_misc_init(struct udevice *dev)
84*1e6f4e58SSimon Glass {
85*1e6f4e58SSimon Glass 	/* Setup SLP signal assertion, SLP_S4=4s, SLP_S3=50ms */
86*1e6f4e58SSimon Glass 	dm_pci_clrset_config8(dev, GEN_PMCON_3, 3 << 4 | 1 << 10,
87*1e6f4e58SSimon Glass 			      1 << 3 | 1 << 11 | 1 << 12);
88*1e6f4e58SSimon Glass 	/* Prepare sleep mode */
89*1e6f4e58SSimon Glass 	clrsetio_32(ACPI_BASE_ADDRESS + PM1_CNT, SLP_TYP, SCI_EN);
90*1e6f4e58SSimon Glass 
91*1e6f4e58SSimon Glass 	/* Setup NMI on errors, disable SERR */
92*1e6f4e58SSimon Glass 	clrsetio_8(0x61, 0xf0, 1 << 2);
93*1e6f4e58SSimon Glass 	/* Disable NMI sources */
94*1e6f4e58SSimon Glass 	setio_8(0x70, 1 << 7);
95*1e6f4e58SSimon Glass 	/* Indicate DRAM init done for MRC */
96*1e6f4e58SSimon Glass 	dm_pci_clrset_config8(dev, GEN_PMCON_2, 0, 1 << 7);
97*1e6f4e58SSimon Glass 
98*1e6f4e58SSimon Glass 	/* Clear status bits to prevent unexpected wake */
99*1e6f4e58SSimon Glass 	setbits_le32(RCB_REG(0x3310), 0x0000002f);
100*1e6f4e58SSimon Glass 	clrsetbits_le32(RCB_REG(0x3f02), 0x0000000f, 0);
101*1e6f4e58SSimon Glass 	/* Enable PCIe Relaxed Order */
102*1e6f4e58SSimon Glass 	setbits_le32(RCB_REG(0x2314), 1 << 31 | 1 << 7);
103*1e6f4e58SSimon Glass 	setbits_le32(RCB_REG(0x1114), 1 << 15 | 1 << 14);
104*1e6f4e58SSimon Glass 	/* Setup SERIRQ, enable continuous mode */
105*1e6f4e58SSimon Glass 	dm_pci_clrset_config8(dev, SERIRQ_CNTL, 0, 1 << 7 | 1 << 6);
106*1e6f4e58SSimon Glass };
107*1e6f4e58SSimon Glass 
108*1e6f4e58SSimon Glass static void pch_enable_ioapic(void)
109*1e6f4e58SSimon Glass {
110*1e6f4e58SSimon Glass 	u32 reg32;
111*1e6f4e58SSimon Glass 
112*1e6f4e58SSimon Glass 	io_apic_set_id(0x02);
113*1e6f4e58SSimon Glass 
114*1e6f4e58SSimon Glass 	/* affirm full set of redirection table entries ("write once") */
115*1e6f4e58SSimon Glass 	reg32 = io_apic_read(0x01);
116*1e6f4e58SSimon Glass 
117*1e6f4e58SSimon Glass 	/* PCH-LP has 39 redirection entries */
118*1e6f4e58SSimon Glass 	reg32 &= ~0x00ff0000;
119*1e6f4e58SSimon Glass 	reg32 |= 0x00270000;
120*1e6f4e58SSimon Glass 
121*1e6f4e58SSimon Glass 	io_apic_write(0x01, reg32);
122*1e6f4e58SSimon Glass 
123*1e6f4e58SSimon Glass 	/*
124*1e6f4e58SSimon Glass 	 * Select Boot Configuration register (0x03) and
125*1e6f4e58SSimon Glass 	 * use Processor System Bus (0x01) to deliver interrupts.
126*1e6f4e58SSimon Glass 	 */
127*1e6f4e58SSimon Glass 	io_apic_write(0x03, 0x01);
128*1e6f4e58SSimon Glass }
129*1e6f4e58SSimon Glass 
130*1e6f4e58SSimon Glass /* Enable all requested GPE */
131*1e6f4e58SSimon Glass void enable_all_gpe(u32 set1, u32 set2, u32 set3, u32 set4)
132*1e6f4e58SSimon Glass {
133*1e6f4e58SSimon Glass 	outl(set1, ACPI_BASE_ADDRESS + GPE0_EN(GPE_31_0));
134*1e6f4e58SSimon Glass 	outl(set2, ACPI_BASE_ADDRESS + GPE0_EN(GPE_63_32));
135*1e6f4e58SSimon Glass 	outl(set3, ACPI_BASE_ADDRESS + GPE0_EN(GPE_94_64));
136*1e6f4e58SSimon Glass 	outl(set4, ACPI_BASE_ADDRESS + GPE0_EN(GPE_STD));
137*1e6f4e58SSimon Glass }
138*1e6f4e58SSimon Glass 
139*1e6f4e58SSimon Glass /*
140*1e6f4e58SSimon Glass  * Enable GPIO SMI events - it would be good to put this in the GPIO driver
141*1e6f4e58SSimon Glass  * but it would need a new driver operation.
142*1e6f4e58SSimon Glass  */
143*1e6f4e58SSimon Glass int enable_alt_smi(struct udevice *pch, u32 mask)
144*1e6f4e58SSimon Glass {
145*1e6f4e58SSimon Glass 	struct pch_lp_gpio_regs *regs;
146*1e6f4e58SSimon Glass 	u32 gpiobase;
147*1e6f4e58SSimon Glass 	int ret;
148*1e6f4e58SSimon Glass 
149*1e6f4e58SSimon Glass 	ret = pch_get_gpio_base(pch, &gpiobase);
150*1e6f4e58SSimon Glass 	if (ret) {
151*1e6f4e58SSimon Glass 		debug("%s: invalid GPIOBASE address (%08x)\n", __func__,
152*1e6f4e58SSimon Glass 		      gpiobase);
153*1e6f4e58SSimon Glass 		return -EINVAL;
154*1e6f4e58SSimon Glass 	}
155*1e6f4e58SSimon Glass 
156*1e6f4e58SSimon Glass 	regs = (struct pch_lp_gpio_regs *)gpiobase;
157*1e6f4e58SSimon Glass 	setio_32(regs->alt_gpi_smi_en, mask);
158*1e6f4e58SSimon Glass 
159*1e6f4e58SSimon Glass 	return 0;
160*1e6f4e58SSimon Glass }
161*1e6f4e58SSimon Glass 
162*1e6f4e58SSimon Glass static int pch_power_options(struct udevice *dev)
163*1e6f4e58SSimon Glass {
164*1e6f4e58SSimon Glass 	int pwr_on_after_power_fail = MAINBOARD_POWER_OFF;
165*1e6f4e58SSimon Glass 	const char *state;
166*1e6f4e58SSimon Glass 	u32 enable[4];
167*1e6f4e58SSimon Glass 	u16 reg16;
168*1e6f4e58SSimon Glass 	int ret;
169*1e6f4e58SSimon Glass 
170*1e6f4e58SSimon Glass 	dm_pci_read_config16(dev, GEN_PMCON_3, &reg16);
171*1e6f4e58SSimon Glass 	reg16 &= 0xfffe;
172*1e6f4e58SSimon Glass 	switch (pwr_on_after_power_fail) {
173*1e6f4e58SSimon Glass 	case MAINBOARD_POWER_OFF:
174*1e6f4e58SSimon Glass 		reg16 |= 1;
175*1e6f4e58SSimon Glass 		state = "off";
176*1e6f4e58SSimon Glass 		break;
177*1e6f4e58SSimon Glass 	case MAINBOARD_POWER_ON:
178*1e6f4e58SSimon Glass 		reg16 &= ~1;
179*1e6f4e58SSimon Glass 		state = "on";
180*1e6f4e58SSimon Glass 		break;
181*1e6f4e58SSimon Glass 	case MAINBOARD_POWER_KEEP:
182*1e6f4e58SSimon Glass 		reg16 &= ~1;
183*1e6f4e58SSimon Glass 		state = "state keep";
184*1e6f4e58SSimon Glass 		break;
185*1e6f4e58SSimon Glass 	default:
186*1e6f4e58SSimon Glass 		state = "undefined";
187*1e6f4e58SSimon Glass 	}
188*1e6f4e58SSimon Glass 	dm_pci_write_config16(dev, GEN_PMCON_3, reg16);
189*1e6f4e58SSimon Glass 	debug("Set power %s after power failure.\n", state);
190*1e6f4e58SSimon Glass 
191*1e6f4e58SSimon Glass 	/* GPE setup based on device tree configuration */
192*1e6f4e58SSimon Glass 	ret = fdtdec_get_int_array(gd->fdt_blob, dev->of_offset,
193*1e6f4e58SSimon Glass 				   "intel,gpe0-en", enable, ARRAY_SIZE(enable));
194*1e6f4e58SSimon Glass 	if (ret)
195*1e6f4e58SSimon Glass 		return -EINVAL;
196*1e6f4e58SSimon Glass 	enable_all_gpe(enable[0], enable[1], enable[2], enable[3]);
197*1e6f4e58SSimon Glass 
198*1e6f4e58SSimon Glass 	/* SMI setup based on device tree configuration */
199*1e6f4e58SSimon Glass 	enable_alt_smi(dev, fdtdec_get_int(gd->fdt_blob, dev->of_offset,
200*1e6f4e58SSimon Glass 					   "intel,alt-gp-smi-enable", 0));
201*1e6f4e58SSimon Glass 
202*1e6f4e58SSimon Glass 	return 0;
203*1e6f4e58SSimon Glass }
204*1e6f4e58SSimon Glass 
205*1e6f4e58SSimon Glass /* Magic register settings for power management */
206*1e6f4e58SSimon Glass static void pch_pm_init_magic(struct udevice *dev)
207*1e6f4e58SSimon Glass {
208*1e6f4e58SSimon Glass 	dm_pci_write_config8(dev, 0xa9, 0x46);
209*1e6f4e58SSimon Glass 	clrbits_le32(RCB_REG(0x232c), 1),
210*1e6f4e58SSimon Glass 	setbits_le32(RCB_REG(0x1100), 0x0000c13f);
211*1e6f4e58SSimon Glass 	clrsetbits_le32(RCB_REG(0x2320), 0x60, 0x10);
212*1e6f4e58SSimon Glass 	writel(0x00012fff, RCB_REG(0x3314));
213*1e6f4e58SSimon Glass 	clrsetbits_le32(RCB_REG(0x3318), 0x000f0330, 0x0dcf0400);
214*1e6f4e58SSimon Glass 	writel(0x04000000, RCB_REG(0x3324));
215*1e6f4e58SSimon Glass 	writel(0x00041400, RCB_REG(0x3368));
216*1e6f4e58SSimon Glass 	writel(0x3f8ddbff, RCB_REG(0x3388));
217*1e6f4e58SSimon Glass 	writel(0x00007001, RCB_REG(0x33ac));
218*1e6f4e58SSimon Glass 	writel(0x00181900, RCB_REG(0x33b0));
219*1e6f4e58SSimon Glass 	writel(0x00060A00, RCB_REG(0x33c0));
220*1e6f4e58SSimon Glass 	writel(0x06200840, RCB_REG(0x33d0));
221*1e6f4e58SSimon Glass 	writel(0x01010101, RCB_REG(0x3a28));
222*1e6f4e58SSimon Glass 	writel(0x040c0404, RCB_REG(0x3a2c));
223*1e6f4e58SSimon Glass 	writel(0x9000000a, RCB_REG(0x3a9c));
224*1e6f4e58SSimon Glass 	writel(0x03808033, RCB_REG(0x2b1c));
225*1e6f4e58SSimon Glass 	writel(0x80000009, RCB_REG(0x2b34));
226*1e6f4e58SSimon Glass 	writel(0x022ddfff, RCB_REG(0x3348));
227*1e6f4e58SSimon Glass 	writel(0x00000001, RCB_REG(0x334c));
228*1e6f4e58SSimon Glass 	writel(0x0001c000, RCB_REG(0x3358));
229*1e6f4e58SSimon Glass 	writel(0x3f8ddbff, RCB_REG(0x3380));
230*1e6f4e58SSimon Glass 	writel(0x0001c7e1, RCB_REG(0x3384));
231*1e6f4e58SSimon Glass 	writel(0x0001c7e1, RCB_REG(0x338c));
232*1e6f4e58SSimon Glass 	writel(0x0001c000, RCB_REG(0x3398));
233*1e6f4e58SSimon Glass 	writel(0x00181900, RCB_REG(0x33a8));
234*1e6f4e58SSimon Glass 	writel(0x00080000, RCB_REG(0x33dc));
235*1e6f4e58SSimon Glass 	writel(0x00000001, RCB_REG(0x33e0));
236*1e6f4e58SSimon Glass 	writel(0x0000040c, RCB_REG(0x3a20));
237*1e6f4e58SSimon Glass 	writel(0x01010101, RCB_REG(0x3a24));
238*1e6f4e58SSimon Glass 	writel(0x01010101, RCB_REG(0x3a30));
239*1e6f4e58SSimon Glass 	dm_pci_clrset_config32(dev, 0xac, 0x00200000, 0);
240*1e6f4e58SSimon Glass 	setbits_le32(RCB_REG(0x0410), 0x00000003);
241*1e6f4e58SSimon Glass 	setbits_le32(RCB_REG(0x2618), 0x08000000);
242*1e6f4e58SSimon Glass 	setbits_le32(RCB_REG(0x2300), 0x00000002);
243*1e6f4e58SSimon Glass 	setbits_le32(RCB_REG(0x2600), 0x00000008);
244*1e6f4e58SSimon Glass 	writel(0x00007001, RCB_REG(0x33b4));
245*1e6f4e58SSimon Glass 	writel(0x022ddfff, RCB_REG(0x3350));
246*1e6f4e58SSimon Glass 	writel(0x00000001, RCB_REG(0x3354));
247*1e6f4e58SSimon Glass 	/* Power Optimizer */
248*1e6f4e58SSimon Glass 	setbits_le32(RCB_REG(0x33d4), 0x08000000);
249*1e6f4e58SSimon Glass 	/*
250*1e6f4e58SSimon Glass 	 * This stops the LCD from turning on:
251*1e6f4e58SSimon Glass 	 * setbits_le32(RCB_REG(0x33c8), 0x08000080);
252*1e6f4e58SSimon Glass 	 */
253*1e6f4e58SSimon Glass 	writel(0x0000883c, RCB_REG(0x2b10));
254*1e6f4e58SSimon Glass 	writel(0x1e0a4616, RCB_REG(0x2b14));
255*1e6f4e58SSimon Glass 	writel(0x40000005, RCB_REG(0x2b24));
256*1e6f4e58SSimon Glass 	writel(0x0005db01, RCB_REG(0x2b20));
257*1e6f4e58SSimon Glass 	writel(0x05145005, RCB_REG(0x3a80));
258*1e6f4e58SSimon Glass 	writel(0x00001005, RCB_REG(0x3a84));
259*1e6f4e58SSimon Glass 	setbits_le32(RCB_REG(0x33d4), 0x2fff2fb1);
260*1e6f4e58SSimon Glass 	setbits_le32(RCB_REG(0x33c8), 0x00008000);
261*1e6f4e58SSimon Glass };
262*1e6f4e58SSimon Glass 
263*1e6f4e58SSimon Glass static int pch_type(struct udevice *dev)
264*1e6f4e58SSimon Glass {
265*1e6f4e58SSimon Glass 	u16 type;
266*1e6f4e58SSimon Glass 
267*1e6f4e58SSimon Glass 	dm_pci_read_config16(dev, PCI_DEVICE_ID, &type);
268*1e6f4e58SSimon Glass 
269*1e6f4e58SSimon Glass 	return type;
270*1e6f4e58SSimon Glass }
271*1e6f4e58SSimon Glass 
272*1e6f4e58SSimon Glass /* Return 1 if PCH type is WildcatPoint */
273*1e6f4e58SSimon Glass static int pch_is_wpt(struct udevice *dev)
274*1e6f4e58SSimon Glass {
275*1e6f4e58SSimon Glass 	return ((pch_type(dev) & 0xfff0) == 0x9cc0) ? 1 : 0;
276*1e6f4e58SSimon Glass }
277*1e6f4e58SSimon Glass 
278*1e6f4e58SSimon Glass /* Return 1 if PCH type is WildcatPoint ULX */
279*1e6f4e58SSimon Glass static int pch_is_wpt_ulx(struct udevice *dev)
280*1e6f4e58SSimon Glass {
281*1e6f4e58SSimon Glass 	u16 lpcid = pch_type(dev);
282*1e6f4e58SSimon Glass 
283*1e6f4e58SSimon Glass 	switch (lpcid) {
284*1e6f4e58SSimon Glass 	case PCH_WPT_BDW_Y_SAMPLE:
285*1e6f4e58SSimon Glass 	case PCH_WPT_BDW_Y_PREMIUM:
286*1e6f4e58SSimon Glass 	case PCH_WPT_BDW_Y_BASE:
287*1e6f4e58SSimon Glass 		return 1;
288*1e6f4e58SSimon Glass 	}
289*1e6f4e58SSimon Glass 
290*1e6f4e58SSimon Glass 	return 0;
291*1e6f4e58SSimon Glass }
292*1e6f4e58SSimon Glass 
293*1e6f4e58SSimon Glass static u32 pch_read_soft_strap(int id)
294*1e6f4e58SSimon Glass {
295*1e6f4e58SSimon Glass 	clrbits_le32(SPI_REG(SPIBAR_FDOC), 0x00007ffc);
296*1e6f4e58SSimon Glass 	setbits_le32(SPI_REG(SPIBAR_FDOC), 0x00004000 | id * 4);
297*1e6f4e58SSimon Glass 
298*1e6f4e58SSimon Glass 	return readl(SPI_REG(SPIBAR_FDOD));
299*1e6f4e58SSimon Glass }
300*1e6f4e58SSimon Glass 
301*1e6f4e58SSimon Glass static void pch_enable_mphy(struct udevice *dev)
302*1e6f4e58SSimon Glass {
303*1e6f4e58SSimon Glass 	u32 data_and = 0xffffffff;
304*1e6f4e58SSimon Glass 	u32 data_or = (1 << 14) | (1 << 13) | (1 << 12);
305*1e6f4e58SSimon Glass 
306*1e6f4e58SSimon Glass 	data_or |= (1 << 0);
307*1e6f4e58SSimon Glass 	if (pch_is_wpt(dev)) {
308*1e6f4e58SSimon Glass 		data_and &= ~((1 << 7) | (1 << 6) | (1 << 3));
309*1e6f4e58SSimon Glass 		data_or |= (1 << 5) | (1 << 4);
310*1e6f4e58SSimon Glass 
311*1e6f4e58SSimon Glass 		if (pch_is_wpt_ulx(dev)) {
312*1e6f4e58SSimon Glass 			/* Check if SATA and USB3 MPHY are enabled */
313*1e6f4e58SSimon Glass 			u32 strap19 = pch_read_soft_strap(19);
314*1e6f4e58SSimon Glass 			strap19 &= ((1 << 31) | (1 << 30));
315*1e6f4e58SSimon Glass 			strap19 >>= 30;
316*1e6f4e58SSimon Glass 			if (strap19 == 3) {
317*1e6f4e58SSimon Glass 				data_or |= (1 << 3);
318*1e6f4e58SSimon Glass 				debug("Enable ULX MPHY PG control in single domain\n");
319*1e6f4e58SSimon Glass 			} else if (strap19 == 0) {
320*1e6f4e58SSimon Glass 				debug("Enable ULX MPHY PG control in split domains\n");
321*1e6f4e58SSimon Glass 			} else {
322*1e6f4e58SSimon Glass 				debug("Invalid PCH Soft Strap 19 configuration\n");
323*1e6f4e58SSimon Glass 			}
324*1e6f4e58SSimon Glass 		} else {
325*1e6f4e58SSimon Glass 			data_or |= (1 << 3);
326*1e6f4e58SSimon Glass 		}
327*1e6f4e58SSimon Glass 	}
328*1e6f4e58SSimon Glass 
329*1e6f4e58SSimon Glass 	pch_iobp_update(0xCF000000, data_and, data_or);
330*1e6f4e58SSimon Glass }
331*1e6f4e58SSimon Glass 
332*1e6f4e58SSimon Glass static void pch_init_deep_sx(bool deep_sx_enable_ac, bool deep_sx_enable_dc)
333*1e6f4e58SSimon Glass {
334*1e6f4e58SSimon Glass 	if (deep_sx_enable_ac) {
335*1e6f4e58SSimon Glass 		setbits_le32(RCB_REG(DEEP_S3_POL), DEEP_S3_EN_AC);
336*1e6f4e58SSimon Glass 		setbits_le32(RCB_REG(DEEP_S5_POL), DEEP_S5_EN_AC);
337*1e6f4e58SSimon Glass 	}
338*1e6f4e58SSimon Glass 
339*1e6f4e58SSimon Glass 	if (deep_sx_enable_dc) {
340*1e6f4e58SSimon Glass 		setbits_le32(RCB_REG(DEEP_S3_POL), DEEP_S3_EN_DC);
341*1e6f4e58SSimon Glass 		setbits_le32(RCB_REG(DEEP_S5_POL), DEEP_S5_EN_DC);
342*1e6f4e58SSimon Glass 	}
343*1e6f4e58SSimon Glass 
344*1e6f4e58SSimon Glass 	if (deep_sx_enable_ac || deep_sx_enable_dc) {
345*1e6f4e58SSimon Glass 		setbits_le32(RCB_REG(DEEP_SX_CONFIG),
346*1e6f4e58SSimon Glass 			     DEEP_SX_WAKE_PIN_EN | DEEP_SX_GP27_PIN_EN);
347*1e6f4e58SSimon Glass 	}
348*1e6f4e58SSimon Glass }
349*1e6f4e58SSimon Glass 
350*1e6f4e58SSimon Glass /* Power Management init */
351*1e6f4e58SSimon Glass static void pch_pm_init(struct udevice *dev)
352*1e6f4e58SSimon Glass {
353*1e6f4e58SSimon Glass 	debug("PCH PM init\n");
354*1e6f4e58SSimon Glass 
355*1e6f4e58SSimon Glass 	pch_init_deep_sx(false, false);
356*1e6f4e58SSimon Glass 	pch_enable_mphy(dev);
357*1e6f4e58SSimon Glass 	pch_pm_init_magic(dev);
358*1e6f4e58SSimon Glass 
359*1e6f4e58SSimon Glass 	if (pch_is_wpt(dev)) {
360*1e6f4e58SSimon Glass 		setbits_le32(RCB_REG(0x33e0), 1 << 4 | 1 << 1);
361*1e6f4e58SSimon Glass 		setbits_le32(RCB_REG(0x2b1c), 1 << 22 | 1 << 14 | 1 << 13);
362*1e6f4e58SSimon Glass 		writel(0x16bf0002, RCB_REG(0x33e4));
363*1e6f4e58SSimon Glass 		setbits_le32(RCB_REG(0x33e4), 0x1);
364*1e6f4e58SSimon Glass 	}
365*1e6f4e58SSimon Glass 
366*1e6f4e58SSimon Glass 	pch_iobp_update(0xCA000000, ~0UL, 0x00000009);
367*1e6f4e58SSimon Glass 
368*1e6f4e58SSimon Glass 	/* Set RCBA 0x2b1c[29]=1 if DSP disabled */
369*1e6f4e58SSimon Glass 	if (readl(RCB_REG(FD)) & PCH_DISABLE_ADSPD)
370*1e6f4e58SSimon Glass 		setbits_le32(RCB_REG(0x2b1c), 1 << 29);
371*1e6f4e58SSimon Glass }
372*1e6f4e58SSimon Glass 
373*1e6f4e58SSimon Glass static void pch_cg_init(struct udevice *dev)
374*1e6f4e58SSimon Glass {
375*1e6f4e58SSimon Glass 	struct udevice *bus = pci_get_controller(dev);
376*1e6f4e58SSimon Glass 	u32 reg32;
377*1e6f4e58SSimon Glass 	u16 reg16;
378*1e6f4e58SSimon Glass 	ulong val;
379*1e6f4e58SSimon Glass 
380*1e6f4e58SSimon Glass 	/* DMI */
381*1e6f4e58SSimon Glass 	setbits_le32(RCB_REG(0x2234), 0xf);
382*1e6f4e58SSimon Glass 
383*1e6f4e58SSimon Glass 	dm_pci_read_config16(dev, GEN_PMCON_1, &reg16);
384*1e6f4e58SSimon Glass 	reg16 &= ~(1 << 10); /* Disable BIOS_PCI_EXP_EN for native PME */
385*1e6f4e58SSimon Glass 	if (pch_is_wpt(dev))
386*1e6f4e58SSimon Glass 		reg16 &= ~(1 << 11);
387*1e6f4e58SSimon Glass 	else
388*1e6f4e58SSimon Glass 		reg16 |= 1 << 11;
389*1e6f4e58SSimon Glass 	reg16 |= 1 << 5 | 1 << 6 | 1 << 7 | 1 << 12;
390*1e6f4e58SSimon Glass 	reg16 |= 1 << 2; /* PCI CLKRUN# Enable */
391*1e6f4e58SSimon Glass 	dm_pci_write_config16(dev, GEN_PMCON_1, reg16);
392*1e6f4e58SSimon Glass 
393*1e6f4e58SSimon Glass 	/*
394*1e6f4e58SSimon Glass 	 * RCBA + 0x2614[27:25,14:13,10,8] = 101,11,1,1
395*1e6f4e58SSimon Glass 	 * RCBA + 0x2614[23:16] = 0x20
396*1e6f4e58SSimon Glass 	 * RCBA + 0x2614[30:28] = 0x0
397*1e6f4e58SSimon Glass 	 * RCBA + 0x2614[26] = 1 (IF 0:2.0@0x08 >= 0x0b)
398*1e6f4e58SSimon Glass 	 */
399*1e6f4e58SSimon Glass 	clrsetbits_le32(RCB_REG(0x2614), 0x64ff0000, 0x0a206500);
400*1e6f4e58SSimon Glass 
401*1e6f4e58SSimon Glass 	/* Check for 0:2.0@0x08 >= 0x0b */
402*1e6f4e58SSimon Glass 	pci_bus_read_config(bus, PCI_BDF(0, 0x2, 0), 0x8, &val, PCI_SIZE_8);
403*1e6f4e58SSimon Glass 	if (pch_is_wpt(dev) || val >= 0x0b)
404*1e6f4e58SSimon Glass 		setbits_le32(RCB_REG(0x2614), 1 << 26);
405*1e6f4e58SSimon Glass 
406*1e6f4e58SSimon Glass 	setbits_le32(RCB_REG(0x900), 0x0000031f);
407*1e6f4e58SSimon Glass 
408*1e6f4e58SSimon Glass 	reg32 = readl(RCB_REG(CG));
409*1e6f4e58SSimon Glass 	if (readl(RCB_REG(0x3454)) & (1 << 4))
410*1e6f4e58SSimon Glass 		reg32 &= ~(1 << 29); /* LPC Dynamic */
411*1e6f4e58SSimon Glass 	else
412*1e6f4e58SSimon Glass 		reg32 |= (1 << 29); /* LPC Dynamic */
413*1e6f4e58SSimon Glass 	reg32 |= 1 << 31; /* LP LPC */
414*1e6f4e58SSimon Glass 	reg32 |= 1 << 30; /* LP BLA */
415*1e6f4e58SSimon Glass 	if (readl(RCB_REG(0x3454)) & (1 << 4))
416*1e6f4e58SSimon Glass 		reg32 &= ~(1 << 29);
417*1e6f4e58SSimon Glass 	else
418*1e6f4e58SSimon Glass 		reg32 |= 1 << 29;
419*1e6f4e58SSimon Glass 	reg32 |= 1 << 28; /* GPIO Dynamic */
420*1e6f4e58SSimon Glass 	reg32 |= 1 << 27; /* HPET Dynamic */
421*1e6f4e58SSimon Glass 	reg32 |= 1 << 26; /* Generic Platform Event Clock */
422*1e6f4e58SSimon Glass 	if (readl(RCB_REG(BUC)) & PCH_DISABLE_GBE)
423*1e6f4e58SSimon Glass 		reg32 |= 1 << 23; /* GbE Static */
424*1e6f4e58SSimon Glass 	if (readl(RCB_REG(FD)) & PCH_DISABLE_HD_AUDIO)
425*1e6f4e58SSimon Glass 		reg32 |= 1 << 21; /* HDA Static */
426*1e6f4e58SSimon Glass 	reg32 |= 1 << 22; /* HDA Dynamic */
427*1e6f4e58SSimon Glass 	writel(reg32, RCB_REG(CG));
428*1e6f4e58SSimon Glass 
429*1e6f4e58SSimon Glass 	/* PCH-LP LPC */
430*1e6f4e58SSimon Glass 	if (pch_is_wpt(dev))
431*1e6f4e58SSimon Glass 		clrsetbits_le32(RCB_REG(0x3434), 0x1f, 0x17);
432*1e6f4e58SSimon Glass 	else
433*1e6f4e58SSimon Glass 		setbits_le32(RCB_REG(0x3434), 0x7);
434*1e6f4e58SSimon Glass 
435*1e6f4e58SSimon Glass 	/* SPI */
436*1e6f4e58SSimon Glass 	setbits_le32(RCB_REG(0x38c0), 0x3c07);
437*1e6f4e58SSimon Glass 
438*1e6f4e58SSimon Glass 	pch_iobp_update(0xCE00C000, ~1UL, 0x00000000);
439*1e6f4e58SSimon Glass }
440*1e6f4e58SSimon Glass 
441*1e6f4e58SSimon Glass static void systemagent_init(void)
442*1e6f4e58SSimon Glass {
443*1e6f4e58SSimon Glass 	/* Enable Power Aware Interrupt Routing */
444*1e6f4e58SSimon Glass 	clrsetbits_8(MCHBAR_REG(MCH_PAIR), 0x7, 0x4); /* Fixed Priority */
445*1e6f4e58SSimon Glass 
446*1e6f4e58SSimon Glass 	/*
447*1e6f4e58SSimon Glass 	 * Set bits 0+1 of BIOS_RESET_CPL to indicate to the CPU
448*1e6f4e58SSimon Glass 	 * that BIOS has initialized memory and power management
449*1e6f4e58SSimon Glass 	 */
450*1e6f4e58SSimon Glass 	setbits_8(MCHBAR_REG(BIOS_RESET_CPL), 3);
451*1e6f4e58SSimon Glass 	debug("Set BIOS_RESET_CPL\n");
452*1e6f4e58SSimon Glass 
453*1e6f4e58SSimon Glass 	/* Configure turbo power limits 1ms after reset complete bit */
454*1e6f4e58SSimon Glass 	mdelay(1);
455*1e6f4e58SSimon Glass 
456*1e6f4e58SSimon Glass 	cpu_set_power_limits(28);
457*1e6f4e58SSimon Glass }
458*1e6f4e58SSimon Glass 
459*1e6f4e58SSimon Glass static int broadwell_pch_init(struct udevice *dev)
460*1e6f4e58SSimon Glass {
461*1e6f4e58SSimon Glass 	int ret;
462*1e6f4e58SSimon Glass 
463*1e6f4e58SSimon Glass 	/* Enable upper 128 bytes of CMOS */
464*1e6f4e58SSimon Glass 	setbits_le32(RCB_REG(RC), 1 << 2);
465*1e6f4e58SSimon Glass 
466*1e6f4e58SSimon Glass 	/*
467*1e6f4e58SSimon Glass 	 * TODO: TCO timer halt - this hangs
468*1e6f4e58SSimon Glass 	 * setio_16(ACPI_BASE_ADDRESS + TCO1_CNT, TCO_TMR_HLT);
469*1e6f4e58SSimon Glass 	 */
470*1e6f4e58SSimon Glass 
471*1e6f4e58SSimon Glass 	/* Disable unused device (always) */
472*1e6f4e58SSimon Glass 	setbits_le32(RCB_REG(FD), PCH_DISABLE_ALWAYS);
473*1e6f4e58SSimon Glass 
474*1e6f4e58SSimon Glass 	pch_misc_init(dev);
475*1e6f4e58SSimon Glass 
476*1e6f4e58SSimon Glass 	/* Interrupt configuration */
477*1e6f4e58SSimon Glass 	pch_enable_ioapic();
478*1e6f4e58SSimon Glass 
479*1e6f4e58SSimon Glass 	/* Initialize power management */
480*1e6f4e58SSimon Glass 	ret = pch_power_options(dev);
481*1e6f4e58SSimon Glass 	if (ret)
482*1e6f4e58SSimon Glass 		return ret;
483*1e6f4e58SSimon Glass 	pch_pm_init(dev);
484*1e6f4e58SSimon Glass 	pch_cg_init(dev);
485*1e6f4e58SSimon Glass 	systemagent_init();
486*1e6f4e58SSimon Glass 
487*1e6f4e58SSimon Glass 	return 0;
488*1e6f4e58SSimon Glass }
489*1e6f4e58SSimon Glass 
490*1e6f4e58SSimon Glass static int broadwell_pch_probe(struct udevice *dev)
491*1e6f4e58SSimon Glass {
492*1e6f4e58SSimon Glass 	if (!(gd->flags & GD_FLG_RELOC))
493*1e6f4e58SSimon Glass 		return broadwell_pch_early_init(dev);
494*1e6f4e58SSimon Glass 	else
495*1e6f4e58SSimon Glass 		return broadwell_pch_init(dev);
496*1e6f4e58SSimon Glass }
497*1e6f4e58SSimon Glass 
498*1e6f4e58SSimon Glass static int broadwell_pch_get_spi_base(struct udevice *dev, ulong *sbasep)
499*1e6f4e58SSimon Glass {
500*1e6f4e58SSimon Glass 	u32 rcba;
501*1e6f4e58SSimon Glass 
502*1e6f4e58SSimon Glass 	dm_pci_read_config32(dev, PCH_RCBA, &rcba);
503*1e6f4e58SSimon Glass 	/* Bits 31-14 are the base address, 13-1 are reserved, 0 is enable */
504*1e6f4e58SSimon Glass 	rcba = rcba & 0xffffc000;
505*1e6f4e58SSimon Glass 	*sbasep = rcba + 0x3800;
506*1e6f4e58SSimon Glass 
507*1e6f4e58SSimon Glass 	return 0;
508*1e6f4e58SSimon Glass }
509*1e6f4e58SSimon Glass 
510*1e6f4e58SSimon Glass static int broadwell_set_spi_protect(struct udevice *dev, bool protect)
511*1e6f4e58SSimon Glass {
512*1e6f4e58SSimon Glass 	return lpc_set_spi_protect(dev, BIOS_CTRL, protect);
513*1e6f4e58SSimon Glass }
514*1e6f4e58SSimon Glass 
515*1e6f4e58SSimon Glass static int broadwell_get_gpio_base(struct udevice *dev, u32 *gbasep)
516*1e6f4e58SSimon Glass {
517*1e6f4e58SSimon Glass 	dm_pci_read_config32(dev, GPIO_BASE, gbasep);
518*1e6f4e58SSimon Glass 	*gbasep &= PCI_BASE_ADDRESS_IO_MASK;
519*1e6f4e58SSimon Glass 
520*1e6f4e58SSimon Glass 	return 0;
521*1e6f4e58SSimon Glass }
522*1e6f4e58SSimon Glass 
523*1e6f4e58SSimon Glass static const struct pch_ops broadwell_pch_ops = {
524*1e6f4e58SSimon Glass 	.get_spi_base	= broadwell_pch_get_spi_base,
525*1e6f4e58SSimon Glass 	.set_spi_protect = broadwell_set_spi_protect,
526*1e6f4e58SSimon Glass 	.get_gpio_base	= broadwell_get_gpio_base,
527*1e6f4e58SSimon Glass };
528*1e6f4e58SSimon Glass 
529*1e6f4e58SSimon Glass static const struct udevice_id broadwell_pch_ids[] = {
530*1e6f4e58SSimon Glass 	{ .compatible = "intel,broadwell-pch" },
531*1e6f4e58SSimon Glass 	{ }
532*1e6f4e58SSimon Glass };
533*1e6f4e58SSimon Glass 
534*1e6f4e58SSimon Glass U_BOOT_DRIVER(broadwell_pch) = {
535*1e6f4e58SSimon Glass 	.name		= "broadwell_pch",
536*1e6f4e58SSimon Glass 	.id		= UCLASS_PCH,
537*1e6f4e58SSimon Glass 	.of_match	= broadwell_pch_ids,
538*1e6f4e58SSimon Glass 	.probe		= broadwell_pch_probe,
539*1e6f4e58SSimon Glass 	.ops		= &broadwell_pch_ops,
540*1e6f4e58SSimon Glass };
541