blob: 74ba823f34f24584376deada22d10ac4df189548 [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
Stefan Reinauerdebb11f2008-10-29 04:46:52 +00005 *
Stefan Reinauera8e11682009-03-11 14:54:18 +00006 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; version 2 of
9 * the License.
Stefan Reinauerdebb11f2008-10-29 04:46:52 +000010 *
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.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#include <console/console.h>
22#include <device/device.h>
23#include <device/pci.h>
24#include <device/pci_ids.h>
25#include "i82801gx.h"
26
27typedef struct southbridge_intel_i82801gx_config config_t;
28
29static void sata_init(struct device *dev)
30{
31 u32 reg32;
Stefan Reinauera8e11682009-03-11 14:54:18 +000032 u16 reg16;
Stefan Reinauerdebb11f2008-10-29 04:46:52 +000033 /* Get the chip configuration */
34 config_t *config = dev->chip_info;
35
36 printk_debug("i82801gx_sata: initializing...\n");
Stefan Reinauera8e11682009-03-11 14:54:18 +000037
Stefan Reinauer573f7d42009-07-21 21:50:34 +000038 if (config == NULL) {
Stefan Reinauera8e11682009-03-11 14:54:18 +000039 printk_err("i82801gx_sata: error: device not in Config.lb!\n");
Stefan Reinauer573f7d42009-07-21 21:50:34 +000040 return;
41 }
Stefan Reinauera8e11682009-03-11 14:54:18 +000042
Stefan Reinauerdebb11f2008-10-29 04:46:52 +000043 /* SATA configuration */
44
45 /* Enable BARs */
Stefan Reinauera8e11682009-03-11 14:54:18 +000046 pci_write_config16(dev, PCI_COMMAND, 0x0007);
Stefan Reinauerdebb11f2008-10-29 04:46:52 +000047
48 if (config->ide_legacy_combined) {
Stefan Reinauera8e11682009-03-11 14:54:18 +000049 printk_debug("SATA controller in combined mode.\n");
50 /* No AHCI: clear AHCI base */
51 pci_write_config32(dev, 0x24, 0x00000000);
52 /* And without AHCI BAR no memory decoding */
53 reg16 = pci_read_config16(dev, PCI_COMMAND);
54 reg16 &= ~PCI_COMMAND_MEMORY;
55 pci_write_config16(dev, PCI_COMMAND, reg16);
56
Stefan Reinauerdebb11f2008-10-29 04:46:52 +000057 pci_write_config8(dev, 0x09, 0x80);
58
59 /* Set timings */
Stefan Reinauer573f7d42009-07-21 21:50:34 +000060 pci_write_config16(dev, IDE_TIM_PRI, IDE_DECODE_ENABLE |
61 IDE_ISP_5_CLOCKS | IDE_RCT_4_CLOCKS);
62 pci_write_config16(dev, IDE_TIM_SEC, IDE_DECODE_ENABLE |
63 IDE_ISP_3_CLOCKS | IDE_RCT_1_CLOCKS |
64 IDE_PPE0 | IDE_IE0 | IDE_TIME0);
Stefan Reinauerdebb11f2008-10-29 04:46:52 +000065
66 /* Sync DMA */
Stefan Reinauer573f7d42009-07-21 21:50:34 +000067 pci_write_config16(dev, IDE_SDMA_CNT, IDE_SSDE0);
68 pci_write_config16(dev, IDE_SDMA_TIM, 0x0200);
Stefan Reinauerdebb11f2008-10-29 04:46:52 +000069
Stefan Reinauera8e11682009-03-11 14:54:18 +000070 /* Set IDE I/O Configuration */
71 reg32 = SIG_MODE_NORMAL | FAST_PCB1 | FAST_PCB0 | PCB1 | PCB0;
72 pci_write_config32(dev, IDE_CONFIG, reg32);
73
Stefan Reinauerdebb11f2008-10-29 04:46:52 +000074 /* Combine IDE - SATA configuration */
75 pci_write_config8(dev, 0x90, 0x02);
76
77 /* Port 0 & 1 enable */
78 pci_write_config8(dev, 0x92, 0x0f);
79
80 /* SATA Initialization register */
Stefan Reinauera8e11682009-03-11 14:54:18 +000081 pci_write_config32(dev, 0x94, 0x5a000180);
Stefan Reinauerdebb11f2008-10-29 04:46:52 +000082 } else if(config->sata_ahci) {
Stefan Reinauera8e11682009-03-11 14:54:18 +000083 printk_debug("SATA controller in AHCI mode.\n");
Stefan Reinauerdebb11f2008-10-29 04:46:52 +000084 /* Allow both Legacy and Native mode */
85 pci_write_config8(dev, 0x09, 0x8f);
86
87 /* Set Interrupt Line */
88 /* Interrupt Pin is set by D31IP.PIP */
89 pci_write_config8(dev, INTR_LN, 0x0a);
90
91 /* Set timings */
Stefan Reinauer573f7d42009-07-21 21:50:34 +000092 pci_write_config16(dev, IDE_TIM_PRI, IDE_DECODE_ENABLE |
93 IDE_ISP_3_CLOCKS | IDE_RCT_1_CLOCKS |
94 IDE_PPE0 | IDE_IE0 | IDE_TIME0);
95 pci_write_config16(dev, IDE_TIM_SEC, IDE_DECODE_ENABLE |
96 IDE_ISP_5_CLOCKS | IDE_RCT_4_CLOCKS);
Stefan Reinauerdebb11f2008-10-29 04:46:52 +000097
98 /* Sync DMA */
Stefan Reinauer573f7d42009-07-21 21:50:34 +000099 pci_write_config16(dev, IDE_SDMA_CNT, IDE_PSDE0);
100 pci_write_config16(dev, IDE_SDMA_TIM, 0x0001);
Stefan Reinauerdebb11f2008-10-29 04:46:52 +0000101
102 /* Set IDE I/O Configuration */
103 reg32 = SIG_MODE_NORMAL | FAST_PCB1 | FAST_PCB0 | PCB1 | PCB0;
104 pci_write_config32(dev, IDE_CONFIG, reg32);
105
106 /* Set Sata Controller Mode. */
107 pci_write_config8(dev, 0x90, 0xc0); // WTF - Reserved?
108
109 /* Port 0 & 1 enable */
110 pci_write_config8(dev, 0x92, 0x0f);
111
112 /* SATA Initialization register */
113 pci_write_config32(dev, 0x94, 0x1a000180);
114 } else {
Stefan Reinauera8e11682009-03-11 14:54:18 +0000115 printk_debug("SATA controller in plain mode.\n");
116 /* Set Sata Controller Mode. No Mapping(?) */
117 pci_write_config8(dev, 0x90, 0x00);
118
119 /* No AHCI: clear AHCI base */
120 pci_write_config32(dev, 0x24, 0x00000000);
121
122 /* And without AHCI BAR no memory decoding */
123 reg16 = pci_read_config16(dev, PCI_COMMAND);
124 reg16 &= ~PCI_COMMAND_MEMORY;
125 pci_write_config16(dev, PCI_COMMAND, reg16);
126
Stefan Reinauerdebb11f2008-10-29 04:46:52 +0000127 /* Native mode capable on both primary and secondary (0xa)
128 * or'ed with enabled (0x50) = 0xf
129 */
130 pci_write_config8(dev, 0x09, 0x8f);
131
132 /* Set Interrupt Line */
133 /* Interrupt Pin is set by D31IP.PIP */
134 pci_write_config8(dev, INTR_LN, 0xff);
135
136 /* Set timings */
Stefan Reinauer573f7d42009-07-21 21:50:34 +0000137 pci_write_config16(dev, IDE_TIM_PRI, IDE_DECODE_ENABLE |
138 IDE_ISP_3_CLOCKS | IDE_RCT_1_CLOCKS |
139 IDE_PPE0 | IDE_IE0 | IDE_TIME0);
140 pci_write_config16(dev, IDE_TIM_SEC, IDE_DECODE_ENABLE |
141 IDE_SITRE | IDE_ISP_3_CLOCKS |
142 IDE_RCT_1_CLOCKS | IDE_IE0 | IDE_TIME0);
Stefan Reinauerdebb11f2008-10-29 04:46:52 +0000143
144 /* Sync DMA */
Stefan Reinauer573f7d42009-07-21 21:50:34 +0000145 pci_write_config16(dev, IDE_SDMA_CNT, IDE_SSDE0 | IDE_PSDE0);
146 pci_write_config16(dev, IDE_SDMA_TIM, 0x0201);
Stefan Reinauerdebb11f2008-10-29 04:46:52 +0000147
148 /* Set IDE I/O Configuration */
149 reg32 = SIG_MODE_NORMAL | FAST_PCB1 | FAST_PCB0 | PCB1 | PCB0;
150 pci_write_config32(dev, IDE_CONFIG, reg32);
151
Stefan Reinauerdebb11f2008-10-29 04:46:52 +0000152 /* Port 0 & 1 enable XXX */
153 pci_write_config8(dev, 0x92, 0x15);
154
155 /* SATA Initialization register */
156 pci_write_config32(dev, 0x94, 0x1a000180);
157 }
158
159 /* All configurations need this SATA initialization sequence */
160 pci_write_config8(dev, 0xa0, 0x40);
161 pci_write_config8(dev, 0xa6, 0x22);
162 pci_write_config8(dev, 0xa0, 0x78);
163 pci_write_config8(dev, 0xa6, 0x22);
164 pci_write_config8(dev, 0xa0, 0x88);
165 reg32 = pci_read_config32(dev, 0xa4);
166 reg32 &= 0xc0c0c0c0;
167 reg32 |= 0x1b1b1212;
168 pci_write_config32(dev, 0xa4, reg32);
169 pci_write_config8(dev, 0xa0, 0x8c);
170 reg32 = pci_read_config32(dev, 0xa4);
171 reg32 &= 0xc0c0ff00;
172 reg32 |= 0x121200aa;
173 pci_write_config32(dev, 0xa4, reg32);
174 pci_write_config8(dev, 0xa0, 0x00);
Stefan Reinauer54309d62009-01-20 22:53:10 +0000175
176 pci_write_config8(dev, PCI_INTERRUPT_LINE, 0);
Stefan Reinauera8e11682009-03-11 14:54:18 +0000177
178 /* Sata Initialization Register */
179 reg32 = pci_read_config32(dev, 0x94);
180 reg32 |= (1 << 30); // due to some bug
181 pci_write_config32(dev, 0x94, reg32);
Stefan Reinauerdebb11f2008-10-29 04:46:52 +0000182}
183
Stefan Reinauera8e11682009-03-11 14:54:18 +0000184static void sata_set_subsystem(device_t dev, unsigned vendor, unsigned device)
185{
186 if (!vendor || !device) {
187 pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
188 pci_read_config32(dev, PCI_VENDOR_ID));
189 } else {
190 pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
191 ((device & 0xffff) << 16) | (vendor & 0xffff));
192 }
193}
194
195static struct pci_operations sata_pci_ops = {
196 .set_subsystem = sata_set_subsystem,
197};
198
Stefan Reinauerdebb11f2008-10-29 04:46:52 +0000199static struct device_operations sata_ops = {
200 .read_resources = pci_dev_read_resources,
201 .set_resources = pci_dev_set_resources,
202 .enable_resources = pci_dev_enable_resources,
203 .init = sata_init,
204 .scan_bus = 0,
205 .enable = i82801gx_enable,
Stefan Reinauera8e11682009-03-11 14:54:18 +0000206 .ops_pci = &sata_pci_ops,
Stefan Reinauerdebb11f2008-10-29 04:46:52 +0000207};
208
209/* Desktop Non-AHCI and Non-RAID Mode */
Uwe Hermannbddc6932008-10-29 13:51:31 +0000210/* 82801GB/GR/GDH (ICH7/ICH7R/ICH7DH) */
Stefan Reinauerdebb11f2008-10-29 04:46:52 +0000211static const struct pci_driver i82801gx_sata_normal_driver __pci_driver = {
212 .ops = &sata_ops,
213 .vendor = PCI_VENDOR_ID_INTEL,
Uwe Hermann5d7a1c82008-10-31 18:41:09 +0000214 .device = 0x27c0,
Stefan Reinauerdebb11f2008-10-29 04:46:52 +0000215};
216
Stefan Reinauera8e11682009-03-11 14:54:18 +0000217/* Mobile Non-AHCI and Non-RAID Mode */
218/* 82801GBM/GHM (ICH7-M/ICH7-M DH) */
219static const struct pci_driver i82801gx_sata_mobile_normal_driver __pci_driver = {
220 .ops = &sata_ops,
221 .vendor = PCI_VENDOR_ID_INTEL,
222 .device = 0x27c4,
223};
224
225
Uwe Hermannbddc6932008-10-29 13:51:31 +0000226/* NOTE: Any of the below are not properly supported yet. */
Stefan Reinauerdebb11f2008-10-29 04:46:52 +0000227
228/* Desktop AHCI Mode */
Uwe Hermannbddc6932008-10-29 13:51:31 +0000229/* 82801GB/GR/GDH (ICH7/ICH7R/ICH7DH) */
Stefan Reinauerdebb11f2008-10-29 04:46:52 +0000230static const struct pci_driver i82801gx_sata_ahci_driver __pci_driver = {
231 .ops = &sata_ops,
232 .vendor = PCI_VENDOR_ID_INTEL,
Uwe Hermann5d7a1c82008-10-31 18:41:09 +0000233 .device = 0x27c1,
Stefan Reinauerdebb11f2008-10-29 04:46:52 +0000234};
235
236/* Desktop RAID mode */
Uwe Hermannbddc6932008-10-29 13:51:31 +0000237/* 82801GB/GR/GDH (ICH7/ICH7R/ICH7DH) */
Stefan Reinauerdebb11f2008-10-29 04:46:52 +0000238static const struct pci_driver i82801gx_sata_raid_driver __pci_driver = {
239 .ops = &sata_ops,
240 .vendor = PCI_VENDOR_ID_INTEL,
Uwe Hermann5d7a1c82008-10-31 18:41:09 +0000241 .device = 0x27c3,
Stefan Reinauerdebb11f2008-10-29 04:46:52 +0000242};
243
Stefan Reinauerdebb11f2008-10-29 04:46:52 +0000244/* Mobile AHCI Mode */
Uwe Hermannbddc6932008-10-29 13:51:31 +0000245/* 82801GBM/GHM (ICH7-M/ICH7-M DH) */
Stefan Reinauerdebb11f2008-10-29 04:46:52 +0000246static const struct pci_driver i82801gx_sata_mobile_ahci_driver __pci_driver = {
247 .ops = &sata_ops,
248 .vendor = PCI_VENDOR_ID_INTEL,
Uwe Hermann5d7a1c82008-10-31 18:41:09 +0000249 .device = 0x27c5,
Stefan Reinauerdebb11f2008-10-29 04:46:52 +0000250};
251
252/* ICH7M DH Raid Mode */
Uwe Hermannbddc6932008-10-29 13:51:31 +0000253/* 82801GHM (ICH7-M DH) */
Stefan Reinauerdebb11f2008-10-29 04:46:52 +0000254static const struct pci_driver i82801gx_sata_ich7dh_raid_driver __pci_driver = {
255 .ops = &sata_ops,
256 .vendor = PCI_VENDOR_ID_INTEL,
Uwe Hermann5d7a1c82008-10-31 18:41:09 +0000257 .device = 0x27c6,
Stefan Reinauerdebb11f2008-10-29 04:46:52 +0000258};