+ Fix compilation error for CI when enabling RTL8169 driver
+ Fix compilation error for pci_mmc.c by adding acpi_table header file
+ Support video console and usb keyboard on RISC-V QEMU virt machine
+ Support StarFive JH7110 PCIe driver
+ Enable PCI on Unmatched board
This commit is contained in:
Tom Rini 2023-08-02 12:13:16 -04:00
commit 38dedebc54
20 changed files with 755 additions and 64 deletions

View File

@ -7,6 +7,7 @@
#include "jh7110.dtsi" #include "jh7110.dtsi"
#include <dt-bindings/pinctrl/pinctrl-starfive-jh7110.h> #include <dt-bindings/pinctrl/pinctrl-starfive-jh7110.h>
#include <dt-bindings/gpio/gpio.h>
/ { / {
aliases { aliases {
serial0 = &uart0; serial0 = &uart0;
@ -308,6 +309,16 @@
}; };
}; };
&pcie0 {
reset-gpios = <&sysgpio 26 GPIO_ACTIVE_LOW>;
status = "disabled";
};
&pcie1 {
reset-gpios = <&sysgpio 28 GPIO_ACTIVE_LOW>;
status = "okay";
};
&syscrg { &syscrg {
assigned-clocks = <&syscrg JH7110_SYSCLK_CPU_ROOT>, assigned-clocks = <&syscrg JH7110_SYSCLK_CPU_ROOT>,
<&syscrg JH7110_SYSCLK_BUS_ROOT>, <&syscrg JH7110_SYSCLK_BUS_ROOT>,

View File

@ -648,5 +648,79 @@
gpio-controller; gpio-controller;
#gpio-cells = <2>; #gpio-cells = <2>;
}; };
pcie0: pcie@2b000000 {
compatible = "starfive,jh7110-pcie";
reg = <0x0 0x2b000000 0x0 0x1000000
0x9 0x40000000 0x0 0x10000000>;
reg-names = "reg", "config";
#address-cells = <3>;
#size-cells = <2>;
#interrupt-cells = <1>;
ranges = <0x82000000 0x0 0x30000000 0x0 0x30000000 0x0 0x08000000>,
<0xc3000000 0x9 0x00000000 0x9 0x00000000 0x0 0x40000000>;
interrupts = <56>;
interrupt-parent = <&plic>;
interrupt-map-mask = <0x0 0x0 0x0 0x7>;
interrupt-map = <0x0 0x0 0x0 0x1 &plic 0x1>,
<0x0 0x0 0x0 0x2 &plic 0x2>,
<0x0 0x0 0x0 0x3 &plic 0x3>,
<0x0 0x0 0x0 0x4 &plic 0x4>;
msi-parent = <&plic>;
device_type = "pci";
starfive,stg-syscon = <&stg_syscon 0xc0 0xc4 0x130 0x1b8>;
bus-range = <0x0 0xff>;
clocks = <&syscrg JH7110_SYSCLK_NOC_BUS_STG_AXI>,
<&stgcrg JH7110_STGCLK_PCIE0_TL>,
<&stgcrg JH7110_STGCLK_PCIE0_AXI>,
<&stgcrg JH7110_STGCLK_PCIE0_APB>;
clock-names = "noc", "tl", "axi", "apb";
resets = <&stgcrg JH7110_STGRST_PCIE0_MST0>,
<&stgcrg JH7110_STGRST_PCIE0_SLV0>,
<&stgcrg JH7110_STGRST_PCIE0_SLV>,
<&stgcrg JH7110_STGRST_PCIE0_BRG>,
<&stgcrg JH7110_STGRST_PCIE0_CORE>,
<&stgcrg JH7110_STGRST_PCIE0_APB>;
reset-names = "mst0", "slv0", "slv", "brg",
"core", "apb";
status = "disabled";
};
pcie1: pcie@2c000000 {
compatible = "starfive,jh7110-pcie";
reg = <0x0 0x2c000000 0x0 0x1000000
0x9 0xc0000000 0x0 0x10000000>;
reg-names = "reg", "config";
#address-cells = <3>;
#size-cells = <2>;
#interrupt-cells = <1>;
ranges = <0x82000000 0x0 0x38000000 0x0 0x38000000 0x0 0x08000000>,
<0xc3000000 0x9 0x80000000 0x9 0x80000000 0x0 0x40000000>;
interrupts = <57>;
interrupt-parent = <&plic>;
interrupt-map-mask = <0x0 0x0 0x0 0x7>;
interrupt-map = <0x0 0x0 0x0 0x1 &plic 0x1>,
<0x0 0x0 0x0 0x2 &plic 0x2>,
<0x0 0x0 0x0 0x3 &plic 0x3>,
<0x0 0x0 0x0 0x4 &plic 0x4>;
msi-parent = <&plic>;
device_type = "pci";
starfive,stg-syscon = <&stg_syscon 0x270 0x274 0x2e0 0x368>;
bus-range = <0x0 0xff>;
clocks = <&syscrg JH7110_SYSCLK_NOC_BUS_STG_AXI>,
<&stgcrg JH7110_STGCLK_PCIE1_TL>,
<&stgcrg JH7110_STGCLK_PCIE1_AXI>,
<&stgcrg JH7110_STGCLK_PCIE1_APB>;
clock-names = "noc", "tl", "axi", "apb";
resets = <&stgcrg JH7110_STGRST_PCIE1_MST0>,
<&stgcrg JH7110_STGRST_PCIE1_SLV0>,
<&stgcrg JH7110_STGRST_PCIE1_SLV>,
<&stgcrg JH7110_STGRST_PCIE1_BRG>,
<&stgcrg JH7110_STGRST_PCIE1_CORE>,
<&stgcrg JH7110_STGRST_PCIE1_APB>;
reset-names = "mst0", "slv0", "slv", "brg",
"core", "apb";
status = "disabled";
};
}; };
}; };

View File

@ -0,0 +1,11 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#ifndef __ASM_ACPI_TABLE_H__
#define __ASM_ACPI_TABLE_H__
/*
* This file is needed by some drivers.
* We will fill it when adding ACPI support for RISC-V.
*/
#endif /* __ASM_ACPI_TABLE_H__ */

View File

@ -25,6 +25,10 @@ config SPL_OPENSBI_LOAD_ADDR
hex hex
default 0x80100000 default 0x80100000
config PRE_CON_BUF_ADDR
hex
default 0x81000000
config BOARD_SPECIFIC_OPTIONS # dummy config BOARD_SPECIFIC_OPTIONS # dummy
def_bool y def_bool y
select GENERIC_RISCV select GENERIC_RISCV
@ -68,5 +72,14 @@ config BOARD_SPECIFIC_OPTIONS # dummy
imply MTD_NOR_FLASH imply MTD_NOR_FLASH
imply CFI_FLASH imply CFI_FLASH
imply OF_HAS_PRIOR_STAGE imply OF_HAS_PRIOR_STAGE
imply VIDEO
imply VIDEO_BOCHS
imply SYS_WHITE_ON_BLACK
imply PRE_CONSOLE_BUFFER
imply USB
imply USB_XHCI_HCD
imply USB_XHCI_PCI
imply USB_KEYBOARD
imply CMD_USB
endif endif

View File

@ -12,6 +12,7 @@
#include <log.h> #include <log.h>
#include <spl.h> #include <spl.h>
#include <init.h> #include <init.h>
#include <usb.h>
#include <virtio_types.h> #include <virtio_types.h>
#include <virtio.h> #include <virtio.h>
@ -41,29 +42,9 @@ int board_init(void)
int board_late_init(void) int board_late_init(void)
{ {
ulong kernel_start; /* start usb so that usb keyboard can be used as input device */
ofnode chosen_node; if (CONFIG_IS_ENABLED(USB_KEYBOARD))
int ret; usb_init();
chosen_node = ofnode_path("/chosen");
if (!ofnode_valid(chosen_node)) {
debug("No chosen node found, can't get kernel start address\n");
return 0;
}
#ifdef CONFIG_ARCH_RV64I
ret = ofnode_read_u64(chosen_node, "riscv,kernel-start",
(u64 *)&kernel_start);
#else
ret = ofnode_read_u32(chosen_node, "riscv,kernel-start",
(u32 *)&kernel_start);
#endif
if (ret) {
debug("Can't find kernel start address in device tree\n");
return 0;
}
env_set_hex("kernel_start", kernel_start);
return 0; return 0;
} }

View File

@ -226,7 +226,7 @@ config CONSOLE_FLUSH_SUPPORT
config CONSOLE_MUX config CONSOLE_MUX
bool "Enable console multiplexing" bool "Enable console multiplexing"
default y if VIDEO || VIDEO || LCD default y if VIDEO || LCD
help help
This allows multiple devices to be used for each console 'file'. This allows multiple devices to be used for each console 'file'.
For example, stdout can be set to go to serial and video. For example, stdout can be set to go to serial and video.

View File

@ -1010,29 +1010,41 @@ int console_init_f(void)
return 0; return 0;
} }
void stdio_print_current_devices(void) static void stdio_print_current_devices(void)
{ {
char *stdinname, *stdoutname, *stderrname;
if (CONFIG_IS_ENABLED(CONSOLE_MUX) &&
CONFIG_IS_ENABLED(SYS_CONSOLE_IS_IN_ENV)) {
/* stdin stdout and stderr are in environment */
stdinname = env_get("stdin");
stdoutname = env_get("stdout");
stderrname = env_get("stderr");
stdinname = stdinname ? : "No input devices available!";
stdoutname = stdoutname ? : "No output devices available!";
stderrname = stderrname ? : "No error devices available!";
} else {
stdinname = stdio_devices[stdin] ?
stdio_devices[stdin]->name :
"No input devices available!";
stdoutname = stdio_devices[stdout] ?
stdio_devices[stdout]->name :
"No output devices available!";
stderrname = stdio_devices[stderr] ?
stdio_devices[stderr]->name :
"No error devices available!";
}
/* Print information */ /* Print information */
puts("In: "); puts("In: ");
if (stdio_devices[stdin] == NULL) { printf("%s\n", stdinname);
puts("No input devices available!\n");
} else {
printf ("%s\n", stdio_devices[stdin]->name);
}
puts("Out: "); puts("Out: ");
if (stdio_devices[stdout] == NULL) { printf("%s\n", stdoutname);
puts("No output devices available!\n");
} else {
printf ("%s\n", stdio_devices[stdout]->name);
}
puts("Err: "); puts("Err: ");
if (stdio_devices[stderr] == NULL) { printf("%s\n", stderrname);
puts("No error devices available!\n");
} else {
printf ("%s\n", stdio_devices[stderr]->name);
}
} }
#if CONFIG_IS_ENABLED(SYS_CONSOLE_IS_IN_ENV) #if CONFIG_IS_ENABLED(SYS_CONSOLE_IS_IN_ENV)

View File

@ -31,6 +31,7 @@ CONFIG_DISPLAY_CPUINFO=y
CONFIG_DISPLAY_BOARDINFO=y CONFIG_DISPLAY_BOARDINFO=y
CONFIG_DISPLAY_BOARDINFO_LATE=y CONFIG_DISPLAY_BOARDINFO_LATE=y
CONFIG_ID_EEPROM=y CONFIG_ID_EEPROM=y
CONFIG_PCI_INIT_R=y
CONFIG_SPL_MAX_SIZE=0x100000 CONFIG_SPL_MAX_SIZE=0x100000
CONFIG_SPL_BSS_START_ADDR=0x85000000 CONFIG_SPL_BSS_START_ADDR=0x85000000
# CONFIG_SPL_SHARES_INIT_SP_ADDR is not set # CONFIG_SPL_SHARES_INIT_SP_ADDR is not set

View File

@ -19,6 +19,8 @@ CONFIG_SPL=y
CONFIG_SPL_SPI_FLASH_SUPPORT=y CONFIG_SPL_SPI_FLASH_SUPPORT=y
CONFIG_SPL_SPI=y CONFIG_SPL_SPI=y
CONFIG_SYS_LOAD_ADDR=0x82000000 CONFIG_SYS_LOAD_ADDR=0x82000000
CONFIG_SYS_PCI_64BIT=y
CONFIG_PCI=y
CONFIG_TARGET_STARFIVE_VISIONFIVE2=y CONFIG_TARGET_STARFIVE_VISIONFIVE2=y
CONFIG_SPL_OPENSBI_LOAD_ADDR=0x40000000 CONFIG_SPL_OPENSBI_LOAD_ADDR=0x40000000
CONFIG_ARCH_RV64I=y CONFIG_ARCH_RV64I=y
@ -62,6 +64,7 @@ CONFIG_SYS_EEPROM_PAGE_WRITE_BITS=4
CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS=5 CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS=5
CONFIG_CMD_MEMINFO=y CONFIG_CMD_MEMINFO=y
CONFIG_CMD_I2C=y CONFIG_CMD_I2C=y
CONFIG_CMD_PCI=y
CONFIG_CMD_TFTPPUT=y CONFIG_CMD_TFTPPUT=y
CONFIG_OF_BOARD=y CONFIG_OF_BOARD=y
CONFIG_SYS_RELOC_GD_ENV_ADDR=y CONFIG_SYS_RELOC_GD_ENV_ADDR=y
@ -92,6 +95,11 @@ CONFIG_DWC_ETH_QOS=y
CONFIG_DWC_ETH_QOS_STARFIVE=y CONFIG_DWC_ETH_QOS_STARFIVE=y
CONFIG_RGMII=y CONFIG_RGMII=y
CONFIG_RMII=y CONFIG_RMII=y
CONFIG_RTL8169=y
CONFIG_NVME_PCI=y
CONFIG_DM_PCI_COMPAT=y
CONFIG_PCI_REGION_MULTI_ENTRY=y
CONFIG_PCIE_STARFIVE_JH7110=y
CONFIG_PINCTRL=y CONFIG_PINCTRL=y
CONFIG_PINCONF=y CONFIG_PINCONF=y
CONFIG_SPL_PINCTRL=y CONFIG_SPL_PINCTRL=y

View File

@ -133,6 +133,16 @@ An attached disk can be emulated in RISC-V virt machine by adding::
You will have to run 'scsi scan' to use it. You will have to run 'scsi scan' to use it.
A video console can be emulated in RISC-V virt machine by removing "-nographic"
and adding::
-serial stdio -device VGA
In addition, a usb keyboard can be attached to an emulated xHCI controller in
RISC-V virt machine as an option of input devices by adding::
-device qemu-xhci,id=xhci -device usb-kbd,bus=xhci.0
Running with KVM Running with KVM
---------------- ----------------

View File

@ -231,6 +231,15 @@ config SYS_I2C_DW
controller is used in various SoCs, e.g. the ST SPEAr, Altera controller is used in various SoCs, e.g. the ST SPEAr, Altera
SoCFPGA, Synopsys ARC700 and some Intel x86 SoCs. SoCFPGA, Synopsys ARC700 and some Intel x86 SoCs.
config SYS_I2C_DW_PCI
bool "Designware PCI I2C Controller"
depends on SYS_I2C_DW && PCI && ACPIGEN
default y
help
Say yes here to select the Designware PCI I2C Host Controller.
This PCI I2C controller is the base on Desigware I2C host
controller.
config SYS_I2C_AST2600 config SYS_I2C_AST2600
bool "AST2600 I2C Controller" bool "AST2600 I2C Controller"
depends on DM_I2C && ARCH_ASPEED depends on DM_I2C && ARCH_ASPEED

View File

@ -18,9 +18,7 @@ obj-$(CONFIG_SYS_I2C_CADENCE) += i2c-cdns.o
obj-$(CONFIG_SYS_I2C_CA) += i2c-cortina.o obj-$(CONFIG_SYS_I2C_CA) += i2c-cortina.o
obj-$(CONFIG_SYS_I2C_DAVINCI) += davinci_i2c.o obj-$(CONFIG_SYS_I2C_DAVINCI) += davinci_i2c.o
obj-$(CONFIG_SYS_I2C_DW) += designware_i2c.o obj-$(CONFIG_SYS_I2C_DW) += designware_i2c.o
ifdef CONFIG_PCI obj-$(CONFIG_SYS_I2C_DW_PCI) += designware_i2c_pci.o
obj-$(CONFIG_SYS_I2C_DW) += designware_i2c_pci.o
endif
obj-$(CONFIG_SYS_I2C_FSL) += fsl_i2c.o obj-$(CONFIG_SYS_I2C_FSL) += fsl_i2c.o
obj-$(CONFIG_SYS_I2C_IHS) += ihs_i2c.o obj-$(CONFIG_SYS_I2C_IHS) += ihs_i2c.o
obj-$(CONFIG_SYS_I2C_INTEL) += intel_i2c.o obj-$(CONFIG_SYS_I2C_INTEL) += intel_i2c.o

View File

@ -96,12 +96,12 @@ static int media[MAX_UNITS] = { -1, -1, -1, -1, -1, -1, -1, -1 };
#define TX_TIMEOUT (6*HZ) #define TX_TIMEOUT (6*HZ)
/* write/read MMIO register. Notice: {read,write}[wl] do the necessary swapping */ /* write/read MMIO register. Notice: {read,write}[wl] do the necessary swapping */
#define RTL_W8(reg, val8) writeb((val8), ioaddr + (reg)) #define RTL_W8(reg, val8) writeb((val8), (void *)(ioaddr + (reg)))
#define RTL_W16(reg, val16) writew((val16), ioaddr + (reg)) #define RTL_W16(reg, val16) writew((val16), (void *)(ioaddr + (reg)))
#define RTL_W32(reg, val32) writel((val32), ioaddr + (reg)) #define RTL_W32(reg, val32) writel((val32), (void *)(ioaddr + (reg)))
#define RTL_R8(reg) readb(ioaddr + (reg)) #define RTL_R8(reg) readb((void *)(ioaddr + (reg)))
#define RTL_R16(reg) readw(ioaddr + (reg)) #define RTL_R16(reg) readw((void *)(ioaddr + (reg)))
#define RTL_R32(reg) readl(ioaddr + (reg)) #define RTL_R32(reg) readl((void *)(ioaddr + (reg)))
#define bus_to_phys(a) pci_mem_to_phys((pci_dev_t)(unsigned long)dev->priv, \ #define bus_to_phys(a) pci_mem_to_phys((pci_dev_t)(unsigned long)dev->priv, \
(pci_addr_t)(unsigned long)a) (pci_addr_t)(unsigned long)a)
@ -311,10 +311,12 @@ static unsigned char rxdata[RX_BUF_LEN];
* *
* This can be fixed by defining CONFIG_SYS_NONCACHED_MEMORY which will cause * This can be fixed by defining CONFIG_SYS_NONCACHED_MEMORY which will cause
* the driver to allocate descriptors from a pool of non-cached memory. * the driver to allocate descriptors from a pool of non-cached memory.
*
* Hardware maintain D-cache coherency in RISC-V architecture.
*/ */
#if RTL8169_DESC_SIZE < ARCH_DMA_MINALIGN #if RTL8169_DESC_SIZE < ARCH_DMA_MINALIGN
#if !defined(CONFIG_SYS_NONCACHED_MEMORY) && \ #if !defined(CONFIG_SYS_NONCACHED_MEMORY) && \
!CONFIG_IS_ENABLED(SYS_DCACHE_OFF) && !defined(CONFIG_X86) !CONFIG_IS_ENABLED(SYS_DCACHE_OFF) && !defined(CONFIG_X86) && !defined(CONFIG_RISCV)
#warning cache-line size is larger than descriptor size #warning cache-line size is larger than descriptor size
#endif #endif
#endif #endif
@ -351,10 +353,11 @@ static const unsigned int rtl8169_rx_config =
(RX_FIFO_THRESH << RxCfgFIFOShift) | (RX_DMA_BURST << RxCfgDMAShift); (RX_FIFO_THRESH << RxCfgFIFOShift) | (RX_DMA_BURST << RxCfgDMAShift);
static struct pci_device_id supported[] = { static struct pci_device_id supported[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8125) },
{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8161) },
{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8167) }, { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8167) },
{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8168) }, { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8168) },
{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8169) }, { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8169) },
{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8125) },
{} {}
}; };
@ -1049,8 +1052,9 @@ static int rtl8169_eth_probe(struct udevice *dev)
int ret; int ret;
switch (pplat->device) { switch (pplat->device) {
case 0x8168:
case 0x8125: case 0x8125:
case 0x8161:
case 0x8168:
region = 2; region = 2;
break; break;
default: default:

View File

@ -393,4 +393,17 @@ config PCIE_XILINX_NWL
Say 'Y' here if you want support for Xilinx / AMD NWL PCIe Say 'Y' here if you want support for Xilinx / AMD NWL PCIe
controller as Root Port. controller as Root Port.
config PCIE_PLDA_COMMON
bool
config PCIE_STARFIVE_JH7110
bool "Enable Starfive JH7110 PCIe driver"
select PCIE_PLDA_COMMON
imply STARFIVE_JH7110
imply CLK_JH7110
imply RESET_JH7110
help
Say Y here if you want to enable PLDA XpressRich PCIe controller
support on StarFive JH7110 SoC.
endif endif

View File

@ -50,3 +50,5 @@ obj-$(CONFIG_PCIE_OCTEON) += pcie_octeon.o
obj-$(CONFIG_PCIE_DW_SIFIVE) += pcie_dw_sifive.o obj-$(CONFIG_PCIE_DW_SIFIVE) += pcie_dw_sifive.o
obj-$(CONFIG_PCIE_UNIPHIER) += pcie_uniphier.o obj-$(CONFIG_PCIE_UNIPHIER) += pcie_uniphier.o
obj-$(CONFIG_PCIE_XILINX_NWL) += pcie-xilinx-nwl.o obj-$(CONFIG_PCIE_XILINX_NWL) += pcie-xilinx-nwl.o
obj-$(CONFIG_PCIE_PLDA_COMMON) += pcie_plda_common.o
obj-$(CONFIG_PCIE_STARFIVE_JH7110) += pcie_starfive_jh7110.o

View File

@ -0,0 +1,116 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* PLDA XpressRich PCIe host controller common functions.
*
* Copyright (C) 2023 StarFive Technology Co., Ltd.
*
*/
#include <common.h>
#include <clk.h>
#include <dm.h>
#include <pci.h>
#include <pci_ids.h>
#include <asm/global_data.h>
#include <asm/io.h>
#include <dm/device_compat.h>
#include <linux/delay.h>
#include <linux/iopoll.h>
#include "pcie_plda_common.h"
static bool plda_pcie_addr_valid(struct pcie_plda *plda, pci_dev_t bdf)
{
/*
* Single device limitation.
* PCIe controller contain HW issue that secondary bus of
* host bridge emumerate duplicate devices.
* Only can access device 0 in secondary bus.
*/
if (PCI_BUS(bdf) == plda->sec_busno && PCI_DEV(bdf) > 0)
return false;
return true;
}
static int plda_pcie_conf_address(const struct udevice *udev, pci_dev_t bdf,
uint offset, void **paddr)
{
struct pcie_plda *priv = dev_get_priv(udev);
int where = PCIE_ECAM_OFFSET(PCI_BUS(bdf), PCI_DEV(bdf),
PCI_FUNC(bdf), offset);
if (!plda_pcie_addr_valid(priv, bdf))
return -ENODEV;
*paddr = (void *)(priv->cfg_base + where);
return 0;
}
int plda_pcie_config_read(const struct udevice *udev, pci_dev_t bdf,
uint offset, ulong *valuep,
enum pci_size_t size)
{
return pci_generic_mmap_read_config(udev, plda_pcie_conf_address,
bdf, offset, valuep, size);
}
int plda_pcie_config_write(struct udevice *udev, pci_dev_t bdf,
uint offset, ulong value,
enum pci_size_t size)
{
struct pcie_plda *priv = dev_get_priv(udev);
int ret;
ret = pci_generic_mmap_write_config(udev, plda_pcie_conf_address,
bdf, offset, value, size);
/* record secondary bus number */
if (!ret && PCI_BUS(bdf) == dev_seq(udev) &&
PCI_DEV(bdf) == 0 && PCI_FUNC(bdf) == 0 &&
(offset == PCI_SECONDARY_BUS ||
(offset == PCI_PRIMARY_BUS && size != PCI_SIZE_8))) {
priv->sec_busno =
((offset == PCI_PRIMARY_BUS) ? (value >> 8) : value) & 0xff;
debug("Secondary bus number was changed to %d\n",
priv->sec_busno);
}
return ret;
}
int plda_pcie_set_atr_entry(struct pcie_plda *plda, phys_addr_t src_addr,
phys_addr_t trsl_addr, phys_size_t window_size,
int trsl_param)
{
void __iomem *base =
plda->reg_base + XR3PCI_ATR_AXI4_SLV0;
/* Support AXI4 Slave 0 Address Translation Tables 0-7. */
if (plda->atr_table_num >= XR3PCI_ATR_MAX_TABLE_NUM) {
dev_err(plda->dev, "ATR table number %d exceeds max num\n",
plda->atr_table_num);
return -EINVAL;
}
base += XR3PCI_ATR_TABLE_OFFSET * plda->atr_table_num;
plda->atr_table_num++;
/*
* X3PCI_ATR_SRC_ADDR_LOW:
* - bit 0: enable entry,
* - bits 1-6: ATR window size: total size in bytes: 2^(ATR_WSIZE + 1)
* - bits 7-11: reserved
* - bits 12-31: start of source address
*/
writel((lower_32_bits(src_addr) & XR3PCI_ATR_SRC_ADDR_MASK) |
(fls(window_size) - 1) << XR3PCI_ATR_SRC_WIN_SIZE_SHIFT | 1,
base + XR3PCI_ATR_SRC_ADDR_LOW);
writel(upper_32_bits(src_addr), base + XR3PCI_ATR_SRC_ADDR_HIGH);
writel((lower_32_bits(trsl_addr) & XR3PCI_ATR_TRSL_ADDR_MASK),
base + XR3PCI_ATR_TRSL_ADDR_LOW);
writel(upper_32_bits(trsl_addr), base + XR3PCI_ATR_TRSL_ADDR_HIGH);
writel(trsl_param, base + XR3PCI_ATR_TRSL_PARAM);
dev_dbg(plda->dev, "ATR entry: 0x%010llx %s 0x%010llx [0x%010llx] (param: 0x%06x)\n",
src_addr, (trsl_param & XR3PCI_ATR_TRSL_DIR) ? "<-" : "->",
trsl_addr, (u64)window_size, trsl_param);
return 0;
}

View File

@ -0,0 +1,118 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Copyright (C) 2023 StarFive Technology Co., Ltd.
* Author: Minda Chen <minda.chen@starfivetech.com>
*
*/
#ifndef PCIE_PLDA_COMMON_H
#define PCIE_PLDA_COMMON_H
#define GEN_SETTINGS 0x80
#define PCIE_PCI_IDS 0x9C
#define PCIE_WINROM 0xFC
#define PMSG_SUPPORT_RX 0x3F0
#define PCI_MISC 0xB4
#define PLDA_EP_ENABLE 0
#define PLDA_RP_ENABLE 1
#define IDS_CLASS_CODE_SHIFT 8
#define PREF_MEM_WIN_64_SUPPORT BIT(3)
#define PMSG_LTR_SUPPORT BIT(2)
#define PLDA_FUNCTION_DIS BIT(15)
#define PLDA_FUNC_NUM 4
#define PLDA_PHY_FUNC_SHIFT 9
#define XR3PCI_ATR_AXI4_SLV0 0x800
#define XR3PCI_ATR_SRC_ADDR_LOW 0x0
#define XR3PCI_ATR_SRC_ADDR_HIGH 0x4
#define XR3PCI_ATR_TRSL_ADDR_LOW 0x8
#define XR3PCI_ATR_TRSL_ADDR_HIGH 0xc
#define XR3PCI_ATR_TRSL_PARAM 0x10
#define XR3PCI_ATR_TABLE_OFFSET 0x20
#define XR3PCI_ATR_MAX_TABLE_NUM 8
#define XR3PCI_ATR_SRC_WIN_SIZE_SHIFT 1
#define XR3PCI_ATR_SRC_ADDR_MASK GENMASK(31, 12)
#define XR3PCI_ATR_TRSL_ADDR_MASK GENMASK(31, 12)
#define XR3PCI_ATR_TRSL_DIR BIT(22)
/* IDs used in the XR3PCI_ATR_TRSL_PARAM */
#define XR3PCI_ATR_TRSLID_PCIE_MEMORY 0x0
#define XR3PCI_ATR_TRSLID_PCIE_CONFIG 0x1
/**
* struct pcie_plda - PLDA PCIe controller state
*
* @reg_base: The base address of controller register space
* @cfg_base: The base address of configuration space
* @cfg_size: The size of configuration space
* @sec_busno: Secondary bus number.
* @atr_table_num: Total ATR table numbers.
*/
struct pcie_plda {
struct udevice *dev;
void __iomem *reg_base;
void __iomem *cfg_base;
phys_size_t cfg_size;
int sec_busno;
int atr_table_num;
};
int plda_pcie_config_read(const struct udevice *udev, pci_dev_t bdf,
uint offset, ulong *valuep,
enum pci_size_t size);
int plda_pcie_config_write(struct udevice *udev, pci_dev_t bdf,
uint offset, ulong value,
enum pci_size_t size);
int plda_pcie_set_atr_entry(struct pcie_plda *plda, phys_addr_t src_addr,
phys_addr_t trsl_addr, phys_size_t window_size,
int trsl_param);
static inline void plda_pcie_enable_root_port(struct pcie_plda *plda)
{
u32 value;
value = readl(plda->reg_base + GEN_SETTINGS);
value |= PLDA_RP_ENABLE;
writel(value, plda->reg_base + GEN_SETTINGS);
}
static inline void plda_pcie_set_standard_class(struct pcie_plda *plda)
{
u32 value;
value = readl(plda->reg_base + PCIE_PCI_IDS);
value &= 0xff;
value |= (PCI_CLASS_BRIDGE_PCI_NORMAL << IDS_CLASS_CODE_SHIFT);
writel(value, plda->reg_base + PCIE_PCI_IDS);
}
static inline void plda_pcie_set_pref_win_64bit(struct pcie_plda *plda)
{
u32 value;
value = readl(plda->reg_base + PCIE_WINROM);
value |= PREF_MEM_WIN_64_SUPPORT;
writel(value, plda->reg_base + PCIE_WINROM);
}
static inline void plda_pcie_disable_ltr(struct pcie_plda *plda)
{
u32 value;
value = readl(plda->reg_base + PMSG_SUPPORT_RX);
value &= ~PMSG_LTR_SUPPORT;
writel(value, plda->reg_base + PMSG_SUPPORT_RX);
}
static inline void plda_pcie_disable_func(struct pcie_plda *plda)
{
u32 value;
value = readl(plda->reg_base + PCI_MISC);
value |= PLDA_FUNCTION_DIS;
writel(value, plda->reg_base + PCI_MISC);
}
#endif

View File

@ -0,0 +1,317 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* StarFive PLDA PCIe host controller driver
*
* Copyright (C) 2023 StarFive Technology Co., Ltd.
* Author: Mason Huo <mason.huo@starfivetech.com>
*
*/
#include <common.h>
#include <clk.h>
#include <dm.h>
#include <pci.h>
#include <pci_ids.h>
#include <power-domain.h>
#include <regmap.h>
#include <reset.h>
#include <syscon.h>
#include <asm/global_data.h>
#include <asm/io.h>
#include <asm-generic/gpio.h>
#include <dm/device_compat.h>
#include <dm/pinctrl.h>
#include <linux/delay.h>
#include <linux/iopoll.h>
#include "pcie_plda_common.h"
/* system control */
#define STG_SYSCON_K_RP_NEP_MASK BIT(8)
#define STG_SYSCON_AXI4_SLVL_ARFUNC_MASK GENMASK(22, 8)
#define STG_SYSCON_AXI4_SLVL_ARFUNC_SHIFT 8
#define STG_SYSCON_AXI4_SLVL_AWFUNC_MASK GENMASK(14, 0)
#define STG_SYSCON_CLKREQ_MASK BIT(22)
#define STG_SYSCON_CKREF_SRC_SHIFT 18
#define STG_SYSCON_CKREF_SRC_MASK GENMASK(19, 18)
DECLARE_GLOBAL_DATA_PTR;
struct starfive_pcie {
struct pcie_plda plda;
struct clk_bulk clks;
struct reset_ctl_bulk rsts;
struct gpio_desc reset_gpio;
struct regmap *regmap;
u32 stg_arfun;
u32 stg_awfun;
u32 stg_rp_nep;
};
static int starfive_pcie_atr_init(struct starfive_pcie *priv)
{
struct udevice *ctlr = pci_get_controller(priv->plda.dev);
struct pci_controller *hose = dev_get_uclass_priv(ctlr);
int i, ret;
/*
* As the two host bridges in JH7110 soc have the same default
* address translation table, this cause the second root port can't
* access it's host bridge config space correctly.
* To workaround, config the ATR of host bridge config space by SW.
*/
ret = plda_pcie_set_atr_entry(&priv->plda,
(phys_addr_t)priv->plda.cfg_base, 0,
priv->plda.cfg_size,
XR3PCI_ATR_TRSLID_PCIE_CONFIG);
if (ret)
return ret;
for (i = 0; i < hose->region_count; i++) {
if (hose->regions[i].flags == PCI_REGION_SYS_MEMORY)
continue;
/* Only support identity mappings. */
if (hose->regions[i].bus_start !=
hose->regions[i].phys_start)
return -EINVAL;
ret = plda_pcie_set_atr_entry(&priv->plda,
hose->regions[i].phys_start,
hose->regions[i].bus_start,
hose->regions[i].size,
XR3PCI_ATR_TRSLID_PCIE_MEMORY);
if (ret)
return ret;
}
return 0;
}
static int starfive_pcie_get_syscon(struct udevice *dev)
{
struct starfive_pcie *priv = dev_get_priv(dev);
struct udevice *syscon;
struct ofnode_phandle_args syscfg_phandle;
u32 cells[4];
int ret;
/* get corresponding syscon phandle */
ret = dev_read_phandle_with_args(dev, "starfive,stg-syscon", NULL, 0, 0,
&syscfg_phandle);
if (ret < 0) {
dev_err(dev, "Can't get syscfg phandle: %d\n", ret);
return ret;
}
ret = uclass_get_device_by_ofnode(UCLASS_SYSCON, syscfg_phandle.node,
&syscon);
if (ret) {
dev_err(dev, "Unable to find syscon device (%d)\n", ret);
return ret;
}
priv->regmap = syscon_get_regmap(syscon);
if (!priv->regmap) {
dev_err(dev, "Unable to find regmap\n");
return -ENODEV;
}
/* get syscon register offset */
ret = dev_read_u32_array(dev, "starfive,stg-syscon",
cells, ARRAY_SIZE(cells));
if (ret) {
dev_err(dev, "Get syscon register err %d\n", ret);
return -EINVAL;
}
dev_dbg(dev, "Get syscon values: %x, %x, %x\n",
cells[1], cells[2], cells[3]);
priv->stg_arfun = cells[1];
priv->stg_awfun = cells[2];
priv->stg_rp_nep = cells[3];
return 0;
}
static int starfive_pcie_parse_dt(struct udevice *dev)
{
struct starfive_pcie *priv = dev_get_priv(dev);
int ret;
priv->plda.reg_base = (void *)dev_read_addr_name(dev, "reg");
if (priv->plda.reg_base == (void __iomem *)FDT_ADDR_T_NONE) {
dev_err(dev, "Missing required reg address range\n");
return -EINVAL;
}
priv->plda.cfg_base =
(void *)dev_read_addr_size_name(dev,
"config",
&priv->plda.cfg_size);
if (priv->plda.cfg_base == (void __iomem *)FDT_ADDR_T_NONE) {
dev_err(dev, "Missing required config address range");
return -EINVAL;
}
ret = starfive_pcie_get_syscon(dev);
if (ret) {
dev_err(dev, "Can't get syscon: %d\n", ret);
return ret;
}
ret = reset_get_bulk(dev, &priv->rsts);
if (ret) {
dev_err(dev, "Can't get reset: %d\n", ret);
return ret;
}
ret = clk_get_bulk(dev, &priv->clks);
if (ret) {
dev_err(dev, "Can't get clock: %d\n", ret);
return ret;
}
ret = gpio_request_by_name(dev, "reset-gpios", 0, &priv->reset_gpio,
GPIOD_IS_OUT);
if (ret) {
dev_err(dev, "Can't get reset-gpio: %d\n", ret);
return ret;
}
if (!dm_gpio_is_valid(&priv->reset_gpio)) {
dev_err(dev, "reset-gpio is not valid\n");
return -EINVAL;
}
return 0;
}
static int starfive_pcie_init_port(struct udevice *dev)
{
int ret, i;
struct starfive_pcie *priv = dev_get_priv(dev);
struct pcie_plda *plda = &priv->plda;
ret = clk_enable_bulk(&priv->clks);
if (ret) {
dev_err(dev, "Failed to enable clks (ret=%d)\n", ret);
return ret;
}
ret = reset_deassert_bulk(&priv->rsts);
if (ret) {
dev_err(dev, "Failed to deassert resets (ret=%d)\n", ret);
goto err_deassert_clk;
}
dm_gpio_set_value(&priv->reset_gpio, 1);
/* Disable physical functions except #0 */
for (i = 1; i < PLDA_FUNC_NUM; i++) {
regmap_update_bits(priv->regmap,
priv->stg_arfun,
STG_SYSCON_AXI4_SLVL_ARFUNC_MASK,
(i << PLDA_PHY_FUNC_SHIFT) <<
STG_SYSCON_AXI4_SLVL_ARFUNC_SHIFT);
regmap_update_bits(priv->regmap,
priv->stg_awfun,
STG_SYSCON_AXI4_SLVL_AWFUNC_MASK,
i << PLDA_PHY_FUNC_SHIFT);
plda_pcie_disable_func(plda);
}
/* Disable physical functions */
regmap_update_bits(priv->regmap,
priv->stg_arfun,
STG_SYSCON_AXI4_SLVL_ARFUNC_MASK,
0);
regmap_update_bits(priv->regmap,
priv->stg_awfun,
STG_SYSCON_AXI4_SLVL_AWFUNC_MASK,
0);
plda_pcie_enable_root_port(plda);
/* PCIe PCI Standard Configuration Identification Settings. */
plda_pcie_set_standard_class(plda);
/*
* The LTR message forwarding of PCIe Message Reception was set by core
* as default, but the forward id & addr are also need to be reset.
* If we do not disable LTR message forwarding here, or set a legal
* forwarding address, the kernel will get stuck after this driver probe.
* To workaround, disable the LTR message forwarding support on
* PCIe Message Reception.
*/
plda_pcie_disable_ltr(plda);
/* Prefetchable memory window 64-bit addressing support */
plda_pcie_set_pref_win_64bit(plda);
starfive_pcie_atr_init(priv);
dm_gpio_set_value(&priv->reset_gpio, 0);
/* Ensure that PERST in default at least 300 ms */
mdelay(300);
return 0;
err_deassert_clk:
clk_disable_bulk(&priv->clks);
return ret;
}
static int starfive_pcie_probe(struct udevice *dev)
{
struct starfive_pcie *priv = dev_get_priv(dev);
int ret;
priv->plda.atr_table_num = 0;
priv->plda.dev = dev;
ret = starfive_pcie_parse_dt(dev);
if (ret)
return ret;
regmap_update_bits(priv->regmap,
priv->stg_rp_nep,
STG_SYSCON_K_RP_NEP_MASK,
STG_SYSCON_K_RP_NEP_MASK);
regmap_update_bits(priv->regmap,
priv->stg_awfun,
STG_SYSCON_CKREF_SRC_MASK,
2 << STG_SYSCON_CKREF_SRC_SHIFT);
regmap_update_bits(priv->regmap,
priv->stg_awfun,
STG_SYSCON_CLKREQ_MASK,
STG_SYSCON_CLKREQ_MASK);
ret = starfive_pcie_init_port(dev);
if (ret)
return ret;
dev_err(dev, "Starfive PCIe bus probed.\n");
return 0;
}
static const struct dm_pci_ops starfive_pcie_ops = {
.read_config = plda_pcie_config_read,
.write_config = plda_pcie_config_write,
};
static const struct udevice_id starfive_pcie_ids[] = {
{ .compatible = "starfive,jh7110-pcie" },
{ }
};
U_BOOT_DRIVER(starfive_pcie_drv) = {
.name = "starfive_7110_pcie",
.id = UCLASS_PCI,
.of_match = starfive_pcie_ids,
.ops = &starfive_pcie_ops,
.probe = starfive_pcie_probe,
.priv_auto = sizeof(struct starfive_pcie),
};

View File

@ -17,24 +17,19 @@
/* Environment options */ /* Environment options */
#define CFG_STD_DEVICES_SETTINGS "stdin=serial,usbkbd\0" \
"stdout=serial,vidconsole\0" \
"stderr=serial,vidconsole\0"
#define BOOT_TARGET_DEVICES(func) \ #define BOOT_TARGET_DEVICES(func) \
func(QEMU, qemu, na) \
func(VIRTIO, virtio, 0) \ func(VIRTIO, virtio, 0) \
func(SCSI, scsi, 0) \ func(SCSI, scsi, 0) \
func(DHCP, dhcp, na) func(DHCP, dhcp, na)
#include <config_distro_bootcmd.h> #include <config_distro_bootcmd.h>
#define BOOTENV_DEV_QEMU(devtypeu, devtypel, instance) \
"bootcmd_qemu=" \
"if env exists kernel_start; then " \
"bootm ${kernel_start} - ${fdtcontroladdr};" \
"fi;\0"
#define BOOTENV_DEV_NAME_QEMU(devtypeu, devtypel, instance) \
"qemu "
#define CFG_EXTRA_ENV_SETTINGS \ #define CFG_EXTRA_ENV_SETTINGS \
CFG_STD_DEVICES_SETTINGS \
"fdt_high=0xffffffffffffffff\0" \ "fdt_high=0xffffffffffffffff\0" \
"initrd_high=0xffffffffffffffff\0" \ "initrd_high=0xffffffffffffffff\0" \
"kernel_addr_r=0x84000000\0" \ "kernel_addr_r=0x84000000\0" \

View File

@ -84,8 +84,6 @@ int stdio_init_tables(void);
*/ */
int stdio_add_devices(void); int stdio_add_devices(void);
void stdio_print_current_devices(void);
/** /**
* stdio_deregister_dev() - deregister the device "devname". * stdio_deregister_dev() - deregister the device "devname".
* *