blob: 33a048d9cf9e3156265d6714d8e283d949da484a [file] [log] [blame]
Angel Pons182dbde2020-04-02 23:49:05 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Aaron Durbin76c37002012-10-30 09:03:43 -05002
Kyösti Mälkki13f66502019-03-03 08:01:05 +02003#include <device/mmio.h>
Kyösti Mälkkif1b58b72019-03-01 13:43:02 +02004#include <device/pci_ops.h>
Aaron Durbin76c37002012-10-30 09:03:43 -05005#include <console/console.h>
6#include <device/device.h>
7#include <device/pci.h>
8#include <device/pci_ids.h>
Duncan Laurie26e7dd72012-12-19 09:12:31 -08009#include <delay.h>
Kyösti Mälkki12b121c2019-08-18 16:33:39 +030010#include "chip.h"
Angel Pons2178b722020-05-31 00:55:35 +020011#include "iobp.h"
Aaron Durbin76c37002012-10-30 09:03:43 -050012#include "pch.h"
13
Angel Ponsbe6ad1a2020-10-30 13:55:23 +010014#if CONFIG(INTEL_LYNXPOINT_LP)
15#define SATA_PORT_MASK 0x0f
16#else
17#define SATA_PORT_MASK 0x3f
18#endif
19
Aaron Durbin76c37002012-10-30 09:03:43 -050020typedef struct southbridge_intel_lynxpoint_config config_t;
21
22static inline u32 sir_read(struct device *dev, int idx)
23{
24 pci_write_config32(dev, SATA_SIRI, idx);
25 return pci_read_config32(dev, SATA_SIRD);
26}
27
28static inline void sir_write(struct device *dev, int idx, u32 value)
29{
30 pci_write_config32(dev, SATA_SIRI, idx);
31 pci_write_config32(dev, SATA_SIRD, value);
32}
33
Angel Ponsd00af4f2020-10-30 12:56:02 +010034static inline void sir_unset_and_set_mask(struct device *dev, int idx, u32 unset, u32 set)
35{
36 pci_write_config32(dev, SATA_SIRI, idx);
37
38 const u32 value = pci_read_config32(dev, SATA_SIRD) & ~unset;
39 pci_write_config32(dev, SATA_SIRD, value | set);
40}
41
Aaron Durbin76c37002012-10-30 09:03:43 -050042static void sata_init(struct device *dev)
43{
44 u32 reg32;
Angel Pons8084b382020-10-30 10:56:31 +010045
46 u32 *abar;
47
Aaron Durbin76c37002012-10-30 09:03:43 -050048 /* Get the chip configuration */
49 config_t *config = dev->chip_info;
50
51 printk(BIOS_DEBUG, "SATA: Initializing...\n");
52
53 if (config == NULL) {
54 printk(BIOS_ERR, "SATA: ERROR: Device not in devicetree.cb!\n");
55 return;
56 }
57
58 /* SATA configuration */
59
Angel Pons1b856922020-10-30 15:30:48 +010060 /* Enable memory space decoding for ABAR */
61 pci_or_config16(dev, PCI_COMMAND, PCI_COMMAND_MEMORY | PCI_COMMAND_IO);
Aaron Durbin76c37002012-10-30 09:03:43 -050062
Angel Pons8084b382020-10-30 10:56:31 +010063 printk(BIOS_DEBUG, "SATA: Controller in AHCI mode.\n");
Aaron Durbin76c37002012-10-30 09:03:43 -050064
Angel Pons8084b382020-10-30 10:56:31 +010065 /* Set Interrupt Line */
66 /* Interrupt Pin is set by D31IP.PIP */
Angel Pons93859e32020-11-02 12:08:50 +010067 pci_write_config8(dev, PCI_INTERRUPT_LINE, 0x0a);
Angel Ponsbf9bc502020-06-08 00:12:43 +020068
Angel Pons93859e32020-11-02 12:08:50 +010069 pci_write_config16(dev, IDE_TIM_PRI, IDE_DECODE_ENABLE);
70 pci_write_config16(dev, IDE_TIM_SEC, IDE_DECODE_ENABLE);
Aaron Durbin76c37002012-10-30 09:03:43 -050071
Angel Pons8084b382020-10-30 10:56:31 +010072 /* for AHCI, Port Enable is managed in memory mapped space */
Angel Ponsbe6ad1a2020-10-30 13:55:23 +010073 pci_update_config16(dev, 0x92, ~SATA_PORT_MASK, 0x8000 | config->sata_port_map);
Angel Pons8084b382020-10-30 10:56:31 +010074 udelay(2);
Aaron Durbin76c37002012-10-30 09:03:43 -050075
Angel Pons8084b382020-10-30 10:56:31 +010076 /* Setup register 98h */
77 reg32 = pci_read_config16(dev, 0x98);
78 reg32 |= 1 << 19; /* BWG step 6 */
79 reg32 |= 1 << 22; /* BWG step 5 */
80 reg32 &= ~(0x3f << 7);
81 reg32 |= 0x04 << 7; /* BWG step 7 */
82 reg32 |= 1 << 20; /* BWG step 8 */
83 reg32 &= ~(0x03 << 5);
84 reg32 |= 1 << 5; /* BWG step 9 */
85 reg32 |= 1 << 18; /* BWG step 10 */
86 reg32 |= 1 << 29; /* BWG step 11 */
87 if (pch_is_lp()) {
88 reg32 &= ~((1 << 31) | (1 << 30));
89 reg32 |= 1 << 23;
90 reg32 |= 1 << 24; /* Disable listen mode (hotplug) */
Aaron Durbin76c37002012-10-30 09:03:43 -050091 }
Angel Pons8084b382020-10-30 10:56:31 +010092 pci_write_config32(dev, 0x98, reg32);
93
94 /* Setup register 9Ch: Disable alternate ID and BWG step 12 */
95 pci_write_config16(dev, 0x9c, 1 << 5);
96
97 /* SATA Initialization register */
98 reg32 = 0x183;
Angel Ponsbe6ad1a2020-10-30 13:55:23 +010099 reg32 |= (config->sata_port_map ^ SATA_PORT_MASK) << 24;
Angel Pons8084b382020-10-30 10:56:31 +0100100 reg32 |= (config->sata_devslp_mux & 1) << 15;
101 pci_write_config32(dev, 0x94, reg32);
102
103 /* Initialize AHCI memory-mapped space */
104 abar = (u32 *)pci_read_config32(dev, PCI_BASE_ADDRESS_5);
105 printk(BIOS_DEBUG, "ABAR: %p\n", abar);
106 /* CAP (HBA Capabilities) : enable power management */
107 reg32 = read32(abar + 0x00);
108 reg32 |= 0x0c006000; // set PSC+SSC+SALP+SSS
109 reg32 &= ~0x00020060; // clear SXS+EMS+PMS
110 if (pch_is_lp())
111 reg32 |= (1 << 18); // SAM: SATA AHCI MODE ONLY
112 write32(abar + 0x00, reg32);
113 /* PI (Ports implemented) */
114 write32(abar + 0x03, config->sata_port_map);
115 (void)read32(abar + 0x03); /* Read back 1 */
116 (void)read32(abar + 0x03); /* Read back 2 */
117 /* CAP2 (HBA Capabilities Extended)*/
118 reg32 = read32(abar + 0x09);
119 /* Enable DEVSLP */
120 if (pch_is_lp()) {
121 if (config->sata_devslp_disable)
122 reg32 &= ~(1 << 3);
123 else
124 reg32 |= (1 << 5)|(1 << 4)|(1 << 3)|(1 << 2);
125 } else {
126 reg32 &= ~0x00000002;
127 }
128 write32(abar + 0x09, reg32);
Aaron Durbin76c37002012-10-30 09:03:43 -0500129
130 /* Set Gen3 Transmitter settings if needed */
131 if (config->sata_port0_gen3_tx)
132 pch_iobp_update(SATA_IOBP_SP0G3IR, 0,
133 config->sata_port0_gen3_tx);
134
135 if (config->sata_port1_gen3_tx)
136 pch_iobp_update(SATA_IOBP_SP1G3IR, 0,
137 config->sata_port1_gen3_tx);
138
Shawn Nematbakhsh28752272013-08-13 10:45:21 -0700139 /* Set Gen3 DTLE DATA / EDGE registers if needed */
140 if (config->sata_port0_gen3_dtle) {
141 pch_iobp_update(SATA_IOBP_SP0DTLE_DATA,
142 ~(SATA_DTLE_MASK << SATA_DTLE_DATA_SHIFT),
143 (config->sata_port0_gen3_dtle & SATA_DTLE_MASK)
144 << SATA_DTLE_DATA_SHIFT);
145
146 pch_iobp_update(SATA_IOBP_SP0DTLE_EDGE,
147 ~(SATA_DTLE_MASK << SATA_DTLE_EDGE_SHIFT),
148 (config->sata_port0_gen3_dtle & SATA_DTLE_MASK)
149 << SATA_DTLE_EDGE_SHIFT);
150 }
151
152 if (config->sata_port1_gen3_dtle) {
153 pch_iobp_update(SATA_IOBP_SP1DTLE_DATA,
154 ~(SATA_DTLE_MASK << SATA_DTLE_DATA_SHIFT),
155 (config->sata_port1_gen3_dtle & SATA_DTLE_MASK)
156 << SATA_DTLE_DATA_SHIFT);
157
158 pch_iobp_update(SATA_IOBP_SP1DTLE_EDGE,
159 ~(SATA_DTLE_MASK << SATA_DTLE_EDGE_SHIFT),
160 (config->sata_port1_gen3_dtle & SATA_DTLE_MASK)
161 << SATA_DTLE_EDGE_SHIFT);
162 }
163
Aaron Durbin76c37002012-10-30 09:03:43 -0500164 /* Additional Programming Requirements */
Duncan Laurie74c0d052012-12-17 11:31:40 -0800165 /* Power Optimizer */
Duncan Laurie74c0d052012-12-17 11:31:40 -0800166
Duncan Laurie26e7dd72012-12-19 09:12:31 -0800167 /* Step 1 */
Duncan Laurie70f04b42013-03-08 17:17:33 -0800168 if (pch_is_lp())
169 sir_write(dev, 0x64, 0x883c9003);
170 else
171 sir_write(dev, 0x64, 0x883c9001);
Duncan Laurie26e7dd72012-12-19 09:12:31 -0800172
173 /* Step 2: SIR 68h[15:0] = 880Ah */
Angel Ponsd00af4f2020-10-30 12:56:02 +0100174 sir_unset_and_set_mask(dev, 0x68, 0xffff, 0x880a);
Aaron Durbin76c37002012-10-30 09:03:43 -0500175
Duncan Laurie26e7dd72012-12-19 09:12:31 -0800176 /* Step 3: SIR 60h[3] = 1 */
Angel Ponsd00af4f2020-10-30 12:56:02 +0100177 sir_unset_and_set_mask(dev, 0x60, 0, 1 << 3);
Duncan Laurie26e7dd72012-12-19 09:12:31 -0800178
179 /* Step 4: SIR 60h[0] = 1 */
Angel Ponsd00af4f2020-10-30 12:56:02 +0100180 sir_unset_and_set_mask(dev, 0x60, 0, 1 << 0);
Duncan Laurie26e7dd72012-12-19 09:12:31 -0800181
182 /* Step 5: SIR 60h[1] = 1 */
Angel Ponsd00af4f2020-10-30 12:56:02 +0100183 sir_unset_and_set_mask(dev, 0x60, 0, 1 << 1);
Duncan Laurie74c0d052012-12-17 11:31:40 -0800184
185 /* Clock Gating */
186 sir_write(dev, 0x70, 0x3f00bf1f);
Duncan Laurie70f04b42013-03-08 17:17:33 -0800187 if (pch_is_lp()) {
188 sir_write(dev, 0x54, 0xcf000f0f);
189 sir_write(dev, 0x58, 0x00190000);
190 }
Duncan Laurie74c0d052012-12-17 11:31:40 -0800191
192 reg32 = pci_read_config32(dev, 0x300);
193 reg32 |= (1 << 17) | (1 << 16);
Angel Pons8963f7d2020-10-24 12:20:28 +0200194 reg32 |= (1 << 31) | (1 << 30) | (1 << 29);
Duncan Laurie74c0d052012-12-17 11:31:40 -0800195 pci_write_config32(dev, 0x300, reg32);
Aaron Durbin76c37002012-10-30 09:03:43 -0500196}
197
Elyes HAOUAS7a5f7712018-06-08 17:20:38 +0200198static void sata_enable(struct device *dev)
Aaron Durbin76c37002012-10-30 09:03:43 -0500199{
200 /* Get the chip configuration */
201 config_t *config = dev->chip_info;
Aaron Durbin76c37002012-10-30 09:03:43 -0500202
203 if (!config)
204 return;
205
206 /*
207 * Set SATA controller mode early so the resource allocator can
208 * properly assign IO/Memory resources for the controller.
209 */
Angel Ponsbe6ad1a2020-10-30 13:55:23 +0100210 pci_write_config16(dev, 0x90, 0x0060 | (config->sata_port_map ^ SATA_PORT_MASK) << 8);
Aaron Durbin76c37002012-10-30 09:03:43 -0500211}
212
Aaron Durbin76c37002012-10-30 09:03:43 -0500213static struct device_operations sata_ops = {
214 .read_resources = pci_dev_read_resources,
215 .set_resources = pci_dev_set_resources,
216 .enable_resources = pci_dev_enable_resources,
217 .init = sata_init,
218 .enable = sata_enable,
Angel Pons1fc0edd2020-05-31 00:03:28 +0200219 .ops_pci = &pci_dev_ops_pci,
Aaron Durbin76c37002012-10-30 09:03:43 -0500220};
221
Duncan Laurie74c0d052012-12-17 11:31:40 -0800222static const unsigned short pci_device_ids[] = {
Felix Singer4ea08f92020-11-20 12:56:44 +0000223 PCI_DEVICE_ID_INTEL_LPT_H_DESKTOP_SATA_IDE,
224 PCI_DEVICE_ID_INTEL_LPT_H_DESKTOP_SATA_AHCI,
225 PCI_DEVICE_ID_INTEL_LPT_H_DESKTOP_SATA_RAID_1,
226 PCI_DEVICE_ID_INTEL_LPT_H_DESKTOP_SATA_RAID_PREM,
227 PCI_DEVICE_ID_INTEL_LPT_H_DESKTOP_SATA_IDE_P45,
228 PCI_DEVICE_ID_INTEL_LPT_H_DESKTOP_SATA_RAID_2,
229 PCI_DEVICE_ID_INTEL_LPT_H_MOBILE_SATA_IDE,
230 PCI_DEVICE_ID_INTEL_LPT_H_MOBILE_SATA_AHCI,
231 PCI_DEVICE_ID_INTEL_LPT_H_MOBILE_SATA_RAID_1,
232 PCI_DEVICE_ID_INTEL_LPT_H_MOBILE_SATA_RAID_PREM,
233 PCI_DEVICE_ID_INTEL_LPT_H_MOBILE_SATA_IDE_P45,
234 PCI_DEVICE_ID_INTEL_LPT_H_MOBILE_SATA_RAID_2,
235 PCI_DEVICE_ID_INTEL_LPT_LP_SATA_AHCI,
236 PCI_DEVICE_ID_INTEL_LPT_LP_SATA_RAID_1,
237 PCI_DEVICE_ID_INTEL_LPT_LP_SATA_RAID_PREM,
238 PCI_DEVICE_ID_INTEL_LPT_LP_SATA_RAID_2,
Duncan Laurie74c0d052012-12-17 11:31:40 -0800239 0
240};
Aaron Durbin76c37002012-10-30 09:03:43 -0500241
242static const struct pci_driver pch_sata __pci_driver = {
243 .ops = &sata_ops,
244 .vendor = PCI_VENDOR_ID_INTEL,
245 .devices = pci_device_ids,
246};