This patch adds a driver for the PCIe controller integrated in the Marvell Armada-8K SoC. This controller is based on the DesignWare IP core. The original version was written by Shadi and Yehuda. I ported this driver to the latest mainline U-Boot version with DM support. Tested on the Marvell DB-88F8040 Armada-8K eval board. Signed-off-by: Shadi Ammouri <shadi@marvell.com> Signed-off-by: Yehuda Yitschak <yehuday@marvell.com> Signed-off-by: Stefan Roese <sr@denx.de> Reviewed-by: Simon Glass <sjg@chromium.org> Cc: Nadav Haklai <nadavh@marvell.com> Cc: Neta Zur Hershkovits <neta@marvell.com> Cc: Kostya Porotchkin <kostap@marvell.com> Cc: Omri Itach <omrii@marvell.com> Cc: Igal Liberman <igall@marvell.com> Cc: Haim Boot <hayim@marvell.com> Cc: Hanna Hawa <hannah@marvell.com>master
parent
e8c3156e8d
commit
182ba1a7df
@ -0,0 +1,535 @@ |
||||
/*
|
||||
* Copyright (C) 2015 Marvell International Ltd. |
||||
* |
||||
* Copyright (C) 2016 Stefan Roese <sr@denx.de> |
||||
* |
||||
* Based on: |
||||
* - drivers/pci/pcie_imx.c |
||||
* - drivers/pci/pci_mvebu.c |
||||
* - drivers/pci/pcie_xilinx.c |
||||
* |
||||
* SPDX-License-Identifier: GPL-2.0+ |
||||
*/ |
||||
|
||||
#include <common.h> |
||||
#include <dm.h> |
||||
#include <pci.h> |
||||
#include <asm/io.h> |
||||
|
||||
DECLARE_GLOBAL_DATA_PTR; |
||||
|
||||
/* PCI Config space registers */ |
||||
#define PCIE_CONFIG_BAR0 0x10 |
||||
#define PCIE_LINK_STATUS_REG 0x80 |
||||
#define PCIE_LINK_STATUS_SPEED_OFF 16 |
||||
#define PCIE_LINK_STATUS_SPEED_MASK (0xf << PCIE_LINK_STATUS_SPEED_OFF) |
||||
#define PCIE_LINK_STATUS_WIDTH_OFF 20 |
||||
#define PCIE_LINK_STATUS_WIDTH_MASK (0xf << PCIE_LINK_STATUS_WIDTH_OFF) |
||||
|
||||
/* Resizable bar capability registers */ |
||||
#define RESIZABLE_BAR_CAP 0x250 |
||||
#define RESIZABLE_BAR_CTL0 0x254 |
||||
#define RESIZABLE_BAR_CTL1 0x258 |
||||
|
||||
/* iATU registers */ |
||||
#define PCIE_ATU_VIEWPORT 0x900 |
||||
#define PCIE_ATU_REGION_INBOUND (0x1 << 31) |
||||
#define PCIE_ATU_REGION_OUTBOUND (0x0 << 31) |
||||
#define PCIE_ATU_REGION_INDEX1 (0x1 << 0) |
||||
#define PCIE_ATU_REGION_INDEX0 (0x0 << 0) |
||||
#define PCIE_ATU_CR1 0x904 |
||||
#define PCIE_ATU_TYPE_MEM (0x0 << 0) |
||||
#define PCIE_ATU_TYPE_IO (0x2 << 0) |
||||
#define PCIE_ATU_TYPE_CFG0 (0x4 << 0) |
||||
#define PCIE_ATU_TYPE_CFG1 (0x5 << 0) |
||||
#define PCIE_ATU_CR2 0x908 |
||||
#define PCIE_ATU_ENABLE (0x1 << 31) |
||||
#define PCIE_ATU_BAR_MODE_ENABLE (0x1 << 30) |
||||
#define PCIE_ATU_LOWER_BASE 0x90C |
||||
#define PCIE_ATU_UPPER_BASE 0x910 |
||||
#define PCIE_ATU_LIMIT 0x914 |
||||
#define PCIE_ATU_LOWER_TARGET 0x918 |
||||
#define PCIE_ATU_BUS(x) (((x) & 0xff) << 24) |
||||
#define PCIE_ATU_DEV(x) (((x) & 0x1f) << 19) |
||||
#define PCIE_ATU_FUNC(x) (((x) & 0x7) << 16) |
||||
#define PCIE_ATU_UPPER_TARGET 0x91C |
||||
|
||||
#define PCIE_LINK_CAPABILITY 0x7C |
||||
#define PCIE_LINK_CTL_2 0xA0 |
||||
#define TARGET_LINK_SPEED_MASK 0xF |
||||
#define LINK_SPEED_GEN_1 0x1 |
||||
#define LINK_SPEED_GEN_2 0x2 |
||||
#define LINK_SPEED_GEN_3 0x3 |
||||
|
||||
#define PCIE_GEN3_RELATED 0x890 |
||||
#define GEN3_EQU_DISABLE (1 << 16) |
||||
#define GEN3_ZRXDC_NON_COMP (1 << 0) |
||||
|
||||
#define PCIE_GEN3_EQU_CTRL 0x8A8 |
||||
#define GEN3_EQU_EVAL_2MS_DISABLE (1 << 5) |
||||
|
||||
#define PCIE_ROOT_COMPLEX_MODE_MASK (0xF << 4) |
||||
|
||||
#define PCIE_LINK_UP_TIMEOUT_MS 100 |
||||
|
||||
#define PCIE_GLOBAL_CONTROL 0x8000 |
||||
#define PCIE_APP_LTSSM_EN (1 << 2) |
||||
#define PCIE_DEVICE_TYPE_OFFSET (4) |
||||
#define PCIE_DEVICE_TYPE_MASK (0xF) |
||||
#define PCIE_DEVICE_TYPE_EP (0x0) /* Endpoint */ |
||||
#define PCIE_DEVICE_TYPE_LEP (0x1) /* Legacy endpoint */ |
||||
#define PCIE_DEVICE_TYPE_RC (0x4) /* Root complex */ |
||||
|
||||
#define PCIE_GLOBAL_STATUS 0x8008 |
||||
#define PCIE_GLB_STS_RDLH_LINK_UP (1 << 1) |
||||
#define PCIE_GLB_STS_PHY_LINK_UP (1 << 9) |
||||
|
||||
#define PCIE_ARCACHE_TRC 0x8050 |
||||
#define PCIE_AWCACHE_TRC 0x8054 |
||||
#define ARCACHE_SHAREABLE_CACHEABLE 0x3511 |
||||
#define AWCACHE_SHAREABLE_CACHEABLE 0x5311 |
||||
|
||||
#define LINK_SPEED_GEN_1 0x1 |
||||
#define LINK_SPEED_GEN_2 0x2 |
||||
#define LINK_SPEED_GEN_3 0x3 |
||||
|
||||
/**
|
||||
* struct pcie_dw_mvebu - MVEBU DW PCIe controller state |
||||
* |
||||
* @ctrl_base: The base address of the register space |
||||
* @cfg_base: The base address of the configuration space |
||||
* @cfg_size: The size of the configuration space which is needed |
||||
* as it gets written into the PCIE_ATU_LIMIT register |
||||
* @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). |
||||
*/ |
||||
struct pcie_dw_mvebu { |
||||
void *ctrl_base; |
||||
void *cfg_base; |
||||
fdt_size_t cfg_size; |
||||
int first_busno; |
||||
}; |
||||
|
||||
static int pcie_dw_get_link_speed(const void *regs_base) |
||||
{ |
||||
return (readl(regs_base + PCIE_LINK_STATUS_REG) & |
||||
PCIE_LINK_STATUS_SPEED_MASK) >> PCIE_LINK_STATUS_SPEED_OFF; |
||||
} |
||||
|
||||
static int pcie_dw_get_link_width(const void *regs_base) |
||||
{ |
||||
return (readl(regs_base + PCIE_LINK_STATUS_REG) & |
||||
PCIE_LINK_STATUS_WIDTH_MASK) >> PCIE_LINK_STATUS_WIDTH_OFF; |
||||
} |
||||
|
||||
/**
|
||||
* set_cfg_address() - Configure the PCIe controller config space access |
||||
* |
||||
* @pcie: Pointer to the PCI controller state |
||||
* @d: PCI device to access |
||||
* @where: Offset in the configuration space |
||||
* |
||||
* Configures the PCIe controller to access the configuration space of |
||||
* a specific PCIe device and returns the address to use for this |
||||
* access. |
||||
* |
||||
* Return: Address that can be used to access the configation space |
||||
* of the requested device / offset |
||||
*/ |
||||
static uintptr_t set_cfg_address(struct pcie_dw_mvebu *pcie, |
||||
pci_dev_t d, uint where) |
||||
{ |
||||
uintptr_t va_address; |
||||
|
||||
/*
|
||||
* Region #0 is used for Outbound CFG space access. |
||||
* Direction = Outbound |
||||
* Region Index = 0 |
||||
*/ |
||||
writel(0, pcie->ctrl_base + PCIE_ATU_VIEWPORT); |
||||
|
||||
if (PCI_BUS(d) == (pcie->first_busno + 1)) |
||||
/* For local bus, change TLP Type field to 4. */ |
||||
writel(PCIE_ATU_TYPE_CFG0, pcie->ctrl_base + PCIE_ATU_CR1); |
||||
else |
||||
/* Otherwise, change TLP Type field to 5. */ |
||||
writel(PCIE_ATU_TYPE_CFG1, pcie->ctrl_base + PCIE_ATU_CR1); |
||||
|
||||
if (PCI_BUS(d) == pcie->first_busno) { |
||||
/* Accessing root port configuration space. */ |
||||
va_address = (uintptr_t)pcie->ctrl_base; |
||||
} else { |
||||
writel(d << 8, pcie->ctrl_base + PCIE_ATU_LOWER_TARGET); |
||||
va_address = (uintptr_t)pcie->cfg_base; |
||||
} |
||||
|
||||
va_address += where & ~0x3; |
||||
|
||||
return va_address; |
||||
} |
||||
|
||||
/**
|
||||
* pcie_dw_addr_valid() - Check for valid bus address |
||||
* |
||||
* @d: The PCI device to access |
||||
* @first_busno: Bus number of the PCIe controller root complex |
||||
* |
||||
* Return 1 (true) if the PCI device can be accessed by this controller. |
||||
* |
||||
* Return: 1 on valid, 0 on invalid |
||||
*/ |
||||
static int pcie_dw_addr_valid(pci_dev_t d, int first_busno) |
||||
{ |
||||
if ((PCI_BUS(d) == first_busno) && (PCI_DEV(d) > 0)) |
||||
return 0; |
||||
if ((PCI_BUS(d) == first_busno + 1) && (PCI_DEV(d) > 0)) |
||||
return 0; |
||||
|
||||
return 1; |
||||
} |
||||
|
||||
/**
|
||||
* pcie_dw_mvebu_read_config() - Read from configuration space |
||||
* |
||||
* @bus: Pointer to the PCI bus |
||||
* @bdf: Identifies the PCIe device to access |
||||
* @offset: The offset into the device's configuration space |
||||
* @valuep: A pointer at which to store the read value |
||||
* @size: Indicates the size of access to perform |
||||
* |
||||
* Read a value of size @size from offset @offset within the configuration |
||||
* space of the device identified by the bus, device & function numbers in @bdf |
||||
* on the PCI bus @bus. |
||||
* |
||||
* Return: 0 on success |
||||
*/ |
||||
static int pcie_dw_mvebu_read_config(struct udevice *bus, pci_dev_t bdf, |
||||
uint offset, ulong *valuep, |
||||
enum pci_size_t size) |
||||
{ |
||||
struct pcie_dw_mvebu *pcie = dev_get_priv(bus); |
||||
uintptr_t va_address; |
||||
ulong value; |
||||
|
||||
debug("PCIE CFG read: (b,d,f)=(%2d,%2d,%2d) ", |
||||
PCI_BUS(bdf), PCI_DEV(bdf), PCI_FUNC(bdf)); |
||||
|
||||
if (!pcie_dw_addr_valid(bdf, pcie->first_busno)) { |
||||
debug("- out of range\n"); |
||||
*valuep = pci_get_ff(size); |
||||
return 0; |
||||
} |
||||
|
||||
va_address = set_cfg_address(pcie, bdf, offset); |
||||
|
||||
value = readl(va_address); |
||||
|
||||
debug("(addr,val)=(0x%04x, 0x%08lx)\n", offset, value); |
||||
*valuep = pci_conv_32_to_size(value, offset, size); |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
/**
|
||||
* pcie_dw_mvebu_write_config() - Write to configuration space |
||||
* |
||||
* @bus: Pointer to the PCI bus |
||||
* @bdf: Identifies the PCIe device to access |
||||
* @offset: The offset into the device's configuration space |
||||
* @value: The value to write |
||||
* @size: Indicates the size of access to perform |
||||
* |
||||
* Write the value @value of size @size from offset @offset within the |
||||
* configuration space of the device identified by the bus, device & function |
||||
* numbers in @bdf on the PCI bus @bus. |
||||
* |
||||
* Return: 0 on success |
||||
*/ |
||||
static int pcie_dw_mvebu_write_config(struct udevice *bus, pci_dev_t bdf, |
||||
uint offset, ulong value, |
||||
enum pci_size_t size) |
||||
{ |
||||
struct pcie_dw_mvebu *pcie = dev_get_priv(bus); |
||||
uintptr_t va_address; |
||||
ulong old; |
||||
|
||||
debug("PCIE CFG write: (b,d,f)=(%2d,%2d,%2d) ", |
||||
PCI_BUS(bdf), PCI_DEV(bdf), PCI_FUNC(bdf)); |
||||
debug("(addr,val)=(0x%04x, 0x%08lx)\n", offset, value); |
||||
|
||||
if (!pcie_dw_addr_valid(bdf, pcie->first_busno)) { |
||||
debug("- out of range\n"); |
||||
return 0; |
||||
} |
||||
|
||||
va_address = set_cfg_address(pcie, bdf, offset); |
||||
|
||||
old = readl(va_address); |
||||
value = pci_conv_size_to_32(old, value, offset, size); |
||||
writel(value, va_address); |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
/**
|
||||
* pcie_dw_configure() - Configure link capabilities and speed |
||||
* |
||||
* @regs_base: A pointer to the PCIe controller registers |
||||
* @cap_speed: The capabilities and speed to configure |
||||
* |
||||
* Configure the link capabilities and speed in the PCIe root complex. |
||||
*/ |
||||
static void pcie_dw_configure(const void *regs_base, u32 cap_speed) |
||||
{ |
||||
/*
|
||||
* TODO (shadi@marvell.com, sr@denx.de): |
||||
* Need to read the serdes speed from the dts and according to it |
||||
* configure the PCIe gen |
||||
*/ |
||||
|
||||
/* Set link to GEN 3 */ |
||||
clrsetbits_le32(regs_base + PCIE_LINK_CTL_2, |
||||
TARGET_LINK_SPEED_MASK, cap_speed); |
||||
clrsetbits_le32(regs_base + PCIE_LINK_CAPABILITY, |
||||
TARGET_LINK_SPEED_MASK, cap_speed); |
||||
setbits_le32(regs_base + PCIE_GEN3_EQU_CTRL, GEN3_EQU_EVAL_2MS_DISABLE); |
||||
} |
||||
|
||||
/**
|
||||
* is_link_up() - Return the link state |
||||
* |
||||
* @regs_base: A pointer to the PCIe controller registers |
||||
* |
||||
* Return: 1 (true) for active line and 0 (false) for no link |
||||
*/ |
||||
static int is_link_up(const void *regs_base) |
||||
{ |
||||
u32 mask = PCIE_GLB_STS_RDLH_LINK_UP | PCIE_GLB_STS_PHY_LINK_UP; |
||||
u32 reg; |
||||
|
||||
reg = readl(regs_base + PCIE_GLOBAL_STATUS); |
||||
if ((reg & mask) == mask) |
||||
return 1; |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
/**
|
||||
* wait_link_up() - Wait for the link to come up |
||||
* |
||||
* @regs_base: A pointer to the PCIe controller registers |
||||
* |
||||
* Return: 1 (true) for active line and 0 (false) for no link (timeout) |
||||
*/ |
||||
static int wait_link_up(const void *regs_base) |
||||
{ |
||||
unsigned long timeout; |
||||
|
||||
timeout = get_timer(0) + PCIE_LINK_UP_TIMEOUT_MS; |
||||
while (!is_link_up(regs_base)) { |
||||
if (get_timer(0) > timeout) |
||||
return 0; |
||||
}; |
||||
|
||||
return 1; |
||||
} |
||||
|
||||
/**
|
||||
* pcie_dw_mvebu_pcie_link_up() - Configure the PCIe root port |
||||
* |
||||
* @regs_base: A pointer to the PCIe controller registers |
||||
* @cap_speed: The capabilities and speed to configure |
||||
* |
||||
* Configure the PCIe controller root complex depending on the |
||||
* requested link capabilities and speed. |
||||
* |
||||
* Return: 1 (true) for active line and 0 (false) for no link |
||||
*/ |
||||
static int pcie_dw_mvebu_pcie_link_up(const void *regs_base, u32 cap_speed) |
||||
{ |
||||
if (!is_link_up(regs_base)) { |
||||
/* Disable LTSSM state machine to enable configuration */ |
||||
clrbits_le32(regs_base + PCIE_GLOBAL_CONTROL, |
||||
PCIE_APP_LTSSM_EN); |
||||
} |
||||
|
||||
clrsetbits_le32(regs_base + PCIE_GLOBAL_CONTROL, |
||||
PCIE_DEVICE_TYPE_MASK << PCIE_DEVICE_TYPE_OFFSET, |
||||
PCIE_DEVICE_TYPE_RC << PCIE_DEVICE_TYPE_OFFSET); |
||||
|
||||
/* Set the PCIe master AXI attributes */ |
||||
writel(ARCACHE_SHAREABLE_CACHEABLE, regs_base + PCIE_ARCACHE_TRC); |
||||
writel(AWCACHE_SHAREABLE_CACHEABLE, regs_base + PCIE_AWCACHE_TRC); |
||||
|
||||
/* DW pre link configurations */ |
||||
pcie_dw_configure(regs_base, cap_speed); |
||||
|
||||
if (!is_link_up(regs_base)) { |
||||
/* Configuration done. Start LTSSM */ |
||||
setbits_le32(regs_base + PCIE_GLOBAL_CONTROL, |
||||
PCIE_APP_LTSSM_EN); |
||||
} |
||||
|
||||
/* Check that link was established */ |
||||
if (!wait_link_up(regs_base)) |
||||
return 0; |
||||
|
||||
/*
|
||||
* Link can be established in Gen 1. still need to wait |
||||
* till MAC nagaotiation is completed |
||||
*/ |
||||
udelay(100); |
||||
|
||||
return 1; |
||||
} |
||||
|
||||
/**
|
||||
* pcie_dw_regions_setup() - iATU region setup |
||||
* |
||||
* @pcie: Pointer to the PCI controller state |
||||
* |
||||
* Configure the iATU regions in the PCIe controller for outbound access. |
||||
*/ |
||||
static void pcie_dw_regions_setup(struct pcie_dw_mvebu *pcie) |
||||
{ |
||||
/*
|
||||
* Region #0 is used for Outbound CFG space access. |
||||
* Direction = Outbound |
||||
* Region Index = 0 |
||||
*/ |
||||
writel(0, pcie->ctrl_base + PCIE_ATU_VIEWPORT); |
||||
|
||||
writel((u32)(uintptr_t)pcie->cfg_base, pcie->ctrl_base |
||||
+ PCIE_ATU_LOWER_BASE); |
||||
writel(0, pcie->ctrl_base + PCIE_ATU_UPPER_BASE); |
||||
writel((u32)(uintptr_t)pcie->cfg_base + pcie->cfg_size, |
||||
pcie->ctrl_base + PCIE_ATU_LIMIT); |
||||
|
||||
writel(0, pcie->ctrl_base + PCIE_ATU_LOWER_TARGET); |
||||
writel(0, pcie->ctrl_base + PCIE_ATU_UPPER_TARGET); |
||||
writel(PCIE_ATU_TYPE_CFG0, pcie->ctrl_base + PCIE_ATU_CR1); |
||||
writel(PCIE_ATU_ENABLE, pcie->ctrl_base + PCIE_ATU_CR2); |
||||
} |
||||
|
||||
/**
|
||||
* pcie_dw_set_host_bars() - Configure the host BARs |
||||
* |
||||
* @regs_base: A pointer to the PCIe controller registers |
||||
* |
||||
* Configure the host BARs of the PCIe controller root port so that |
||||
* PCI(e) devices may access the system memory. |
||||
*/ |
||||
static void pcie_dw_set_host_bars(const void *regs_base) |
||||
{ |
||||
u32 size = gd->ram_size; |
||||
u64 max_size; |
||||
u32 reg; |
||||
u32 bar0; |
||||
|
||||
/* Verify the maximal BAR size */ |
||||
reg = readl(regs_base + RESIZABLE_BAR_CAP); |
||||
max_size = 1ULL << (5 + (reg + (1 << 4))); |
||||
|
||||
if (size > max_size) { |
||||
size = max_size; |
||||
printf("Warning: PCIe BARs can't map all DRAM space\n"); |
||||
} |
||||
|
||||
/* Set the BAR base and size towards DDR */ |
||||
bar0 = CONFIG_SYS_SDRAM_BASE & ~0xf; |
||||
bar0 |= PCI_BASE_ADDRESS_MEM_TYPE_32; |
||||
writel(CONFIG_SYS_SDRAM_BASE, regs_base + PCIE_CONFIG_BAR0); |
||||
|
||||
reg = ((size >> 20) - 1) << 12; |
||||
writel(size, regs_base + RESIZABLE_BAR_CTL0); |
||||
} |
||||
|
||||
/**
|
||||
* pcie_dw_mvebu_probe() - Probe the PCIe bus for active link |
||||
* |
||||
* @dev: A pointer to the device being operated on |
||||
* |
||||
* Probe for an active link on the PCIe bus and configure the controller |
||||
* to enable this port. |
||||
* |
||||
* Return: 0 on success, else -ENODEV |
||||
*/ |
||||
static int pcie_dw_mvebu_probe(struct udevice *dev) |
||||
{ |
||||
struct pcie_dw_mvebu *pcie = dev_get_priv(dev); |
||||
struct udevice *ctlr = pci_get_controller(dev); |
||||
struct pci_controller *hose = dev_get_uclass_priv(ctlr); |
||||
|
||||
pcie->first_busno = dev->seq; |
||||
|
||||
/* Don't register host if link is down */ |
||||
if (!pcie_dw_mvebu_pcie_link_up(pcie->ctrl_base, LINK_SPEED_GEN_3)) { |
||||
printf("PCIE-%d: Link down\n", dev->seq); |
||||
return -ENODEV; |
||||
} |
||||
|
||||
printf("PCIE-%d: Link up (Gen%d-x%d, Bus%d)\n", dev->seq, |
||||
pcie_dw_get_link_speed(pcie->ctrl_base), |
||||
pcie_dw_get_link_width(pcie->ctrl_base), hose->first_busno); |
||||
|
||||
pcie_dw_regions_setup(pcie); |
||||
|
||||
/* Set the CLASS_REV of RC CFG header to PCI_CLASS_BRIDGE_PCI */ |
||||
clrsetbits_le32(pcie->ctrl_base + PCI_CLASS_REVISION, |
||||
0xffff << 16, PCI_CLASS_BRIDGE_PCI << 16); |
||||
|
||||
pcie_dw_set_host_bars(pcie->ctrl_base); |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
/**
|
||||
* pcie_dw_mvebu_ofdata_to_platdata() - Translate from DT to device state |
||||
* |
||||
* @dev: A pointer to the device being operated on |
||||
* |
||||
* Translate relevant data from the device tree pertaining to device @dev into |
||||
* state that the driver will later make use of. This state is stored in the |
||||
* device's private data structure. |
||||
* |
||||
* Return: 0 on success, else -EINVAL |
||||
*/ |
||||
static int pcie_dw_mvebu_ofdata_to_platdata(struct udevice *dev) |
||||
{ |
||||
struct pcie_dw_mvebu *pcie = dev_get_priv(dev); |
||||
|
||||
/* Get the controller base address */ |
||||
pcie->ctrl_base = (void *)dev_get_addr_index(dev, 0); |
||||
if ((fdt_addr_t)pcie->ctrl_base == FDT_ADDR_T_NONE) |
||||
return -EINVAL; |
||||
|
||||
/* Get the config space base address and size */ |
||||
pcie->cfg_base = (void *)dev_get_addr_size_index(dev, 1, |
||||
&pcie->cfg_size); |
||||
if ((fdt_addr_t)pcie->cfg_base == FDT_ADDR_T_NONE) |
||||
return -EINVAL; |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
static const struct dm_pci_ops pcie_dw_mvebu_ops = { |
||||
.read_config = pcie_dw_mvebu_read_config, |
||||
.write_config = pcie_dw_mvebu_write_config, |
||||
}; |
||||
|
||||
static const struct udevice_id pcie_dw_mvebu_ids[] = { |
||||
{ .compatible = "marvell,armada8k-pcie" }, |
||||
{ } |
||||
}; |
||||
|
||||
U_BOOT_DRIVER(pcie_dw_mvebu) = { |
||||
.name = "pcie_dw_mvebu", |
||||
.id = UCLASS_PCI, |
||||
.of_match = pcie_dw_mvebu_ids, |
||||
.ops = &pcie_dw_mvebu_ops, |
||||
.ofdata_to_platdata = pcie_dw_mvebu_ofdata_to_platdata, |
||||
.probe = pcie_dw_mvebu_probe, |
||||
.priv_auto_alloc_size = sizeof(struct pcie_dw_mvebu), |
||||
}; |
Loading…
Reference in new issue