600 lines
15 KiB
C
600 lines
15 KiB
C
/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
|
|
/*
|
|
* drivers/pci/pcie_amlogic.c
|
|
*
|
|
* Copyright (C) 2020 Amlogic, Inc. All rights reserved.
|
|
*
|
|
*/
|
|
|
|
#include <common.h>
|
|
#include <pci.h>
|
|
#include <asm/arch/clock.h>
|
|
#include <asm/gpio.h>
|
|
#include <asm/io.h>
|
|
#include <linux/sizes.h>
|
|
#include <errno.h>
|
|
#include "pcie_amlogic.h"
|
|
#include <asm/arch-axg/pci.h>
|
|
|
|
static t_pl_region_regs *pcieA_pl_region_regs =
|
|
(t_pl_region_regs *)(PCIE_A_PORT_LOGIC_BASE_ADDR);
|
|
static t_pl_region_regs *pcieB_pl_region_regs =
|
|
(t_pl_region_regs *)(PCIE_B_PORT_LOGIC_BASE_ADDR);
|
|
static t_pcie_user_cfg *pcieA_user_cfg =
|
|
(t_pcie_user_cfg *)(PCIE_A_USER_CFG_BASE_ADDR);
|
|
static t_pcie_user_cfg *pcieB_user_cfg =
|
|
(t_pcie_user_cfg *)(PCIE_B_USER_CFG_BASE_ADDR);
|
|
static t_pcie_user_status *pcieA_user_status =
|
|
(t_pcie_user_status *)(PCIE_A_USER_STATUS_BASE_ADDR);
|
|
static t_pcie_user_status *pcieB_user_status =
|
|
(t_pcie_user_status *)(PCIE_B_USER_STATUS_BASE_ADDR);
|
|
static t_pcie_cap_regs *pcieA_pcie_cap_regs =
|
|
(t_pcie_cap_regs *)(PCIE_A_PCIE_CAP_BASE_ADDR);
|
|
static t_pcie_cap_regs *pcieB_pcie_cap_regs =
|
|
(t_pcie_cap_regs *)(PCIE_B_PCIE_CAP_BASE_ADDR);
|
|
static t_type1_hdr_regs *pcieA_type1_hdr_regs =
|
|
(t_type1_hdr_regs *)(PCIE_A_HDR_BASE_ADDR);
|
|
static t_type1_hdr_regs *pcieB_type1_hdr_regs =
|
|
(t_type1_hdr_regs *)(PCIE_B_HDR_BASE_ADDR);
|
|
|
|
static u8 dw_pcie_iatu_unroll_enabled(e_pcieDev pcie_dev)
|
|
{
|
|
u32 val;
|
|
u64 amlogic_dbi_addr;
|
|
|
|
if (pcie_dev == PCIE_A)
|
|
amlogic_dbi_addr = AMLOGIC_PCIE_A_DBI_ADDR;
|
|
else
|
|
amlogic_dbi_addr = AMLOGIC_PCIE_B_DBI_ADDR;
|
|
|
|
val = readl(amlogic_dbi_addr+PCIE_ATU_VIEWPORT);
|
|
if (val == 0xffffffff)
|
|
return 1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void dw_pcie_writel_unroll(e_pcieDev pcie_dev, u32 index, u32 reg,
|
|
u32 val)
|
|
{
|
|
u32 offset = PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(index);
|
|
u64 amlogic_dbi_addr;
|
|
|
|
if (pcie_dev == PCIE_A)
|
|
amlogic_dbi_addr = AMLOGIC_PCIE_A_DBI_ADDR;
|
|
else
|
|
amlogic_dbi_addr = AMLOGIC_PCIE_B_DBI_ADDR;
|
|
|
|
writel(val, amlogic_dbi_addr + offset + reg);
|
|
}
|
|
|
|
static void dw_pcie_prog_outbound_atu(e_pcieDev pcie_dev, int index,
|
|
int type, u64 cpu_addr, u64 pci_addr, u32 size)
|
|
{
|
|
u64 amlogic_dbi_addr;
|
|
|
|
if (pcie_dev == PCIE_A)
|
|
amlogic_dbi_addr = AMLOGIC_PCIE_A_DBI_ADDR;
|
|
else
|
|
amlogic_dbi_addr = AMLOGIC_PCIE_B_DBI_ADDR;
|
|
|
|
if (iatu_unroll_enabled) {
|
|
dw_pcie_writel_unroll(pcie_dev, index, PCIE_ATU_UNR_LOWER_BASE,
|
|
lower_32_bits(cpu_addr));
|
|
dw_pcie_writel_unroll(pcie_dev, index, PCIE_ATU_UNR_UPPER_BASE,
|
|
upper_32_bits(cpu_addr));
|
|
dw_pcie_writel_unroll(pcie_dev, index, PCIE_ATU_UNR_LIMIT,
|
|
lower_32_bits(size - 1));
|
|
dw_pcie_writel_unroll(pcie_dev, index, PCIE_ATU_UNR_LOWER_TARGET,
|
|
lower_32_bits(pci_addr));
|
|
dw_pcie_writel_unroll(pcie_dev, index, PCIE_ATU_UNR_UPPER_TARGET,
|
|
upper_32_bits(pci_addr));
|
|
dw_pcie_writel_unroll(pcie_dev, index, PCIE_ATU_UNR_REGION_CTRL1,
|
|
type);
|
|
dw_pcie_writel_unroll(pcie_dev, index, PCIE_ATU_UNR_REGION_CTRL2,
|
|
PCIE_ATU_ENABLE);
|
|
} else {
|
|
writel(PCIE_ATU_REGION_OUTBOUND | index,
|
|
amlogic_dbi_addr + PCIE_ATU_VIEWPORT);
|
|
writel(lower_32_bits(cpu_addr),
|
|
amlogic_dbi_addr + PCIE_ATU_LOWER_BASE);
|
|
writel(upper_32_bits(cpu_addr),
|
|
amlogic_dbi_addr + PCIE_ATU_UPPER_BASE);
|
|
writel(lower_32_bits(cpu_addr + size - 1),
|
|
amlogic_dbi_addr + PCIE_ATU_LIMIT);
|
|
writel(lower_32_bits(pci_addr),
|
|
amlogic_dbi_addr + PCIE_ATU_LOWER_TARGET);
|
|
writel(upper_32_bits(pci_addr),
|
|
amlogic_dbi_addr + PCIE_ATU_UPPER_TARGET);
|
|
writel(type, amlogic_dbi_addr + PCIE_ATU_CR1);
|
|
writel(PCIE_ATU_ENABLE, amlogic_dbi_addr + PCIE_ATU_CR2);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* iATU region setup
|
|
*/
|
|
static int amlogic_pcie_regions_setup(e_pcieDev pcie_dev)
|
|
{
|
|
u64 amlogic_dbi_addr;
|
|
u32 high_2m_base_addr;
|
|
u32 high_2m_limit;
|
|
u64 target_base_addr;
|
|
int type;
|
|
|
|
if (pcie_dev == PCIE_A) {
|
|
amlogic_dbi_addr = AMLOGIC_PCIE_A_DBI_ADDR;
|
|
high_2m_base_addr = EP_A_BASE_ADDR + 0x200000;
|
|
high_2m_limit = high_2m_base_addr + 0x1fffff;
|
|
} else {
|
|
amlogic_dbi_addr = AMLOGIC_PCIE_B_DBI_ADDR;
|
|
high_2m_base_addr = EP_B_BASE_ADDR + 0x200000;
|
|
high_2m_limit = high_2m_base_addr + 0x1fffff;
|
|
}
|
|
|
|
/* CMD reg:I/O space, MEM space, and Bus Master Enable */
|
|
/* Set the CLASS_REV of RC CFG header to PCI_CLASS_BRIDGE_PCI */
|
|
setbits_le32(amlogic_dbi_addr + PCI_CLASS_REVISION,
|
|
PCI_CLASS_BRIDGE_PCI << 16);
|
|
|
|
iatu_unroll_enabled = dw_pcie_iatu_unroll_enabled(pcie_dev);
|
|
|
|
target_base_addr = high_2m_base_addr & 0x3fffff;
|
|
type = PCIE_ATU_TYPE_MEM;
|
|
if (type == PCIE_ATU_TYPE_MEM)
|
|
target_base_addr &= (~0xfff);
|
|
|
|
dw_pcie_prog_outbound_atu(pcie_dev, PCIE_ATU_REGION_INDEX1,
|
|
PCIE_ATU_TYPE_MEM, high_2m_base_addr,
|
|
target_base_addr, high_2m_limit);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int amlogic_pcie_read_config
|
|
(struct pci_controller *hose, pci_dev_t d, int where, u32 *val)
|
|
{
|
|
int type;
|
|
e_pcieDev pcie_dev = *(int *)hose->priv_data;
|
|
u64 ep_type0_hdr_regs;
|
|
u32 ep_cfg_base_addr;
|
|
u32 ep_cfg_addr_limit;
|
|
u64 target_base_addr;
|
|
|
|
if (pcie_dev == PCIE_A) {
|
|
ep_type0_hdr_regs = EP_A_BASE_ADDR;
|
|
ep_cfg_base_addr = EP_A_BASE_ADDR;
|
|
ep_cfg_addr_limit = EP_A_BASE_ADDR + 0x1fffff;
|
|
} else {
|
|
ep_type0_hdr_regs = EP_B_BASE_ADDR;
|
|
ep_cfg_base_addr = EP_B_BASE_ADDR;
|
|
ep_cfg_addr_limit = EP_B_BASE_ADDR + 0x1fffff;
|
|
}
|
|
|
|
target_base_addr = ep_cfg_base_addr & 0x3fffff;
|
|
type = TYPE_CFG0;
|
|
|
|
if (type == TYPE_CFG0)
|
|
target_base_addr = (0 & 0xff) << 24 |
|
|
(0 & 0x1F) << 19 |
|
|
(0 & 0x7) << 16;
|
|
|
|
dw_pcie_prog_outbound_atu(pcie_dev, PCIE_ATU_REGION_INDEX0,
|
|
type, ep_cfg_base_addr,
|
|
target_base_addr, ep_cfg_addr_limit);
|
|
|
|
*val = readl(ep_type0_hdr_regs + where);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int amlogic_pcie_write_config(struct pci_controller *hose, pci_dev_t d,
|
|
int where, u32 val)
|
|
{
|
|
int type;
|
|
e_pcieDev pcie_dev = *(int *)hose->priv_data;
|
|
u64 ep_type0_hdr_regs;
|
|
u32 ep_cfg_base_addr;
|
|
u32 ep_cfg_addr_limit;
|
|
u64 target_base_addr;
|
|
|
|
if (pcie_dev == PCIE_A) {
|
|
ep_type0_hdr_regs = EP_A_BASE_ADDR;
|
|
ep_cfg_base_addr = EP_A_BASE_ADDR;
|
|
ep_cfg_addr_limit = EP_A_BASE_ADDR + 0x1fffff;
|
|
} else {
|
|
ep_type0_hdr_regs = EP_B_BASE_ADDR;
|
|
ep_cfg_base_addr = EP_B_BASE_ADDR;
|
|
ep_cfg_addr_limit = EP_B_BASE_ADDR + 0x1fffff;
|
|
}
|
|
|
|
target_base_addr = ep_cfg_base_addr & 0x3fffff;
|
|
type = TYPE_CFG0;
|
|
|
|
if (type == TYPE_CFG0)
|
|
target_base_addr = (0 & 0xff) << 24 |
|
|
(0 & 0x1F) << 19 |
|
|
(0 & 0x7) << 16;
|
|
|
|
dw_pcie_prog_outbound_atu(pcie_dev, PCIE_ATU_REGION_INDEX0,
|
|
type, ep_cfg_base_addr,
|
|
target_base_addr, ep_cfg_addr_limit);
|
|
|
|
writel(val, ep_type0_hdr_regs + where);
|
|
return 0;
|
|
}
|
|
|
|
static void amlogic_pcie_init_PLL(e_pcieDev pcie_dev)
|
|
{
|
|
if (pcie_dev == PCIE_A) {
|
|
*PCIE_PHY_BASE = 0x1d;
|
|
mdelay(1);
|
|
*PCIE_PHY_BASE = 0x1c;
|
|
mdelay(1);
|
|
*P_RESET0_LEVEL &= ~((0x3<<6) | (0x3<<1));
|
|
mdelay(1);
|
|
*PCIE_CTRL_6 &= ~(0X3 << 3);
|
|
*MIPI_CTRL &= ~((0x1 << 26) | (0x1 << 29));
|
|
mdelay(1);
|
|
|
|
*PCIE_CTRL_0 = 0x400106c8;
|
|
*PCIE_CTRL_1 = 0x0084a2aa;
|
|
*PCIE_CTRL_2 = 0xb75020be;
|
|
*PCIE_CTRL_3 = 0x0a47488e;
|
|
*PCIE_CTRL_4 = 0xc000004d;
|
|
*PCIE_CTRL_5 = 0x00078000;
|
|
*PCIE_CTRL_6 = 0x002323c6;
|
|
mdelay(1);
|
|
|
|
writel(readl(PCIE_CTRL_0) | 1<<29, PCIE_CTRL_0);
|
|
mdelay(1);
|
|
writel(readl(PCIE_CTRL_0) & ~(1<<29), PCIE_CTRL_0);
|
|
|
|
*P_RESET0_LEVEL |= (0x3<<6);
|
|
mdelay(1);
|
|
|
|
*CLK81_HIGH |= (0x1 << 26);
|
|
}
|
|
|
|
mdelay(1);
|
|
if (pcie_dev == PCIE_A)
|
|
*CLK81_LOW |= (0x1 << 16);
|
|
else
|
|
*CLK81_LOW |= (0x1 << 17);
|
|
mdelay(1);
|
|
|
|
if (pcie_dev == PCIE_A)
|
|
*P_RESET0_LEVEL |= (0x1 << 1);
|
|
else
|
|
*P_RESET0_LEVEL |= (0x1 << 2);
|
|
mdelay(1);
|
|
|
|
if (pcie_dev == PCIE_A)
|
|
*MIPI_CTRL |= ((0x1 << 26) | (0x1 << 29));
|
|
mdelay(1);
|
|
|
|
if (pcie_dev == PCIE_A)
|
|
*PCIE_CTRL_6 |= (0x1 << 4);
|
|
else
|
|
*PCIE_CTRL_6 |= (0x1 << 3);
|
|
mdelay(1);
|
|
}
|
|
|
|
static int amlogic_pcie_init_dw(e_pcieDev pcie_dev)
|
|
{
|
|
t_pl_region_regs *pl_region_regs;
|
|
t_type1_hdr_regs *type1_hdr_regs;
|
|
|
|
if (pcie_dev == PCIE_A) {
|
|
pl_region_regs = pcieA_pl_region_regs;
|
|
type1_hdr_regs = pcieA_type1_hdr_regs;
|
|
pcieA_user_cfg->cfg0 |= (1<<7);
|
|
} else {
|
|
pl_region_regs = pcieB_pl_region_regs;
|
|
type1_hdr_regs = pcieB_type1_hdr_regs;
|
|
pcieB_user_cfg->cfg0 |= (1<<7);
|
|
}
|
|
|
|
pl_region_regs->port_link_ctrl_off_reg |= 1<<7;
|
|
|
|
pl_region_regs->port_link_ctrl_off_reg &= ~(0x3f<<16);
|
|
pl_region_regs->port_link_ctrl_off_reg |= 0x1<<16;
|
|
|
|
pl_region_regs->gen2_ctrl_off_reg &= ~(0x1f<<8);
|
|
pl_region_regs->gen2_ctrl_off_reg |= 0x1<<8;
|
|
|
|
pl_region_regs->gen2_ctrl_off_reg |= (1<<17);
|
|
|
|
type1_hdr_regs->base_addr0_reg = 0x0;
|
|
type1_hdr_regs->base_addr1_reg = 0x0;
|
|
|
|
return 0;
|
|
}
|
|
|
|
void amlogic_wait_linkup(e_pcieDev pcie_dev)
|
|
{
|
|
t_pcie_user_status *user_status;
|
|
int smlh_up = 0;
|
|
int rdlh_up = 0;
|
|
int ltssm_up = 0;
|
|
int speed_okay = 0;
|
|
int current_data_rate;
|
|
int cnt = 0;
|
|
|
|
if (pcie_dev == PCIE_A)
|
|
user_status = pcieA_user_status;
|
|
else
|
|
user_status = pcieB_user_status;
|
|
|
|
while (smlh_up == 0 || rdlh_up == 0 ||
|
|
ltssm_up == 0 || speed_okay == 0) {
|
|
smlh_up = (user_status->status12 >> 6) & 0x1;
|
|
rdlh_up = (user_status->status12 >> 16) & 0x1;
|
|
ltssm_up = ((user_status->status12 >> 10)
|
|
& 0x1f) == 0x11 ? 1 : 0;
|
|
current_data_rate = (user_status->status17>> 7) & 0x1;
|
|
|
|
if (current_data_rate == PCIE_GEN2 ||
|
|
current_data_rate == PCIE_GEN1)
|
|
speed_okay = 1;
|
|
|
|
cnt++;
|
|
|
|
if (cnt >= WAIT_LINKUP_TIMEOUT) {
|
|
if (pcie_dev == PCIE_A)
|
|
printf("Error:PCIE A Wait linkup timeout.\n");
|
|
else
|
|
printf("Error:PCIE B Wait linkup timeout.\n");
|
|
return;
|
|
}
|
|
|
|
udelay(20);
|
|
}
|
|
|
|
if (pcie_dev == PCIE_A)
|
|
printf("PCIE A linkup success\n");
|
|
else
|
|
printf("PCIE B linkup success\n");
|
|
}
|
|
|
|
void amlogic_set_max_payload(e_pcieDev pcie_dev, int size)
|
|
{
|
|
int max_payload_size = 1;
|
|
|
|
switch (size) {
|
|
case 128:
|
|
max_payload_size = 0;
|
|
break;
|
|
case 256:
|
|
max_payload_size = 1;
|
|
break;
|
|
case 512:
|
|
max_payload_size = 2;
|
|
break;
|
|
case 1024:
|
|
max_payload_size = 3;
|
|
break;
|
|
case 2048:
|
|
max_payload_size = 4;
|
|
break;
|
|
case 4096:
|
|
max_payload_size = 5;
|
|
break;
|
|
}
|
|
|
|
if (pcie_dev == PCIE_A) {
|
|
pcieA_pcie_cap_regs->dev_ctrl_dev_stus_reg &= ~(0x7<<5);
|
|
pcieA_pcie_cap_regs->dev_ctrl_dev_stus_reg |= (max_payload_size<<5);
|
|
} else {
|
|
pcieB_pcie_cap_regs->dev_ctrl_dev_stus_reg &= ~(0x7<<5);
|
|
pcieB_pcie_cap_regs->dev_ctrl_dev_stus_reg |= (max_payload_size<<5);
|
|
}
|
|
}
|
|
|
|
void amlogic_set_max_rd_req_size(e_pcieDev pcie_dev, int size)
|
|
{
|
|
int max_rd_req_size = 1;
|
|
|
|
switch (size) {
|
|
case 128:
|
|
max_rd_req_size = 0;
|
|
break;
|
|
case 256:
|
|
max_rd_req_size = 1;
|
|
break;
|
|
case 512:
|
|
max_rd_req_size = 2;
|
|
break;
|
|
case 1024:
|
|
max_rd_req_size = 3;
|
|
break;
|
|
case 2048:
|
|
max_rd_req_size = 4;
|
|
break;
|
|
case 4096:
|
|
max_rd_req_size = 5;
|
|
break;
|
|
}
|
|
|
|
if (pcie_dev == PCIE_A) {
|
|
pcieA_pcie_cap_regs->dev_ctrl_dev_stus_reg &= ~(0x7<<12);
|
|
pcieA_pcie_cap_regs->dev_ctrl_dev_stus_reg |= (max_rd_req_size<<12);
|
|
} else {
|
|
pcieB_pcie_cap_regs->dev_ctrl_dev_stus_reg &= ~(0x7<<12);
|
|
pcieB_pcie_cap_regs->dev_ctrl_dev_stus_reg |= (max_rd_req_size<<12);
|
|
}
|
|
}
|
|
|
|
void amlogic_configure_dsp_memory_map(e_pcieDev pcie_dev)
|
|
{
|
|
t_type1_hdr_regs *type1_hdr_regs;
|
|
u32 io_base_addr;
|
|
u32 io_limit;
|
|
u32 mem_base_addr;
|
|
u32 mem_limit;
|
|
u32 pref_mem_base_addr;
|
|
u32 pref_mem_limit;
|
|
|
|
if (pcie_dev == PCIE_A) {
|
|
type1_hdr_regs = pcieA_type1_hdr_regs;
|
|
io_base_addr = PCIE_A_IO_BASE_ADDR;
|
|
io_limit = PCIE_A_IO_LIMIT;
|
|
mem_base_addr = PCIE_A_MEM_BASE_ADDR;
|
|
mem_limit = PCIE_A_MEM_LIMIT;
|
|
pref_mem_base_addr = PCIE_A_PREF_MEM_BASE_ADDR;
|
|
pref_mem_limit = PCIE_A_PREF_MEM_LIMIT;
|
|
} else {
|
|
type1_hdr_regs = pcieB_type1_hdr_regs;
|
|
io_base_addr = PCIE_B_IO_BASE_ADDR;
|
|
io_limit = PCIE_B_IO_LIMIT;
|
|
mem_base_addr = PCIE_B_MEM_BASE_ADDR;
|
|
mem_limit = PCIE_B_MEM_LIMIT;
|
|
pref_mem_base_addr = PCIE_B_PREF_MEM_BASE_ADDR;
|
|
pref_mem_limit = PCIE_B_PREF_MEM_LIMIT;
|
|
}
|
|
type1_hdr_regs->io_limit_base_reg = (((io_base_addr >> 12) & 0xF) << 4)
|
|
| (1 << 0) | (1 << 8) |
|
|
(((io_limit >> 12) & 0XF) << 12);
|
|
|
|
type1_hdr_regs->io_limit_base_upper_reg = ((io_base_addr >> 16) & 0xFFFF)
|
|
<< 0 | ((io_limit >> 16) & 0XFFFF) << 16;
|
|
|
|
type1_hdr_regs->pref_mem_limit_base_reg = 0x00010001;
|
|
type1_hdr_regs->pref_base_upper_reg = 0;
|
|
type1_hdr_regs->pref_limit_upper_reg = 0;
|
|
type1_hdr_regs->pref_mem_limit_base_reg =
|
|
((pref_mem_base_addr >> 20) & 0xFFF) << 4 |
|
|
((pref_mem_limit >> 20) & 0xFFF) << 20;
|
|
|
|
type1_hdr_regs->mem_limit_base_reg =
|
|
((mem_base_addr >> 20) & 0xFFF) << 4 |
|
|
((mem_limit >> 20) & 0xFFF) << 20;
|
|
}
|
|
|
|
void amlogic_enable_memory_space(e_pcieDev pcie_dev)
|
|
{
|
|
t_type1_hdr_regs *type1_hdr_regs;
|
|
|
|
if (pcie_dev == PCIE_A)
|
|
type1_hdr_regs = pcieA_type1_hdr_regs;
|
|
else
|
|
type1_hdr_regs = pcieB_type1_hdr_regs;
|
|
|
|
type1_hdr_regs->stus_cmd_reg = 7;
|
|
}
|
|
|
|
static int amlogic_pcie_link_up(e_pcieDev pcie_dev)
|
|
{
|
|
amlogic_pcie_init_dw(pcie_dev);
|
|
|
|
amlogic_set_max_payload(pcie_dev, 256);
|
|
amlogic_set_max_rd_req_size(pcie_dev, 256);
|
|
|
|
amlogic_pcie_regions_setup(pcie_dev);
|
|
|
|
amlogic_configure_dsp_memory_map(pcie_dev);
|
|
amlogic_enable_memory_space(pcie_dev);
|
|
|
|
amlogic_pcie_init_reset_pin(pcie_dev);
|
|
amlogic_wait_linkup(pcie_dev);
|
|
|
|
return 0;
|
|
}
|
|
|
|
void amlogic_pcie_PLL_disable(void)
|
|
{
|
|
amlogic_pcie_disable();
|
|
|
|
*PCIE_PHY_BASE = 0x1d;
|
|
|
|
mdelay(1);
|
|
*P_RESET0_LEVEL &= ~((0x3<<6) | (0x3<<1));
|
|
mdelay(1);
|
|
|
|
*PCIE_CTRL_0 = 0x80000000;
|
|
*PCIE_CTRL_1 = 0x0;
|
|
*PCIE_CTRL_2 = 0x0;
|
|
*PCIE_CTRL_3 = 0x0;
|
|
*PCIE_CTRL_4 = 0x0;
|
|
*PCIE_CTRL_5 = 0x0;
|
|
*PCIE_CTRL_6 = 0x0;
|
|
|
|
*CLK81_LOW &= ~(0x1 << 16);
|
|
*CLK81_LOW &= ~(0x1 << 17);
|
|
|
|
*MIPI_CTRL &= ~((0x1 << 26) | (0x1 << 29));
|
|
*PCIE_CTRL_6 &= ~(0X3 << 3);
|
|
}
|
|
|
|
void amlogic_pcie_init(e_pcieDev pcie_dev)
|
|
{
|
|
/* Static instance of the controller. */
|
|
static struct pci_controller pcc;
|
|
struct pci_controller *hose = &pcc;
|
|
int ret;
|
|
|
|
amlogic_pcie_init_PLL(pcie_dev);
|
|
|
|
memset(&pcc, 0, sizeof(pcc));
|
|
if (pcie_dev == PCIE_A) {
|
|
/* PCI I/O space */
|
|
pci_set_region(&hose->regions[0],
|
|
PCIE_A_IO_BASE_ADDR, PCIE_A_IO_BASE_ADDR,
|
|
0xff, PCI_REGION_IO);
|
|
|
|
/* PCI memory space */
|
|
pci_set_region(&hose->regions[1],
|
|
PCIE_A_MEM_BASE_ADDR, PCIE_A_MEM_BASE_ADDR,
|
|
0x6fffffff, PCI_REGION_MEM);
|
|
|
|
/* System memory space */
|
|
pci_set_region(&hose->regions[2],
|
|
EP_A_PREF_MEM_BASE_ADDR, EP_A_PREF_MEM_BASE_ADDR,
|
|
0x7fffff, PCI_REGION_MEM | PCI_REGION_SYS_MEMORY);
|
|
} else {
|
|
/* PCI I/O space */
|
|
pci_set_region(&hose->regions[0],
|
|
PCIE_B_IO_BASE_ADDR, PCIE_B_IO_BASE_ADDR,
|
|
0xff, PCI_REGION_IO);
|
|
|
|
/* PCI memory space */
|
|
pci_set_region(&hose->regions[1],
|
|
PCIE_B_MEM_BASE_ADDR, PCIE_B_MEM_BASE_ADDR,
|
|
0x6fffffff, PCI_REGION_MEM);
|
|
|
|
/* System memory space */
|
|
pci_set_region(&hose->regions[2],
|
|
EP_B_PREF_MEM_BASE_ADDR, EP_B_PREF_MEM_BASE_ADDR,
|
|
0x7fffff, PCI_REGION_MEM | PCI_REGION_SYS_MEMORY);
|
|
}
|
|
|
|
hose->region_count = 3;
|
|
pcie_type = pcie_dev;
|
|
hose->priv_data = &pcie_type;
|
|
|
|
pci_set_ops(hose,
|
|
pci_hose_read_config_byte_via_dword,
|
|
pci_hose_read_config_word_via_dword,
|
|
amlogic_pcie_read_config,
|
|
pci_hose_write_config_byte_via_dword,
|
|
pci_hose_write_config_word_via_dword,
|
|
amlogic_pcie_write_config);
|
|
|
|
/* Start the controller. */
|
|
ret = amlogic_pcie_link_up(pcie_dev);
|
|
if (!ret) {
|
|
pci_register_hose(hose);
|
|
hose->last_busno = pci_hose_scan(hose);
|
|
}
|
|
if (pcie_dev == PCIE_B)
|
|
amlogic_pcie_PLL_disable();
|
|
}
|
|
|
|
/* Probe function. */
|
|
void pci_init_board(void)
|
|
{
|
|
amlogic_pcie_init(PCIE_A);
|
|
amlogic_pcie_init(PCIE_B);
|
|
}
|