coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
pcie.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <commonlib/stdlib.h>
4 #include <console/console.h>
5 #include <device/device.h>
6 #include <device/mmio.h>
7 #include <device/pci.h>
8 #include <device/pci_def.h>
9 #include <device/pci_ids.h>
10 #include <device/resource.h>
11 #include <delay.h>
12 #include <lib.h>
13 #include <soc/addressmap.h>
14 #include <soc/early_init.h>
15 #include <soc/pcie.h>
16 #include <soc/pcie_common.h>
17 #include <soc/soc_chip.h>
18 #include <stdlib.h>
19 #include <types.h>
20 
21 #define PCIE_SETTING_REG 0x80
22 #define PCIE_PCI_IDS_1 0x9c
23 #define PCI_CLASS(class) ((class) << 8)
24 #define PCIE_RC_MODE BIT(0)
25 
26 #define PCIE_CFGNUM_REG 0x140
27 #define PCIE_CFG_DEVFN(devfn) ((devfn) & GENMASK(7, 0))
28 #define PCIE_CFG_BUS(bus) (((bus) << 8) & GENMASK(15, 8))
29 #define PCIE_CFG_OFFSET_ADDR 0x1000
30 #define PCIE_CFG_HEADER(bus, devfn) \
31  (PCIE_CFG_BUS(bus) | PCIE_CFG_DEVFN(devfn))
32 
33 #define PCIE_RST_CTRL_REG 0x148
34 #define PCIE_MAC_RSTB BIT(0)
35 #define PCIE_PHY_RSTB BIT(1)
36 #define PCIE_BRG_RSTB BIT(2)
37 #define PCIE_PE_RSTB BIT(3)
38 
39 #define PCIE_LTSSM_STATUS_REG 0x150
40 #define PCIE_LTSSM_STATE(val) (((val) >> 24) & 0x1f)
41 
42 #define PCIE_LINK_STATUS_REG 0x154
43 #define PCIE_CTRL_LINKUP BIT(8)
44 
45 #define PCI_NUM_INTX 4
46 #define PCIE_INT_ENABLE_REG 0x180
47 #define PCIE_INTX_SHIFT 24
48 #define PCIE_INTX_ENABLE \
49  GENMASK(PCIE_INTX_SHIFT + PCI_NUM_INTX - 1, PCIE_INTX_SHIFT)
50 
51 #define PCIE_TRANS_TABLE_BASE_REG 0x800
52 #define PCIE_ATR_SRC_ADDR_MSB_OFFSET 0x4
53 #define PCIE_ATR_TRSL_ADDR_LSB_OFFSET 0x8
54 #define PCIE_ATR_TRSL_ADDR_MSB_OFFSET 0xc
55 #define PCIE_ATR_TRSL_PARAM_OFFSET 0x10
56 #define PCIE_ATR_TLB_SET_OFFSET 0x20
57 
58 #define PCIE_MAX_TRANS_TABLES 8
59 #define PCIE_ATR_EN BIT(0)
60 #define PCIE_ATR_SIZE(size) \
61  (((((size) - 1) << 1) & GENMASK(6, 1)) | PCIE_ATR_EN)
62 #define PCIE_ATR_ID(id) ((id) & GENMASK(3, 0))
63 #define PCIE_ATR_TYPE_MEM PCIE_ATR_ID(0)
64 #define PCIE_ATR_TYPE_IO PCIE_ATR_ID(1)
65 #define PCIE_ATR_TLP_TYPE(type) (((type) << 16) & GENMASK(18, 16))
66 #define PCIE_ATR_TLP_TYPE_MEM PCIE_ATR_TLP_TYPE(0)
67 #define PCIE_ATR_TLP_TYPE_IO PCIE_ATR_TLP_TYPE(2)
68 
69 /* LTSSM state in PCIE_LTSSM_STATUS_REG bit[28:24] */
70 static const char *const ltssm_str[] = {
71  "detect.quiet", /* 0x00 */
72  "detect.active", /* 0x01 */
73  "polling.active", /* 0x02 */
74  "polling.compliance", /* 0x03 */
75  "polling.configuration", /* 0x04 */
76  "config.linkwidthstart", /* 0x05 */
77  "config.linkwidthaccept", /* 0x06 */
78  "config.lanenumwait", /* 0x07 */
79  "config.lanenumaccept", /* 0x08 */
80  "config.complete", /* 0x09 */
81  "config.idle", /* 0x0A */
82  "recovery.receiverlock", /* 0x0B */
83  "recovery.equalization", /* 0x0C */
84  "recovery.speed", /* 0x0D */
85  "recovery.receiverconfig", /* 0x0E */
86  "recovery.idle", /* 0x0F */
87  "L0", /* 0x10 */
88  "L0s", /* 0x11 */
89  "L1.entry", /* 0x12 */
90  "L1.idle", /* 0x13 */
91  "L2.idle", /* 0x14 */
92  "L2.transmitwake", /* 0x15 */
93  "disable", /* 0x16 */
94  "loopback.entry", /* 0x17 */
95  "loopback.active", /* 0x18 */
96  "loopback.exit", /* 0x19 */
97  "hotreset", /* 0x1A */
98 };
99 
101 {
102  struct device *root_dev;
103  const mtk_soc_config_t *config;
104  static uintptr_t base = 0;
105 
106  if (!base) {
107  root_dev = pcidev_path_on_root(devfn);
108  config = config_of(root_dev);
109  base = config->pcie_config.base;
110  }
111 
112  return base;
113 }
114 
115 volatile union pci_bank *pci_map_bus(pci_devfn_t dev)
116 {
117  u32 val, devfn, bus;
118  uintptr_t base;
119 
120  devfn = PCI_DEV2DEVFN(dev);
121  bus = PCI_DEV2SEGBUS(dev);
122  val = PCIE_CFG_HEADER(bus, devfn);
123 
126 
127  return (void *)(base + PCIE_CFG_OFFSET_ADDR);
128 }
129 
130 static int mtk_pcie_set_trans_window(struct device *dev, uintptr_t table,
131  const struct mtk_pcie_mmio_res *mmio_res)
132 {
133  const char *range_type;
134  uint32_t table_attr;
135 
136  if (!mmio_res)
137  return -1;
138 
139  if (mmio_res->type == IORESOURCE_IO) {
140  range_type = "IO";
141  table_attr = PCIE_ATR_TYPE_IO | PCIE_ATR_TLP_TYPE_IO;
142  } else if (mmio_res->type == IORESOURCE_MEM) {
143  range_type = "MEM";
145  } else {
146  printk(BIOS_ERR, "%s: Unknown trans table type %#lx\n",
147  __func__, mmio_res->type);
148  return -1;
149  }
150 
151  write32p(table, mmio_res->cpu_addr |
154  write32p(table + PCIE_ATR_TRSL_ADDR_LSB_OFFSET, mmio_res->pci_addr);
156  write32p(table + PCIE_ATR_TRSL_PARAM_OFFSET, table_attr);
157 
159  "%s: set %s trans window: cpu_addr = %#x, pci_addr = %#x, size = %#x\n",
160  __func__, range_type, mmio_res->cpu_addr, mmio_res->pci_addr,
161  mmio_res->size);
162 
163  return 0;
164 }
165 
166 static void mtk_pcie_domain_new_res(struct device *dev, unsigned int index,
167  const struct mtk_pcie_mmio_res *mmio_res)
168 {
169  struct resource *res;
170 
171  if (!mmio_res)
172  return;
173 
174  res = new_resource(dev, index);
175  res->base = mmio_res->cpu_addr;
176  res->limit = mmio_res->cpu_addr + mmio_res->size - 1;
177  res->flags = mmio_res->type | IORESOURCE_SUBTRACTIVE |
179 }
180 
182 {
183  const mtk_soc_config_t *config = config_of(dev);
184  const struct mtk_pcie_config *conf = &config->pcie_config;
185 
187  &conf->mmio_res_io);
188 
190  &conf->mmio_res_mem);
191 }
192 
194 {
195  const mtk_soc_config_t *config = config_of(dev);
196  const struct mtk_pcie_config *conf = &config->pcie_config;
197  uintptr_t table;
198 
199  /* Initialize I/O space constraints. */
200  table = conf->base + PCIE_TRANS_TABLE_BASE_REG;
201  if (mtk_pcie_set_trans_window(dev, table, &conf->mmio_res_io) < 0)
202  printk(BIOS_ERR, "%s: Failed to set IO window\n", __func__);
203 
204  /* Initialize memory resources constraints. */
205  table = conf->base + PCIE_TRANS_TABLE_BASE_REG +
207  if (mtk_pcie_set_trans_window(dev, table, &conf->mmio_res_mem) < 0)
208  printk(BIOS_ERR, "%s: Failed to set MEM window\n", __func__);
209 
211 }
212 
214 {
215  const mtk_soc_config_t *config = config_of(dev);
216  const struct mtk_pcie_config *conf = &config->pcie_config;
217  const char *ltssm_state;
218  long perst_time_us;
219  size_t tries = 0;
220  uint32_t val;
221 
222  /* Set as RC mode */
223  val = read32p(conf->base + PCIE_SETTING_REG);
224  val |= PCIE_RC_MODE;
225  write32p(conf->base + PCIE_SETTING_REG, val);
226 
227  /* Set class code */
228  val = read32p(conf->base + PCIE_PCI_IDS_1);
229  val &= ~GENMASK(31, 8);
231  write32p(conf->base + PCIE_PCI_IDS_1, val);
232 
233  /* Mask all INTx interrupts */
234  val = read32p(conf->base + PCIE_INT_ENABLE_REG);
235  val &= ~PCIE_INTX_ENABLE;
237 
239  printk(BIOS_DEBUG, "%s: %ld us elapsed since assert PERST#\n",
240  __func__, perst_time_us);
241 
242  /*
243  * Described in PCIe CEM specification sections 2.2
244  * (PERST# Signal) and 2.2.1 (Initial Power-Up (G3 to S0)).
245  * The deassertion of PERST# should be delayed 100ms (TPVPERL)
246  * for the power and clock to become stable.
247  */
248  const long min_perst_time_us = 100000; /* 100 ms */
249  if (perst_time_us < min_perst_time_us) {
250  if (!perst_time_us) {
252  "%s: PCIe early init data not found, sleeping 100ms\n",
253  __func__);
254  mtk_pcie_reset(conf->base + PCIE_RST_CTRL_REG, true);
255  } else {
257  "%s: Need an extra %ld us delay to meet PERST# deassertion requirement\n",
258  __func__, min_perst_time_us - perst_time_us);
259  }
260 
261  udelay(min_perst_time_us - perst_time_us);
262  }
263 
264  /* De-assert reset signals */
265  mtk_pcie_reset(conf->base + PCIE_RST_CTRL_REG, false);
266 
267  if (!retry(100,
268  (tries++, read32p(conf->base + PCIE_LINK_STATUS_REG) &
269  PCIE_CTRL_LINKUP), mdelay(1))) {
271  ltssm_state = PCIE_LTSSM_STATE(val) >= ARRAY_SIZE(ltssm_str) ?
272  "Unknown state" : ltssm_str[PCIE_LTSSM_STATE(val)];
273  printk(BIOS_ERR, "%s: PCIe link down, current ltssm state: %s\n",
274  __func__, ltssm_state);
275  return;
276  }
277 
278  printk(BIOS_INFO, "%s: PCIe link up success (%ld tries)\n", __func__,
279  tries);
280 }
#define ARRAY_SIZE(a)
Definition: helpers.h:12
#define retry(attempts, condition,...)
Definition: helpers.h:126
#define GENMASK(high, low)
Definition: helpers.h:58
#define printk(level,...)
Definition: stdlib.h:16
void mdelay(unsigned int msecs)
Definition: delay.c:2
DEVTREE_CONST struct device * pcidev_path_on_root(pci_devfn_t devfn)
Definition: device_const.c:255
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
static DEVTREE_CONST void * config_of(const struct device *dev)
Definition: device.h:382
static __always_inline uint32_t read32p(const uintptr_t addr)
Definition: mmio.h:220
static __always_inline void write32p(const uintptr_t addr, const uint32_t value)
Definition: mmio.h:240
static int __fls(u32 x)
Definition: lib.h:57
#define BIOS_INFO
BIOS_INFO - Expected events.
Definition: loglevel.h:113
#define BIOS_DEBUG
BIOS_DEBUG - Verbose output.
Definition: loglevel.h:128
#define BIOS_ERR
BIOS_ERR - System in incomplete state.
Definition: loglevel.h:72
#define BIOS_WARNING
BIOS_WARNING - Bad configuration.
Definition: loglevel.h:86
enum board_config config
Definition: memory.c:448
static struct resource * mmio_res
Definition: gma.c:42
#define PCI_DEV2DEVFN(sdev)
Definition: pci_def.h:553
#define PCI_DEV2SEGBUS(sdev)
Definition: pci_def.h:554
void pci_domain_set_resources(struct device *dev)
Definition: pci_device.c:564
#define PCI_CLASS_BRIDGE_PCI
Definition: pci_ids.h:56
u32 pci_devfn_t
Definition: pci_type.h:8
#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
uintptr_t base
Definition: uart.c:17
long early_init_get_elapsed_time_us(enum early_init_type init_type)
Definition: early_init.c:34
@ EARLY_INIT_PCIE
Definition: early_init.h:14
#define PCIE_TRANS_TABLE_BASE_REG
Definition: pcie.c:51
#define PCIE_ATR_TRSL_ADDR_LSB_OFFSET
Definition: pcie.c:53
static uintptr_t mtk_pcie_get_controller_base(pci_devfn_t devfn)
Definition: pcie.c:100
#define PCIE_LINK_STATUS_REG
Definition: pcie.c:42
#define PCIE_CFG_OFFSET_ADDR
Definition: pcie.c:29
#define PCIE_INT_ENABLE_REG
Definition: pcie.c:46
#define PCIE_ATR_TRSL_PARAM_OFFSET
Definition: pcie.c:55
#define PCIE_PCI_IDS_1
Definition: pcie.c:22
#define PCIE_ATR_TYPE_MEM
Definition: pcie.c:63
static int mtk_pcie_set_trans_window(struct device *dev, uintptr_t table, const struct mtk_pcie_mmio_res *mmio_res)
Definition: pcie.c:130
#define PCIE_ATR_TLP_TYPE_MEM
Definition: pcie.c:66
static const char *const ltssm_str[]
Definition: pcie.c:70
volatile union pci_bank * pci_map_bus(pci_devfn_t dev)
Definition: pcie.c:115
void mtk_pcie_domain_set_resources(struct device *dev)
Definition: pcie.c:193
void mtk_pcie_domain_read_resources(struct device *dev)
Definition: pcie.c:181
#define PCIE_RC_MODE
Definition: pcie.c:24
#define PCIE_CFG_HEADER(bus, devfn)
Definition: pcie.c:30
#define PCIE_ATR_SIZE(size)
Definition: pcie.c:60
static void mtk_pcie_domain_new_res(struct device *dev, unsigned int index, const struct mtk_pcie_mmio_res *mmio_res)
Definition: pcie.c:166
#define PCIE_LTSSM_STATE(val)
Definition: pcie.c:40
#define PCIE_SETTING_REG
Definition: pcie.c:21
#define PCIE_INTX_ENABLE
Definition: pcie.c:48
#define PCIE_ATR_TLB_SET_OFFSET
Definition: pcie.c:56
#define PCI_CLASS(class)
Definition: pcie.c:23
#define PCIE_ATR_TRSL_ADDR_MSB_OFFSET
Definition: pcie.c:54
#define PCIE_CFGNUM_REG
Definition: pcie.c:26
#define PCIE_CTRL_LINKUP
Definition: pcie.c:43
void mtk_pcie_domain_enable(struct device *dev)
Definition: pcie.c:213
#define PCIE_ATR_TYPE_IO
Definition: pcie.c:64
#define PCIE_LTSSM_STATUS_REG
Definition: pcie.c:39
#define PCIE_ATR_SRC_ADDR_MSB_OFFSET
Definition: pcie.c:52
#define PCIE_RST_CTRL_REG
Definition: pcie.c:33
#define PCIE_ATR_TLP_TYPE_IO
Definition: pcie.c:67
void mtk_pcie_reset(uintptr_t reg, bool enable)
Definition: pcie.c:54
unsigned int uint32_t
Definition: stdint.h:14
uint32_t u32
Definition: stdint.h:51
unsigned long uintptr_t
Definition: stdint.h:21
Definition: device.h:76
Definition: device.h:107
const struct mtk_pcie_mmio_res mmio_res_mem
Definition: pcie_common.h:19
uintptr_t base
Definition: pcie_common.h:17
const struct mtk_pcie_mmio_res mmio_res_io
Definition: pcie_common.h:18
unsigned long flags
Definition: resource.h:49
resource_t limit
Definition: resource.h:47
resource_t base
Definition: resource.h:45
unsigned long index
Definition: resource.h:50
resource_t size
Definition: resource.h:46
u8 val
Definition: sys.c:300
void udelay(uint32_t us)
Definition: udelay.c:15