225 lines
5.9 KiB
C
225 lines
5.9 KiB
C
/*
|
|
*
|
|
* Copyright 2017 NXP
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0
|
|
*/
|
|
|
|
#include <common.h>
|
|
#include <pci.h>
|
|
#include <asm/gpio.h>
|
|
#include <asm/io.h>
|
|
#include <asm/mach-imx/sci/sci.h>
|
|
#include <linux/sizes.h>
|
|
#include <errno.h>
|
|
#include <imx8_hsio.h>
|
|
|
|
void mx8x_pcie_controller_reset(sc_ipc_t ipc, u32 scr)
|
|
{
|
|
sc_err_t err;
|
|
int i;
|
|
|
|
err = sc_misc_set_control(ipc, scr, SC_C_PCIE_G_RST, 1);
|
|
if (err != SC_ERR_NONE)
|
|
printf("SC_R_PCIE G_RST failed! (error = %d)\n", err);
|
|
for (i = 0; i < 200; i = i + 1)
|
|
asm("nop");
|
|
|
|
err = sc_misc_set_control(ipc, scr, SC_C_PCIE_G_RST, 0);
|
|
if (err != SC_ERR_NONE)
|
|
printf("SC_R_PCIE G_RST failed! (error = %d)\n", err);
|
|
|
|
err = sc_misc_set_control(ipc, scr, SC_C_PCIE_PERST, 1);
|
|
if (err != SC_ERR_NONE)
|
|
printf("SC_R_PCIE PCIE_RST failed! (error = %d)\n", err);
|
|
|
|
err = sc_misc_set_control(ipc, scr, SC_C_PCIE_BUTTON_RST, 1);
|
|
if (err != SC_ERR_NONE)
|
|
printf("SC_R_PCIE BUTTON_RST failed! (error = %d)\n", err);
|
|
}
|
|
|
|
static void pcie_mapping_region(u32 index, u32 direction, u32 type,
|
|
u32 addr, u32 size, u32 target_l, u32 target_h)
|
|
{
|
|
/* Select a iATU and configure its direction */
|
|
pcie_writel(index | direction, PCIE0_ATU_VIEWPORT);
|
|
setbits_le32(PCIE0_ATU_CR1, type);
|
|
|
|
/* Set memory address and size */
|
|
pcie_writel(addr, PCIE0_ATU_LOWER_BASE);
|
|
pcie_writel(0, PCIE0_ATU_UPPER_BASE);
|
|
pcie_writel((addr + size - 1), PCIE0_ATU_LIMIT);
|
|
|
|
pcie_writel(target_l, PCIE0_ATU_LOWER_TARGET);
|
|
pcie_writel(target_h, PCIE0_ATU_UPPER_TARGET);
|
|
|
|
/* Enable this iATU */
|
|
setbits_le32(PCIE0_ATU_CR2, PCIE_ATU_ENABLE);
|
|
}
|
|
|
|
static void pcie_ctrlb_mapping_region(u32 index, u32 direction, u32 type,
|
|
u32 addr, u32 size, u32 target_l, u32 target_h)
|
|
{
|
|
/* Select a iATU and configure its direction */
|
|
pcie_writel(index | direction, PCIE1_ATU_VIEWPORT);
|
|
setbits_le32(PCIE1_ATU_CR1, type);
|
|
|
|
/* Set memory address and size */
|
|
pcie_writel(addr, PCIE1_ATU_LOWER_BASE);
|
|
pcie_writel(0, PCIE1_ATU_UPPER_BASE);
|
|
pcie_writel((addr + size - 1), PCIE1_ATU_LIMIT);
|
|
|
|
pcie_writel(target_l, PCIE1_ATU_LOWER_TARGET);
|
|
pcie_writel(target_h, PCIE1_ATU_UPPER_TARGET);
|
|
|
|
/* Enable this iATU */
|
|
setbits_le32(PCIE1_ATU_CR2, PCIE_ATU_ENABLE);
|
|
}
|
|
|
|
/* CFG Space --> 0x40000000
|
|
* 1st Region --> 0x41000000
|
|
* 2nd Region --> 0x42000000
|
|
* ...
|
|
*/
|
|
void mx8x_pcie_ctrla_setup_regions(void)
|
|
{
|
|
u32 i, cmd;
|
|
u32 val, index;
|
|
u32 is_32bit;
|
|
u32 type, size;
|
|
u64 size64;
|
|
const u32 region_types[] = {
|
|
PCIE_ATU_TYPE_MEM,
|
|
PCIE_ATU_TYPE_IO,
|
|
};
|
|
|
|
cmd = PCI_COMMAND_MASTER;
|
|
|
|
pcie_mapping_region(0, PCIE_ATU_REGION_OUTBOUND, PCIE_ATU_TYPE_CFG0,
|
|
PCIEA_CFG_PCI_BASE, PCIE_CFG_MEM_SIZE, 0, 0);
|
|
|
|
index = 1;
|
|
udelay(1000);
|
|
|
|
for (i = 0; i < 6; i++) {
|
|
val = pcie_readl(PCIEA_CFG_CPU_BASE + 0x10 + i * 4);
|
|
printf("#### [%d] val=%X addr=%X\r\n ", i, val,
|
|
PCIEA_CFG_CPU_BASE + 0x10 + i * 4);
|
|
if (!val)
|
|
continue;
|
|
type = region_types[val & 0x1];
|
|
is_32bit = ((val & 0x4) == 0);
|
|
pcie_writel(0xFFFFFFFF, PCIEA_CFG_CPU_BASE + 0x10 + i * 4);
|
|
size = pcie_readl(PCIEA_CFG_CPU_BASE + 0x10 + i * 4);
|
|
size = 0xFFFFFFFF - (size & ~0xF) + 1;
|
|
if (is_32bit) {
|
|
pcie_mapping_region(index, PCIE_ATU_REGION_OUTBOUND,
|
|
type, PCIEA_CFG_PCI_BASE
|
|
+ index * 0x1000000, size,
|
|
index * 0x1000000, 0);
|
|
val = (val & 0xF) + index * 0x1000000;
|
|
pcie_writel(val, (PCIEA_CFG_CPU_BASE + 0x10 + i * 4));
|
|
} else {
|
|
pcie_writel(0xFFFFFFFF, (PCIEA_CFG_CPU_BASE + 0x10
|
|
+ i * 4 + 4));
|
|
size64 = pcie_readl(PCIEA_CFG_CPU_BASE
|
|
+ 0x10 + i * 4 + 4);
|
|
size64 = 0xFFFFFFFF - size64;
|
|
size64 <<= 32;
|
|
size64 |= size;
|
|
size64++;
|
|
pcie_mapping_region(index, PCIE_ATU_REGION_OUTBOUND,
|
|
type, PCIEA_CFG_PCI_BASE
|
|
+ index * 0x1000000, size64,
|
|
index * 0x1000000, 0);
|
|
val = (val & 0xF) + index * 0x1000000;
|
|
pcie_writel(val, (PCIEA_CFG_CPU_BASE + 0x10 + i * 4));
|
|
pcie_writel(0, (PCIEA_CFG_CPU_BASE + 0x10 + i * 4 + 4));
|
|
i++;
|
|
}
|
|
|
|
index++;
|
|
|
|
if (type == PCIE_ATU_TYPE_MEM)
|
|
cmd |= PCI_COMMAND_MEMORY;
|
|
else
|
|
cmd |= PCI_COMMAND_IO;
|
|
}
|
|
|
|
pcie_writel(cmd, PCIEA_CFG_CPU_BASE + 4);
|
|
}
|
|
|
|
/* CFG Space --> 0x80000000
|
|
* 1st Region --> 0x81000000
|
|
* 2nd Region --> 0x82000000
|
|
* ...
|
|
*/
|
|
void mx8x_pcie_ctrlb_setup_regions(void)
|
|
{
|
|
u32 i, cmd;
|
|
u32 val, index;
|
|
u32 is_32bit;
|
|
u32 type, size;
|
|
u64 size64;
|
|
const u32 region_types[] = {
|
|
PCIE_ATU_TYPE_MEM,
|
|
PCIE_ATU_TYPE_IO,
|
|
};
|
|
|
|
cmd = PCI_COMMAND_MASTER;
|
|
|
|
pcie_ctrlb_mapping_region(0, PCIE_ATU_REGION_OUTBOUND, PCIE_ATU_TYPE_CFG0,
|
|
PCIEB_CFG_PCI_BASE, PCIE_CFG_MEM_SIZE, 0, 0);
|
|
|
|
index = 1;
|
|
udelay(1000);
|
|
|
|
for (i = 0; i < 6; i++) {
|
|
val = pcie_readl(PCIEB_CFG_CPU_BASE + 0x10 + i * 4);
|
|
printf("#### [%d] val=%X addr=%X\r\n ", i, val,
|
|
PCIEB_CFG_CPU_BASE + 0x10 + i * 4);
|
|
if (!val)
|
|
continue;
|
|
type = region_types[val & 0x1];
|
|
is_32bit = ((val & 0x4) == 0);
|
|
pcie_writel(0xFFFFFFFF, PCIEB_CFG_CPU_BASE + 0x10 + i * 4);
|
|
size = pcie_readl(PCIEB_CFG_CPU_BASE + 0x10 + i * 4);
|
|
size = 0xFFFFFFFF - (size & ~0xF) + 1;
|
|
if (is_32bit) {
|
|
pcie_ctrlb_mapping_region(index, PCIE_ATU_REGION_OUTBOUND,
|
|
type, PCIEB_CFG_PCI_BASE
|
|
+ index * 0x1000000, size,
|
|
index * 0x1000000, 0);
|
|
val = (val & 0xF) + index * 0x1000000;
|
|
pcie_writel(val, (PCIEB_CFG_CPU_BASE + 0x10 + i * 4));
|
|
} else {
|
|
pcie_writel(0xFFFFFFFF, (PCIEB_CFG_CPU_BASE + 0x10
|
|
+ i * 4 + 4));
|
|
size64 = pcie_readl(PCIEB_CFG_CPU_BASE
|
|
+ 0x10 + i * 4 + 4);
|
|
size64 = 0xFFFFFFFF - size64;
|
|
size64 <<= 32;
|
|
size64 |= size;
|
|
size64++;
|
|
pcie_ctrlb_mapping_region(index, PCIE_ATU_REGION_OUTBOUND,
|
|
type, PCIEB_CFG_PCI_BASE
|
|
+ index * 0x1000000, size64,
|
|
index * 0x1000000, 0);
|
|
val = (val & 0xF) + index * 0x1000000;
|
|
pcie_writel(val, (PCIEB_CFG_CPU_BASE + 0x10 + i * 4));
|
|
pcie_writel(0, (PCIEB_CFG_CPU_BASE + 0x10 + i * 4 + 4));
|
|
i++;
|
|
}
|
|
|
|
index++;
|
|
|
|
if (type == PCIE_ATU_TYPE_MEM)
|
|
cmd |= PCI_COMMAND_MEMORY;
|
|
else
|
|
cmd |= PCI_COMMAND_IO;
|
|
}
|
|
|
|
pcie_writel(cmd, PCIEB_CFG_CPU_BASE + 4);
|
|
}
|
|
|