blob: 48d55210d3628eb76521a8f268dbe6f131d1ba9b [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
18#include <arch/io.h>
19#include <console/console.h>
20#include <soc/pci_devs.h>
21#include <soc/reg_access.h>
22
23void mcr_write(uint8_t opcode, uint8_t port, uint32_t reg_address)
24{
25 pci_write_config32(MC_BDF, QNC_ACCESS_PORT_MCR,
26 (opcode << QNC_MCR_OP_OFFSET)
27 | ((uint32_t)port << QNC_MCR_PORT_OFFSET)
28 | ((reg_address & QNC_MCR_MASK) << QNC_MCR_REG_OFFSET)
29 | QNC_MCR_BYTE_ENABLES);
30}
31
32uint32_t mdr_read(void)
33{
34 return pci_read_config32(MC_BDF, QNC_ACCESS_PORT_MDR);
35}
36
37void mdr_write(uint32_t value)
38{
39 pci_write_config32(MC_BDF, QNC_ACCESS_PORT_MDR, value);
40}
41
42void mea_write(uint32_t reg_address)
43{
44 pci_write_config32(MC_BDF, QNC_ACCESS_PORT_MEA, reg_address
45 & QNC_MEA_MASK);
46}
47
Lee Leahy083da162016-05-15 13:32:24 -070048static uint32_t *get_gpio_address(uint32_t reg_address)
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_1);
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 (uint32_t *)(gpio_base_address + reg_address);
59}
60
61static uint32_t reg_gpio_read(uint32_t reg_address)
62{
63 /* Read the GPIO register */
64 return *get_gpio_address(reg_address);
65}
66
67static void reg_gpio_write(uint32_t reg_address, uint32_t value)
68{
69 /* Write the GPIO register */
70 *get_gpio_address(reg_address) = value;
71}
72
73static uint16_t get_legacy_gpio_address(uint32_t reg_address)
74{
75 uint32_t gpio_base_address;
76
77 /* Get the GPIO base address */
78 gpio_base_address = pci_read_config32(LPC_BDF, R_QNC_LPC_GBA_BASE);
79 ASSERT (gpio_base_address >= 0x80000000);
80 gpio_base_address &= B_QNC_LPC_GPA_BASE_MASK;
81
82 /* Return the GPIO register address */
83 return (uint16_t)(gpio_base_address + reg_address);
84}
85
86uint32_t reg_legacy_gpio_read(uint32_t reg_address)
87{
88 /* Read the legacy GPIO register */
89 return inl(get_legacy_gpio_address(reg_address));
90}
91
92void reg_legacy_gpio_write(uint32_t reg_address, uint32_t value)
93{
94 /* Write the legacy GPIO register */
95 outl(value, get_legacy_gpio_address(reg_address));
96}
97
Lee Leahy63e3dff2016-04-30 08:48:52 -070098uint32_t reg_rmu_temp_read(uint32_t reg_address)
99{
100 /* Read the RMU temperature register */
101 mea_write(reg_address);
102 mcr_write(QUARK_OPCODE_READ, QUARK_NC_RMU_SB_PORT_ID, reg_address);
103 return mdr_read();
104}
105
106static void reg_rmu_temp_write(uint32_t reg_address, uint32_t value)
107{
108 /* Write the RMU temperature register */
109 mea_write(reg_address);
110 mdr_write(value);
111 mcr_write(QUARK_OPCODE_WRITE, QUARK_NC_RMU_SB_PORT_ID, reg_address);
112}
113
114static uint32_t reg_soc_unit_read(uint32_t reg_address)
115{
116 /* Read the temperature sensor register */
117 mea_write(reg_address);
118 mcr_write(QUARK_ALT_OPCODE_READ, QUARK_SCSS_SOC_UNIT_SB_PORT_ID,
119 reg_address);
120 return mdr_read();
121}
122
123static void reg_soc_unit_write(uint32_t reg_address, uint32_t value)
124{
125 /* Write the temperature sensor register */
126 mea_write(reg_address);
127 mdr_write(value);
128 mcr_write(QUARK_ALT_OPCODE_WRITE, QUARK_SCSS_SOC_UNIT_SB_PORT_ID,
129 reg_address);
130}
131
Lee Leahy4dd34ee2016-05-02 14:31:02 -0700132static uint32_t reg_usb_read(uint32_t reg_address)
133{
134 /* Read the USB register */
135 mea_write(reg_address);
136 mcr_write(QUARK_ALT_OPCODE_READ, QUARK_SC_USB_AFE_SB_PORT_ID,
137 reg_address);
138 return mdr_read();
139}
140
141static void reg_usb_write(uint32_t reg_address, uint32_t value)
142{
143 /* Write the USB register */
144 mea_write(reg_address);
145 mdr_write(value);
146 mcr_write(QUARK_ALT_OPCODE_WRITE, QUARK_SC_USB_AFE_SB_PORT_ID,
147 reg_address);
148}
149
150static uint64_t reg_read(struct reg_script_context *ctx)
151{
152 const struct reg_script *step = ctx->step;
153 uint64_t value = 0;
154
155 switch (step->id) {
156 default:
157 printk(BIOS_ERR,
158 "ERROR - Unknown register set (0x%08x)!\n",
159 step->id);
160 ctx->display_features = REG_SCRIPT_DISPLAY_NOTHING;
161 return 0;
162
Lee Leahy083da162016-05-15 13:32:24 -0700163 case GPIO_REGS:
164 ctx->display_prefix = "GPIO: ";
165 value = reg_gpio_read(step->reg);
166 break;
167
168 case LEG_GPIO_REGS:
169 ctx->display_prefix = "Legacy GPIO: ";
170 value = reg_legacy_gpio_read(step->reg);
171 break;
172
Lee Leahy63e3dff2016-04-30 08:48:52 -0700173 case RMU_TEMP_REGS:
174 ctx->display_prefix = "RMU TEMP";
175 value = reg_rmu_temp_read(step->reg);
176 break;
177
178 case SOC_UNIT_REGS:
179 ctx->display_prefix = "SOC Unit";
180 value = reg_soc_unit_read(step->reg);
181 break;
182
Lee Leahy4dd34ee2016-05-02 14:31:02 -0700183 case USB_PHY_REGS:
184 ctx->display_prefix = "USB PHY";
185 value = reg_usb_read(step->reg);
186 break;
187 }
188 return value;
189}
190
191static void reg_write(struct reg_script_context *ctx)
192{
193 const struct reg_script *step = ctx->step;
194
195 switch (step->id) {
196 default:
197 printk(BIOS_ERR,
198 "ERROR - Unknown register set (0x%08x)!\n",
199 step->id);
200 ctx->display_features = REG_SCRIPT_DISPLAY_NOTHING;
201 return;
202
Lee Leahy083da162016-05-15 13:32:24 -0700203 case GPIO_REGS:
204 ctx->display_prefix = "GPIO: ";
205 reg_gpio_write(step->reg, (uint32_t)step->value);
206 break;
207
208 case LEG_GPIO_REGS:
209 ctx->display_prefix = "Legacy GPIO: ";
210 reg_legacy_gpio_write(step->reg, (uint32_t)step->value);
211 break;
212
Lee Leahy63e3dff2016-04-30 08:48:52 -0700213 case RMU_TEMP_REGS:
214 ctx->display_prefix = "RMU TEMP";
215 reg_rmu_temp_write(step->reg, (uint32_t)step->value);
216 break;
217
218 case SOC_UNIT_REGS:
219 ctx->display_prefix = "SOC Unit";
220 reg_soc_unit_write(step->reg, (uint32_t)step->value);
221 break;
222
Lee Leahy4c3f5dc2016-04-29 16:36:02 -0700223 case MICROSECOND_DELAY:
224 /* The actual delay is >= the requested delay */
225 if (ctx->display_features) {
226 /* Higher baud-rates will reduce the impact of displaying this message */
227 printk(BIOS_INFO, "Delay %lld uSec\n", step->value);
228 ctx->display_features = REG_SCRIPT_DISPLAY_NOTHING;
229 }
230 udelay(step->value);
231 break;
232
Lee Leahy4dd34ee2016-05-02 14:31:02 -0700233 case USB_PHY_REGS:
234 ctx->display_prefix = "USB PHY";
235 reg_usb_write(step->reg, (uint32_t)step->value);
236 break;
237 }
238}
239
240const struct reg_script_bus_entry soc_reg_script_bus_table = {
241 SOC_TYPE, reg_read, reg_write
242};
243
244REG_SCRIPT_BUS_ENTRY(soc_reg_script_bus_table);