mirror of
https://github.com/Fishwaldo/u-boot.git
synced 2025-03-18 13:11:31 +00:00
Merge git://git.denx.de/u-boot-marvell
This commit is contained in:
commit
f3b623fa52
16 changed files with 1088 additions and 92 deletions
|
@ -82,7 +82,7 @@
|
|||
|
||||
ð0 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&rgmii_pins>;
|
||||
pinctrl-0 = <&rgmii_pins>, <&smi_pins>;
|
||||
status = "okay";
|
||||
phy-mode = "rgmii";
|
||||
};
|
||||
|
@ -100,6 +100,8 @@
|
|||
|
||||
&sdhci0 {
|
||||
bus-width = <4>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&sdio_pins>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
|
@ -109,6 +111,8 @@
|
|||
mmc-ddr-1_8v;
|
||||
mmc-hs400-1_8v;
|
||||
marvell,pad-type = "fixed-1-8v";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&mmc_pins>;
|
||||
status = "okay";
|
||||
|
||||
#address-cells = <1>;
|
||||
|
@ -150,3 +154,11 @@
|
|||
&usb3 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
/* CON17 */
|
||||
&pcie0 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pcie_pins>;
|
||||
reset-gpio = <&gpiosb 3 GPIO_ACTIVE_HIGH>;
|
||||
status = "okay";
|
||||
};
|
||||
|
|
|
@ -89,6 +89,8 @@
|
|||
|
||||
ð0 {
|
||||
status = "okay";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&rgmii_pins>, <&smi_pins>;
|
||||
phy-mode = "rgmii";
|
||||
phy_addr = <0x1>;
|
||||
fixed-link {
|
||||
|
@ -98,6 +100,8 @@
|
|||
};
|
||||
|
||||
&i2c0 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&i2c1_pins>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
|
@ -108,6 +112,8 @@
|
|||
|
||||
&spi0 {
|
||||
status = "okay";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&spi_quad_pins>;
|
||||
|
||||
spi-flash@0 {
|
||||
#address-cells = <1>;
|
||||
|
@ -121,6 +127,8 @@
|
|||
|
||||
/* Exported on the micro USB connector CON32 through an FTDI */
|
||||
&uart0 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&uart1_pins>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
|
@ -133,3 +141,10 @@
|
|||
&usb3 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&pcie0 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pcie_pins>;
|
||||
reset-gpio = <&gpiosb 3 GPIO_ACTIVE_HIGH>;
|
||||
status = "okay";
|
||||
};
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/comphy/comphy_data.h>
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
||||
/ {
|
||||
model = "Marvell Armada 37xx SoC";
|
||||
|
@ -154,6 +155,11 @@
|
|||
groups = "uart2";
|
||||
function = "uart";
|
||||
};
|
||||
|
||||
mmc_pins: mmc-pins {
|
||||
groups = "emmc_nb";
|
||||
function = "emmc";
|
||||
};
|
||||
};
|
||||
|
||||
pinctrl_sb: pinctrl-sb@18800 {
|
||||
|
@ -162,7 +168,7 @@
|
|||
reg = <0x18800 0x100>, <0x18C00 0x20>;
|
||||
gpiosb: gpiosb {
|
||||
#gpio-cells = <2>;
|
||||
gpio-ranges = <&pinctrl_sb 0 0 29>;
|
||||
gpio-ranges = <&pinctrl_sb 0 0 30>;
|
||||
gpio-controller;
|
||||
interrupts =
|
||||
<GIC_SPI 160 IRQ_TYPE_LEVEL_HIGH>,
|
||||
|
@ -177,6 +183,20 @@
|
|||
function = "mii";
|
||||
};
|
||||
|
||||
smi_pins: smi-pins {
|
||||
groups = "smi";
|
||||
function = "smi";
|
||||
};
|
||||
|
||||
sdio_pins: sdio-pins {
|
||||
groups = "sdio_sb";
|
||||
function = "sdio";
|
||||
};
|
||||
|
||||
pcie_pins: pcie-pins {
|
||||
groups = "pcie1";
|
||||
function = "gpio";
|
||||
};
|
||||
};
|
||||
|
||||
usb3: usb@58000 {
|
||||
|
@ -266,20 +286,6 @@
|
|||
status = "disabled";
|
||||
};
|
||||
|
||||
pinctl0: pinctl@13830 { /* north bridge */
|
||||
compatible = "marvell,armada-3700-pinctl";
|
||||
bank-name = "armada-3700-nb";
|
||||
reg = <0x13830 0x4>;
|
||||
pin-count = <36>;
|
||||
};
|
||||
|
||||
pinctl1: pinctl@18830 { /* south bridge */
|
||||
compatible = "marvell,armada-3700-pinctl";
|
||||
bank-name = "armada-3700-sb";
|
||||
reg = <0x18830 0x4>;
|
||||
pin-count = <30>;
|
||||
};
|
||||
|
||||
comphy: comphy@18300 {
|
||||
compatible = "marvell,mvebu-comphy", "marvell,comphy-armada-3700";
|
||||
reg = <0x18300 0x28>,
|
||||
|
@ -288,5 +294,21 @@
|
|||
max-lanes = <2>;
|
||||
};
|
||||
};
|
||||
|
||||
pcie0: pcie@d0070000 {
|
||||
compatible = "marvell,armada-37xx-pcie";
|
||||
reg = <0 0xd0070000 0 0x20000>;
|
||||
#address-cells = <3>;
|
||||
#size-cells = <2>;
|
||||
device_type = "pci";
|
||||
num-lanes = <1>;
|
||||
status = "disabled";
|
||||
|
||||
bus-range = <0 0xff>;
|
||||
ranges = <0x82000000 0 0xe8000000
|
||||
0 0xe8000000 0 0x1000000 /* Port 0 MEM */
|
||||
0x81000000 0 0xe9000000
|
||||
0 0xe9000000 0 0x10000>; /* Port 0 IO*/
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
@ -45,6 +45,14 @@ static struct mm_region mvebu_mem_map[] = {
|
|||
.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
|
||||
PTE_BLOCK_NON_SHARE
|
||||
},
|
||||
{
|
||||
/* PCI regions */
|
||||
.phys = 0xe8000000UL,
|
||||
.virt = 0xe8000000UL,
|
||||
.size = 0x02000000UL, /* 32MiB master PCI space */
|
||||
.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
|
||||
PTE_BLOCK_NON_SHARE
|
||||
},
|
||||
{
|
||||
/* List terminator */
|
||||
0,
|
||||
|
|
|
@ -50,29 +50,6 @@ DECLARE_GLOBAL_DATA_PTR;
|
|||
|
||||
int board_early_init_f(void)
|
||||
{
|
||||
const void *blob = gd->fdt_blob;
|
||||
const char *bank_name;
|
||||
const char *compat = "marvell,armada-3700-pinctl";
|
||||
int off, len;
|
||||
void __iomem *addr;
|
||||
|
||||
/* FIXME
|
||||
* Temporary WA for setting correct pin control values
|
||||
* until the real pin control driver is awailable.
|
||||
*/
|
||||
off = fdt_node_offset_by_compatible(blob, -1, compat);
|
||||
while (off != -FDT_ERR_NOTFOUND) {
|
||||
bank_name = fdt_getprop(blob, off, "bank-name", &len);
|
||||
addr = (void __iomem *)fdtdec_get_addr_size_auto_noparent(
|
||||
blob, off, "reg", 0, NULL, true);
|
||||
if (!strncmp(bank_name, "armada-3700-nb", len))
|
||||
writel(PINCTRL_NB_REG_VALUE, addr);
|
||||
else if (!strncmp(bank_name, "armada-3700-sb", len))
|
||||
writel(PINCTRL_SB_REG_VALUE, addr);
|
||||
|
||||
off = fdt_node_offset_by_compatible(blob, off, compat);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@ CONFIG_CMD_CACHE=y
|
|||
CONFIG_CMD_TIME=y
|
||||
# CONFIG_SPL_PARTITION_UUIDS is not set
|
||||
CONFIG_ENV_IS_IN_MMC=y
|
||||
CONFIG_NET_RANDOM_ETHADDR=y
|
||||
CONFIG_SPL_OF_TRANSLATE=y
|
||||
CONFIG_MMC_SDHCI=y
|
||||
CONFIG_MMC_SDHCI_SDMA=y
|
||||
|
|
|
@ -17,6 +17,7 @@ CONFIG_BOARD_EARLY_INIT_F=y
|
|||
CONFIG_CMD_GPIO=y
|
||||
CONFIG_CMD_I2C=y
|
||||
CONFIG_CMD_MMC=y
|
||||
CONFIG_CMD_PCI=y
|
||||
CONFIG_CMD_SF=y
|
||||
CONFIG_CMD_SPI=y
|
||||
CONFIG_CMD_USB=y
|
||||
|
@ -44,6 +45,10 @@ CONFIG_SPI_FLASH_SPANSION=y
|
|||
CONFIG_SPI_FLASH_STMICRO=y
|
||||
CONFIG_PHYLIB=y
|
||||
CONFIG_PHY_GIGE=y
|
||||
CONFIG_E1000=y
|
||||
CONFIG_PCI=y
|
||||
CONFIG_DM_PCI=y
|
||||
CONFIG_PCI_AARDVARK=y
|
||||
CONFIG_MVEBU_COMPHY_SUPPORT=y
|
||||
CONFIG_PINCTRL=y
|
||||
CONFIG_PINCTRL_ARMADA_37XX=y
|
||||
|
|
|
@ -14,8 +14,10 @@ CONFIG_SYS_CONSOLE_INFO_QUIET=y
|
|||
CONFIG_ARCH_EARLY_INIT_R=y
|
||||
CONFIG_BOARD_EARLY_INIT_F=y
|
||||
# CONFIG_CMD_FLASH is not set
|
||||
CONFIG_CMD_GPIO=y
|
||||
CONFIG_CMD_I2C=y
|
||||
CONFIG_CMD_MMC=y
|
||||
CONFIG_CMD_PCI=y
|
||||
CONFIG_CMD_SF=y
|
||||
CONFIG_CMD_SPI=y
|
||||
CONFIG_CMD_USB=y
|
||||
|
@ -29,6 +31,7 @@ CONFIG_MAC_PARTITION=y
|
|||
CONFIG_ENV_IS_IN_SPI_FLASH=y
|
||||
CONFIG_SCSI_AHCI=y
|
||||
CONFIG_BLOCK_CACHE=y
|
||||
CONFIG_DM_GPIO=y
|
||||
CONFIG_DM_I2C=y
|
||||
CONFIG_MISC=y
|
||||
CONFIG_DM_MMC=y
|
||||
|
@ -42,7 +45,13 @@ CONFIG_SPI_FLASH_STMICRO=y
|
|||
CONFIG_SPI_FLASH_WINBOND=y
|
||||
CONFIG_PHYLIB=y
|
||||
CONFIG_PHY_GIGE=y
|
||||
CONFIG_E1000=y
|
||||
CONFIG_PCI=y
|
||||
CONFIG_DM_PCI=y
|
||||
CONFIG_PCI_AARDVARK=y
|
||||
CONFIG_MVEBU_COMPHY_SUPPORT=y
|
||||
CONFIG_PINCTRL=y
|
||||
CONFIG_PINCTRL_ARMADA_37XX=y
|
||||
# CONFIG_SPL_SERIAL_PRESENT is not set
|
||||
CONFIG_DEBUG_MVEBU_A3700_UART=y
|
||||
CONFIG_DEBUG_UART_BASE=0xd0012000
|
||||
|
|
186
doc/device-tree-bindings/pinctrl/marvell,armada-37xx-pinctrl.txt
Normal file
186
doc/device-tree-bindings/pinctrl/marvell,armada-37xx-pinctrl.txt
Normal file
|
@ -0,0 +1,186 @@
|
|||
* Marvell Armada 37xx SoC pin and GPIO controller
|
||||
|
||||
Each Armada 37xx SoC comes with two pin and GPIO controllers, one for the
|
||||
South Bridge and the other for the North Bridge.
|
||||
|
||||
GPIO and pin controller:
|
||||
------------------------
|
||||
|
||||
Main node:
|
||||
|
||||
Refer to pinctrl-bindings.txt in this directory for details of the
|
||||
common pinctrl bindings used by client devices, including the meaning
|
||||
of the phrase "pin configuration node".
|
||||
|
||||
Required properties for pinctrl driver:
|
||||
|
||||
- compatible: "marvell,armada3710-sb-pinctrl", "syscon, "simple-mfd"
|
||||
for the South Bridge
|
||||
"marvell,armada3710-nb-pinctrl", "syscon, "simple-mfd"
|
||||
for the North Bridge
|
||||
- reg: The first set of registers is for pinctrl/GPIO and the second
|
||||
set is for the interrupt controller
|
||||
- interrupts: list of interrupts used by the GPIO
|
||||
|
||||
Available groups and functions for the North Bridge:
|
||||
|
||||
group: jtag
|
||||
- pins 20-24
|
||||
- functions jtag, gpio
|
||||
|
||||
group sdio0
|
||||
- pins 8-10
|
||||
- functions sdio, gpio
|
||||
|
||||
group emmc_nb
|
||||
- pins 27-35
|
||||
- functions emmc, gpio
|
||||
|
||||
group pwm0
|
||||
- pin 11 (GPIO1-11)
|
||||
- functions pwm, gpio
|
||||
|
||||
group pwm1
|
||||
- pin 12
|
||||
- functions pwm, gpio
|
||||
|
||||
group pwm2
|
||||
- pin 13
|
||||
- functions pwm, gpio
|
||||
|
||||
group pwm3
|
||||
- pin 14
|
||||
- functions pwm, gpio
|
||||
|
||||
group pmic1
|
||||
- pin 7
|
||||
- functions pmic, gpio
|
||||
|
||||
group pmic0
|
||||
- pin 6
|
||||
- functions pmic, gpio
|
||||
|
||||
group i2c2
|
||||
- pins 2-3
|
||||
- functions i2c, gpio
|
||||
|
||||
group i2c1
|
||||
- pins 0-1
|
||||
- functions i2c, gpio
|
||||
|
||||
group spi_cs1
|
||||
- pin 17
|
||||
- functions spi, gpio
|
||||
|
||||
group spi_cs2
|
||||
- pin 18
|
||||
- functions spi, gpio
|
||||
|
||||
group spi_cs3
|
||||
- pin 19
|
||||
- functions spi, gpio
|
||||
|
||||
group onewire
|
||||
- pin 4
|
||||
- functions onewire, gpio
|
||||
|
||||
group uart1
|
||||
- pins 25-26
|
||||
- functions uart, gpio
|
||||
|
||||
group spi_quad
|
||||
- pins 15-16
|
||||
- functions spi, gpio
|
||||
|
||||
group uart_2
|
||||
- pins 9-10
|
||||
- functions uart, gpio
|
||||
|
||||
Available groups and functions for the South Bridge:
|
||||
|
||||
group usb32_drvvbus0
|
||||
- pin 36
|
||||
- functions drvbus, gpio
|
||||
|
||||
group usb2_drvvbus1
|
||||
- pin 37
|
||||
- functions drvbus, gpio
|
||||
|
||||
group sdio_sb
|
||||
- pins 60-65
|
||||
- functions sdio, gpio
|
||||
|
||||
group rgmii
|
||||
- pins 42-53
|
||||
- functions mii, gpio
|
||||
|
||||
group pcie1
|
||||
- pins 39-41
|
||||
- functions pcie, gpio
|
||||
|
||||
group smi
|
||||
- pins 54-55
|
||||
- functions smi, gpio
|
||||
|
||||
group ptp
|
||||
- pins 56-58
|
||||
- functions ptp, gpio
|
||||
|
||||
group ptp_clk
|
||||
- pin 57
|
||||
- functions ptp, mii
|
||||
|
||||
group ptp_trig
|
||||
- pin 58
|
||||
- functions ptp, mii
|
||||
|
||||
group mii_col
|
||||
- pin 59
|
||||
- functions mii, mii_err
|
||||
|
||||
GPIO subnode:
|
||||
|
||||
Please refer to gpio.txt in "gpio" directory for details of gpio-ranges property
|
||||
and the common GPIO bindings used by client devices.
|
||||
|
||||
Required properties for the GPIO driver under the gpio subnode:
|
||||
- interrupts: List of interrupt specifiers for the controllers interrupt.
|
||||
- gpio-controller: Marks the device node as a GPIO controller.
|
||||
- #gpio-cells: Should be 2. The first cell is the GPIO number and the
|
||||
second cell specifies GPIO flags, as defined in
|
||||
<dt-bindings/gpio/gpio.h>. Only the GPIO_ACTIVE_HIGH and
|
||||
GPIO_ACTIVE_LOW flags are supported.
|
||||
- gpio-ranges: Range of pins managed by the GPIO controller.
|
||||
|
||||
Example:
|
||||
pinctrl_sb: pinctrl-sb@18800 {
|
||||
compatible = "marvell,armada3710-sb-pinctrl",
|
||||
"syscon", "simple-mfd";
|
||||
reg = <0x18800 0x100>, <0x18C00 0x20>;
|
||||
gpiosb: gpiosb {
|
||||
#gpio-cells = <2>;
|
||||
gpio-ranges = <&pinctrl_sb 0 0 30>;
|
||||
gpio-controller;
|
||||
interrupts =
|
||||
<GIC_SPI 160 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 159 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 158 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 157 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 156 IRQ_TYPE_LEVEL_HIGH>;
|
||||
};
|
||||
|
||||
rgmii_pins: mii-pins {
|
||||
groups = "rgmii";
|
||||
function = "mii";
|
||||
};
|
||||
|
||||
sdio_pins: sdio-pins {
|
||||
groups = "sdio_sb";
|
||||
function = "sdio";
|
||||
};
|
||||
|
||||
pcie_pins: pcie-pins {
|
||||
groups = "pcie1";
|
||||
function = "pcie";
|
||||
};
|
||||
};
|
|
@ -26,6 +26,16 @@ config DM_PCI_COMPAT
|
|||
measure when porting a board to use driver model for PCI. Once the
|
||||
board is fully supported, this option should be disabled.
|
||||
|
||||
config PCI_AARDVARK
|
||||
bool "Enable Aardvark PCIe driver"
|
||||
default n
|
||||
depends on DM_PCI
|
||||
depends on ARMADA_3700
|
||||
help
|
||||
Say Y here if you want to enable PCIe controller support on
|
||||
Armada37x0 SoCs. The PCIe controller on Armada37x0 is based on
|
||||
Aardvark hardware.
|
||||
|
||||
config PCI_PNP
|
||||
bool "Enable Plug & Play support for PCI"
|
||||
depends on PCI || DM_PCI
|
||||
|
|
|
@ -30,6 +30,7 @@ obj-$(CONFIG_SH4_PCI) += pci_sh4.o
|
|||
obj-$(CONFIG_SH7751_PCI) +=pci_sh7751.o
|
||||
obj-$(CONFIG_SH7780_PCI) +=pci_sh7780.o
|
||||
obj-$(CONFIG_PCI_TEGRA) += pci_tegra.o
|
||||
obj-$(CONFIG_PCI_AARDVARK) += pci-aardvark.o
|
||||
obj-$(CONFIG_PCIE_DW_MVEBU) += pcie_dw_mvebu.o
|
||||
obj-$(CONFIG_PCIE_LAYERSCAPE) += pcie_layerscape.o
|
||||
obj-$(CONFIG_PCIE_LAYERSCAPE) += pcie_layerscape_fixup.o
|
||||
|
|
690
drivers/pci/pci-aardvark.c
Normal file
690
drivers/pci/pci-aardvark.c
Normal file
|
@ -0,0 +1,690 @@
|
|||
/*
|
||||
* ***************************************************************************
|
||||
* Copyright (C) 2015 Marvell International Ltd.
|
||||
* ***************************************************************************
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation, either version 2 of the License, or any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
* ***************************************************************************
|
||||
*/
|
||||
/* pcie_advk.c
|
||||
*
|
||||
* Ported from Linux driver - driver/pci/host/pci-aardvark.c
|
||||
*
|
||||
* Author: Victor Gu <xigu@marvell.com>
|
||||
* Hezi Shahmoon <hezi.shahmoon@marvell.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <pci.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm-generic/gpio.h>
|
||||
#include <linux/ioport.h>
|
||||
|
||||
/* PCIe core registers */
|
||||
#define PCIE_CORE_CMD_STATUS_REG 0x4
|
||||
#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_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)
|
||||
#define PCIE_CORE_LINK_CTRL_STAT_REG 0xd0
|
||||
#define PCIE_CORE_LINK_TRAINING BIT(5)
|
||||
#define PCIE_CORE_ERR_CAPCTL_REG 0x118
|
||||
#define PCIE_CORE_ERR_CAPCTL_ECRC_CHK_TX BIT(5)
|
||||
#define PCIE_CORE_ERR_CAPCTL_ECRC_CHK_TX_EN BIT(6)
|
||||
#define PCIE_CORE_ERR_CAPCTL_ECRC_CHECK BIT(7)
|
||||
#define PCIE_CORE_ERR_CAPCTL_ECRC_CHECK_RCV BIT(8)
|
||||
|
||||
/* PIO registers base address and register offsets */
|
||||
#define PIO_BASE_ADDR 0x4000
|
||||
#define PIO_CTRL (PIO_BASE_ADDR + 0x0)
|
||||
#define PIO_CTRL_TYPE_MASK GENMASK(3, 0)
|
||||
#define PIO_CTRL_ADDR_WIN_DISABLE BIT(24)
|
||||
#define PIO_STAT (PIO_BASE_ADDR + 0x4)
|
||||
#define PIO_COMPLETION_STATUS_SHIFT 7
|
||||
#define PIO_COMPLETION_STATUS_MASK GENMASK(9, 7)
|
||||
#define PIO_COMPLETION_STATUS_OK 0
|
||||
#define PIO_COMPLETION_STATUS_UR 1
|
||||
#define PIO_COMPLETION_STATUS_CRS 2
|
||||
#define PIO_COMPLETION_STATUS_CA 4
|
||||
#define PIO_NON_POSTED_REQ BIT(10)
|
||||
#define PIO_ERR_STATUS BIT(11)
|
||||
#define PIO_ADDR_LS (PIO_BASE_ADDR + 0x8)
|
||||
#define PIO_ADDR_MS (PIO_BASE_ADDR + 0xc)
|
||||
#define PIO_WR_DATA (PIO_BASE_ADDR + 0x10)
|
||||
#define PIO_WR_DATA_STRB (PIO_BASE_ADDR + 0x14)
|
||||
#define PIO_RD_DATA (PIO_BASE_ADDR + 0x18)
|
||||
#define PIO_START (PIO_BASE_ADDR + 0x1c)
|
||||
#define PIO_ISR (PIO_BASE_ADDR + 0x20)
|
||||
|
||||
/* Aardvark Control registers */
|
||||
#define CONTROL_BASE_ADDR 0x4800
|
||||
#define PCIE_CORE_CTRL0_REG (CONTROL_BASE_ADDR + 0x0)
|
||||
#define PCIE_GEN_SEL_MSK 0x3
|
||||
#define PCIE_GEN_SEL_SHIFT 0x0
|
||||
#define SPEED_GEN_1 0
|
||||
#define SPEED_GEN_2 1
|
||||
#define SPEED_GEN_3 2
|
||||
#define IS_RC_MSK 1
|
||||
#define IS_RC_SHIFT 2
|
||||
#define LANE_CNT_MSK 0x18
|
||||
#define LANE_CNT_SHIFT 0x3
|
||||
#define LANE_COUNT_1 (0 << LANE_CNT_SHIFT)
|
||||
#define LANE_COUNT_2 (1 << LANE_CNT_SHIFT)
|
||||
#define LANE_COUNT_4 (2 << LANE_CNT_SHIFT)
|
||||
#define LANE_COUNT_8 (3 << LANE_CNT_SHIFT)
|
||||
#define LINK_TRAINING_EN BIT(6)
|
||||
#define PCIE_CORE_CTRL2_REG (CONTROL_BASE_ADDR + 0x8)
|
||||
#define PCIE_CORE_CTRL2_RESERVED 0x7
|
||||
#define PCIE_CORE_CTRL2_TD_ENABLE BIT(4)
|
||||
#define PCIE_CORE_CTRL2_STRICT_ORDER_ENABLE BIT(5)
|
||||
#define PCIE_CORE_CTRL2_ADDRWIN_MAP_ENABLE BIT(6)
|
||||
|
||||
/* LMI registers base address and register offsets */
|
||||
#define LMI_BASE_ADDR 0x6000
|
||||
#define CFG_REG (LMI_BASE_ADDR + 0x0)
|
||||
#define LTSSM_SHIFT 24
|
||||
#define LTSSM_MASK 0x3f
|
||||
#define LTSSM_L0 0x10
|
||||
|
||||
/* PCIe core controller registers */
|
||||
#define CTRL_CORE_BASE_ADDR 0x18000
|
||||
#define CTRL_CONFIG_REG (CTRL_CORE_BASE_ADDR + 0x0)
|
||||
#define CTRL_MODE_SHIFT 0x0
|
||||
#define CTRL_MODE_MASK 0x1
|
||||
#define PCIE_CORE_MODE_DIRECT 0x0
|
||||
#define PCIE_CORE_MODE_COMMAND 0x1
|
||||
|
||||
/* Transaction types */
|
||||
#define PCIE_CONFIG_RD_TYPE0 0x8
|
||||
#define PCIE_CONFIG_RD_TYPE1 0x9
|
||||
#define PCIE_CONFIG_WR_TYPE0 0xa
|
||||
#define PCIE_CONFIG_WR_TYPE1 0xb
|
||||
|
||||
/* PCI_BDF shifts 8bit, so we need extra 4bit shift */
|
||||
#define PCIE_BDF(dev) (dev << 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)
|
||||
#define PCIE_CONF_REG(reg) ((reg) & 0xffc)
|
||||
#define PCIE_CONF_ADDR(bus, devfn, where) \
|
||||
(PCIE_CONF_BUS(bus) | PCIE_CONF_DEV(PCI_SLOT(devfn)) | \
|
||||
PCIE_CONF_FUNC(PCI_FUNC(devfn)) | PCIE_CONF_REG(where))
|
||||
|
||||
/* PCIe Retries & Timeout definitions */
|
||||
#define MAX_RETRIES 10
|
||||
#define PIO_WAIT_TIMEOUT 100
|
||||
#define LINK_WAIT_TIMEOUT 100000
|
||||
|
||||
#define CFG_RD_UR_VAL 0xFFFFFFFF
|
||||
#define CFG_RD_CRS_VAL 0xFFFF0001
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
struct pcie_advk {
|
||||
void *base;
|
||||
int first_busno;
|
||||
struct udevice *dev;
|
||||
};
|
||||
|
||||
static inline void advk_writel(struct pcie_advk *pcie, uint val, uint reg)
|
||||
{
|
||||
writel(val, pcie->base + reg);
|
||||
}
|
||||
|
||||
static inline uint advk_readl(struct pcie_advk *pcie, uint reg)
|
||||
{
|
||||
return readl(pcie->base + reg);
|
||||
}
|
||||
|
||||
/**
|
||||
* pcie_advk_addr_valid() - Check for valid bus address
|
||||
*
|
||||
* @bdf: The PCI device to access
|
||||
* @first_busno: Bus number of the PCIe controller root complex
|
||||
*
|
||||
* Return: 1 on valid, 0 on invalid
|
||||
*/
|
||||
static int pcie_advk_addr_valid(pci_dev_t bdf, int first_busno)
|
||||
{
|
||||
/*
|
||||
* 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;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* pcie_advk_wait_pio() - Wait for PIO access to be accomplished
|
||||
*
|
||||
* @pcie: The PCI device to access
|
||||
*
|
||||
* Wait up to 1 micro second for PIO access to be accomplished.
|
||||
*
|
||||
* Return 1 (true) if PIO access is accomplished.
|
||||
* Return 0 (false) if PIO access is timed out.
|
||||
*/
|
||||
static int pcie_advk_wait_pio(struct pcie_advk *pcie)
|
||||
{
|
||||
uint start, isr;
|
||||
uint count;
|
||||
|
||||
for (count = 0; count < MAX_RETRIES; count++) {
|
||||
start = advk_readl(pcie, PIO_START);
|
||||
isr = advk_readl(pcie, PIO_ISR);
|
||||
if (!start && isr)
|
||||
return 1;
|
||||
/*
|
||||
* Do not check the PIO state too frequently,
|
||||
* 100us delay is appropriate.
|
||||
*/
|
||||
udelay(PIO_WAIT_TIMEOUT);
|
||||
}
|
||||
|
||||
dev_err(pcie->dev, "config read/write timed out\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* pcie_advk_check_pio_status() - Validate PIO status and get the read result
|
||||
*
|
||||
* @pcie: Pointer to the PCI bus
|
||||
* @read: Read from or write to configuration space - true(read) false(write)
|
||||
* @read_val: Pointer to the read result, only valid when read is true
|
||||
*
|
||||
*/
|
||||
static int pcie_advk_check_pio_status(struct pcie_advk *pcie,
|
||||
bool read,
|
||||
uint *read_val)
|
||||
{
|
||||
uint reg;
|
||||
unsigned int status;
|
||||
char *strcomp_status, *str_posted;
|
||||
|
||||
reg = advk_readl(pcie, PIO_STAT);
|
||||
status = (reg & PIO_COMPLETION_STATUS_MASK) >>
|
||||
PIO_COMPLETION_STATUS_SHIFT;
|
||||
|
||||
switch (status) {
|
||||
case PIO_COMPLETION_STATUS_OK:
|
||||
if (reg & PIO_ERR_STATUS) {
|
||||
strcomp_status = "COMP_ERR";
|
||||
break;
|
||||
}
|
||||
/* Get the read result */
|
||||
if (read)
|
||||
*read_val = advk_readl(pcie, PIO_RD_DATA);
|
||||
/* No error */
|
||||
strcomp_status = NULL;
|
||||
break;
|
||||
case PIO_COMPLETION_STATUS_UR:
|
||||
if (read) {
|
||||
/* For reading, UR is not an error status. */
|
||||
*read_val = CFG_RD_UR_VAL;
|
||||
strcomp_status = NULL;
|
||||
} else {
|
||||
strcomp_status = "UR";
|
||||
}
|
||||
break;
|
||||
case PIO_COMPLETION_STATUS_CRS:
|
||||
if (read) {
|
||||
/* For reading, CRS is not an error status. */
|
||||
*read_val = CFG_RD_CRS_VAL;
|
||||
strcomp_status = NULL;
|
||||
} else {
|
||||
strcomp_status = "CRS";
|
||||
}
|
||||
break;
|
||||
case PIO_COMPLETION_STATUS_CA:
|
||||
strcomp_status = "CA";
|
||||
break;
|
||||
default:
|
||||
strcomp_status = "Unknown";
|
||||
break;
|
||||
}
|
||||
|
||||
if (!strcomp_status)
|
||||
return 0;
|
||||
|
||||
if (reg & PIO_NON_POSTED_REQ)
|
||||
str_posted = "Non-posted";
|
||||
else
|
||||
str_posted = "Posted";
|
||||
|
||||
dev_err(pcie->dev, "%s PIO Response Status: %s, %#x @ %#x\n",
|
||||
str_posted, strcomp_status, reg,
|
||||
advk_readl(pcie, PIO_ADDR_LS));
|
||||
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
/**
|
||||
* pcie_advk_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_advk_read_config(struct udevice *bus, pci_dev_t bdf,
|
||||
uint offset, ulong *valuep,
|
||||
enum pci_size_t size)
|
||||
{
|
||||
struct pcie_advk *pcie = dev_get_priv(bus);
|
||||
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)) {
|
||||
dev_dbg(pcie->dev, "- out of range\n");
|
||||
*valuep = pci_get_ff(size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Start PIO */
|
||||
advk_writel(pcie, 0, PIO_START);
|
||||
advk_writel(pcie, 1, PIO_ISR);
|
||||
|
||||
/* Program the control register */
|
||||
reg = advk_readl(pcie, PIO_CTRL);
|
||||
reg &= ~PIO_CTRL_TYPE_MASK;
|
||||
if (PCI_BUS(bdf) == pcie->first_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);
|
||||
advk_writel(pcie, reg, PIO_ADDR_LS);
|
||||
advk_writel(pcie, 0, PIO_ADDR_MS);
|
||||
|
||||
/* Start the transfer */
|
||||
advk_writel(pcie, 1, PIO_START);
|
||||
|
||||
if (!pcie_advk_wait_pio(pcie))
|
||||
return -EINVAL;
|
||||
|
||||
/* Check PIO status and get the read result */
|
||||
ret = pcie_advk_check_pio_status(pcie, true, ®);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
dev_dbg(pcie->dev, "(addr,size,val)=(0x%04x, %d, 0x%08x)\n",
|
||||
offset, size, reg);
|
||||
*valuep = pci_conv_32_to_size(reg, offset, size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* pcie_calc_datastrobe() - Calculate data strobe
|
||||
*
|
||||
* @offset: The offset into the device's configuration space
|
||||
* @size: Indicates the size of access to perform
|
||||
*
|
||||
* Calculate data strobe according to offset and size
|
||||
*
|
||||
*/
|
||||
static uint pcie_calc_datastrobe(uint offset, enum pci_size_t size)
|
||||
{
|
||||
uint bytes, data_strobe;
|
||||
|
||||
switch (size) {
|
||||
case PCI_SIZE_8:
|
||||
bytes = 1;
|
||||
break;
|
||||
case PCI_SIZE_16:
|
||||
bytes = 2;
|
||||
break;
|
||||
default:
|
||||
bytes = 4;
|
||||
}
|
||||
|
||||
data_strobe = GENMASK(bytes - 1, 0) << (offset & 0x3);
|
||||
|
||||
return data_strobe;
|
||||
}
|
||||
|
||||
/**
|
||||
* pcie_advk_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_advk_write_config(struct udevice *bus, pci_dev_t bdf,
|
||||
uint offset, ulong value,
|
||||
enum pci_size_t size)
|
||||
{
|
||||
struct pcie_advk *pcie = dev_get_priv(bus);
|
||||
uint reg;
|
||||
|
||||
dev_dbg(pcie->dev, "PCIE CFG write: (b,d,f)=(%2d,%2d,%2d) ",
|
||||
PCI_BUS(bdf), PCI_DEV(bdf), PCI_FUNC(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)) {
|
||||
dev_dbg(pcie->dev, "- out of range\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Start PIO */
|
||||
advk_writel(pcie, 0, PIO_START);
|
||||
advk_writel(pcie, 1, PIO_ISR);
|
||||
|
||||
/* Program the control register */
|
||||
reg = advk_readl(pcie, PIO_CTRL);
|
||||
reg &= ~PIO_CTRL_TYPE_MASK;
|
||||
if (PCI_BUS(bdf) == pcie->first_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);
|
||||
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);
|
||||
|
||||
/* Program the data register */
|
||||
reg = pci_conv_size_to_32(0, value, offset, size);
|
||||
advk_writel(pcie, reg, PIO_WR_DATA);
|
||||
dev_dbg(pcie->dev, "\tPIO req. - val = 0x%08x\n", reg);
|
||||
|
||||
/* Program the data strobe */
|
||||
reg = pcie_calc_datastrobe(offset, size);
|
||||
advk_writel(pcie, reg, PIO_WR_DATA_STRB);
|
||||
dev_dbg(pcie->dev, "\tPIO req. - strb = 0x%02x\n", reg);
|
||||
|
||||
/* Start the transfer */
|
||||
advk_writel(pcie, 1, PIO_START);
|
||||
|
||||
if (!pcie_advk_wait_pio(pcie)) {
|
||||
dev_dbg(pcie->dev, "- wait pio timeout\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Check PIO status */
|
||||
pcie_advk_check_pio_status(pcie, false, ®);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* pcie_advk_link_up() - Check if PCIe link is up or not
|
||||
*
|
||||
* @pcie: The PCI device to access
|
||||
*
|
||||
* Return 1 (true) on link up.
|
||||
* Return 0 (false) on link down.
|
||||
*/
|
||||
static int pcie_advk_link_up(struct pcie_advk *pcie)
|
||||
{
|
||||
u32 val, ltssm_state;
|
||||
|
||||
val = advk_readl(pcie, CFG_REG);
|
||||
ltssm_state = (val >> LTSSM_SHIFT) & LTSSM_MASK;
|
||||
return ltssm_state >= LTSSM_L0;
|
||||
}
|
||||
|
||||
/**
|
||||
* pcie_advk_wait_for_link() - Wait for link training to be accomplished
|
||||
*
|
||||
* @pcie: The PCI device to access
|
||||
*
|
||||
* Wait up to 1 second for link training to be accomplished.
|
||||
*
|
||||
* Return 1 (true) if link training ends up with link up success.
|
||||
* Return 0 (false) if link training ends up with link up failure.
|
||||
*/
|
||||
static int pcie_advk_wait_for_link(struct pcie_advk *pcie)
|
||||
{
|
||||
int retries;
|
||||
|
||||
/* check if the link is up or not */
|
||||
for (retries = 0; retries < MAX_RETRIES; retries++) {
|
||||
if (pcie_advk_link_up(pcie)) {
|
||||
printf("PCIE-%d: Link up\n", pcie->first_busno);
|
||||
return 0;
|
||||
}
|
||||
|
||||
udelay(LINK_WAIT_TIMEOUT);
|
||||
}
|
||||
|
||||
printf("PCIE-%d: Link down\n", pcie->first_busno);
|
||||
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
/**
|
||||
* pcie_advk_setup_hw() - PCIe initailzation
|
||||
*
|
||||
* @pcie: The PCI device to access
|
||||
*
|
||||
* Return: 0 on success
|
||||
*/
|
||||
static int pcie_advk_setup_hw(struct pcie_advk *pcie)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
/* Set to Direct mode */
|
||||
reg = advk_readl(pcie, CTRL_CONFIG_REG);
|
||||
reg &= ~(CTRL_MODE_MASK << CTRL_MODE_SHIFT);
|
||||
reg |= ((PCIE_CORE_MODE_DIRECT & CTRL_MODE_MASK) << CTRL_MODE_SHIFT);
|
||||
advk_writel(pcie, reg, CTRL_CONFIG_REG);
|
||||
|
||||
/* Set PCI global control register to RC mode */
|
||||
reg = advk_readl(pcie, PCIE_CORE_CTRL0_REG);
|
||||
reg |= (IS_RC_MSK << IS_RC_SHIFT);
|
||||
advk_writel(pcie, reg, PCIE_CORE_CTRL0_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 |
|
||||
PCIE_CORE_ERR_CAPCTL_ECRC_CHECK |
|
||||
PCIE_CORE_ERR_CAPCTL_ECRC_CHECK_RCV;
|
||||
advk_writel(pcie, reg, PCIE_CORE_ERR_CAPCTL_REG);
|
||||
|
||||
/* Set PCIe Device Control and Status 1 PF0 register */
|
||||
reg = PCIE_CORE_DEV_CTRL_STATS_RELAX_ORDER_DISABLE |
|
||||
PCIE_CORE_DEV_CTRL_STATS_SNOOP_DISABLE;
|
||||
advk_writel(pcie, reg, PCIE_CORE_DEV_CTRL_STATS_REG);
|
||||
|
||||
/* Program PCIe Control 2 to disable strict ordering */
|
||||
reg = PCIE_CORE_CTRL2_RESERVED |
|
||||
PCIE_CORE_CTRL2_TD_ENABLE;
|
||||
advk_writel(pcie, reg, PCIE_CORE_CTRL2_REG);
|
||||
|
||||
/* Set GEN2 */
|
||||
reg = advk_readl(pcie, PCIE_CORE_CTRL0_REG);
|
||||
reg &= ~PCIE_GEN_SEL_MSK;
|
||||
reg |= SPEED_GEN_2;
|
||||
advk_writel(pcie, reg, PCIE_CORE_CTRL0_REG);
|
||||
|
||||
/* Set lane X1 */
|
||||
reg = advk_readl(pcie, PCIE_CORE_CTRL0_REG);
|
||||
reg &= ~LANE_CNT_MSK;
|
||||
reg |= LANE_COUNT_1;
|
||||
advk_writel(pcie, reg, PCIE_CORE_CTRL0_REG);
|
||||
|
||||
/* Enable link training */
|
||||
reg = advk_readl(pcie, PCIE_CORE_CTRL0_REG);
|
||||
reg |= LINK_TRAINING_EN;
|
||||
advk_writel(pcie, reg, PCIE_CORE_CTRL0_REG);
|
||||
|
||||
/*
|
||||
* Enable AXI address window location generation:
|
||||
* When it is enabled, the default outbound window
|
||||
* configurations (Default User Field: 0xD0074CFC)
|
||||
* are used to transparent address translation for
|
||||
* the outbound transactions. Thus, PCIe address
|
||||
* windows are not required.
|
||||
*/
|
||||
reg = advk_readl(pcie, PCIE_CORE_CTRL2_REG);
|
||||
reg |= PCIE_CORE_CTRL2_ADDRWIN_MAP_ENABLE;
|
||||
advk_writel(pcie, reg, PCIE_CORE_CTRL2_REG);
|
||||
|
||||
/*
|
||||
* Bypass the address window mapping for PIO:
|
||||
* Since PIO access already contains all required
|
||||
* info over AXI interface by PIO registers, the
|
||||
* address window is not required.
|
||||
*/
|
||||
reg = advk_readl(pcie, PIO_CTRL);
|
||||
reg |= PIO_CTRL_ADDR_WIN_DISABLE;
|
||||
advk_writel(pcie, reg, PIO_CTRL);
|
||||
|
||||
/* Start link training */
|
||||
reg = advk_readl(pcie, PCIE_CORE_LINK_CTRL_STAT_REG);
|
||||
reg |= PCIE_CORE_LINK_TRAINING;
|
||||
advk_writel(pcie, reg, PCIE_CORE_LINK_CTRL_STAT_REG);
|
||||
|
||||
/* Wait for PCIe link up */
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* pcie_advk_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_advk_probe(struct udevice *dev)
|
||||
{
|
||||
struct pcie_advk *pcie = dev_get_priv(dev);
|
||||
|
||||
#ifdef CONFIG_DM_GPIO
|
||||
struct gpio_desc reset_gpio;
|
||||
|
||||
gpio_request_by_name(dev, "reset-gpio", 0, &reset_gpio,
|
||||
GPIOD_IS_OUT);
|
||||
/*
|
||||
* Issue reset to add-in card through the dedicated GPIO.
|
||||
* Some boards are connecting the card reset pin to common system
|
||||
* reset wire and others are using separate GPIO port.
|
||||
* In the last case we have to release a reset of the addon card
|
||||
* using this GPIO.
|
||||
*
|
||||
* FIX-ME:
|
||||
* The PCIe RESET signal is not supposed to be released along
|
||||
* with the SOC RESET signal. It should be lowered as early as
|
||||
* possible before PCIe PHY initialization. Moreover, the PCIe
|
||||
* clock should be gated as well.
|
||||
*/
|
||||
if (dm_gpio_is_valid(&reset_gpio)) {
|
||||
dev_dbg(pcie->dev, "Toggle PCIE Reset GPIO ...\n");
|
||||
dm_gpio_set_value(&reset_gpio, 0);
|
||||
mdelay(200);
|
||||
dm_gpio_set_value(&reset_gpio, 1);
|
||||
}
|
||||
#else
|
||||
dev_dbg(pcie->dev, "PCIE Reset on GPIO support is missing\n");
|
||||
#endif /* CONFIG_DM_GPIO */
|
||||
|
||||
pcie->first_busno = dev->seq;
|
||||
pcie->dev = pci_get_controller(dev);
|
||||
|
||||
return pcie_advk_setup_hw(pcie);
|
||||
}
|
||||
|
||||
/**
|
||||
* pcie_advk_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_advk_ofdata_to_platdata(struct udevice *dev)
|
||||
{
|
||||
struct pcie_advk *pcie = dev_get_priv(dev);
|
||||
|
||||
/* Get the register base address */
|
||||
pcie->base = (void *)dev_read_addr_index(dev, 0);
|
||||
if ((fdt_addr_t)pcie->base == FDT_ADDR_T_NONE)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dm_pci_ops pcie_advk_ops = {
|
||||
.read_config = pcie_advk_read_config,
|
||||
.write_config = pcie_advk_write_config,
|
||||
};
|
||||
|
||||
static const struct udevice_id pcie_advk_ids[] = {
|
||||
{ .compatible = "marvell,armada-37xx-pcie" },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(pcie_advk) = {
|
||||
.name = "pcie_advk",
|
||||
.id = UCLASS_PCI,
|
||||
.of_match = pcie_advk_ids,
|
||||
.ops = &pcie_advk_ops,
|
||||
.ofdata_to_platdata = pcie_advk_ofdata_to_platdata,
|
||||
.probe = pcie_advk_probe,
|
||||
.priv_auto_alloc_size = sizeof(struct pcie_advk),
|
||||
};
|
|
@ -111,6 +111,10 @@ struct pcie_dw_mvebu {
|
|||
void *cfg_base;
|
||||
fdt_size_t cfg_size;
|
||||
int first_busno;
|
||||
|
||||
/* IO and MEM PCI regions */
|
||||
struct pci_region io;
|
||||
struct pci_region mem;
|
||||
};
|
||||
|
||||
static int pcie_dw_get_link_speed(const void *regs_base)
|
||||
|
@ -125,6 +129,34 @@ static int pcie_dw_get_link_width(const void *regs_base)
|
|||
PCIE_LINK_STATUS_WIDTH_MASK) >> PCIE_LINK_STATUS_WIDTH_OFF;
|
||||
}
|
||||
|
||||
/**
|
||||
* pcie_dw_prog_outbound_atu() - Configure ATU for outbound accesses
|
||||
*
|
||||
* @pcie: Pointer to the PCI controller state
|
||||
* @index: ATU region index
|
||||
* @type: ATU accsess type
|
||||
* @cpu_addr: the physical address for the translation entry
|
||||
* @pci_addr: the pcie bus address for the translation entry
|
||||
* @size: the size of the translation entry
|
||||
*/
|
||||
static void pcie_dw_prog_outbound_atu(struct pcie_dw_mvebu *pcie, int index,
|
||||
int type, u64 cpu_addr, u64 pci_addr,
|
||||
u32 size)
|
||||
{
|
||||
writel(PCIE_ATU_REGION_OUTBOUND | index,
|
||||
pcie->ctrl_base + PCIE_ATU_VIEWPORT);
|
||||
writel(lower_32_bits(cpu_addr), pcie->ctrl_base + PCIE_ATU_LOWER_BASE);
|
||||
writel(upper_32_bits(cpu_addr), pcie->ctrl_base + PCIE_ATU_UPPER_BASE);
|
||||
writel(lower_32_bits(cpu_addr + size - 1),
|
||||
pcie->ctrl_base + PCIE_ATU_LIMIT);
|
||||
writel(lower_32_bits(pci_addr),
|
||||
pcie->ctrl_base + PCIE_ATU_LOWER_TARGET);
|
||||
writel(upper_32_bits(pci_addr),
|
||||
pcie->ctrl_base + PCIE_ATU_UPPER_TARGET);
|
||||
writel(type, pcie->ctrl_base + PCIE_ATU_CR1);
|
||||
writel(PCIE_ATU_ENABLE, pcie->ctrl_base + PCIE_ATU_CR2);
|
||||
}
|
||||
|
||||
/**
|
||||
* set_cfg_address() - Configure the PCIe controller config space access
|
||||
*
|
||||
|
@ -143,27 +175,29 @@ static uintptr_t set_cfg_address(struct pcie_dw_mvebu *pcie,
|
|||
pci_dev_t d, uint where)
|
||||
{
|
||||
uintptr_t va_address;
|
||||
u32 atu_type;
|
||||
|
||||
/*
|
||||
* 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);
|
||||
atu_type = PCIE_ATU_TYPE_CFG0;
|
||||
else
|
||||
/* Otherwise, change TLP Type field to 5. */
|
||||
writel(PCIE_ATU_TYPE_CFG1, pcie->ctrl_base + PCIE_ATU_CR1);
|
||||
atu_type = PCIE_ATU_TYPE_CFG1;
|
||||
|
||||
if (PCI_BUS(d) == pcie->first_busno) {
|
||||
/* Accessing root port configuration space. */
|
||||
va_address = (uintptr_t)pcie->ctrl_base;
|
||||
} else {
|
||||
d = PCI_MASK_BUS(d) | (PCI_BUS(d) - pcie->first_busno);
|
||||
writel(d << 8, pcie->ctrl_base + PCIE_ATU_LOWER_TARGET);
|
||||
pcie_dw_prog_outbound_atu(pcie, PCIE_ATU_REGION_INDEX0,
|
||||
atu_type, (u64)pcie->cfg_base,
|
||||
d << 8, pcie->cfg_size);
|
||||
va_address = (uintptr_t)pcie->cfg_base;
|
||||
}
|
||||
|
||||
|
@ -231,6 +265,10 @@ static int pcie_dw_mvebu_read_config(struct udevice *bus, pci_dev_t bdf,
|
|||
debug("(addr,val)=(0x%04x, 0x%08lx)\n", offset, value);
|
||||
*valuep = pci_conv_32_to_size(value, offset, size);
|
||||
|
||||
pcie_dw_prog_outbound_atu(pcie, PCIE_ATU_REGION_INDEX0,
|
||||
PCIE_ATU_TYPE_IO, pcie->io.phys_start,
|
||||
pcie->io.bus_start, pcie->io.size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -272,6 +310,10 @@ static int pcie_dw_mvebu_write_config(struct udevice *bus, pci_dev_t bdf,
|
|||
value = pci_conv_size_to_32(old, value, offset, size);
|
||||
writel(value, va_address);
|
||||
|
||||
pcie_dw_prog_outbound_atu(pcie, PCIE_ATU_REGION_INDEX0,
|
||||
PCIE_ATU_TYPE_IO, pcie->io.phys_start,
|
||||
pcie->io.bus_start, pcie->io.size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -387,34 +429,6 @@ static int pcie_dw_mvebu_pcie_link_up(const void *regs_base, u32 cap_speed)
|
|||
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
|
||||
*
|
||||
|
@ -495,7 +509,18 @@ static int pcie_dw_mvebu_probe(struct udevice *dev)
|
|||
hose->first_busno);
|
||||
}
|
||||
|
||||
pcie_dw_regions_setup(pcie);
|
||||
/* Store the IO and MEM windows settings for future use by the ATU */
|
||||
pcie->io.phys_start = hose->regions[0].phys_start; /* IO base */
|
||||
pcie->io.bus_start = hose->regions[0].bus_start; /* IO_bus_addr */
|
||||
pcie->io.size = hose->regions[0].size; /* IO size */
|
||||
|
||||
pcie->mem.phys_start = hose->regions[1].phys_start; /* MEM base */
|
||||
pcie->mem.bus_start = hose->regions[1].bus_start; /* MEM_bus_addr */
|
||||
pcie->mem.size = hose->regions[1].size; /* MEM size */
|
||||
|
||||
pcie_dw_prog_outbound_atu(pcie, PCIE_ATU_REGION_INDEX1,
|
||||
PCIE_ATU_TYPE_MEM, pcie->mem.phys_start,
|
||||
pcie->mem.bus_start, pcie->mem.size);
|
||||
|
||||
/* Set the CLASS_REV of RC CFG header to PCI_CLASS_BRIDGE_PCI */
|
||||
clrsetbits_le32(pcie->ctrl_base + PCI_CLASS_REVISION,
|
||||
|
|
|
@ -44,7 +44,7 @@ DECLARE_GLOBAL_DATA_PTR;
|
|||
#define IRQ_STATUS 0x10
|
||||
#define IRQ_WKUP 0x18
|
||||
|
||||
#define NB_FUNCS 2
|
||||
#define NB_FUNCS 3
|
||||
#define GPIO_PER_REG 32
|
||||
|
||||
/**
|
||||
|
@ -128,6 +128,16 @@ struct armada_37xx_pinctrl {
|
|||
.funcs = {_func1, "gpio"} \
|
||||
}
|
||||
|
||||
#define PIN_GRP_GPIO_3(_name, _start, _nr, _mask, _v1, _v2, _v3, _f1, _f2) \
|
||||
{ \
|
||||
.name = _name, \
|
||||
.start_pin = _start, \
|
||||
.npins = _nr, \
|
||||
.reg_mask = _mask, \
|
||||
.val = {_v1, _v2, _v3}, \
|
||||
.funcs = {_f1, _f2, "gpio"} \
|
||||
}
|
||||
|
||||
#define PIN_GRP_EXTRA(_name, _start, _nr, _mask, _v1, _v2, _start2, _nr2, \
|
||||
_f1, _f2) \
|
||||
{ \
|
||||
|
@ -149,8 +159,8 @@ static struct armada_37xx_pin_group armada_37xx_nb_groups[] = {
|
|||
PIN_GRP_GPIO("pwm1", 12, 1, BIT(4), "pwm"),
|
||||
PIN_GRP_GPIO("pwm2", 13, 1, BIT(5), "pwm"),
|
||||
PIN_GRP_GPIO("pwm3", 14, 1, BIT(6), "pwm"),
|
||||
PIN_GRP_GPIO("pmic1", 17, 1, BIT(7), "pmic"),
|
||||
PIN_GRP_GPIO("pmic0", 16, 1, BIT(8), "pmic"),
|
||||
PIN_GRP_GPIO("pmic1", 7, 1, BIT(7), "pmic"),
|
||||
PIN_GRP_GPIO("pmic0", 6, 1, BIT(8), "pmic"),
|
||||
PIN_GRP_GPIO("i2c2", 2, 2, BIT(9), "i2c"),
|
||||
PIN_GRP_GPIO("i2c1", 0, 2, BIT(10), "i2c"),
|
||||
PIN_GRP_GPIO("spi_cs1", 17, 1, BIT(12), "spi"),
|
||||
|
@ -172,13 +182,15 @@ static struct armada_37xx_pin_group armada_37xx_nb_groups[] = {
|
|||
static struct armada_37xx_pin_group armada_37xx_sb_groups[] = {
|
||||
PIN_GRP_GPIO("usb32_drvvbus0", 0, 1, BIT(0), "drvbus"),
|
||||
PIN_GRP_GPIO("usb2_drvvbus1", 1, 1, BIT(1), "drvbus"),
|
||||
PIN_GRP_GPIO("sdio_sb", 24, 5, BIT(2), "sdio"),
|
||||
PIN_GRP_EXTRA("rgmii", 6, 14, BIT(3), 0, BIT(3), 23, 1, "mii", "gpio"),
|
||||
PIN_GRP_GPIO("pcie1", 3, 2, BIT(4), "pcie"),
|
||||
PIN_GRP_GPIO("ptp", 20, 3, BIT(5), "ptp"),
|
||||
PIN_GRP_GPIO("sdio_sb", 24, 6, BIT(2), "sdio"),
|
||||
PIN_GRP_GPIO("rgmii", 6, 12, BIT(3), "mii"),
|
||||
PIN_GRP_GPIO("smi", 18, 2, BIT(4), "smi"),
|
||||
PIN_GRP_GPIO("pcie1", 3, 3, BIT(5) | BIT(9) | BIT(10), "pcie"),
|
||||
PIN_GRP_GPIO("ptp", 20, 3, BIT(11) | BIT(12) | BIT(13), "ptp"),
|
||||
PIN_GRP("ptp_clk", 21, 1, BIT(6), "ptp", "mii"),
|
||||
PIN_GRP("ptp_trig", 22, 1, BIT(7), "ptp", "mii"),
|
||||
PIN_GRP("mii_col", 23, 1, BIT(8), "mii", "mii_err"),
|
||||
PIN_GRP_GPIO_3("mii_col", 23, 1, BIT(8) | BIT(14), 0, BIT(8), BIT(14),
|
||||
"mii", "mii_err"),
|
||||
};
|
||||
|
||||
const struct armada_37xx_pin_data armada_37xx_pin_nb = {
|
||||
|
@ -189,18 +201,18 @@ const struct armada_37xx_pin_data armada_37xx_pin_nb = {
|
|||
};
|
||||
|
||||
const struct armada_37xx_pin_data armada_37xx_pin_sb = {
|
||||
.nr_pins = 29,
|
||||
.nr_pins = 30,
|
||||
.name = "GPIO2",
|
||||
.groups = armada_37xx_sb_groups,
|
||||
.ngroups = ARRAY_SIZE(armada_37xx_sb_groups),
|
||||
};
|
||||
|
||||
static inline void armada_37xx_update_reg(unsigned int *reg,
|
||||
unsigned int offset)
|
||||
unsigned int *offset)
|
||||
{
|
||||
/* We never have more than 2 registers */
|
||||
if (offset >= GPIO_PER_REG) {
|
||||
offset -= GPIO_PER_REG;
|
||||
if (*offset >= GPIO_PER_REG) {
|
||||
*offset -= GPIO_PER_REG;
|
||||
*reg += sizeof(u32);
|
||||
}
|
||||
}
|
||||
|
@ -210,7 +222,7 @@ static int armada_37xx_get_func_reg(struct armada_37xx_pin_group *grp,
|
|||
{
|
||||
int f;
|
||||
|
||||
for (f = 0; f < NB_FUNCS; f++)
|
||||
for (f = 0; (f < NB_FUNCS) && grp->funcs[f]; f++)
|
||||
if (!strcmp(grp->funcs[f], func))
|
||||
return f;
|
||||
|
||||
|
@ -352,7 +364,7 @@ static int armada_37xx_fill_group(struct armada_37xx_pinctrl *info)
|
|||
for (j = 0; j < grp->extra_npins; j++)
|
||||
grp->pins[i+j] = grp->extra_pin + j;
|
||||
|
||||
for (f = 0; f < NB_FUNCS; f++) {
|
||||
for (f = 0; (f < NB_FUNCS) && grp->funcs[f]; f++) {
|
||||
int ret;
|
||||
/* check for unique functions and count groups */
|
||||
ret = armada_37xx_add_function(info->funcs, &funcsize,
|
||||
|
@ -404,7 +416,7 @@ static int armada_37xx_fill_func(struct armada_37xx_pinctrl *info)
|
|||
struct armada_37xx_pin_group *gp = &info->groups[g];
|
||||
int f;
|
||||
|
||||
for (f = 0; f < NB_FUNCS; f++) {
|
||||
for (f = 0; (f < NB_FUNCS) && gp->funcs[f]; f++) {
|
||||
if (strcmp(gp->funcs[f], name) == 0) {
|
||||
*groups = gp->name;
|
||||
groups++;
|
||||
|
@ -421,7 +433,7 @@ static int armada_37xx_gpio_get(struct udevice *dev, unsigned int offset)
|
|||
unsigned int reg = INPUT_VAL;
|
||||
unsigned int val, mask;
|
||||
|
||||
armada_37xx_update_reg(®, offset);
|
||||
armada_37xx_update_reg(®, &offset);
|
||||
mask = BIT(offset);
|
||||
|
||||
val = readl(info->base + reg);
|
||||
|
@ -436,7 +448,7 @@ static int armada_37xx_gpio_set(struct udevice *dev, unsigned int offset,
|
|||
unsigned int reg = OUTPUT_VAL;
|
||||
unsigned int mask, val;
|
||||
|
||||
armada_37xx_update_reg(®, offset);
|
||||
armada_37xx_update_reg(®, &offset);
|
||||
mask = BIT(offset);
|
||||
val = value ? mask : 0;
|
||||
|
||||
|
@ -452,7 +464,7 @@ static int armada_37xx_gpio_get_direction(struct udevice *dev,
|
|||
unsigned int reg = OUTPUT_EN;
|
||||
unsigned int val, mask;
|
||||
|
||||
armada_37xx_update_reg(®, offset);
|
||||
armada_37xx_update_reg(®, &offset);
|
||||
mask = BIT(offset);
|
||||
val = readl(info->base + reg);
|
||||
|
||||
|
@ -469,7 +481,7 @@ static int armada_37xx_gpio_direction_input(struct udevice *dev,
|
|||
unsigned int reg = OUTPUT_EN;
|
||||
unsigned int mask;
|
||||
|
||||
armada_37xx_update_reg(®, offset);
|
||||
armada_37xx_update_reg(®, &offset);
|
||||
mask = BIT(offset);
|
||||
|
||||
clrbits_le32(info->base + reg, mask);
|
||||
|
@ -484,7 +496,7 @@ static int armada_37xx_gpio_direction_output(struct udevice *dev,
|
|||
unsigned int reg = OUTPUT_EN;
|
||||
unsigned int mask;
|
||||
|
||||
armada_37xx_update_reg(®, offset);
|
||||
armada_37xx_update_reg(®, &offset);
|
||||
mask = BIT(offset);
|
||||
|
||||
setbits_le32(info->base + reg, mask);
|
||||
|
|
|
@ -106,4 +106,23 @@
|
|||
#define CONFIG_E1000
|
||||
#endif
|
||||
|
||||
#define BOOT_TARGET_DEVICES(func) \
|
||||
func(MMC, mmc, 1) \
|
||||
func(MMC, mmc, 0) \
|
||||
func(USB, usb, 0) \
|
||||
func(SCSI, scsi, 0) \
|
||||
func(PXE, pxe, na) \
|
||||
func(DHCP, dhcp, na)
|
||||
|
||||
#include <config_distro_bootcmd.h>
|
||||
|
||||
#define CONFIG_EXTRA_ENV_SETTINGS \
|
||||
"scriptaddr=0x4d00000\0" \
|
||||
"pxefile_addr_r=0x4e00000\0" \
|
||||
"fdt_addr_r=0x4f00000\0" \
|
||||
"kernel_addr_r=0x5000000\0" \
|
||||
"ramdisk_addr_r=0x8000000\0" \
|
||||
"fdtfile=marvell/" CONFIG_DEFAULT_DEVICE_TREE ".dtb\0" \
|
||||
BOOTENV
|
||||
|
||||
#endif /* _CONFIG_MVEBU_ARMADA_8K_H */
|
||||
|
|
|
@ -1616,6 +1616,10 @@ static int kwbimage_verify_header(unsigned char *ptr, int image_size,
|
|||
struct image_tool_params *params)
|
||||
{
|
||||
uint8_t checksum;
|
||||
size_t header_size = kwbimage_header_size(ptr);
|
||||
|
||||
if (header_size > image_size)
|
||||
return -FDT_ERR_BADSTRUCTURE;
|
||||
|
||||
if (!main_hdr_checksum_ok(ptr))
|
||||
return -FDT_ERR_BADSTRUCTURE;
|
||||
|
|
Loading…
Add table
Reference in a new issue