soc/mediatek: Add chip config for setting PCIe config

Add chip config for setting PCIe config.

TEST=Build pass and boot up to kernel successfully via SSD on Dojo
board, here is the SSD information in boot log:
 == NVME IDENTIFY CONTROLLER DATA ==
    PCI VID   : 0x15b7
    PCI SSVID : 0x15b7
    SN        : 21517J440114
    MN        : WDC PC SN530 SDBPTPZ-256G-1006
    RAB       : 0x4
    AERL      : 0x7
    SQES      : 0x66
    CQES      : 0x44
    NN        : 0x1
Identified NVMe model WDC PC SN530 SDBPTPZ-256G-1006

BUG=b:178565024

Signed-off-by: Jianjun Wang <jianjun.wang@mediatek.com>
Change-Id: Icff83f2a9f76862065987a74cfcc7e511be80a20
Reviewed-on: https://review.coreboot.org/c/coreboot/+/62791
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Yu-Ping Wu <yupingso@google.com>
This commit is contained in:
Jianjun Wang 2022-03-14 20:38:18 +08:00 committed by Felix Held
parent d59b3dd085
commit c0808b6497
6 changed files with 77 additions and 93 deletions

View File

@ -13,12 +13,10 @@ struct mtk_pcie_mmio_res {
unsigned long type; unsigned long type;
}; };
struct mtk_pcie_controller { struct mtk_pcie_config {
uintptr_t base; /* MAC physical address */ uintptr_t base; /* MAC physical address */
int (*phy_init)(void); const struct mtk_pcie_mmio_res mmio_res_io;
void (*reset)(uintptr_t base, bool enable); const struct mtk_pcie_mmio_res mmio_res_mem;
const struct mtk_pcie_mmio_res *mmio_res_io;
const struct mtk_pcie_mmio_res *mmio_res_mem;
}; };
void mtk_pcie_domain_read_resources(struct device *dev); void mtk_pcie_domain_read_resources(struct device *dev);

View File

@ -13,6 +13,7 @@
#include <soc/addressmap.h> #include <soc/addressmap.h>
#include <soc/pcie.h> #include <soc/pcie.h>
#include <soc/pcie_common.h> #include <soc/pcie_common.h>
#include <soc/soc_chip.h>
#include <stdlib.h> #include <stdlib.h>
#include <types.h> #include <types.h>
@ -64,7 +65,7 @@
#define PCIE_ATR_TLP_TYPE_MEM PCIE_ATR_TLP_TYPE(0) #define PCIE_ATR_TLP_TYPE_MEM PCIE_ATR_TLP_TYPE(0)
#define PCIE_ATR_TLP_TYPE_IO PCIE_ATR_TLP_TYPE(2) #define PCIE_ATR_TLP_TYPE_IO PCIE_ATR_TLP_TYPE(2)
static struct mtk_pcie_controller pcie_ctrl; static const struct mtk_pcie_config *pcie_ctrl;
/* LTSSM state in PCIE_LTSSM_STATUS_REG bit[28:24] */ /* LTSSM state in PCIE_LTSSM_STATUS_REG bit[28:24] */
static const char *const ltssm_str[] = { static const char *const ltssm_str[] = {
@ -105,56 +106,9 @@ volatile union pci_bank *pci_map_bus(pci_devfn_t dev)
bus = PCI_DEV2SEGBUS(dev); bus = PCI_DEV2SEGBUS(dev);
val = PCIE_CFG_HEADER(bus, devfn); val = PCIE_CFG_HEADER(bus, devfn);
write32p(pcie_ctrl.base + PCIE_CFGNUM_REG, val); write32p(pcie_ctrl->base + PCIE_CFGNUM_REG, val);
return (void *)(pcie_ctrl.base + PCIE_CFG_OFFSET_ADDR); return (void *)(pcie_ctrl->base + PCIE_CFG_OFFSET_ADDR);
}
static int mtk_pcie_startup_port(struct mtk_pcie_controller *ctrl)
{
uint32_t val;
size_t tries = 0;
const char *ltssm_state;
/* Set as RC mode */
val = read32p(ctrl->base + PCIE_SETTING_REG);
val |= PCIE_RC_MODE;
write32p(ctrl->base + PCIE_SETTING_REG, val);
/* Set class code */
val = read32p(ctrl->base + PCIE_PCI_IDS_1);
val &= ~GENMASK(31, 8);
val |= PCI_CLASS(PCI_CLASS_BRIDGE_PCI << 8);
write32p(ctrl->base + PCIE_PCI_IDS_1, val);
/* Mask all INTx interrupts */
val = read32p(ctrl->base + PCIE_INT_ENABLE_REG);
val &= ~PCIE_INTX_ENABLE;
write32p(ctrl->base + PCIE_INT_ENABLE_REG, val);
if (!ctrl->reset) {
printk(BIOS_ERR, "%s: Missing reset function\n", __func__);
return -1;
}
/* De-assert reset signals */
ctrl->reset(ctrl->base + PCIE_RST_CTRL_REG, false);
if (!retry(100,
(tries++, read32p(ctrl->base + PCIE_LINK_STATUS_REG) &
PCIE_CTRL_LINKUP), mdelay(1))) {
val = read32p(ctrl->base + PCIE_LTSSM_STATUS_REG);
ltssm_state = PCIE_LTSSM_STATE(val) >= ARRAY_SIZE(ltssm_str) ?
"Unknown state" : ltssm_str[PCIE_LTSSM_STATE(val)];
printk(BIOS_ERR, "%s: PCIe link down, current ltssm state: %s\n",
__func__, ltssm_state);
return -1;
}
printk(BIOS_INFO, "%s: PCIe link up success (%ld tries)\n", __func__,
tries);
return 0;
} }
static int mtk_pcie_set_trans_window(struct device *dev, uintptr_t table, static int mtk_pcie_set_trans_window(struct device *dev, uintptr_t table,
@ -210,29 +164,31 @@ static void mtk_pcie_domain_new_res(struct device *dev, unsigned int index,
void mtk_pcie_domain_read_resources(struct device *dev) void mtk_pcie_domain_read_resources(struct device *dev)
{ {
struct mtk_pcie_controller *ctrl = dev->chip_info; const mtk_soc_config_t *config = config_of(dev);
const struct mtk_pcie_config *conf = &config->pcie_config;
mtk_pcie_domain_new_res(dev, IOINDEX_SUBTRACTIVE(0, 0), mtk_pcie_domain_new_res(dev, IOINDEX_SUBTRACTIVE(0, 0),
ctrl->mmio_res_io); &conf->mmio_res_io);
mtk_pcie_domain_new_res(dev, IOINDEX_SUBTRACTIVE(1, 0), mtk_pcie_domain_new_res(dev, IOINDEX_SUBTRACTIVE(1, 0),
ctrl->mmio_res_mem); &conf->mmio_res_mem);
} }
void mtk_pcie_domain_set_resources(struct device *dev) void mtk_pcie_domain_set_resources(struct device *dev)
{ {
struct mtk_pcie_controller *ctrl = dev->chip_info; const mtk_soc_config_t *config = config_of(dev);
const struct mtk_pcie_config *conf = &config->pcie_config;
uintptr_t table; uintptr_t table;
/* Initialize I/O space constraints. */ /* Initialize I/O space constraints. */
table = ctrl->base + PCIE_TRANS_TABLE_BASE_REG; table = conf->base + PCIE_TRANS_TABLE_BASE_REG;
if (mtk_pcie_set_trans_window(dev, table, ctrl->mmio_res_io) < 0) if (mtk_pcie_set_trans_window(dev, table, &conf->mmio_res_io) < 0)
printk(BIOS_ERR, "%s: Failed to set IO window\n", __func__); printk(BIOS_ERR, "%s: Failed to set IO window\n", __func__);
/* Initialize memory resources constraints. */ /* Initialize memory resources constraints. */
table = ctrl->base + PCIE_TRANS_TABLE_BASE_REG + table = conf->base + PCIE_TRANS_TABLE_BASE_REG +
PCIE_ATR_TLB_SET_OFFSET; PCIE_ATR_TLB_SET_OFFSET;
if (mtk_pcie_set_trans_window(dev, table, ctrl->mmio_res_mem) < 0) if (mtk_pcie_set_trans_window(dev, table, &conf->mmio_res_mem) < 0)
printk(BIOS_ERR, "%s: Failed to set MEM window\n", __func__); printk(BIOS_ERR, "%s: Failed to set MEM window\n", __func__);
pci_domain_set_resources(dev); pci_domain_set_resources(dev);
@ -240,10 +196,43 @@ void mtk_pcie_domain_set_resources(struct device *dev)
void mtk_pcie_domain_enable(struct device *dev) void mtk_pcie_domain_enable(struct device *dev)
{ {
mtk_pcie_get_hw_info(&pcie_ctrl); const mtk_soc_config_t *config = config_of(dev);
const char *ltssm_state;
size_t tries = 0;
uint32_t val;
if (mtk_pcie_startup_port(&pcie_ctrl) < 0) pcie_ctrl = &config->pcie_config;
/* Set as RC mode */
val = read32p(pcie_ctrl->base + PCIE_SETTING_REG);
val |= PCIE_RC_MODE;
write32p(pcie_ctrl->base + PCIE_SETTING_REG, val);
/* Set class code */
val = read32p(pcie_ctrl->base + PCIE_PCI_IDS_1);
val &= ~GENMASK(31, 8);
val |= PCI_CLASS(PCI_CLASS_BRIDGE_PCI << 8);
write32p(pcie_ctrl->base + PCIE_PCI_IDS_1, val);
/* Mask all INTx interrupts */
val = read32p(pcie_ctrl->base + PCIE_INT_ENABLE_REG);
val &= ~PCIE_INTX_ENABLE;
write32p(pcie_ctrl->base + PCIE_INT_ENABLE_REG, val);
/* De-assert reset signals */
mtk_pcie_reset(pcie_ctrl->base + PCIE_RST_CTRL_REG, false);
if (!retry(100,
(tries++, read32p(pcie_ctrl->base + PCIE_LINK_STATUS_REG) &
PCIE_CTRL_LINKUP), mdelay(1))) {
val = read32p(pcie_ctrl->base + PCIE_LTSSM_STATUS_REG);
ltssm_state = PCIE_LTSSM_STATE(val) >= ARRAY_SIZE(ltssm_str) ?
"Unknown state" : ltssm_str[PCIE_LTSSM_STATE(val)];
printk(BIOS_ERR, "%s: PCIe link down, current ltssm state: %s\n",
__func__, ltssm_state);
return; return;
}
dev->chip_info = &pcie_ctrl; printk(BIOS_INFO, "%s: PCIe link up success (%ld tries)\n", __func__,
tries);
} }

View File

@ -0,0 +1,14 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef SOC_MEDIATEK_CHIP_H
#define SOC_MEDIATEK_CHIP_H
#include <soc/pcie_common.h>
struct soc_mediatek_mt8195_config {
struct mtk_pcie_config pcie_config;
};
typedef struct soc_mediatek_mt8195_config mtk_soc_config_t;
#endif /* SOC_MEDIATEK_CHIP_H */

View File

@ -5,7 +5,7 @@
#include <soc/pcie_common.h> #include <soc/pcie_common.h>
void mtk_pcie_reset(uintptr_t reg, bool enable);
void mtk_pcie_pre_init(void); void mtk_pcie_pre_init(void);
void mtk_pcie_get_hw_info(struct mtk_pcie_controller *ctrl);
#endif #endif

View File

@ -0,0 +1,8 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef SOC_MEDIATEK_SOC_CHIP_H
#define SOC_MEDIATEK_SOC_CHIP_H
#include "../../chip.h"
#endif /* SOC_MEDIATEK_SOC_CHIP_H */

View File

@ -19,23 +19,6 @@
#define PCIE_BRG_RSTB BIT(2) #define PCIE_BRG_RSTB BIT(2)
#define PCIE_PE_RSTB BIT(3) #define PCIE_PE_RSTB BIT(3)
/* MMIO range (64MB): 0x20000000 ~ 0x24000000 */
/* Some devices still need io ranges, reserve 16MB for compatibility */
static const struct mtk_pcie_mmio_res pcie_mmio_res_io = {
.cpu_addr = 0x20000000,
.pci_addr = 0x20000000,
.size = 16 * MiB,
.type = IORESOURCE_IO,
};
static const struct mtk_pcie_mmio_res pcie_mmio_res_mem = {
.cpu_addr = 0x21000000,
.pci_addr = 0x21000000,
.size = 48 * MiB,
.type = IORESOURCE_MEM,
};
struct pad_func { struct pad_func {
gpio_t gpio; gpio_t gpio;
u8 func; u8 func;
@ -67,7 +50,7 @@ static void mtk_pcie_set_pinmux(uint8_t port)
} }
} }
static void mtk_pcie_reset(uintptr_t reg, bool enable) void mtk_pcie_reset(uintptr_t reg, bool enable)
{ {
uint32_t val; uint32_t val;
@ -90,11 +73,3 @@ void mtk_pcie_pre_init(void)
/* Assert all reset signals at early stage */ /* Assert all reset signals at early stage */
mtk_pcie_reset(PCIE_RST_CTRL_REG, true); mtk_pcie_reset(PCIE_RST_CTRL_REG, true);
} }
void mtk_pcie_get_hw_info(struct mtk_pcie_controller *ctrl)
{
ctrl->base = PCIE_REG_BASE_PORT0;
ctrl->mmio_res_io = &pcie_mmio_res_io;
ctrl->mmio_res_mem = &pcie_mmio_res_mem;
ctrl->reset = &mtk_pcie_reset;
}