blob: b4c707d3ecee92aead311b99bc6bc4b50d3dcc10 [file] [log] [blame]
Angel Pons80d92382020-04-05 15:47:00 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Mariusz Szafranskia4041332017-08-02 17:28:17 +02002
3#include <stdint.h>
Kyösti Mälkki13f66502019-03-03 08:01:05 +02004#include <device/mmio.h>
Kyösti Mälkkif1b58b72019-03-01 13:43:02 +02005#include <device/pci_ops.h>
Mariusz Szafranskia4041332017-08-02 17:28:17 +02006#include <device/pci.h>
7#include <device/pci_def.h>
8#include <device/device.h>
Elyes HAOUASa1e22b82019-03-18 22:49:36 +01009#include <string.h>
Mariusz Szafranskia4041332017-08-02 17:28:17 +020010#include <soc/iomap.h>
11#include <soc/soc_util.h>
12#include <soc/pmc.h>
13#include <soc/smbus.h>
14#include <soc/lpc.h>
15#include <soc/pci_devs.h>
16#include <soc/systemagent.h>
17
Elyes HAOUAS6f01f432018-12-05 10:56:30 +010018#ifdef __SIMPLE_DEVICE__
19pci_devfn_t get_hostbridge_dev(void)
Mariusz Szafranskia4041332017-08-02 17:28:17 +020020{
Mariusz Szafranskia4041332017-08-02 17:28:17 +020021 return PCI_DEV(0, SA_DEV, SA_FUNC);
Elyes HAOUAS6f01f432018-12-05 10:56:30 +010022}
Mariusz Szafranskia4041332017-08-02 17:28:17 +020023#else
Elyes HAOUAS6f01f432018-12-05 10:56:30 +010024struct device *get_hostbridge_dev(void)
25{
Kyösti Mälkki903b40a2019-07-03 07:25:59 +030026 return pcidev_on_root(SA_DEV, SA_FUNC);
Mariusz Szafranskia4041332017-08-02 17:28:17 +020027}
Elyes HAOUAS6f01f432018-12-05 10:56:30 +010028#endif
Mariusz Szafranskia4041332017-08-02 17:28:17 +020029
Elyes HAOUAS6f01f432018-12-05 10:56:30 +010030#ifdef __SIMPLE_DEVICE__
31pci_devfn_t get_lpc_dev(void)
Mariusz Szafranskia4041332017-08-02 17:28:17 +020032{
Mariusz Szafranskia4041332017-08-02 17:28:17 +020033 return PCI_DEV(0, LPC_DEV, LPC_FUNC);
Elyes HAOUAS6f01f432018-12-05 10:56:30 +010034}
Mariusz Szafranskia4041332017-08-02 17:28:17 +020035#else
Elyes HAOUAS6f01f432018-12-05 10:56:30 +010036struct device *get_lpc_dev(void)
37{
Kyösti Mälkki903b40a2019-07-03 07:25:59 +030038 return pcidev_on_root(LPC_DEV, LPC_FUNC);
Mariusz Szafranskia4041332017-08-02 17:28:17 +020039}
Elyes HAOUAS6f01f432018-12-05 10:56:30 +010040#endif
Mariusz Szafranskia4041332017-08-02 17:28:17 +020041
Elyes HAOUAS6f01f432018-12-05 10:56:30 +010042#ifdef __SIMPLE_DEVICE__
43pci_devfn_t get_pmc_dev(void)
Mariusz Szafranskia4041332017-08-02 17:28:17 +020044{
Mariusz Szafranskia4041332017-08-02 17:28:17 +020045 return PCI_DEV(0, PMC_DEV, PMC_FUNC);
Mariusz Szafranskia4041332017-08-02 17:28:17 +020046}
Elyes HAOUAS6f01f432018-12-05 10:56:30 +010047#else
48struct device *get_pmc_dev(void)
Mariusz Szafranskia4041332017-08-02 17:28:17 +020049{
Kyösti Mälkki903b40a2019-07-03 07:25:59 +030050 return pcidev_on_root(PMC_DEV, PMC_FUNC);
Mariusz Szafranskia4041332017-08-02 17:28:17 +020051}
Elyes HAOUAS6f01f432018-12-05 10:56:30 +010052#endif
53
54#ifdef __SIMPLE_DEVICE__
55pci_devfn_t get_smbus_dev(void)
56{
57 return PCI_DEV(0, SMBUS_DEV, SMBUS_FUNC);
58}
59#else
60struct device *get_smbus_dev(void)
61{
Kyösti Mälkki903b40a2019-07-03 07:25:59 +030062 return pcidev_on_root(SMBUS_DEV, SMBUS_FUNC);
Elyes HAOUAS6f01f432018-12-05 10:56:30 +010063}
64#endif
Mariusz Szafranskia4041332017-08-02 17:28:17 +020065
66uint32_t get_pciebase(void)
67{
Elyes HAOUAS6f01f432018-12-05 10:56:30 +010068#ifdef __SIMPLE_DEVICE__
69 pci_devfn_t dev;
70#else
71 struct device *dev;
72#endif
Mariusz Szafranskia4041332017-08-02 17:28:17 +020073 u32 pciexbar_reg;
74
75 dev = get_hostbridge_dev();
76 if (!dev)
77 return 0;
78
79 pciexbar_reg = pci_read_config32(dev, PCIEXBAR);
80
81 if (!(pciexbar_reg & (1 << 0)))
82 return 0;
83
84 switch (pciexbar_reg & MASK_PCIEXBAR_LENGTH) {
85 case MASK_PCIEXBAR_LENGTH_256M:
86 pciexbar_reg &= MASK_PCIEXBAR_256M;
87 break;
88 case MASK_PCIEXBAR_LENGTH_128M:
89 pciexbar_reg &= MASK_PCIEXBAR_128M;
90 break;
91 case MASK_PCIEXBAR_LENGTH_64M:
92 pciexbar_reg &= MASK_PCIEXBAR_64M;
93 break;
94 default:
95 pciexbar_reg &= MASK_PCIEXBAR_256M;
96 break;
97 }
98
99 return pciexbar_reg;
100}
101
102uint32_t get_pcielength(void)
103{
Elyes HAOUAS6f01f432018-12-05 10:56:30 +0100104#ifdef __SIMPLE_DEVICE__
105 pci_devfn_t dev;
106#else
107 struct device *dev;
108#endif
Mariusz Szafranskia4041332017-08-02 17:28:17 +0200109 u32 pciexbar_reg;
110
111 dev = get_hostbridge_dev();
112 if (!dev)
113 return 0;
114
115 pciexbar_reg = pci_read_config32(dev, PCIEXBAR);
116
117 if (!(pciexbar_reg & (1 << 0)))
118 return 0;
119
120 switch (pciexbar_reg & MASK_PCIEXBAR_LENGTH) {
121 case MASK_PCIEXBAR_LENGTH_256M:
122 pciexbar_reg = 256;
123 break;
124 case MASK_PCIEXBAR_LENGTH_128M:
125 pciexbar_reg = 128;
126 break;
127 case MASK_PCIEXBAR_LENGTH_64M:
128 pciexbar_reg = 64;
129 break;
130 default:
131 pciexbar_reg = 64;
132 break;
133 }
134
135 return pciexbar_reg;
136}
137
138uint32_t get_tseg_memory(void)
139{
Elyes HAOUAS6f01f432018-12-05 10:56:30 +0100140#ifdef __SIMPLE_DEVICE__
141 pci_devfn_t dev;
142#else
143 struct device *dev;
144#endif
145 dev = get_hostbridge_dev();
Mariusz Szafranskia4041332017-08-02 17:28:17 +0200146
147 if (!dev)
148 return 0;
149
150 return pci_read_config32(dev, TSEGMB) & MASK_TSEGMB;
151}
152
153uint32_t get_top_of_low_memory(void)
154{
Elyes HAOUAS6f01f432018-12-05 10:56:30 +0100155#ifdef __SIMPLE_DEVICE__
156 pci_devfn_t dev;
157#else
158 struct device *dev;
159#endif
160 dev = get_hostbridge_dev();
Mariusz Szafranskia4041332017-08-02 17:28:17 +0200161
162 if (!dev)
163 return 0;
164
165 return pci_read_config32(dev, TOLUD) & MASK_TOLUD;
166}
167
168uint64_t get_top_of_upper_memory(void)
169{
Elyes HAOUAS6f01f432018-12-05 10:56:30 +0100170#ifdef __SIMPLE_DEVICE__
171 pci_devfn_t dev;
172#else
173 struct device *dev;
174#endif
175 dev = get_hostbridge_dev();
Mariusz Szafranskia4041332017-08-02 17:28:17 +0200176
177 if (!dev)
178 return 0;
179
180 return ((uint64_t)(pci_read_config32(dev, TOUUD_HI) & MASK_TOUUD_HI)
181 << 32) +
182 (uint64_t)(pci_read_config32(dev, TOUUD_LO) & MASK_TOUUD_LO);
183}
184
185uint16_t get_pmbase(void)
186{
Elyes HAOUAS6f01f432018-12-05 10:56:30 +0100187#ifdef __SIMPLE_DEVICE__
188 pci_devfn_t dev;
189#else
190 struct device *dev;
191#endif
192 dev = get_pmc_dev();
Mariusz Szafranskia4041332017-08-02 17:28:17 +0200193
194 if (!dev)
195 return 0;
196
197 return pci_read_config16(dev, PMC_ACPI_BASE) & 0xfff8;
198}
199
200uint16_t get_tcobase(void)
201{
Elyes HAOUAS6f01f432018-12-05 10:56:30 +0100202#ifdef __SIMPLE_DEVICE__
203 pci_devfn_t dev;
204#else
205 struct device *dev;
206#endif
207 dev = get_smbus_dev();
Mariusz Szafranskia4041332017-08-02 17:28:17 +0200208
209 if (!dev)
210 return 0;
211
212 return pci_read_config16(dev, TCOBASE) & MASK_TCOBASE;
213}
214
215void mmio_andthenor32(void *addr, uint32_t val2and, uint32_t val2or)
216{
217 uint32_t reg32;
218
219 reg32 = read32(addr);
220 reg32 &= (uint32_t)val2and;
221 reg32 |= (uint32_t)val2or;
222 write32(addr, reg32);
223}
224
225uint8_t silicon_stepping(void)
226{
227 uint8_t revision_id;
Elyes HAOUAS6f01f432018-12-05 10:56:30 +0100228#ifdef __SIMPLE_DEVICE__
229 pci_devfn_t dev;
230#else
231 struct device *dev;
232#endif
233 dev = get_lpc_dev();
Mariusz Szafranskia4041332017-08-02 17:28:17 +0200234
235 if (!dev)
236 return 0;
237
238 revision_id = pci_read_config8(dev, PCI_REVISION_ID);
239
240 return revision_id;
241}
242
243void *memcpy_s(void *dest, const void *src, size_t n)
244{
245 uint8_t *dp;
246 const uint8_t *sp;
247
248 dp = (uint8_t *)dest;
249 sp = (uint8_t *)src;
250
251 if (!n)
252 return dest;
253
254 if (n > UINT32_MAX)
255 return dest;
256
257 if (!dp)
258 return dest;
259
260 if (!sp)
261 return dest;
262
263 /*
264 * overlap is undefined behavior, do not allow
265 */
266 if (((dp > sp) && (dp < (sp + n))) || ((sp > dp) && (sp < (dp + n))))
267 return dest;
268
269 /*
270 * now perform the copy
271 */
272
273 /* Original memcpy() function */
274 unsigned long d0, d1, d2;
275
276 asm volatile(
Patrick Rudolphadcf7822020-08-27 20:50:18 +0200277#if ENV_X86_64
Mariusz Szafranskia4041332017-08-02 17:28:17 +0200278 "rep ; movsd\n\t"
279 "mov %4,%%rcx\n\t"
280#else
281 "rep ; movsl\n\t"
282 "movl %4,%%ecx\n\t"
283#endif
284 "rep ; movsb\n\t"
285 : "=&c"(d0), "=&D"(d1), "=&S"(d2)
286 : "0"(n >> 2), "g"(n & 3), "1"(dest), "2"(src)
287 : "memory");
288
289 return dest;
290}