blob: e5c0f0b6dc9806f617928c19494f06c0d4e4cfe9 [file] [log] [blame]
Lee Leahy4dd34ee2016-05-02 14:31:02 -07001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2016 Intel Corp.
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 wacbmem_entryanty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 */
15
16#define __SIMPLE_DEVICE__
17
Lee Leahy14d09262016-07-21 09:17:10 -070018#include <assert.h>
Lee Leahyae738ac2016-07-24 08:03:37 -070019#include <cpu/x86/mtrr.h>
Lee Leahy4dd34ee2016-05-02 14:31:02 -070020#include <console/console.h>
21#include <soc/pci_devs.h>
Lee Leahy5ef051a2016-04-29 15:16:54 -070022#include <soc/ramstage.h>
Lee Leahy4dd34ee2016-05-02 14:31:02 -070023
Lee Leahy7f4b0532016-05-22 11:52:28 -070024static uint16_t get_gpe0_address(uint32_t reg_address)
25{
26 uint32_t gpe0_base_address;
27
28 /* Get the GPE0 base address */
29 gpe0_base_address = pci_read_config32(LPC_BDF, R_QNC_LPC_GPE0BLK);
30 ASSERT (gpe0_base_address >= 0x80000000);
31 gpe0_base_address &= B_QNC_LPC_GPE0BLK_MASK;
32
33 /* Return the GPE0 register address */
34 return (uint16_t)(gpe0_base_address + reg_address);
35}
36
Lee Leahyac690b12016-05-15 15:12:56 -070037static uint32_t *get_gpio_address(uint32_t reg_address)
38{
39 uint32_t gpio_base_address;
40
41 /* Get the GPIO base address */
42 gpio_base_address = pci_read_config32(I2CGPIO_BDF, PCI_BASE_ADDRESS_1);
43 gpio_base_address &= ~PCI_BASE_ADDRESS_MEM_ATTR_MASK;
44 ASSERT (gpio_base_address != 0x00000000);
45
46 /* Return the GPIO register address */
47 return (uint32_t *)(gpio_base_address + reg_address);
48}
49
50void *get_i2c_address(void)
51{
52 uint32_t gpio_base_address;
53
54 /* Get the GPIO base address */
55 gpio_base_address = pci_read_config32(I2CGPIO_BDF, PCI_BASE_ADDRESS_0);
56 gpio_base_address &= ~PCI_BASE_ADDRESS_MEM_ATTR_MASK;
57 ASSERT (gpio_base_address != 0x00000000);
58
59 /* Return the GPIO register address */
60 return (void *)gpio_base_address;
61}
62
63static uint16_t get_legacy_gpio_address(uint32_t reg_address)
64{
65 uint32_t gpio_base_address;
66
67 /* Get the GPIO base address */
68 gpio_base_address = pci_read_config32(LPC_BDF, R_QNC_LPC_GBA_BASE);
69 ASSERT (gpio_base_address >= 0x80000000);
70 gpio_base_address &= B_QNC_LPC_GPA_BASE_MASK;
71
72 /* Return the GPIO register address */
73 return (uint16_t)(gpio_base_address + reg_address);
74}
75
Lee Leahyae738ac2016-07-24 08:03:37 -070076static uint32_t mtrr_index_to_host_bridge_register_offset(unsigned long index)
77{
78 uint32_t offset;
79
80 /* Convert from MTRR index to host brigde offset (Datasheet 12.7.2) */
81 if (index == MTRR_CAP_MSR)
82 offset = QUARK_NC_HOST_BRIDGE_IA32_MTRR_CAP;
83 else if (index == MTRR_DEF_TYPE_MSR)
84 offset = QUARK_NC_HOST_BRIDGE_IA32_MTRR_DEF_TYPE;
85 else if (index == MTRR_FIX_64K_00000)
86 offset = QUARK_NC_HOST_BRIDGE_MTRR_FIX64K_00000;
87 else if ((index >= MTRR_FIX_16K_80000) && (index <= MTRR_FIX_16K_A0000))
88 offset = ((index - MTRR_FIX_16K_80000) << 1)
89 + QUARK_NC_HOST_BRIDGE_MTRR_FIX16K_80000;
90 else if ((index >= MTRR_FIX_4K_C0000) && (index <= MTRR_FIX_4K_F8000))
91 offset = ((index - MTRR_FIX_4K_C0000) << 1)
92 + QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSBASE0;
93 else if ((index >= MTRR_PHYS_BASE(0)) && (index <= MTRR_PHYS_MASK(7)))
94 offset = (index - MTRR_PHYS_BASE(0))
95 + QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSBASE0;
96 else {
97 printk(BIOS_DEBUG, "index: 0x%08lx\n", index);
98 die("Invalid MTRR index specified!\n");
99 }
100 return offset;
101}
102
Lee Leahy4dd34ee2016-05-02 14:31:02 -0700103void mcr_write(uint8_t opcode, uint8_t port, uint32_t reg_address)
104{
105 pci_write_config32(MC_BDF, QNC_ACCESS_PORT_MCR,
106 (opcode << QNC_MCR_OP_OFFSET)
107 | ((uint32_t)port << QNC_MCR_PORT_OFFSET)
108 | ((reg_address & QNC_MCR_MASK) << QNC_MCR_REG_OFFSET)
109 | QNC_MCR_BYTE_ENABLES);
110}
111
112uint32_t mdr_read(void)
113{
114 return pci_read_config32(MC_BDF, QNC_ACCESS_PORT_MDR);
115}
116
117void mdr_write(uint32_t value)
118{
119 pci_write_config32(MC_BDF, QNC_ACCESS_PORT_MDR, value);
120}
121
122void mea_write(uint32_t reg_address)
123{
124 pci_write_config32(MC_BDF, QNC_ACCESS_PORT_MEA, reg_address
125 & QNC_MEA_MASK);
126}
127
Lee Leahyae738ac2016-07-24 08:03:37 -0700128uint32_t port_reg_read(uint8_t port, uint32_t offset)
129{
130 /* Read the port register */
131 mea_write(offset);
132 mcr_write(QUARK_OPCODE_READ, port, offset);
133 return mdr_read();
134}
135
136void port_reg_write(uint8_t port, uint32_t offset, uint32_t value)
137{
138 /* Write the port register */
139 mea_write(offset);
140 mdr_write(value);
141 mcr_write(QUARK_OPCODE_WRITE, port, offset);
142}
143
Lee Leahy5fafc6a2016-07-30 18:21:53 -0700144static CRx_TYPE reg_cpu_cr_read(uint32_t reg_address)
145{
146 /* Read the CPU CRx register */
147 switch(reg_address) {
148 case 0:
149 return read_cr0();
150
151 case 4:
152 return read_cr4();
153 }
154 die("ERROR - Unsupported CPU register!\n");
155}
156
157static void reg_cpu_cr_write(uint32_t reg_address, CRx_TYPE value)
158{
159 /* Write the CPU CRx register */
160 switch(reg_address) {
161 default:
162 die("ERROR - Unsupported CPU register!\n");
163
164 case 0:
165 write_cr0(value);
166
167 case 4:
168 write_cr4(value);
169 }
170}
171
Lee Leahy7f4b0532016-05-22 11:52:28 -0700172static uint32_t reg_gpe0_read(uint32_t reg_address)
173{
174 /* Read the GPE0 register */
175 return inl(get_gpe0_address(reg_address));
176}
177
178static void reg_gpe0_write(uint32_t reg_address, uint32_t value)
179{
180 /* Write the GPE0 register */
181 outl(get_gpe0_address(reg_address), value);
182}
183
Lee Leahy083da162016-05-15 13:32:24 -0700184static uint32_t reg_gpio_read(uint32_t reg_address)
185{
186 /* Read the GPIO register */
187 return *get_gpio_address(reg_address);
188}
189
190static void reg_gpio_write(uint32_t reg_address, uint32_t value)
191{
192 /* Write the GPIO register */
193 *get_gpio_address(reg_address) = value;
194}
195
Lee Leahy660c67a2016-07-10 17:09:24 -0700196uint32_t reg_host_bridge_unit_read(uint32_t reg_address)
197{
198 /* Read the host bridge register */
199 mea_write(reg_address);
200 mcr_write(QUARK_OPCODE_READ, QUARK_NC_HOST_BRIDGE_SB_PORT_ID,
201 reg_address);
202 return mdr_read();
203}
204
205static void reg_host_bridge_unit_write(uint32_t reg_address, uint32_t value)
206{
207 /* Write the host bridge register */
208 mea_write(reg_address);
209 mdr_write(value);
210 mcr_write(QUARK_OPCODE_WRITE, QUARK_NC_HOST_BRIDGE_SB_PORT_ID,
211 reg_address);
212}
213
Lee Leahy083da162016-05-15 13:32:24 -0700214uint32_t reg_legacy_gpio_read(uint32_t reg_address)
215{
216 /* Read the legacy GPIO register */
217 return inl(get_legacy_gpio_address(reg_address));
218}
219
220void reg_legacy_gpio_write(uint32_t reg_address, uint32_t value)
221{
222 /* Write the legacy GPIO register */
223 outl(value, get_legacy_gpio_address(reg_address));
224}
225
Lee Leahy5ef051a2016-04-29 15:16:54 -0700226static uint32_t reg_pcie_afe_read(uint32_t reg_address)
227{
228 /* Read the PCIE AFE register */
229 mea_write(reg_address);
230 mcr_write(QUARK_OPCODE_IO_READ, QUARK_SC_PCIE_AFE_SB_PORT_ID,
231 reg_address);
232 return mdr_read();
233}
234
235static void reg_pcie_afe_write(uint32_t reg_address, uint32_t value)
236{
237 /* Write the PCIE AFE register */
238 mea_write(reg_address);
239 mdr_write(value);
240 mcr_write(QUARK_OPCODE_IO_WRITE, QUARK_SC_PCIE_AFE_SB_PORT_ID,
241 reg_address);
242}
243
Lee Leahy63e3dff2016-04-30 08:48:52 -0700244uint32_t reg_rmu_temp_read(uint32_t reg_address)
245{
246 /* Read the RMU temperature register */
247 mea_write(reg_address);
248 mcr_write(QUARK_OPCODE_READ, QUARK_NC_RMU_SB_PORT_ID, reg_address);
249 return mdr_read();
250}
251
252static void reg_rmu_temp_write(uint32_t reg_address, uint32_t value)
253{
254 /* Write the RMU temperature register */
255 mea_write(reg_address);
256 mdr_write(value);
257 mcr_write(QUARK_OPCODE_WRITE, QUARK_NC_RMU_SB_PORT_ID, reg_address);
258}
259
260static uint32_t reg_soc_unit_read(uint32_t reg_address)
261{
262 /* Read the temperature sensor register */
263 mea_write(reg_address);
264 mcr_write(QUARK_ALT_OPCODE_READ, QUARK_SCSS_SOC_UNIT_SB_PORT_ID,
265 reg_address);
266 return mdr_read();
267}
268
269static void reg_soc_unit_write(uint32_t reg_address, uint32_t value)
270{
271 /* Write the temperature sensor register */
272 mea_write(reg_address);
273 mdr_write(value);
274 mcr_write(QUARK_ALT_OPCODE_WRITE, QUARK_SCSS_SOC_UNIT_SB_PORT_ID,
275 reg_address);
276}
277
Lee Leahy4dd34ee2016-05-02 14:31:02 -0700278static uint32_t reg_usb_read(uint32_t reg_address)
279{
280 /* Read the USB register */
281 mea_write(reg_address);
282 mcr_write(QUARK_ALT_OPCODE_READ, QUARK_SC_USB_AFE_SB_PORT_ID,
283 reg_address);
284 return mdr_read();
285}
286
287static void reg_usb_write(uint32_t reg_address, uint32_t value)
288{
289 /* Write the USB register */
290 mea_write(reg_address);
291 mdr_write(value);
292 mcr_write(QUARK_ALT_OPCODE_WRITE, QUARK_SC_USB_AFE_SB_PORT_ID,
293 reg_address);
294}
295
296static uint64_t reg_read(struct reg_script_context *ctx)
297{
298 const struct reg_script *step = ctx->step;
299 uint64_t value = 0;
300
301 switch (step->id) {
302 default:
303 printk(BIOS_ERR,
304 "ERROR - Unknown register set (0x%08x)!\n",
305 step->id);
306 ctx->display_features = REG_SCRIPT_DISPLAY_NOTHING;
307 return 0;
308
Lee Leahy5fafc6a2016-07-30 18:21:53 -0700309 case CPU_CR:
310 ctx->display_prefix = "CPU CR";
311 value = reg_cpu_cr_read(step->reg);
312 break;
313
Lee Leahy7f4b0532016-05-22 11:52:28 -0700314 case GPE0_REGS:
Lee Leahy6b24dfc2016-05-22 16:24:36 -0700315 ctx->display_prefix = "GPE0";
Lee Leahy7f4b0532016-05-22 11:52:28 -0700316 value = reg_gpe0_read(step->reg);
317 break;
318
Lee Leahy083da162016-05-15 13:32:24 -0700319 case GPIO_REGS:
Lee Leahy6b24dfc2016-05-22 16:24:36 -0700320 ctx->display_prefix = "GPIO";
Lee Leahy083da162016-05-15 13:32:24 -0700321 value = reg_gpio_read(step->reg);
322 break;
323
Lee Leahy660c67a2016-07-10 17:09:24 -0700324 case HOST_BRIDGE:
325 ctx->display_prefix = "Host Bridge";
326 value = reg_host_bridge_unit_read(step->reg);
327 break;
328
Lee Leahy083da162016-05-15 13:32:24 -0700329 case LEG_GPIO_REGS:
Lee Leahy6b24dfc2016-05-22 16:24:36 -0700330 ctx->display_prefix = "Legacy GPIO";
Lee Leahy083da162016-05-15 13:32:24 -0700331 value = reg_legacy_gpio_read(step->reg);
Lee Leahyb06724022016-07-18 10:39:55 -0700332 break;
Lee Leahy5ef051a2016-04-29 15:16:54 -0700333
334 case PCIE_AFE_REGS:
Lee Leahy6b24dfc2016-05-22 16:24:36 -0700335 ctx->display_prefix = "PCIe AFE";
Lee Leahy5ef051a2016-04-29 15:16:54 -0700336 value = reg_pcie_afe_read(step->reg);
Lee Leahy083da162016-05-15 13:32:24 -0700337 break;
338
Lee Leahy63e3dff2016-04-30 08:48:52 -0700339 case RMU_TEMP_REGS:
340 ctx->display_prefix = "RMU TEMP";
341 value = reg_rmu_temp_read(step->reg);
342 break;
343
344 case SOC_UNIT_REGS:
345 ctx->display_prefix = "SOC Unit";
346 value = reg_soc_unit_read(step->reg);
347 break;
348
Lee Leahy4dd34ee2016-05-02 14:31:02 -0700349 case USB_PHY_REGS:
350 ctx->display_prefix = "USB PHY";
351 value = reg_usb_read(step->reg);
352 break;
353 }
354 return value;
355}
356
357static void reg_write(struct reg_script_context *ctx)
358{
359 const struct reg_script *step = ctx->step;
360
361 switch (step->id) {
362 default:
363 printk(BIOS_ERR,
364 "ERROR - Unknown register set (0x%08x)!\n",
365 step->id);
366 ctx->display_features = REG_SCRIPT_DISPLAY_NOTHING;
367 return;
368
Lee Leahy5fafc6a2016-07-30 18:21:53 -0700369 case CPU_CR:
370 ctx->display_prefix = "CPU CR";
371 reg_cpu_cr_write(step->reg, step->value);
372 break;
373
Lee Leahy7f4b0532016-05-22 11:52:28 -0700374 case GPE0_REGS:
Lee Leahy6b24dfc2016-05-22 16:24:36 -0700375 ctx->display_prefix = "GPE0";
Lee Leahy7f4b0532016-05-22 11:52:28 -0700376 reg_gpe0_write(step->reg, (uint32_t)step->value);
377 break;
378
Lee Leahy083da162016-05-15 13:32:24 -0700379 case GPIO_REGS:
Lee Leahy6b24dfc2016-05-22 16:24:36 -0700380 ctx->display_prefix = "GPIO";
Lee Leahy083da162016-05-15 13:32:24 -0700381 reg_gpio_write(step->reg, (uint32_t)step->value);
382 break;
383
Lee Leahy660c67a2016-07-10 17:09:24 -0700384 case HOST_BRIDGE:
385 ctx->display_prefix = "Host Bridge";
386 reg_host_bridge_unit_write(step->reg, (uint32_t)step->value);
387 break;
388
Lee Leahy083da162016-05-15 13:32:24 -0700389 case LEG_GPIO_REGS:
Lee Leahy6b24dfc2016-05-22 16:24:36 -0700390 ctx->display_prefix = "Legacy GPIO";
Lee Leahy083da162016-05-15 13:32:24 -0700391 reg_legacy_gpio_write(step->reg, (uint32_t)step->value);
392 break;
393
Lee Leahy5ef051a2016-04-29 15:16:54 -0700394 case PCIE_AFE_REGS:
Lee Leahy6b24dfc2016-05-22 16:24:36 -0700395 ctx->display_prefix = "PCIe AFE";
Lee Leahy5ef051a2016-04-29 15:16:54 -0700396 reg_pcie_afe_write(step->reg, (uint32_t)step->value);
397 break;
398
399 case PCIE_RESET:
400 if (ctx->display_features) {
Lee Leahy6b24dfc2016-05-22 16:24:36 -0700401 ctx->display_prefix = "PCIe reset";
Lee Leahy5ef051a2016-04-29 15:16:54 -0700402 ctx->display_features &= ~REG_SCRIPT_DISPLAY_REGISTER;
403 }
404 mainboard_gpio_pcie_reset(step->value);
405 break;
406
Lee Leahy63e3dff2016-04-30 08:48:52 -0700407 case RMU_TEMP_REGS:
408 ctx->display_prefix = "RMU TEMP";
409 reg_rmu_temp_write(step->reg, (uint32_t)step->value);
410 break;
411
412 case SOC_UNIT_REGS:
413 ctx->display_prefix = "SOC Unit";
414 reg_soc_unit_write(step->reg, (uint32_t)step->value);
415 break;
416
Lee Leahy4c3f5dc2016-04-29 16:36:02 -0700417 case MICROSECOND_DELAY:
418 /* The actual delay is >= the requested delay */
419 if (ctx->display_features) {
420 /* Higher baud-rates will reduce the impact of displaying this message */
421 printk(BIOS_INFO, "Delay %lld uSec\n", step->value);
422 ctx->display_features = REG_SCRIPT_DISPLAY_NOTHING;
423 }
424 udelay(step->value);
425 break;
426
Lee Leahy4dd34ee2016-05-02 14:31:02 -0700427 case USB_PHY_REGS:
428 ctx->display_prefix = "USB PHY";
429 reg_usb_write(step->reg, (uint32_t)step->value);
430 break;
431 }
432}
433
Lee Leahyae738ac2016-07-24 08:03:37 -0700434msr_t soc_msr_read(unsigned index)
435{
436 uint32_t offset;
437 union {
438 uint64_t u64;
439 msr_t msr;
440 } value;
441
442 /* Read the low 32-bits of the register */
443 offset = mtrr_index_to_host_bridge_register_offset(index);
444 value.u64 = port_reg_read(QUARK_NC_HOST_BRIDGE_SB_PORT_ID, offset);
445
446 /* For 64-bit registers, read the upper 32-bits */
447 if ((offset >= QUARK_NC_HOST_BRIDGE_MTRR_FIX64K_00000)
448 && (offset <= QUARK_NC_HOST_BRIDGE_MTRR_FIX4K_F8000)) {
449 offset += 1;
450 value.u64 |= port_reg_read(QUARK_NC_HOST_BRIDGE_SB_PORT_ID,
451 offset);
452 }
453 return value.msr;
454}
455
456void soc_msr_write(unsigned index, msr_t msr)
457{
458 uint32_t offset;
459 union {
460 uint32_t u32[2];
461 msr_t msr;
462 } value;
463
464 /* Write the low 32-bits of the register */
465 value.msr = msr;
466 offset = mtrr_index_to_host_bridge_register_offset(index);
467 port_reg_write(QUARK_NC_HOST_BRIDGE_SB_PORT_ID, offset, value.u32[0]);
468
469 /* For 64-bit registers, write the upper 32-bits */
470 if ((offset >= QUARK_NC_HOST_BRIDGE_MTRR_FIX64K_00000)
471 && (offset <= QUARK_NC_HOST_BRIDGE_MTRR_FIX4K_F8000)) {
472 offset += 1;
473 port_reg_write(QUARK_NC_HOST_BRIDGE_SB_PORT_ID, offset,
474 value.u32[1]);
475 }
476}
477
Lee Leahy4dd34ee2016-05-02 14:31:02 -0700478const struct reg_script_bus_entry soc_reg_script_bus_table = {
479 SOC_TYPE, reg_read, reg_write
480};
481
482REG_SCRIPT_BUS_ENTRY(soc_reg_script_bus_table);