blob: 03c8e0cf55b55279f3210e25311c42fa25416d82 [file] [log] [blame]
Alexandru Gagniuc23211b02013-06-09 16:06:07 -05001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2012 Alexandru Gagniuc <mr.nuke.me@gmail.com>
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 as published by
8 * the Free Software Foundation, either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
Alexandru Gagniuc23211b02013-06-09 16:06:07 -050015 */
16
17#include <arch/io.h>
18#include <config.h>
19#include <console/console.h>
20#include <device/pci.h>
21#include <device/pci_ids.h>
22#include <pc80/vga_io.h>
Alexandru Gagniuc560433b2013-06-10 15:47:25 -050023#include <stdlib.h>
Alexandru Gagniuc23211b02013-06-09 16:06:07 -050024
25#include "vx900.h"
26
27#define CHROME_9_HD_MIN_FB_SIZE 8
28#define CHROME_9_HD_MAX_FB_SIZE 512
29
30/**
31 * @file chrome9hd.c
32 *
33 * \brief Initialization for Chrome9HD integrated graphics adapters
34 *
35 * This takes care of the initialization we need to do before calling the VGA
36 * BIOS. The device is not documented in the VX900 datasheet.
37 *
38 * The device is documented in:
39 * Open Graphics Programming Manual
40 * Chrome9GraphicsHD Processor
41 * VX900 Series System Processor
42 * Part I: Graphics Core / 2D
43 *
44 * This document was released by VIA to the Xorg project, and is available at:
45 * <http://www.x.org/docs/via/OGPM_Chrome9%20HD%20DX9%20_R100_PartI_Core_2D.pdf>
46 *
47 * STATUS:
48 * We do the minimal initialization described in VIA documents. Running the VGA
49 * option ROM does not get us a usable display. We configure the framebuffer and
50 * the IGP is able to use it. GRUB2 and linux are capable of getting a usable
51 * text console, which uses the monitor's native resolution (even 1920x1080).
52 * The graphical console (linux) does not work properly.
Martin Roth543888d2015-01-06 10:20:42 -070053 * @todo
Alexandru Gagniuc23211b02013-06-09 16:06:07 -050054 * 1. Figure out what sequence we need to do to get the VGA BIOS running
55 * properly. Use the code provided by VIA and compare their sequence to ours,
56 * fill in any missing steps, etc.
57 * 2. Make BAR2 and the framebuffer use the same memory space. This is a feature
58 * called "Direct framebuffer access" which allows us to save memory space by
59 * setting BAR2 of the VGA to the location in memory of the framebuffer. This
60 * reduces the amount of PCI MMIO space we need below 4G, and is especially
61 * useful considering we only have 8GB (33 bits) of memory-mapped space.
62 */
63
64/* Helper to determine the framebuffer size */
65u32 chrome9hd_fb_size(void)
66{
67 static u32 fb_size = 0;
68 u8 reg8, ranksize;
69 u32 size_mb, tom_mb, max_size_mb;
70 int i;
71 /* We do some PCI and CMOS IO to find our value, so if we've already
72 * found it, save some time */
73 if (fb_size != 0)
74 return fb_size;
75 /* FIXME: read fb_size from CMOS, but until that is implemented, start
76 * from 512MB */
77 size_mb = 512;
78
79 /* The minimum framebuffer size is 8MB. */
Alexandru Gagniuc560433b2013-06-10 15:47:25 -050080 size_mb = MAX(size_mb, CHROME_9_HD_MIN_FB_SIZE);
Alexandru Gagniuc23211b02013-06-09 16:06:07 -050081
82 const device_t mcu = dev_find_device(PCI_VENDOR_ID_VIA,
83 PCI_DEVICE_ID_VIA_VX900_MEMCTRL,
84 0);
85 /*
86 * We have two limitations on the maximum framebuffer size:
87 * 1) (Sanity) No more that 1/4 of system RAM
88 * 2) (Hardware limitation) No larger than DRAM in last rank
89 * Check both of these limitations and apply them to our framebuffer */
90 tom_mb = (pci_read_config16(mcu, 0x88) & 0x07ff) << (24 - 20);
91 max_size_mb = tom_mb >> 2;
92 if (size_mb > max_size_mb) {
93 printk(BIOS_ALERT, "The framebuffer size of of %dMB is larger"
94 " than 1/4 of available memory.\n"
95 " Limiting framebuffer to %dMB\n", size_mb, max_size_mb);
96 size_mb = max_size_mb;
97 }
98
99 /* Now handle limitation #2
100 * Look at the ending address of the memory ranks, from last to first,
101 * until we find one that is not zero. That is our last rank, and its
102 * size is the limit of our framebuffer. */
103 /* FIXME: This has a bug. If we remap memory above 4G, we consider the
104 * memory hole as part of our RAM. Thus if we install 3G, with a TOLM of
105 * 2.5G, our TOM will be at 5G and we'll assume we have 5G RAM instead
106 * of the actual 3.5G */
107 for (i = VX900_MAX_MEM_RANKS - 1; i > -1; i--) {
108 reg8 = pci_read_config8(mcu, 0x40 + i);
109 if (reg8 == 0)
110 continue;
111 /* We've reached the last populated rank */
112 ranksize = reg8 - pci_read_config8(mcu, 0x48 + i);
113 max_size_mb = ranksize << 6;
114 /* That's it. We got what we needed. */
115 break;
116 };
117 if (size_mb > max_size_mb) {
118 printk(BIOS_ALERT, "The framebuffer size of %dMB is larger"
119 " than size of the last DRAM rank.\n"
120 " Limiting framebuffer to %dMB\n", size_mb, max_size_mb);
121 size_mb = max_size_mb;
122 }
123
124 /* Now round the framebuffer size to the closest power of 2 */
125 u8 fb_pow = 0;
126 while (size_mb >> fb_pow)
127 fb_pow++;
128 fb_pow--;
129 size_mb = (1 << fb_pow);
130 /* We store the framebuffer size in bytes, for simplicity */
131 fb_size = size_mb << 20;
132 return fb_size;
133}
134
135/**
Martin Roth6e222252014-12-29 14:44:38 -0700136 * vx900_int15
Alexandru Gagniuc23211b02013-06-09 16:06:07 -0500137 *
138 * \brief INT15 helpers for Chrome9HD IGP
139 *
140 * The following are helpers for INT15 handlers for the VGA BIOS. The full set
141 * of INT15 callbacks is described in
142 *
143 * VIA/S3Graphics
144 * Video BIOS External Interface Specification for Chrome9 Series IGP
145 * VX900 Series
146 *
147 * This document is only available under NDA, however, the callbacks are very
148 * similar to other VIA/Intel IGP callbacks.
149 *
150 * Callback 0x5f18 is the most important one. It informs the VGA BIOS of the
151 * RAM speed and framebuffer size. The other callbacks seem to be optional.
152 * @{
153 */
154
155/**
156 * \brief Get X86_BL value for VGA INT15 function 5f18
157 *
158 * Int15 5f18 lets the VGA BIOS know the framebuffer size and the memory speed.
159 * This handler is very important. If it is not implemented, the VGA BIOS will
160 * not work correctly.
161 *
162 * To use, just call this from the 15f18 handler, and place the return value in
163 * X86_BL
164 *
165 * @code{.c}
166 * case 0x5f18:
167 * X86_BX = vx900_int15_get_5f18_bl();
168 * res = 0;
169 * break;
170 * @endcode
171 *
172 */
173u8 vx900_int15_get_5f18_bl(void)
174{
175 u8 reg8, ret;
176 device_t dev;
177 /*
178 * BL Bit[7:4]
179 * Memory Data Rate (not to be confused with fCLK)
180 * 0000: 66MHz
181 * 0001: 100MHz
182 * 0010: 133MHz
183 * 0011: 200MHz ( DDR200 )
184 * 0100: 266MHz ( DDR266 )
185 * 0101: 333MHz ( DDR333 )
186 * 0110: 400MHz ( DDR400 )
187 * 0111: 533MHz ( DDR I/II 533)
188 * 1000: 667MHz ( DDR I/II 667)
189 * 1001: 800MHz ( DDR3 800)
190 * 1010: 1066MHz ( DDR3 1066)
191 * 1011: 1333MHz ( DDR3 1333)
192 * Bit[3:0]
193 * N: Frame Buffer Size 2^N MB
194 */
195 dev = dev_find_slot(0, PCI_DEVFN(0, 3));
196 reg8 = pci_read_config8(dev, 0xa1);
197 ret = (u32) ((reg8 & 0x70) >> 4) + 2;
198 reg8 = pci_read_config8(dev, 0x90);
199 reg8 = ((reg8 & 0x07) + 3) << 4;
200 ret |= (u32) reg8;
201
202 return ret;
203}
Alexandru Gagniuc560433b2013-06-10 15:47:25 -0500204
Alexandru Gagniuc23211b02013-06-09 16:06:07 -0500205/** @} */
206
207static void chrome9hd_set_sid_vid(u16 vendor, u16 device)
208{
209 vga_sr_write(0x36, vendor >> 8); /* SVID high byte */
210 vga_sr_write(0x35, vendor & 0xff); /* SVID low byte */
211 vga_sr_write(0x38, device >> 8); /* SID high byte */
212 vga_sr_write(0x37, device & 0xff); /* SID low byte */
213}
214
215static void chrome9hd_handle_uma(device_t dev)
216{
217 /* Mirror mirror, shiny glass, tell me that is not my ass */
218 u32 fb_size = chrome9hd_fb_size() >> 20;
219
Alexandru Gagniuc23211b02013-06-09 16:06:07 -0500220 u8 fb_pow = 0;
221 while (fb_size >> fb_pow)
222 fb_pow++;
223 fb_pow--;
224
225 /* Step 6 - Let MCU know the framebuffer size */
226 device_t mcu = dev_find_device(PCI_VENDOR_ID_VIA,
227 PCI_DEVICE_ID_VIA_VX900_MEMCTRL, 0);
228 pci_mod_config8(mcu, 0xa1, 7 << 4, (fb_pow - 2) << 4);
229
230 /* Step 7 - Let GFX know the framebuffer size (through PCI and IOCTL)
231 * The size we set here affects the behavior of BAR2, and the amount of
232 * MMIO space it requests. The default is 512MB, so if we don't set this
233 * before reading the resources, we could waste space below 4G */
234 pci_write_config8(dev, 0xb2, ((0xff << (fb_pow - 2)) & ~(1 << 7)));
235 vga_sr_write(0x68, (0xff << (fb_pow - 1)));
236 /* And also that the framebuffer is in the system, RAM */
237 pci_mod_config8(dev, 0xb0, 0, 1 << 0);
238}
239
240/**
241 * \brief Initialization sequence before running the VGA BIOS
242 *
243 * This is the initialization sequence described in:
244 *
245 * BIOS Porting Guide
246 * VX900 Series
247 * All-in-One System Processor
248 *
249 * This document is only available under NDA.
250 */
251static void chrome9hd_biosguide_init_seq(device_t dev)
252{
253 device_t mcu = dev_find_device(PCI_VENDOR_ID_VIA,
254 PCI_DEVICE_ID_VIA_VX900_MEMCTRL, 0);
255 device_t host = dev_find_device(PCI_VENDOR_ID_VIA,
256 PCI_DEVICE_ID_VIA_VX900_HOST_BR, 0);
257
258 /* Step 1 - Enable VGA controller */
259 /* FIXME: This is the VGA hole @ 640k-768k, and the vga port io
260 * We need the port IO, but can we disable the memory hole? */
261 pci_mod_config8(mcu, 0xa4, 0, (1 << 7)); /* VGA memory hole */
262
263 /* Step 2 - Forward MDA cycles to GFX */
264 pci_mod_config8(host, 0x4e, 0, (1 << 1));
265
266 /* Step 3 - Enable GFX I/O space */
267 pci_mod_config8(dev, PCI_COMMAND, 0, PCI_COMMAND_IO);
268
269 /* Step 4 - Enable video subsystem */
270 vga_enable_mask((1 << 0), (1 << 0));
271
272 /* FIXME: VGA IO Address Select. 3B5 or 3D5? */
273 vga_misc_mask((1 << 0), (1 << 0));
274
275 /* Step 5 - Unlock accessing of IO space */
276 vga_sr_write(0x10, 0x01);
277
278 chrome9hd_handle_uma(dev);
279
Kyösti Mälkki5cf88242013-10-18 11:02:56 +0300280 uint64_t gfx_base = get_uma_memory_base();
281 if (gfx_base == 0)
Alexandru Gagniuc23211b02013-06-09 16:06:07 -0500282 die("uma_memory_base not set. Abandon ship!\n");
Kyösti Mälkki5cf88242013-10-18 11:02:56 +0300283
284 /* Step 8 - Enable memory base register on the GFX */
285 vga_sr_write(0x6d, (gfx_base >> 21) & 0xff); /* base 28:21 */
286 vga_sr_write(0x6e, (gfx_base >> 29) & 0xff); /* base 36:29 */
Alexandru Gagniuc23211b02013-06-09 16:06:07 -0500287 vga_sr_write(0x6f, 0x00); /* base 43:37 */
288
289 /* Step 9 - Set SID/VID */
290 chrome9hd_set_sid_vid(0x1106, 0x7122);
291
292}
293
294static void chrome9hd_init(device_t dev)
295{
Stefan Reinauer65b72ab2015-01-05 12:59:54 -0800296 printk(BIOS_DEBUG, "======================================================\n");
297 printk(BIOS_DEBUG, "== Chrome9 HD INIT\n");
298 printk(BIOS_DEBUG, "======================================================\n");
Alexandru Gagniuc23211b02013-06-09 16:06:07 -0500299
300 chrome9hd_biosguide_init_seq(dev);
301
302 /* Prime PLL FIXME: bad comment */
303 vga_sr_mask(0x3c, 1 << 2, 1 << 2);
304
305 /* FIXME: recheck; VGA IO Address Select. 3B5 or 3D5? */
306 vga_misc_mask(1 << 0, 1 << 0);
307
308 /* FIXME: recheck; Enable Base VGA 16 Bits Decode */
309 ////pci_mod_config8(host, 0x4e, 0, 1<<4);
310
311 u32 fb_address = pci_read_config32(dev, PCI_BASE_ADDRESS_2);
312 fb_address &= ~0x0F;
313 if (!fb_address) {
314 printk(BIOS_WARNING, "Chrome9HD: No FB BAR assigned!\n");
315 return;
316 }
317
318 printk(BIOS_INFO, "Chrome: Using %dMB Framebuffer at 0x%08X.\n",
319 256, fb_address);
320
321 printk(BIOS_DEBUG, "Initializing VGA...\n");
322
323 pci_dev_init(dev);
324
325 printk(BIOS_DEBUG, "Enable VGA console\n");
326
327 dump_pci_device(dev);
328}
329
330static void chrome9hd_enable(device_t dev)
331{
332 device_t mcu = dev_find_device(PCI_VENDOR_ID_VIA,
333 PCI_DEVICE_ID_VIA_VX900_MEMCTRL, 0);
Elyes HAOUAS0f92f632014-07-27 19:37:31 +0200334 /* FIXME: here? -=- ACLK 250MHz */
Alexandru Gagniuc23211b02013-06-09 16:06:07 -0500335 pci_mod_config8(mcu, 0xbb, 0, 0x01);
336}
337
338static void chrome9hd_disable(device_t dev)
339{
340 device_t mcu = dev_find_device(PCI_VENDOR_ID_VIA,
341 PCI_DEVICE_ID_VIA_VX900_MEMCTRL, 0);
342 /* Disable GFX - This step effectively renders the GFX inert
343 * It won't even show up as a PCI device during enumeration */
344 pci_mod_config8(mcu, 0xa1, 1 << 7, 0);
345}
346
347static struct device_operations chrome9hd_operations = {
348 .read_resources = pci_dev_read_resources,
349 .set_resources = pci_dev_set_resources,
350 .enable_resources = pci_dev_enable_resources,
351 .init = chrome9hd_init,
352 .disable = chrome9hd_disable,
353 .enable = chrome9hd_enable,
354 .ops_pci = 0,
355};
356
357static const struct pci_driver chrome9hd_driver __pci_driver = {
358 .ops = &chrome9hd_operations,
359 .vendor = PCI_VENDOR_ID_VIA,
360 .device = PCI_DEVICE_ID_VIA_VX900_VGA,
361};