arm: add initial support for the Phytium Durian Board

This adds platform code and the device tree for the Phytium Durian Board.
The initial support comprises the UART and the PCIE.

Cc: Bin Meng <bmeng.cn@gmail.com>
Cc: Kever Yang <kever.yang@rock-chips.com>
Cc: Tom Rini <trini@konsulko.com>
Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>

Signed-off-by: Steven Hao <liuhao@phytium.com.cn>
This commit is contained in:
liu hao 2019-10-31 07:51:08 +00:00 committed by Tom Rini
parent 672c57057f
commit e3aafef4cf
15 changed files with 556 additions and 0 deletions

View file

@ -481,6 +481,13 @@ S: Maintained
T: git https://gitlab.denx.de/u-boot/custodians/u-boot-microblaze.git
F: arch/arm/mach-zynqmp-r5/
ARM PHYTIUM
M: liuhao <liuhao@phytium.com.cn>
M: shuyiqi <shuyiqi@phytium.com.cn>
S: Maintained
F: drivers/pci/pcie_phytium.c
F: arch/arm/dts/phytium-durian.dts
BINMAN
M: Simon Glass <sjg@chromium.org>
S: Maintained

View file

@ -1631,6 +1631,13 @@ config ARCH_ASPEED
select OF_CONTROL
imply CMD_DM
config TARGET_DURIAN
bool "Support Phytium Durian Platform"
select ARM64
help
Support for durian platform.
It has 2GB Sdram, uart and pcie.
endchoice
config ARCH_SUPPORT_TFABOOT
@ -1830,6 +1837,7 @@ source "board/woodburn/Kconfig"
source "board/xilinx/Kconfig"
source "board/xilinx/zynq/Kconfig"
source "board/xilinx/zynqmp/Kconfig"
source "board/phytium/durian/Kconfig"
source "arch/arm/Kconfig.debug"

View file

@ -834,6 +834,8 @@ dtb-$(CONFIG_TARGET_VEXPRESS_CA5X2) += vexpress-v2p-ca5s.dtb
dtb-$(CONFIG_TARGET_VEXPRESS_CA9X4) += vexpress-v2p-ca9.dtb
dtb-$(CONFIG_TARGET_VEXPRESS_CA15_TC2) += vexpress-v2p-ca15_a7.dtb
dtb-$(CONFIG_TARGET_DURIAN) += phytium-durian.dtb
targets += $(dtb-y)
# Add any required device tree compiler flags here

View file

@ -0,0 +1,33 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2019, Phytium Ltd.
* shuyiqi <shuyiqi@phytium.com.cn>
*/
/dts-v1/;
/ {
model = "Phytium Durian";
compatible = "phytium,durian";
#address-cells = <2>;
#size-cells = <2>;
pcie-controller@40000000 {
compatible = "phytium,pcie-host-1.0";
device_type = "pci";
#address-cells = <3>;
#size-cells = <2>;
reg = <0x0 0x40000000 0x0 0x10000000>;
bus-range = <0x0 0xff>;
ranges = <0x1000000 0x0 0x0 0x0 0x50000000 0x0 0xF00000>,
<0x2000000 0x0 0x58000000 0x0 0x58000000 0x0 0x28000000>,
<0x43000000 0x10 0x00000000 0x10 0x00000000 0x10 0x00000000>;
};
uart@28001000 {
compatible = "arm,pl011";
reg = <0x0 0x28001000 0x0 0x1000>;
clock = <48000000>;
};
};

View file

@ -0,0 +1,12 @@
if TARGET_DURIAN
config SYS_BOARD
default "durian"
config SYS_VENDOR
default "phytium"
config SYS_CONFIG_NAME
default "durian"
endif

View file

@ -0,0 +1,8 @@
DURIAN BOARD
M: liuhao <liuhao@phytium.com.cn>
M: shuyiqi <shuyiqi@phytium.com.cn>
S: Maintained
F: board/phytium/durian/*
F: include/configs/durian.h
F: configs/durian_defconfig

View file

@ -0,0 +1,9 @@
# SPDX-License-Identifier: GPL-2.0+
#
# Copyright (C) 2019
# shuyiqi <shuyiqi@phytium.com.cn>
# liuhao <liuhao@phytium.com.cn>
#
obj-y += durian.o

View file

@ -0,0 +1,59 @@
Here is the step-by-step to boot U-Boot on phytium durian board.
Compile U-Boot
==============
> make durian_defconfig
> make
Get the prebuild binary about BPF
=================================
> cd ../
> git clone https://github.com/phytium-durian/bpf.git
Package the image
=================
> cd bpf
> cp ../u-boot/u-boot.bin ./
> ./dopack
The fip-all.bin is the final image.
Flash the image into the spi nor-flash
======================================
Any spi nor-flash and appropriate tool can be used to flash.
For example, we choose the S25FL256 chip that produced from
SPANSION company and EZP_XPro V1.2.
Reset the board, you can get U-Boot log message from boot console:
Power on...
Start pcie setup!
End pcie setup!
Start ddr setup!
End ddr setup!
Jump to entrypoint: 0x500000
U-Boot 2019.10-00594-g9ccc1b17ea-dirty (Oct 18 2019 - 00:17:09 +0800)
DRAM: 1.9 GiB
In: uart@28001000
Out: uart@28001000
Err: uart@28001000
scanning bus for devices...
Target spinup took 0 ms.
SATA link 1 timeout.
SATA link 2 timeout.
SATA link 3 timeout.
AHCI 0001.0000 32 slots 4 ports 6 Gbps 0xf impl SATA mode
flags: 64bit ncq led only pmp fbss pio slum part sxs
Device 0: (0:0) Vendor: ATA Prod.: ST1000DM010-2EP1 Rev: CC43
Type: Hard Disk
Capacity: 953869.7 MB = 931.5 GB (1953525168 x 512)
SATA link 0 timeout.
SATA link 1 timeout.
SATA link 2 timeout.
SATA link 3 timeout.
AHCI 0001.0000 32 slots 4 ports 6 Gbps 0xf impl SATA mode
flags: 64bit ncq led only pmp fbss pio slum part sxs
Hit any key to stop autoboot: 0
durian#

View file

@ -0,0 +1,23 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* (C) Copyright 2019
* Phytium Technology Ltd <www.phytium.com>
* shuyiqi <shuyiqi@phytium.com.cn>
*/
#ifndef _FT_DURIAN_H
#define _FT_DURIAN_H
/* FLUSH L3 CASHE */
#define HNF_COUNT 0x8
#define HNF_PSTATE_REQ (HNF_BASE + 0x10)
#define HNF_PSTATE_STAT (HNF_BASE + 0x18)
#define HNF_PSTATE_OFF 0x0
#define HNF_PSTATE_SFONLY 0x1
#define HNF_PSTATE_HALF 0x2
#define HNF_PSTATE_FULL 0x3
#define HNF_STRIDE 0x10000
#define HNF_BASE (unsigned long)(0x3A200000)
#endif /* _FT_DURIAN_H */

View file

@ -0,0 +1,110 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2019
* shuyiqi <shuyiqi@phytium.com.cn>
* liuhao <liuhao@phytium.com.cn>
*/
#include <common.h>
#include <asm/armv8/mmu.h>
#include <asm/system.h>
#include <asm/io.h>
#include <linux/arm-smccc.h>
#include <linux/kernel.h>
#include <scsi.h>
#include "cpu.h"
DECLARE_GLOBAL_DATA_PTR;
int dram_init(void)
{
gd->mem_clk = 0;
gd->ram_size = PHYS_SDRAM_1_SIZE;
return 0;
}
int dram_init_banksize(void)
{
gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE;
return 0;
}
int board_init(void)
{
return 0;
}
void reset_cpu(ulong addr)
{
struct arm_smccc_res res;
arm_smccc_smc(0x84000009, 0, 0, 0, 0, 0, 0, 0, &res);
debug("reset cpu error, %lx\n", res.a0);
}
static struct mm_region durian_mem_map[] = {
{
.virt = 0x0UL,
.phys = 0x0UL,
.size = 0x80000000UL,
.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
PTE_BLOCK_NON_SHARE |
PTE_BLOCK_PXN |
PTE_BLOCK_UXN
},
{
.virt = (u64)PHYS_SDRAM_1,
.phys = (u64)PHYS_SDRAM_1,
.size = (u64)PHYS_SDRAM_1_SIZE,
.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
PTE_BLOCK_NS |
PTE_BLOCK_INNER_SHARE
},
{
0,
}
};
struct mm_region *mem_map = durian_mem_map;
int print_cpuinfo(void)
{
printf("CPU: Phytium ft2004 %ld MHz\n", gd->cpu_clk);
return 0;
}
int __asm_flush_l3_dcache(void)
{
int i, pstate;
for (i = 0; i < HNF_COUNT; i++)
writeq(HNF_PSTATE_SFONLY, HNF_PSTATE_REQ + i * HNF_STRIDE);
for (i = 0; i < HNF_COUNT; i++) {
do {
pstate = readq(HNF_PSTATE_STAT + i * HNF_STRIDE);
} while ((pstate & 0xf) != (HNF_PSTATE_SFONLY << 2));
}
for (i = 0; i < HNF_COUNT; i++)
writeq(HNF_PSTATE_FULL, HNF_PSTATE_REQ + i * HNF_STRIDE);
return 0;
}
int last_stage_init(void)
{
int ret;
/* pci e */
pci_init();
/* scsi scan */
ret = scsi_scan(true);
if (ret) {
printf("scsi scan failed\n");
return CMD_RET_FAILURE;
}
return ret;
}

33
configs/durian_defconfig Normal file
View file

@ -0,0 +1,33 @@
CONFIG_ARM=y
CONFIG_ARM_SMCCC=y
CONFIG_TARGET_DURIAN=y
CONFIG_SYS_TEXT_BASE=0x500000
CONFIG_NR_DRAM_BANKS=1
# CONFIG_PSCI_RESET is not set
CONFIG_AHCI=y
CONFIG_DISTRO_DEFAULTS=y
CONFIG_USE_BOOTARGS=y
CONFIG_BOOTARGS="console=ttyAMA0,115200 earlycon=pl011,0x28001000 root=/dev/sda2 rw"
# CONFIG_DISPLAY_CPUINFO is not set
# CONFIG_DISPLAY_BOARDINFO is not set
CONFIG_LAST_STAGE_INIT=y
CONFIG_SYS_PROMPT="durian#"
# CONFIG_CMD_LZMADEC is not set
# CONFIG_CMD_UNZIP is not set
CONFIG_CMD_PCI=y
CONFIG_OF_CONTROL=y
CONFIG_DEFAULT_DEVICE_TREE="phytium-durian"
# CONFIG_NET is not set
CONFIG_DM=y
CONFIG_SCSI_AHCI=y
CONFIG_AHCI_PCI=y
CONFIG_BLK=y
# CONFIG_MMC is not set
CONFIG_PCI=y
CONFIG_DM_PCI=y
CONFIG_DM_PCI_COMPAT=y
CONFIG_PCI_PHYTIUM=y
CONFIG_SCSI=y
CONFIG_DM_SCSI=y
CONFIG_DM_SERIAL=y
CONFIG_PL01X_SERIAL=y

View file

@ -51,6 +51,13 @@ config PCIE_ECAM_GENERIC
Say Y here if you want to enable support for generic ECAM-based
PCIe host controllers, such as the one emulated by QEMU.
config PCI_PHYTIUM
bool "Phytium PCIe support"
depends on DM_PCI
help
Say Y here if you want to enable PCIe controller support on
Phytium SoCs.
config PCIE_DW_MVEBU
bool "Enable Armada-8K PCIe driver (DesignWare core)"
depends on DM_PCI

View file

@ -38,6 +38,7 @@ obj-$(CONFIG_PCIE_LAYERSCAPE) += pcie_layerscape_fixup.o
obj-$(CONFIG_PCIE_LAYERSCAPE_GEN4) += pcie_layerscape_gen4.o \
pcie_layerscape_gen4_fixup.o
obj-$(CONFIG_PCI_XILINX) += pcie_xilinx.o
obj-$(CONFIG_PCI_PHYTIUM) += pcie_phytium.o
obj-$(CONFIG_PCIE_INTEL_FPGA) += pcie_intel_fpga.o
obj-$(CONFIG_PCI_KEYSTONE) += pcie_dw_ti.o
obj-$(CONFIG_PCIE_MEDIATEK) += pcie_mediatek.o

200
drivers/pci/pcie_phytium.c Normal file
View file

@ -0,0 +1,200 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Phytium PCIE host driver
*
* Heavily based on drivers/pci/pcie_xilinx.c
*
* Copyright (C) 2019
*/
#include <common.h>
#include <dm.h>
#include <pci.h>
#include <asm/io.h>
/**
* struct phytium_pcie - phytium PCIe controller state
* @cfg_base: The base address of memory mapped configuration space
*/
struct phytium_pcie {
void *cfg_base;
};
/*
* phytium_pci_skip_dev()
* @parent: Identifies the PCIe device to access
*
* Checks whether the parent of the PCIe device is bridge
*
* Return: true if it is bridge, else false.
*/
static int phytium_pci_skip_dev(pci_dev_t parent)
{
unsigned char pos, id;
unsigned long addr = 0x40000000;
unsigned short capreg;
unsigned char port_type;
addr += PCI_BUS(parent) << 20;
addr += PCI_DEV(parent) << 15;
addr += PCI_FUNC(parent) << 12;
pos = 0x34;
while (1) {
pos = readb(addr + pos);
if (pos < 0x40)
break;
pos &= ~3;
id = readb(addr + pos);
if (id == 0xff)
break;
if (id == 0x10) {
capreg = readw(addr + pos + 2);
port_type = (capreg >> 4) & 0xf;
if (port_type == 0x6 || port_type == 0x4)
return 1;
else
return 0;
}
pos += 1;
}
return 0;
}
/**
* pci_phytium_conf_address() - Calculate the address of a config access
* @bus: Pointer to the PCI bus
* @bdf: Identifies the PCIe device to access
* @offset: The offset into the device's configuration space
* @paddress: Pointer to the pointer to write the calculates address to
*
* Calculates the address that should be accessed to perform a PCIe
* configuration space access for a given device identified by the PCIe
* controller device @pcie and the bus, device & function numbers in @bdf. If
* access to the device is not valid then the function will return an error
* code. Otherwise the address to access will be written to the pointer pointed
* to by @paddress.
*/
static int pci_phytium_conf_address(struct udevice *bus, pci_dev_t bdf,
uint offset,
void **paddress)
{
struct phytium_pcie *pcie = dev_get_priv(bus);
void *addr;
pci_dev_t bdf_parent;
unsigned int bus_no = PCI_BUS(bdf);
unsigned int dev_no = PCI_DEV(bdf);
bdf_parent = PCI_BDF((bus_no - 1), 0, 0);
addr = pcie->cfg_base;
addr += PCI_BUS(bdf) << 20;
addr += PCI_DEV(bdf) << 15;
addr += PCI_FUNC(bdf) << 12;
if (bus_no > 0 && dev_no > 0) {
if ((readb(addr + PCI_HEADER_TYPE) & 0x7f) !=
PCI_HEADER_TYPE_BRIDGE)
return -ENODEV;
if (phytium_pci_skip_dev(bdf_parent))
return -ENODEV;
}
addr += offset;
*paddress = addr;
return 0;
}
/**
* pci_phytium_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.
*/
static int pci_phytium_read_config(struct udevice *bus, pci_dev_t bdf,
uint offset, ulong *valuep,
enum pci_size_t size)
{
return pci_generic_mmap_read_config(bus, pci_phytium_conf_address,
bdf, offset, valuep, size);
}
/**
* pci_phytium_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.
*/
static int pci_phytium_write_config(struct udevice *bus, pci_dev_t bdf,
uint offset, ulong value,
enum pci_size_t size)
{
return pci_generic_mmap_write_config(bus, pci_phytium_conf_address,
bdf, offset, value, size);
}
/**
* pci_phytium_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 pci_phytium_ofdata_to_platdata(struct udevice *dev)
{
struct phytium_pcie *pcie = dev_get_priv(dev);
struct fdt_resource reg_res;
DECLARE_GLOBAL_DATA_PTR;
int err;
err = fdt_get_resource(gd->fdt_blob, dev_of_offset(dev), "reg",
0, &reg_res);
if (err < 0) {
pr_err("\"reg\" resource not found\n");
return err;
}
pcie->cfg_base = map_physmem(reg_res.start,
fdt_resource_size(&reg_res),
MAP_NOCACHE);
return 0;
}
static const struct dm_pci_ops pci_phytium_ops = {
.read_config = pci_phytium_read_config,
.write_config = pci_phytium_write_config,
};
static const struct udevice_id pci_phytium_ids[] = {
{ .compatible = "phytium,pcie-host-1.0" },
{ }
};
U_BOOT_DRIVER(pci_phytium) = {
.name = "pci_phytium",
.id = UCLASS_PCI,
.of_match = pci_phytium_ids,
.ops = &pci_phytium_ops,
.ofdata_to_platdata = pci_phytium_ofdata_to_platdata,
.priv_auto_alloc_size = sizeof(struct phytium_pcie),
};

44
include/configs/durian.h Normal file
View file

@ -0,0 +1,44 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Copyright (C) 2019
* shuyiqi <shuyiqi@phytium.com.cn>
* liuhao <liuhao@phytium.com.cn>
*/
#ifndef __DURIAN_CONFIG_H__
#define __DURIAN_CONFIG_H__
/* Sdram Bank #1 Address */
#define PHYS_SDRAM_1 0x80000000
#define PHYS_SDRAM_1_SIZE 0x7B000000
#define CONFIG_SYS_SDRAM_BASE PHYS_SDRAM_1
#define CONFIG_SYS_LOAD_ADDR (CONFIG_SYS_SDRAM_BASE + 0x10000000)
/* Size of Malloc Pool */
#define CONFIG_ENV_SIZE 4096
#define CONFIG_SYS_MALLOC_LEN (1 * 1024 * 1024 + CONFIG_ENV_SIZE)
#define CONFIG_SYS_INIT_SP_ADDR (0x88000000 - 0x100000)
/* PCI CONFIG */
#define CONFIG_SYS_PCI_64BIT 1
#define CONFIG_PCI_SCAN_SHOW
/* SCSI */
#define CONFIG_SYS_SCSI_MAX_SCSI_ID 4
#define CONFIG_SYS_SCSI_MAX_LUN 1
#define CONFIG_SYS_SCSI_MAX_DEVICE 128
#define CONFIG_SCSI_AHCI_PLAT
#define CONFIG_SYS_SATA_MAX_DEVICE 4
/* BOOT */
#define CONFIG_SYS_BOOTM_LEN (60 * 1024 * 1024)
#define CONFIG_EXTRA_ENV_SETTINGS \
"load_kernel=ext4load scsi 0:1 0x90100000 uImage-2004\0" \
"load_fdt=ext4load scsi 0:1 0x95000000 ft2004-pci-64.dtb\0"\
"boot_fdt=bootm 0x90100000 -:- 0x95000000\0" \
"distro_bootcmd=run load_kernel; run load_fdt; run boot_fdt"
#endif