summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/mainboard/olpc/rev_a/cmos.layout1
-rw-r--r--src/mainboard/olpc/rev_a/mainboard.c62
2 files changed, 63 insertions, 0 deletions
diff --git a/src/mainboard/olpc/rev_a/cmos.layout b/src/mainboard/olpc/rev_a/cmos.layout
index 5ba4c032c1..7b3fe21b49 100644
--- a/src/mainboard/olpc/rev_a/cmos.layout
+++ b/src/mainboard/olpc/rev_a/cmos.layout
@@ -36,6 +36,7 @@ entries
424 4 e 7 boot_third
428 4 h 0 boot_index
432 8 h 0 boot_countdown
+440 1 e 0 dcon_present
1008 16 h 0 check_sum
enumerations
diff --git a/src/mainboard/olpc/rev_a/mainboard.c b/src/mainboard/olpc/rev_a/mainboard.c
index 80d01586c8..50698d5001 100644
--- a/src/mainboard/olpc/rev_a/mainboard.c
+++ b/src/mainboard/olpc/rev_a/mainboard.c
@@ -4,9 +4,69 @@
#include <device/pci_ids.h>
#include <device/pci_ops.h>
#include <arch/io.h>
+#include <pc80/mc146818rtc.h>
#include "chip.h"
+#include "../southbridge/amd/cs5536/cs5536_smbus2.h"
+/* Borrowed from mc146818rtc.c */
+#define CMOS_READ(addr) ({ \
+ outb((addr),RTC_PORT(0)); \
+ inb(RTC_PORT(1)); \
+ })
+
+#define CMOS_WRITE(val, addr) ({ \
+ outb((addr),RTC_PORT(0)); \
+ outb((val),RTC_PORT(1)); \
+ })
+
+static void write_bit(unsigned char val) {
+
+ unsigned char byte = CMOS_READ(440 / 8);
+
+ /* Don't change it if its already set */
+
+ if ((byte & 1) == (val & 1))
+ return;
+
+ byte &= ~1;
+ byte |= val & 1;
+ CMOS_WRITE(val, 440/8);
+}
+
+static unsigned short _getsmbusbase(void) {
+ unsigned devfn = PCI_DEVFN(0xf, 0);
+ device_t dev = dev_find_slot(0x0, devfn);
+ unsigned long addr = pci_read_config32(dev, PCI_BASE_ADDRESS_0);
+
+ return (unsigned short) (addr & ~1);
+}
+
+static void init_dcon(void) {
+
+ int ret = 1;
+ unsigned short rev = 0;
+ unsigned short iobase = _getsmbusbase();
+
+ printk_debug("CHECKING FOR DCON (%x)\n", iobase);
+
+ /* Get the IO base for the SMBUS */
+
+ rev = do_smbus_read_word(iobase, 0x0D << 1, 0x00);
+
+ if (rev & 0xDC00) {
+ printk_debug("DCON FOUND - REV %x\n", rev);
+
+ /* Enable the DCON */
+ ret = do_smbus_write_word(iobase, 0x0D << 1, 0x01, 0x0069);
+ if (ret != 0)
+ printk_debug("DCON ENABLE FAILED\n", ret);
+ }
+ else
+ printk_debug("DCON NOT FOUND (%x)\n", rev);
+
+ write_bit(rev > 0 ? 1 : 0);
+}
static void init(struct device *dev) {
/*
@@ -32,6 +92,8 @@ static void init(struct device *dev) {
pci_write_config8(usb, PCI_INTERRUPT_LINE, usbirq);
}
#endif
+
+ init_dcon();
printk_debug("OLPC REVA EXIT %s\n", __FUNCTION__);
}