1 /* SPDX-License-Identifier: GPL-2.0-only */
2
3 #include <stdint.h>
4 #include <device/mmio.h>
5 #include <device/pci_ops.h>
6 #include <device/pci.h>
7 #include <device/device.h>
8 #include <string.h>
9 #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
17 #ifdef __SIMPLE_DEVICE__
get_hostbridge_dev(void)18 pci_devfn_t get_hostbridge_dev(void)
19 {
20 return PCI_DEV(0, SA_DEV, SA_FUNC);
21 }
22 #else
get_hostbridge_dev(void)23 struct device *get_hostbridge_dev(void)
24 {
25 return pcidev_on_root(SA_DEV, SA_FUNC);
26 }
27 #endif
28
29 #ifdef __SIMPLE_DEVICE__
get_lpc_dev(void)30 pci_devfn_t get_lpc_dev(void)
31 {
32 return PCI_DEV(0, LPC_DEV, LPC_FUNC);
33 }
34 #else
get_lpc_dev(void)35 struct device *get_lpc_dev(void)
36 {
37 return pcidev_on_root(LPC_DEV, LPC_FUNC);
38 }
39 #endif
40
41 #ifdef __SIMPLE_DEVICE__
get_pmc_dev(void)42 pci_devfn_t get_pmc_dev(void)
43 {
44 return PCI_DEV(0, PMC_DEV, PMC_FUNC);
45 }
46 #else
get_pmc_dev(void)47 struct device *get_pmc_dev(void)
48 {
49 return pcidev_on_root(PMC_DEV, PMC_FUNC);
50 }
51 #endif
52
53 #ifdef __SIMPLE_DEVICE__
get_smbus_dev(void)54 pci_devfn_t get_smbus_dev(void)
55 {
56 return PCI_DEV(0, SMBUS_DEV, SMBUS_FUNC);
57 }
58 #else
get_smbus_dev(void)59 struct device *get_smbus_dev(void)
60 {
61 return pcidev_on_root(SMBUS_DEV, SMBUS_FUNC);
62 }
63 #endif
64
get_pciebase(void)65 uint32_t get_pciebase(void)
66 {
67 #ifdef __SIMPLE_DEVICE__
68 pci_devfn_t dev;
69 #else
70 struct device *dev;
71 #endif
72 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
get_pcielength(void)101 uint32_t get_pcielength(void)
102 {
103 #ifdef __SIMPLE_DEVICE__
104 pci_devfn_t dev;
105 #else
106 struct device *dev;
107 #endif
108 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
get_tseg_memory(void)137 uint32_t get_tseg_memory(void)
138 {
139 #ifdef __SIMPLE_DEVICE__
140 pci_devfn_t dev;
141 #else
142 struct device *dev;
143 #endif
144 dev = get_hostbridge_dev();
145
146 if (!dev)
147 return 0;
148
149 return pci_read_config32(dev, TSEGMB) & MASK_TSEGMB;
150 }
151
get_top_of_low_memory(void)152 uint32_t get_top_of_low_memory(void)
153 {
154 #ifdef __SIMPLE_DEVICE__
155 pci_devfn_t dev;
156 #else
157 struct device *dev;
158 #endif
159 dev = get_hostbridge_dev();
160
161 if (!dev)
162 return 0;
163
164 return pci_read_config32(dev, TOLUD) & MASK_TOLUD;
165 }
166
get_top_of_upper_memory(void)167 uint64_t get_top_of_upper_memory(void)
168 {
169 #ifdef __SIMPLE_DEVICE__
170 pci_devfn_t dev;
171 #else
172 struct device *dev;
173 #endif
174 dev = get_hostbridge_dev();
175
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
get_pmbase(void)184 uint16_t get_pmbase(void)
185 {
186 #ifdef __SIMPLE_DEVICE__
187 pci_devfn_t dev;
188 #else
189 struct device *dev;
190 #endif
191 dev = get_pmc_dev();
192
193 if (!dev)
194 return 0;
195
196 return pci_read_config16(dev, PMC_ACPI_BASE) & 0xfff8;
197 }
198
get_tcobase(void)199 uint16_t get_tcobase(void)
200 {
201 #ifdef __SIMPLE_DEVICE__
202 pci_devfn_t dev;
203 #else
204 struct device *dev;
205 #endif
206 dev = get_smbus_dev();
207
208 if (!dev)
209 return 0;
210
211 return pci_read_config16(dev, TCOBASE) & MASK_TCOBASE;
212 }
213
mmio_andthenor32(void * addr,uint32_t val2and,uint32_t val2or)214 void 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
silicon_stepping(void)224 uint8_t silicon_stepping(void)
225 {
226 uint8_t revision_id;
227 #ifdef __SIMPLE_DEVICE__
228 pci_devfn_t dev;
229 #else
230 struct device *dev;
231 #endif
232 dev = get_lpc_dev();
233
234 if (!dev)
235 return 0;
236
237 revision_id = pci_read_config8(dev, PCI_REVISION_ID);
238
239 return revision_id;
240 }
241
memcpy_s(void * dest,const void * src,size_t n)242 void *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(
276 #if ENV_X86_64
277 "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 }
290