blob: 25a52ff7627cae678c503502606ac6d88ecfd737 [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 Leahy4dd34ee2016-05-02 14:31:02 -070018#include <console/console.h>
19#include <soc/pci_devs.h>
Lee Leahy5ef051a2016-04-29 15:16:54 -070020#include <soc/ramstage.h>
Lee Leahy4dd34ee2016-05-02 14:31:02 -070021
Lee Leahy7f4b0532016-05-22 11:52:28 -070022static uint16_t get_gpe0_address(uint32_t reg_address)
23{
24 uint32_t gpe0_base_address;
25
26 /* Get the GPE0 base address */
27 gpe0_base_address = pci_read_config32(LPC_BDF, R_QNC_LPC_GPE0BLK);
28 ASSERT (gpe0_base_address >= 0x80000000);
29 gpe0_base_address &= B_QNC_LPC_GPE0BLK_MASK;
30
31 /* Return the GPE0 register address */
32 return (uint16_t)(gpe0_base_address + reg_address);
33}
34
Lee Leahyac690b12016-05-15 15:12:56 -070035static uint32_t *get_gpio_address(uint32_t reg_address)
36{
37 uint32_t gpio_base_address;
38
39 /* Get the GPIO base address */
40 gpio_base_address = pci_read_config32(I2CGPIO_BDF, PCI_BASE_ADDRESS_1);
41 gpio_base_address &= ~PCI_BASE_ADDRESS_MEM_ATTR_MASK;
42 ASSERT (gpio_base_address != 0x00000000);
43
44 /* Return the GPIO register address */
45 return (uint32_t *)(gpio_base_address + reg_address);
46}
47
48void *get_i2c_address(void)
49{
50 uint32_t gpio_base_address;
51
52 /* Get the GPIO base address */
53 gpio_base_address = pci_read_config32(I2CGPIO_BDF, PCI_BASE_ADDRESS_0);
54 gpio_base_address &= ~PCI_BASE_ADDRESS_MEM_ATTR_MASK;
55 ASSERT (gpio_base_address != 0x00000000);
56
57 /* Return the GPIO register address */
58 return (void *)gpio_base_address;
59}
60
61static uint16_t get_legacy_gpio_address(uint32_t reg_address)
62{
63 uint32_t gpio_base_address;
64
65 /* Get the GPIO base address */
66 gpio_base_address = pci_read_config32(LPC_BDF, R_QNC_LPC_GBA_BASE);
67 ASSERT (gpio_base_address >= 0x80000000);
68 gpio_base_address &= B_QNC_LPC_GPA_BASE_MASK;
69
70 /* Return the GPIO register address */
71 return (uint16_t)(gpio_base_address + reg_address);
72}
73
Lee Leahy4dd34ee2016-05-02 14:31:02 -070074void mcr_write(uint8_t opcode, uint8_t port, uint32_t reg_address)
75{
76 pci_write_config32(MC_BDF, QNC_ACCESS_PORT_MCR,
77 (opcode << QNC_MCR_OP_OFFSET)
78 | ((uint32_t)port << QNC_MCR_PORT_OFFSET)
79 | ((reg_address & QNC_MCR_MASK) << QNC_MCR_REG_OFFSET)
80 | QNC_MCR_BYTE_ENABLES);
81}
82
83uint32_t mdr_read(void)
84{
85 return pci_read_config32(MC_BDF, QNC_ACCESS_PORT_MDR);
86}
87
88void mdr_write(uint32_t value)
89{
90 pci_write_config32(MC_BDF, QNC_ACCESS_PORT_MDR, value);
91}
92
93void mea_write(uint32_t reg_address)
94{
95 pci_write_config32(MC_BDF, QNC_ACCESS_PORT_MEA, reg_address
96 & QNC_MEA_MASK);
97}
98
Lee Leahy7f4b0532016-05-22 11:52:28 -070099static uint32_t reg_gpe0_read(uint32_t reg_address)
100{
101 /* Read the GPE0 register */
102 return inl(get_gpe0_address(reg_address));
103}
104
105static void reg_gpe0_write(uint32_t reg_address, uint32_t value)
106{
107 /* Write the GPE0 register */
108 outl(get_gpe0_address(reg_address), value);
109}
110
Lee Leahy083da162016-05-15 13:32:24 -0700111static uint32_t reg_gpio_read(uint32_t reg_address)
112{
113 /* Read the GPIO register */
114 return *get_gpio_address(reg_address);
115}
116
117static void reg_gpio_write(uint32_t reg_address, uint32_t value)
118{
119 /* Write the GPIO register */
120 *get_gpio_address(reg_address) = value;
121}
122
Lee Leahy660c67a2016-07-10 17:09:24 -0700123uint32_t reg_host_bridge_unit_read(uint32_t reg_address)
124{
125 /* Read the host bridge register */
126 mea_write(reg_address);
127 mcr_write(QUARK_OPCODE_READ, QUARK_NC_HOST_BRIDGE_SB_PORT_ID,
128 reg_address);
129 return mdr_read();
130}
131
132static void reg_host_bridge_unit_write(uint32_t reg_address, uint32_t value)
133{
134 /* Write the host bridge register */
135 mea_write(reg_address);
136 mdr_write(value);
137 mcr_write(QUARK_OPCODE_WRITE, QUARK_NC_HOST_BRIDGE_SB_PORT_ID,
138 reg_address);
139}
140
Lee Leahy083da162016-05-15 13:32:24 -0700141uint32_t reg_legacy_gpio_read(uint32_t reg_address)
142{
143 /* Read the legacy GPIO register */
144 return inl(get_legacy_gpio_address(reg_address));
145}
146
147void reg_legacy_gpio_write(uint32_t reg_address, uint32_t value)
148{
149 /* Write the legacy GPIO register */
150 outl(value, get_legacy_gpio_address(reg_address));
151}
152
Lee Leahy5ef051a2016-04-29 15:16:54 -0700153static uint32_t reg_pcie_afe_read(uint32_t reg_address)
154{
155 /* Read the PCIE AFE register */
156 mea_write(reg_address);
157 mcr_write(QUARK_OPCODE_IO_READ, QUARK_SC_PCIE_AFE_SB_PORT_ID,
158 reg_address);
159 return mdr_read();
160}
161
162static void reg_pcie_afe_write(uint32_t reg_address, uint32_t value)
163{
164 /* Write the PCIE AFE register */
165 mea_write(reg_address);
166 mdr_write(value);
167 mcr_write(QUARK_OPCODE_IO_WRITE, QUARK_SC_PCIE_AFE_SB_PORT_ID,
168 reg_address);
169}
170
Lee Leahy63e3dff2016-04-30 08:48:52 -0700171uint32_t reg_rmu_temp_read(uint32_t reg_address)
172{
173 /* Read the RMU temperature register */
174 mea_write(reg_address);
175 mcr_write(QUARK_OPCODE_READ, QUARK_NC_RMU_SB_PORT_ID, reg_address);
176 return mdr_read();
177}
178
179static void reg_rmu_temp_write(uint32_t reg_address, uint32_t value)
180{
181 /* Write the RMU temperature register */
182 mea_write(reg_address);
183 mdr_write(value);
184 mcr_write(QUARK_OPCODE_WRITE, QUARK_NC_RMU_SB_PORT_ID, reg_address);
185}
186
187static uint32_t reg_soc_unit_read(uint32_t reg_address)
188{
189 /* Read the temperature sensor register */
190 mea_write(reg_address);
191 mcr_write(QUARK_ALT_OPCODE_READ, QUARK_SCSS_SOC_UNIT_SB_PORT_ID,
192 reg_address);
193 return mdr_read();
194}
195
196static void reg_soc_unit_write(uint32_t reg_address, uint32_t value)
197{
198 /* Write the temperature sensor register */
199 mea_write(reg_address);
200 mdr_write(value);
201 mcr_write(QUARK_ALT_OPCODE_WRITE, QUARK_SCSS_SOC_UNIT_SB_PORT_ID,
202 reg_address);
203}
204
Lee Leahy4dd34ee2016-05-02 14:31:02 -0700205static uint32_t reg_usb_read(uint32_t reg_address)
206{
207 /* Read the USB register */
208 mea_write(reg_address);
209 mcr_write(QUARK_ALT_OPCODE_READ, QUARK_SC_USB_AFE_SB_PORT_ID,
210 reg_address);
211 return mdr_read();
212}
213
214static void reg_usb_write(uint32_t reg_address, uint32_t value)
215{
216 /* Write the USB register */
217 mea_write(reg_address);
218 mdr_write(value);
219 mcr_write(QUARK_ALT_OPCODE_WRITE, QUARK_SC_USB_AFE_SB_PORT_ID,
220 reg_address);
221}
222
223static uint64_t reg_read(struct reg_script_context *ctx)
224{
225 const struct reg_script *step = ctx->step;
226 uint64_t value = 0;
227
228 switch (step->id) {
229 default:
230 printk(BIOS_ERR,
231 "ERROR - Unknown register set (0x%08x)!\n",
232 step->id);
233 ctx->display_features = REG_SCRIPT_DISPLAY_NOTHING;
234 return 0;
235
Lee Leahy7f4b0532016-05-22 11:52:28 -0700236 case GPE0_REGS:
Lee Leahy6b24dfc2016-05-22 16:24:36 -0700237 ctx->display_prefix = "GPE0";
Lee Leahy7f4b0532016-05-22 11:52:28 -0700238 value = reg_gpe0_read(step->reg);
239 break;
240
Lee Leahy083da162016-05-15 13:32:24 -0700241 case GPIO_REGS:
Lee Leahy6b24dfc2016-05-22 16:24:36 -0700242 ctx->display_prefix = "GPIO";
Lee Leahy083da162016-05-15 13:32:24 -0700243 value = reg_gpio_read(step->reg);
244 break;
245
Lee Leahy660c67a2016-07-10 17:09:24 -0700246 case HOST_BRIDGE:
247 ctx->display_prefix = "Host Bridge";
248 value = reg_host_bridge_unit_read(step->reg);
249 break;
250
Lee Leahy083da162016-05-15 13:32:24 -0700251 case LEG_GPIO_REGS:
Lee Leahy6b24dfc2016-05-22 16:24:36 -0700252 ctx->display_prefix = "Legacy GPIO";
Lee Leahy083da162016-05-15 13:32:24 -0700253 value = reg_legacy_gpio_read(step->reg);
Lee Leahyb06724022016-07-18 10:39:55 -0700254 break;
Lee Leahy5ef051a2016-04-29 15:16:54 -0700255
256 case PCIE_AFE_REGS:
Lee Leahy6b24dfc2016-05-22 16:24:36 -0700257 ctx->display_prefix = "PCIe AFE";
Lee Leahy5ef051a2016-04-29 15:16:54 -0700258 value = reg_pcie_afe_read(step->reg);
Lee Leahy083da162016-05-15 13:32:24 -0700259 break;
260
Lee Leahy63e3dff2016-04-30 08:48:52 -0700261 case RMU_TEMP_REGS:
262 ctx->display_prefix = "RMU TEMP";
263 value = reg_rmu_temp_read(step->reg);
264 break;
265
266 case SOC_UNIT_REGS:
267 ctx->display_prefix = "SOC Unit";
268 value = reg_soc_unit_read(step->reg);
269 break;
270
Lee Leahy4dd34ee2016-05-02 14:31:02 -0700271 case USB_PHY_REGS:
272 ctx->display_prefix = "USB PHY";
273 value = reg_usb_read(step->reg);
274 break;
275 }
276 return value;
277}
278
279static void reg_write(struct reg_script_context *ctx)
280{
281 const struct reg_script *step = ctx->step;
282
283 switch (step->id) {
284 default:
285 printk(BIOS_ERR,
286 "ERROR - Unknown register set (0x%08x)!\n",
287 step->id);
288 ctx->display_features = REG_SCRIPT_DISPLAY_NOTHING;
289 return;
290
Lee Leahy7f4b0532016-05-22 11:52:28 -0700291 case GPE0_REGS:
Lee Leahy6b24dfc2016-05-22 16:24:36 -0700292 ctx->display_prefix = "GPE0";
Lee Leahy7f4b0532016-05-22 11:52:28 -0700293 reg_gpe0_write(step->reg, (uint32_t)step->value);
294 break;
295
Lee Leahy083da162016-05-15 13:32:24 -0700296 case GPIO_REGS:
Lee Leahy6b24dfc2016-05-22 16:24:36 -0700297 ctx->display_prefix = "GPIO";
Lee Leahy083da162016-05-15 13:32:24 -0700298 reg_gpio_write(step->reg, (uint32_t)step->value);
299 break;
300
Lee Leahy660c67a2016-07-10 17:09:24 -0700301 case HOST_BRIDGE:
302 ctx->display_prefix = "Host Bridge";
303 reg_host_bridge_unit_write(step->reg, (uint32_t)step->value);
304 break;
305
Lee Leahy083da162016-05-15 13:32:24 -0700306 case LEG_GPIO_REGS:
Lee Leahy6b24dfc2016-05-22 16:24:36 -0700307 ctx->display_prefix = "Legacy GPIO";
Lee Leahy083da162016-05-15 13:32:24 -0700308 reg_legacy_gpio_write(step->reg, (uint32_t)step->value);
309 break;
310
Lee Leahy5ef051a2016-04-29 15:16:54 -0700311 case PCIE_AFE_REGS:
Lee Leahy6b24dfc2016-05-22 16:24:36 -0700312 ctx->display_prefix = "PCIe AFE";
Lee Leahy5ef051a2016-04-29 15:16:54 -0700313 reg_pcie_afe_write(step->reg, (uint32_t)step->value);
314 break;
315
316 case PCIE_RESET:
317 if (ctx->display_features) {
Lee Leahy6b24dfc2016-05-22 16:24:36 -0700318 ctx->display_prefix = "PCIe reset";
Lee Leahy5ef051a2016-04-29 15:16:54 -0700319 ctx->display_features &= ~REG_SCRIPT_DISPLAY_REGISTER;
320 }
321 mainboard_gpio_pcie_reset(step->value);
322 break;
323
Lee Leahy63e3dff2016-04-30 08:48:52 -0700324 case RMU_TEMP_REGS:
325 ctx->display_prefix = "RMU TEMP";
326 reg_rmu_temp_write(step->reg, (uint32_t)step->value);
327 break;
328
329 case SOC_UNIT_REGS:
330 ctx->display_prefix = "SOC Unit";
331 reg_soc_unit_write(step->reg, (uint32_t)step->value);
332 break;
333
Lee Leahy4c3f5dc2016-04-29 16:36:02 -0700334 case MICROSECOND_DELAY:
335 /* The actual delay is >= the requested delay */
336 if (ctx->display_features) {
337 /* Higher baud-rates will reduce the impact of displaying this message */
338 printk(BIOS_INFO, "Delay %lld uSec\n", step->value);
339 ctx->display_features = REG_SCRIPT_DISPLAY_NOTHING;
340 }
341 udelay(step->value);
342 break;
343
Lee Leahy4dd34ee2016-05-02 14:31:02 -0700344 case USB_PHY_REGS:
345 ctx->display_prefix = "USB PHY";
346 reg_usb_write(step->reg, (uint32_t)step->value);
347 break;
348 }
349}
350
351const struct reg_script_bus_entry soc_reg_script_bus_table = {
352 SOC_TYPE, reg_read, reg_write
353};
354
355REG_SCRIPT_BUS_ENTRY(soc_reg_script_bus_table);