blob: 47c35ba7c68e7d6264f66fe81664b4838231b03a [file] [log] [blame]
Stefan Reinauerdebb11f2008-10-29 04:46:52 +00001/*
2 * This file is part of the coreboot project.
3 *
Stefan Reinauer54309d62009-01-20 22:53:10 +00004 * Copyright (C) 2008-2009 coresystems GmbH
Damien Zammit647e3852016-01-15 13:44:53 +11005 * Copyright (C) 2016 Damien Zammit <damien@zamaudio.com>
Stefan Reinauerdebb11f2008-10-29 04:46:52 +00006 *
Stefan Reinauera8e11682009-03-11 14:54:18 +00007 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; version 2 of
10 * the License.
Stefan Reinauerdebb11f2008-10-29 04:46:52 +000011 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
Stefan Reinauerdebb11f2008-10-29 04:46:52 +000016 */
17
18#include <console/console.h>
19#include <device/device.h>
20#include <device/pci.h>
Kyösti Mälkkif1b58b72019-03-01 13:43:02 +020021#include <device/pci_ops.h>
Stefan Reinauerdebb11f2008-10-29 04:46:52 +000022#include <device/pci_ids.h>
Arthur Heymans742df5a2019-06-03 16:24:41 +020023#include "chip.h"
Stefan Reinauerdebb11f2008-10-29 04:46:52 +000024#include "i82801gx.h"
Damien Zammit647e3852016-01-15 13:44:53 +110025#include "sata.h"
Stefan Reinauerdebb11f2008-10-29 04:46:52 +000026
27typedef struct southbridge_intel_i82801gx_config config_t;
28
Damien Zammit647e3852016-01-15 13:44:53 +110029static u8 get_ich7_sata_ports(void)
30{
31 struct device *lpc;
32
Kyösti Mälkkic70eed12018-05-22 02:18:00 +030033 lpc = pcidev_on_root(31, 0);
Damien Zammit647e3852016-01-15 13:44:53 +110034
35 switch (pci_read_config16(lpc, PCI_DEVICE_ID)) {
36 case 0x27b0:
37 case 0x27b8:
38 return 0xf;
39 case 0x27b9:
40 case 0x27bd:
41 return 0x5;
42 case 0x27bc:
43 return 0x3;
44 default:
45 printk(BIOS_ERR,
46 "i82801gx_sata: error: cannot determine port config\n");
47 return 0;
48 }
49}
50
51void sata_enable(struct device *dev)
52{
53 /* Get the chip configuration */
Arthur Heymans5eb81be2019-01-10 23:13:11 +010054 struct southbridge_intel_i82801gx_config *config = dev->chip_info;
Damien Zammit647e3852016-01-15 13:44:53 +110055
Arthur Heymans5eb81be2019-01-10 23:13:11 +010056 if (config->sata_mode == SATA_MODE_AHCI) {
57 /* Check if the southbridge supports AHCI */
58 struct device *lpc_dev = pcidev_on_root(31, 0);
59 if (!lpc_dev) {
60 /* According to the PCI spec function 0 on a bus:device
61 needs to be active for other functions to be enabled.
62 Since SATA is on the same bus:device as the LPC
63 bridge, it makes little sense to continue. */
64 die("Couldn't find the LPC device!\n");
65 }
66
67 const bool ahci_supported = !(pci_read_config32(lpc_dev, FDVCT)
68 & AHCI_UNSUPPORTED);
69
70 if (!ahci_supported) {
71 /* Fallback to IDE PLAIN for sata for the rest of the
72 initialization */
73 config->sata_mode = SATA_MODE_IDE_PLAIN;
74 printk(BIOS_DEBUG,
75 "AHCI not supported, falling back to plain mode.\n");
76 }
77
Damien Zammit647e3852016-01-15 13:44:53 +110078 }
79
Arthur Heymans5eb81be2019-01-10 23:13:11 +010080 if (config->sata_mode == SATA_MODE_AHCI) {
81 /* Set map to ahci */
82 pci_write_config8(dev, SATA_MAP,
83 (pci_read_config8(dev, SATA_MAP)
84 & ~0xc3) | 0x40);
85 } else {
86 /* Set map to ide */
87 pci_write_config8(dev, SATA_MAP,
88 pci_read_config8(dev, SATA_MAP) & ~0xc3);
89 }
Damien Zammit647e3852016-01-15 13:44:53 +110090 /* At this point, the new pci id will appear on the bus */
91}
92
Stefan Reinauerdebb11f2008-10-29 04:46:52 +000093static void sata_init(struct device *dev)
94{
95 u32 reg32;
Stefan Reinauera8e11682009-03-11 14:54:18 +000096 u16 reg16;
Damien Zammit647e3852016-01-15 13:44:53 +110097 u8 ports;
Sven Schnelleb2f173e2011-10-27 13:05:40 +020098
Stefan Reinauerdebb11f2008-10-29 04:46:52 +000099 /* Get the chip configuration */
100 config_t *config = dev->chip_info;
101
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000102 printk(BIOS_DEBUG, "i82801gx_sata: initializing...\n");
Stefan Reinauera8e11682009-03-11 14:54:18 +0000103
Stefan Reinauer573f7d42009-07-21 21:50:34 +0000104 if (config == NULL) {
Uwe Hermann607614d2010-11-18 20:12:13 +0000105 printk(BIOS_ERR, "i82801gx_sata: error: device not in devicetree.cb!\n");
Stefan Reinauer573f7d42009-07-21 21:50:34 +0000106 return;
107 }
Stefan Reinauera8e11682009-03-11 14:54:18 +0000108
Damien Zammit647e3852016-01-15 13:44:53 +1100109 /* Get ICH7 SATA port config */
110 ports = get_ich7_sata_ports();
Stefan Reinauerdebb11f2008-10-29 04:46:52 +0000111
112 /* Enable BARs */
Stefan Reinauera8e11682009-03-11 14:54:18 +0000113 pci_write_config16(dev, PCI_COMMAND, 0x0007);
Stefan Reinauerdebb11f2008-10-29 04:46:52 +0000114
Arthur Heymans5eb81be2019-01-10 23:13:11 +0100115 switch (config->sata_mode) {
116 case SATA_MODE_IDE_LEGACY_COMBINED:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000117 printk(BIOS_DEBUG, "SATA controller in combined mode.\n");
Stefan Reinauera8e11682009-03-11 14:54:18 +0000118 /* No AHCI: clear AHCI base */
Petr Cvekc49869b2019-10-01 04:01:21 +0200119 pci_write_config32(dev, PCI_BASE_ADDRESS_5, 0x00000000);
Stefan Reinauera8e11682009-03-11 14:54:18 +0000120 /* And without AHCI BAR no memory decoding */
121 reg16 = pci_read_config16(dev, PCI_COMMAND);
122 reg16 &= ~PCI_COMMAND_MEMORY;
123 pci_write_config16(dev, PCI_COMMAND, reg16);
124
Stefan Reinauerdebb11f2008-10-29 04:46:52 +0000125 pci_write_config8(dev, 0x09, 0x80);
126
127 /* Set timings */
Stefan Reinauer573f7d42009-07-21 21:50:34 +0000128 pci_write_config16(dev, IDE_TIM_PRI, IDE_DECODE_ENABLE |
129 IDE_ISP_5_CLOCKS | IDE_RCT_4_CLOCKS);
130 pci_write_config16(dev, IDE_TIM_SEC, IDE_DECODE_ENABLE |
131 IDE_ISP_3_CLOCKS | IDE_RCT_1_CLOCKS |
132 IDE_PPE0 | IDE_IE0 | IDE_TIME0);
Stefan Reinauerdebb11f2008-10-29 04:46:52 +0000133
134 /* Sync DMA */
Stefan Reinauer573f7d42009-07-21 21:50:34 +0000135 pci_write_config16(dev, IDE_SDMA_CNT, IDE_SSDE0);
136 pci_write_config16(dev, IDE_SDMA_TIM, 0x0200);
Stefan Reinauerdebb11f2008-10-29 04:46:52 +0000137
Stefan Reinauera8e11682009-03-11 14:54:18 +0000138 /* Set IDE I/O Configuration */
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000139 reg32 = SIG_MODE_PRI_NORMAL | FAST_PCB1 | FAST_PCB0 | PCB1 | PCB0;
Stefan Reinauera8e11682009-03-11 14:54:18 +0000140 pci_write_config32(dev, IDE_CONFIG, reg32);
141
Stefan Reinauerdebb11f2008-10-29 04:46:52 +0000142 /* Combine IDE - SATA configuration */
Damien Zammit647e3852016-01-15 13:44:53 +1100143 pci_write_config8(dev, SATA_MAP, 0x02);
Stefan Reinauerdebb11f2008-10-29 04:46:52 +0000144
Damien Zammit1533f132016-01-16 02:52:53 +1100145 /* Restrict ports - 0 and 2 only available */
146 ports &= 0x5;
Arthur Heymans5eb81be2019-01-10 23:13:11 +0100147 break;
148 case SATA_MODE_AHCI:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000149 printk(BIOS_DEBUG, "SATA controller in AHCI mode.\n");
Stefan Reinauerdebb11f2008-10-29 04:46:52 +0000150 /* Allow both Legacy and Native mode */
151 pci_write_config8(dev, 0x09, 0x8f);
152
153 /* Set Interrupt Line */
154 /* Interrupt Pin is set by D31IP.PIP */
155 pci_write_config8(dev, INTR_LN, 0x0a);
156
Petr Cvekc49869b2019-10-01 04:01:21 +0200157 struct resource *ahci_res = find_resource(dev, PCI_BASE_ADDRESS_5);
158 if (ahci_res != NULL)
159 /* write AHCI GHC_PI register */
160 write32(res2mmio(ahci_res, 0xc, 0),
161 config->sata_ports_implemented);
Arthur Heymans5eb81be2019-01-10 23:13:11 +0100162 break;
163 default:
164 case SATA_MODE_IDE_PLAIN:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000165 printk(BIOS_DEBUG, "SATA controller in plain mode.\n");
Stefan Reinauera8e11682009-03-11 14:54:18 +0000166 /* Set Sata Controller Mode. No Mapping(?) */
Damien Zammit647e3852016-01-15 13:44:53 +1100167 pci_write_config8(dev, SATA_MAP, 0x00);
Stefan Reinauera8e11682009-03-11 14:54:18 +0000168
169 /* No AHCI: clear AHCI base */
Petr Cvekc49869b2019-10-01 04:01:21 +0200170 pci_write_config32(dev, PCI_BASE_ADDRESS_5, 0x00000000);
Stefan Reinauera8e11682009-03-11 14:54:18 +0000171
172 /* And without AHCI BAR no memory decoding */
173 reg16 = pci_read_config16(dev, PCI_COMMAND);
174 reg16 &= ~PCI_COMMAND_MEMORY;
175 pci_write_config16(dev, PCI_COMMAND, reg16);
176
Stefan Reinauerdebb11f2008-10-29 04:46:52 +0000177 /* Native mode capable on both primary and secondary (0xa)
178 * or'ed with enabled (0x50) = 0xf
179 */
180 pci_write_config8(dev, 0x09, 0x8f);
181
182 /* Set Interrupt Line */
183 /* Interrupt Pin is set by D31IP.PIP */
184 pci_write_config8(dev, INTR_LN, 0xff);
Stefan Reinauer109ab312009-08-12 16:08:05 +0000185
Stefan Reinauerdebb11f2008-10-29 04:46:52 +0000186 /* Set timings */
Stefan Reinauer573f7d42009-07-21 21:50:34 +0000187 pci_write_config16(dev, IDE_TIM_PRI, IDE_DECODE_ENABLE |
188 IDE_ISP_3_CLOCKS | IDE_RCT_1_CLOCKS |
189 IDE_PPE0 | IDE_IE0 | IDE_TIME0);
190 pci_write_config16(dev, IDE_TIM_SEC, IDE_DECODE_ENABLE |
Stefan Reinauer109ab312009-08-12 16:08:05 +0000191 IDE_SITRE | IDE_ISP_3_CLOCKS |
Stefan Reinauer573f7d42009-07-21 21:50:34 +0000192 IDE_RCT_1_CLOCKS | IDE_IE0 | IDE_TIME0);
Stefan Reinauer109ab312009-08-12 16:08:05 +0000193
Stefan Reinauerdebb11f2008-10-29 04:46:52 +0000194 /* Sync DMA */
Stefan Reinauer573f7d42009-07-21 21:50:34 +0000195 pci_write_config16(dev, IDE_SDMA_CNT, IDE_SSDE0 | IDE_PSDE0);
196 pci_write_config16(dev, IDE_SDMA_TIM, 0x0201);
Stefan Reinauer109ab312009-08-12 16:08:05 +0000197
Stefan Reinauerdebb11f2008-10-29 04:46:52 +0000198 /* Set IDE I/O Configuration */
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000199 reg32 = SIG_MODE_PRI_NORMAL | FAST_PCB1 | FAST_PCB0 | PCB1 | PCB0;
Stefan Reinauerdebb11f2008-10-29 04:46:52 +0000200 pci_write_config32(dev, IDE_CONFIG, reg32);
Arthur Heymans5eb81be2019-01-10 23:13:11 +0100201 break;
Stefan Reinauerdebb11f2008-10-29 04:46:52 +0000202 }
203
Damien Zammit1533f132016-01-16 02:52:53 +1100204 /* Set port control */
205 pci_write_config8(dev, SATA_PCS, ports);
206
Damien Zammit647e3852016-01-15 13:44:53 +1100207 /* Enable clock gating for unused ports and set initialization reg */
208 pci_write_config32(dev, SATA_IR, SIF3(ports) | SIF2 | SIF1 | SCRE);
209
Stefan Reinauerdebb11f2008-10-29 04:46:52 +0000210 /* All configurations need this SATA initialization sequence */
211 pci_write_config8(dev, 0xa0, 0x40);
212 pci_write_config8(dev, 0xa6, 0x22);
213 pci_write_config8(dev, 0xa0, 0x78);
214 pci_write_config8(dev, 0xa6, 0x22);
215 pci_write_config8(dev, 0xa0, 0x88);
216 reg32 = pci_read_config32(dev, 0xa4);
217 reg32 &= 0xc0c0c0c0;
218 reg32 |= 0x1b1b1212;
219 pci_write_config32(dev, 0xa4, reg32);
220 pci_write_config8(dev, 0xa0, 0x8c);
221 reg32 = pci_read_config32(dev, 0xa4);
222 reg32 &= 0xc0c0ff00;
223 reg32 |= 0x121200aa;
224 pci_write_config32(dev, 0xa4, reg32);
225 pci_write_config8(dev, 0xa0, 0x00);
Stefan Reinauer54309d62009-01-20 22:53:10 +0000226
227 pci_write_config8(dev, PCI_INTERRUPT_LINE, 0);
Stefan Reinauera8e11682009-03-11 14:54:18 +0000228
229 /* Sata Initialization Register */
Damien Zammit647e3852016-01-15 13:44:53 +1100230 reg32 = pci_read_config32(dev, SATA_IR);
231 reg32 |= SCRD; // due to some bug
232 pci_write_config32(dev, SATA_IR, reg32);
Stefan Reinauerdebb11f2008-10-29 04:46:52 +0000233}
234
Stefan Reinauera8e11682009-03-11 14:54:18 +0000235static struct pci_operations sata_pci_ops = {
Subrata Banik4a0f0712019-03-20 14:29:47 +0530236 .set_subsystem = pci_dev_set_subsystem,
Stefan Reinauera8e11682009-03-11 14:54:18 +0000237};
238
Stefan Reinauerdebb11f2008-10-29 04:46:52 +0000239static struct device_operations sata_ops = {
240 .read_resources = pci_dev_read_resources,
241 .set_resources = pci_dev_set_resources,
242 .enable_resources = pci_dev_enable_resources,
243 .init = sata_init,
244 .scan_bus = 0,
245 .enable = i82801gx_enable,
Stefan Reinauera8e11682009-03-11 14:54:18 +0000246 .ops_pci = &sata_pci_ops,
Stefan Reinauerdebb11f2008-10-29 04:46:52 +0000247};
248
Patrick Georgiefff7332012-07-26 19:48:23 +0200249static const unsigned short sata_ids[] = {
250 0x27c0, /* Desktop Non-AHCI and Non-RAID Mode: 82801GB/GR/GDH (ICH7/ICH7R/ICH7DH) */
Patrick Georgiefff7332012-07-26 19:48:23 +0200251 0x27c1, /* Desktop AHCI Mode: 82801GB/GR/GDH (ICH7/ICH7R/ICH7DH) */
Damien Zammit647e3852016-01-15 13:44:53 +1100252 0x27c4, /* Mobile Non-AHCI and Non-RAID Mode: 82801GBM/GHM (ICH7-M/ICH7-M DH) */
Patrick Georgiefff7332012-07-26 19:48:23 +0200253 0x27c5, /* Mobile AHCI Mode: 82801GBM/GHM (ICH7-M/ICH7-M DH) */
Damien Zammit647e3852016-01-15 13:44:53 +1100254 /* NOTE: Any of the below are not properly supported yet. */
255 0x27c3, /* Desktop RAID mode: 82801GB/GR/GDH (ICH7/ICH7R/ICH7DH) */
Patrick Georgiefff7332012-07-26 19:48:23 +0200256 0x27c6, /* ICH7M DH Raid Mode: 82801GHM (ICH7-M DH) */
257 0
Stefan Reinauerdebb11f2008-10-29 04:46:52 +0000258};
259
Patrick Georgiefff7332012-07-26 19:48:23 +0200260static const struct pci_driver i82801gx_sata_driver __pci_driver = {
Arthur Heymans3f111b02017-03-09 12:02:52 +0100261 .ops = &sata_ops,
262 .vendor = PCI_VENDOR_ID_INTEL,
263 .devices = sata_ids,
Stefan Reinauerdebb11f2008-10-29 04:46:52 +0000264};