- a37xx: pci: Increase PCIe IO size from 64 KiB to 1 MiB (Pali) - phy: marvell: a3700: Misc improvements (Pali) - a38x serdes cleanup (Pali) - A3720 PCIe enhancements (Pali & Marek) - mvebu: mvebu_armada-8k: Puzzle M801 enhancements (Robert) - mvebu: x530: Remove custom kwbimage.cfg (Chris) - mvebu: Select SPL_SKIP_LOWLEVEL_INIT on ARMADA_32BIT (Stefan)
This commit is contained in:
@@ -335,14 +335,14 @@
|
||||
/*
|
||||
* The 128 MiB address range [0xe8000000-0xf0000000] is
|
||||
* dedicated for PCIe and can be assigned to 8 windows
|
||||
* with size a power of two. Use one 64 KiB window for
|
||||
* with size a power of two. Use one 1 MiB window for
|
||||
* IO at the end and the remaining seven windows
|
||||
* (totaling 127 MiB) for MEM.
|
||||
*/
|
||||
ranges = <0x82000000 0 0xe8000000
|
||||
0 0xe8000000 0 0x7f00000 /* Port 0 MEM */
|
||||
0x81000000 0 0xefff0000
|
||||
0 0xefff0000 0 0x10000>; /* Port 0 IO*/
|
||||
0x81000000 0 0xeff00000
|
||||
0 0xeff00000 0 0x100000>; /* Port 0 IO*/
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -243,6 +243,9 @@
|
||||
|
||||
&cp1_mdio {
|
||||
status = "okay";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&cp1_smi_pins>;
|
||||
|
||||
cp1_ge_phy0: ethernet-phy@3 {
|
||||
reg = <1>;
|
||||
};
|
||||
@@ -292,33 +295,24 @@
|
||||
/*
|
||||
* MPP Bus:
|
||||
* [0-5] TDM
|
||||
* [6,7] CP1_UART 0
|
||||
* [8] CP1 10G SFP LOS
|
||||
* [9] CP1 10G PHY RESET
|
||||
* [10] CP1 10G SFP TX Disable
|
||||
* [11] CP1 10G SFP Mode
|
||||
* [12] SPI1 CS1n
|
||||
* [13] SPI1 MISO (TDM and SPI ROM shared)
|
||||
* [14] SPI1 CS0n
|
||||
* [15] SPI1 MOSI (TDM and SPI ROM shared)
|
||||
* [16] SPI1 CLK (TDM and SPI ROM shared)
|
||||
* [24] CP1 2.5G SFP TX Disable
|
||||
* [26] CP0 10G SFP TX Fault
|
||||
* [27] CP0 10G SFP Mode
|
||||
* [28] CP0 10G SFP LOS
|
||||
* [29] CP0 10G SFP TX Disable
|
||||
* [30] USB Over current indication
|
||||
* [31] 10G Port 0 phy reset
|
||||
* [27-28] SMI
|
||||
* [29-30] CP1 MSS I2C
|
||||
* [6-26, 31] GPIO
|
||||
* [32-62] = 0xff: Keep default CP1_shared_pins:
|
||||
*/
|
||||
/* 0 1 2 3 4 5 6 7 8 9 */
|
||||
pin-func = < 0x4 0x4 0x4 0x4 0x4 0x4 0x8 0x8 0x0 0x0
|
||||
0x0 0x0 0x3 0x3 0x3 0x3 0x3 0xff 0xff 0xff
|
||||
0xff 0xff 0xff 0xff 0x0 0xff 0x0 0x0 0x0 0x0
|
||||
0x0 0x0 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
|
||||
pin-func = < 0x4 0x4 0x4 0x4 0x4 0x4 0x0 0x0 0x0 0x0
|
||||
0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0
|
||||
0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x8 0x8 0x8
|
||||
0x8 0x0 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
|
||||
0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
|
||||
0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
|
||||
0xff 0xff 0xff>;
|
||||
|
||||
cp1_smi_pins: cp1-smi-pins {
|
||||
marvell,pins = < 27 28 >;
|
||||
marvell,function = <8>;
|
||||
};
|
||||
};
|
||||
|
||||
&ap_spi0 {
|
||||
|
||||
@@ -11,6 +11,7 @@ config ARMADA_32BIT
|
||||
select SPL_DM if SPL
|
||||
select SPL_DM_SEQ_ALIAS if SPL
|
||||
select SPL_OF_CONTROL if SPL
|
||||
select SPL_SKIP_LOWLEVEL_INIT
|
||||
select SPL_SIMPLE_BUS if SPL
|
||||
select SUPPORT_SPL
|
||||
select TRANSLATION_OFFSET
|
||||
|
||||
@@ -21,35 +21,12 @@ __weak void board_pex_config(void)
|
||||
|
||||
int hws_pex_config(const struct serdes_map *serdes_map, u8 count)
|
||||
{
|
||||
u32 pex_idx, tmp, next_busno, first_busno, temp_pex_reg,
|
||||
temp_reg, addr, dev_id, ctrl_mode;
|
||||
enum serdes_type serdes_type;
|
||||
u32 idx;
|
||||
u32 idx, tmp;
|
||||
|
||||
DEBUG_INIT_FULL_S("\n### hws_pex_config ###\n");
|
||||
|
||||
for (idx = 0; idx < count; idx++) {
|
||||
serdes_type = serdes_map[idx].serdes_type;
|
||||
/* configuration for PEX only */
|
||||
if ((serdes_type != PEX0) && (serdes_type != PEX1) &&
|
||||
(serdes_type != PEX2) && (serdes_type != PEX3))
|
||||
continue;
|
||||
|
||||
if ((serdes_type != PEX0) &&
|
||||
((serdes_map[idx].serdes_mode == PEX_ROOT_COMPLEX_X4) ||
|
||||
(serdes_map[idx].serdes_mode == PEX_END_POINT_X4))) {
|
||||
/* for PEX by4 - relevant for the first port only */
|
||||
continue;
|
||||
}
|
||||
|
||||
pex_idx = serdes_type - PEX0;
|
||||
tmp = reg_read(PEX_CAPABILITIES_REG(pex_idx));
|
||||
tmp &= ~(0xf << 20);
|
||||
tmp |= (0x4 << 20);
|
||||
reg_write(PEX_CAPABILITIES_REG(pex_idx), tmp);
|
||||
}
|
||||
|
||||
tmp = reg_read(SOC_CTRL_REG);
|
||||
tmp = reg_read(SOC_CONTROL_REG1);
|
||||
tmp &= ~0x03;
|
||||
|
||||
for (idx = 0; idx < count; idx++) {
|
||||
@@ -79,277 +56,9 @@ int hws_pex_config(const struct serdes_map *serdes_map, u8 count)
|
||||
}
|
||||
}
|
||||
|
||||
reg_write(SOC_CTRL_REG, tmp);
|
||||
|
||||
/* Support gen1/gen2 */
|
||||
DEBUG_INIT_FULL_S("Support gen1/gen2\n");
|
||||
reg_write(SOC_CONTROL_REG1, tmp);
|
||||
|
||||
board_pex_config();
|
||||
|
||||
next_busno = 0;
|
||||
mdelay(150);
|
||||
|
||||
for (idx = 0; idx < count; idx++) {
|
||||
serdes_type = serdes_map[idx].serdes_type;
|
||||
DEBUG_INIT_FULL_S(" serdes_type=0x");
|
||||
DEBUG_INIT_FULL_D(serdes_type, 8);
|
||||
DEBUG_INIT_FULL_S("\n");
|
||||
DEBUG_INIT_FULL_S(" idx=0x");
|
||||
DEBUG_INIT_FULL_D(idx, 8);
|
||||
DEBUG_INIT_FULL_S("\n");
|
||||
|
||||
/* Configuration for PEX only */
|
||||
if ((serdes_type != PEX0) && (serdes_type != PEX1) &&
|
||||
(serdes_type != PEX2) && (serdes_type != PEX3))
|
||||
continue;
|
||||
|
||||
if ((serdes_type != PEX0) &&
|
||||
((serdes_map[idx].serdes_mode == PEX_ROOT_COMPLEX_X4) ||
|
||||
(serdes_map[idx].serdes_mode == PEX_END_POINT_X4))) {
|
||||
/* for PEX by4 - relevant for the first port only */
|
||||
continue;
|
||||
}
|
||||
|
||||
pex_idx = serdes_type - PEX0;
|
||||
tmp = reg_read(PEX_DBG_STATUS_REG(pex_idx));
|
||||
|
||||
first_busno = next_busno;
|
||||
if ((tmp & 0x7f) != 0x7e) {
|
||||
DEBUG_INIT_S("PCIe, Idx ");
|
||||
DEBUG_INIT_D(pex_idx, 1);
|
||||
DEBUG_INIT_S(": detected no link\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
next_busno++;
|
||||
temp_pex_reg = reg_read((PEX_CFG_DIRECT_ACCESS
|
||||
(pex_idx, PEX_LINK_CAPABILITY_REG)));
|
||||
temp_pex_reg &= 0xf;
|
||||
if (temp_pex_reg != 0x2)
|
||||
continue;
|
||||
|
||||
temp_reg = (reg_read(PEX_CFG_DIRECT_ACCESS(
|
||||
pex_idx,
|
||||
PEX_LINK_CTRL_STAT_REG)) &
|
||||
0xf0000) >> 16;
|
||||
|
||||
/* Check if the link established is GEN1 */
|
||||
DEBUG_INIT_FULL_S
|
||||
("Checking if the link established is gen1\n");
|
||||
if (temp_reg != 0x1)
|
||||
continue;
|
||||
|
||||
pex_local_bus_num_set(pex_idx, first_busno);
|
||||
pex_local_dev_num_set(pex_idx, 1);
|
||||
DEBUG_INIT_FULL_S("PCIe, Idx ");
|
||||
DEBUG_INIT_FULL_D(pex_idx, 1);
|
||||
|
||||
DEBUG_INIT_S(":** Link is Gen1, check the EP capability\n");
|
||||
/* link is Gen1, check the EP capability */
|
||||
addr = pex_config_read(pex_idx, first_busno, 0, 0, 0x34) & 0xff;
|
||||
DEBUG_INIT_FULL_C("pex_config_read: return addr=0x%x", addr, 4);
|
||||
if (addr == 0xff) {
|
||||
DEBUG_INIT_FULL_C
|
||||
("pex_config_read: return 0xff -->PCIe (%d): Detected No Link.",
|
||||
pex_idx, 1);
|
||||
continue;
|
||||
}
|
||||
|
||||
while ((pex_config_read(pex_idx, first_busno, 0, 0, addr)
|
||||
& 0xff) != 0x10) {
|
||||
addr = (pex_config_read(pex_idx, first_busno, 0,
|
||||
0, addr) & 0xff00) >> 8;
|
||||
}
|
||||
|
||||
/* Check for Gen2 and above */
|
||||
if ((pex_config_read(pex_idx, first_busno, 0, 0,
|
||||
addr + 0xc) & 0xf) < 0x2) {
|
||||
DEBUG_INIT_S("PCIe, Idx ");
|
||||
DEBUG_INIT_D(pex_idx, 1);
|
||||
DEBUG_INIT_S(": remains Gen1\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
tmp = reg_read(PEX_LINK_CTRL_STATUS2_REG(pex_idx));
|
||||
DEBUG_RD_REG(PEX_LINK_CTRL_STATUS2_REG(pex_idx), tmp);
|
||||
tmp &= ~(BIT(0) | BIT(1));
|
||||
tmp |= BIT(1);
|
||||
tmp |= BIT(6); /* Select Deemphasize (-3.5d_b) */
|
||||
reg_write(PEX_LINK_CTRL_STATUS2_REG(pex_idx), tmp);
|
||||
DEBUG_WR_REG(PEX_LINK_CTRL_STATUS2_REG(pex_idx), tmp);
|
||||
|
||||
tmp = reg_read(PEX_CTRL_REG(pex_idx));
|
||||
DEBUG_RD_REG(PEX_CTRL_REG(pex_idx), tmp);
|
||||
tmp |= BIT(10);
|
||||
reg_write(PEX_CTRL_REG(pex_idx), tmp);
|
||||
DEBUG_WR_REG(PEX_CTRL_REG(pex_idx), tmp);
|
||||
|
||||
/*
|
||||
* We need to wait 10ms before reading the PEX_DBG_STATUS_REG
|
||||
* in order not to read the status of the former state
|
||||
*/
|
||||
mdelay(10);
|
||||
|
||||
DEBUG_INIT_S("PCIe, Idx ");
|
||||
DEBUG_INIT_D(pex_idx, 1);
|
||||
DEBUG_INIT_S
|
||||
(": Link upgraded to Gen2 based on client capabilities\n");
|
||||
}
|
||||
|
||||
/* Update pex DEVICE ID */
|
||||
ctrl_mode = sys_env_model_get();
|
||||
|
||||
for (idx = 0; idx < count; idx++) {
|
||||
serdes_type = serdes_map[idx].serdes_type;
|
||||
/* configuration for PEX only */
|
||||
if ((serdes_type != PEX0) && (serdes_type != PEX1) &&
|
||||
(serdes_type != PEX2) && (serdes_type != PEX3))
|
||||
continue;
|
||||
|
||||
if ((serdes_type != PEX0) &&
|
||||
((serdes_map[idx].serdes_mode == PEX_ROOT_COMPLEX_X4) ||
|
||||
(serdes_map[idx].serdes_mode == PEX_END_POINT_X4))) {
|
||||
/* for PEX by4 - relevant for the first port only */
|
||||
continue;
|
||||
}
|
||||
|
||||
pex_idx = serdes_type - PEX0;
|
||||
dev_id = reg_read(PEX_CFG_DIRECT_ACCESS
|
||||
(pex_idx, PEX_DEVICE_AND_VENDOR_ID));
|
||||
dev_id &= 0xffff;
|
||||
dev_id |= ((ctrl_mode << 16) & 0xffff0000);
|
||||
reg_write(PEX_CFG_DIRECT_ACCESS
|
||||
(pex_idx, PEX_DEVICE_AND_VENDOR_ID), dev_id);
|
||||
}
|
||||
DEBUG_INIT_FULL_C("Update PEX Device ID ", ctrl_mode, 4);
|
||||
|
||||
return MV_OK;
|
||||
}
|
||||
|
||||
int pex_local_bus_num_set(u32 pex_if, u32 bus_num)
|
||||
{
|
||||
u32 pex_status;
|
||||
|
||||
DEBUG_INIT_FULL_S("\n### pex_local_bus_num_set ###\n");
|
||||
|
||||
if (bus_num >= MAX_PEX_BUSSES) {
|
||||
DEBUG_INIT_C("pex_local_bus_num_set: Illegal bus number %d\n",
|
||||
bus_num, 4);
|
||||
return MV_BAD_PARAM;
|
||||
}
|
||||
|
||||
pex_status = reg_read(PEX_STATUS_REG(pex_if));
|
||||
pex_status &= ~PXSR_PEX_BUS_NUM_MASK;
|
||||
pex_status |=
|
||||
(bus_num << PXSR_PEX_BUS_NUM_OFFS) & PXSR_PEX_BUS_NUM_MASK;
|
||||
reg_write(PEX_STATUS_REG(pex_if), pex_status);
|
||||
|
||||
return MV_OK;
|
||||
}
|
||||
|
||||
int pex_local_dev_num_set(u32 pex_if, u32 dev_num)
|
||||
{
|
||||
u32 pex_status;
|
||||
|
||||
DEBUG_INIT_FULL_S("\n### pex_local_dev_num_set ###\n");
|
||||
|
||||
pex_status = reg_read(PEX_STATUS_REG(pex_if));
|
||||
pex_status &= ~PXSR_PEX_DEV_NUM_MASK;
|
||||
pex_status |=
|
||||
(dev_num << PXSR_PEX_DEV_NUM_OFFS) & PXSR_PEX_DEV_NUM_MASK;
|
||||
reg_write(PEX_STATUS_REG(pex_if), pex_status);
|
||||
|
||||
return MV_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* pex_config_read - Read from configuration space
|
||||
*
|
||||
* DESCRIPTION:
|
||||
* This function performs a 32 bit read from PEX configuration space.
|
||||
* It supports both type 0 and type 1 of Configuration Transactions
|
||||
* (local and over bridge). In order to read from local bus segment, use
|
||||
* bus number retrieved from pex_local_bus_num_get(). Other bus numbers
|
||||
* will result configuration transaction of type 1 (over bridge).
|
||||
*
|
||||
* INPUT:
|
||||
* pex_if - PEX interface number.
|
||||
* bus - PEX segment bus number.
|
||||
* dev - PEX device number.
|
||||
* func - Function number.
|
||||
* reg_offs - Register offset.
|
||||
*
|
||||
* OUTPUT:
|
||||
* None.
|
||||
*
|
||||
* RETURN:
|
||||
* 32bit register data, 0xffffffff on error
|
||||
*/
|
||||
u32 pex_config_read(u32 pex_if, u32 bus, u32 dev, u32 func, u32 reg_off)
|
||||
{
|
||||
u32 pex_data = 0;
|
||||
u32 local_dev, local_bus;
|
||||
u32 pex_status;
|
||||
|
||||
pex_status = reg_read(PEX_STATUS_REG(pex_if));
|
||||
local_dev =
|
||||
((pex_status & PXSR_PEX_DEV_NUM_MASK) >> PXSR_PEX_DEV_NUM_OFFS);
|
||||
local_bus =
|
||||
((pex_status & PXSR_PEX_BUS_NUM_MASK) >> PXSR_PEX_BUS_NUM_OFFS);
|
||||
|
||||
/*
|
||||
* In PCI Express we have only one device number
|
||||
* and this number is the first number we encounter
|
||||
* else that the local_dev
|
||||
* spec pex define return on config read/write on any device
|
||||
*/
|
||||
if (bus == local_bus) {
|
||||
if (local_dev == 0) {
|
||||
/*
|
||||
* if local dev is 0 then the first number we encounter
|
||||
* after 0 is 1
|
||||
*/
|
||||
if ((dev != 1) && (dev != local_dev))
|
||||
return MV_ERROR;
|
||||
} else {
|
||||
/*
|
||||
* if local dev is not 0 then the first number we
|
||||
* encounter is 0
|
||||
*/
|
||||
if ((dev != 0) && (dev != local_dev))
|
||||
return MV_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/* Creating PEX address to be passed */
|
||||
pex_data = (bus << PXCAR_BUS_NUM_OFFS);
|
||||
pex_data |= (dev << PXCAR_DEVICE_NUM_OFFS);
|
||||
pex_data |= (func << PXCAR_FUNC_NUM_OFFS);
|
||||
/* Legacy register space */
|
||||
pex_data |= (reg_off & PXCAR_REG_NUM_MASK);
|
||||
/* Extended register space */
|
||||
pex_data |= (((reg_off & PXCAR_REAL_EXT_REG_NUM_MASK) >>
|
||||
PXCAR_REAL_EXT_REG_NUM_OFFS) << PXCAR_EXT_REG_NUM_OFFS);
|
||||
pex_data |= PXCAR_CONFIG_EN;
|
||||
|
||||
/* Write the address to the PEX configuration address register */
|
||||
reg_write(PEX_CFG_ADDR_REG(pex_if), pex_data);
|
||||
|
||||
/*
|
||||
* In order to let the PEX controller absorbed the address
|
||||
* of the read transaction we perform a validity check that
|
||||
* the address was written
|
||||
*/
|
||||
if (pex_data != reg_read(PEX_CFG_ADDR_REG(pex_if)))
|
||||
return MV_ERROR;
|
||||
|
||||
/* Cleaning Master Abort */
|
||||
reg_bit_set(PEX_CFG_DIRECT_ACCESS(pex_if, PEX_STATUS_AND_COMMAND),
|
||||
PXSAC_MABORT);
|
||||
/* Read the Data returned in the PEX Data register */
|
||||
pex_data = reg_read(PEX_CFG_DATA_REG(pex_if));
|
||||
|
||||
DEBUG_INIT_FULL_C(" --> ", pex_data, 4);
|
||||
|
||||
return pex_data;
|
||||
}
|
||||
|
||||
@@ -6,35 +6,13 @@
|
||||
#ifndef _CTRL_PEX_H
|
||||
#define _CTRL_PEX_H
|
||||
|
||||
#include <pci.h>
|
||||
#include "high_speed_env_spec.h"
|
||||
|
||||
/* Sample at Reset */
|
||||
#define MPP_SAMPLE_AT_RESET(id) (0xe4200 + (id * 4))
|
||||
/* Direct access to PEX0 Root Port's PCIe Capability structure */
|
||||
#define PEX0_RP_PCIE_CFG_OFFSET (0x00080000 + 0x60)
|
||||
|
||||
/* PCI Express Control and Status Registers */
|
||||
#define MAX_PEX_BUSSES 256
|
||||
|
||||
#define MISC_REGS_OFFSET 0x18200
|
||||
#define MV_MISC_REGS_BASE MISC_REGS_OFFSET
|
||||
#define SOC_CTRL_REG (MV_MISC_REGS_BASE + 0x4)
|
||||
|
||||
#define PEX_IF_REGS_OFFSET(if) ((if) > 0 ? \
|
||||
(0x40000 + ((if) - 1) * 0x4000) : \
|
||||
0x80000)
|
||||
#define PEX_IF_REGS_BASE(if) (PEX_IF_REGS_OFFSET(if))
|
||||
#define PEX_CAPABILITIES_REG(if) ((PEX_IF_REGS_BASE(if)) + 0x60)
|
||||
#define PEX_LINK_CTRL_STATUS2_REG(if) ((PEX_IF_REGS_BASE(if)) + 0x90)
|
||||
#define PEX_CTRL_REG(if) ((PEX_IF_REGS_BASE(if)) + 0x1a00)
|
||||
#define PEX_STATUS_REG(if) ((PEX_IF_REGS_BASE(if)) + 0x1a04)
|
||||
#define PEX_DBG_STATUS_REG(if) ((PEX_IF_REGS_BASE(if)) + 0x1a64)
|
||||
#define PEX_LINK_CAPABILITY_REG 0x6c
|
||||
#define PEX_LINK_CTRL_STAT_REG 0x70
|
||||
#define PXSR_PEX_DEV_NUM_OFFS 16 /* Device Number Indication */
|
||||
#define PXSR_PEX_DEV_NUM_MASK (0x1f << PXSR_PEX_DEV_NUM_OFFS)
|
||||
#define PXSR_PEX_BUS_NUM_OFFS 8 /* Bus Number Indication */
|
||||
#define PXSR_PEX_BUS_NUM_MASK (0xff << PXSR_PEX_BUS_NUM_OFFS)
|
||||
|
||||
/* PEX_CAPABILITIES_REG fields */
|
||||
/* SOC_CONTROL_REG1 fields */
|
||||
#define PCIE0_ENABLE_OFFS 0
|
||||
#define PCIE0_ENABLE_MASK (0x1 << PCIE0_ENABLE_OFFS)
|
||||
#define PCIE1_ENABLE_OFFS 1
|
||||
@@ -44,45 +22,7 @@
|
||||
#define PCIE3_ENABLE_OFFS 3
|
||||
#define PCIE4_ENABLE_MASK (0x1 << PCIE3_ENABLE_OFFS)
|
||||
|
||||
/* Controller revision info */
|
||||
#define PEX_DEVICE_AND_VENDOR_ID 0x000
|
||||
#define PEX_CFG_DIRECT_ACCESS(if, reg) (PEX_IF_REGS_BASE(if) + (reg))
|
||||
|
||||
/* PCI Express Configuration Address Register */
|
||||
#define PXCAR_REG_NUM_OFFS 2
|
||||
#define PXCAR_REG_NUM_MAX 0x3f
|
||||
#define PXCAR_REG_NUM_MASK (PXCAR_REG_NUM_MAX << \
|
||||
PXCAR_REG_NUM_OFFS)
|
||||
#define PXCAR_FUNC_NUM_OFFS 8
|
||||
#define PXCAR_FUNC_NUM_MAX 0x7
|
||||
#define PXCAR_FUNC_NUM_MASK (PXCAR_FUNC_NUM_MAX << \
|
||||
PXCAR_FUNC_NUM_OFFS)
|
||||
#define PXCAR_DEVICE_NUM_OFFS 11
|
||||
#define PXCAR_DEVICE_NUM_MAX 0x1f
|
||||
#define PXCAR_DEVICE_NUM_MASK (PXCAR_DEVICE_NUM_MAX << \
|
||||
PXCAR_DEVICE_NUM_OFFS)
|
||||
#define PXCAR_BUS_NUM_OFFS 16
|
||||
#define PXCAR_BUS_NUM_MAX 0xff
|
||||
#define PXCAR_BUS_NUM_MASK (PXCAR_BUS_NUM_MAX << \
|
||||
PXCAR_BUS_NUM_OFFS)
|
||||
#define PXCAR_EXT_REG_NUM_OFFS 24
|
||||
#define PXCAR_EXT_REG_NUM_MAX 0xf
|
||||
|
||||
#define PEX_CFG_ADDR_REG(if) ((PEX_IF_REGS_BASE(if)) + 0x18f8)
|
||||
#define PEX_CFG_DATA_REG(if) ((PEX_IF_REGS_BASE(if)) + 0x18fc)
|
||||
|
||||
#define PXCAR_REAL_EXT_REG_NUM_OFFS 8
|
||||
#define PXCAR_REAL_EXT_REG_NUM_MASK (0xf << PXCAR_REAL_EXT_REG_NUM_OFFS)
|
||||
|
||||
#define PXCAR_CONFIG_EN BIT(31)
|
||||
#define PEX_STATUS_AND_COMMAND 0x004
|
||||
#define PXSAC_MABORT BIT(29) /* Recieved Master Abort */
|
||||
|
||||
int hws_pex_config(const struct serdes_map *serdes_map, u8 count);
|
||||
int pex_local_bus_num_set(u32 pex_if, u32 bus_num);
|
||||
int pex_local_dev_num_set(u32 pex_if, u32 dev_num);
|
||||
u32 pex_config_read(u32 pex_if, u32 bus, u32 dev, u32 func, u32 reg_off);
|
||||
|
||||
void board_pex_config(void);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1712,7 +1712,7 @@ int serdes_power_up_ctrl(u32 serdes_num, int serdes_power_up,
|
||||
(serdes_mode == PEX_END_POINT_X1);
|
||||
pex_idx = serdes_type - PEX0;
|
||||
|
||||
if ((is_pex_by1 == 1) || (serdes_type == PEX0)) {
|
||||
if (serdes_type == PEX0) {
|
||||
/* For PEX by 4, init only the PEX 0 */
|
||||
reg_data = reg_read(SOC_CONTROL_REG1);
|
||||
if (is_pex_by1 == 1)
|
||||
@@ -1721,32 +1721,20 @@ int serdes_power_up_ctrl(u32 serdes_num, int serdes_power_up,
|
||||
reg_data &= ~0x4000;
|
||||
reg_write(SOC_CONTROL_REG1, reg_data);
|
||||
|
||||
reg_data =
|
||||
reg_read(((PEX_IF_REGS_BASE(pex_idx)) +
|
||||
0x6c));
|
||||
reg_data &= ~0x3f0;
|
||||
if (is_pex_by1 == 1)
|
||||
reg_data |= 0x10;
|
||||
else
|
||||
reg_data |= 0x40;
|
||||
reg_write(((PEX_IF_REGS_BASE(pex_idx)) + 0x6c),
|
||||
reg_data);
|
||||
|
||||
reg_data =
|
||||
reg_read(((PEX_IF_REGS_BASE(pex_idx)) +
|
||||
0x6c));
|
||||
reg_data &= ~0xf;
|
||||
reg_data |= 0x2;
|
||||
reg_write(((PEX_IF_REGS_BASE(pex_idx)) + 0x6c),
|
||||
reg_data);
|
||||
|
||||
reg_data =
|
||||
reg_read(((PEX_IF_REGS_BASE(pex_idx)) +
|
||||
0x70));
|
||||
reg_data &= ~0x40;
|
||||
reg_data |= 0x40;
|
||||
reg_write(((PEX_IF_REGS_BASE(pex_idx)) + 0x70),
|
||||
reg_data);
|
||||
/*
|
||||
* Set Maximum Link Width to X1 or X4 in Root
|
||||
* Port's PCIe Link Capability register.
|
||||
* This register is read-only but if is not set
|
||||
* correctly then access to PCI config space of
|
||||
* endpoint card behind this Root Port does not
|
||||
* work.
|
||||
*/
|
||||
reg_data = reg_read(PEX0_RP_PCIE_CFG_OFFSET +
|
||||
PCI_EXP_LNKCAP);
|
||||
reg_data &= ~PCI_EXP_LNKCAP_MLW;
|
||||
reg_data |= (is_pex_by1 ? 1 : 4) << 4;
|
||||
reg_write(PEX0_RP_PCIE_CFG_OFFSET +
|
||||
PCI_EXP_LNKCAP, reg_data);
|
||||
}
|
||||
|
||||
CHECK_STATUS(mv_seq_exec(serdes_num, PEX_POWER_UP_SEQ));
|
||||
|
||||
@@ -35,17 +35,6 @@ DECLARE_GLOBAL_DATA_PTR;
|
||||
#define I2C_IO_REG_CL ((1 << I2C_IO_REG_0_USB_H0_CL) | \
|
||||
(1 << I2C_IO_REG_0_USB_H1_CL))
|
||||
|
||||
/*
|
||||
* Information specific to the iEi Puzzle-M801 board.
|
||||
*/
|
||||
|
||||
/* Internal configuration registers */
|
||||
#define CP1_CONF_REG_BASE 0xf4440000
|
||||
#define CONF_REG_MPP0 0x0
|
||||
#define CONF_REG_MPP1 0x4
|
||||
#define CONF_REG_MPP2 0x8
|
||||
#define CONF_REG_MPP3 0xC
|
||||
|
||||
static int usb_enabled = 0;
|
||||
|
||||
/* Board specific xHCI dis-/enable code */
|
||||
@@ -153,14 +142,7 @@ int board_xhci_enable(fdt_addr_t base)
|
||||
|
||||
int board_early_init_f(void)
|
||||
{
|
||||
/* Initialize some platform specific memory locations */
|
||||
if (of_machine_is_compatible("marvell,armada8040-puzzle-m801")) {
|
||||
/* MPP setup */
|
||||
writel(0x00444444, CP1_CONF_REG_BASE + CONF_REG_MPP0);
|
||||
writel(0x00000000, CP1_CONF_REG_BASE + CONF_REG_MPP1);
|
||||
writel(0x00000000, CP1_CONF_REG_BASE + CONF_REG_MPP2);
|
||||
writel(0x08888000, CP1_CONF_REG_BASE + CONF_REG_MPP3);
|
||||
}
|
||||
/* Nothing to do yet */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
#
|
||||
# Copyright (C) 2017 Allied Telesis Labs
|
||||
#
|
||||
|
||||
# Armada XP uses version 1 image format
|
||||
VERSION 1
|
||||
|
||||
# Boot Media configurations
|
||||
BOOT_FROM spi
|
||||
|
||||
# Binary Header (bin_hdr) with DDR3 training code
|
||||
BINARY spl/u-boot-spl-dtb.bin 0000005b 00000068
|
||||
@@ -39,6 +39,9 @@
|
||||
#define PCIE_CORE_CMD_IO_ACCESS_EN BIT(0)
|
||||
#define PCIE_CORE_CMD_MEM_ACCESS_EN BIT(1)
|
||||
#define PCIE_CORE_CMD_MEM_IO_REQ_EN BIT(2)
|
||||
#define PCIE_CORE_DEV_REV_REG 0x8
|
||||
#define PCIE_CORE_EXP_ROM_BAR_REG 0x30
|
||||
#define PCIE_CORE_PCIEXP_CAP_OFF 0xc0
|
||||
#define PCIE_CORE_DEV_CTRL_STATS_REG 0xc8
|
||||
#define PCIE_CORE_DEV_CTRL_STATS_RELAX_ORDER_DISABLE (0 << 4)
|
||||
#define PCIE_CORE_DEV_CTRL_STATS_SNOOP_DISABLE (0 << 11)
|
||||
@@ -145,6 +148,7 @@
|
||||
#define LTSSM_SHIFT 24
|
||||
#define LTSSM_MASK 0x3f
|
||||
#define LTSSM_L0 0x10
|
||||
#define LTSSM_DISABLED 0x20
|
||||
#define VENDOR_ID_REG (LMI_BASE_ADDR + 0x44)
|
||||
|
||||
/* PCIe core controller registers */
|
||||
@@ -162,7 +166,7 @@
|
||||
#define PCIE_CONFIG_WR_TYPE1 0xb
|
||||
|
||||
/* PCI_BDF shifts 8bit, so we need extra 4bit shift */
|
||||
#define PCIE_BDF(dev) (dev << 4)
|
||||
#define PCIE_BDF(b, d, f) (PCI_BDF(b, d, f) << 4)
|
||||
#define PCIE_CONF_BUS(bus) (((bus) & 0xff) << 20)
|
||||
#define PCIE_CONF_DEV(dev) (((dev) & 0x1f) << 15)
|
||||
#define PCIE_CONF_FUNC(fun) (((fun) & 0x7) << 12)
|
||||
@@ -182,18 +186,24 @@
|
||||
/**
|
||||
* struct pcie_advk - Advk PCIe controller state
|
||||
*
|
||||
* @reg_base: The base address of the register space.
|
||||
* @first_busno: This driver supports multiple PCIe controllers.
|
||||
* first_busno stores the bus number of the PCIe root-port
|
||||
* number which may vary depending on the PCIe setup
|
||||
* (PEX switches etc).
|
||||
* @device: The pointer to PCI uclass device.
|
||||
* @base: The base address of the register space.
|
||||
* @first_busno: Bus number of the PCIe root-port.
|
||||
* This may vary depending on the PCIe setup.
|
||||
* @sec_busno: Bus number for the device behind the PCIe root-port.
|
||||
* @dev: The pointer to PCI uclass device.
|
||||
* @reset_gpio: GPIO descriptor for PERST.
|
||||
* @cfgcache: Buffer for emulation of PCIe Root Port's PCI Bridge registers
|
||||
* that are not available on Aardvark.
|
||||
* @cfgcrssve: For CRSSVE emulation.
|
||||
*/
|
||||
struct pcie_advk {
|
||||
void *base;
|
||||
int first_busno;
|
||||
struct udevice *dev;
|
||||
struct gpio_desc reset_gpio;
|
||||
void *base;
|
||||
int first_busno;
|
||||
int sec_busno;
|
||||
struct udevice *dev;
|
||||
struct gpio_desc reset_gpio;
|
||||
u32 cfgcache[0x34 - 0x10];
|
||||
bool cfgcrssve;
|
||||
};
|
||||
|
||||
static inline void advk_writel(struct pcie_advk *pcie, uint val, uint reg)
|
||||
@@ -209,22 +219,30 @@ static inline uint advk_readl(struct pcie_advk *pcie, uint reg)
|
||||
/**
|
||||
* pcie_advk_addr_valid() - Check for valid bus address
|
||||
*
|
||||
* @pcie: Pointer to the PCI bus
|
||||
* @busno: Bus number of PCI device
|
||||
* @dev: Device number of PCI device
|
||||
* @func: Function number of PCI device
|
||||
* @bdf: The PCI device to access
|
||||
* @first_busno: Bus number of the PCIe controller root complex
|
||||
*
|
||||
* Return: 1 on valid, 0 on invalid
|
||||
* Return: true on valid, false on invalid
|
||||
*/
|
||||
static int pcie_advk_addr_valid(pci_dev_t bdf, int first_busno)
|
||||
static bool pcie_advk_addr_valid(struct pcie_advk *pcie,
|
||||
int busno, u8 dev, u8 func)
|
||||
{
|
||||
/*
|
||||
* In PCIE-E only a single device (0) can exist
|
||||
* on the local bus. Beyound the local bus, there might be
|
||||
* a Switch and everything is possible.
|
||||
*/
|
||||
if ((PCI_BUS(bdf) == first_busno) && (PCI_DEV(bdf) > 0))
|
||||
return 0;
|
||||
/* On the primary (local) bus there is only one PCI Bridge */
|
||||
if (busno == pcie->first_busno && (dev != 0 || func != 0))
|
||||
return false;
|
||||
|
||||
return 1;
|
||||
/*
|
||||
* In PCI-E only a single device (0) can exist on the secondary bus.
|
||||
* Beyond the secondary bus, there might be a Switch and anything is
|
||||
* possible.
|
||||
*/
|
||||
if (busno == pcie->sec_busno && dev != 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -354,32 +372,80 @@ static int pcie_advk_read_config(const struct udevice *bus, pci_dev_t bdf,
|
||||
enum pci_size_t size)
|
||||
{
|
||||
struct pcie_advk *pcie = dev_get_priv(bus);
|
||||
int busno = PCI_BUS(bdf) - dev_seq(bus);
|
||||
int retry_count;
|
||||
bool allow_crs;
|
||||
ulong data;
|
||||
uint reg;
|
||||
int ret;
|
||||
|
||||
dev_dbg(pcie->dev, "PCIE CFG read: (b,d,f)=(%2d,%2d,%2d) ",
|
||||
PCI_BUS(bdf), PCI_DEV(bdf), PCI_FUNC(bdf));
|
||||
|
||||
if (!pcie_advk_addr_valid(bdf, pcie->first_busno)) {
|
||||
if (!pcie_advk_addr_valid(pcie, busno, PCI_DEV(bdf), PCI_FUNC(bdf))) {
|
||||
dev_dbg(pcie->dev, "- out of range\n");
|
||||
*valuep = pci_get_ff(size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* The configuration space of the PCI Bridge on primary (local) bus is
|
||||
* not accessible via PIO transfers like all other PCIe devices. PCI
|
||||
* Bridge config registers are available directly in Aardvark memory
|
||||
* space starting at offset zero. Moreover PCI Bridge registers in the
|
||||
* range 0x10 - 0x34 are not available and register 0x38 (Expansion ROM
|
||||
* Base Address) is at offset 0x30.
|
||||
* We therefore read configuration space content of the primary PCI
|
||||
* Bridge from our virtual cache.
|
||||
*/
|
||||
if (busno == pcie->first_busno) {
|
||||
if (offset >= 0x10 && offset < 0x34)
|
||||
data = pcie->cfgcache[(offset - 0x10) / 4];
|
||||
else if ((offset & ~3) == PCI_ROM_ADDRESS1)
|
||||
data = advk_readl(pcie, PCIE_CORE_EXP_ROM_BAR_REG);
|
||||
else
|
||||
data = advk_readl(pcie, offset & ~3);
|
||||
|
||||
if ((offset & ~3) == (PCI_HEADER_TYPE & ~3)) {
|
||||
/*
|
||||
* Change Header Type of PCI Bridge device to Type 1
|
||||
* (0x01, used by PCI Bridges) because hardwired value
|
||||
* is Type 0 (0x00, used by Endpoint devices).
|
||||
*/
|
||||
data &= ~0x007f0000;
|
||||
data |= PCI_HEADER_TYPE_BRIDGE << 16;
|
||||
}
|
||||
|
||||
if ((offset & ~3) == PCIE_CORE_PCIEXP_CAP_OFF + PCI_EXP_RTCTL) {
|
||||
/* CRSSVE bit is stored only in cache */
|
||||
if (pcie->cfgcrssve)
|
||||
data |= PCI_EXP_RTCTL_CRSSVE;
|
||||
}
|
||||
|
||||
if ((offset & ~3) == PCIE_CORE_PCIEXP_CAP_OFF +
|
||||
(PCI_EXP_RTCAP & ~3)) {
|
||||
/* CRS is emulated below, so set CRSVIS capability */
|
||||
data |= PCI_EXP_RTCAP_CRSVIS << 16;
|
||||
}
|
||||
|
||||
*valuep = pci_conv_32_to_size(data, offset, size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returning fabricated CRS value (0xFFFF0001) by PCIe Root Complex to
|
||||
* OS is allowed only for 4-byte PCI_VENDOR_ID config read request and
|
||||
* only when CRSSVE bit in Root Port PCIe device is enabled. In all
|
||||
* other error PCIe Root Complex must return all-ones.
|
||||
* Aardvark HW does not have Root Port PCIe device and U-Boot does not
|
||||
* implement emulation of this device.
|
||||
*
|
||||
* U-Boot currently does not support handling of CRS return value for
|
||||
* PCI_VENDOR_ID config read request and also does not set CRSSVE bit.
|
||||
* Therefore disable returning CRS response for now.
|
||||
* So it means that pcie->cfgcrssve is false. But the code is prepared
|
||||
* for returning CRS, so that if U-Boot does support CRS in the future,
|
||||
* it will work for Aardvark.
|
||||
*/
|
||||
allow_crs = false;
|
||||
allow_crs = pcie->cfgcrssve;
|
||||
|
||||
if (advk_readl(pcie, PIO_START)) {
|
||||
dev_err(pcie->dev,
|
||||
@@ -395,14 +461,14 @@ static int pcie_advk_read_config(const struct udevice *bus, pci_dev_t bdf,
|
||||
/* Program the control register */
|
||||
reg = advk_readl(pcie, PIO_CTRL);
|
||||
reg &= ~PIO_CTRL_TYPE_MASK;
|
||||
if (PCI_BUS(bdf) == pcie->first_busno)
|
||||
if (busno == pcie->sec_busno)
|
||||
reg |= PCIE_CONFIG_RD_TYPE0;
|
||||
else
|
||||
reg |= PCIE_CONFIG_RD_TYPE1;
|
||||
advk_writel(pcie, reg, PIO_CTRL);
|
||||
|
||||
/* Program the address registers */
|
||||
reg = PCIE_BDF(bdf) | PCIE_CONF_REG(offset);
|
||||
reg = PCIE_BDF(busno, PCI_DEV(bdf), PCI_FUNC(bdf)) | PCIE_CONF_REG(offset);
|
||||
advk_writel(pcie, reg, PIO_ADDR_LS);
|
||||
advk_writel(pcie, 0, PIO_ADDR_MS);
|
||||
|
||||
@@ -490,7 +556,9 @@ static int pcie_advk_write_config(struct udevice *bus, pci_dev_t bdf,
|
||||
enum pci_size_t size)
|
||||
{
|
||||
struct pcie_advk *pcie = dev_get_priv(bus);
|
||||
int busno = PCI_BUS(bdf) - dev_seq(bus);
|
||||
int retry_count;
|
||||
ulong data;
|
||||
uint reg;
|
||||
int ret;
|
||||
|
||||
@@ -499,11 +567,44 @@ static int pcie_advk_write_config(struct udevice *bus, pci_dev_t bdf,
|
||||
dev_dbg(pcie->dev, "(addr,size,val)=(0x%04x, %d, 0x%08lx)\n",
|
||||
offset, size, value);
|
||||
|
||||
if (!pcie_advk_addr_valid(bdf, pcie->first_busno)) {
|
||||
if (!pcie_advk_addr_valid(pcie, busno, PCI_DEV(bdf), PCI_FUNC(bdf))) {
|
||||
dev_dbg(pcie->dev, "- out of range\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* As explained in pcie_advk_read_config(), for the configuration
|
||||
* space of the primary PCI Bridge, we write the content into virtual
|
||||
* cache.
|
||||
*/
|
||||
if (busno == pcie->first_busno) {
|
||||
if (offset >= 0x10 && offset < 0x34) {
|
||||
data = pcie->cfgcache[(offset - 0x10) / 4];
|
||||
data = pci_conv_size_to_32(data, value, offset, size);
|
||||
pcie->cfgcache[(offset - 0x10) / 4] = data;
|
||||
} else if ((offset & ~3) == PCI_ROM_ADDRESS1) {
|
||||
data = advk_readl(pcie, PCIE_CORE_EXP_ROM_BAR_REG);
|
||||
data = pci_conv_size_to_32(data, value, offset, size);
|
||||
advk_writel(pcie, data, PCIE_CORE_EXP_ROM_BAR_REG);
|
||||
} else {
|
||||
data = advk_readl(pcie, offset & ~3);
|
||||
data = pci_conv_size_to_32(data, value, offset, size);
|
||||
advk_writel(pcie, data, offset & ~3);
|
||||
}
|
||||
|
||||
if (offset == PCI_PRIMARY_BUS)
|
||||
pcie->first_busno = data & 0xff;
|
||||
|
||||
if (offset == PCI_SECONDARY_BUS ||
|
||||
(offset == PCI_PRIMARY_BUS && size != PCI_SIZE_8))
|
||||
pcie->sec_busno = (data >> 8) & 0xff;
|
||||
|
||||
if ((offset & ~3) == PCIE_CORE_PCIEXP_CAP_OFF + PCI_EXP_RTCTL)
|
||||
pcie->cfgcrssve = data & PCI_EXP_RTCTL_CRSSVE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (advk_readl(pcie, PIO_START)) {
|
||||
dev_err(pcie->dev,
|
||||
"Previous PIO read/write transfer is still running\n");
|
||||
@@ -513,14 +614,14 @@ static int pcie_advk_write_config(struct udevice *bus, pci_dev_t bdf,
|
||||
/* Program the control register */
|
||||
reg = advk_readl(pcie, PIO_CTRL);
|
||||
reg &= ~PIO_CTRL_TYPE_MASK;
|
||||
if (PCI_BUS(bdf) == pcie->first_busno)
|
||||
if (busno == pcie->sec_busno)
|
||||
reg |= PCIE_CONFIG_WR_TYPE0;
|
||||
else
|
||||
reg |= PCIE_CONFIG_WR_TYPE1;
|
||||
advk_writel(pcie, reg, PIO_CTRL);
|
||||
|
||||
/* Program the address registers */
|
||||
reg = PCIE_BDF(bdf) | PCIE_CONF_REG(offset);
|
||||
reg = PCIE_BDF(busno, PCI_DEV(bdf), PCI_FUNC(bdf)) | PCIE_CONF_REG(offset);
|
||||
advk_writel(pcie, reg, PIO_ADDR_LS);
|
||||
advk_writel(pcie, 0, PIO_ADDR_MS);
|
||||
dev_dbg(pcie->dev, "\tPIO req. - addr = 0x%08x\n", reg);
|
||||
@@ -569,7 +670,7 @@ static int pcie_advk_link_up(struct pcie_advk *pcie)
|
||||
|
||||
val = advk_readl(pcie, CFG_REG);
|
||||
ltssm_state = (val >> LTSSM_SHIFT) & LTSSM_MASK;
|
||||
return ltssm_state >= LTSSM_L0;
|
||||
return ltssm_state >= LTSSM_L0 && ltssm_state < LTSSM_DISABLED;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -589,14 +690,14 @@ static int pcie_advk_wait_for_link(struct pcie_advk *pcie)
|
||||
/* check if the link is up or not */
|
||||
for (retries = 0; retries < LINK_MAX_RETRIES; retries++) {
|
||||
if (pcie_advk_link_up(pcie)) {
|
||||
printf("PCIE-%d: Link up\n", pcie->first_busno);
|
||||
printf("PCIe: Link up\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
udelay(LINK_WAIT_TIMEOUT);
|
||||
}
|
||||
|
||||
printf("PCIE-%d: Link down\n", pcie->first_busno);
|
||||
printf("PCIe: Link down\n");
|
||||
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
@@ -715,6 +816,25 @@ static int pcie_advk_setup_hw(struct pcie_advk *pcie)
|
||||
*/
|
||||
advk_writel(pcie, 0x11ab11ab, VENDOR_ID_REG);
|
||||
|
||||
/*
|
||||
* Change Class Code of PCI Bridge device to PCI Bridge (0x600400),
|
||||
* because default value is Mass Storage Controller (0x010400), causing
|
||||
* U-Boot to fail to recognize it as P2P Bridge.
|
||||
*
|
||||
* Note that this Aardvark PCI Bridge does not have a compliant Type 1
|
||||
* Configuration Space and it even cannot be accessed via Aardvark's
|
||||
* PCI config space access method. Something like config space is
|
||||
* available in internal Aardvark registers starting at offset 0x0
|
||||
* and is reported as Type 0. In range 0x10 - 0x34 it has totally
|
||||
* different registers. So our driver reports Header Type as Type 1 and
|
||||
* for the above mentioned range redirects access to the virtual
|
||||
* cfgcache[] buffer, which avoids changing internal Aardvark registers.
|
||||
*/
|
||||
reg = advk_readl(pcie, PCIE_CORE_DEV_REV_REG);
|
||||
reg &= ~0xffffff00;
|
||||
reg |= (PCI_CLASS_BRIDGE_PCI << 8) << 8;
|
||||
advk_writel(pcie, reg, PCIE_CORE_DEV_REV_REG);
|
||||
|
||||
/* Set Advanced Error Capabilities and Control PF0 register */
|
||||
reg = PCIE_CORE_ERR_CAPCTL_ECRC_CHK_TX |
|
||||
PCIE_CORE_ERR_CAPCTL_ECRC_CHK_TX_EN |
|
||||
@@ -809,12 +929,6 @@ static int pcie_advk_setup_hw(struct pcie_advk *pcie)
|
||||
if (pcie_advk_wait_for_link(pcie))
|
||||
return -ENXIO;
|
||||
|
||||
reg = advk_readl(pcie, PCIE_CORE_CMD_STATUS_REG);
|
||||
reg |= PCIE_CORE_CMD_MEM_ACCESS_EN |
|
||||
PCIE_CORE_CMD_IO_ACCESS_EN |
|
||||
PCIE_CORE_CMD_MEM_IO_REQ_EN;
|
||||
advk_writel(pcie, reg, PCIE_CORE_CMD_STATUS_REG);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -856,9 +970,14 @@ static int pcie_advk_probe(struct udevice *dev)
|
||||
dev_warn(dev, "PCIE Reset on GPIO support is missing\n");
|
||||
}
|
||||
|
||||
pcie->first_busno = dev_seq(dev);
|
||||
pcie->dev = pci_get_controller(dev);
|
||||
|
||||
/* PCI Bridge support 32-bit I/O and 64-bit prefetch mem addressing */
|
||||
pcie->cfgcache[(PCI_IO_BASE - 0x10) / 4] =
|
||||
PCI_IO_RANGE_TYPE_32 | (PCI_IO_RANGE_TYPE_32 << 8);
|
||||
pcie->cfgcache[(PCI_PREF_MEMORY_BASE - 0x10) / 4] =
|
||||
PCI_PREF_RANGE_TYPE_64 | (PCI_PREF_RANGE_TYPE_64 << 16);
|
||||
|
||||
return pcie_advk_setup_hw(pcie);
|
||||
}
|
||||
|
||||
|
||||
@@ -200,7 +200,7 @@ static int comphy_pcie_power_up(u32 speed, u32 invert)
|
||||
* 6. Enable the output of 100M/125M/500M clock
|
||||
*/
|
||||
reg_set16(phy_addr(PCIE, MISC_REG0),
|
||||
0xA00D | rb_clk500m_en | rb_clk100m_125m_en, 0xFFFF);
|
||||
0xA00D | rb_clk500m_en | rb_txdclk_2x_sel | rb_clk100m_125m_en, 0xFFFF);
|
||||
|
||||
/*
|
||||
* 7. Enable TX
|
||||
@@ -230,9 +230,13 @@ static int comphy_pcie_power_up(u32 speed, u32 invert)
|
||||
*/
|
||||
if (invert & COMPHY_POLARITY_TXD_INVERT)
|
||||
reg_set16(phy_addr(PCIE, SYNC_PATTERN), phy_txd_inv, 0);
|
||||
else
|
||||
reg_set16(phy_addr(PCIE, SYNC_PATTERN), 0, phy_txd_inv);
|
||||
|
||||
if (invert & COMPHY_POLARITY_RXD_INVERT)
|
||||
reg_set16(phy_addr(PCIE, SYNC_PATTERN), phy_rxd_inv, 0);
|
||||
else
|
||||
reg_set16(phy_addr(PCIE, SYNC_PATTERN), 0, phy_rxd_inv);
|
||||
|
||||
/*
|
||||
* 11. Release SW reset
|
||||
@@ -467,9 +471,13 @@ static int comphy_usb3_power_up(u32 lane, u32 type, u32 speed, u32 invert)
|
||||
*/
|
||||
if (invert & COMPHY_POLARITY_TXD_INVERT)
|
||||
usb3_reg_set16(SYNC_PATTERN, phy_txd_inv, 0, lane);
|
||||
else
|
||||
usb3_reg_set16(SYNC_PATTERN, 0, phy_txd_inv, lane);
|
||||
|
||||
if (invert & COMPHY_POLARITY_RXD_INVERT)
|
||||
usb3_reg_set16(SYNC_PATTERN, phy_rxd_inv, 0, lane);
|
||||
else
|
||||
usb3_reg_set16(SYNC_PATTERN, 0, phy_rxd_inv, lane);
|
||||
|
||||
/*
|
||||
* 10. Set max speed generation to USB3.0 5Gbps
|
||||
@@ -586,24 +594,30 @@ static int comphy_usb2_power_up(u8 usb32)
|
||||
rb_usb2phy_pllcal_done, /* value */
|
||||
rb_usb2phy_pllcal_done, /* mask */
|
||||
POLL_32B_REG); /* 32bit */
|
||||
if (!ret)
|
||||
if (!ret) {
|
||||
printf("Failed to end USB2 PLL calibration\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Assert impedance calibration done */
|
||||
ret = comphy_poll_reg(USB2_PHY_CAL_CTRL_ADDR(usb32),
|
||||
rb_usb2phy_impcal_done, /* value */
|
||||
rb_usb2phy_impcal_done, /* mask */
|
||||
POLL_32B_REG); /* 32bit */
|
||||
if (!ret)
|
||||
if (!ret) {
|
||||
printf("Failed to end USB2 impedance calibration\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Assert squetch calibration done */
|
||||
ret = comphy_poll_reg(USB2_PHY_RX_CHAN_CTRL1_ADDR(usb32),
|
||||
rb_usb2phy_sqcal_done, /* value */
|
||||
rb_usb2phy_sqcal_done, /* mask */
|
||||
POLL_32B_REG); /* 32bit */
|
||||
if (!ret)
|
||||
if (!ret) {
|
||||
printf("Failed to end USB2 unknown calibration\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Assert PLL is ready */
|
||||
ret = comphy_poll_reg(USB2_PHY_PLL_CTRL0_ADDR(usb32),
|
||||
@@ -611,9 +625,12 @@ static int comphy_usb2_power_up(u8 usb32)
|
||||
rb_usb2phy_pll_ready, /* mask */
|
||||
POLL_32B_REG); /* 32bit */
|
||||
|
||||
if (!ret)
|
||||
if (!ret) {
|
||||
printf("Failed to lock USB2 PLL\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
debug_exit();
|
||||
|
||||
return ret;
|
||||
@@ -839,9 +856,13 @@ static int comphy_sgmii_power_up(u32 lane, u32 speed, u32 invert)
|
||||
*/
|
||||
if (invert & COMPHY_POLARITY_TXD_INVERT)
|
||||
reg_set16(sgmiiphy_addr(lane, SYNC_PATTERN), phy_txd_inv, 0);
|
||||
else
|
||||
reg_set16(sgmiiphy_addr(lane, SYNC_PATTERN), 0, phy_txd_inv);
|
||||
|
||||
if (invert & COMPHY_POLARITY_RXD_INVERT)
|
||||
reg_set16(sgmiiphy_addr(lane, SYNC_PATTERN), phy_rxd_inv, 0);
|
||||
else
|
||||
reg_set16(sgmiiphy_addr(lane, SYNC_PATTERN), 0, phy_rxd_inv);
|
||||
|
||||
/*
|
||||
* 19. Set PHY input ports PIN_PU_PLL, PIN_PU_TX and PIN_PU_RX to 1
|
||||
@@ -861,8 +882,10 @@ static int comphy_sgmii_power_up(u32 lane, u32 speed, u32 invert)
|
||||
rb_pll_ready_tx | rb_pll_ready_rx, /* value */
|
||||
rb_pll_ready_tx | rb_pll_ready_rx, /* mask */
|
||||
POLL_32B_REG); /* 32bit */
|
||||
if (!ret)
|
||||
if (!ret) {
|
||||
printf("Failed to lock PLL for SGMII PHY %d\n", lane);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* 21. Set COMPHY input port PIN_TX_IDLE=0
|
||||
@@ -883,14 +906,17 @@ static int comphy_sgmii_power_up(u32 lane, u32 speed, u32 invert)
|
||||
rb_rx_init_done, /* value */
|
||||
rb_rx_init_done, /* mask */
|
||||
POLL_32B_REG); /* 32bit */
|
||||
if (!ret)
|
||||
if (!ret) {
|
||||
printf("Failed to init RX of SGMII PHY %d\n", lane);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Restore saved selector.
|
||||
*/
|
||||
reg_set(COMPHY_SEL_ADDR, saved_selector, 0xFFFFFFFF);
|
||||
|
||||
out:
|
||||
debug_exit();
|
||||
|
||||
return ret;
|
||||
|
||||
@@ -120,6 +120,7 @@ static inline void __iomem *phy_addr(enum phy_unit unit, u32 addr)
|
||||
|
||||
#define MISC_REG0 0x4f
|
||||
#define rb_clk100m_125m_en BIT(4)
|
||||
#define rb_txdclk_2x_sel BIT(6)
|
||||
#define rb_clk500m_en BIT(7)
|
||||
#define rb_ref_clk_sel BIT(10)
|
||||
|
||||
|
||||
@@ -495,6 +495,10 @@
|
||||
#define PCI_EXP_LNKSTA_DLLLA 0x2000 /* Data Link Layer Link Active */
|
||||
#define PCI_EXP_SLTCAP 20 /* Slot Capabilities */
|
||||
#define PCI_EXP_SLTCAP_PSN 0xfff80000 /* Physical Slot Number */
|
||||
#define PCI_EXP_RTCTL 28 /* Root Control */
|
||||
#define PCI_EXP_RTCTL_CRSSVE 0x0010 /* CRS Software Visibility Enable */
|
||||
#define PCI_EXP_RTCAP 30 /* Root Capabilities */
|
||||
#define PCI_EXP_RTCAP_CRSVIS 0x0001 /* CRS Software Visibility capability */
|
||||
#define PCI_EXP_DEVCAP2 36 /* Device Capabilities 2 */
|
||||
#define PCI_EXP_DEVCAP2_ARI 0x00000020 /* ARI Forwarding Supported */
|
||||
#define PCI_EXP_DEVCTL2 40 /* Device Control 2 */
|
||||
|
||||
Reference in New Issue
Block a user