blob: 3e2bbf004a04dc6e4ee58e2f5b32666ad6029927 [file] [log] [blame]
Jonathan A. Kollaschd9247822015-10-30 18:15:55 -05001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2007 AMD
5 * Written by Yinghai Lu <yinghailu@amd.com> for AMD.
6 * Copyright (C) 2010 coresystems GmbH
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; version 2 of the License.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 */
17
Jonathan A. Kollaschb65fd3e2015-11-03 12:19:35 -060018#include <arch/io.h>
Jonathan A. Kollaschd9247822015-10-30 18:15:55 -050019#include <console/console.h>
20#include <device/device.h>
Jonathan A. Kollaschb65fd3e2015-11-03 12:19:35 -060021#include <device/pnp_def.h>
22#include <device/smbus.h>
23#include <stdlib.h>
24#include <superio/smsc/dme1737/dme1737.h>
Jonathan A. Kollaschd9247822015-10-30 18:15:55 -050025
Jonathan A. Kollaschb65fd3e2015-11-03 12:19:35 -060026static void emc6d103_init(void)
27{
28 size_t i;
29 int reg;
30
31 static const struct { uint8_t idx; uint8_t msk; uint8_t set; } script[] = {
32 { 0x7f, 0x7f, 0x80 }, // INIT
33 { 0x4f, 0x00, 0x64 }, // Diode 1 High 100°C
34 { 0x53, 0x00, 0x64 }, // Diode 2 High 100°C (Sun firmware didn't set this)
35 { 0x54, 0x00, 0x30 }, // Tach1 Minimum LSB
36 { 0x55, 0x00, 0x2a }, // Tach1 Minimum MSB
37 { 0x56, 0x00, 0x30 }, // Tach2 Minimum LSB
38 { 0x57, 0x00, 0x2a }, // Tach2 Minimum MSB
39 { 0x5c, 0x00, 0x02 }, // PWM 1 Config
40 { 0x5d, 0x00, 0x42 }, // PWM 2 Config
41 { 0x5f, 0x00, 0x8a }, // Zone 1 range, Fan 1 freq
42 { 0x60, 0x00, 0xca }, // Zone 2 range, Fan 2 freq
43 { 0x61, 0x00, 0x8a }, // Zone 3 range, Fan 3 freq
44 { 0x62, 0x00, 0x67 }, // Min/Off, PWM 1 ramp rate
45 { 0x63, 0x00, 0x70 }, // PWM 2, PWM 3 ramp rate
46 { 0x64, 0x00, 0x59 }, // PWM1 Minimum Duty Cycle
47 { 0x65, 0x00, 0x59 }, // PWM2 Minimum Duty Cycle
48 { 0x67, 0x00, 0x47 }, // Zone 1 Low Temp Limit
49 { 0x69, 0x00, 0x47 }, // Zone 3 Low Temp Limit
50 { 0x80, 0x00, 0x07 }, // Interrupt Enable 2
51 { 0x40, 0xfe, 0x01 }, // START
52 };
53
54 struct device * const dev = dev_find_slot_on_smbus(2, 0x2d);
55 if (dev == NULL)
56 printk(BIOS_WARNING, "EMC6D103 not found\n");
57
58 printk(BIOS_SPEW, "%s EMC6D103 id: %x %x\n", __func__, smbus_read_byte(dev, 0x3e), smbus_read_byte(dev, 0x3f));
59
60 for (i = 0; i < ARRAY_SIZE(script); i++) {
61 reg = smbus_read_byte(dev, script[i].idx);
62 if (reg < 0)
63 goto fail;
64 reg &= script[i].msk;
65 reg |= script[i].set;
66 reg = smbus_write_byte(dev, script[i].idx, reg & 0xff);
67 if (reg < 0)
68 goto fail;
69 }
70
71 return;
72
73fail:
74 printk(BIOS_WARNING, "failed to initialize EMC6D103\n");
75}
76
77/* set up DME1737 runtime registers for FAN/PWM 5/6 */
78static void dme1737_runtime_init(void)
79{
80 size_t i;
81 uint8_t reg;
82
83 static const struct { uint8_t idx; uint8_t msk; uint8_t set; } rttab[] = {
84 { 0x43, 0xf3, 0x08 },
85 { 0x44, 0xf0, 0x08 },
86 { 0x45, 0xf3, 0x08 },
87 { 0x46, 0xf0, 0x08 },
88 };
89
90 /* find DME1737 runtime device (LDN 10) */
91 struct device * const dev = dev_find_slot_pnp(0x2e, DME1737_RT);
92 if (dev == NULL)
93 return;
94
95 struct resource * const res = find_resource(dev, PNP_IDX_IO0);
96 if (res == NULL)
97 return;
98
99 for (i = 0; i < ARRAY_SIZE(rttab); i++) {
100 reg = inb(res->base + rttab[i].idx);
101 reg &= rttab[i].msk;
102 reg |= rttab[i].set;
103 outb(reg, res->base + rttab[i].idx);
104 }
105}
106
107static void dme1737_hwm_init(void)
108{
109 size_t i;
110 int reg;
111
112 static const struct { uint8_t idx; uint8_t msk; uint8_t set; } script[] = {
113 //{ 0x7f, 0x7f, 0x80 }, // INIT
114 { 0x4f, 0x00, 0x32 }, // High
115 { 0x54, 0x00, 0x30 }, // Tach0 Minimum LSB
116 { 0x55, 0x00, 0x2a }, // Tach0 Minimum MSB
117 { 0x56, 0x00, 0x30 }, // Tach1 Minimum LSB
118 { 0x57, 0x00, 0x2a }, // Tach1 Minimum MSB
119 { 0x5a, 0x00, 0x30 }, // Tach3 Minimum LSB
120 { 0x5b, 0x00, 0x2a }, // Tach3 Minimum MSB
121 { 0x5d, 0x00, 0x07 }, // PWM 1 Config: Zone 0
122 { 0x5f, 0x0f, 0x50 }, // Zone 0 range, PWM freq
123 { 0x62, 0x00, 0x67 }, // Ramp Rate
124 { 0x63, 0x00, 0x80 }, // Ramp Rate
125 { 0x65, 0x00, 0x0d }, // PWM 1 Minimum
126 { 0x67, 0x00, 0x23 }, // Zone 0 Low
127 { 0x6a, 0x00, 0x32 }, // Zone 0 High
128 { 0x6c, 0x00, 0x5a }, // Zone 2 Abs
129 { 0x80, 0x00, 0x17 }, // Interrupt Enable 2?
130 { 0xa5, 0x00, 0x40 }, // PMW 4: 25% duty
131 { 0xa6, 0x00, 0x40 }, // PWM 5: 25% duty
132 { 0x40, 0xfe, 0x01 }, // START
133 };
134
135 struct device * const dev = dev_find_slot_on_smbus(2, 0x2e);
136 if (dev == NULL) {
137 printk(BIOS_INFO, "SMBus DME1737 not found\n");
138 return;
139 }
140
141 printk(BIOS_SPEW, "%s DME1737 id: %x %x\n", __func__, smbus_read_byte(dev, 0x3e), smbus_read_byte(dev, 0x3f));
142
143 for (i = 0; i < ARRAY_SIZE(script); i++) {
144 reg = smbus_read_byte(dev, script[i].idx);
145 if (reg < 0)
146 goto fail;
147 reg &= script[i].msk;
148 reg |= script[i].set;
149 reg = smbus_write_byte(dev, script[i].idx, reg & 0xff);
150 if (reg < 0)
151 goto fail;
152 }
153
154 return;
155
156fail:
157 printk(BIOS_WARNING, "failed to initialize EMC6D103\n");
158}
159
160static void mainboard_init(device_t dev)
161{
162 emc6d103_init();
163 dme1737_runtime_init();
164 dme1737_hwm_init();
165
166 printk(BIOS_DEBUG, "%s done\n", __func__);
167}
Jonathan A. Kollaschd9247822015-10-30 18:15:55 -0500168
169static void mainboard_enable(device_t dev)
170{
Jonathan A. Kollaschb65fd3e2015-11-03 12:19:35 -0600171 dev->ops->init = mainboard_init;
Jonathan A. Kollaschd9247822015-10-30 18:15:55 -0500172}
173
174struct chip_operations mainboard_ops = {
175 .enable_dev = mainboard_enable,
176};