Add support for ITE IT8772F SuperI/O chip
[coreboot.git] / src / superio / ite / it8772f / early_serial.c
1 /*
2  * This file is part of the coreboot project.
3  *
4  * Copyright (C) 2011 The ChromiumOS Authors.  All rights reserved.
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; either version 2 of the License, or
9  * (at your option) any later version.
10  *
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.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
19  */
20
21 #include <arch/romcc_io.h>
22 #include <device/pnp_def.h>
23 #include "it8772f.h"
24
25 /* The base address is 0x2e or 0x4e, depending on config bytes. */
26 #define SIO_BASE                     IT8772F_BASE
27 #define SIO_INDEX                    SIO_BASE
28 #define SIO_DATA                     (SIO_BASE + 1)
29
30 /* Global configuration registers. */
31 #define IT8772F_CONFIG_REG_CC        0x02 /* Configure Control (write-only). */
32 #define IT8772F_CONFIG_REG_LDN       0x07 /* Logical Device Number. */
33 #define IT8772F_CONFIG_REG_CLOCKSEL  0x23 /* Clock Selection. */
34 #define IT8772F_CONFIG_REG_MFC       0x2a /* Multi-function control */
35 #define IT8772F_CONFIG_REG_WATCHDOG  0x72 /* Watchdog control. */
36
37 u8 it8772f_sio_read(u8 index)
38 {
39         outb(index, SIO_BASE);
40         return inb(SIO_DATA);
41 }
42
43 void it8772f_sio_write(u8 index, u8 value)
44 {
45         outb(index, SIO_BASE);
46         outb(value, SIO_DATA);
47 }
48
49 static void it8772f_enter_conf(void)
50 {
51         u16 port = SIO_BASE;
52
53         outb(0x87, port);
54         outb(0x01, port);
55         outb(0x55, port);
56         outb((port == 0x4e) ? 0xaa : 0x55, port);
57 }
58
59 static void it8772f_exit_conf(void)
60 {
61         it8772f_sio_write(IT8772F_CONFIG_REG_CC, 0x02);
62 }
63
64 /* Select 24MHz CLKIN (48MHz is the default). */
65 void it8772f_24mhz_clkin(void)
66 {
67         it8772f_enter_conf();
68         it8772f_sio_write(IT8772F_CONFIG_REG_LDN, 0x00);
69         it8772f_sio_write(IT8772F_CONFIG_REG_CLOCKSEL, 0x1);
70         it8772f_exit_conf();
71 }
72
73 /*
74  * LDN 7, reg 0x2a - needed for S3, or memory power will be cut off.
75  *
76  * Enable 3VSBSW#. (For System Suspend-to-RAM)
77  * 0: 3VSBSW# will be always inactive.
78  * 1: 3VSBSW# enabled. It will be (NOT SUSB#) NAND SUSC#.
79  */
80 void it8772f_enable_3vsbsw(void)
81 {
82         it8772f_enter_conf();
83         it8772f_sio_write(IT8772F_CONFIG_REG_LDN, IT8772F_GPIO);
84         it8772f_sio_write(IT8772F_CONFIG_REG_MFC, 0x80);
85         it8772f_exit_conf();
86 }
87
88 void it8772f_kill_watchdog(void)
89 {
90         it8772f_enter_conf();
91         it8772f_sio_write(IT8772F_CONFIG_REG_LDN, IT8772F_GPIO);
92         it8772f_sio_write(IT8772F_CONFIG_REG_WATCHDOG, 0x00);
93         it8772f_exit_conf();
94 }
95
96 /* Enable the serial port(s). */
97 void it8772f_enable_serial(device_t dev, u16 iobase)
98 {
99         it8772f_enter_conf();
100         it8772f_sio_write(IT8772F_CONFIG_REG_LDN, dev & 0xff);
101         it8772f_sio_write(PNP_IDX_IO0, (iobase >> 8) & 0xff);
102         it8772f_sio_write(PNP_IDX_IO0+1, iobase & 0xff);
103         it8772f_sio_write(PNP_IDX_EN, 1);
104         it8772f_exit_conf();
105 }
106
107 /* Set AC resume to be up to the Southbridge */
108 void it8772f_ac_resume_southbridge(void)
109 {
110         it8772f_enter_conf();
111         it8772f_sio_write(IT8772F_CONFIG_REG_LDN, IT8772F_EC);
112         it8772f_sio_write(0xf4, 0x60);
113         it8772f_exit_conf();
114 }
115
116 /* Configure a set of GPIOs */
117 void it8772f_gpio_setup(int set, u8 select, u8 polarity, u8 pullup,
118                         u8 output, u8 enable)
119 {
120         set--; /* Set 1 is offset 0 */
121         it8772f_enter_conf();
122         it8772f_sio_write(IT8772F_CONFIG_REG_LDN, IT8772F_GPIO);
123         if (set < 5) {
124                 it8772f_sio_write(GPIO_REG_SELECT(set), select);
125                 it8772f_sio_write(GPIO_REG_ENABLE(set), enable);
126                 it8772f_sio_write(GPIO_REG_POLARITY(set), polarity);
127         }
128         it8772f_sio_write(GPIO_REG_OUTPUT(set), output);
129         it8772f_sio_write(GPIO_REG_PULLUP(set), pullup);
130         it8772f_exit_conf();
131 }