summaryrefslogtreecommitdiff
path: root/src/superio/ite/common/early_serial.c
blob: ec218a6c901c3457f986e792a5dd093131d82d94 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
/* SPDX-License-Identifier: GPL-2.0-or-later */

#include <arch/io.h>
#include <device/pnp_ops.h>
#include <device/pnp.h>
#include <stdint.h>
#include "ite.h"

/* Global configuration registers. */
#define ITE_CONFIG_REG_CC		0x02 /* Configure Control (write-only). */
#define ITE_CONFIG_REG_LDN		0x07 /* Logical Device Number. */
#define ITE_CONFIG_REG_CLOCKSEL		0x23 /* Clock Selection. */
#define ITE_CONFIG_REG_SWSUSP		0x24 /* Software Suspend, Flash I/F. */
#define ITE_CONFIG_REG_MFC		0x2a /* multi function pin */
#define ITE_CONFIG_REG_WATCHDOG		0x72 /* watchdog config */
#define ITE_CONFIG_REG_WDT_TIMEOUT_LSB	0x73 /* watchdog timeout (LSB) */
#define ITE_CONFIG_REG_WDT_TIMEOUT_MSB	0x74 /* watchdog timeout (MSB) */
#define ITE_CONFIG_REG_APC_PME_CTL1	0xf2 /* APC_PME Control 1 */
#define ITE_CONFIG_REG_APC_PME_CTL2	0xf4 /* APC_PME Control 2 */

/* Helper procedure */
static void ite_sio_write(pnp_devfn_t dev, u8 reg, u8 value)
{
	pnp_set_logical_device(dev);
	pnp_write_config(dev, reg, value);
}

/* Enable configuration */
void pnp_enter_conf_state(pnp_devfn_t dev)
{
	u16 port = dev >> 8;

	outb(0x87, port);
	outb(0x01, port);
	outb(0x55, port);
	outb((port == 0x4e) ? 0xaa : 0x55, port);
}

/* Disable configuration */
void pnp_exit_conf_state(pnp_devfn_t dev)
{
	ite_sio_write(dev, ITE_CONFIG_REG_CC, 0x02);
}

void ite_reg_write(pnp_devfn_t dev, u8 reg, u8 value)
{
	pnp_enter_conf_state(dev);
	ite_sio_write(dev, reg, value);
	pnp_exit_conf_state(dev);
}

/*
 * in romstage.c
 * #define CLKIN_DEV PNP_DEV(0x2e, ITE_GPIO)
 * and pass: CLKIN_DEV
 * ITE_UART_CLK_PREDIVIDE_24
 * ITE_UART_CLK_PREDIVIDE_48 (default)
 */
void ite_conf_clkin(pnp_devfn_t dev, u8 predivide)
{
	ite_reg_write(dev, ITE_CONFIG_REG_CLOCKSEL, (0x1 & predivide));
}

/* Bring up early serial debugging output before the RAM is initialized. */
void ite_enable_serial(pnp_devfn_t dev, u16 iobase)
{
	pnp_enter_conf_state(dev);
	pnp_set_logical_device(dev);
	pnp_set_enable(dev, 0);
	pnp_set_iobase(dev, PNP_IDX_IO0, iobase);
	pnp_set_enable(dev, 1);
	pnp_exit_conf_state(dev);
}

/*
 *
 * LDN 7, reg 0x2a - needed for S3, or memory power will be cut off
 * this was documented only in IT8712F_V0.9.2!
 * Also documented in IT8728F_V0.4.2 and IT8772E_V0.4
 *
 * Enable 3VSBSW#. (For System Suspend-to-RAM)
 * 0: 3VSBSW# will be always inactive.
 * 1: 3VSBSW# enabled. It will be (NOT SUSB#) NAND SUSC#.
 *
 * in romstage.c
 * #define GPIO_DEV PNP_DEV(0x2e, ITE_GPIO)
 * and pass: GPIO_DEV
 */

void ite_set_3vsbsw(pnp_devfn_t dev, bool enable)
{
	u8 tmp;
	pnp_enter_conf_state(dev);
	pnp_set_logical_device(dev);
	tmp = pnp_read_config(dev, ITE_CONFIG_REG_MFC);
	if (enable)
		tmp |= 0x80;
	else
		tmp &= ~0x80;
	pnp_write_config(dev, ITE_CONFIG_REG_MFC, tmp);
	pnp_exit_conf_state(dev);
}

/*
 *
 * LDN 7, reg 0x2a, bit 0 - delay PWRGD3 rising edge after 3VSBSW# rising edge
 * This can be needed for S3 resume.
 * Documented in IT8728F V0.4.2 but also applies to IT8720F where it is marked
 * as reserved.
 *
 * Delay PWRGD3 assertion after setting 3VSBSW#.
 * 0: There will be no extra delay before PWRGD3 is set.
 * 1: The delay after 3VSBSW# rising edge before PWRGD3 is set is increased.
 *
 * in romstage.c
 * #define GPIO_DEV PNP_DEV(0x2e, ITE_GPIO)
 * and pass: GPIO_DEV
 */

void ite_delay_pwrgd3(pnp_devfn_t dev)
{
	u8 tmp;
	pnp_enter_conf_state(dev);
	pnp_set_logical_device(dev);
	tmp = pnp_read_config(dev, ITE_CONFIG_REG_MFC);
	tmp |= 0x01;
	pnp_write_config(dev, ITE_CONFIG_REG_MFC, tmp);
	pnp_exit_conf_state(dev);
}

/*
 * in romstage.c
 * #define GPIO_DEV PNP_DEV(0x2e, ITE_GPIO)
 * and pass: GPIO_DEV
*/

void ite_kill_watchdog(pnp_devfn_t dev)
{
	pnp_enter_conf_state(dev);
	ite_sio_write(dev, ITE_CONFIG_REG_WATCHDOG, 0x00);
	ite_sio_write(dev, ITE_CONFIG_REG_WDT_TIMEOUT_LSB, 0x00);
	ite_sio_write(dev, ITE_CONFIG_REG_WDT_TIMEOUT_MSB, 0x00);
	pnp_exit_conf_state(dev);
}

/*
 * Disable PME# Output
 * pass EC_DEV
 */
void ite_disable_pme_out(pnp_devfn_t dev)
{
	u8 tmp;
	pnp_enter_conf_state(dev);
	pnp_set_logical_device(dev);
	tmp = pnp_read_config(dev, ITE_CONFIG_REG_APC_PME_CTL1);
	tmp |= 0x40;
	pnp_write_config(dev, ITE_CONFIG_REG_APC_PME_CTL1, tmp);
	pnp_exit_conf_state(dev);
}

/*
 * Set AC resume to be up to the Southbridge
 * pass EC_DEV
 */
void ite_ac_resume_southbridge(pnp_devfn_t dev)
{
	u8 tmp;
	pnp_enter_conf_state(dev);
	pnp_set_logical_device(dev);
	tmp = pnp_read_config(dev, ITE_CONFIG_REG_APC_PME_CTL2);
	/*
	 * Set both
	 * 6: Gate Extra PWRON# Pulse
	 * 5: PSON# state when 3VSB switched to on
	 */
	tmp |= 0x60;
	pnp_write_config(dev, ITE_CONFIG_REG_APC_PME_CTL2, tmp);
	pnp_exit_conf_state(dev);
}