diff options
author | Lubomir Rintel <lkundrak@v3.sk> | 2017-12-28 01:48:09 +0100 |
---|---|---|
committer | Kyösti Mälkki <kyosti.malkki@gmail.com> | 2018-05-16 06:19:34 +0000 |
commit | d8ec973fd24e091d0038d7060bfb516bad7534f0 (patch) | |
tree | 0945e83c1648cf6dc10569d863543b01de4362e8 /src/northbridge/via/vx900 | |
parent | faafbfb81e28df373d3319a6378e73cb37c9ced3 (diff) | |
download | coreboot-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/Kconfig | 1 | ||||
-rw-r--r-- | src/northbridge/via/vx900/Makefile.inc | 2 | ||||
-rw-r--r-- | src/northbridge/via/vx900/chrome9hd.c | 88 | ||||
-rw-r--r-- | src/northbridge/via/vx900/memmap.c | 128 | ||||
-rw-r--r-- | src/northbridge/via/vx900/northbridge.c | 6 | ||||
-rw-r--r-- | src/northbridge/via/vx900/vx900.h | 5 |
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); |