blob: b56c8396d9f6d4653b6f1d4d5d2e38c849088a1c [file] [log] [blame]
Mariusz Szafranskia4041332017-08-02 17:28:17 +02001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2014 - 2017 Intel Corporation.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of 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
17#include <stdint.h>
18#include <arch/io.h>
19#include <device/pci.h>
20#include <device/pci_def.h>
21#include <device/device.h>
Mariusz Szafranskia4041332017-08-02 17:28:17 +020022
23#include <soc/iomap.h>
24#include <soc/soc_util.h>
25#include <soc/pmc.h>
26#include <soc/smbus.h>
27#include <soc/lpc.h>
28#include <soc/pci_devs.h>
29#include <soc/systemagent.h>
30
Elyes HAOUAS6f01f432018-12-05 10:56:30 +010031#ifdef __SIMPLE_DEVICE__
32pci_devfn_t get_hostbridge_dev(void)
Mariusz Szafranskia4041332017-08-02 17:28:17 +020033{
Mariusz Szafranskia4041332017-08-02 17:28:17 +020034 return PCI_DEV(0, SA_DEV, SA_FUNC);
Elyes HAOUAS6f01f432018-12-05 10:56:30 +010035}
Mariusz Szafranskia4041332017-08-02 17:28:17 +020036#else
Elyes HAOUAS6f01f432018-12-05 10:56:30 +010037struct device *get_hostbridge_dev(void)
38{
Mariusz Szafranskia4041332017-08-02 17:28:17 +020039 return dev_find_slot(0, PCI_DEVFN(SA_DEV, SA_FUNC));
Mariusz Szafranskia4041332017-08-02 17:28:17 +020040}
Elyes HAOUAS6f01f432018-12-05 10:56:30 +010041#endif
Mariusz Szafranskia4041332017-08-02 17:28:17 +020042
Elyes HAOUAS6f01f432018-12-05 10:56:30 +010043#ifdef __SIMPLE_DEVICE__
44pci_devfn_t get_lpc_dev(void)
Mariusz Szafranskia4041332017-08-02 17:28:17 +020045{
Mariusz Szafranskia4041332017-08-02 17:28:17 +020046 return PCI_DEV(0, LPC_DEV, LPC_FUNC);
Elyes HAOUAS6f01f432018-12-05 10:56:30 +010047}
Mariusz Szafranskia4041332017-08-02 17:28:17 +020048#else
Elyes HAOUAS6f01f432018-12-05 10:56:30 +010049struct device *get_lpc_dev(void)
50{
Mariusz Szafranskia4041332017-08-02 17:28:17 +020051 return dev_find_slot(0, PCI_DEVFN(LPC_DEV, LPC_FUNC));
Mariusz Szafranskia4041332017-08-02 17:28:17 +020052}
Elyes HAOUAS6f01f432018-12-05 10:56:30 +010053#endif
Mariusz Szafranskia4041332017-08-02 17:28:17 +020054
Elyes HAOUAS6f01f432018-12-05 10:56:30 +010055#ifdef __SIMPLE_DEVICE__
56pci_devfn_t get_pmc_dev(void)
Mariusz Szafranskia4041332017-08-02 17:28:17 +020057{
Mariusz Szafranskia4041332017-08-02 17:28:17 +020058 return PCI_DEV(0, PMC_DEV, PMC_FUNC);
Mariusz Szafranskia4041332017-08-02 17:28:17 +020059}
Elyes HAOUAS6f01f432018-12-05 10:56:30 +010060#else
61struct device *get_pmc_dev(void)
Mariusz Szafranskia4041332017-08-02 17:28:17 +020062{
Elyes HAOUAS6f01f432018-12-05 10:56:30 +010063 return dev_find_slot(0, PCI_DEVFN(PMC_DEV, PMC_FUNC));
Mariusz Szafranskia4041332017-08-02 17:28:17 +020064}
Elyes HAOUAS6f01f432018-12-05 10:56:30 +010065#endif
66
67#ifdef __SIMPLE_DEVICE__
68pci_devfn_t get_smbus_dev(void)
69{
70 return PCI_DEV(0, SMBUS_DEV, SMBUS_FUNC);
71}
72#else
73struct device *get_smbus_dev(void)
74{
75 return dev_find_slot(0, PCI_DEVFN(SMBUS_DEV, SMBUS_FUNC));
76}
77#endif
Mariusz Szafranskia4041332017-08-02 17:28:17 +020078
79uint32_t get_pciebase(void)
80{
Elyes HAOUAS6f01f432018-12-05 10:56:30 +010081#ifdef __SIMPLE_DEVICE__
82 pci_devfn_t dev;
83#else
84 struct device *dev;
85#endif
Mariusz Szafranskia4041332017-08-02 17:28:17 +020086 u32 pciexbar_reg;
87
88 dev = get_hostbridge_dev();
89 if (!dev)
90 return 0;
91
92 pciexbar_reg = pci_read_config32(dev, PCIEXBAR);
93
94 if (!(pciexbar_reg & (1 << 0)))
95 return 0;
96
97 switch (pciexbar_reg & MASK_PCIEXBAR_LENGTH) {
98 case MASK_PCIEXBAR_LENGTH_256M:
99 pciexbar_reg &= MASK_PCIEXBAR_256M;
100 break;
101 case MASK_PCIEXBAR_LENGTH_128M:
102 pciexbar_reg &= MASK_PCIEXBAR_128M;
103 break;
104 case MASK_PCIEXBAR_LENGTH_64M:
105 pciexbar_reg &= MASK_PCIEXBAR_64M;
106 break;
107 default:
108 pciexbar_reg &= MASK_PCIEXBAR_256M;
109 break;
110 }
111
112 return pciexbar_reg;
113}
114
115uint32_t get_pcielength(void)
116{
Elyes HAOUAS6f01f432018-12-05 10:56:30 +0100117#ifdef __SIMPLE_DEVICE__
118 pci_devfn_t dev;
119#else
120 struct device *dev;
121#endif
Mariusz Szafranskia4041332017-08-02 17:28:17 +0200122 u32 pciexbar_reg;
123
124 dev = get_hostbridge_dev();
125 if (!dev)
126 return 0;
127
128 pciexbar_reg = pci_read_config32(dev, PCIEXBAR);
129
130 if (!(pciexbar_reg & (1 << 0)))
131 return 0;
132
133 switch (pciexbar_reg & MASK_PCIEXBAR_LENGTH) {
134 case MASK_PCIEXBAR_LENGTH_256M:
135 pciexbar_reg = 256;
136 break;
137 case MASK_PCIEXBAR_LENGTH_128M:
138 pciexbar_reg = 128;
139 break;
140 case MASK_PCIEXBAR_LENGTH_64M:
141 pciexbar_reg = 64;
142 break;
143 default:
144 pciexbar_reg = 64;
145 break;
146 }
147
148 return pciexbar_reg;
149}
150
151uint32_t get_tseg_memory(void)
152{
Elyes HAOUAS6f01f432018-12-05 10:56:30 +0100153#ifdef __SIMPLE_DEVICE__
154 pci_devfn_t dev;
155#else
156 struct device *dev;
157#endif
158 dev = get_hostbridge_dev();
Mariusz Szafranskia4041332017-08-02 17:28:17 +0200159
160 if (!dev)
161 return 0;
162
163 return pci_read_config32(dev, TSEGMB) & MASK_TSEGMB;
164}
165
166uint32_t get_top_of_low_memory(void)
167{
Elyes HAOUAS6f01f432018-12-05 10:56:30 +0100168#ifdef __SIMPLE_DEVICE__
169 pci_devfn_t dev;
170#else
171 struct device *dev;
172#endif
173 dev = get_hostbridge_dev();
Mariusz Szafranskia4041332017-08-02 17:28:17 +0200174
175 if (!dev)
176 return 0;
177
178 return pci_read_config32(dev, TOLUD) & MASK_TOLUD;
179}
180
181uint64_t get_top_of_upper_memory(void)
182{
Elyes HAOUAS6f01f432018-12-05 10:56:30 +0100183#ifdef __SIMPLE_DEVICE__
184 pci_devfn_t dev;
185#else
186 struct device *dev;
187#endif
188 dev = get_hostbridge_dev();
Mariusz Szafranskia4041332017-08-02 17:28:17 +0200189
190 if (!dev)
191 return 0;
192
193 return ((uint64_t)(pci_read_config32(dev, TOUUD_HI) & MASK_TOUUD_HI)
194 << 32) +
195 (uint64_t)(pci_read_config32(dev, TOUUD_LO) & MASK_TOUUD_LO);
196}
197
198uint16_t get_pmbase(void)
199{
Elyes HAOUAS6f01f432018-12-05 10:56:30 +0100200#ifdef __SIMPLE_DEVICE__
201 pci_devfn_t dev;
202#else
203 struct device *dev;
204#endif
205 dev = get_pmc_dev();
Mariusz Szafranskia4041332017-08-02 17:28:17 +0200206
207 if (!dev)
208 return 0;
209
210 return pci_read_config16(dev, PMC_ACPI_BASE) & 0xfff8;
211}
212
213uint16_t get_tcobase(void)
214{
Elyes HAOUAS6f01f432018-12-05 10:56:30 +0100215#ifdef __SIMPLE_DEVICE__
216 pci_devfn_t dev;
217#else
218 struct device *dev;
219#endif
220 dev = get_smbus_dev();
Mariusz Szafranskia4041332017-08-02 17:28:17 +0200221
222 if (!dev)
223 return 0;
224
225 return pci_read_config16(dev, TCOBASE) & MASK_TCOBASE;
226}
227
228void mmio_andthenor32(void *addr, uint32_t val2and, uint32_t val2or)
229{
230 uint32_t reg32;
231
232 reg32 = read32(addr);
233 reg32 &= (uint32_t)val2and;
234 reg32 |= (uint32_t)val2or;
235 write32(addr, reg32);
236}
237
238uint8_t silicon_stepping(void)
239{
240 uint8_t revision_id;
Elyes HAOUAS6f01f432018-12-05 10:56:30 +0100241#ifdef __SIMPLE_DEVICE__
242 pci_devfn_t dev;
243#else
244 struct device *dev;
245#endif
246 dev = get_lpc_dev();
Mariusz Szafranskia4041332017-08-02 17:28:17 +0200247
248 if (!dev)
249 return 0;
250
251 revision_id = pci_read_config8(dev, PCI_REVISION_ID);
252
253 return revision_id;
254}
255
256void *memcpy_s(void *dest, const void *src, size_t n)
257{
258 uint8_t *dp;
259 const uint8_t *sp;
260
261 dp = (uint8_t *)dest;
262 sp = (uint8_t *)src;
263
264 if (!n)
265 return dest;
266
267 if (n > UINT32_MAX)
268 return dest;
269
270 if (!dp)
271 return dest;
272
273 if (!sp)
274 return dest;
275
276 /*
277 * overlap is undefined behavior, do not allow
278 */
279 if (((dp > sp) && (dp < (sp + n))) || ((sp > dp) && (sp < (dp + n))))
280 return dest;
281
282 /*
283 * now perform the copy
284 */
285
286 /* Original memcpy() function */
287 unsigned long d0, d1, d2;
288
289 asm volatile(
290#ifdef __x86_64__
291 "rep ; movsd\n\t"
292 "mov %4,%%rcx\n\t"
293#else
294 "rep ; movsl\n\t"
295 "movl %4,%%ecx\n\t"
296#endif
297 "rep ; movsb\n\t"
298 : "=&c"(d0), "=&D"(d1), "=&S"(d2)
299 : "0"(n >> 2), "g"(n & 3), "1"(dest), "2"(src)
300 : "memory");
301
302 return dest;
303}