blob: dbe924b40ee4c2a1c6af1efddddd1bdcfca2e11a [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>
Mariusz Szafranskia4041332017-08-02 17:28:17 +02007#include <device/device.h>
Elyes HAOUASa1e22b82019-03-18 22:49:36 +01008#include <string.h>
Mariusz Szafranskia4041332017-08-02 17:28:17 +02009#include <soc/iomap.h>
10#include <soc/soc_util.h>
11#include <soc/pmc.h>
12#include <soc/smbus.h>
13#include <soc/lpc.h>
14#include <soc/pci_devs.h>
15#include <soc/systemagent.h>
16
Elyes HAOUAS6f01f432018-12-05 10:56:30 +010017#ifdef __SIMPLE_DEVICE__
18pci_devfn_t get_hostbridge_dev(void)
Mariusz Szafranskia4041332017-08-02 17:28:17 +020019{
Mariusz Szafranskia4041332017-08-02 17:28:17 +020020 return PCI_DEV(0, SA_DEV, SA_FUNC);
Elyes HAOUAS6f01f432018-12-05 10:56:30 +010021}
Mariusz Szafranskia4041332017-08-02 17:28:17 +020022#else
Elyes HAOUAS6f01f432018-12-05 10:56:30 +010023struct device *get_hostbridge_dev(void)
24{
Kyösti Mälkki903b40a2019-07-03 07:25:59 +030025 return pcidev_on_root(SA_DEV, SA_FUNC);
Mariusz Szafranskia4041332017-08-02 17:28:17 +020026}
Elyes HAOUAS6f01f432018-12-05 10:56:30 +010027#endif
Mariusz Szafranskia4041332017-08-02 17:28:17 +020028
Elyes HAOUAS6f01f432018-12-05 10:56:30 +010029#ifdef __SIMPLE_DEVICE__
30pci_devfn_t get_lpc_dev(void)
Mariusz Szafranskia4041332017-08-02 17:28:17 +020031{
Mariusz Szafranskia4041332017-08-02 17:28:17 +020032 return PCI_DEV(0, LPC_DEV, LPC_FUNC);
Elyes HAOUAS6f01f432018-12-05 10:56:30 +010033}
Mariusz Szafranskia4041332017-08-02 17:28:17 +020034#else
Elyes HAOUAS6f01f432018-12-05 10:56:30 +010035struct device *get_lpc_dev(void)
36{
Kyösti Mälkki903b40a2019-07-03 07:25:59 +030037 return pcidev_on_root(LPC_DEV, LPC_FUNC);
Mariusz Szafranskia4041332017-08-02 17:28:17 +020038}
Elyes HAOUAS6f01f432018-12-05 10:56:30 +010039#endif
Mariusz Szafranskia4041332017-08-02 17:28:17 +020040
Elyes HAOUAS6f01f432018-12-05 10:56:30 +010041#ifdef __SIMPLE_DEVICE__
42pci_devfn_t get_pmc_dev(void)
Mariusz Szafranskia4041332017-08-02 17:28:17 +020043{
Mariusz Szafranskia4041332017-08-02 17:28:17 +020044 return PCI_DEV(0, PMC_DEV, PMC_FUNC);
Mariusz Szafranskia4041332017-08-02 17:28:17 +020045}
Elyes HAOUAS6f01f432018-12-05 10:56:30 +010046#else
47struct device *get_pmc_dev(void)
Mariusz Szafranskia4041332017-08-02 17:28:17 +020048{
Kyösti Mälkki903b40a2019-07-03 07:25:59 +030049 return pcidev_on_root(PMC_DEV, PMC_FUNC);
Mariusz Szafranskia4041332017-08-02 17:28:17 +020050}
Elyes HAOUAS6f01f432018-12-05 10:56:30 +010051#endif
52
53#ifdef __SIMPLE_DEVICE__
54pci_devfn_t get_smbus_dev(void)
55{
56 return PCI_DEV(0, SMBUS_DEV, SMBUS_FUNC);
57}
58#else
59struct device *get_smbus_dev(void)
60{
Kyösti Mälkki903b40a2019-07-03 07:25:59 +030061 return pcidev_on_root(SMBUS_DEV, SMBUS_FUNC);
Elyes HAOUAS6f01f432018-12-05 10:56:30 +010062}
63#endif
Mariusz Szafranskia4041332017-08-02 17:28:17 +020064
65uint32_t get_pciebase(void)
66{
Elyes HAOUAS6f01f432018-12-05 10:56:30 +010067#ifdef __SIMPLE_DEVICE__
68 pci_devfn_t dev;
69#else
70 struct device *dev;
71#endif
Mariusz Szafranskia4041332017-08-02 17:28:17 +020072 u32 pciexbar_reg;
73
74 dev = get_hostbridge_dev();
75 if (!dev)
76 return 0;
77
78 pciexbar_reg = pci_read_config32(dev, PCIEXBAR);
79
80 if (!(pciexbar_reg & (1 << 0)))
81 return 0;
82
83 switch (pciexbar_reg & MASK_PCIEXBAR_LENGTH) {
84 case MASK_PCIEXBAR_LENGTH_256M:
85 pciexbar_reg &= MASK_PCIEXBAR_256M;
86 break;
87 case MASK_PCIEXBAR_LENGTH_128M:
88 pciexbar_reg &= MASK_PCIEXBAR_128M;
89 break;
90 case MASK_PCIEXBAR_LENGTH_64M:
91 pciexbar_reg &= MASK_PCIEXBAR_64M;
92 break;
93 default:
94 pciexbar_reg &= MASK_PCIEXBAR_256M;
95 break;
96 }
97
98 return pciexbar_reg;
99}
100
101uint32_t get_pcielength(void)
102{
Elyes HAOUAS6f01f432018-12-05 10:56:30 +0100103#ifdef __SIMPLE_DEVICE__
104 pci_devfn_t dev;
105#else
106 struct device *dev;
107#endif
Mariusz Szafranskia4041332017-08-02 17:28:17 +0200108 u32 pciexbar_reg;
109
110 dev = get_hostbridge_dev();
111 if (!dev)
112 return 0;
113
114 pciexbar_reg = pci_read_config32(dev, PCIEXBAR);
115
116 if (!(pciexbar_reg & (1 << 0)))
117 return 0;
118
119 switch (pciexbar_reg & MASK_PCIEXBAR_LENGTH) {
120 case MASK_PCIEXBAR_LENGTH_256M:
121 pciexbar_reg = 256;
122 break;
123 case MASK_PCIEXBAR_LENGTH_128M:
124 pciexbar_reg = 128;
125 break;
126 case MASK_PCIEXBAR_LENGTH_64M:
127 pciexbar_reg = 64;
128 break;
129 default:
130 pciexbar_reg = 64;
131 break;
132 }
133
134 return pciexbar_reg;
135}
136
137uint32_t get_tseg_memory(void)
138{
Elyes HAOUAS6f01f432018-12-05 10:56:30 +0100139#ifdef __SIMPLE_DEVICE__
140 pci_devfn_t dev;
141#else
142 struct device *dev;
143#endif
144 dev = get_hostbridge_dev();
Mariusz Szafranskia4041332017-08-02 17:28:17 +0200145
146 if (!dev)
147 return 0;
148
149 return pci_read_config32(dev, TSEGMB) & MASK_TSEGMB;
150}
151
152uint32_t get_top_of_low_memory(void)
153{
Elyes HAOUAS6f01f432018-12-05 10:56:30 +0100154#ifdef __SIMPLE_DEVICE__
155 pci_devfn_t dev;
156#else
157 struct device *dev;
158#endif
159 dev = get_hostbridge_dev();
Mariusz Szafranskia4041332017-08-02 17:28:17 +0200160
161 if (!dev)
162 return 0;
163
164 return pci_read_config32(dev, TOLUD) & MASK_TOLUD;
165}
166
167uint64_t get_top_of_upper_memory(void)
168{
Elyes HAOUAS6f01f432018-12-05 10:56:30 +0100169#ifdef __SIMPLE_DEVICE__
170 pci_devfn_t dev;
171#else
172 struct device *dev;
173#endif
174 dev = get_hostbridge_dev();
Mariusz Szafranskia4041332017-08-02 17:28:17 +0200175
176 if (!dev)
177 return 0;
178
179 return ((uint64_t)(pci_read_config32(dev, TOUUD_HI) & MASK_TOUUD_HI)
180 << 32) +
181 (uint64_t)(pci_read_config32(dev, TOUUD_LO) & MASK_TOUUD_LO);
182}
183
184uint16_t get_pmbase(void)
185{
Elyes HAOUAS6f01f432018-12-05 10:56:30 +0100186#ifdef __SIMPLE_DEVICE__
187 pci_devfn_t dev;
188#else
189 struct device *dev;
190#endif
191 dev = get_pmc_dev();
Mariusz Szafranskia4041332017-08-02 17:28:17 +0200192
193 if (!dev)
194 return 0;
195
196 return pci_read_config16(dev, PMC_ACPI_BASE) & 0xfff8;
197}
198
199uint16_t get_tcobase(void)
200{
Elyes HAOUAS6f01f432018-12-05 10:56:30 +0100201#ifdef __SIMPLE_DEVICE__
202 pci_devfn_t dev;
203#else
204 struct device *dev;
205#endif
206 dev = get_smbus_dev();
Mariusz Szafranskia4041332017-08-02 17:28:17 +0200207
208 if (!dev)
209 return 0;
210
211 return pci_read_config16(dev, TCOBASE) & MASK_TCOBASE;
212}
213
214void mmio_andthenor32(void *addr, uint32_t val2and, uint32_t val2or)
215{
216 uint32_t reg32;
217
218 reg32 = read32(addr);
219 reg32 &= (uint32_t)val2and;
220 reg32 |= (uint32_t)val2or;
221 write32(addr, reg32);
222}
223
224uint8_t silicon_stepping(void)
225{
226 uint8_t revision_id;
Elyes HAOUAS6f01f432018-12-05 10:56:30 +0100227#ifdef __SIMPLE_DEVICE__
228 pci_devfn_t dev;
229#else
230 struct device *dev;
231#endif
232 dev = get_lpc_dev();
Mariusz Szafranskia4041332017-08-02 17:28:17 +0200233
234 if (!dev)
235 return 0;
236
237 revision_id = pci_read_config8(dev, PCI_REVISION_ID);
238
239 return revision_id;
240}
241
242void *memcpy_s(void *dest, const void *src, size_t n)
243{
244 uint8_t *dp;
245 const uint8_t *sp;
246
247 dp = (uint8_t *)dest;
248 sp = (uint8_t *)src;
249
250 if (!n)
251 return dest;
252
253 if (n > UINT32_MAX)
254 return dest;
255
256 if (!dp)
257 return dest;
258
259 if (!sp)
260 return dest;
261
262 /*
263 * overlap is undefined behavior, do not allow
264 */
265 if (((dp > sp) && (dp < (sp + n))) || ((sp > dp) && (sp < (dp + n))))
266 return dest;
267
268 /*
269 * now perform the copy
270 */
271
272 /* Original memcpy() function */
273 unsigned long d0, d1, d2;
274
275 asm volatile(
Patrick Rudolphadcf7822020-08-27 20:50:18 +0200276#if ENV_X86_64
Mariusz Szafranskia4041332017-08-02 17:28:17 +0200277 "rep ; movsd\n\t"
278 "mov %4,%%rcx\n\t"
279#else
280 "rep ; movsl\n\t"
281 "movl %4,%%ecx\n\t"
282#endif
283 "rep ; movsb\n\t"
284 : "=&c"(d0), "=&D"(d1), "=&S"(d2)
285 : "0"(n >> 2), "g"(n & 3), "1"(dest), "2"(src)
286 : "memory");
287
288 return dest;
289}