blob: 6c896fcc551ce46434f7181e4cd84656ee50633a [file] [log] [blame]
Stefan Reinauer49428d82013-02-21 15:48:37 -08001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2007-2009 coresystems GmbH
5 * Copyright (C) 2011 Google Inc.
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; version 2 of the License.
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.
Stefan Reinauer49428d82013-02-21 15:48:37 -080015 */
16
17#include <types.h>
18#include <string.h>
19#include <device/device.h>
Stefan Reinauer49428d82013-02-21 15:48:37 -080020#include <device/pci_def.h>
21#include <device/pci_ops.h>
22#include <console/console.h>
Martin Roth356b5192017-06-24 21:53:37 -060023#if IS_ENABLED(CONFIG_VGA_ROM_RUN)
Stefan Reinauer49428d82013-02-21 15:48:37 -080024#include <x86emu/x86emu.h>
25#endif
Stefan Reinauer49428d82013-02-21 15:48:37 -080026#include <arch/acpi.h>
27#include <arch/io.h>
28#include <arch/interrupt.h>
Stefan Reinauer3e4e3032013-03-20 14:08:04 -070029#include <boot/coreboot_tables.h>
Stefan Reinauer49428d82013-02-21 15:48:37 -080030#include "onboard.h"
31#include "ec.h"
32#include <southbridge/intel/bd82x6x/pch.h>
Patrick Rudolphe8e66f42016-02-06 17:42:42 +010033#include <southbridge/intel/common/gpio.h>
Stefan Reinauer49428d82013-02-21 15:48:37 -080034#include <smbios.h>
35#include <device/pci.h>
36#include <ec/google/chromeec/ec.h>
Aaron Durbinb0f81512016-07-25 21:31:41 -050037#include <vendorcode/google/chromeos/chromeos.h>
Stefan Reinauer49428d82013-02-21 15:48:37 -080038
39/* placeholder for evenual link post. Not sure what we'll
40 * do but it will look nice
41 */
42void mainboard_post(u8 value)
43{
44 /*
45 * What you DO NOT want to do: push every post to the EC backlight.
46 * it seems cute but in practice it looks like a hardware failure.
47 * I'm leaving this here so we don't make this mistake again later.
48 * And it seems to break the SMP startup.
49 * google_chromeec_post(value);
50 */
51}
52
Martin Roth356b5192017-06-24 21:53:37 -060053#if IS_ENABLED(CONFIG_VGA_ROM_RUN)
Stefan Reinauerfe8290d2013-04-23 15:00:02 -070054static int int15_handler(void)
Stefan Reinauer49428d82013-02-21 15:48:37 -080055{
Duncan Laurie1c054002013-05-10 13:50:09 -070056 int res = 0;
Stefan Reinauer49428d82013-02-21 15:48:37 -080057
58 printk(BIOS_DEBUG, "%s: INT15 function %04x!\n",
Stefan Reinauerfe8290d2013-04-23 15:00:02 -070059 __func__, X86_AX);
Stefan Reinauer49428d82013-02-21 15:48:37 -080060
Elyes HAOUAS0ce41f12018-11-13 10:03:31 +010061 switch (X86_AX) {
Stefan Reinauer49428d82013-02-21 15:48:37 -080062 case 0x5f34:
63 /*
64 * Set Panel Fitting Hook:
65 * bit 2 = Graphics Stretching
66 * bit 1 = Text Stretching
67 * bit 0 = Centering (do not set with bit1 or bit2)
68 * 0 = video bios default
69 */
Stefan Reinauerfe8290d2013-04-23 15:00:02 -070070 X86_AX = 0x005f;
71 X86_CL = 0x00; /* Use video bios default */
Duncan Laurie1c054002013-05-10 13:50:09 -070072 res = 1;
Stefan Reinauer49428d82013-02-21 15:48:37 -080073 break;
74 case 0x5f35:
75 /*
76 * Boot Display Device Hook:
77 * bit 0 = CRT
78 * bit 1 = TV (eDP)
79 * bit 2 = EFP
80 * bit 3 = LFP
81 * bit 4 = CRT2
82 * bit 5 = TV2 (eDP)
83 * bit 6 = EFP2
84 * bit 7 = LFP2
85 */
Stefan Reinauerfe8290d2013-04-23 15:00:02 -070086 X86_AX = 0x005f;
87 X86_CX = 0x0000; /* Use video bios default */
Duncan Laurie1c054002013-05-10 13:50:09 -070088 res = 1;
Stefan Reinauer49428d82013-02-21 15:48:37 -080089 break;
90 case 0x5f51:
91 /*
92 * Hook to select active LFP configuration:
93 * 00h = No LVDS, VBIOS does not enable LVDS
94 * 01h = Int-LVDS, LFP driven by integrated LVDS decoder
95 * 02h = SVDO-LVDS, LFP driven by SVDO decoder
96 * 03h = eDP, LFP Driven by Int-DisplayPort encoder
97 */
Stefan Reinauerfe8290d2013-04-23 15:00:02 -070098 X86_AX = 0x005f;
99 X86_CX = 0x0003; /* eDP */
Duncan Laurie1c054002013-05-10 13:50:09 -0700100 res = 1;
Stefan Reinauer49428d82013-02-21 15:48:37 -0800101 break;
102 case 0x5f70:
Stefan Reinauerfe8290d2013-04-23 15:00:02 -0700103 switch (X86_CH) {
Stefan Reinauer49428d82013-02-21 15:48:37 -0800104 case 0:
105 /* Get Mux */
Stefan Reinauerfe8290d2013-04-23 15:00:02 -0700106 X86_AX = 0x005f;
107 X86_CX = 0x0000;
Duncan Laurie1c054002013-05-10 13:50:09 -0700108 res = 1;
Stefan Reinauer49428d82013-02-21 15:48:37 -0800109 break;
110 case 1:
111 /* Set Mux */
Stefan Reinauerfe8290d2013-04-23 15:00:02 -0700112 X86_AX = 0x005f;
113 X86_CX = 0x0000;
Duncan Laurie1c054002013-05-10 13:50:09 -0700114 res = 1;
Stefan Reinauer49428d82013-02-21 15:48:37 -0800115 break;
116 case 2:
117 /* Get SG/Non-SG mode */
Stefan Reinauerfe8290d2013-04-23 15:00:02 -0700118 X86_AX = 0x005f;
119 X86_CX = 0x0000;
Duncan Laurie1c054002013-05-10 13:50:09 -0700120 res = 1;
Stefan Reinauer49428d82013-02-21 15:48:37 -0800121 break;
122 default:
123 /* Interrupt was not handled */
124 printk(BIOS_DEBUG, "Unknown INT15 5f70 function: 0x%02x\n",
Stefan Reinauerfe8290d2013-04-23 15:00:02 -0700125 X86_CH);
Duncan Laurie1c054002013-05-10 13:50:09 -0700126 break;
Stefan Reinauer49428d82013-02-21 15:48:37 -0800127 }
128 break;
129 case 0x5fac:
Duncan Laurie1c054002013-05-10 13:50:09 -0700130 res = 1;
Stefan Reinauer49428d82013-02-21 15:48:37 -0800131 break;
132 default:
Stefan Reinauerfe8290d2013-04-23 15:00:02 -0700133 printk(BIOS_DEBUG, "Unknown INT15 function %04x!\n", X86_AX);
Stefan Reinauer49428d82013-02-21 15:48:37 -0800134 break;
135 }
136 return res;
137}
138#endif
139
Stefan Reinauer49428d82013-02-21 15:48:37 -0800140
Stefan Reinauer49428d82013-02-21 15:48:37 -0800141
Elyes HAOUASd129d432018-05-04 20:23:33 +0200142static void mainboard_init(struct device *dev)
Stefan Reinauer49428d82013-02-21 15:48:37 -0800143{
Karthikeyan Ramasubramanianc80ff842018-09-17 16:19:34 -0600144 uint32_t board_version = 0;
145
Stefan Reinauer49428d82013-02-21 15:48:37 -0800146 /* Initialize the Embedded Controller */
147 link_ec_init();
148
Karthikeyan Ramasubramanianc80ff842018-09-17 16:19:34 -0600149 google_chromeec_get_board_version(&board_version);
150 if (board_version == 0) {
Stefan Reinauer49428d82013-02-21 15:48:37 -0800151 /* If running on proto1 - enable reversion of gpio11. */
152 u32 gpio_inv;
153 u16 gpio_base = pci_read_config16
Kyösti Mälkkic70eed12018-05-22 02:18:00 +0300154 (pcidev_on_root(0x1f, 0), GPIO_BASE) &
Stefan Reinauer49428d82013-02-21 15:48:37 -0800155 0xfffc;
156 u16 gpio_inv_addr = gpio_base + GPI_INV;
157 gpio_inv = inl(gpio_inv_addr);
158 outl(gpio_inv | (1 << 11), gpio_inv_addr);
159 }
160}
161
Elyes HAOUASd129d432018-05-04 20:23:33 +0200162static int link_onboard_smbios_data(struct device *dev, int *handle,
Stefan Reinauer49428d82013-02-21 15:48:37 -0800163 unsigned long *current)
164{
165 int len = 0;
166
Duncan Laurie21a78702013-05-23 14:17:05 -0700167 len += smbios_write_type41(
168 current, handle,
Kyösti Mälkkib9cd5ec2015-04-24 16:05:58 +0300169 BOARD_LIGHTSENSOR_NAME, /* name */
170 BOARD_LIGHTSENSOR_IRQ, /* instance */
Duncan Laurie21a78702013-05-23 14:17:05 -0700171 0, /* segment */
Kyösti Mälkkib9cd5ec2015-04-24 16:05:58 +0300172 BOARD_LIGHTSENSOR_I2C_ADDR, /* bus */
Duncan Laurie21a78702013-05-23 14:17:05 -0700173 0, /* device */
174 0); /* function */
Stefan Reinauer49428d82013-02-21 15:48:37 -0800175
Duncan Laurie21a78702013-05-23 14:17:05 -0700176 len += smbios_write_type41(
177 current, handle,
Kyösti Mälkkib9cd5ec2015-04-24 16:05:58 +0300178 BOARD_TRACKPAD_NAME, /* name */
179 BOARD_TRACKPAD_IRQ, /* instance */
Duncan Laurie21a78702013-05-23 14:17:05 -0700180 0, /* segment */
Kyösti Mälkkib9cd5ec2015-04-24 16:05:58 +0300181 BOARD_TRACKPAD_I2C_ADDR, /* bus */
Duncan Laurie21a78702013-05-23 14:17:05 -0700182 0, /* device */
183 0); /* function */
Stefan Reinauer49428d82013-02-21 15:48:37 -0800184
Duncan Laurie21a78702013-05-23 14:17:05 -0700185 len += smbios_write_type41(
186 current, handle,
Kyösti Mälkkib9cd5ec2015-04-24 16:05:58 +0300187 BOARD_TOUCHSCREEN_NAME, /* name */
188 BOARD_TOUCHSCREEN_IRQ, /* instance */
Duncan Laurie21a78702013-05-23 14:17:05 -0700189 0, /* segment */
Kyösti Mälkkib9cd5ec2015-04-24 16:05:58 +0300190 BOARD_TOUCHSCREEN_I2C_ADDR, /* bus */
Duncan Laurie21a78702013-05-23 14:17:05 -0700191 0, /* device */
192 0); /* function */
Stefan Reinauer49428d82013-02-21 15:48:37 -0800193
194 return len;
195}
196
197// mainboard_enable is executed as first thing after
198// enumerate_buses().
199
Elyes HAOUASd129d432018-05-04 20:23:33 +0200200static void mainboard_enable(struct device *dev)
Stefan Reinauer49428d82013-02-21 15:48:37 -0800201{
202 dev->ops->init = mainboard_init;
203 dev->ops->get_smbios_data = link_onboard_smbios_data;
Aaron Durbinb0f81512016-07-25 21:31:41 -0500204 dev->ops->acpi_inject_dsdt_generator = chromeos_dsdt_generator;
Martin Roth356b5192017-06-24 21:53:37 -0600205#if IS_ENABLED(CONFIG_VGA_ROM_RUN)
Stefan Reinauer49428d82013-02-21 15:48:37 -0800206 /* Install custom int15 handler for VGA OPROM */
Stefan Reinauerfe8290d2013-04-23 15:00:02 -0700207 mainboard_interrupt_handlers(0x15, &int15_handler);
Stefan Reinauer49428d82013-02-21 15:48:37 -0800208#endif
Stefan Reinauer49428d82013-02-21 15:48:37 -0800209}
210
211struct chip_operations mainboard_ops = {
Stefan Reinauer49428d82013-02-21 15:48:37 -0800212 .enable_dev = mainboard_enable,
213};