xref: /openbmc/u-boot/arch/x86/cpu/ivybridge/bd82x6x.c (revision f2b85ab5e6a91e29c1d64304be371753d75ed172)
14e7a6acaSSimon Glass /*
24e7a6acaSSimon Glass  * Copyright (C) 2014 Google, Inc
34e7a6acaSSimon Glass  *
44e7a6acaSSimon Glass  * SPDX-License-Identifier:	GPL-2.0+
54e7a6acaSSimon Glass  */
64e7a6acaSSimon Glass #include <common.h>
7aad78d27SSimon Glass #include <dm.h>
84e7a6acaSSimon Glass #include <errno.h>
94e7a6acaSSimon Glass #include <fdtdec.h>
104e7a6acaSSimon Glass #include <malloc.h>
11*f2b85ab5SSimon Glass #include <pch.h>
124e7a6acaSSimon Glass #include <asm/lapic.h>
134e7a6acaSSimon Glass #include <asm/pci.h>
144e7a6acaSSimon Glass #include <asm/arch/bd82x6x.h>
154e7a6acaSSimon Glass #include <asm/arch/model_206ax.h>
164e7a6acaSSimon Glass #include <asm/arch/pch.h>
174e7a6acaSSimon Glass #include <asm/arch/sandybridge.h>
184e7a6acaSSimon Glass 
19*f2b85ab5SSimon Glass #define BIOS_CTRL	0xdc
20*f2b85ab5SSimon Glass 
214e7a6acaSSimon Glass void bd82x6x_pci_init(pci_dev_t dev)
224e7a6acaSSimon Glass {
234e7a6acaSSimon Glass 	u16 reg16;
244e7a6acaSSimon Glass 	u8 reg8;
254e7a6acaSSimon Glass 
264e7a6acaSSimon Glass 	debug("bd82x6x PCI init.\n");
274e7a6acaSSimon Glass 	/* Enable Bus Master */
2831f57c28SSimon Glass 	reg16 = x86_pci_read_config16(dev, PCI_COMMAND);
294e7a6acaSSimon Glass 	reg16 |= PCI_COMMAND_MASTER;
3031f57c28SSimon Glass 	x86_pci_write_config16(dev, PCI_COMMAND, reg16);
314e7a6acaSSimon Glass 
324e7a6acaSSimon Glass 	/* This device has no interrupt */
3331f57c28SSimon Glass 	x86_pci_write_config8(dev, INTR, 0xff);
344e7a6acaSSimon Glass 
354e7a6acaSSimon Glass 	/* disable parity error response and SERR */
3631f57c28SSimon Glass 	reg16 = x86_pci_read_config16(dev, BCTRL);
374e7a6acaSSimon Glass 	reg16 &= ~(1 << 0);
384e7a6acaSSimon Glass 	reg16 &= ~(1 << 1);
3931f57c28SSimon Glass 	x86_pci_write_config16(dev, BCTRL, reg16);
404e7a6acaSSimon Glass 
414e7a6acaSSimon Glass 	/* Master Latency Count must be set to 0x04! */
4231f57c28SSimon Glass 	reg8 = x86_pci_read_config8(dev, SMLT);
434e7a6acaSSimon Glass 	reg8 &= 0x07;
444e7a6acaSSimon Glass 	reg8 |= (0x04 << 3);
4531f57c28SSimon Glass 	x86_pci_write_config8(dev, SMLT, reg8);
464e7a6acaSSimon Glass 
474e7a6acaSSimon Glass 	/* Will this improve throughput of bus masters? */
4831f57c28SSimon Glass 	x86_pci_write_config8(dev, PCI_MIN_GNT, 0x06);
494e7a6acaSSimon Glass 
504e7a6acaSSimon Glass 	/* Clear errors in status registers */
5131f57c28SSimon Glass 	reg16 = x86_pci_read_config16(dev, PSTS);
524e7a6acaSSimon Glass 	/* reg16 |= 0xf900; */
5331f57c28SSimon Glass 	x86_pci_write_config16(dev, PSTS, reg16);
544e7a6acaSSimon Glass 
5531f57c28SSimon Glass 	reg16 = x86_pci_read_config16(dev, SECSTS);
564e7a6acaSSimon Glass 	/* reg16 |= 0xf900; */
5731f57c28SSimon Glass 	x86_pci_write_config16(dev, SECSTS, reg16);
584e7a6acaSSimon Glass }
594e7a6acaSSimon Glass 
60aad78d27SSimon Glass static int bd82x6x_probe(struct udevice *dev)
614e7a6acaSSimon Glass {
623ac83935SSimon Glass 	const void *blob = gd->fdt_blob;
6372cd085aSSimon Glass 	struct pci_controller *hose;
64bb80be39SSimon Glass 	struct x86_cpu_priv *cpu;
65effcf067SSimon Glass 	int sata_node, gma_node;
66effcf067SSimon Glass 	int ret;
6772cd085aSSimon Glass 
6872cd085aSSimon Glass 	hose = pci_bus_to_hose(0);
6972cd085aSSimon Glass 	lpc_enable(PCH_LPC_DEV);
7072cd085aSSimon Glass 	lpc_init(hose, PCH_LPC_DEV);
713ac83935SSimon Glass 	sata_node = fdtdec_next_compatible(blob, 0,
723ac83935SSimon Glass 					   COMPAT_INTEL_PANTHERPOINT_AHCI);
733ac83935SSimon Glass 	if (sata_node < 0) {
743ac83935SSimon Glass 		debug("%s: Cannot find SATA node\n", __func__);
753ac83935SSimon Glass 		return -EINVAL;
763ac83935SSimon Glass 	}
773ac83935SSimon Glass 	bd82x6x_sata_init(PCH_SATA_DEV, blob, sata_node);
789baeca4bSSimon Glass 	bd82x6x_usb_ehci_init(PCH_EHCI1_DEV);
799baeca4bSSimon Glass 	bd82x6x_usb_ehci_init(PCH_EHCI2_DEV);
8072cd085aSSimon Glass 
81bb80be39SSimon Glass 	cpu = calloc(1, sizeof(*cpu));
82bb80be39SSimon Glass 	if (!cpu)
83bb80be39SSimon Glass 		return -ENOMEM;
84bb80be39SSimon Glass 	model_206ax_init(cpu);
85bb80be39SSimon Glass 
86effcf067SSimon Glass 	gma_node = fdtdec_next_compatible(blob, 0, COMPAT_INTEL_GMA);
87effcf067SSimon Glass 	if (gma_node < 0) {
88effcf067SSimon Glass 		debug("%s: Cannot find GMA node\n", __func__);
89effcf067SSimon Glass 		return -EINVAL;
90effcf067SSimon Glass 	}
919bf727fcSSimon Glass 	ret = dm_pci_bus_find_bdf(PCH_VIDEO_DEV, &dev);
929bf727fcSSimon Glass 	if (ret)
939bf727fcSSimon Glass 		return ret;
949bf727fcSSimon Glass 	ret = gma_func0_init(dev, blob, gma_node);
95effcf067SSimon Glass 	if (ret)
96effcf067SSimon Glass 		return ret;
97effcf067SSimon Glass 
984e7a6acaSSimon Glass 	return 0;
994e7a6acaSSimon Glass }
1004e7a6acaSSimon Glass 
101*f2b85ab5SSimon Glass /* TODO(sjg@chromium.org): Move this to the PCH init() method */
1024e7a6acaSSimon Glass int bd82x6x_init(void)
1034e7a6acaSSimon Glass {
1043ac83935SSimon Glass 	const void *blob = gd->fdt_blob;
1053ac83935SSimon Glass 	int sata_node;
1063ac83935SSimon Glass 
1073ac83935SSimon Glass 	sata_node = fdtdec_next_compatible(blob, 0,
1083ac83935SSimon Glass 					   COMPAT_INTEL_PANTHERPOINT_AHCI);
1093ac83935SSimon Glass 	if (sata_node < 0) {
1103ac83935SSimon Glass 		debug("%s: Cannot find SATA node\n", __func__);
1113ac83935SSimon Glass 		return -EINVAL;
1123ac83935SSimon Glass 	}
1133ac83935SSimon Glass 
1144e7a6acaSSimon Glass 	bd82x6x_pci_init(PCH_DEV);
1153ac83935SSimon Glass 	bd82x6x_sata_enable(PCH_SATA_DEV, blob, sata_node);
11624774278SSimon Glass 	northbridge_enable(PCH_DEV);
11724774278SSimon Glass 	northbridge_init(PCH_DEV);
1184e7a6acaSSimon Glass 
1194e7a6acaSSimon Glass 	return 0;
1204e7a6acaSSimon Glass }
121aad78d27SSimon Glass 
122*f2b85ab5SSimon Glass static int bd82x6x_pch_get_sbase(struct udevice *dev, ulong *sbasep)
123*f2b85ab5SSimon Glass {
124*f2b85ab5SSimon Glass 	u32 rcba;
125*f2b85ab5SSimon Glass 
126*f2b85ab5SSimon Glass 	dm_pci_read_config32(dev, PCH_RCBA, &rcba);
127*f2b85ab5SSimon Glass 	/* Bits 31-14 are the base address, 13-1 are reserved, 0 is enable */
128*f2b85ab5SSimon Glass 	rcba = rcba & 0xffffc000;
129*f2b85ab5SSimon Glass 	*sbasep = rcba + 0x3800;
130*f2b85ab5SSimon Glass 
131*f2b85ab5SSimon Glass 	return 0;
132*f2b85ab5SSimon Glass }
133*f2b85ab5SSimon Glass 
134*f2b85ab5SSimon Glass static enum pch_version bd82x6x_pch_get_version(struct udevice *dev)
135*f2b85ab5SSimon Glass {
136*f2b85ab5SSimon Glass 	return PCHV_9;
137*f2b85ab5SSimon Glass }
138*f2b85ab5SSimon Glass 
139*f2b85ab5SSimon Glass static int bd82x6x_set_spi_protect(struct udevice *dev, bool protect)
140*f2b85ab5SSimon Glass {
141*f2b85ab5SSimon Glass 	uint8_t bios_cntl;
142*f2b85ab5SSimon Glass 
143*f2b85ab5SSimon Glass 	/* Adjust the BIOS write protect and SMM BIOS Write Protect Disable */
144*f2b85ab5SSimon Glass 	dm_pci_read_config8(dev, BIOS_CTRL, &bios_cntl);
145*f2b85ab5SSimon Glass 	if (protect) {
146*f2b85ab5SSimon Glass 		bios_cntl &= ~BIOS_CTRL_BIOSWE;
147*f2b85ab5SSimon Glass 		bios_cntl |= BIT(5);
148*f2b85ab5SSimon Glass 	} else {
149*f2b85ab5SSimon Glass 		bios_cntl |= BIOS_CTRL_BIOSWE;
150*f2b85ab5SSimon Glass 		bios_cntl &= ~BIT(5);
151*f2b85ab5SSimon Glass 	}
152*f2b85ab5SSimon Glass 	dm_pci_write_config8(dev, BIOS_CTRL, bios_cntl);
153*f2b85ab5SSimon Glass 
154*f2b85ab5SSimon Glass 	return 0;
155*f2b85ab5SSimon Glass }
156*f2b85ab5SSimon Glass 
157*f2b85ab5SSimon Glass static const struct pch_ops bd82x6x_pch_ops = {
158*f2b85ab5SSimon Glass 	.get_sbase	= bd82x6x_pch_get_sbase,
159*f2b85ab5SSimon Glass 	.get_version	= bd82x6x_pch_get_version,
160*f2b85ab5SSimon Glass 	.set_spi_protect = bd82x6x_set_spi_protect,
161*f2b85ab5SSimon Glass };
162*f2b85ab5SSimon Glass 
163aad78d27SSimon Glass static const struct udevice_id bd82x6x_ids[] = {
164aad78d27SSimon Glass 	{ .compatible = "intel,bd82x6x" },
165aad78d27SSimon Glass 	{ }
166aad78d27SSimon Glass };
167aad78d27SSimon Glass 
168aad78d27SSimon Glass U_BOOT_DRIVER(bd82x6x_drv) = {
169aad78d27SSimon Glass 	.name		= "bd82x6x",
170aad78d27SSimon Glass 	.id		= UCLASS_PCH,
171aad78d27SSimon Glass 	.of_match	= bd82x6x_ids,
172aad78d27SSimon Glass 	.probe		= bd82x6x_probe,
173*f2b85ab5SSimon Glass 	.ops		= &bd82x6x_pch_ops,
174aad78d27SSimon Glass };
175