blob: 69df88c4cbc8dd8bbe463dfede056b9d3375d060 [file] [log] [blame]
Arthur Heymans7b9c1392017-04-09 20:40:39 +02001/*
2 * This file is part of the coreboot project.
3 *
Arthur Heymans7b9c1392017-04-09 20:40:39 +02004 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; version 2 of
8 * the License.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 */
15
16#include <arch/io.h>
Kyösti Mälkki13f66502019-03-03 08:01:05 +020017#include <device/mmio.h>
Kyösti Mälkkif1b58b72019-03-01 13:43:02 +020018#include <device/pci_ops.h>
Arthur Heymans7b9c1392017-04-09 20:40:39 +020019#include <console/console.h>
20#include <device/device.h>
21#include <device/pci.h>
22#include <device/pci_ids.h>
Kyösti Mälkkicbf95712020-01-05 08:05:45 +020023#include <option.h>
Elyes HAOUASab89edb2019-05-15 21:10:44 +020024#include <types.h>
25
Kyösti Mälkki12b121c2019-08-18 16:33:39 +030026#include "chip.h"
Elyes HAOUASab89edb2019-05-15 21:10:44 +020027#include "i82801jx.h"
Arthur Heymans7b9c1392017-04-09 20:40:39 +020028
Arthur Heymans349e0852017-04-09 20:48:37 +020029typedef struct southbridge_intel_i82801jx_config config_t;
Arthur Heymans7b9c1392017-04-09 20:40:39 +020030
31static void sata_enable_ahci_mmap(struct device *const dev, const u8 port_map,
32 const int is_mobile)
33{
34 int i;
35 u32 reg32;
36
37 /* Initialize AHCI memory-mapped space */
38 u8 *abar = (u8 *)pci_read_config32(dev, PCI_BASE_ADDRESS_5);
39 printk(BIOS_DEBUG, "ABAR: %p\n", abar);
40
41 /* Set AHCI access mode.
42 No other ABAR registers should be accessed before this. */
43 reg32 = read32(abar + 0x04);
44 reg32 |= 1 << 31;
45 write32(abar + 0x04, reg32);
46
47 /* CAP (HBA Capabilities) : enable power management */
48 reg32 = read32(abar + 0x00);
49 /* CCCS must be set. */
50 reg32 |= 0x0c006080; /* set CCCS+PSC+SSC+SALP+SSS */
51 reg32 &= ~0x00020060; /* clear SXS+EMS+PMS */
52 write32(abar + 0x00, reg32);
53
54 /* PI (Ports implemented) */
55 write32(abar + 0x0c, port_map);
56 /* PCH code reads back twice, do we need it, too? */
57 (void) read32(abar + 0x0c); /* Read back 1 */
58 (void) read32(abar + 0x0c); /* Read back 2 */
59
60 /* VSP (Vendor Specific Register) */
61 reg32 = read32(abar + 0xa0);
62 reg32 &= ~0x00000001; /* clear SLPD */
63 write32(abar + 0xa0, reg32);
64
65 /* Lock R/WO bits in Port command registers. */
66 for (i = 0; i < 6; ++i) {
67 if (((i == 2) || (i == 3)) && is_mobile)
68 continue;
69 u8 *addr = abar + 0x118 + (i * 0x80);
70 write32(addr, read32(addr));
71 }
72}
73
74static void sata_program_indexed(struct device *const dev, const int is_mobile)
75{
76 u32 reg32;
77
78 pci_write_config8(dev, D31F2_SIDX, 0x18);
79 reg32 = pci_read_config32(dev, D31F2_SDAT);
80 reg32 &= ~((7 << 6) | (7 << 3) | (7 << 0));
81 reg32 |= (3 << 3) | (3 << 0);
82 pci_write_config32(dev, D31F2_SDAT, reg32);
83
84 pci_write_config8(dev, D31F2_SIDX, 0x28);
85 pci_write_config32(dev, D31F2_SDAT, 0x00cc2080);
86
87 pci_write_config8(dev, D31F2_SIDX, 0x40);
88 pci_write_config8(dev, D31F2_SDAT + 2, 0x22);
89
90 pci_write_config8(dev, D31F2_SIDX, 0x78);
91 pci_write_config8(dev, D31F2_SDAT + 2, 0x22);
92
93 if (!is_mobile) {
94 pci_write_config8(dev, D31F2_SIDX, 0x84);
95 reg32 = pci_read_config32(dev, D31F2_SDAT);
96 reg32 &= ~((7 << 3) | (7 << 0));
97 reg32 |= (3 << 3) | (3 << 0);
98 pci_write_config32(dev, D31F2_SDAT, reg32);
99 }
100
101 pci_write_config8(dev, D31F2_SIDX, 0x88);
102 reg32 = pci_read_config32(dev, D31F2_SDAT);
103 if (!is_mobile)
104 reg32 &= ~((7 << 27) | (7 << 24) | (7 << 11) | (7 << 8));
105 reg32 &= ~((7 << 19) | (7 << 16) | (7 << 3) | (7 << 0));
106 if (!is_mobile)
107 reg32 |= (4 << 27) | (4 << 24) | (2 << 11) | (2 << 8);
108 reg32 |= (4 << 19) | (4 << 16) | (2 << 3) | (2 << 0);
109 pci_write_config32(dev, D31F2_SDAT, reg32);
110
111 pci_write_config8(dev, D31F2_SIDX, 0x8c);
112 reg32 = pci_read_config32(dev, D31F2_SDAT);
113 if (!is_mobile)
114 reg32 &= ~((7 << 27) | (7 << 24));
115 reg32 &= ~((7 << 19) | (7 << 16) | 0xffff);
116 if (!is_mobile)
117 reg32 |= (2 << 27) | (2 << 24);
118 reg32 |= (2 << 19) | (2 << 16) | 0x00aa;
119 pci_write_config32(dev, D31F2_SDAT, reg32);
120
121 pci_write_config8(dev, D31F2_SIDX, 0x94);
122 pci_write_config32(dev, D31F2_SDAT, 0x00000022);
123
124 pci_write_config8(dev, D31F2_SIDX, 0xa0);
125 reg32 = pci_read_config32(dev, D31F2_SDAT);
126 reg32 &= ~((7 << 3) | (7 << 0));
127 reg32 |= (3 << 3) | (3 << 0);
128 pci_write_config32(dev, D31F2_SDAT, reg32);
129
130 pci_write_config8(dev, D31F2_SIDX, 0xa8);
131 reg32 = pci_read_config32(dev, D31F2_SDAT);
132 reg32 &= ~((7 << 19) | (7 << 16) | (7 << 3) | (7 << 0));
133 reg32 |= (4 << 19) | (4 << 16) | (2 << 3) | (2 << 0);
134 pci_write_config32(dev, D31F2_SDAT, reg32);
135
136 pci_write_config8(dev, D31F2_SIDX, 0xac);
137 reg32 = pci_read_config32(dev, D31F2_SDAT);
138 reg32 &= ~((7 << 19) | (7 << 16) | 0xffff);
139 reg32 |= (2 << 19) | (2 << 16) | 0x000a;
140 pci_write_config32(dev, D31F2_SDAT, reg32);
141}
142
143static void sata_init(struct device *const dev)
144{
145 u16 reg16;
146
147 /* Get the chip configuration */
148 const config_t *const config = dev->chip_info;
149
150 const u16 devid = pci_read_config16(dev, PCI_DEVICE_ID);
151 const int is_mobile = (devid == 0x2928) || (devid == 0x2929);
152 u8 sata_mode;
153
Arthur Heymans349e0852017-04-09 20:48:37 +0200154 printk(BIOS_DEBUG, "i82801jx_sata: initializing...\n");
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200155
156 if (config == NULL) {
Arthur Heymans349e0852017-04-09 20:48:37 +0200157 printk(BIOS_ERR, "i82801jx_sata: error: "
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200158 "device not in devicetree.cb!\n");
159 return;
160 }
161
162 if (get_option(&sata_mode, "sata_mode") != CB_SUCCESS)
163 /* Default to AHCI */
164 sata_mode = 0;
165
166 /*
167 * TODO: In contrast to ICH7 and PCH code we don't set
168 * timings, dma and IDE-I/O settings here. Looks like they
169 * became obsolete with the fading of real IDE ports.
170 * Maybe we can safely remove those settings from PCH code and
171 * even ICH7 code if it doesn't use the feature to combine the
172 * IDE and SATA controllers.
173 */
174
175 pci_write_config16(dev, PCI_COMMAND,
176 PCI_COMMAND_MASTER |
177 PCI_COMMAND_MEMORY | /* read-only in IDE modes */
178 PCI_COMMAND_IO);
179 if (sata_mode != 0)
180 /* No AHCI: clear AHCI base */
181 pci_write_config32(dev, PCI_BASE_ADDRESS_5, 0x00000000);
182
183 if (sata_mode == 0) {
184 printk(BIOS_DEBUG, "SATA controller in AHCI mode.\n");
185 } else {
186 printk(BIOS_DEBUG, "SATA controller in native mode.\n");
187
188 /* Enable native mode on both primary and secondary. */
189 pci_write_config8(dev, PCI_CLASS_PROG, 0x8f);
190 }
191
192 /* Looks like we should only enable decoding here. */
193 pci_write_config16(dev, D31F2_IDE_TIM_PRI, (1 << 15));
194 pci_write_config16(dev, D31F2_IDE_TIM_SEC, (1 << 15));
195
196 /* Port enable. For AHCI, it's managed in memory mapped space. */
197 reg16 = pci_read_config16(dev, 0x92);
198 reg16 &= ~0x3f;
199 reg16 |= (1 << 15) | ((sata_mode == 0) ? 0x3f : config->sata_port_map);
200 pci_write_config16(dev, 0x92, reg16);
201
202 /* SATA clock settings */
203 u32 sclkcg = 0;
204 if (config->sata_clock_request &&
205 !(inb(DEFAULT_GPIOBASE + 0x30) & (1 << (35 - 32))))
206 sclkcg |= 1 << 30; /* Enable SATA clock request. */
207 /* Disable unused ports. */
208 sclkcg |= ((~config->sata_port_map) & 0x3f) << 24;
209 /* Must be programmed. */
210 sclkcg |= 0x193;
211 pci_write_config32(dev, 0x94, sclkcg);
212
213 if (is_mobile && config->sata_traffic_monitor) {
Kyösti Mälkkic70eed12018-05-22 02:18:00 +0300214 struct device *const lpc_dev = pcidev_on_root(0x1f, 0);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200215 if (((pci_read_config8(lpc_dev, D31F0_CxSTATE_CNF)
216 >> 3) & 3) == 3) {
217 u8 reg8 = pci_read_config8(dev, 0x9c);
218 reg8 &= ~(0x1f << 2);
219 reg8 |= 3 << 2;
220 pci_write_config8(dev, 0x9c, reg8);
221 }
222 }
223
224 if (sata_mode == 0)
225 sata_enable_ahci_mmap(dev, config->sata_port_map, is_mobile);
226
227 sata_program_indexed(dev, is_mobile);
228}
229
Elyes HAOUAS1a8c1df2018-05-13 13:36:44 +0200230static void sata_enable(struct device *dev)
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200231{
232 /* Get the chip configuration */
233 const config_t *const config = dev->chip_info;
234
235 u16 map = 0;
236 u8 sata_mode;
237
238 if (!config)
239 return;
240
241 if (get_option(&sata_mode, "sata_mode") != CB_SUCCESS)
242 /* Default to AHCI */
243 sata_mode = 0;
244
245 /*
246 * Set SATA controller mode early so the resource allocator can
247 * properly assign IO/Memory resources for the controller.
248 */
249 if (sata_mode == 0)
250 map = 0x0040 | 0x0020; /* SATA mode + all ports on D31:F2 */
251
252 map |= (config->sata_port_map ^ 0x3f) << 8;
253
254 pci_write_config16(dev, 0x90, map);
255}
256
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200257static struct pci_operations sata_pci_ops = {
Subrata Banik4a0f0712019-03-20 14:29:47 +0530258 .set_subsystem = pci_dev_set_subsystem,
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200259};
260
261static struct device_operations sata_ops = {
262 .read_resources = pci_dev_read_resources,
263 .set_resources = pci_dev_set_resources,
264 .enable_resources = pci_dev_enable_resources,
265 .init = sata_init,
266 .enable = sata_enable,
267 .scan_bus = 0,
268 .ops_pci = &sata_pci_ops,
269};
270
271static const unsigned short pci_device_ids[] = {
Arthur Heymans349e0852017-04-09 20:48:37 +0200272 0x3a00,
273 0x3a02,
274 0x3a05,
275 0x3a06,
276 0x3a20,
277 0x3a22,
278 0x3a25,
279 0x3a26,
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200280 0,
281};
282
283static const struct pci_driver pch_sata __pci_driver = {
284 .ops = &sata_ops,
285 .vendor = PCI_VENDOR_ID_INTEL,
286 .devices = pci_device_ids,
287};