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 <amdblocks/acpimmio.h>
4 #include <console/console.h>
5 #include <device/device.h>
6 #include <device/pci.h>
7 #include <device/pnp.h>
8 #include <device/pci_ids.h>
9 #include <device/pci_ops.h>
10 #include <device/pci_def.h>
11 #include <pc80/mc146818rtc.h>
12 #include <pc80/isa-dma.h>
13 #include <arch/io.h>
14 #include <arch/ioapic.h>
15 #include <acpi/acpi.h>
16 #include <pc80/i8254.h>
17 #include <pc80/i8259.h>
18 #include "hudson.h"
19 #include "pci_devs.h"
20 
21 static void lpc_init(struct device *dev)
22 {
23  u8 byte;
24  u32 dword;
25  struct device *sm_dev;
26 
27  /* Enable the LPC Controller */
28  sm_dev = pcidev_on_root(0x14, 0);
29  dword = pci_read_config32(sm_dev, 0x64);
30  dword |= 1 << 20;
31  pci_write_config32(sm_dev, 0x64, dword);
32 
33  /* Initialize isa dma */
34  isa_dma_init();
35 
36  /* Enable DMA transaction on the LPC bus */
37  byte = pci_read_config8(dev, 0x40);
38  byte |= (1 << 2);
39  pci_write_config8(dev, 0x40, byte);
40 
41  /* Disable the timeout mechanism on LPC */
42  byte = pci_read_config8(dev, 0x48);
43  byte &= ~(1 << 7);
44  pci_write_config8(dev, 0x48, byte);
45 
46  /* Disable LPC MSI Capability */
47  byte = pci_read_config8(dev, 0x78);
48  byte &= ~(1 << 1);
49  byte &= ~(1 << 0); /* Keep the old way. i.e., when bus master/DMA cycle is going
50  on on LPC, it holds PCI grant, so no LPC slave cycle can
51  interrupt and visit LPC. */
52  pci_write_config8(dev, 0x78, byte);
53 
54  /* bit0: Enable prefetch a cacheline (64 bytes) when Host reads code from SPI ROM */
55  /* bit3: Fix SPI_CS# timing issue when running at 66M. TODO:A12. */
56  byte = pci_read_config8(dev, 0xBB);
57  byte |= 1 << 0 | 1 << 3;
58  pci_write_config8(dev, 0xBB, byte);
59 
61 
62  /*
63  * Initialize the real time clock.
64  * The 0 argument tells cmos_init not to
65  * update CMOS unless it is invalid.
66  * 1 tells cmos_init to always initialize the CMOS.
67  */
68  cmos_init(0);
69 
70  /* Initialize i8259 pic */
71  setup_i8259();
72 
73  /* Initialize i8254 timers */
74  setup_i8254();
75 }
76 
77 static void hudson_lpc_read_resources(struct device *dev)
78 {
79  struct resource *res;
80 
81  /* Get the normal pci resources of this device */
82  pci_dev_read_resources(dev); /* We got one for APIC, or one more for TRAP */
83 
84  /* Add an extra subtractive resource for both memory and I/O. */
85  res = new_resource(dev, IOINDEX_SUBTRACTIVE(0, 0));
86  res->base = 0;
87  res->size = 0x1000;
90 
91  res = new_resource(dev, IOINDEX_SUBTRACTIVE(1, 0));
92  res->base = 0xff800000;
93  res->size = 0x00800000; /* 8 MB for flash */
96 
97  /* Add a memory resource for the SPI BAR. */
99 
100  res = new_resource(dev, 3); /* IOAPIC */
101  res->base = IO_APIC_ADDR;
102  res->size = 0x00001000;
104 
105  compact_resources(dev);
106 }
107 
108 static void hudson_lpc_set_resources(struct device *dev)
109 {
110  struct resource *res;
111 
112  /* Special case. SPI Base Address. The SpiRomEnable should STAY set. */
113  res = find_resource(dev, 2);
115 
117 }
118 
119 /**
120  * @brief Enable resources for children devices
121  *
122  * @param dev the device whose children's resources are to be enabled
123  *
124  */
126 {
127  struct bus *link;
128  u32 reg, reg_x;
129  int var_num = 0;
130  u16 reg_var[3];
131  u16 reg_size[1] = {512};
132  u8 wiosize = pci_read_config8(dev, 0x74);
133 
134  /* Be bit relaxed, tolerate that LPC region might be bigger than resource we try to fit,
135  * do it like this for all regions < 16 bytes. If there is a resource > 16 bytes
136  * it must be 512 bytes to be able to allocate the fresh LPC window.
137  *
138  * AGESA likes to enable already one LPC region in wide port base 0x64-0x65,
139  * using DFLT_SIO_PME_BASE_ADDRESS, 512 bytes size
140  * The code tries to check if resource can fit into this region
141  */
142 
143  reg = pci_read_config32(dev, 0x44);
144  reg_x = pci_read_config32(dev, 0x48);
145 
146  /* check if ranges are free and not use them if entry is just already taken */
147  if (reg_x & (1 << 2))
148  var_num = 1;
149  /* just in case check if someone did not manually set other ranges too */
150  if (reg_x & (1 << 24))
151  var_num = 2;
152 
153  if (reg_x & (1 << 25))
154  var_num = 3;
155 
156  /* check AGESA region size */
157  if (wiosize & (1 << 0))
158  reg_size[0] = 16;
159 
160  reg_var[2] = pci_read_config16(dev, 0x90);
161  reg_var[1] = pci_read_config16(dev, 0x66);
162  reg_var[0] = pci_read_config16(dev, 0x64);
163 
164  for (link = dev->link_list; link; link = link->next) {
165  struct device *child;
166  for (child = link->children; child;
167  child = child->sibling) {
168  if (child->enabled
169  && (child->path.type == DEVICE_PATH_PNP)) {
170  struct resource *res;
171  for (res = child->resource_list; res; res = res->next) {
172  u32 base, end; /* don't need long long */
173  u32 rsize, set = 0, set_x = 0;
174  if (!(res->flags & IORESOURCE_IO))
175  continue;
176  base = res->base;
177  end = resource_end(res);
178  /* find a resource size */
179  printk(BIOS_DEBUG, "hudson lpc decode:%s, base=0x%08x, end=0x%08x\n",
180  dev_path(child), base, end);
181  switch (base) {
182  case 0x60: /* KB */
183  case 0x64: /* MS */
184  set |= (1 << 29);
185  rsize = 1;
186  break;
187  case 0x3f8: /* COM1 */
188  set |= (1 << 6);
189  rsize = 8;
190  break;
191  case 0x2f8: /* COM2 */
192  set |= (1 << 7);
193  rsize = 8;
194  break;
195  case 0x378: /* Parallel 1 */
196  set |= (1 << 0);
197  set |= (1 << 1); /* + 0x778 for ECP */
198  rsize = 8;
199  break;
200  case 0x3f0: /* FD0 */
201  set |= (1 << 26);
202  rsize = 8;
203  break;
204  case 0x220: /* 0x220 - 0x227 */
205  set |= (1 << 8);
206  rsize = 8;
207  break;
208  case 0x228: /* 0x228 - 0x22f */
209  set |= (1 << 9);
210  rsize = 8;
211  break;
212  case 0x238: /* 0x238 - 0x23f */
213  set |= (1 << 10);
214  rsize = 8;
215  break;
216  case 0x300: /* 0x300 -0x301 */
217  set |= (1 << 18);
218  rsize = 2;
219  break;
220  case 0x400:
221  set_x |= (1 << 16);
222  rsize = 0x40;
223  break;
224  case 0x480:
225  set_x |= (1 << 17);
226  rsize = 0x40;
227  break;
228  case 0x500:
229  set_x |= (1 << 18);
230  rsize = 0x40;
231  break;
232  case 0x580:
233  set_x |= (1 << 19);
234  rsize = 0x40;
235  break;
236  case 0x4700:
237  set_x |= (1 << 22);
238  rsize = 0xc;
239  break;
240  case 0xfd60:
241  set_x |= (1 << 23);
242  rsize = 16;
243  break;
244  default:
245  rsize = 0;
246  /* try AGESA allocated region in region 0 */
247  if ((var_num > 0) && ((base >=reg_var[0]) &&
248  ((base + res->size) <= (reg_var[0] + reg_size[0]))))
249  rsize = reg_size[0];
250  }
251  /* check if region found and matches the enable */
252  if (res->size <= rsize) {
253  reg |= set;
254  reg_x |= set_x;
255  /* check if we can fit resource in variable range */
256  } else if ((var_num < 3) &&
257  ((res->size <= 16) || (res->size == 512))) {
258  /* use variable ranges if pre-defined do not match */
259  switch (var_num) {
260  case 0:
261  reg_x |= (1 << 2);
262  if (res->size <= 16) {
263  wiosize |= (1 << 0);
264  }
265  break;
266  case 1:
267  reg_x |= (1 << 24);
268  if (res->size <= 16)
269  wiosize |= (1 << 2);
270  break;
271  case 2:
272  reg_x |= (1 << 25);
273  if (res->size <= 16)
274  wiosize |= (1 << 3);
275  break;
276  }
277  reg_var[var_num++] =
278  base & 0xffff;
279  } else {
280  printk(BIOS_ERR, "cannot fit LPC decode region:%s, base=0x%08x, end=0x%08x\n",
281  dev_path(child), base, end);
282  }
283  }
284  }
285  }
286  }
287  pci_write_config32(dev, 0x44, reg);
288  pci_write_config32(dev, 0x48, reg_x);
289  /* Set WideIO for as many IOs found (fall through is on purpose) */
290  switch (var_num) {
291  case 3:
292  pci_write_config16(dev, 0x90, reg_var[2]);
294  case 2:
295  pci_write_config16(dev, 0x66, reg_var[1]);
297  case 1:
298  pci_write_config16(dev, 0x64, reg_var[0]);
299  break;
300  }
301  pci_write_config8(dev, 0x74, wiosize);
302 }
303 
304 static void hudson_lpc_enable_resources(struct device *dev)
305 {
308 }
309 
310 static const char *lpc_acpi_name(const struct device *dev)
311 {
312  if (dev->path.type != DEVICE_PATH_PCI)
313  return NULL;
314 
315  if (dev->path.pci.devfn == LPC_DEVFN)
316  return "LIBR";
317 
318  return NULL;
319 }
320 
321 static void lpc_final(struct device *dev)
322 {
323  if (!acpi_is_wakeup_s3()) {
324  if (CONFIG(HAVE_SMI_HANDLER))
325  outl(0x0, ACPI_PM1_CNT_BLK); /* clear SCI_EN */
326  else
327  outl(0x1, ACPI_PM1_CNT_BLK); /* set SCI_EN */
328  }
329 }
330 
331 static struct device_operations lpc_ops = {
333  .set_resources = hudson_lpc_set_resources,
334  .enable_resources = hudson_lpc_enable_resources,
335 #if CONFIG(HAVE_ACPI_TABLES)
336  .write_acpi_tables = acpi_write_hpet,
337 #endif
338  .init = lpc_init,
339  .final = lpc_final,
340  .scan_bus = scan_static_bus,
341  .ops_pci = &pci_dev_ops_pci,
342  .acpi_name = lpc_acpi_name,
343 };
344 static const struct pci_driver lpc_driver __pci_driver = {
345  .ops = &lpc_ops,
346  .vendor = PCI_VID_AMD,
347  .device = PCI_DID_AMD_SB900_LPC,
348 };
unsigned long acpi_write_hpet(const struct device *device, unsigned long current, acpi_rsdp_t *rsdp)
Definition: acpi.c:1141
#define SPIROM_BASE_ADDRESS_REGISTER
Definition: hudson.h:75
#define ACPI_PM1_CNT_BLK
Definition: iomap.h:43
#define SPI_BASE_ADDRESS
Definition: iomap.h:8
static int acpi_is_wakeup_s3(void)
Definition: acpi.h:9
#define IO_APIC_ADDR
Definition: ioapic.h:6
#define printk(level,...)
Definition: stdlib.h:16
#define __fallthrough
Definition: compiler.h:39
void outl(u32 val, u16 port)
DEVTREE_CONST struct device * pcidev_on_root(uint8_t dev, uint8_t fn)
Definition: device_const.c:260
void fixed_mem_resource(struct device *dev, unsigned long index, unsigned long basek, unsigned long sizek, unsigned long type)
Definition: device_util.c:825
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
void compact_resources(struct device *dev)
See if we have unused but allocated resource structures.
Definition: device_util.c:302
resource_t resource_end(const struct resource *resource)
Compute the maximum address that is part of a resource.
Definition: device_util.c:445
struct resource * find_resource(const struct device *dev, unsigned int index)
Return an existing resource structure for a given index.
Definition: device_util.c:394
const char * dev_path(const struct device *dev)
Definition: device_util.c:149
@ CONFIG
Definition: dsi_common.h:201
void setup_i8254(void)
Definition: i8254.c:10
void setup_i8259(void)
Definition: i8259.c:46
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
void isa_dma_init(void)
Definition: isa-dma.c:35
#define BIOS_DEBUG
BIOS_DEBUG - Verbose output.
Definition: loglevel.h:128
#define BIOS_ERR
BIOS_ERR - System in incomplete state.
Definition: loglevel.h:72
void cmos_check_update_date(void)
Definition: mc146818rtc.c:192
void cmos_init(bool invalid)
Definition: mc146818rtc.c:156
@ DEVICE_PATH_PNP
Definition: path.h:10
@ DEVICE_PATH_PCI
Definition: path.h:9
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
struct pci_operations pci_dev_ops_pci
Default device operation for PCI devices.
Definition: pci_device.c:911
void pci_dev_set_resources(struct device *dev)
Definition: pci_device.c:691
#define PCI_VID_AMD
Definition: pci_ids.h:496
#define PCI_DID_AMD_SB900_LPC
Definition: pci_ids.h:517
#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 SPI_ROM_ENABLE
Definition: lpc.h:18
#define LPC_DEVFN
Definition: pci_devs.h:123
uintptr_t base
Definition: uart.c:17
static void lpc_final(struct device *dev)
Definition: lpc.c:321
static const char * lpc_acpi_name(const struct device *dev)
Definition: lpc.c:310
static void hudson_lpc_set_resources(struct device *dev)
Definition: lpc.c:108
static void hudson_lpc_enable_childrens_resources(struct device *dev)
Enable resources for children devices.
Definition: lpc.c:125
static void hudson_lpc_enable_resources(struct device *dev)
Definition: lpc.c:304
static struct device_operations lpc_ops
Definition: lpc.c:331
static void lpc_init(struct device *dev)
Definition: lpc.c:21
static void hudson_lpc_read_resources(struct device *dev)
Definition: lpc.c:77
static const struct pci_driver lpc_driver __pci_driver
Definition: lpc.c:344
#define NULL
Definition: stddef.h:19
uint32_t u32
Definition: stdint.h:51
uint16_t u16
Definition: stdint.h:48
uint8_t u8
Definition: stdint.h:45
Definition: device.h:76
DEVTREE_CONST struct bus * next
Definition: device.h:80
DEVTREE_CONST struct device * children
Definition: device.h:79
DEVTREE_CONST struct device * dev
Definition: device.h:78
void(* read_resources)(struct device *dev)
Definition: device.h:39
struct pci_path pci
Definition: path.h:116
enum device_path_type type
Definition: path.h:114
Definition: device.h:107
DEVTREE_CONST struct device * sibling
Definition: device.h:111
struct device_path path
Definition: device.h:115
DEVTREE_CONST struct bus * link_list
Definition: device.h:139
DEVTREE_CONST struct resource * resource_list
Definition: device.h:134
unsigned int enabled
Definition: device.h:122
unsigned int devfn
Definition: path.h:54
unsigned long flags
Definition: resource.h:49
resource_t base
Definition: resource.h:45
resource_t size
Definition: resource.h:46
DEVTREE_CONST struct resource * next
Definition: resource.h:48