1
2
3
4
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 <asm/cpu.h>
13#include <asm/intel_regs.h>
14#include <asm/io.h>
15#include <asm/lapic.h>
16#include <asm/lpc_common.h>
17#include <asm/pci.h>
18#include <asm/arch/model_206ax.h>
19#include <asm/arch/pch.h>
20#include <asm/arch/sandybridge.h>
21
22DECLARE_GLOBAL_DATA_PTR;
23
24#define GPIO_BASE 0x48
25#define BIOS_CTRL 0xdc
26
27#ifndef CONFIG_HAVE_FSP
28static int pch_revision_id = -1;
29static int pch_type = -1;
30
31
32
33
34
35
36
37static int pch_silicon_revision(struct udevice *dev)
38{
39 u8 val;
40
41 if (pch_revision_id < 0) {
42 dm_pci_read_config8(dev, PCI_REVISION_ID, &val);
43 pch_revision_id = val;
44 }
45
46 return pch_revision_id;
47}
48
49int pch_silicon_type(struct udevice *dev)
50{
51 u8 val;
52
53 if (pch_type < 0) {
54 dm_pci_read_config8(dev, PCI_DEVICE_ID + 1, &val);
55 pch_type = val;
56 }
57
58 return pch_type;
59}
60
61
62
63
64
65
66
67
68
69static int pch_silicon_supported(struct udevice *dev, int type, int rev)
70{
71 int cur_type = pch_silicon_type(dev);
72 int cur_rev = pch_silicon_revision(dev);
73
74 switch (type) {
75 case PCH_TYPE_CPT:
76
77 if (cur_type == PCH_TYPE_CPT && cur_rev >= rev)
78 return 1;
79
80 if (cur_type == PCH_TYPE_PPT)
81 return 1;
82 break;
83
84 case PCH_TYPE_PPT:
85
86 if (cur_type == PCH_TYPE_PPT && cur_rev >= rev)
87 return 1;
88 break;
89 }
90
91 return 0;
92}
93
94#define IOBP_RETRY 1000
95static inline int iobp_poll(void)
96{
97 unsigned try = IOBP_RETRY;
98 u32 data;
99
100 while (try--) {
101 data = readl(RCB_REG(IOBPS));
102 if ((data & 1) == 0)
103 return 1;
104 udelay(10);
105 }
106
107 printf("IOBP timeout\n");
108 return 0;
109}
110
111void pch_iobp_update(struct udevice *dev, u32 address, u32 andvalue,
112 u32 orvalue)
113{
114 u32 data;
115
116
117 writel(address, RCB_REG(IOBPIRI));
118
119
120 if (pch_silicon_supported(dev, PCH_TYPE_CPT, PCH_STEP_B0))
121 writel(IOBPS_RW_BX, RCB_REG(IOBPS));
122 else
123 writel(IOBPS_READ_AX, RCB_REG(IOBPS));
124 if (!iobp_poll())
125 return;
126
127
128 data = readl(RCB_REG(IOBPD));
129 if (!iobp_poll())
130 return;
131
132
133 if ((readl(RCB_REG(IOBPS)) & 0x6) != 0) {
134 printf("IOBP read 0x%08x failed\n", address);
135 return;
136 }
137
138
139 data &= andvalue;
140 data |= orvalue;
141
142
143 if (pch_silicon_supported(dev, PCH_TYPE_CPT, PCH_STEP_B0))
144 writel(IOBPS_RW_BX, RCB_REG(IOBPS));
145 else
146 writel(IOBPS_WRITE_AX, RCB_REG(IOBPS));
147 if (!iobp_poll())
148 return;
149
150
151 writel(data, RCB_REG(IOBPD));
152 if (!iobp_poll())
153 return;
154}
155
156static int bd82x6x_probe(struct udevice *dev)
157{
158 if (!(gd->flags & GD_FLG_RELOC))
159 return 0;
160
161
162 uclass_first_device(UCLASS_AHCI, &dev);
163
164 return 0;
165}
166#endif
167
168static int bd82x6x_pch_get_spi_base(struct udevice *dev, ulong *sbasep)
169{
170 u32 rcba;
171
172 dm_pci_read_config32(dev, PCH_RCBA, &rcba);
173
174 rcba = rcba & 0xffffc000;
175 *sbasep = rcba + 0x3800;
176
177 return 0;
178}
179
180static int bd82x6x_set_spi_protect(struct udevice *dev, bool protect)
181{
182 return lpc_set_spi_protect(dev, BIOS_CTRL, protect);
183}
184
185static int bd82x6x_get_gpio_base(struct udevice *dev, u32 *gbasep)
186{
187 u32 base;
188
189
190
191
192
193
194
195
196
197
198
199 dm_pci_read_config32(dev, GPIO_BASE, &base);
200 if (base == 0x00000000 || base == 0xffffffff) {
201 debug("%s: unexpected BASE value\n", __func__);
202 return -ENODEV;
203 }
204
205
206
207
208
209
210
211 *gbasep = base & 1 ? base & ~3 : base & ~15;
212
213 return 0;
214}
215
216static const struct pch_ops bd82x6x_pch_ops = {
217 .get_spi_base = bd82x6x_pch_get_spi_base,
218 .set_spi_protect = bd82x6x_set_spi_protect,
219 .get_gpio_base = bd82x6x_get_gpio_base,
220};
221
222static const struct udevice_id bd82x6x_ids[] = {
223 { .compatible = "intel,bd82x6x" },
224 { }
225};
226
227U_BOOT_DRIVER(bd82x6x_drv) = {
228 .name = "bd82x6x",
229 .id = UCLASS_PCH,
230 .of_match = bd82x6x_ids,
231#ifndef CONFIG_HAVE_FSP
232 .probe = bd82x6x_probe,
233#endif
234 .ops = &bd82x6x_pch_ops,
235};
236