blob: 2b172d49bade73704529abfbadd64beb28a932a7 [file] [log] [blame]
Simon Glass17f1c402014-11-14 18:18:32 -07001/*
2 * Copyright (C) 2014 Google, Inc
3 *
4 * SPDX-License-Identifier: GPL-2.0+
5 */
Simon Glass17f1c402014-11-14 18:18:32 -07006#include <common.h>
Simon Glasse0e7b362015-03-05 12:25:33 -07007#include <dm.h>
Simon Glass17f1c402014-11-14 18:18:32 -07008#include <errno.h>
9#include <fdtdec.h>
10#include <malloc.h>
Simon Glass32761632016-01-18 20:19:21 -070011#include <pch.h>
Simon Glassa75abeb2016-01-17 16:11:59 -070012#include <syscon.h>
13#include <asm/cpu.h>
Simon Glass6c9e1d82016-01-17 16:11:53 -070014#include <asm/io.h>
Simon Glass17f1c402014-11-14 18:18:32 -070015#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
Simon Glass32761632016-01-18 20:19:21 -070022#define BIOS_CTRL 0xdc
23
Simon Glass6c9e1d82016-01-17 16:11:53 -070024static int pch_revision_id = -1;
25static 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 */
33static 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
45int 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 */
65static 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
91static 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
107void 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
Simon Glasse0e7b362015-03-05 12:25:33 -0700152static int bd82x6x_probe(struct udevice *dev)
Simon Glass17f1c402014-11-14 18:18:32 -0700153{
Simon Glassa75abeb2016-01-17 16:11:59 -0700154 struct udevice *gma_dev;
Simon Glassd90f8e12014-11-14 20:56:36 -0700155 int ret;
Simon Glass06409c92014-11-14 18:18:35 -0700156
Simon Glass044f1a02016-01-17 16:11:10 -0700157 if (!(gd->flags & GD_FLG_RELOC))
158 return 0;
159
Simon Glass39f3f8c2016-01-17 16:11:37 -0700160 /* Cause the SATA device to do its init */
161 uclass_first_device(UCLASS_DISK, &dev);
162
Simon Glassa75abeb2016-01-17 16:11:59 -0700163 ret = syscon_get_by_driver_data(X86_SYSCON_GMA, &gma_dev);
Simon Glass35230352015-11-29 13:17:55 -0700164 if (ret)
165 return ret;
Simon Glassa75abeb2016-01-17 16:11:59 -0700166 ret = gma_func0_init(gma_dev);
Simon Glassd90f8e12014-11-14 20:56:36 -0700167 if (ret)
168 return ret;
169
Simon Glass17f1c402014-11-14 18:18:32 -0700170 return 0;
171}
172
Simon Glass32761632016-01-18 20:19:21 -0700173static 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
185static enum pch_version bd82x6x_pch_get_version(struct udevice *dev)
186{
187 return PCHV_9;
188}
189
190static 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
208static 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
Simon Glasse0e7b362015-03-05 12:25:33 -0700214static const struct udevice_id bd82x6x_ids[] = {
215 { .compatible = "intel,bd82x6x" },
216 { }
217};
218
219U_BOOT_DRIVER(bd82x6x_drv) = {
220 .name = "bd82x6x",
221 .id = UCLASS_PCH,
222 .of_match = bd82x6x_ids,
223 .probe = bd82x6x_probe,
Simon Glass32761632016-01-18 20:19:21 -0700224 .ops = &bd82x6x_pch_ops,
Simon Glasse0e7b362015-03-05 12:25:33 -0700225};