xref: /openbmc/u-boot/arch/x86/cpu/ivybridge/bd82x6x.c (revision 9671f696)
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2014 Google, Inc
4  */
5 #include <common.h>
6 #include <dm.h>
7 #include <errno.h>
8 #include <fdtdec.h>
9 #include <malloc.h>
10 #include <pch.h>
11 #include <asm/cpu.h>
12 #include <asm/intel_regs.h>
13 #include <asm/io.h>
14 #include <asm/lapic.h>
15 #include <asm/lpc_common.h>
16 #include <asm/pci.h>
17 #include <asm/arch/model_206ax.h>
18 #include <asm/arch/pch.h>
19 #include <asm/arch/sandybridge.h>
20 
21 DECLARE_GLOBAL_DATA_PTR;
22 
23 #define GPIO_BASE	0x48
24 #define BIOS_CTRL	0xdc
25 
26 #ifndef CONFIG_HAVE_FSP
27 static int pch_revision_id = -1;
28 static int pch_type = -1;
29 
30 /**
31  * pch_silicon_revision() - Read silicon revision ID from the PCH
32  *
33  * @dev:	PCH device
34  * @return silicon revision ID
35  */
36 static int pch_silicon_revision(struct udevice *dev)
37 {
38 	u8 val;
39 
40 	if (pch_revision_id < 0) {
41 		dm_pci_read_config8(dev, PCI_REVISION_ID, &val);
42 		pch_revision_id = val;
43 	}
44 
45 	return pch_revision_id;
46 }
47 
48 int pch_silicon_type(struct udevice *dev)
49 {
50 	u8 val;
51 
52 	if (pch_type < 0) {
53 		dm_pci_read_config8(dev, PCI_DEVICE_ID + 1, &val);
54 		pch_type = val;
55 	}
56 
57 	return pch_type;
58 }
59 
60 /**
61  * pch_silicon_supported() - Check if a certain revision is supported
62  *
63  * @dev:	PCH device
64  * @type:	PCH type
65  * @rev:	Minimum required resion
66  * @return 0 if not supported, 1 if supported
67  */
68 static int pch_silicon_supported(struct udevice *dev, int type, int rev)
69 {
70 	int cur_type = pch_silicon_type(dev);
71 	int cur_rev = pch_silicon_revision(dev);
72 
73 	switch (type) {
74 	case PCH_TYPE_CPT:
75 		/* CougarPoint minimum revision */
76 		if (cur_type == PCH_TYPE_CPT && cur_rev >= rev)
77 			return 1;
78 		/* PantherPoint any revision */
79 		if (cur_type == PCH_TYPE_PPT)
80 			return 1;
81 		break;
82 
83 	case PCH_TYPE_PPT:
84 		/* PantherPoint minimum revision */
85 		if (cur_type == PCH_TYPE_PPT && cur_rev >= rev)
86 			return 1;
87 		break;
88 	}
89 
90 	return 0;
91 }
92 
93 #define IOBP_RETRY 1000
94 static inline int iobp_poll(void)
95 {
96 	unsigned try = IOBP_RETRY;
97 	u32 data;
98 
99 	while (try--) {
100 		data = readl(RCB_REG(IOBPS));
101 		if ((data & 1) == 0)
102 			return 1;
103 		udelay(10);
104 	}
105 
106 	printf("IOBP timeout\n");
107 	return 0;
108 }
109 
110 void pch_iobp_update(struct udevice *dev, u32 address, u32 andvalue,
111 		     u32 orvalue)
112 {
113 	u32 data;
114 
115 	/* Set the address */
116 	writel(address, RCB_REG(IOBPIRI));
117 
118 	/* READ OPCODE */
119 	if (pch_silicon_supported(dev, PCH_TYPE_CPT, PCH_STEP_B0))
120 		writel(IOBPS_RW_BX, RCB_REG(IOBPS));
121 	else
122 		writel(IOBPS_READ_AX, RCB_REG(IOBPS));
123 	if (!iobp_poll())
124 		return;
125 
126 	/* Read IOBP data */
127 	data = readl(RCB_REG(IOBPD));
128 	if (!iobp_poll())
129 		return;
130 
131 	/* Check for successful transaction */
132 	if ((readl(RCB_REG(IOBPS)) & 0x6) != 0) {
133 		printf("IOBP read 0x%08x failed\n", address);
134 		return;
135 	}
136 
137 	/* Update the data */
138 	data &= andvalue;
139 	data |= orvalue;
140 
141 	/* WRITE OPCODE */
142 	if (pch_silicon_supported(dev, PCH_TYPE_CPT, PCH_STEP_B0))
143 		writel(IOBPS_RW_BX, RCB_REG(IOBPS));
144 	else
145 		writel(IOBPS_WRITE_AX, RCB_REG(IOBPS));
146 	if (!iobp_poll())
147 		return;
148 
149 	/* Write IOBP data */
150 	writel(data, RCB_REG(IOBPD));
151 	if (!iobp_poll())
152 		return;
153 }
154 
155 static int bd82x6x_probe(struct udevice *dev)
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_AHCI, &dev);
162 
163 	return 0;
164 }
165 #endif /* CONFIG_HAVE_FSP */
166 
167 static int bd82x6x_pch_get_spi_base(struct udevice *dev, ulong *sbasep)
168 {
169 	u32 rcba;
170 
171 	dm_pci_read_config32(dev, PCH_RCBA, &rcba);
172 	/* Bits 31-14 are the base address, 13-1 are reserved, 0 is enable */
173 	rcba = rcba & 0xffffc000;
174 	*sbasep = rcba + 0x3800;
175 
176 	return 0;
177 }
178 
179 static int bd82x6x_set_spi_protect(struct udevice *dev, bool protect)
180 {
181 	return lpc_set_spi_protect(dev, BIOS_CTRL, protect);
182 }
183 
184 static int bd82x6x_get_gpio_base(struct udevice *dev, u32 *gbasep)
185 {
186 	u32 base;
187 
188 	/*
189 	 * GPIO_BASE moved to its current offset with ICH6, but prior to
190 	 * that it was unused (or undocumented). Check that it looks
191 	 * okay: not all ones or zeros.
192 	 *
193 	 * Note we don't need check bit0 here, because the Tunnel Creek
194 	 * GPIO base address register bit0 is reserved (read returns 0),
195 	 * while on the Ivybridge the bit0 is used to indicate it is an
196 	 * I/O space.
197 	 */
198 	dm_pci_read_config32(dev, GPIO_BASE, &base);
199 	if (base == 0x00000000 || base == 0xffffffff) {
200 		debug("%s: unexpected BASE value\n", __func__);
201 		return -ENODEV;
202 	}
203 
204 	/*
205 	 * Okay, I guess we're looking at the right device. The actual
206 	 * GPIO registers are in the PCI device's I/O space, starting
207 	 * at the offset that we just read. Bit 0 indicates that it's
208 	 * an I/O address, not a memory address, so mask that off.
209 	 */
210 	*gbasep = base & 1 ? base & ~3 : base & ~15;
211 
212 	return 0;
213 }
214 
215 static const struct pch_ops bd82x6x_pch_ops = {
216 	.get_spi_base	= bd82x6x_pch_get_spi_base,
217 	.set_spi_protect = bd82x6x_set_spi_protect,
218 	.get_gpio_base	= bd82x6x_get_gpio_base,
219 };
220 
221 static const struct udevice_id bd82x6x_ids[] = {
222 	{ .compatible = "intel,bd82x6x" },
223 	{ }
224 };
225 
226 U_BOOT_DRIVER(bd82x6x_drv) = {
227 	.name		= "bd82x6x",
228 	.id		= UCLASS_PCH,
229 	.of_match	= bd82x6x_ids,
230 #ifndef CONFIG_HAVE_FSP
231 	.probe		= bd82x6x_probe,
232 #endif
233 	.ops		= &bd82x6x_pch_ops,
234 };
235