mirror of
https://github.com/AsahiLinux/m1n1
synced 2025-02-16 21:58:27 +00:00
pcie: Add initial t602x support
Signed-off-by: Hector Martin <marcan@marcan.st>
This commit is contained in:
parent
046620d4d5
commit
c2c0ac04aa
1 changed files with 266 additions and 27 deletions
293
src/pcie.c
293
src/pcie.c
|
@ -44,10 +44,18 @@
|
|||
#define APCIE_PHYIF_CTRL 0x024
|
||||
#define APCIE_PHYIF_CTRL_RUN BIT(0)
|
||||
|
||||
/* PHY common registers */
|
||||
#define APCIE_PHYCMN_CLK 0x000
|
||||
#define APCIE_PHYCMN_CLK_MODE GENMASK(1, 0) /* Guesswork */
|
||||
#define APCIE_PHYCMN_CLK_MODE_ON 1
|
||||
#define APCIE_PHYCMN_CLK_100MHZ BIT(31)
|
||||
|
||||
/* Port registers */
|
||||
|
||||
#define APCIE_PORT_LINKSTS 0x208
|
||||
#define APCIE_PORT_LINKSTS_UP BIT(0)
|
||||
#define APCIE_PORT_LINKSTS_BUSY BIT(2)
|
||||
#define APCIE_PORT_LINKSTS_L2 BIT(6)
|
||||
|
||||
#define APCIE_PORT_APPCLK 0x800
|
||||
#define APCIE_PORT_APPCLK_EN BIT(0)
|
||||
|
@ -58,10 +66,14 @@
|
|||
#define APCIE_PORT_RESET 0x814
|
||||
#define APCIE_PORT_RESET_DIS BIT(0)
|
||||
|
||||
#define APCIE_T602X_PORT_RESET 0x82c
|
||||
#define APCIE_T602X_PORT_MSIMAP 0x3800
|
||||
|
||||
/* PCIe capability registers */
|
||||
#define PCIE_CAP_BASE 0x70
|
||||
#define PCIE_LNKCAP 0x0c
|
||||
#define PCIE_LNKCAP_SLS GENMASK(3, 0)
|
||||
#define PCIE_LNKCAP_MLW GENMASK(9, 4)
|
||||
#define PCIE_LNKCAP2 0x2c
|
||||
#define PCIE_LNKCAP2_SLS GENMASK(6, 1)
|
||||
#define PCIE_LNKCTL2 0x30
|
||||
|
@ -72,7 +84,18 @@
|
|||
#define DWC_DBI_RO_WR 0x8bc
|
||||
#define DWC_DBI_RO_WR_EN BIT(0)
|
||||
|
||||
#define DWC_DBI_PORT_LINK_CONTROL 0x710
|
||||
#define DWC_DBI_PORT_LINK_DLL_LINK_EN BIT(5)
|
||||
#define DWC_DBI_PORT_LINK_FAST_LINK_MODE BIT(7)
|
||||
#define DWC_DBI_PORT_LINK_MODE GENMASK(21, 16)
|
||||
#define DWC_DBI_PORT_LINK_MODE_1_LANE 0x1
|
||||
#define DWC_DBI_PORT_LINK_MODE_2_LANES 0x3
|
||||
#define DWC_DBI_PORT_LINK_MODE_4_LANES 0x7
|
||||
#define DWC_DBI_PORT_LINK_MODE_8_LANES 0xf
|
||||
#define DWC_DBI_PORT_LINK_MODE_16_LANES 0x1f
|
||||
|
||||
#define DWC_DBI_LINK_WIDTH_SPEED_CONTROL 0x80c
|
||||
#define DWC_DBI_LINK_WIDTH GENMASK(12, 8)
|
||||
#define DWC_DBI_SPEED_CHANGE BIT(17)
|
||||
|
||||
struct fuse_bits {
|
||||
|
@ -107,15 +130,61 @@ const struct fuse_bits pcie_fuse_bits_t8112[] = {
|
|||
};
|
||||
/* clang-format on */
|
||||
|
||||
enum apcie_type {
|
||||
APCIE_T81XX = 0,
|
||||
APCIE_T602X = 1,
|
||||
};
|
||||
|
||||
struct reg_info {
|
||||
enum apcie_type type;
|
||||
int shared_reg_count;
|
||||
int config_idx;
|
||||
int rc_idx;
|
||||
int phy_common_idx;
|
||||
int phy_idx;
|
||||
int phy_ip_idx;
|
||||
int axi_idx;
|
||||
int fuse_idx;
|
||||
bool alt_phy_start;
|
||||
};
|
||||
|
||||
static const struct reg_info regs_t8xxx_t600x = {
|
||||
.type = APCIE_T81XX,
|
||||
.shared_reg_count = 6,
|
||||
.config_idx = 0,
|
||||
.rc_idx = 1,
|
||||
.phy_common_idx = -1,
|
||||
.phy_idx = 2,
|
||||
.phy_ip_idx = 3,
|
||||
.axi_idx = 4,
|
||||
.fuse_idx = 5,
|
||||
};
|
||||
|
||||
static const struct reg_info regs_t602x = {
|
||||
.type = APCIE_T602X,
|
||||
.shared_reg_count = 8,
|
||||
.config_idx = 0,
|
||||
.rc_idx = 1,
|
||||
// 2 = phy unknown?
|
||||
.phy_common_idx = 3,
|
||||
.phy_idx = 4,
|
||||
.phy_ip_idx = 5,
|
||||
.axi_idx = 6,
|
||||
.fuse_idx = 7,
|
||||
};
|
||||
|
||||
static bool pcie_initialized = false;
|
||||
static u64 rc_base;
|
||||
static u64 phy_common_base;
|
||||
static u64 phy_base;
|
||||
static u64 phy_ip_base;
|
||||
static u64 fuse_base;
|
||||
static u32 port_count;
|
||||
static u64 port_base[8];
|
||||
|
||||
#define SHARED_REG_COUNT 6
|
||||
static u64 port_ltssm_base[8];
|
||||
static u64 port_phy_base[8];
|
||||
static u64 port_intr2axi_base[8];
|
||||
static const struct reg_info *pcie_regs;
|
||||
|
||||
int pcie_init(void)
|
||||
{
|
||||
|
@ -135,13 +204,20 @@ int pcie_init(void)
|
|||
|
||||
if (adt_is_compatible(adt, adt_offset, "apcie,t8103")) {
|
||||
fuse_bits = pcie_fuse_bits_t8103;
|
||||
pcie_regs = ®s_t8xxx_t600x;
|
||||
printf("pcie: Initializing t8103 PCIe controller\n");
|
||||
} else if (adt_is_compatible(adt, adt_offset, "apcie,t6000")) {
|
||||
fuse_bits = pcie_fuse_bits_t6000;
|
||||
pcie_regs = ®s_t8xxx_t600x;
|
||||
printf("pcie: Initializing t6000 PCIe controller\n");
|
||||
} else if (adt_is_compatible(adt, adt_offset, "apcie,t8112")) {
|
||||
fuse_bits = pcie_fuse_bits_t8112;
|
||||
pcie_regs = ®s_t8xxx_t600x;
|
||||
printf("pcie: Initializing t8112 PCIe controller\n");
|
||||
} else if (adt_is_compatible(adt, adt_offset, "apcie,t6020")) {
|
||||
fuse_bits = NULL;
|
||||
pcie_regs = ®s_t602x;
|
||||
printf("pcie: Initializing t6020 PCIe controller\n");
|
||||
} else {
|
||||
printf("pcie: Unsupported compatible\n");
|
||||
return -1;
|
||||
|
@ -153,28 +229,37 @@ int pcie_init(void)
|
|||
}
|
||||
|
||||
u64 config_base;
|
||||
if (adt_get_reg(adt, adt_path, "reg", 0, &config_base, NULL)) {
|
||||
printf("pcie: Error getting reg with index %d for %s\n", 0, path);
|
||||
if (adt_get_reg(adt, adt_path, "reg", pcie_regs->config_idx, &config_base, NULL)) {
|
||||
printf("pcie: Error getting reg with index %d for %s\n", pcie_regs->config_idx, path);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (adt_get_reg(adt, adt_path, "reg", 1, &rc_base, NULL)) {
|
||||
printf("pcie: Error getting reg with index %d for %s\n", 1, path);
|
||||
if (adt_get_reg(adt, adt_path, "reg", pcie_regs->rc_idx, &rc_base, NULL)) {
|
||||
printf("pcie: Error getting reg with index %d for %s\n", pcie_regs->rc_idx, path);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (adt_get_reg(adt, adt_path, "reg", 2, &phy_base, NULL)) {
|
||||
printf("pcie: Error getting reg with index %d for %s\n", 2, path);
|
||||
if (pcie_regs->phy_common_idx != -1) {
|
||||
if (adt_get_reg(adt, adt_path, "reg", pcie_regs->phy_common_idx, &phy_common_base, NULL)) {
|
||||
printf("pcie: Error getting reg with index %d for %s\n", pcie_regs->phy_idx, path);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
phy_common_base = 0;
|
||||
}
|
||||
|
||||
if (adt_get_reg(adt, adt_path, "reg", pcie_regs->phy_idx, &phy_base, NULL)) {
|
||||
printf("pcie: Error getting reg with index %d for %s\n", pcie_regs->phy_idx, path);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (adt_get_reg(adt, adt_path, "reg", 3, &phy_ip_base, NULL)) {
|
||||
printf("pcie: Error getting reg with index %d for %s\n", 3, path);
|
||||
if (adt_get_reg(adt, adt_path, "reg", pcie_regs->phy_ip_idx, &phy_ip_base, NULL)) {
|
||||
printf("pcie: Error getting reg with index %d for %s\n", pcie_regs->phy_ip_idx, path);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (adt_get_reg(adt, adt_path, "reg", 5, &fuse_base, NULL)) {
|
||||
printf("pcie: Error getting reg with index %d for %s\n", 5, path);
|
||||
if (adt_get_reg(adt, adt_path, "reg", pcie_regs->fuse_idx, &fuse_base, NULL)) {
|
||||
printf("pcie: Error getting reg with index %d for %s\n", pcie_regs->fuse_idx, path);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -184,7 +269,7 @@ int pcie_init(void)
|
|||
return -1;
|
||||
}
|
||||
|
||||
int port_regs = (reg_len / 16) - SHARED_REG_COUNT;
|
||||
int port_regs = (reg_len / 16) - pcie_regs->shared_reg_count;
|
||||
|
||||
if (port_regs % port_count) {
|
||||
printf("pcie: %d port registers do not evenly divide into %d ports\n", port_regs,
|
||||
|
@ -200,7 +285,7 @@ int pcie_init(void)
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (tunables_apply_local(path, "apcie-axi2af-tunables", 4)) {
|
||||
if (tunables_apply_local(path, "apcie-axi2af-tunables", pcie_regs->axi_idx)) {
|
||||
printf("pcie: Error applying %s for %s\n", "apcie-axi2af-tunables", path);
|
||||
return -1;
|
||||
}
|
||||
|
@ -208,7 +293,9 @@ int pcie_init(void)
|
|||
/* ??? */
|
||||
write32(rc_base + 0x4, 0);
|
||||
|
||||
if (tunables_apply_local(path, "apcie-common-tunables", 1)) {
|
||||
if (!adt_getprop(adt, adt_offset, "apcie-common-tunables", NULL)) {
|
||||
printf("pcie: No common tunables\n");
|
||||
} else if (tunables_apply_local(path, "apcie-common-tunables", pcie_regs->rc_idx)) {
|
||||
printf("pcie: Error applying %s for %s\n", "apcie-common-tunables", path);
|
||||
return -1;
|
||||
}
|
||||
|
@ -217,11 +304,21 @@ int pcie_init(void)
|
|||
* Initialize PHY.
|
||||
*/
|
||||
|
||||
if (tunables_apply_local(path, "apcie-phy-tunables", 2)) {
|
||||
if (!adt_getprop(adt, adt_offset, "apcie-phy-tunables", NULL)) {
|
||||
printf("pcie: No PHY tunables\n");
|
||||
} else if (tunables_apply_local(path, "apcie-phy-tunables", pcie_regs->phy_idx)) {
|
||||
printf("pcie: Error applying %s for %s\n", "apcie-phy-tunables", path);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (pcie_regs->type == APCIE_T602X) {
|
||||
if (poll32(phy_common_base + APCIE_PHYCMN_CLK, APCIE_PHYCMN_CLK_100MHZ,
|
||||
APCIE_PHYCMN_CLK_100MHZ, 250000)) {
|
||||
printf("pcie: Reference clock not available\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
set32(phy_base + APCIE_PHY_CTRL, APCIE_PHY_CTRL_CLK0REQ);
|
||||
if (poll32(phy_base + APCIE_PHY_CTRL, APCIE_PHY_CTRL_CLK0ACK, APCIE_PHY_CTRL_CLK0ACK, 50000)) {
|
||||
printf("pcie: Timeout enabling PHY CLK0\n");
|
||||
|
@ -238,11 +335,15 @@ int pcie_init(void)
|
|||
udelay(1);
|
||||
|
||||
/* ??? */
|
||||
set32(rc_base + APCIE_PHYIF_CTRL, APCIE_PHYIF_CTRL_RUN);
|
||||
udelay(1);
|
||||
if (pcie_regs->type == APCIE_T81XX) {
|
||||
set32(rc_base + APCIE_PHYIF_CTRL, APCIE_PHYIF_CTRL_RUN);
|
||||
udelay(1);
|
||||
} else if (pcie_regs->type == APCIE_T602X) {
|
||||
set32(phy_base + 4, 0x01);
|
||||
}
|
||||
|
||||
/* Apply "fuses". */
|
||||
for (int i = 0; fuse_bits[i].width; i++) {
|
||||
for (int i = 0; fuse_bits && fuse_bits[i].width; i++) {
|
||||
u32 fuse;
|
||||
fuse = (read32(fuse_base + fuse_bits[i].src_reg) >> fuse_bits[i].src_bit);
|
||||
fuse &= (1 << fuse_bits[i].width) - 1;
|
||||
|
@ -251,15 +352,34 @@ int pcie_init(void)
|
|||
fuse << fuse_bits[i].tgt_bit);
|
||||
}
|
||||
|
||||
if (tunables_apply_local(path, "apcie-phy-ip-pll-tunables", 3)) {
|
||||
if (tunables_apply_local(path, "apcie-phy-ip-pll-tunables", pcie_regs->phy_ip_idx)) {
|
||||
printf("pcie: Error applying %s for %s\n", "apcie-phy-ip-pll-tunables", path);
|
||||
return -1;
|
||||
}
|
||||
if (tunables_apply_local(path, "apcie-phy-ip-auspma-tunables", 3)) {
|
||||
if (tunables_apply_local(path, "apcie-phy-ip-auspma-tunables", pcie_regs->phy_ip_idx)) {
|
||||
printf("pcie: Error applying %s for %s\n", "apcie-phy-ip-auspma-tunables", path);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (pcie_regs->type == APCIE_T602X) {
|
||||
set32(phy_base + 4, 0x10);
|
||||
mask32(phy_common_base + APCIE_PHYCMN_CLK, APCIE_PHYCMN_CLK_MODE,
|
||||
FIELD_PREP(APCIE_PHYCMN_CLK_MODE, 1));
|
||||
if (poll32(phy_base + 0x8, 1, 1, 250000)) {
|
||||
printf("pcie: PHY clock enable timed out\n");
|
||||
return -1;
|
||||
}
|
||||
set32(phy_base + APCIE_PHY_CTRL, 0x300);
|
||||
write32(rc_base + 0x54, 0x140);
|
||||
write32(rc_base + 0x50, 0x1);
|
||||
if (poll32(rc_base + 0x58, 1, 1, 250000)) {
|
||||
printf("pcie: Failed to initialize RC thing\n");
|
||||
return -1;
|
||||
}
|
||||
clear32(rc_base + 0x3c, 0x1);
|
||||
pmgr_adt_power_disable_index(path, 1);
|
||||
}
|
||||
|
||||
for (u32 port = 0; port < port_count; port++) {
|
||||
char bridge[64];
|
||||
int bridge_offset;
|
||||
|
@ -275,13 +395,67 @@ int pcie_init(void)
|
|||
|
||||
printf("pcie: Initializing port %d\n", port);
|
||||
|
||||
if (adt_get_reg(adt, adt_path, "reg", port * port_reg_cnt + SHARED_REG_COUNT,
|
||||
if (adt_get_reg(adt, adt_path, "reg", port * port_reg_cnt + pcie_regs->shared_reg_count,
|
||||
&port_base[port], NULL)) {
|
||||
printf("pcie: Error getting reg with index %d for %s\n",
|
||||
port * port_reg_cnt + SHARED_REG_COUNT, path);
|
||||
port * port_reg_cnt + pcie_regs->shared_reg_count, path);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (adt_get_reg(adt, adt_path, "reg", port * port_reg_cnt + pcie_regs->shared_reg_count + 1,
|
||||
&port_ltssm_base[port], NULL)) {
|
||||
printf("pcie: Error getting reg with index %d for %s\n",
|
||||
port * port_reg_cnt + pcie_regs->shared_reg_count + 1, path);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (adt_get_reg(adt, adt_path, "reg", port * port_reg_cnt + pcie_regs->shared_reg_count + 2,
|
||||
&port_phy_base[port], NULL)) {
|
||||
printf("pcie: Error getting reg with index %d for %s\n",
|
||||
port * port_reg_cnt + pcie_regs->shared_reg_count + 2, path);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (port_reg_cnt >= 5) {
|
||||
if (adt_get_reg(adt, adt_path, "reg",
|
||||
port * port_reg_cnt + pcie_regs->shared_reg_count + 4,
|
||||
&port_intr2axi_base[port], NULL)) {
|
||||
printf("pcie: Error getting reg with index %d for %s\n",
|
||||
port * port_reg_cnt + pcie_regs->shared_reg_count + 4, path);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
port_intr2axi_base[port] = 0;
|
||||
}
|
||||
|
||||
if (pcie_regs->type == APCIE_T602X) {
|
||||
set32(rc_base + 0x3c, 0x1);
|
||||
|
||||
// ??????
|
||||
write32(port_base[port] + 0x10, 0x2);
|
||||
write32(port_base[port] + 0x88, 0x110);
|
||||
write32(port_base[port] + 0x100, 0xffffffff);
|
||||
write32(port_base[port] + 0x148, 0xffffffff);
|
||||
write32(port_base[port] + 0x210, 0xffffffff);
|
||||
write32(port_base[port] + 0x80, 0x0);
|
||||
write32(port_base[port] + 0x84, 0x0);
|
||||
write32(port_base[port] + 0x104, 0x7fffffff);
|
||||
write32(port_base[port] + 0x124, 0x100);
|
||||
write32(port_base[port] + 0x16c, 0x0);
|
||||
write32(port_base[port] + 0x13c, 0x10);
|
||||
write32(port_base[port] + 0x800, 0x100100);
|
||||
write32(port_base[port] + 0x808, 0x1000ff);
|
||||
write32(port_base[port] + 0x82c, 0x0);
|
||||
for (int i = 0; i < 512; i++)
|
||||
write32(port_base[port] + APCIE_T602X_PORT_MSIMAP + 4 * i, 0);
|
||||
write32(port_base[port] + 0x397c, 0x0);
|
||||
write32(port_base[port] + 0x130, 0x3000000);
|
||||
write32(port_base[port] + 0x140, 0x10);
|
||||
write32(port_base[port] + 0x144, 0x253770);
|
||||
write32(port_base[port] + 0x21c, 0x0);
|
||||
write32(port_base[port] + 0x834, 0x0);
|
||||
}
|
||||
|
||||
if (tunables_apply_local_addr(bridge, "apcie-config-tunables", port_base[port])) {
|
||||
printf("pcie: Error applying %s for %s\n", "apcie-config-tunables", bridge);
|
||||
return -1;
|
||||
|
@ -289,8 +463,33 @@ int pcie_init(void)
|
|||
|
||||
set32(port_base[port] + APCIE_PORT_APPCLK, APCIE_PORT_APPCLK_EN);
|
||||
|
||||
/* PERSTN */
|
||||
set32(port_base[port] + APCIE_PORT_RESET, APCIE_PORT_RESET_DIS);
|
||||
if (pcie_regs->type == APCIE_T602X) {
|
||||
clear32(port_phy_base[port] + APCIE_PHY_CTRL,
|
||||
APCIE_PHY_CTRL_CLK0REQ | APCIE_PHY_CTRL_CLK1REQ);
|
||||
|
||||
set32(port_phy_base[port] + APCIE_PHY_CTRL, APCIE_PHY_CTRL_CLK0REQ);
|
||||
if (poll32(port_phy_base[port] + APCIE_PHY_CTRL, APCIE_PHY_CTRL_CLK0ACK,
|
||||
APCIE_PHY_CTRL_CLK0ACK, 50000)) {
|
||||
printf("pcie: Timeout enabling PHY CLK0\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
set32(port_phy_base[port] + APCIE_PHY_CTRL, APCIE_PHY_CTRL_CLK1REQ);
|
||||
if (poll32(port_phy_base[port] + APCIE_PHY_CTRL, APCIE_PHY_CTRL_CLK1ACK,
|
||||
APCIE_PHY_CTRL_CLK1ACK, 50000)) {
|
||||
printf("pcie: Timeout enabling PHY CLK1\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
clear32(port_phy_base[port] + APCIE_PHY_CTRL, 0x4000);
|
||||
set32(port_phy_base[port] + APCIE_PHY_CTRL, 0x200);
|
||||
set32(port_phy_base[port] + APCIE_PHY_CTRL, 0x400);
|
||||
|
||||
set32(port_base[port] + APCIE_T602X_PORT_RESET, APCIE_PORT_RESET_DIS);
|
||||
} else {
|
||||
/* PERSTN */
|
||||
set32(port_base[port] + APCIE_PORT_RESET, APCIE_PORT_RESET_DIS);
|
||||
}
|
||||
|
||||
if (poll32(port_base[port] + APCIE_PORT_STATUS, APCIE_PORT_STATUS_RUN,
|
||||
APCIE_PORT_STATUS_RUN, 250000)) {
|
||||
|
@ -303,6 +502,24 @@ int pcie_init(void)
|
|||
return -1;
|
||||
}
|
||||
|
||||
/* Do it again? */
|
||||
if (pcie_regs->type == APCIE_T602X) {
|
||||
clear32(port_base[port] + APCIE_T602X_PORT_RESET, APCIE_PORT_RESET_DIS);
|
||||
set32(port_base[port] + APCIE_T602X_PORT_RESET, APCIE_PORT_RESET_DIS);
|
||||
|
||||
if (poll32(port_base[port] + APCIE_PORT_LINKSTS, APCIE_PORT_LINKSTS_BUSY, 0, 250000)) {
|
||||
printf("pcie: Port failed to become idle on %s\n", bridge);
|
||||
return -1;
|
||||
}
|
||||
|
||||
udelay(1000);
|
||||
|
||||
write32(port_ltssm_base[port] + 0x10, 0x2);
|
||||
write32(port_ltssm_base[port] + 0x1c, 0x4);
|
||||
set32(port_ltssm_base[port] + 0x20, 0x2);
|
||||
write32(port_ltssm_base[port] + 0x14, 0x1);
|
||||
}
|
||||
|
||||
/* Make Designware PCIe Core registers writable. */
|
||||
set32(config_base + DWC_DBI_RO_WR, DWC_DBI_RO_WR_EN);
|
||||
|
||||
|
@ -356,13 +573,32 @@ int pcie_init(void)
|
|||
|
||||
mask16(config_base + PCIE_CAP_BASE + PCIE_LNKCTL2, PCIE_LNKCTL2_TLS,
|
||||
FIELD_PREP(PCIE_LNKCTL2_TLS, max_speed));
|
||||
|
||||
set32(config_base + DWC_DBI_LINK_WIDTH_SPEED_CONTROL, DWC_DBI_SPEED_CHANGE);
|
||||
}
|
||||
|
||||
set32(config_base + DWC_DBI_LINK_WIDTH_SPEED_CONTROL, DWC_DBI_SPEED_CHANGE);
|
||||
/* Max link width 1 */
|
||||
mask32(config_base + DWC_DBI_PORT_LINK_CONTROL, DWC_DBI_PORT_LINK_MODE,
|
||||
FIELD_PREP(DWC_DBI_PORT_LINK_MODE, DWC_DBI_PORT_LINK_MODE_1_LANE));
|
||||
mask32(config_base + DWC_DBI_LINK_WIDTH_SPEED_CONTROL, DWC_DBI_LINK_WIDTH,
|
||||
FIELD_PREP(DWC_DBI_LINK_WIDTH, 1));
|
||||
mask32(config_base + PCIE_CAP_BASE + PCIE_LNKCAP, PCIE_LNKCAP_MLW,
|
||||
FIELD_PREP(PCIE_LNKCAP_MLW, 1));
|
||||
|
||||
/* Make Designware PCIe Core registers readonly. */
|
||||
clear32(config_base + DWC_DBI_RO_WR, DWC_DBI_RO_WR_EN);
|
||||
|
||||
if (pcie_regs->type == APCIE_T602X) {
|
||||
write32(port_base[port] + 0x4020, 0x3);
|
||||
write32(port_intr2axi_base[port] + 0x80, 0x1);
|
||||
|
||||
clear32(rc_base + 0x3c, 0x1);
|
||||
for (int i = 0; i < 32; i++)
|
||||
write32(port_base[port] + APCIE_T602X_PORT_MSIMAP + 4 * i, 0x80000000 | i);
|
||||
}
|
||||
|
||||
read32(port_base[port] + APCIE_PORT_LINKSTS);
|
||||
|
||||
/* Move to the next PCIe device on this bus. */
|
||||
config_base += (1 << 15);
|
||||
}
|
||||
|
@ -379,7 +615,10 @@ int pcie_shutdown(void)
|
|||
return 0;
|
||||
|
||||
for (u32 port = 0; port < port_count; port++) {
|
||||
clear32(port_base[port] + APCIE_PORT_RESET, APCIE_PORT_RESET_DIS);
|
||||
if (pcie_regs->type == APCIE_T602X)
|
||||
clear32(port_base[port] + APCIE_T602X_PORT_RESET, APCIE_PORT_RESET_DIS);
|
||||
else
|
||||
clear32(port_base[port] + APCIE_PORT_RESET, APCIE_PORT_RESET_DIS);
|
||||
clear32(port_base[port] + APCIE_PORT_APPCLK, APCIE_PORT_APPCLK_EN);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue