blob: 5cd8997355fbf2e2150a012f024a550f778cc3b1 [file] [log] [blame]
Sven Schnelled8129f92011-04-20 09:12:17 +00001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2011 Sven Schnelle <svens@stackframe.org>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; version 2 of
9 * the License.
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,
19 * MA 02110-1301 USA
20 */
21
22#include <console/console.h>
23#include <device/device.h>
24#include <arch/io.h>
25#include <boot/tables.h>
26#include <delay.h>
27#include <arch/io.h>
28#include "dock.h"
29#include "superio/nsc/pc87384/pc87384.h"
30#include "ec/acpi/ec.h"
Sven Schnelleb5381102011-10-15 17:31:01 +020031#include "ec/lenovo/pmh7/pmh7.h"
Sven Schnelled8129f92011-04-20 09:12:17 +000032#include "southbridge/intel/i82801gx/i82801gx.h"
33
Sven Schnelleb5381102011-10-15 17:31:01 +020034#define DLPC_CONTROL 0x164c
35
Sven Schnelled8129f92011-04-20 09:12:17 +000036static void dlpc_write_register(int reg, int value)
37{
38 outb(reg, 0x164e);
39 outb(value, 0x164f);
40}
41
42static u8 dlpc_read_register(int reg)
43{
44 outb(reg, 0x164e);
45 return inb(0x164f);
46}
47
48static void dock_write_register(int reg, int value)
49{
50 outb(reg, 0x2e);
51 outb(value, 0x2f);
52}
53
54static u8 dock_read_register(int reg)
55{
56 outb(reg, 0x2e);
57 return inb(0x2f);
58}
59
60static void dlpc_gpio_set_mode(int port, int mode)
61{
62 dlpc_write_register(0xf0, port);
63 dlpc_write_register(0xf1, mode);
64}
65
66static void dock_gpio_set_mode(int port, int mode, int irq)
67{
68 dock_write_register(0xf0, port);
69 dock_write_register(0xf1, mode);
70 dock_write_register(0xf2, irq);
71}
72
73static void dlpc_gpio_init(void)
74{
75 /* Select GPIO module */
76 dlpc_write_register(0x07, 0x07);
77 /* GPIO Base Address 0x1680 */
78 dlpc_write_register(0x60, 0x16);
79 dlpc_write_register(0x61, 0x80);
80
81 /* Activate GPIO */
82 dlpc_write_register(0x30, 0x01);
83
84 dlpc_gpio_set_mode(0x00, 3);
85 dlpc_gpio_set_mode(0x01, 3);
86 dlpc_gpio_set_mode(0x02, 0);
87 dlpc_gpio_set_mode(0x03, 3);
88 dlpc_gpio_set_mode(0x04, 4);
89 dlpc_gpio_set_mode(0x20, 4);
90 dlpc_gpio_set_mode(0x21, 4);
91 dlpc_gpio_set_mode(0x23, 4);
92}
93
94int dlpc_init(void)
95{
96 int timeout = 1000;
97
98 /* Enable 14.318MHz CLK on CLKIN */
99 dlpc_write_register(0x29, 0xa0);
100 while(!(dlpc_read_register(0x29) & 0x10) && timeout--)
101 udelay(1000);
102
103 if (!timeout)
104 return 1;
105
106 /* Select DLPC module */
107 dlpc_write_register(0x07, 0x19);
Sven Schnelleb5381102011-10-15 17:31:01 +0200108 /* DLPC Base Address */
109 dlpc_write_register(0x60, (DLPC_CONTROL >> 8) & 0xff);
110 dlpc_write_register(0x61, DLPC_CONTROL & 0xff);
Sven Schnelled8129f92011-04-20 09:12:17 +0000111 /* Activate DLPC */
112 dlpc_write_register(0x30, 0x01);
113
Sven Schnelleb5381102011-10-15 17:31:01 +0200114 /* Reset docking state */
115 outb(0x00, DLPC_CONTROL);
116
Sven Schnelled8129f92011-04-20 09:12:17 +0000117 dlpc_gpio_init();
118 return 0;
119}
120
121static int dock_superio_init(void)
122{
123 int timeout = 1000;
124 /* startup 14.318MHz Clock */
125 dock_write_register(0x29, 0xa0);
126 /* wait until clock is settled */
127 while(!(dock_read_register(0x29) & 0x10) && timeout--)
128 udelay(1000);
129
130 if (!timeout)
131 return 1;
132
133 /* set GPIO pins to Serial/Parallel Port
134 * functions
135 */
Sven Schnelleb5381102011-10-15 17:31:01 +0200136 dock_write_register(0x22, 0xa9);
Sven Schnelled8129f92011-04-20 09:12:17 +0000137
138 dock_write_register(0x07, PC87384_GPIO);
139 dock_write_register(0x60, 0x16);
140 dock_write_register(0x61, 0x20);
Sven Schnelle40d99bc2011-07-11 15:22:42 +0200141 /* enable GPIO */
142 dock_write_register(0x30, 0x01);
Sven Schnelled8129f92011-04-20 09:12:17 +0000143
144 dock_gpio_set_mode(0x00, PC87384_GPIO_PIN_DEBOUNCE |
145 PC87384_GPIO_PIN_PULLUP, 0x00);
146
147 dock_gpio_set_mode(0x01, PC87384_GPIO_PIN_TYPE_PUSH_PULL |
148 PC87384_GPIO_PIN_OE, 0x00);
149
150 dock_gpio_set_mode(0x02, PC87384_GPIO_PIN_TYPE_PUSH_PULL |
151 PC87384_GPIO_PIN_OE, 0x00);
152
153 dock_gpio_set_mode(0x03, PC87384_GPIO_PIN_DEBOUNCE |
154 PC87384_GPIO_PIN_PULLUP, 0x00);
155
156 dock_gpio_set_mode(0x04, PC87384_GPIO_PIN_DEBOUNCE |
157 PC87384_GPIO_PIN_PULLUP, 0x00);
158
159 dock_gpio_set_mode(0x05, PC87384_GPIO_PIN_DEBOUNCE |
160 PC87384_GPIO_PIN_PULLUP, 0x00);
161
162 dock_gpio_set_mode(0x06, PC87384_GPIO_PIN_DEBOUNCE |
163 PC87384_GPIO_PIN_PULLUP, 0x00);
164
165 dock_gpio_set_mode(0x07, PC87384_GPIO_PIN_DEBOUNCE |
166 PC87384_GPIO_PIN_PULLUP, 0x00);
167
Sven Schnelled8129f92011-04-20 09:12:17 +0000168
169 /* no GPIO events enabled for PORT0 */
170 outb(0x00, 0x1622);
171 /* clear GPIO events on PORT0 */
172 outb(0xff, 0x1623);
173 outb(0xff, 0x1624);
174 /* no GPIO events enabled for PORT1 */
175 outb(0x00, 0x1626);
176
177 /* clear GPIO events on PORT1*/
178 outb(0xff, 0x1627);
179 outb(0x1F, 0x1628);
Sven Schnelle40d99bc2011-07-11 15:22:42 +0200180 outb(0xfd, 0x1620);
Sven Schnelled8129f92011-04-20 09:12:17 +0000181 return 0;
182}
183
184int dock_connect(void)
185{
186 int timeout = 1000;
187
Sven Schnelleb5381102011-10-15 17:31:01 +0200188 outb(0x07, DLPC_CONTROL);
Sven Schnelled8129f92011-04-20 09:12:17 +0000189
190 timeout = 1000;
191
Sven Schnelleb5381102011-10-15 17:31:01 +0200192 while(!(inb(DLPC_CONTROL) & 8) && timeout--)
Sven Schnelled8129f92011-04-20 09:12:17 +0000193 udelay(1000);
194
195 if (!timeout) {
196 /* docking failed, disable DLPC switch */
Sven Schnelleb5381102011-10-15 17:31:01 +0200197 outb(0x00, DLPC_CONTROL);
Sven Schnelled8129f92011-04-20 09:12:17 +0000198 dlpc_write_register(0x30, 0x00);
199 return 1;
200 }
201
202 /* Assert D_PLTRST# */
203 outb(0xfe, 0x1680);
204 udelay(1000);
205 /* Deassert D_PLTRST# */
206 outb(0xff, 0x1680);
207 udelay(10000);
208
209 return dock_superio_init();
210}
211
212void dock_disconnect(void)
213{
214 /* disconnect LPC bus */
Sven Schnelleb5381102011-10-15 17:31:01 +0200215 outb(0x00, DLPC_CONTROL);
Sven Schnelled8129f92011-04-20 09:12:17 +0000216 /* Assert PLTRST and DLPCPD */
217 outb(0xfc, 0x1680);
218}
219
220int dock_present(void)
221{
Sven Schnelleb5381102011-10-15 17:31:01 +0200222 return pmh7_register_read(0x61) & 1;
Sven Schnelled8129f92011-04-20 09:12:17 +0000223}
224
Sven Schnelleb5381102011-10-15 17:31:01 +0200225int legacy_io_present(void)
226{
227 return !(inb(DEFAULT_GPIOBASE + 0x0c) & 0x40);
228}
229
230void legacy_io_init(void)
231{
232 /* Enable Power for Ultrabay slot */
233 pmh7_ultrabay_power_enable(1);
234 udelay(100000);
235 dock_superio_init();
236}