coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
lpc.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <arch/hpet.h>
4 #include <arch/io.h>
5 #include <arch/ioapic.h>
6 #include <console/console.h>
7 #include <device/device.h>
8 #include <device/pci.h>
9 #include <device/pci_ids.h>
10 #include <device/pci_ops.h>
11 #include <option.h>
12 #include <pc80/mc146818rtc.h>
13 #include <pc80/isa-dma.h>
14 #include <pc80/i8259.h>
15 #include "chip.h"
16 #include "i82801dx.h"
17 
18 #define NMI_OFF 0
19 
21 
22 /**
23  * Enable ACPI I/O range.
24  *
25  * @param dev PCI device with ACPI and PM BAR's
26  */
27 static void i82801dx_enable_acpi(struct device *dev)
28 {
29  /* Set ACPI base address (I/O space). */
31 
32  /* Enable ACPI I/O range decode and ACPI power management. */
34 }
35 
36 /**
37  * Set miscellaneous static southbridge features.
38  *
39  * @param dev PCI device with I/O APIC control registers
40  */
41 static void i82801dx_enable_ioapic(struct device *dev)
42 {
43  u32 reg32;
44 
45  reg32 = pci_read_config32(dev, GEN_CNTL);
46  reg32 |= (1 << 13); /* Coprocessor error enable (COPR_ERR_EN) */
47  reg32 |= (3 << 7); /* IOAPIC enable (APIC_EN) */
48  reg32 |= (1 << 2); /* DMA collection buffer enable (DCB_EN) */
49  reg32 |= (1 << 1); /* Delayed transaction enable (DTE) */
50  pci_write_config32(dev, GEN_CNTL, reg32);
51  printk(BIOS_DEBUG, "IOAPIC Southbridge enabled %x\n", reg32);
52 
54 
56 }
57 
58 static void i82801dx_enable_serial_irqs(struct device *dev)
59 {
60  /* Set packet length and toggle silent mode bit. */
62  (1 << 7) | (1 << 6) | ((21 - 17) << 2) | (0 << 0));
64  (1 << 7) | (0 << 6) | ((21 - 17) << 2) | (0 << 0));
65 }
66 
67 static void i82801dx_pirq_init(struct device *dev)
68 {
69  /* Get the chip configuration */
70  config_t *config = dev->chip_info;
71 
72  pci_write_config8(dev, PIRQA_ROUT, config->pirqa_routing);
73  pci_write_config8(dev, PIRQB_ROUT, config->pirqb_routing);
74  pci_write_config8(dev, PIRQC_ROUT, config->pirqc_routing);
75  pci_write_config8(dev, PIRQD_ROUT, config->pirqd_routing);
76  pci_write_config8(dev, PIRQE_ROUT, config->pirqe_routing);
77  pci_write_config8(dev, PIRQF_ROUT, config->pirqf_routing);
78  pci_write_config8(dev, PIRQG_ROUT, config->pirqg_routing);
79  pci_write_config8(dev, PIRQH_ROUT, config->pirqh_routing);
80 }
81 
82 static void i82801dx_power_options(struct device *dev)
83 {
84  u8 reg8;
85  u16 reg16, pmbase;
86  u32 reg32;
87  const char *state;
88 
89  /* Which state do we want to goto after g3 (power restored)?
90  * 0 == S0 Full On
91  * 1 == S5 Soft Off
92  *
93  * If the option is not existent (Laptops), use MAINBOARD_POWER_ON.
94  */
95  const unsigned int pwr_on = get_uint_option("power_on_after_fail", MAINBOARD_POWER_ON);
96 
97  reg8 = pci_read_config8(dev, GEN_PMCON_3);
98  reg8 &= 0xfe;
99  switch (pwr_on) {
100  case MAINBOARD_POWER_OFF:
101  reg8 |= 1;
102  state = "off";
103  break;
104  case MAINBOARD_POWER_ON:
105  reg8 &= ~1;
106  state = "on";
107  break;
109  reg8 &= ~1;
110  state = "state keep";
111  break;
112  default:
113  state = "undefined";
114  }
115 
116  reg8 &= ~(1 << 3); /* minimum assertion is 1 to 2 RTCCLK */
117 
118  pci_write_config8(dev, GEN_PMCON_3, reg8);
119  printk(BIOS_INFO, "Set power %s after power failure.\n", state);
120 
121  /* Set up NMI on errors. */
122  reg8 = inb(0x61);
123  reg8 &= 0x0f; /* Higher Nibble must be 0 */
124  reg8 &= ~(1 << 3); /* IOCHK# NMI Enable */
125  // reg8 &= ~(1 << 2); /* PCI SERR# Enable */
126  reg8 |= (1 << 2); /* PCI SERR# Disable for now */
127  outb(reg8, 0x61);
128 
129  reg8 = inb(0x70);
130  const unsigned int nmi_option = get_uint_option("nmi", NMI_OFF);
131  if (nmi_option) {
132  printk(BIOS_INFO, "NMI sources enabled.\n");
133  reg8 &= ~(1 << 7); /* Set NMI. */
134  } else {
135  printk(BIOS_INFO, "NMI sources disabled.\n");
136  reg8 |= (1 << 7); /* Disable NMI. */
137  }
138  outb(reg8, 0x70);
139 
140  /* Set SMI# rate down and enable CPU_SLP# */
141  reg16 = pci_read_config16(dev, GEN_PMCON_1);
142  reg16 &= ~(3 << 0); // SMI# rate 1 minute
143  reg16 |= (1 << 5); // CPUSLP_EN Desktop only
144  pci_write_config16(dev, GEN_PMCON_1, reg16);
145 
146  pmbase = pci_read_config16(dev, 0x40) & 0xfffe;
147 
148  /* Set up power management block and determine sleep mode */
149  reg32 = inl(pmbase + 0x04); // PM1_CNT
150 
151  reg32 &= ~(7 << 10); // SLP_TYP
152  reg32 |= (1 << 0); // SCI_EN
153  outl(reg32, pmbase + 0x04);
154 }
155 
156 static void gpio_init(struct device *dev)
157 {
158  /* This should be done in romstage.c already */
160  pci_write_config8(dev, GPIO_CNTL, 0x10);
161 }
162 
163 static void i82801dx_rtc_init(struct device *dev)
164 {
165  u8 reg8;
166  u32 reg32;
167  int rtc_failed;
168 
169  reg8 = pci_read_config8(dev, GEN_PMCON_3);
170  rtc_failed = reg8 & RTC_BATTERY_DEAD;
171  if (rtc_failed) {
172  reg8 &= ~(1 << 1); /* Preserve the power fail state. */
173  pci_write_config8(dev, GEN_PMCON_3, reg8);
174  }
175  reg32 = pci_read_config32(dev, GEN_STS);
176  rtc_failed |= reg32 & (1 << 2);
178 
179  /* Enable access to the upper 128 byte bank of CMOS RAM. */
180  pci_write_config8(dev, RTC_CONF, 0x04);
181 }
182 
183 static void i82801dx_lpc_route_dma(struct device *dev, u8 mask)
184 {
185  u16 reg16;
186  int i;
187 
188  reg16 = pci_read_config16(dev, PCI_DMA_CFG);
189  reg16 &= 0x300;
190  for (i = 0; i < 8; i++) {
191  if (i == 4)
192  continue;
193  reg16 |= ((mask & (1 << i)) ? 3 : 1) << (i * 2);
194  }
195  pci_write_config16(dev, PCI_DMA_CFG, reg16);
196 }
197 
198 static void i82801dx_lpc_decode_en(struct device *dev)
199 {
200  /* Decode 0x3F8-0x3FF (COM1) for COMA port, 0x2F8-0x2FF (COM2) for COMB.
201  * LPT decode defaults to 0x378-0x37F and 0x778-0x77F.
202  * Floppy decode defaults to 0x3F0-0x3F5, 0x3F7.
203  * We also need to set the value for LPC I/F Enables Register.
204  */
205  pci_write_config8(dev, COM_DEC, 0x10);
206  pci_write_config16(dev, LPC_EN, 0x300F);
207 }
208 
209 /* ICH4 does not mention HPET in the docs, but
210  * all ICH3 and ICH4 do have HPETs built in.
211  */
212 static void enable_hpet(struct device *dev)
213 {
214  u32 reg32, hpet, val;
215 
216  /* Set HPET base address and enable it */
217  printk(BIOS_DEBUG, "Enabling HPET at 0x%x\n", HPET_BASE_ADDRESS);
218  reg32 = pci_read_config32(dev, GEN_CNTL);
219  /*
220  * Bit 17 is HPET enable bit.
221  * Bit 16:15 control the HPET base address.
222  */
223  reg32 &= ~(3 << 15); /* Clear it */
224 
225  hpet = HPET_BASE_ADDRESS >> 12;
226  hpet &= 0x3;
227 
228  reg32 |= (hpet << 15);
229  reg32 |= (1 << 17); /* Enable HPET. */
230  pci_write_config32(dev, GEN_CNTL, reg32);
231 
232  /* Check to see whether it took */
233  reg32 = pci_read_config32(dev, GEN_CNTL);
234  val = reg32 >> 15;
235  val &= 0x7;
236 
237  if ((val & 0x4) && (hpet == (val & 0x3))) {
238  printk(BIOS_INFO, "HPET enabled at 0x%x\n", HPET_BASE_ADDRESS);
239  } else {
240  printk(BIOS_WARNING, "HPET was not enabled correctly\n");
241  reg32 &= ~(1 << 17); /* Clear Enable */
242  pci_write_config32(dev, GEN_CNTL, reg32);
243  }
244 }
245 
246 static void lpc_init(struct device *dev)
247 {
249  /* IO APIC initialization. */
251 
253 
254  /* Setup the PIRQ. */
255  i82801dx_pirq_init(dev);
256 
257  /* Setup power options. */
259 
260  /* Set the state of the GPIO lines. */
261  gpio_init(dev);
262 
263  /* Initialize the real time clock. */
264  i82801dx_rtc_init(dev);
265 
266  /* Route DMA. */
267  i82801dx_lpc_route_dma(dev, 0xff);
268 
269  /* Initialize ISA DMA. */
270  isa_dma_init();
271 
272  /* Setup decode ports and LPC I/F enables. */
274 
275  /* Initialize the High Precision Event Timers */
276  enable_hpet(dev);
277 
278  setup_i8259();
279 
280  /* Don't allow evil boot loaders, kernels, or
281  * userspace applications to deceive us:
282  */
283  if (CONFIG(SMM_LEGACY_ASEG))
284  aseg_smm_lock();
285 }
286 
287 static void i82801dx_lpc_read_resources(struct device *dev)
288 {
289  struct resource *res;
290 
291  /* Get the normal PCI resources of this device. */
293 
294  /* Add an extra subtractive resource for both memory and I/O. */
295  res = new_resource(dev, IOINDEX_SUBTRACTIVE(0, 0));
296  res->base = 0;
297  res->size = 0x1000;
300 
301  res = new_resource(dev, IOINDEX_SUBTRACTIVE(1, 0));
302  res->base = 0xff800000;
303  res->size = 0x00800000; /* 8 MB for flash */
306 
307  res = new_resource(dev, 3); /* IOAPIC */
308  res->base = IO_APIC_ADDR;
309  res->size = 0x00001000;
311 }
312 
313 static struct device_operations lpc_ops = {
315  .set_resources = pci_dev_set_resources,
316  .enable_resources = pci_dev_enable_resources,
317  .init = lpc_init,
318  .scan_bus = scan_static_bus,
319  .enable = i82801dx_enable,
320 };
321 
322 /* 82801DB/DBL */
323 static const struct pci_driver lpc_driver_db __pci_driver = {
324  .ops = &lpc_ops,
325  .vendor = PCI_VID_INTEL,
326  .device = PCI_DID_INTEL_82801DB_LPC,
327 };
328 
329 /* 82801DBM */
330 static const struct pci_driver lpc_driver_dbm __pci_driver = {
331  .ops = &lpc_ops,
332  .vendor = PCI_VID_INTEL,
333  .device = PCI_DID_INTEL_82801DBM_LPC,
334 };
#define HPET_BASE_ADDRESS
Definition: hpet.h:6
#define VIO_APIC_VADDR
Definition: ioapic.h:7
#define IO_APIC_ADDR
Definition: ioapic.h:6
void ioapic_set_boot_config(void *ioapic_base, bool irq_on_fsb)
Definition: ioapic.c:143
void setup_ioapic(void *ioapic_base, u8 ioapic_id)
Definition: ioapic.c:160
#define MAINBOARD_POWER_ON
Definition: pm.h:94
#define MAINBOARD_POWER_OFF
Definition: pm.h:93
#define MAINBOARD_POWER_KEEP
Definition: pm.h:95
#define printk(level,...)
Definition: stdlib.h:16
u8 inb(u16 port)
void outb(u8 val, u16 port)
u32 inl(u16 port)
void outl(u32 val, u16 port)
struct resource * new_resource(struct device *dev, unsigned int index)
See if a resource structure already exists for a given index and if not allocate one.
Definition: device_util.c:346
@ CONFIG
Definition: dsi_common.h:201
void setup_i8259(void)
Definition: i8259.c:46
void i82801dx_enable(struct device *dev)
Definition: i82801dx.c:8
#define PCI_DMA_CFG
Definition: i82801dx.h:49
#define GPIOBASE_ADDR
Definition: i82801dx.h:65
void aseg_smm_lock(void)
Definition: smi.c:315
#define GEN_STS
Definition: i82801dx.h:52
#define PMBASE_ADDR
Definition: i82801dx.h:58
#define COM_DEC
Definition: i82801dx.h:74
#define GEN_CNTL
Definition: i82801dx.h:51
#define RTC_CONF
Definition: i82801dx.h:53
static __always_inline void pci_write_config32(const struct device *dev, u16 reg, u32 val)
Definition: pci_ops.h:76
static __always_inline u16 pci_read_config16(const struct device *dev, u16 reg)
Definition: pci_ops.h:52
static __always_inline u32 pci_read_config32(const struct device *dev, u16 reg)
Definition: pci_ops.h:58
static __always_inline u8 pci_read_config8(const struct device *dev, u16 reg)
Definition: pci_ops.h:46
static __always_inline void pci_write_config16(const struct device *dev, u16 reg, u16 val)
Definition: pci_ops.h:70
static __always_inline void pci_write_config8(const struct device *dev, u16 reg, u8 val)
Definition: pci_ops.h:64
#define ACPI_EN
Definition: pmc.h:146
#define RTC_BATTERY_DEAD
Definition: pmc.h:61
void isa_dma_init(void)
Definition: isa-dma.c:35
#define BIOS_INFO
BIOS_INFO - Expected events.
Definition: loglevel.h:113
#define BIOS_DEBUG
BIOS_DEBUG - Verbose output.
Definition: loglevel.h:128
#define BIOS_WARNING
BIOS_WARNING - Bad configuration.
Definition: loglevel.h:86
enum board_config config
Definition: memory.c:448
void cmos_init(bool invalid)
Definition: mc146818rtc.c:156
state
Definition: raminit.c:1787
unsigned int get_uint_option(const char *name, const unsigned int fallback)
Definition: option.c:116
void pci_dev_enable_resources(struct device *dev)
Definition: pci_device.c:721
void pci_dev_read_resources(struct device *dev)
Definition: pci_device.c:534
void pci_dev_set_resources(struct device *dev)
Definition: pci_device.c:691
#define PCI_DID_INTEL_82801DB_LPC
Definition: pci_ids.h:2275
#define PCI_DID_INTEL_82801DBM_LPC
Definition: pci_ids.h:2307
#define PCI_VID_INTEL
Definition: pci_ids.h:2157
#define IORESOURCE_MEM
Definition: resource.h:10
#define IORESOURCE_SUBTRACTIVE
Definition: resource.h:24
#define IORESOURCE_ASSIGNED
Definition: resource.h:34
#define IORESOURCE_IO
Definition: resource.h:9
#define IOINDEX_SUBTRACTIVE(IDX, LINK)
Definition: resource.h:57
#define IORESOURCE_FIXED
Definition: resource.h:36
void scan_static_bus(struct device *bus)
Definition: root_device.c:89
#define SERIRQ_CNTL
Definition: espi.h:21
static int rtc_failed(uint32_t gen_pmcon_b)
Definition: pmutil.c:169
#define PIRQE_ROUT
Definition: lpc.h:30
#define PIRQG_ROUT
Definition: lpc.h:32
#define GEN_PMCON_3
Definition: lpc.h:63
#define PMBASE
Definition: lpc.h:8
#define GPIO_CNTL
Definition: lpc.h:22
#define PIRQB_ROUT
Definition: lpc.h:27
#define GEN_PMCON_1
Definition: lpc.h:56
#define PIRQD_ROUT
Definition: lpc.h:29
#define ACPI_CNTL
Definition: lpc.h:9
#define PIRQC_ROUT
Definition: lpc.h:28
#define GPIO_BASE
Definition: lpc.h:21
#define PIRQH_ROUT
Definition: lpc.h:33
#define PIRQA_ROUT
Definition: lpc.h:26
#define PIRQF_ROUT
Definition: lpc.h:31
#define LPC_EN
Definition: lpc.h:36
static const int mask[4]
Definition: gpio.c:308
static const struct pci_driver lpc_driver_db __pci_driver
Definition: lpc.c:323
static void i82801dx_enable_serial_irqs(struct device *dev)
Definition: lpc.c:58
static void enable_hpet(struct device *dev)
Definition: lpc.c:212
static void i82801dx_lpc_decode_en(struct device *dev)
Definition: lpc.c:198
static struct device_operations lpc_ops
Definition: lpc.c:313
static void i82801dx_enable_ioapic(struct device *dev)
Set miscellaneous static southbridge features.
Definition: lpc.c:41
static void i82801dx_power_options(struct device *dev)
Definition: lpc.c:82
static void lpc_init(struct device *dev)
Definition: lpc.c:246
static void i82801dx_rtc_init(struct device *dev)
Definition: lpc.c:163
static void i82801dx_lpc_read_resources(struct device *dev)
Definition: lpc.c:287
static void i82801dx_pirq_init(struct device *dev)
Definition: lpc.c:67
static void i82801dx_enable_acpi(struct device *dev)
Enable ACPI I/O range.
Definition: lpc.c:27
#define NMI_OFF
Definition: lpc.c:18
static void gpio_init(struct device *dev)
Definition: lpc.c:156
static void i82801dx_lpc_route_dma(struct device *dev, u8 mask)
Definition: lpc.c:183
static u16 pmbase
Definition: smi.c:27
uint32_t u32
Definition: stdint.h:51
uint16_t u16
Definition: stdint.h:48
uint8_t u8
Definition: stdint.h:45
void(* read_resources)(struct device *dev)
Definition: device.h:39
Definition: device.h:107
DEVTREE_CONST void * chip_info
Definition: device.h:164
unsigned long flags
Definition: resource.h:49
resource_t base
Definition: resource.h:45
resource_t size
Definition: resource.h:46
u8 val
Definition: sys.c:300