blob: 0e24b95c24dff88b4532e546866a85dfe90c50eb [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.
Sven Schnelled8129f92011-04-20 09:12:17 +000015 */
16
17#include <console/console.h>
18#include <device/device.h>
19#include <arch/io.h>
Sven Schnelled8129f92011-04-20 09:12:17 +000020#include <delay.h>
Sven Schnelled8129f92011-04-20 09:12:17 +000021#include "dock.h"
Edward O'Callaghan74834e02015-01-04 04:17:35 +110022#include <superio/nsc/pc87384/pc87384.h>
Sven Schnelled8129f92011-04-20 09:12:17 +000023#include "ec/acpi/ec.h"
Sven Schnelleb5381102011-10-15 17:31:01 +020024#include "ec/lenovo/pmh7/pmh7.h"
Sven Schnelled8129f92011-04-20 09:12:17 +000025#include "southbridge/intel/i82801gx/i82801gx.h"
26
Sven Schnelleb5381102011-10-15 17:31:01 +020027#define DLPC_CONTROL 0x164c
28
Sven Schnelled8129f92011-04-20 09:12:17 +000029static void dlpc_write_register(int reg, int value)
30{
31 outb(reg, 0x164e);
32 outb(value, 0x164f);
33}
34
35static u8 dlpc_read_register(int reg)
36{
37 outb(reg, 0x164e);
38 return inb(0x164f);
39}
40
41static void dock_write_register(int reg, int value)
42{
43 outb(reg, 0x2e);
44 outb(value, 0x2f);
45}
46
47static u8 dock_read_register(int reg)
48{
49 outb(reg, 0x2e);
50 return inb(0x2f);
51}
52
53static void dlpc_gpio_set_mode(int port, int mode)
54{
55 dlpc_write_register(0xf0, port);
56 dlpc_write_register(0xf1, mode);
57}
58
59static void dock_gpio_set_mode(int port, int mode, int irq)
60{
61 dock_write_register(0xf0, port);
62 dock_write_register(0xf1, mode);
63 dock_write_register(0xf2, irq);
64}
65
66static void dlpc_gpio_init(void)
67{
68 /* Select GPIO module */
69 dlpc_write_register(0x07, 0x07);
70 /* GPIO Base Address 0x1680 */
71 dlpc_write_register(0x60, 0x16);
72 dlpc_write_register(0x61, 0x80);
73
74 /* Activate GPIO */
75 dlpc_write_register(0x30, 0x01);
76
77 dlpc_gpio_set_mode(0x00, 3);
78 dlpc_gpio_set_mode(0x01, 3);
79 dlpc_gpio_set_mode(0x02, 0);
80 dlpc_gpio_set_mode(0x03, 3);
81 dlpc_gpio_set_mode(0x04, 4);
82 dlpc_gpio_set_mode(0x20, 4);
83 dlpc_gpio_set_mode(0x21, 4);
84 dlpc_gpio_set_mode(0x23, 4);
85}
86
87int dlpc_init(void)
88{
89 int timeout = 1000;
90
91 /* Enable 14.318MHz CLK on CLKIN */
92 dlpc_write_register(0x29, 0xa0);
93 while(!(dlpc_read_register(0x29) & 0x10) && timeout--)
94 udelay(1000);
95
96 if (!timeout)
97 return 1;
98
99 /* Select DLPC module */
100 dlpc_write_register(0x07, 0x19);
Sven Schnelleb5381102011-10-15 17:31:01 +0200101 /* DLPC Base Address */
102 dlpc_write_register(0x60, (DLPC_CONTROL >> 8) & 0xff);
103 dlpc_write_register(0x61, DLPC_CONTROL & 0xff);
Sven Schnelled8129f92011-04-20 09:12:17 +0000104 /* Activate DLPC */
105 dlpc_write_register(0x30, 0x01);
106
Sven Schnelleb5381102011-10-15 17:31:01 +0200107 /* Reset docking state */
108 outb(0x00, DLPC_CONTROL);
109
Sven Schnelled8129f92011-04-20 09:12:17 +0000110 dlpc_gpio_init();
111 return 0;
112}
113
114static int dock_superio_init(void)
115{
116 int timeout = 1000;
117 /* startup 14.318MHz Clock */
118 dock_write_register(0x29, 0xa0);
119 /* wait until clock is settled */
120 while(!(dock_read_register(0x29) & 0x10) && timeout--)
121 udelay(1000);
122
123 if (!timeout)
124 return 1;
125
126 /* set GPIO pins to Serial/Parallel Port
127 * functions
128 */
Sven Schnelleb5381102011-10-15 17:31:01 +0200129 dock_write_register(0x22, 0xa9);
Sven Schnelled8129f92011-04-20 09:12:17 +0000130
Damien Zammit40788c62014-05-16 18:52:47 +1000131 /* enable serial port */
132 dock_write_register(0x07, PC87384_SP1);
133 dock_write_register(0x30, 0x01);
134
Sven Schnelled8129f92011-04-20 09:12:17 +0000135 dock_write_register(0x07, PC87384_GPIO);
136 dock_write_register(0x60, 0x16);
137 dock_write_register(0x61, 0x20);
Sven Schnelle40d99bc2011-07-11 15:22:42 +0200138 /* enable GPIO */
139 dock_write_register(0x30, 0x01);
Sven Schnelled8129f92011-04-20 09:12:17 +0000140
141 dock_gpio_set_mode(0x00, PC87384_GPIO_PIN_DEBOUNCE |
142 PC87384_GPIO_PIN_PULLUP, 0x00);
143
144 dock_gpio_set_mode(0x01, PC87384_GPIO_PIN_TYPE_PUSH_PULL |
145 PC87384_GPIO_PIN_OE, 0x00);
146
147 dock_gpio_set_mode(0x02, PC87384_GPIO_PIN_TYPE_PUSH_PULL |
148 PC87384_GPIO_PIN_OE, 0x00);
149
150 dock_gpio_set_mode(0x03, PC87384_GPIO_PIN_DEBOUNCE |
151 PC87384_GPIO_PIN_PULLUP, 0x00);
152
153 dock_gpio_set_mode(0x04, PC87384_GPIO_PIN_DEBOUNCE |
154 PC87384_GPIO_PIN_PULLUP, 0x00);
155
156 dock_gpio_set_mode(0x05, PC87384_GPIO_PIN_DEBOUNCE |
157 PC87384_GPIO_PIN_PULLUP, 0x00);
158
159 dock_gpio_set_mode(0x06, PC87384_GPIO_PIN_DEBOUNCE |
160 PC87384_GPIO_PIN_PULLUP, 0x00);
161
162 dock_gpio_set_mode(0x07, PC87384_GPIO_PIN_DEBOUNCE |
163 PC87384_GPIO_PIN_PULLUP, 0x00);
164
Sven Schnelled8129f92011-04-20 09:12:17 +0000165
166 /* no GPIO events enabled for PORT0 */
167 outb(0x00, 0x1622);
168 /* clear GPIO events on PORT0 */
169 outb(0xff, 0x1623);
170 outb(0xff, 0x1624);
171 /* no GPIO events enabled for PORT1 */
172 outb(0x00, 0x1626);
173
174 /* clear GPIO events on PORT1*/
175 outb(0xff, 0x1627);
176 outb(0x1F, 0x1628);
Sven Schnelle40d99bc2011-07-11 15:22:42 +0200177 outb(0xfd, 0x1620);
Sven Schnelled8129f92011-04-20 09:12:17 +0000178 return 0;
179}
180
181int dock_connect(void)
182{
183 int timeout = 1000;
184
Sven Schnelleb5381102011-10-15 17:31:01 +0200185 outb(0x07, DLPC_CONTROL);
Sven Schnelled8129f92011-04-20 09:12:17 +0000186
187 timeout = 1000;
188
Sven Schnelleb5381102011-10-15 17:31:01 +0200189 while(!(inb(DLPC_CONTROL) & 8) && timeout--)
Sven Schnelled8129f92011-04-20 09:12:17 +0000190 udelay(1000);
191
192 if (!timeout) {
193 /* docking failed, disable DLPC switch */
Sven Schnelleb5381102011-10-15 17:31:01 +0200194 outb(0x00, DLPC_CONTROL);
Sven Schnelled8129f92011-04-20 09:12:17 +0000195 dlpc_write_register(0x30, 0x00);
196 return 1;
197 }
198
199 /* Assert D_PLTRST# */
200 outb(0xfe, 0x1680);
201 udelay(1000);
202 /* Deassert D_PLTRST# */
203 outb(0xff, 0x1680);
204 udelay(10000);
205
206 return dock_superio_init();
207}
208
209void dock_disconnect(void)
210{
211 /* disconnect LPC bus */
Sven Schnelleb5381102011-10-15 17:31:01 +0200212 outb(0x00, DLPC_CONTROL);
Sven Schnelled8129f92011-04-20 09:12:17 +0000213 /* Assert PLTRST and DLPCPD */
214 outb(0xfc, 0x1680);
215}
216
217int dock_present(void)
218{
Sven Schnelleb5381102011-10-15 17:31:01 +0200219 return pmh7_register_read(0x61) & 1;
Sven Schnelled8129f92011-04-20 09:12:17 +0000220}
221
Sven Schnelleb5381102011-10-15 17:31:01 +0200222int legacy_io_present(void)
223{
224 return !(inb(DEFAULT_GPIOBASE + 0x0c) & 0x40);
225}
226
227void legacy_io_init(void)
228{
229 /* Enable Power for Ultrabay slot */
230 pmh7_ultrabay_power_enable(1);
231 udelay(100000);
232 dock_superio_init();
233}