blob: 14e072541cfc61b01542d260ed782cc980560e14 [file] [log] [blame]
Angel Pons230e4f9d2020-04-05 15:47:14 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Lee Leahy4dd34ee2016-05-02 14:31:02 -07002
3#define __SIMPLE_DEVICE__
4
Kyösti Mälkkibdaec072019-03-02 23:18:29 +02005#include <arch/io.h>
Lee Leahy14d09262016-07-21 09:17:10 -07006#include <assert.h>
Lee Leahyae738ac2016-07-24 08:03:37 -07007#include <cpu/x86/mtrr.h>
Elyes HAOUAS63f98f22019-06-26 20:17:50 +02008#include <cpu/x86/cr.h>
Lee Leahy4dd34ee2016-05-02 14:31:02 -07009#include <console/console.h>
Elyes HAOUASbf0970e2019-03-21 11:10:03 +010010#include <delay.h>
Kyösti Mälkkif1b58b72019-03-01 13:43:02 +020011#include <device/pci_ops.h>
Lee Leahy4dd34ee2016-05-02 14:31:02 -070012#include <soc/pci_devs.h>
Lee Leahy5ef051a2016-04-29 15:16:54 -070013#include <soc/ramstage.h>
Lee Leahye0a60382017-04-18 12:38:29 -070014#include <soc/reg_access.h>
Lee Leahy4dd34ee2016-05-02 14:31:02 -070015
Lee Leahy7f4b0532016-05-22 11:52:28 -070016static uint16_t get_gpe0_address(uint32_t reg_address)
17{
18 uint32_t gpe0_base_address;
19
20 /* Get the GPE0 base address */
21 gpe0_base_address = pci_read_config32(LPC_BDF, R_QNC_LPC_GPE0BLK);
Lee Leahy94b971a2017-03-06 08:59:23 -080022 ASSERT(gpe0_base_address >= 0x80000000);
Lee Leahy7f4b0532016-05-22 11:52:28 -070023 gpe0_base_address &= B_QNC_LPC_GPE0BLK_MASK;
24
25 /* Return the GPE0 register address */
26 return (uint16_t)(gpe0_base_address + reg_address);
27}
28
Lee Leahyac690b12016-05-15 15:12:56 -070029static uint32_t *get_gpio_address(uint32_t reg_address)
30{
31 uint32_t gpio_base_address;
32
33 /* Get the GPIO base address */
34 gpio_base_address = pci_read_config32(I2CGPIO_BDF, PCI_BASE_ADDRESS_1);
35 gpio_base_address &= ~PCI_BASE_ADDRESS_MEM_ATTR_MASK;
Lee Leahy94b971a2017-03-06 08:59:23 -080036 ASSERT(gpio_base_address != 0x00000000);
Lee Leahyac690b12016-05-15 15:12:56 -070037
38 /* Return the GPIO register address */
39 return (uint32_t *)(gpio_base_address + reg_address);
40}
41
42void *get_i2c_address(void)
43{
44 uint32_t gpio_base_address;
45
46 /* Get the GPIO base address */
47 gpio_base_address = pci_read_config32(I2CGPIO_BDF, PCI_BASE_ADDRESS_0);
48 gpio_base_address &= ~PCI_BASE_ADDRESS_MEM_ATTR_MASK;
Lee Leahy94b971a2017-03-06 08:59:23 -080049 ASSERT(gpio_base_address != 0x00000000);
Lee Leahyac690b12016-05-15 15:12:56 -070050
51 /* Return the GPIO register address */
52 return (void *)gpio_base_address;
53}
54
55static uint16_t get_legacy_gpio_address(uint32_t reg_address)
56{
57 uint32_t gpio_base_address;
58
59 /* Get the GPIO base address */
60 gpio_base_address = pci_read_config32(LPC_BDF, R_QNC_LPC_GBA_BASE);
Lee Leahy94b971a2017-03-06 08:59:23 -080061 ASSERT(gpio_base_address >= 0x80000000);
Lee Leahyac690b12016-05-15 15:12:56 -070062 gpio_base_address &= B_QNC_LPC_GPA_BASE_MASK;
63
64 /* Return the GPIO register address */
65 return (uint16_t)(gpio_base_address + reg_address);
66}
67
Lee Leahyae738ac2016-07-24 08:03:37 -070068static uint32_t mtrr_index_to_host_bridge_register_offset(unsigned long index)
69{
70 uint32_t offset;
71
Martin Roth26f97f92021-10-01 14:53:22 -060072 /* Convert from MTRR index to host bridge offset (Datasheet 12.7.2) */
Lee Leahyae738ac2016-07-24 08:03:37 -070073 if (index == MTRR_CAP_MSR)
74 offset = QUARK_NC_HOST_BRIDGE_IA32_MTRR_CAP;
75 else if (index == MTRR_DEF_TYPE_MSR)
76 offset = QUARK_NC_HOST_BRIDGE_IA32_MTRR_DEF_TYPE;
77 else if (index == MTRR_FIX_64K_00000)
78 offset = QUARK_NC_HOST_BRIDGE_MTRR_FIX64K_00000;
79 else if ((index >= MTRR_FIX_16K_80000) && (index <= MTRR_FIX_16K_A0000))
80 offset = ((index - MTRR_FIX_16K_80000) << 1)
81 + QUARK_NC_HOST_BRIDGE_MTRR_FIX16K_80000;
82 else if ((index >= MTRR_FIX_4K_C0000) && (index <= MTRR_FIX_4K_F8000))
83 offset = ((index - MTRR_FIX_4K_C0000) << 1)
84 + QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSBASE0;
85 else if ((index >= MTRR_PHYS_BASE(0)) && (index <= MTRR_PHYS_MASK(7)))
86 offset = (index - MTRR_PHYS_BASE(0))
87 + QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSBASE0;
88 else {
Lee Leahyf74ce242016-07-31 17:20:30 -070089 printk(BIOS_SPEW, "index: 0x%08lx\n", index);
Lee Leahyae738ac2016-07-24 08:03:37 -070090 die("Invalid MTRR index specified!\n");
91 }
92 return offset;
93}
94
Lee Leahy4dd34ee2016-05-02 14:31:02 -070095void mcr_write(uint8_t opcode, uint8_t port, uint32_t reg_address)
96{
97 pci_write_config32(MC_BDF, QNC_ACCESS_PORT_MCR,
98 (opcode << QNC_MCR_OP_OFFSET)
99 | ((uint32_t)port << QNC_MCR_PORT_OFFSET)
100 | ((reg_address & QNC_MCR_MASK) << QNC_MCR_REG_OFFSET)
101 | QNC_MCR_BYTE_ENABLES);
102}
103
104uint32_t mdr_read(void)
105{
106 return pci_read_config32(MC_BDF, QNC_ACCESS_PORT_MDR);
107}
108
109void mdr_write(uint32_t value)
110{
111 pci_write_config32(MC_BDF, QNC_ACCESS_PORT_MDR, value);
112}
113
114void mea_write(uint32_t reg_address)
115{
116 pci_write_config32(MC_BDF, QNC_ACCESS_PORT_MEA, reg_address
117 & QNC_MEA_MASK);
118}
119
Lee Leahyae738ac2016-07-24 08:03:37 -0700120uint32_t port_reg_read(uint8_t port, uint32_t offset)
121{
122 /* Read the port register */
123 mea_write(offset);
124 mcr_write(QUARK_OPCODE_READ, port, offset);
125 return mdr_read();
126}
127
128void port_reg_write(uint8_t port, uint32_t offset, uint32_t value)
129{
130 /* Write the port register */
131 mea_write(offset);
132 mdr_write(value);
133 mcr_write(QUARK_OPCODE_WRITE, port, offset);
134}
135
Lee Leahy5fafc6a2016-07-30 18:21:53 -0700136static CRx_TYPE reg_cpu_cr_read(uint32_t reg_address)
137{
138 /* Read the CPU CRx register */
Lee Leahy94b971a2017-03-06 08:59:23 -0800139 switch (reg_address) {
Lee Leahy5fafc6a2016-07-30 18:21:53 -0700140 case 0:
141 return read_cr0();
142
143 case 4:
144 return read_cr4();
145 }
146 die("ERROR - Unsupported CPU register!\n");
147}
148
149static void reg_cpu_cr_write(uint32_t reg_address, CRx_TYPE value)
150{
151 /* Write the CPU CRx register */
Lee Leahy94b971a2017-03-06 08:59:23 -0800152 switch (reg_address) {
Lee Leahy5fafc6a2016-07-30 18:21:53 -0700153 default:
154 die("ERROR - Unsupported CPU register!\n");
155
156 case 0:
157 write_cr0(value);
Lee Leahyd924fac2016-08-05 06:11:19 -0700158 break;
Lee Leahy5fafc6a2016-07-30 18:21:53 -0700159
160 case 4:
161 write_cr4(value);
Lee Leahyd924fac2016-08-05 06:11:19 -0700162 break;
Lee Leahy5fafc6a2016-07-30 18:21:53 -0700163 }
164}
165
Lee Leahy7f4b0532016-05-22 11:52:28 -0700166static uint32_t reg_gpe0_read(uint32_t reg_address)
167{
168 /* Read the GPE0 register */
169 return inl(get_gpe0_address(reg_address));
170}
171
172static void reg_gpe0_write(uint32_t reg_address, uint32_t value)
173{
174 /* Write the GPE0 register */
Kyösti Mälkki0c745342022-11-17 05:19:58 +0200175 outl(value, get_gpe0_address(reg_address));
Lee Leahy7f4b0532016-05-22 11:52:28 -0700176}
177
Lee Leahy083da162016-05-15 13:32:24 -0700178static uint32_t reg_gpio_read(uint32_t reg_address)
179{
180 /* Read the GPIO register */
181 return *get_gpio_address(reg_address);
182}
183
184static void reg_gpio_write(uint32_t reg_address, uint32_t value)
185{
186 /* Write the GPIO register */
187 *get_gpio_address(reg_address) = value;
188}
189
Lee Leahy660c67a2016-07-10 17:09:24 -0700190uint32_t reg_host_bridge_unit_read(uint32_t reg_address)
191{
192 /* Read the host bridge register */
193 mea_write(reg_address);
194 mcr_write(QUARK_OPCODE_READ, QUARK_NC_HOST_BRIDGE_SB_PORT_ID,
195 reg_address);
196 return mdr_read();
197}
198
199static void reg_host_bridge_unit_write(uint32_t reg_address, uint32_t value)
200{
201 /* Write the host bridge register */
202 mea_write(reg_address);
203 mdr_write(value);
204 mcr_write(QUARK_OPCODE_WRITE, QUARK_NC_HOST_BRIDGE_SB_PORT_ID,
205 reg_address);
206}
207
Lee Leahy083da162016-05-15 13:32:24 -0700208uint32_t reg_legacy_gpio_read(uint32_t reg_address)
209{
210 /* Read the legacy GPIO register */
211 return inl(get_legacy_gpio_address(reg_address));
212}
213
214void reg_legacy_gpio_write(uint32_t reg_address, uint32_t value)
215{
216 /* Write the legacy GPIO register */
217 outl(value, get_legacy_gpio_address(reg_address));
218}
219
Lee Leahy5ef051a2016-04-29 15:16:54 -0700220static uint32_t reg_pcie_afe_read(uint32_t reg_address)
221{
222 /* Read the PCIE AFE register */
223 mea_write(reg_address);
224 mcr_write(QUARK_OPCODE_IO_READ, QUARK_SC_PCIE_AFE_SB_PORT_ID,
225 reg_address);
226 return mdr_read();
227}
228
229static void reg_pcie_afe_write(uint32_t reg_address, uint32_t value)
230{
231 /* Write the PCIE AFE register */
232 mea_write(reg_address);
233 mdr_write(value);
234 mcr_write(QUARK_OPCODE_IO_WRITE, QUARK_SC_PCIE_AFE_SB_PORT_ID,
235 reg_address);
236}
237
Lee Leahy63e3dff2016-04-30 08:48:52 -0700238uint32_t reg_rmu_temp_read(uint32_t reg_address)
239{
240 /* Read the RMU temperature register */
241 mea_write(reg_address);
242 mcr_write(QUARK_OPCODE_READ, QUARK_NC_RMU_SB_PORT_ID, reg_address);
243 return mdr_read();
244}
245
246static void reg_rmu_temp_write(uint32_t reg_address, uint32_t value)
247{
248 /* Write the RMU temperature register */
249 mea_write(reg_address);
250 mdr_write(value);
251 mcr_write(QUARK_OPCODE_WRITE, QUARK_NC_RMU_SB_PORT_ID, reg_address);
252}
253
254static uint32_t reg_soc_unit_read(uint32_t reg_address)
255{
256 /* Read the temperature sensor register */
257 mea_write(reg_address);
258 mcr_write(QUARK_ALT_OPCODE_READ, QUARK_SCSS_SOC_UNIT_SB_PORT_ID,
259 reg_address);
260 return mdr_read();
261}
262
263static void reg_soc_unit_write(uint32_t reg_address, uint32_t value)
264{
265 /* Write the temperature sensor register */
266 mea_write(reg_address);
267 mdr_write(value);
268 mcr_write(QUARK_ALT_OPCODE_WRITE, QUARK_SCSS_SOC_UNIT_SB_PORT_ID,
269 reg_address);
270}
271
Lee Leahy4dd34ee2016-05-02 14:31:02 -0700272static uint32_t reg_usb_read(uint32_t reg_address)
273{
274 /* Read the USB register */
275 mea_write(reg_address);
276 mcr_write(QUARK_ALT_OPCODE_READ, QUARK_SC_USB_AFE_SB_PORT_ID,
277 reg_address);
278 return mdr_read();
279}
280
281static void reg_usb_write(uint32_t reg_address, uint32_t value)
282{
283 /* Write the USB register */
284 mea_write(reg_address);
285 mdr_write(value);
286 mcr_write(QUARK_ALT_OPCODE_WRITE, QUARK_SC_USB_AFE_SB_PORT_ID,
287 reg_address);
288}
289
290static uint64_t reg_read(struct reg_script_context *ctx)
291{
292 const struct reg_script *step = ctx->step;
293 uint64_t value = 0;
294
295 switch (step->id) {
296 default:
297 printk(BIOS_ERR,
298 "ERROR - Unknown register set (0x%08x)!\n",
299 step->id);
300 ctx->display_features = REG_SCRIPT_DISPLAY_NOTHING;
301 return 0;
302
Lee Leahy5fafc6a2016-07-30 18:21:53 -0700303 case CPU_CR:
304 ctx->display_prefix = "CPU CR";
305 value = reg_cpu_cr_read(step->reg);
306 break;
307
Lee Leahy7f4b0532016-05-22 11:52:28 -0700308 case GPE0_REGS:
Lee Leahy6b24dfc2016-05-22 16:24:36 -0700309 ctx->display_prefix = "GPE0";
Lee Leahy7f4b0532016-05-22 11:52:28 -0700310 value = reg_gpe0_read(step->reg);
311 break;
312
Lee Leahy083da162016-05-15 13:32:24 -0700313 case GPIO_REGS:
Lee Leahy6b24dfc2016-05-22 16:24:36 -0700314 ctx->display_prefix = "GPIO";
Lee Leahy083da162016-05-15 13:32:24 -0700315 value = reg_gpio_read(step->reg);
316 break;
317
Lee Leahy660c67a2016-07-10 17:09:24 -0700318 case HOST_BRIDGE:
319 ctx->display_prefix = "Host Bridge";
320 value = reg_host_bridge_unit_read(step->reg);
321 break;
322
Lee Leahy083da162016-05-15 13:32:24 -0700323 case LEG_GPIO_REGS:
Lee Leahy6b24dfc2016-05-22 16:24:36 -0700324 ctx->display_prefix = "Legacy GPIO";
Lee Leahy083da162016-05-15 13:32:24 -0700325 value = reg_legacy_gpio_read(step->reg);
Lee Leahyb06724022016-07-18 10:39:55 -0700326 break;
Lee Leahy5ef051a2016-04-29 15:16:54 -0700327
328 case PCIE_AFE_REGS:
Lee Leahy6b24dfc2016-05-22 16:24:36 -0700329 ctx->display_prefix = "PCIe AFE";
Lee Leahy5ef051a2016-04-29 15:16:54 -0700330 value = reg_pcie_afe_read(step->reg);
Lee Leahy083da162016-05-15 13:32:24 -0700331 break;
332
Lee Leahy63e3dff2016-04-30 08:48:52 -0700333 case RMU_TEMP_REGS:
334 ctx->display_prefix = "RMU TEMP";
335 value = reg_rmu_temp_read(step->reg);
336 break;
337
338 case SOC_UNIT_REGS:
339 ctx->display_prefix = "SOC Unit";
340 value = reg_soc_unit_read(step->reg);
341 break;
342
Lee Leahy4dd34ee2016-05-02 14:31:02 -0700343 case USB_PHY_REGS:
344 ctx->display_prefix = "USB PHY";
345 value = reg_usb_read(step->reg);
346 break;
347 }
348 return value;
349}
350
351static void reg_write(struct reg_script_context *ctx)
352{
353 const struct reg_script *step = ctx->step;
354
355 switch (step->id) {
356 default:
357 printk(BIOS_ERR,
358 "ERROR - Unknown register set (0x%08x)!\n",
359 step->id);
360 ctx->display_features = REG_SCRIPT_DISPLAY_NOTHING;
361 return;
362
Lee Leahy5fafc6a2016-07-30 18:21:53 -0700363 case CPU_CR:
364 ctx->display_prefix = "CPU CR";
365 reg_cpu_cr_write(step->reg, step->value);
366 break;
367
Lee Leahy7f4b0532016-05-22 11:52:28 -0700368 case GPE0_REGS:
Lee Leahy6b24dfc2016-05-22 16:24:36 -0700369 ctx->display_prefix = "GPE0";
Lee Leahy7f4b0532016-05-22 11:52:28 -0700370 reg_gpe0_write(step->reg, (uint32_t)step->value);
371 break;
372
Lee Leahy083da162016-05-15 13:32:24 -0700373 case GPIO_REGS:
Lee Leahy6b24dfc2016-05-22 16:24:36 -0700374 ctx->display_prefix = "GPIO";
Lee Leahy083da162016-05-15 13:32:24 -0700375 reg_gpio_write(step->reg, (uint32_t)step->value);
376 break;
377
Lee Leahy660c67a2016-07-10 17:09:24 -0700378 case HOST_BRIDGE:
379 ctx->display_prefix = "Host Bridge";
380 reg_host_bridge_unit_write(step->reg, (uint32_t)step->value);
381 break;
382
Lee Leahy083da162016-05-15 13:32:24 -0700383 case LEG_GPIO_REGS:
Lee Leahy6b24dfc2016-05-22 16:24:36 -0700384 ctx->display_prefix = "Legacy GPIO";
Lee Leahy083da162016-05-15 13:32:24 -0700385 reg_legacy_gpio_write(step->reg, (uint32_t)step->value);
386 break;
387
Lee Leahy5ef051a2016-04-29 15:16:54 -0700388 case PCIE_AFE_REGS:
Lee Leahy6b24dfc2016-05-22 16:24:36 -0700389 ctx->display_prefix = "PCIe AFE";
Lee Leahy5ef051a2016-04-29 15:16:54 -0700390 reg_pcie_afe_write(step->reg, (uint32_t)step->value);
391 break;
392
393 case PCIE_RESET:
394 if (ctx->display_features) {
Lee Leahy6b24dfc2016-05-22 16:24:36 -0700395 ctx->display_prefix = "PCIe reset";
Lee Leahy5ef051a2016-04-29 15:16:54 -0700396 ctx->display_features &= ~REG_SCRIPT_DISPLAY_REGISTER;
397 }
398 mainboard_gpio_pcie_reset(step->value);
399 break;
400
Lee Leahy63e3dff2016-04-30 08:48:52 -0700401 case RMU_TEMP_REGS:
402 ctx->display_prefix = "RMU TEMP";
403 reg_rmu_temp_write(step->reg, (uint32_t)step->value);
404 break;
405
406 case SOC_UNIT_REGS:
407 ctx->display_prefix = "SOC Unit";
408 reg_soc_unit_write(step->reg, (uint32_t)step->value);
409 break;
410
Lee Leahy4c3f5dc2016-04-29 16:36:02 -0700411 case MICROSECOND_DELAY:
412 /* The actual delay is >= the requested delay */
413 if (ctx->display_features) {
Lee Leahy94b971a2017-03-06 08:59:23 -0800414 /* Higher baud-rates will reduce the impact of
415 * displaying this message
416 */
Lee Leahy4c3f5dc2016-04-29 16:36:02 -0700417 printk(BIOS_INFO, "Delay %lld uSec\n", step->value);
418 ctx->display_features = REG_SCRIPT_DISPLAY_NOTHING;
419 }
420 udelay(step->value);
421 break;
422
Lee Leahy4dd34ee2016-05-02 14:31:02 -0700423 case USB_PHY_REGS:
424 ctx->display_prefix = "USB PHY";
425 reg_usb_write(step->reg, (uint32_t)step->value);
426 break;
427 }
428}
429
Lee Leahy94b971a2017-03-06 08:59:23 -0800430msr_t soc_msr_read(unsigned int index)
Lee Leahyae738ac2016-07-24 08:03:37 -0700431{
432 uint32_t offset;
433 union {
434 uint64_t u64;
435 msr_t msr;
436 } value;
437
438 /* Read the low 32-bits of the register */
439 offset = mtrr_index_to_host_bridge_register_offset(index);
440 value.u64 = port_reg_read(QUARK_NC_HOST_BRIDGE_SB_PORT_ID, offset);
441
442 /* For 64-bit registers, read the upper 32-bits */
443 if ((offset >= QUARK_NC_HOST_BRIDGE_MTRR_FIX64K_00000)
444 && (offset <= QUARK_NC_HOST_BRIDGE_MTRR_FIX4K_F8000)) {
445 offset += 1;
446 value.u64 |= port_reg_read(QUARK_NC_HOST_BRIDGE_SB_PORT_ID,
447 offset);
448 }
449 return value.msr;
450}
451
Lee Leahy94b971a2017-03-06 08:59:23 -0800452void soc_msr_write(unsigned int index, msr_t msr)
Lee Leahyae738ac2016-07-24 08:03:37 -0700453{
454 uint32_t offset;
455 union {
456 uint32_t u32[2];
457 msr_t msr;
458 } value;
459
460 /* Write the low 32-bits of the register */
461 value.msr = msr;
462 offset = mtrr_index_to_host_bridge_register_offset(index);
463 port_reg_write(QUARK_NC_HOST_BRIDGE_SB_PORT_ID, offset, value.u32[0]);
464
465 /* For 64-bit registers, write the upper 32-bits */
466 if ((offset >= QUARK_NC_HOST_BRIDGE_MTRR_FIX64K_00000)
467 && (offset <= QUARK_NC_HOST_BRIDGE_MTRR_FIX4K_F8000)) {
468 offset += 1;
469 port_reg_write(QUARK_NC_HOST_BRIDGE_SB_PORT_ID, offset,
470 value.u32[1]);
471 }
472}
473
Lee Leahy4dd34ee2016-05-02 14:31:02 -0700474const struct reg_script_bus_entry soc_reg_script_bus_table = {
475 SOC_TYPE, reg_read, reg_write
476};
477
478REG_SCRIPT_BUS_ENTRY(soc_reg_script_bus_table);