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>
23 #include <superio/conf_mode.h>
25 #include "chip.h" /* FIXME */
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
)
45 /* Wait up to 10ms for non-busy state. */
47 reg
= it8772f_envc_read(res
, IT8772F_EXTEMP_STATUS
);
49 if ((reg
& IT8772F_EXTEMP_STATUS_HOST_BUSY
) == 0x0)
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)
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
,
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
,
100 * Setup a FAN PWM interface for software control
102 static void it8772f_enable_fan(struct resource
*res
, int fan
)
106 if (fan
< 1 || fan
> 3)
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
);
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);
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);
146 static void it8772f_init(struct device
*dev
)
148 struct superio_ite_it8772f_config
*conf
= dev
->chip_info
;
149 struct resource
*res
;
154 switch (dev
->path
.pnp
.device
) {
156 res
= find_resource(dev
, PNP_IDX_IO0
);
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
);
179 /* Set GPIO output levels */
180 res
= find_resource(dev
, PNP_IDX_IO1
);
183 outb(conf
->gpio_set1
, res
->base
+ 0);
185 outb(conf
->gpio_set2
, res
->base
+ 1);
187 outb(conf
->gpio_set3
, res
->base
+ 2);
189 outb(conf
->gpio_set4
, res
->base
+ 3);
191 outb(conf
->gpio_set5
, res
->base
+ 4);
193 outb(conf
->gpio_set6
, res
->base
+ 5);
197 if (!conf
->skip_keyboard
) {
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}, },
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}, },
228 { &ops
, IT8772F_KBCK
, PNP_IO0
| PNP_IO1
| PNP_IRQ0
,
229 {0x0fff, 0}, {0x0fff, 4}, },
231 { &ops
, IT8772F_KBCM
, PNP_IRQ0
, },
233 { &ops
, IT8772F_GPIO
, PNP_IO0
| PNP_IO1
,
234 {0x0fff, 0}, {0x0ff8, 0}, },
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
,