blob: 4a0f5031e8c651d2f5258e631ad578b5b80cf2ea [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",
276 })
277
278 sb := Create(ctx, "early_southbridge.c")
279 defer sb.Close()
280 AddROMStageFile("early_southbridge.c", "")
281 sb.WriteString(`#include <stdint.h>
282#include <string.h>
283#include <lib.h>
284#include <timestamp.h>
285#include <arch/byteorder.h>
286#include <arch/io.h>
287#include <device/pci_def.h>
288#include <device/pnp_def.h>
289#include <cpu/x86/lapic.h>
290#include <arch/acpi.h>
291#include <console/console.h>
292#include "northbridge/intel/sandybridge/sandybridge.h"
293#include "northbridge/intel/sandybridge/raminit_native.h"
294#include "southbridge/intel/bd82x6x/pch.h"
295#include "southbridge/intel/bd82x6x/gpio.h"
296#include <arch/cpu.h>
297#include <cpu/x86/msr.h>
298
299void pch_enable_lpc(void)
300{
301`)
302 RestorePCI16Simple(sb, addr, 0x82)
303 RestorePCI32Simple(sb, addr, 0x84)
304 RestorePCI32Simple(sb, addr, 0x88)
305 RestorePCI32Simple(sb, addr, 0x8c)
306 RestorePCI32Simple(sb, addr, 0x90)
307
308 RestorePCI16Simple(sb, addr, 0x80)
309
310 RestorePCI32Simple(sb, addr, 0xac)
311
312 sb.WriteString(`}
313
314void rcba_config(void)
315{
316 /* Disable devices. */
317`)
318 RestoreRCBA32(sb, inteltool, 0x3414)
319 RestoreRCBA32(sb, inteltool, 0x3418)
320
321 sb.WriteString("\n}\n")
322
323 sb.WriteString("const struct southbridge_usb_port mainboard_usb_ports[] = {\n")
324
325 currentMap := map[uint32]int{
326 0x20000153: 0,
327 0x20000f57: 1,
328 0x2000055b: 2,
329 0x20000f51: 3,
330 0x2000094a: 4,
331 }
332
333 for port := uint(0); port < 14; port++ {
334 var pinmask uint32
335 OCPin := -1
336 if port < 8 {
337 pinmask = inteltool.RCBA[0x35a0]
338 } else {
339 pinmask = inteltool.RCBA[0x35a4]
340 }
341 for pin := uint(0); pin < 4; pin++ {
342 if ((pinmask >> ((port % 8) + 8*pin)) & 1) != 0 {
343 OCPin = int(pin)
344 if port >= 8 {
345 OCPin += 4
346 }
347 }
348 }
349 fmt.Fprintf(sb, "\t{ %d, %d, %d },\n",
350 ((inteltool.RCBA[0x359c]>>port)&1)^1,
351 currentMap[inteltool.RCBA[uint16(0x3500+4*port)]],
352 OCPin)
353 }
354 sb.WriteString("};\n")
355
356 guessedMap := GuessSPDMap(ctx)
357
358 sb.WriteString(`
359/* FIXME: Put proper SPD map here. */
360void mainboard_get_spd(spd_raw_data *spd)
361{
362`)
363 for i, spd := range guessedMap {
364 fmt.Fprintf(sb, "\tread_spd(&spd[%d], 0x%02x);\n", i, spd)
365 }
366 sb.WriteString("}\n")
367
368 gnvs := Create(ctx, "gnvs.c")
369 defer gnvs.Close()
370
371 gnvs.WriteString(`#include <southbridge/intel/bd82x6x/nvs.h>
372
373/* FIXME: check this function. */
374void acpi_create_gnvs(global_nvs_t *gnvs)
375{
376 /* Disable USB ports in S3 by default */
377 gnvs->s3u0 = 0;
378 gnvs->s3u1 = 0;
379
380 /* Disable USB ports in S5 by default */
381 gnvs->s5u0 = 0;
382 gnvs->s5u1 = 0;
383
384 // the lid is open by default.
385 gnvs->lids = 1;
386
387 gnvs->tcrt = 100;
388 gnvs->tpsv = 90;
389}
390`)
391
392 AddRAMStageFile("gnvs.c", "")
393}
394
395func init() {
396 /* BD82X6X LPC */
397 for _, id := range []uint16{
398 0x1c46, 0x1c47, 0x1c49, 0x1c4a,
399 0x1c4b, 0x1c4c, 0x1c4d, 0x1c4e,
400 0x1c4f, 0x1c50, 0x1c52, 0x1c54,
401 0x1c56, 0x1c5c,
402 } {
403 RegisterPCI(0x8086, id, bd82x6x{variant: "BD82X6X"})
404 }
405
406 /* C216 LPC */
407 for _, id := range []uint16{
408 0x1e55, 0x1e57, 0x1e5d, 0x1e5e, 0x1e5f, 0x1e49,
409 } {
410 RegisterPCI(0x8086, id, bd82x6x{variant: "C216"})
411 }
412
413 /* PCIe bridge */
414 for _, id := range []uint16{
415 0x1c10, 0x1c12, 0x1c14, 0x1c16,
416 0x1c18, 0x1c1a, 0x1c1c, 0x1c1e,
417 0x1e10, 0x1e12, 0x1e14, 0x1e16,
418 0x1e18, 0x1e1a, 0x1e1c, 0x1e1e,
419 } {
420 RegisterPCI(0x8086, id, GenericPCI{})
421 }
422
423 /* SMBus controller */
424 RegisterPCI(0x8086, 0x1c22, GenericPCI{MissingParent: "smbus"})
425 RegisterPCI(0x8086, 0x1e22, GenericPCI{MissingParent: "smbus"})
426
427 /* SATA */
428 for _, id := range []uint16{
429 0x1c00, 0x1c01, 0x1c02, 0x1c03,
430 0x1e00, 0x1e01, 0x1e02, 0x1e03,
431 } {
432 RegisterPCI(0x8086, id, GenericPCI{})
433 }
434
435 /* EHCI */
436 for _, id := range []uint16{
437 0x1c26, 0x1c2d, 0x1e26, 0x1e2d,
438 } {
439 RegisterPCI(0x8086, id, GenericPCI{})
440 }
441
442 /* XHCI */
443 RegisterPCI(0x8086, 0x1e31, GenericPCI{})
444
445 /* ME and children */
446 for _, id := range []uint16{
447 0x1c3a, 0x1c3b, 0x1c3c, 0x1c3d,
448 0x1e3a, 0x1e3b, 0x1e3c, 0x1e3d,
449 } {
450 RegisterPCI(0x8086, id, GenericPCI{})
451 }
452
453 /* Ethernet */
454 RegisterPCI(0x8086, 0x1502, GenericPCI{})
455
456}