mb/google/nissa/var/rull: Add 6W and 15W DPTF parameters
[coreboot2.git] / payloads / libpayload / drivers / storage / ahci.c
blobeeeab6976c6eb865283f44d11c7e0363c6056418
1 /*
3 * Copyright (C) 2012 secunet Security Networks AG
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
29 //#define DEBUG_STATUS
31 #include <stdlib.h>
32 #include <stdint.h>
33 #include <string.h>
34 #include <libpayload.h>
35 #include <pci.h>
36 #include <pci/pci.h>
37 #include <storage/ata.h>
38 #include <storage/ahci.h>
40 #include "ahci_private.h"
42 #ifdef DEBUG_STATUS
43 static inline u32 _ahci_clear_status(volatile u32 *const reg,
44 const char *const r,
45 const char *const f)
47 const u32 bits = *reg;
48 if (bits)
49 *reg = bits;
50 printf("ahci: %s: %s == 0x%08x\n", f, r, bits);
52 return bits;
54 #define ahci_clear_status(p, r) _ahci_clear_status(&(p)->r, #r, __func__)
55 #else
56 static inline u32 _ahci_clear_status(volatile u32 *const reg)
58 const u32 bits = *reg;
59 if (bits)
60 *reg = bits;
61 return bits;
63 #define ahci_clear_status(p, r) _ahci_clear_status(&(p)->r)
64 #endif
66 static inline int ahci_port_is_active(const hba_port_t *const port)
68 return (port->sata_status & (HBA_PxSSTS_IPM_MASK | HBA_PxSSTS_DET_MASK))
69 == (HBA_PxSSTS_IPM_ACTIVE | HBA_PxSSTS_DET_ESTABLISHED);
72 /** Do minimal error recovery. */
73 int ahci_error_recovery(ahci_dev_t *const dev, const u32 intr_status)
75 /* Command engine has to be restarted.
76 We don't call ahci_cmdengine_stop() here as it also checks
77 HBA_PxCMD_FR which won't clear on fatal errors. */
78 dev->port->cmd_stat &= ~HBA_PxCMD_ST;
80 /* Always clear sata_error. */
81 ahci_clear_status(dev->port, sata_error);
83 /* Perform COMRESET if appropriate. */
84 const u32 tfd = dev->port->taskfile_data;
85 if ((tfd & (HBA_PxTFD_BSY | HBA_PxTFD_DRQ)) |
86 (intr_status & HBA_PxIS_PCS)) {
87 const u32 sctl = dev->port->sata_control & ~HBA_PxSCTL_DET_MASK;
88 dev->port->sata_control = sctl | HBA_PxSCTL_DET_COMRESET;
89 mdelay(1);
90 dev->port->sata_control = sctl;
93 if (ahci_port_is_active(dev->port))
94 /* Start command engine. */
95 return ahci_cmdengine_start(dev->port);
96 else
97 return -1;
100 static int ahci_dev_init(hba_ctrl_t *const ctrl,
101 hba_port_t *const port,
102 const int portnum)
104 int ret = 1;
106 const int ncs = HBA_CAPS_DECODE_NCS(ctrl->caps);
108 if (ahci_cmdengine_stop(port))
109 return 1;
111 /* Allocate command list, one command table and received FIS. */
112 cmd_t *const cmdlist = memalign(1024, ncs * sizeof(cmd_t));
113 cmdtable_t *const cmdtable = memalign(128, sizeof(cmdtable_t));
114 rcvd_fis_t *const rcvd_fis = memalign(256, sizeof(rcvd_fis_t));
115 /* Allocate our device structure. */
116 ahci_dev_t *const dev = calloc(1, sizeof(ahci_dev_t));
117 if (!cmdlist || !cmdtable || !rcvd_fis || !dev)
118 goto _cleanup_ret;
119 memset((void *)cmdlist, '\0', ncs * sizeof(cmd_t));
120 memset((void *)cmdtable, '\0', sizeof(*cmdtable));
121 memset((void *)rcvd_fis, '\0', sizeof(*rcvd_fis));
123 /* Set command list base and received FIS base. */
124 port->cmdlist_base = virt_to_phys(cmdlist);
125 port->frameinfo_base = virt_to_phys(rcvd_fis);
126 if (ahci_cmdengine_start(port))
127 goto _cleanup_ret;
128 /* Put port into active state. */
129 port->cmd_stat |= HBA_PxCMD_ICC_ACTIVE;
131 dev->ctrl = ctrl;
132 dev->port = port;
133 dev->cmdlist = cmdlist;
134 dev->cmdtable = cmdtable;
135 dev->rcvd_fis = rcvd_fis;
138 * Wait for D2H Register FIS with device' signature.
139 * The drive has to spin up here, so wait up to 30s.
141 const int timeout_s = 30; /* Time out after 30s. */
142 int timeout = timeout_s * 100;
143 while ((port->taskfile_data & HBA_PxTFD_BSY) && timeout--)
144 mdelay(10);
146 if (port->taskfile_data & HBA_PxTFD_BSY)
147 printf("ahci: Timed out after %d seconds "
148 "of waiting for device to spin up.\n", timeout_s);
150 /* Initialize device or fall through to clean up. */
151 switch (port->signature) {
152 case HBA_PxSIG_ATA:
153 printf("ahci: ATA drive on port #%d.\n", portnum);
154 #if CONFIG(LP_STORAGE_ATA)
155 dev->ata_dev.identify = ahci_identify_device;
156 dev->ata_dev.read_sectors = ahci_ata_read_sectors;
157 return ata_attach_device(&dev->ata_dev, PORT_TYPE_SATA);
158 #endif
159 break;
160 case HBA_PxSIG_ATAPI:
161 printf("ahci: ATAPI drive on port #%d.\n", portnum);
162 #if CONFIG(LP_STORAGE_ATAPI)
163 dev->atapi_dev.identify = ahci_identify_device;
164 dev->atapi_dev.packet_read_cmd = ahci_packet_read_cmd;
165 return atapi_attach_device(&dev->atapi_dev, PORT_TYPE_SATA);
166 #endif
167 break;
168 default:
169 printf("ahci: Unsupported device (signature == 0x%08x) "
170 "on port #%d.\n", port->signature, portnum);
171 break;
173 ret = 2;
175 _cleanup_ret:
176 /* Clean up (not reached for initialized devices). */
177 if (dev)
178 free(dev);
179 /* Only free if stopping succeeds, since otherwise the controller may
180 still use the resources for DMA. */
181 if (!ahci_cmdengine_stop(port)) {
182 port->cmdlist_base = 0;
183 port->frameinfo_base = 0;
184 if (rcvd_fis)
185 free((void *)rcvd_fis);
186 if (cmdtable)
187 free((void *)cmdtable);
188 if (cmdlist)
189 free((void *)cmdlist);
191 return ret;
194 static void ahci_port_probe(hba_ctrl_t *const ctrl,
195 hba_port_t *const port,
196 const int portnum)
198 /* If staggered spin-up is supported, spin-up device. */
199 if (ctrl->caps & HBA_CAPS_SSS) {
200 port->cmd_stat |= HBA_PxCMD_SUD;
203 /* Wait 1s if we just told the device to spin up or
204 if it's the first port. */
205 if ((ctrl->caps & HBA_CAPS_SSS) ||
206 !(ctrl->ports_impl & ((1 << (portnum - 1)) - 1))) {
207 /* Wait for port to become active. */
208 int timeout = 100; /* Time out after 100 * 100us == 10ms. */
209 while (!ahci_port_is_active(port) && timeout--)
210 udelay(100);
212 if (!ahci_port_is_active(port))
213 return;
215 ahci_clear_status(port, sata_error);
216 ahci_clear_status(port, intr_status);
218 ahci_dev_init(ctrl, port, portnum);
221 #if CONFIG(LP_STORAGE_AHCI_ONLY_TESTED)
222 static u32 working_controllers[] = {
223 0x8086 | 0x2929 << 16, /* Mobile ICH9 */
224 0x8086 | 0x1c03 << 16, /* Mobile Cougar Point PCH */
225 0x8086 | 0x1e03 << 16, /* Mobile Panther Point PCH */
226 0x8086 | 0xa102 << 16, /* Desktop / Mobile-Wks Sunrise Point PCH */
227 0x8086 | 0xa353 << 16, /* Mobile 300 series Cannon Point PCH */
228 0x8086 | 0x5ae3 << 16, /* Apollo Lake */
230 #endif
232 void ahci_initialize(struct pci_dev *dev)
234 int i;
236 #if CONFIG(LP_STORAGE_AHCI_ONLY_TESTED)
237 const u32 vendor_device = dev->vendor_id | dev->device_id << 16;
238 for (i = 0; i < ARRAY_SIZE(working_controllers); ++i)
239 if (vendor_device == working_controllers[i])
240 break;
241 if (i == ARRAY_SIZE(working_controllers)) {
242 printf("ahci: Not using untested SATA controller "
243 "%02x:%02x.%02x (%04x:%04x).\n", dev->bus,
244 dev->dev, dev->func, dev->vendor_id, dev->device_id);
245 return;
247 #endif
249 printf("ahci: Found SATA controller %02x:%02x.%02x (%04x:%04x).\n",
250 dev->bus, dev->dev, dev->func, dev->vendor_id, dev->device_id);
252 hba_ctrl_t *const ctrl = phys_to_virt(pci_read_long(dev, 0x24) & ~0x3ff);
253 hba_port_t *const ports = ctrl->ports;
255 /* Reset host controller. */
256 ctrl->global_ctrl |= HBA_CTRL_RESET;
257 /* Reset has to be finished after 1s. */
258 int timeout = 10 * 1000; /* Time out after 10,000 * 100us == 1s. */
259 while (ctrl->global_ctrl & HBA_CTRL_RESET && timeout--)
260 udelay(100);
261 if (ctrl->global_ctrl & HBA_CTRL_RESET) {
262 printf("ahci: ERROR: "
263 "Controller reset didn't finish within 1s.\n");
264 return;
267 /* Set AHCI access mode. */
268 ctrl->global_ctrl |= HBA_CTRL_AHCI_EN;
270 /* Enable bus mastering. */
271 const u16 command = pci_read_word(dev, PCI_COMMAND);
272 pci_write_word(dev, PCI_COMMAND, command | PCI_COMMAND_MASTER);
274 /* Probe for devices. */
275 for (i = 0; i < 32; ++i) {
276 if (ctrl->ports_impl & (1 << i))
277 ahci_port_probe(ctrl, &ports[i], i + 1);