coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
i82801ix.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <arch/io.h>
4 #include <device/pci_ops.h>
5 #include <device/device.h>
6 #include <device/pci.h>
7 #include <console/console.h>
8 #include "chip.h"
9 #include "i82801ix.h"
10 
12 
13 static void i82801ix_enable_device(struct device *dev)
14 {
15  /* Enable SERR */
17 }
18 
19 static void i82801ix_early_settings(const config_t *const info)
20 {
21  /* Program FERR# as processor break event indicator. */
22  RCBA32(GCS) |= (1 << 6);
23  /* BIOS must program...
24  * NB: other CIRs are handled in i82801ix_dmi_setup(). */
25  RCBA32(RCBA_CIR8) = (RCBA32(RCBA_CIR8) & ~(0x3 << 0)) | (0x2 << 0);
26  RCBA32(RCBA_FD) |= (1 << 0);
27  RCBA32(RCBA_CIR9) = (RCBA32(RCBA_CIR9) & ~(0x3 << 26)) | (0x2 << 26);
28  RCBA32(RCBA_CIR7) = (RCBA32(RCBA_CIR7) & ~(0xf << 16)) | (0x5 << 16);
29  RCBA32(RCBA_CIR13) = (RCBA32(RCBA_CIR13) & ~(0xf << 16)) | (0x5 << 16);
30  /* RCBA32(RCBA_CIR5) |= (1 << 0); cf. Specification Update */
31  RCBA32(RCBA_CIR10) |= (3 << 16);
32 }
33 
34 static void i82801ix_pcie_init(const config_t *const info)
35 {
36  struct device *pciePort[6];
37  int i, slot_number = 1; /* Reserve slot number 0 for nb's PEG. */
38 
39  /* PCIe - BIOS must program... */
40  for (i = 0; i < 6; ++i) {
41  pciePort[i] = pcidev_on_root(0x1c, i);
42  if (!pciePort[i]) {
43  printk(BIOS_EMERG, "PCIe port 00:1c.%x", i);
44  die(" is not listed in devicetree.\n");
45  }
46  pci_or_config32(pciePort[i], 0x300, 1 << 21);
47  pci_write_config8(pciePort[i], 0x324, 0x40);
48  }
49 
50  if (LPC_IS_MOBILE(pcidev_on_root(0x1f, 0))) {
51  for (i = 0; i < 6; ++i) {
52  if (pciePort[i]->enabled) {
53  pci_or_config32(pciePort[i], 0xe8, 1);
54  }
55  }
56  }
57 
58  for (i = 5; (i >= 0) && !pciePort[i]->enabled; --i) {
59  /* Only for the top disabled ports. */
60  pci_or_config32(pciePort[i], 0x300, 0x3 << 16);
61  }
62 
63  /* Set slot implemented, slot number and slot power limits. */
64  for (i = 0; i < 6; ++i) {
65  struct device *const dev = pciePort[i];
66  u32 xcap = pci_read_config32(dev, D28Fx_XCAP);
67  if (info->pcie_slot_implemented & (1 << i))
68  xcap |= PCI_EXP_FLAGS_SLOT;
69  else
70  xcap &= ~PCI_EXP_FLAGS_SLOT;
71  pci_write_config32(dev, D28Fx_XCAP, xcap);
72 
73  if (info->pcie_slot_implemented & (1 << i)) {
74  u32 slcap = pci_read_config32(dev, D28Fx_SLCAP);
75  slcap &= ~(0x1fff << 19);
76  slcap |= (slot_number++ << 19);
77  slcap &= ~(0x0003 << 16);
78  slcap |= (info->pcie_power_limits[i].scale << 16);
79  slcap &= ~(0x00ff << 7);
80  slcap |= (info->pcie_power_limits[i].value << 7);
81  pci_write_config32(dev, D28Fx_SLCAP, slcap);
82  }
83  }
84 
85  /* Lock R/WO ASPM support bits. */
86  for (i = 0; i < 6; ++i)
87  pci_update_config32(pciePort[i], 0x4c, ~0, 0);
88 }
89 
90 static void i82801ix_ehci_init(void)
91 {
92  struct device *const pciEHCI1 = pcidev_on_root(0x1d, 7);
93  if (!pciEHCI1)
94  die("EHCI controller (00:1d.7) not listed in devicetree.\n");
95  struct device *const pciEHCI2 = pcidev_on_root(0x1a, 7);
96  if (!pciEHCI2)
97  die("EHCI controller (00:1a.7) not listed in devicetree.\n");
98 
99  u32 reg32;
100 
101  /* TODO: Maybe we have to save and
102  restore these settings across S3. */
103  reg32 = pci_read_config32(pciEHCI1, 0xfc);
104  pci_write_config32(pciEHCI1, 0xfc, (reg32 & ~(3 << 2)) |
105  (1 << 29) | (1 << 17) | (2 << 2));
106  reg32 = pci_read_config32(pciEHCI2, 0xfc);
107  pci_write_config32(pciEHCI2, 0xfc, (reg32 & ~(3 << 2)) |
108  (1 << 29) | (1 << 17) | (2 << 2));
109 }
110 
111 static int i82801ix_function_disabled(const unsigned int devfn)
112 {
113  struct device *const dev = pcidev_path_on_root(devfn);
114  if (!dev) {
116  "PCI device 00:%x.%x",
117  PCI_SLOT(devfn), PCI_FUNC(devfn));
118  die(" is not listed in devicetree.\n");
119  }
120  return !dev->enabled;
121 }
122 
123 static void i82801ix_hide_functions(void)
124 {
125  int i;
126  u32 reg32;
127 
128  /* FIXME: This works pretty good if the devicetree is consistent. But
129  some functions have to be disabled in right order and/or have
130  other constraints. */
131 
134 
135  reg32 = RCBA32(RCBA_FD);
136  struct {
137  int devfn;
138  u32 mask;
139  } functions[] = {
140  { PCI_DEVFN(0x1a, 0), FD_U4D }, /* UHCI #4 */
141  { PCI_DEVFN(0x1a, 1), FD_U5D }, /* UHCI #5 */
142  { PCI_DEVFN(0x1a, 2), FD_U6D }, /* UHCI #6 */
143  { PCI_DEVFN(0x1a, 7), FD_EHCI2D }, /* EHCI #2 */
144  { PCI_DEVFN(0x1b, 0), FD_HDAD }, /* HD Audio */
145  { PCI_DEVFN(0x1c, 0), FD_PE1D }, /* PCIe #1 */
146  { PCI_DEVFN(0x1c, 1), FD_PE2D }, /* PCIe #2 */
147  { PCI_DEVFN(0x1c, 2), FD_PE3D }, /* PCIe #3 */
148  { PCI_DEVFN(0x1c, 3), FD_PE4D }, /* PCIe #4 */
149  { PCI_DEVFN(0x1c, 4), FD_PE5D }, /* PCIe #5 */
150  { PCI_DEVFN(0x1c, 5), FD_PE6D }, /* PCIe #6 */
151  { PCI_DEVFN(0x1d, 0), FD_U1D }, /* UHCI #1 */
152  { PCI_DEVFN(0x1d, 1), FD_U2D }, /* UHCI #2 */
153  { PCI_DEVFN(0x1d, 2), FD_U3D }, /* UHCI #3 */
154  { PCI_DEVFN(0x1d, 7), FD_EHCI1D }, /* EHCI #1 */
155  { PCI_DEVFN(0x1f, 0), FD_LBD }, /* LPC */
156  { PCI_DEVFN(0x1f, 2), FD_SAD1 }, /* SATA #1 */
157  { PCI_DEVFN(0x1f, 3), FD_SD }, /* SMBus */
158  { PCI_DEVFN(0x1f, 5), FD_SAD2 }, /* SATA #2 */
159  { PCI_DEVFN(0x1f, 6), FD_TTD }, /* Thermal Throttle */
160  };
161  for (i = 0; i < ARRAY_SIZE(functions); ++i) {
162  if (i82801ix_function_disabled(functions[i].devfn))
163  reg32 |= functions[i].mask;
164  }
165  RCBA32(RCBA_FD) = reg32;
166  RCBA32(RCBA_FD) |= (1 << 0); /* BIOS must write this... */
167  RCBA32(RCBA_FDSW) |= (1 << 7); /* Lock function-disable? */
168 
169  /* Hide PCIe root port PCI functions. RPFN is partially R/WO. */
170  reg32 = RCBA32(RCBA_RPFN);
171  for (i = 0; i < 6; ++i) {
173  reg32 |= (1 << ((i * 4) + 3));
174  }
175  RCBA32(RCBA_RPFN) = reg32;
176 
177  /* Lock R/WO UHCI controller #6 remapping. */
179 }
180 
181 static void i82801ix_init(void *chip_info)
182 {
183  const config_t *const info = (config_t *)chip_info;
184 
185  printk(BIOS_DEBUG, "Initializing i82801ix southbridge...\n");
186 
188 
189  /* PCI Express setup. */
191 
192  /* EHCI configuration. */
194 
195  /* Now hide internal functions. We can't access them after this. */
197 
198  /* Reset watchdog timer. */
199 #if !CONFIG(HAVE_SMI_HANDLER)
200  outw(0x0008, DEFAULT_TCOBASE + 0x12); /* Set higher timer value. */
201 #endif
202  outw(0x0000, DEFAULT_TCOBASE + 0x00); /* Update timer. */
203 }
204 
206  CHIP_NAME("Intel ICH9/ICH9-M (82801Ix) Series Southbridge")
207  .enable_dev = i82801ix_enable_device,
208  .init = i82801ix_init,
209 };
#define ARRAY_SIZE(a)
Definition: helpers.h:12
#define printk(level,...)
Definition: stdlib.h:16
void __noreturn die(const char *fmt,...)
Definition: die.c:17
void outw(u16 val, u16 port)
DEVTREE_CONST struct device * pcidev_path_on_root(pci_devfn_t devfn)
Definition: device_const.c:255
DEVTREE_CONST struct device * pcidev_on_root(uint8_t dev, uint8_t fn)
Definition: device_const.c:260
static struct smmstore_params_info info
Definition: ramstage.c:12
static void i82801ix_ehci_init(void)
Definition: i82801ix.c:90
static void i82801ix_pcie_init(const config_t *const info)
Definition: i82801ix.c:34
static int i82801ix_function_disabled(const unsigned int devfn)
Definition: i82801ix.c:111
static void i82801ix_init(void *chip_info)
Definition: i82801ix.c:181
static void i82801ix_hide_functions(void)
Definition: i82801ix.c:123
static void i82801ix_enable_device(struct device *dev)
Definition: i82801ix.c:13
static void i82801ix_early_settings(const config_t *const info)
Definition: i82801ix.c:19
struct chip_operations southbridge_intel_i82801ix_ops
Definition: i82801ix.c:205
#define FD_U4D
Definition: i82801ix.h:141
#define FD_SAD1
Definition: i82801ix.h:148
#define FD_TTD
Definition: i82801ix.h:130
#define RCBA_FDSW
Definition: i82801ix.h:122
#define D28Fx_SLCAP
Definition: i82801ix.h:84
#define FD_PE2D
Definition: i82801ix.h:135
#define FD_U2D
Definition: i82801ix.h:143
#define FD_EHCI1D
Definition: i82801ix.h:137
#define DEFAULT_TCOBASE
Definition: i82801ix.h:20
#define RCBA_CIR7
Definition: i82801ix.h:116
#define FD_SD
Definition: i82801ix.h:147
#define FD_U6D
Definition: i82801ix.h:145
#define RCBA_RPFN
Definition: i82801ix.h:111
#define FD_U3D
Definition: i82801ix.h:142
#define LPC_IS_MOBILE(dev)
Definition: i82801ix.h:159
#define FD_PE5D
Definition: i82801ix.h:132
#define FD_PE3D
Definition: i82801ix.h:134
#define D28Fx_XCAP
Definition: i82801ix.h:83
#define RCBA_CIR8
Definition: i82801ix.h:123
#define FD_SAD2
Definition: i82801ix.h:129
#define FD_PE1D
Definition: i82801ix.h:136
#define RCBA_BUC
Definition: i82801ix.h:119
#define RCBA_MAP
Definition: i82801ix.h:126
#define FD_PE6D
Definition: i82801ix.h:131
#define FD_EHCI2D
Definition: i82801ix.h:139
#define FD_PE4D
Definition: i82801ix.h:133
#define FD_HDAD
Definition: i82801ix.h:146
#define RCBA_CIR9
Definition: i82801ix.h:124
#define FD_U1D
Definition: i82801ix.h:144
#define FD_U5D
Definition: i82801ix.h:140
#define RCBA_CIR13
Definition: i82801ix.h:112
#define FD_LBD
Definition: i82801ix.h:138
#define BUC_LAND
Definition: i82801ix.h:128
#define RCBA_CIR10
Definition: i82801ix.h:125
#define RCBA_FD
Definition: i82801ix.h:120
#define CHIP_NAME(X)
Definition: device.h:32
static __always_inline void pci_or_config32(const struct device *dev, u16 reg, u32 ormask)
Definition: pci_ops.h:191
static __always_inline void pci_write_config32(const struct device *dev, u16 reg, u32 val)
Definition: pci_ops.h:76
static __always_inline void pci_update_config32(const struct device *dev, u16 reg, u32 mask, u32 or)
Definition: pci_ops.h:120
static __always_inline void pci_or_config16(const struct device *dev, u16 reg, u16 ormask)
Definition: pci_ops.h:180
static __always_inline u32 pci_read_config32(const struct device *dev, u16 reg)
Definition: pci_ops.h:58
static __always_inline void pci_write_config8(const struct device *dev, u16 reg, u8 val)
Definition: pci_ops.h:64
#define BIOS_DEBUG
BIOS_DEBUG - Verbose output.
Definition: loglevel.h:128
#define BIOS_EMERG
BIOS_EMERG - Emergency / Fatal.
Definition: loglevel.h:25
#define PCI_COMMAND_SERR
Definition: pci_def.h:19
#define PCI_DEVFN(slot, func)
Definition: pci_def.h:548
#define PCI_FUNC(devfn)
Definition: pci_def.h:550
#define PCI_EXP_FLAGS_SLOT
Definition: pci_def.h:388
#define PCI_COMMAND
Definition: pci_def.h:10
#define PCI_SLOT(devfn)
Definition: pci_def.h:549
#define GCS
Definition: lpc.h:36
static const int mask[4]
Definition: gpio.c:308
#define RCBA32(x)
Definition: rcba.h:14
uint32_t u32
Definition: stdint.h:51
Definition: device.h:107
unsigned int enabled
Definition: device.h:122