blob: 567c1e50472308363d07be775a746d0a99e2a061 [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>
21#include <device/pci_ids.h>
22#include "i82801gx.h"
Damien Zammit647e3852016-01-15 13:44:53 +110023#include "sata.h"
Stefan Reinauerdebb11f2008-10-29 04:46:52 +000024
25typedef struct southbridge_intel_i82801gx_config config_t;
26
Damien Zammit647e3852016-01-15 13:44:53 +110027static u8 get_ich7_sata_ports(void)
28{
29 struct device *lpc;
30
Kyösti Mälkkic70eed12018-05-22 02:18:00 +030031 lpc = pcidev_on_root(31, 0);
Damien Zammit647e3852016-01-15 13:44:53 +110032
33 switch (pci_read_config16(lpc, PCI_DEVICE_ID)) {
34 case 0x27b0:
35 case 0x27b8:
36 return 0xf;
37 case 0x27b9:
38 case 0x27bd:
39 return 0x5;
40 case 0x27bc:
41 return 0x3;
42 default:
43 printk(BIOS_ERR,
44 "i82801gx_sata: error: cannot determine port config\n");
45 return 0;
46 }
47}
48
49void sata_enable(struct device *dev)
50{
51 /* Get the chip configuration */
52 config_t *config = dev->chip_info;
53
54 if (config->sata_ahci) {
55 /* Set map to ahci */
56 pci_write_config8(dev, SATA_MAP,
57 (pci_read_config8(dev, SATA_MAP) & ~0xc3) | 0x40);
58 } else {
59 /* Set map to ide */
60 pci_write_config8(dev, SATA_MAP,
61 pci_read_config8(dev, SATA_MAP) & ~0xc3);
62 }
63
64 /* At this point, the new pci id will appear on the bus */
65}
66
Stefan Reinauerdebb11f2008-10-29 04:46:52 +000067static void sata_init(struct device *dev)
68{
69 u32 reg32;
Stefan Reinauera8e11682009-03-11 14:54:18 +000070 u16 reg16;
Sven Schnelleb2f173e2011-10-27 13:05:40 +020071 u32 *ahci_bar;
Damien Zammit647e3852016-01-15 13:44:53 +110072 u8 ports;
Sven Schnelleb2f173e2011-10-27 13:05:40 +020073
Stefan Reinauerdebb11f2008-10-29 04:46:52 +000074 /* Get the chip configuration */
75 config_t *config = dev->chip_info;
76
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000077 printk(BIOS_DEBUG, "i82801gx_sata: initializing...\n");
Stefan Reinauera8e11682009-03-11 14:54:18 +000078
Stefan Reinauer573f7d42009-07-21 21:50:34 +000079 if (config == NULL) {
Uwe Hermann607614d2010-11-18 20:12:13 +000080 printk(BIOS_ERR, "i82801gx_sata: error: device not in devicetree.cb!\n");
Stefan Reinauer573f7d42009-07-21 21:50:34 +000081 return;
82 }
Stefan Reinauera8e11682009-03-11 14:54:18 +000083
Damien Zammit647e3852016-01-15 13:44:53 +110084 /* Get ICH7 SATA port config */
85 ports = get_ich7_sata_ports();
Stefan Reinauerdebb11f2008-10-29 04:46:52 +000086
87 /* Enable BARs */
Stefan Reinauera8e11682009-03-11 14:54:18 +000088 pci_write_config16(dev, PCI_COMMAND, 0x0007);
Stefan Reinauerdebb11f2008-10-29 04:46:52 +000089
90 if (config->ide_legacy_combined) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000091 printk(BIOS_DEBUG, "SATA controller in combined mode.\n");
Stefan Reinauera8e11682009-03-11 14:54:18 +000092 /* No AHCI: clear AHCI base */
93 pci_write_config32(dev, 0x24, 0x00000000);
94 /* And without AHCI BAR no memory decoding */
95 reg16 = pci_read_config16(dev, PCI_COMMAND);
96 reg16 &= ~PCI_COMMAND_MEMORY;
97 pci_write_config16(dev, PCI_COMMAND, reg16);
98
Stefan Reinauerdebb11f2008-10-29 04:46:52 +000099 pci_write_config8(dev, 0x09, 0x80);
100
101 /* Set timings */
Stefan Reinauer573f7d42009-07-21 21:50:34 +0000102 pci_write_config16(dev, IDE_TIM_PRI, IDE_DECODE_ENABLE |
103 IDE_ISP_5_CLOCKS | IDE_RCT_4_CLOCKS);
104 pci_write_config16(dev, IDE_TIM_SEC, IDE_DECODE_ENABLE |
105 IDE_ISP_3_CLOCKS | IDE_RCT_1_CLOCKS |
106 IDE_PPE0 | IDE_IE0 | IDE_TIME0);
Stefan Reinauerdebb11f2008-10-29 04:46:52 +0000107
108 /* Sync DMA */
Stefan Reinauer573f7d42009-07-21 21:50:34 +0000109 pci_write_config16(dev, IDE_SDMA_CNT, IDE_SSDE0);
110 pci_write_config16(dev, IDE_SDMA_TIM, 0x0200);
Stefan Reinauerdebb11f2008-10-29 04:46:52 +0000111
Stefan Reinauera8e11682009-03-11 14:54:18 +0000112 /* Set IDE I/O Configuration */
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000113 reg32 = SIG_MODE_PRI_NORMAL | FAST_PCB1 | FAST_PCB0 | PCB1 | PCB0;
Stefan Reinauera8e11682009-03-11 14:54:18 +0000114 pci_write_config32(dev, IDE_CONFIG, reg32);
115
Stefan Reinauerdebb11f2008-10-29 04:46:52 +0000116 /* Combine IDE - SATA configuration */
Damien Zammit647e3852016-01-15 13:44:53 +1100117 pci_write_config8(dev, SATA_MAP, 0x02);
Stefan Reinauerdebb11f2008-10-29 04:46:52 +0000118
Damien Zammit1533f132016-01-16 02:52:53 +1100119 /* Restrict ports - 0 and 2 only available */
120 ports &= 0x5;
Elyes HAOUAS70d79a42016-08-21 18:36:06 +0200121 } else if (config->sata_ahci) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000122 printk(BIOS_DEBUG, "SATA controller in AHCI mode.\n");
Stefan Reinauerdebb11f2008-10-29 04:46:52 +0000123 /* Allow both Legacy and Native mode */
124 pci_write_config8(dev, 0x09, 0x8f);
125
126 /* Set Interrupt Line */
127 /* Interrupt Pin is set by D31IP.PIP */
128 pci_write_config8(dev, INTR_LN, 0x0a);
129
Sven Schnelleb2f173e2011-10-27 13:05:40 +0200130 ahci_bar = (u32 *)(pci_read_config32(dev, 0x27) & ~0x3ff);
131 ahci_bar[3] = config->sata_ports_implemented;
Stefan Reinauerdebb11f2008-10-29 04:46:52 +0000132 } else {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000133 printk(BIOS_DEBUG, "SATA controller in plain mode.\n");
Stefan Reinauera8e11682009-03-11 14:54:18 +0000134 /* Set Sata Controller Mode. No Mapping(?) */
Damien Zammit647e3852016-01-15 13:44:53 +1100135 pci_write_config8(dev, SATA_MAP, 0x00);
Stefan Reinauera8e11682009-03-11 14:54:18 +0000136
137 /* No AHCI: clear AHCI base */
138 pci_write_config32(dev, 0x24, 0x00000000);
139
140 /* And without AHCI BAR no memory decoding */
141 reg16 = pci_read_config16(dev, PCI_COMMAND);
142 reg16 &= ~PCI_COMMAND_MEMORY;
143 pci_write_config16(dev, PCI_COMMAND, reg16);
144
Stefan Reinauerdebb11f2008-10-29 04:46:52 +0000145 /* Native mode capable on both primary and secondary (0xa)
146 * or'ed with enabled (0x50) = 0xf
147 */
148 pci_write_config8(dev, 0x09, 0x8f);
149
150 /* Set Interrupt Line */
151 /* Interrupt Pin is set by D31IP.PIP */
152 pci_write_config8(dev, INTR_LN, 0xff);
Stefan Reinauer109ab312009-08-12 16:08:05 +0000153
Stefan Reinauerdebb11f2008-10-29 04:46:52 +0000154 /* Set timings */
Stefan Reinauer573f7d42009-07-21 21:50:34 +0000155 pci_write_config16(dev, IDE_TIM_PRI, IDE_DECODE_ENABLE |
156 IDE_ISP_3_CLOCKS | IDE_RCT_1_CLOCKS |
157 IDE_PPE0 | IDE_IE0 | IDE_TIME0);
158 pci_write_config16(dev, IDE_TIM_SEC, IDE_DECODE_ENABLE |
Stefan Reinauer109ab312009-08-12 16:08:05 +0000159 IDE_SITRE | IDE_ISP_3_CLOCKS |
Stefan Reinauer573f7d42009-07-21 21:50:34 +0000160 IDE_RCT_1_CLOCKS | IDE_IE0 | IDE_TIME0);
Stefan Reinauer109ab312009-08-12 16:08:05 +0000161
Stefan Reinauerdebb11f2008-10-29 04:46:52 +0000162 /* Sync DMA */
Stefan Reinauer573f7d42009-07-21 21:50:34 +0000163 pci_write_config16(dev, IDE_SDMA_CNT, IDE_SSDE0 | IDE_PSDE0);
164 pci_write_config16(dev, IDE_SDMA_TIM, 0x0201);
Stefan Reinauer109ab312009-08-12 16:08:05 +0000165
Stefan Reinauerdebb11f2008-10-29 04:46:52 +0000166 /* Set IDE I/O Configuration */
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000167 reg32 = SIG_MODE_PRI_NORMAL | FAST_PCB1 | FAST_PCB0 | PCB1 | PCB0;
Stefan Reinauerdebb11f2008-10-29 04:46:52 +0000168 pci_write_config32(dev, IDE_CONFIG, reg32);
Stefan Reinauerdebb11f2008-10-29 04:46:52 +0000169 }
170
Damien Zammit1533f132016-01-16 02:52:53 +1100171 /* Set port control */
172 pci_write_config8(dev, SATA_PCS, ports);
173
Damien Zammit647e3852016-01-15 13:44:53 +1100174 /* Enable clock gating for unused ports and set initialization reg */
175 pci_write_config32(dev, SATA_IR, SIF3(ports) | SIF2 | SIF1 | SCRE);
176
Stefan Reinauerdebb11f2008-10-29 04:46:52 +0000177 /* All configurations need this SATA initialization sequence */
178 pci_write_config8(dev, 0xa0, 0x40);
179 pci_write_config8(dev, 0xa6, 0x22);
180 pci_write_config8(dev, 0xa0, 0x78);
181 pci_write_config8(dev, 0xa6, 0x22);
182 pci_write_config8(dev, 0xa0, 0x88);
183 reg32 = pci_read_config32(dev, 0xa4);
184 reg32 &= 0xc0c0c0c0;
185 reg32 |= 0x1b1b1212;
186 pci_write_config32(dev, 0xa4, reg32);
187 pci_write_config8(dev, 0xa0, 0x8c);
188 reg32 = pci_read_config32(dev, 0xa4);
189 reg32 &= 0xc0c0ff00;
190 reg32 |= 0x121200aa;
191 pci_write_config32(dev, 0xa4, reg32);
192 pci_write_config8(dev, 0xa0, 0x00);
Stefan Reinauer54309d62009-01-20 22:53:10 +0000193
194 pci_write_config8(dev, PCI_INTERRUPT_LINE, 0);
Stefan Reinauera8e11682009-03-11 14:54:18 +0000195
196 /* Sata Initialization Register */
Damien Zammit647e3852016-01-15 13:44:53 +1100197 reg32 = pci_read_config32(dev, SATA_IR);
198 reg32 |= SCRD; // due to some bug
199 pci_write_config32(dev, SATA_IR, reg32);
Stefan Reinauerdebb11f2008-10-29 04:46:52 +0000200}
201
Elyes HAOUAS99667032018-05-13 12:47:28 +0200202static void sata_set_subsystem(struct device *dev, unsigned int vendor,
203 unsigned int device)
Stefan Reinauera8e11682009-03-11 14:54:18 +0000204{
205 if (!vendor || !device) {
206 pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
207 pci_read_config32(dev, PCI_VENDOR_ID));
208 } else {
209 pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
210 ((device & 0xffff) << 16) | (vendor & 0xffff));
211 }
212}
213
214static struct pci_operations sata_pci_ops = {
215 .set_subsystem = sata_set_subsystem,
216};
217
Stefan Reinauerdebb11f2008-10-29 04:46:52 +0000218static struct device_operations sata_ops = {
219 .read_resources = pci_dev_read_resources,
220 .set_resources = pci_dev_set_resources,
221 .enable_resources = pci_dev_enable_resources,
222 .init = sata_init,
223 .scan_bus = 0,
224 .enable = i82801gx_enable,
Stefan Reinauera8e11682009-03-11 14:54:18 +0000225 .ops_pci = &sata_pci_ops,
Stefan Reinauerdebb11f2008-10-29 04:46:52 +0000226};
227
Patrick Georgiefff7332012-07-26 19:48:23 +0200228static const unsigned short sata_ids[] = {
229 0x27c0, /* Desktop Non-AHCI and Non-RAID Mode: 82801GB/GR/GDH (ICH7/ICH7R/ICH7DH) */
Patrick Georgiefff7332012-07-26 19:48:23 +0200230 0x27c1, /* Desktop AHCI Mode: 82801GB/GR/GDH (ICH7/ICH7R/ICH7DH) */
Damien Zammit647e3852016-01-15 13:44:53 +1100231 0x27c4, /* Mobile Non-AHCI and Non-RAID Mode: 82801GBM/GHM (ICH7-M/ICH7-M DH) */
Patrick Georgiefff7332012-07-26 19:48:23 +0200232 0x27c5, /* Mobile AHCI Mode: 82801GBM/GHM (ICH7-M/ICH7-M DH) */
Damien Zammit647e3852016-01-15 13:44:53 +1100233 /* NOTE: Any of the below are not properly supported yet. */
234 0x27c3, /* Desktop RAID mode: 82801GB/GR/GDH (ICH7/ICH7R/ICH7DH) */
Patrick Georgiefff7332012-07-26 19:48:23 +0200235 0x27c6, /* ICH7M DH Raid Mode: 82801GHM (ICH7-M DH) */
236 0
Stefan Reinauerdebb11f2008-10-29 04:46:52 +0000237};
238
Patrick Georgiefff7332012-07-26 19:48:23 +0200239static const struct pci_driver i82801gx_sata_driver __pci_driver = {
Arthur Heymans3f111b02017-03-09 12:02:52 +0100240 .ops = &sata_ops,
241 .vendor = PCI_VENDOR_ID_INTEL,
242 .devices = sata_ids,
Stefan Reinauerdebb11f2008-10-29 04:46:52 +0000243};