blob: a1513e8b0d0fc33ff2937bd3772973f36194343f [file] [log] [blame]
Vladimir Serbinenko3129f792014-10-15 21:51:47 +02001package main
2
3import (
4 "fmt"
5 "os"
6)
7
8type bd82x6x struct {
9 variant string
10 node *DevTreeNode
11}
12
13func (b bd82x6x) writeGPIOSet(ctx Context, sb *os.File,
14 val uint32, set uint, partno int) {
15
16 max := uint(32)
17 if set == 3 {
18 max = 12
19 }
20
21 bits := [6][2]string{
22 {"GPIO_MODE_NATIVE", "GPIO_MODE_GPIO"},
23 {"GPIO_DIR_OUTPUT", "GPIO_DIR_INPUT"},
24 {"GPIO_LEVEL_LOW", "GPIO_LEVEL_HIGH"},
25 {"GPIO_RESET_PWROK", "GPIO_RESET_RSMRST"},
26 {"GPIO_NO_INVERT", "GPIO_INVERT"},
27 {"GPIO_NO_BLINK", "GPIO_BLINK"},
28 }
29
30 for i := uint(0); i < max; i++ {
31 fmt.Fprintf(sb, " .gpio%d = %s,\n",
32 (set-1)*32+i,
33 bits[partno][(val>>i)&1])
34 }
35}
36
37func (b bd82x6x) GPIO(ctx Context, inteltool InteltoolData) {
38 gpio := Create(ctx, "gpio.c")
39 defer gpio.Close()
40
41 AddROMStageFile("gpio.c", "")
42
43 gpio.WriteString(`#include "southbridge/intel/bd82x6x/gpio.h"
44`)
45
46 adresses := [3][6]int{
47 {0x00, 0x04, 0x0c, 0x60, 0x2c, 0x18},
48 {0x30, 0x34, 0x38, 0x64, -1, -1},
49 {0x40, 0x44, 0x48, 0x68, -1, -1},
50 }
51
52 for set := 1; set <= 3; set++ {
53 for partno, part := range []string{"mode", "direction", "level", "reset", "invert", "blink"} {
54 addr := adresses[set-1][partno]
55 if addr < 0 {
56 continue
57 }
58 fmt.Fprintf(gpio, "const struct pch_gpio_set%d pch_gpio_set%d_%s = {\n",
59 set, set, part)
60
61 b.writeGPIOSet(ctx, gpio, inteltool.GPIO[uint16(addr)], uint(set), partno)
62 gpio.WriteString("};\n\n")
63 }
64 }
65
66 gpio.WriteString(`const struct pch_gpio_map mainboard_gpio_map = {
67 .set1 = {
68 .mode = &pch_gpio_set1_mode,
69 .direction = &pch_gpio_set1_direction,
70 .level = &pch_gpio_set1_level,
71 .blink = &pch_gpio_set1_blink,
72 .invert = &pch_gpio_set1_invert,
73 .reset = &pch_gpio_set1_reset,
74 },
75 .set2 = {
76 .mode = &pch_gpio_set2_mode,
77 .direction = &pch_gpio_set2_direction,
78 .level = &pch_gpio_set2_level,
79 .reset = &pch_gpio_set2_reset,
80 },
81 .set3 = {
82 .mode = &pch_gpio_set3_mode,
83 .direction = &pch_gpio_set3_direction,
84 .level = &pch_gpio_set3_level,
85 .reset = &pch_gpio_set3_reset,
86 },
87};
88`)
89}
90
91func (b bd82x6x) IsPCIeHotplug(ctx Context, port int) bool {
92 portDev, ok := PCIMap[PCIAddr{Bus: 0, Dev: 0x1c, Func: port}]
93 if !ok {
94 return false
95 }
96 return (portDev.ConfigDump[0xdb] & (1 << 6)) != 0
97}
98
99func ich9GetFlashSize(ctx Context) {
100 inteltool := ctx.InfoSource.GetInteltool()
101 switch (inteltool.RCBA[0x3410] >> 10) & 3 {
102 /* SPI. All boards I've seen with sandy/ivy use SPI. */
103 case 3:
104 ROMProtocol = "SPI"
105 highflkb := uint32(0)
106 for reg := uint16(0); reg < 5; reg++ {
107 fl := (inteltool.RCBA[0x3854+4*reg] >> 16) & 0x1fff
Vladimir Serbinenko68f5f622015-05-29 21:43:42 +0200108 flkb := (fl + 1) << 2
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200109 if flkb > highflkb {
110 highflkb = flkb
111 }
112 }
113 ROMSizeKB = int(highflkb)
114 /* Shared with ME. Flashrom is unable to handle it. */
115 FlashROMSupport = "n"
116 }
117}
118
119func (b bd82x6x) GetGPIOHeader() string {
120 return "southbridge/intel/bd82x6x/pch.h"
121}
122
123func (b bd82x6x) EnableGPE(in int) {
124 b.node.Registers[fmt.Sprintf("gpi%d_routing", in)] = "2"
125}
126
127func (b bd82x6x) EncodeGPE(in int) int {
128 return in + 0x10
129}
130
131func (b bd82x6x) DecodeGPE(in int) int {
132 return in - 0x10
133}
134
135func (b bd82x6x) NeedRouteGPIOManually() {
136 b.node.Comment += ", FIXME: set gpiX_routing for EC support"
137}
138
139func (b bd82x6x) Scan(ctx Context, addr PCIDevData) {
140
141 SouthBridge = &b
142
143 inteltool := ctx.InfoSource.GetInteltool()
144 b.GPIO(ctx, inteltool)
145
146 KconfigBool["SOUTHBRIDGE_INTEL_"+b.variant] = true
147 KconfigBool["SERIRQ_CONTINUOUS_MODE"] = true
148 KconfigInt["USBDEBUG_HCD_INDEX"] = 2
149 KconfigComment["USBDEBUG_HCD_INDEX"] = "FIXME: check this"
150 dmi := ctx.InfoSource.GetDMI()
151 if dmi.Vendor == "LENOVO" {
152 KconfigInt["DRAM_RESET_GATE_GPIO"] = 10
153 } else {
154 KconfigInt["DRAM_RESET_GATE_GPIO"] = 60
155 }
156 KconfigComment["DRAM_RESET_GATE_GPIO"] = "FIXME: check this"
157
158 /* Not strictly speaking correct. These subsys/subvendor referer to PCI devices.
159 But most systems don't have any of those. But the config needs to be set
160 nevertheless. So set it to southbridge subsys/subvendor. */
161 KconfigHex["MAINBOARD_PCI_SUBSYSTEM_VENDOR_ID"] = uint32(GetLE16(addr.ConfigDump[0x2c:0x2e]))
162 KconfigHex["MAINBOARD_PCI_SUBSYSTEM_DEVICE_ID"] = uint32(GetLE16(addr.ConfigDump[0x2e:0x30]))
163
164 ich9GetFlashSize(ctx)
165
166 DSDTDefines = append(DSDTDefines,
167 DSDTDefine{
168 Key: "BRIGHTNESS_UP",
169 Value: "\\_SB.PCI0.GFX0.INCB",
170 },
171 DSDTDefine{
172 Key: "BRIGHTNESS_DOWN",
173 Value: "\\_SB.PCI0.GFX0.DECB",
174 },
175 DSDTDefine{
176 Key: "ACPI_VIDEO_DEVICE",
177 Value: "\\_SB.PCI0.GFX0",
178 })
179
180 /* SPI init */
181 MainboardIncludes = append(MainboardIncludes, "southbridge/intel/bd82x6x/pch.h")
182 /* FIXME:XX Move this to runtime. */
183 for _, addr := range []uint16{0x38c8, 0x38c4, 0x38c0} {
184 MainboardInit += fmt.Sprintf("\tRCBA32(0x%04x) = 0x%08x;\n", addr, inteltool.RCBA[addr])
185 }
186
187 FADT := ctx.InfoSource.GetACPI()["FACP"]
188
189 pcieHotplugMap := "{ "
190
191 for port := 0; port < 7; port++ {
192 if b.IsPCIeHotplug(ctx, port) {
193 pcieHotplugMap += "1, "
194 } else {
195 pcieHotplugMap += "0, "
196 }
197 }
198
199 if b.IsPCIeHotplug(ctx, 7) {
200 pcieHotplugMap += "1 }"
201 } else {
202 pcieHotplugMap += "0 }"
203 }
204
205 cur := DevTreeNode{
206 Chip: "southbridge/intel/bd82x6x",
207 Comment: "Intel Series 6 Cougar Point PCH",
208
209 Registers: map[string]string{
210 "sata_interface_speed_support": "0x3",
211 "gen1_dec": FormatHexLE32(PCIMap[PCIAddr{Bus: 0, Dev: 0x1f, Func: 0}].ConfigDump[0x84:0x88]),
212 "gen2_dec": FormatHexLE32(PCIMap[PCIAddr{Bus: 0, Dev: 0x1f, Func: 0}].ConfigDump[0x88:0x8c]),
213 "gen3_dec": FormatHexLE32(PCIMap[PCIAddr{Bus: 0, Dev: 0x1f, Func: 0}].ConfigDump[0x8c:0x90]),
214 "gen4_dec": FormatHexLE32(PCIMap[PCIAddr{Bus: 0, Dev: 0x1f, Func: 0}].ConfigDump[0x90:0x94]),
215 "pcie_port_coalesce": "1",
216 "pcie_hotplug_map": pcieHotplugMap,
217
218 "sata_port_map": fmt.Sprintf("0x%x", PCIMap[PCIAddr{Bus: 0, Dev: 0x1f, Func: 2}].ConfigDump[0x92]&0x3f),
219
220 "p_cnt_throttling_supported": (FormatBool(FADT[104] == 1 && FADT[105] == 3)),
221 "c2_latency": FormatHexLE16(FADT[96:98]),
222 "docking_supported": (FormatBool((FADT[113] & (1 << 1)) != 0)),
223 },
224 PCISlots: []PCISlot{
225 PCISlot{PCIAddr: PCIAddr{Dev: 0x14, Func: 0}, writeEmpty: false, additionalComment: "USB 3.0 Controller"},
226 PCISlot{PCIAddr: PCIAddr{Dev: 0x16, Func: 0}, writeEmpty: true, additionalComment: "Management Engine Interface 1"},
227 PCISlot{PCIAddr: PCIAddr{Dev: 0x16, Func: 1}, writeEmpty: true, additionalComment: "Management Engine Interface 2"},
228 PCISlot{PCIAddr: PCIAddr{Dev: 0x16, Func: 2}, writeEmpty: true, additionalComment: "Management Engine IDE-R"},
229 PCISlot{PCIAddr: PCIAddr{Dev: 0x16, Func: 3}, writeEmpty: true, additionalComment: "Management Engine KT"},
230 PCISlot{PCIAddr: PCIAddr{Dev: 0x19, Func: 0}, writeEmpty: true, additionalComment: "Intel Gigabit Ethernet"},
231 PCISlot{PCIAddr: PCIAddr{Dev: 0x1a, Func: 0}, writeEmpty: true, additionalComment: "USB2 EHCI #2"},
232 PCISlot{PCIAddr: PCIAddr{Dev: 0x1b, Func: 0}, writeEmpty: true, additionalComment: "High Definition Audio"},
233 PCISlot{PCIAddr: PCIAddr{Dev: 0x1c, Func: 0}, writeEmpty: true, additionalComment: "PCIe Port #1"},
234 PCISlot{PCIAddr: PCIAddr{Dev: 0x1c, Func: 1}, writeEmpty: true, additionalComment: "PCIe Port #2"},
235 PCISlot{PCIAddr: PCIAddr{Dev: 0x1c, Func: 2}, writeEmpty: true, additionalComment: "PCIe Port #3"},
236 PCISlot{PCIAddr: PCIAddr{Dev: 0x1c, Func: 3}, writeEmpty: true, additionalComment: "PCIe Port #4"},
237 PCISlot{PCIAddr: PCIAddr{Dev: 0x1c, Func: 4}, writeEmpty: true, additionalComment: "PCIe Port #5"},
238 PCISlot{PCIAddr: PCIAddr{Dev: 0x1c, Func: 5}, writeEmpty: true, additionalComment: "PCIe Port #6"},
239 PCISlot{PCIAddr: PCIAddr{Dev: 0x1c, Func: 6}, writeEmpty: true, additionalComment: "PCIe Port #7"},
240 PCISlot{PCIAddr: PCIAddr{Dev: 0x1c, Func: 7}, writeEmpty: true, additionalComment: "PCIe Port #8"},
241 PCISlot{PCIAddr: PCIAddr{Dev: 0x1d, Func: 0}, writeEmpty: true, additionalComment: "USB2 EHCI #1"},
242 PCISlot{PCIAddr: PCIAddr{Dev: 0x1e, Func: 0}, writeEmpty: true, additionalComment: "PCI bridge"},
243 PCISlot{PCIAddr: PCIAddr{Dev: 0x1f, Func: 0}, writeEmpty: true, additionalComment: "LPC bridge"},
244 PCISlot{PCIAddr: PCIAddr{Dev: 0x1f, Func: 2}, writeEmpty: true, additionalComment: "SATA Controller 1"},
245 PCISlot{PCIAddr: PCIAddr{Dev: 0x1f, Func: 3}, writeEmpty: true, additionalComment: "SMBus"},
246 PCISlot{PCIAddr: PCIAddr{Dev: 0x1f, Func: 5}, writeEmpty: true, additionalComment: "SATA Controller 2"},
247 PCISlot{PCIAddr: PCIAddr{Dev: 0x1f, Func: 6}, writeEmpty: true, additionalComment: "Thermal"},
248 },
249 }
250
251 b.node = &cur
252
253 xhciDev, ok := PCIMap[PCIAddr{Bus: 0, Dev: 0x14, Func: 0}]
254
255 if ok {
256 cur.Registers["xhci_switchable_ports"] = FormatHexLE32(xhciDev.ConfigDump[0xd4:0xd8])
257 cur.Registers["superspeed_capable_ports"] = FormatHexLE32(xhciDev.ConfigDump[0xdc:0xe0])
258 cur.Registers["xhci_overcurrent_mapping"] = FormatHexLE32(xhciDev.ConfigDump[0xc0:0xc4])
259 }
260
261 PutPCIChip(addr, cur)
262 PutPCIDevParent(addr, "PCI-LPC bridge", "lpc")
263
264 DSDTIncludes = append(DSDTIncludes, DSDTInclude{
265 File: "southbridge/intel/bd82x6x/acpi/platform.asl",
266 })
267 DSDTIncludes = append(DSDTIncludes, DSDTInclude{
268 File: "southbridge/intel/bd82x6x/acpi/globalnvs.asl",
269 Comment: "global NVS and variables",
270 })
271 DSDTIncludes = append(DSDTIncludes, DSDTInclude{
272 File: "southbridge/intel/bd82x6x/acpi/sleepstates.asl",
273 })
274 DSDTPCI0Includes = append(DSDTPCI0Includes, DSDTInclude{
275 File: "southbridge/intel/bd82x6x/acpi/pch.asl",
Stefan Reinauerf2ccc432015-06-20 21:40:42 +0200276 }, DSDTInclude{
277 File: "southbridge/intel/bd82x6x/acpi/default_irq_route.asl",
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200278 })
279
280 sb := Create(ctx, "early_southbridge.c")
281 defer sb.Close()
282 AddROMStageFile("early_southbridge.c", "")
283 sb.WriteString(`#include <stdint.h>
284#include <string.h>
285#include <lib.h>
286#include <timestamp.h>
287#include <arch/byteorder.h>
288#include <arch/io.h>
289#include <device/pci_def.h>
290#include <device/pnp_def.h>
291#include <cpu/x86/lapic.h>
292#include <arch/acpi.h>
293#include <console/console.h>
294#include "northbridge/intel/sandybridge/sandybridge.h"
295#include "northbridge/intel/sandybridge/raminit_native.h"
296#include "southbridge/intel/bd82x6x/pch.h"
297#include "southbridge/intel/bd82x6x/gpio.h"
298#include <arch/cpu.h>
299#include <cpu/x86/msr.h>
300
301void pch_enable_lpc(void)
302{
303`)
304 RestorePCI16Simple(sb, addr, 0x82)
305 RestorePCI32Simple(sb, addr, 0x84)
306 RestorePCI32Simple(sb, addr, 0x88)
307 RestorePCI32Simple(sb, addr, 0x8c)
308 RestorePCI32Simple(sb, addr, 0x90)
309
310 RestorePCI16Simple(sb, addr, 0x80)
311
312 RestorePCI32Simple(sb, addr, 0xac)
313
314 sb.WriteString(`}
315
316void rcba_config(void)
317{
318 /* Disable devices. */
319`)
320 RestoreRCBA32(sb, inteltool, 0x3414)
321 RestoreRCBA32(sb, inteltool, 0x3418)
322
323 sb.WriteString("\n}\n")
324
325 sb.WriteString("const struct southbridge_usb_port mainboard_usb_ports[] = {\n")
326
327 currentMap := map[uint32]int{
328 0x20000153: 0,
329 0x20000f57: 1,
330 0x2000055b: 2,
331 0x20000f51: 3,
332 0x2000094a: 4,
333 }
334
335 for port := uint(0); port < 14; port++ {
336 var pinmask uint32
337 OCPin := -1
338 if port < 8 {
339 pinmask = inteltool.RCBA[0x35a0]
340 } else {
341 pinmask = inteltool.RCBA[0x35a4]
342 }
343 for pin := uint(0); pin < 4; pin++ {
344 if ((pinmask >> ((port % 8) + 8*pin)) & 1) != 0 {
345 OCPin = int(pin)
346 if port >= 8 {
347 OCPin += 4
348 }
349 }
350 }
351 fmt.Fprintf(sb, "\t{ %d, %d, %d },\n",
352 ((inteltool.RCBA[0x359c]>>port)&1)^1,
353 currentMap[inteltool.RCBA[uint16(0x3500+4*port)]],
354 OCPin)
355 }
356 sb.WriteString("};\n")
357
358 guessedMap := GuessSPDMap(ctx)
359
360 sb.WriteString(`
361/* FIXME: Put proper SPD map here. */
362void mainboard_get_spd(spd_raw_data *spd)
363{
364`)
365 for i, spd := range guessedMap {
366 fmt.Fprintf(sb, "\tread_spd(&spd[%d], 0x%02x);\n", i, spd)
367 }
368 sb.WriteString("}\n")
369
370 gnvs := Create(ctx, "gnvs.c")
371 defer gnvs.Close()
372
373 gnvs.WriteString(`#include <southbridge/intel/bd82x6x/nvs.h>
374
375/* FIXME: check this function. */
376void acpi_create_gnvs(global_nvs_t *gnvs)
377{
378 /* Disable USB ports in S3 by default */
379 gnvs->s3u0 = 0;
380 gnvs->s3u1 = 0;
381
382 /* Disable USB ports in S5 by default */
383 gnvs->s5u0 = 0;
384 gnvs->s5u1 = 0;
385
386 // the lid is open by default.
387 gnvs->lids = 1;
388
389 gnvs->tcrt = 100;
390 gnvs->tpsv = 90;
391}
392`)
393
394 AddRAMStageFile("gnvs.c", "")
395}
396
397func init() {
398 /* BD82X6X LPC */
Vladimir Serbinenko42d55e02016-01-02 01:47:26 +0100399 for id := 0x1c40; id <= 0x1c5f; id++ {
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200400 RegisterPCI(0x8086, id, bd82x6x{variant: "BD82X6X"})
401 }
402
403 /* C216 LPC */
Vladimir Serbinenko42d55e02016-01-02 01:47:26 +0100404 for id := 0x1e41; id <= 0x1e5f; id++ {
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200405 RegisterPCI(0x8086, id, bd82x6x{variant: "C216"})
406 }
407
408 /* PCIe bridge */
409 for _, id := range []uint16{
410 0x1c10, 0x1c12, 0x1c14, 0x1c16,
411 0x1c18, 0x1c1a, 0x1c1c, 0x1c1e,
412 0x1e10, 0x1e12, 0x1e14, 0x1e16,
413 0x1e18, 0x1e1a, 0x1e1c, 0x1e1e,
414 } {
415 RegisterPCI(0x8086, id, GenericPCI{})
416 }
417
418 /* SMBus controller */
419 RegisterPCI(0x8086, 0x1c22, GenericPCI{MissingParent: "smbus"})
420 RegisterPCI(0x8086, 0x1e22, GenericPCI{MissingParent: "smbus"})
421
422 /* SATA */
423 for _, id := range []uint16{
424 0x1c00, 0x1c01, 0x1c02, 0x1c03,
425 0x1e00, 0x1e01, 0x1e02, 0x1e03,
426 } {
427 RegisterPCI(0x8086, id, GenericPCI{})
428 }
429
430 /* EHCI */
431 for _, id := range []uint16{
432 0x1c26, 0x1c2d, 0x1e26, 0x1e2d,
433 } {
434 RegisterPCI(0x8086, id, GenericPCI{})
435 }
436
437 /* XHCI */
438 RegisterPCI(0x8086, 0x1e31, GenericPCI{})
439
440 /* ME and children */
441 for _, id := range []uint16{
442 0x1c3a, 0x1c3b, 0x1c3c, 0x1c3d,
443 0x1e3a, 0x1e3b, 0x1e3c, 0x1e3d,
444 } {
445 RegisterPCI(0x8086, id, GenericPCI{})
446 }
447
448 /* Ethernet */
449 RegisterPCI(0x8086, 0x1502, GenericPCI{})
450
451}