blob: 98e4bd2f0032653245165f3430a4aaf3b4dfc7d6 [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 <console/console.h>
18#include <device/pci.h>
19#include <device/pci_ids.h>
20
21#include "vx900.h"
22
23/**
Martin Roth543888d2015-01-06 10:20:42 -070024 * @file vx900/sata.c
Alexandru Gagniuc23211b02013-06-09 16:06:07 -050025 *
26 * STATUS: Pretty good
27 * The only issue is the SATA EPHY configuration. We do not know if it is board
28 * specific or not. Otherwise, the SATA controller works without issues.
29 */
30
31static void vx900_print_sata_errors(u32 flags)
32{
33 /* Status flags */
34 printk(BIOS_DEBUG, "\tPhyRdy %s\n",
35 (flags & (1 << 16)) ? "changed" : "not changed");
36 printk(BIOS_DEBUG, "\tCOMWAKE %s\n",
37 (flags & (1 << 16)) ? "detected" : "not detected");
38 printk(BIOS_DEBUG, "\tExchange as determined by COMINIT %s\n",
Martin Roth2ed0aa22016-01-05 20:58:58 -070039 (flags & (1 << 26)) ? "occurred" : "not occurred");
Alexandru Gagniuc23211b02013-06-09 16:06:07 -050040 printk(BIOS_DEBUG, "\tPort selector presence %s\n",
41 (flags & (1 << 27)) ? "detected" : "not detected");
42 /* Errors */
43 if (flags & (1 << 0))
Stefan Reinauer65b72ab2015-01-05 12:59:54 -080044 printk(BIOS_DEBUG, "\tRecovered data integrity ERROR\n");
Alexandru Gagniuc23211b02013-06-09 16:06:07 -050045 if (flags & (1 << 1))
Stefan Reinauer65b72ab2015-01-05 12:59:54 -080046 printk(BIOS_DEBUG, "\tRecovered data communication ERROR\n");
Alexandru Gagniuc23211b02013-06-09 16:06:07 -050047 if (flags & (1 << 8))
Stefan Reinauer65b72ab2015-01-05 12:59:54 -080048 printk(BIOS_DEBUG, "\tNon-recovered Transient Data Integrity ERROR\n");
Alexandru Gagniuc23211b02013-06-09 16:06:07 -050049 if (flags & (1 << 9))
Stefan Reinauer65b72ab2015-01-05 12:59:54 -080050 printk(BIOS_DEBUG, "\tNon-recovered Persistent Communication or"
Alexandru Gagniuc23211b02013-06-09 16:06:07 -050051 "\tData Integrity ERROR\n");
52 if (flags & (1 << 10))
Stefan Reinauer65b72ab2015-01-05 12:59:54 -080053 printk(BIOS_DEBUG, "\tProtocol ERROR\n");
Alexandru Gagniuc23211b02013-06-09 16:06:07 -050054 if (flags & (1 << 11))
Stefan Reinauer65b72ab2015-01-05 12:59:54 -080055 printk(BIOS_DEBUG, "\tInternal ERROR\n");
Alexandru Gagniuc23211b02013-06-09 16:06:07 -050056 if (flags & (1 << 17))
Stefan Reinauer65b72ab2015-01-05 12:59:54 -080057 printk(BIOS_DEBUG, "\tPHY Internal ERROR\n");
Alexandru Gagniuc23211b02013-06-09 16:06:07 -050058 if (flags & (1 << 19))
Stefan Reinauer65b72ab2015-01-05 12:59:54 -080059 printk(BIOS_DEBUG, "\t10B to 8B Decode ERROR\n");
Alexandru Gagniuc23211b02013-06-09 16:06:07 -050060 if (flags & (1 << 20))
Stefan Reinauer65b72ab2015-01-05 12:59:54 -080061 printk(BIOS_DEBUG, "\tDisparity ERROR\n");
Alexandru Gagniuc23211b02013-06-09 16:06:07 -050062 if (flags & (1 << 21))
Stefan Reinauer65b72ab2015-01-05 12:59:54 -080063 printk(BIOS_DEBUG, "\tCRC ERROR\n");
Alexandru Gagniuc23211b02013-06-09 16:06:07 -050064 if (flags & (1 << 22))
Stefan Reinauer65b72ab2015-01-05 12:59:54 -080065 printk(BIOS_DEBUG, "\tHandshake ERROR\n");
Alexandru Gagniuc23211b02013-06-09 16:06:07 -050066 if (flags & (1 << 23))
Stefan Reinauer65b72ab2015-01-05 12:59:54 -080067 printk(BIOS_DEBUG, "\tLink Sequence ERROR\n");
Alexandru Gagniuc23211b02013-06-09 16:06:07 -050068 if (flags & (1 << 24))
Stefan Reinauer65b72ab2015-01-05 12:59:54 -080069 printk(BIOS_DEBUG, "\tTransport State Transition ERROR\n");
Alexandru Gagniuc23211b02013-06-09 16:06:07 -050070 if (flags & (1 << 25))
Stefan Reinauer65b72ab2015-01-05 12:59:54 -080071 printk(BIOS_DEBUG, "\tUNRECOGNIZED FIS type\n");
Alexandru Gagniuc23211b02013-06-09 16:06:07 -050072}
73
74static void vx900_dbg_sata_errors(device_t dev)
75{
76 /* Port 0 */
77 if (pci_read_config8(dev, 0xa0) & (1 << 0)) {
Stefan Reinauer65b72ab2015-01-05 12:59:54 -080078 printk(BIOS_DEBUG, "Device detected in SATA port 0.\n");
Alexandru Gagniuc23211b02013-06-09 16:06:07 -050079 u32 flags = pci_read_config32(dev, 0xa8);
80 vx900_print_sata_errors(flags);
81 };
82 /* Port 1 */
83 if (pci_read_config8(dev, 0xa1) & (1 << 0)) {
Stefan Reinauer65b72ab2015-01-05 12:59:54 -080084 printk(BIOS_DEBUG, "Device detected in SATA port 1.\n");
Alexandru Gagniuc23211b02013-06-09 16:06:07 -050085 u32 flags = pci_read_config32(dev, 0xac);
86 vx900_print_sata_errors(flags);
87 };
88}
89
90typedef u8 sata_phy_config[64];
91
92static sata_phy_config reference_ephy = {
93 0x80, 0xb8, 0xf0, 0xfe, 0x40, 0x7e, 0xf6, 0xdd,
94 0x1a, 0x22, 0xa0, 0x10, 0x02, 0xa9, 0x7c, 0x7e,
95 0x00, 0x00, 0x00, 0x00, 0x40, 0x30, 0x84, 0x8c,
96 0x75, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
97 0x20, 0x40, 0xd0, 0x41, 0x40, 0x00, 0x00, 0x08,
98 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
99 0x20, 0x40, 0x50, 0x41, 0x40, 0x00, 0x00, 0x00,
100 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
101};
102
103static u32 sata_phy_read32(device_t dev, u8 index)
104{
105 /* The SATA PHY control registers are accessed by a funny index/value
106 * scheme. Each byte (0,1,2,3) has its own 4-bit index */
107 index = (index >> 2) & 0xf;
108 u16 i16 = index | (index << 4) | (index << 8) | (index << 12);
109 /* The index */
110 pci_write_config16(dev, 0x68, i16);
111 /* The value */
112 return pci_read_config32(dev, 0x64);
113}
114
115static void sata_phy_write32(device_t dev, u8 index, u32 val)
116{
117 /* The SATA PHY control registers are accessed by a funny index/value
118 * scheme. Each byte (0,1,2,3) has its own 4-bit index */
119 index = (index >> 2) & 0xf;
120 u16 i16 = index | (index << 4) | (index << 8) | (index << 12);
121 /* The index */
122 pci_write_config16(dev, 0x68, i16);
123 /* The value */
124 pci_write_config32(dev, 0x64, val);
125}
126
127static void vx900_sata_read_phy_config(device_t dev, sata_phy_config cfg)
128{
129 size_t i;
130 u32 *data = (u32 *) cfg;
131 for (i = 0; i < (sizeof(sata_phy_config)) >> 2; i++) {
132 data[i] = sata_phy_read32(dev, i << 2);
133 }
134}
135
136static void vx900_sata_write_phy_config(device_t dev, sata_phy_config cfg)
137{
138 size_t i;
139 u32 *data = (u32 *) cfg;
140 for (i = 0; i < (sizeof(sata_phy_config)) >> 2; i++) {
141 sata_phy_write32(dev, i << 2, data[i]);
142 }
143}
144
145static void vx900_sata_dump_phy_config(sata_phy_config cfg)
146{
Stefan Reinauer65b72ab2015-01-05 12:59:54 -0800147 printk(BIOS_DEBUG, "SATA PHY config:\n");
Alexandru Gagniuc23211b02013-06-09 16:06:07 -0500148 int i;
149 for (i = 0; i < sizeof(sata_phy_config); i++) {
150 unsigned char val;
Stefan Reinauer65b72ab2015-01-05 12:59:54 -0800151 if ((i & 0x0f) == 0)
152 printk(BIOS_DEBUG, "%02x:", i);
Alexandru Gagniuc23211b02013-06-09 16:06:07 -0500153 val = cfg[i];
154 if ((i & 7) == 0)
Stefan Reinauer65b72ab2015-01-05 12:59:54 -0800155 printk(BIOS_DEBUG, " |");
156 printk(BIOS_DEBUG, " %02x", val);
Alexandru Gagniuc23211b02013-06-09 16:06:07 -0500157 if ((i & 0x0f) == 0x0f) {
Stefan Reinauer65b72ab2015-01-05 12:59:54 -0800158 printk(BIOS_DEBUG, "\n");
Alexandru Gagniuc23211b02013-06-09 16:06:07 -0500159 }
160 }
161}
162
163/**
164 * \brief VX900: Place the onboard SATA controller in Native IDE mode
165 *
166 * AHCI mode requires a sub-class of 0x06, and Interface of 0x0
167 * SATA mode requires a sub-class of 0x06, and Interface of 0x00
168 * Unfortunately, setting the class to SATA, will prevent us from modyfing the
169 * interface register to an AHCI/SATA compliant value. Thus, payloads or OS may
170 * not properly identify this as a SATA controller.
171 * We could set the class code to 0x04, which would cause the interface register
172 * to become 0x00, which represents a RAID controller. Unfortunately, when we do
173 * this, SeaBIOS will skip this as a storage device, and we will not be able to
174 * boot.
175 * Our only option is to operate in IDE mode. We choose native IDE so that we
176 * can freely assign an IRQ, and are not forced to use IRQ14
177 */
178static void vx900_native_ide_mode(device_t dev)
179{
180 /* Disable subclass write protect */
181 pci_mod_config8(dev, 0x45, 1 << 7, 0);
182 /* Change the device class to IDE */
183 pci_write_config16(dev, PCI_CLASS_DEVICE, PCI_CLASS_STORAGE_IDE);
184 /* Re-enable subclass write protect */
185 pci_mod_config8(dev, 0x45, 0, 1 << 7);
186 /* Put it in native IDE mode */
187 pci_write_config8(dev, PCI_CLASS_PROG, 0x8f);
188}
189
190static void vx900_sata_init(device_t dev)
191{
192 /* Enable SATA primary channel IO access */
193 pci_mod_config8(dev, 0x40, 0, 1 << 1);
194 /* Just SATA, so it makes sense to be in native SATA mode */
195 vx900_native_ide_mode(dev);
196
197 /* TP Layer Idle at least 20us before the Following Command */
198 pci_mod_config8(dev, 0x53, 0, 1 << 7);
199 /* Resend COMRESET When Recovering SATA Gen2 Device Error */
200 pci_mod_config8(dev, 0x62, 1 << 1, 1 << 7);
201
202 /* Fix "PMP Device Can’t Detect HDD Normally" (VIA Porting Guide)
203 * SATA device detection will not work unless we clear these bits.
204 * Without doing this, SeaBIOS (and potentially other payloads) will
205 * timeout when detecting SATA devices */
206 pci_mod_config8(dev, 0x89, (1 << 3) | (1 << 6), 0);
207
208 /* 12.7 Two Software Resets May Affect the System
209 * When the software does the second reset before the first reset
210 * finishes, it may cause the system hang. It would do one software
211 * reset and check the BSY bit of one port only, and the BSY bit of
212 * other port would be 1, then it does another software reset
213 * immediately and causes the system hang.
214 * This is because the first software reset doesn’t finish, and the
215 * state machine of the host controller conflicts, it can’t finish the
216 * second one anymore. The BSY bit of slave port would be always 1 after
217 * the second software reset issues. BIOS should set the following
218 * bit to avoid this issue. */
219 pci_mod_config8(dev, 0x80, 0, 1 << 6);
220
221 /* We need to set the EPHY values before doing anything with the link */
222 sata_phy_config ephy;
223 vx900_sata_read_phy_config(dev, ephy);
224 if (1) {
225 vx900_sata_dump_phy_config(ephy);
226 vx900_sata_write_phy_config(dev, reference_ephy);
227 } else {
228 /* Enable TX and RX driving resistance */
229 /* TX - 50 Ohm */
230 ephy[1] &= ~(0x1f << 3);
231 ephy[1] |= (1 << 7) | (8 << 3);
232 /* RX - 50 Ohm */
233 ephy[2] &= ~(0x1f << 3);
234 ephy[2] |= (1 << 7) | (8 << 3);
235 vx900_sata_write_phy_config(dev, ephy);
236 }
237
238 vx900_sata_read_phy_config(dev, ephy);
239 vx900_sata_dump_phy_config(ephy);
240
241 /* Clear error flags */
242 pci_write_config32(dev, 0xa8, 0xffffffff);
243 pci_write_config32(dev, 0xac, 0xffffffff);
244
245 /* Start OOB link negotiation sequence */
246 pci_mod_config8(dev, 0xb9, 0, 3 << 4);
247
248 /* FIXME: From now on, we are just doing DEBUG stuff
249 * Wait until PHY communication is enabled */
250 u32 wloops = 0;
251 while (!(pci_read_config8(dev, 0xa0) & (1 << 1)))
252 wloops++;
253 printk(BIOS_SPEW, "SATA wait loops: %u\n", wloops);
254
255 vx900_dbg_sata_errors(dev);
256}
257
258static void vx900_sata_read_resources(device_t dev)
259{
260 pci_dev_read_resources(dev);
261}
262
263static struct device_operations vga_operations = {
264 .read_resources = vx900_sata_read_resources,
265 .set_resources = pci_dev_set_resources,
266 .enable_resources = pci_dev_enable_resources,
267 .init = vx900_sata_init,
268};
269
270static const struct pci_driver chrome9hd_driver __pci_driver = {
271 .ops = &vga_operations,
272 .vendor = PCI_VENDOR_ID_VIA,
273 .device = PCI_DEVICE_ID_VIA_VX900_SATA,
274};