blob: c2bed9a087da545b7ee7facb1a91a76d621f6bf9 [file] [log] [blame]
Sven Schnellefea6bd12011-04-01 07:28:56 +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 Schnellefea6bd12011-04-01 07:28:56 +000015 */
16
17#include <console/console.h>
18#include <device/device.h>
19#include <arch/io.h>
Sven Schnellefea6bd12011-04-01 07:28:56 +000020#include <delay.h>
21#include <arch/io.h>
22#include "dock.h"
23#include "southbridge/intel/i82801gx/i82801gx.h"
Edward O'Callaghan74834e02015-01-04 04:17:35 +110024#include <superio/nsc/pc87392/pc87392.h>
Sven Schnellefea6bd12011-04-01 07:28:56 +000025
26static void dlpc_write_register(int reg, int value)
27{
28 outb(reg, 0x164e);
29 outb(value, 0x164f);
30}
31
32static u8 dlpc_read_register(int reg)
33{
34 outb(reg, 0x164e);
35 return inb(0x164f);
36}
37
38static void dock_write_register(int reg, int value)
39{
40 outb(reg, 0x2e);
41 outb(value, 0x2f);
42}
43
44static u8 dock_read_register(int reg)
45{
46 outb(reg, 0x2e);
47 return inb(0x2f);
48}
49
50static void dlpc_gpio_set_mode(int port, int mode)
51{
52 dlpc_write_register(0xf0, port);
53 dlpc_write_register(0xf1, mode);
54}
55
56static void dock_gpio_set_mode(int port, int mode, int irq)
57{
58 dock_write_register(0xf0, port);
59 dock_write_register(0xf1, mode);
60 dock_write_register(0xf2, irq);
61}
62
63static void dlpc_gpio_init(void)
64{
65 /* Select GPIO module */
66 dlpc_write_register(0x07, 0x07);
67 /* GPIO Base Address 0x1680 */
68 dlpc_write_register(0x60, 0x16);
69 dlpc_write_register(0x61, 0x80);
70
71 /* Activate GPIO */
72 dlpc_write_register(0x30, 0x01);
73
74 dlpc_gpio_set_mode(0x00, 3);
75 dlpc_gpio_set_mode(0x01, 3);
76 dlpc_gpio_set_mode(0x02, 0);
77 dlpc_gpio_set_mode(0x03, 3);
78 dlpc_gpio_set_mode(0x04, 4);
79 dlpc_gpio_set_mode(0x20, 4);
80 dlpc_gpio_set_mode(0x21, 4);
81 dlpc_gpio_set_mode(0x23, 4);
82}
83
84int dlpc_init(void)
85{
86 int timeout = 1000;
87
88 /* Enable 14.318MHz CLK on CLKIN */
89 dlpc_write_register(0x29, 0xa0);
90 while(!(dlpc_read_register(0x29) & 0x10) && timeout--)
91 udelay(1000);
92
93 if (!timeout)
94 return 1;
95
96 /* Select DLPC module */
97 dlpc_write_register(0x07, 0x19);
98 /* DLPC Base Address 0x164c */
99 dlpc_write_register(0x60, 0x16);
100 dlpc_write_register(0x61, 0x4c);
101 /* Activate DLPC */
102 dlpc_write_register(0x30, 0x01);
103
Sven Schnelle483ec412012-01-10 14:44:12 +0100104 dlpc_gpio_init();
105
106 return 0;
107}
108
109int dock_connect(void)
110{
111 int timeout = 1000;
112
Sven Schnellefea6bd12011-04-01 07:28:56 +0000113 outb(0x07, 0x164c);
114
115 timeout = 1000;
116
117 while(!(inb(0x164c) & 8) && timeout--)
118 udelay(1000);
119
120 if (!timeout) {
121 /* docking failed, disable DLPC switch */
122 outb(0x00, 0x164c);
123 dlpc_write_register(0x30, 0x00);
124 return 1;
125 }
126
Sven Schnellefea6bd12011-04-01 07:28:56 +0000127 /* Assert D_PLTRST# */
128 outb(0xfe, 0x1680);
Sven Schnelle8d0b86c2011-07-11 18:36:16 +0200129 udelay(100000);
Sven Schnellefea6bd12011-04-01 07:28:56 +0000130 /* Deassert D_PLTRST# */
131 outb(0xff, 0x1680);
132
Sven Schnelle483ec412012-01-10 14:44:12 +0100133 udelay(100000);
Sven Schnelle8d0b86c2011-07-11 18:36:16 +0200134
Sven Schnellefea6bd12011-04-01 07:28:56 +0000135 /* startup 14.318MHz Clock */
136 dock_write_register(0x29, 0x06);
137 /* wait until clock is settled */
Sven Schnelle483ec412012-01-10 14:44:12 +0100138 timeout = 1000;
Sven Schnellefea6bd12011-04-01 07:28:56 +0000139 while(!(dock_read_register(0x29) & 0x08) && timeout--)
140 udelay(1000);
141
142 if (!timeout)
143 return 1;
144
145 /* Pin 6: CLKRUN
146 * Pin 72: #DR1
147 * Pin 19: #SMI
148 * Pin 73: #MTR
149 */
150 dock_write_register(0x24, 0x37);
151
152 /* PNF active HIGH */
153 dock_write_register(0x25, 0xa0);
154
155 /* disable FDC */
156 dock_write_register(0x26, 0x01);
157
158 /* Enable GPIO IRQ to #SMI */
159 dock_write_register(0x28, 0x02);
160
161 /* select GPIO */
162 dock_write_register(0x07, 0x07);
163
164 /* set base address */
165 dock_write_register(0x60, 0x16);
166 dock_write_register(0x61, 0x20);
167
168 /* init GPIO pins */
169 dock_gpio_set_mode(0x00, PC87392_GPIO_PIN_DEBOUNCE |
170 PC87392_GPIO_PIN_PULLUP, 0x00);
171
172 dock_gpio_set_mode(0x01, PC87392_GPIO_PIN_DEBOUNCE |
173 PC87392_GPIO_PIN_PULLUP,
174 PC87392_GPIO_PIN_TRIGGERS_SMI);
175
176 dock_gpio_set_mode(0x02, PC87392_GPIO_PIN_PULLUP, 0x00);
177 dock_gpio_set_mode(0x03, PC87392_GPIO_PIN_PULLUP, 0x00);
178 dock_gpio_set_mode(0x04, PC87392_GPIO_PIN_PULLUP, 0x00);
179 dock_gpio_set_mode(0x05, PC87392_GPIO_PIN_PULLUP, 0x00);
180 dock_gpio_set_mode(0x06, PC87392_GPIO_PIN_PULLUP, 0x00);
181 dock_gpio_set_mode(0x07, PC87392_GPIO_PIN_PULLUP, 0x02);
182
183 dock_gpio_set_mode(0x10, PC87392_GPIO_PIN_DEBOUNCE |
184 PC87392_GPIO_PIN_PULLUP,
185 PC87392_GPIO_PIN_TRIGGERS_SMI);
186
187 dock_gpio_set_mode(0x11, PC87392_GPIO_PIN_PULLUP, 0x00);
188 dock_gpio_set_mode(0x12, PC87392_GPIO_PIN_PULLUP, 0x00);
189 dock_gpio_set_mode(0x13, PC87392_GPIO_PIN_PULLUP, 0x00);
190 dock_gpio_set_mode(0x14, PC87392_GPIO_PIN_PULLUP, 0x00);
191 dock_gpio_set_mode(0x15, PC87392_GPIO_PIN_PULLUP, 0x00);
192 dock_gpio_set_mode(0x16, PC87392_GPIO_PIN_PULLUP |
193 PC87392_GPIO_PIN_OE , 0x00);
194
195 dock_gpio_set_mode(0x17, PC87392_GPIO_PIN_PULLUP, 0x00);
196
197 dock_gpio_set_mode(0x20, PC87392_GPIO_PIN_TYPE_PUSH_PULL |
198 PC87392_GPIO_PIN_OE, 0x00);
199
200 dock_gpio_set_mode(0x21, PC87392_GPIO_PIN_TYPE_PUSH_PULL |
201 PC87392_GPIO_PIN_OE, 0x00);
202
203 dock_gpio_set_mode(0x22, PC87392_GPIO_PIN_PULLUP, 0x00);
204 dock_gpio_set_mode(0x23, PC87392_GPIO_PIN_PULLUP, 0x00);
205 dock_gpio_set_mode(0x24, PC87392_GPIO_PIN_PULLUP, 0x00);
206 dock_gpio_set_mode(0x25, PC87392_GPIO_PIN_PULLUP, 0x00);
207 dock_gpio_set_mode(0x26, PC87392_GPIO_PIN_PULLUP, 0x00);
208 dock_gpio_set_mode(0x27, PC87392_GPIO_PIN_PULLUP, 0x00);
209
210 dock_gpio_set_mode(0x30, PC87392_GPIO_PIN_PULLUP, 0x00);
211 dock_gpio_set_mode(0x31, PC87392_GPIO_PIN_PULLUP, 0x00);
212 dock_gpio_set_mode(0x32, PC87392_GPIO_PIN_PULLUP, 0x00);
213 dock_gpio_set_mode(0x33, PC87392_GPIO_PIN_PULLUP, 0x00);
214 dock_gpio_set_mode(0x34, PC87392_GPIO_PIN_PULLUP, 0x00);
215
216 dock_gpio_set_mode(0x35, PC87392_GPIO_PIN_PULLUP |
217 PC87392_GPIO_PIN_OE, 0x00);
218
219 dock_gpio_set_mode(0x36, PC87392_GPIO_PIN_PULLUP, 0x00);
220 dock_gpio_set_mode(0x37, PC87392_GPIO_PIN_PULLUP, 0x00);
221
222 /* enable GPIO */
223 dock_write_register(0x30, 0x01);
224
225 outb(0x00, 0x1628);
226 outb(0x00, 0x1623);
227 outb(0x82, 0x1622);
228 outb(0xff, 0x1624);
229
230 /* Enable USB and Ultrabay power */
231 outb(0x03, 0x1628);
Sven Schnelle8d0b86c2011-07-11 18:36:16 +0200232
233 dock_write_register(0x07, 0x03);
234 dock_write_register(0x30, 0x01);
Sven Schnellefea6bd12011-04-01 07:28:56 +0000235 return 0;
236}
237
238void dock_disconnect(void)
239{
Sven Schnelle483ec412012-01-10 14:44:12 +0100240 printk(BIOS_DEBUG, "%s enter\n", __func__);
Sven Schnellefea6bd12011-04-01 07:28:56 +0000241 /* disconnect LPC bus */
242 outb(0x00, 0x164c);
Sven Schnelle483ec412012-01-10 14:44:12 +0100243 udelay(10000);
244
Sven Schnellefea6bd12011-04-01 07:28:56 +0000245 /* Assert PLTRST and DLPCPD */
246 outb(0xfc, 0x1680);
Sven Schnelle483ec412012-01-10 14:44:12 +0100247 udelay(10000);
248
249 /* disable Ultrabay and USB Power */
250 outb(0x00, 0x1628);
251 udelay(10000);
252
253 printk(BIOS_DEBUG, "%s finish\n", __func__);
Sven Schnellefea6bd12011-04-01 07:28:56 +0000254}
255
256int dock_present(void)
257{
Patrick Georgib9eee8e2016-08-02 14:28:49 +0200258 return !((inw(DEFAULT_GPIOBASE + 0x0c) >> 13) & 1);
Sven Schnellefea6bd12011-04-01 07:28:56 +0000259}
Sven Schnelle50270b82011-04-27 19:48:05 +0000260
261int dock_ultrabay_device_present(void)
262{
263 return inb(0x1621) & 0x02 ? 0 : 1;
264}