blob: 8cc7607356999b0dd921deb75a33090b4e90884a [file] [log] [blame]
Lubomir Rinteld8ec9732017-12-28 01:48:09 +01001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2012 Alexandru Gagniuc <mr.nuke.me@gmail.com>
5 * Copyright (C) 2018 Lubomir Rintel <lkundrak@v3.sk>
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 */
17
18#define __SIMPLE_DEVICE__
19
20#include "vx900.h"
21
22#include <device/pci.h>
23#include <cbmem.h>
24
25#define MCU PCI_DEV(0, 0, 3)
26
27#define CHROME_9_HD_MIN_FB_SIZE 8
28#define CHROME_9_HD_MAX_FB_SIZE 512
29
30/* Helper to determine the framebuffer size */
31void vx900_set_chrome9hd_fb_size(u32 size_mb)
32{
33 u8 reg8, ranksize;
34 u32 tom_mb, max_size_mb;
35 int i;
36
37 /* The minimum framebuffer size is 8MB. */
38 size_mb = MAX(size_mb, CHROME_9_HD_MIN_FB_SIZE);
39
40 /*
41 * We have two limitations on the maximum framebuffer size:
42 * 1) (Sanity) No more that 1/4 of system RAM
43 * 2) (Hardware limitation) No larger than DRAM in last rank
44 * Check both of these limitations and apply them to our framebuffer */
45 tom_mb = (pci_read_config16(MCU, 0x88) & 0x07ff) << (24 - 20);
46 max_size_mb = tom_mb >> 2;
47 if (size_mb > max_size_mb) {
48 printk(BIOS_ALERT, "The framebuffer size of %dMB is larger"
49 " than 1/4 of available memory.\n"
50 " Limiting framebuffer to %dMB\n", size_mb, max_size_mb);
51 size_mb = max_size_mb;
52 }
53
54 /* Now handle limitation #2
55 * Look at the ending address of the memory ranks, from last to first,
56 * until we find one that is not zero. That is our last rank, and its
57 * size is the limit of our framebuffer. */
58 /* FIXME: This has a bug. If we remap memory above 4G, we consider the
59 * memory hole as part of our RAM. Thus if we install 3G, with a TOLM of
60 * 2.5G, our TOM will be at 5G and we'll assume we have 5G RAM instead
61 * of the actual 3.5G */
62 for (i = VX900_MAX_MEM_RANKS - 1; i > -1; i--) {
63 reg8 = pci_read_config8(MCU, 0x40 + i);
64 if (reg8 == 0)
65 continue;
66 /* We've reached the last populated rank */
67 ranksize = reg8 - pci_read_config8(MCU, 0x48 + i);
68 max_size_mb = ranksize << 6;
69 /* That's it. We got what we needed. */
70 break;
71 }
72 if (size_mb > max_size_mb) {
73 printk(BIOS_ALERT, "The framebuffer size of %dMB is larger"
74 " than size of the last DRAM rank.\n"
75 " Limiting framebuffer to %dMB\n", size_mb, max_size_mb);
76 size_mb = max_size_mb;
77 }
78
79 /* Now round the framebuffer size to the closest power of 2 */
80 u8 fb_pow = 0;
81 while (size_mb >> fb_pow)
82 fb_pow++;
83 fb_pow--;
84 size_mb = (1 << fb_pow);
85
86 pci_mod_config8(MCU, 0xa1, 7 << 4, (fb_pow - 2) << 4);
87}
88
89/* Gets the configured framebuffer size as a power of 2 */
90u8 vx900_get_chrome9hd_fb_pow(void)
91{
92 u8 fb_pow = (pci_read_config8(MCU, 0xa1) >> 4) & 7;
93
94 if (fb_pow > 0)
95 fb_pow += 2;
96
97 return fb_pow;
98}
99
100/* Gets the configured framebuffer size in MB */
101u32 vx900_get_chrome9hd_fb_size(void)
102{
103 u8 size = vx900_get_chrome9hd_fb_pow();
104
105 if (size == 0)
106 return 0;
107
108 return 1 << size;
109}
110
111u32 vx900_get_tolm(void)
112{
113 return (pci_read_config16(MCU, 0x84) & 0xfff0) >> 4;
114}
115
116void *cbmem_top(void)
117{
118 uintptr_t tolm;
119 uintptr_t fb_size;
120
121 tolm = vx900_get_tolm ();
122 fb_size = vx900_get_chrome9hd_fb_size ();
123
124 if (tolm > 0xfc0 || tolm <= 0x3ff || fb_size == 0x0)
125 return NULL;
126
127 return (void *)((tolm - fb_size) << 20);
128}