mirror of
https://github.com/u-boot/u-boot.git
synced 2025-04-11 07:24:46 +00:00
Merge patch series "Implement ACPI on aarch64"
Patrick Rudolph <patrick.rudolph@9elements.com> says: Based on the existing work done by Simon Glass this series adds support for booting aarch64 devices using ACPI only. As first target QEMU SBSA support is added, which relies on ACPI only to boot an OS. As secondary target the Raspberry Pi4 was used, which is broadly available and allows easy testing of the proposed solution. The series is split into ACPI cleanups and code movements, adding Arm specific ACPI tables and finally SoC and mainboard related changes to boot a Linux on the QEMU SBSA and RPi4. Currently only the mandatory ACPI tables are supported, allowing to boot into Linux without errors. The QEMU SBSA support is feature complete and provides the same functionality as the EDK2 implementation. The changes were tested on real hardware as well on QEMU v9.0: qemu-system-aarch64 -machine sbsa-ref -nographic -cpu cortex-a57 \ -pflash secure-world.rom \ -pflash unsecure-world.rom qemu-system-aarch64 -machine raspi4b -kernel u-boot.bin -cpu cortex-a72 \ -smp 4 -m 2G -drive file=raspbian.img,format=raw,index=0 \ -dtb bcm2711-rpi-4-b.dtb -nographic Tested against FWTS V24.03.00. Known issues: - The QEMU rpi4 support is currently limited as it doesn't emulate PCI, USB or ethernet devices! - The SMP bringup doesn't work on RPi4, but works in QEMU (Possibly cache related). - PCI on RPI4 isn't working on real hardware since the pcie_brcmstb Linux kernel module doesn't support ACPI yet. Link: https://lore.kernel.org/r/20241023132116.970117-1-patrick.rudolph@9elements.com
This commit is contained in:
commit
2800aecce0
113 changed files with 6528 additions and 551 deletions
|
@ -255,6 +255,11 @@ stages:
|
|||
wget -O - https://github.com/riscv-software-src/opensbi/releases/download/v1.3.1/opensbi-1.3.1-rv-bin.tar.xz | tar -C /tmp -xJ;
|
||||
export OPENSBI=/tmp/opensbi-1.3.1-rv-bin/share/opensbi/lp64/generic/firmware/fw_dynamic.bin;
|
||||
fi
|
||||
if [[ "\${TEST_PY_BD}" == "qemu-arm-sbsa" ]]; then
|
||||
wget -O /tmp/bl1.bin https://artifacts.codelinaro.org/artifactory/linaro-419-sbsa-ref/latest/tf-a/bl1.bin;
|
||||
wget -O /tmp/fip.bin https://artifacts.codelinaro.org/artifactory/linaro-419-sbsa-ref/latest/tf-a/fip.bin;
|
||||
export BINMAN_INDIRS=/tmp
|
||||
fi
|
||||
# the below corresponds to .gitlab-ci.yml "script"
|
||||
cd \${WORK_DIR}
|
||||
export UBOOT_TRAVIS_BUILD_DIR=/tmp/\${TEST_PY_BD}
|
||||
|
@ -426,6 +431,9 @@ stages:
|
|||
qemu_arm64_lwip:
|
||||
TEST_PY_BD: "qemu_arm64_lwip"
|
||||
TEST_PY_TEST_SPEC: "test_net_dhcp or test_net_ping or test_net_tftpboot"
|
||||
qemu_arm_sbsa_ref:
|
||||
TEST_PY_BD: "qemu-arm-sbsa"
|
||||
TEST_PY_TEST_SPEC: "not sleep"
|
||||
qemu_m68k:
|
||||
TEST_PY_BD: "M5208EVBE"
|
||||
TEST_PY_ID: "--id qemu"
|
||||
|
|
|
@ -42,6 +42,11 @@ stages:
|
|||
wget -O - https://github.com/riscv-software-src/opensbi/releases/download/v1.3.1/opensbi-1.3.1-rv-bin.tar.xz | tar -C /tmp -xJ;
|
||||
export OPENSBI=/tmp/opensbi-1.3.1-rv-bin/share/opensbi/lp64/generic/firmware/fw_dynamic.bin;
|
||||
fi
|
||||
- if [[ "${TEST_PY_BD}" == "qemu-arm-sbsa" ]]; then
|
||||
wget -O /tmp/bl1.bin https://artifacts.codelinaro.org/artifactory/linaro-419-sbsa-ref/latest/tf-a/bl1.bin;
|
||||
wget -O /tmp/fip.bin https://artifacts.codelinaro.org/artifactory/linaro-419-sbsa-ref/latest/tf-a/fip.bin;
|
||||
export BINMAN_INDIRS=/tmp;
|
||||
fi
|
||||
|
||||
after_script:
|
||||
- cp -v /tmp/${TEST_PY_BD}/*.{html,css,xml} .
|
||||
|
@ -357,6 +362,12 @@ qemu_arm64_lwip test.py:
|
|||
TEST_PY_TEST_SPEC: "test_net_dhcp or test_net_ping or test_net_tftpboot"
|
||||
<<: *buildman_and_testpy_dfn
|
||||
|
||||
qemu_arm_sbsa test.py:
|
||||
variables:
|
||||
TEST_PY_BD: "qemu-arm-sbsa"
|
||||
TEST_PY_TEST_SPEC: "not sleep"
|
||||
<<: *buildman_and_testpy_dfn
|
||||
|
||||
qemu_m68k test.py:
|
||||
variables:
|
||||
TEST_PY_BD: "M5208EVBE"
|
||||
|
|
|
@ -355,7 +355,7 @@ S: Maintained
|
|||
T: git https://source.denx.de/u-boot/custodians/u-boot-marvell.git
|
||||
F: arch/arm/mach-kirkwood/
|
||||
F: arch/arm/mach-mvebu/
|
||||
F: drivers/ata/ahci_mvebu.c
|
||||
F: drivers/ata/ahci_generic.c
|
||||
F: drivers/clk/mvebu/
|
||||
F: drivers/ddr/marvell/
|
||||
F: drivers/gpio/mvebu_gpio.c
|
||||
|
|
|
@ -113,6 +113,13 @@ config GICV2
|
|||
config GICV3
|
||||
bool
|
||||
|
||||
config DRIVER_GICV2
|
||||
bool "ARM GICV2 driver"
|
||||
select IRQ
|
||||
help
|
||||
ARM GICV2 driver.
|
||||
Basic support for parsing the GICV2 node and generate ACPI tables.
|
||||
|
||||
config GIC_V3_ITS
|
||||
bool "ARM GICV3 ITS"
|
||||
select IRQ
|
||||
|
@ -644,6 +651,7 @@ config ARCH_ORION5X
|
|||
|
||||
config ARCH_BCM283X
|
||||
bool "Broadcom BCM283X family"
|
||||
select CPU
|
||||
select DM
|
||||
select DM_GPIO
|
||||
select DM_SERIAL
|
||||
|
@ -1047,7 +1055,7 @@ config ARCH_QEMU
|
|||
imply DM_RNG
|
||||
imply DM_RTC
|
||||
imply RTC_PL031
|
||||
imply OF_HAS_PRIOR_STAGE
|
||||
imply OF_HAS_PRIOR_STAGE if !TARGET_QEMU_ARM_SBSA
|
||||
imply VIDEO
|
||||
imply VIDEO_BOCHS
|
||||
imply SYS_WHITE_ON_BLACK
|
||||
|
@ -2374,6 +2382,7 @@ source "board/broadcom/bcmns3/Kconfig"
|
|||
source "board/cavium/thunderx/Kconfig"
|
||||
source "board/eets/pdu001/Kconfig"
|
||||
source "board/emulation/qemu-arm/Kconfig"
|
||||
source "board/emulation/qemu-sbsa/Kconfig"
|
||||
source "board/freescale/ls2080aqds/Kconfig"
|
||||
source "board/freescale/ls2080ardb/Kconfig"
|
||||
source "board/freescale/ls1088a/Kconfig"
|
||||
|
|
|
@ -29,6 +29,7 @@ obj-$(CONFIG_ARM_SMCCC) += smccc-call.o
|
|||
|
||||
ifndef CONFIG_XPL_BUILD
|
||||
obj-$(CONFIG_ARMV8_SPIN_TABLE) += spin_table.o spin_table_v8.o
|
||||
obj-$(CONFIG_ACPI_PARKING_PROTOCOL) += acpi_park_v8.o
|
||||
else
|
||||
obj-$(CONFIG_ARCH_SUNXI) += fel_utils.o
|
||||
endif
|
||||
|
|
113
arch/arm/cpu/armv8/acpi_park_v8.S
Normal file
113
arch/arm/cpu/armv8/acpi_park_v8.S
Normal file
|
@ -0,0 +1,113 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright (C) 2024 9elements GmbH
|
||||
* Author: Patrick Rudolph <patrick.rudolph@9elements.com>
|
||||
*
|
||||
* This file provides ARMv8 specific code for the generic part of the
|
||||
* ACPI parking protocol implementation. It contains the spinning code
|
||||
* that will be installed into the parking protocol and it points the
|
||||
* secondary CPUs to their own parking protocol page once it has been
|
||||
* set up by the generic part.
|
||||
*/
|
||||
|
||||
#include <asm/acpi_table.h>
|
||||
#include <linux/linkage.h>
|
||||
|
||||
/* Filled by C code */
|
||||
.global acpi_pp_tables
|
||||
acpi_pp_tables:
|
||||
.quad 0
|
||||
|
||||
.global acpi_pp_etables
|
||||
acpi_pp_etables:
|
||||
.quad 0
|
||||
|
||||
/* Read by C code */
|
||||
.global acpi_pp_code_size
|
||||
acpi_pp_code_size:
|
||||
.word __secondary_pp_code_end - __secondary_pp_code_start
|
||||
|
||||
.global acpi_pp_secondary_jump
|
||||
ENTRY(acpi_pp_secondary_jump)
|
||||
0:
|
||||
/*
|
||||
* Cannot use atomic operations since the MMU and D-cache
|
||||
* might be off. Use the MPIDR instead to find the spintable.
|
||||
*/
|
||||
|
||||
/* Check if parking protocol table is ready */
|
||||
ldr x1, =acpi_pp_tables
|
||||
ldr x0, [x1]
|
||||
cbnz x0, 0f
|
||||
wfe
|
||||
b 0b
|
||||
|
||||
0: /* Get end of page tables in x3 */
|
||||
ldr x1, =acpi_pp_etables
|
||||
ldr x3, [x1]
|
||||
|
||||
/* Get own CPU ID in w2 */
|
||||
mrs x2, mpidr_el1
|
||||
lsr x9, x2, #32
|
||||
bfi x2, x9, #24, #8 /* w2 is aff3:aff2:aff1:aff0 */
|
||||
|
||||
0: /* Loop over all parking protocol pages */
|
||||
cmp x0, x3
|
||||
b.ge hlt
|
||||
|
||||
/* Fetch CPU_ID from current page */
|
||||
ldr x1, [x0, #ACPI_PP_CPU_ID_OFFSET]
|
||||
lsr x9, x1, #32
|
||||
bfi x1, x9, #24, #8 /* w1 is aff3:aff2:aff1:aff0 */
|
||||
|
||||
/* Compare CPU_IDs */
|
||||
cmp w1, w2
|
||||
b.eq 0f
|
||||
|
||||
add x0, x0, #ACPI_PP_PAGE_SIZE
|
||||
b 0b
|
||||
|
||||
hlt: wfi
|
||||
b hlt /* Should never happen. */
|
||||
|
||||
0: /* x0 points to the 4K-aligned, parking protocol page */
|
||||
add x2, x0, #ACPI_PP_CPU_CODE_OFFSET
|
||||
|
||||
/* Jump to spin code in own parking protocol page */
|
||||
br x2
|
||||
ENDPROC(acpi_pp_secondary_jump)
|
||||
|
||||
.align 8
|
||||
__secondary_pp_code_start:
|
||||
.global acpi_pp_code_start
|
||||
ENTRY(acpi_pp_code_start)
|
||||
/* x0 points to the 4K-aligned, parking protocol page */
|
||||
|
||||
/* Prepare defines for spinning code */
|
||||
mov w3, #ACPI_PP_CPU_ID_INVALID
|
||||
mov x2, #ACPI_PP_JMP_ADR_INVALID
|
||||
|
||||
/* Mark parking protocol page as ready */
|
||||
str w3, [x0, #ACPI_PP_CPU_ID_OFFSET]
|
||||
dsb sy
|
||||
|
||||
0: wfe
|
||||
ldr w1, [x0, #ACPI_PP_CPU_ID_OFFSET]
|
||||
|
||||
/* Check CPU ID is valid */
|
||||
cmp w1, w3
|
||||
b.eq 0b
|
||||
|
||||
/* Check jump address valid */
|
||||
ldr x1, [x0, #ACPI_PP_CPU_JMP_OFFSET]
|
||||
cmp x1, x2
|
||||
b.eq 0b
|
||||
|
||||
/* Clear jump address before jump */
|
||||
str x2, [x0, #ACPI_PP_CPU_JMP_OFFSET]
|
||||
dsb sy
|
||||
|
||||
br x1
|
||||
ENDPROC(acpi_pp_code_start)
|
||||
/* Secondary Boot Code ends here */
|
||||
__secondary_pp_code_end:
|
|
@ -178,6 +178,18 @@ pie_fixup_done:
|
|||
branch_if_master x0, master_cpu
|
||||
b spin_table_secondary_jump
|
||||
/* never return */
|
||||
#elif defined(CONFIG_ACPI_PARKING_PROTOCOL) && !defined(CONFIG_SPL_BUILD)
|
||||
branch_if_master x0, master_cpu
|
||||
/*
|
||||
* Waits for ACPI parking protocol memory to be allocated and the spin-table
|
||||
* code to be written. Once ready the secondary CPUs will jump and spin in
|
||||
* their own 4KiB memory region, which is also used as mailbox, until released
|
||||
* by the OS.
|
||||
* The mechanism is similar to the DT enable-method = "spin-table", but works
|
||||
* with ACPI enabled platforms.
|
||||
*/
|
||||
b acpi_pp_secondary_jump
|
||||
/* never return */
|
||||
#elif defined(CONFIG_ARMV8_MULTIENTRY)
|
||||
branch_if_master x0, master_cpu
|
||||
|
||||
|
|
138
arch/arm/dts/qemu-sbsa.dts
Normal file
138
arch/arm/dts/qemu-sbsa.dts
Normal file
|
@ -0,0 +1,138 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+ OR MIT
|
||||
/*
|
||||
* Devicetree with onboard devices for qemu_sbsa-ref for internal use only!
|
||||
* DO NOT PASS TO THE OS!
|
||||
*
|
||||
* As QEMU provides only a minimal devicetree this one is merged with
|
||||
* it and then fixed at runtime.
|
||||
*
|
||||
* Copyright 2024 9elements GmbH
|
||||
*/
|
||||
#include "configs/qemu-sbsa.h"
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
|
||||
/dts-v1/;
|
||||
|
||||
/ {
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
interrupt-parent = <&intc>;
|
||||
compatible = "linux,sbsa-ref";
|
||||
|
||||
binman: binman {
|
||||
multiple-images;
|
||||
};
|
||||
|
||||
cpus {
|
||||
/* Filled by fdtdec_board_setup() */
|
||||
};
|
||||
|
||||
memory {
|
||||
/* Filled by fdtdec_board_setup() */
|
||||
};
|
||||
|
||||
soc {
|
||||
compatible = "simple-bus";
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
ranges;
|
||||
|
||||
cfi_flash {
|
||||
compatible = "cfi-flash";
|
||||
reg = /bits/ 64 <SBSA_FLASH_BASE_ADDR
|
||||
SBSA_FLASH_LENGTH>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
uart0 {
|
||||
compatible = "arm,pl011";
|
||||
status = "okay";
|
||||
reg = /bits/ 64 <SBSA_UART_BASE_ADDR
|
||||
SBSA_UART_LENGTH>;
|
||||
};
|
||||
|
||||
ahci {
|
||||
compatible = "generic-ahci";
|
||||
status = "okay";
|
||||
reg = /bits/ 64 <0x60100000 0x00010000>;
|
||||
};
|
||||
|
||||
xhci {
|
||||
compatible = "generic-xhci";
|
||||
status = "okay";
|
||||
reg = /bits/ 64 <0x60110000 0x00010000>;
|
||||
};
|
||||
|
||||
pci {
|
||||
#address-cells = <3>;
|
||||
#size-cells = <2>;
|
||||
compatible = "pci-host-ecam-generic";
|
||||
device_type = "pci";
|
||||
status = "okay";
|
||||
reg = /bits/ 64 <0xf0000000 0x10000000>;
|
||||
bus-range = <0 0xff>;
|
||||
ranges = /bits/ 32 <0x01000000>,
|
||||
/bits/ 64 <0
|
||||
SBSA_PIO_BASE_ADDR
|
||||
SBSA_PIO_LENGTH>,
|
||||
/bits/ 32 <0x02000000>,
|
||||
/bits/ 64 <SBSA_PCIE_MMIO_BASE_ADDR
|
||||
SBSA_PCIE_MMIO_BASE_ADDR
|
||||
SBSA_PCIE_MMIO_LENGTH>,
|
||||
/bits/ 32 <0x43000000>,
|
||||
/bits/ 64 <SBSA_PCIE_MMIO_HIGH_BASE_ADDR
|
||||
SBSA_PCIE_MMIO_HIGH_BASE_ADDR
|
||||
SBSA_PCIE_MMIO_HIGH_LENGTH>;
|
||||
};
|
||||
};
|
||||
|
||||
intc: interrupt-controller {
|
||||
compatible = "arm,gic-v3";
|
||||
#interrupt-cells = <3>;
|
||||
status = "okay";
|
||||
interrupt-controller;
|
||||
interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>;
|
||||
reg = /bits/ 64 <SBSA_GIC_DIST_BASE_ADDR SBSA_GIC_DIST_LENGTH>,
|
||||
/bits/ 64 <SBSA_GIC_REDIST_BASE_ADDR SBSA_GIC_REDIST_LENGTH>,
|
||||
/bits/ 64 <0 0>,
|
||||
/bits/ 64 <SBSA_GIC_HBASE_ADDR SBSA_GIC_HBASE_LENGTH>,
|
||||
/bits/ 64 <SBSA_GIC_VBASE_ADDR SBSA_GIC_VBASE_LENGTH>;
|
||||
};
|
||||
|
||||
its {
|
||||
compatible = "arm,gic-v3-its";
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
|
||||
&binman {
|
||||
secure-world {
|
||||
filename = "secure-world.rom";
|
||||
size = <SBSA_SECURE_FLASH_LENGTH>;
|
||||
|
||||
bl1 {
|
||||
offset = <0x0>;
|
||||
description = "ARM Trusted Firmware BL1";
|
||||
filename = "bl1.bin";
|
||||
type = "blob-ext";
|
||||
};
|
||||
|
||||
fip {
|
||||
offset = <0x12000>;
|
||||
description = "ARM Trusted Firmware FIP";
|
||||
filename = "fip.bin";
|
||||
type = "blob-ext";
|
||||
};
|
||||
};
|
||||
|
||||
unsecure-world {
|
||||
filename = "unsecure-world.rom";
|
||||
size = <SBSA_FLASH_LENGTH>;
|
||||
|
||||
u-boot {
|
||||
};
|
||||
u-boot-dtb {
|
||||
compress = "lz4";
|
||||
};
|
||||
};
|
||||
};
|
|
@ -0,0 +1,147 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#ifndef __ASM_ACPI_TABLE_H__
|
||||
#define __ASM_ACPI_TABLE_H__
|
||||
|
||||
#ifndef __ACPI__
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#include <acpi/acpi_table.h>
|
||||
|
||||
/**
|
||||
* acpi_write_madt_gicc() - Write out a MADT GICC sub-table
|
||||
*
|
||||
* Write out the GIC CPU Interface sub-table.
|
||||
*
|
||||
* @gicc: Pointer to place to put the sub-table
|
||||
* @cpu_num: GIC's CPU Interface Number
|
||||
* @perf_gsiv: The GSIV used for Performance Monitoring Interrupts
|
||||
* @phys_base: Address at which the processor can access this
|
||||
* GIC CPU Interface
|
||||
* @gicv: Address of the GIC virtual CPU interface registers
|
||||
* @gich: Address of the GIC virtual interface control block
|
||||
* registers
|
||||
* @vgic_maint_irq: GSIV for Virtual GIC maintenance interrupt
|
||||
* @gicr_base: Physical address of the associated Redistributor
|
||||
* @mpidr: MPIDR as defined by ARM architecture
|
||||
* @efficiency: Describes the relative power efficiency
|
||||
*/
|
||||
void acpi_write_madt_gicc(struct acpi_madt_gicc *gicc, uint cpu_num,
|
||||
uint perf_gsiv, ulong phys_base, ulong gicv,
|
||||
ulong gich, uint vgic_maint_irq, u64 gicr_base,
|
||||
ulong mpidr, uint efficiency);
|
||||
|
||||
/**
|
||||
* acpi_write_madt_gicd() - Write out a MADT GICD sub-table
|
||||
*
|
||||
* Write out the GIC Distributor sub-table.
|
||||
*
|
||||
* @gicd: Pointer to place to put the sub-table
|
||||
* @gic_id: This GIC Distributor's hardware ID
|
||||
* @phys_base: The 64-bit physical address for this Distributor
|
||||
* @gic_version: GIC version
|
||||
*/
|
||||
void acpi_write_madt_gicd(struct acpi_madt_gicd *gicd, uint gic_id,
|
||||
ulong phys_base, uint gic_version);
|
||||
|
||||
/**
|
||||
* acpi_write_madt_gicr() - Write out a MADT GICR sub-table
|
||||
*
|
||||
* Write out the GIC Redistributor sub-table.
|
||||
*
|
||||
* @gicr: Pointer to place to put the sub-table
|
||||
* @discovery_range_base_address: Physical address of a page range
|
||||
* containing all GIC Redistributors
|
||||
* @discovery_range_length: Length of the GIC Redistributor
|
||||
* Discovery page range
|
||||
*/
|
||||
void acpi_write_madt_gicr(struct acpi_madt_gicr *gicr,
|
||||
u64 discovery_range_base_address,
|
||||
u32 discovery_range_length);
|
||||
|
||||
/**
|
||||
* acpi_write_madt_its() - Write out a MADT ITS sub-table
|
||||
*
|
||||
* Write out the GIC Interrupt Translation Service sub-table.
|
||||
*
|
||||
* @its: Pointer to place to put the sub-table
|
||||
* @its_id: Uniqueue GIC ITS ID
|
||||
* @physical_base_address: Physical address for the Interrupt
|
||||
* Translation Service
|
||||
*/
|
||||
void acpi_write_madt_its(struct acpi_madt_its *its,
|
||||
u32 its_id,
|
||||
u64 physical_base_address);
|
||||
|
||||
/**
|
||||
* acpi_pptt_add_proc() - Write out a PPTT processor sub-table
|
||||
*
|
||||
* Write out the Processor Properties Topology Table processor sub-table.
|
||||
*
|
||||
* @ctx: ACPI context pointer
|
||||
* @flags: Processor Structure Flags
|
||||
* @parent: Reference to parent processor
|
||||
* @proc_id: ACPI processor ID as defined in MADT
|
||||
* @num_resources: Number of resource structure references
|
||||
* @resource_list: References to other PPTT structures
|
||||
* Return: offset from start of PPTT in bytes
|
||||
*/
|
||||
int acpi_pptt_add_proc(struct acpi_ctx *ctx, const u32 flags, const u32 parent,
|
||||
const u32 proc_id, const u32 num_resources,
|
||||
const u32 *resource_list);
|
||||
|
||||
/**
|
||||
* acpi_pptt_add_cache() - Write out a PPTT cache sub-table
|
||||
*
|
||||
* Write out the Processor Properties Topology Table cache sub-table.
|
||||
*
|
||||
* @ctx: ACPI context pointer
|
||||
* @flags: Cache Structure Flags
|
||||
* @next_cache_level: Reference to next level of cache
|
||||
* @size: Size of the cache in bytes
|
||||
* @sets: Number of sets in the cache
|
||||
* @assoc: Integer number of ways
|
||||
* @attributes: Allocation type, Cache type, policy
|
||||
* @line_size: Line size in bytes
|
||||
* Return: offset from start of PPTT in bytes
|
||||
*/
|
||||
int acpi_pptt_add_cache(struct acpi_ctx *ctx, const u32 flags,
|
||||
const u32 next_cache_level, const u32 size,
|
||||
const u32 sets, const u8 assoc, const u8 attributes,
|
||||
const u16 line_size);
|
||||
|
||||
/* Multi-processor Startup for ARM Platforms */
|
||||
/**
|
||||
* struct acpi_pp_page - MP startup handshake mailbox
|
||||
*
|
||||
* Defines a 4096 byte memory region that is used for starting secondary CPUs on
|
||||
* an Arm system that follows the "Multi-processor Startup for ARM Platforms" spec.
|
||||
*
|
||||
* @cpu_id: MPIDR as returned by the Multiprocessor Affinity Register.
|
||||
* On 32bit Arm systems the upper bits are unused.
|
||||
* @jumping_address: On 32bit Arm systems the address must be below 4 GiB
|
||||
* @os_reserved: Reserved for OS use. Firmware must not access this memory.
|
||||
* @spinning_code: Reserved for firmware use. OS must not access this memory.
|
||||
* The spinning code will be installed by firmware and the secondary
|
||||
* CPUs will enter it before the control is handed over to the OS.
|
||||
*/
|
||||
struct acpi_pp_page {
|
||||
u64 cpu_id;
|
||||
u64 jumping_address;
|
||||
u8 os_reserved[2032];
|
||||
u8 spinning_code[2048];
|
||||
} __packed;
|
||||
|
||||
#endif /* !__ASSEMBLY__ */
|
||||
#endif /* !__ACPI__ */
|
||||
|
||||
/* Multi-processor Startup for ARM Platforms defines */
|
||||
#define ACPI_PP_CPU_ID_INVALID 0xffffffff
|
||||
#define ACPI_PP_JMP_ADR_INVALID 0
|
||||
#define ACPI_PP_PAGE_SIZE 4096
|
||||
#define ACPI_PP_CPU_ID_OFFSET 0
|
||||
#define ACPI_PP_CPU_JMP_OFFSET 8
|
||||
#define ACPI_PP_CPU_CODE_OFFSET 2048
|
||||
#define ACPI_PP_VERSION 1
|
||||
|
||||
#endif /* __ASM_ACPI_TABLE_H__ */
|
34
arch/arm/include/asm/arch-qemu-sbsa/boot0.h
Normal file
34
arch/arm/include/asm/arch-qemu-sbsa/boot0.h
Normal file
|
@ -0,0 +1,34 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* sbsa-ref starts U-Boot in XIP memory. Need to relocate U-Boot
|
||||
* to DRAM which is already up. Instead of using SPL this simple loader
|
||||
* is being used.
|
||||
*/
|
||||
relocate_check:
|
||||
/* x0 contains the pointer to FDT provided by ATF */
|
||||
adr x1, _start /* x1 <- Runtime value of _start */
|
||||
ldr x2, _TEXT_BASE /* x2 <- Linked value of _start */
|
||||
subs x9, x1, x2 /* x9 <- Run-vs-link offset */
|
||||
beq reset
|
||||
|
||||
adrp x1, __image_copy_start /* x2 <- address bits [31:12] */
|
||||
add x1, x1, :lo12:__image_copy_start/* x2 <- address bits [11:00] */
|
||||
adrp x3, __image_copy_end /* x3 <- address bits [31:12] */
|
||||
add x3, x3, :lo12:__image_copy_end /* x3 <- address bits [11:00] */
|
||||
add x3, x3, #0x100000 /* 1 MiB for the DTB found at _end */
|
||||
|
||||
copy_loop:
|
||||
ldp x10, x11, [x1], #16 /* copy from source address [x1] */
|
||||
stp x10, x11, [x2], #16 /* copy to target address [x2] */
|
||||
cmp x1, x3 /* until source end address [x3] */
|
||||
b.lo copy_loop
|
||||
|
||||
isb
|
||||
ldr x2, _TEXT_BASE /* x2 <- Linked value of _start */
|
||||
br x2 /* Jump to linked address */
|
||||
/* Never reaches this point */
|
||||
1:
|
||||
wfi
|
||||
b 1b
|
||||
|
||||
relocate_done:
|
|
@ -394,6 +394,15 @@ void switch_to_hypervisor_ret(void);
|
|||
#define wfi()
|
||||
#endif
|
||||
|
||||
static inline unsigned long read_mpidr(void)
|
||||
{
|
||||
unsigned long val;
|
||||
|
||||
asm volatile("mrc p15, 0, %0, c0, c0, 5" : "=r" (val));
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline unsigned long get_cpsr(void)
|
||||
{
|
||||
unsigned long cpsr;
|
||||
|
|
|
@ -68,6 +68,7 @@ obj-$(CONFIG_FSL_LAYERSCAPE) += ccn504.o
|
|||
ifneq ($(CONFIG_GICV2)$(CONFIG_GICV3),)
|
||||
obj-y += gic_64.o
|
||||
endif
|
||||
obj-$(CONFIG_DRIVER_GICV2) += gic-v2.o
|
||||
obj-$(CONFIG_GIC_V3_ITS) += gic-v3-its.o
|
||||
obj-y += interrupts_64.o
|
||||
else
|
||||
|
@ -86,6 +87,7 @@ obj-y += psci-dt.o
|
|||
obj-$(CONFIG_DEBUG_LL) += debug.o
|
||||
|
||||
obj-$(CONFIG_BLOBLIST) += xferlist.o
|
||||
obj-$(CONFIG_GENERATE_ACPI_TABLE) += acpi_table.o
|
||||
|
||||
# For EABI conformant tool chains, provide eabi_compat()
|
||||
ifneq (,$(findstring -mabi=aapcs-linux,$(PLATFORM_CPPFLAGS)))
|
||||
|
|
276
arch/arm/lib/acpi_table.c
Normal file
276
arch/arm/lib/acpi_table.c
Normal file
|
@ -0,0 +1,276 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Based on acpi.c from coreboot
|
||||
*
|
||||
* Copyright (C) 2024 9elements GmbH
|
||||
*/
|
||||
|
||||
#define LOG_CATEGORY LOGC_ACPI
|
||||
|
||||
#include <bloblist.h>
|
||||
#include <cpu_func.h>
|
||||
#include <efi_loader.h>
|
||||
#include <malloc.h>
|
||||
#include <string.h>
|
||||
#include <tables_csum.h>
|
||||
#include <acpi/acpigen.h>
|
||||
#include <acpi/acpi_device.h>
|
||||
#include <acpi/acpi_table.h>
|
||||
#include <asm-generic/io.h>
|
||||
#include <dm/acpi.h>
|
||||
#include <dm/uclass.h>
|
||||
#include <linux/log2.h>
|
||||
#include <linux/sizes.h>
|
||||
|
||||
/* defined in assembly file */
|
||||
/**
|
||||
* acpi_pp_code_size - Spinloop code size *
|
||||
*/
|
||||
extern u16 acpi_pp_code_size;
|
||||
|
||||
/**
|
||||
* acpi_pp_tables - Start of ACPI PP tables.
|
||||
*/
|
||||
extern ulong acpi_pp_tables;
|
||||
|
||||
/**
|
||||
* acpi_pp_etables - End of ACPI PP tables.
|
||||
*/
|
||||
extern ulong acpi_pp_etables;
|
||||
|
||||
/**
|
||||
* acpi_pp_code_start() - Spinloop code
|
||||
*
|
||||
* Architectural spinloop code to be installed in each parking protocol
|
||||
* page. The spinloop code must be less than 2048 bytes.
|
||||
*
|
||||
* The spinloop code will be entered after calling
|
||||
* acpi_parking_protocol_install().
|
||||
*
|
||||
*/
|
||||
void acpi_pp_code_start(void);
|
||||
|
||||
void acpi_write_madt_gicc(struct acpi_madt_gicc *gicc, uint cpu_num,
|
||||
uint perf_gsiv, ulong phys_base, ulong gicv,
|
||||
ulong gich, uint vgic_maint_irq, u64 gicr_base,
|
||||
ulong mpidr, uint efficiency)
|
||||
{
|
||||
memset(gicc, '\0', sizeof(struct acpi_madt_gicc));
|
||||
gicc->type = ACPI_APIC_GICC;
|
||||
gicc->length = sizeof(struct acpi_madt_gicc);
|
||||
gicc->cpu_if_num = cpu_num;
|
||||
gicc->processor_id = cpu_num;
|
||||
gicc->flags = ACPI_MADTF_ENABLED;
|
||||
gicc->perf_gsiv = perf_gsiv;
|
||||
gicc->phys_base = phys_base;
|
||||
gicc->gicv = gicv;
|
||||
gicc->gich = gich;
|
||||
gicc->vgic_maint_irq = vgic_maint_irq;
|
||||
gicc->gicr_base = gicr_base;
|
||||
gicc->mpidr = mpidr;
|
||||
gicc->efficiency = efficiency;
|
||||
}
|
||||
|
||||
void acpi_write_madt_gicd(struct acpi_madt_gicd *gicd, uint gic_id,
|
||||
ulong phys_base, uint gic_version)
|
||||
{
|
||||
memset(gicd, '\0', sizeof(struct acpi_madt_gicd));
|
||||
gicd->type = ACPI_APIC_GICD;
|
||||
gicd->length = sizeof(struct acpi_madt_gicd);
|
||||
gicd->gic_id = gic_id;
|
||||
gicd->phys_base = phys_base;
|
||||
gicd->gic_version = gic_version;
|
||||
}
|
||||
|
||||
void acpi_write_madt_gicr(struct acpi_madt_gicr *gicr,
|
||||
u64 discovery_range_base_address,
|
||||
u32 discovery_range_length)
|
||||
{
|
||||
memset(gicr, '\0', sizeof(struct acpi_madt_gicr));
|
||||
gicr->type = ACPI_APIC_GICR;
|
||||
gicr->length = sizeof(struct acpi_madt_gicr);
|
||||
gicr->discovery_range_base_address = discovery_range_base_address;
|
||||
gicr->discovery_range_length = discovery_range_length;
|
||||
}
|
||||
|
||||
void acpi_write_madt_its(struct acpi_madt_its *its,
|
||||
u32 its_id,
|
||||
u64 physical_base_address)
|
||||
{
|
||||
memset(its, '\0', sizeof(struct acpi_madt_its));
|
||||
its->type = ACPI_APIC_ITS;
|
||||
its->length = sizeof(struct acpi_madt_its);
|
||||
its->gic_its_id = its_id;
|
||||
its->physical_base_address = physical_base_address;
|
||||
}
|
||||
|
||||
int acpi_pptt_add_proc(struct acpi_ctx *ctx, const u32 flags, const u32 parent,
|
||||
const u32 proc_id, const u32 num_resources,
|
||||
const u32 *resource_list)
|
||||
{
|
||||
struct acpi_pptt_proc *proc = ctx->current;
|
||||
int offset;
|
||||
|
||||
offset = ctx->current - ctx->tab_start;
|
||||
proc->hdr.type = ACPI_PPTT_TYPE_PROC;
|
||||
proc->flags = flags;
|
||||
proc->parent = parent;
|
||||
proc->proc_id = proc_id;
|
||||
proc->num_resources = num_resources;
|
||||
proc->hdr.length = sizeof(struct acpi_pptt_proc) +
|
||||
sizeof(u32) * num_resources;
|
||||
|
||||
if (resource_list)
|
||||
memcpy(proc + 1, resource_list, sizeof(u32) * num_resources);
|
||||
|
||||
acpi_inc(ctx, proc->hdr.length);
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
int acpi_pptt_add_cache(struct acpi_ctx *ctx, const u32 flags,
|
||||
const u32 next_cache_level, const u32 size,
|
||||
const u32 sets, const u8 assoc, const u8 attributes,
|
||||
const u16 line_size)
|
||||
{
|
||||
struct acpi_pptt_cache *cache = ctx->current;
|
||||
int offset;
|
||||
|
||||
offset = ctx->current - ctx->tab_start;
|
||||
cache->hdr.type = ACPI_PPTT_TYPE_CACHE;
|
||||
cache->hdr.length = sizeof(struct acpi_pptt_cache);
|
||||
cache->flags = flags;
|
||||
cache->next_cache_level = next_cache_level;
|
||||
cache->size = size;
|
||||
cache->sets = sets;
|
||||
cache->assoc = assoc;
|
||||
cache->attributes = attributes;
|
||||
cache->line_size = line_size;
|
||||
acpi_inc(ctx, cache->hdr.length);
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
void *acpi_fill_madt(struct acpi_madt *madt, struct acpi_ctx *ctx)
|
||||
{
|
||||
uclass_probe_all(UCLASS_CPU);
|
||||
uclass_probe_all(UCLASS_IRQ);
|
||||
|
||||
/* All SoCs must use the driver model */
|
||||
acpi_fill_madt_subtbl(ctx);
|
||||
|
||||
return ctx->current;
|
||||
}
|
||||
|
||||
/**
|
||||
* acpi_write_pp_setup_one_page() - Fill out one page used by the PP
|
||||
*
|
||||
* Fill out the struct acpi_pp_page to contain the spin-loop
|
||||
* code and the mailbox area. After this function the page is ready for
|
||||
* the secondary core's to enter the spin-loop code.
|
||||
*
|
||||
* @page: Pointer to current parking protocol page
|
||||
* @gicc: Pointer to corresponding GICC sub-table
|
||||
*/
|
||||
static void acpi_write_pp_setup_one_page(struct acpi_pp_page *page,
|
||||
struct acpi_madt_gicc *gicc)
|
||||
{
|
||||
void *reloc;
|
||||
|
||||
/* Update GICC. Mark parking protocol as available. */
|
||||
gicc->parking_proto = ACPI_PP_VERSION;
|
||||
gicc->parked_addr = virt_to_phys(page);
|
||||
|
||||
/* Prepare parking protocol page */
|
||||
memset(page, '\0', sizeof(struct acpi_pp_page));
|
||||
|
||||
/* Init mailbox. Set MPIDR so core's will find their page. */
|
||||
page->cpu_id = gicc->mpidr;
|
||||
page->jumping_address = ACPI_PP_JMP_ADR_INVALID;
|
||||
|
||||
/* Relocate spinning code */
|
||||
reloc = &page->spinning_code[0];
|
||||
|
||||
log_debug("Relocating spin table from %lx to %lx (size %x)\n",
|
||||
(ulong)&acpi_pp_code_start, (ulong)reloc, acpi_pp_code_size);
|
||||
memcpy(reloc, &acpi_pp_code_start, acpi_pp_code_size);
|
||||
|
||||
if (!CONFIG_IS_ENABLED(SYS_DCACHE_OFF))
|
||||
flush_dcache_range((unsigned long)page,
|
||||
(unsigned long)(page + 1));
|
||||
}
|
||||
|
||||
void acpi_write_park(struct acpi_madt *madt)
|
||||
{
|
||||
struct acpi_pp_page *start, *page;
|
||||
struct acpi_madt_gicc *gicc;
|
||||
int ret, i, ncpus = 0;
|
||||
|
||||
/*
|
||||
* According to the "Multi-processor Startup for ARM Platforms":
|
||||
* - Every CPU as specified by MADT GICC has it's own 4K page
|
||||
* - Every page is divided into two sections: OS and FW reserved
|
||||
* - Memory occupied by "Parking Protocol" must be marked 'Reserved'
|
||||
* - Spinloop code should reside in FW reserved 2048 bytes
|
||||
* - Spinloop code will check the mailbox in OS reserved area
|
||||
*/
|
||||
|
||||
if (acpi_pp_code_size > sizeof(page->spinning_code)) {
|
||||
log_err("Spinning code too big to fit: %d\n",
|
||||
acpi_pp_code_size);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Count all MADT GICCs including BSP */
|
||||
for (i = sizeof(struct acpi_madt); i < madt->header.length;
|
||||
i += gicc->length) {
|
||||
gicc = (struct acpi_madt_gicc *)((void *)madt + i);
|
||||
if (gicc->type != ACPI_APIC_GICC)
|
||||
continue;
|
||||
ncpus++;
|
||||
}
|
||||
log_debug("Found %#x GICCs in MADT\n", ncpus);
|
||||
|
||||
/* Allocate pages linearly due to assembly code requirements */
|
||||
start = bloblist_add(BLOBLISTT_ACPI_PP, ACPI_PP_PAGE_SIZE * ncpus,
|
||||
ilog2(SZ_4K));
|
||||
if (!start) {
|
||||
log_err("Failed to allocate memory for ACPI-parking-protocol pages\n");
|
||||
return;
|
||||
}
|
||||
log_debug("Allocated parking protocol at %p\n", start);
|
||||
page = start;
|
||||
|
||||
if (IS_ENABLED(CONFIG_EFI_LOADER)) {
|
||||
/* Default mapping is 'BOOT CODE'. Mark as reserved instead. */
|
||||
ret = efi_add_memory_map((u64)(uintptr_t)start,
|
||||
ncpus * ACPI_PP_PAGE_SIZE,
|
||||
EFI_RESERVED_MEMORY_TYPE);
|
||||
|
||||
if (ret)
|
||||
log_err("Reserved memory mapping failed addr %p size %x\n",
|
||||
start, ncpus * ACPI_PP_PAGE_SIZE);
|
||||
}
|
||||
|
||||
/* Prepare the parking protocol pages */
|
||||
for (i = sizeof(struct acpi_madt); i < madt->header.length;
|
||||
i += gicc->length) {
|
||||
gicc = (struct acpi_madt_gicc *)((void *)madt + i);
|
||||
if (gicc->type != ACPI_APIC_GICC)
|
||||
continue;
|
||||
|
||||
acpi_write_pp_setup_one_page(page++, gicc);
|
||||
}
|
||||
|
||||
acpi_pp_etables = virt_to_phys(start) +
|
||||
ACPI_PP_PAGE_SIZE * ncpus;
|
||||
acpi_pp_tables = virt_to_phys(start);
|
||||
|
||||
/* Make sure other cores see written value in memory */
|
||||
if (!CONFIG_IS_ENABLED(SYS_DCACHE_OFF))
|
||||
flush_dcache_all();
|
||||
|
||||
/* Send an event to wake up the secondary CPU. */
|
||||
asm("dsb ishst\n"
|
||||
"sev");
|
||||
}
|
89
arch/arm/lib/gic-v2.c
Normal file
89
arch/arm/lib/gic-v2.c
Normal file
|
@ -0,0 +1,89 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright 2019 Broadcom.
|
||||
*/
|
||||
#include <dm.h>
|
||||
#include <irq.h>
|
||||
#include <asm/gic.h>
|
||||
#include <asm/acpi_table.h>
|
||||
#include <cpu_func.h>
|
||||
#include <dm/acpi.h>
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
|
||||
#ifdef CONFIG_ACPIGEN
|
||||
/**
|
||||
* acpi_gicv2_fill_madt() - Fill out the body of the MADT
|
||||
*
|
||||
* Write GICD and GICR tables based on collected devicetree data.
|
||||
*
|
||||
* @dev: Device to write ACPI tables for
|
||||
* @ctx: ACPI context to write MADT sub-tables to
|
||||
* Return: 0 if OK
|
||||
*/
|
||||
static int acpi_gicv2_fill_madt(const struct udevice *dev, struct acpi_ctx *ctx)
|
||||
{
|
||||
struct acpi_madt_gicd *gicd;
|
||||
fdt_addr_t addr;
|
||||
|
||||
addr = dev_read_addr_index(dev, 0);
|
||||
if (addr == FDT_ADDR_T_NONE) {
|
||||
pr_err("%s: failed to get GICD address\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
gicd = ctx->current;
|
||||
acpi_write_madt_gicd(gicd, dev_seq(dev), addr, 2);
|
||||
acpi_inc(ctx, gicd->length);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct acpi_ops gic_v2_acpi_ops = {
|
||||
.fill_madt = acpi_gicv2_fill_madt,
|
||||
};
|
||||
#endif
|
||||
|
||||
static const struct udevice_id gic_v2_ids[] = {
|
||||
{ .compatible = "arm,arm11mp-gic" },
|
||||
{ .compatible = "arm,cortex-a15-gic" },
|
||||
{ .compatible = "arm,cortex-a7-gic" },
|
||||
{ .compatible = "arm,cortex-a5-gic" },
|
||||
{ .compatible = "arm,cortex-a9-gic" },
|
||||
{ .compatible = "arm,eb11mp-gic" },
|
||||
{ .compatible = "arm,gic-400" },
|
||||
{ .compatible = "arm,pl390" },
|
||||
{ .compatible = "arm,tc11mp-gic" },
|
||||
{ .compatible = "qcom,msm-8660-qgic" },
|
||||
{ .compatible = "qcom,msm-qgic2" },
|
||||
{}
|
||||
};
|
||||
|
||||
static int arm_gic_v2_of_xlate(struct irq *irq, struct ofnode_phandle_args *args)
|
||||
{
|
||||
if (args->args_count != 3) {
|
||||
log_debug("Invalid args_count: %d\n", args->args_count);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* ARM Generic Interrupt Controller v1 and v2 */
|
||||
if (args->args[0] == GIC_SPI)
|
||||
irq->id = args->args[1] + 32;
|
||||
else
|
||||
irq->id = args->args[1] + 16;
|
||||
|
||||
irq->flags = args->args[2];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct irq_ops arm_gic_v2_ops = {
|
||||
.of_xlate = arm_gic_v2_of_xlate,
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(arm_gic_v2) = {
|
||||
.name = "gic-v2",
|
||||
.id = UCLASS_IRQ,
|
||||
.of_match = gic_v2_ids,
|
||||
.ops = &arm_gic_v2_ops,
|
||||
ACPI_OPS_PTR(&gic_v2_acpi_ops)
|
||||
};
|
|
@ -4,9 +4,13 @@
|
|||
*/
|
||||
#include <cpu_func.h>
|
||||
#include <dm.h>
|
||||
#include <irq.h>
|
||||
#include <asm/acpi_table.h>
|
||||
#include <asm/gic.h>
|
||||
#include <asm/gic-v3.h>
|
||||
#include <asm/io.h>
|
||||
#include <dm/acpi.h>
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/printk.h>
|
||||
#include <linux/sizes.h>
|
||||
|
@ -26,19 +30,21 @@ static u32 lpi_id_bits;
|
|||
struct gic_v3_its_priv {
|
||||
ulong gicd_base;
|
||||
ulong gicr_base;
|
||||
ulong gicr_length;
|
||||
};
|
||||
|
||||
static int gic_v3_its_get_gic_addr(struct gic_v3_its_priv *priv)
|
||||
{
|
||||
struct udevice *dev;
|
||||
fdt_addr_t addr;
|
||||
fdt_size_t size;
|
||||
int ret;
|
||||
|
||||
ret = uclass_get_device_by_driver(UCLASS_IRQ,
|
||||
DM_DRIVER_GET(arm_gic_v3_its), &dev);
|
||||
DM_DRIVER_GET(arm_gic_v3), &dev);
|
||||
if (ret) {
|
||||
pr_err("%s: failed to get %s irq device\n", __func__,
|
||||
DM_DRIVER_GET(arm_gic_v3_its)->name);
|
||||
DM_DRIVER_GET(arm_gic_v3)->name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -49,12 +55,13 @@ static int gic_v3_its_get_gic_addr(struct gic_v3_its_priv *priv)
|
|||
}
|
||||
priv->gicd_base = addr;
|
||||
|
||||
addr = dev_read_addr_index(dev, 1);
|
||||
addr = dev_read_addr_size_index(dev, 1, &size);
|
||||
if (addr == FDT_ADDR_T_NONE) {
|
||||
pr_err("%s: failed to get GICR address\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
priv->gicr_base = addr;
|
||||
priv->gicr_length = size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -158,13 +165,117 @@ int gic_lpi_tables_init(u64 base, u32 num_redist)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static const struct udevice_id gic_v3_its_ids[] = {
|
||||
#ifdef CONFIG_ACPIGEN
|
||||
/**
|
||||
* acpi_gicv3_fill_madt() - Fill out the body of the MADT
|
||||
*
|
||||
* Write GICD and GICR tables based on collected devicetree data.
|
||||
*
|
||||
* @dev: Device to write ACPI tables for
|
||||
* @ctx: ACPI context to write MADT sub-tables to
|
||||
* Return: 0 if OK
|
||||
*/
|
||||
static int acpi_gicv3_fill_madt(const struct udevice *dev, struct acpi_ctx *ctx)
|
||||
{
|
||||
struct acpi_madt_gicd *gicd;
|
||||
struct acpi_madt_gicr *gicr;
|
||||
|
||||
struct gic_v3_its_priv priv;
|
||||
|
||||
if (gic_v3_its_get_gic_addr(&priv))
|
||||
return -EINVAL;
|
||||
|
||||
gicd = ctx->current;
|
||||
acpi_write_madt_gicd(gicd, dev_seq(dev), priv.gicd_base, 3);
|
||||
acpi_inc(ctx, gicd->length);
|
||||
|
||||
gicr = ctx->current;
|
||||
acpi_write_madt_gicr(gicr, priv.gicr_base, priv.gicr_length);
|
||||
acpi_inc(ctx, gicr->length);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct acpi_ops gic_v3_acpi_ops = {
|
||||
.fill_madt = acpi_gicv3_fill_madt,
|
||||
};
|
||||
#endif
|
||||
|
||||
static const struct udevice_id gic_v3_ids[] = {
|
||||
{ .compatible = "arm,gic-v3" },
|
||||
{}
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(arm_gic_v3_its) = {
|
||||
static int arm_gic_v3_of_xlate(struct irq *irq, struct ofnode_phandle_args *args)
|
||||
{
|
||||
if (args->args_count < 3) {
|
||||
log_debug("Invalid args_count: %d\n", args->args_count);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (args->args[0] == GIC_SPI)
|
||||
irq->id = args->args[1] + 32;
|
||||
else
|
||||
irq->id = args->args[1] + 16;
|
||||
|
||||
irq->flags = args->args[2];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct irq_ops arm_gic_v3_ops = {
|
||||
.of_xlate = arm_gic_v3_of_xlate,
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(arm_gic_v3) = {
|
||||
.name = "gic-v3",
|
||||
.id = UCLASS_IRQ,
|
||||
.of_match = gic_v3_its_ids,
|
||||
.of_match = gic_v3_ids,
|
||||
.ops = &arm_gic_v3_ops,
|
||||
ACPI_OPS_PTR(&gic_v3_acpi_ops)
|
||||
};
|
||||
|
||||
#ifdef CONFIG_ACPIGEN
|
||||
/**
|
||||
* acpi_gic_its_fill_madt() - Fill out the body of the MADT
|
||||
*
|
||||
* Write ITS tables based on collected devicetree data.
|
||||
*
|
||||
* @dev: Device to write ACPI tables for
|
||||
* @ctx: ACPI context to write MADT sub-tables to
|
||||
* Return: 0 if OK
|
||||
*/
|
||||
static int acpi_gic_its_fill_madt(const struct udevice *dev, struct acpi_ctx *ctx)
|
||||
{
|
||||
struct acpi_madt_its *its;
|
||||
fdt_addr_t addr;
|
||||
|
||||
addr = dev_read_addr_index(dev, 0);
|
||||
if (addr == FDT_ADDR_T_NONE) {
|
||||
pr_err("%s: failed to get GIC ITS address\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
its = ctx->current;
|
||||
acpi_write_madt_its(its, dev_seq(dev), addr);
|
||||
acpi_inc(ctx, its->length);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct acpi_ops gic_v3_its_acpi_ops = {
|
||||
.fill_madt = acpi_gic_its_fill_madt,
|
||||
};
|
||||
#endif
|
||||
|
||||
static const struct udevice_id gic_v3_its_ids[] = {
|
||||
{ .compatible = "arm,gic-v3-its" },
|
||||
{}
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(arm_gic_v3_its) = {
|
||||
.name = "gic-v3-its",
|
||||
.id = UCLASS_IRQ,
|
||||
.of_match = gic_v3_its_ids,
|
||||
ACPI_OPS_PTR(&gic_v3_its_acpi_ops)
|
||||
};
|
||||
|
|
|
@ -24,7 +24,13 @@ config BCM2837_64B
|
|||
bool "Broadcom BCM2837 SoC 64-bit support"
|
||||
depends on ARCH_BCM283X
|
||||
select BCM2837
|
||||
select DRIVER_GICV2
|
||||
select ARM64
|
||||
select CPU_ARMV8
|
||||
select ARMV8_MULTIENTRY if GENERATE_ACPI_TABLE
|
||||
select BLOBLIST if GENERATE_ACPI_TABLE
|
||||
select BLOBLIST_ALLOC if GENERATE_ACPI_TABLE
|
||||
select BLOBLIST_TABLES if GENERATE_ACPI_TABLE
|
||||
|
||||
config BCM2711
|
||||
bool "Broadcom BCM2711 SoC support"
|
||||
|
@ -42,11 +48,16 @@ config BCM2711_64B
|
|||
bool "Broadcom BCM2711 SoC 64-bit support"
|
||||
depends on ARCH_BCM283X
|
||||
select BCM2711
|
||||
select DRIVER_GICV2
|
||||
select ARM64
|
||||
select CPU_ARMV8
|
||||
select ARMV8_MULTIENTRY if GENERATE_ACPI_TABLE
|
||||
select BLOBLIST if GENERATE_ACPI_TABLE
|
||||
select BLOBLIST_ALLOC if GENERATE_ACPI_TABLE
|
||||
select BLOBLIST_TABLES if GENERATE_ACPI_TABLE
|
||||
|
||||
menu "Broadcom BCM283X family"
|
||||
depends on ARCH_BCM283X
|
||||
|
||||
choice
|
||||
prompt "Broadcom BCM283X board select"
|
||||
optional
|
||||
|
@ -210,6 +221,9 @@ config SYS_SOC
|
|||
config SYS_CONFIG_NAME
|
||||
default "rpi"
|
||||
|
||||
config BLOBLIST_SIZE_RELOC
|
||||
default 0x20000
|
||||
|
||||
source "board/raspberrypi/rpi/Kconfig"
|
||||
|
||||
endmenu
|
||||
|
|
|
@ -4,3 +4,7 @@
|
|||
|
||||
obj-$(CONFIG_BCM2835) += lowlevel_init.o
|
||||
obj-y += init.o reset.o mbox.o msg.o phys2bus.o
|
||||
|
||||
ifeq ($(CONFIG_GENERATE_ACPI_TABLE),y)
|
||||
obj-$(CONFIG_BCM2711) += bcm2711_acpi.o
|
||||
endif
|
128
arch/arm/mach-bcm283x/bcm2711_acpi.c
Normal file
128
arch/arm/mach-bcm283x/bcm2711_acpi.c
Normal file
|
@ -0,0 +1,128 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* (C) Copyright 2024 9elements GmbH
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <tables_csum.h>
|
||||
#include <acpi/acpi_table.h>
|
||||
#include <asm/acpi_table.h>
|
||||
#include <asm/armv8/sec_firmware.h>
|
||||
#include <asm/arch/acpi/bcm2711.h>
|
||||
#include <dm/uclass.h>
|
||||
|
||||
void acpi_fill_fadt(struct acpi_fadt *fadt)
|
||||
{
|
||||
fadt->flags = ACPI_FADT_HW_REDUCED_ACPI | ACPI_FADT_LOW_PWR_IDLE_S0;
|
||||
|
||||
if (CONFIG_IS_ENABLED(SEC_FIRMWARE_ARMV8_PSCI) &&
|
||||
sec_firmware_support_psci_version() != PSCI_INVALID_VER)
|
||||
fadt->arm_boot_arch = ACPI_ARM_PSCI_COMPLIANT;
|
||||
}
|
||||
|
||||
#define L3_ATTRIBUTES (ACPI_PPTT_READ_ALLOC | ACPI_PPTT_WRITE_ALLOC | \
|
||||
(ACPI_PPTT_CACHE_TYPE_UNIFIED << \
|
||||
ACPI_PPTT_CACHE_TYPE_SHIFT))
|
||||
#define L3_SIZE 0x100000
|
||||
#define L3_SETS 0x400
|
||||
#define L3_WAYS 0x10
|
||||
|
||||
#define L1D_ATTRIBUTES (ACPI_PPTT_READ_ALLOC | ACPI_PPTT_WRITE_ALLOC | \
|
||||
(ACPI_PPTT_CACHE_TYPE_DATA << \
|
||||
ACPI_PPTT_CACHE_TYPE_SHIFT))
|
||||
#define L1D_SIZE 0x8000
|
||||
#define L1D_SETS 0x100
|
||||
#define L1D_WAYS 2
|
||||
|
||||
#define L1I_ATTRIBUTES (ACPI_PPTT_READ_ALLOC | \
|
||||
(ACPI_PPTT_CACHE_TYPE_INSTR << \
|
||||
ACPI_PPTT_CACHE_TYPE_SHIFT))
|
||||
#define L1I_SIZE 0xc000
|
||||
#define L1I_SETS 0x100
|
||||
#define L1I_WAYS 3
|
||||
|
||||
static int acpi_write_pptt(struct acpi_ctx *ctx, const struct acpi_writer *entry)
|
||||
{
|
||||
struct acpi_table_header *header;
|
||||
int cluster_offset, l3_offset;
|
||||
u32 offsets[2];
|
||||
|
||||
header = ctx->current;
|
||||
ctx->tab_start = ctx->current;
|
||||
|
||||
memset(header, '\0', sizeof(struct acpi_table_header));
|
||||
|
||||
acpi_fill_header(header, "PPTT");
|
||||
header->revision = acpi_get_table_revision(ACPITAB_PPTT);
|
||||
acpi_inc(ctx, sizeof(*header));
|
||||
|
||||
l3_offset = acpi_pptt_add_cache(ctx, ACPI_PPTT_ALL_VALID, 0, L3_SIZE,
|
||||
L3_SETS, L3_WAYS, L3_ATTRIBUTES, 64);
|
||||
|
||||
cluster_offset = acpi_pptt_add_proc(ctx, ACPI_PPTT_PHYSICAL_PACKAGE |
|
||||
ACPI_PPTT_CHILDREN_IDENTICAL,
|
||||
0, 0, 1, &l3_offset);
|
||||
|
||||
offsets[0] = acpi_pptt_add_cache(ctx, ACPI_PPTT_ALL_VALID, 0, L1D_SIZE,
|
||||
L1D_SETS, L1D_WAYS, L1D_ATTRIBUTES, 64);
|
||||
|
||||
offsets[1] = acpi_pptt_add_cache(ctx, ACPI_PPTT_ALL_BUT_WRITE_POL, 0,
|
||||
L1I_SIZE, L1I_SETS, L1I_WAYS,
|
||||
L1I_ATTRIBUTES, 64);
|
||||
|
||||
for (int i = 0; i < uclass_id_count(UCLASS_CPU); i++) {
|
||||
acpi_pptt_add_proc(ctx, ACPI_PPTT_CHILDREN_IDENTICAL |
|
||||
ACPI_PPTT_NODE_IS_LEAF |
|
||||
ACPI_PPTT_PROC_ID_VALID,
|
||||
cluster_offset, i, 2, offsets);
|
||||
}
|
||||
|
||||
header->length = ctx->current - ctx->tab_start;
|
||||
header->checksum = table_compute_checksum(header, header->length);
|
||||
|
||||
acpi_inc(ctx, header->length);
|
||||
acpi_add_table(ctx, header);
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
ACPI_WRITER(5pptt, "PPTT", acpi_write_pptt, 0);
|
||||
|
||||
static int rpi_write_gtdt(struct acpi_ctx *ctx, const struct acpi_writer *entry)
|
||||
{
|
||||
struct acpi_table_header *header;
|
||||
struct acpi_gtdt *gtdt;
|
||||
|
||||
gtdt = ctx->current;
|
||||
header = >dt->header;
|
||||
|
||||
memset(gtdt, '\0', sizeof(struct acpi_gtdt));
|
||||
|
||||
acpi_fill_header(header, "GTDT");
|
||||
header->length = sizeof(struct acpi_gtdt);
|
||||
header->revision = acpi_get_table_revision(ACPITAB_GTDT);
|
||||
|
||||
gtdt->cnt_ctrl_base = BCM2711_ARM_LOCAL_BASE_ADDRESS + 0x1c;
|
||||
gtdt->sec_el1_gsiv = 29;
|
||||
gtdt->sec_el1_flags = GTDT_FLAG_INT_ACTIVE_LOW;
|
||||
gtdt->el1_gsiv = 30;
|
||||
gtdt->el1_flags = GTDT_FLAG_INT_ACTIVE_LOW;
|
||||
gtdt->virt_el1_gsiv = 27;
|
||||
gtdt->virt_el1_flags = GTDT_FLAG_INT_ACTIVE_LOW;
|
||||
gtdt->el2_gsiv = 26;
|
||||
gtdt->el2_flags = GTDT_FLAG_INT_ACTIVE_LOW;
|
||||
gtdt->cnt_read_base = 0xffffffffffffffff;
|
||||
|
||||
header->checksum = table_compute_checksum(header, header->length);
|
||||
|
||||
acpi_add_table(ctx, gtdt);
|
||||
|
||||
acpi_inc(ctx, sizeof(struct acpi_gtdt));
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
ACPI_WRITER(5gtdt, "GTDT", rpi_write_gtdt, 0);
|
152
arch/arm/mach-bcm283x/include/mach/acpi/bcm2711.h
Normal file
152
arch/arm/mach-bcm283x/include/mach/acpi/bcm2711.h
Normal file
|
@ -0,0 +1,152 @@
|
|||
/* SPDX-License-Identifier: BSD-2-Clause-Patent */
|
||||
/**
|
||||
*
|
||||
* Copyright (c) 2019, Jeremy Linton
|
||||
* Copyright (c) 2019, Pete Batard <pete@akeo.ie>.
|
||||
*
|
||||
**/
|
||||
|
||||
#ifndef BCM2711_H__
|
||||
#define BCM2711_H__
|
||||
|
||||
#define BCM2711_SOC_REGISTERS 0xfc000000
|
||||
#define BCM2711_SOC_REGISTER_LENGTH 0x02000000
|
||||
|
||||
#define BCM2711_ARM_LOCAL_REGISTERS 0xfe000000
|
||||
#define BCM2711_ARM_LOCAL_REGISTER_LENGTH 0x02000000
|
||||
|
||||
/* arm local addresses */
|
||||
#define BCM2711_ARMC_OFFSET 0x0000b000
|
||||
#define BCM2711_ARMC_BASE_ADDRESS (BCM2711_ARM_LOCAL_REGISTERS + BCM2711_ARMC_OFFSET)
|
||||
#define BCM2711_ARMC_LENGTH 0x00000400
|
||||
|
||||
#define BCM2711_ARM_LOCAL_OFFSET 0x01800000
|
||||
#define BCM2711_ARM_LOCAL_BASE_ADDRESS (BCM2711_ARM_LOCAL_REGISTERS + BCM2711_ARM_LOCAL_OFFSET)
|
||||
#define BCM2711_ARM_LOCAL_LENGTH 0x00000080
|
||||
|
||||
#define BCM2711_GIC400_OFFSET 0x01840000
|
||||
#define BCM2711_GIC400_BASE_ADDRESS (BCM2711_ARM_LOCAL_REGISTERS + BCM2711_GIC400_OFFSET)
|
||||
#define BCM2711_GIC400_LENGTH 0x00008000
|
||||
|
||||
/* Generic PCI addresses */
|
||||
#define PCIE_TOP_OF_MEM_WIN 0xf8000000
|
||||
#define PCIE_CPU_MMIO_WINDOW 0x600000000
|
||||
#define PCIE_BRIDGE_MMIO_LEN 0x3ffffff
|
||||
|
||||
/* PCI root bridge control registers location */
|
||||
#define PCIE_REG_BASE 0xfd500000
|
||||
#define PCIE_REG_LIMIT 0x9310
|
||||
|
||||
/* PCI root bridge control registers */
|
||||
#define BRCM_PCIE_CAP_REGS 0x00ac
|
||||
#define PCIE_RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1 0x0188
|
||||
#define VENDOR_SPECIFIC_REG1_LITTLE_ENDIAN 0x0
|
||||
#define PCIE_RC_CFG_PRIV1_ID_VAL3 0x043c
|
||||
#define PCIE_RC_CFG_PRIV1_LINK_CAPABILITY 0x04dc
|
||||
#define LINK_CAPABILITY_ASPM_SUPPORT_MASK 0xc00
|
||||
|
||||
#define PCIE_RC_DL_MDIO_ADDR 0x1100
|
||||
#define PCIE_RC_DL_MDIO_WR_DATA 0x1104
|
||||
#define PCIE_RC_DL_MDIO_RD_DATA 0x1108
|
||||
|
||||
#define PCIE_MISC_MISC_CTRL 0x4008
|
||||
#define MISC_CTRL_SCB_ACCESS_EN_MASK 0x1000
|
||||
#define MISC_CTRL_CFG_READ_UR_MODE_MASK 0x2000
|
||||
#define MISC_CTRL_MAX_BURST_SIZE_MASK 0x300000
|
||||
#define MISC_CTRL_MAX_BURST_SIZE_128 0x0
|
||||
#define MISC_CTRL_SCB0_SIZE_MASK 0xf8000000
|
||||
|
||||
#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LO 0x400c
|
||||
#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_HI 0x4010
|
||||
#define PCIE_MEM_WIN0_LO(win) \
|
||||
PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LO + ((win) * 4)
|
||||
|
||||
#define PCIE_MEM_WIN0_HI(win) \
|
||||
PCIE_MISC_CPU_2_PCIE_MEM_WIN0_HI + ((win) * 4)
|
||||
#define PCIE_MISC_RC_BAR1_CONFIG_LO 0x402c
|
||||
#define RC_BAR1_CONFIG_LO_SIZE_MASK 0x1f
|
||||
#define PCIE_MISC_RC_BAR2_CONFIG_LO 0x4034
|
||||
#define RC_BAR2_CONFIG_LO_SIZE_MASK 0x1f
|
||||
#define PCIE_MISC_RC_BAR2_CONFIG_HI 0x4038
|
||||
#define PCIE_MISC_RC_BAR3_CONFIG_LO 0x403c
|
||||
#define RC_BAR3_CONFIG_LO_SIZE_MASK 0x1f
|
||||
#define PCIE_MISC_PCIE_STATUS 0x4068
|
||||
#define STATUS_PCIE_PORT_MASK 0x80
|
||||
#define STATUS_PCIE_PORT_SHIFT 7
|
||||
#define STATUS_PCIE_DL_ACTIVE_MASK 0x20
|
||||
#define STATUS_PCIE_DL_ACTIVE_SHIFT 5
|
||||
#define STATUS_PCIE_PHYLINKUP_MASK 0x10
|
||||
#define STATUS_PCIE_PHYLINKUP_SHIFT 4
|
||||
#define PCIE_MISC_REVISION 0x406c
|
||||
#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT 0x4070
|
||||
#define MEM_WIN0_BASE_LIMIT_LIMIT_MASK 0xfff00000
|
||||
#define MEM_WIN0_BASE_LIMIT_BASE_MASK 0xfff0
|
||||
#define MEM_WIN0_BASE_LIMIT_BASE_HI_SHIFT 12
|
||||
#define PCIE_MEM_WIN0_BASE_LIMIT(win) \
|
||||
PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT + ((win) * 4)
|
||||
#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_HI 0x4080
|
||||
#define MEM_WIN0_BASE_HI_BASE_MASK 0xff
|
||||
#define PCIE_MEM_WIN0_BASE_HI(win) \
|
||||
PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_HI + ((win) * 8)
|
||||
#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI 0x4084
|
||||
#define PCIE_MEM_WIN0_LIMIT_HI_LIMIT_MASK 0xff
|
||||
#define PCIE_MEM_WIN0_LIMIT_HI(win) \
|
||||
PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI + ((win) * 8)
|
||||
|
||||
#define PCIE_MISC_HARD_PCIE_HARD_DEBUG 0x4204
|
||||
#define PCIE_HARD_DEBUG_SERDES_IDDQ_MASK 0x08000000
|
||||
|
||||
#define PCIE_INTR2_CPU_STATUS 0x4300
|
||||
#define PCIE_INTR2_CPU_SET 0x4304
|
||||
#define PCIE_INTR2_CPU_CLR 0x4308
|
||||
#define PCIE_INTR2_CPU_MASK_STATUS 0x430c
|
||||
#define PCIE_INTR2_CPU_MASK_SET 0x4310
|
||||
#define PCIE_INTR2_CPU_MASK_CLR 0x4314
|
||||
|
||||
#define PCIE_MSI_INTR2_CLR 0x4508
|
||||
#define PCIE_MSI_INTR2_MASK_SET 0x4510
|
||||
|
||||
#define PCIE_RGR1_SW_INIT_1 0x9210
|
||||
#define PCIE_EXT_CFG_INDEX 0x9000
|
||||
/* A small window pointing at the ECAM of the device selected by CFG_INDEX */
|
||||
#define PCIE_EXT_CFG_DATA 0x8000
|
||||
|
||||
#define PCIE_RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1_ENDIAN_MODE_BAR2_MASK 0xc
|
||||
#define PCIE_RC_CFG_PRIV1_ID_VAL3_CLASS_CODE_MASK 0xffffff
|
||||
|
||||
#define PCIE_MISC_MISC_CTRL_SCB_ACCESS_EN_MASK 0x1000
|
||||
#define PCIE_MISC_MISC_CTRL_CFG_READ_UR_MODE_MASK 0x2000
|
||||
#define PCIE_MISC_MISC_CTRL_MAX_BURST_SIZE_MASK 0x300000
|
||||
#define PCIE_MISC_MISC_CTRL_SCB0_SIZE_MASK 0xf8000000
|
||||
#define PCIE_MISC_MISC_CTRL_SCB1_SIZE_MASK 0x7c00000
|
||||
#define PCIE_MISC_MISC_CTRL_SCB2_SIZE_MASK 0x1f
|
||||
#define PCIE_MISC_RC_BAR2_CONFIG_LO_SIZE_MASK 0x1f
|
||||
|
||||
#define PCIE_RGR1_SW_INIT_1_INIT_MASK 0x2
|
||||
#define PCIE_RGR1_SW_INIT_1_PERST_MASK 0x1
|
||||
|
||||
#define PCIE_MISC_HARD_PCIE_HARD_DEBUG_SERDES_IDDQ_MASK 0x08000000
|
||||
|
||||
#define PCIE_MISC_HARD_PCIE_HARD_DEBUG_CLKREQ_DEBUG_ENABLE_MASK 0x2
|
||||
|
||||
#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT_LIMIT_MASK 0xfff00000
|
||||
#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT_BASE_MASK 0xfff0
|
||||
#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_HI_BASE_MASK 0xff
|
||||
#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI_LIMIT_MASK 0xff
|
||||
#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_MASK_BITS 0xc
|
||||
|
||||
#define PCIE_MISC_REVISION_MAJMIN_MASK 0xffff
|
||||
|
||||
#define BURST_SIZE_128 0
|
||||
#define BURST_SIZE_256 1
|
||||
#define BURST_SIZE_512 2
|
||||
|
||||
#define BCM2711_THERM_SENSOR_OFFSET 0x015d2200
|
||||
#define BCM2711_THERM_SENSOR_BASE_ADDRESS (BCM2711_SOC_REGISTERS + BCM2711_THERM_SENSOR_OFFSET)
|
||||
#define BCM2711_THERM_SENSOR_LENGTH 0x00000008
|
||||
|
||||
#define BCM2711_GENET_BASE_OFFSET 0x01580000
|
||||
#define BCM2711_GENET_BASE_ADDRESS (BCM2711_SOC_REGISTERS + BCM2711_GENET_BASE_OFFSET)
|
||||
#define BCM2711_GENET_LENGTH 0x10000
|
||||
|
||||
#endif /* BCM2711_H__ */
|
127
arch/arm/mach-bcm283x/include/mach/acpi/bcm2836.h
Normal file
127
arch/arm/mach-bcm283x/include/mach/acpi/bcm2836.h
Normal file
|
@ -0,0 +1,127 @@
|
|||
/* SPDX-License-Identifier: BSD-2-Clause-Patent */
|
||||
/**
|
||||
*
|
||||
* Copyright (c) 2019, ARM Limited. All rights reserved.
|
||||
* Copyright (c) 2017, Andrei Warkentin <andrey.warkentin@gmail.com>
|
||||
* Copyright (c) 2016, Linaro Limited. All rights reserved.
|
||||
*
|
||||
**/
|
||||
|
||||
#ifndef __BCM2836_H__
|
||||
#define __BCM2836_H__
|
||||
|
||||
/*
|
||||
* Both "core" and SoC perpherals (1M each).
|
||||
*/
|
||||
#define BCM2836_SOC_REGISTERS 0xfe000000
|
||||
#define BCM2836_SOC_REGISTER_LENGTH 0x02000000
|
||||
|
||||
/*
|
||||
* Offset between the CPU's view and the VC's view of system memory.
|
||||
*/
|
||||
#define BCM2836_DMA_DEVICE_OFFSET 0xc0000000
|
||||
|
||||
/* watchdog constants */
|
||||
#define BCM2836_WDOG_OFFSET 0x00100000
|
||||
#define BCM2836_WDOG_BASE_ADDRESS (BCM2836_SOC_REGISTERS + BCM2836_WDOG_OFFSET)
|
||||
#define BCM2836_WDOG_PASSWORD 0x5a000000
|
||||
#define BCM2836_WDOG_RSTC_OFFSET 0x0000001c
|
||||
#define BCM2836_WDOG_WDOG_OFFSET 0x00000024
|
||||
#define BCM2836_WDOG_RSTC_WRCFG_MASK 0x00000030
|
||||
#define BCM2836_WDOG_RSTC_WRCFG_FULL_RESET 0x00000020
|
||||
|
||||
/* clock manager constants */
|
||||
#define BCM2836_CM_OFFSET 0x00101000
|
||||
#define BCM2836_CM_BASE (BCM2836_SOC_REGISTERS + BCM2836_CM_OFFSET)
|
||||
#define BCM2836_CM_GEN_CLOCK_CONTROL 0x0000
|
||||
#define BCM2836_CM_GEN_CLOCK_DIVISOR 0x0004
|
||||
#define BCM2836_CM_VPU_CLOCK_CONTROL 0x0008
|
||||
#define BCM2836_CM_VPU_CLOCK_DIVISOR 0x000c
|
||||
#define BCM2836_CM_SYSTEM_CLOCK_CONTROL 0x0010
|
||||
#define BCM2836_CM_SYSTEM_CLOCK_DIVISOR 0x0014
|
||||
#define BCM2836_CM_H264_CLOCK_CONTROL 0x0028
|
||||
#define BCM2836_CM_H264_CLOCK_DIVISOR 0x002c
|
||||
#define BCM2836_CM_PWM_CLOCK_CONTROL 0x00a0
|
||||
#define BCM2836_CM_PWM_CLOCK_DIVISOR 0x00a4
|
||||
#define BCM2836_CM_UART_CLOCK_CONTROL 0x00f0
|
||||
#define BCM2836_CM_UART_CLOCK_DIVISOR 0x00f4
|
||||
#define BCM2836_CM_SDC_CLOCK_CONTROL 0x01a8
|
||||
#define BCM2836_CM_SDC_CLOCK_DIVISOR 0x01ac
|
||||
#define BCM2836_CM_ARM_CLOCK_CONTROL 0x01b0
|
||||
#define BCM2836_CM_ARM_CLOCK_DIVISOR 0x01b4
|
||||
#define BCM2836_CM_EMMC_CLOCK_CONTROL 0x01c0
|
||||
#define BCM2836_CM_EMMC_CLOCK_DIVISOR 0x01c4
|
||||
|
||||
/* mailbox interface constants */
|
||||
#define BCM2836_MBOX_OFFSET 0x0000b880
|
||||
#define BCM2836_MBOX_BASE_ADDRESS (BCM2836_SOC_REGISTERS + BCM2836_MBOX_OFFSET)
|
||||
#define BCM2836_MBOX_LENGTH 0x00000024
|
||||
#define BCM2836_MBOX_READ_OFFSET 0x00000000
|
||||
#define BCM2836_MBOX_STATUS_OFFSET 0x00000018
|
||||
#define BCM2836_MBOX_CONFIG_OFFSET 0x0000001c
|
||||
#define BCM2836_MBOX_WRITE_OFFSET 0x00000020
|
||||
|
||||
#define BCM2836_MBOX_STATUS_FULL 0x1f
|
||||
#define BCM2836_MBOX_STATUS_EMPTY 0x1e
|
||||
|
||||
#define BCM2836_MBOX_NUM_CHANNELS 16
|
||||
|
||||
/* interrupt controller constants */
|
||||
#define BCM2836_INTC_TIMER_CONTROL_OFFSET 0x00000040
|
||||
#define BCM2836_INTC_TIMER_PENDING_OFFSET 0x00000060
|
||||
|
||||
/* usb constants */
|
||||
#define BCM2836_USB_OFFSET 0x00980000
|
||||
#define BCM2836_USB_BASE_ADDRESS (BCM2836_SOC_REGISTERS + BCM2836_USB_OFFSET)
|
||||
#define BCM2836_USB_LENGTH 0x00010000
|
||||
|
||||
/* serial based protocol constants */
|
||||
#define BCM2836_PL011_UART_OFFSET 0x00201000
|
||||
#define BCM2836_PL011_UART_BASE_ADDRESS (BCM2836_SOC_REGISTERS + BCM2836_PL011_UART_OFFSET)
|
||||
#define BCM2836_PL011_UART_LENGTH 0x00001000
|
||||
|
||||
#define BCM2836_MINI_UART_OFFSET 0x00215000
|
||||
#define BCM2836_MINI_UART_BASE_ADDRESS (BCM2836_SOC_REGISTERS + BCM2836_MINI_UART_OFFSET)
|
||||
#define BCM2836_MINI_UART_LENGTH 0x00000070
|
||||
|
||||
#define BCM2836_I2C0_OFFSET 0x00205000
|
||||
#define BCM2836_I2C0_BASE_ADDRESS (BCM2836_SOC_REGISTERS + BCM2836_I2C0_OFFSET)
|
||||
#define BCM2836_I2C0_LENGTH 0x00000020
|
||||
|
||||
#define BCM2836_I2C1_OFFSET 0x00804000
|
||||
#define BCM2836_I2C1_BASE_ADDRESS (BCM2836_SOC_REGISTERS + BCM2836_I2C1_OFFSET)
|
||||
#define BCM2836_I2C1_LENGTH 0x00000020
|
||||
|
||||
#define BCM2836_I2C2_OFFSET 0x00805000
|
||||
#define BCM2836_I2C2_BASE_ADDRESS (BCM2836_SOC_REGISTERS + BCM2836_I2C2_OFFSET)
|
||||
#define BCM2836_I2C2_LENGTH 0x00000020
|
||||
|
||||
#define BCM2836_SPI0_OFFSET 0x00204000
|
||||
#define BCM2836_SPI0_BASE_ADDRESS (BCM2836_SOC_REGISTERS + BCM2836_SPI0_OFFSET)
|
||||
#define BCM2836_SPI0_LENGTH 0x00000020
|
||||
|
||||
#define BCM2836_SPI1_OFFSET 0x00215080
|
||||
#define BCM2836_SPI1_LENGTH 0x00000040
|
||||
#define BCM2836_SPI1_BASE_ADDRESS (BCM2836_SOC_REGISTERS + BCM2836_SPI1_OFFSET)
|
||||
|
||||
#define BCM2836_SPI2_OFFSET 0x002150C0
|
||||
#define BCM2836_SPI2_LENGTH 0x00000040
|
||||
#define BCM2836_SPI2_BASE_ADDRESS (BCM2836_SOC_REGISTERS + BCM2836_SPI2_OFFSET)
|
||||
|
||||
#define BCM2836_SYSTEM_TIMER_OFFSET 0x00003000
|
||||
#define BCM2836_SYSTEM_TIMER_LENGTH 0x00000020
|
||||
#define BCM2836_SYSTEM_TIMER_ADDRESS (BCM2836_SOC_REGISTERS + BCM2836_SYSTEM_TIMER_OFFSET)
|
||||
|
||||
/* dma constants */
|
||||
#define BCM2836_DMA0_OFFSET 0x00007000
|
||||
#define BCM2836_DMA0_BASE_ADDRESS (BCM2836_SOC_REGISTERS + BCM2836_DMA0_OFFSET)
|
||||
|
||||
#define BCM2836_DMA15_OFFSET 0x00E05000
|
||||
#define BCM2836_DMA15_BASE_ADDRESS (BCM2836_SOC_REGISTERS + BCM2836_DMA15_OFFSET)
|
||||
|
||||
#define BCM2836_DMA_CTRL_OFFSET 0x00007FE0
|
||||
#define BCM2836_DMA_CTRL_BASE_ADDRESS (BCM2836_SOC_REGISTERS + BCM2836_DMA_CTRL_OFFSET)
|
||||
|
||||
#define BCM2836_DMA_CHANNEL_LENGTH 0x00000100
|
||||
|
||||
#endif /*__BCM2836_H__ */
|
19
arch/arm/mach-bcm283x/include/mach/acpi/bcm2836_gpio.h
Normal file
19
arch/arm/mach-bcm283x/include/mach/acpi/bcm2836_gpio.h
Normal file
|
@ -0,0 +1,19 @@
|
|||
/* SPDX-License-Identifier: BSD-2-Clause-Patent */
|
||||
/**
|
||||
*
|
||||
* Copyright (c) 2020, Pete Batard <pete@akeo.ie>
|
||||
* Copyright (c) 2018, Andrei Warkentin <andrey.warkentin@gmail.com>
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
*
|
||||
**/
|
||||
|
||||
#include <asm/arch/acpi/bcm2836.h>
|
||||
|
||||
#ifndef __BCM2836_GPIO_H__
|
||||
#define __BCM2836_GPIO_H__
|
||||
|
||||
#define GPIO_OFFSET 0x00200000
|
||||
#define GPIO_BASE_ADDRESS (BCM2836_SOC_REGISTERS + GPIO_OFFSET)
|
||||
#define GPIO_LENGTH 0x000000B4
|
||||
|
||||
#endif /* __BCM2836_GPIO_H__ */
|
47
arch/arm/mach-bcm283x/include/mach/acpi/bcm2836_gpu.h
Normal file
47
arch/arm/mach-bcm283x/include/mach/acpi/bcm2836_gpu.h
Normal file
|
@ -0,0 +1,47 @@
|
|||
/* SPDX-License-Identifier: BSD-2-Clause-Patent */
|
||||
/**
|
||||
*
|
||||
* Copyright (c) 2020, Pete Batard <pete@akeo.ie>
|
||||
*
|
||||
**/
|
||||
|
||||
#include <asm/arch/acpi/bcm2836.h>
|
||||
|
||||
#ifndef __BCM2836_GPU_H__
|
||||
#define __BCM2836_GPU_H__
|
||||
|
||||
/* VideoCore constants */
|
||||
|
||||
#define BCM2836_VCHIQ_OFFSET 0x0000B840
|
||||
#define BCM2836_VCHIQ_BASE_ADDRESS (BCM2836_SOC_REGISTERS + BCM2836_VCHIQ_OFFSET)
|
||||
#define BCM2836_VCHIQ_LENGTH 0x00000010
|
||||
|
||||
#define BCM2836_V3D_BUS_OFFSET 0x00C00000
|
||||
#define BCM2836_V3D_BUS_BASE_ADDRESS (BCM2836_SOC_REGISTERS + BCM2836_V3D_BUS_OFFSET)
|
||||
#define BCM2836_V3D_BUS_LENGTH 0x00001000
|
||||
|
||||
#define BCM2836_HVS_OFFSET 0x00400000
|
||||
#define BCM2836_HVS_BASE_ADDRESS (BCM2836_SOC_REGISTERS + BCM2836_HVS_OFFSET)
|
||||
#define BCM2836_HVS_LENGTH 0x00006000
|
||||
|
||||
#define BCM2836_PV0_OFFSET 0x00206000
|
||||
#define BCM2836_PV0_BASE_ADDRESS (BCM2836_SOC_REGISTERS + BCM2836_PV0_OFFSET)
|
||||
#define BCM2836_PV0_LENGTH 0x00000100
|
||||
|
||||
#define BCM2836_PV1_OFFSET 0x00207000
|
||||
#define BCM2836_PV1_BASE_ADDRESS (BCM2836_SOC_REGISTERS + BCM2836_PV1_OFFSET)
|
||||
#define BCM2836_PV1_LENGTH 0x00000100
|
||||
|
||||
#define BCM2836_PV2_OFFSET 0x00807000
|
||||
#define BCM2836_PV2_BASE_ADDRESS (BCM2836_SOC_REGISTERS + BCM2836_PV2_OFFSET)
|
||||
#define BCM2836_PV2_LENGTH 0x00000100
|
||||
|
||||
#define BCM2836_HDMI0_OFFSET 0x00902000
|
||||
#define BCM2836_HDMI0_BASE_ADDRESS (BCM2836_SOC_REGISTERS + BCM2836_HDMI0_OFFSET)
|
||||
#define BCM2836_HDMI0_LENGTH 0x00000600
|
||||
|
||||
#define BCM2836_HDMI1_OFFSET 0x00808000
|
||||
#define BCM2836_HDMI1_BASE_ADDRESS (BCM2836_SOC_REGISTERS + BCM2836_HDMI1_OFFSET)
|
||||
#define BCM2836_HDMI1_LENGTH 0x00000100
|
||||
|
||||
#endif /* __BCM2836_MISC_H__ */
|
33
arch/arm/mach-bcm283x/include/mach/acpi/bcm2836_pwm.h
Normal file
33
arch/arm/mach-bcm283x/include/mach/acpi/bcm2836_pwm.h
Normal file
|
@ -0,0 +1,33 @@
|
|||
/* SPDX-License-Identifier: BSD-2-Clause-Patent */
|
||||
/**
|
||||
*
|
||||
* Copyright (c) 2020, Pete Batard <pete@akeo.ie>
|
||||
*
|
||||
**/
|
||||
|
||||
#include <asm/arch/acpi/bcm2836.h>
|
||||
|
||||
#ifndef __BCM2836_PWM_H__
|
||||
#define __BCM2836_PWM_H__
|
||||
|
||||
/* PWM controller constants */
|
||||
|
||||
#define BCM2836_PWM_DMA_OFFSET 0x00007B00
|
||||
#define BCM2836_PWM_DMA_BASE_ADDRESS (BCM2836_SOC_REGISTERS + BCM2836_PWM_DMA_OFFSET)
|
||||
#define BCM2836_PWM_DMA_LENGTH 0x00000100
|
||||
|
||||
#define BCM2836_PWM_CLK_OFFSET 0x001010A0
|
||||
#define BCM2836_PWM_CLK_BASE_ADDRESS (BCM2836_SOC_REGISTERS + BCM2836_PWM_CLK_OFFSET)
|
||||
#define BCM2836_PWM_CLK_LENGTH 0x00000008
|
||||
|
||||
#define BCM2836_PWM_CTRL_OFFSET 0x0020C000
|
||||
#define BCM2836_PWM_CTRL_BASE_ADDRESS (BCM2836_SOC_REGISTERS + BCM2836_PWM_CTRL_OFFSET)
|
||||
#define BCM2836_PWM_CTRL_LENGTH 0x00000028
|
||||
|
||||
#define BCM2836_PWM_BUS_BASE_ADDRESS 0x7E20C000
|
||||
#define BCM2836_PWM_BUS_LENGTH 0x00000028
|
||||
|
||||
#define BCM2836_PWM_CTRL_UNCACHED_BASE_ADDRESS 0xFF20C000
|
||||
#define BCM2836_PWM_CTRL_UNCACHED_LENGTH 0x00000028
|
||||
|
||||
#endif /* __BCM2836_PWM_H__ */
|
18
arch/arm/mach-bcm283x/include/mach/acpi/bcm2836_sdhost.h
Normal file
18
arch/arm/mach-bcm283x/include/mach/acpi/bcm2836_sdhost.h
Normal file
|
@ -0,0 +1,18 @@
|
|||
/* SPDX-License-Identifier: BSD-2-Clause-Patent */
|
||||
/**
|
||||
*
|
||||
* Copyright (c) 2017, Andrei Warkentin <andrey.warkentin@gmail.com>
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
*
|
||||
**/
|
||||
|
||||
#include <asm/arch/acpi/bcm2836.h>
|
||||
|
||||
#ifndef __BCM2836_SDHOST_H__
|
||||
#define __BCM2836_SDHOST_H__
|
||||
|
||||
#define SDHOST_OFFSET 0x00202000
|
||||
#define SDHOST_BASE_ADDRESS (BCM2836_SOC_REGISTERS + SDHOST_OFFSET)
|
||||
#define SDHOST_LENGTH 0x00000100
|
||||
|
||||
#endif /*__BCM2836_SDHOST_H__ */
|
21
arch/arm/mach-bcm283x/include/mach/acpi/bcm2836_sdio.h
Normal file
21
arch/arm/mach-bcm283x/include/mach/acpi/bcm2836_sdio.h
Normal file
|
@ -0,0 +1,21 @@
|
|||
/* SPDX-License-Identifier: BSD-2-Clause-Patent */
|
||||
/**
|
||||
*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
*
|
||||
**/
|
||||
|
||||
#include <asm/arch/acpi/bcm2836.h>
|
||||
|
||||
#ifndef __BCM2836_SDIO_H__
|
||||
#define __BCM2836_SDIO_H__
|
||||
|
||||
// MMC/SD/SDIO1 register definitions.
|
||||
#define MMCHS1_OFFSET 0x00300000
|
||||
#define MMCHS2_OFFSET 0x00340000
|
||||
#define MMCHS1_BASE (BCM2836_SOC_REGISTERS + MMCHS1_OFFSET)
|
||||
#define MMCHS2_BASE (BCM2836_SOC_REGISTERS + MMCHS2_OFFSET)
|
||||
#define MMCHS1_LENGTH 0x00000100
|
||||
#define MMCHS2_LENGTH 0x00000100
|
||||
|
||||
#endif /* __BCM2836_SDIO_H__ */
|
|
@ -50,7 +50,7 @@ static struct mm_region bcm2711_mem_map[MEM_MAP_MAX_ENTRIES] = {
|
|||
}, {
|
||||
.virt = 0xfc000000UL,
|
||||
.phys = 0xfc000000UL,
|
||||
.size = 0x03800000UL,
|
||||
.size = 0x04000000UL,
|
||||
.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
|
||||
PTE_BLOCK_NON_SHARE |
|
||||
PTE_BLOCK_PXN | PTE_BLOCK_UXN
|
||||
|
|
|
@ -3,12 +3,6 @@ if ARCH_QEMU
|
|||
config SYS_VENDOR
|
||||
default "emulation"
|
||||
|
||||
config SYS_BOARD
|
||||
default "qemu-arm"
|
||||
|
||||
config SYS_CONFIG_NAME
|
||||
default "qemu-arm"
|
||||
|
||||
choice
|
||||
prompt "QEMU ARM architecture"
|
||||
default TARGET_QEMU_ARM_64BIT
|
||||
|
@ -25,6 +19,36 @@ config TARGET_QEMU_ARM_64BIT
|
|||
select ARM64
|
||||
select BOARD_LATE_INIT
|
||||
|
||||
config TARGET_QEMU_ARM_SBSA
|
||||
bool "SBSA Reference"
|
||||
select ARM64
|
||||
select BINMAN
|
||||
select BOARD_LATE_INIT
|
||||
select ENABLE_ARM_SOC_BOOT0_HOOK
|
||||
select MISC_INIT_R
|
||||
endchoice
|
||||
|
||||
if TARGET_QEMU_ARM_32BIT || TARGET_QEMU_ARM_64BIT
|
||||
|
||||
config SYS_BOARD
|
||||
default "qemu-arm"
|
||||
|
||||
config SYS_CONFIG_NAME
|
||||
default "qemu-arm"
|
||||
|
||||
endif
|
||||
|
||||
if TARGET_QEMU_ARM_SBSA
|
||||
|
||||
config SYS_BOARD
|
||||
default "qemu-sbsa"
|
||||
|
||||
config SYS_CONFIG_NAME
|
||||
default "qemu-sbsa"
|
||||
|
||||
config SYS_SOC
|
||||
default "qemu-sbsa"
|
||||
|
||||
endif
|
||||
|
||||
endif
|
||||
|
|
|
@ -527,6 +527,9 @@
|
|||
};
|
||||
|
||||
f-test {
|
||||
#interrupt-cells = <2>;
|
||||
interrupt-parent = <&irq>;
|
||||
interrupts = <4 0>;
|
||||
compatible = "denx,u-boot-fdt-test";
|
||||
};
|
||||
|
||||
|
|
|
@ -5,7 +5,8 @@
|
|||
# (C) Copyright 2002-2006
|
||||
# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
|
||||
obj-y += fdt_fixup.o interrupts.o
|
||||
obj-$(CONFIG_PCI) += pci_io.o
|
||||
obj-$(CONFIG_CMD_BOOTM) += bootm.o
|
||||
obj-$(CONFIG_CMD_BOOTZ) += bootm.o
|
||||
obj-y += fdt_fixup.o interrupts.o
|
||||
obj-$(CONFIG_PCI) += pci_io.o
|
||||
obj-$(CONFIG_CMD_BOOTM) += bootm.o
|
||||
obj-$(CONFIG_CMD_BOOTZ) += bootm.o
|
||||
obj-$(CONFIG_$(SPL_)ACPIGEN) += acpi_table.o
|
||||
|
|
11
arch/sandbox/lib/acpi_table.c
Normal file
11
arch/sandbox/lib/acpi_table.c
Normal file
|
@ -0,0 +1,11 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
#include <acpi/acpi_table.h>
|
||||
|
||||
void acpi_fill_fadt(struct acpi_fadt *fadt)
|
||||
{
|
||||
}
|
||||
|
||||
void *acpi_fill_madt(struct acpi_madt *madt, struct acpi_ctx *ctx)
|
||||
{
|
||||
return ctx->current;
|
||||
}
|
|
@ -128,8 +128,10 @@ int arch_madt_sci_irq_polarity(int sci)
|
|||
return MP_IRQ_POLARITY_LOW;
|
||||
}
|
||||
|
||||
void fill_fadt(struct acpi_fadt *fadt)
|
||||
void acpi_fill_fadt(struct acpi_fadt *fadt)
|
||||
{
|
||||
intel_acpi_fill_fadt(fadt);
|
||||
|
||||
fadt->pm_tmr_blk = IOMAP_ACPI_BASE + PM1_TMR;
|
||||
|
||||
fadt->p_lvl2_lat = ACPI_FADT_C2_NOT_SUPPORTED;
|
||||
|
@ -143,24 +145,10 @@ void fill_fadt(struct acpi_fadt *fadt)
|
|||
fadt->x_pm_tmr_blk.space_id = 1;
|
||||
fadt->x_pm_tmr_blk.bit_width = fadt->pm_tmr_len * 8;
|
||||
fadt->x_pm_tmr_blk.addrl = IOMAP_ACPI_BASE + PM1_TMR;
|
||||
|
||||
fadt->preferred_pm_profile = ACPI_PM_MOBILE;
|
||||
}
|
||||
|
||||
static int apl_write_fadt(struct acpi_ctx *ctx, const struct acpi_writer *entry)
|
||||
{
|
||||
struct acpi_table_header *header;
|
||||
struct acpi_fadt *fadt;
|
||||
|
||||
fadt = ctx->current;
|
||||
acpi_fadt_common(fadt, ctx->facs, ctx->dsdt);
|
||||
intel_acpi_fill_fadt(fadt);
|
||||
fill_fadt(fadt);
|
||||
header = &fadt->header;
|
||||
header->checksum = table_compute_checksum(fadt, header->length);
|
||||
|
||||
return acpi_add_fadt(ctx, fadt);
|
||||
}
|
||||
ACPI_WRITER(5fadt, "FADT", apl_write_fadt, 0);
|
||||
|
||||
int apl_acpi_fill_dmar(struct acpi_ctx *ctx)
|
||||
{
|
||||
struct udevice *dev, *sa_dev;
|
||||
|
|
|
@ -15,20 +15,13 @@
|
|||
#include <asm/arch/iomap.h>
|
||||
#include <dm/uclass-internal.h>
|
||||
|
||||
static int baytrail_write_fadt(struct acpi_ctx *ctx,
|
||||
const struct acpi_writer *entry)
|
||||
void acpi_fill_fadt(struct acpi_fadt *fadt)
|
||||
{
|
||||
struct acpi_table_header *header;
|
||||
struct acpi_fadt *fadt;
|
||||
|
||||
fadt = ctx->current;
|
||||
header = &fadt->header;
|
||||
u16 pmbase = ACPI_BASE_ADDRESS;
|
||||
|
||||
memset(fadt, '\0', sizeof(struct acpi_fadt));
|
||||
|
||||
acpi_fill_header(header, "FACP");
|
||||
header->length = sizeof(struct acpi_fadt);
|
||||
header->revision = 4;
|
||||
|
||||
fadt->preferred_pm_profile = ACPI_PM_MOBILE;
|
||||
|
@ -77,9 +70,6 @@ static int baytrail_write_fadt(struct acpi_ctx *ctx,
|
|||
fadt->reset_reg.addrh = 0;
|
||||
fadt->reset_value = SYS_RST | RST_CPU | FULL_RST;
|
||||
|
||||
fadt->x_firmware_ctrl = map_to_sysmem(ctx->facs);
|
||||
fadt->x_dsdt = map_to_sysmem(ctx->dsdt);
|
||||
|
||||
fadt->x_pm1a_evt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
|
||||
fadt->x_pm1a_evt_blk.bit_width = fadt->pm1_evt_len * 8;
|
||||
fadt->x_pm1a_evt_blk.bit_offset = 0;
|
||||
|
@ -135,12 +125,7 @@ static int baytrail_write_fadt(struct acpi_ctx *ctx,
|
|||
fadt->x_gpe1_blk.access_size = 0;
|
||||
fadt->x_gpe1_blk.addrl = 0x0;
|
||||
fadt->x_gpe1_blk.addrh = 0x0;
|
||||
|
||||
header->checksum = table_compute_checksum(fadt, header->length);
|
||||
|
||||
return acpi_add_fadt(ctx, fadt);
|
||||
}
|
||||
ACPI_WRITER(5fadt, "FADT", baytrail_write_fadt, 0);
|
||||
|
||||
int acpi_create_gnvs(struct acpi_global_nvs *gnvs)
|
||||
{
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include <asm/global_data.h>
|
||||
#include <asm/intel_acpi.h>
|
||||
#include <asm/ioapic.h>
|
||||
#include <asm/lapic.h>
|
||||
#include <asm/mpspec.h>
|
||||
#include <asm/smm.h>
|
||||
#include <asm/turbo.h>
|
||||
|
@ -80,33 +81,40 @@ static int acpi_sci_irq(void)
|
|||
return sci_irq;
|
||||
}
|
||||
|
||||
static unsigned long acpi_madt_irq_overrides(unsigned long current)
|
||||
static void *acpi_madt_irq_overrides(void *current)
|
||||
{
|
||||
int sci = acpi_sci_irq();
|
||||
u16 flags = MP_IRQ_TRIGGER_LEVEL;
|
||||
|
||||
if (sci < 0)
|
||||
return log_msg_ret("sci irq", sci);
|
||||
if (sci < 0) {
|
||||
log_err("sci irq %d", sci);
|
||||
return current;
|
||||
}
|
||||
|
||||
/* INT_SRC_OVR */
|
||||
current += acpi_create_madt_irqoverride((void *)current, 0, 0, 2, 0);
|
||||
current += acpi_create_madt_irqoverride(current, 0, 0, 2, 0);
|
||||
|
||||
flags |= arch_madt_sci_irq_polarity(sci);
|
||||
|
||||
/* SCI */
|
||||
current +=
|
||||
acpi_create_madt_irqoverride((void *)current, 0, sci, sci, flags);
|
||||
acpi_create_madt_irqoverride(current, 0, sci, sci, flags);
|
||||
|
||||
return current;
|
||||
}
|
||||
|
||||
u32 acpi_fill_madt(u32 current)
|
||||
void *acpi_fill_madt(struct acpi_madt *madt, struct acpi_ctx *ctx)
|
||||
{
|
||||
void *current = ctx->current;
|
||||
|
||||
madt->lapic_addr = LAPIC_DEFAULT_BASE;
|
||||
madt->flags = ACPI_MADT_PCAT_COMPAT;
|
||||
|
||||
/* Local APICs */
|
||||
current += acpi_create_madt_lapics(current);
|
||||
|
||||
/* IOAPIC */
|
||||
current += acpi_create_madt_ioapic((void *)current, 2, IO_APIC_ADDR, 0);
|
||||
current += acpi_create_madt_ioapic(current, 2, IO_APIC_ADDR, 0);
|
||||
|
||||
return acpi_madt_irq_overrides(current);
|
||||
}
|
||||
|
|
|
@ -11,23 +11,14 @@
|
|||
#include <asm/arch/iomap.h>
|
||||
#include <linux/string.h>
|
||||
|
||||
static int quark_write_fadt(struct acpi_ctx *ctx,
|
||||
const struct acpi_writer *entry)
|
||||
void acpi_fill_fadt(struct acpi_fadt *fadt)
|
||||
{
|
||||
u16 pmbase = ACPI_PM1_BASE_ADDRESS;
|
||||
struct acpi_table_header *header;
|
||||
struct acpi_fadt *fadt;
|
||||
|
||||
fadt = ctx->current;
|
||||
header = &fadt->header;
|
||||
|
||||
memset(fadt, '\0', sizeof(struct acpi_fadt));
|
||||
|
||||
acpi_fill_header(header, "FACP");
|
||||
header->length = sizeof(struct acpi_fadt);
|
||||
header->revision = 4;
|
||||
|
||||
fadt->preferred_pm_profile = ACPI_PM_UNSPECIFIED;
|
||||
fadt->sci_int = 9;
|
||||
fadt->smi_cmd = 0;
|
||||
fadt->acpi_enable = 0;
|
||||
|
@ -73,9 +64,6 @@ static int quark_write_fadt(struct acpi_ctx *ctx,
|
|||
fadt->reset_reg.addrh = 0;
|
||||
fadt->reset_value = SYS_RST | RST_CPU | FULL_RST;
|
||||
|
||||
fadt->x_firmware_ctrl = map_to_sysmem(ctx->facs);
|
||||
fadt->x_dsdt = map_to_sysmem(ctx->dsdt);
|
||||
|
||||
fadt->x_pm1a_evt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
|
||||
fadt->x_pm1a_evt_blk.bit_width = fadt->pm1_evt_len * 8;
|
||||
fadt->x_pm1a_evt_blk.bit_offset = 0;
|
||||
|
@ -131,12 +119,7 @@ static int quark_write_fadt(struct acpi_ctx *ctx,
|
|||
fadt->x_gpe1_blk.access_size = 0;
|
||||
fadt->x_gpe1_blk.addrl = 0x0;
|
||||
fadt->x_gpe1_blk.addrh = 0x0;
|
||||
|
||||
header->checksum = table_compute_checksum(fadt, header->length);
|
||||
|
||||
return acpi_add_fadt(ctx, fadt);
|
||||
}
|
||||
ACPI_WRITER(5fadt, "FADT", quark_write_fadt, 0);
|
||||
|
||||
int acpi_create_gnvs(struct acpi_global_nvs *gnvs)
|
||||
{
|
||||
|
|
|
@ -10,27 +10,15 @@
|
|||
#include <mapmem.h>
|
||||
#include <acpi/acpi_table.h>
|
||||
#include <asm/ioapic.h>
|
||||
#include <asm/lapic.h>
|
||||
#include <asm/mpspec.h>
|
||||
#include <asm/tables.h>
|
||||
#include <asm/arch/global_nvs.h>
|
||||
#include <asm/arch/iomap.h>
|
||||
#include <dm/uclass-internal.h>
|
||||
|
||||
static int tangier_write_fadt(struct acpi_ctx *ctx,
|
||||
const struct acpi_writer *entry)
|
||||
void acpi_fill_fadt(struct acpi_fadt *fadt)
|
||||
{
|
||||
struct acpi_table_header *header;
|
||||
struct acpi_fadt *fadt;
|
||||
|
||||
fadt = ctx->current;
|
||||
header = &fadt->header;
|
||||
|
||||
memset(fadt, '\0', sizeof(struct acpi_fadt));
|
||||
|
||||
acpi_fill_header(header, "FACP");
|
||||
header->length = sizeof(struct acpi_fadt);
|
||||
header->revision = 6;
|
||||
|
||||
fadt->preferred_pm_profile = ACPI_PM_UNSPECIFIED;
|
||||
|
||||
fadt->iapc_boot_arch = ACPI_FADT_VGA_NOT_PRESENT |
|
||||
|
@ -40,20 +28,15 @@ static int tangier_write_fadt(struct acpi_ctx *ctx,
|
|||
ACPI_FADT_POWER_BUTTON | ACPI_FADT_SLEEP_BUTTON |
|
||||
ACPI_FADT_SEALED_CASE | ACPI_FADT_HEADLESS |
|
||||
ACPI_FADT_HW_REDUCED_ACPI;
|
||||
|
||||
fadt->minor_revision = 2;
|
||||
|
||||
fadt->x_firmware_ctrl = map_to_sysmem(ctx->facs);
|
||||
fadt->x_dsdt = map_to_sysmem(ctx->dsdt);
|
||||
|
||||
header->checksum = table_compute_checksum(fadt, header->length);
|
||||
|
||||
return acpi_add_fadt(ctx, fadt);
|
||||
}
|
||||
ACPI_WRITER(5fadt, "FADT", tangier_write_fadt, 0);
|
||||
|
||||
u32 acpi_fill_madt(u32 current)
|
||||
void *acpi_fill_madt(struct acpi_madt *madt, struct acpi_ctx *ctx)
|
||||
{
|
||||
void *current = ctx->current;
|
||||
|
||||
madt->lapic_addr = LAPIC_DEFAULT_BASE;
|
||||
madt->flags = ACPI_MADT_PCAT_COMPAT;
|
||||
|
||||
current += acpi_create_madt_lapics(current);
|
||||
|
||||
current += acpi_create_madt_ioapic((struct acpi_madt_ioapic *)current,
|
||||
|
|
|
@ -24,16 +24,13 @@ struct acpi_table_header;
|
|||
|
||||
/* These can be used by the target port */
|
||||
|
||||
int acpi_create_madt_lapics(u32 current);
|
||||
int acpi_create_madt_lapics(void *current);
|
||||
int acpi_create_madt_ioapic(struct acpi_madt_ioapic *ioapic, u8 id,
|
||||
u32 addr, u32 gsi_base);
|
||||
int acpi_create_madt_irqoverride(struct acpi_madt_irqoverride *irqoverride,
|
||||
u8 bus, u8 source, u32 gsirq, u16 flags);
|
||||
int acpi_create_madt_lapic_nmi(struct acpi_madt_lapic_nmi *lapic_nmi,
|
||||
u8 cpu, u16 flags, u8 lint);
|
||||
u32 acpi_fill_madt(u32 current);
|
||||
int acpi_create_mcfg_mmconfig(struct acpi_mcfg_mmconfig *mmconfig, u32 base,
|
||||
u16 seg_nr, u8 start, u8 end);
|
||||
|
||||
/**
|
||||
* acpi_write_hpet() - Write out a HPET table
|
||||
|
@ -45,17 +42,6 @@ int acpi_create_mcfg_mmconfig(struct acpi_mcfg_mmconfig *mmconfig, u32 base,
|
|||
*/
|
||||
int acpi_write_hpet(struct acpi_ctx *ctx);
|
||||
|
||||
/**
|
||||
* acpi_write_dbg2_pci_uart() - Write out a DBG2 table
|
||||
*
|
||||
* @ctx: Current ACPI context
|
||||
* @dev: Debug UART device to describe
|
||||
* @access_size: Access size for UART (e.g. ACPI_ACCESS_SIZE_DWORD_ACCESS)
|
||||
* Return: 0 if OK, -ve on error
|
||||
*/
|
||||
int acpi_write_dbg2_pci_uart(struct acpi_ctx *ctx, struct udevice *dev,
|
||||
uint access_size);
|
||||
|
||||
/**
|
||||
* acpi_create_gnvs() - Create a GNVS (Global Non Volatile Storage) table
|
||||
*
|
||||
|
@ -179,18 +165,6 @@ int acpi_create_dmar_ds_ioapic(struct acpi_ctx *ctx, uint enumeration_id,
|
|||
int acpi_create_dmar_ds_msi_hpet(struct acpi_ctx *ctx, uint enumeration_id,
|
||||
pci_dev_t bdf);
|
||||
|
||||
/**
|
||||
* acpi_fadt_common() - Handle common parts of filling out an FADT
|
||||
*
|
||||
* This sets up the Fixed ACPI Description Table
|
||||
*
|
||||
* @fadt: Pointer to place to put FADT
|
||||
* @facs: Pointer to the FACS
|
||||
* @dsdt: Pointer to the DSDT
|
||||
*/
|
||||
void acpi_fadt_common(struct acpi_fadt *fadt, struct acpi_facs *facs,
|
||||
void *dsdt);
|
||||
|
||||
/**
|
||||
* intel_acpi_fill_fadt() - Set up the contents of the FADT
|
||||
*
|
||||
|
|
|
@ -40,7 +40,7 @@ static int acpi_create_madt_lapic(struct acpi_madt_lapic *lapic,
|
|||
return lapic->length;
|
||||
}
|
||||
|
||||
int acpi_create_madt_lapics(u32 current)
|
||||
int acpi_create_madt_lapics(void *current)
|
||||
{
|
||||
struct udevice *dev;
|
||||
int total_length = 0;
|
||||
|
@ -100,23 +100,28 @@ int acpi_create_madt_lapic_nmi(struct acpi_madt_lapic_nmi *lapic_nmi,
|
|||
return lapic_nmi->length;
|
||||
}
|
||||
|
||||
static int acpi_create_madt_irq_overrides(u32 current)
|
||||
static int acpi_create_madt_irq_overrides(void *current)
|
||||
{
|
||||
struct acpi_madt_irqoverride *irqovr;
|
||||
u16 sci_flags = MP_IRQ_TRIGGER_LEVEL | MP_IRQ_POLARITY_HIGH;
|
||||
int length = 0;
|
||||
|
||||
irqovr = (void *)current;
|
||||
irqovr = current;
|
||||
length += acpi_create_madt_irqoverride(irqovr, 0, 0, 2, 0);
|
||||
|
||||
irqovr = (void *)(current + length);
|
||||
irqovr = current + length;
|
||||
length += acpi_create_madt_irqoverride(irqovr, 0, 9, 9, sci_flags);
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
__weak u32 acpi_fill_madt(u32 current)
|
||||
__weak void *acpi_fill_madt(struct acpi_madt *madt, struct acpi_ctx *ctx)
|
||||
{
|
||||
void *current = ctx->current;
|
||||
|
||||
madt->lapic_addr = LAPIC_DEFAULT_BASE;
|
||||
madt->flags = ACPI_MADT_PCAT_COMPAT;
|
||||
|
||||
current += acpi_create_madt_lapics(current);
|
||||
|
||||
current += acpi_create_madt_ioapic((struct acpi_madt_ioapic *)current,
|
||||
|
@ -127,39 +132,6 @@ __weak u32 acpi_fill_madt(u32 current)
|
|||
return current;
|
||||
}
|
||||
|
||||
int acpi_write_madt(struct acpi_ctx *ctx, const struct acpi_writer *entry)
|
||||
{
|
||||
struct acpi_table_header *header;
|
||||
struct acpi_madt *madt;
|
||||
u32 current;
|
||||
|
||||
madt = ctx->current;
|
||||
|
||||
memset(madt, '\0', sizeof(struct acpi_madt));
|
||||
header = &madt->header;
|
||||
|
||||
/* Fill out header fields */
|
||||
acpi_fill_header(header, "APIC");
|
||||
header->length = sizeof(struct acpi_madt);
|
||||
header->revision = ACPI_MADT_REV_ACPI_3_0;
|
||||
|
||||
madt->lapic_addr = LAPIC_DEFAULT_BASE;
|
||||
madt->flags = ACPI_MADT_PCAT_COMPAT;
|
||||
|
||||
current = (u32)madt + sizeof(struct acpi_madt);
|
||||
current = acpi_fill_madt(current);
|
||||
|
||||
/* (Re)calculate length and checksum */
|
||||
header->length = current - (u32)madt;
|
||||
|
||||
header->checksum = table_compute_checksum((void *)madt, header->length);
|
||||
acpi_add_table(ctx, madt);
|
||||
acpi_inc(ctx, madt->header.length);
|
||||
|
||||
return 0;
|
||||
}
|
||||
ACPI_WRITER(5x86, NULL, acpi_write_madt, 0);
|
||||
|
||||
/**
|
||||
* acpi_create_tcpa() - Create a TCPA table
|
||||
*
|
||||
|
@ -279,140 +251,6 @@ static int acpi_write_tpm2(struct acpi_ctx *ctx,
|
|||
}
|
||||
ACPI_WRITER(5tpm2, "TPM2", acpi_write_tpm2, 0);
|
||||
|
||||
int acpi_write_spcr(struct acpi_ctx *ctx, const struct acpi_writer *entry)
|
||||
{
|
||||
struct serial_device_info serial_info = {0};
|
||||
ulong serial_address, serial_offset;
|
||||
struct acpi_table_header *header;
|
||||
struct acpi_spcr *spcr;
|
||||
struct udevice *dev;
|
||||
uint serial_config;
|
||||
uint serial_width;
|
||||
int access_size;
|
||||
int space_id;
|
||||
int ret = -ENODEV;
|
||||
|
||||
spcr = ctx->current;
|
||||
header = &spcr->header;
|
||||
|
||||
memset(spcr, '\0', sizeof(struct acpi_spcr));
|
||||
|
||||
/* Fill out header fields */
|
||||
acpi_fill_header(header, "SPCR");
|
||||
header->length = sizeof(struct acpi_spcr);
|
||||
header->revision = 2;
|
||||
|
||||
/* Read the device once, here. It is reused below */
|
||||
dev = gd->cur_serial_dev;
|
||||
if (dev)
|
||||
ret = serial_getinfo(dev, &serial_info);
|
||||
if (ret)
|
||||
serial_info.type = SERIAL_CHIP_UNKNOWN;
|
||||
|
||||
/* Encode chip type */
|
||||
switch (serial_info.type) {
|
||||
case SERIAL_CHIP_16550_COMPATIBLE:
|
||||
spcr->interface_type = ACPI_DBG2_16550_COMPATIBLE;
|
||||
break;
|
||||
case SERIAL_CHIP_UNKNOWN:
|
||||
default:
|
||||
spcr->interface_type = ACPI_DBG2_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Encode address space */
|
||||
switch (serial_info.addr_space) {
|
||||
case SERIAL_ADDRESS_SPACE_MEMORY:
|
||||
space_id = ACPI_ADDRESS_SPACE_MEMORY;
|
||||
break;
|
||||
case SERIAL_ADDRESS_SPACE_IO:
|
||||
default:
|
||||
space_id = ACPI_ADDRESS_SPACE_IO;
|
||||
break;
|
||||
}
|
||||
|
||||
serial_width = serial_info.reg_width * 8;
|
||||
serial_offset = serial_info.reg_offset << serial_info.reg_shift;
|
||||
serial_address = serial_info.addr + serial_offset;
|
||||
|
||||
/* Encode register access size */
|
||||
switch (serial_info.reg_shift) {
|
||||
case 0:
|
||||
access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
|
||||
break;
|
||||
case 1:
|
||||
access_size = ACPI_ACCESS_SIZE_WORD_ACCESS;
|
||||
break;
|
||||
case 2:
|
||||
access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
|
||||
break;
|
||||
case 3:
|
||||
access_size = ACPI_ACCESS_SIZE_QWORD_ACCESS;
|
||||
break;
|
||||
default:
|
||||
access_size = ACPI_ACCESS_SIZE_UNDEFINED;
|
||||
break;
|
||||
}
|
||||
|
||||
debug("UART type %u @ %lx\n", spcr->interface_type, serial_address);
|
||||
|
||||
/* Fill GAS */
|
||||
spcr->serial_port.space_id = space_id;
|
||||
spcr->serial_port.bit_width = serial_width;
|
||||
spcr->serial_port.bit_offset = 0;
|
||||
spcr->serial_port.access_size = access_size;
|
||||
spcr->serial_port.addrl = lower_32_bits(serial_address);
|
||||
spcr->serial_port.addrh = upper_32_bits(serial_address);
|
||||
|
||||
/* Encode baud rate */
|
||||
switch (serial_info.baudrate) {
|
||||
case 9600:
|
||||
spcr->baud_rate = 3;
|
||||
break;
|
||||
case 19200:
|
||||
spcr->baud_rate = 4;
|
||||
break;
|
||||
case 57600:
|
||||
spcr->baud_rate = 6;
|
||||
break;
|
||||
case 115200:
|
||||
spcr->baud_rate = 7;
|
||||
break;
|
||||
default:
|
||||
spcr->baud_rate = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
serial_config = SERIAL_DEFAULT_CONFIG;
|
||||
if (dev)
|
||||
ret = serial_getconfig(dev, &serial_config);
|
||||
|
||||
spcr->parity = SERIAL_GET_PARITY(serial_config);
|
||||
spcr->stop_bits = SERIAL_GET_STOP(serial_config);
|
||||
|
||||
/* No PCI devices for now */
|
||||
spcr->pci_device_id = 0xffff;
|
||||
spcr->pci_vendor_id = 0xffff;
|
||||
|
||||
/*
|
||||
* SPCR has no clue if the UART base clock speed is different
|
||||
* to the default one. However, the SPCR 1.04 defines baud rate
|
||||
* 0 as a preconfigured state of UART and OS is supposed not
|
||||
* to touch the configuration of the serial device.
|
||||
*/
|
||||
if (serial_info.clock != SERIAL_DEFAULT_CLOCK)
|
||||
spcr->baud_rate = 0;
|
||||
|
||||
/* Fix checksum */
|
||||
header->checksum = table_compute_checksum((void *)spcr, header->length);
|
||||
|
||||
acpi_add_table(ctx, spcr);
|
||||
acpi_inc(ctx, spcr->header.length);
|
||||
|
||||
return 0;
|
||||
}
|
||||
ACPI_WRITER(5spcr, "SPCR", acpi_write_spcr, 0);
|
||||
|
||||
int acpi_write_gnvs(struct acpi_ctx *ctx, const struct acpi_writer *entry)
|
||||
{
|
||||
ulong addr;
|
||||
|
@ -515,69 +353,6 @@ int acpi_write_hpet(struct acpi_ctx *ctx)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int acpi_write_dbg2_pci_uart(struct acpi_ctx *ctx, struct udevice *dev,
|
||||
uint access_size)
|
||||
{
|
||||
struct acpi_dbg2_header *dbg2 = ctx->current;
|
||||
char path[ACPI_PATH_MAX];
|
||||
struct acpi_gen_regaddr address;
|
||||
phys_addr_t addr;
|
||||
int ret;
|
||||
|
||||
if (!device_active(dev)) {
|
||||
log_info("Device not enabled\n");
|
||||
return -EACCES;
|
||||
}
|
||||
/*
|
||||
* PCI devices don't remember their resource allocation information in
|
||||
* U-Boot at present. We assume that MMIO is used for the UART and that
|
||||
* the address space is 32 bytes: ns16550 uses 8 registers of up to
|
||||
* 32-bits each. This is only for debugging so it is not a big deal.
|
||||
*/
|
||||
addr = dm_pci_read_bar32(dev, 0);
|
||||
log_debug("UART addr %lx\n", (ulong)addr);
|
||||
|
||||
memset(&address, '\0', sizeof(address));
|
||||
address.space_id = ACPI_ADDRESS_SPACE_MEMORY;
|
||||
address.addrl = (uint32_t)addr;
|
||||
address.addrh = (uint32_t)((addr >> 32) & 0xffffffff);
|
||||
address.access_size = access_size;
|
||||
|
||||
ret = acpi_device_path(dev, path, sizeof(path));
|
||||
if (ret)
|
||||
return log_msg_ret("path", ret);
|
||||
acpi_create_dbg2(dbg2, ACPI_DBG2_SERIAL_PORT,
|
||||
ACPI_DBG2_16550_COMPATIBLE, &address, 0x1000, path);
|
||||
|
||||
acpi_inc_align(ctx, dbg2->header.length);
|
||||
acpi_add_table(ctx, dbg2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void acpi_fadt_common(struct acpi_fadt *fadt, struct acpi_facs *facs,
|
||||
void *dsdt)
|
||||
{
|
||||
struct acpi_table_header *header = &fadt->header;
|
||||
|
||||
memset((void *)fadt, '\0', sizeof(struct acpi_fadt));
|
||||
|
||||
acpi_fill_header(header, "FACP");
|
||||
header->length = sizeof(struct acpi_fadt);
|
||||
header->revision = 4;
|
||||
memcpy(header->oem_id, OEM_ID, 6);
|
||||
memcpy(header->oem_table_id, OEM_TABLE_ID, 8);
|
||||
memcpy(header->creator_id, ASLC_ID, 4);
|
||||
|
||||
fadt->x_firmware_ctrl = map_to_sysmem(facs);
|
||||
fadt->x_dsdt = map_to_sysmem(dsdt);
|
||||
|
||||
fadt->preferred_pm_profile = ACPI_PM_MOBILE;
|
||||
|
||||
/* Use ACPI 3.0 revision */
|
||||
fadt->header.revision = 4;
|
||||
}
|
||||
|
||||
void acpi_create_dmar_drhd(struct acpi_ctx *ctx, uint flags, uint segment,
|
||||
u64 bar)
|
||||
{
|
||||
|
|
|
@ -4,5 +4,7 @@ S: Maintained
|
|||
F: board/emulation/qemu-arm/
|
||||
F: board/emulation/common/
|
||||
F: include/configs/qemu-arm.h
|
||||
F: include/configs/qemu-sbsa.h
|
||||
F: configs/qemu_arm_defconfig
|
||||
F: configs/qemu_arm64_defconfig
|
||||
F: configs/qemu-arm-sbsa_defconfig
|
||||
|
|
59
board/emulation/qemu-sbsa/Kconfig
Normal file
59
board/emulation/qemu-sbsa/Kconfig
Normal file
|
@ -0,0 +1,59 @@
|
|||
if TARGET_QEMU_ARM_SBSA
|
||||
|
||||
config SYS_SOC
|
||||
default "qemu-sbsa"
|
||||
|
||||
config TEXT_BASE
|
||||
default 0x10000100000
|
||||
|
||||
config SYS_LOAD_ADDR
|
||||
default 0x10000100000
|
||||
|
||||
config PRE_CON_BUF_ADDR
|
||||
default 0x100000FF000
|
||||
|
||||
config DEFAULT_DEVICE_TREE
|
||||
default "qemu-sbsa"
|
||||
|
||||
config BOARD_SPECIFIC_OPTIONS # dummy
|
||||
def_bool y
|
||||
select AHCI
|
||||
select ACPIGEN
|
||||
select ACPI
|
||||
select BLOBLIST
|
||||
select CPU
|
||||
select CPU_ARMV8
|
||||
select DM
|
||||
select DM_USB
|
||||
select DM_MTD
|
||||
select GENERATE_ACPI_TABLE
|
||||
select HAS_ROM
|
||||
select MTD
|
||||
select OF_LIBFDT_OVERLAY
|
||||
select OF_SEPARATE
|
||||
select PCI
|
||||
select PCIE_ECAM_GENERIC
|
||||
select USB
|
||||
select GIC_V3
|
||||
select GIC_V3_ITS
|
||||
select SYS_FLASH_CFI_WIDTH_16BIT
|
||||
imply AHCI_GENERIC
|
||||
imply USB_XHCI_HCD
|
||||
imply USB_XHCI_GENERIC
|
||||
imply USB_STORAGE
|
||||
imply E1000
|
||||
imply E1000_NO_NVM
|
||||
imply NET_RANDOM_ETHADDR
|
||||
imply VIDEO_BOCHS
|
||||
imply CFI_FLASH
|
||||
imply SYS_MTDPARTS_RUNTIME
|
||||
imply SET_DFU_ALT_INFO
|
||||
|
||||
if DEBUG_UART
|
||||
|
||||
config DEBUG_UART_BASE
|
||||
default 0x60000000
|
||||
endif
|
||||
|
||||
source "board/emulation/common/Kconfig"
|
||||
endif
|
8
board/emulation/qemu-sbsa/Makefile
Normal file
8
board/emulation/qemu-sbsa/Makefile
Normal file
|
@ -0,0 +1,8 @@
|
|||
# SPDX-License-Identifier: GPL-2.0+
|
||||
|
||||
obj-y += qemu-sbsa.o
|
||||
obj-y += lowlevel_init.o
|
||||
obj-y += smc.o
|
||||
|
||||
obj-$(CONFIG_GENERATE_ACPI_TABLE) += dsdt_generated.o
|
||||
obj-$(CONFIG_GENERATE_ACPI_TABLE) += acpi.o
|
192
board/emulation/qemu-sbsa/acpi.c
Normal file
192
board/emulation/qemu-sbsa/acpi.c
Normal file
|
@ -0,0 +1,192 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (c) 2024 9elements GmbH
|
||||
*/
|
||||
|
||||
#include <cpu.h>
|
||||
#include <tables_csum.h>
|
||||
#include <string.h>
|
||||
#include <acpi/acpi_table.h>
|
||||
#include <asm/acpi_table.h>
|
||||
#include <asm/armv8/sec_firmware.h>
|
||||
#include <configs/qemu-sbsa.h>
|
||||
#include <dm/uclass.h>
|
||||
#include <dm/device.h>
|
||||
#include "qemu-sbsa.h"
|
||||
|
||||
#define SBSAQEMU_MADT_GIC_VBASE 0x2c020000
|
||||
#define SBSAQEMU_MADT_GIC_HBASE 0x2c010000
|
||||
#define SBSAQEMU_MADT_GIC_PMU_IRQ 23
|
||||
|
||||
#define SBSA_PLATFORM_WATCHDOG_COUNT 1
|
||||
#define SBSA_PLATFORM_TIMER_COUNT (SBSA_PLATFORM_WATCHDOG_COUNT)
|
||||
|
||||
#define L2_ATTRIBUTES (ACPI_PPTT_READ_ALLOC | ACPI_PPTT_WRITE_ALLOC | \
|
||||
(ACPI_PPTT_CACHE_TYPE_UNIFIED << \
|
||||
ACPI_PPTT_CACHE_TYPE_SHIFT))
|
||||
#define L2_SIZE 0x80000
|
||||
#define L2_SETS 0x400
|
||||
#define L2_WAYS 8
|
||||
|
||||
#define L1D_ATTRIBUTES (ACPI_PPTT_READ_ALLOC | ACPI_PPTT_WRITE_ALLOC | \
|
||||
(ACPI_PPTT_CACHE_TYPE_DATA << \
|
||||
ACPI_PPTT_CACHE_TYPE_SHIFT))
|
||||
#define L1D_SIZE 0x8000
|
||||
#define L1D_SETS 0x100
|
||||
#define L1D_WAYS 2
|
||||
|
||||
#define L1I_ATTRIBUTES (ACPI_PPTT_READ_ALLOC | \
|
||||
(ACPI_PPTT_CACHE_TYPE_INSTR << \
|
||||
ACPI_PPTT_CACHE_TYPE_SHIFT))
|
||||
#define L1I_SIZE 0x8000
|
||||
#define L1I_SETS 0x100
|
||||
#define L1I_WAYS 2
|
||||
|
||||
int acpi_fill_iort(struct acpi_ctx *ctx)
|
||||
{
|
||||
u32 its_offset, smmu_offset;
|
||||
u64 gic_its_base = 0;
|
||||
|
||||
smc_get_gic_its_base(&gic_its_base);
|
||||
if (gic_its_base == 0)
|
||||
return 0;
|
||||
|
||||
u32 identifiers[] = { 0 };
|
||||
|
||||
its_offset = acpi_iort_add_its_group(ctx, ARRAY_SIZE(identifiers),
|
||||
identifiers);
|
||||
|
||||
struct acpi_iort_id_mapping map_smmu[] = {{
|
||||
0, 0xffff, 0, its_offset, 0
|
||||
}};
|
||||
|
||||
smmu_offset = acpi_iort_add_smmu_v3(ctx,
|
||||
SBSA_SMMU_BASE_ADDR, // Base address
|
||||
ACPI_IORT_SMMU_V3_COHACC_OVERRIDE, // Flags
|
||||
0, // VATOS address
|
||||
0, // SMMUv3 Model
|
||||
74, // Event
|
||||
75, // Pri
|
||||
77, // Gerror
|
||||
76, // Sync
|
||||
0, // Proximity domain
|
||||
1, // DevIDMappingIndex
|
||||
ARRAY_SIZE(map_smmu),
|
||||
map_smmu);
|
||||
|
||||
struct acpi_iort_id_mapping map_rc[] = {{
|
||||
0, 0xffff, 0, smmu_offset, 0
|
||||
}};
|
||||
|
||||
acpi_iort_add_rc(ctx,
|
||||
BIT(0) | BIT(56), // CacheCoherent + CPM
|
||||
0, // AtsAttribute
|
||||
0, // PciSegmentNumber
|
||||
64, // MemoryAddressSizeLimit
|
||||
ARRAY_SIZE(map_rc),
|
||||
map_rc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void acpi_fill_fadt(struct acpi_fadt *fadt)
|
||||
{
|
||||
fadt->flags = ACPI_FADT_HW_REDUCED_ACPI | ACPI_FADT_LOW_PWR_IDLE_S0;
|
||||
fadt->preferred_pm_profile = ACPI_PM_PERFORMANCE_SERVER;
|
||||
fadt->arm_boot_arch = ACPI_ARM_PSCI_COMPLIANT;
|
||||
}
|
||||
|
||||
int acpi_fill_mcfg(struct acpi_ctx *ctx)
|
||||
{
|
||||
size_t size;
|
||||
|
||||
/* PCI Segment Group 0, Start Bus Number 0, End Bus Number is 255 */
|
||||
size = acpi_create_mcfg_mmconfig((void *)ctx->current,
|
||||
SBSA_PCIE_ECAM_BASE_ADDR, 0, 0, 255);
|
||||
acpi_inc(ctx, size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sbsa_write_gtdt(struct acpi_ctx *ctx, const struct acpi_writer *entry)
|
||||
{
|
||||
struct acpi_table_header *header;
|
||||
struct acpi_gtdt *gtdt;
|
||||
|
||||
gtdt = ctx->current;
|
||||
header = >dt->header;
|
||||
|
||||
memset(gtdt, '\0', sizeof(struct acpi_gtdt));
|
||||
|
||||
acpi_fill_header(header, "GTDT");
|
||||
header->length = sizeof(struct acpi_gtdt);
|
||||
header->revision = acpi_get_table_revision(ACPITAB_GTDT);
|
||||
|
||||
gtdt->cnt_ctrl_base = 0xFFFFFFFFFFFFFFFF;
|
||||
gtdt->sec_el1_gsiv = 29;
|
||||
gtdt->sec_el1_flags = GTDT_FLAG_INT_ACTIVE_LOW;
|
||||
gtdt->el1_gsiv = 30;
|
||||
gtdt->el1_flags = GTDT_FLAG_INT_ACTIVE_LOW;
|
||||
gtdt->virt_el1_gsiv = 27;
|
||||
gtdt->virt_el1_flags = GTDT_FLAG_INT_ACTIVE_LOW;
|
||||
gtdt->el2_gsiv = 26;
|
||||
gtdt->el2_flags = GTDT_FLAG_INT_ACTIVE_LOW;
|
||||
gtdt->cnt_read_base = 0xffffffffffffffff;
|
||||
|
||||
// FIXME: VirtualPL2Timer
|
||||
header->checksum = table_compute_checksum(header, header->length);
|
||||
|
||||
acpi_add_table(ctx, gtdt);
|
||||
|
||||
acpi_inc(ctx, sizeof(struct acpi_gtdt));
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
ACPI_WRITER(5gtdt, "GTDT", sbsa_write_gtdt, 0);
|
||||
|
||||
static int acpi_write_pptt(struct acpi_ctx *ctx, const struct acpi_writer *entry)
|
||||
{
|
||||
struct acpi_table_header *header;
|
||||
int cluster_offset, l2_offset;
|
||||
u32 offsets[2];
|
||||
|
||||
header = ctx->current;
|
||||
ctx->tab_start = ctx->current;
|
||||
|
||||
memset(header, '\0', sizeof(struct acpi_table_header));
|
||||
|
||||
acpi_fill_header(header, "PPTT");
|
||||
header->revision = acpi_get_table_revision(ACPITAB_PPTT);
|
||||
acpi_inc(ctx, sizeof(*header));
|
||||
|
||||
cluster_offset = acpi_pptt_add_proc(ctx, ACPI_PPTT_PHYSICAL_PACKAGE |
|
||||
ACPI_PPTT_CHILDREN_IDENTICAL,
|
||||
0, 0, 0, NULL);
|
||||
|
||||
l2_offset = acpi_pptt_add_cache(ctx, ACPI_PPTT_ALL_VALID, 0, L2_SIZE,
|
||||
L2_SETS, L2_WAYS, L2_ATTRIBUTES, 64);
|
||||
|
||||
offsets[0] = acpi_pptt_add_cache(ctx, ACPI_PPTT_ALL_VALID, l2_offset,
|
||||
L1D_SIZE, L1D_SETS, L1D_WAYS,
|
||||
L1D_ATTRIBUTES, 64);
|
||||
|
||||
offsets[1] = acpi_pptt_add_cache(ctx, ACPI_PPTT_ALL_BUT_WRITE_POL,
|
||||
l2_offset, L1I_SIZE, L1I_SETS,
|
||||
L1I_WAYS, L1I_ATTRIBUTES, 64);
|
||||
|
||||
for (int i = 0; i < uclass_id_count(UCLASS_CPU); i++) {
|
||||
acpi_pptt_add_proc(ctx, ACPI_PPTT_CHILDREN_IDENTICAL |
|
||||
ACPI_PPTT_NODE_IS_LEAF | ACPI_PPTT_PROC_ID_VALID,
|
||||
cluster_offset, i, 2, offsets);
|
||||
}
|
||||
|
||||
header->length = ctx->current - ctx->tab_start;
|
||||
header->checksum = table_compute_checksum(header, header->length);
|
||||
|
||||
acpi_inc(ctx, header->length);
|
||||
acpi_add_table(ctx, header);
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
ACPI_WRITER(5pptt, "PPTT", acpi_write_pptt, 0);
|
483
board/emulation/qemu-sbsa/dsdt.asl
Normal file
483
board/emulation/qemu-sbsa/dsdt.asl
Normal file
|
@ -0,0 +1,483 @@
|
|||
/** @file
|
||||
* Differentiated System Description Table Fields (DSDT).
|
||||
*
|
||||
* Copyright (c) 2020, Linaro Ltd. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
**/
|
||||
|
||||
#include <configs/qemu-sbsa.h>
|
||||
|
||||
#define LINK_DEVICE(Uid, LinkName, Irq) \
|
||||
Device (LinkName) { \
|
||||
Name (_HID, EISAID("PNP0C0F")) \
|
||||
Name (_UID, Uid) \
|
||||
Name (_PRS, ResourceTemplate() { \
|
||||
Interrupt (ResourceProducer, Level, ActiveHigh, Exclusive) { Irq } \
|
||||
}) \
|
||||
Method (_STA) { \
|
||||
Return (0xF) \
|
||||
} \
|
||||
Method (_CRS, 0) { Return (_PRS) } \
|
||||
Method (_SRS, 1) { } \
|
||||
Method (_DIS) { } \
|
||||
}
|
||||
|
||||
#define PRT_ENTRY(Address, Pin, Link) \
|
||||
Package (4) { \
|
||||
Address, Pin, Link, Zero \
|
||||
}
|
||||
|
||||
DefinitionBlock ("Dsdt.aml", "DSDT", 2, "U-Boot", "SBSAQEMU", 2) {
|
||||
Scope (_SB) {
|
||||
// UART PL011
|
||||
Device (COM0) {
|
||||
Name (_HID, "ARMH0011")
|
||||
Name (_UID, Zero)
|
||||
Name (_CRS, ResourceTemplate () {
|
||||
Memory32Fixed (ReadWrite,
|
||||
SBSA_UART_BASE_ADDR,
|
||||
SBSA_UART_LENGTH)
|
||||
Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 33 }
|
||||
})
|
||||
Method (_STA) {
|
||||
Return (0xF)
|
||||
}
|
||||
}
|
||||
|
||||
// AHCI Host Controller
|
||||
Device (AHC0) {
|
||||
Name (_HID, "LNRO001E")
|
||||
Name (_CLS, Package (3) {
|
||||
0x01,
|
||||
0x06,
|
||||
0x01,
|
||||
})
|
||||
Name (_CCA, 1)
|
||||
Name (_CRS, ResourceTemplate() {
|
||||
Memory32Fixed (ReadWrite,
|
||||
SBSA_AHCI_BASE_ADDR,
|
||||
SBSA_AHCI_LENGTH)
|
||||
Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 42 }
|
||||
})
|
||||
Method (_STA) {
|
||||
Return (0xF)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// USB XHCI Host Controller
|
||||
Device (USB0) {
|
||||
Name (_HID, "PNP0D10") // _HID: Hardware ID
|
||||
Name (_UID, 0x00) // _UID: Unique ID
|
||||
Name (_CCA, 0x01) // _CCA: Cache Coherency Attribute
|
||||
Name (XHCI, 0xF) // will be set using AcpiLib
|
||||
Method (_STA) {
|
||||
Return (XHCI)
|
||||
}
|
||||
Name (_CRS, ResourceTemplate() {
|
||||
Memory32Fixed (ReadWrite,
|
||||
SBSA_XHCI_BASE_ADDR,
|
||||
SBSA_XHCI_LENGTH)
|
||||
Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 43 }
|
||||
})
|
||||
|
||||
// Root Hub
|
||||
Device (RHUB) {
|
||||
Name (_ADR, 0x00000000) // Address of Root Hub should be 0 as per ACPI 5.0 spec
|
||||
Method (_STA) {
|
||||
Return (0xF)
|
||||
}
|
||||
|
||||
// Ports connected to Root Hub
|
||||
Device (HUB1) {
|
||||
Name (_ADR, 0x00000001)
|
||||
Name (_UPC, Package() {
|
||||
0x00, // Port is NOT connectable
|
||||
0xFF, // Don't care
|
||||
0x00000000, // Reserved 0 must be zero
|
||||
0x00000000 // Reserved 1 must be zero
|
||||
})
|
||||
Method (_STA) {
|
||||
Return (0xF)
|
||||
}
|
||||
|
||||
Device (PRT1) {
|
||||
Name (_ADR, 0x00000001)
|
||||
Name (_UPC, Package() {
|
||||
0xFF, // Port is connectable
|
||||
0x00, // Port connector is A
|
||||
0x00000000,
|
||||
0x00000000
|
||||
})
|
||||
Name (_PLD, Package() {
|
||||
Buffer(0x10) {
|
||||
0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x31, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
}
|
||||
})
|
||||
Method (_STA) {
|
||||
Return (0xF)
|
||||
}
|
||||
} // USB0_RHUB_HUB1_PRT1
|
||||
Device (PRT2) {
|
||||
Name (_ADR, 0x00000002)
|
||||
Name (_UPC, Package() {
|
||||
0xFF, // Port is connectable
|
||||
0x00, // Port connector is A
|
||||
0x00000000,
|
||||
0x00000000
|
||||
})
|
||||
Name (_PLD, Package() {
|
||||
Buffer(0x10) {
|
||||
0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x31, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
}
|
||||
})
|
||||
Method (_STA) {
|
||||
Return (0xF)
|
||||
}
|
||||
} // USB0_RHUB_HUB1_PRT2
|
||||
|
||||
Device (PRT3) {
|
||||
Name (_ADR, 0x00000003)
|
||||
Name (_UPC, Package() {
|
||||
0xFF, // Port is connectable
|
||||
0x09, // Type C connector - USB2 and SS with Switch
|
||||
0x00000000,
|
||||
0x00000000
|
||||
})
|
||||
Name (_PLD, Package() {
|
||||
Buffer (0x10) {
|
||||
0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x31, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
}
|
||||
})
|
||||
Method (_STA) {
|
||||
Return (0xF)
|
||||
}
|
||||
} // USB0_RHUB_HUB1_PRT3
|
||||
|
||||
Device (PRT4) {
|
||||
Name (_ADR, 0x00000004)
|
||||
Name (_UPC, Package() {
|
||||
0xFF, // Port is connectable
|
||||
0x09, // Type C connector - USB2 and SS with Switch
|
||||
0x00000000,
|
||||
0x00000000
|
||||
})
|
||||
Name (_PLD, Package() {
|
||||
Buffer (0x10){
|
||||
0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x31, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
}
|
||||
})
|
||||
Method (_STA) {
|
||||
Return (0xF)
|
||||
}
|
||||
} // USB0_RHUB_HUB1_PRT4
|
||||
} // USB0_RHUB_HUB1
|
||||
} // USB0_RHUB
|
||||
} // USB0
|
||||
|
||||
Device (PCI0)
|
||||
{
|
||||
Name (_HID, EISAID ("PNP0A08")) // PCI Express Root Bridge
|
||||
Name (_CID, EISAID ("PNP0A03")) // Compatible PCI Root Bridge
|
||||
Name (_SEG, Zero) // PCI Segment Group number
|
||||
Name (_BBN, Zero) // PCI Base Bus Number
|
||||
Name (_UID, "PCI0")
|
||||
Name (_CCA, One) // Initially mark the PCI coherent (for JunoR1)
|
||||
|
||||
Method (_STA) {
|
||||
Return (0xF)
|
||||
}
|
||||
|
||||
Method (_CBA, 0, NotSerialized) {
|
||||
return (SBSA_PCIE_ECAM_BASE_ADDR)
|
||||
}
|
||||
|
||||
LINK_DEVICE(0, GSI0, 0x23)
|
||||
LINK_DEVICE(1, GSI1, 0x24)
|
||||
LINK_DEVICE(2, GSI2, 0x25)
|
||||
LINK_DEVICE(3, GSI3, 0x26)
|
||||
|
||||
Name (_PRT, Package () // _PRT: PCI Routing Table
|
||||
{
|
||||
PRT_ENTRY(0x0000FFFF, 0, GSI0),
|
||||
PRT_ENTRY(0x0000FFFF, 0, GSI1),
|
||||
PRT_ENTRY(0x0000FFFF, 0, GSI2),
|
||||
PRT_ENTRY(0x0000FFFF, 0, GSI3),
|
||||
|
||||
PRT_ENTRY(0x0001FFFF, 0, GSI1),
|
||||
PRT_ENTRY(0x0001FFFF, 1, GSI2),
|
||||
PRT_ENTRY(0x0001FFFF, 2, GSI3),
|
||||
PRT_ENTRY(0x0001FFFF, 3, GSI0),
|
||||
|
||||
PRT_ENTRY(0x0002FFFF, 0, GSI2),
|
||||
PRT_ENTRY(0x0002FFFF, 1, GSI3),
|
||||
PRT_ENTRY(0x0002FFFF, 2, GSI0),
|
||||
PRT_ENTRY(0x0002FFFF, 3, GSI1),
|
||||
|
||||
PRT_ENTRY(0x0003FFFF, 0, GSI3),
|
||||
PRT_ENTRY(0x0003FFFF, 1, GSI0),
|
||||
PRT_ENTRY(0x0003FFFF, 2, GSI1),
|
||||
PRT_ENTRY(0x0003FFFF, 3, GSI2),
|
||||
|
||||
PRT_ENTRY(0x0004FFFF, 0, GSI0),
|
||||
PRT_ENTRY(0x0004FFFF, 1, GSI1),
|
||||
PRT_ENTRY(0x0004FFFF, 2, GSI2),
|
||||
PRT_ENTRY(0x0004FFFF, 3, GSI3),
|
||||
|
||||
PRT_ENTRY(0x0005FFFF, 0, GSI1),
|
||||
PRT_ENTRY(0x0005FFFF, 1, GSI2),
|
||||
PRT_ENTRY(0x0005FFFF, 2, GSI3),
|
||||
PRT_ENTRY(0x0005FFFF, 3, GSI0),
|
||||
|
||||
PRT_ENTRY(0x0006FFFF, 0, GSI2),
|
||||
PRT_ENTRY(0x0006FFFF, 1, GSI3),
|
||||
PRT_ENTRY(0x0006FFFF, 2, GSI0),
|
||||
PRT_ENTRY(0x0006FFFF, 3, GSI1),
|
||||
|
||||
PRT_ENTRY(0x0007FFFF, 0, GSI3),
|
||||
PRT_ENTRY(0x0007FFFF, 1, GSI0),
|
||||
PRT_ENTRY(0x0007FFFF, 2, GSI1),
|
||||
PRT_ENTRY(0x0007FFFF, 3, GSI2),
|
||||
|
||||
PRT_ENTRY(0x0008FFFF, 0, GSI0),
|
||||
PRT_ENTRY(0x0008FFFF, 1, GSI1),
|
||||
PRT_ENTRY(0x0008FFFF, 2, GSI2),
|
||||
PRT_ENTRY(0x0008FFFF, 3, GSI3),
|
||||
|
||||
PRT_ENTRY(0x0009FFFF, 0, GSI1),
|
||||
PRT_ENTRY(0x0009FFFF, 1, GSI2),
|
||||
PRT_ENTRY(0x0009FFFF, 2, GSI3),
|
||||
PRT_ENTRY(0x0009FFFF, 3, GSI0),
|
||||
|
||||
PRT_ENTRY(0x000AFFFF, 0, GSI2),
|
||||
PRT_ENTRY(0x000AFFFF, 1, GSI3),
|
||||
PRT_ENTRY(0x000AFFFF, 2, GSI0),
|
||||
PRT_ENTRY(0x000AFFFF, 3, GSI1),
|
||||
|
||||
PRT_ENTRY(0x000BFFFF, 0, GSI3),
|
||||
PRT_ENTRY(0x000BFFFF, 1, GSI0),
|
||||
PRT_ENTRY(0x000BFFFF, 2, GSI1),
|
||||
PRT_ENTRY(0x000BFFFF, 3, GSI2),
|
||||
|
||||
PRT_ENTRY(0x000CFFFF, 0, GSI0),
|
||||
PRT_ENTRY(0x000CFFFF, 1, GSI1),
|
||||
PRT_ENTRY(0x000CFFFF, 2, GSI2),
|
||||
PRT_ENTRY(0x000CFFFF, 3, GSI3),
|
||||
|
||||
PRT_ENTRY(0x000DFFFF, 0, GSI1),
|
||||
PRT_ENTRY(0x000DFFFF, 1, GSI2),
|
||||
PRT_ENTRY(0x000DFFFF, 2, GSI3),
|
||||
PRT_ENTRY(0x000DFFFF, 3, GSI0),
|
||||
|
||||
PRT_ENTRY(0x000EFFFF, 0, GSI2),
|
||||
PRT_ENTRY(0x000EFFFF, 1, GSI3),
|
||||
PRT_ENTRY(0x000EFFFF, 2, GSI0),
|
||||
PRT_ENTRY(0x000EFFFF, 3, GSI1),
|
||||
|
||||
PRT_ENTRY(0x000FFFFF, 0, GSI3),
|
||||
PRT_ENTRY(0x000FFFFF, 1, GSI0),
|
||||
PRT_ENTRY(0x000FFFFF, 2, GSI1),
|
||||
PRT_ENTRY(0x000FFFFF, 3, GSI2),
|
||||
|
||||
PRT_ENTRY(0x0010FFFF, 0, GSI0),
|
||||
PRT_ENTRY(0x0010FFFF, 1, GSI1),
|
||||
PRT_ENTRY(0x0010FFFF, 2, GSI2),
|
||||
PRT_ENTRY(0x0010FFFF, 3, GSI3),
|
||||
|
||||
PRT_ENTRY(0x0011FFFF, 0, GSI1),
|
||||
PRT_ENTRY(0x0011FFFF, 1, GSI2),
|
||||
PRT_ENTRY(0x0011FFFF, 2, GSI3),
|
||||
PRT_ENTRY(0x0011FFFF, 3, GSI0),
|
||||
|
||||
PRT_ENTRY(0x0012FFFF, 0, GSI2),
|
||||
PRT_ENTRY(0x0012FFFF, 1, GSI3),
|
||||
PRT_ENTRY(0x0012FFFF, 2, GSI0),
|
||||
PRT_ENTRY(0x0012FFFF, 3, GSI1),
|
||||
|
||||
PRT_ENTRY(0x0013FFFF, 0, GSI3),
|
||||
PRT_ENTRY(0x0013FFFF, 1, GSI0),
|
||||
PRT_ENTRY(0x0013FFFF, 2, GSI1),
|
||||
PRT_ENTRY(0x0013FFFF, 3, GSI2),
|
||||
|
||||
PRT_ENTRY(0x0014FFFF, 0, GSI0),
|
||||
PRT_ENTRY(0x0014FFFF, 1, GSI1),
|
||||
PRT_ENTRY(0x0014FFFF, 2, GSI2),
|
||||
PRT_ENTRY(0x0014FFFF, 3, GSI3),
|
||||
|
||||
PRT_ENTRY(0x0015FFFF, 0, GSI1),
|
||||
PRT_ENTRY(0x0015FFFF, 1, GSI2),
|
||||
PRT_ENTRY(0x0015FFFF, 2, GSI3),
|
||||
PRT_ENTRY(0x0015FFFF, 3, GSI0),
|
||||
|
||||
PRT_ENTRY(0x0016FFFF, 0, GSI2),
|
||||
PRT_ENTRY(0x0016FFFF, 1, GSI3),
|
||||
PRT_ENTRY(0x0016FFFF, 2, GSI0),
|
||||
PRT_ENTRY(0x0016FFFF, 3, GSI1),
|
||||
|
||||
PRT_ENTRY(0x0017FFFF, 0, GSI3),
|
||||
PRT_ENTRY(0x0017FFFF, 1, GSI0),
|
||||
PRT_ENTRY(0x0017FFFF, 2, GSI1),
|
||||
PRT_ENTRY(0x0017FFFF, 3, GSI2),
|
||||
|
||||
PRT_ENTRY(0x0018FFFF, 0, GSI0),
|
||||
PRT_ENTRY(0x0018FFFF, 1, GSI1),
|
||||
PRT_ENTRY(0x0018FFFF, 2, GSI2),
|
||||
PRT_ENTRY(0x0018FFFF, 3, GSI3),
|
||||
|
||||
PRT_ENTRY(0x0019FFFF, 0, GSI1),
|
||||
PRT_ENTRY(0x0019FFFF, 1, GSI2),
|
||||
PRT_ENTRY(0x0019FFFF, 2, GSI3),
|
||||
PRT_ENTRY(0x0019FFFF, 3, GSI0),
|
||||
|
||||
PRT_ENTRY(0x001AFFFF, 0, GSI2),
|
||||
PRT_ENTRY(0x001AFFFF, 1, GSI3),
|
||||
PRT_ENTRY(0x001AFFFF, 2, GSI0),
|
||||
PRT_ENTRY(0x001AFFFF, 3, GSI1),
|
||||
|
||||
PRT_ENTRY(0x001BFFFF, 0, GSI3),
|
||||
PRT_ENTRY(0x001BFFFF, 1, GSI0),
|
||||
PRT_ENTRY(0x001BFFFF, 2, GSI1),
|
||||
PRT_ENTRY(0x001BFFFF, 3, GSI2),
|
||||
|
||||
PRT_ENTRY(0x001CFFFF, 0, GSI0),
|
||||
PRT_ENTRY(0x001CFFFF, 1, GSI1),
|
||||
PRT_ENTRY(0x001CFFFF, 2, GSI2),
|
||||
PRT_ENTRY(0x001CFFFF, 3, GSI3),
|
||||
|
||||
PRT_ENTRY(0x001DFFFF, 0, GSI1),
|
||||
PRT_ENTRY(0x001DFFFF, 1, GSI2),
|
||||
PRT_ENTRY(0x001DFFFF, 2, GSI3),
|
||||
PRT_ENTRY(0x001DFFFF, 3, GSI0),
|
||||
|
||||
PRT_ENTRY(0x001EFFFF, 0, GSI2),
|
||||
PRT_ENTRY(0x001EFFFF, 1, GSI3),
|
||||
PRT_ENTRY(0x001EFFFF, 2, GSI0),
|
||||
PRT_ENTRY(0x001EFFFF, 3, GSI1),
|
||||
|
||||
PRT_ENTRY(0x001FFFFF, 0, GSI3),
|
||||
PRT_ENTRY(0x001FFFFF, 1, GSI0),
|
||||
PRT_ENTRY(0x001FFFFF, 2, GSI1),
|
||||
PRT_ENTRY(0x001FFFFF, 3, GSI2),
|
||||
})
|
||||
|
||||
// Root complex resources
|
||||
Name (_CRS, ResourceTemplate () {
|
||||
WordBusNumber ( // Bus numbers assigned to this root
|
||||
ResourceProducer,
|
||||
MinFixed, MaxFixed, PosDecode,
|
||||
0, // AddressGranularity
|
||||
0, // AddressMinimum - Minimum Bus Number
|
||||
0xff,// AddressMaximum - Maximum Bus Number
|
||||
0, // AddressTranslation - Set to 0
|
||||
256 // RangeLength - Number of Busses
|
||||
)
|
||||
|
||||
// IO to mmio window
|
||||
QWordIO (
|
||||
ResourceProducer, MinFixed,
|
||||
MaxFixed, PosDecode,
|
||||
EntireRange,
|
||||
0x00000000, // Granularity
|
||||
0x0000, // Min Base Address
|
||||
0xffff, // Max Base Address
|
||||
SBSA_PIO_BASE_ADDR, // Translate
|
||||
SBSA_PIO_LENGTH // Length
|
||||
)
|
||||
|
||||
DWordMemory ( // 32-bit BAR Windows
|
||||
ResourceProducer, PosDecode,
|
||||
MinFixed, MaxFixed,
|
||||
Cacheable, ReadWrite,
|
||||
0x00000000, // Granularity
|
||||
SBSA_PCIE_MMIO_BASE_ADDR, // Min Base Address
|
||||
SBSA_PCIE_MMIO_END, // Max Base Address
|
||||
0, // Translate
|
||||
SBSA_PCIE_MMIO_LENGTH // Length
|
||||
)
|
||||
|
||||
QWordMemory ( // 64-bit BAR Windows
|
||||
ResourceProducer, PosDecode,
|
||||
MinFixed, MaxFixed,
|
||||
Cacheable, ReadWrite,
|
||||
0x00000000, // Granularity
|
||||
SBSA_PCIE_MMIO_HIGH_BASE_ADDR, // Min Base Address
|
||||
SBSA_PCIE_MMIO_HIGH_END, // Max Base Address
|
||||
0, // Translate
|
||||
SBSA_PCIE_MMIO_HIGH_LENGTH // Length
|
||||
)
|
||||
}) // Name(_CRS)
|
||||
|
||||
Device (RES0)
|
||||
{
|
||||
Name (_HID, "PNP0C02" /* PNP Motherboard Resources */) // _HID: Hardware ID
|
||||
Name (_CRS, ResourceTemplate () // _CRS: Current Resource Settings
|
||||
{
|
||||
QWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, NonCacheable, ReadWrite,
|
||||
0x0000000000000000, // Granularity
|
||||
SBSA_PCIE_ECAM_BASE_ADDR, // Range Minimum
|
||||
SBSA_PCIE_ECAM_END, // Range Maximum
|
||||
0x0000000000000000, // Translation Offset
|
||||
SBSA_PCIE_ECAM_LENGTH, // Length
|
||||
,, , AddressRangeMemory, TypeStatic)
|
||||
})
|
||||
Method (_STA) {
|
||||
Return (0xF)
|
||||
}
|
||||
}
|
||||
|
||||
// OS Control Handoff
|
||||
Name (SUPP, Zero) // PCI _OSC Support Field value
|
||||
Name (CTRL, Zero) // PCI _OSC Control Field value
|
||||
|
||||
/*
|
||||
* See [1] 6.2.10, [2] 4.5
|
||||
*/
|
||||
Method (_OSC,4) {
|
||||
// Check for proper UUID
|
||||
If (Arg0 == ToUUID("33DB4D5B-1FF7-401C-9657-7441C03DD766")) {
|
||||
// Create DWord-adressable fields from the Capabilities Buffer
|
||||
CreateDWordField (Arg3,0,CDW1)
|
||||
CreateDWordField (Arg3,4,CDW2)
|
||||
CreateDWordField (Arg3,8,CDW3)
|
||||
|
||||
// Save Capabilities DWord2 & 3
|
||||
Store (CDW2,SUPP)
|
||||
Store (CDW3,CTRL)
|
||||
|
||||
// Only allow native hot plug control if OS supports:
|
||||
// * ASPM
|
||||
// * Clock PM
|
||||
// * MSI/MSI-X
|
||||
If ((SUPP & 0x16) != 0x16) {
|
||||
CTRL &= 0x1E // Mask bit 0 (and undefined bits)
|
||||
}
|
||||
|
||||
// Always allow native PME, AER (no dependencies)
|
||||
|
||||
// Never allow SHPC (no SHPC controller in this system)
|
||||
CTRL &= 0x1D
|
||||
|
||||
If (Arg1 != One) { // Unknown revision
|
||||
CDW1 |= 0x08
|
||||
}
|
||||
|
||||
If (CDW3 != CTRL) { // Capabilities bits were masked
|
||||
CDW1 |= 0x10
|
||||
}
|
||||
|
||||
// Update DWORD3 in the buffer
|
||||
Store (CTRL,CDW3)
|
||||
Return (Arg3)
|
||||
} Else {
|
||||
CDW1 |= 4 // Unrecognized UUID
|
||||
Return (Arg3)
|
||||
}
|
||||
} // End _OSC
|
||||
}
|
||||
} // Scope (_SB)
|
||||
}
|
22
board/emulation/qemu-sbsa/lowlevel_init.S
Normal file
22
board/emulation/qemu-sbsa/lowlevel_init.S
Normal file
|
@ -0,0 +1,22 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* (C) Copyright 2016
|
||||
* Cédric Schieli <cschieli@gmail.com>
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
/*
|
||||
* Routine: save_boot_params (called after reset from start.S)
|
||||
* Description: save ATAG/FDT address provided by the firmware at boot time
|
||||
*/
|
||||
|
||||
.global save_boot_params
|
||||
save_boot_params:
|
||||
/* The firmware provided ATAG/FDT address can be found in r2/x0 */
|
||||
adr x8, fw_dtb_pointer
|
||||
str x0, [x8]
|
||||
|
||||
|
||||
/* Returns */
|
||||
b save_boot_params_ret
|
273
board/emulation/qemu-sbsa/qemu-sbsa.c
Normal file
273
board/emulation/qemu-sbsa/qemu-sbsa.c
Normal file
|
@ -0,0 +1,273 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright (c) 2017 Tuomas Tynkkynen
|
||||
*/
|
||||
|
||||
#include <cpu_func.h>
|
||||
#include <dm.h>
|
||||
#include <env.h>
|
||||
#include <fdtdec.h>
|
||||
#include <fdt_support.h>
|
||||
#include <init.h>
|
||||
#include <log.h>
|
||||
#include <usb.h>
|
||||
#include <asm/armv8/mmu.h>
|
||||
|
||||
#include "qemu-sbsa.h"
|
||||
|
||||
/* Assigned in lowlevel_init.S
|
||||
* Push the variable into the .data section so that it
|
||||
* does not get cleared later.
|
||||
*/
|
||||
unsigned long __section(".data") fw_dtb_pointer;
|
||||
|
||||
static struct mm_region qemu_sbsa_mem_map[] = {
|
||||
{
|
||||
/* Secure flash */
|
||||
.virt = SBSA_SECURE_FLASH_BASE_ADDR,
|
||||
.phys = SBSA_SECURE_FLASH_BASE_ADDR,
|
||||
.size = SBSA_SECURE_FLASH_LENGTH,
|
||||
.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
|
||||
PTE_BLOCK_INNER_SHARE |
|
||||
PTE_BLOCK_PXN | PTE_BLOCK_UXN
|
||||
}, {
|
||||
/* Flash */
|
||||
.virt = SBSA_FLASH_BASE_ADDR,
|
||||
.phys = SBSA_FLASH_BASE_ADDR,
|
||||
.size = SBSA_FLASH_LENGTH,
|
||||
.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
|
||||
PTE_BLOCK_INNER_SHARE
|
||||
}, {
|
||||
/* Lowmem peripherals */
|
||||
.virt = SBSA_PERIPH_BASE_ADDR,
|
||||
.phys = SBSA_PERIPH_BASE_ADDR,
|
||||
.size = SBSA_PCIE_MMIO_BASE_ADDR - SBSA_PERIPH_BASE_ADDR,
|
||||
.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
|
||||
PTE_BLOCK_NON_SHARE |
|
||||
PTE_BLOCK_PXN | PTE_BLOCK_UXN
|
||||
}, {
|
||||
/* 32-bit address PCIE MMIO space */
|
||||
.virt = SBSA_PCIE_MMIO_BASE_ADDR,
|
||||
.phys = SBSA_PCIE_MMIO_BASE_ADDR,
|
||||
.size = SBSA_PCIE_MMIO_LENGTH,
|
||||
.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
|
||||
PTE_BLOCK_NON_SHARE |
|
||||
PTE_BLOCK_PXN | PTE_BLOCK_UXN
|
||||
}, {
|
||||
/* PCI-E ECAM memory area */
|
||||
.virt = SBSA_PCIE_ECAM_BASE_ADDR,
|
||||
.phys = SBSA_PCIE_ECAM_BASE_ADDR,
|
||||
.size = SBSA_PCIE_ECAM_LENGTH,
|
||||
.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
|
||||
PTE_BLOCK_NON_SHARE |
|
||||
PTE_BLOCK_PXN | PTE_BLOCK_UXN
|
||||
}, {
|
||||
/* Highmem PCI-E MMIO memory area */
|
||||
.virt = SBSA_PCIE_MMIO_HIGH_BASE_ADDR,
|
||||
.phys = SBSA_PCIE_MMIO_HIGH_BASE_ADDR,
|
||||
.size = SBSA_PCIE_MMIO_HIGH_LENGTH,
|
||||
.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
|
||||
PTE_BLOCK_NON_SHARE |
|
||||
PTE_BLOCK_PXN | PTE_BLOCK_UXN
|
||||
}, {
|
||||
/* DRAM */
|
||||
.virt = SBSA_MEM_BASE_ADDR,
|
||||
.phys = SBSA_MEM_BASE_ADDR,
|
||||
.size = 0x800000000000ULL,
|
||||
.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
|
||||
PTE_BLOCK_INNER_SHARE
|
||||
}, {
|
||||
/* List terminator */
|
||||
0,
|
||||
}
|
||||
};
|
||||
|
||||
struct mm_region *mem_map = qemu_sbsa_mem_map;
|
||||
|
||||
int board_late_init(void)
|
||||
{
|
||||
/* start usb so that usb keyboard can be used as input device */
|
||||
if (CONFIG_IS_ENABLED(USB_KEYBOARD))
|
||||
usb_init();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int board_init(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* dtb_dt_qemu - Return the address of the QEMU provided FDT.
|
||||
*
|
||||
* @return: Pointer to FDT or NULL on failure
|
||||
*/
|
||||
static void *dtb_dt_qemu(void)
|
||||
{
|
||||
/* FDT might be at start of DRAM */
|
||||
if (fdt_magic(SBSA_MEM_BASE_ADDR) == FDT_MAGIC)
|
||||
return (void *)(u64)SBSA_MEM_BASE_ADDR;
|
||||
|
||||
/* When ARM_LINUX_KERNEL_AS_BL33 is enabled in ATF, it's passed in x0 */
|
||||
if (fw_dtb_pointer >= SBSA_MEM_BASE_ADDR &&
|
||||
fdt_magic(fw_dtb_pointer) == FDT_MAGIC) {
|
||||
return (void *)fw_dtb_pointer;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* QEMU doesn't set compatible on cpus.
|
||||
* Add them to make sure the U-Boot driver properly bind.
|
||||
*/
|
||||
static int fdtdec_fix_cpus(void *fdt_blob)
|
||||
{
|
||||
int cpus_offset, off, ret;
|
||||
u64 mpidr, i = 0;
|
||||
|
||||
cpus_offset = fdt_path_offset(fdt_blob, "/cpus");
|
||||
if (cpus_offset < 0) {
|
||||
puts("couldn't find /cpus node\n");
|
||||
return cpus_offset;
|
||||
}
|
||||
|
||||
fdt_for_each_subnode(off, fdt_blob, cpus_offset) {
|
||||
if (strncmp(fdt_get_name(fdt_blob, off, NULL), "cpu@", 4))
|
||||
continue;
|
||||
|
||||
mpidr = 0;
|
||||
ret = smc_get_mpidr(i, &mpidr);
|
||||
if (ret) {
|
||||
log_warning("Failed to get MPIDR for processor %lld from SMC: %d\n",
|
||||
i, ret);
|
||||
mpidr = i;
|
||||
}
|
||||
|
||||
ret = fdt_setprop_string(fdt_blob, off, "compatible", "arm,armv8");
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = fdt_setprop_string(fdt_blob, off, "device_type", "cpu");
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = fdt_setprop_u64(fdt_blob, off, "reg", mpidr);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
i++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Update the GIC node when necessary and add optional ITS when it has a
|
||||
* non zero base-address.
|
||||
*/
|
||||
static int fdtdec_fix_gic(void *fdt)
|
||||
{
|
||||
u64 gic_dist_base = SBSA_GIC_DIST_BASE_ADDR;
|
||||
u64 gic_redist_base = SBSA_GIC_REDIST_BASE_ADDR;
|
||||
u64 gic_its_base = 0;
|
||||
int offs, ret;
|
||||
u64 reg[10];
|
||||
|
||||
/* Invoke SMC to get real base-address */
|
||||
smc_get_gic_dist_base(&gic_dist_base);
|
||||
smc_get_gic_redist_base(&gic_redist_base);
|
||||
|
||||
if ((gic_dist_base != SBSA_GIC_DIST_BASE_ADDR) ||
|
||||
(gic_redist_base != SBSA_GIC_REDIST_BASE_ADDR)) {
|
||||
offs = fdt_path_offset(fdt, "/interrupt-controller");
|
||||
if (offs < 0) {
|
||||
puts("couldn't find /interrupt-controller node\n");
|
||||
return offs;
|
||||
}
|
||||
|
||||
reg[0] = cpu_to_fdt64(gic_dist_base);
|
||||
reg[1] = cpu_to_fdt64((u64)SBSA_GIC_DIST_LENGTH);
|
||||
reg[2] = cpu_to_fdt64(gic_redist_base);
|
||||
reg[3] = cpu_to_fdt64((u64)SBSA_GIC_REDIST_LENGTH);
|
||||
reg[4] = cpu_to_fdt64(0);
|
||||
reg[5] = cpu_to_fdt64(0);
|
||||
reg[6] = cpu_to_fdt64(SBSA_GIC_HBASE_ADDR);
|
||||
reg[7] = cpu_to_fdt64((u64)SBSA_GIC_HBASE_LENGTH);
|
||||
reg[8] = cpu_to_fdt64(SBSA_GIC_VBASE_ADDR);
|
||||
reg[9] = cpu_to_fdt64((u64)SBSA_GIC_VBASE_LENGTH);
|
||||
|
||||
ret = fdt_setprop_inplace(fdt, offs, "reg", reg, sizeof(reg));
|
||||
}
|
||||
|
||||
smc_get_gic_its_base(&gic_its_base);
|
||||
|
||||
if (gic_its_base != 0) {
|
||||
offs = fdt_path_offset(fdt, "/its");
|
||||
if (offs < 0)
|
||||
return offs;
|
||||
|
||||
ret = fdt_setprop_string(fdt, offs, "status", "okay");
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
reg[0] = cpu_to_fdt64(gic_its_base);
|
||||
reg[1] = 0;
|
||||
|
||||
ret = fdt_setprop(fdt, offs, "reg", reg, sizeof(u64) * 2);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fdtdec_board_setup(const void *fdt_blob)
|
||||
{
|
||||
void *qemu_fdt;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Locate the QEMU provided DTB that contains the CPUs and amount of DRAM.
|
||||
*/
|
||||
qemu_fdt = dtb_dt_qemu();
|
||||
if (!qemu_fdt) {
|
||||
log_err("QEMU FDT not found\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret = fdt_increase_size((void *)fdt_blob, 1024 + fdt_totalsize(qemu_fdt));
|
||||
if (ret)
|
||||
return -ENOMEM;
|
||||
|
||||
/*
|
||||
* Merge the QEMU DTB as overlay into the U-Boot provided DTB.
|
||||
*/
|
||||
ret = fdt_overlay_apply_node((void *)fdt_blob, 0, qemu_fdt, 0);
|
||||
if (ret < 0)
|
||||
log_err("Failed to apply overlay: %d\n", ret);
|
||||
|
||||
/* Fix QEMU nodes to make sure U-Boot drivers are properly working */
|
||||
ret = fdtdec_fix_cpus((void *)fdt_blob);
|
||||
if (ret < 0)
|
||||
log_err("Failed to fix CPUs in FDT: %d\n", ret);
|
||||
|
||||
ret = fdtdec_fix_gic((void *)fdt_blob);
|
||||
if (ret < 0)
|
||||
log_err("Failed to fix INTC in FDT: %d\n", ret);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int misc_init_r(void)
|
||||
{
|
||||
return env_set_hex("fdt_addr", (uintptr_t)gd->fdt_blob);
|
||||
}
|
||||
|
||||
void reset_cpu(void)
|
||||
{
|
||||
}
|
||||
|
||||
int dram_init(void)
|
||||
{
|
||||
return fdtdec_setup_mem_size_base();
|
||||
}
|
14
board/emulation/qemu-sbsa/qemu-sbsa.env
Normal file
14
board/emulation/qemu-sbsa/qemu-sbsa.env
Normal file
|
@ -0,0 +1,14 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
|
||||
/* environment for qemu-arm and qemu-arm64 */
|
||||
|
||||
stdin=serial,usbkbd
|
||||
stdout=serial,vidconsole
|
||||
stderr=serial,vidconsole
|
||||
fdt_high=0xffffffffffffffff
|
||||
initrd_high=0xffffffffffffffff
|
||||
scriptaddr=0x100000300000
|
||||
pxefile_addr_r=0x10000400000
|
||||
kernel_addr_r=0x10000200000
|
||||
ramdisk_addr_r=0x10001000000
|
||||
boot_targets=qfw usb scsi virtio nvme dhcp
|
38
board/emulation/qemu-sbsa/qemu-sbsa.h
Normal file
38
board/emulation/qemu-sbsa/qemu-sbsa.h
Normal file
|
@ -0,0 +1,38 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright (c) 2024 9elements GmbH
|
||||
*/
|
||||
|
||||
/**
|
||||
* smc_get_mpidr() - Call into SMC and get the MPIDR for given CPU
|
||||
*
|
||||
* @id: CPU index
|
||||
* @mpidr: Pointer where to place the MPIDR
|
||||
* @return 0 if OK, other -ve on error
|
||||
*/
|
||||
int smc_get_mpidr(unsigned long id, u64 *mpidr);
|
||||
|
||||
/**
|
||||
* smc_get_gic_dist_base() - Call into SMC and get GIC dist base address
|
||||
*
|
||||
* @mpidr: Pointer where to place the base address
|
||||
* @return 0 if OK, other -ve on error
|
||||
*/
|
||||
int smc_get_gic_dist_base(u64 *base);
|
||||
|
||||
/**
|
||||
* smc_get_gic_redist_base() - Call into SMC and get the GIC redistributor
|
||||
* base address
|
||||
*
|
||||
* @mpidr: Pointer where to place the base address
|
||||
* @return 0 if OK, other -ve on error
|
||||
*/
|
||||
int smc_get_gic_redist_base(u64 *base);
|
||||
|
||||
/**
|
||||
* smc_get_gic_its_base() - Call into SMC and get the ITS base address
|
||||
*
|
||||
* @mpidr: Pointer where to place the base address
|
||||
* @return 0 if OK, other -ve on error
|
||||
*/
|
||||
int smc_get_gic_its_base(u64 *base);
|
71
board/emulation/qemu-sbsa/smc.c
Normal file
71
board/emulation/qemu-sbsa/smc.c
Normal file
|
@ -0,0 +1,71 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (c) 2024 9elements GmbH
|
||||
*/
|
||||
|
||||
#include <cpu.h>
|
||||
#include <init.h>
|
||||
#include <log.h>
|
||||
#include <linux/arm-smccc.h>
|
||||
|
||||
#define SMC_SIP_FUNCTION_ID(n) (0xC2000000 | (n))
|
||||
|
||||
#define SIP_SVC_VERSION SMC_SIP_FUNCTION_ID(1)
|
||||
#define SIP_SVC_GET_GIC SMC_SIP_FUNCTION_ID(100)
|
||||
#define SIP_SVC_GET_GIC_ITS SMC_SIP_FUNCTION_ID(101)
|
||||
#define SIP_SVC_GET_CPU_COUNT SMC_SIP_FUNCTION_ID(200)
|
||||
#define SIP_SVC_GET_CPU_NODE SMC_SIP_FUNCTION_ID(201)
|
||||
#define SIP_SVC_GET_MEMORY_NODE_COUNT SMC_SIP_FUNCTION_ID(300)
|
||||
#define SIP_SVC_GET_MEMORY_NODE SMC_SIP_FUNCTION_ID(301)
|
||||
|
||||
int smc_get_mpidr(unsigned long id, u64 *mpidr)
|
||||
{
|
||||
struct arm_smccc_res res;
|
||||
|
||||
res.a0 = ~0;
|
||||
arm_smccc_smc(SIP_SVC_GET_CPU_NODE, id, 0, 0, 0, 0, 0, 0, &res);
|
||||
|
||||
if (!res.a0)
|
||||
*mpidr = res.a2;
|
||||
|
||||
return res.a0;
|
||||
}
|
||||
|
||||
int smc_get_gic_dist_base(u64 *base)
|
||||
{
|
||||
struct arm_smccc_res res;
|
||||
|
||||
res.a0 = ~0;
|
||||
arm_smccc_smc(SIP_SVC_GET_GIC, 0, 0, 0, 0, 0, 0, 0, &res);
|
||||
|
||||
if (!res.a0)
|
||||
*base = res.a1;
|
||||
|
||||
return res.a0;
|
||||
}
|
||||
|
||||
int smc_get_gic_redist_base(u64 *base)
|
||||
{
|
||||
struct arm_smccc_res res;
|
||||
|
||||
res.a0 = ~0;
|
||||
arm_smccc_smc(SIP_SVC_GET_GIC, 0, 0, 0, 0, 0, 0, 0, &res);
|
||||
|
||||
if (!res.a0)
|
||||
*base = res.a2;
|
||||
|
||||
return res.a0;
|
||||
}
|
||||
|
||||
int smc_get_gic_its_base(u64 *base)
|
||||
{
|
||||
struct arm_smccc_res res;
|
||||
|
||||
res.a0 = ~0;
|
||||
arm_smccc_smc(SIP_SVC_GET_GIC_ITS, 0, 0, 0, 0, 0, 0, 0, &res);
|
||||
|
||||
if (!res.a0)
|
||||
*base = res.a1;
|
||||
|
||||
return res.a0;
|
||||
}
|
3
board/raspberrypi/rpi/.gitignore
vendored
Normal file
3
board/raspberrypi/rpi/.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
dsdt_generated.aml
|
||||
dsdt_generated.asl.tmp
|
||||
dsdt_generated.c
|
|
@ -4,3 +4,5 @@
|
|||
|
||||
obj-y := rpi.o
|
||||
obj-y += lowlevel_init.o
|
||||
|
||||
obj-$(CONFIG_GENERATE_ACPI_TABLE) += dsdt_generated.o
|
||||
|
|
90
board/raspberrypi/rpi/acpitables.h
Normal file
90
board/raspberrypi/rpi/acpitables.h
Normal file
|
@ -0,0 +1,90 @@
|
|||
/** @file
|
||||
*
|
||||
* RPi defines for constructing ACPI tables
|
||||
*
|
||||
* Copyright (c) 2020, Pete Batard <pete@akeo.ie>
|
||||
* Copyright (c) 2019, ARM Ltd. All rights reserved.
|
||||
* Copyright (c) 2018, Andrei Warkentin <andrey.warkentin@gmail.com>
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
*
|
||||
**/
|
||||
|
||||
#ifndef __RPI_ACPITABLES_H__
|
||||
#define __RPI_ACPITABLES_H__
|
||||
|
||||
#include <acpi/acpi_table.h>
|
||||
|
||||
// The ASL compiler can't perform arithmetic on MEMORY32FIXED ()
|
||||
// parameters so you can't pass a constant like BASE + OFFSET.
|
||||
// We therefore define a macro that can perform arithmetic base
|
||||
// address update with an offset.
|
||||
#define MEMORY32SETBASE(BufName, MemName, VarName, Offset) \
|
||||
CreateDwordField (^BufName, ^MemName._BAS, VarName) \
|
||||
Add (BCM2836_SOC_REGISTERS, Offset, VarName)
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Interrupts. These are specific to each platform
|
||||
//------------------------------------------------------------------------
|
||||
#if defined(CONFIG_TARGET_RPI_3)
|
||||
#define BCM2836_V3D_BUS_INTERRUPT 0x2A
|
||||
#define BCM2836_DMA_INTERRUPT 0x3B
|
||||
#define BCM2836_SPI1_INTERRUPT 0x3D
|
||||
#define BCM2836_SPI2_INTERRUPT 0x3D
|
||||
#define BCM2836_HVS_INTERRUPT 0x41
|
||||
#define BCM2836_HDMI0_INTERRUPT 0x48
|
||||
#define BCM2836_HDMI1_INTERRUPT 0x49
|
||||
#define BCM2836_PV2_INTERRUPT 0x4A
|
||||
#define BCM2836_PV0_INTERRUPT 0x4D
|
||||
#define BCM2836_PV1_INTERRUPT 0x4E
|
||||
#define BCM2836_MBOX_INTERRUPT 0x61
|
||||
#define BCM2836_VCHIQ_INTERRUPT 0x62
|
||||
#define BCM2386_GPIO_INTERRUPT0 0x51
|
||||
#define BCM2386_GPIO_INTERRUPT1 0x52
|
||||
#define BCM2386_GPIO_INTERRUPT2 0x53
|
||||
#define BCM2386_GPIO_INTERRUPT3 0x54
|
||||
#define BCM2836_I2C1_INTERRUPT 0x55
|
||||
#define BCM2836_I2C2_INTERRUPT 0x55
|
||||
#define BCM2836_SPI0_INTERRUPT 0x56
|
||||
#define BCM2836_USB_INTERRUPT 0x29
|
||||
#define BCM2836_SDHOST_INTERRUPT 0x58
|
||||
#define BCM2836_MMCHS1_INTERRUPT 0x5E
|
||||
#define BCM2836_MINI_UART_INTERRUPT 0x3D
|
||||
#define BCM2836_PL011_UART_INTERRUPT 0x59
|
||||
#elif defined(CONFIG_TARGET_RPI_4)
|
||||
#define BCM2836_V3D_BUS_INTERRUPT 0x2A
|
||||
#define BCM2836_DMA_INTERRUPT 0x3B
|
||||
#define BCM2836_SPI1_INTERRUPT 0x7D
|
||||
#define BCM2836_SPI2_INTERRUPT 0x7D
|
||||
#define BCM2836_HVS_INTERRUPT 0x41
|
||||
#define BCM2836_HDMI0_INTERRUPT 0x48
|
||||
#define BCM2836_HDMI1_INTERRUPT 0x49
|
||||
#define BCM2836_PV2_INTERRUPT 0x4A
|
||||
#define BCM2836_PV0_INTERRUPT 0x4D
|
||||
#define BCM2836_PV1_INTERRUPT 0x4E
|
||||
#define BCM2836_MBOX_INTERRUPT 0x41
|
||||
#define BCM2836_VCHIQ_INTERRUPT 0x42
|
||||
#define BCM2386_GPIO_INTERRUPT0 0x91
|
||||
#define BCM2386_GPIO_INTERRUPT1 0x92
|
||||
#define BCM2386_GPIO_INTERRUPT2 0x93
|
||||
#define BCM2386_GPIO_INTERRUPT3 0x94
|
||||
#define BCM2836_I2C1_INTERRUPT 0x95
|
||||
#define BCM2836_I2C2_INTERRUPT 0x95
|
||||
#define BCM2836_SPI0_INTERRUPT 0x96
|
||||
#define BCM2836_USB_INTERRUPT 0x69
|
||||
#define BCM2836_SDHOST_INTERRUPT 0x98
|
||||
#define BCM2836_MMCHS1_INTERRUPT 0x9E
|
||||
#define BCM2836_MINI_UART_INTERRUPT 0x7D
|
||||
#define BCM2836_PL011_UART_INTERRUPT 0x99
|
||||
#define GENET_INTERRUPT0 0xBD
|
||||
#define GENET_INTERRUPT1 0xBE
|
||||
#define GENET_BASE_ADDRESS 0xFD580000
|
||||
#define GENET_LENGTH 0x10000
|
||||
#define THERM_SENSOR_BASE_ADDRESS 0xFD5d2200
|
||||
#define THERM_SENSOR_LENGTH 0x8
|
||||
#else
|
||||
#error "Unsupported rpi module for ACPI tables"
|
||||
#endif
|
||||
|
||||
#endif // __ACPITABLES_H__
|
254
board/raspberrypi/rpi/dsdt.asl
Normal file
254
board/raspberrypi/rpi/dsdt.asl
Normal file
|
@ -0,0 +1,254 @@
|
|||
/** @file
|
||||
*
|
||||
* Differentiated System Definition Table (DSDT)
|
||||
*
|
||||
* Copyright (c) 2020, Pete Batard <pete@akeo.ie>
|
||||
* Copyright (c) 2018-2020, Andrey Warkentin <andrey.warkentin@gmail.com>
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Copyright (c) 2021, ARM Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
*
|
||||
**/
|
||||
|
||||
#include <asm/arch/acpi/bcm2711.h>
|
||||
#include <asm/arch/acpi/bcm2836.h>
|
||||
#include <asm/arch/acpi/bcm2836_gpio.h>
|
||||
#include <asm/arch/acpi/bcm2836_gpu.h>
|
||||
#include <asm/arch/acpi/bcm2836_pwm.h>
|
||||
#include <asm/arch/acpi/bcm2836_sdio.h>
|
||||
#include <asm/arch/acpi/bcm2836_sdhost.h>
|
||||
|
||||
#include "acpitables.h"
|
||||
|
||||
#define BCM_ALT0 0x4
|
||||
#define BCM_ALT1 0x5
|
||||
#define BCM_ALT2 0x6
|
||||
#define BCM_ALT3 0x7
|
||||
#define BCM_ALT4 0x3
|
||||
#define BCM_ALT5 0x2
|
||||
|
||||
//
|
||||
// The ASL compiler does not support argument arithmetic in functions
|
||||
// like QWordMemory (). So we need to instantiate dummy qword regions
|
||||
// that we can then update the Min, Max and Length attributes of.
|
||||
// The three macros below help accomplish this.
|
||||
//
|
||||
// QWORDMEMORYSET specifies a CPU memory range (whose base address is
|
||||
// BCM2836_SOC_REGISTERS + Offset), and QWORDBUSMEMORYSET specifies
|
||||
// a VPU memory range (whose base address is provided directly).
|
||||
//
|
||||
#define QWORDMEMORYBUF(Index) \
|
||||
QWordMemory (ResourceProducer,, \
|
||||
MinFixed, MaxFixed, NonCacheable, ReadWrite, \
|
||||
0x0, 0x0, 0x0, 0x0, 0x1,,, RB ## Index)
|
||||
|
||||
#define QWORDMEMORYSET(Index, Offset, Length) \
|
||||
CreateQwordField (RBUF, RB ## Index._MIN, MI ## Index) \
|
||||
CreateQwordField (RBUF, RB ## Index._MAX, MA ## Index) \
|
||||
CreateQwordField (RBUF, RB ## Index._LEN, LE ## Index) \
|
||||
Store (Length, LE ## Index) \
|
||||
Add (BCM2836_SOC_REGISTERS, Offset, MI ## Index) \
|
||||
Add (MI ## Index, LE ## Index - 1, MA ## Index)
|
||||
|
||||
#define QWORDBUSMEMORYSET(Index, Base, Length) \
|
||||
CreateQwordField (RBUF, RB ## Index._MIN, MI ## Index) \
|
||||
CreateQwordField (RBUF, RB ## Index._MAX, MA ## Index) \
|
||||
CreateQwordField (RBUF, RB ## Index._LEN, LE ## Index) \
|
||||
Store (Base, MI ## Index) \
|
||||
Store (Length, LE ## Index) \
|
||||
Add (MI ## Index, LE ## Index - 1, MA ## Index)
|
||||
|
||||
DefinitionBlock ("Dsdt.aml", "DSDT", 2, "RPIFDN", "RPI", 2)
|
||||
{
|
||||
External (\_PR.CP00, DeviceObj)
|
||||
External (\_PR.CP01, DeviceObj)
|
||||
External (\_PR.CP02, DeviceObj)
|
||||
External (\_PR.CP03, DeviceObj)
|
||||
Scope (\_SB_)
|
||||
{
|
||||
include ("pep.asl")
|
||||
|
||||
//
|
||||
// GPU device container describes the DMA translation required
|
||||
// when a device behind the GPU wants to access Arm memory.
|
||||
// Only the first GB can be addressed.
|
||||
//
|
||||
Device (GDV0)
|
||||
{
|
||||
Name (_HID, "ACPI0004")
|
||||
Name (_UID, 0x1)
|
||||
Name (_CCA, 0x0)
|
||||
|
||||
Method (_CRS, 0, Serialized) {
|
||||
//
|
||||
// Container devices with _DMA must have _CRS, meaning GDV0
|
||||
// to provide all resources that GpuDevs.asl consume (except
|
||||
// interrupts).
|
||||
//
|
||||
Name (RBUF, ResourceTemplate () {
|
||||
QWORDMEMORYBUF(01)
|
||||
QWORDMEMORYBUF(02)
|
||||
QWORDMEMORYBUF(03)
|
||||
// QWORDMEMORYBUF(04)
|
||||
// QWORDMEMORYBUF(05)
|
||||
QWORDMEMORYBUF(06)
|
||||
QWORDMEMORYBUF(07)
|
||||
QWORDMEMORYBUF(08)
|
||||
QWORDMEMORYBUF(09)
|
||||
QWORDMEMORYBUF(10)
|
||||
QWORDMEMORYBUF(11)
|
||||
QWORDMEMORYBUF(12)
|
||||
QWORDMEMORYBUF(13)
|
||||
QWORDMEMORYBUF(14)
|
||||
QWORDMEMORYBUF(15)
|
||||
// QWORDMEMORYBUF(16)
|
||||
QWORDMEMORYBUF(17)
|
||||
QWORDMEMORYBUF(18)
|
||||
QWORDMEMORYBUF(19)
|
||||
QWORDMEMORYBUF(20)
|
||||
QWORDMEMORYBUF(21)
|
||||
QWORDMEMORYBUF(22)
|
||||
QWORDMEMORYBUF(23)
|
||||
QWORDMEMORYBUF(24)
|
||||
QWORDMEMORYBUF(25)
|
||||
})
|
||||
|
||||
// USB
|
||||
QWORDMEMORYSET(01, BCM2836_USB_OFFSET, BCM2836_USB_LENGTH)
|
||||
|
||||
// GPU
|
||||
QWORDMEMORYSET(02, BCM2836_V3D_BUS_OFFSET, BCM2836_V3D_BUS_LENGTH)
|
||||
QWORDMEMORYSET(03, BCM2836_HVS_OFFSET, BCM2836_HVS_LENGTH)
|
||||
// QWORDMEMORYSET(04, BCM2836_PV0_OFFSET, BCM2836_PV0_LENGTH)
|
||||
// QWORDMEMORYSET(05, BCM2836_PV1_OFFSET, BCM2836_PV1_LENGTH)
|
||||
QWORDMEMORYSET(06, BCM2836_PV2_OFFSET, BCM2836_PV2_LENGTH)
|
||||
QWORDMEMORYSET(07, BCM2836_HDMI0_OFFSET, BCM2836_HDMI0_LENGTH)
|
||||
QWORDMEMORYSET(08, BCM2836_HDMI1_OFFSET, BCM2836_HDMI1_LENGTH)
|
||||
|
||||
// Mailbox
|
||||
QWORDMEMORYSET(09, BCM2836_MBOX_OFFSET, BCM2836_MBOX_LENGTH)
|
||||
|
||||
// VCHIQ
|
||||
QWORDMEMORYSET(10, BCM2836_VCHIQ_OFFSET, BCM2836_VCHIQ_LENGTH)
|
||||
|
||||
// GPIO
|
||||
QWORDMEMORYSET(11, GPIO_OFFSET, GPIO_LENGTH)
|
||||
|
||||
// I2C
|
||||
QWORDMEMORYSET(12, BCM2836_I2C1_OFFSET, BCM2836_I2C1_LENGTH)
|
||||
QWORDMEMORYSET(13, BCM2836_I2C2_OFFSET, BCM2836_I2C2_LENGTH)
|
||||
|
||||
// SPI
|
||||
QWORDMEMORYSET(14, BCM2836_SPI0_OFFSET, BCM2836_SPI0_LENGTH)
|
||||
QWORDMEMORYSET(15, BCM2836_SPI1_OFFSET, BCM2836_SPI1_LENGTH)
|
||||
// QWORDMEMORYSET(16, BCM2836_SPI2_OFFSET, BCM2836_SPI2_LENGTH)
|
||||
|
||||
// PWM
|
||||
QWORDMEMORYSET(17, BCM2836_PWM_DMA_OFFSET, BCM2836_PWM_DMA_LENGTH)
|
||||
QWORDMEMORYSET(18, BCM2836_PWM_CTRL_OFFSET, BCM2836_PWM_CTRL_LENGTH)
|
||||
QWORDBUSMEMORYSET(19, BCM2836_PWM_BUS_BASE_ADDRESS, BCM2836_PWM_BUS_LENGTH)
|
||||
QWORDBUSMEMORYSET(20, BCM2836_PWM_CTRL_UNCACHED_BASE_ADDRESS, BCM2836_PWM_CTRL_UNCACHED_LENGTH)
|
||||
QWORDMEMORYSET(21, BCM2836_PWM_CLK_OFFSET, BCM2836_PWM_CLK_LENGTH)
|
||||
|
||||
// UART
|
||||
QWORDMEMORYSET(22, BCM2836_PL011_UART_OFFSET, BCM2836_PL011_UART_LENGTH)
|
||||
QWORDMEMORYSET(23, BCM2836_MINI_UART_OFFSET, BCM2836_MINI_UART_LENGTH)
|
||||
|
||||
// SDC
|
||||
QWORDMEMORYSET(24, MMCHS1_OFFSET, MMCHS1_LENGTH)
|
||||
QWORDMEMORYSET(25, SDHOST_OFFSET, SDHOST_LENGTH)
|
||||
|
||||
Return (RBUF)
|
||||
}
|
||||
|
||||
Name (_DMA, ResourceTemplate() {
|
||||
//
|
||||
// Only the first GB is available.
|
||||
// Bus 0xC0000000 -> CPU 0x00000000.
|
||||
//
|
||||
QWordMemory (ResourceProducer,
|
||||
,
|
||||
MinFixed,
|
||||
MaxFixed,
|
||||
NonCacheable,
|
||||
ReadWrite,
|
||||
0x0,
|
||||
0x00000000C0000000, // MIN
|
||||
0x00000000FFFFFFFF, // MAX
|
||||
0xFFFFFFFF40000000, // TRA
|
||||
0x0000000040000000, // LEN
|
||||
,
|
||||
,
|
||||
)
|
||||
})
|
||||
#include "gpudevs.asl"
|
||||
}
|
||||
|
||||
#if defined(CONFIG_TARGET_RPI_4)
|
||||
Device (ETH0)
|
||||
{
|
||||
Name (_HID, "BCM6E4E")
|
||||
Name (_CID, "BCM6E4E")
|
||||
Name (_UID, 0x0)
|
||||
Name (_CCA, 0x0)
|
||||
|
||||
Method (_CRS, 0x0, Serialized)
|
||||
{
|
||||
Return (ResourceTemplate ()
|
||||
{
|
||||
// No need for MEMORY32SETBASE on Genet as we have a straight base address constant
|
||||
MEMORY32FIXED (ReadWrite, GENET_BASE_ADDRESS, GENET_LENGTH, )
|
||||
Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { GENET_INTERRUPT0, GENET_INTERRUPT1 }
|
||||
})
|
||||
}
|
||||
Name (_DSD, Package () {
|
||||
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
|
||||
Package () {
|
||||
Package () { "brcm,max-dma-burst-size", 0x08 },
|
||||
Package () { "phy-mode", "rgmii-rxid" },
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Define a simple thermal zone. The idea here is we compute the SOC temp
|
||||
// via a register we can read, and give it to the OS. This enables basic
|
||||
// reports from the "sensors" utility, and the OS can then poll and take
|
||||
// actions if that temp exceeds any of the given thresholds.
|
||||
Device (EC00)
|
||||
{
|
||||
Name (_HID, EISAID ("PNP0C06"))
|
||||
Name (_CCA, 0x0)
|
||||
|
||||
// all temps in are tenths of K (aka 2732 is the min temps in Linux (aka 0C))
|
||||
ThermalZone (TZ00) {
|
||||
OperationRegion (TEMS, SystemMemory, THERM_SENSOR_BASE_ADDRESS, THERM_SENSOR_LENGTH)
|
||||
Field (TEMS, DWordAcc, NoLock, Preserve) {
|
||||
TMPS, 32
|
||||
}
|
||||
Method (_TMP, 0, Serialized) {
|
||||
return (((410040 - ((TMPS & 0x3ff) * 487)) / 100) + 2732);
|
||||
}
|
||||
|
||||
Method (_SCP, 3) { } // receive cooling policy from OS
|
||||
|
||||
Method (_CRT) { Return (3632) } // (90C) Critical temp point (immediate power-off)
|
||||
Method (_HOT) { Return (3582) } // (85C) HOT state where OS should hibernate
|
||||
Method (_PSV) { Return (3532) } // (80C) Passive cooling (CPU throttling) trip point
|
||||
|
||||
// SSDT inserts _AC0/_AL0 @60C here, if a FAN is configured
|
||||
|
||||
Name (_TZP, 10) //The OSPM must poll this device every 1 seconds
|
||||
Name (_PSL, Package () { \_PR.CP00, \_PR.CP01, \_PR.CP02, \_PR.CP03 })
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#include "uart.asl"
|
||||
#include "rhpx.asl"
|
||||
#include "sdhc.asl"
|
||||
#include "emmc.asl"
|
||||
#include "pci.asl"
|
||||
}
|
||||
}
|
136
board/raspberrypi/rpi/emmc.asl
Normal file
136
board/raspberrypi/rpi/emmc.asl
Normal file
|
@ -0,0 +1,136 @@
|
|||
/** @file
|
||||
*
|
||||
* Copyright (c) 2021, ARM Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
*
|
||||
**/
|
||||
|
||||
#include <asm/arch/acpi/bcm2836_sdhost.h>
|
||||
#include <asm/arch/acpi/bcm2836_sdio.h>
|
||||
#include <asm/arch/acpi/bcm2711.h>
|
||||
|
||||
Device (GDV1) {
|
||||
Name (_HID, "ACPI0004")
|
||||
Name (_UID, 0x2)
|
||||
Name (_CCA, 0x0)
|
||||
|
||||
Name (RBUF, ResourceTemplate ()
|
||||
{
|
||||
MEMORY32FIXED (ReadWrite, 0, MMCHS2_LENGTH, RMEM)
|
||||
})
|
||||
Method (_CRS, 0x0, Serialized)
|
||||
{
|
||||
MEMORY32SETBASE (RBUF, RMEM, RBAS, MMCHS2_OFFSET)
|
||||
Return (^RBUF)
|
||||
}
|
||||
|
||||
// Translated DMA region for BCM2711 silicon revisions older than C0
|
||||
Name (DMTR, ResourceTemplate() {
|
||||
QWordMemory (ResourceProducer,
|
||||
,
|
||||
MinFixed,
|
||||
MaxFixed,
|
||||
NonCacheable,
|
||||
ReadWrite,
|
||||
0x0,
|
||||
0x00000000C0000000, // MIN
|
||||
0x00000000FFFFFFFF, // MAX
|
||||
0xFFFFFFFF40000000, // TRA
|
||||
0x0000000040000000, // LEN
|
||||
,
|
||||
,
|
||||
)
|
||||
})
|
||||
|
||||
// Non translated DMA region for BCM2711 revisions C0 and newer
|
||||
Name (DMNT, ResourceTemplate() {
|
||||
QWordMemory (ResourceProducer,
|
||||
,
|
||||
MinFixed,
|
||||
MaxFixed,
|
||||
NonCacheable,
|
||||
ReadWrite,
|
||||
0x0,
|
||||
0x0000000000000000, // MIN
|
||||
0x000000FFFFFFFFFF, // MAX
|
||||
0x0000000000000000, // TRA
|
||||
0x0000010000000000, // LEN
|
||||
,
|
||||
,
|
||||
)
|
||||
})
|
||||
|
||||
// emmc2 Host Controller. (brcm,bcm2711-emmc2)
|
||||
Device (SDC3)
|
||||
{
|
||||
Name (_HID, "BRCME88C")
|
||||
Name (_UID, 0x1)
|
||||
Name (_CCA, 0x0)
|
||||
Name (_S1D, 0x1)
|
||||
Name (_S2D, 0x1)
|
||||
Name (_S3D, 0x1)
|
||||
Name (_S4D, 0x1)
|
||||
Name (SDMA, 0x2)
|
||||
|
||||
Name (RBUF, ResourceTemplate ()
|
||||
{
|
||||
MEMORY32FIXED (ReadWrite, 0, MMCHS2_LENGTH, RMEM)
|
||||
Interrupt (ResourceConsumer, Level, ActiveHigh, Shared) { BCM2836_MMCHS1_INTERRUPT }
|
||||
})
|
||||
Method (_CRS, 0x0, Serialized)
|
||||
{
|
||||
MEMORY32SETBASE (RBUF, RMEM, RBAS, MMCHS2_OFFSET)
|
||||
Return (^RBUF)
|
||||
}
|
||||
|
||||
// Unfortunately this controller doesn't honor the
|
||||
// standard SDHCI voltage control registers
|
||||
// (or at least Linux's standard code can't
|
||||
// lower the voltage) So, UHS mode is disabled with caps
|
||||
Name (DSD1, Package () {
|
||||
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
|
||||
Package () {
|
||||
Package () { "sdhci-caps-mask", 0x0000000500080000 },
|
||||
}
|
||||
})
|
||||
// Along with disabling UHS, here both SDMA and ADMA2
|
||||
// are also disabled until the linux _DMA() mask/translate
|
||||
// works properly.
|
||||
Name (DSD2, Package () {
|
||||
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
|
||||
Package () {
|
||||
Package () { "sdhci-caps-mask", 0x0000000504480000 },
|
||||
}
|
||||
})
|
||||
Method (_DSD, 0x0, Serialized)
|
||||
{
|
||||
// Select one of the sdhci-caps-mask definitions
|
||||
// depending on whether we also want to disable DMA
|
||||
if (SDMA == 0)
|
||||
{
|
||||
return (^DSD2)
|
||||
}
|
||||
else
|
||||
{
|
||||
return (^DSD1)
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// A child device that represents the
|
||||
// sd card, which is marked as non-removable.
|
||||
//
|
||||
Device (SDMM)
|
||||
{
|
||||
Method (_ADR)
|
||||
{
|
||||
Return (0)
|
||||
}
|
||||
Method (_RMV) // Is removable
|
||||
{
|
||||
Return (0) // 0 - fixed
|
||||
}
|
||||
}
|
||||
} //SDC3
|
||||
} //GDV1
|
372
board/raspberrypi/rpi/gpudevs.asl
Normal file
372
board/raspberrypi/rpi/gpudevs.asl
Normal file
|
@ -0,0 +1,372 @@
|
|||
/** @file
|
||||
*
|
||||
* [DSDT] Devices behind the GPU.
|
||||
*
|
||||
* Copyright (c) 2018-2020, Andrey Warkentin <andrey.warkentin@gmail.com>
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
*
|
||||
**/
|
||||
|
||||
// DWC OTG Controller
|
||||
Device (USB0)
|
||||
{
|
||||
Name (_HID, "BCM2848")
|
||||
#if defined(CONFIG_TARGET_RPI_3)
|
||||
Name (_CID, "DWC_OTG")
|
||||
#elif defined(CONFIG_TARGET_RPI_4)
|
||||
Name (_CID, "BCM2848")
|
||||
#endif
|
||||
Name (_UID, 0x0)
|
||||
Name (_CCA, 0x0)
|
||||
Method (_STA)
|
||||
{
|
||||
Return (0xf)
|
||||
}
|
||||
Name (RBUF, ResourceTemplate ()
|
||||
{
|
||||
MEMORY32FIXED (ReadWrite, 0, BCM2836_USB_LENGTH, RMEM)
|
||||
Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { BCM2836_USB_INTERRUPT }
|
||||
})
|
||||
Method (_CRS, 0x0, Serialized)
|
||||
{
|
||||
MEMORY32SETBASE (RBUF, RMEM, RBAS, BCM2836_USB_OFFSET)
|
||||
Return (^RBUF)
|
||||
}
|
||||
}
|
||||
|
||||
// Video Core 4 GPU
|
||||
Device (GPU0)
|
||||
{
|
||||
Name (_HID, "BCM2850")
|
||||
Name (_CID, "BCM2850")
|
||||
Name (_UID, 0x0)
|
||||
Name (_CCA, 0x0)
|
||||
Method (_STA)
|
||||
{
|
||||
Return (0xf)
|
||||
}
|
||||
Name (RBUF, ResourceTemplate ()
|
||||
{
|
||||
// Memory and interrupt for the GPU
|
||||
MEMORY32FIXED (ReadWrite, 0, BCM2836_V3D_BUS_LENGTH, RM01)
|
||||
Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { BCM2836_V3D_BUS_INTERRUPT }
|
||||
|
||||
// HVS - Hardware Video Scalar
|
||||
MEMORY32FIXED (ReadWrite, 0, BCM2836_HVS_LENGTH, RM02)
|
||||
// The HVS interrupt is reserved by the VPU
|
||||
// Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { BCM2836_HVS_INTERRUPT }
|
||||
|
||||
// PixelValve0 - DSI0 or DPI
|
||||
// MEMORY32FIXED (ReadWrite, BCM2836_PV0_BASE_ADDRESS, BCM2836_PV0_LENGTH, RM03)
|
||||
// Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { BCM2836_PV0_INTERRUPT }
|
||||
|
||||
// PixelValve1 - DS1 or SMI
|
||||
// MEMORY32FIXED (ReadWrite, BCM2836_PV1_BASE_ADDRESS, BCM2836_PV1_LENGTH, RM04)
|
||||
// Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { BCM2836_PV1_INTERRUPT }
|
||||
|
||||
// PixelValve2 - HDMI output - connected to HVS display FIFO 1
|
||||
MEMORY32FIXED (ReadWrite, 0, BCM2836_PV2_LENGTH, RM05)
|
||||
Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { BCM2836_PV2_INTERRUPT }
|
||||
|
||||
// HDMI registers
|
||||
MEMORY32FIXED (ReadWrite, 0, BCM2836_HDMI0_LENGTH, RM06)
|
||||
MEMORY32FIXED (ReadWrite, 0, BCM2836_HDMI1_LENGTH, RM07)
|
||||
// hdmi_int[0]
|
||||
// Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { BCM2836_HDMI0_INTERRUPT }
|
||||
// hdmi_int[1]
|
||||
// Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { BCM2836_HDMI1_INTERRUPT }
|
||||
|
||||
// HDMI DDC connection
|
||||
I2CSerialBus (0x50,, 100000,, "\\_SB.GDV0.I2C2",,,,) // EDID
|
||||
I2CSerialBus (0x30,, 100000,, "\\_SB.GDV0.I2C2",,,,) // E-DDC Segment Pointer
|
||||
})
|
||||
Method (_CRS, 0x0, Serialized)
|
||||
{
|
||||
MEMORY32SETBASE (RBUF, RM01, RB01, BCM2836_V3D_BUS_OFFSET)
|
||||
MEMORY32SETBASE (RBUF, RM02, RB02, BCM2836_HVS_OFFSET)
|
||||
MEMORY32SETBASE (RBUF, RM05, RB05, BCM2836_PV2_OFFSET)
|
||||
MEMORY32SETBASE (RBUF, RM06, RB06, BCM2836_HDMI0_OFFSET)
|
||||
MEMORY32SETBASE (RBUF, RM07, RB07, BCM2836_HDMI1_OFFSET)
|
||||
Return (^RBUF)
|
||||
}
|
||||
|
||||
// GPU Power Management Component Data
|
||||
// Reference : https://github.com/Microsoft/graphics-driver-samples/wiki/Install-Driver-in-a-Windows-VM
|
||||
Method (PMCD, 0, Serialized)
|
||||
{
|
||||
Name (RBUF, Package ()
|
||||
{
|
||||
1, // Version
|
||||
1, // Number of graphics power components
|
||||
Package () // Power components package
|
||||
{
|
||||
Package () // GPU component package
|
||||
{
|
||||
0, // Component Index
|
||||
0, // DXGK_POWER_COMPONENT_MAPPING.ComponentType (0 = DXGK_POWER_COMPONENT_ENGINE)
|
||||
0, // DXGK_POWER_COMPONENT_MAPPING.NodeIndex
|
||||
|
||||
Buffer () // DXGK_POWER_RUNTIME_COMPONENT.ComponentGuid
|
||||
{ // 9B2D1E26-1575-4747-8FC0-B9EB4BAA2D2B
|
||||
0x26, 0x1E, 0x2D, 0x9B, 0x75, 0x15, 0x47, 0x47,
|
||||
0x8f, 0xc0, 0xb9, 0xeb, 0x4b, 0xaa, 0x2d, 0x2b
|
||||
},
|
||||
|
||||
"VC4_Engine_00",// DXGK_POWER_RUNTIME_COMPONENT.ComponentName
|
||||
2, // DXGK_POWER_RUNTIME_COMPONENT.StateCount
|
||||
|
||||
Package () // DXGK_POWER_RUNTIME_COMPONENT.States[] package
|
||||
{
|
||||
Package () // F0
|
||||
{
|
||||
0, // DXGK_POWER_RUNTIME_STATE.TransitionLatency
|
||||
0, // DXGK_POWER_RUNTIME_STATE.ResidencyRequirement
|
||||
1210000, // DXGK_POWER_RUNTIME_STATE.NominalPower (microwatt)
|
||||
},
|
||||
|
||||
Package () // F1 - Placeholder
|
||||
{
|
||||
10000, // DXGK_POWER_RUNTIME_STATE.TransitionLatency
|
||||
10000, // DXGK_POWER_RUNTIME_STATE.ResidencyRequirement
|
||||
4, // DXGK_POWER_RUNTIME_STATE.NominalPower
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
Return (RBUF)
|
||||
}
|
||||
}
|
||||
|
||||
// PiQ Mailbox Driver
|
||||
Device (RPIQ)
|
||||
{
|
||||
Name (_HID, "BCM2849")
|
||||
Name (_CID, "BCM2849")
|
||||
Name (_UID, 0)
|
||||
Name (_CCA, 0x0)
|
||||
|
||||
Name (RBUF, ResourceTemplate ()
|
||||
{
|
||||
MEMORY32FIXED (ReadWrite, 0, BCM2836_MBOX_LENGTH, RMEM)
|
||||
Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { BCM2836_MBOX_INTERRUPT }
|
||||
})
|
||||
|
||||
Method (_CRS, 0x0, Serialized)
|
||||
{
|
||||
MEMORY32SETBASE (RBUF, RMEM, RBAS, BCM2836_MBOX_OFFSET)
|
||||
Return (^RBUF)
|
||||
}
|
||||
}
|
||||
|
||||
// VCHIQ Driver
|
||||
Device (VCIQ)
|
||||
{
|
||||
Name (_HID, "BCM2835")
|
||||
Name (_CID, "BCM2835")
|
||||
Name (_UID, 0)
|
||||
Name (_CCA, 0x0)
|
||||
Name (_DEP, Package() { \_SB.GDV0.RPIQ })
|
||||
Method (_STA)
|
||||
{
|
||||
Return (0xf)
|
||||
}
|
||||
Name (RBUF, ResourceTemplate ()
|
||||
{
|
||||
MEMORY32FIXED (ReadWrite, 0, BCM2836_VCHIQ_LENGTH, RMEM)
|
||||
Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { BCM2836_VCHIQ_INTERRUPT }
|
||||
})
|
||||
|
||||
Method (_CRS, 0x0, Serialized)
|
||||
{
|
||||
MEMORY32SETBASE (RBUF, RMEM, RBAS, BCM2836_VCHIQ_OFFSET)
|
||||
Return (^RBUF)
|
||||
}
|
||||
}
|
||||
|
||||
// VC Shared Memory Driver
|
||||
Device (VCSM)
|
||||
{
|
||||
Name (_HID, "BCM2856")
|
||||
Name (_CID, "BCM2856")
|
||||
Name (_UID, 0)
|
||||
Name (_CCA, 0x0)
|
||||
Name (_DEP, Package() { \_SB.GDV0.VCIQ })
|
||||
Method (_STA)
|
||||
{
|
||||
Return (0xf)
|
||||
}
|
||||
}
|
||||
|
||||
// Description: GPIO
|
||||
Device (GPI0)
|
||||
{
|
||||
Name (_HID, "BCM2845")
|
||||
Name (_CID, "BCM2845")
|
||||
Name (_UID, 0x0)
|
||||
Name (_CCA, 0x0)
|
||||
|
||||
Name (RBUF, ResourceTemplate ()
|
||||
{
|
||||
MEMORY32FIXED (ReadWrite, 0, GPIO_LENGTH, RMEM)
|
||||
Interrupt (ResourceConsumer, Level, ActiveHigh, Shared)
|
||||
{
|
||||
BCM2386_GPIO_INTERRUPT0, BCM2386_GPIO_INTERRUPT1,
|
||||
BCM2386_GPIO_INTERRUPT2, BCM2386_GPIO_INTERRUPT3
|
||||
}
|
||||
})
|
||||
Method (_CRS, 0x0, Serialized)
|
||||
{
|
||||
MEMORY32SETBASE (RBUF, RMEM, RBAS, GPIO_OFFSET)
|
||||
Return (^RBUF)
|
||||
}
|
||||
}
|
||||
|
||||
// Description: I2C
|
||||
Device (I2C1)
|
||||
{
|
||||
Name (_HID, "BCM2841")
|
||||
Name (_CID, "BCM2841")
|
||||
Name (_UID, 0x1)
|
||||
Name (_CCA, 0x0)
|
||||
|
||||
Name (RBUF, ResourceTemplate ()
|
||||
{
|
||||
MEMORY32FIXED (ReadWrite, 0, BCM2836_I2C1_LENGTH, RMEM)
|
||||
Interrupt (ResourceConsumer, Level, ActiveHigh, Shared) { BCM2836_I2C1_INTERRUPT }
|
||||
PinFunction (Exclusive, PullUp, BCM_ALT0, "\\_SB.GDV0.GPI0", 0, ResourceConsumer, , ) { 2, 3 }
|
||||
})
|
||||
Method (_CRS, 0x0, Serialized)
|
||||
{
|
||||
MEMORY32SETBASE (RBUF, RMEM, RBAS, BCM2836_I2C1_OFFSET)
|
||||
Return (^RBUF)
|
||||
}
|
||||
}
|
||||
|
||||
// I2C2 is the HDMI DDC connection
|
||||
Device (I2C2)
|
||||
{
|
||||
Name (_HID, "BCM2841")
|
||||
Name (_CID, "BCM2841")
|
||||
Name (_UID, 0x2)
|
||||
Name (_CCA, 0x0)
|
||||
|
||||
Name (RBUF, ResourceTemplate()
|
||||
{
|
||||
MEMORY32FIXED (ReadWrite, 0, BCM2836_I2C2_LENGTH, RMEM)
|
||||
Interrupt (ResourceConsumer, Level, ActiveHigh, Shared) { BCM2836_I2C2_INTERRUPT }
|
||||
})
|
||||
|
||||
Method (_CRS, 0x0, Serialized)
|
||||
{
|
||||
MEMORY32SETBASE (RBUF, RMEM, RBAS, BCM2836_I2C2_OFFSET)
|
||||
Return (^RBUF)
|
||||
}
|
||||
}
|
||||
|
||||
// SPI
|
||||
Device (SPI0)
|
||||
{
|
||||
Name (_HID, "BCM2838")
|
||||
Name (_CID, "BCM2838")
|
||||
Name (_UID, 0x0)
|
||||
Name (_CCA, 0x0)
|
||||
|
||||
Name (RBUF, ResourceTemplate ()
|
||||
{
|
||||
MEMORY32FIXED (ReadWrite, 0, BCM2836_SPI0_LENGTH, RMEM)
|
||||
Interrupt (ResourceConsumer, Level, ActiveHigh, Shared) { BCM2836_SPI0_INTERRUPT }
|
||||
PinFunction (Exclusive, PullDown, BCM_ALT0, "\\_SB.GDV0.GPI0", 0, ResourceConsumer, , ) { 9, 10, 11 } // MISO, MOSI, SCLK
|
||||
PinFunction (Exclusive, PullUp, BCM_ALT0, "\\_SB.GDV0.GPI0", 0, ResourceConsumer, , ) { 8 } // CE0
|
||||
PinFunction (Exclusive, PullUp, BCM_ALT0, "\\_SB.GDV0.GPI0", 0, ResourceConsumer, , ) { 7 } // CE1
|
||||
})
|
||||
|
||||
Method (_CRS, 0x0, Serialized)
|
||||
{
|
||||
MEMORY32SETBASE (RBUF, RMEM, RBAS, BCM2836_SPI0_OFFSET)
|
||||
Return (^RBUF)
|
||||
}
|
||||
}
|
||||
|
||||
Device (SPI1)
|
||||
{
|
||||
Name (_HID, "BCM2839")
|
||||
Name (_CID, "BCM2839")
|
||||
Name (_UID, 0x1)
|
||||
Name (_CCA, 0x0)
|
||||
Name (_DEP, Package() { \_SB.GDV0.RPIQ })
|
||||
|
||||
Name (RBUF, ResourceTemplate ()
|
||||
{
|
||||
MEMORY32FIXED (ReadWrite, 0, BCM2836_SPI1_LENGTH, RMEM)
|
||||
Interrupt (ResourceConsumer, Level, ActiveHigh, Shared,) { BCM2836_SPI1_INTERRUPT }
|
||||
PinFunction (Exclusive, PullDown, BCM_ALT4, "\\_SB.GDV0.GPI0", 0, ResourceConsumer, , ) { 19, 20, 21 } // MISO, MOSI, SCLK
|
||||
PinFunction (Exclusive, PullDown, BCM_ALT4, "\\_SB.GDV0.GPI0", 0, ResourceConsumer, , ) { 16 } // CE2
|
||||
})
|
||||
|
||||
Method (_CRS, 0x0, Serialized)
|
||||
{
|
||||
MEMORY32SETBASE (RBUF, RMEM, RBAS, BCM2836_SPI1_OFFSET)
|
||||
Return (^RBUF)
|
||||
}
|
||||
}
|
||||
|
||||
// SPI2 has no pins on GPIO header
|
||||
// Device (SPI2)
|
||||
// {
|
||||
// Name (_HID, "BCM2839")
|
||||
// Name (_CID, "BCM2839")
|
||||
// Name (_UID, 0x2)
|
||||
// Name (_CCA, 0x0)
|
||||
// Name (_DEP, Package() { \_SB.GDV0.RPIQ })
|
||||
// Method (_STA)
|
||||
// {
|
||||
// Return (0xf) // Disabled
|
||||
// }
|
||||
// Method (_CRS, 0x0, Serialized)
|
||||
// {
|
||||
// Name (RBUF, ResourceTemplate ()
|
||||
// {
|
||||
// MEMORY32FIXED (ReadWrite, BCM2836_SPI2_BASE_ADDRESS, BCM2836_SPI2_LENGTH, RMEM)
|
||||
// Interrupt (ResourceConsumer, Level, ActiveHigh, Shared,) { BCM2836_SPI2_INTERRUPT }
|
||||
// })
|
||||
// Return (RBUF)
|
||||
// }
|
||||
// }
|
||||
|
||||
// PWM Driver
|
||||
Device (PWM0)
|
||||
{
|
||||
Name (_HID, "BCM2844")
|
||||
Name (_CID, "BCM2844")
|
||||
Name (_UID, 0)
|
||||
Name (_CCA, 0x0)
|
||||
|
||||
Name (RBUF, ResourceTemplate ()
|
||||
{
|
||||
// DMA channel 11 control
|
||||
MEMORY32FIXED (ReadWrite, 0, BCM2836_PWM_DMA_LENGTH, RM01)
|
||||
// PWM control
|
||||
MEMORY32FIXED (ReadWrite, 0, BCM2836_PWM_CTRL_LENGTH, RM02)
|
||||
// PWM control bus
|
||||
MEMORY32FIXED (ReadWrite, BCM2836_PWM_BUS_BASE_ADDRESS, BCM2836_PWM_BUS_LENGTH, )
|
||||
// PWM control uncached
|
||||
MEMORY32FIXED (ReadWrite, BCM2836_PWM_CTRL_UNCACHED_BASE_ADDRESS, BCM2836_PWM_CTRL_UNCACHED_LENGTH, )
|
||||
// PWM clock control
|
||||
MEMORY32FIXED (ReadWrite, 0, BCM2836_PWM_CLK_LENGTH, RM03)
|
||||
// Interrupt DMA channel 11
|
||||
Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { BCM2836_DMA_INTERRUPT }
|
||||
// DMA channel 11, DREQ 5 for PWM
|
||||
FixedDMA (5, 11, Width32Bit, )
|
||||
})
|
||||
|
||||
Method (_CRS, 0x0, Serialized)
|
||||
{
|
||||
MEMORY32SETBASE (RBUF, RM01, RB01, BCM2836_PWM_DMA_OFFSET)
|
||||
MEMORY32SETBASE (RBUF, RM02, RB02, BCM2836_PWM_CTRL_OFFSET)
|
||||
MEMORY32SETBASE (RBUF, RM03, RB03, BCM2836_PWM_CLK_OFFSET)
|
||||
Return (^RBUF)
|
||||
}
|
||||
}
|
177
board/raspberrypi/rpi/pci.asl
Normal file
177
board/raspberrypi/rpi/pci.asl
Normal file
|
@ -0,0 +1,177 @@
|
|||
/** @file
|
||||
*
|
||||
* Copyright (c) 2019 Linaro, Limited. All rights reserved.
|
||||
* Copyright (c) 2021 Arm
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
*
|
||||
**/
|
||||
|
||||
Device(PCI0)
|
||||
{
|
||||
Name(_HID, EISAID("PNP0A08")) // PCI Express Root Bridge
|
||||
Name(_CID, EISAID("PNP0A03")) // Compatible PCI Root Bridge
|
||||
Name(_SEG, Zero) // PCI Segment Group number
|
||||
Name(_BBN, Zero) // PCI Base Bus Number
|
||||
Name(_CCA, 0) // Mark the PCI noncoherent
|
||||
|
||||
// PCIe can only DMA to first 3GB with early SOC's
|
||||
// But we keep the restriction on the later ones
|
||||
// To avoid DMA translation problems.
|
||||
Name (_DMA, ResourceTemplate() {
|
||||
QWordMemory (ResourceProducer,
|
||||
,
|
||||
MinFixed,
|
||||
MaxFixed,
|
||||
NonCacheable,
|
||||
ReadWrite,
|
||||
0x0,
|
||||
0x0, // MIN
|
||||
0xbfffffff, // MAX
|
||||
0x0, // TRA
|
||||
0xc0000000, // LEN
|
||||
,
|
||||
,
|
||||
)
|
||||
})
|
||||
|
||||
// PCI Routing Table
|
||||
Name(_PRT, Package() {
|
||||
Package (4) { 0x0000FFFF, 0, zero, 175 },
|
||||
Package (4) { 0x0000FFFF, 1, zero, 176 },
|
||||
Package (4) { 0x0000FFFF, 2, zero, 177 },
|
||||
Package (4) { 0x0000FFFF, 3, zero, 178 }
|
||||
})
|
||||
|
||||
Name (_DSD, Package () {
|
||||
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
|
||||
Package () {
|
||||
Package () { "linux-ecam-quirk-id", "bcm2711" },
|
||||
}
|
||||
})
|
||||
|
||||
// Root complex resources
|
||||
Method (_CRS, 0, Serialized) {
|
||||
Name (RBUF, ResourceTemplate () {
|
||||
|
||||
// bus numbers assigned to this root
|
||||
WordBusNumber (
|
||||
ResourceProducer,
|
||||
MinFixed, MaxFixed, PosDecode,
|
||||
0, // AddressGranularity
|
||||
0, // AddressMinimum - Minimum Bus Number
|
||||
255, // AddressMaximum - Maximum Bus Number
|
||||
0, // AddressTranslation - Set to 0
|
||||
256 // RangeLength - Number of Busses
|
||||
)
|
||||
|
||||
// 32-bit mmio window in 64-bit addr
|
||||
QWordMemory (
|
||||
ResourceProducer, PosDecode,
|
||||
MinFixed, MaxFixed,
|
||||
NonCacheable, ReadWrite, // cacheable
|
||||
0x00000000, // Granularity
|
||||
0, // PCIE_PCI_MMIO_BEGIN
|
||||
1, // PCIE_MMIO_LEN + PCIE_PCI_MMIO_BEGIN
|
||||
PCIE_CPU_MMIO_WINDOW, // PCIE_PCI_MMIO_BEGIN - PCIE_CPU_MMIO_WINDOW
|
||||
2 // PCIE_MMIO_LEN + 1
|
||||
,,,MMI1
|
||||
)
|
||||
|
||||
// root port registers, not to be used if SMCCC is utilized
|
||||
QWordMemory (
|
||||
ResourceConsumer, ,
|
||||
MinFixed, MaxFixed,
|
||||
NonCacheable, ReadWrite, // cacheable
|
||||
0x00000000, // Granularity
|
||||
0xFD500000, // Root port begin
|
||||
0xFD509FFF, // Root port end
|
||||
0x00000000, // no translation
|
||||
0x0000A000, // size
|
||||
,,
|
||||
)
|
||||
}) // end Name(RBUF)
|
||||
|
||||
// Work around ASL's inability to add in a resource definition
|
||||
// or for that matter compute the min,max,len properly
|
||||
CreateQwordField (RBUF, MMI1._MIN, MMIB)
|
||||
CreateQwordField (RBUF, MMI1._MAX, MMIE)
|
||||
CreateQwordField (RBUF, MMI1._TRA, MMIT)
|
||||
CreateQwordField (RBUF, MMI1._LEN, MMIL)
|
||||
Add (MMIB, PCIE_TOP_OF_MEM_WIN, MMIB)
|
||||
Add (PCIE_BRIDGE_MMIO_LEN, PCIE_TOP_OF_MEM_WIN, MMIE)
|
||||
Subtract (MMIT, PCIE_TOP_OF_MEM_WIN, MMIT)
|
||||
Add (PCIE_BRIDGE_MMIO_LEN, 1 , MMIL)
|
||||
|
||||
Return (RBUF)
|
||||
} // end Method(_CRS)
|
||||
|
||||
// OS Control Handoff
|
||||
Name(SUPP, Zero) // PCI _OSC Support Field value
|
||||
Name(CTRL, Zero) // PCI _OSC Control Field value
|
||||
|
||||
// See [1] 6.2.10, [2] 4.5
|
||||
Method(_OSC,4) {
|
||||
// Note, This code is very similar to the code in the PCIe firmware
|
||||
// specification which can be used as a reference
|
||||
// Check for proper UUID
|
||||
If(LEqual(Arg0,ToUUID("33DB4D5B-1FF7-401C-9657-7441C03DD766"))) {
|
||||
// Create DWord-adressable fields from the Capabilities Buffer
|
||||
CreateDWordField(Arg3,0,CDW1)
|
||||
CreateDWordField(Arg3,4,CDW2)
|
||||
CreateDWordField(Arg3,8,CDW3)
|
||||
// Save Capabilities DWord2 & 3
|
||||
Store(CDW2,SUPP)
|
||||
Store(CDW3,CTRL)
|
||||
// Mask out Native HotPlug
|
||||
And(CTRL,0x1E,CTRL)
|
||||
// Always allow native PME, AER (no dependencies)
|
||||
// Never allow SHPC (no SHPC controller in this system)
|
||||
And(CTRL,0x1D,CTRL)
|
||||
|
||||
If(LNotEqual(Arg1,One)) { // Unknown revision
|
||||
Or(CDW1,0x08,CDW1)
|
||||
}
|
||||
|
||||
If(LNotEqual(CDW3,CTRL)) { // Capabilities bits were masked
|
||||
Or(CDW1,0x10,CDW1)
|
||||
}
|
||||
// Update DWORD3 in the buffer
|
||||
Store(CTRL,CDW3)
|
||||
Return(Arg3)
|
||||
} Else {
|
||||
Or(CDW1,4,CDW1) // Unrecognized UUID
|
||||
Return(Arg3)
|
||||
}
|
||||
} // End _OSC
|
||||
|
||||
Device (XHC0)
|
||||
{
|
||||
Name (_ADR, 0x00010000)
|
||||
Name (_CID, "PNP0D10")
|
||||
Name (_UID, 0x0) // _UID: Unique ID
|
||||
Name (_CCA, 0x0) // _CCA: Cache Coherency Attribute
|
||||
|
||||
/*
|
||||
* Microsoft's USB Device-Specific Methods. See:
|
||||
* https://docs.microsoft.com/en-us/windows-hardware/drivers/bringup/usb-device-specific-method---dsm-
|
||||
*/
|
||||
Name (DSMU, ToUUID ("ce2ee385-00e6-48cb-9f05-2edb927c4899"))
|
||||
|
||||
Method (_DSM, 4, Serialized) {
|
||||
If (LEqual (Arg0, DSMU)) { // USB capabilities UUID
|
||||
Switch (ToInteger (Arg2)) {
|
||||
Case (0) { // Function 0: List of supported functions
|
||||
Return (Buffer () { 0x41 }) // 0x41 - Functions 0 and 6 supported
|
||||
}
|
||||
Case (6) { // Function 6: RegisterAccessType
|
||||
Return (Buffer () { 0x01 }) // 0x01 - Must use 32bit register access
|
||||
}
|
||||
Default { } // Unsupported
|
||||
}
|
||||
}
|
||||
return (Buffer () { 0x00 }) // Return 0x00 for anything unsupported
|
||||
}
|
||||
} // end XHC0
|
||||
|
||||
} // PCI0
|
90
board/raspberrypi/rpi/pep.asl
Normal file
90
board/raspberrypi/rpi/pep.asl
Normal file
|
@ -0,0 +1,90 @@
|
|||
/** @file
|
||||
*
|
||||
* Platform Extension Plugin (PEP).
|
||||
*
|
||||
* Copyright (c) 2019, ARM Ltd. All rights reserved.
|
||||
* Copyright (c) 2018, Andrey Warkentin <andrey.warkentin@gmail.com>
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
*
|
||||
**/
|
||||
|
||||
Device(PEPD)
|
||||
{
|
||||
//
|
||||
// PEP virtual device.
|
||||
//
|
||||
Name (_HID, "BCM2854") // Note: Since PEP on RPi is a virtual device,
|
||||
Name (_CID, "BCM2854") // its device id needs to be generated by Microsoft
|
||||
Name (_UID, 0x0)
|
||||
Name (_CRS, ResourceTemplate ()
|
||||
{
|
||||
// No hardware resources for PEP driver are needed.
|
||||
})
|
||||
|
||||
//
|
||||
// Processor info. PEP proprietary method to return
|
||||
// PEP_PROCESSOR_TABLE_PLAT structure.
|
||||
//
|
||||
// See Pep.h and Pep.c.
|
||||
//
|
||||
Name (_GPI, Buffer()
|
||||
{
|
||||
0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x5C, 0x00, 0x5F, 0x00, 0x53,
|
||||
0x00, 0x42, 0x00, 0x2E, 0x00, 0x43, 0x00, 0x50, 0x00, 0x55, 0x00, 0x30,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
})
|
||||
|
||||
//
|
||||
// Coordinated state info. PEP proprietary method to return
|
||||
// PEP_COORDINATED_STATE_TABLE_PLAT structure.
|
||||
//
|
||||
// See Pep.h and Pep.c.
|
||||
//
|
||||
Name (_GCI, Buffer()
|
||||
{
|
||||
0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
|
||||
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00
|
||||
})
|
||||
|
||||
//
|
||||
// Device info. PEP proprietary method to return
|
||||
// PEP_DEVICE_TABLE_PLAT structure.
|
||||
//
|
||||
// See Pep.h and Pep.c.
|
||||
//
|
||||
Name (_GDI, Buffer()
|
||||
{
|
||||
0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x5C, 0x00, 0x5F, 0x00, 0x53,
|
||||
0x00, 0x42, 0x00, 0x2E, 0x00, 0x49, 0x00, 0x32, 0x00, 0x43, 0x00, 0x30,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09,
|
||||
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
})
|
||||
}
|
195
board/raspberrypi/rpi/rhpx.asl
Normal file
195
board/raspberrypi/rpi/rhpx.asl
Normal file
|
@ -0,0 +1,195 @@
|
|||
/** @file
|
||||
*
|
||||
* [DSDT] RHProxy device to enable WinRT API (RHPX)
|
||||
*
|
||||
* Copyright (c) 2018, Andrey Warkentin <andrey.warkentin@gmail.com>
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
*
|
||||
**/
|
||||
|
||||
Device (RHPX)
|
||||
{
|
||||
Name (_HID, "MSFT8000")
|
||||
Name (_CID, "MSFT8000")
|
||||
Name (_UID, 1)
|
||||
|
||||
Name(_CRS, ResourceTemplate ()
|
||||
{
|
||||
// Index 0
|
||||
SPISerialBus ( // SCKL - GPIO 11 - Pin 23
|
||||
// MOSI - GPIO 10 - Pin 19
|
||||
// MISO - GPIO 9 - Pin 21
|
||||
// CE0 - GPIO 8 - Pin 24
|
||||
0, // Device selection (CE0)
|
||||
PolarityLow, // Device selection polarity
|
||||
FourWireMode, // WireMode
|
||||
8, // DataBit len
|
||||
ControllerInitiated, // Slave mode
|
||||
4000000, // Connection speed
|
||||
ClockPolarityLow, // Clock polarity
|
||||
ClockPhaseFirst, // Clock phase
|
||||
"\\_SB.GDV0.SPI0", // ResourceSource: SPI bus controller name
|
||||
0, // ResourceSourceIndex
|
||||
// Resource usage
|
||||
// DescriptorName: creates name for offset of resource descriptor
|
||||
) // Vendor Data
|
||||
|
||||
// Index 1
|
||||
SPISerialBus ( // SCKL - GPIO 11 - Pin 23
|
||||
// MOSI - GPIO 10 - Pin 19
|
||||
// MISO - GPIO 9 - Pin 21
|
||||
// CE1 - GPIO 7 - Pin 26
|
||||
1, // Device selection (CE1)
|
||||
PolarityLow, // Device selection polarity
|
||||
FourWireMode, // WireMode
|
||||
8, // DataBit len
|
||||
ControllerInitiated, // Slave mode
|
||||
4000000, // Connection speed
|
||||
ClockPolarityLow, // Clock polarity
|
||||
ClockPhaseFirst, // Clock phase
|
||||
"\\_SB.GDV0.SPI0", // ResourceSource: SPI bus controller name
|
||||
0, // ResourceSourceIndex
|
||||
// Resource usage
|
||||
// DescriptorName: creates name for offset of resource descriptor
|
||||
) // Vendor Data
|
||||
|
||||
// Index 2
|
||||
I2CSerialBus ( // Pin 3 (GPIO2, SDA1), 5 (GPIO3, SCL1)
|
||||
0xFFFF, // SlaveAddress: placeholder
|
||||
, // SlaveMode: default to ControllerInitiated
|
||||
0, // ConnectionSpeed: placeholder
|
||||
, // Addressing Mode: default to 7 bit
|
||||
"\\_SB.GDV0.I2C1", // ResourceSource: I2C bus controller name
|
||||
,
|
||||
,
|
||||
, // Descriptor Name: creates name for offset of resource descriptor
|
||||
) // Vendor Data
|
||||
|
||||
// Index 3
|
||||
SPISerialBus ( // SPI1_SCLK - GPIO21
|
||||
// SPI1_MOSI - GPIO20
|
||||
// SPI1_MISO - GPIO19
|
||||
// SPI1_CE2_N - GPIO16
|
||||
2, // Device selection (CE2)
|
||||
PolarityLow, // Device selection polarity
|
||||
FourWireMode, // WireMode
|
||||
8, // DataBit len
|
||||
ControllerInitiated, // Slave mode
|
||||
4000000, // Connection speed
|
||||
ClockPolarityLow, // Clock polarity
|
||||
ClockPhaseFirst, // Clock phase
|
||||
"\\_SB.GDV0.SPI1", // ResourceSource: SPI bus controller name
|
||||
0, // ResourceSourceIndex
|
||||
// Resource usage
|
||||
// DescriptorName: creates name for offset of resource descriptor
|
||||
) // Vendor Data
|
||||
|
||||
// GPIO 2
|
||||
GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GDV0.GPI0", 0, ResourceConsumer,,) { 2 }
|
||||
GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GDV0.GPI0",) { 2 }
|
||||
// GPIO 3
|
||||
GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GDV0.GPI0", 0, ResourceConsumer,,) { 3 }
|
||||
GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GDV0.GPI0",) { 3 }
|
||||
// GPIO 4
|
||||
GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GDV0.GPI0", 0, ResourceConsumer,,) { 4 }
|
||||
GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GDV0.GPI0",) { 4 }
|
||||
// GPIO 5
|
||||
GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GDV0.GPI0", 0, ResourceConsumer,,) { 5 }
|
||||
GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GDV0.GPI0",) { 5 }
|
||||
// GPIO 6
|
||||
GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GDV0.GPI0", 0, ResourceConsumer,,) { 6 }
|
||||
GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GDV0.GPI0",) { 6 }
|
||||
// GPIO 7
|
||||
GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GDV0.GPI0", 0, ResourceConsumer,,) { 7 }
|
||||
GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GDV0.GPI0",) { 7 }
|
||||
// GPIO 8
|
||||
GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GDV0.GPI0", 0, ResourceConsumer,,) { 8 }
|
||||
GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GDV0.GPI0",) { 8 }
|
||||
// GPIO 9
|
||||
GpioIO (Shared, PullDown, 0, 0, IoRestrictionNone, "\\_SB.GDV0.GPI0", 0, ResourceConsumer,,) { 9 }
|
||||
GpioInt (Edge, ActiveBoth, Shared, PullDown, 0, "\\_SB.GDV0.GPI0",) { 9 }
|
||||
// GPIO 10
|
||||
GpioIO (Shared, PullDown, 0, 0, IoRestrictionNone, "\\_SB.GDV0.GPI0", 0, ResourceConsumer,,) { 10 }
|
||||
GpioInt (Edge, ActiveBoth, Shared, PullDown, 0, "\\_SB.GDV0.GPI0",) { 10 }
|
||||
// GPIO 11
|
||||
GpioIO (Shared, PullDown, 0, 0, IoRestrictionNone, "\\_SB.GDV0.GPI0", 0, ResourceConsumer,,) { 11 }
|
||||
GpioInt (Edge, ActiveBoth, Shared, PullDown, 0, "\\_SB.GDV0.GPI0",) { 11 }
|
||||
// GPIO 12
|
||||
GpioIO (Shared, PullDown, 0, 0, IoRestrictionNone, "\\_SB.GDV0.GPI0", 0, ResourceConsumer,,) { 12 }
|
||||
GpioInt (Edge, ActiveBoth, Shared, PullDown, 0, "\\_SB.GDV0.GPI0",) { 12 }
|
||||
// GPIO 13
|
||||
GpioIO (Shared, PullDown, 0, 0, IoRestrictionNone, "\\_SB.GDV0.GPI0", 0, ResourceConsumer,,) { 13 }
|
||||
GpioInt (Edge, ActiveBoth, Shared, PullDown, 0, "\\_SB.GDV0.GPI0",) { 13 }
|
||||
// NTRAID#MSFT-7141401-2016/04/7-jordanrh - disable UART muxing
|
||||
// until a proper solution can be created for the dmap conflict
|
||||
// GPIO 14 - UART TX
|
||||
// GpioIO (Shared, PullDown, 0, 0, IoRestrictionNone, "\\_SB.GDV0.GPI0", 0, ResourceConsumer,,) { 14 }
|
||||
// GpioInt (Edge, ActiveBoth, Shared, PullDown, 0, "\\_SB.GDV0.GPI0",) { 14 }
|
||||
// GPIO 15 - UART RX
|
||||
// GpioIO (Shared, PullDown, 0, 0, IoRestrictionNone, "\\_SB.GDV0.GPI0", 0, ResourceConsumer,,) { 15 }
|
||||
// GpioInt (Edge, ActiveBoth, Shared, PullDown, 0, "\\_SB.GDV0.GPI0",) { 15 }
|
||||
// GPIO 16
|
||||
GpioIO (Shared, PullDown, 0, 0, IoRestrictionNone, "\\_SB.GDV0.GPI0", 0, ResourceConsumer,,) { 16 }
|
||||
GpioInt (Edge, ActiveBoth, Shared, PullDown, 0, "\\_SB.GDV0.GPI0",) { 16 }
|
||||
// GPIO 17
|
||||
GpioIO (Shared, PullDown, 0, 0, IoRestrictionNone, "\\_SB.GDV0.GPI0", 0, ResourceConsumer,,) { 17 }
|
||||
GpioInt (Edge, ActiveBoth, Shared, PullDown, 0, "\\_SB.GDV0.GPI0",) { 17 }
|
||||
// GPIO 18
|
||||
GpioIO (Shared, PullDown, 0, 0, IoRestrictionNone, "\\_SB.GDV0.GPI0", 0, ResourceConsumer,,) { 18 }
|
||||
GpioInt (Edge, ActiveBoth, Shared, PullDown, 0, "\\_SB.GDV0.GPI0",) { 18 }
|
||||
// GPIO 19
|
||||
GpioIO (Shared, PullDown, 0, 0, IoRestrictionNone, "\\_SB.GDV0.GPI0", 0, ResourceConsumer,,) { 19 }
|
||||
GpioInt (Edge, ActiveBoth, Shared, PullDown, 0, "\\_SB.GDV0.GPI0",) { 19 }
|
||||
// GPIO 20
|
||||
GpioIO (Shared, PullDown, 0, 0, IoRestrictionNone, "\\_SB.GDV0.GPI0", 0, ResourceConsumer,,) { 20 }
|
||||
GpioInt (Edge, ActiveBoth, Shared, PullDown, 0, "\\_SB.GDV0.GPI0",) { 20 }
|
||||
// GPIO 21
|
||||
GpioIO (Shared, PullDown, 0, 0, IoRestrictionNone, "\\_SB.GDV0.GPI0", 0, ResourceConsumer,,) { 21 }
|
||||
GpioInt (Edge, ActiveBoth, Shared, PullDown, 0, "\\_SB.GDV0.GPI0",) { 21 }
|
||||
// GPIO 22
|
||||
GpioIO (Shared, PullDown, 0, 0, IoRestrictionNone, "\\_SB.GDV0.GPI0", 0, ResourceConsumer,,) { 22 }
|
||||
GpioInt (Edge, ActiveBoth, Shared, PullDown, 0, "\\_SB.GDV0.GPI0",) { 22 }
|
||||
// GPIO 23
|
||||
GpioIO (Shared, PullDown, 0, 0, IoRestrictionNone, "\\_SB.GDV0.GPI0", 0, ResourceConsumer,,) { 23 }
|
||||
GpioInt (Edge, ActiveBoth, Shared, PullDown, 0, "\\_SB.GDV0.GPI0",) { 23 }
|
||||
// GPIO 24
|
||||
GpioIO (Shared, PullDown, 0, 0, IoRestrictionNone, "\\_SB.GDV0.GPI0", 0, ResourceConsumer,,) { 24 }
|
||||
GpioInt (Edge, ActiveBoth, Shared, PullDown, 0, "\\_SB.GDV0.GPI0",) { 24 }
|
||||
// GPIO 25
|
||||
GpioIO (Shared, PullDown, 0, 0, IoRestrictionNone, "\\_SB.GDV0.GPI0", 0, ResourceConsumer,,) { 25 }
|
||||
GpioInt (Edge, ActiveBoth, Shared, PullDown, 0, "\\_SB.GDV0.GPI0",) { 25 }
|
||||
// GPIO 26
|
||||
GpioIO (Shared, PullDown, 0, 0, IoRestrictionNone, "\\_SB.GDV0.GPI0", 0, ResourceConsumer,,) { 26 }
|
||||
GpioInt (Edge, ActiveBoth, Shared, PullDown, 0, "\\_SB.GDV0.GPI0",) { 26 }
|
||||
// GPIO 27
|
||||
GpioIO (Shared, PullDown, 0, 0, IoRestrictionNone, "\\_SB.GDV0.GPI0", 0, ResourceConsumer,,) { 27 }
|
||||
GpioInt (Edge, ActiveBoth, Shared, PullDown, 0, "\\_SB.GDV0.GPI0",) { 27 }
|
||||
})
|
||||
|
||||
Name (_DSD, Package()
|
||||
{
|
||||
ToUUID ("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
|
||||
Package ()
|
||||
{
|
||||
// Reference http://www.raspberrypi.org/documentation/hardware/raspberrypi/spi/README.md
|
||||
// SPI 0
|
||||
Package (2) { "bus-SPI-SPI0", Package() { 0, 1 } }, // Index 0 & 1
|
||||
Package (2) { "SPI0-MinClockInHz", 7629 }, // 7629 Hz
|
||||
Package (2) { "SPI0-MaxClockInHz", 125000000 }, // 125 MHz
|
||||
Package (2) { "SPI0-SupportedDataBitLengths", Package() { 8 } }, // Data Bit Length
|
||||
// I2C1
|
||||
Package (2) { "bus-I2C-I2C1", Package() { 2 } },
|
||||
// GPIO Pin Count and supported drive modes
|
||||
Package (2) { "GPIO-PinCount", 54 },
|
||||
Package (2) { "GPIO-UseDescriptorPinNumbers", 1 },
|
||||
Package (2) { "GPIO-SupportedDriveModes", 0xf }, // InputHighImpedance, InputPullUp, InputPullDown, OutputCmos
|
||||
// SPI 1
|
||||
Package (2) { "bus-SPI-SPI1", Package() { 3 }}, // Index 3
|
||||
Package (2) { "SPI1-MinClockInHz", 30511 }, // 30.5 kHz
|
||||
Package (2) { "SPI1-MaxClockInHz", 20000000 }, // 20 MHz
|
||||
Package (2) { "SPI1-SupportedDataBitLengths", Package() { 8 } }, // Data Bit Length
|
||||
}
|
||||
})
|
||||
}
|
|
@ -23,6 +23,11 @@
|
|||
#endif
|
||||
#include <watchdog.h>
|
||||
#include <dm/pinctrl.h>
|
||||
#include <dm/ofnode.h>
|
||||
#include <acpi/acpi_table.h>
|
||||
#include <acpi/acpigen.h>
|
||||
#include <dm/lists.h>
|
||||
#include <tables_csum.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
|
@ -583,3 +588,181 @@ int ft_board_setup(void *blob, struct bd_info *bd)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if CONFIG_IS_ENABLED(GENERATE_ACPI_TABLE)
|
||||
static bool is_rpi4(void)
|
||||
{
|
||||
return of_machine_is_compatible("brcm,bcm2711") ||
|
||||
of_machine_is_compatible("brcm,bcm2712");
|
||||
}
|
||||
|
||||
static bool is_rpi3(void)
|
||||
{
|
||||
return of_machine_is_compatible("brcm,bcm2837");
|
||||
}
|
||||
|
||||
static int acpi_rpi_board_fill_ssdt(struct acpi_ctx *ctx)
|
||||
{
|
||||
int node, ret, uart_in_use, mini_clock_rate;
|
||||
bool enabled;
|
||||
struct udevice *dev;
|
||||
struct {
|
||||
const char *fdt_compatible;
|
||||
const char *acpi_scope;
|
||||
bool on_rpi4;
|
||||
bool on_rpi3;
|
||||
u32 mmio_address;
|
||||
} map[] = {
|
||||
{"brcm,bcm2711-pcie", "\\_SB.PCI0", true, false},
|
||||
{"brcm,bcm2711-emmc2", "\\_SB.GDV1.SDC3", true, false},
|
||||
{"brcm,bcm2835-pwm", "\\_SB.GDV0.PWM0", true, true},
|
||||
{"brcm,bcm2711-genet-v5", "\\_SB.ETH0", true, false},
|
||||
{"brcm,bcm2711-thermal", "\\_SB.EC00", true, true},
|
||||
{"brcm,bcm2835-sdhci", "\\_SB.SDC1", true, true},
|
||||
{"brcm,bcm2835-sdhost", "\\_SB.SDC2", false, true},
|
||||
{"brcm,bcm2835-mbox", "\\_SB.GDV0.RPIQ", true, true},
|
||||
{"brcm,bcm2835-i2c", "\\_SB.GDV0.I2C1", true, true, 0xfe205000},
|
||||
{"brcm,bcm2835-i2c", "\\_SB.GDV0.I2C2", true, true, 0xfe804000},
|
||||
{"brcm,bcm2835-spi", "\\_SB.GDV0.SPI0", true, true},
|
||||
{"brcm,bcm2835-aux-spi", "\\_SB.GDV0.SPI1", true, true, 0xfe215080},
|
||||
{"arm,pl011", "\\_SB.URT0", true, true},
|
||||
{"brcm,bcm2835-aux-uart", "\\_SB.URTM", true, true},
|
||||
{ /* Sentinel */ }
|
||||
};
|
||||
|
||||
/* Device enable */
|
||||
for (int i = 0; map[i].fdt_compatible; i++) {
|
||||
if ((is_rpi4() && !map[i].on_rpi4) ||
|
||||
(is_rpi3() && !map[i].on_rpi3)) {
|
||||
enabled = false;
|
||||
} else {
|
||||
node = fdt_node_offset_by_compatible(gd->fdt_blob, -1,
|
||||
map[i].fdt_compatible);
|
||||
while (node != -FDT_ERR_NOTFOUND && map[i].mmio_address) {
|
||||
struct fdt_resource r;
|
||||
|
||||
ret = fdt_get_resource(gd->fdt_blob, node, "reg", 0, &r);
|
||||
if (ret) {
|
||||
node = -FDT_ERR_NOTFOUND;
|
||||
break;
|
||||
}
|
||||
|
||||
if (r.start == map[i].mmio_address)
|
||||
break;
|
||||
|
||||
node = fdt_node_offset_by_compatible(gd->fdt_blob, node,
|
||||
map[i].fdt_compatible);
|
||||
}
|
||||
|
||||
enabled = (node > 0) ? fdtdec_get_is_enabled(gd->fdt_blob, node) : 0;
|
||||
}
|
||||
acpigen_write_scope(ctx, map[i].acpi_scope);
|
||||
acpigen_write_name_integer(ctx, "_STA", enabled ? 0xf : 0);
|
||||
acpigen_pop_len(ctx);
|
||||
}
|
||||
|
||||
/* GPIO quirks */
|
||||
node = fdt_node_offset_by_compatible(gd->fdt_blob, -1, "brcm,bcm2835-gpio");
|
||||
if (node <= 0)
|
||||
node = fdt_node_offset_by_compatible(gd->fdt_blob, -1, "brcm,bcm2711-gpio");
|
||||
|
||||
acpigen_write_scope(ctx, "\\_SB.GDV0.GPI0");
|
||||
enabled = (node > 0) ? fdtdec_get_is_enabled(gd->fdt_blob, node) : 0;
|
||||
acpigen_write_name_integer(ctx, "_STA", enabled ? 0xf : 0);
|
||||
acpigen_pop_len(ctx);
|
||||
|
||||
if (is_rpi4()) {
|
||||
/* eMMC quirks */
|
||||
node = fdt_node_offset_by_compatible(gd->fdt_blob, -1, "brcm,bcm2711-emmc2");
|
||||
if (node) {
|
||||
phys_addr_t cpu;
|
||||
dma_addr_t bus;
|
||||
u64 size;
|
||||
|
||||
ret = fdt_get_dma_range(gd->fdt_blob, node, &cpu, &bus, &size);
|
||||
|
||||
acpigen_write_scope(ctx, "\\_SB.GDV1");
|
||||
acpigen_write_method_serialized(ctx, "_DMA", 0);
|
||||
acpigen_emit_byte(ctx, RETURN_OP);
|
||||
|
||||
if (!ret && bus != cpu) /* Translated DMA range */
|
||||
acpigen_emit_namestring(ctx, "\\_SB.GDV1.DMTR");
|
||||
else if (!ret && bus == cpu) /* Non translated DMA */
|
||||
acpigen_emit_namestring(ctx, "\\_SB.GDV1.DMNT");
|
||||
else /* Silicon revisions older than C0: Translated DMA range */
|
||||
acpigen_emit_namestring(ctx, "\\_SB.GDV1.DMTR");
|
||||
acpigen_pop_len(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
/* Serial */
|
||||
uart_in_use = ~0;
|
||||
mini_clock_rate = 0x1000000;
|
||||
|
||||
ret = uclass_get_device_by_driver(UCLASS_SERIAL,
|
||||
DM_DRIVER_GET(bcm283x_pl011_uart),
|
||||
&dev);
|
||||
if (!ret)
|
||||
uart_in_use = 0;
|
||||
|
||||
ret = uclass_get_device_by_driver(UCLASS_SERIAL,
|
||||
DM_DRIVER_GET(serial_bcm283x_mu),
|
||||
&dev);
|
||||
if (!ret) {
|
||||
if (uart_in_use == 0)
|
||||
log_err("Invalid config: PL011 and MiniUART are both enabled.");
|
||||
else
|
||||
uart_in_use = 1;
|
||||
|
||||
mini_clock_rate = dev_read_u32_default(dev, "clock", 0x1000000);
|
||||
}
|
||||
if (uart_in_use > 1)
|
||||
log_err("No working serial: PL011 and MiniUART are both disabled.");
|
||||
|
||||
acpigen_write_scope(ctx, "\\_SB.BTH0");
|
||||
acpigen_write_name_integer(ctx, "URIU", uart_in_use);
|
||||
acpigen_pop_len(ctx);
|
||||
|
||||
acpigen_write_scope(ctx, "\\_SB.URTM");
|
||||
acpigen_write_name_integer(ctx, "MUCR", mini_clock_rate);
|
||||
acpigen_pop_len(ctx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rpi_acpi_write_ssdt(struct acpi_ctx *ctx, const struct acpi_writer *entry)
|
||||
{
|
||||
struct acpi_table_header *ssdt;
|
||||
int ret;
|
||||
|
||||
ssdt = ctx->current;
|
||||
memset(ssdt, '\0', sizeof(struct acpi_table_header));
|
||||
|
||||
acpi_fill_header(ssdt, "SSDT");
|
||||
ssdt->revision = acpi_get_table_revision(ACPITAB_SSDT);
|
||||
ssdt->creator_revision = 1;
|
||||
ssdt->length = sizeof(struct acpi_table_header);
|
||||
|
||||
acpi_inc(ctx, sizeof(struct acpi_table_header));
|
||||
|
||||
ret = acpi_rpi_board_fill_ssdt(ctx);
|
||||
if (ret) {
|
||||
ctx->current = ssdt;
|
||||
return log_msg_ret("fill", ret);
|
||||
}
|
||||
|
||||
/* (Re)calculate length and checksum */
|
||||
ssdt->length = ctx->current - (void *)ssdt;
|
||||
ssdt->checksum = table_compute_checksum((void *)ssdt, ssdt->length);
|
||||
log_debug("SSDT at %p, length %x\n", ssdt, ssdt->length);
|
||||
|
||||
/* Drop the table if it is empty */
|
||||
if (ssdt->length == sizeof(struct acpi_table_header))
|
||||
return log_msg_ret("fill", -ENOENT);
|
||||
acpi_add_table(ctx, ssdt);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ACPI_WRITER(5ssdt, "SSDT", rpi_acpi_write_ssdt, 0);
|
||||
#endif
|
||||
|
|
111
board/raspberrypi/rpi/sdhc.asl
Normal file
111
board/raspberrypi/rpi/sdhc.asl
Normal file
|
@ -0,0 +1,111 @@
|
|||
/** @file
|
||||
*
|
||||
* [DSDT] SD controller/card definition (SDHC)
|
||||
*
|
||||
* Copyright (c) 2020, Pete Batard <pete@akeo.ie>
|
||||
* Copyright (c) 2018, Andrey Warkentin <andrey.warkentin@gmail.com>
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
*
|
||||
**/
|
||||
|
||||
#include <asm/arch/acpi/bcm2836_sdhost.h>
|
||||
#include <asm/arch/acpi/bcm2836_sdio.h>
|
||||
|
||||
#include "acpitables.h"
|
||||
|
||||
//
|
||||
// Note: UEFI can use either SDHost or Arasan. We expose both to the OS.
|
||||
//
|
||||
|
||||
// ArasanSD 3.0 SD Host Controller. (brcm,bcm2835-sdhci)
|
||||
Device (SDC1)
|
||||
{
|
||||
Name (_HID, "BCM2847")
|
||||
Name (_CID, "BCM2847")
|
||||
Name (_UID, 0x0)
|
||||
Name (_CCA, 0x0)
|
||||
Name (_S1D, 0x1)
|
||||
Name (_S2D, 0x1)
|
||||
Name (_S3D, 0x1)
|
||||
Name (_S4D, 0x1)
|
||||
|
||||
Name (RBUF, ResourceTemplate ()
|
||||
{
|
||||
MEMORY32FIXED (ReadWrite, 0, MMCHS1_LENGTH, RMEM)
|
||||
Interrupt (ResourceConsumer, Level, ActiveHigh, Shared) { BCM2836_MMCHS1_INTERRUPT }
|
||||
})
|
||||
Method (_CRS, 0x0, Serialized)
|
||||
{
|
||||
MEMORY32SETBASE (RBUF, RMEM, RBAS, MMCHS1_OFFSET)
|
||||
Return (^RBUF)
|
||||
}
|
||||
|
||||
// The standard CAPs registers on this controller
|
||||
// appear to be 0, lets set some minimal defaults
|
||||
// Since this cap doesn't indicate DMA capability
|
||||
// we don't need a _DMA()
|
||||
Name (_DSD, Package () {
|
||||
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
|
||||
Package () {
|
||||
Package () { "sdhci-caps", 0x0120fa81 },
|
||||
}
|
||||
})
|
||||
|
||||
//
|
||||
// A child device that represents the
|
||||
// sd card, which is marked as non-removable.
|
||||
//
|
||||
Device (SDMM)
|
||||
{
|
||||
Method (_ADR)
|
||||
{
|
||||
Return (0)
|
||||
}
|
||||
Method (_RMV) // Is removable
|
||||
{
|
||||
Return (0) // 0 - fixed
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Broadcom SDHost 2.0 SD Host Controller
|
||||
Device (SDC2)
|
||||
{
|
||||
Name (_HID, "BCM2855")
|
||||
Name (_CID, "BCM2855")
|
||||
Name (_UID, 0x0)
|
||||
Name (_CCA, 0x0)
|
||||
Name (_S1D, 0x1)
|
||||
Name (_S2D, 0x1)
|
||||
Name (_S3D, 0x1)
|
||||
Name (_S4D, 0x1)
|
||||
|
||||
Name (RBUF, ResourceTemplate ()
|
||||
{
|
||||
MEMORY32FIXED (ReadWrite, 0, SDHOST_LENGTH, RMEM)
|
||||
Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { BCM2836_SDHOST_INTERRUPT }
|
||||
})
|
||||
Method (_CRS, 0x0, Serialized)
|
||||
{
|
||||
MEMORY32SETBASE (RBUF, RMEM, RBAS, SDHOST_OFFSET)
|
||||
Return (^RBUF)
|
||||
}
|
||||
|
||||
//
|
||||
// A child device that represents the
|
||||
// sd card, which is marked as non-removable.
|
||||
//
|
||||
Device (SDMM)
|
||||
{
|
||||
Method (_ADR)
|
||||
{
|
||||
Return (0)
|
||||
}
|
||||
Method (_RMV) // Is removable
|
||||
{
|
||||
Return (0) // 0 - fixed
|
||||
}
|
||||
}
|
||||
}
|
208
board/raspberrypi/rpi/uart.asl
Normal file
208
board/raspberrypi/rpi/uart.asl
Normal file
|
@ -0,0 +1,208 @@
|
|||
/** @file
|
||||
*
|
||||
* [DSDT] Serial devices (UART).
|
||||
*
|
||||
* Copyright (c) 2021, ARM Limited. All rights reserved.
|
||||
* Copyright (c) 2020, Pete Batard <pete@akeo.ie>
|
||||
* Copyright (c) 2018, Andrey Warkentin <andrey.warkentin@gmail.com>
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
*
|
||||
**/
|
||||
|
||||
#include <asm/arch/acpi/bcm2836.h>
|
||||
|
||||
#include "acpitables.h"
|
||||
|
||||
// PL011 based UART.
|
||||
Device (URT0)
|
||||
{
|
||||
Name (_HID, "BCM2837")
|
||||
Name (_CID, "ARMH0011")
|
||||
Name (_UID, 0x4)
|
||||
Name (_CCA, 0x0)
|
||||
|
||||
Name (RBUF, ResourceTemplate ()
|
||||
{
|
||||
MEMORY32FIXED (ReadWrite, 0, BCM2836_PL011_UART_LENGTH, RMEM)
|
||||
Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { BCM2836_PL011_UART_INTERRUPT }
|
||||
})
|
||||
Method (_CRS, 0x0, Serialized)
|
||||
{
|
||||
MEMORY32SETBASE (RBUF, RMEM, RBAS, BCM2836_PL011_UART_OFFSET)
|
||||
Return (^RBUF)
|
||||
}
|
||||
|
||||
Name (CLCK, 48000000)
|
||||
|
||||
Name (_DSD, Package ()
|
||||
{
|
||||
ToUUID ("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"), Package ()
|
||||
{
|
||||
Package (2) { "clock-frequency", CLCK },
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
//
|
||||
// UART Mini.
|
||||
//
|
||||
// This device is referenced in the DBG2 table, which will cause the system to
|
||||
// not start the driver when the debugger is enabled and to mark the device
|
||||
// with problem code 53 (CM_PROB_USED_BY_DEBUGGER).
|
||||
//
|
||||
|
||||
Device (URTM)
|
||||
{
|
||||
Name (_HID, "BCM2836")
|
||||
Name (_CID, "BCM2836")
|
||||
Name (_UID, 0x0)
|
||||
Name (_CCA, 0x0)
|
||||
|
||||
Name (RBUF, ResourceTemplate ()
|
||||
{
|
||||
MEMORY32FIXED (ReadWrite, 0, BCM2836_MINI_UART_LENGTH, RMEM)
|
||||
Interrupt(ResourceConsumer, Level, ActiveHigh, Shared) { BCM2836_MINI_UART_INTERRUPT }
|
||||
|
||||
})
|
||||
Method (_CRS, 0x0, Serialized)
|
||||
{
|
||||
MEMORY32SETBASE (RBUF, RMEM, RBAS, BCM2836_MINI_UART_OFFSET)
|
||||
Return (^RBUF)
|
||||
}
|
||||
|
||||
//
|
||||
// Mini Uart Clock Rate will be dynamically updated during boot
|
||||
//
|
||||
External (\_SB.URTM.MUCR, IntObj)
|
||||
|
||||
Name (_DSD, Package ()
|
||||
{
|
||||
ToUUID ("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"), Package ()
|
||||
{
|
||||
Package (2) { "clock-frequency", MUCR },
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
//
|
||||
// Multifunction serial bus device to support Bluetooth function.
|
||||
//
|
||||
Device(BTH0)
|
||||
{
|
||||
Name (_HID, "BCM2EA6")
|
||||
Name (_CID, "BCM2EA6")
|
||||
|
||||
//
|
||||
// UART In Use will be dynamically updated during boot
|
||||
//
|
||||
External (\_SB.BTH0.URIU, IntObj)
|
||||
|
||||
Method (_STA)
|
||||
{
|
||||
Return (0xf)
|
||||
}
|
||||
|
||||
//
|
||||
// Resource for URT0 (PL011)
|
||||
//
|
||||
Name (BTPL, ResourceTemplate ()
|
||||
{
|
||||
UARTSerialBus(
|
||||
115200, // InitialBaudRate: in BPS
|
||||
, // BitsPerByte: default to 8 bits
|
||||
, // StopBits: Defaults to one bit
|
||||
0x00, // LinesInUse: 8 1-bit flags to
|
||||
// declare enabled control lines.
|
||||
// Raspberry Pi does not exposed
|
||||
// HW control signals -> not supported.
|
||||
// Optional bits:
|
||||
// - Bit 7 (0x80) Request To Send (RTS)
|
||||
// - Bit 6 (0x40) Clear To Send (CTS)
|
||||
// - Bit 5 (0x20) Data Terminal Ready (DTR)
|
||||
// - Bit 4 (0x10) Data Set Ready (DSR)
|
||||
// - Bit 3 (0x08) Ring Indicator (RI)
|
||||
// - Bit 2 (0x04) Data Carrier Detect (DTD)
|
||||
// - Bit 1 (0x02) Reserved. Must be 0.
|
||||
// - Bit 0 (0x01) Reserved. Must be 0.
|
||||
, // IsBigEndian:
|
||||
// default to LittleEndian.
|
||||
, // Parity: Defaults to no parity
|
||||
, // FlowControl: Defaults to
|
||||
// no flow control.
|
||||
16, // ReceiveBufferSize
|
||||
16, // TransmitBufferSize
|
||||
"\\_SB.GDV0.URT0", // ResourceSource:
|
||||
// UART bus controller name
|
||||
, // ResourceSourceIndex: assumed to be 0
|
||||
, // ResourceUsage: assumed to be
|
||||
// ResourceConsumer
|
||||
UAR0, // DescriptorName: creates name
|
||||
// for offset of resource descriptor
|
||||
) // Vendor data
|
||||
})
|
||||
|
||||
//
|
||||
// Resource for URTM (miniUART)
|
||||
//
|
||||
Name (BTMN, ResourceTemplate ()
|
||||
{
|
||||
//
|
||||
// BT UART: ResourceSource will be dynamically updated to
|
||||
// either URT0 (PL011) or URTM (miniUART) during boot
|
||||
//
|
||||
UARTSerialBus(
|
||||
115200, // InitialBaudRate: in BPS
|
||||
, // BitsPerByte: default to 8 bits
|
||||
, // StopBits: Defaults to one bit
|
||||
0x00, // LinesInUse: 8 1-bit flags to
|
||||
// declare enabled control lines.
|
||||
// Raspberry Pi does not exposed
|
||||
// HW control signals -> not supported.
|
||||
// Optional bits:
|
||||
// - Bit 7 (0x80) Request To Send (RTS)
|
||||
// - Bit 6 (0x40) Clear To Send (CTS)
|
||||
// - Bit 5 (0x20) Data Terminal Ready (DTR)
|
||||
// - Bit 4 (0x10) Data Set Ready (DSR)
|
||||
// - Bit 3 (0x08) Ring Indicator (RI)
|
||||
// - Bit 2 (0x04) Data Carrier Detect (DTD)
|
||||
// - Bit 1 (0x02) Reserved. Must be 0.
|
||||
// - Bit 0 (0x01) Reserved. Must be 0.
|
||||
, // IsBigEndian:
|
||||
// default to LittleEndian.
|
||||
, // Parity: Defaults to no parity
|
||||
, // FlowControl: Defaults to
|
||||
// no flow control.
|
||||
16, // ReceiveBufferSize
|
||||
16, // TransmitBufferSize
|
||||
"\\_SB.GDV0.URTM", // ResourceSource:
|
||||
// UART bus controller name
|
||||
, // ResourceSourceIndex: assumed to be 0
|
||||
, // ResourceUsage: assumed to be
|
||||
// ResourceConsumer
|
||||
UARM, // DescriptorName: creates name
|
||||
// for offset of resource descriptor
|
||||
) // Vendor data
|
||||
})
|
||||
|
||||
Method (_CRS, 0x0, Serialized)
|
||||
{
|
||||
if (URIU == 0)
|
||||
{
|
||||
//
|
||||
// PL011 UART is configured for console output
|
||||
// Return Mini UART for Bluetooth
|
||||
//
|
||||
return (^BTMN)
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// Mini UART is configured for console output
|
||||
// Return PL011 UART for Bluetooth
|
||||
//
|
||||
return (^BTPL)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -936,11 +936,15 @@ int bootflow_cmdline_auto(struct bootflow *bflow, const char *arg)
|
|||
return ret;
|
||||
|
||||
*buf = '\0';
|
||||
if (!strcmp("earlycon", arg)) {
|
||||
if (!strcmp("earlycon", arg) && info.type == SERIAL_CHIP_16550_COMPATIBLE) {
|
||||
snprintf(buf, sizeof(buf),
|
||||
"uart8250,mmio32,%#lx,%dn8", info.addr,
|
||||
info.baudrate);
|
||||
} else if (!strcmp("console", arg)) {
|
||||
} else if (!strcmp("earlycon", arg) && info.type == SERIAL_CHIP_PL01X) {
|
||||
snprintf(buf, sizeof(buf),
|
||||
"pl011,mmio32,%#lx,%dn8", info.addr,
|
||||
info.baudrate);
|
||||
} else if (!strcmp("console", arg) && info.type == SERIAL_CHIP_16550_COMPATIBLE) {
|
||||
snprintf(buf, sizeof(buf),
|
||||
"ttyS0,%dn8", info.baudrate);
|
||||
}
|
||||
|
|
|
@ -1081,6 +1081,7 @@ config BLOBLIST_SIZE_RELOC
|
|||
hex "Size of bloblist after relocation"
|
||||
default BLOBLIST_SIZE if BLOBLIST_FIXED || BLOBLIST_ALLOC
|
||||
default 0x0 if BLOBLIST_PASSAGE
|
||||
default 0x20000 if (ARM && EFI_LOADER && GENERATE_ACPI_TABLE)
|
||||
help
|
||||
Sets the size of the bloblist in bytes after relocation. Since U-Boot
|
||||
has a lot more memory available then, it is possible to use a larger
|
||||
|
|
|
@ -499,7 +499,7 @@ int bloblist_init(void)
|
|||
{
|
||||
bool fixed = IS_ENABLED(CONFIG_BLOBLIST_FIXED);
|
||||
int ret = -ENOENT;
|
||||
ulong addr, size;
|
||||
ulong addr = 0, size;
|
||||
/*
|
||||
* If U-Boot is not in the first phase, an existing bloblist must be
|
||||
* at a fixed address.
|
||||
|
|
|
@ -53,7 +53,7 @@ CONFIG_ARP_TIMEOUT=200
|
|||
CONFIG_NET_RETRY_COUNT=50
|
||||
CONFIG_NET_RANDOM_ETHADDR=y
|
||||
CONFIG_SPL_OF_TRANSLATE=y
|
||||
CONFIG_AHCI_MVEBU=y
|
||||
CONFIG_AHCI_GENERIC=y
|
||||
CONFIG_DM_PCA953X=y
|
||||
CONFIG_DM_I2C=y
|
||||
CONFIG_SYS_I2C_MVTWSI=y
|
||||
|
|
|
@ -46,7 +46,7 @@ CONFIG_SYS_RELOC_GD_ENV_ADDR=y
|
|||
CONFIG_ARP_TIMEOUT=200
|
||||
CONFIG_NET_RETRY_COUNT=50
|
||||
CONFIG_NET_RANDOM_ETHADDR=y
|
||||
CONFIG_AHCI_MVEBU=y
|
||||
CONFIG_AHCI_GENERIC=y
|
||||
CONFIG_LBA48=y
|
||||
CONFIG_SYS_64BIT_LBA=y
|
||||
CONFIG_DM_I2C=y
|
||||
|
|
|
@ -53,7 +53,7 @@ CONFIG_ARP_TIMEOUT=200
|
|||
CONFIG_NET_RETRY_COUNT=50
|
||||
CONFIG_NET_RANDOM_ETHADDR=y
|
||||
CONFIG_SPL_OF_TRANSLATE=y
|
||||
CONFIG_AHCI_MVEBU=y
|
||||
CONFIG_AHCI_GENERIC=y
|
||||
CONFIG_DM_PCA953X=y
|
||||
CONFIG_DM_I2C=y
|
||||
CONFIG_SYS_I2C_MVTWSI=y
|
||||
|
|
|
@ -53,7 +53,7 @@ CONFIG_ARP_TIMEOUT=200
|
|||
CONFIG_NET_RETRY_COUNT=50
|
||||
CONFIG_NET_RANDOM_ETHADDR=y
|
||||
CONFIG_SPL_OF_TRANSLATE=y
|
||||
CONFIG_AHCI_MVEBU=y
|
||||
CONFIG_AHCI_GENERIC=y
|
||||
CONFIG_DM_PCA953X=y
|
||||
CONFIG_DM_I2C=y
|
||||
CONFIG_SYS_I2C_MVTWSI=y
|
||||
|
|
|
@ -58,7 +58,7 @@ CONFIG_SYS_RELOC_GD_ENV_ADDR=y
|
|||
CONFIG_ARP_TIMEOUT=200
|
||||
CONFIG_NET_RETRY_COUNT=50
|
||||
CONFIG_SPL_OF_TRANSLATE=y
|
||||
CONFIG_AHCI_MVEBU=y
|
||||
CONFIG_AHCI_GENERIC=y
|
||||
CONFIG_SYS_I2C_LEGACY=y
|
||||
CONFIG_SPL_SYS_I2C_LEGACY=y
|
||||
CONFIG_SYS_I2C_MVTWSI=y
|
||||
|
|
|
@ -65,7 +65,7 @@ CONFIG_NET_RETRY_COUNT=50
|
|||
CONFIG_NET_RANDOM_ETHADDR=y
|
||||
CONFIG_NETCONSOLE=y
|
||||
CONFIG_SPL_OF_TRANSLATE=y
|
||||
CONFIG_AHCI_MVEBU=y
|
||||
CONFIG_AHCI_GENERIC=y
|
||||
CONFIG_LBA48=y
|
||||
CONFIG_SYS_64BIT_LBA=y
|
||||
CONFIG_DM_I2C=y
|
||||
|
|
|
@ -53,7 +53,7 @@ CONFIG_ARP_TIMEOUT=200
|
|||
CONFIG_NET_RETRY_COUNT=50
|
||||
CONFIG_NET_RANDOM_ETHADDR=y
|
||||
CONFIG_SPL_OF_TRANSLATE=y
|
||||
CONFIG_AHCI_MVEBU=y
|
||||
CONFIG_AHCI_GENERIC=y
|
||||
CONFIG_DM_PCA953X=y
|
||||
CONFIG_DM_I2C=y
|
||||
CONFIG_SYS_I2C_MVTWSI=y
|
||||
|
|
|
@ -46,7 +46,7 @@ CONFIG_SYS_RELOC_GD_ENV_ADDR=y
|
|||
CONFIG_SYS_MMC_ENV_DEV=1
|
||||
CONFIG_ARP_TIMEOUT=200
|
||||
CONFIG_NET_RETRY_COUNT=50
|
||||
CONFIG_AHCI_MVEBU=y
|
||||
CONFIG_AHCI_GENERIC=y
|
||||
CONFIG_LBA48=y
|
||||
CONFIG_SYS_64BIT_LBA=y
|
||||
CONFIG_DM_I2C=y
|
||||
|
|
|
@ -43,7 +43,7 @@ CONFIG_ENV_IS_IN_SPI_FLASH=y
|
|||
CONFIG_SYS_RELOC_GD_ENV_ADDR=y
|
||||
CONFIG_ARP_TIMEOUT=200
|
||||
CONFIG_NET_RETRY_COUNT=50
|
||||
CONFIG_AHCI_MVEBU=y
|
||||
CONFIG_AHCI_GENERIC=y
|
||||
CONFIG_LBA48=y
|
||||
CONFIG_SYS_64BIT_LBA=y
|
||||
CONFIG_CLK=y
|
||||
|
|
|
@ -42,7 +42,7 @@ CONFIG_ENV_IS_IN_SPI_FLASH=y
|
|||
CONFIG_SYS_RELOC_GD_ENV_ADDR=y
|
||||
CONFIG_ARP_TIMEOUT=200
|
||||
CONFIG_NET_RETRY_COUNT=50
|
||||
CONFIG_AHCI_MVEBU=y
|
||||
CONFIG_AHCI_GENERIC=y
|
||||
CONFIG_LBA48=y
|
||||
CONFIG_SYS_64BIT_LBA=y
|
||||
CONFIG_DM_I2C=y
|
||||
|
|
|
@ -47,7 +47,7 @@ CONFIG_SYS_RELOC_GD_ENV_ADDR=y
|
|||
CONFIG_SYS_MMC_ENV_DEV=1
|
||||
CONFIG_ARP_TIMEOUT=200
|
||||
CONFIG_NET_RETRY_COUNT=50
|
||||
CONFIG_AHCI_MVEBU=y
|
||||
CONFIG_AHCI_GENERIC=y
|
||||
CONFIG_LBA48=y
|
||||
CONFIG_SYS_64BIT_LBA=y
|
||||
CONFIG_DM_GPIO_LOOKUP_LABEL=y
|
||||
|
|
|
@ -54,7 +54,7 @@ CONFIG_ARP_TIMEOUT=200
|
|||
CONFIG_NET_RETRY_COUNT=50
|
||||
CONFIG_NET_RANDOM_ETHADDR=y
|
||||
CONFIG_AHCI_PCI=y
|
||||
CONFIG_AHCI_MVEBU=y
|
||||
CONFIG_AHCI_GENERIC=y
|
||||
CONFIG_LBA48=y
|
||||
CONFIG_SYS_64BIT_LBA=y
|
||||
CONFIG_CLK=y
|
||||
|
|
|
@ -53,7 +53,7 @@ CONFIG_ARP_TIMEOUT=200
|
|||
CONFIG_NET_RETRY_COUNT=50
|
||||
CONFIG_NET_RANDOM_ETHADDR=y
|
||||
CONFIG_AHCI_PCI=y
|
||||
CONFIG_AHCI_MVEBU=y
|
||||
CONFIG_AHCI_GENERIC=y
|
||||
CONFIG_LBA48=y
|
||||
CONFIG_SYS_64BIT_LBA=y
|
||||
CONFIG_CLK=y
|
||||
|
|
|
@ -46,7 +46,7 @@ CONFIG_SYS_RELOC_GD_ENV_ADDR=y
|
|||
CONFIG_ARP_TIMEOUT=200
|
||||
CONFIG_NET_RETRY_COUNT=50
|
||||
CONFIG_NET_RANDOM_ETHADDR=y
|
||||
CONFIG_AHCI_MVEBU=y
|
||||
CONFIG_AHCI_GENERIC=y
|
||||
CONFIG_LBA48=y
|
||||
CONFIG_SYS_64BIT_LBA=y
|
||||
CONFIG_DM_I2C=y
|
||||
|
|
|
@ -50,7 +50,7 @@ CONFIG_SYS_RELOC_GD_ENV_ADDR=y
|
|||
CONFIG_ARP_TIMEOUT=200
|
||||
CONFIG_NET_RETRY_COUNT=50
|
||||
CONFIG_NET_RANDOM_ETHADDR=y
|
||||
CONFIG_AHCI_MVEBU=y
|
||||
CONFIG_AHCI_GENERIC=y
|
||||
CONFIG_LBA48=y
|
||||
CONFIG_SYS_64BIT_LBA=y
|
||||
CONFIG_DM_PCA953X=y
|
||||
|
|
|
@ -65,7 +65,7 @@ CONFIG_NET_RETRY_COUNT=50
|
|||
CONFIG_NET_RANDOM_ETHADDR=y
|
||||
CONFIG_NETCONSOLE=y
|
||||
CONFIG_SPL_OF_TRANSLATE=y
|
||||
CONFIG_AHCI_MVEBU=y
|
||||
CONFIG_AHCI_GENERIC=y
|
||||
CONFIG_LBA48=y
|
||||
CONFIG_SYS_64BIT_LBA=y
|
||||
CONFIG_DM_I2C=y
|
||||
|
|
|
@ -46,7 +46,7 @@ CONFIG_EFI_PARTITION=y
|
|||
CONFIG_ENV_IS_IN_SPI_FLASH=y
|
||||
CONFIG_TFTP_TSIZE=y
|
||||
CONFIG_SATA=y
|
||||
CONFIG_AHCI_MVEBU=y
|
||||
CONFIG_AHCI_GENERIC=y
|
||||
CONFIG_LBA48=y
|
||||
CONFIG_SYS_64BIT_LBA=y
|
||||
CONFIG_CLK=y
|
||||
|
|
12
configs/qemu-arm-sbsa_defconfig
Normal file
12
configs/qemu-arm-sbsa_defconfig
Normal file
|
@ -0,0 +1,12 @@
|
|||
CONFIG_ARM=y
|
||||
CONFIG_ARCH_QEMU=y
|
||||
CONFIG_TARGET_QEMU_ARM_SBSA=y
|
||||
CONFIG_USE_BOOTCOMMAND=y
|
||||
CONFIG_BOOTCOMMAND="bootflow scan"
|
||||
CONFIG_EFI_PARTITION=y
|
||||
CONFIG_PARTITION_TYPE_GUID=y
|
||||
CONFIG_EFI_MEDIA=y
|
||||
CONFIG_FS_FAT=y
|
||||
CONFIG_EFI_VARIABLE_NO_STORE=y
|
||||
CONFIG_BLOBLIST_ALLOC=y
|
||||
CONFIG_BLOBLIST_SIZE_RELOC=0x20000
|
10
configs/rpi_4_acpi_defconfig
Normal file
10
configs/rpi_4_acpi_defconfig
Normal file
|
@ -0,0 +1,10 @@
|
|||
#include <configs/rpi_4_defconfig>
|
||||
|
||||
CONFIG_ARM=y
|
||||
CONFIG_ARCH_BCM283X=y
|
||||
CONFIG_TARGET_RPI_4=y
|
||||
CONFIG_BLOBLIST_ALLOC=y
|
||||
CONFIG_OF_BOARD=y
|
||||
CONFIG_ACPI=y
|
||||
CONFIG_GENERATE_ACPI_TABLE=y
|
||||
|
|
@ -90,7 +90,7 @@ CONFIG_NET_RETRY_COUNT=50
|
|||
CONFIG_NETCONSOLE=y
|
||||
CONFIG_SPL_OF_TRANSLATE=y
|
||||
CONFIG_AHCI_PCI=y
|
||||
CONFIG_AHCI_MVEBU=y
|
||||
CONFIG_AHCI_GENERIC=y
|
||||
CONFIG_DM_PCA953X=y
|
||||
CONFIG_MMC_SDHCI=y
|
||||
CONFIG_MMC_SDHCI_MV=y
|
||||
|
|
|
@ -13,5 +13,6 @@ Emulation
|
|||
qemu-mips
|
||||
qemu-ppce500
|
||||
qemu-riscv
|
||||
qemu-sbsa
|
||||
qemu-x86
|
||||
qemu-xtensa
|
||||
|
|
98
doc/board/emulation/qemu-sbsa.rst
Normal file
98
doc/board/emulation/qemu-sbsa.rst
Normal file
|
@ -0,0 +1,98 @@
|
|||
.. SPDX-License-Identifier: GPL-2.0+
|
||||
.. Copyright (C) 2024, Patrick Rudolph <patrick.rudolph@9elements.com>
|
||||
|
||||
QEMU ARM SBSA
|
||||
=============
|
||||
|
||||
QEMU for ARM supports Arm Server Base System Architecture Reference board,
|
||||
short 'sbsa-ref' that utilizes ACPI over FDT. This document describes how to run
|
||||
U-Boot under it. Only AArch64 is supported.
|
||||
|
||||
The 'sbsa' platform provides the following as the basic functionality:
|
||||
|
||||
- A freely configurable amount of CPU cores
|
||||
- U-Boot loaded and executing in the emulated flash at address 0x10000000
|
||||
- No device tree blob
|
||||
- A freely configurable amount of RAM
|
||||
- A PL011 serial port
|
||||
- An ARMv7/ARMv8 architected timer
|
||||
- PSCI for rebooting the system
|
||||
- A generic ECAM-based PCI host controller
|
||||
|
||||
Additionally, a number of optional peripherals can be added to the PCI bus.
|
||||
|
||||
Compile ARM Trusted Firmware (ATF)
|
||||
----------------------------------
|
||||
|
||||
Get and Build the ARM Trusted firmware
|
||||
--------------------------------------
|
||||
|
||||
Note: srctree is U-Boot source directory
|
||||
Get ATF from: https://github.com/ARM-software/arm-trusted-firmware
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
git clone https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git tfa
|
||||
cd tfa
|
||||
make CROSS_COMPILE=aarch64-linux-gnu- all fip \
|
||||
ARM_LINUX_KERNEL_AS_BL33=1 DEBUG=1 PLAT=qemu_sbsa
|
||||
|
||||
Copy the resulting FIP and BL1 binary
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
cp build/qemu_sbsa/debug/fip.bin ../
|
||||
cp build/qemu_sbsa/debug/bl1.bin ../
|
||||
|
||||
Building U-Boot
|
||||
---------------
|
||||
Set the CROSS_COMPILE environment variable as usual, and run:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
make qemu-arm-sbsa_defconfig
|
||||
make
|
||||
|
||||
Running U-Boot
|
||||
--------------
|
||||
The minimal QEMU command line to get U-Boot up and running is:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
qemu-system-aarch64 -machine sbsa-ref -nographic -cpu cortex-a57 \
|
||||
-pflash secure-world.rom \
|
||||
-pflash unsecure-world.rom
|
||||
|
||||
Note that for some odd reason qemu-system-aarch64 needs to be explicitly
|
||||
told to use a 64-bit CPU or it will boot in 32-bit mode. The -nographic argument
|
||||
ensures that output appears on the terminal. Use Ctrl-A X to quit.
|
||||
|
||||
Booting distros
|
||||
---------------
|
||||
|
||||
It is possible to install and boot a standard Linux distribution using
|
||||
sbsa by setting up a root disk::
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
qemu-img create root.img 20G
|
||||
|
||||
then using the installer to install. For example, with Debian 12::
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
qemu-system-aarch64 \
|
||||
-machine sbsa-ref -cpu cortex-a57 -m 4G -smp 4 \
|
||||
-pflash secure-world.rom \
|
||||
-pflash unsecure-world.rom \
|
||||
-device virtio-rng-pci \
|
||||
-device usb-kbd -device usb-tablet \
|
||||
-cdrom debian-12.0.0-arm64-netinst.iso \
|
||||
-hda root.img
|
||||
|
||||
Debug UART
|
||||
----------
|
||||
|
||||
The debug UART on the ARM sbsa board uses these settings::
|
||||
|
||||
CONFIG_DEBUG_UART=y
|
|
@ -34,6 +34,7 @@ The following QEMU targets are supported.
|
|||
|
||||
- qemu_arm_defconfig
|
||||
- qemu_arm64_defconfig
|
||||
- qemu-arm-sbsa_defconfig
|
||||
- qemu-riscv32_defconfig
|
||||
- qemu-riscv64_defconfig
|
||||
- qemu-x86_defconfig
|
||||
|
|
|
@ -78,14 +78,16 @@ config MTK_AHCI
|
|||
Enable this driver to support Sata devices through
|
||||
Mediatek AHCI controller (e.g. MT7622).
|
||||
|
||||
config AHCI_MVEBU
|
||||
bool "Marvell EBU AHCI SATA support"
|
||||
depends on ARCH_MVEBU || ARCH_OCTEON
|
||||
config AHCI_GENERIC
|
||||
bool "Generic AHCI SATA support"
|
||||
depends on OF_CONTROL
|
||||
select SCSI_AHCI
|
||||
select SCSI
|
||||
help
|
||||
This option enables support for the Marvell EBU SoC's
|
||||
onboard AHCI SATA.
|
||||
This option enables support for generic onboard AHCI SATA controller
|
||||
that do not need platform specific quirks, like emulated devices,
|
||||
Marvell EBU SoC's onboard AHCI SATA controllers or Cavium's Octeon
|
||||
7130 AHCI controllers.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
|
|
|
@ -14,6 +14,6 @@ obj-$(CONFIG_SATA) += sata.o sata_bootdev.o
|
|||
obj-$(CONFIG_SATA_CEVA) += sata_ceva.o
|
||||
obj-$(CONFIG_SATA_MV) += sata_mv.o
|
||||
obj-$(CONFIG_SATA_SIL) += sata_sil.o
|
||||
obj-$(CONFIG_AHCI_MVEBU) += ahci_mvebu.o
|
||||
obj-$(CONFIG_AHCI_GENERIC) += ahci_generic.o
|
||||
obj-$(CONFIG_SUNXI_AHCI) += ahci_sunxi.o
|
||||
obj-$(CONFIG_MTK_AHCI) += mtk_ahci.o
|
||||
|
|
|
@ -16,7 +16,7 @@ __weak int board_ahci_enable(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int mvebu_ahci_bind(struct udevice *dev)
|
||||
static int generic_ahci_bind(struct udevice *dev)
|
||||
{
|
||||
struct udevice *scsi_dev;
|
||||
int ret;
|
||||
|
@ -30,7 +30,7 @@ static int mvebu_ahci_bind(struct udevice *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int mvebu_ahci_probe(struct udevice *dev)
|
||||
static int generic_ahci_probe(struct udevice *dev)
|
||||
{
|
||||
/*
|
||||
* Board specific SATA / AHCI enable code, e.g. enable the
|
||||
|
@ -43,18 +43,19 @@ static int mvebu_ahci_probe(struct udevice *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static const struct udevice_id mvebu_ahci_ids[] = {
|
||||
static const struct udevice_id generic_ahci_ids[] = {
|
||||
{ .compatible = "marvell,armada-380-ahci" },
|
||||
{ .compatible = "marvell,armada-3700-ahci" },
|
||||
{ .compatible = "marvell,armada-8k-ahci" },
|
||||
{ .compatible = "cavium,octeon-7130-ahci" },
|
||||
{ .compatible = "generic-ahci" },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(ahci_mvebu_drv) = {
|
||||
.name = "ahci_mvebu",
|
||||
U_BOOT_DRIVER(ahci_generic_drv) = {
|
||||
.name = "ahci_generic",
|
||||
.id = UCLASS_AHCI,
|
||||
.of_match = mvebu_ahci_ids,
|
||||
.bind = mvebu_ahci_bind,
|
||||
.probe = mvebu_ahci_probe,
|
||||
.of_match = generic_ahci_ids,
|
||||
.bind = generic_ahci_bind,
|
||||
.probe = generic_ahci_probe,
|
||||
};
|
|
@ -48,6 +48,7 @@ enum method_t {
|
|||
METHOD_FILL_SSDT,
|
||||
METHOD_INJECT_DSDT,
|
||||
METHOD_SETUP_NHLT,
|
||||
METHOD_FILL_MADT,
|
||||
};
|
||||
|
||||
/* Prototype for all methods */
|
||||
|
@ -282,6 +283,8 @@ acpi_method acpi_get_method(struct udevice *dev, enum method_t method)
|
|||
switch (method) {
|
||||
case METHOD_WRITE_TABLES:
|
||||
return aops->write_tables;
|
||||
case METHOD_FILL_MADT:
|
||||
return aops->fill_madt;
|
||||
case METHOD_FILL_SSDT:
|
||||
return aops->fill_ssdt;
|
||||
case METHOD_INJECT_DSDT:
|
||||
|
@ -328,6 +331,19 @@ int acpi_recurse_method(struct acpi_ctx *ctx, struct udevice *parent,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int acpi_fill_madt_subtbl(struct acpi_ctx *ctx)
|
||||
{
|
||||
int ret;
|
||||
|
||||
log_debug("Writing MADT table\n");
|
||||
ret = acpi_recurse_method(ctx, dm_root(), METHOD_FILL_MADT, TYPE_NONE);
|
||||
log_debug("Writing MADT finished, err=%d\n", ret);
|
||||
if (ret)
|
||||
return log_msg_ret("build", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int acpi_fill_ssdt(struct acpi_ctx *ctx)
|
||||
{
|
||||
void *start = ctx->current;
|
||||
|
|
|
@ -26,6 +26,13 @@ config CPU_RISCV
|
|||
help
|
||||
Support CPU cores for RISC-V architecture.
|
||||
|
||||
config CPU_ARMV8
|
||||
bool "Enable generic ARMv8 CPU driver"
|
||||
depends on CPU && ARM64
|
||||
select IRQ
|
||||
help
|
||||
Support CPU cores for armv8 architecture.
|
||||
|
||||
config CPU_MICROBLAZE
|
||||
bool "Enable Microblaze CPU driver"
|
||||
depends on CPU && MICROBLAZE
|
||||
|
|
|
@ -6,10 +6,12 @@
|
|||
|
||||
obj-$(CONFIG_CPU) += cpu-uclass.o
|
||||
|
||||
obj-$(CONFIG_ARCH_BCM283X) += bcm283x_cpu.o
|
||||
obj-$(CONFIG_ARCH_BMIPS) += bmips_cpu.o
|
||||
obj-$(CONFIG_ARCH_IMX8) += imx8_cpu.o
|
||||
obj-$(CONFIG_ARCH_AT91) += at91_cpu.o
|
||||
obj-$(CONFIG_ARCH_MEDIATEK) += mtk_cpu.o
|
||||
obj-$(CONFIG_CPU_ARMV8) += armv8_cpu.o
|
||||
obj-$(CONFIG_CPU_IMX) += imx8_cpu.o
|
||||
obj-$(CONFIG_CPU_MPC83XX) += mpc83xx_cpu.o
|
||||
obj-$(CONFIG_CPU_RISCV) += riscv_cpu.o
|
||||
|
|
151
drivers/cpu/armv8_cpu.c
Normal file
151
drivers/cpu/armv8_cpu.c
Normal file
|
@ -0,0 +1,151 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright 2024 9elements GmbH
|
||||
*/
|
||||
#include <cpu.h>
|
||||
#include <dm.h>
|
||||
#include <irq.h>
|
||||
#include <acpi/acpigen.h>
|
||||
#include <asm/armv8/cpu.h>
|
||||
#include <asm/io.h>
|
||||
#include <dm/acpi.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/printk.h>
|
||||
#include <linux/sizes.h>
|
||||
|
||||
static int armv8_cpu_get_desc(const struct udevice *dev, char *buf, int size)
|
||||
{
|
||||
int cpuid;
|
||||
|
||||
cpuid = (read_midr() & MIDR_PARTNUM_MASK) >> MIDR_PARTNUM_SHIFT;
|
||||
|
||||
snprintf(buf, size, "CPU MIDR %04x", cpuid);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int armv8_cpu_get_info(const struct udevice *dev,
|
||||
struct cpu_info *info)
|
||||
{
|
||||
info->cpu_freq = 0;
|
||||
info->features = BIT(CPU_FEAT_L1_CACHE) | BIT(CPU_FEAT_MMU);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int armv8_cpu_get_count(const struct udevice *dev)
|
||||
{
|
||||
return uclass_id_count(UCLASS_CPU);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ACPIGEN
|
||||
int armv8_cpu_fill_ssdt(const struct udevice *dev, struct acpi_ctx *ctx)
|
||||
{
|
||||
uint core_id = dev_seq(dev);
|
||||
|
||||
acpigen_write_processor_device(ctx, core_id);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int armv8_cpu_fill_madt(const struct udevice *dev, struct acpi_ctx *ctx)
|
||||
{
|
||||
struct acpi_madt_gicc *gicc;
|
||||
struct cpu_plat *cpu_plat;
|
||||
struct udevice *gic;
|
||||
u64 gicc_gicv = 0;
|
||||
u64 gicc_gich = 0;
|
||||
u64 gicc_gicr_base = 0;
|
||||
u64 gicc_phys_base = 0;
|
||||
u32 gicc_perf_gsiv = 0;
|
||||
u64 gicc_mpidr;
|
||||
u32 gicc_vgic_maint_irq = 0;
|
||||
int addr_index;
|
||||
fdt_addr_t addr;
|
||||
int ret;
|
||||
struct irq req_irq;
|
||||
|
||||
cpu_plat = dev_get_parent_plat(dev);
|
||||
if (!cpu_plat)
|
||||
return 0;
|
||||
|
||||
ret = irq_get_interrupt_parent(dev, &gic);
|
||||
if (ret) {
|
||||
log_err("%s: Failed to find interrupt parent for %s\n",
|
||||
__func__, dev->name);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
addr_index = 1;
|
||||
|
||||
if (device_is_compatible(gic, "arm,gic-v3")) {
|
||||
addr = dev_read_addr_index(gic, addr_index++);
|
||||
if (addr != FDT_ADDR_T_NONE)
|
||||
gicc_gicr_base = addr;
|
||||
}
|
||||
|
||||
addr = dev_read_addr_index(gic, addr_index++);
|
||||
if (addr != FDT_ADDR_T_NONE)
|
||||
gicc_phys_base = addr;
|
||||
|
||||
addr = dev_read_addr_index(gic, addr_index++);
|
||||
if (addr != FDT_ADDR_T_NONE)
|
||||
gicc_gich = addr;
|
||||
|
||||
addr = dev_read_addr_index(gic, addr_index++);
|
||||
if (addr != FDT_ADDR_T_NONE)
|
||||
gicc_gicv = addr;
|
||||
|
||||
ret = irq_get_by_index(gic, 0, &req_irq);
|
||||
if (!ret)
|
||||
gicc_vgic_maint_irq = req_irq.id;
|
||||
|
||||
gicc_mpidr = dev_read_u64_default(dev, "reg", 0);
|
||||
if (!gicc_mpidr)
|
||||
gicc_mpidr = dev_read_u32_default(dev, "reg", 0);
|
||||
|
||||
/*
|
||||
* gicc_vgic_maint_irq and gicc_gicv are the same for every CPU
|
||||
*/
|
||||
gicc = ctx->current;
|
||||
acpi_write_madt_gicc(gicc,
|
||||
dev_seq(dev),
|
||||
gicc_perf_gsiv, /* FIXME: needs a PMU driver */
|
||||
gicc_phys_base,
|
||||
gicc_gicv,
|
||||
gicc_gich,
|
||||
gicc_vgic_maint_irq,
|
||||
gicc_gicr_base,
|
||||
gicc_mpidr,
|
||||
0); /* FIXME: Not defined in DT */
|
||||
|
||||
acpi_inc(ctx, gicc->length);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct acpi_ops armv8_cpu_acpi_ops = {
|
||||
.fill_ssdt = armv8_cpu_fill_ssdt,
|
||||
.fill_madt = armv8_cpu_fill_madt,
|
||||
};
|
||||
#endif
|
||||
|
||||
static const struct cpu_ops cpu_ops = {
|
||||
.get_count = armv8_cpu_get_count,
|
||||
.get_desc = armv8_cpu_get_desc,
|
||||
.get_info = armv8_cpu_get_info,
|
||||
};
|
||||
|
||||
static const struct udevice_id cpu_ids[] = {
|
||||
{ .compatible = "arm,armv8" },
|
||||
{}
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(arm_cpu) = {
|
||||
.name = "arm-cpu",
|
||||
.id = UCLASS_CPU,
|
||||
.of_match = cpu_ids,
|
||||
.ops = &cpu_ops,
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
ACPI_OPS_PTR(&armv8_cpu_acpi_ops)
|
||||
};
|
31
drivers/cpu/armv8_cpu.h
Normal file
31
drivers/cpu/armv8_cpu.h
Normal file
|
@ -0,0 +1,31 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright 2024 9elements GmbH
|
||||
*/
|
||||
#include <dm/acpi.h>
|
||||
#include <dm/device.h>
|
||||
|
||||
#ifndef _ARMV8_CPU_H_
|
||||
#define _ARMV8_CPU_H_
|
||||
|
||||
/**
|
||||
* armv8_cpu_fill_ssdt() - Fill the SSDT
|
||||
* Parses the FDT and writes the SSDT nodes.
|
||||
*
|
||||
* @dev: cpu device to generate ACPI tables for
|
||||
* @ctx: ACPI context pointer
|
||||
* @return: 0 if OK, or a negative error code.
|
||||
*/
|
||||
int armv8_cpu_fill_ssdt(const struct udevice *dev, struct acpi_ctx *ctx);
|
||||
|
||||
/**
|
||||
* armv8_cpu_fill_madt() - Fill the MADT
|
||||
* Parses the FDT and writes the MADT subtables.
|
||||
*
|
||||
* @dev: cpu device to generate ACPI tables for
|
||||
* @ctx: ACPI context pointer
|
||||
* @return: 0 if OK, or a negative error code.
|
||||
*/
|
||||
int armv8_cpu_fill_madt(const struct udevice *dev, struct acpi_ctx *ctx);
|
||||
|
||||
#endif
|
214
drivers/cpu/bcm283x_cpu.c
Normal file
214
drivers/cpu/bcm283x_cpu.c
Normal file
|
@ -0,0 +1,214 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright 2024 9elements GmbH
|
||||
*/
|
||||
|
||||
#include <cpu.h>
|
||||
#include <cpu_func.h>
|
||||
#include <dm.h>
|
||||
#include <fdt_support.h>
|
||||
#include <acpi/acpigen.h>
|
||||
#include <asm/armv8/cpu.h>
|
||||
#include <asm/cache.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/global_data.h>
|
||||
#include <asm/system.h>
|
||||
#include <asm-generic/sections.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/delay.h>
|
||||
#include "armv8_cpu.h"
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
struct bcm_plat {
|
||||
u64 release_addr;
|
||||
};
|
||||
|
||||
static int cpu_bcm_get_desc(const struct udevice *dev, char *buf, int size)
|
||||
{
|
||||
struct cpu_plat *plat = dev_get_parent_plat(dev);
|
||||
const char *name;
|
||||
|
||||
if (size < 32)
|
||||
return -ENOSPC;
|
||||
|
||||
if (device_is_compatible(dev, "arm,cortex-a53"))
|
||||
name = "A53";
|
||||
else if (device_is_compatible(dev, "arm,cortex-a72"))
|
||||
name = "A72";
|
||||
else
|
||||
name = "?";
|
||||
|
||||
snprintf(buf, size, "Broadcom Cortex-%s at %u MHz\n",
|
||||
name, plat->timebase_freq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cpu_bcm_get_info(const struct udevice *dev, struct cpu_info *info)
|
||||
{
|
||||
struct cpu_plat *plat = dev_get_parent_plat(dev);
|
||||
|
||||
info->cpu_freq = plat->timebase_freq * 1000;
|
||||
info->features = BIT(CPU_FEAT_L1_CACHE) | BIT(CPU_FEAT_MMU);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cpu_bcm_get_count(const struct udevice *dev)
|
||||
{
|
||||
return uclass_id_count(UCLASS_CPU);
|
||||
}
|
||||
|
||||
static int cpu_bcm_get_vendor(const struct udevice *dev, char *buf, int size)
|
||||
{
|
||||
snprintf(buf, size, "Broadcom");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cpu_bcm_is_current(struct udevice *dev)
|
||||
{
|
||||
struct cpu_plat *plat = dev_get_parent_plat(dev);
|
||||
|
||||
if (plat->cpu_id == (read_mpidr() & 0xffff))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* bcm_cpu_on - Releases the secondary CPU from it's spintable
|
||||
*
|
||||
* Write the CPU's spintable mailbox and let the CPU enter U-Boot.
|
||||
*
|
||||
* @dev: Device to start
|
||||
* @return: zero on success or error code on failure.
|
||||
*/
|
||||
static int bcm_cpu_on(struct udevice *dev)
|
||||
{
|
||||
struct bcm_plat *plat = dev_get_plat(dev);
|
||||
ulong *start_address;
|
||||
|
||||
if (plat->release_addr == ~0ULL)
|
||||
return -ENODATA;
|
||||
|
||||
start_address = map_physmem(plat->release_addr, sizeof(uintptr_t), MAP_NOCACHE);
|
||||
|
||||
/* Point secondary CPU to U-Boot entry */
|
||||
*start_address = (uintptr_t)_start;
|
||||
|
||||
/* Make sure the other CPUs see the written start address */
|
||||
if (!CONFIG_IS_ENABLED(SYS_DCACHE_OFF))
|
||||
flush_dcache_all();
|
||||
|
||||
/* Send an event to wake up the secondary CPU. */
|
||||
asm("dsb ishst\n"
|
||||
"sev");
|
||||
|
||||
unmap_physmem(start_address, MAP_NOCACHE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct cpu_ops cpu_bcm_ops = {
|
||||
.get_desc = cpu_bcm_get_desc,
|
||||
.get_info = cpu_bcm_get_info,
|
||||
.get_count = cpu_bcm_get_count,
|
||||
.get_vendor = cpu_bcm_get_vendor,
|
||||
.is_current = cpu_bcm_is_current,
|
||||
};
|
||||
|
||||
static const struct udevice_id cpu_bcm_ids[] = {
|
||||
{ .compatible = "arm,cortex-a53" }, /* RPi 3 */
|
||||
{ .compatible = "arm,cortex-a72" }, /* RPi 4 */
|
||||
{ }
|
||||
};
|
||||
|
||||
static int bcm_cpu_bind(struct udevice *dev)
|
||||
{
|
||||
struct cpu_plat *plat = dev_get_parent_plat(dev);
|
||||
|
||||
plat->cpu_id = dev_read_addr(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* bcm_cpu_of_to_plat - Gather spin-table release address
|
||||
*
|
||||
* Read the spin-table release address to allow all seconary CPUs to enter
|
||||
* U-Boot when necessary.
|
||||
*
|
||||
* @dev: Device to start
|
||||
*/
|
||||
static int bcm_cpu_of_to_plat(struct udevice *dev)
|
||||
{
|
||||
struct bcm_plat *plat = dev_get_plat(dev);
|
||||
const char *prop;
|
||||
|
||||
if (CONFIG_IS_ENABLED(ARMV8_MULTIENTRY)) {
|
||||
plat->release_addr = ~0ULL;
|
||||
|
||||
prop = dev_read_string(dev, "enable-method");
|
||||
if (!prop || strcmp(prop, "spin-table"))
|
||||
return -ENODEV;
|
||||
|
||||
plat->release_addr = dev_read_u64_default(dev, "cpu-release-addr", ~0ULL);
|
||||
|
||||
if (plat->release_addr == ~0ULL)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bcm_cpu_probe(struct udevice *dev)
|
||||
{
|
||||
struct cpu_plat *plat = dev_get_parent_plat(dev);
|
||||
struct clk clk;
|
||||
int ret;
|
||||
|
||||
/* Get a clock if it exists */
|
||||
ret = clk_get_by_index(dev, 0, &clk);
|
||||
if (!ret) {
|
||||
ret = clk_enable(&clk);
|
||||
if (ret && (ret != -ENOSYS || ret != -EOPNOTSUPP))
|
||||
return ret;
|
||||
ret = clk_get_rate(&clk);
|
||||
if (IS_ERR_VALUE(ret))
|
||||
return ret;
|
||||
plat->timebase_freq = ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* The armstub holds the secondary CPUs in a spinloop. When
|
||||
* ARMV8_MULTIENTRY is enabled release the secondary CPUs and
|
||||
* let them enter U-Boot as well.
|
||||
*/
|
||||
if (CONFIG_IS_ENABLED(ARMV8_MULTIENTRY)) {
|
||||
ret = bcm_cpu_on(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct acpi_ops bcm283x_cpu_acpi_ops = {
|
||||
.fill_ssdt = armv8_cpu_fill_ssdt,
|
||||
.fill_madt = armv8_cpu_fill_madt,
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(cpu_bcm_drv) = {
|
||||
.name = "bcm283x_cpu",
|
||||
.id = UCLASS_CPU,
|
||||
.of_match = cpu_bcm_ids,
|
||||
.ops = &cpu_bcm_ops,
|
||||
.probe = bcm_cpu_probe,
|
||||
.bind = bcm_cpu_bind,
|
||||
.of_to_plat = bcm_cpu_of_to_plat,
|
||||
.plat_auto = sizeof(struct bcm_plat),
|
||||
ACPI_OPS_PTR(&bcm283x_cpu_acpi_ops)
|
||||
};
|
|
@ -62,6 +62,40 @@ int irq_read_and_clear(struct irq *irq)
|
|||
return ops->read_and_clear(irq);
|
||||
}
|
||||
|
||||
int irq_get_interrupt_parent(const struct udevice *dev,
|
||||
struct udevice **interrupt_parent)
|
||||
{
|
||||
struct ofnode_phandle_args phandle_args;
|
||||
struct udevice *irq = NULL;
|
||||
ofnode node;
|
||||
int ret;
|
||||
|
||||
if (!dev || !interrupt_parent)
|
||||
return -EINVAL;
|
||||
|
||||
*interrupt_parent = NULL;
|
||||
|
||||
node = dev_ofnode(dev);
|
||||
if (!ofnode_valid(node))
|
||||
return -EINVAL;
|
||||
|
||||
while (ofnode_valid(node)) {
|
||||
ret = ofnode_parse_phandle_with_args(node, "interrupt-parent",
|
||||
NULL, 0, 0, &phandle_args);
|
||||
if (!ret && !device_get_global_by_ofnode(phandle_args.node, &irq))
|
||||
break;
|
||||
node = ofnode_get_parent(node);
|
||||
}
|
||||
|
||||
if (!irq) {
|
||||
log_err("Cannot find an interrupt parent for device %s\n", dev->name);
|
||||
return -ENODEV;
|
||||
}
|
||||
*interrupt_parent = irq;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if CONFIG_IS_ENABLED(OF_PLATDATA)
|
||||
int irq_get_by_phandle(struct udevice *dev, const struct phandle_2_arg *cells,
|
||||
struct irq *irq)
|
||||
|
@ -142,10 +176,40 @@ err:
|
|||
int irq_get_by_index(struct udevice *dev, int index, struct irq *irq)
|
||||
{
|
||||
struct ofnode_phandle_args args;
|
||||
int ret;
|
||||
struct udevice *interrupt_parent;
|
||||
int ret, size, i;
|
||||
const __be32 *list;
|
||||
u32 count;
|
||||
|
||||
ret = dev_read_phandle_with_args(dev, "interrupts-extended",
|
||||
"#interrupt-cells", 0, index, &args);
|
||||
if (ret) {
|
||||
list = dev_read_prop(dev, "interrupts", &size);
|
||||
if (!list)
|
||||
return -ENOENT;
|
||||
|
||||
ret = irq_get_interrupt_parent(dev, &interrupt_parent);
|
||||
if (ret)
|
||||
return -ENODEV;
|
||||
args.node = dev_ofnode(interrupt_parent);
|
||||
|
||||
if (dev_read_u32(interrupt_parent, "#interrupt-cells", &count)) {
|
||||
log_err("%s: could not get #interrupt-cells for %s\n",
|
||||
__func__, dev->name);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
if (index * count >= size / sizeof(*list))
|
||||
return -ENOENT;
|
||||
if (count > OF_MAX_PHANDLE_ARGS)
|
||||
count = OF_MAX_PHANDLE_ARGS;
|
||||
args.args_count = count;
|
||||
for (i = 0; i < count; i++)
|
||||
args.args[i] = be32_to_cpup(&list[index * count + i]);
|
||||
|
||||
return irq_get_by_index_tail(ret, dev_ofnode(dev), &args,
|
||||
"interrupts", index, irq);
|
||||
}
|
||||
|
||||
return irq_get_by_index_tail(ret, dev_ofnode(dev), &args,
|
||||
"interrupts-extended", index > 0, irq);
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
* Copyright (C) 2020 Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
|
||||
*/
|
||||
|
||||
#include <asm/arch/acpi/bcm2711.h>
|
||||
#include <errno.h>
|
||||
#include <dm.h>
|
||||
#include <dm/ofnode.h>
|
||||
|
@ -21,88 +22,6 @@
|
|||
#include <linux/log2.h>
|
||||
#include <linux/iopoll.h>
|
||||
|
||||
/* Offset of the mandatory PCIe capability config registers */
|
||||
#define BRCM_PCIE_CAP_REGS 0x00ac
|
||||
|
||||
/* The PCIe controller register offsets */
|
||||
#define PCIE_RC_CFG_VENDOR_SPECIFIC_REG1 0x0188
|
||||
#define VENDOR_SPECIFIC_REG1_ENDIAN_MODE_BAR2_MASK 0xc
|
||||
#define VENDOR_SPECIFIC_REG1_LITTLE_ENDIAN 0x0
|
||||
|
||||
#define PCIE_RC_CFG_PRIV1_ID_VAL3 0x043c
|
||||
#define CFG_PRIV1_ID_VAL3_CLASS_CODE_MASK 0xffffff
|
||||
|
||||
#define PCIE_RC_CFG_PRIV1_LINK_CAPABILITY 0x04dc
|
||||
#define PCIE_RC_CFG_PRIV1_LINK_CAPABILITY_ASPM_SUPPORT_MASK 0xc00
|
||||
|
||||
#define PCIE_RC_DL_MDIO_ADDR 0x1100
|
||||
#define PCIE_RC_DL_MDIO_WR_DATA 0x1104
|
||||
#define PCIE_RC_DL_MDIO_RD_DATA 0x1108
|
||||
|
||||
#define PCIE_MISC_MISC_CTRL 0x4008
|
||||
#define MISC_CTRL_SCB_ACCESS_EN_MASK 0x1000
|
||||
#define MISC_CTRL_CFG_READ_UR_MODE_MASK 0x2000
|
||||
#define MISC_CTRL_MAX_BURST_SIZE_MASK 0x300000
|
||||
#define MISC_CTRL_MAX_BURST_SIZE_128 0x0
|
||||
#define MISC_CTRL_SCB0_SIZE_MASK 0xf8000000
|
||||
|
||||
#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LO 0x400c
|
||||
#define PCIE_MEM_WIN0_LO(win) \
|
||||
PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LO + ((win) * 4)
|
||||
|
||||
#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_HI 0x4010
|
||||
#define PCIE_MEM_WIN0_HI(win) \
|
||||
PCIE_MISC_CPU_2_PCIE_MEM_WIN0_HI + ((win) * 4)
|
||||
|
||||
#define PCIE_MISC_RC_BAR1_CONFIG_LO 0x402c
|
||||
#define RC_BAR1_CONFIG_LO_SIZE_MASK 0x1f
|
||||
|
||||
#define PCIE_MISC_RC_BAR2_CONFIG_LO 0x4034
|
||||
#define RC_BAR2_CONFIG_LO_SIZE_MASK 0x1f
|
||||
#define PCIE_MISC_RC_BAR2_CONFIG_HI 0x4038
|
||||
|
||||
#define PCIE_MISC_RC_BAR3_CONFIG_LO 0x403c
|
||||
#define RC_BAR3_CONFIG_LO_SIZE_MASK 0x1f
|
||||
|
||||
#define PCIE_MISC_PCIE_STATUS 0x4068
|
||||
#define STATUS_PCIE_PORT_MASK 0x80
|
||||
#define STATUS_PCIE_PORT_SHIFT 7
|
||||
#define STATUS_PCIE_DL_ACTIVE_MASK 0x20
|
||||
#define STATUS_PCIE_DL_ACTIVE_SHIFT 5
|
||||
#define STATUS_PCIE_PHYLINKUP_MASK 0x10
|
||||
#define STATUS_PCIE_PHYLINKUP_SHIFT 4
|
||||
|
||||
#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT 0x4070
|
||||
#define MEM_WIN0_BASE_LIMIT_LIMIT_MASK 0xfff00000
|
||||
#define MEM_WIN0_BASE_LIMIT_BASE_MASK 0xfff0
|
||||
#define MEM_WIN0_BASE_LIMIT_BASE_HI_SHIFT 12
|
||||
#define PCIE_MEM_WIN0_BASE_LIMIT(win) \
|
||||
PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT + ((win) * 4)
|
||||
|
||||
#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_HI 0x4080
|
||||
#define MEM_WIN0_BASE_HI_BASE_MASK 0xff
|
||||
#define PCIE_MEM_WIN0_BASE_HI(win) \
|
||||
PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_HI + ((win) * 8)
|
||||
|
||||
#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI 0x4084
|
||||
#define PCIE_MEM_WIN0_LIMIT_HI_LIMIT_MASK 0xff
|
||||
#define PCIE_MEM_WIN0_LIMIT_HI(win) \
|
||||
PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI + ((win) * 8)
|
||||
|
||||
#define PCIE_MISC_HARD_PCIE_HARD_DEBUG 0x4204
|
||||
#define PCIE_HARD_DEBUG_SERDES_IDDQ_MASK 0x08000000
|
||||
|
||||
#define PCIE_MSI_INTR2_CLR 0x4508
|
||||
#define PCIE_MSI_INTR2_MASK_SET 0x4510
|
||||
|
||||
#define PCIE_EXT_CFG_DATA 0x8000
|
||||
|
||||
#define PCIE_EXT_CFG_INDEX 0x9000
|
||||
|
||||
#define PCIE_RGR1_SW_INIT_1 0x9210
|
||||
#define RGR1_SW_INIT_1_PERST_MASK 0x1
|
||||
#define RGR1_SW_INIT_1_INIT_MASK 0x2
|
||||
|
||||
/* PCIe parameters */
|
||||
#define BRCM_NUM_PCIE_OUT_WINS 4
|
||||
|
||||
|
@ -447,7 +366,7 @@ static int brcm_pcie_probe(struct udevice *dev)
|
|||
* This will need to be changed when support for other SoCs is added.
|
||||
*/
|
||||
setbits_le32(base + PCIE_RGR1_SW_INIT_1,
|
||||
RGR1_SW_INIT_1_INIT_MASK | RGR1_SW_INIT_1_PERST_MASK);
|
||||
PCIE_RGR1_SW_INIT_1_INIT_MASK | PCIE_RGR1_SW_INIT_1_PERST_MASK);
|
||||
/*
|
||||
* The delay is a safety precaution to preclude the reset signal
|
||||
* from looking like a glitch.
|
||||
|
@ -455,7 +374,7 @@ static int brcm_pcie_probe(struct udevice *dev)
|
|||
udelay(100);
|
||||
|
||||
/* Take the bridge out of reset */
|
||||
clrbits_le32(base + PCIE_RGR1_SW_INIT_1, RGR1_SW_INIT_1_INIT_MASK);
|
||||
clrbits_le32(base + PCIE_RGR1_SW_INIT_1, PCIE_RGR1_SW_INIT_1_INIT_MASK);
|
||||
|
||||
clrbits_le32(base + PCIE_MISC_HARD_PCIE_HARD_DEBUG,
|
||||
PCIE_HARD_DEBUG_SERDES_IDDQ_MASK);
|
||||
|
@ -508,7 +427,7 @@ static int brcm_pcie_probe(struct udevice *dev)
|
|||
|
||||
/* Unassert the fundamental reset */
|
||||
clrbits_le32(pcie->base + PCIE_RGR1_SW_INIT_1,
|
||||
RGR1_SW_INIT_1_PERST_MASK);
|
||||
PCIE_RGR1_SW_INIT_1_PERST_MASK);
|
||||
|
||||
/*
|
||||
* Wait for 100ms after PERST# deassertion; see PCIe CEM specification
|
||||
|
@ -552,7 +471,7 @@ static int brcm_pcie_probe(struct udevice *dev)
|
|||
* a PCIe-PCIe bridge (the default setting is to be EP mode).
|
||||
*/
|
||||
clrsetbits_le32(base + PCIE_RC_CFG_PRIV1_ID_VAL3,
|
||||
CFG_PRIV1_ID_VAL3_CLASS_CODE_MASK, 0x060400);
|
||||
PCIE_RC_CFG_PRIV1_ID_VAL3_CLASS_CODE_MASK, 0x060400);
|
||||
|
||||
if (pcie->ssc) {
|
||||
ret = brcm_pcie_set_ssc(pcie->base);
|
||||
|
@ -570,8 +489,8 @@ static int brcm_pcie_probe(struct udevice *dev)
|
|||
nlw, ssc_good ? "(SSC)" : "(!SSC)");
|
||||
|
||||
/* PCIe->SCB endian mode for BAR */
|
||||
clrsetbits_le32(base + PCIE_RC_CFG_VENDOR_SPECIFIC_REG1,
|
||||
VENDOR_SPECIFIC_REG1_ENDIAN_MODE_BAR2_MASK,
|
||||
clrsetbits_le32(base + PCIE_RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1,
|
||||
PCIE_RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1_ENDIAN_MODE_BAR2_MASK,
|
||||
VENDOR_SPECIFIC_REG1_LITTLE_ENDIAN);
|
||||
|
||||
/*
|
||||
|
@ -584,7 +503,7 @@ static int brcm_pcie_probe(struct udevice *dev)
|
|||
* let's instead just unadvertise ASPM support.
|
||||
*/
|
||||
clrbits_le32(base + PCIE_RC_CFG_PRIV1_LINK_CAPABILITY,
|
||||
PCIE_RC_CFG_PRIV1_LINK_CAPABILITY_ASPM_SUPPORT_MASK);
|
||||
LINK_CAPABILITY_ASPM_SUPPORT_MASK);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -595,14 +514,14 @@ static int brcm_pcie_remove(struct udevice *dev)
|
|||
void __iomem *base = pcie->base;
|
||||
|
||||
/* Assert fundamental reset */
|
||||
setbits_le32(base + PCIE_RGR1_SW_INIT_1, RGR1_SW_INIT_1_PERST_MASK);
|
||||
setbits_le32(base + PCIE_RGR1_SW_INIT_1, PCIE_RGR1_SW_INIT_1_PERST_MASK);
|
||||
|
||||
/* Turn off SerDes */
|
||||
setbits_le32(base + PCIE_MISC_HARD_PCIE_HARD_DEBUG,
|
||||
PCIE_HARD_DEBUG_SERDES_IDDQ_MASK);
|
||||
|
||||
/* Shutdown bridge */
|
||||
setbits_le32(base + PCIE_RGR1_SW_INIT_1, RGR1_SW_INIT_1_INIT_MASK);
|
||||
setbits_le32(base + PCIE_RGR1_SW_INIT_1, PCIE_RGR1_SW_INIT_1_INIT_MASK);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include <watchdog.h>
|
||||
#include <asm/io.h>
|
||||
#include <serial.h>
|
||||
#include <spl.h>
|
||||
#include <dm/device_compat.h>
|
||||
#include <dm/platform_data/serial_pl01x.h>
|
||||
#include <linux/compiler.h>
|
||||
|
@ -272,6 +273,28 @@ __weak struct serial_device *default_serial_console(void)
|
|||
return &pl01x_serial_drv;
|
||||
}
|
||||
#else
|
||||
|
||||
static int pl01x_serial_getinfo(struct udevice *dev,
|
||||
struct serial_device_info *info)
|
||||
{
|
||||
struct pl01x_serial_plat *plat = dev_get_plat(dev);
|
||||
|
||||
/* save code size */
|
||||
if (!not_xpl())
|
||||
return -ENOSYS;
|
||||
|
||||
info->type = SERIAL_CHIP_PL01X;
|
||||
info->addr_space = SERIAL_ADDRESS_SPACE_MEMORY;
|
||||
info->addr = plat->base;
|
||||
info->size = 0x1000;
|
||||
info->reg_width = 4;
|
||||
info->reg_shift = 2;
|
||||
info->reg_offset = 0;
|
||||
info->clock = plat->clock;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pl01x_serial_setbrg(struct udevice *dev, int baudrate)
|
||||
{
|
||||
struct pl01x_serial_plat *plat = dev_get_plat(dev);
|
||||
|
@ -341,6 +364,7 @@ static const struct dm_serial_ops pl01x_serial_ops = {
|
|||
.pending = pl01x_serial_pending,
|
||||
.getc = pl01x_serial_getc,
|
||||
.setbrg = pl01x_serial_setbrg,
|
||||
.getinfo = pl01x_serial_getinfo,
|
||||
};
|
||||
|
||||
#if CONFIG_IS_ENABLED(OF_REAL)
|
||||
|
|
|
@ -68,6 +68,14 @@ config USB_XHCI_MVEBU
|
|||
SoCs, which includes Armada8K, Armada3700 and other Armada
|
||||
family SoCs.
|
||||
|
||||
config USB_XHCI_GENERIC
|
||||
bool "Generic SoC USB 3.0 support"
|
||||
depends on OF_CONTROL
|
||||
default n
|
||||
help
|
||||
Choose this option to add support for USB 3.0 driver for SoCs
|
||||
that do not need platform specific code, like on emulated targets.
|
||||
|
||||
config USB_XHCI_OCTEON
|
||||
bool "Support for Marvell Octeon family on-chip xHCI USB controller"
|
||||
depends on ARCH_OCTEON
|
||||
|
|
|
@ -50,6 +50,7 @@ obj-$(CONFIG_USB_XHCI_EXYNOS) += xhci-exynos5.o
|
|||
obj-$(CONFIG_USB_XHCI_FSL) += xhci-fsl.o
|
||||
obj-$(CONFIG_USB_XHCI_MTK) += xhci-mtk.o
|
||||
obj-$(CONFIG_USB_XHCI_MVEBU) += xhci-mvebu.o
|
||||
obj-$(CONFIG_USB_XHCI_GENERIC) += xhci-generic.o
|
||||
obj-$(CONFIG_USB_XHCI_OMAP) += xhci-omap.o
|
||||
obj-$(CONFIG_USB_XHCI_PCI) += xhci-pci.o
|
||||
obj-$(CONFIG_USB_XHCI_RCAR) += xhci-rcar.o
|
||||
|
|
75
drivers/usb/host/xhci-generic.c
Normal file
75
drivers/usb/host/xhci-generic.c
Normal file
|
@ -0,0 +1,75 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2024 9elements GmbH
|
||||
*
|
||||
* GENERIC USB HOST xHCI Controller
|
||||
*/
|
||||
#include <dm.h>
|
||||
#include <fdtdec.h>
|
||||
#include <log.h>
|
||||
#include <usb.h>
|
||||
#include <asm/io.h>
|
||||
#include <dm/device_compat.h>
|
||||
#include <usb/xhci.h>
|
||||
|
||||
struct generic_xhci_plat {
|
||||
fdt_addr_t hcd_base;
|
||||
};
|
||||
|
||||
/**
|
||||
* Contains pointers to register base addresses
|
||||
* for the usb controller.
|
||||
*/
|
||||
struct generic_xhci {
|
||||
struct xhci_ctrl ctrl; /* Needs to come first in this struct! */
|
||||
struct usb_plat usb_plat;
|
||||
struct xhci_hccr *hcd;
|
||||
};
|
||||
|
||||
static int xhci_usb_probe(struct udevice *dev)
|
||||
{
|
||||
struct generic_xhci_plat *plat = dev_get_plat(dev);
|
||||
struct generic_xhci *ctx = dev_get_priv(dev);
|
||||
struct xhci_hcor *hcor;
|
||||
int len;
|
||||
|
||||
ctx->hcd = (struct xhci_hccr *)phys_to_virt(plat->hcd_base);
|
||||
len = HC_LENGTH(xhci_readl(&ctx->hcd->cr_capbase));
|
||||
hcor = (struct xhci_hcor *)((uintptr_t)ctx->hcd + len);
|
||||
|
||||
return xhci_register(dev, ctx->hcd, hcor);
|
||||
}
|
||||
|
||||
static int xhci_usb_of_to_plat(struct udevice *dev)
|
||||
{
|
||||
struct generic_xhci_plat *plat = dev_get_plat(dev);
|
||||
|
||||
/*
|
||||
* Get the base address for XHCI controller from the device node
|
||||
*/
|
||||
plat->hcd_base = dev_read_addr(dev);
|
||||
if (plat->hcd_base == FDT_ADDR_T_NONE) {
|
||||
dev_dbg(dev, "Can't get the XHCI register base address\n");
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct udevice_id xhci_usb_ids[] = {
|
||||
{ .compatible = "generic-xhci" },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(usb_xhci) = {
|
||||
.name = "xhci_generic",
|
||||
.id = UCLASS_USB,
|
||||
.of_match = xhci_usb_ids,
|
||||
.of_to_plat = xhci_usb_of_to_plat,
|
||||
.probe = xhci_usb_probe,
|
||||
.remove = xhci_deregister,
|
||||
.ops = &xhci_usb_ops,
|
||||
.plat_auto = sizeof(struct generic_xhci_plat),
|
||||
.priv_auto = sizeof(struct generic_xhci),
|
||||
.flags = DM_FLAG_ALLOC_PRIV_DMA,
|
||||
};
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue