blob: 4734135b2c54a572c9dd84b4d5331165278da37a [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
Lee Leahyac690b12016-05-15 15:12:56 -070023static uint32_t *get_gpio_address(uint32_t reg_address)
24{
25 uint32_t gpio_base_address;
26
27 /* Get the GPIO base address */
28 gpio_base_address = pci_read_config32(I2CGPIO_BDF, PCI_BASE_ADDRESS_1);
29 gpio_base_address &= ~PCI_BASE_ADDRESS_MEM_ATTR_MASK;
30 ASSERT (gpio_base_address != 0x00000000);
31
32 /* Return the GPIO register address */
33 return (uint32_t *)(gpio_base_address + reg_address);
34}
35
36void *get_i2c_address(void)
37{
38 uint32_t gpio_base_address;
39
40 /* Get the GPIO base address */
41 gpio_base_address = pci_read_config32(I2CGPIO_BDF, PCI_BASE_ADDRESS_0);
42 gpio_base_address &= ~PCI_BASE_ADDRESS_MEM_ATTR_MASK;
43 ASSERT (gpio_base_address != 0x00000000);
44
45 /* Return the GPIO register address */
46 return (void *)gpio_base_address;
47}
48
49static uint16_t get_legacy_gpio_address(uint32_t reg_address)
50{
51 uint32_t gpio_base_address;
52
53 /* Get the GPIO base address */
54 gpio_base_address = pci_read_config32(LPC_BDF, R_QNC_LPC_GBA_BASE);
55 ASSERT (gpio_base_address >= 0x80000000);
56 gpio_base_address &= B_QNC_LPC_GPA_BASE_MASK;
57
58 /* Return the GPIO register address */
59 return (uint16_t)(gpio_base_address + reg_address);
60}
61
Lee Leahy4dd34ee2016-05-02 14:31:02 -070062void mcr_write(uint8_t opcode, uint8_t port, uint32_t reg_address)
63{
64 pci_write_config32(MC_BDF, QNC_ACCESS_PORT_MCR,
65 (opcode << QNC_MCR_OP_OFFSET)
66 | ((uint32_t)port << QNC_MCR_PORT_OFFSET)
67 | ((reg_address & QNC_MCR_MASK) << QNC_MCR_REG_OFFSET)
68 | QNC_MCR_BYTE_ENABLES);
69}
70
71uint32_t mdr_read(void)
72{
73 return pci_read_config32(MC_BDF, QNC_ACCESS_PORT_MDR);
74}
75
76void mdr_write(uint32_t value)
77{
78 pci_write_config32(MC_BDF, QNC_ACCESS_PORT_MDR, value);
79}
80
81void mea_write(uint32_t reg_address)
82{
83 pci_write_config32(MC_BDF, QNC_ACCESS_PORT_MEA, reg_address
84 & QNC_MEA_MASK);
85}
86
Lee Leahy083da162016-05-15 13:32:24 -070087static uint32_t reg_gpio_read(uint32_t reg_address)
88{
89 /* Read the GPIO register */
90 return *get_gpio_address(reg_address);
91}
92
93static void reg_gpio_write(uint32_t reg_address, uint32_t value)
94{
95 /* Write the GPIO register */
96 *get_gpio_address(reg_address) = value;
97}
98
Lee Leahy083da162016-05-15 13:32:24 -070099uint32_t reg_legacy_gpio_read(uint32_t reg_address)
100{
101 /* Read the legacy GPIO register */
102 return inl(get_legacy_gpio_address(reg_address));
103}
104
105void reg_legacy_gpio_write(uint32_t reg_address, uint32_t value)
106{
107 /* Write the legacy GPIO register */
108 outl(value, get_legacy_gpio_address(reg_address));
109}
110
Lee Leahy63e3dff2016-04-30 08:48:52 -0700111uint32_t reg_rmu_temp_read(uint32_t reg_address)
112{
113 /* Read the RMU temperature register */
114 mea_write(reg_address);
115 mcr_write(QUARK_OPCODE_READ, QUARK_NC_RMU_SB_PORT_ID, reg_address);
116 return mdr_read();
117}
118
119static void reg_rmu_temp_write(uint32_t reg_address, uint32_t value)
120{
121 /* Write the RMU temperature register */
122 mea_write(reg_address);
123 mdr_write(value);
124 mcr_write(QUARK_OPCODE_WRITE, QUARK_NC_RMU_SB_PORT_ID, reg_address);
125}
126
127static uint32_t reg_soc_unit_read(uint32_t reg_address)
128{
129 /* Read the temperature sensor register */
130 mea_write(reg_address);
131 mcr_write(QUARK_ALT_OPCODE_READ, QUARK_SCSS_SOC_UNIT_SB_PORT_ID,
132 reg_address);
133 return mdr_read();
134}
135
136static void reg_soc_unit_write(uint32_t reg_address, uint32_t value)
137{
138 /* Write the temperature sensor register */
139 mea_write(reg_address);
140 mdr_write(value);
141 mcr_write(QUARK_ALT_OPCODE_WRITE, QUARK_SCSS_SOC_UNIT_SB_PORT_ID,
142 reg_address);
143}
144
Lee Leahy4dd34ee2016-05-02 14:31:02 -0700145static uint32_t reg_usb_read(uint32_t reg_address)
146{
147 /* Read the USB register */
148 mea_write(reg_address);
149 mcr_write(QUARK_ALT_OPCODE_READ, QUARK_SC_USB_AFE_SB_PORT_ID,
150 reg_address);
151 return mdr_read();
152}
153
154static void reg_usb_write(uint32_t reg_address, uint32_t value)
155{
156 /* Write the USB register */
157 mea_write(reg_address);
158 mdr_write(value);
159 mcr_write(QUARK_ALT_OPCODE_WRITE, QUARK_SC_USB_AFE_SB_PORT_ID,
160 reg_address);
161}
162
163static uint64_t reg_read(struct reg_script_context *ctx)
164{
165 const struct reg_script *step = ctx->step;
166 uint64_t value = 0;
167
168 switch (step->id) {
169 default:
170 printk(BIOS_ERR,
171 "ERROR - Unknown register set (0x%08x)!\n",
172 step->id);
173 ctx->display_features = REG_SCRIPT_DISPLAY_NOTHING;
174 return 0;
175
Lee Leahy083da162016-05-15 13:32:24 -0700176 case GPIO_REGS:
177 ctx->display_prefix = "GPIO: ";
178 value = reg_gpio_read(step->reg);
179 break;
180
181 case LEG_GPIO_REGS:
182 ctx->display_prefix = "Legacy GPIO: ";
183 value = reg_legacy_gpio_read(step->reg);
184 break;
185
Lee Leahy63e3dff2016-04-30 08:48:52 -0700186 case RMU_TEMP_REGS:
187 ctx->display_prefix = "RMU TEMP";
188 value = reg_rmu_temp_read(step->reg);
189 break;
190
191 case SOC_UNIT_REGS:
192 ctx->display_prefix = "SOC Unit";
193 value = reg_soc_unit_read(step->reg);
194 break;
195
Lee Leahy4dd34ee2016-05-02 14:31:02 -0700196 case USB_PHY_REGS:
197 ctx->display_prefix = "USB PHY";
198 value = reg_usb_read(step->reg);
199 break;
200 }
201 return value;
202}
203
204static void reg_write(struct reg_script_context *ctx)
205{
206 const struct reg_script *step = ctx->step;
207
208 switch (step->id) {
209 default:
210 printk(BIOS_ERR,
211 "ERROR - Unknown register set (0x%08x)!\n",
212 step->id);
213 ctx->display_features = REG_SCRIPT_DISPLAY_NOTHING;
214 return;
215
Lee Leahy083da162016-05-15 13:32:24 -0700216 case GPIO_REGS:
217 ctx->display_prefix = "GPIO: ";
218 reg_gpio_write(step->reg, (uint32_t)step->value);
219 break;
220
221 case LEG_GPIO_REGS:
222 ctx->display_prefix = "Legacy GPIO: ";
223 reg_legacy_gpio_write(step->reg, (uint32_t)step->value);
224 break;
225
Lee Leahy63e3dff2016-04-30 08:48:52 -0700226 case RMU_TEMP_REGS:
227 ctx->display_prefix = "RMU TEMP";
228 reg_rmu_temp_write(step->reg, (uint32_t)step->value);
229 break;
230
231 case SOC_UNIT_REGS:
232 ctx->display_prefix = "SOC Unit";
233 reg_soc_unit_write(step->reg, (uint32_t)step->value);
234 break;
235
Lee Leahy4c3f5dc2016-04-29 16:36:02 -0700236 case MICROSECOND_DELAY:
237 /* The actual delay is >= the requested delay */
238 if (ctx->display_features) {
239 /* Higher baud-rates will reduce the impact of displaying this message */
240 printk(BIOS_INFO, "Delay %lld uSec\n", step->value);
241 ctx->display_features = REG_SCRIPT_DISPLAY_NOTHING;
242 }
243 udelay(step->value);
244 break;
245
Lee Leahy4dd34ee2016-05-02 14:31:02 -0700246 case USB_PHY_REGS:
247 ctx->display_prefix = "USB PHY";
248 reg_usb_write(step->reg, (uint32_t)step->value);
249 break;
250 }
251}
252
253const struct reg_script_bus_entry soc_reg_script_bus_table = {
254 SOC_TYPE, reg_read, reg_write
255};
256
257REG_SCRIPT_BUS_ENTRY(soc_reg_script_bus_table);