blob: 80fc2c6a4a219446064408903661af4aaefdc22a [file] [log] [blame]
Christian Gmeiner86f992c2012-07-13 11:36:08 +02001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2012 Bachmann electronic GmbH
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Paul Menzela8ae1c62013-02-20 13:21:20 +010012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Christian Gmeiner86f992c2012-07-13 11:36:08 +020013 * GNU General Public License for more details.
Christian Gmeiner86f992c2012-07-13 11:36:08 +020014 */
15
16#include <device/device.h>
Christian Gmeinera59a9f72012-09-14 16:29:10 +020017#include <device/smbus.h>
18#include <smbios.h>
19#include <console/console.h>
Christian Gmeiner4412bc42013-03-12 11:07:07 +010020#include <cpu/x86/msr.h>
Christian Gmeiner1990ab92013-05-23 13:26:37 +020021#include <arch/io.h>
Christian Gmeinera59a9f72012-09-14 16:29:10 +020022
23/* overwrite a weak function to fill SMBIOS table with a custom value */
24static u8 hw_rev = 0;
25static char mb_rev_str[2] = { '0' };
26
27const char *smbios_mainboard_version(void)
28{
29 /* UDMA is not working on all supported devices */
30 if (hw_rev < 113) {
31 mb_rev_str[0] = '1';
32 } else {
33 mb_rev_str[0] = '2';
34 }
35
36 return mb_rev_str;
37}
38
39static void init(struct device *dev)
40{
41 unsigned int i;
42 u32 chksum = 0;
43 char block[20];
Christian Gmeiner4412bc42013-03-12 11:07:07 +010044 msr_t reset;
Christian Gmeinera59a9f72012-09-14 16:29:10 +020045 device_t eeprom_dev = dev_find_slot_on_smbus(1, 0x52);
46
47 if (eeprom_dev == 0) {
48 printk(BIOS_WARNING, "eeprom not found\n");
49 return;
50 }
51
Christian Gmeiner1990ab92013-05-23 13:26:37 +020052 /* turn off all leds except led_ini */
53 outb(0x02, 0x5a); /* bit0 - led_run */
54 /* bit1 - led_ini */
55 /* bit2 - led_err */
56 /* bit3-bit7 - write has no effect */
57 outb(0x00, 0x49); /* bit0-bit6 - led_7-led_1 */
58 /* bit7 - write has no effect */
59
Christian Gmeinera59a9f72012-09-14 16:29:10 +020060 /* read the whole block and check if checksum is okay */
61 for (i = 0; i < 20; i++) {
62 block[i] = smbus_read_byte(eeprom_dev, i);
63 chksum += block[i];
64 }
65
66 if (chksum != 0) {
67 printk(BIOS_WARNING, "wrong checksum: 0x%0x\n", chksum);
68 }
69
70 hw_rev = block[5];
71
72 printk(BIOS_DEBUG, "hw revision: %u\n", hw_rev);
Christian Gmeiner4412bc42013-03-12 11:07:07 +010073
74 /* Reset MFGPT7 (standby power domain) - this is done via
75 * an undocumented register */
76 reset = rdmsr(0x5140002b);
77 reset.lo |= 1 << 7;
78 wrmsr(0x5140002b, reset);
Christian Gmeinera59a9f72012-09-14 16:29:10 +020079}
80
Paul Menzel528640d2013-02-23 21:31:23 +010081static void mainboard_enable(struct device *dev)
Christian Gmeinera59a9f72012-09-14 16:29:10 +020082{
83 dev->ops->init = init;
84}
Christian Gmeiner86f992c2012-07-13 11:36:08 +020085
86struct chip_operations mainboard_ops = {
Paul Menzel528640d2013-02-23 21:31:23 +010087 .enable_dev = mainboard_enable,
Christian Gmeiner86f992c2012-07-13 11:36:08 +020088};