]>
Commit | Line | Data |
---|---|---|
3ac83935 SG |
1 | /* |
2 | * From Coreboot | |
3 | * Copyright (C) 2008-2009 coresystems GmbH | |
4 | * | |
5 | * SPDX-License-Identifier: GPL-2.0 | |
6 | */ | |
7 | ||
8 | #include <common.h> | |
9 | #include <fdtdec.h> | |
10 | #include <asm/io.h> | |
11 | #include <asm/pci.h> | |
12 | #include <asm/arch/pch.h> | |
13 | #include <asm/arch/bd82x6x.h> | |
14 | ||
15 | static inline u32 sir_read(pci_dev_t dev, int idx) | |
16 | { | |
31f57c28 SG |
17 | x86_pci_write_config32(dev, SATA_SIRI, idx); |
18 | return x86_pci_read_config32(dev, SATA_SIRD); | |
3ac83935 SG |
19 | } |
20 | ||
21 | static inline void sir_write(pci_dev_t dev, int idx, u32 value) | |
22 | { | |
31f57c28 SG |
23 | x86_pci_write_config32(dev, SATA_SIRI, idx); |
24 | x86_pci_write_config32(dev, SATA_SIRD, value); | |
3ac83935 SG |
25 | } |
26 | ||
27 | static void common_sata_init(pci_dev_t dev, unsigned int port_map) | |
28 | { | |
29 | u32 reg32; | |
30 | u16 reg16; | |
31 | ||
32 | /* Set IDE I/O Configuration */ | |
33 | reg32 = SIG_MODE_PRI_NORMAL | FAST_PCB1 | FAST_PCB0 | PCB1 | PCB0; | |
31f57c28 | 34 | x86_pci_write_config32(dev, IDE_CONFIG, reg32); |
3ac83935 SG |
35 | |
36 | /* Port enable */ | |
31f57c28 | 37 | reg16 = x86_pci_read_config16(dev, 0x92); |
3ac83935 SG |
38 | reg16 &= ~0x3f; |
39 | reg16 |= port_map; | |
31f57c28 | 40 | x86_pci_write_config16(dev, 0x92, reg16); |
3ac83935 SG |
41 | |
42 | /* SATA Initialization register */ | |
43 | port_map &= 0xff; | |
31f57c28 | 44 | x86_pci_write_config32(dev, 0x94, ((port_map ^ 0x3f) << 24) | 0x183); |
3ac83935 SG |
45 | } |
46 | ||
47 | void bd82x6x_sata_init(pci_dev_t dev, const void *blob, int node) | |
48 | { | |
49 | unsigned int port_map, speed_support, port_tx; | |
50 | struct pci_controller *hose = pci_bus_to_hose(0); | |
51 | const char *mode; | |
52 | u32 reg32; | |
53 | u16 reg16; | |
54 | ||
55 | debug("SATA: Initializing...\n"); | |
56 | ||
57 | /* SATA configuration */ | |
58 | port_map = fdtdec_get_int(blob, node, "intel,sata-port-map", 0); | |
59 | speed_support = fdtdec_get_int(blob, node, | |
60 | "sata_interface_speed_support", 0); | |
61 | ||
62 | /* Enable BARs */ | |
31f57c28 | 63 | x86_pci_write_config16(dev, PCI_COMMAND, 0x0007); |
3ac83935 SG |
64 | |
65 | mode = fdt_getprop(blob, node, "intel,sata-mode", NULL); | |
66 | if (!mode || !strcmp(mode, "ahci")) { | |
67 | u32 abar; | |
68 | ||
69 | debug("SATA: Controller in AHCI mode\n"); | |
70 | ||
71 | /* Set Interrupt Line, Interrupt Pin is set by D31IP.PIP */ | |
31f57c28 | 72 | x86_pci_write_config8(dev, INTR_LN, 0x0a); |
3ac83935 SG |
73 | |
74 | /* Set timings */ | |
31f57c28 | 75 | x86_pci_write_config16(dev, IDE_TIM_PRI, IDE_DECODE_ENABLE | |
3ac83935 SG |
76 | IDE_ISP_3_CLOCKS | IDE_RCT_1_CLOCKS | |
77 | IDE_PPE0 | IDE_IE0 | IDE_TIME0); | |
31f57c28 | 78 | x86_pci_write_config16(dev, IDE_TIM_SEC, IDE_DECODE_ENABLE | |
3ac83935 SG |
79 | IDE_ISP_5_CLOCKS | IDE_RCT_4_CLOCKS); |
80 | ||
81 | /* Sync DMA */ | |
31f57c28 SG |
82 | x86_pci_write_config16(dev, IDE_SDMA_CNT, IDE_PSDE0); |
83 | x86_pci_write_config16(dev, IDE_SDMA_TIM, 0x0001); | |
3ac83935 SG |
84 | |
85 | common_sata_init(dev, 0x8000 | port_map); | |
86 | ||
87 | /* Initialize AHCI memory-mapped space */ | |
88 | abar = pci_read_bar32(hose, dev, 5); | |
89 | debug("ABAR: %08X\n", abar); | |
90 | /* CAP (HBA Capabilities) : enable power management */ | |
91 | reg32 = readl(abar + 0x00); | |
92 | reg32 |= 0x0c006000; /* set PSC+SSC+SALP+SSS */ | |
93 | reg32 &= ~0x00020060; /* clear SXS+EMS+PMS */ | |
94 | /* Set ISS, if available */ | |
95 | if (speed_support) { | |
96 | reg32 &= ~0x00f00000; | |
97 | reg32 |= (speed_support & 0x03) << 20; | |
98 | } | |
99 | writel(reg32, abar + 0x00); | |
100 | /* PI (Ports implemented) */ | |
101 | writel(port_map, abar + 0x0c); | |
102 | (void) readl(abar + 0x0c); /* Read back 1 */ | |
103 | (void) readl(abar + 0x0c); /* Read back 2 */ | |
104 | /* CAP2 (HBA Capabilities Extended)*/ | |
105 | reg32 = readl(abar + 0x24); | |
106 | reg32 &= ~0x00000002; | |
107 | writel(reg32, abar + 0x24); | |
108 | /* VSP (Vendor Specific Register */ | |
109 | reg32 = readl(abar + 0xa0); | |
110 | reg32 &= ~0x00000005; | |
111 | writel(reg32, abar + 0xa0); | |
112 | } else if (!strcmp(mode, "combined")) { | |
113 | debug("SATA: Controller in combined mode\n"); | |
114 | ||
115 | /* No AHCI: clear AHCI base */ | |
116 | pci_write_bar32(hose, dev, 5, 0x00000000); | |
117 | /* And without AHCI BAR no memory decoding */ | |
31f57c28 | 118 | reg16 = x86_pci_read_config16(dev, PCI_COMMAND); |
3ac83935 | 119 | reg16 &= ~PCI_COMMAND_MEMORY; |
31f57c28 | 120 | x86_pci_write_config16(dev, PCI_COMMAND, reg16); |
3ac83935 | 121 | |
31f57c28 | 122 | x86_pci_write_config8(dev, 0x09, 0x80); |
3ac83935 SG |
123 | |
124 | /* Set timings */ | |
31f57c28 | 125 | x86_pci_write_config16(dev, IDE_TIM_PRI, IDE_DECODE_ENABLE | |
3ac83935 | 126 | IDE_ISP_5_CLOCKS | IDE_RCT_4_CLOCKS); |
31f57c28 | 127 | x86_pci_write_config16(dev, IDE_TIM_SEC, IDE_DECODE_ENABLE | |
3ac83935 SG |
128 | IDE_ISP_3_CLOCKS | IDE_RCT_1_CLOCKS | |
129 | IDE_PPE0 | IDE_IE0 | IDE_TIME0); | |
130 | ||
131 | /* Sync DMA */ | |
31f57c28 SG |
132 | x86_pci_write_config16(dev, IDE_SDMA_CNT, IDE_SSDE0); |
133 | x86_pci_write_config16(dev, IDE_SDMA_TIM, 0x0200); | |
3ac83935 SG |
134 | |
135 | common_sata_init(dev, port_map); | |
136 | } else { | |
137 | debug("SATA: Controller in plain-ide mode\n"); | |
138 | ||
139 | /* No AHCI: clear AHCI base */ | |
140 | pci_write_bar32(hose, dev, 5, 0x00000000); | |
141 | ||
142 | /* And without AHCI BAR no memory decoding */ | |
31f57c28 | 143 | reg16 = x86_pci_read_config16(dev, PCI_COMMAND); |
3ac83935 | 144 | reg16 &= ~PCI_COMMAND_MEMORY; |
31f57c28 | 145 | x86_pci_write_config16(dev, PCI_COMMAND, reg16); |
3ac83935 SG |
146 | |
147 | /* | |
148 | * Native mode capable on both primary and secondary (0xa) | |
149 | * OR'ed with enabled (0x50) = 0xf | |
150 | */ | |
31f57c28 | 151 | x86_pci_write_config8(dev, 0x09, 0x8f); |
3ac83935 SG |
152 | |
153 | /* Set Interrupt Line */ | |
154 | /* Interrupt Pin is set by D31IP.PIP */ | |
31f57c28 | 155 | x86_pci_write_config8(dev, INTR_LN, 0xff); |
3ac83935 SG |
156 | |
157 | /* Set timings */ | |
31f57c28 | 158 | x86_pci_write_config16(dev, IDE_TIM_PRI, IDE_DECODE_ENABLE | |
3ac83935 SG |
159 | IDE_ISP_3_CLOCKS | IDE_RCT_1_CLOCKS | |
160 | IDE_PPE0 | IDE_IE0 | IDE_TIME0); | |
31f57c28 | 161 | x86_pci_write_config16(dev, IDE_TIM_SEC, IDE_DECODE_ENABLE | |
3ac83935 SG |
162 | IDE_SITRE | IDE_ISP_3_CLOCKS | |
163 | IDE_RCT_1_CLOCKS | IDE_IE0 | IDE_TIME0); | |
164 | ||
165 | /* Sync DMA */ | |
31f57c28 SG |
166 | x86_pci_write_config16(dev, IDE_SDMA_CNT, |
167 | IDE_SSDE0 | IDE_PSDE0); | |
168 | x86_pci_write_config16(dev, IDE_SDMA_TIM, 0x0201); | |
3ac83935 SG |
169 | |
170 | common_sata_init(dev, port_map); | |
171 | } | |
172 | ||
173 | /* Set Gen3 Transmitter settings if needed */ | |
174 | port_tx = fdtdec_get_int(blob, node, "intel,sata-port0-gen3-tx", 0); | |
175 | if (port_tx) | |
176 | pch_iobp_update(SATA_IOBP_SP0G3IR, 0, port_tx); | |
177 | ||
178 | port_tx = fdtdec_get_int(blob, node, "intel,sata-port1-gen3-tx", 0); | |
179 | if (port_tx) | |
180 | pch_iobp_update(SATA_IOBP_SP1G3IR, 0, port_tx); | |
181 | ||
182 | /* Additional Programming Requirements */ | |
183 | sir_write(dev, 0x04, 0x00001600); | |
184 | sir_write(dev, 0x28, 0xa0000033); | |
185 | reg32 = sir_read(dev, 0x54); | |
186 | reg32 &= 0xff000000; | |
187 | reg32 |= 0x5555aa; | |
188 | sir_write(dev, 0x54, reg32); | |
189 | sir_write(dev, 0x64, 0xcccc8484); | |
190 | reg32 = sir_read(dev, 0x68); | |
191 | reg32 &= 0xffff0000; | |
192 | reg32 |= 0xcccc; | |
193 | sir_write(dev, 0x68, reg32); | |
194 | reg32 = sir_read(dev, 0x78); | |
195 | reg32 &= 0x0000ffff; | |
196 | reg32 |= 0x88880000; | |
197 | sir_write(dev, 0x78, reg32); | |
198 | sir_write(dev, 0x84, 0x001c7000); | |
199 | sir_write(dev, 0x88, 0x88338822); | |
200 | sir_write(dev, 0xa0, 0x001c7000); | |
201 | sir_write(dev, 0xc4, 0x0c0c0c0c); | |
202 | sir_write(dev, 0xc8, 0x0c0c0c0c); | |
203 | sir_write(dev, 0xd4, 0x10000000); | |
204 | ||
205 | pch_iobp_update(0xea004001, 0x3fffffff, 0xc0000000); | |
206 | pch_iobp_update(0xea00408a, 0xfffffcff, 0x00000100); | |
207 | } | |
208 | ||
209 | void bd82x6x_sata_enable(pci_dev_t dev, const void *blob, int node) | |
210 | { | |
211 | unsigned port_map; | |
212 | const char *mode; | |
213 | u16 map = 0; | |
214 | ||
215 | /* | |
216 | * Set SATA controller mode early so the resource allocator can | |
217 | * properly assign IO/Memory resources for the controller. | |
218 | */ | |
219 | mode = fdt_getprop(blob, node, "intel,sata-mode", NULL); | |
220 | if (mode && !strcmp(mode, "ahci")) | |
221 | map = 0x0060; | |
222 | port_map = fdtdec_get_int(blob, node, "intel,sata-port-map", 0); | |
223 | ||
224 | map |= (port_map ^ 0x3f) << 8; | |
31f57c28 | 225 | x86_pci_write_config16(dev, 0x90, map); |
3ac83935 | 226 | } |