blob: 791133142fbb07338baca90bbcff363c4da1206a [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>
Kyösti Mälkkif1b58b72019-03-01 13:43:02 +020019#include <device/pci_ops.h>
Alexandru Gagniuc23211b02013-06-09 16:06:07 -050020#include <device/pci_ids.h>
21
22#include "vx900.h"
23
24/**
Martin Roth543888d2015-01-06 10:20:42 -070025 * @file vx900/sata.c
Alexandru Gagniuc23211b02013-06-09 16:06:07 -050026 *
27 * STATUS: Pretty good
28 * The only issue is the SATA EPHY configuration. We do not know if it is board
29 * specific or not. Otherwise, the SATA controller works without issues.
30 */
31
32static void vx900_print_sata_errors(u32 flags)
33{
34 /* Status flags */
35 printk(BIOS_DEBUG, "\tPhyRdy %s\n",
36 (flags & (1 << 16)) ? "changed" : "not changed");
37 printk(BIOS_DEBUG, "\tCOMWAKE %s\n",
38 (flags & (1 << 16)) ? "detected" : "not detected");
39 printk(BIOS_DEBUG, "\tExchange as determined by COMINIT %s\n",
Martin Roth2ed0aa22016-01-05 20:58:58 -070040 (flags & (1 << 26)) ? "occurred" : "not occurred");
Alexandru Gagniuc23211b02013-06-09 16:06:07 -050041 printk(BIOS_DEBUG, "\tPort selector presence %s\n",
42 (flags & (1 << 27)) ? "detected" : "not detected");
43 /* Errors */
44 if (flags & (1 << 0))
Stefan Reinauer65b72ab2015-01-05 12:59:54 -080045 printk(BIOS_DEBUG, "\tRecovered data integrity ERROR\n");
Alexandru Gagniuc23211b02013-06-09 16:06:07 -050046 if (flags & (1 << 1))
Stefan Reinauer65b72ab2015-01-05 12:59:54 -080047 printk(BIOS_DEBUG, "\tRecovered data communication ERROR\n");
Alexandru Gagniuc23211b02013-06-09 16:06:07 -050048 if (flags & (1 << 8))
Stefan Reinauer65b72ab2015-01-05 12:59:54 -080049 printk(BIOS_DEBUG, "\tNon-recovered Transient Data Integrity ERROR\n");
Alexandru Gagniuc23211b02013-06-09 16:06:07 -050050 if (flags & (1 << 9))
Stefan Reinauer65b72ab2015-01-05 12:59:54 -080051 printk(BIOS_DEBUG, "\tNon-recovered Persistent Communication or"
Alexandru Gagniuc23211b02013-06-09 16:06:07 -050052 "\tData Integrity ERROR\n");
53 if (flags & (1 << 10))
Stefan Reinauer65b72ab2015-01-05 12:59:54 -080054 printk(BIOS_DEBUG, "\tProtocol ERROR\n");
Alexandru Gagniuc23211b02013-06-09 16:06:07 -050055 if (flags & (1 << 11))
Stefan Reinauer65b72ab2015-01-05 12:59:54 -080056 printk(BIOS_DEBUG, "\tInternal ERROR\n");
Alexandru Gagniuc23211b02013-06-09 16:06:07 -050057 if (flags & (1 << 17))
Stefan Reinauer65b72ab2015-01-05 12:59:54 -080058 printk(BIOS_DEBUG, "\tPHY Internal ERROR\n");
Alexandru Gagniuc23211b02013-06-09 16:06:07 -050059 if (flags & (1 << 19))
Stefan Reinauer65b72ab2015-01-05 12:59:54 -080060 printk(BIOS_DEBUG, "\t10B to 8B Decode ERROR\n");
Alexandru Gagniuc23211b02013-06-09 16:06:07 -050061 if (flags & (1 << 20))
Stefan Reinauer65b72ab2015-01-05 12:59:54 -080062 printk(BIOS_DEBUG, "\tDisparity ERROR\n");
Alexandru Gagniuc23211b02013-06-09 16:06:07 -050063 if (flags & (1 << 21))
Stefan Reinauer65b72ab2015-01-05 12:59:54 -080064 printk(BIOS_DEBUG, "\tCRC ERROR\n");
Alexandru Gagniuc23211b02013-06-09 16:06:07 -050065 if (flags & (1 << 22))
Stefan Reinauer65b72ab2015-01-05 12:59:54 -080066 printk(BIOS_DEBUG, "\tHandshake ERROR\n");
Alexandru Gagniuc23211b02013-06-09 16:06:07 -050067 if (flags & (1 << 23))
Stefan Reinauer65b72ab2015-01-05 12:59:54 -080068 printk(BIOS_DEBUG, "\tLink Sequence ERROR\n");
Alexandru Gagniuc23211b02013-06-09 16:06:07 -050069 if (flags & (1 << 24))
Stefan Reinauer65b72ab2015-01-05 12:59:54 -080070 printk(BIOS_DEBUG, "\tTransport State Transition ERROR\n");
Alexandru Gagniuc23211b02013-06-09 16:06:07 -050071 if (flags & (1 << 25))
Stefan Reinauer65b72ab2015-01-05 12:59:54 -080072 printk(BIOS_DEBUG, "\tUNRECOGNIZED FIS type\n");
Alexandru Gagniuc23211b02013-06-09 16:06:07 -050073}
74
Elyes HAOUAS2a5f6cb2018-05-25 08:09:53 +020075static void vx900_dbg_sata_errors(struct device *dev)
Alexandru Gagniuc23211b02013-06-09 16:06:07 -050076{
77 /* Port 0 */
78 if (pci_read_config8(dev, 0xa0) & (1 << 0)) {
Stefan Reinauer65b72ab2015-01-05 12:59:54 -080079 printk(BIOS_DEBUG, "Device detected in SATA port 0.\n");
Alexandru Gagniuc23211b02013-06-09 16:06:07 -050080 u32 flags = pci_read_config32(dev, 0xa8);
81 vx900_print_sata_errors(flags);
82 };
83 /* Port 1 */
84 if (pci_read_config8(dev, 0xa1) & (1 << 0)) {
Stefan Reinauer65b72ab2015-01-05 12:59:54 -080085 printk(BIOS_DEBUG, "Device detected in SATA port 1.\n");
Alexandru Gagniuc23211b02013-06-09 16:06:07 -050086 u32 flags = pci_read_config32(dev, 0xac);
87 vx900_print_sata_errors(flags);
88 };
89}
90
91typedef u8 sata_phy_config[64];
92
93static sata_phy_config reference_ephy = {
94 0x80, 0xb8, 0xf0, 0xfe, 0x40, 0x7e, 0xf6, 0xdd,
95 0x1a, 0x22, 0xa0, 0x10, 0x02, 0xa9, 0x7c, 0x7e,
96 0x00, 0x00, 0x00, 0x00, 0x40, 0x30, 0x84, 0x8c,
97 0x75, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
98 0x20, 0x40, 0xd0, 0x41, 0x40, 0x00, 0x00, 0x08,
99 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
100 0x20, 0x40, 0x50, 0x41, 0x40, 0x00, 0x00, 0x00,
101 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
102};
103
Elyes HAOUAS2a5f6cb2018-05-25 08:09:53 +0200104static u32 sata_phy_read32(struct device *dev, u8 index)
Alexandru Gagniuc23211b02013-06-09 16:06:07 -0500105{
106 /* The SATA PHY control registers are accessed by a funny index/value
107 * scheme. Each byte (0,1,2,3) has its own 4-bit index */
108 index = (index >> 2) & 0xf;
109 u16 i16 = index | (index << 4) | (index << 8) | (index << 12);
110 /* The index */
111 pci_write_config16(dev, 0x68, i16);
112 /* The value */
113 return pci_read_config32(dev, 0x64);
114}
115
Elyes HAOUAS2a5f6cb2018-05-25 08:09:53 +0200116static void sata_phy_write32(struct device *dev, u8 index, u32 val)
Alexandru Gagniuc23211b02013-06-09 16:06:07 -0500117{
118 /* The SATA PHY control registers are accessed by a funny index/value
119 * scheme. Each byte (0,1,2,3) has its own 4-bit index */
120 index = (index >> 2) & 0xf;
121 u16 i16 = index | (index << 4) | (index << 8) | (index << 12);
122 /* The index */
123 pci_write_config16(dev, 0x68, i16);
124 /* The value */
125 pci_write_config32(dev, 0x64, val);
126}
127
Elyes HAOUAS2a5f6cb2018-05-25 08:09:53 +0200128static void vx900_sata_read_phy_config(struct device *dev, sata_phy_config cfg)
Alexandru Gagniuc23211b02013-06-09 16:06:07 -0500129{
130 size_t i;
131 u32 *data = (u32 *) cfg;
132 for (i = 0; i < (sizeof(sata_phy_config)) >> 2; i++) {
133 data[i] = sata_phy_read32(dev, i << 2);
134 }
135}
136
Elyes HAOUAS2a5f6cb2018-05-25 08:09:53 +0200137static void vx900_sata_write_phy_config(struct device *dev, sata_phy_config cfg)
Alexandru Gagniuc23211b02013-06-09 16:06:07 -0500138{
139 size_t i;
140 u32 *data = (u32 *) cfg;
141 for (i = 0; i < (sizeof(sata_phy_config)) >> 2; i++) {
142 sata_phy_write32(dev, i << 2, data[i]);
143 }
144}
145
146static void vx900_sata_dump_phy_config(sata_phy_config cfg)
147{
Stefan Reinauer65b72ab2015-01-05 12:59:54 -0800148 printk(BIOS_DEBUG, "SATA PHY config:\n");
Alexandru Gagniuc23211b02013-06-09 16:06:07 -0500149 int i;
150 for (i = 0; i < sizeof(sata_phy_config); i++) {
151 unsigned char val;
Stefan Reinauer65b72ab2015-01-05 12:59:54 -0800152 if ((i & 0x0f) == 0)
153 printk(BIOS_DEBUG, "%02x:", i);
Alexandru Gagniuc23211b02013-06-09 16:06:07 -0500154 val = cfg[i];
155 if ((i & 7) == 0)
Stefan Reinauer65b72ab2015-01-05 12:59:54 -0800156 printk(BIOS_DEBUG, " |");
157 printk(BIOS_DEBUG, " %02x", val);
Alexandru Gagniuc23211b02013-06-09 16:06:07 -0500158 if ((i & 0x0f) == 0x0f) {
Stefan Reinauer65b72ab2015-01-05 12:59:54 -0800159 printk(BIOS_DEBUG, "\n");
Alexandru Gagniuc23211b02013-06-09 16:06:07 -0500160 }
161 }
162}
163
164/**
165 * \brief VX900: Place the onboard SATA controller in Native IDE mode
166 *
167 * AHCI mode requires a sub-class of 0x06, and Interface of 0x0
168 * SATA mode requires a sub-class of 0x06, and Interface of 0x00
169 * Unfortunately, setting the class to SATA, will prevent us from modyfing the
170 * interface register to an AHCI/SATA compliant value. Thus, payloads or OS may
171 * not properly identify this as a SATA controller.
172 * We could set the class code to 0x04, which would cause the interface register
173 * to become 0x00, which represents a RAID controller. Unfortunately, when we do
174 * this, SeaBIOS will skip this as a storage device, and we will not be able to
175 * boot.
176 * Our only option is to operate in IDE mode. We choose native IDE so that we
177 * can freely assign an IRQ, and are not forced to use IRQ14
178 */
Elyes HAOUAS2a5f6cb2018-05-25 08:09:53 +0200179static void vx900_native_ide_mode(struct device *dev)
Alexandru Gagniuc23211b02013-06-09 16:06:07 -0500180{
181 /* Disable subclass write protect */
Kyösti Mälkkic0434082019-02-07 16:18:20 +0200182 pci_update_config8(dev, 0x45, (u8)~(1 << 7), 0);
Alexandru Gagniuc23211b02013-06-09 16:06:07 -0500183 /* Change the device class to IDE */
184 pci_write_config16(dev, PCI_CLASS_DEVICE, PCI_CLASS_STORAGE_IDE);
185 /* Re-enable subclass write protect */
Kyösti Mälkkic0434082019-02-07 16:18:20 +0200186 pci_or_config8(dev, 0x45, 1 << 7);
Alexandru Gagniuc23211b02013-06-09 16:06:07 -0500187 /* Put it in native IDE mode */
188 pci_write_config8(dev, PCI_CLASS_PROG, 0x8f);
189}
190
Elyes HAOUAS2a5f6cb2018-05-25 08:09:53 +0200191static void vx900_sata_init(struct device *dev)
Alexandru Gagniuc23211b02013-06-09 16:06:07 -0500192{
193 /* Enable SATA primary channel IO access */
Kyösti Mälkkic0434082019-02-07 16:18:20 +0200194 pci_or_config8(dev, 0x40, 1 << 1);
Alexandru Gagniuc23211b02013-06-09 16:06:07 -0500195 /* Just SATA, so it makes sense to be in native SATA mode */
196 vx900_native_ide_mode(dev);
197
198 /* TP Layer Idle at least 20us before the Following Command */
Kyösti Mälkkic0434082019-02-07 16:18:20 +0200199 pci_or_config8(dev, 0x53, 1 << 7);
Alexandru Gagniuc23211b02013-06-09 16:06:07 -0500200 /* Resend COMRESET When Recovering SATA Gen2 Device Error */
Kyösti Mälkkic0434082019-02-07 16:18:20 +0200201 pci_update_config8(dev, 0x62, ~(1 << 1), 1 << 7);
Alexandru Gagniuc23211b02013-06-09 16:06:07 -0500202
Martin Roth0cd338e2016-07-29 14:07:30 -0600203 /* Fix "PMP Device Can't Detect HDD Normally" (VIA Porting Guide)
Alexandru Gagniuc23211b02013-06-09 16:06:07 -0500204 * SATA device detection will not work unless we clear these bits.
205 * Without doing this, SeaBIOS (and potentially other payloads) will
206 * timeout when detecting SATA devices */
Kyösti Mälkkic0434082019-02-07 16:18:20 +0200207 pci_update_config8(dev, 0x89, ~(1 << 3) | (1 << 6), 0);
Alexandru Gagniuc23211b02013-06-09 16:06:07 -0500208
209 /* 12.7 Two Software Resets May Affect the System
210 * When the software does the second reset before the first reset
211 * finishes, it may cause the system hang. It would do one software
212 * reset and check the BSY bit of one port only, and the BSY bit of
213 * other port would be 1, then it does another software reset
214 * immediately and causes the system hang.
Martin Roth0cd338e2016-07-29 14:07:30 -0600215 * This is because the first software reset doesn't finish, and the
216 * state machine of the host controller conflicts, it can't finish the
Alexandru Gagniuc23211b02013-06-09 16:06:07 -0500217 * second one anymore. The BSY bit of slave port would be always 1 after
218 * the second software reset issues. BIOS should set the following
219 * bit to avoid this issue. */
Kyösti Mälkkic0434082019-02-07 16:18:20 +0200220 pci_or_config8(dev, 0x80, 1 << 6);
Alexandru Gagniuc23211b02013-06-09 16:06:07 -0500221
222 /* We need to set the EPHY values before doing anything with the link */
223 sata_phy_config ephy;
224 vx900_sata_read_phy_config(dev, ephy);
225 if (1) {
226 vx900_sata_dump_phy_config(ephy);
227 vx900_sata_write_phy_config(dev, reference_ephy);
228 } else {
229 /* Enable TX and RX driving resistance */
230 /* TX - 50 Ohm */
231 ephy[1] &= ~(0x1f << 3);
232 ephy[1] |= (1 << 7) | (8 << 3);
233 /* RX - 50 Ohm */
234 ephy[2] &= ~(0x1f << 3);
235 ephy[2] |= (1 << 7) | (8 << 3);
236 vx900_sata_write_phy_config(dev, ephy);
237 }
238
239 vx900_sata_read_phy_config(dev, ephy);
240 vx900_sata_dump_phy_config(ephy);
241
242 /* Clear error flags */
243 pci_write_config32(dev, 0xa8, 0xffffffff);
244 pci_write_config32(dev, 0xac, 0xffffffff);
245
246 /* Start OOB link negotiation sequence */
Kyösti Mälkkic0434082019-02-07 16:18:20 +0200247 pci_or_config8(dev, 0xb9, 3 << 4);
Alexandru Gagniuc23211b02013-06-09 16:06:07 -0500248
249 /* FIXME: From now on, we are just doing DEBUG stuff
250 * Wait until PHY communication is enabled */
251 u32 wloops = 0;
252 while (!(pci_read_config8(dev, 0xa0) & (1 << 1)))
253 wloops++;
254 printk(BIOS_SPEW, "SATA wait loops: %u\n", wloops);
255
256 vx900_dbg_sata_errors(dev);
257}
258
Elyes HAOUAS2a5f6cb2018-05-25 08:09:53 +0200259static void vx900_sata_read_resources(struct device *dev)
Alexandru Gagniuc23211b02013-06-09 16:06:07 -0500260{
261 pci_dev_read_resources(dev);
262}
263
264static struct device_operations vga_operations = {
265 .read_resources = vx900_sata_read_resources,
266 .set_resources = pci_dev_set_resources,
267 .enable_resources = pci_dev_enable_resources,
268 .init = vx900_sata_init,
269};
270
271static const struct pci_driver chrome9hd_driver __pci_driver = {
272 .ops = &vga_operations,
273 .vendor = PCI_VENDOR_ID_VIA,
274 .device = PCI_DEVICE_ID_VIA_VX900_SATA,
275};