95ed7368f96e94c38bd7143231df1b2473008197
[coreboot.git] / src / mainboard / arima / hdama / mainboard.c
1 #include <console/console.h>
2 #include <device/device.h>
3 #include <device/pci.h>
4 #include <device/pci_ids.h>
5 #include <device/pci_ops.h>
6 #include <cpu/x86/msr.h>
7 #include <part/hard_reset.h>
8 #include <device/smbus.h>
9 #include <delay.h>
10
11 #include <arch/io.h>
12 #include "../../../northbridge/amd/amdk8/northbridge.h"
13 #include "../../../northbridge/amd/amdk8/cpu_rev.c"
14 #include "chip.h"
15
16 #include "pc80/mc146818rtc.h"
17
18
19 #undef DEBUG
20 #define DEBUG 0
21 #if DEBUG 
22 static void debug_init(device_t dev)
23 {
24         unsigned bus;
25         unsigned devfn;
26 #if 0
27         for(bus = 0; bus < 256; bus++) {
28                 for(devfn = 0; devfn < 256; devfn++) {
29                         int i;
30                         dev = dev_find_slot(bus, devfn);
31                         if (!dev) {
32                                 continue;
33                         }
34                         if (!dev->enabled) {
35                                 continue;
36                         }
37                         printk_info("%02x:%02x.%0x aka %s\n", 
38                                 bus, devfn >> 3, devfn & 7, dev_path(dev));
39                         for(i = 0; i < 256; i++) {
40                                 if ((i & 0x0f) == 0) {
41                                         printk_info("%02x:", i);
42                                 }
43                                 printk_info(" %02x", pci_read_config8(dev, i));
44                                 if ((i & 0x0f) == 0xf) {
45                                         printk_info("\n");
46                                 }
47                         }
48                         printk_info("\n");
49                 }
50         }
51 #endif
52 #if 0
53         msr_t msr;
54         unsigned index;
55         unsigned eax, ebx, ecx, edx;
56         index = 0x80000007;
57         printk_debug("calling cpuid 0x%08x\n", index);
58         asm volatile(
59                 "cpuid"
60                 : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx)
61                 : "a" (index)
62                 );
63         printk_debug("cpuid[%08x]: %08x %08x %08x %08x\n",
64                 index, eax, ebx, ecx, edx);
65         if (edx & (3 << 1)) {
66                 index = 0xC0010042;
67                 printk_debug("Reading msr: 0x%08x\n", index);
68                 msr = rdmsr(index);
69                 printk_debug("msr[0x%08x]: 0x%08x%08x\n",
70                         index, msr.hi, msr.hi);
71         }
72 #endif
73 }
74
75 static void debug_noop(device_t dummy)
76 {
77 }
78
79 static struct device_operations debug_operations = {
80         .read_resources   = debug_noop,
81         .set_resources    = debug_noop,
82         .enable_resources = debug_noop,
83         .init             = debug_init,
84 };
85
86 static unsigned int scan_root_bus(device_t root, unsigned int max)
87 {
88         struct device_path path;
89         device_t debug;
90         max = root_dev_scan_bus(root, max);
91         path.type = DEVICE_PATH_PNP;
92         path.u.pnp.port   = 0;
93         path.u.pnp.device = 0;
94         debug = alloc_dev(&root->link[1], &path);
95         debug->ops = &debug_operations;
96         return max;
97 }
98 #endif
99
100 #if 0
101 static void handle_smbus_error(int value, const char *msg)
102 {
103         if (value >= 0) {
104                 return;
105         }
106         switch(value) {
107         case SMBUS_WAIT_UNTIL_READY_TIMEOUT:
108                 printk_emerg("SMBUS wait until ready timed out - resetting...");
109                 hard_reset();
110                 break;
111         case SMBUS_WAIT_UNTIL_DONE_TIMEOUT:
112                 printk_emerg("SMBUS wait until done timed out - resetting...");
113                 hard_reset();
114                 break;
115         default:
116                 die(msg);
117                 break;
118         }
119 }
120
121 #define ADM1026_DEVICE 0x2c /* 0x2e or 0x2d */
122 #define ADM1026_REG_CONFIG1 0x00
123 #define CFG1_MONITOR     0x01
124 #define CFG1_INT_ENABLE  0x02
125 #define CFG1_INT_CLEAR   0x04
126 #define CFG1_AIN8_9      0x08
127 #define CFG1_THERM_HOT   0x10
128 #define CFT1_DAC_AFC     0x20
129 #define CFG1_PWM_AFC     0x40
130 #define CFG1_RESET       0x80
131 #define ADM1026_REG_CONFIG2 0x01
132 #define ADM1026_REG_CONFIG3 0x07
133
134
135
136 #define BILLION 1000000000UL
137
138 static void  verify_cpu_voltage(const char *name, 
139         device_t dev, unsigned int reg, 
140         unsigned factor, unsigned cpu_volts, unsigned delta)
141 {
142         unsigned nvolts_lo, nvolts_hi;
143         unsigned cpuvolts_hi, cpuvolts_lo;
144         int value;
145         int loops;
146
147         loops = 1000;
148         do {
149                 value = smbus_read_byte(dev, reg);
150                 handle_smbus_error(value, "SMBUS read byte failed");
151         } while ((--loops > 0) && value == 0);
152         /* Convert the byte value to nanoVolts.
153          * My accuracy is nowhere near that good but I don't
154          * have to round so the math is simple. 
155          * I can only go up to about 4.2 Volts this way so my range is
156          * limited.
157          */
158         nvolts_lo = ((unsigned)value * factor);
159         nvolts_hi = nvolts_lo + factor - 1;
160         /* Get the range of acceptable cpu voltage values */
161         cpuvolts_lo = cpu_volts - delta;
162         cpuvolts_hi = cpu_volts + delta;
163         if ((nvolts_lo < cpuvolts_lo) || (nvolts_hi > cpuvolts_hi)) {
164                 printk_emerg("%s at (%u.%09u-%u.%09u)Volts expected %u.%09u+/-%u.%09uVolts\n",
165                         name,
166                         nvolts_lo/BILLION, nvolts_lo%BILLION,
167                         nvolts_hi/BILLION, nvolts_hi%BILLION,
168                         cpu_volts/BILLION, cpu_volts%BILLION,
169                         delta/BILLION, delta%BILLION);
170                 die("");
171         }
172         printk_info("%s at (%u.%09u-%u.%09u)Volts\n",
173                 name,
174                 nvolts_lo/BILLION, nvolts_lo%BILLION,
175                 nvolts_hi/BILLION, nvolts_hi%BILLION);
176                 
177 }
178
179 static void adm1026_enable_monitoring(device_t dev)
180 {
181         int result;
182         result = smbus_read_byte(dev, ADM1026_REG_CONFIG1);
183         handle_smbus_error(result, "ADM1026: cannot read config1");
184
185         result = (result | CFG1_MONITOR) & ~(CFG1_INT_CLEAR | CFG1_RESET);
186         result = smbus_write_byte(dev, ADM1026_REG_CONFIG1, result);
187         handle_smbus_error(result, "ADM1026: cannot write to config1");
188
189         result = smbus_read_byte(dev, ADM1026_REG_CONFIG1);
190         handle_smbus_error(result, "ADM1026: cannot reread config1");
191         if (!(result & CFG1_MONITOR)) {
192                 die("ADM1026: monitoring would not enable");
193         }
194 }
195
196
197 static unsigned k8_cpu_volts(void)
198 {
199         unsigned volts = ~0;
200         if (is_cpu_c0()) {
201                 volts = 1500000000;
202         }
203         if (is_cpu_b3()) {
204                 volts = 1550000000;
205         }
206         return volts;
207 }
208
209 static void verify_cpu_voltages(device_t dev)
210 {
211         unsigned cpu_volts;
212         unsigned delta;
213 #if 0
214         delta =  50000000;
215 #else
216         delta =  75000000;
217 #endif
218         cpu_volts = k8_cpu_volts();
219         if (cpu_volts == ~0) {
220                 printk_info("Required cpu voltage unknwon not checking\n");
221                 return; 
222         }
223         /* I need to read registers 0x37 == Ain7CPU1 core 0x2d == VcppCPU0 core */
224         /* CPU1 core 
225          * The sensor has a range of 0-2.5V and reports in
226          * 256 distinct steps.
227          */
228         verify_cpu_voltage("CPU1 Vcore", dev, 0x37, 9765625, 
229                 cpu_volts, delta);
230         /* CPU0 core 
231          * The sensor has range of 0-3.0V and reports in 
232          * 256 distinct steps.
233          */
234         verify_cpu_voltage("CPU0 Vcore", dev, 0x2d, 11718750, 
235                 cpu_volts, delta);
236 }
237
238 #define SMBUS_MUX 0x70
239
240 static void do_verify_cpu_voltages(void)
241 {
242         device_t smbus_dev;
243         device_t mux, sensor;
244         struct device_path mux_path, sensor_path;
245         int result;
246         int mux_setting;
247         
248         /* Find the smbus controller */
249         smbus_dev = dev_find_device(0x1022, 0x746b, 0);
250         if (!smbus_dev) {
251                 die("SMBUS controller not found\n");
252         }
253         
254         /* Find the smbus mux */
255         mux_path.type         = DEVICE_PATH_I2C;
256         mux_path.u.i2c.device = SMBUS_MUX;
257         mux = find_dev_path(smbus_dev, &mux_path);
258         if (!mux) {
259                 die("SMBUS mux not found\n");
260         }
261
262         /* Find the adm1026 sensor */
263         sensor_path.type         = DEVICE_PATH_I2C;
264         sensor_path.u.i2c.device = ADM1026_DEVICE;
265         sensor = find_dev_path(mux, &sensor_path);
266         if (!sensor) {
267                 die("ADM1026 not found\n");
268         }
269         
270         /* Set the mux to see the temperature sensors */
271         mux_setting = 1;
272         result = smbus_send_byte(mux, mux_setting);
273         handle_smbus_error(result, "SMBUS send byte failed\n");
274
275         result = smbus_recv_byte(mux);
276         handle_smbus_error(result, "SMBUS recv byte failed\n");
277         if (result != mux_setting) {
278                 printk_emerg("SMBUS mux would not set to %d\n", mux_setting);
279                 die("");
280         }
281
282         adm1026_enable_monitoring(sensor);
283
284         /* It takes 11.38ms to read a new voltage sensor value */
285         mdelay(12);
286
287         /* Read the cpu voltages and make certain everything looks sane */
288         verify_cpu_voltages(sensor);
289 }
290 #else
291 #define do_verify_cpu_voltages() do {} while(0)
292 #endif
293
294 static void mainboard_init(device_t dev)
295 {
296         root_dev_init(dev);
297
298         do_verify_cpu_voltages();
299 }
300
301 static struct device_operations mainboard_operations = {
302         .read_resources   = root_dev_read_resources,
303         .set_resources    = root_dev_set_resources,
304         .enable_resources = root_dev_enable_resources,
305         .init             = mainboard_init,
306 #if !DEBUG
307         .scan_bus         = root_dev_scan_bus,
308 #else
309         .scan_bus         = scan_root_bus,
310 #endif
311         .enable           = 0,
312 };
313
314 static void enable_dev(struct device *dev)
315 {
316         dev->ops = &mainboard_operations;
317 }
318 struct chip_operations mainboard_arima_hdama_ops = {
319         .enable_dev = enable_dev, 
320 };
321