nb/via/vx900: Get rid of device_t
[coreboot.git] / src / northbridge / via / vx900 / sata.c
blob4df0053874c8b7fe0330035eb83746fdfffcc791
1 /*
2 * This file is part of the coreboot project.
4 * Copyright (C) 2012 Alexandru Gagniuc <mr.nuke.me@gmail.com>
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.
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.
17 #include <console/console.h>
18 #include <device/pci.h>
19 #include <device/pci_ids.h>
21 #include "vx900.h"
23 /**
24 * @file vx900/sata.c
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.
31 static void vx900_print_sata_errors(u32 flags)
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",
39 (flags & (1 << 26)) ? "occurred" : "not occurred");
40 printk(BIOS_DEBUG, "\tPort selector presence %s\n",
41 (flags & (1 << 27)) ? "detected" : "not detected");
42 /* Errors */
43 if (flags & (1 << 0))
44 printk(BIOS_DEBUG, "\tRecovered data integrity ERROR\n");
45 if (flags & (1 << 1))
46 printk(BIOS_DEBUG, "\tRecovered data communication ERROR\n");
47 if (flags & (1 << 8))
48 printk(BIOS_DEBUG, "\tNon-recovered Transient Data Integrity ERROR\n");
49 if (flags & (1 << 9))
50 printk(BIOS_DEBUG, "\tNon-recovered Persistent Communication or"
51 "\tData Integrity ERROR\n");
52 if (flags & (1 << 10))
53 printk(BIOS_DEBUG, "\tProtocol ERROR\n");
54 if (flags & (1 << 11))
55 printk(BIOS_DEBUG, "\tInternal ERROR\n");
56 if (flags & (1 << 17))
57 printk(BIOS_DEBUG, "\tPHY Internal ERROR\n");
58 if (flags & (1 << 19))
59 printk(BIOS_DEBUG, "\t10B to 8B Decode ERROR\n");
60 if (flags & (1 << 20))
61 printk(BIOS_DEBUG, "\tDisparity ERROR\n");
62 if (flags & (1 << 21))
63 printk(BIOS_DEBUG, "\tCRC ERROR\n");
64 if (flags & (1 << 22))
65 printk(BIOS_DEBUG, "\tHandshake ERROR\n");
66 if (flags & (1 << 23))
67 printk(BIOS_DEBUG, "\tLink Sequence ERROR\n");
68 if (flags & (1 << 24))
69 printk(BIOS_DEBUG, "\tTransport State Transition ERROR\n");
70 if (flags & (1 << 25))
71 printk(BIOS_DEBUG, "\tUNRECOGNIZED FIS type\n");
74 static void vx900_dbg_sata_errors(struct device *dev)
76 /* Port 0 */
77 if (pci_read_config8(dev, 0xa0) & (1 << 0)) {
78 printk(BIOS_DEBUG, "Device detected in SATA port 0.\n");
79 u32 flags = pci_read_config32(dev, 0xa8);
80 vx900_print_sata_errors(flags);
82 /* Port 1 */
83 if (pci_read_config8(dev, 0xa1) & (1 << 0)) {
84 printk(BIOS_DEBUG, "Device detected in SATA port 1.\n");
85 u32 flags = pci_read_config32(dev, 0xac);
86 vx900_print_sata_errors(flags);
90 typedef u8 sata_phy_config[64];
92 static 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,
103 static u32 sata_phy_read32(struct device *dev, u8 index)
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);
115 static void sata_phy_write32(struct device *dev, u8 index, u32 val)
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);
127 static void vx900_sata_read_phy_config(struct device *dev, sata_phy_config cfg)
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);
136 static void vx900_sata_write_phy_config(struct device *dev, sata_phy_config cfg)
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]);
145 static void vx900_sata_dump_phy_config(sata_phy_config cfg)
147 printk(BIOS_DEBUG, "SATA PHY config:\n");
148 int i;
149 for (i = 0; i < sizeof(sata_phy_config); i++) {
150 unsigned char val;
151 if ((i & 0x0f) == 0)
152 printk(BIOS_DEBUG, "%02x:", i);
153 val = cfg[i];
154 if ((i & 7) == 0)
155 printk(BIOS_DEBUG, " |");
156 printk(BIOS_DEBUG, " %02x", val);
157 if ((i & 0x0f) == 0x0f) {
158 printk(BIOS_DEBUG, "\n");
164 * \brief VX900: Place the onboard SATA controller in Native IDE mode
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
178 static void vx900_native_ide_mode(struct device *dev)
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);
190 static void vx900_sata_init(struct device *dev)
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);
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);
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);
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);
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);
238 vx900_sata_read_phy_config(dev, ephy);
239 vx900_sata_dump_phy_config(ephy);
241 /* Clear error flags */
242 pci_write_config32(dev, 0xa8, 0xffffffff);
243 pci_write_config32(dev, 0xac, 0xffffffff);
245 /* Start OOB link negotiation sequence */
246 pci_mod_config8(dev, 0xb9, 0, 3 << 4);
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);
255 vx900_dbg_sata_errors(dev);
258 static void vx900_sata_read_resources(struct device *dev)
260 pci_dev_read_resources(dev);
263 static 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,
270 static 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,