tree: drop last paragraph of GPL copyright header
[coreboot.git] / src / superio / ite / it8772f / superio.c
blob6c6a5038863b731e9b269ae0dba94cdd003cad30
1 /*
2 * This file is part of the coreboot project.
4 * Copyright (C) 2011 The ChromiumOS Authors. All rights reserved.
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; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
17 #include <device/device.h>
18 #include <device/pnp.h>
19 #include <pc80/keyboard.h>
20 #include <arch/io.h>
21 #include <delay.h>
22 #include <stdlib.h>
23 #include <superio/conf_mode.h>
25 #include "chip.h" /* FIXME */
26 #include "it8772f.h"
28 static inline u8 it8772f_envc_read(struct resource *res, u8 addr)
30 outb(addr, res->base + 5);
31 return inb(res->base + 6);
34 static inline void it8772f_envc_write(struct resource *res, u8 addr, u8 value)
36 outb(addr, res->base + 5);
37 outb(value, res->base + 6);
40 static void it8772f_extemp_force_idle_status(struct resource *res)
42 u8 reg;
43 int retries = 10;
45 /* Wait up to 10ms for non-busy state. */
46 while (retries > 0) {
47 reg = it8772f_envc_read(res, IT8772F_EXTEMP_STATUS);
49 if ((reg & IT8772F_EXTEMP_STATUS_HOST_BUSY) == 0x0)
50 break;
52 retries--;
54 mdelay(1);
57 if (retries == 0 && (reg & IT8772F_EXTEMP_STATUS_HOST_BUSY) == 0x1) {
59 * SIO is busy due to unfinished peci transaction.
60 * Re-configure Register 0x8E to terminate processes.
62 it8772f_envc_write(res, IT8772F_EXTEMP_CONTROL,
63 IT8772F_EXTEMP_CONTROL_AUTO_4HZ |
64 IT8772F_EXTEMP_CONTROL_AUTO_START);
69 * Setup External Temperature to read via PECI into TMPINx register
71 static void it8772f_enable_peci(struct resource *res, int tmpin)
73 if (tmpin < 1 || tmpin > 3)
74 return;
76 /* Enable PECI interface */
77 it8772f_envc_write(res, IT8772F_INTERFACE_SELECT,
78 IT8772F_INTERFACE_SEL_PECI |
79 IT8772F_INTERFACE_SPEED_TOLERANCE);
81 /* Setup External Temperature using PECI GetTemp */
82 it8772f_envc_write(res, IT8772F_EXTEMP_ADDRESS,
83 PECI_CLIENT_ADDRESS);
84 it8772f_envc_write(res, IT8772F_EXTEMP_COMMAND,
85 PECI_GETTEMP_COMMAND);
86 it8772f_envc_write(res, IT8772F_EXTEMP_WRITE_LENGTH,
87 PECI_GETTEMP_WRITE_LENGTH);
88 it8772f_envc_write(res, IT8772F_EXTEMP_READ_LENGTH,
89 PECI_GETTEMP_READ_LENGTH);
90 it8772f_envc_write(res, IT8772F_EXTEMP_CONTROL,
91 IT8772F_EXTEMP_CONTROL_AUTO_4HZ |
92 IT8772F_EXTEMP_CONTROL_AUTO_START);
94 /* External Temperature reported in TMPINx register */
95 it8772f_envc_write(res, IT8772F_ADC_TEMP_CHANNEL_ENABLE,
96 (tmpin & 3) << 6);
100 * Setup a FAN PWM interface for software control
102 static void it8772f_enable_fan(struct resource *res, int fan)
104 u8 reg;
106 if (fan < 1 || fan > 3)
107 return;
109 /* Enable 6MHz (23.43kHz PWM) active high output */
110 reg = it8772f_envc_read(res, IT8772F_FAN_CTL_MODE);
111 reg |= IT8772F_FAN_CTL_ON(fan) |
112 IT8772F_FAN_PWM_CLOCK_6MHZ |
113 IT8772F_FAN_CTL_POLARITY_HIGH;
114 it8772f_envc_write(res, IT8772F_FAN_CTL_MODE, reg);
116 /* Enable output in smart mode */
117 reg = it8772f_envc_read(res, IT8772F_FAN_MAIN_CTL);
118 reg |= IT8772F_FAN_MAIN_CTL_TAC_SMART(fan);
119 reg |= IT8772F_FAN_MAIN_CTL_TAC_EN(fan);
120 it8772f_envc_write(res, IT8772F_FAN_MAIN_CTL, reg);
122 switch (fan) {
123 case 2:
124 /* Enable software operation */
125 it8772f_envc_write(res, IT8772F_FAN_CTL2_PWM_MODE,
126 IT8772F_FAN_CTL_PWM_MODE_SOFTWARE);
127 /* Disable Smoothing */
128 it8772f_envc_write(res, IT8772F_FAN_CTL2_AUTO_MODE,
129 IT8772F_FAN_CTL_AUTO_SMOOTHING_DIS);
130 /* Set a default medium fan speed */
131 it8772f_envc_write(res, IT8772F_FAN_CTL2_PWM_START, 0x80);
132 break;
133 case 3:
134 /* Enable software operation */
135 it8772f_envc_write(res, IT8772F_FAN_CTL3_PWM_MODE,
136 IT8772F_FAN_CTL_PWM_MODE_SOFTWARE);
137 /* Disable Smoothing */
138 it8772f_envc_write(res, IT8772F_FAN_CTL3_AUTO_MODE,
139 IT8772F_FAN_CTL_AUTO_SMOOTHING_DIS);
140 /* Set a default medium fan speed */
141 it8772f_envc_write(res, IT8772F_FAN_CTL3_PWM_START, 0x80);
142 break;
146 static void it8772f_init(struct device *dev)
148 struct superio_ite_it8772f_config *conf = dev->chip_info;
149 struct resource *res;
151 if (!dev->enabled)
152 return;
154 switch (dev->path.pnp.device) {
155 case IT8772F_EC:
156 res = find_resource(dev, PNP_IDX_IO0);
157 if (!res)
158 break;
160 /* Enable PECI if configured */
161 it8772f_enable_peci(res, conf->peci_tmpin);
163 /* Enable FANx if configured */
164 if (conf->fan1_enable)
165 it8772f_enable_fan(res, 1);
166 if (conf->fan2_enable)
167 it8772f_enable_fan(res, 2);
168 if (conf->fan3_enable)
169 it8772f_enable_fan(res, 3);
172 * System may get wrong temperature data when SIO is in
173 * busy state. Therefore, check the status and terminate
174 * processes if needed.
176 it8772f_extemp_force_idle_status(res);
177 break;
178 case IT8772F_GPIO:
179 /* Set GPIO output levels */
180 res = find_resource(dev, PNP_IDX_IO1);
181 if (res) {
182 if (conf->gpio_set1)
183 outb(conf->gpio_set1, res->base + 0);
184 if (conf->gpio_set2)
185 outb(conf->gpio_set2, res->base + 1);
186 if (conf->gpio_set3)
187 outb(conf->gpio_set3, res->base + 2);
188 if (conf->gpio_set4)
189 outb(conf->gpio_set4, res->base + 3);
190 if (conf->gpio_set5)
191 outb(conf->gpio_set5, res->base + 4);
192 if (conf->gpio_set6)
193 outb(conf->gpio_set6, res->base + 5);
195 break;
196 case IT8772F_KBCK:
197 if (!conf->skip_keyboard) {
198 set_kbc_ps2_mode();
199 pc_keyboard_init();
201 break;
202 case IT8772F_KBCM:
203 break;
204 case IT8772F_IR:
205 break;
209 static struct device_operations ops = {
210 .read_resources = pnp_read_resources,
211 .set_resources = pnp_set_resources,
212 .enable_resources = pnp_enable_resources,
213 .enable = pnp_alt_enable,
214 .init = it8772f_init,
215 .ops_pnp_mode = &pnp_conf_mode_870155_aa,
218 static struct pnp_info pnp_dev_info[] = {
219 /* Floppy Disk Controller */
220 { &ops, IT8772F_FDC, PNP_IO0 | PNP_IRQ0, {0x0ff8, 0}, },
221 /* Serial Port 1 */
222 { &ops, IT8772F_SP1, PNP_IO0 | PNP_IRQ0, {0x0ff8, 0}, },
223 /* Environmental Controller */
224 { &ops, IT8772F_EC, PNP_IO0 | PNP_IO1 | PNP_IRQ0 |
225 PNP_MSC4 | PNP_MSC10,
226 {0x0ff8, 0}, {0x0ffc, 4}, },
227 /* KBC Keyboard */
228 { &ops, IT8772F_KBCK, PNP_IO0 | PNP_IO1 | PNP_IRQ0,
229 {0x0fff, 0}, {0x0fff, 4}, },
230 /* KBC Mouse */
231 { &ops, IT8772F_KBCM, PNP_IRQ0, },
232 /* 27 GPIOs */
233 { &ops, IT8772F_GPIO, PNP_IO0 | PNP_IO1,
234 {0x0fff, 0}, {0x0ff8, 0}, },
235 /* Infrared */
236 { &ops, IT8772F_IR, PNP_IO0 | PNP_IRQ0, {0x0ff8, 0}, },
239 static void enable_dev(struct device *dev)
241 pnp_enable_devices(dev, &pnp_ops,
242 ARRAY_SIZE(pnp_dev_info), pnp_dev_info);
245 struct chip_operations superio_ite_it8772f_ops = {
246 CHIP_NAME("ITE IT8772F Super I/O")
247 .enable_dev = enable_dev,