blob: 3abe5c1151682c8a8da417f5a65f9153cdf2dcfb [file] [log] [blame]
Angel Pons89ab2502020-04-03 01:22:28 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Sven Schnellefea6bd12011-04-01 07:28:56 +00002
3#include <console/console.h>
4#include <device/device.h>
5#include <arch/io.h>
Sven Schnellefea6bd12011-04-01 07:28:56 +00006#include <delay.h>
Sven Schnellefea6bd12011-04-01 07:28:56 +00007#include "dock.h"
Elyes HAOUAS4ad14462018-06-16 18:29:33 +02008#include <southbridge/intel/i82801gx/i82801gx.h>
Edward O'Callaghan74834e02015-01-04 04:17:35 +11009#include <superio/nsc/pc87392/pc87392.h>
Sven Schnellefea6bd12011-04-01 07:28:56 +000010
11static void dlpc_write_register(int reg, int value)
12{
13 outb(reg, 0x164e);
14 outb(value, 0x164f);
15}
16
17static u8 dlpc_read_register(int reg)
18{
19 outb(reg, 0x164e);
20 return inb(0x164f);
21}
22
23static void dock_write_register(int reg, int value)
24{
25 outb(reg, 0x2e);
26 outb(value, 0x2f);
27}
28
29static u8 dock_read_register(int reg)
30{
31 outb(reg, 0x2e);
32 return inb(0x2f);
33}
34
35static void dlpc_gpio_set_mode(int port, int mode)
36{
37 dlpc_write_register(0xf0, port);
38 dlpc_write_register(0xf1, mode);
39}
40
41static void dock_gpio_set_mode(int port, int mode, int irq)
42{
43 dock_write_register(0xf0, port);
44 dock_write_register(0xf1, mode);
45 dock_write_register(0xf2, irq);
46}
47
48static void dlpc_gpio_init(void)
49{
50 /* Select GPIO module */
51 dlpc_write_register(0x07, 0x07);
52 /* GPIO Base Address 0x1680 */
53 dlpc_write_register(0x60, 0x16);
54 dlpc_write_register(0x61, 0x80);
55
56 /* Activate GPIO */
57 dlpc_write_register(0x30, 0x01);
58
59 dlpc_gpio_set_mode(0x00, 3);
60 dlpc_gpio_set_mode(0x01, 3);
61 dlpc_gpio_set_mode(0x02, 0);
62 dlpc_gpio_set_mode(0x03, 3);
63 dlpc_gpio_set_mode(0x04, 4);
64 dlpc_gpio_set_mode(0x20, 4);
65 dlpc_gpio_set_mode(0x21, 4);
66 dlpc_gpio_set_mode(0x23, 4);
67}
68
69int dlpc_init(void)
70{
71 int timeout = 1000;
72
73 /* Enable 14.318MHz CLK on CLKIN */
74 dlpc_write_register(0x29, 0xa0);
Elyes HAOUAS6aa9d662020-08-04 13:20:13 +020075 while (!(dlpc_read_register(0x29) & 0x10) && timeout--)
Sven Schnellefea6bd12011-04-01 07:28:56 +000076 udelay(1000);
77
78 if (!timeout)
79 return 1;
80
81 /* Select DLPC module */
82 dlpc_write_register(0x07, 0x19);
83 /* DLPC Base Address 0x164c */
84 dlpc_write_register(0x60, 0x16);
85 dlpc_write_register(0x61, 0x4c);
86 /* Activate DLPC */
87 dlpc_write_register(0x30, 0x01);
88
Sven Schnelle483ec412012-01-10 14:44:12 +010089 dlpc_gpio_init();
90
91 return 0;
92}
93
94int dock_connect(void)
95{
96 int timeout = 1000;
97
Sven Schnellefea6bd12011-04-01 07:28:56 +000098 outb(0x07, 0x164c);
99
100 timeout = 1000;
101
Elyes HAOUAS6aa9d662020-08-04 13:20:13 +0200102 while (!(inb(0x164c) & 8) && timeout--)
Sven Schnellefea6bd12011-04-01 07:28:56 +0000103 udelay(1000);
104
105 if (!timeout) {
106 /* docking failed, disable DLPC switch */
107 outb(0x00, 0x164c);
108 dlpc_write_register(0x30, 0x00);
109 return 1;
110 }
111
Sven Schnellefea6bd12011-04-01 07:28:56 +0000112 /* Assert D_PLTRST# */
113 outb(0xfe, 0x1680);
Sven Schnelle8d0b86c2011-07-11 18:36:16 +0200114 udelay(100000);
Sven Schnellefea6bd12011-04-01 07:28:56 +0000115 /* Deassert D_PLTRST# */
116 outb(0xff, 0x1680);
117
Sven Schnelle483ec412012-01-10 14:44:12 +0100118 udelay(100000);
Sven Schnelle8d0b86c2011-07-11 18:36:16 +0200119
Sven Schnellefea6bd12011-04-01 07:28:56 +0000120 /* startup 14.318MHz Clock */
121 dock_write_register(0x29, 0x06);
122 /* wait until clock is settled */
Sven Schnelle483ec412012-01-10 14:44:12 +0100123 timeout = 1000;
Elyes HAOUAS6aa9d662020-08-04 13:20:13 +0200124 while (!(dock_read_register(0x29) & 0x08) && timeout--)
Sven Schnellefea6bd12011-04-01 07:28:56 +0000125 udelay(1000);
126
127 if (!timeout)
128 return 1;
129
130 /* Pin 6: CLKRUN
131 * Pin 72: #DR1
132 * Pin 19: #SMI
133 * Pin 73: #MTR
134 */
135 dock_write_register(0x24, 0x37);
136
137 /* PNF active HIGH */
138 dock_write_register(0x25, 0xa0);
139
140 /* disable FDC */
141 dock_write_register(0x26, 0x01);
142
143 /* Enable GPIO IRQ to #SMI */
144 dock_write_register(0x28, 0x02);
145
146 /* select GPIO */
147 dock_write_register(0x07, 0x07);
148
149 /* set base address */
150 dock_write_register(0x60, 0x16);
151 dock_write_register(0x61, 0x20);
152
153 /* init GPIO pins */
154 dock_gpio_set_mode(0x00, PC87392_GPIO_PIN_DEBOUNCE |
155 PC87392_GPIO_PIN_PULLUP, 0x00);
156
157 dock_gpio_set_mode(0x01, PC87392_GPIO_PIN_DEBOUNCE |
158 PC87392_GPIO_PIN_PULLUP,
159 PC87392_GPIO_PIN_TRIGGERS_SMI);
160
161 dock_gpio_set_mode(0x02, PC87392_GPIO_PIN_PULLUP, 0x00);
162 dock_gpio_set_mode(0x03, PC87392_GPIO_PIN_PULLUP, 0x00);
163 dock_gpio_set_mode(0x04, PC87392_GPIO_PIN_PULLUP, 0x00);
164 dock_gpio_set_mode(0x05, PC87392_GPIO_PIN_PULLUP, 0x00);
165 dock_gpio_set_mode(0x06, PC87392_GPIO_PIN_PULLUP, 0x00);
166 dock_gpio_set_mode(0x07, PC87392_GPIO_PIN_PULLUP, 0x02);
167
168 dock_gpio_set_mode(0x10, PC87392_GPIO_PIN_DEBOUNCE |
169 PC87392_GPIO_PIN_PULLUP,
170 PC87392_GPIO_PIN_TRIGGERS_SMI);
171
172 dock_gpio_set_mode(0x11, PC87392_GPIO_PIN_PULLUP, 0x00);
173 dock_gpio_set_mode(0x12, PC87392_GPIO_PIN_PULLUP, 0x00);
174 dock_gpio_set_mode(0x13, PC87392_GPIO_PIN_PULLUP, 0x00);
175 dock_gpio_set_mode(0x14, PC87392_GPIO_PIN_PULLUP, 0x00);
176 dock_gpio_set_mode(0x15, PC87392_GPIO_PIN_PULLUP, 0x00);
177 dock_gpio_set_mode(0x16, PC87392_GPIO_PIN_PULLUP |
Elyes HAOUASa342f392018-10-17 10:56:26 +0200178 PC87392_GPIO_PIN_OE, 0x00);
Sven Schnellefea6bd12011-04-01 07:28:56 +0000179
180 dock_gpio_set_mode(0x17, PC87392_GPIO_PIN_PULLUP, 0x00);
181
182 dock_gpio_set_mode(0x20, PC87392_GPIO_PIN_TYPE_PUSH_PULL |
183 PC87392_GPIO_PIN_OE, 0x00);
184
185 dock_gpio_set_mode(0x21, PC87392_GPIO_PIN_TYPE_PUSH_PULL |
186 PC87392_GPIO_PIN_OE, 0x00);
187
188 dock_gpio_set_mode(0x22, PC87392_GPIO_PIN_PULLUP, 0x00);
189 dock_gpio_set_mode(0x23, PC87392_GPIO_PIN_PULLUP, 0x00);
190 dock_gpio_set_mode(0x24, PC87392_GPIO_PIN_PULLUP, 0x00);
191 dock_gpio_set_mode(0x25, PC87392_GPIO_PIN_PULLUP, 0x00);
192 dock_gpio_set_mode(0x26, PC87392_GPIO_PIN_PULLUP, 0x00);
193 dock_gpio_set_mode(0x27, PC87392_GPIO_PIN_PULLUP, 0x00);
194
195 dock_gpio_set_mode(0x30, PC87392_GPIO_PIN_PULLUP, 0x00);
196 dock_gpio_set_mode(0x31, PC87392_GPIO_PIN_PULLUP, 0x00);
197 dock_gpio_set_mode(0x32, PC87392_GPIO_PIN_PULLUP, 0x00);
198 dock_gpio_set_mode(0x33, PC87392_GPIO_PIN_PULLUP, 0x00);
199 dock_gpio_set_mode(0x34, PC87392_GPIO_PIN_PULLUP, 0x00);
200
201 dock_gpio_set_mode(0x35, PC87392_GPIO_PIN_PULLUP |
202 PC87392_GPIO_PIN_OE, 0x00);
203
204 dock_gpio_set_mode(0x36, PC87392_GPIO_PIN_PULLUP, 0x00);
205 dock_gpio_set_mode(0x37, PC87392_GPIO_PIN_PULLUP, 0x00);
206
207 /* enable GPIO */
208 dock_write_register(0x30, 0x01);
209
210 outb(0x00, 0x1628);
211 outb(0x00, 0x1623);
212 outb(0x82, 0x1622);
213 outb(0xff, 0x1624);
214
215 /* Enable USB and Ultrabay power */
216 outb(0x03, 0x1628);
Sven Schnelle8d0b86c2011-07-11 18:36:16 +0200217
218 dock_write_register(0x07, 0x03);
219 dock_write_register(0x30, 0x01);
Sven Schnellefea6bd12011-04-01 07:28:56 +0000220 return 0;
221}
222
223void dock_disconnect(void)
224{
Sven Schnelle483ec412012-01-10 14:44:12 +0100225 printk(BIOS_DEBUG, "%s enter\n", __func__);
Sven Schnellefea6bd12011-04-01 07:28:56 +0000226 /* disconnect LPC bus */
227 outb(0x00, 0x164c);
Sven Schnelle483ec412012-01-10 14:44:12 +0100228 udelay(10000);
229
Sven Schnellefea6bd12011-04-01 07:28:56 +0000230 /* Assert PLTRST and DLPCPD */
231 outb(0xfc, 0x1680);
Sven Schnelle483ec412012-01-10 14:44:12 +0100232 udelay(10000);
233
234 /* disable Ultrabay and USB Power */
235 outb(0x00, 0x1628);
236 udelay(10000);
237
238 printk(BIOS_DEBUG, "%s finish\n", __func__);
Sven Schnellefea6bd12011-04-01 07:28:56 +0000239}
240
241int dock_present(void)
242{
Patrick Georgib9eee8e2016-08-02 14:28:49 +0200243 return !((inw(DEFAULT_GPIOBASE + 0x0c) >> 13) & 1);
Sven Schnellefea6bd12011-04-01 07:28:56 +0000244}
Sven Schnelle50270b82011-04-27 19:48:05 +0000245
246int dock_ultrabay_device_present(void)
247{
248 return inb(0x1621) & 0x02 ? 0 : 1;
249}