blob: ffa829ab62cbfb5240c281359b3326851e80f72e [file] [log] [blame] [edit]
/*
*
* 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/imx-common/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);
}