summaryrefslogtreecommitdiff
path: root/src/northbridge/via/vx900
diff options
context:
space:
mode:
authorLubomir Rintel <lkundrak@v3.sk>2017-12-28 01:48:09 +0100
committerKyösti Mälkki <kyosti.malkki@gmail.com>2018-05-16 06:19:34 +0000
commitd8ec973fd24e091d0038d7060bfb516bad7534f0 (patch)
tree0945e83c1648cf6dc10569d863543b01de4362e8 /src/northbridge/via/vx900
parentfaafbfb81e28df373d3319a6378e73cb37c9ced3 (diff)
downloadcoreboot-d8ec973fd24e091d0038d7060bfb516bad7534f0.tar.xz
vx900: Move to EARLY_CBMEM_INIT
To calculate the CBMEM address we need to determine the framebuffer size early in the ROMSTAGE. We now do the calculation before cbmem_recovery() and configure the memory controller right away. If the calculation was done from cbmem_top() instead, we'd loose some logging that seems useful, since printk() would recurse to cbmem_top() too with CONSOLE_CBMEM enabled. If we didn't configure the memory controller at this point, we'd need to store the result somewhere else. However, CAR_GLOBAL is not practical at this point, because calling car_get_var() from cbmem_top() would recurse back to cbmem_top(). Change-Id: Ib9ae0f97f9f769a20a610f8d76f14165fb924042 Signed-off-by: Lubomir Rintel <lkundrak@v3.sk> Reviewed-on: https://review.coreboot.org/25798 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Kyösti Mälkki <kyosti.malkki@gmail.com>
Diffstat (limited to 'src/northbridge/via/vx900')
-rw-r--r--src/northbridge/via/vx900/Kconfig1
-rw-r--r--src/northbridge/via/vx900/Makefile.inc2
-rw-r--r--src/northbridge/via/vx900/chrome9hd.c88
-rw-r--r--src/northbridge/via/vx900/memmap.c128
-rw-r--r--src/northbridge/via/vx900/northbridge.c6
-rw-r--r--src/northbridge/via/vx900/vx900.h5
6 files changed, 139 insertions, 91 deletions
diff --git a/src/northbridge/via/vx900/Kconfig b/src/northbridge/via/vx900/Kconfig
index bb5e06fc77..e9d94514ca 100644
--- a/src/northbridge/via/vx900/Kconfig
+++ b/src/northbridge/via/vx900/Kconfig
@@ -21,7 +21,6 @@ config NORTHBRIDGE_VIA_VX900
select HAVE_DEBUG_RAM_SETUP
select HAVE_DEBUG_SMBUS
select HAVE_HARD_RESET
- select LATE_CBMEM_INIT
if NORTHBRIDGE_VIA_VX900
diff --git a/src/northbridge/via/vx900/Makefile.inc b/src/northbridge/via/vx900/Makefile.inc
index b46f8809d6..bbfe63b45a 100644
--- a/src/northbridge/via/vx900/Makefile.inc
+++ b/src/northbridge/via/vx900/Makefile.inc
@@ -21,6 +21,7 @@ romstage-y += early_smbus.c
romstage-y += early_vx900.c
romstage-y += early_host_bus_ctl.c
romstage-y += raminit_ddr3.c
+romstage-y += memmap.c
romstage-y += ./../../../device/dram/ddr3.c
romstage-y += ./../../../southbridge/via/common/early_smbus_delay.c
romstage-y += ./../../../southbridge/via/common/early_smbus_is_busy.c
@@ -36,6 +37,7 @@ ramstage-y += chrome9hd.c
ramstage-y += traf_ctrl.c
ramstage-y += sata.c
ramstage-y += lpc.c
+ramstage-y += memmap.c
# The buildsystem only includes this file if CONFIG_VGA is selected.
# We need to do some VGA I/O before the VGA can be initialized. We can make good
diff --git a/src/northbridge/via/vx900/chrome9hd.c b/src/northbridge/via/vx900/chrome9hd.c
index 147b30894b..00b5c4bb77 100644
--- a/src/northbridge/via/vx900/chrome9hd.c
+++ b/src/northbridge/via/vx900/chrome9hd.c
@@ -23,9 +23,6 @@
#include "vx900.h"
-#define CHROME_9_HD_MIN_FB_SIZE 8
-#define CHROME_9_HD_MAX_FB_SIZE 512
-
/**
* @file chrome9hd.c
*
@@ -60,77 +57,6 @@
* useful considering we only have 8GB (33 bits) of memory-mapped space.
*/
-/* Helper to determine the framebuffer size */
-u32 chrome9hd_fb_size(void)
-{
- static u32 fb_size = 0;
- u8 reg8, ranksize;
- u32 size_mb, tom_mb, max_size_mb;
- int i;
- /* We do some PCI and CMOS IO to find our value, so if we've already
- * found it, save some time */
- if (fb_size != 0)
- return fb_size;
- /* FIXME: read fb_size from CMOS, but until that is implemented, start
- * from 512MB */
- size_mb = 512;
-
- /* The minimum framebuffer size is 8MB. */
- size_mb = MAX(size_mb, CHROME_9_HD_MIN_FB_SIZE);
-
- const device_t mcu = dev_find_device(PCI_VENDOR_ID_VIA,
- PCI_DEVICE_ID_VIA_VX900_MEMCTRL,
- 0);
- /*
- * We have two limitations on the maximum framebuffer size:
- * 1) (Sanity) No more that 1/4 of system RAM
- * 2) (Hardware limitation) No larger than DRAM in last rank
- * Check both of these limitations and apply them to our framebuffer */
- tom_mb = (pci_read_config16(mcu, 0x88) & 0x07ff) << (24 - 20);
- max_size_mb = tom_mb >> 2;
- if (size_mb > max_size_mb) {
- printk(BIOS_ALERT, "The framebuffer size of %dMB is larger"
- " than 1/4 of available memory.\n"
- " Limiting framebuffer to %dMB\n", size_mb, max_size_mb);
- size_mb = max_size_mb;
- }
-
- /* Now handle limitation #2
- * Look at the ending address of the memory ranks, from last to first,
- * until we find one that is not zero. That is our last rank, and its
- * size is the limit of our framebuffer. */
- /* FIXME: This has a bug. If we remap memory above 4G, we consider the
- * memory hole as part of our RAM. Thus if we install 3G, with a TOLM of
- * 2.5G, our TOM will be at 5G and we'll assume we have 5G RAM instead
- * of the actual 3.5G */
- for (i = VX900_MAX_MEM_RANKS - 1; i > -1; i--) {
- reg8 = pci_read_config8(mcu, 0x40 + i);
- if (reg8 == 0)
- continue;
- /* We've reached the last populated rank */
- ranksize = reg8 - pci_read_config8(mcu, 0x48 + i);
- max_size_mb = ranksize << 6;
- /* That's it. We got what we needed. */
- break;
- };
- if (size_mb > max_size_mb) {
- printk(BIOS_ALERT, "The framebuffer size of %dMB is larger"
- " than size of the last DRAM rank.\n"
- " Limiting framebuffer to %dMB\n", size_mb, max_size_mb);
- size_mb = max_size_mb;
- }
-
- /* Now round the framebuffer size to the closest power of 2 */
- u8 fb_pow = 0;
- while (size_mb >> fb_pow)
- fb_pow++;
- fb_pow--;
- size_mb = (1 << fb_pow);
- /* We store the framebuffer size in bytes, for simplicity */
- fb_size = size_mb << 20;
- return fb_size;
-}
-
/**
* vx900_int15
*
@@ -213,18 +139,10 @@ static void chrome9hd_set_sid_vid(u16 vendor, u16 device)
static void chrome9hd_handle_uma(device_t dev)
{
- /* Mirror mirror, shiny glass, tell me that is not my ass */
- u32 fb_size = chrome9hd_fb_size() >> 20;
-
- u8 fb_pow = 0;
- while (fb_size >> fb_pow)
- fb_pow++;
- fb_pow--;
+ u8 fb_pow = vx900_get_chrome9hd_fb_pow();
- /* Step 6 - Let MCU know the framebuffer size */
- device_t mcu = dev_find_device(PCI_VENDOR_ID_VIA,
- PCI_DEVICE_ID_VIA_VX900_MEMCTRL, 0);
- pci_mod_config8(mcu, 0xa1, 7 << 4, (fb_pow - 2) << 4);
+ if (fb_pow == 0)
+ return;
/* Step 7 - Let GFX know the framebuffer size (through PCI and IOCTL)
* The size we set here affects the behavior of BAR2, and the amount of
diff --git a/src/northbridge/via/vx900/memmap.c b/src/northbridge/via/vx900/memmap.c
new file mode 100644
index 0000000000..8cc7607356
--- /dev/null
+++ b/src/northbridge/via/vx900/memmap.c
@@ -0,0 +1,128 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2012 Alexandru Gagniuc <mr.nuke.me@gmail.com>
+ * Copyright (C) 2018 Lubomir Rintel <lkundrak@v3.sk>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#define __SIMPLE_DEVICE__
+
+#include "vx900.h"
+
+#include <device/pci.h>
+#include <cbmem.h>
+
+#define MCU PCI_DEV(0, 0, 3)
+
+#define CHROME_9_HD_MIN_FB_SIZE 8
+#define CHROME_9_HD_MAX_FB_SIZE 512
+
+/* Helper to determine the framebuffer size */
+void vx900_set_chrome9hd_fb_size(u32 size_mb)
+{
+ u8 reg8, ranksize;
+ u32 tom_mb, max_size_mb;
+ int i;
+
+ /* The minimum framebuffer size is 8MB. */
+ size_mb = MAX(size_mb, CHROME_9_HD_MIN_FB_SIZE);
+
+ /*
+ * We have two limitations on the maximum framebuffer size:
+ * 1) (Sanity) No more that 1/4 of system RAM
+ * 2) (Hardware limitation) No larger than DRAM in last rank
+ * Check both of these limitations and apply them to our framebuffer */
+ tom_mb = (pci_read_config16(MCU, 0x88) & 0x07ff) << (24 - 20);
+ max_size_mb = tom_mb >> 2;
+ if (size_mb > max_size_mb) {
+ printk(BIOS_ALERT, "The framebuffer size of %dMB is larger"
+ " than 1/4 of available memory.\n"
+ " Limiting framebuffer to %dMB\n", size_mb, max_size_mb);
+ size_mb = max_size_mb;
+ }
+
+ /* Now handle limitation #2
+ * Look at the ending address of the memory ranks, from last to first,
+ * until we find one that is not zero. That is our last rank, and its
+ * size is the limit of our framebuffer. */
+ /* FIXME: This has a bug. If we remap memory above 4G, we consider the
+ * memory hole as part of our RAM. Thus if we install 3G, with a TOLM of
+ * 2.5G, our TOM will be at 5G and we'll assume we have 5G RAM instead
+ * of the actual 3.5G */
+ for (i = VX900_MAX_MEM_RANKS - 1; i > -1; i--) {
+ reg8 = pci_read_config8(MCU, 0x40 + i);
+ if (reg8 == 0)
+ continue;
+ /* We've reached the last populated rank */
+ ranksize = reg8 - pci_read_config8(MCU, 0x48 + i);
+ max_size_mb = ranksize << 6;
+ /* That's it. We got what we needed. */
+ break;
+ }
+ if (size_mb > max_size_mb) {
+ printk(BIOS_ALERT, "The framebuffer size of %dMB is larger"
+ " than size of the last DRAM rank.\n"
+ " Limiting framebuffer to %dMB\n", size_mb, max_size_mb);
+ size_mb = max_size_mb;
+ }
+
+ /* Now round the framebuffer size to the closest power of 2 */
+ u8 fb_pow = 0;
+ while (size_mb >> fb_pow)
+ fb_pow++;
+ fb_pow--;
+ size_mb = (1 << fb_pow);
+
+ pci_mod_config8(MCU, 0xa1, 7 << 4, (fb_pow - 2) << 4);
+}
+
+/* Gets the configured framebuffer size as a power of 2 */
+u8 vx900_get_chrome9hd_fb_pow(void)
+{
+ u8 fb_pow = (pci_read_config8(MCU, 0xa1) >> 4) & 7;
+
+ if (fb_pow > 0)
+ fb_pow += 2;
+
+ return fb_pow;
+}
+
+/* Gets the configured framebuffer size in MB */
+u32 vx900_get_chrome9hd_fb_size(void)
+{
+ u8 size = vx900_get_chrome9hd_fb_pow();
+
+ if (size == 0)
+ return 0;
+
+ return 1 << size;
+}
+
+u32 vx900_get_tolm(void)
+{
+ return (pci_read_config16(MCU, 0x84) & 0xfff0) >> 4;
+}
+
+void *cbmem_top(void)
+{
+ uintptr_t tolm;
+ uintptr_t fb_size;
+
+ tolm = vx900_get_tolm ();
+ fb_size = vx900_get_chrome9hd_fb_size ();
+
+ if (tolm > 0xfc0 || tolm <= 0x3ff || fb_size == 0x0)
+ return NULL;
+
+ return (void *)((tolm - fb_size) << 20);
+}
diff --git a/src/northbridge/via/vx900/northbridge.c b/src/northbridge/via/vx900/northbridge.c
index bf6cb660a0..3f839c7f72 100644
--- a/src/northbridge/via/vx900/northbridge.c
+++ b/src/northbridge/via/vx900/northbridge.c
@@ -245,7 +245,7 @@ static void vx900_set_resources(device_t dev)
printk(BIOS_SPEW, "Found top of memory at %dMB\n", tomk >> 10);
/* Do the same for top of low RAM */
- vx900_tolm = (pci_read_config16(mcu, 0x84) & 0xfff0) >> 4;
+ vx900_tolm = vx900_get_tolm();
full_tolmk = vx900_tolm << (20 - 10);
/* Remap above 4G if needed */
full_tolmk = MIN(full_tolmk, pci_tolm >> 10);
@@ -253,7 +253,7 @@ static void vx900_set_resources(device_t dev)
full_tolmk >> 10);
/* What about the framebuffer for the integrated GPU? */
- fbufk = chrome9hd_fb_size() >> 10;
+ fbufk = vx900_get_chrome9hd_fb_size() << (20 - 10);
printk(BIOS_SPEW, "Integrated graphics buffer: %dMB\n", fbufk >> 10);
/* Can't use the framebuffer as system RAM, sorry */
@@ -279,8 +279,6 @@ static void vx900_set_resources(device_t dev)
if (tor)
ram_resource(dev, idx++, RAM_4GB >> 10, (tor - RAM_4GB) >> 10);
- set_late_cbmem_top(tolmk << 10);
-
printk(BIOS_DEBUG, "======================================================\n");
assign_resources(dev->link_list);
}
diff --git a/src/northbridge/via/vx900/vx900.h b/src/northbridge/via/vx900/vx900.h
index fe756f9665..cb7bca9703 100644
--- a/src/northbridge/via/vx900/vx900.h
+++ b/src/northbridge/via/vx900/vx900.h
@@ -31,7 +31,10 @@
#include <console/console.h>
-u32 chrome9hd_fb_size(void);
+u32 vx900_get_tolm(void);
+void vx900_set_chrome9hd_fb_size(u32 size_mb);
+u8 vx900_get_chrome9hd_fb_pow(void);
+u32 vx900_get_chrome9hd_fb_size(void);
u8 vx900_int15_get_5f18_bl(void);
uint64_t get_uma_memory_base(void);