xref: /openbmc/u-boot/arch/x86/cpu/ivybridge/bd82x6x.c (revision a3b15a05)
1 /*
2  * Copyright (C) 2014 Google, Inc
3  *
4  * SPDX-License-Identifier:	GPL-2.0+
5  */
6 #include <common.h>
7 #include <dm.h>
8 #include <errno.h>
9 #include <fdtdec.h>
10 #include <malloc.h>
11 #include <pch.h>
12 #include <syscon.h>
13 #include <asm/cpu.h>
14 #include <asm/io.h>
15 #include <asm/lapic.h>
16 #include <asm/pci.h>
17 #include <asm/arch/bd82x6x.h>
18 #include <asm/arch/model_206ax.h>
19 #include <asm/arch/pch.h>
20 #include <asm/arch/sandybridge.h>
21 
22 #define BIOS_CTRL	0xdc
23 
24 static int pch_revision_id = -1;
25 static int pch_type = -1;
26 
27 /**
28  * pch_silicon_revision() - Read silicon revision ID from the PCH
29  *
30  * @dev:	PCH device
31  * @return silicon revision ID
32  */
33 static int pch_silicon_revision(struct udevice *dev)
34 {
35 	u8 val;
36 
37 	if (pch_revision_id < 0) {
38 		dm_pci_read_config8(dev, PCI_REVISION_ID, &val);
39 		pch_revision_id = val;
40 	}
41 
42 	return pch_revision_id;
43 }
44 
45 int pch_silicon_type(struct udevice *dev)
46 {
47 	u8 val;
48 
49 	if (pch_type < 0) {
50 		dm_pci_read_config8(dev, PCI_DEVICE_ID + 1, &val);
51 		pch_type = val;
52 	}
53 
54 	return pch_type;
55 }
56 
57 /**
58  * pch_silicon_supported() - Check if a certain revision is supported
59  *
60  * @dev:	PCH device
61  * @type:	PCH type
62  * @rev:	Minimum required resion
63  * @return 0 if not supported, 1 if supported
64  */
65 static int pch_silicon_supported(struct udevice *dev, int type, int rev)
66 {
67 	int cur_type = pch_silicon_type(dev);
68 	int cur_rev = pch_silicon_revision(dev);
69 
70 	switch (type) {
71 	case PCH_TYPE_CPT:
72 		/* CougarPoint minimum revision */
73 		if (cur_type == PCH_TYPE_CPT && cur_rev >= rev)
74 			return 1;
75 		/* PantherPoint any revision */
76 		if (cur_type == PCH_TYPE_PPT)
77 			return 1;
78 		break;
79 
80 	case PCH_TYPE_PPT:
81 		/* PantherPoint minimum revision */
82 		if (cur_type == PCH_TYPE_PPT && cur_rev >= rev)
83 			return 1;
84 		break;
85 	}
86 
87 	return 0;
88 }
89 
90 #define IOBP_RETRY 1000
91 static inline int iobp_poll(void)
92 {
93 	unsigned try = IOBP_RETRY;
94 	u32 data;
95 
96 	while (try--) {
97 		data = readl(RCB_REG(IOBPS));
98 		if ((data & 1) == 0)
99 			return 1;
100 		udelay(10);
101 	}
102 
103 	printf("IOBP timeout\n");
104 	return 0;
105 }
106 
107 void pch_iobp_update(struct udevice *dev, u32 address, u32 andvalue,
108 		     u32 orvalue)
109 {
110 	u32 data;
111 
112 	/* Set the address */
113 	writel(address, RCB_REG(IOBPIRI));
114 
115 	/* READ OPCODE */
116 	if (pch_silicon_supported(dev, PCH_TYPE_CPT, PCH_STEP_B0))
117 		writel(IOBPS_RW_BX, RCB_REG(IOBPS));
118 	else
119 		writel(IOBPS_READ_AX, RCB_REG(IOBPS));
120 	if (!iobp_poll())
121 		return;
122 
123 	/* Read IOBP data */
124 	data = readl(RCB_REG(IOBPD));
125 	if (!iobp_poll())
126 		return;
127 
128 	/* Check for successful transaction */
129 	if ((readl(RCB_REG(IOBPS)) & 0x6) != 0) {
130 		printf("IOBP read 0x%08x failed\n", address);
131 		return;
132 	}
133 
134 	/* Update the data */
135 	data &= andvalue;
136 	data |= orvalue;
137 
138 	/* WRITE OPCODE */
139 	if (pch_silicon_supported(dev, PCH_TYPE_CPT, PCH_STEP_B0))
140 		writel(IOBPS_RW_BX, RCB_REG(IOBPS));
141 	else
142 		writel(IOBPS_WRITE_AX, RCB_REG(IOBPS));
143 	if (!iobp_poll())
144 		return;
145 
146 	/* Write IOBP data */
147 	writel(data, RCB_REG(IOBPD));
148 	if (!iobp_poll())
149 		return;
150 }
151 
152 static int bd82x6x_probe(struct udevice *dev)
153 {
154 	struct udevice *gma_dev;
155 	int ret;
156 
157 	if (!(gd->flags & GD_FLG_RELOC))
158 		return 0;
159 
160 	/* Cause the SATA device to do its init */
161 	uclass_first_device(UCLASS_DISK, &dev);
162 
163 	ret = syscon_get_by_driver_data(X86_SYSCON_GMA, &gma_dev);
164 	if (ret)
165 		return ret;
166 	ret = gma_func0_init(gma_dev);
167 	if (ret)
168 		return ret;
169 
170 	return 0;
171 }
172 
173 static int bd82x6x_pch_get_sbase(struct udevice *dev, ulong *sbasep)
174 {
175 	u32 rcba;
176 
177 	dm_pci_read_config32(dev, PCH_RCBA, &rcba);
178 	/* Bits 31-14 are the base address, 13-1 are reserved, 0 is enable */
179 	rcba = rcba & 0xffffc000;
180 	*sbasep = rcba + 0x3800;
181 
182 	return 0;
183 }
184 
185 static enum pch_version bd82x6x_pch_get_version(struct udevice *dev)
186 {
187 	return PCHV_9;
188 }
189 
190 static int bd82x6x_set_spi_protect(struct udevice *dev, bool protect)
191 {
192 	uint8_t bios_cntl;
193 
194 	/* Adjust the BIOS write protect and SMM BIOS Write Protect Disable */
195 	dm_pci_read_config8(dev, BIOS_CTRL, &bios_cntl);
196 	if (protect) {
197 		bios_cntl &= ~BIOS_CTRL_BIOSWE;
198 		bios_cntl |= BIT(5);
199 	} else {
200 		bios_cntl |= BIOS_CTRL_BIOSWE;
201 		bios_cntl &= ~BIT(5);
202 	}
203 	dm_pci_write_config8(dev, BIOS_CTRL, bios_cntl);
204 
205 	return 0;
206 }
207 
208 static const struct pch_ops bd82x6x_pch_ops = {
209 	.get_sbase	= bd82x6x_pch_get_sbase,
210 	.get_version	= bd82x6x_pch_get_version,
211 	.set_spi_protect = bd82x6x_set_spi_protect,
212 };
213 
214 static const struct udevice_id bd82x6x_ids[] = {
215 	{ .compatible = "intel,bd82x6x" },
216 	{ }
217 };
218 
219 U_BOOT_DRIVER(bd82x6x_drv) = {
220 	.name		= "bd82x6x",
221 	.id		= UCLASS_PCH,
222 	.of_match	= bd82x6x_ids,
223 	.probe		= bd82x6x_probe,
224 	.ops		= &bd82x6x_pch_ops,
225 };
226