blob: 7ed279272bf7330e299de141a94c99fb587b7446 [file] [log] [blame]
Stefan Reinauerf75b19a2010-04-22 18:15:32 +00001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2007-2009 coresystems GmbH
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; version 2 of the License.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
Paul Menzela46a7122013-02-23 18:37:27 +010017 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Stefan Reinauerf75b19a2010-04-22 18:15:32 +000018 */
19
20#include <console/console.h>
21#include <arch/io.h>
22#include <stdint.h>
23#include <device/device.h>
24#include <device/pci.h>
25#include <device/pci_ids.h>
26#include <stdlib.h>
27#include <string.h>
Stefan Reinauerf75b19a2010-04-22 18:15:32 +000028#include <cpu/cpu.h>
29#include <cpu/x86/mtrr.h>
30#include <cpu/x86/msr.h>
31#include <arch/interrupt.h>
Patrick Georgi199b09c2012-11-22 12:46:12 +010032#include <x86emu/regs.h>
Stefan Reinauerc5334632012-11-13 12:49:59 -080033#if CONFIG_PCI_OPTION_ROM_RUN_REALMODE
Stefan Reinauer8d711552012-11-30 12:34:04 -080034#include <device/oprom/realmode/x86.h>
Stefan Reinauerc5334632012-11-13 12:49:59 -080035#endif
Stefan Reinauerf75b19a2010-04-22 18:15:32 +000036
Patrick Georgi199b09c2012-11-22 12:46:12 +010037static int via_vt8623_int15_handler(void)
Stefan Reinauerf75b19a2010-04-22 18:15:32 +000038{
Patrick Georgi503af722012-11-22 10:48:18 +010039 int res=0;
Stefan Reinauerf75b19a2010-04-22 18:15:32 +000040 printk(BIOS_DEBUG, "via_vt8623_int15_handler\n");
Patrick Georgi199b09c2012-11-22 12:46:12 +010041 switch(X86_EAX & 0xffff) {
Stefan Reinauerf75b19a2010-04-22 18:15:32 +000042 case 0x5f19:
43 break;
44 case 0x5f18:
Patrick Georgi199b09c2012-11-22 12:46:12 +010045 X86_EAX=0x5f;
46 X86_EBX=0x545; // MCLK = 133, 32M frame buffer, 256 M main memory
47 X86_ECX=0x060;
Patrick Georgi503af722012-11-22 10:48:18 +010048 res=1;
Stefan Reinauerf75b19a2010-04-22 18:15:32 +000049 break;
50 case 0x5f00:
Patrick Georgi199b09c2012-11-22 12:46:12 +010051 X86_EAX = 0x8600;
Stefan Reinauerf75b19a2010-04-22 18:15:32 +000052 break;
53 case 0x5f01:
Patrick Georgi199b09c2012-11-22 12:46:12 +010054 X86_EAX = 0x5f;
55 X86_ECX = (X86_ECX & 0xffffff00 ) | 2; // panel type = 2 = 1024 * 768
Patrick Georgi503af722012-11-22 10:48:18 +010056 res = 1;
Stefan Reinauerf75b19a2010-04-22 18:15:32 +000057 break;
58 case 0x5f02:
Patrick Georgi199b09c2012-11-22 12:46:12 +010059 X86_EAX=0x5f;
60 X86_EBX= (X86_EBX & 0xffff0000) | 2;
61 X86_ECX= (X86_ECX & 0xffff0000) | 0x401; // PAL + crt only
62 X86_EDX= (X86_EDX & 0xffff0000) | 0; // TV Layout - default
Patrick Georgi503af722012-11-22 10:48:18 +010063 res=1;
Stefan Reinauerf75b19a2010-04-22 18:15:32 +000064 break;
65 case 0x5f0f:
Patrick Georgi199b09c2012-11-22 12:46:12 +010066 X86_EAX=0x860f;
Stefan Reinauerf75b19a2010-04-22 18:15:32 +000067 break;
68 default:
Stefan Reinauer14e22772010-04-27 06:56:47 +000069 printk(BIOS_DEBUG, "Unknown INT15 function %04x!\n",
Patrick Georgi199b09c2012-11-22 12:46:12 +010070 X86_EAX & 0xffff);
Stefan Reinauerf75b19a2010-04-22 18:15:32 +000071 break;
72 }
73 return res;
74}
75
Stefan Reinauer841af5e2010-05-11 15:39:20 +000076#ifdef UNUSED_CODE
77static void write_protect_vgabios(void)
Stefan Reinauerf75b19a2010-04-22 18:15:32 +000078{
79 device_t dev;
80
81 printk(BIOS_DEBUG, "write_protect_vgabios\n");
82
83 dev = dev_find_device(PCI_VENDOR_ID_VIA, 0x3122, 0);
84 if (dev)
85 pci_write_config8(dev, 0x61, 0xaa);
86
87 dev = dev_find_device(PCI_VENDOR_ID_VIA, 0x3123, 0);
88 if (dev)
89 pci_write_config8(dev, 0x61, 0xaa);
90}
Stefan Reinauer841af5e2010-05-11 15:39:20 +000091#endif
Stefan Reinauerf75b19a2010-04-22 18:15:32 +000092
93static void vga_random_fixup(device_t dev)
94{
95 printk(BIOS_DEBUG, "VGA random fixup ...\n");
96 pci_write_config8(dev, 0x04, 0x07);
97 pci_write_config8(dev, 0x0d, 0x20);
98 pci_write_config32(dev,0x10,0xd8000008);
99 pci_write_config32(dev,0x14,0xdc000000);
100}
101
Stefan Reinauer841af5e2010-05-11 15:39:20 +0000102static void vga_enable_console(void)
103{
Stefan Reinauerc5334632012-11-13 12:49:59 -0800104#if CONFIG_PCI_OPTION_ROM_RUN_REALMODE
Stefan Reinauer841af5e2010-05-11 15:39:20 +0000105 /* Call VGA BIOS int10 function 0x4f14 to enable main console
106 * Epia-M does not always autosense the main console so forcing
107 * it on is good.
108 */
109
110 /* int#, EAX, EBX, ECX, EDX, ESI, EDI */
Michael Marineauba818172010-05-24 15:51:15 +0000111 realmode_interrupt(0x10, 0x4f14, 0x8003, 0x0001, 0x0000, 0x0000, 0x0000);
Stefan Reinauerc5334632012-11-13 12:49:59 -0800112#endif
Stefan Reinauer841af5e2010-05-11 15:39:20 +0000113}
114
Stefan Reinauerf75b19a2010-04-22 18:15:32 +0000115static void vga_init(device_t dev)
116{
117 vga_random_fixup(dev);
118
119 mainboard_interrupt_handlers(0x15, &via_vt8623_int15_handler);
120
121#ifdef MEASURE_VGA_INIT_TIME
122 msr_t clocks1, clocks2, instructions, setup;
123
124 // set up performnce counters for debugging vga init sequence
125 setup.lo = 0x1c0; // count instructions
126 wrmsr(0x187,setup);
127 instructions.hi = 0;
128 instructions.lo = 0;
129 wrmsr(0xc2,instructions);
130 clocks1 = rdmsr(0x10);
131#endif
132 printk(BIOS_DEBUG, "Initializing VGA...\n");
133
134 pci_dev_init(dev);
135
136 printk(BIOS_DEBUG, "Enable VGA console\n");
Stefan Reinauerf75b19a2010-04-22 18:15:32 +0000137 vga_enable_console();
Stefan Reinauer14e22772010-04-27 06:56:47 +0000138
Stefan Reinauerf75b19a2010-04-22 18:15:32 +0000139#ifdef MEASURE_VGA_INIT_TIME
140 clocks2 = rdmsr(0x10);
141 instructions = rdmsr(0xc2);
Stefan Reinauer14e22772010-04-27 06:56:47 +0000142
Stefan Reinauerf75b19a2010-04-22 18:15:32 +0000143 printk(BIOS_DEBUG, "Clocks 1 = %08x:%08x\n",clocks1.hi,clocks1.lo);
144 printk(BIOS_DEBUG, "Clocks 2 = %08x:%08x\n",clocks2.hi,clocks2.lo);
145 printk(BIOS_DEBUG, "Instructions = %08x:%08x\n",instructions.hi,instructions.lo);
146#endif
147
148 pci_write_config32(dev, 0x30, 0);
149
150#if 0
151 /* Set the vga mtrrs - disable for the moment as the add_var_mtrr function has vapourised */
152 unsigned long fb;
153 add_var_mtrr( 0xd0000000 >> 10, 0x08000000>>10, MTRR_TYPE_WRCOMB);
154 fb = pci_read_config32(dev,0x10); // get the fb address
155 add_var_mtrr( fb>>10, 8192, MTRR_TYPE_WRCOMB);
156#endif
157}
158
159static struct device_operations vga_operations = {
160 .read_resources = pci_dev_read_resources,
161 .set_resources = pci_dev_set_resources,
162 .enable_resources = pci_dev_enable_resources,
163 .init = vga_init,
164 .ops_pci = 0,
165};
166
167static const struct pci_driver vga_driver __pci_driver = {
168 .ops = &vga_operations,
169 .vendor = PCI_VENDOR_ID_VIA,
170 .device = 0x3122,
171};