coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
dock.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #define __SIMPLE_DEVICE__
4 #include <console/console.h>
5 #include <arch/io.h>
6 #include <device/pnp_ops.h>
7 #include <device/device.h>
8 #include <device/pnp.h>
9 #include <delay.h>
10 #include "dock.h"
12 
14 #include <ec/lenovo/h8/h8.h>
15 #include <ec/acpi/ec.h>
16 
17 struct pin_config {
20 };
21 
22 static int poll_clk_stable(pnp_devfn_t dev, int timeout)
23 {
24  /* Enable 14.318MHz CLK on CLKIN */
25  pnp_write_config(dev, 0x29, 0xa0);
26  while (!(pnp_read_config(dev, 0x29) & 0x10) && timeout--)
27  udelay(1000);
28  if (!timeout)
29  return 1;
30 
31  return 0;
32 }
33 
34 static int gpio_init(pnp_devfn_t gpio, u16 gpio_base,
35  const struct pin_config pincfg[], int num_cfgs)
36 {
37  int i;
38 
39  /* Enable GPIO LDN. */
41  pnp_set_iobase(gpio, PNP_IDX_IO0, gpio_base);
42  pnp_set_enable(gpio, 1);
43 
44  for (i = 0; i < num_cfgs; i++) {
45  pnp_write_config(gpio, 0xf0, pincfg[i].port);
46  pnp_write_config(gpio, 0xf1, pincfg[i].mode);
47  pnp_write_config(gpio, 0xf2, 0x0);
48  }
49  return 0;
50 }
51 
52 static const pnp_devfn_t l_dlpc = PNP_DEV(0x164e, PC87382_DOCK);
53 static const pnp_devfn_t l_gpio = PNP_DEV(0x164e, PC87382_GPIO);
54 
55 static int pc87382_init(pnp_devfn_t dlpc, u16 dlpc_base)
56 {
57  /* Maximum 3300 LCLKs at 14.318MHz */
58  int timeout = 230;
59 
60  /* Enable LPC bridge LDN. */
62  pnp_set_iobase(dlpc, PNP_IDX_IO0, dlpc_base);
63  pnp_set_enable(dlpc, 1);
64 
65  /* Reset docking state */
66  outb(0x00, dlpc_base);
67  outb(0x07, dlpc_base);
68  while (!(inb(dlpc_base) & 8) && timeout--)
69  udelay(1);
70  if (!timeout)
71  return 1;
72 
73  return 0;
74 }
75 
76 static void pc87382_close(pnp_devfn_t dlpc)
77 {
79 
80  /* Disconnect LPC bus */
81  u16 dlpc_base = pnp_read_iobase(dlpc, PNP_IDX_IO0);
82  if (dlpc_base) {
83  outb(0x00, dlpc_base);
84  pnp_set_enable(dlpc, 0);
85  }
86 }
87 
88 static const struct pin_config local_gpio[] = {
89  {0x00, 3}, {0x01, 3}, {0x02, 0}, {0x03, 3},
90  {0x04, 4}, {0x20, 4}, {0x21, 4}, {0x23, 4},
91 };
92 
93 /* Enable internal clock and configure GPIO LDN */
94 int pc87382_early(void)
95 {
96  /* Wake-up time is 33 msec (maximum). */
97  if (poll_clk_stable(l_gpio, 33) != 0)
98  return 1;
99 
100  /* Set up GPIOs */
102  local_gpio, ARRAY_SIZE(local_gpio)) != 0) {
103  return 1;
104  }
105 
106  return 0;
107 }
108 
109 static int pc87382_connect(void)
110 {
111  u8 reg;
112 
113  reg = inb(DLPC_GPDO0);
114  reg |= D_PLTRST | D_LPCPD;
115  /* Deassert D_PLTRST# and D_LPCPD# */
116  outb(reg, DLPC_GPDO0);
117 
118  if (pc87382_init(l_dlpc, DLPC_CONTROL) != 0)
119  return 1;
120 
121  /* Assert D_PLTRST# */
122  reg &= ~D_PLTRST;
123  outb(reg, DLPC_GPDO0);
124  udelay(1000);
125 
126  /* Deassert D_PLTRST# */
127  reg |= D_PLTRST;
128  outb(reg, DLPC_GPDO0);
129  mdelay(10);
130 
131  return 0;
132 }
133 
134 static void pc87382_disconnect(void)
135 {
137 
138  /* Assert D_PLTRST# and D_LPCPD# */
139  u8 reg = inb(DLPC_GPDO0);
140  reg &= ~(D_PLTRST | D_LPCPD);
141  outb(reg, DLPC_GPDO0);
142 }
143 
144 /* Returns 3bit dock id */
145 static u8 dock_identify(void)
146 {
147  u8 id;
148 
149  /* Make sure GPIO LDN is configured first ! */
150  id = (inb(DLPC_GPDI0) >> 4) & 1;
151  id |= (inb(DLPC_GPDI2) & 3) << 1;
152 
153  return id;
154 }
155 
156 /* Docking station side. */
157 
159 
162 
163 static const struct pin_config remote_gpio[] = {
172 };
173 
174 static int pc87384_init(void)
175 {
176  if (poll_clk_stable(r_gpio, 1000) != 0)
177  return 1;
178 
179  /* set GPIO pins to Serial/Parallel Port
180  * functions
181  */
182  pnp_write_config(r_gpio, 0x22, 0xa9);
183 
184  /* enable serial port */
185 
186  if (CONFIG_TTYS0_BASE > 0) {
188  pnp_set_iobase(r_serial, PNP_IDX_IO0, CONFIG_TTYS0_BASE);
190  }
191 
194  return 1;
195 
196  /* no GPIO events enabled for PORT0 */
197  outb(0x00, DOCK_GPIO_BASE + 0x02);
198  /* clear GPIO events on PORT0 */
199  outb(0xff, DOCK_GPIO_BASE + 0x03);
200  outb(0xff, DOCK_GPIO_BASE + 0x04);
201 
202  /* no GPIO events enabled for PORT1 */
203  outb(0x00, DOCK_GPIO_BASE + 0x06);
204  /* clear GPIO events on PORT1*/
205  outb(0xff, DOCK_GPIO_BASE + 0x07);
206  outb(0x1f, DOCK_GPIO_BASE + 0x08);
207 
208  outb(0xfd, DOCK_GPIO_BASE + 0x00);
209 
210  return 0;
211 }
212 
213 /* Mainboard */
214 
215 void dock_connect(void)
216 {
217  const u8 id = dock_identify();
218 
219  /* Dock type 2505 doesn't have serial, LPT port or LEDs */
220  if (id == DOCK_TYPE_NONE || id == DOCK_TYPE_2505)
221  return;
222 
223  if (pc87382_connect() != 0 || pc87384_init() != 0) {
225  return;
226  }
227 
232 }
233 
234 void dock_disconnect(void)
235 {
237 
242 }
243 
244 void dock_info(void)
245 {
246  const u8 id = dock_identify();
247 
248  if (id != DOCK_TYPE_NONE)
249  printk(BIOS_DEBUG, "DOCK: is present: id=%d\n", id);
250  else
251  printk(BIOS_DEBUG, "DOCK: not connected\n");
252 }
#define ARRAY_SIZE(a)
Definition: helpers.h:12
#define printk(level,...)
Definition: stdlib.h:16
void mdelay(unsigned int msecs)
Definition: delay.c:2
u8 inb(u16 port)
void outb(u8 val, u16 port)
int ec_write(u8 addr, u8 data)
Definition: ec.c:115
#define H8_LED_CONTROL
Definition: h8.h:71
#define H8_LED_CONTROL_DOCK_LED1
Definition: h8.h:82
#define H8_LED_CONTROL_ON
Definition: h8.h:73
#define H8_LED_CONTROL_OFF
Definition: h8.h:72
#define H8_LED_CONTROL_DOCK_LED2
Definition: h8.h:83
port
Definition: i915.h:29
#define BIOS_DEBUG
BIOS_DEBUG - Verbose output.
Definition: loglevel.h:128
#define SUPERIO_DEV
Definition: early_init.c:11
#define PC87382_GPIO
Definition: pc87382.h:8
#define PC87382_DOCK
Definition: pc87382.h:9
#define PC87384_GPIO_PIN_OE
Definition: pc87384.h:11
#define PC87384_GPIO
Definition: pc87384.h:9
#define PC87384_SP1
Definition: pc87384.h:8
#define PC87384_GPIO_PIN_DEBOUNCE
Definition: pc87384.h:17
#define PC87384_GPIO_PIN_TYPE_PUSH_PULL
Definition: pc87384.h:12
#define PC87384_GPIO_PIN_PULLUP
Definition: pc87384.h:13
#define PNP_IDX_IO0
Definition: pnp_def.h:5
void pnp_set_logical_device(struct device *dev)
Definition: pnp_device.c:59
void pnp_set_enable(struct device *dev, int enable)
Definition: pnp_device.c:64
u8 pnp_read_config(struct device *dev, u8 reg)
Definition: pnp_device.c:44
void pnp_set_iobase(struct device *dev, u8 index, u16 iobase)
Definition: pnp_device.c:93
void pnp_write_config(struct device *dev, u8 reg, u8 value)
Definition: pnp_device.c:38
#define PNP_DEV(PORT, FUNC)
Definition: pnp_type.h:10
u32 pnp_devfn_t
Definition: pnp_type.h:8
uint16_t u16
Definition: stdint.h:48
uint8_t u8
Definition: stdint.h:45
Definition: pinmux.c:36
u8 port
Definition: dock.c:18
u8 mode
Definition: dock.c:19
void dock_connect(void)
Definition: dock.c:215
static const pnp_devfn_t r_serial
Definition: dock.c:161
int pc87382_early(void)
Definition: dock.c:94
void dock_disconnect(void)
Definition: dock.c:234
static int pc87382_init(pnp_devfn_t dlpc, u16 dlpc_base)
Definition: dock.c:55
static int pc87384_init(void)
Definition: dock.c:174
static int gpio_init(pnp_devfn_t gpio, u16 gpio_base, const struct pin_config pincfg[], int num_cfgs)
Definition: dock.c:34
static int pc87382_connect(void)
Definition: dock.c:109
static const pnp_devfn_t l_gpio
Definition: dock.c:53
static void pc87382_close(pnp_devfn_t dlpc)
Definition: dock.c:76
static u8 dock_identify(void)
Definition: dock.c:145
static int poll_clk_stable(pnp_devfn_t dev, int timeout)
Definition: dock.c:22
void dock_info(void)
Definition: dock.c:244
static void pc87382_disconnect(void)
Definition: dock.c:134
static const pnp_devfn_t l_dlpc
Definition: dock.c:52
static const struct pin_config remote_gpio[]
Definition: dock.c:163
static const pnp_devfn_t r_gpio
Definition: dock.c:160
static const struct pin_config local_gpio[]
Definition: dock.c:88
#define DOCK_TYPE_NONE
Definition: dock.h:30
#define D_PLTRST
Definition: dock.h:21
#define DLPC_GPDI0
Definition: dock.h:20
#define DLPC_GPIO_BASE
Definition: dock.h:17
#define DOCK_GPIO_BASE
Definition: dock.h:34
#define DOCK_TYPE_2505
Definition: dock.h:29
#define DLPC_GPDI2
Definition: dock.h:25
#define DLPC_GPDO0
Definition: dock.h:19
#define D_LPCPD
Definition: dock.h:22
#define DLPC_CONTROL
Definition: dock.c:12
void udelay(uint32_t us)
Definition: udelay.c:15