Merge tag 'u-boot-amlogic-next-20251219' of https://source.denx.de/u-boot/custodians/u-boot-amlogic into next
- Add u-boot SPL support for GX SoCs - meson_gx_mmc: reduce maximum frequency - Add support for EFI capsule updates on all Amlogic boards
This commit is contained in:
@@ -186,6 +186,7 @@ F: drivers/video/meson/
|
||||
F: drivers/watchdog/meson_gxbb_wdt.c
|
||||
F: include/configs/meson64.h
|
||||
F: include/configs/meson64_android.h
|
||||
F: tools/amlimage*
|
||||
F: doc/board/amlogic/
|
||||
N: meson
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
/*
|
||||
* Copyright (c) 2019 BayLibre, SAS.
|
||||
* Author: Maxime Jourdan <mjourdan@baylibre.com>
|
||||
* Copyright (c) 2023 Ferass El Hafidi <funderscore@postmarketos.org>
|
||||
*/
|
||||
|
||||
/ {
|
||||
@@ -15,6 +16,12 @@
|
||||
soc {
|
||||
bootph-all;
|
||||
};
|
||||
|
||||
#if defined(CONFIG_BINMAN)
|
||||
binman: binman {
|
||||
multiple-images;
|
||||
};
|
||||
#endif
|
||||
};
|
||||
|
||||
&vpu {
|
||||
@@ -30,3 +37,121 @@
|
||||
<0x0 0xc883c000 0x0 0x1000>;
|
||||
reg-names = "hdmitx", "hhi";
|
||||
};
|
||||
|
||||
#if defined(CONFIG_BINMAN)
|
||||
/* binman configuration on GXBB and GXL */
|
||||
|
||||
&binman {
|
||||
u-boot-amlogic {
|
||||
filename = "u-boot-meson-with-spl.bin";
|
||||
pad-byte = <0xff>;
|
||||
|
||||
mkimage {
|
||||
filename = "spl/u-boot-spl-signed.bin";
|
||||
/* args are per-SoC, and defined in meson-(gxbb/gxl)-u-boot.dtsi */
|
||||
|
||||
u-boot-spl {
|
||||
};
|
||||
};
|
||||
|
||||
fit: fit {
|
||||
description = "ATF and U-Boot images";
|
||||
#address-cells = <1>;
|
||||
fit,fdt-list = "of-list";
|
||||
fit,external-offset = <CONFIG_FIT_EXTERNAL_OFFSET>;
|
||||
fit,align = <512>;
|
||||
offset = <CONFIG_SPL_PAD_TO>;
|
||||
|
||||
images {
|
||||
u-boot {
|
||||
description = "U-Boot";
|
||||
type = "standalone";
|
||||
os = "u-boot";
|
||||
arch = "arm64";
|
||||
compression = "none";
|
||||
load = <CONFIG_TEXT_BASE>;
|
||||
entry = <CONFIG_TEXT_BASE>;
|
||||
|
||||
u-boot-nodtb {
|
||||
};
|
||||
|
||||
#if CONFIG_IS_ENABLED(FIT_SIGNATURE) && CONFIG_IS_ENABLED(SHA256)
|
||||
hash {
|
||||
algo = "sha256";
|
||||
};
|
||||
#endif
|
||||
};
|
||||
|
||||
atf {
|
||||
description = "ARM Trusted Firmware";
|
||||
type = "firmware";
|
||||
os = "arm-trusted-firmware";
|
||||
arch = "arm64";
|
||||
compression = "none";
|
||||
/*
|
||||
* load and entry are SoC-specific, and thus
|
||||
* defined in meson-(gxbb/gxl)-u-boot.dtsi
|
||||
*/
|
||||
|
||||
atf-bl31 {
|
||||
filename = "bl31.bin";
|
||||
};
|
||||
|
||||
#if CONFIG_IS_ENABLED(FIT_SIGNATURE) && CONFIG_IS_ENABLED(SHA256)
|
||||
hash {
|
||||
algo = "sha256";
|
||||
};
|
||||
#endif
|
||||
};
|
||||
|
||||
scp {
|
||||
description = "SCP BL30 Firmware";
|
||||
type = "scp";
|
||||
arch = "arm"; /* The Cortex-M core is used as SCP */
|
||||
compression = "none";
|
||||
/*
|
||||
* On GXBB the base address of the SCP firmware doesn't matter as SPL will
|
||||
* send the firmware to the SCP anyway, and can get the base address from the
|
||||
* FIT. On GXL it matters, as BL31 is supposed to send the firmware, so set the
|
||||
* base address to what GXL BL2 would load the binary to.
|
||||
*/
|
||||
load = <0x13c0000>;
|
||||
|
||||
scp {
|
||||
filename = "scp.bin";
|
||||
};
|
||||
hash {
|
||||
/*
|
||||
* The hash is used by the SCP and passed to it
|
||||
* by U-Boot SPL.
|
||||
*/
|
||||
algo = "sha256";
|
||||
};
|
||||
};
|
||||
|
||||
@fdt-SEQ {
|
||||
description = "NAME";
|
||||
type = "flat_dt";
|
||||
compression = "none";
|
||||
|
||||
#if CONFIG_IS_ENABLED(FIT_SIGNATURE) && CONFIG_IS_ENABLED(SHA256)
|
||||
hash {
|
||||
algo = "sha256";
|
||||
};
|
||||
#endif
|
||||
};
|
||||
|
||||
};
|
||||
configurations {
|
||||
default = "@config-DEFAULT-SEQ";
|
||||
@config-SEQ {
|
||||
description = "NAME.dtb";
|
||||
fdt = "fdt-SEQ";
|
||||
firmware = "atf";
|
||||
loadables = "scp", "u-boot";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* Author: Neil Armstrong <narmstrong@baylibre.com>
|
||||
*/
|
||||
|
||||
#include "meson-gx-u-boot.dtsi"
|
||||
#include "meson-gxbb-u-boot.dtsi"
|
||||
|
||||
ðmac {
|
||||
snps,reset-gpio = <&gpio GPIOZ_14 0>;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* Author: Neil Armstrong <narmstrong@baylibre.com>
|
||||
*/
|
||||
|
||||
#include "meson-gx-u-boot.dtsi"
|
||||
#include "meson-gxbb-u-boot.dtsi"
|
||||
|
||||
ðmac {
|
||||
snps,reset-gpio = <&gpio GPIOZ_14 0>;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* Author: Neil Armstrong <narmstrong@baylibre.com>
|
||||
*/
|
||||
|
||||
#include "meson-gx-u-boot.dtsi"
|
||||
#include "meson-gxbb-u-boot.dtsi"
|
||||
|
||||
/ {
|
||||
smbios {
|
||||
|
||||
@@ -4,4 +4,4 @@
|
||||
* Author: Neil Armstrong <narmstrong@baylibre.com>
|
||||
*/
|
||||
|
||||
#include "meson-gx-u-boot.dtsi"
|
||||
#include "meson-gxbb-u-boot.dtsi"
|
||||
|
||||
@@ -4,4 +4,4 @@
|
||||
* Author: Neil Armstrong <narmstrong@baylibre.com>
|
||||
*/
|
||||
|
||||
#include "meson-gx-u-boot.dtsi"
|
||||
#include "meson-gxbb-u-boot.dtsi"
|
||||
|
||||
27
arch/arm/dts/meson-gxbb-u-boot.dtsi
Normal file
27
arch/arm/dts/meson-gxbb-u-boot.dtsi
Normal file
@@ -0,0 +1,27 @@
|
||||
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
|
||||
/*
|
||||
* Copyright (c) 2019 BayLibre, SAS.
|
||||
* Author: Neil Armstrong <narmstrong@baylibre.com>
|
||||
*/
|
||||
|
||||
#include "meson-gx-u-boot.dtsi"
|
||||
|
||||
#if defined(CONFIG_BINMAN)
|
||||
/* GXBB-specific binman configuration */
|
||||
&binman {
|
||||
u-boot-amlogic {
|
||||
mkimage {
|
||||
args = "-n", "gxbb", "-T", "amlimage";
|
||||
};
|
||||
|
||||
fit: fit {
|
||||
images {
|
||||
atf {
|
||||
load = <0x10100000>;
|
||||
entry = <0x10100000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
#endif
|
||||
@@ -4,7 +4,7 @@
|
||||
* Author: Neil Armstrong <narmstrong@baylibre.com>
|
||||
*/
|
||||
|
||||
#include "meson-gx-u-boot.dtsi"
|
||||
#include "meson-gxbb-u-boot.dtsi"
|
||||
|
||||
ðmac {
|
||||
snps,reset-gpio = <&gpio GPIOZ_14 0>;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* Author: Neil Armstrong <narmstrong@baylibre.com>
|
||||
*/
|
||||
|
||||
#include "meson-gx-u-boot.dtsi"
|
||||
#include "meson-gxbb-u-boot.dtsi"
|
||||
|
||||
ðmac {
|
||||
snps,reset-gpio = <&gpio GPIOZ_14 0>;
|
||||
|
||||
@@ -5,3 +5,23 @@
|
||||
*/
|
||||
|
||||
#include "meson-gx-u-boot.dtsi"
|
||||
|
||||
#if defined(CONFIG_BINMAN)
|
||||
/* GXL-specific binman configuration */
|
||||
&binman {
|
||||
u-boot-amlogic {
|
||||
mkimage {
|
||||
args = "-n", "gxl", "-T", "amlimage";
|
||||
};
|
||||
|
||||
fit: fit {
|
||||
images {
|
||||
atf {
|
||||
load = <0x5100000>;
|
||||
entry = <0x5100000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -21,6 +21,8 @@ int meson_get_boot_device(void);
|
||||
|
||||
int meson_get_soc_rev(char *buff, size_t buff_len);
|
||||
|
||||
void meson_setup_capsule(void);
|
||||
|
||||
/**
|
||||
* meson_get_socinfo - retrieve cpu_id of the Amlogic SoC
|
||||
*
|
||||
|
||||
@@ -87,6 +87,7 @@
|
||||
#define HHI_VDAC_CNTL0 0x2F4 /* 0xbd offset in data sheet */
|
||||
#define HHI_VDAC_CNTL1 0x2F8 /* 0xbe offset in data sheet */
|
||||
|
||||
#define HHI_SYS_PLL_CNTL1 0x2fc /* 0xbf offset in data sheet */
|
||||
#define HHI_SYS_PLL_CNTL 0x300 /* 0xc0 offset in data sheet */
|
||||
#define HHI_SYS_PLL_CNTL2 0x304 /* 0xc1 offset in data sheet */
|
||||
#define HHI_SYS_PLL_CNTL3 0x308 /* 0xc2 offset in data sheet */
|
||||
@@ -114,4 +115,17 @@
|
||||
|
||||
ulong meson_measure_clk_rate(unsigned int clk);
|
||||
|
||||
#if defined(CONFIG_SPL_BUILD)
|
||||
#define HHI_SCC_CNTL0_FINAL_MUX_SEL BIT(11)
|
||||
#define HHI_SCC_CNTL0_FINAL_DYN_MUX_SEL BIT(10)
|
||||
#define HHI_SCC_CNTL0_MUX0_DIVN_TCNT (0x3f << 4)
|
||||
#define HHI_SCC_CNTL0_MUX1_DIVN_TCNT (0x3f << 20)
|
||||
#define HHI_SCC_CNTL0_POSTMUX0 BIT(2)
|
||||
#define HHI_SCC_CNTL0_POSTMUX1 BIT(18)
|
||||
#define HHI_SCC_CNTL0_PREMUX0 3
|
||||
#define HHI_SCC_CNTL0_PREMUX1 (3 << 16)
|
||||
#define HHI_SCC_CNTL0_DYN_ENABLE BIT(26)
|
||||
#define HHI_SCC_CNTL0_BUSY BIT(28)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
341
arch/arm/include/asm/arch-meson/dram-gx.h
Normal file
341
arch/arm/include/asm/arch-meson/dram-gx.h
Normal file
@@ -0,0 +1,341 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright (C) 2015, Amlogic, Inc. All rights reserved.
|
||||
* Copyright (C) 2023, Ferass El Hafidi <funderscore@postmarketos.org>
|
||||
*/
|
||||
#ifndef DRAM_GX_H
|
||||
#define DRAM_GX_H
|
||||
|
||||
/*
|
||||
* Registers
|
||||
*/
|
||||
|
||||
/* PCTL */
|
||||
#define DDR0_PCTL_BASE 0xc8839000
|
||||
/* DDR1_PCTL_BASE is DDR0_PCTL_BASE + 0x400 */
|
||||
|
||||
/* DMC */
|
||||
#define DMC_REG_BASE 0xc8838000
|
||||
|
||||
#define DMC_REQ_CTRL (DMC_REG_BASE + (0x00 << 2))
|
||||
#define DMC_SOFT_RST (DMC_REG_BASE + (0x01 << 2))
|
||||
#define DMC_SOFT_RST1 (DMC_REG_BASE + (0x02 << 2))
|
||||
#define DMC_RST_STS (DMC_REG_BASE + (0x03 << 2))
|
||||
#define DMC_VERSION (DMC_REG_BASE + (0x05 << 2))
|
||||
|
||||
#define DMC_REFR_CTRL1 (DMC_REG_BASE + (0x23 << 2))
|
||||
#define DMC_REFR_CTRL2 (DMC_REG_BASE + (0x24 << 2))
|
||||
|
||||
#define DMC_PCTL_LP_CTRL (DMC_REG_BASE + (0x46 << 2))
|
||||
|
||||
#define DMC_AM0_QOS_INC (DMC_REG_BASE + (0x62 << 2))
|
||||
#define DMC_AM0_QOS_DEC (DMC_REG_BASE + (0x64 << 2))
|
||||
#define DMC_AM0_QOS_DIS (DMC_REG_BASE + (0x66 << 2))
|
||||
|
||||
#define DMC_AM1_QOS_INC (DMC_REG_BASE + (0x6c << 2))
|
||||
#define DMC_AM1_QOS_DEC (DMC_REG_BASE + (0x6e << 2))
|
||||
#define DMC_AM1_QOS_DIS (DMC_REG_BASE + (0x70 << 2))
|
||||
|
||||
#define DMC_AM2_QOS_INC (DMC_REG_BASE + (0x76 << 2))
|
||||
#define DMC_AM2_QOS_DEC (DMC_REG_BASE + (0x78 << 2))
|
||||
#define DMC_AM2_QOS_DIS (DMC_REG_BASE + (0x7a << 2))
|
||||
|
||||
#define DMC_AM3_QOS_INC (DMC_REG_BASE + (0x80 << 2))
|
||||
#define DMC_AM3_QOS_DEC (DMC_REG_BASE + (0x82 << 2))
|
||||
#define DMC_AM3_QOS_DIS (DMC_REG_BASE + (0x84 << 2))
|
||||
|
||||
#define DMC_AM4_QOS_INC (DMC_REG_BASE + (0x8a << 2))
|
||||
#define DMC_AM4_QOS_DEC (DMC_REG_BASE + (0x8c << 2))
|
||||
#define DMC_AM4_QOS_DIS (DMC_REG_BASE + (0x8e << 2))
|
||||
|
||||
#define DMC_AM5_QOS_INC (DMC_REG_BASE + (0x94 << 2))
|
||||
#define DMC_AM5_QOS_DEC (DMC_REG_BASE + (0x96 << 2))
|
||||
#define DMC_AM5_QOS_DIS (DMC_REG_BASE + (0x98 << 2))
|
||||
|
||||
#define DMC_AM6_QOS_INC (DMC_REG_BASE + (0x9e << 2))
|
||||
#define DMC_AM6_QOS_DEC (DMC_REG_BASE + (0xa0 << 2))
|
||||
#define DMC_AM6_QOS_DIS (DMC_REG_BASE + (0xa2 << 2))
|
||||
|
||||
#define DMC_AM7_QOS_INC (DMC_REG_BASE + (0xa8 << 2))
|
||||
#define DMC_AM7_QOS_DEC (DMC_REG_BASE + (0xaa << 2))
|
||||
#define DMC_AM7_QOS_DIS (DMC_REG_BASE + (0xac << 2))
|
||||
|
||||
#define DMC_AXI0_QOS_INC (DMC_REG_BASE + (0xb2 << 2))
|
||||
#define DMC_AXI0_QOS_DEC (DMC_REG_BASE + (0xb4 << 2))
|
||||
#define DMC_AXI0_QOS_DIS (DMC_REG_BASE + (0xb6 << 2))
|
||||
#define DMC_AXI0_QOS_CTRL1 (DMC_REG_BASE + (0xb9 << 2))
|
||||
|
||||
#define DMC_AXI1_QOS_INC (DMC_REG_BASE + (0xbc << 2))
|
||||
#define DMC_AXI1_QOS_DEC (DMC_REG_BASE + (0xbe << 2))
|
||||
#define DMC_AXI1_QOS_DIS (DMC_REG_BASE + (0xc0 << 2))
|
||||
|
||||
#define DMC_AXI2_QOS_INC (DMC_REG_BASE + (0xc6 << 2))
|
||||
#define DMC_AXI2_QOS_DEC (DMC_REG_BASE + (0xc8 << 2))
|
||||
#define DMC_AXI2_QOS_DIS (DMC_REG_BASE + (0xca << 2))
|
||||
|
||||
#define DMC_AXI3_QOS_INC (DMC_REG_BASE + (0xd0 << 2))
|
||||
#define DMC_AXI3_QOS_DEC (DMC_REG_BASE + (0xd2 << 2))
|
||||
#define DMC_AXI3_QOS_DIS (DMC_REG_BASE + (0xd4 << 2))
|
||||
|
||||
#define DMC_AXI4_QOS_INC (DMC_REG_BASE + (0xda << 2))
|
||||
#define DMC_AXI4_QOS_DEC (DMC_REG_BASE + (0xdc << 2))
|
||||
#define DMC_AXI4_QOS_DIS (DMC_REG_BASE + (0xde << 2))
|
||||
|
||||
#define DMC_AXI5_QOS_INC (DMC_REG_BASE + (0xe4 << 2))
|
||||
#define DMC_AXI5_QOS_DEC (DMC_REG_BASE + (0xe6 << 2))
|
||||
#define DMC_AXI5_QOS_DIS (DMC_REG_BASE + (0xe8 << 2))
|
||||
|
||||
#define DMC_AXI6_QOS_INC (DMC_REG_BASE + (0xee << 2))
|
||||
#define DMC_AXI6_QOS_DEC (DMC_REG_BASE + (0xf0 << 2))
|
||||
#define DMC_AXI6_QOS_DIS (DMC_REG_BASE + (0xf2 << 2))
|
||||
|
||||
#define DMC_AXI7_QOS_INC (DMC_REG_BASE + (0xf8 << 2))
|
||||
#define DMC_AXI7_QOS_DEC (DMC_REG_BASE + (0xfa << 2))
|
||||
#define DMC_AXI7_QOS_DIS (DMC_REG_BASE + (0xfc << 2))
|
||||
|
||||
/* DDR MMC */
|
||||
#define AM_DDR_PLL_CNTL0 (DDR_MMC_BASE + 0x00)
|
||||
#define AM_DDR_PLL_CNTL1 (DDR_MMC_BASE + 0x04)
|
||||
#define AM_DDR_PLL_CNTL2 (DDR_MMC_BASE + 0x08)
|
||||
#define AM_DDR_PLL_CNTL3 (DDR_MMC_BASE + 0x0c)
|
||||
#define AM_DDR_PLL_CNTL4 (DDR_MMC_BASE + 0x10)
|
||||
#if defined(CONFIG_MESON_GXBB)
|
||||
#define AM_DDR_PLL_STS (DDR_MMC_BASE + 0x14)
|
||||
#else
|
||||
#define AM_DDR_PLL_CNTL5 (DDR_MMC_BASE + 0x14)
|
||||
#endif
|
||||
|
||||
#define DDR0_CLK_CTRL (DDR_MMC_BASE + 0x400)
|
||||
|
||||
/* DMC SEC */
|
||||
#define DMC_SEC_REG_BASE 0xda838400
|
||||
|
||||
#define DMC_SEC_CTRL (DMC_SEC_REG_BASE + (0x00 << 2))
|
||||
#define DMC_SEC_RANGE_CTRL (DMC_SEC_REG_BASE + (0x07 << 2))
|
||||
#define DMC_SEC_AXI_PORT_CTRL (DMC_SEC_REG_BASE + (0x0e << 2))
|
||||
|
||||
#define DMC_VDEC_SEC_READ_CTRL (DMC_SEC_REG_BASE + (0x10 << 2))
|
||||
#define DMC_VDEC_SEC_WRITE_CTRL (DMC_SEC_REG_BASE + (0x11 << 2))
|
||||
#define DMC_VDEC_SEC_CFG (DMC_SEC_REG_BASE + (0x12 << 2))
|
||||
|
||||
#define DMC_HCODEC_SEC_READ_CTRL (DMC_SEC_REG_BASE + (0x17 << 2))
|
||||
#define DMC_HCODEC_SEC_WRITE_CTRL (DMC_SEC_REG_BASE + (0x18 << 2))
|
||||
#define DMC_HCODEC_SEC_CFG (DMC_SEC_REG_BASE + (0x19 << 2))
|
||||
|
||||
#define DMC_HEVC_SEC_READ_CTRL (DMC_SEC_REG_BASE + (0x1e << 2))
|
||||
#define DMC_HEVC_SEC_WRITE_CTRL (DMC_SEC_REG_BASE + (0x1f << 2))
|
||||
#define DMC_HEVC_SEC_CFG (DMC_SEC_REG_BASE + (0x20 << 2))
|
||||
|
||||
#define DMC_VPU_SEC_READ_CTRL (DMC_SEC_REG_BASE + (0x32 << 2))
|
||||
#define DMC_VPU_SEC_WRITE_CTRL (DMC_SEC_REG_BASE + (0x33 << 2))
|
||||
#define DMC_VPU_SEC_CFG (DMC_SEC_REG_BASE + (0x25 << 2))
|
||||
|
||||
#define DMC_GE2D_SEC_CTRL (DMC_SEC_REG_BASE + (0x34 << 2))
|
||||
#define DMC_PARSER_SEC_CTRL (DMC_SEC_REG_BASE + (0x35 << 2))
|
||||
#define DMC_DEV_SEC_READ_CTRL (DMC_SEC_REG_BASE + (0x36 << 2))
|
||||
#define DMC_DEV_SEC_WRITE_CTRL (DMC_SEC_REG_BASE + (0x37 << 2))
|
||||
|
||||
#define DMC_WTCH0_CTRL (DMC_SEC_REG_BASE + (0xa9 << 2))
|
||||
#define DMC_WTCH1_CTRL (DMC_SEC_REG_BASE + (0xb0 << 2))
|
||||
|
||||
#define DDR0_ADDRMAP_0 (DMC_SEC_REG_BASE + (0xd0 << 2))
|
||||
#define DDR0_ADDRMAP_1 (DMC_SEC_REG_BASE + (0xd1 << 2))
|
||||
#define DDR0_ADDRMAP_2 (DMC_SEC_REG_BASE + (0xd2 << 2))
|
||||
#define DDR0_ADDRMAP_3 (DMC_SEC_REG_BASE + (0xd3 << 2))
|
||||
#define DDR0_ADDRMAP_4 (DMC_SEC_REG_BASE + (0xd4 << 2))
|
||||
|
||||
#define DDR1_ADDRMAP_0 (DMC_SEC_REG_BASE + (0xd5 << 2))
|
||||
#define DDR1_ADDRMAP_1 (DMC_SEC_REG_BASE + (0xd6 << 2))
|
||||
#define DDR1_ADDRMAP_2 (DMC_SEC_REG_BASE + (0xd7 << 2))
|
||||
#define DDR1_ADDRMAP_3 (DMC_SEC_REG_BASE + (0xd8 << 2))
|
||||
#define DDR1_ADDRMAP_4 (DMC_SEC_REG_BASE + (0xd9 << 2))
|
||||
|
||||
#if defined(CONFIG_MESON_GXL)
|
||||
#define DMC_DES_KEY0_H (DMC_SEC_REG_BASE + (0x90 << 2))
|
||||
#define DMC_DES_KEY0_L (DMC_SEC_REG_BASE + (0x91 << 2))
|
||||
#define DMC_DES_KEY1_H (DMC_SEC_REG_BASE + (0x92 << 2))
|
||||
#define DMC_DES_KEY1_L (DMC_SEC_REG_BASE + (0x93 << 2))
|
||||
|
||||
#define DMC_DES_CTRL (DMC_SEC_REG_BASE + (0x9d << 2))
|
||||
#endif
|
||||
|
||||
#define DMC_DDR_CTRL (DMC_SEC_REG_BASE + (0xda << 2))
|
||||
|
||||
#define AM_ANALOG_TOP_REG1 (0xc8834400 + (0x6f << 2))
|
||||
|
||||
/* Macros */
|
||||
#define DQSCORR_DX(dx) \
|
||||
if ((readl(dx) & ~(0xe00)) && ((readl(dx) >> 8) & ~(0xe00))) \
|
||||
writel((((readl(dx) & ~(0xe00)) * 95) / 100) | \
|
||||
(((((readl(dx) >> 8) & ~(0xe00)) * 88) / 100) << 8) | \
|
||||
(((((readl(dx) >> 8) & ~(0xe00)) * 88) / 100) << 16), \
|
||||
dx); \
|
||||
else if (((readl(dx) >> 8) & ~(0xe00))) \
|
||||
writel((95 / 100) | \
|
||||
(((((readl(dx) >> 8) & ~(0xe00)) * 88) / 100) << 8) | \
|
||||
(((((readl(dx) >> 8) & ~(0xe00)) * 88) / 100) << 16), \
|
||||
dx); \
|
||||
else if (((readl(dx)) & ~(0xe00))) \
|
||||
writel((((readl(dx) & ~(0xe00)) * 95) / 100) | \
|
||||
(((88) / 100) << 8) | (((88) / 100) << 16), \
|
||||
dx); \
|
||||
else \
|
||||
writel((95 / 100) | \
|
||||
((88 / 100) << 8) | ((88 / 100) << 16), dx)
|
||||
|
||||
#define DMC_ENABLE_REGION(REGION) \
|
||||
writel(0xffffffff, REGION## _SEC_CFG); \
|
||||
writel(0x55555555, REGION## _SEC_WRITE_CTRL); \
|
||||
writel(0x55555555, REGION## _SEC_READ_CTRL)
|
||||
|
||||
/* TODO: Timeout */
|
||||
#define WAIT_FOR(a) \
|
||||
while (!(readl(a) & 1)) \
|
||||
; \
|
||||
if (!(readl(a) & 1)) \
|
||||
panic("%s: init failed, err=%d", __func__, -ETIMEDOUT)
|
||||
|
||||
/**
|
||||
* Register values
|
||||
**/
|
||||
|
||||
/*
|
||||
* PLL
|
||||
*/
|
||||
#define DDR_CLK_CNTL_CLKGEN_SOFTRESET BIT(28)
|
||||
#define DDR_CLK_CNTL_PHY_CLK_ENABLE BIT(29)
|
||||
#define DDR_CLK_CNTL_DDRPLL_ENABLE BIT(31)
|
||||
|
||||
/*
|
||||
* PCTL
|
||||
*/
|
||||
|
||||
/* PCTL_SCTL: state control register (S905X datasheet p.451) */
|
||||
#define PCTL_SCTL_CFG_STATE BIT(0)
|
||||
#define PCTL_SCTL_GO_STATE BIT(1)
|
||||
|
||||
/* PCTL_STAT */
|
||||
#define PCTL_STAT_ACCESS (BIT(1) | BIT(0))
|
||||
|
||||
/* PCTL_POWCTL: power control */
|
||||
#define PCTL_POWCTL_POWERON BIT(0)
|
||||
|
||||
/*
|
||||
* PUB
|
||||
*/
|
||||
|
||||
/* PUB_PGSR0: PHY General Status Register 0 */
|
||||
#define PUB_PGSR0_IDONE BIT(0) /* Initialization Done */
|
||||
#define PUB_PGSR0_PLDONE BIT(1) /* PLL Lock Done */
|
||||
#define PUB_PGSR0_DCDONE BIT(2) /* DDL Calibration Done */
|
||||
#define PUB_PGSR0_ZCDONE BIT(3) /* Impedance Calibration Done */
|
||||
#define PUB_PGSR0_DIDONE BIT(4) /* DRAM Initialization Done */
|
||||
#define PUB_PGSR0_WLDONE BIT(5) /* Write Leveling Done */
|
||||
#define PUB_PGSR0_QSGDONE BIT(6) /* DQS Gate Training Done */
|
||||
#define PUB_PGSR0_WLADONE BIT(7) /* Write Leveling Adjust Done */
|
||||
#define PUB_PGSR0_RDDONE BIT(8) /* Read Bit Deskew Done */
|
||||
#define PUB_PGSR0_WDDONE BIT(9) /* Write Bit Deskew Done */
|
||||
#define PUB_PGSR0_REDONE BIT(10) /* Read Eye Training Done */
|
||||
#define PUB_PGSR0_WEDONE BIT(11) /* Write Eye Training Done */
|
||||
#define PUB_PGSR0_ZCERR BIT(20) /* Impedance Calib Error */
|
||||
#define PUB_PGSR0_WLERR BIT(21) /* Write Leveling Error */
|
||||
#define PUB_PGSR0_QSGERR BIT(22) /* DQS Gate Training Error */
|
||||
#define PUB_PGSR0_WLAERR BIT(23) /* Write Leveling Adj Error */
|
||||
#define PUB_PGSR0_RDERR BIT(24) /* Read Bit Deskew Error */
|
||||
#define PUB_PGSR0_WDERR BIT(25) /* Write Bit Deskew Error */
|
||||
#define PUB_PGSR0_REERR BIT(26) /* Read Eye Training Error */
|
||||
#define PUB_PGSR0_WEERR BIT(27) /* Write Eye Training Error */
|
||||
|
||||
/* PUB_PIR: PHY init register */
|
||||
#define PUB_PIR_INIT BIT(0)
|
||||
#define PUB_PIR_ZCAL BIT(1)
|
||||
#define PUB_PIR_CA BIT(2)
|
||||
|
||||
#define PUB_PIR_PLLINIT BIT(4)
|
||||
#define PUB_PIR_DCAL BIT(5)
|
||||
#define PUB_PIR_PHYRST BIT(6)
|
||||
#define PUB_PIR_DRAMRST BIT(7)
|
||||
#define PUB_PIR_DRAMINIT BIT(8)
|
||||
#define PUB_PIR_WL BIT(9)
|
||||
#define PUB_PIR_QSGATE BIT(10)
|
||||
#define PUB_PIR_WLADJ BIT(11)
|
||||
#define PUB_PIR_RDDSKW BIT(12)
|
||||
#define PUB_PIR_WRDSKW BIT(13)
|
||||
#define PUB_PIR_RDEYE BIT(14)
|
||||
#define PUB_PIR_WREYE BIT(15)
|
||||
#define PUB_PIR_ICPC BIT(16)
|
||||
#define PUB_PIR_PLLBYP BIT(17)
|
||||
#define PUB_PIR_CTLDINIT BIT(18)
|
||||
#define PUB_PIR_RDIMMINIT BIT(19)
|
||||
#define PUB_PIR_CLRSR BIT(27)
|
||||
#define PUB_PIR_LOCKBYP BIT(28)
|
||||
#define PUB_PIR_DCALBYP BIT(29)
|
||||
#define PUB_PIR_ZCALBYP BIT(30)
|
||||
#define PUB_PIR_INITBYP BIT(31)
|
||||
|
||||
#define PUB_PIR_FINAL_STEP (PUB_PIR_INIT | PUB_PIR_ZCAL | \
|
||||
PUB_PIR_PLLINIT | PUB_PIR_DCAL | PUB_PIR_PHYRST | PUB_PIR_DRAMRST | \
|
||||
PUB_PIR_DRAMINIT | PUB_PIR_WL | PUB_PIR_QSGATE | PUB_PIR_WLADJ | \
|
||||
PUB_PIR_RDDSKW | PUB_PIR_WRDSKW | PUB_PIR_RDEYE | PUB_PIR_WREYE)
|
||||
|
||||
/* Struct which holds timings (see dram-settings-gx.h) */
|
||||
struct meson_gx_dram_timings {
|
||||
u8 drv;
|
||||
u8 odt;
|
||||
u8 rtp;
|
||||
u8 wtr;
|
||||
u8 rp;
|
||||
u8 rcd;
|
||||
u8 ras;
|
||||
u8 rrd;
|
||||
u8 rc;
|
||||
u8 mrd;
|
||||
u8 mod;
|
||||
u8 faw;
|
||||
u8 wlmrd;
|
||||
u8 wlo;
|
||||
ushort rfc;
|
||||
u8 xp;
|
||||
ushort xs;
|
||||
ushort dllk;
|
||||
u8 cke;
|
||||
u8 rtodt;
|
||||
u8 rtw;
|
||||
u8 refi;
|
||||
u8 refi_mddr3;
|
||||
u8 cl;
|
||||
u8 wr;
|
||||
u8 cwl;
|
||||
u8 al;
|
||||
u8 dqs;
|
||||
u8 cksre;
|
||||
u8 cksrx;
|
||||
u8 zqcs;
|
||||
u8 xpdll;
|
||||
ushort exsr;
|
||||
ushort zqcl;
|
||||
ushort zqcsi;
|
||||
u8 rpab;
|
||||
u8 rppb;
|
||||
u8 tccdl;
|
||||
u8 tdqsck;
|
||||
u8 tdqsckmax;
|
||||
u8 tckesr;
|
||||
u8 tdpd;
|
||||
u8 taond_aofd;
|
||||
};
|
||||
|
||||
#if defined(CONFIG_MESON_GXBB)
|
||||
# include <asm/arch/dram-gxbb.h>
|
||||
#elif defined(CONFIG_MESON_GXL)
|
||||
# include <asm/arch/dram-gxl.h>
|
||||
#endif
|
||||
|
||||
/* Functions */
|
||||
int dram_init(void);
|
||||
void meson_dram_prepare_pctl(void);
|
||||
void meson_dram_phy_init(void);
|
||||
void meson_dram_phy_setup_ranks(void);
|
||||
void meson_dram_finalise_init(void);
|
||||
extern const struct meson_gx_dram_timings timings;
|
||||
#endif
|
||||
168
arch/arm/include/asm/arch-meson/dram-gxbb.h
Normal file
168
arch/arm/include/asm/arch-meson/dram-gxbb.h
Normal file
@@ -0,0 +1,168 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright (C) 2015, Amlogic, Inc. All rights reserved.
|
||||
* Copyright (C) 2023-2025, Ferass El Hafidi <funderscore@postmarketos.org>
|
||||
*/
|
||||
#ifndef DRAM_GXBB_H
|
||||
#define DRAM_GXBB_H
|
||||
|
||||
/* PUB (not much documented) */
|
||||
#define DDR0_PUB_REG_BASE 0xc8836000
|
||||
|
||||
#define DDR0_PUB_PIR (DDR0_PUB_REG_BASE + (0x01 << 2))
|
||||
|
||||
#define DDR0_PUB_PGCR1 (DDR0_PUB_REG_BASE + (0x03 << 2))
|
||||
#define DDR0_PUB_PGCR2 (DDR0_PUB_REG_BASE + (0x04 << 2))
|
||||
#define DDR0_PUB_PGCR3 (DDR0_PUB_REG_BASE + (0x05 << 2))
|
||||
#define DDR0_PUB_PGSR0 (DDR0_PUB_REG_BASE + (0x06 << 2))
|
||||
|
||||
#define DDR0_PUB_ACLCDLR (DDR0_PUB_REG_BASE + (0x0F << 2))
|
||||
#define DDR0_PUB_ACBDLR0 (DDR0_PUB_REG_BASE + (0x10 << 2))
|
||||
#define DDR0_PUB_ACIOCR1 (DDR0_PUB_REG_BASE + (0x1B << 2))
|
||||
#define DDR0_PUB_ACIOCR2 (DDR0_PUB_REG_BASE + (0x1C << 2))
|
||||
#define DDR0_PUB_ACIOCR3 (DDR0_PUB_REG_BASE + (0x1D << 2))
|
||||
#define DDR0_PUB_ACIOCR4 (DDR0_PUB_REG_BASE + (0x1E << 2))
|
||||
#define DDR0_PUB_ACIOCR5 (DDR0_PUB_REG_BASE + (0x1F << 2))
|
||||
|
||||
#define DDR0_PUB_DXCCR (DDR0_PUB_REG_BASE + (0x20 << 2))
|
||||
#define DDR0_PUB_DSGCR (DDR0_PUB_REG_BASE + (0x21 << 2))
|
||||
#define DDR0_PUB_DCR (DDR0_PUB_REG_BASE + (0x22 << 2))
|
||||
|
||||
#define DDR0_PUB_DTPR0 (DDR0_PUB_REG_BASE + (0x23 << 2))
|
||||
#define DDR0_PUB_DTPR1 (DDR0_PUB_REG_BASE + (0x24 << 2))
|
||||
#define DDR0_PUB_DTPR2 (DDR0_PUB_REG_BASE + (0x25 << 2))
|
||||
#define DDR0_PUB_DTPR3 (DDR0_PUB_REG_BASE + (0x26 << 2))
|
||||
|
||||
#define DDR0_PUB_MR0 (DDR0_PUB_REG_BASE + (0x27 << 2))
|
||||
#define DDR0_PUB_MR1 (DDR0_PUB_REG_BASE + (0x28 << 2))
|
||||
#define DDR0_PUB_MR2 (DDR0_PUB_REG_BASE + (0x29 << 2))
|
||||
#define DDR0_PUB_MR3 (DDR0_PUB_REG_BASE + (0x2A << 2))
|
||||
|
||||
#define DDR0_PUB_ODTCR (DDR0_PUB_REG_BASE + (0x2B << 2))
|
||||
|
||||
#define DDR0_PUB_DTCR (DDR0_PUB_REG_BASE + (0x2C << 2))
|
||||
|
||||
#define DDR0_PUB_DTAR0 (DDR0_PUB_REG_BASE + (0x2D << 2))
|
||||
#define DDR0_PUB_DTAR1 (DDR0_PUB_REG_BASE + (0x2E << 2))
|
||||
#define DDR0_PUB_DTAR2 (DDR0_PUB_REG_BASE + (0x2F << 2))
|
||||
#define DDR0_PUB_DTAR3 (DDR0_PUB_REG_BASE + (0x30 << 2))
|
||||
|
||||
#define DDR0_PUB_IOVCR0 (DDR0_PUB_REG_BASE + (0x8E << 2))
|
||||
#define DDR0_PUB_IOVCR1 (DDR0_PUB_REG_BASE + (0x8F << 2))
|
||||
|
||||
#define DDR0_PUB_ZQCR (DDR0_PUB_REG_BASE + (0x90 << 2))
|
||||
|
||||
#define DDR0_PUB_ZQ0PR (DDR0_PUB_REG_BASE + (0x91 << 2))
|
||||
#define DDR0_PUB_ZQ1PR (DDR0_PUB_REG_BASE + (0x95 << 2))
|
||||
#define DDR0_PUB_ZQ2PR (DDR0_PUB_REG_BASE + (0x99 << 2))
|
||||
#define DDR0_PUB_ZQ3PR (DDR0_PUB_REG_BASE + (0x9D << 2))
|
||||
|
||||
#define DDR0_PUB_DX0GCR1 (DDR0_PUB_REG_BASE + (0xA1 << 2))
|
||||
#define DDR0_PUB_DX0GCR2 (DDR0_PUB_REG_BASE + (0xA2 << 2))
|
||||
#define DDR0_PUB_DX0GCR3 (DDR0_PUB_REG_BASE + (0xA3 << 2))
|
||||
|
||||
#define DDR0_PUB_DX0LCDLR0 (DDR0_PUB_REG_BASE + (0xAE << 2))
|
||||
#define DDR0_PUB_DX0LCDLR2 (DDR0_PUB_REG_BASE + (0xB0 << 2))
|
||||
|
||||
#define DDR0_PUB_DX0GTR (DDR0_PUB_REG_BASE + (0xB2 << 2))
|
||||
#define DDR0_PUB_DX1GTR (DDR0_PUB_REG_BASE + (0xD2 << 2))
|
||||
#define DDR0_PUB_DX2GTR (DDR0_PUB_REG_BASE + (0xF2 << 2))
|
||||
#define DDR0_PUB_DX3GTR (DDR0_PUB_REG_BASE + (0x112 << 2))
|
||||
|
||||
#define DDR0_PUB_DX1GCR1 (DDR0_PUB_REG_BASE + (0xC1 << 2))
|
||||
#define DDR0_PUB_DX1GCR2 (DDR0_PUB_REG_BASE + (0xC2 << 2))
|
||||
#define DDR0_PUB_DX1GCR3 (DDR0_PUB_REG_BASE + (0xC3 << 2))
|
||||
#define DDR0_PUB_DX1LCDLR0 (DDR0_PUB_REG_BASE + (0xCE << 2))
|
||||
#define DDR0_PUB_DX1LCDLR2 (DDR0_PUB_REG_BASE + (0xD0 << 2))
|
||||
|
||||
#define DDR0_PUB_DX2GCR1 (DDR0_PUB_REG_BASE + (0xE1 << 2))
|
||||
#define DDR0_PUB_DX2GCR2 (DDR0_PUB_REG_BASE + (0xE2 << 2))
|
||||
#define DDR0_PUB_DX2GCR3 (DDR0_PUB_REG_BASE + (0xE3 << 2))
|
||||
#define DDR0_PUB_DX2LCDLR2 (DDR0_PUB_REG_BASE + (0xF0 << 2))
|
||||
|
||||
#define DDR0_PUB_DX3GCR1 (DDR0_PUB_REG_BASE + (0x101 << 2))
|
||||
#define DDR0_PUB_DX3GCR2 (DDR0_PUB_REG_BASE + (0x102 << 2))
|
||||
#define DDR0_PUB_DX3GCR3 (DDR0_PUB_REG_BASE + (0x103 << 2))
|
||||
#define DDR0_PUB_DX3LCDLR0 (DDR0_PUB_REG_BASE + (0x10E << 2))
|
||||
#define DDR0_PUB_DX3LCDLR2 (DDR0_PUB_REG_BASE + (0x110 << 2))
|
||||
|
||||
/* PCTL */
|
||||
#define DDR0_PCTL_BASE 0xc8839000
|
||||
/* DDR1_PCTL_BASE is DDR0_PCTL_BASE + 0x400 */
|
||||
|
||||
#define PCTL_SCFG (DDR0_PCTL_BASE + 0x000)
|
||||
#define PCTL_SCTL (DDR0_PCTL_BASE + (0x1 << 2))
|
||||
#define PCTL_STAT (DDR0_PCTL_BASE + (0x2 << 2))
|
||||
|
||||
#define PCTL_POWSTAT (DDR0_PCTL_BASE + (0x12 << 2))
|
||||
#define PCTL_POWCTL (DDR0_PCTL_BASE + (0x11 << 2))
|
||||
|
||||
#define PCTL_CMDTSTAT (DDR0_PCTL_BASE + (0x13 << 2))
|
||||
#define PCTL_CMDTSTATEN (DDR0_PCTL_BASE + (0x14 << 2))
|
||||
|
||||
#define PCTL_PPCFG (DDR0_PCTL_BASE + (0x21 << 2))
|
||||
|
||||
#define PCTL_MCFG (DDR0_PCTL_BASE + (0x20 << 2))
|
||||
#define PCTL_MCFG1 (DDR0_PCTL_BASE + (0x1f << 2))
|
||||
|
||||
#define PCTL_TCKSRE (DDR0_PCTL_BASE + (0x49 << 2))
|
||||
#define PCTL_TZQCSI (DDR0_PCTL_BASE + (0x47 << 2))
|
||||
#define PCTL_TINIT (DDR0_PCTL_BASE + (0x31 << 2))
|
||||
#define PCTL_TOGCNT1U (DDR0_PCTL_BASE + (0x30 << 2))
|
||||
#define PCTL_TCKE (DDR0_PCTL_BASE + (0x4b << 2))
|
||||
#define PCTL_TMOD (DDR0_PCTL_BASE + (0x4c << 2))
|
||||
#define PCTL_TEXSR (DDR0_PCTL_BASE + (0x43 << 2))
|
||||
#define PCTL_TAL (DDR0_PCTL_BASE + (0x39 << 2))
|
||||
#define PCTL_TRTP (DDR0_PCTL_BASE + (0x40 << 2))
|
||||
#define PCTL_TCKSRX (DDR0_PCTL_BASE + (0x4a << 2))
|
||||
#define PCTL_TRTW (DDR0_PCTL_BASE + (0x38 << 2))
|
||||
#define PCTL_TCWL (DDR0_PCTL_BASE + (0x3b << 2))
|
||||
#define PCTL_TWR (DDR0_PCTL_BASE + (0x41 << 2))
|
||||
#define PCTL_TCL (DDR0_PCTL_BASE + (0x3a << 2))
|
||||
#define PCTL_TDQS (DDR0_PCTL_BASE + (0x48 << 2))
|
||||
#define PCTL_TRSTH (DDR0_PCTL_BASE + (0x32 << 2))
|
||||
#define PCTL_TRCD (DDR0_PCTL_BASE + (0x3e << 2))
|
||||
#define PCTL_TXP (DDR0_PCTL_BASE + (0x44 << 2))
|
||||
#define PCTL_TOGCNT100N (DDR0_PCTL_BASE + (0x33 << 2))
|
||||
#define PCTL_TMRD (DDR0_PCTL_BASE + (0x35 << 2))
|
||||
#define PCTL_TREFI (DDR0_PCTL_BASE + (0x34 << 2))
|
||||
#define PCTL_TRAS (DDR0_PCTL_BASE + (0x3c << 2))
|
||||
#define PCTL_TREFI_MEM_DDR3 (DDR0_PCTL_BASE + (0x52 << 2))
|
||||
#define PCTL_TWTR (DDR0_PCTL_BASE + (0x42 << 2))
|
||||
#define PCTL_TRC (DDR0_PCTL_BASE + (0x3d << 2))
|
||||
#define PCTL_TRFC (DDR0_PCTL_BASE + (0x36 << 2))
|
||||
#define PCTL_TCKESR (DDR0_PCTL_BASE + (0x50 << 2))
|
||||
#define PCTL_TZQCL (DDR0_PCTL_BASE + (0x4e << 2))
|
||||
#define PCTL_TRRD (DDR0_PCTL_BASE + (0x3f << 2))
|
||||
#define PCTL_TRP (DDR0_PCTL_BASE + (0x37 << 2))
|
||||
#define PCTL_TZQCS (DDR0_PCTL_BASE + (0x46 << 2))
|
||||
#define PCTL_TXPDLL (DDR0_PCTL_BASE + (0x45 << 2))
|
||||
|
||||
#define PCTL_DFIODTCFG (DDR0_PCTL_BASE + (0x91 << 2))
|
||||
#define PCTL_DFIODTCFG1 (DDR0_PCTL_BASE + (0x92 << 2))
|
||||
#define PCTL_DFITCTRLDELAY (DDR0_PCTL_BASE + (0x90 << 2))
|
||||
#define PCTL_DFITPHYWRLAT (DDR0_PCTL_BASE + (0x95 << 2))
|
||||
#define PCTL_DFITPHYWRDATA (DDR0_PCTL_BASE + (0x94 << 2))
|
||||
#define PCTL_DFITRDDATAEN (DDR0_PCTL_BASE + (0x98 << 2))
|
||||
#define PCTL_DFITPHYRDLAT (DDR0_PCTL_BASE + (0x99 << 2))
|
||||
#define PCTL_DFITPHYUPDTYPE1 (DDR0_PCTL_BASE + (0x9d << 2))
|
||||
#define PCTL_DFISTCFG0 (DDR0_PCTL_BASE + (0xb1 << 2))
|
||||
#define PCTL_DFISTCFG1 (DDR0_PCTL_BASE + (0xb2 << 2))
|
||||
#define PCTL_DFISTSTAT0 (DDR0_PCTL_BASE + (0xb0 << 2))
|
||||
#define PCTL_DFILPCFG0 (DDR0_PCTL_BASE + (0xbc << 2))
|
||||
#define PCTL_DFITCTRLUPDMIN (DDR0_PCTL_BASE + (0xa0 << 2))
|
||||
#define PCTL_DFITDRAMCLKEN (DDR0_PCTL_BASE + (0xb4 << 2))
|
||||
#define PCTL_DFITDRAMCLKDIS (DDR0_PCTL_BASE + (0xb5 << 2))
|
||||
|
||||
/* DDR MMC (see dram-gx.h for more details) */
|
||||
#define DDR_MMC_BASE 0xc8836800
|
||||
|
||||
#define DDR0_SOFT_RESET (DDR_MMC_BASE + 0x404)
|
||||
#define DDR_CLK_CNTL (DDR_MMC_BASE + 0x18)
|
||||
#define DDR0_APD_CTRL (DDR_MMC_BASE + 0x408)
|
||||
|
||||
/* These will get optimized out by the compiler */
|
||||
#define AM_DDR_PLL_CNTL5 0
|
||||
#define PCTL_TCCD 0
|
||||
#define PCTL_TFAW 0
|
||||
#endif
|
||||
193
arch/arm/include/asm/arch-meson/dram-gxl.h
Normal file
193
arch/arm/include/asm/arch-meson/dram-gxl.h
Normal file
@@ -0,0 +1,193 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright (C) 2015, Amlogic, Inc. All rights reserved.
|
||||
* Copyright (C) 2023-2025, Ferass El Hafidi <funderscore@postmarketos.org>
|
||||
*/
|
||||
#ifndef DRAM_GXL_H
|
||||
#define DRAM_GXL_H
|
||||
|
||||
/* PUB (not much documented) */
|
||||
#define DDR0_PUB_REG_BASE 0xc8836000
|
||||
|
||||
#define DDR0_PUB_PIR (DDR0_PUB_REG_BASE + (0x01 << 2))
|
||||
|
||||
#define DDR0_PUB_PGCR1 (DDR0_PUB_REG_BASE + (0x05 << 2))
|
||||
#define DDR0_PUB_PGCR2 (DDR0_PUB_REG_BASE + (0x06 << 2))
|
||||
#define DDR0_PUB_PGCR3 (DDR0_PUB_REG_BASE + (0x07 << 2))
|
||||
#define DDR0_PUB_PGCR4 (DDR0_PUB_REG_BASE + (0x08 << 2))
|
||||
#define DDR0_PUB_PGCR5 (DDR0_PUB_REG_BASE + (0x09 << 2))
|
||||
#define DDR0_PUB_PGCR6 (DDR0_PUB_REG_BASE + (0x0a << 2))
|
||||
#define DDR0_PUB_PGSR0 (DDR0_PUB_REG_BASE + (0x0d << 2))
|
||||
|
||||
#define DDR0_PUB_ACLCDLR (DDR0_PUB_REG_BASE + (0x160 << 2))
|
||||
#define DDR0_PUB_ACMDLR0 (DDR0_PUB_REG_BASE + (0x168 << 2))
|
||||
#define DDR0_PUB_ACBDLR0 (DDR0_PUB_REG_BASE + (0x150 << 2))
|
||||
#define DDR0_PUB_ACBDLR1 (DDR0_PUB_REG_BASE + (0x151 << 2))
|
||||
#define DDR0_PUB_ACBDLR2 (DDR0_PUB_REG_BASE + (0x152 << 2))
|
||||
#define DDR0_PUB_ACBDLR3 (DDR0_PUB_REG_BASE + (0x153 << 2))
|
||||
#define DDR0_PUB_ACBDLR6 (DDR0_PUB_REG_BASE + (0x156 << 2))
|
||||
#define DDR0_PUB_ACBDLR7 (DDR0_PUB_REG_BASE + (0x157 << 2))
|
||||
#define DDR0_PUB_ACBDLR8 (DDR0_PUB_REG_BASE + (0x158 << 2))
|
||||
#define DDR0_PUB_ACBDLR9 (DDR0_PUB_REG_BASE + (0x159 << 2))
|
||||
#define DDR0_PUB_ACIOCR1 (DDR0_PUB_REG_BASE + (0x141 << 2))
|
||||
#define DDR0_PUB_ACIOCR2 (DDR0_PUB_REG_BASE + (0x142 << 2))
|
||||
#define DDR0_PUB_ACIOCR3 (DDR0_PUB_REG_BASE + (0x143 << 2))
|
||||
#define DDR0_PUB_ACIOCR4 (DDR0_PUB_REG_BASE + (0x144 << 2))
|
||||
#define DDR0_PUB_ACIOCR5 (DDR0_PUB_REG_BASE + (0x145 << 2))
|
||||
|
||||
#define DDR0_PUB_PTR3 (DDR0_PUB_REG_BASE + (0x13 << 2))
|
||||
#define DDR0_PUB_PTR4 (DDR0_PUB_REG_BASE + (0x14 << 2))
|
||||
|
||||
#define DDR0_PUB_DXCCR (DDR0_PUB_REG_BASE + (0x22 << 2))
|
||||
#define DDR0_PUB_DSGCR (DDR0_PUB_REG_BASE + (0x24 << 2))
|
||||
#define DDR0_PUB_DCR (DDR0_PUB_REG_BASE + (0x40 << 2))
|
||||
|
||||
#define DDR0_PUB_DTPR0 (DDR0_PUB_REG_BASE + (0x44 << 2))
|
||||
#define DDR0_PUB_DTPR1 (DDR0_PUB_REG_BASE + (0x45 << 2))
|
||||
#define DDR0_PUB_DTPR2 (DDR0_PUB_REG_BASE + (0x46 << 2))
|
||||
#define DDR0_PUB_DTPR3 (DDR0_PUB_REG_BASE + (0x47 << 2))
|
||||
#define DDR0_PUB_DTPR4 (DDR0_PUB_REG_BASE + (0x48 << 2))
|
||||
#define DDR0_PUB_DTPR5 (DDR0_PUB_REG_BASE + (0x49 << 2))
|
||||
|
||||
#define DDR0_PUB_MR0 (DDR0_PUB_REG_BASE + (0x60 << 2))
|
||||
#define DDR0_PUB_MR1 (DDR0_PUB_REG_BASE + (0x61 << 2))
|
||||
#define DDR0_PUB_MR2 (DDR0_PUB_REG_BASE + (0x62 << 2))
|
||||
#define DDR0_PUB_MR3 (DDR0_PUB_REG_BASE + (0x63 << 2))
|
||||
#define DDR0_PUB_MR4 (DDR0_PUB_REG_BASE + (0x64 << 2))
|
||||
#define DDR0_PUB_MR5 (DDR0_PUB_REG_BASE + (0x65 << 2))
|
||||
#define DDR0_PUB_MR6 (DDR0_PUB_REG_BASE + (0x66 << 2))
|
||||
#define DDR0_PUB_MR11 (DDR0_PUB_REG_BASE + (0x6b << 2))
|
||||
|
||||
#define DDR0_PUB_ODTCR (DDR0_PUB_REG_BASE + (0x26 << 2))
|
||||
|
||||
#define DDR0_PUB_DTCR (DDR0_PUB_REG_BASE + (0x80 << 2))
|
||||
#define DDR0_PUB_DTCR1 (DDR0_PUB_REG_BASE + (0x81 << 2))
|
||||
|
||||
#define DDR0_PUB_DTAR0 (DDR0_PUB_REG_BASE + (0x82 << 2))
|
||||
#define DDR0_PUB_DTAR1 (DDR0_PUB_REG_BASE + (0x83 << 2))
|
||||
#define DDR0_PUB_DTAR2 (DDR0_PUB_REG_BASE + (0x84 << 2))
|
||||
#define DDR0_PUB_DTAR3 (DDR0_PUB_REG_BASE + (0x85 << 2))
|
||||
|
||||
#define DDR0_PUB_RANKIDR (DDR0_PUB_REG_BASE + (0x137 << 2))
|
||||
|
||||
#define DDR0_PUB_IOVCR0 (DDR0_PUB_REG_BASE + (0x148 << 2))
|
||||
#define DDR0_PUB_IOVCR1 (DDR0_PUB_REG_BASE + (0x149 << 2))
|
||||
|
||||
#define DDR0_PUB_VTCR0 (DDR0_PUB_REG_BASE + (0x14a << 2))
|
||||
#define DDR0_PUB_VTCR1 (DDR0_PUB_REG_BASE + (0x14b << 2))
|
||||
|
||||
#define DDR0_PUB_ZQCR (DDR0_PUB_REG_BASE + (0x1a0 << 2))
|
||||
|
||||
#define DDR0_PUB_ZQ0PR (DDR0_PUB_REG_BASE + (0x1a1 << 2))
|
||||
#define DDR0_PUB_ZQ1PR (DDR0_PUB_REG_BASE + (0x1a5 << 2))
|
||||
#define DDR0_PUB_ZQ2PR (DDR0_PUB_REG_BASE + (0x1a9 << 2))
|
||||
#define DDR0_PUB_ZQ3PR (DDR0_PUB_REG_BASE + (0x1ad << 2))
|
||||
|
||||
#define DDR0_PUB_DX0GCR1 (DDR0_PUB_REG_BASE + (0x1c1 << 2))
|
||||
#define DDR0_PUB_DX0GCR2 (DDR0_PUB_REG_BASE + (0x1c2 << 2))
|
||||
#define DDR0_PUB_DX0GCR3 (DDR0_PUB_REG_BASE + (0x1c3 << 2))
|
||||
#define DDR0_PUB_DX0GCR4 (DDR0_PUB_REG_BASE + (0x1c4 << 2))
|
||||
#define DDR0_PUB_DX0LCDLR0 (DDR0_PUB_REG_BASE + (0x1e0 << 2))
|
||||
#define DDR0_PUB_DX0LCDLR2 (DDR0_PUB_REG_BASE + (0x1e2 << 2))
|
||||
|
||||
#define DDR0_PUB_DX0GTR (DDR0_PUB_REG_BASE + (0x1f0 << 2))
|
||||
#define DDR0_PUB_DX1GTR (DDR0_PUB_REG_BASE + (0x230 << 2))
|
||||
#define DDR0_PUB_DX2GTR (DDR0_PUB_REG_BASE + (0x270 << 2))
|
||||
#define DDR0_PUB_DX3GTR (DDR0_PUB_REG_BASE + (0x2b0 << 2))
|
||||
|
||||
#define DDR0_PUB_DX1GCR1 (DDR0_PUB_REG_BASE + (0x201 << 2))
|
||||
#define DDR0_PUB_DX1GCR2 (DDR0_PUB_REG_BASE + (0x202 << 2))
|
||||
#define DDR0_PUB_DX1GCR3 (DDR0_PUB_REG_BASE + (0x203 << 2))
|
||||
#define DDR0_PUB_DX1GCR4 (DDR0_PUB_REG_BASE + (0x204 << 2))
|
||||
#define DDR0_PUB_DX1LCDLR0 (DDR0_PUB_REG_BASE + (0x220 << 2))
|
||||
#define DDR0_PUB_DX1LCDLR2 (DDR0_PUB_REG_BASE + (0x222 << 2))
|
||||
|
||||
#define DDR0_PUB_DX2GCR0 (DDR0_PUB_REG_BASE + (0x240 << 2))
|
||||
#define DDR0_PUB_DX2GCR1 (DDR0_PUB_REG_BASE + (0x241 << 2))
|
||||
#define DDR0_PUB_DX2GCR2 (DDR0_PUB_REG_BASE + (0x242 << 2))
|
||||
#define DDR0_PUB_DX2GCR3 (DDR0_PUB_REG_BASE + (0x243 << 2))
|
||||
#define DDR0_PUB_DX2GCR4 (DDR0_PUB_REG_BASE + (0x244 << 2))
|
||||
#define DDR0_PUB_DX2LCDLR0 (DDR0_PUB_REG_BASE + (0x260 << 2))
|
||||
#define DDR0_PUB_DX2LCDLR2 (DDR0_PUB_REG_BASE + (0x262 << 2))
|
||||
|
||||
#define DDR0_PUB_DX3GCR0 (DDR0_PUB_REG_BASE + (0x280 << 2))
|
||||
#define DDR0_PUB_DX3GCR1 (DDR0_PUB_REG_BASE + (0x281 << 2))
|
||||
#define DDR0_PUB_DX3GCR2 (DDR0_PUB_REG_BASE + (0x282 << 2))
|
||||
#define DDR0_PUB_DX3GCR3 (DDR0_PUB_REG_BASE + (0x283 << 2))
|
||||
#define DDR0_PUB_DX3GCR4 (DDR0_PUB_REG_BASE + (0x284 << 2))
|
||||
#define DDR0_PUB_DX3LCDLR0 (DDR0_PUB_REG_BASE + (0x2a0 << 2))
|
||||
#define DDR0_PUB_DX3LCDLR2 (DDR0_PUB_REG_BASE + (0x2a2 << 2))
|
||||
|
||||
/* PCTL */
|
||||
#define DMC_PCTL_BASE 0xc8839000
|
||||
|
||||
#define PCTL_SCFG (DDR0_PCTL_BASE + 0x000)
|
||||
#define PCTL_SCTL (DDR0_PCTL_BASE + (0x1 << 2))
|
||||
#define PCTL_STAT (DDR0_PCTL_BASE + (0x48 << 2))
|
||||
|
||||
#define PCTL_CMDTSTAT (DDR0_PCTL_BASE + (0x48 << 2))
|
||||
|
||||
#define PCTL_PPCFG (DDR0_PCTL_BASE + (0x43 << 2))
|
||||
#define PCTL_ZQCFG (DDR0_PCTL_BASE + (0x44 << 2))
|
||||
|
||||
#define PCTL_MCFG (DDR0_PCTL_BASE + (0x41 << 2))
|
||||
#define PCTL_MCFG1 (DDR0_PCTL_BASE + (0x42 << 2))
|
||||
|
||||
#define PCTL_TCKSRE (DDR0_PCTL_BASE + (0x1a << 2))
|
||||
#define PCTL_TZQCSI (DDR0_PCTL_BASE + (0x19 << 2))
|
||||
#define PCTL_TCKE (DDR0_PCTL_BASE + (0x1c << 2))
|
||||
#define PCTL_TMOD (DDR0_PCTL_BASE + (0x1d << 2))
|
||||
#define PCTL_TEXSR (DDR0_PCTL_BASE + (0x15 << 2))
|
||||
#define PCTL_TAL (DDR0_PCTL_BASE + (0x50 << 2))
|
||||
#define PCTL_TCCD (DDR0_PCTL_BASE + (0x52 << 2))
|
||||
#define PCTL_TRTP (DDR0_PCTL_BASE + (0x12 << 2))
|
||||
#define PCTL_TFAW (DDR0_PCTL_BASE + (0x11 << 2))
|
||||
#define PCTL_TCKSRX (DDR0_PCTL_BASE + (0x1b << 2))
|
||||
#define PCTL_TRTW (DDR0_PCTL_BASE + (0x9 << 2))
|
||||
#define PCTL_TCWL (DDR0_PCTL_BASE + (0xc << 2))
|
||||
#define PCTL_TWR (DDR0_PCTL_BASE + (0x13 << 2))
|
||||
#define PCTL_TCL (DDR0_PCTL_BASE + (0xb << 2))
|
||||
#define PCTL_TDQS (DDR0_PCTL_BASE + (0x1e << 2))
|
||||
#define PCTL_TRCD (DDR0_PCTL_BASE + (0xf << 2))
|
||||
#define PCTL_TXP (DDR0_PCTL_BASE + (0x16 << 2))
|
||||
#define PCTL_TMRD (DDR0_PCTL_BASE + (0x6 << 2))
|
||||
#define PCTL_TRAS (DDR0_PCTL_BASE + (0xd << 2))
|
||||
#define PCTL_TREFI_MEM_DDR3 (DDR0_PCTL_BASE + (0x24 << 2)) // replaced by TREFI
|
||||
#define PCTL_TWTR (DDR0_PCTL_BASE + (0x14 << 2))
|
||||
#define PCTL_TRC (DDR0_PCTL_BASE + (0xe << 2))
|
||||
#define PCTL_TRFC (DDR0_PCTL_BASE + (0x7 << 2))
|
||||
#define PCTL_TCKESR (DDR0_PCTL_BASE + (0x22 << 2))
|
||||
#define PCTL_TZQCL (DDR0_PCTL_BASE + (0x20 << 2))
|
||||
#define PCTL_TRRD (DDR0_PCTL_BASE + (0x10 << 2))
|
||||
#define PCTL_TRP (DDR0_PCTL_BASE + (0x8 << 2))
|
||||
#define PCTL_TZQCS (DDR0_PCTL_BASE + (0x18 << 2))
|
||||
#define PCTL_TXPDLL (DDR0_PCTL_BASE + (0x17 << 2))
|
||||
|
||||
#define PCTL_DFIODTCFG (DDR0_PCTL_BASE + (0x27 << 2))
|
||||
#define PCTL_DFIODTCFG1 (DDR0_PCTL_BASE + (0x28 << 2))
|
||||
#define PCTL_DFITCTRLDELAY (DDR0_PCTL_BASE + (0x26 << 2))
|
||||
#define PCTL_DFITPHYWRLAT (DDR0_PCTL_BASE + (0x2b << 2))
|
||||
#define PCTL_DFITPHYWRDATA (DDR0_PCTL_BASE + (0x2a << 2))
|
||||
#define PCTL_DFITRDDATAEN (DDR0_PCTL_BASE + (0x2c << 2))
|
||||
#define PCTL_DFITPHYRDLAT (DDR0_PCTL_BASE + (0x2d << 2))
|
||||
#define PCTL_DFITPHYUPDTYPE0 (DDR0_PCTL_BASE + (0x2e << 2))
|
||||
#define PCTL_DFITPHYUPDTYPE1 (DDR0_PCTL_BASE + (0x2f << 2))
|
||||
#define PCTL_DFIUPDCFG (DDR0_PCTL_BASE + (0x35 << 2))
|
||||
#define PCTL_DFISTCFG0 (DDR0_PCTL_BASE + (0x3c << 2))
|
||||
#define PCTL_DFISTCFG1 (DDR0_PCTL_BASE + (0x3d << 2))
|
||||
#define PCTL_DFISTSTAT0 (DDR0_PCTL_BASE + (0x46 << 2))
|
||||
#define PCTL_DFILPCFG0 (DDR0_PCTL_BASE + (0x40 << 2))
|
||||
#define PCTL_DFITCTRLUPDMIN (DDR0_PCTL_BASE + (0x32 << 2))
|
||||
#define PCTL_DFITCTRLUPDMAX (DDR0_PCTL_BASE + (0x33 << 2))
|
||||
#define PCTL_DFITDRAMCLKEN (DDR0_PCTL_BASE + (0x3e << 2))
|
||||
#define PCTL_DFITDRAMCLKDIS (DDR0_PCTL_BASE + (0x3f << 2))
|
||||
|
||||
/* DDR MMC (see dram-gx.h for more details) */
|
||||
#define DDR_MMC_BASE 0xc8837000
|
||||
|
||||
#define DDR0_SOFT_RESET (DDR_MMC_BASE + 0x20)
|
||||
|
||||
#define AM_DDR_PLL_STS (DDR_MMC_BASE + 0x18)
|
||||
#define DDR_CLK_CNTL (DDR_MMC_BASE + 0x1c)
|
||||
#define DDR0_APD_CTRL (DDR_MMC_BASE + 0x24)
|
||||
#endif
|
||||
296
arch/arm/include/asm/arch-meson/dram-settings-gx.h
Normal file
296
arch/arm/include/asm/arch-meson/dram-settings-gx.h
Normal file
@@ -0,0 +1,296 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright (C) 2023-2024, Ferass El Hafidi <funderscore@postmarketos.org>
|
||||
*/
|
||||
#ifndef DRAM_SETTINGS_GX_H
|
||||
#define DRAM_SETTINGS_GX_H
|
||||
#include <linux/bitops.h>
|
||||
#include <asm/arch/dram-gx.h>
|
||||
|
||||
/*
|
||||
* These registers are pretty similar to other DRAM registers found in
|
||||
* Allwinner A31/sun6i. Some of these registers also exist in some Rockchip
|
||||
* SoCs and the TI KeyStone3.
|
||||
*/
|
||||
/* DMC control register */
|
||||
#if defined(CONFIG_DRAM_TWO_IDENTICAL_RANKS) || defined(CONFIG_DRAM_ONE_RANK)
|
||||
#define DMC_DRAM_SIZE_SHIFT 6
|
||||
#else
|
||||
#define DMC_DRAM_SIZE_SHIFT 7
|
||||
#endif
|
||||
#define DMC_CTRL_CHANNEL BIT(6) /* Channel 0 only */
|
||||
#if defined(CONFIG_DRAM_DDR4)
|
||||
#define DMC_CTRL_DDR_TYPE BIT(22) | BIT(20) /* DDR4 */
|
||||
#else
|
||||
#define DMC_CTRL_DDR_TYPE 0
|
||||
#endif
|
||||
#if defined(CONFIG_DRAM_ONE_RANK) || defined(CONFIG_DRAM_TWO_DIFF_RANKS)
|
||||
#define DMC_CTRL_RANK BIT(21) /* Enable rank 1 */
|
||||
#elif defined(CONFIG_DRAM_TWO_IDENTICAL_RANKS)
|
||||
#define DMC_CTRL_RANK BIT(22) /* Rank 0 and 1 are identical */
|
||||
#elif defined(CONFIG_DRAM_16BIT_RANK)
|
||||
#define DMC_CTRL_RANK BIT(16) /* 16-bit Rank 0 */
|
||||
#endif
|
||||
#define DMC_CTRL DMC_CTRL_CHANNEL | DMC_CTRL_RANK | DMC_CTRL_DDR_TYPE
|
||||
|
||||
/* Mode Register */
|
||||
#if defined(CONFIG_MESON_GXL) && defined(CONFIG_DRAM_DDR4)
|
||||
#define PUB_MR0 4 | (((((timings.cl - 9) >> 1) & 7) << 4)) | \
|
||||
((((timings.wr - 10) >> 1) & 7) << 9)
|
||||
#define PUB_MR1 (timings.odt << 8) | (timings.drv << 1) | 0x81
|
||||
#define PUB_MR2 (((timings.cwl - 6) >> 1) & 7) << 3 | 0xc0
|
||||
#define PUB_MR3 0
|
||||
#define PUB_MR4 8
|
||||
#else
|
||||
#define PUB_MR0 (((timings.cl - 4) & 8) >> 1) | \
|
||||
(((timings.cl - 4) & 7) << 4) | \
|
||||
(((timings.wr <= 8 ? (timings.wr - 4) : (timings.wr >> 1)) & 7) << 9) | 0x1c00
|
||||
#define PUB_MR1 (timings.drv << 1) | \
|
||||
((timings.odt & 1) << 2) | \
|
||||
(((timings.odt >> 1) & 1) << 6) | \
|
||||
(((timings.odt >> 2) & 1) << 9) | \
|
||||
BIT(7) | \
|
||||
((timings.al ? ((timings.cl - timings.al) & 3) : 0) << 3)
|
||||
#define PUB_MR2 BIT(6) | (((timings.cwl - 5) & 7) << 3)
|
||||
#endif
|
||||
#define PUB_MR3 0
|
||||
#if defined(CONFIG_MESON_GXL)
|
||||
#if defined(CONFIG_DRAM_DDR3)
|
||||
#define PUB_MR4 0
|
||||
#define PUB_MR5 0x420
|
||||
#elif defined(CONFIG_DRAM_DDR4)
|
||||
#define PUB_MR5 0x400
|
||||
#endif
|
||||
#define PUB_MR6 0x800
|
||||
#endif
|
||||
|
||||
/* ODT Configuration Register */
|
||||
#if defined(CONFIG_MESON_GXBB)
|
||||
#define PUB_ODTCR 0x210000
|
||||
#elif defined(CONFIG_MESON_GXL)
|
||||
#define PUB_ODTCR 0x30000
|
||||
#endif
|
||||
|
||||
/* DDR Timing Parameter */
|
||||
#if defined(CONFIG_MESON_GXBB)
|
||||
#define PUB_DTPR0 timings.rtp | \
|
||||
(timings.wtr << 4) | \
|
||||
(timings.rp << 8) | \
|
||||
(timings.ras << 16) | \
|
||||
(timings.rrd << 22) | \
|
||||
(timings.rcd << 26)
|
||||
#define PUB_DTPR1 (timings.mod << 2) | \
|
||||
(timings.faw << 5) | \
|
||||
(timings.rfc << 11) | \
|
||||
(timings.wlmrd << 20) | \
|
||||
(timings.wlo << 26)
|
||||
#define PUB_DTPR2 timings.xs | \
|
||||
(timings.xp << 10) | \
|
||||
(timings.dllk << 19)
|
||||
#define PUB_DTPR3 0 | \
|
||||
(0 << 3) | \
|
||||
(timings.rc << 6) | \
|
||||
(timings.cke << 13) | \
|
||||
(timings.mrd << 18) | \
|
||||
(0 << 29)
|
||||
#elif defined(CONFIG_MESON_GXL)
|
||||
#define PUB_DTPR0 timings.rtp | \
|
||||
(timings.rp << 8) | \
|
||||
(timings.ras << 16) | \
|
||||
(timings.rrd << 24)
|
||||
#define PUB_DTPR1 (timings.wlmrd << 24) | \
|
||||
(timings.faw << 16) | \
|
||||
timings.mrd
|
||||
#define PUB_DTPR2 timings.xs | \
|
||||
(timings.cke << 16)
|
||||
#define PUB_DTPR3 (timings.dllk << 16) | (4 << 28)
|
||||
#define PUB_DTPR4 timings.xp | BIT(11) | (timings.rfc << 0x10)
|
||||
#define PUB_DTPR5 (timings.rc << 16) | (timings.rcd << 8) | \
|
||||
timings.wtr
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_MESON_GXBB)
|
||||
#define PUB_PGCR0 0x7D81E3F
|
||||
#define PUB_PGCR1 0x380C6A0
|
||||
#define PUB_PGCR2 (0x1F12480 & 0xefffffff)
|
||||
#define PUB_PGCR3 0xC0AAFE60
|
||||
#elif defined(CONFIG_MESON_GXL)
|
||||
#define PUB_PGCR0 0x7d81e3f
|
||||
#define PUB_PGCR1 0x2004620
|
||||
#define PUB_PGCR2 (0xf05f97 & 0xefffffff)
|
||||
#if defined(CONFIG_DRAM_DDR3)
|
||||
#define PUB_PGCR3 0xc0aae860
|
||||
#elif defined(CONFIG_DRAM_DDR4)
|
||||
#define PUB_PGCR3 0xc0aae860 | 0x4000000
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_MESON_GXBB)
|
||||
#define PUB_DXCCR 0x181884
|
||||
#define PUB_DTCR 0x4300308f
|
||||
#define PUB_DSGCR 0x20645A
|
||||
|
||||
#define PUB_ZQ0PR 0x69
|
||||
#define PUB_ZQ1PR 0x69
|
||||
#define PUB_ZQ2PR 0x69
|
||||
#define PUB_ZQ3PR 0x69
|
||||
#elif defined(CONFIG_MESON_GXL)
|
||||
#define PUB_DXCCR 0x20c01204
|
||||
|
||||
#if defined(CONFIG_DRAM_DDR4)
|
||||
#define PUB_DTCR 0x80003187 | 0x40
|
||||
#else
|
||||
#define PUB_DTCR 0x80003187
|
||||
#endif
|
||||
|
||||
#define PUB_DTCR1 0x00010237 /* XXX: Needed? */
|
||||
#define PUB_DSGCR (0x20641b | 0x800004) /* Works on DDR4 too? */
|
||||
|
||||
#if defined(CONFIG_DRAM_DDR3)
|
||||
#define PUB_ZQ0PR 0x5d95d
|
||||
#define PUB_ZQ1PR 0x5d95d
|
||||
#define PUB_ZQ2PR 0x5d95d
|
||||
#define PUB_ZQ3PR 0x1dd1d
|
||||
#elif defined(CONFIG_DRAM_DDR4)
|
||||
#define PUB_ZQ0PR 0x775d
|
||||
#define PUB_ZQ1PR 0x6fc5d
|
||||
#define PUB_ZQ2PR 0x6fc5d
|
||||
#define PUB_ZQ3PR 0x1dd1d
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_DRAM_DDR3)
|
||||
#define PUB_DCR 0xb
|
||||
#elif defined(CONFIG_DRAM_DDR4)
|
||||
#define PUB_DCR 0x1800040c
|
||||
#endif
|
||||
#define PUB_DTAR (0 | (0 << 12) | (0 << 28)) /* Uh? */
|
||||
|
||||
#define PCTL0_1US_PCK 0x1C8
|
||||
#define PCTL0_100NS_PCK 0x2D
|
||||
#define PCTL0_INIT_US 0x2
|
||||
#define PCTL0_RSTH_US 0x2
|
||||
|
||||
/* Mode Config(?) */
|
||||
#if defined(CONFIG_MESON_GXBB)
|
||||
#define PCTL0_MCFG ((((timings.faw + timings.rrd - 1) / timings.rrd) & 3) << 0x12) | \
|
||||
(0xa2f21 & 0xfff3ffff)
|
||||
#define PCTL0_MCFG1 (((timings.rrd - ((timings.faw - (timings.faw / timings.rrd) * \
|
||||
timings.rrd) & 0xff)) & 7) << 8) | \
|
||||
(0x80200000 & 0xfffffcff)
|
||||
#elif defined(CONFIG_MESON_GXL)
|
||||
#if defined(CONFIG_DRAM_DDR3)
|
||||
#define PCTL0_MCFG_DDRTYPE 0
|
||||
#elif defined(CONFIG_DRAM_DDR4)
|
||||
#define PCTL0_MCFG_DDRTYPE BIT(4)
|
||||
#endif
|
||||
|
||||
#define PCTL0_MCFG (0xa2f21 & 0xffffff8f) | PCTL0_MCFG_DDRTYPE
|
||||
/* XXX: What is this? ↓ ??? */
|
||||
#define PCTL0_MCFG1 0
|
||||
#endif
|
||||
|
||||
#define PCTL0_SCFG 0xF01
|
||||
|
||||
#if defined(CONFIG_MESON_GXL) && defined(CONFIG_DRAM_16BIT_RANK)
|
||||
#define PCTL0_PPCFG 0x1fd
|
||||
#else
|
||||
#define PCTL0_PPCFG 0x1e0
|
||||
#endif
|
||||
|
||||
#define PCTL0_DFISTCFG0 0x4
|
||||
#define PCTL0_DFISTCFG1 0x1
|
||||
|
||||
#define PCTL0_DFITCTRLDELAY 0x2
|
||||
|
||||
#if defined(CONFIG_MESON_GXBB)
|
||||
#define PCTL0_DFITPHYWRDATA 0x1
|
||||
#else
|
||||
#define PCTL0_DFITPHYWRDATA 0x2
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_MESON_GXBB)
|
||||
#define PCTL0_DFITPHYWRLTA (timings.cwl + timings.al - \
|
||||
(((timings.cwl + timings.al) % 2) ? 3 : 4)) / 2
|
||||
#define PCTL0_DFITRDDATAEN (timings.cl + timings.al - \
|
||||
(((timings.cl + timings.al) % 2) ? 3 : 4)) / 2
|
||||
#define PCTL0_DFITPHYRDLAT ((timings.cl + timings.al) % 2) ? 14 : 16
|
||||
#elif defined(CONFIG_MESON_GXL)
|
||||
#define PCTL0_DFITPHYWRLTA ((timings.cwl + timings.al) - 2)
|
||||
#define PCTL0_DFITRDDATAEN ((timings.cl + timings.al) - 4)
|
||||
#define PCTL0_DFITPHYRDLAT 0x16
|
||||
#endif
|
||||
|
||||
#define PCTL0_DFITDRAMCLKDIS 1
|
||||
#define PCTL0_DFITDRAMCLKEN 1
|
||||
#if defined(CONFIG_MESON_GXBB)
|
||||
#define PCTL0_DFITPHYUPDTYPE1 0x200
|
||||
#else
|
||||
#define PCTL0_DFITPHYUPDTYPE0 16
|
||||
#define PCTL0_DFITPHYUPDTYPE1 16
|
||||
#define PCTL0_DFITCTRLUPDMAX 64
|
||||
#define PCTL0_DFIUPDCFG 3
|
||||
#endif
|
||||
#define PCTL0_DFITCTRLUPDMIN 16
|
||||
|
||||
#define PCTL0_CMDTSTATEN 1
|
||||
|
||||
#if defined(CONFIG_DRAM_ONE_RANK) || defined(CONFIG_DRAM_16BIT_RANK)
|
||||
#define PCTL0_DFIODTCFG 0x808
|
||||
#elif defined(CONFIG_DRAM_TWO_DIFF_RANKS)
|
||||
#define PCTL0_DFIODTCFG 0xc0c
|
||||
#elif defined(CONFIG_DRAM_TWO_IDENTICAL_RANKS)
|
||||
#define PCTL0_DFIODTCFG 0x8
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_MESON_GXBB)
|
||||
#define PCTL0_DFIODTCFG1 (0 | (6 << 16))
|
||||
#elif defined(CONFIG_MESON_GXL)
|
||||
#if defined(CONFIG_DRAM_16BIT_RANK)
|
||||
#define PCTL0_DFIODTCFG1 ((6 << 16) | (8 << 16))
|
||||
#else
|
||||
#define PCTL0_DFIODTCFG1 ((6 << 16) | (3 << 25) | (8 << 16))
|
||||
#endif
|
||||
#endif
|
||||
#define PCTL0_DFILPCFG0 (1 | (3 << 4) | BIT(8) | (3 << 12) | \
|
||||
(7 << 16) | BIT(24) | (3 << 28))
|
||||
|
||||
#if defined(CONFIG_MESON_GXBB)
|
||||
#define PUB_ACBDLR0 0x10
|
||||
#elif defined(CONFIG_MESON_GXL)
|
||||
#if defined(CONFIG_DRAM_DDR3)
|
||||
#define PUB_ACBDLR0 0
|
||||
#define PUB_ACBDLR3 0
|
||||
#define PUB_ACLCDLR 48
|
||||
#elif defined(CONFIG_DRAM_DDR4)
|
||||
#define PUB_ACBDLR0 0x3f
|
||||
#define PUB_ACBDLR3 0x10
|
||||
#define PUB_ACLCDLR 0x28
|
||||
#else
|
||||
#define PUB_ACBDLR0 0
|
||||
#define PUB_ACBDLR3 0
|
||||
#define PUB_ACLCDLR 48
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define LPDDR3_CA0 2
|
||||
#define LPDDR3_CA1 0
|
||||
#define LPDDR3_REMAP 3
|
||||
#define LPDDR3_WL 1
|
||||
|
||||
/* PLL */
|
||||
#if defined(CONFIG_MESON_GXBB)
|
||||
#define DDR_PLL_CNTL1 0x69c80000
|
||||
#define DDR_PLL_CNTL2 0xca463823
|
||||
#define DDR_PLL_CNTL3 0xc00023
|
||||
#define DDR_PLL_CNTL4 0x303500
|
||||
#define DDR_PLL_CNTL5 0 /* Unused */
|
||||
#elif defined(CONFIG_MESON_GXL)
|
||||
#define DDR_PLL_CNTL1 0xaa203
|
||||
#define DDR_PLL_CNTL2 0x2919a288
|
||||
#define DDR_PLL_CNTL3 0x3e3b744
|
||||
#define DDR_PLL_CNTL4 0xc0101
|
||||
#define DDR_PLL_CNTL5 0xe600001e
|
||||
#endif
|
||||
|
||||
#endif /* DRAM_SETTINGS_GX_H */
|
||||
117
arch/arm/include/asm/arch-meson/dram-timings-gx.h
Normal file
117
arch/arm/include/asm/arch-meson/dram-timings-gx.h
Normal file
@@ -0,0 +1,117 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright (C) 2024, Ferass El Hafidi <funderscore@postmarketos.org>
|
||||
*/
|
||||
#ifndef DRAM_TIMINGS_GX_H
|
||||
#define DRAM_TIMINGS_GX_H
|
||||
|
||||
/*
|
||||
* DRAM timings
|
||||
* It looks like those are quite similar in regular boards based on reference
|
||||
* designs and not using counterfeit RAM chips. Those are hacked around by lowbin
|
||||
* TV box vendors to support lowbin RAM chips, however. Here, we are hardcoding
|
||||
* timings, which *will* cause issues on lowbin boards, but should be fine on other
|
||||
* boards derived from Amlogic reference designs.
|
||||
*/
|
||||
|
||||
/*
|
||||
* TODO:
|
||||
* - Add timings for different DRAM clocks
|
||||
* - Support overwriting those if board needs different timings (how?)
|
||||
* - Other things
|
||||
*/
|
||||
|
||||
#if defined(CONFIG_DRAM_DDR3)
|
||||
/* DDR3: 912 MHz */
|
||||
const struct meson_gx_dram_timings timings = {
|
||||
.drv = 0,
|
||||
.odt = 2,
|
||||
|
||||
/* Timings */
|
||||
.rtp = 0x7,
|
||||
.wtr = 0x7,
|
||||
.rp = 0xd,
|
||||
.rcd = 0xd,
|
||||
.ras = 0x25,
|
||||
.rrd = 0x7,
|
||||
.rc = 0x34,
|
||||
.mrd = 0x6, /* Should be < 8 */
|
||||
.mod = 0x4,
|
||||
.faw = 0x21,
|
||||
.wlmrd = 0x28,
|
||||
.wlo = 0x7,
|
||||
.rfc = 0x118,
|
||||
.xp = 0x7,
|
||||
.xs = 0x200,
|
||||
.dllk = 0x200,
|
||||
.cke = 0x5,
|
||||
.rtodt = 0x0,
|
||||
.rtw = 0x7,
|
||||
.refi = 0x4e,
|
||||
.refi_mddr3 = 0x4,
|
||||
.cl = 0xd,
|
||||
.wr = 0x10,
|
||||
.cwl = 0x9,
|
||||
.al = 0x0,
|
||||
.dqs = 0x17,
|
||||
.cksre = 0xf,
|
||||
.cksrx = 0xf,
|
||||
.zqcs = 0x40,
|
||||
.xpdll = 0x17,
|
||||
.exsr = 0x200, /* Should be < 0x3ff */
|
||||
.zqcl = 0x88,
|
||||
.zqcsi = 0x3e8,
|
||||
.rpab = 0x0,
|
||||
.rppb = 0x0,
|
||||
.tdqsck = 0x0,
|
||||
.tdqsckmax = 0x0,
|
||||
.tckesr = 0x0,
|
||||
.tdpd = 0x0,
|
||||
.taond_aofd = 0x0,
|
||||
.tccdl = 0, /* Unused on GXBB */
|
||||
};
|
||||
|
||||
#elif defined(CONFIG_DRAM_DDR4)
|
||||
/* DDR4: 1080 MHz */
|
||||
const struct meson_gx_dram_timings timings = {
|
||||
.drv = 1,
|
||||
.odt = 1,
|
||||
|
||||
/* Timings */
|
||||
.rtp = 9,
|
||||
.wtr = 9,
|
||||
.rp = 0x10, // ddr_clk < 1200
|
||||
.rcd = 0x10, // ddr_clk < 1200
|
||||
.ras = 35 * 1.2,
|
||||
.rrd = 6,
|
||||
.rc = 0x3a,
|
||||
.mrd = 8,
|
||||
.mod = 24,
|
||||
.faw = 35 * 1.2,
|
||||
.rfc = 350 * 1.2,
|
||||
.wlmrd = 40,
|
||||
.wlo = 9.5 * 1.2,
|
||||
.xs = 512,
|
||||
.xp = 7,
|
||||
.cke = 5,
|
||||
.dllk = 1024,
|
||||
.rtodt = 0,
|
||||
.rtw = 8,
|
||||
.refi = 76,
|
||||
.refi_mddr3 = 4,
|
||||
.cl = 0x10, // ddr_clk < 1200
|
||||
.wr = 0x12,
|
||||
.cwl = 12,
|
||||
.al = 0,
|
||||
.exsr = 1024,
|
||||
.dqs = 9,
|
||||
.cksre = 15,
|
||||
.cksrx = 15,
|
||||
.zqcs = 128,
|
||||
.zqcl = 256,
|
||||
.xpdll = 23,
|
||||
.zqcsi = 1000,
|
||||
.tccdl = 6, // ddr_clk < 1200
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
@@ -12,7 +12,10 @@
|
||||
|
||||
#define GX_FIRMWARE_MEM_SIZE 0x1000000
|
||||
|
||||
#define GX_MB_SRAM_BASE 0xd9013800
|
||||
#define GX_AOBUS_BASE 0xc8100000
|
||||
#define GX_SEC_HIU_MB_BASE 0xda83c400
|
||||
#define GX_SEC_AOBUS_BASE 0xda100000
|
||||
#define GX_PERIPHS_BASE 0xc8834400
|
||||
#define GX_HIU_BASE 0xc883c000
|
||||
#define GX_ETH_BASE 0xc9410000
|
||||
@@ -24,6 +27,10 @@
|
||||
#define GX_AO_SEC_GP_CFG3 GX_AO_ADDR(0x93)
|
||||
#define GX_AO_SEC_GP_CFG4 GX_AO_ADDR(0x94)
|
||||
#define GX_AO_SEC_GP_CFG5 GX_AO_ADDR(0x95)
|
||||
#define GX_AO_SEC_SD_CFG15 GX_AO_ADDR(0x8f)
|
||||
|
||||
#define GX_SEC_AO_ADDR(off) (GX_SEC_AOBUS_BASE + ((off) << 2))
|
||||
#define GX_SEC_AO_SEC_GP_CFG0 GX_SEC_AO_ADDR(0x90)
|
||||
|
||||
#define GX_AO_BOOT_DEVICE 0xF
|
||||
#define GX_AO_MEM_SIZE_MASK 0xFFFF0000
|
||||
@@ -41,4 +48,38 @@
|
||||
#define GX_GPIO_IN(n) GX_PERIPHS_ADDR(_GX_GPIO_OFF(n) + 1)
|
||||
#define GX_GPIO_OUT(n) GX_PERIPHS_ADDR(_GX_GPIO_OFF(n) + 2)
|
||||
|
||||
/* Mailbox registers */
|
||||
#define GX_SEC_HIU_MB_ADDR(off) (GX_SEC_HIU_MB_BASE + ((off) << 2))
|
||||
#define GX_SEC_HIU_MAILBOX_SET_0 GX_SEC_HIU_MB_ADDR(0x01)
|
||||
#define GX_SEC_HIU_MAILBOX_STAT_0 GX_SEC_HIU_MB_ADDR(0x02)
|
||||
#define GX_SEC_HIU_MAILBOX_CLR_0 GX_SEC_HIU_MB_ADDR(0x03)
|
||||
|
||||
/* Mailbox commands */
|
||||
#define GX_MB_CMD_SHA 0xc0de0001
|
||||
#define GX_MB_CMD_DATA 0xc0dec0de
|
||||
#define GX_MB_CMD_END 0xe00de00d
|
||||
#define GX_MB_CMD_OP_SHA 0xc0de0002
|
||||
#define GX_MB_CMD_DATA_LEN 0xc0dec0d0
|
||||
|
||||
/* PIN_MUX registers */
|
||||
#define GX_PIN_MUX_REG1 (0xda834400 + (0x2d << 2))
|
||||
#define GX_PIN_MUX_REG2 (0xda834400 + (0x2e << 2))
|
||||
#define GX_PIN_MUX_REG3 (0xda834400 + (0x2f << 2))
|
||||
#define GX_PIN_MUX_REG7 (0xda834400 + (0x33 << 2))
|
||||
|
||||
/* PWM registers */
|
||||
#define GX_PWM_PWM_B (0xc1100000 + (0x2155 << 2))
|
||||
#define GX_PWM_PWM_D (0xc1100000 + (0x2195 << 2))
|
||||
#define GX_PWM_MISC_REG_CD (0xc1100000 + (0x2196 << 2))
|
||||
#define GX_PWM_MISC_REG_AB (0xc1100000 + (0x2156 << 2))
|
||||
|
||||
/* Non-DM MMC init */
|
||||
#if CONFIG_IS_ENABLED(MMC) && !CONFIG_IS_ENABLED(DM_MMC)
|
||||
struct mmc *meson_mmc_init(int mmc_no);
|
||||
#endif
|
||||
|
||||
#if !CONFIG_IS_ENABLED(WDT_MESON_GXBB) && defined(CONFIG_SPL_BUILD)
|
||||
#define GX_WDT_CTRL_REG 0xc11098d0
|
||||
#endif
|
||||
|
||||
#endif /* __GX_H__ */
|
||||
|
||||
@@ -17,6 +17,8 @@ config MESON64_COMMON
|
||||
config MESON_GX
|
||||
bool
|
||||
select MESON64_COMMON
|
||||
select SUPPORT_SPL
|
||||
select BINMAN if SPL
|
||||
|
||||
choice
|
||||
prompt "Platform select"
|
||||
@@ -69,7 +71,7 @@ config SYS_SOC
|
||||
default "meson"
|
||||
|
||||
config SYS_MALLOC_F_LEN
|
||||
default 0x1000
|
||||
default 0x2000
|
||||
|
||||
config SYS_VENDOR
|
||||
string "Vendor name"
|
||||
@@ -93,4 +95,112 @@ config SYS_BOARD
|
||||
Based on this option board/<CONFIG_SYS_VENDOR>/<CONFIG_SYS_BOARD> will
|
||||
be used.
|
||||
|
||||
if MESON_GX && SPL
|
||||
config SPL_SYS_MALLOC_F_LEN
|
||||
default 0x2000
|
||||
|
||||
choice
|
||||
prompt "DRAM rank mode"
|
||||
help
|
||||
Choose rank mode. This heavily depends on the board and you should
|
||||
leave the board default set if you don't know what this is.
|
||||
If you choose the wrong rank mode DRAM init in SPL may either fail
|
||||
or in rare occasions require multiple resets before it succeeds.
|
||||
|
||||
config DRAM_ONE_RANK
|
||||
bool "One rank"
|
||||
|
||||
config DRAM_TWO_IDENTICAL_RANKS
|
||||
bool "Two identical ranks"
|
||||
|
||||
if MESON_GXBB
|
||||
config DRAM_TWO_DIFF_RANKS
|
||||
bool "Two different ranks"
|
||||
endif
|
||||
|
||||
if MESON_GXL
|
||||
config DRAM_16BIT_RANK
|
||||
bool "One 16-bit rank"
|
||||
endif
|
||||
endchoice
|
||||
|
||||
choice
|
||||
prompt "DRAM memory type"
|
||||
default DRAM_DDR3
|
||||
help
|
||||
Select the DDR type according to your board design. GXBB/S905
|
||||
currently only supports DDR3.
|
||||
|
||||
config DRAM_DDR3
|
||||
bool "DDR3"
|
||||
|
||||
if MESON_GXL
|
||||
config DRAM_DDR4
|
||||
bool "DDR4"
|
||||
endif
|
||||
endchoice
|
||||
|
||||
config DRAM_DQS_CORR
|
||||
bool "Enable DQS correction"
|
||||
|
||||
config DRAM_CLK
|
||||
int "DRAM clock"
|
||||
default 912
|
||||
help
|
||||
This option contains the DRAM clock to use in MHz.
|
||||
|
||||
config DRAM_SIZE
|
||||
int "DRAM size"
|
||||
default 1024
|
||||
help
|
||||
This option contains the DRAM size. Units in MB.
|
||||
|
||||
choice
|
||||
prompt "Enable DRAM 2T mode"
|
||||
default DRAM_1T_MODE
|
||||
help
|
||||
Choose whenever to use 2T mode or not.
|
||||
|
||||
config DRAM_1T_MODE
|
||||
bool "Use DRAM 1T mode"
|
||||
|
||||
config DRAM_2T_MODE
|
||||
bool "Use DRAM 2T mode"
|
||||
|
||||
endchoice
|
||||
|
||||
choice
|
||||
prompt "Set VDDEE init voltage"
|
||||
default SPL_MESON_GX_VDDEE_1000MV
|
||||
help
|
||||
This option is used to set the VDDEE voltage on boot up.
|
||||
If unsure, leave it to the board default.
|
||||
|
||||
config SPL_MESON_GX_VDDEE_1000MV
|
||||
bool "Set VDDEE to 1000 mv"
|
||||
|
||||
config SPL_MESON_GX_VDDEE_1100MV
|
||||
bool "Set VDDEE to 1100 mv"
|
||||
|
||||
endchoice
|
||||
|
||||
choice
|
||||
prompt "Set VCCK init voltage"
|
||||
default SPL_MESON_GX_VCCK_1100MV
|
||||
help
|
||||
This option is used to set the VCCK voltage on boot up.
|
||||
If unsure, leave it to the board default.
|
||||
|
||||
config SPL_MESON_GX_VCCK_1000MV
|
||||
bool "Set VCCK to 1000 mv"
|
||||
|
||||
config SPL_MESON_GX_VCCK_1100MV
|
||||
bool "Set VCCK to 1100 mv"
|
||||
|
||||
config SPL_MESON_GX_VCCK_1120MV
|
||||
bool "Set VCCK to 1120 mv"
|
||||
|
||||
endchoice
|
||||
|
||||
endif
|
||||
endif
|
||||
|
||||
@@ -2,8 +2,18 @@
|
||||
#
|
||||
# Copyright (c) 2016 Beniamino Galvani <b.galvani@gmail.com>
|
||||
|
||||
obj-y += board-common.o sm.o board-info.o
|
||||
obj-y += board-common.o sm.o board-info.o capsule.o
|
||||
obj-$(CONFIG_MESON_GX) += board-gx.o
|
||||
ifeq ($(CONFIG_SPL_BUILD),y)
|
||||
obj-$(CONFIG_MESON_GXBB) += dram-gxbb.o
|
||||
obj-$(CONFIG_MESON_GXL) += dram-gxl.o
|
||||
obj-$(CONFIG_MESON_GX) += dram-gx.o
|
||||
obj-$(CONFIG_MESON_GXBB) += spl-gxbb.o
|
||||
obj-$(CONFIG_MESON_GXL) += spl-gxl.o
|
||||
obj-$(CONFIG_MESON_GX) += spl-gx.o
|
||||
obj-$(CONFIG_MESON_GX) += spl.o
|
||||
endif
|
||||
|
||||
obj-$(CONFIG_MESON_AXG) += board-axg.o
|
||||
obj-$(CONFIG_MESON_G12A) += board-g12a.o
|
||||
obj-$(CONFIG_MESON_A1) += board-a1.o
|
||||
|
||||
@@ -30,6 +30,7 @@ __weak int board_init(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_SPL_BUILD
|
||||
int dram_init(void)
|
||||
{
|
||||
const fdt64_t *val;
|
||||
@@ -49,6 +50,7 @@ int dram_init(void)
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
__weak int meson_ft_board_setup(void *blob, struct bd_info *bd)
|
||||
{
|
||||
@@ -145,10 +147,24 @@ int board_late_init(void)
|
||||
{
|
||||
meson_set_boot_source();
|
||||
|
||||
if (CONFIG_IS_ENABLED(DFU) && CONFIG_IS_ENABLED(EFI_LOADER)) {
|
||||
/* Generate dfu_string for EFI capsule updates */
|
||||
meson_setup_capsule();
|
||||
}
|
||||
|
||||
return meson_board_late_init();
|
||||
}
|
||||
|
||||
void reset_cpu(void)
|
||||
{
|
||||
#if CONFIG_SPL_BUILD
|
||||
/*
|
||||
* We do not have BL31 running yet, so no PSCI.
|
||||
* Instead, let the watchdog reset the board.
|
||||
*/
|
||||
for (;;)
|
||||
;
|
||||
#else
|
||||
psci_system_reset();
|
||||
#endif
|
||||
}
|
||||
|
||||
61
arch/arm/mach-meson/capsule.c
Normal file
61
arch/arm/mach-meson/capsule.c
Normal file
@@ -0,0 +1,61 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (c) 2025, Ferass El Hafidi <funderscore@postmarketos.org>
|
||||
*/
|
||||
|
||||
#include <asm/arch/boot.h>
|
||||
#include <dm.h>
|
||||
#include <efi_loader.h>
|
||||
#include <mmc.h>
|
||||
|
||||
/*
|
||||
* To be able to support multiple devices and flash to the correct one we need
|
||||
* to automatically generate the dfu_string and fw_name to match the device we
|
||||
* are booted from. This is done by meson_setup_capsule() which is then called
|
||||
* in board_late_init(). Right now we support EFI capsule updates on SPI flash,
|
||||
* eMMC and SD cards.
|
||||
*/
|
||||
struct efi_fw_image fw_images[] = {
|
||||
{
|
||||
.image_index = 1,
|
||||
},
|
||||
};
|
||||
|
||||
struct efi_capsule_update_info update_info = {
|
||||
.dfu_string = NULL, /* to be set in meson_capsule_setup */
|
||||
.num_images = ARRAY_SIZE(fw_images),
|
||||
.images = fw_images,
|
||||
};
|
||||
|
||||
/*
|
||||
* TODO: Support usecase e.g. FIT image on eMMC + SPL on SD.
|
||||
*/
|
||||
void meson_setup_capsule(void)
|
||||
{
|
||||
static char dfu_string[32] = { 0 };
|
||||
int mmc_devnum = 0; /* mmc0 => SD card */
|
||||
u32 max_size = 0x2000; /* 4 MB (MMC sectors are 512 bytes each) */
|
||||
u32 offset = 0x1; /* offset for flashing to eMMC/SD */
|
||||
int boot_device = meson_get_boot_device();
|
||||
|
||||
switch (boot_device) {
|
||||
case BOOT_DEVICE_EMMC:
|
||||
mmc_devnum = 1; /* mmc1 is always eMMC */
|
||||
fallthrough;
|
||||
case BOOT_DEVICE_SD:
|
||||
snprintf(dfu_string, 32, "mmc %d=u-boot.bin raw %d %d", mmc_devnum, offset, max_size);
|
||||
fw_images[0].fw_name = u"U_BOOT_MESON_MMC";
|
||||
break;
|
||||
case BOOT_DEVICE_SPI:
|
||||
/* We assume there's only one SPI flash */
|
||||
fw_images[0].fw_name = u"U_BOOT_MESON_SPI";
|
||||
snprintf(dfu_string, 32, "sf 0:0=u-boot.bin raw 0 %d", max_size);
|
||||
break;
|
||||
default:
|
||||
debug("setup_capsule: Boot device %d unsupported\n", boot_device);
|
||||
return;
|
||||
}
|
||||
debug("EFI Capsule DFU string: %s", dfu_string);
|
||||
|
||||
update_info.dfu_string = dfu_string;
|
||||
}
|
||||
419
arch/arm/mach-meson/dram-gx.c
Normal file
419
arch/arm/mach-meson/dram-gx.c
Normal file
@@ -0,0 +1,419 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Portions Copyright (C) 2015, Amlogic, Inc. All rights reserved.
|
||||
* Copyright (C) 2023-2025, Ferass El Hafidi <funderscore@postmarketos.org>
|
||||
*/
|
||||
#include <init.h>
|
||||
#include <asm/unaligned.h>
|
||||
#include <linux/libfdt.h>
|
||||
#include <config.h>
|
||||
#include <errno.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/arch/dram-gx.h>
|
||||
#include <asm/arch/gx.h>
|
||||
#include <asm/arch/clock-gx.h>
|
||||
#include <asm/arch/dram-settings-gx.h>
|
||||
#include <asm/arch/dram-timings-gx.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
/*
|
||||
* Meson GX common shared DRAM init code
|
||||
*
|
||||
* See dram-gxbb.c and dram-gxl.c for gxbb/gxl-specific code
|
||||
*/
|
||||
|
||||
void meson_dram_pll_init(void)
|
||||
{
|
||||
setbits_32(AM_ANALOG_TOP_REG1, 1);
|
||||
setbits_32(GX_HIU_BASE + HHI_MPLL_CNTL5, 1);
|
||||
|
||||
clrbits_32(AM_DDR_PLL_CNTL4, BIT(12));
|
||||
setbits_32(AM_DDR_PLL_CNTL4, BIT(12));
|
||||
|
||||
udelay(10);
|
||||
|
||||
do {
|
||||
if (IS_ENABLED(CONFIG_MESON_GXBB))
|
||||
writel(1 << 29, AM_DDR_PLL_CNTL0);
|
||||
writel(DDR_PLL_CNTL1, AM_DDR_PLL_CNTL1);
|
||||
writel(DDR_PLL_CNTL2, AM_DDR_PLL_CNTL2);
|
||||
writel(DDR_PLL_CNTL3, AM_DDR_PLL_CNTL3);
|
||||
writel(DDR_PLL_CNTL4, AM_DDR_PLL_CNTL4);
|
||||
if (IS_ENABLED(CONFIG_MESON_GXBB)) {
|
||||
if (CONFIG_DRAM_CLK >= 375 && CONFIG_DRAM_CLK <= 749)
|
||||
writel((1 << 29) | ((2 << 16) | (1 << 9) |
|
||||
(((CONFIG_DRAM_CLK / 6) * 6) / 12)), AM_DDR_PLL_CNTL0);
|
||||
else if (CONFIG_DRAM_CLK >= 750 && CONFIG_DRAM_CLK <= 1449)
|
||||
writel((1 << 29) | ((1 << 16) | (1 << 9) |
|
||||
(((CONFIG_DRAM_CLK / 12) * 12) / 24)), AM_DDR_PLL_CNTL0);
|
||||
clrbits_32(AM_DDR_PLL_CNTL0, 1 << 29);
|
||||
} else if (IS_ENABLED(CONFIG_MESON_GXL)) {
|
||||
writel(DDR_PLL_CNTL5, AM_DDR_PLL_CNTL5);
|
||||
if (CONFIG_DRAM_CLK >= 399 && CONFIG_DRAM_CLK <= 799)
|
||||
writel(((1 << 16) | ((1 << 2) | 1) |
|
||||
((CONFIG_DRAM_CLK / 12) << 4)) |
|
||||
((1 << 31) | (1 << 29) | (1 << 28)), AM_DDR_PLL_CNTL0);
|
||||
else if (CONFIG_DRAM_CLK >= 800 && CONFIG_DRAM_CLK <= 1498)
|
||||
writel(((1 << 16) | (1 << 2) |
|
||||
((CONFIG_DRAM_CLK / 24) << 4)) |
|
||||
((1 << 31) | (1 << 29) | (1 << 28)), AM_DDR_PLL_CNTL0);
|
||||
}
|
||||
udelay(200);
|
||||
} while (!((readl(AM_DDR_PLL_STS) >> 0x1F) & 1));
|
||||
|
||||
if (IS_ENABLED(CONFIG_MESON_GXBB)) {
|
||||
writel(DDR_CLK_CNTL_CLKGEN_SOFTRESET |
|
||||
DDR_CLK_CNTL_PHY_CLK_ENABLE |
|
||||
DDR_CLK_CNTL_DDRPLL_ENABLE, DDR_CLK_CNTL);
|
||||
} else if (IS_ENABLED(CONFIG_MESON_GXL)) {
|
||||
writel(DDR_CLK_CNTL_CLKGEN_SOFTRESET |
|
||||
DDR_CLK_CNTL_PHY_CLK_ENABLE |
|
||||
DDR_CLK_CNTL_DDRPLL_ENABLE |
|
||||
0xa005 /* unknown */, DDR_CLK_CNTL);
|
||||
}
|
||||
|
||||
printf("DRAM clock: %d MHz\n", CONFIG_DRAM_CLK);
|
||||
}
|
||||
|
||||
void meson_dram_phy_prepare(void)
|
||||
{
|
||||
/* Release reset of DLL */
|
||||
writel(0xffffffff, DMC_SOFT_RST);
|
||||
writel(0xffffffff, DMC_SOFT_RST1);
|
||||
udelay(10);
|
||||
|
||||
/* Enable UPCTL and PUB clock */
|
||||
if (IS_ENABLED(CONFIG_MESON_GXBB))
|
||||
writel(0x550620, DMC_PCTL_LP_CTRL);
|
||||
else if (IS_ENABLED(CONFIG_MESON_GXL))
|
||||
writel(0, DMC_PCTL_LP_CTRL);
|
||||
writel(0xf, DDR0_SOFT_RESET);
|
||||
udelay(10);
|
||||
}
|
||||
|
||||
void meson_dram_set_memory_timings(void)
|
||||
{
|
||||
/* Set memory timings */
|
||||
writel(timings.rfc, PCTL_TRFC);
|
||||
if (IS_ENABLED(CONFIG_MESON_GXL))
|
||||
writel(timings.faw, PCTL_TFAW);
|
||||
writel(timings.refi_mddr3, PCTL_TREFI_MEM_DDR3);
|
||||
writel(timings.mrd, PCTL_TMRD);
|
||||
if (IS_ENABLED(CONFIG_MESON_GXL))
|
||||
writel((timings.rp << 16) | timings.rp, PCTL_TRP);
|
||||
else /* Meson GXBB */
|
||||
writel(timings.rp, PCTL_TRP);
|
||||
writel(timings.cke + 1, PCTL_TCKESR);
|
||||
writel(timings.al, PCTL_TAL);
|
||||
writel(timings.cwl, PCTL_TCWL);
|
||||
writel(timings.cl, PCTL_TCL);
|
||||
writel(timings.ras, PCTL_TRAS);
|
||||
writel(timings.rc, PCTL_TRC);
|
||||
writel(timings.rcd, PCTL_TRCD);
|
||||
if (IS_ENABLED(CONFIG_MESON_GXBB)) {
|
||||
writel(timings.rrd, PCTL_TRRD);
|
||||
} else {
|
||||
writel(timings.rrd | ((timings.rrd + 2) * 0x10000), PCTL_TRRD);
|
||||
writel((timings.tccdl << 16) | 4, PCTL_TCCD);
|
||||
}
|
||||
writel(timings.rtp, PCTL_TRTP);
|
||||
writel(timings.wr, PCTL_TWR);
|
||||
writel(timings.wtr, PCTL_TWTR);
|
||||
writel(timings.exsr, PCTL_TEXSR);
|
||||
writel(timings.xp, PCTL_TXP);
|
||||
writel(timings.dqs, PCTL_TDQS);
|
||||
writel(timings.rtw, PCTL_TRTW);
|
||||
writel(timings.cksre, PCTL_TCKSRE);
|
||||
writel(timings.cksrx, PCTL_TCKSRX);
|
||||
writel(timings.mod, PCTL_TMOD);
|
||||
writel(timings.cke, PCTL_TCKE);
|
||||
writel(timings.zqcs, PCTL_TZQCS);
|
||||
writel(timings.zqcl, PCTL_TZQCL);
|
||||
writel(timings.xpdll, PCTL_TXPDLL);
|
||||
writel(timings.zqcsi, PCTL_TZQCSI);
|
||||
|
||||
if (IS_ENABLED(CONFIG_MESON_GXBB)) {
|
||||
/* GXBB: Enter config state */
|
||||
writel(PCTL0_SCFG, PCTL_SCFG);
|
||||
writel(PCTL_SCTL_CFG_STATE, PCTL_SCTL);
|
||||
}
|
||||
}
|
||||
|
||||
void meson_dram_set_dfi_timings(void)
|
||||
{
|
||||
#ifdef CONFIG_MESON_GXL
|
||||
writel(0xab0a560a, PCTL_ZQCFG);
|
||||
#endif
|
||||
WAIT_FOR(PCTL_STAT);
|
||||
|
||||
writel(PCTL0_PPCFG, PCTL_PPCFG);
|
||||
writel(PCTL0_DFISTCFG0, PCTL_DFISTCFG0);
|
||||
writel(PCTL0_DFISTCFG1, PCTL_DFISTCFG1);
|
||||
writel(PCTL0_DFITCTRLDELAY, PCTL_DFITCTRLDELAY);
|
||||
writel(PCTL0_DFITPHYWRDATA, PCTL_DFITPHYWRDATA);
|
||||
writel(PCTL0_DFITPHYWRLTA, PCTL_DFITPHYWRLAT);
|
||||
writel(PCTL0_DFITRDDATAEN, PCTL_DFITRDDATAEN);
|
||||
writel(PCTL0_DFITPHYRDLAT, PCTL_DFITPHYRDLAT);
|
||||
writel(PCTL0_DFITDRAMCLKDIS, PCTL_DFITDRAMCLKDIS);
|
||||
writel(PCTL0_DFITDRAMCLKEN, PCTL_DFITDRAMCLKEN);
|
||||
writel(PCTL0_DFITCTRLUPDMIN, PCTL_DFITCTRLUPDMIN);
|
||||
#if defined(CONFIG_MESON_GXL)
|
||||
writel(PCTL0_DFITCTRLUPDMAX, PCTL_DFITCTRLUPDMAX);
|
||||
writel(PCTL0_DFIUPDCFG, PCTL_DFIUPDCFG);
|
||||
#endif
|
||||
writel(PCTL0_DFILPCFG0, PCTL_DFILPCFG0);
|
||||
#if defined(CONFIG_MESON_GXL)
|
||||
writel(PCTL0_DFITPHYUPDTYPE0, PCTL_DFITPHYUPDTYPE0);
|
||||
#endif
|
||||
writel(PCTL0_DFITPHYUPDTYPE1, PCTL_DFITPHYUPDTYPE1);
|
||||
writel(PCTL0_DFIODTCFG, PCTL_DFIODTCFG);
|
||||
writel(PCTL0_DFIODTCFG1, PCTL_DFIODTCFG1);
|
||||
#if defined(CONFIG_MESON_GXBB)
|
||||
writel(PCTL0_CMDTSTATEN, PCTL_CMDTSTATEN);
|
||||
#endif
|
||||
}
|
||||
|
||||
uint meson_dram_phy_finalise_init(void)
|
||||
{
|
||||
writel(PUB_ZQ0PR, DDR0_PUB_ZQ0PR);
|
||||
writel(PUB_ZQ1PR, DDR0_PUB_ZQ1PR);
|
||||
writel(PUB_ZQ2PR, DDR0_PUB_ZQ2PR);
|
||||
#if defined(CONFIG_MESON_GXBB)
|
||||
writel(PUB_ZQ3PR, DDR0_PUB_ZQ3PR);
|
||||
#endif
|
||||
|
||||
writel(PUB_PIR_INIT | PUB_PIR_ZCAL, DDR0_PUB_PIR);
|
||||
WAIT_FOR(DDR0_PUB_PGSR0);
|
||||
/*
|
||||
* Is this needed?
|
||||
* TODO: test without
|
||||
*/
|
||||
writel(readl(DDR0_PUB_ZQCR) | (1 << 2) | (1 << 27), DDR0_PUB_ZQCR);
|
||||
udelay(10);
|
||||
writel(readl(DDR0_PUB_ZQCR) & ~((1 << 2) | (1 << 27)), DDR0_PUB_ZQCR);
|
||||
udelay(30);
|
||||
|
||||
#if defined(CONFIG_MESON_GXL) && defined(CONFIG_DRAM_16BIT_RANK)
|
||||
clrsetbits_32(DDR0_PUB_DX2GCR0, 0xb0001, 0xb0000); /* Make it neat somehow? */
|
||||
clrsetbits_32(DDR0_PUB_DX3GCR0, 0xb0001, 0xb0000);
|
||||
#endif
|
||||
|
||||
writel(PUB_ACBDLR0, DDR0_PUB_ACBDLR0);
|
||||
#if defined(CONFIG_MESON_GXL)
|
||||
writel(PUB_ACBDLR3, DDR0_PUB_ACBDLR3);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_MESON_GXL) && defined(CONFIG_DRAM_2T_MODE) && defined(CONFIG_DRAM_DDR3)
|
||||
writel(0x10101010, DDR0_PUB_ACBDLR1);
|
||||
writel(0x10101010, DDR0_PUB_ACBDLR7);
|
||||
writel(0x20202020, DDR0_PUB_ACBDLR8);
|
||||
writel(0x30303030, DDR0_PUB_ACBDLR9);
|
||||
writel(0x3f003f, DDR0_PUB_ACBDLR2);
|
||||
writel(0, DDR0_PUB_ACBDLR6);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_MESON_GXL) && defined(CONFIG_DRAM_DDR3)
|
||||
clrsetbits_32(DDR0_PUB_DXCCR, (3 << 5) | (3 << 7) |
|
||||
(3 << 9) | (3 << 11), (1 << 12) | (1 << 9));
|
||||
#endif
|
||||
|
||||
writel(PUB_PIR_FINAL_STEP, DDR0_PUB_PIR);
|
||||
udelay(1000);
|
||||
|
||||
for (u32 pgsr0 = readl(DDR0_PUB_PGSR0); (pgsr0 != 0xc0000fff) &&
|
||||
(pgsr0 != 0x80000fff); pgsr0 = readl(DDR0_PUB_PGSR0)) {
|
||||
udelay(20);
|
||||
debug("Waiting for PGSR0, currently 0x%x\n", pgsr0);
|
||||
|
||||
/* Check for errors */
|
||||
if (pgsr0 & PUB_PGSR0_ZCERR)
|
||||
pr_err("%s: impedance calibration error\n", __func__);
|
||||
if (pgsr0 & PUB_PGSR0_WLERR)
|
||||
pr_err("%s: write leveling error\n", __func__);
|
||||
if (pgsr0 & PUB_PGSR0_QSGERR)
|
||||
pr_err("%s: DQS gate training error\n", __func__);
|
||||
if (pgsr0 & PUB_PGSR0_WLAERR)
|
||||
pr_err("%s: WL Adj error\n", __func__);
|
||||
if (pgsr0 & PUB_PGSR0_RDERR)
|
||||
pr_err("%s: read bit deskew error", __func__);
|
||||
if (pgsr0 & PUB_PGSR0_WDERR)
|
||||
pr_err("%s: write bit deskew error", __func__);
|
||||
if (pgsr0 & PUB_PGSR0_REERR)
|
||||
pr_err("%s: read eye training error", __func__);
|
||||
if (pgsr0 & PUB_PGSR0_WEERR)
|
||||
pr_err("%s: write eye training error", __func__);
|
||||
}
|
||||
debug("Wait done for PGSR0, currently 0x%x\n", readl(DDR0_PUB_PGSR0));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void meson_dram_dmc_set_addrmap(void)
|
||||
{
|
||||
if (IS_ENABLED(CONFIG_MESON_GXBB)) {
|
||||
/* GXBB address map */
|
||||
if (IS_ENABLED(CONFIG_DRAM_TWO_IDENTICAL_RANKS) ||
|
||||
IS_ENABLED(CONFIG_DRAM_ONE_RANK)) {
|
||||
writel(11 | 31 << 5 | 0 << 10 | 14 << 15 | 15 << 20 | 16 << 25,
|
||||
DDR0_ADDRMAP_1);
|
||||
writel(30 | 12 << 5 | 13 << 10 | 29 << 15 | 0 << 20 | 0 << 25,
|
||||
DDR0_ADDRMAP_4);
|
||||
} else if (IS_ENABLED(CONFIG_DRAM_TWO_DIFF_RANKS)) {
|
||||
writel(11 | 31 << 5 | 0 << 10 | 14 << 15 | 15 << 20 | 16 << 25,
|
||||
DDR0_ADDRMAP_1);
|
||||
writel(0 | 12 << 5 | 13 << 10 | 29 << 15 | 0 << 20 | 30 << 25,
|
||||
DDR0_ADDRMAP_4);
|
||||
}
|
||||
} else if (IS_ENABLED(CONFIG_MESON_GXL) && IS_ENABLED(CONFIG_DRAM_DDR3)) {
|
||||
/* This applies for GXL + DDR3 RAM (e.g. LePotato) */
|
||||
if (IS_ENABLED(CONFIG_DRAM_TWO_IDENTICAL_RANKS) ||
|
||||
IS_ENABLED(CONFIG_DRAM_ONE_RANK)) {
|
||||
writel(11 | 30 << 5 | 0 << 10 | 15 << 15 | 16 << 20 | 17 << 25,
|
||||
DDR0_ADDRMAP_1);
|
||||
writel(18 | 19 << 5 | 20 << 10 | 21 << 15 | 22 << 20 | 23 << 25,
|
||||
DDR0_ADDRMAP_2);
|
||||
writel(24 | 25 << 5 | 26 << 10 | 27 << 15 | 28 << 20 | 29 << 25,
|
||||
DDR0_ADDRMAP_3);
|
||||
writel(30 | 12 << 5 | 13 << 10 | 14 << 15 | 0 << 20 | 31 << 25,
|
||||
DDR0_ADDRMAP_4);
|
||||
|
||||
writel(5 | 6 << 5 | 7 << 10 | 8 << 15 | 9 << 20 | 10 << 25,
|
||||
DDR1_ADDRMAP_0);
|
||||
writel(11 | 30 << 5 | 0 << 10 | 15 << 15 | 16 << 20 | 17 << 25,
|
||||
DDR1_ADDRMAP_1);
|
||||
writel(18 | 19 << 5 | 20 << 10 | 21 << 15 | 22 << 20 | 23 << 25,
|
||||
DDR1_ADDRMAP_2);
|
||||
writel(24 | 25 << 5 | 26 << 10 | 27 << 15 | 28 << 20 | 29 << 25,
|
||||
DDR1_ADDRMAP_3);
|
||||
writel(30 | 12 << 5 | 13 << 10 | 14 << 15 | 0 << 20 | 31 << 25,
|
||||
DDR1_ADDRMAP_4);
|
||||
}
|
||||
} else if (IS_ENABLED(CONFIG_MESON_GXL) && IS_ENABLED(CONFIG_DRAM_DDR4)) {
|
||||
/* This applies for GXL + DDR4 RAM (e.g. LaFrite) */
|
||||
if (IS_ENABLED(CONFIG_DRAM_TWO_IDENTICAL_RANKS) ||
|
||||
IS_ENABLED(CONFIG_DRAM_ONE_RANK)) {
|
||||
writel(6 | 7 << 5 | 8 << 10 | 9 << 15 | 10 << 20 | 11 << 25,
|
||||
DDR0_ADDRMAP_0);
|
||||
writel(12 | 0 << 5 | 0 << 10 | 15 << 15 | 16 << 20 | 17 << 25,
|
||||
DDR0_ADDRMAP_1);
|
||||
writel(18 | 19 << 5 | 20 << 10 | 21 << 15 | 22 << 20 | 23 << 25,
|
||||
DDR0_ADDRMAP_2);
|
||||
writel(24 | 25 << 5 | 26 << 10 | 27 << 15 | 28 << 20 | 29 << 25,
|
||||
DDR0_ADDRMAP_3);
|
||||
writel(30 | 13 << 5 | 14 << 10 | 5 << 15 | 0 << 20 | 31 << 25,
|
||||
DDR0_ADDRMAP_4);
|
||||
|
||||
writel(6 | 7 << 5 | 8 << 10 | 9 << 15 | 10 << 20 | 11 << 25,
|
||||
DDR1_ADDRMAP_0);
|
||||
writel(12 | 0 << 5 | 0 << 10 | 15 << 15 | 16 << 20 | 17 << 25,
|
||||
DDR1_ADDRMAP_1);
|
||||
writel(18 | 19 << 5 | 20 << 10 | 21 << 15 | 22 << 20 | 23 << 25,
|
||||
DDR1_ADDRMAP_2);
|
||||
writel(24 | 25 << 5 | 26 << 10 | 27 << 15 | 28 << 20 | 29 << 25,
|
||||
DDR1_ADDRMAP_3);
|
||||
writel(30 | 13 << 5 | 14 << 10 | 5 << 15 | 0 << 20 | 31 << 25,
|
||||
DDR1_ADDRMAP_4);
|
||||
} else if (IS_ENABLED(CONFIG_DRAM_16BIT_RANK)) {
|
||||
writel(0 | 6 << 5 | 7 << 10 | 8 << 15 | 9 << 20 | 10 << 25,
|
||||
DDR0_ADDRMAP_0);
|
||||
writel(11 | 0 << 5 | 0 << 10 | 14 << 15 | 15 << 20 | 16 << 25,
|
||||
DDR0_ADDRMAP_1);
|
||||
writel(17 | 18 << 5 | 19 << 10 | 20 << 15 | 21 << 20 | 22 << 25,
|
||||
DDR0_ADDRMAP_2);
|
||||
writel(23 | 24 << 5 | 25 << 10 | 26 << 15 | 27 << 20 | 28 << 25,
|
||||
DDR0_ADDRMAP_3);
|
||||
writel(29 | 12 << 5 | 13 << 10 | 5 << 15 | 0 << 20 | 30 << 25,
|
||||
DDR0_ADDRMAP_4);
|
||||
|
||||
writel(0 | 6 << 5 | 7 << 10 | 8 << 15 | 9 << 20 | 10 << 25,
|
||||
DDR1_ADDRMAP_0);
|
||||
writel(11 | 0 << 5 | 0 << 10 | 14 << 15 | 15 << 20 | 16 << 25,
|
||||
DDR1_ADDRMAP_1);
|
||||
writel(17 | 18 << 5 | 19 << 10 | 20 << 15 | 21 << 20 | 22 << 25,
|
||||
DDR1_ADDRMAP_2);
|
||||
writel(23 | 24 << 5 | 25 << 10 | 26 << 15 | 27 << 20 | 28 << 25,
|
||||
DDR1_ADDRMAP_3);
|
||||
writel(29 | 12 << 5 | 13 << 10 | 5 << 15 | 0 << 20 | 30 << 25,
|
||||
DDR1_ADDRMAP_4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void meson_dram_dmc_init(void)
|
||||
{
|
||||
u32 ddr_size_register = 0;
|
||||
|
||||
printf("DMC version: 0x%x\n", readl(DMC_VERSION));
|
||||
|
||||
for (int i = CONFIG_DRAM_SIZE >> DMC_DRAM_SIZE_SHIFT;
|
||||
!((i >>= 1) & 1); ddr_size_register++)
|
||||
;
|
||||
|
||||
if (IS_ENABLED(CONFIG_DRAM_TWO_IDENTICAL_RANKS) || IS_ENABLED(CONFIG_DRAM_ONE_RANK))
|
||||
writel(DMC_CTRL | ddr_size_register |
|
||||
(ddr_size_register << 3),
|
||||
DMC_DDR_CTRL);
|
||||
else
|
||||
writel(DMC_CTRL | ddr_size_register |
|
||||
(5 << 3),
|
||||
DMC_DDR_CTRL);
|
||||
|
||||
meson_dram_dmc_set_addrmap();
|
||||
|
||||
if (IS_ENABLED(CONFIG_MESON_GXBB)) {
|
||||
writel(0x440620, DMC_PCTL_LP_CTRL);
|
||||
writel(BIT(13) | BIT(5), DDR0_APD_CTRL);
|
||||
writel(0x5, DDR0_CLK_CTRL);
|
||||
|
||||
writel(0x11, DMC_AXI0_QOS_CTRL1);
|
||||
} else if (IS_ENABLED(CONFIG_MESON_GXL)) {
|
||||
writel(BIT(13), DDR0_APD_CTRL);
|
||||
}
|
||||
|
||||
writel(0x0, DMC_SEC_RANGE_CTRL);
|
||||
writel(0x80000000, DMC_SEC_CTRL);
|
||||
writel(0x55555555, DMC_SEC_AXI_PORT_CTRL);
|
||||
writel(0x55555555, DMC_DEV_SEC_READ_CTRL);
|
||||
writel(0x55555555, DMC_DEV_SEC_WRITE_CTRL);
|
||||
writel(0x15, DMC_GE2D_SEC_CTRL);
|
||||
writel(0x5, DMC_PARSER_SEC_CTRL);
|
||||
DMC_ENABLE_REGION(DMC_VPU);
|
||||
DMC_ENABLE_REGION(DMC_VDEC);
|
||||
DMC_ENABLE_REGION(DMC_HCODEC);
|
||||
DMC_ENABLE_REGION(DMC_HEVC);
|
||||
|
||||
writel(0xffff, DMC_REQ_CTRL);
|
||||
|
||||
dmb();
|
||||
isb();
|
||||
|
||||
debug("dram: memory controller init done\n");
|
||||
}
|
||||
|
||||
int dram_init(void)
|
||||
{
|
||||
uint ret;
|
||||
|
||||
debug("SPL: initialising dram\n");
|
||||
|
||||
meson_dram_pll_init();
|
||||
meson_dram_phy_prepare();
|
||||
meson_dram_phy_init();
|
||||
meson_dram_prepare_pctl();
|
||||
meson_dram_set_memory_timings();
|
||||
meson_dram_set_dfi_timings();
|
||||
ret = meson_dram_phy_finalise_init();
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
meson_dram_phy_setup_ranks();
|
||||
meson_dram_finalise_init();
|
||||
meson_dram_dmc_init();
|
||||
|
||||
/* Write size */
|
||||
clrsetbits_32(GX_SEC_AO_SEC_GP_CFG0, GX_AO_MEM_SIZE_MASK,
|
||||
CONFIG_DRAM_SIZE << GX_AO_MEM_SIZE_SHIFT);
|
||||
|
||||
debug("SPL: dram init done\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
174
arch/arm/mach-meson/dram-gxbb.c
Normal file
174
arch/arm/mach-meson/dram-gxbb.c
Normal file
@@ -0,0 +1,174 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Portions Copyright (C) 2015, Amlogic, Inc. All rights reserved.
|
||||
* Copyright (C) 2023-2025, Ferass El Hafidi <funderscore@postmarketos.org>
|
||||
*/
|
||||
#include <init.h>
|
||||
#include <asm/unaligned.h>
|
||||
#include <linux/libfdt.h>
|
||||
#include <config.h>
|
||||
#include <errno.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/arch/dram-gx.h>
|
||||
#include <asm/arch/gx.h>
|
||||
#include <asm/arch/clock-gx.h>
|
||||
#include <asm/arch/dram-settings-gx.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
/* Meson GXBB specific DRAM init */
|
||||
|
||||
void meson_dram_prepare_pctl(void)
|
||||
{
|
||||
writel(PCTL0_1US_PCK, PCTL_TOGCNT1U);
|
||||
writel(PCTL0_100NS_PCK, PCTL_TOGCNT100N);
|
||||
writel(PCTL0_INIT_US, PCTL_TINIT);
|
||||
writel(PCTL0_RSTH_US, PCTL_TRSTH);
|
||||
|
||||
writel(PCTL0_MCFG | (CONFIG_DRAM_2T_MODE ? 8 : 0),
|
||||
PCTL_MCFG);
|
||||
writel(PCTL0_MCFG1, PCTL_MCFG1);
|
||||
udelay(500);
|
||||
|
||||
WAIT_FOR(PCTL_DFISTSTAT0);
|
||||
|
||||
/* Ask the DRAM to kindly power on and wait until it is ready */
|
||||
writel(PCTL_POWCTL_POWERON, PCTL_POWCTL);
|
||||
WAIT_FOR(PCTL_POWSTAT);
|
||||
}
|
||||
|
||||
void meson_dram_phy_init(void)
|
||||
{
|
||||
/* Some unknown magic done by bl2 */
|
||||
writel(0x49494949, DDR0_PUB_IOVCR0);
|
||||
writel(0x49494949, DDR0_PUB_IOVCR1);
|
||||
|
||||
writel(PUB_ODTCR, DDR0_PUB_ODTCR);
|
||||
|
||||
writel(PUB_MR0, DDR0_PUB_MR0);
|
||||
writel(PUB_MR1, DDR0_PUB_MR1);
|
||||
writel(PUB_MR2, DDR0_PUB_MR2);
|
||||
writel(PUB_MR3, DDR0_PUB_MR3);
|
||||
|
||||
/* Configure DRAM timing parameters (DTPR) */
|
||||
writel(PUB_DTPR0, DDR0_PUB_DTPR0);
|
||||
writel(PUB_DTPR1, DDR0_PUB_DTPR1);
|
||||
writel(PUB_PGCR1, DDR0_PUB_PGCR1);
|
||||
writel(PUB_DTPR2, DDR0_PUB_DTPR2);
|
||||
writel(PUB_DTPR3, DDR0_PUB_DTPR3);
|
||||
|
||||
if (IS_ENABLED(CONFIG_DRAM_TWO_IDENTICAL_RANKS))
|
||||
writel(PUB_PGCR2 | (1 << 28), DDR0_PUB_PGCR2);
|
||||
else
|
||||
writel(PUB_PGCR2, DDR0_PUB_PGCR2);
|
||||
|
||||
writel(PUB_PGCR3, DDR0_PUB_PGCR3);
|
||||
writel(PUB_DXCCR, DDR0_PUB_DXCCR);
|
||||
|
||||
writel(PUB_DTCR, DDR0_PUB_DTCR);
|
||||
/* Wait for DLL lock */
|
||||
WAIT_FOR(DDR0_PUB_PGSR0);
|
||||
|
||||
writel(0, DDR0_PUB_ACIOCR1);
|
||||
writel(0, DDR0_PUB_ACIOCR2);
|
||||
writel(0, DDR0_PUB_ACIOCR3);
|
||||
writel(0, DDR0_PUB_ACIOCR4);
|
||||
writel(0, DDR0_PUB_ACIOCR5);
|
||||
|
||||
writel(0, DDR0_PUB_DX0GCR1);
|
||||
writel(0, DDR0_PUB_DX0GCR2);
|
||||
writel((1 << 10) | (2 << 12), DDR0_PUB_DX0GCR3);
|
||||
writel(0, DDR0_PUB_DX1GCR1);
|
||||
writel(0, DDR0_PUB_DX1GCR2);
|
||||
writel((1 << 10) | (2 << 12), DDR0_PUB_DX1GCR3);
|
||||
writel(0, DDR0_PUB_DX2GCR1);
|
||||
writel(0, DDR0_PUB_DX2GCR2);
|
||||
writel((1 << 10) | (2 << 12), DDR0_PUB_DX2GCR3);
|
||||
writel(0, DDR0_PUB_DX3GCR1);
|
||||
writel(0, DDR0_PUB_DX3GCR2);
|
||||
writel((1 << 10) | (2 << 12), DDR0_PUB_DX3GCR3);
|
||||
|
||||
writel(PUB_DCR, DDR0_PUB_DCR);
|
||||
|
||||
writel(PUB_DTAR, DDR0_PUB_DTAR0);
|
||||
writel(PUB_DTAR | 0x8, DDR0_PUB_DTAR1);
|
||||
writel(PUB_DTAR | 0x10, DDR0_PUB_DTAR2);
|
||||
writel(PUB_DTAR | 0x18, DDR0_PUB_DTAR3);
|
||||
|
||||
writel(PUB_DSGCR, DDR0_PUB_DSGCR);
|
||||
|
||||
/* Wait for the SDRAM to initialise */
|
||||
WAIT_FOR(DDR0_PUB_PGSR0);
|
||||
}
|
||||
|
||||
void meson_dram_phy_setup_ranks(void)
|
||||
{
|
||||
if (IS_ENABLED(CONFIG_DRAM_ONE_RANK) || IS_ENABLED(CONFIG_DRAM_TWO_DIFF_RANKS)) {
|
||||
uint i = 0, j = 0;
|
||||
|
||||
writel((readl(DDR0_PUB_DX0LCDLR0) >> 8) |
|
||||
(readl(DDR0_PUB_DX0LCDLR0) & 0xffffff00),
|
||||
DDR0_PUB_DX0LCDLR0);
|
||||
|
||||
i = ((readl(DDR0_PUB_DX2GTR) >> 3) & (7 << 0));
|
||||
j = ((readl(DDR0_PUB_DX2GTR) >> 14) & (3 << 0));
|
||||
writel(i | (i << 3) | (j << 12) | (j << 14), DDR0_PUB_DX2GTR);
|
||||
|
||||
writel((readl(DDR0_PUB_DX2LCDLR2) >> 8) |
|
||||
(readl(DDR0_PUB_DX2LCDLR2) & 0xffffff00),
|
||||
DDR0_PUB_DX2LCDLR2);
|
||||
|
||||
writel((readl(DDR0_PUB_DX3LCDLR0) >> 8) |
|
||||
(readl(DDR0_PUB_DX3LCDLR0) & 0xffffff00),
|
||||
DDR0_PUB_DX3LCDLR0);
|
||||
|
||||
i = (readl(DDR0_PUB_DX3GTR) >> 3) & (7 << 0);
|
||||
j = (readl(DDR0_PUB_DX3GTR) >> 14) & (3 << 0);
|
||||
writel(i | (i << 3) | (j << 12) | (j << 14), DDR0_PUB_DX3GTR);
|
||||
|
||||
writel((readl(DDR0_PUB_DX3LCDLR2) >> 8) |
|
||||
(readl(DDR0_PUB_DX3LCDLR2) & 0xffffff00),
|
||||
DDR0_PUB_DX3LCDLR2);
|
||||
|
||||
writel((readl(DDR0_PUB_DX0LCDLR0) << 8) |
|
||||
(readl(DDR0_PUB_DX0LCDLR0) & 0xffff00ff),
|
||||
DDR0_PUB_DX0LCDLR0);
|
||||
|
||||
i = (readl(DDR0_PUB_DX0GTR) << 0) & (7 << 0);
|
||||
j = (readl(DDR0_PUB_DX0GTR) >> 12) & (3 << 0);
|
||||
writel(i | (i << 3) | (j << 12) | (j << 14), DDR0_PUB_DX0GTR);
|
||||
|
||||
writel((readl(DDR0_PUB_DX0LCDLR2) << 8) |
|
||||
(readl(DDR0_PUB_DX0LCDLR2) & 0xffff00ff),
|
||||
DDR0_PUB_DX0LCDLR2);
|
||||
|
||||
writel((readl(DDR0_PUB_DX1LCDLR0) << 8) |
|
||||
(readl(DDR0_PUB_DX1LCDLR0) & 0xffff00ff),
|
||||
DDR0_PUB_DX1LCDLR0);
|
||||
|
||||
i = (readl(DDR0_PUB_DX1GTR) << 0) & (7 << 0);
|
||||
j = (readl(DDR0_PUB_DX1GTR) >> 12) & (3 << 0);
|
||||
writel(i | (i << 3) | (j << 12) | (j << 14), DDR0_PUB_DX0GTR);
|
||||
|
||||
writel((readl(DDR0_PUB_DX1LCDLR2) >> 8) |
|
||||
(readl(DDR0_PUB_DX1LCDLR2) & 0xffffff00),
|
||||
DDR0_PUB_DX1LCDLR2);
|
||||
}
|
||||
|
||||
writel((~(1 << 28)) & PUB_PGCR2, DDR0_PUB_PGCR2);
|
||||
|
||||
if (IS_ENABLED(CONFIG_DRAM_2T_MODE) && (PUB_DCR & 7) == 3)
|
||||
writel(0x1f, DDR0_PUB_ACLCDLR);
|
||||
}
|
||||
|
||||
void meson_dram_finalise_init(void)
|
||||
{
|
||||
WAIT_FOR(PCTL_CMDTSTAT);
|
||||
writel(PCTL_SCTL_GO_STATE, PCTL_SCTL);
|
||||
|
||||
while (readl(PCTL_STAT) != PCTL_STAT_ACCESS)
|
||||
;
|
||||
writel(0x880019d, DMC_REFR_CTRL1);
|
||||
writel(0x20100000 | (CONFIG_DRAM_CLK / 20) |
|
||||
(timings.refi << 8), DMC_REFR_CTRL2);
|
||||
clrbits_32(DDR0_PUB_ZQCR, 4);
|
||||
}
|
||||
167
arch/arm/mach-meson/dram-gxl.c
Normal file
167
arch/arm/mach-meson/dram-gxl.c
Normal file
@@ -0,0 +1,167 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Portions Copyright (C) 2015, Amlogic, Inc. All rights reserved.
|
||||
* Copyright (C) 2023-2025, Ferass El Hafidi <funderscore@postmarketos.org>
|
||||
*/
|
||||
#include <init.h>
|
||||
#include <asm/unaligned.h>
|
||||
#include <linux/libfdt.h>
|
||||
#include <config.h>
|
||||
#include <errno.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/arch/dram-gx.h>
|
||||
#include <asm/arch/gx.h>
|
||||
#include <asm/arch/clock-gx.h>
|
||||
#include <asm/arch/dram-settings-gx.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
/* Meson GXL specific DRAM init */
|
||||
|
||||
void meson_dram_prepare_pctl(void)
|
||||
{
|
||||
writel(CONFIG_DRAM_2T_MODE ? 8 : 0, PCTL_MCFG);
|
||||
setbits_32(PCTL_MCFG, PCTL0_MCFG);
|
||||
udelay(500);
|
||||
|
||||
WAIT_FOR(PCTL_DFISTSTAT0);
|
||||
|
||||
/* Enter config state */
|
||||
writel(PCTL0_SCFG, PCTL_SCFG);
|
||||
writel(PCTL_SCTL_CFG_STATE, PCTL_SCTL);
|
||||
WAIT_FOR(PCTL_STAT);
|
||||
|
||||
writel(0x581, DDR0_PUB_PIR);
|
||||
WAIT_FOR(DDR0_PUB_PGSR0);
|
||||
}
|
||||
|
||||
void meson_dram_phy_init(void)
|
||||
{
|
||||
/* Some unknown magic done by bl2 */
|
||||
writel(0x190c3500, DDR0_PUB_PTR3);
|
||||
writel(0x12c493e0, DDR0_PUB_PTR4);
|
||||
|
||||
writel(0x1f090909, DDR0_PUB_IOVCR0);
|
||||
writel(0x109, DDR0_PUB_IOVCR1);
|
||||
|
||||
writel(0xe09093c, DDR0_PUB_DX0GCR4);
|
||||
writel(0xe09093c, DDR0_PUB_DX1GCR4);
|
||||
writel(0xe09093c, DDR0_PUB_DX2GCR4);
|
||||
writel(0xe09093c, DDR0_PUB_DX3GCR4);
|
||||
|
||||
writel(PUB_ODTCR, DDR0_PUB_ODTCR);
|
||||
|
||||
writel(PUB_MR0, DDR0_PUB_MR0);
|
||||
writel(PUB_MR1, DDR0_PUB_MR1);
|
||||
writel(PUB_MR2, DDR0_PUB_MR2);
|
||||
writel(PUB_MR3, DDR0_PUB_MR3);
|
||||
writel(PUB_MR4, DDR0_PUB_MR4);
|
||||
writel(PUB_MR5, DDR0_PUB_MR5);
|
||||
writel(PUB_MR6, DDR0_PUB_MR6);
|
||||
|
||||
/* Configure DRAM timing parameters (DTPR) */
|
||||
writel(timings.odt | (1 << 2), DDR0_PUB_MR11);
|
||||
writel(PUB_DTPR0, DDR0_PUB_DTPR0);
|
||||
writel(PUB_DTPR1, DDR0_PUB_DTPR1);
|
||||
writel(PUB_DTPR2, DDR0_PUB_DTPR2);
|
||||
writel(PUB_DTPR3, DDR0_PUB_DTPR3);
|
||||
writel(PUB_DTPR4, DDR0_PUB_DTPR4);
|
||||
writel(PUB_DTPR5, DDR0_PUB_DTPR5);
|
||||
|
||||
if (IS_ENABLED(CONFIG_DRAM_TWO_IDENTICAL_RANKS))
|
||||
writel(PUB_PGCR2 | (1 << 28), DDR0_PUB_PGCR2);
|
||||
else
|
||||
writel(PUB_PGCR2, DDR0_PUB_PGCR2);
|
||||
|
||||
writel(PUB_PGCR3, DDR0_PUB_PGCR3);
|
||||
writel(PUB_DXCCR, DDR0_PUB_DXCCR);
|
||||
|
||||
writel(PUB_DTCR, DDR0_PUB_DTCR);
|
||||
writel(PUB_DTCR1, DDR0_PUB_DTCR1);
|
||||
writel(PUB_PGCR1, DDR0_PUB_PGCR1);
|
||||
|
||||
writel(0, DDR0_PUB_ACIOCR1);
|
||||
writel(0, DDR0_PUB_ACIOCR2);
|
||||
writel(0, DDR0_PUB_ACIOCR3);
|
||||
writel(0, DDR0_PUB_ACIOCR4);
|
||||
writel(0, DDR0_PUB_ACIOCR5);
|
||||
|
||||
writel(0, DDR0_PUB_DX0GCR1);
|
||||
writel(0, DDR0_PUB_DX0GCR2);
|
||||
writel(0, DDR0_PUB_DX1GCR1);
|
||||
writel(0, DDR0_PUB_DX1GCR2);
|
||||
writel(0, DDR0_PUB_DX2GCR1);
|
||||
writel(0, DDR0_PUB_DX2GCR2);
|
||||
writel(0, DDR0_PUB_DX3GCR1);
|
||||
writel(0, DDR0_PUB_DX3GCR2);
|
||||
|
||||
if (IS_ENABLED(CONFIG_DRAM_16BIT_RANK)) {
|
||||
writel(0, DDR0_PUB_DX2GCR0);
|
||||
writel(0, DDR0_PUB_DX3GCR0);
|
||||
}
|
||||
writel(0x73, DDR0_PUB_PIR);
|
||||
WAIT_FOR(DDR0_PUB_PGSR0);
|
||||
|
||||
writel(PUB_DCR | (CONFIG_DRAM_2T_MODE ? 1 << 28 : 0), DDR0_PUB_DCR);
|
||||
|
||||
writel(0xfc00172, DDR0_PUB_VTCR1);
|
||||
|
||||
writel(PUB_DSGCR & ~(0x800004), DDR0_PUB_DSGCR);
|
||||
|
||||
/* Wait for the SDRAM to initialise */
|
||||
WAIT_FOR(DDR0_PUB_PGSR0);
|
||||
}
|
||||
|
||||
void meson_dram_phy_setup_ranks(void)
|
||||
{
|
||||
if (IS_ENABLED(CONFIG_DRAM_2T_MODE)) {
|
||||
writel(0x3f003f, DDR0_PUB_ACBDLR2);
|
||||
if (PUB_ACLCDLR <= 62) {
|
||||
writel(((PUB_ACLCDLR - 24) + (readl(DDR0_PUB_ACMDLR0) & ~(0xe00))) |
|
||||
(((PUB_ACLCDLR - 24) + (readl(DDR0_PUB_ACMDLR0) & ~(0xe00)))
|
||||
* 0xffff), DDR0_PUB_ACBDLR2);
|
||||
}
|
||||
}
|
||||
writel((PUB_ACLCDLR - 24) + (readl(DDR0_PUB_ACMDLR0) & ~(0xe00)), DDR0_PUB_ACLCDLR);
|
||||
|
||||
if (IS_ENABLED(CONFIG_DRAM_DQS_CORR)) {
|
||||
/* DQS correction stuff(?) */
|
||||
clrbits_32(DDR0_PUB_ACLCDLR, 0xe00);
|
||||
if (!readl(DDR0_PUB_ACLCDLR))
|
||||
writel(1, DDR0_PUB_ACLCDLR);
|
||||
|
||||
writel(readl(DDR0_PUB_ACLCDLR) & ~(0xe00), DDR0_PUB_ACLCDLR);
|
||||
|
||||
clrbits_32(DDR0_PUB_ACBDLR0, 0xe00);
|
||||
if (!readl(DDR0_PUB_ACBDLR0))
|
||||
writel(1, DDR0_PUB_ACBDLR0);
|
||||
|
||||
writel(readl(DDR0_PUB_ACBDLR0) & ~(0xc0), DDR0_PUB_ACBDLR0);
|
||||
|
||||
DQSCORR_DX(DDR0_PUB_DX0LCDLR0);
|
||||
DQSCORR_DX(DDR0_PUB_DX1LCDLR0);
|
||||
DQSCORR_DX(DDR0_PUB_DX2LCDLR0);
|
||||
DQSCORR_DX(DDR0_PUB_DX3LCDLR0);
|
||||
}
|
||||
}
|
||||
|
||||
void meson_dram_finalise_init(void)
|
||||
{
|
||||
writel((0x3f << 12) | 0xf8, DDR0_PUB_PGCR6);
|
||||
writel(PCTL_SCTL_GO_STATE, PCTL_SCTL);
|
||||
while ((readl(PCTL_STAT) & 7) != PCTL_STAT_ACCESS)
|
||||
;
|
||||
|
||||
writel(0xfffc << 16, DDR0_PUB_DX0GCR3);
|
||||
writel(0xfffc << 16, DDR0_PUB_DX1GCR3);
|
||||
writel(0xfffc << 16, DDR0_PUB_DX2GCR3);
|
||||
writel(0xfffc << 16, DDR0_PUB_DX3GCR3);
|
||||
|
||||
writel(0, DDR0_PUB_RANKIDR);
|
||||
writel(PUB_DSGCR | 0x800004, DDR0_PUB_DSGCR);
|
||||
|
||||
setbits_32(DDR0_PUB_ZQCR, 4);
|
||||
writel(0x20100000 | ((CONFIG_DRAM_CLK / 20) - 1) |
|
||||
(timings.refi << 8), DMC_REFR_CTRL2);
|
||||
writel(0xf08f, DMC_REFR_CTRL1);
|
||||
}
|
||||
|
||||
168
arch/arm/mach-meson/spl-gx.c
Normal file
168
arch/arm/mach-meson/spl-gx.c
Normal file
@@ -0,0 +1,168 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Portions Copyright (C) 2015, Amlogic, Inc. All rights reserved.
|
||||
* Copyright (C) 2023, Ferass El Hafidi <funderscore@postmarketos.org>
|
||||
*/
|
||||
#include <hang.h>
|
||||
#include <image.h>
|
||||
#include <spl.h>
|
||||
#include <vsprintf.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/arch/boot.h>
|
||||
#include <asm/arch/clock-gx.h>
|
||||
#include <asm/arch/gx.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
/* Meson GX SPL code */
|
||||
|
||||
inline void cpu_pll_switch_to(int mode)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
reg = readl(GX_HIU_BASE + HHI_SYS_CPU_CLK_CNTL0);
|
||||
|
||||
while (reg & HHI_SCC_CNTL0_BUSY)
|
||||
reg = readl(GX_HIU_BASE + HHI_SYS_CPU_CLK_CNTL0);
|
||||
|
||||
reg |= HHI_SCC_CNTL0_DYN_ENABLE;
|
||||
|
||||
if (mode == 1) {
|
||||
/* Switch to System PLL */
|
||||
reg |= HHI_SCC_CNTL0_FINAL_MUX_SEL;
|
||||
} else {
|
||||
if (reg & HHI_SCC_CNTL0_FINAL_DYN_MUX_SEL) {
|
||||
reg = (reg & ~(HHI_SCC_CNTL0_FINAL_DYN_MUX_SEL |
|
||||
HHI_SCC_CNTL0_MUX0_DIVN_TCNT |
|
||||
HHI_SCC_CNTL0_POSTMUX0 | HHI_SCC_CNTL0_PREMUX0));
|
||||
} else {
|
||||
reg = (reg & ~(HHI_SCC_CNTL0_FINAL_DYN_MUX_SEL |
|
||||
HHI_SCC_CNTL0_MUX1_DIVN_TCNT |
|
||||
(HHI_SCC_CNTL0_POSTMUX1 | HHI_SCC_CNTL0_PREMUX1))) |
|
||||
HHI_SCC_CNTL0_FINAL_DYN_MUX_SEL;
|
||||
}
|
||||
/* Select dynamic mux */
|
||||
reg = reg & ~(HHI_SCC_CNTL0_FINAL_MUX_SEL) /*final_mux_sel*/;
|
||||
}
|
||||
writel(reg, GX_HIU_BASE + HHI_SYS_CPU_CLK_CNTL0);
|
||||
}
|
||||
|
||||
int meson_pll_init(void)
|
||||
{
|
||||
clrbits_32(GX_HIU_BASE + HHI_MPEG_CLK_CNTL, 1 << 8);
|
||||
cpu_pll_switch_to(0);
|
||||
|
||||
setbits_32(GX_HIU_BASE + HHI_MPLL_CNTL6, 1 << 26);
|
||||
udelay(100);
|
||||
|
||||
while (!((readl(GX_HIU_BASE + HHI_SYS_PLL_CNTL) >> 31) & 1)) {
|
||||
if (IS_ENABLED(CONFIG_MESON_GXBB)) {
|
||||
setbits_32(GX_HIU_BASE + HHI_SYS_PLL_CNTL, 1 << 29);
|
||||
writel(0x5ac80000, GX_HIU_BASE + HHI_SYS_PLL_CNTL2);
|
||||
writel(0x8e452015, GX_HIU_BASE + HHI_SYS_PLL_CNTL3);
|
||||
writel(0x401d40c, GX_HIU_BASE + HHI_SYS_PLL_CNTL4);
|
||||
writel(0x870, GX_HIU_BASE + HHI_SYS_PLL_CNTL5);
|
||||
writel((1 << 30) | (1 << 29) |
|
||||
((0 << 16) | (1 << 9) |
|
||||
(1536 / 24)), /* 1.5 GHz */
|
||||
GX_HIU_BASE + HHI_SYS_PLL_CNTL);
|
||||
clrbits_32(GX_HIU_BASE + HHI_SYS_PLL_CNTL, 1 << 29);
|
||||
} else if (IS_ENABLED(CONFIG_MESON_GXL)) {
|
||||
writel(0xc4258100, GX_HIU_BASE + HHI_SYS_PLL_CNTL1);
|
||||
writel(0xb7400000, GX_HIU_BASE + HHI_SYS_PLL_CNTL2);
|
||||
writel(0xa59a288, GX_HIU_BASE + HHI_SYS_PLL_CNTL3);
|
||||
writel(0x40002d, GX_HIU_BASE + HHI_SYS_PLL_CNTL4);
|
||||
writel(0x7c700007, GX_HIU_BASE + HHI_SYS_PLL_CNTL5);
|
||||
writel((1 << 30) | ((1 << 9) |
|
||||
(1200 / 24)), /* 1.2 GHz */
|
||||
GX_HIU_BASE + HHI_SYS_PLL_CNTL);
|
||||
}
|
||||
udelay(20);
|
||||
}
|
||||
cpu_pll_switch_to(1); /* Hook the CPU to the PLL divider output */
|
||||
|
||||
if (IS_ENABLED(CONFIG_MESON_GXBB))
|
||||
writel(0x10007, GX_HIU_BASE + HHI_MPLL_CNTL4);
|
||||
else if (IS_ENABLED(CONFIG_MESON_GXL))
|
||||
writel(0x10006, GX_HIU_BASE + HHI_MPLL_CNTL4);
|
||||
|
||||
setbits_32(GX_HIU_BASE + HHI_MPLL_CNTL, 1 << 29);
|
||||
udelay(200);
|
||||
|
||||
writel(0x59C80000, GX_HIU_BASE + HHI_MPLL_CNTL2);
|
||||
writel(0xCA45B822, GX_HIU_BASE + HHI_MPLL_CNTL3);
|
||||
|
||||
if (IS_ENABLED(CONFIG_MESON_GXBB))
|
||||
writel(0xB5500E1A, GX_HIU_BASE + HHI_MPLL_CNTL5);
|
||||
else if (IS_ENABLED(CONFIG_MESON_GXL))
|
||||
writel(0x95520E1A, GX_HIU_BASE + HHI_MPLL_CNTL5);
|
||||
|
||||
writel(0xFC454545, GX_HIU_BASE + HHI_MPLL_CNTL6);
|
||||
|
||||
if (IS_ENABLED(CONFIG_MESON_GXBB)) {
|
||||
writel((1 << 30) | (1 << 29) | (3 << 9) | (250 << 0), GX_HIU_BASE + HHI_MPLL_CNTL);
|
||||
clrbits_32(GX_HIU_BASE + HHI_MPLL_CNTL, 1 << 29);
|
||||
} else if (IS_ENABLED(CONFIG_MESON_GXL)) {
|
||||
writel((1 << 30) | (3 << 9) | (250 << 0), GX_HIU_BASE + HHI_MPLL_CNTL);
|
||||
}
|
||||
udelay(800);
|
||||
|
||||
setbits_32(GX_HIU_BASE + HHI_MPLL_CNTL4, 1 << 14);
|
||||
|
||||
while (!((readl(GX_HIU_BASE + HHI_MPLL_CNTL) >> 31) & 1)) {
|
||||
if ((readl(GX_HIU_BASE + HHI_MPLL_CNTL) & (1 << 31)) != 0)
|
||||
break;
|
||||
setbits_32(GX_HIU_BASE + HHI_MPLL_CNTL, 1 << 29);
|
||||
udelay(1000);
|
||||
clrbits_32(GX_HIU_BASE + HHI_MPLL_CNTL, 1 << 29);
|
||||
udelay(1000);
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_MESON_GXBB)) {
|
||||
writel(0xFFF << 16, GX_HIU_BASE + HHI_MPLL_CNTL10);
|
||||
writel(((7 << 16) | (1 << 15) | (1 << 14) | (4681 << 0)),
|
||||
GX_HIU_BASE + HHI_MPLL_CNTL7);
|
||||
writel(((readl(GX_HIU_BASE + HHI_MPEG_CLK_CNTL) & (~((0x7 << 12) | (1 << 7) |
|
||||
(0x7F << 0)))) | ((5 << 12) | (1 << 7) | (2 << 0))),
|
||||
GX_HIU_BASE + HHI_MPEG_CLK_CNTL);
|
||||
setbits_32(GX_HIU_BASE + HHI_MPEG_CLK_CNTL, 1 << 8);
|
||||
writel(((5 << 16) | (1 << 15) | (1 << 14) | (12524 << 0)),
|
||||
GX_HIU_BASE + HHI_MPLL_CNTL8);
|
||||
} else if (IS_ENABLED(CONFIG_MESON_GXL)) {
|
||||
writel((1 << 12) | 3, GX_HIU_BASE + HHI_MPLL_CNTL10);
|
||||
writel(0x5edb7, GX_HIU_BASE + HHI_MPLL_CNTL7);
|
||||
clrbits_32(GX_HIU_BASE + HHI_MPEG_CLK_CNTL,
|
||||
(3 << 13) | (1 << 12) | (15 << 4) | 15);
|
||||
setbits_32(GX_HIU_BASE + HHI_MPEG_CLK_CNTL,
|
||||
(1 << 14) | (1 << 12) | (1 << 8) | (2 << 6) | (1 << 1));
|
||||
writel((4 << 16) | (7 << 13) | (1 << 8) | (5 << 4) | 10,
|
||||
GX_HIU_BASE + HHI_MPLL_CNTL8);
|
||||
}
|
||||
|
||||
udelay(200);
|
||||
|
||||
/* TODO: Some error handling and timeouts... */
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if CONFIG_IS_ENABLED(MMC) && !CONFIG_IS_ENABLED(DM_MMC)
|
||||
int board_mmc_init(struct bd_info *bis)
|
||||
{
|
||||
int mmc_device;
|
||||
|
||||
switch (meson_get_boot_device()) {
|
||||
case BOOT_DEVICE_SD:
|
||||
mmc_device = 0;
|
||||
break;
|
||||
case BOOT_DEVICE_EMMC:
|
||||
mmc_device = 1;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!meson_mmc_init(mmc_device))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
113
arch/arm/mach-meson/spl-gxbb.c
Normal file
113
arch/arm/mach-meson/spl-gxbb.c
Normal file
@@ -0,0 +1,113 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Portions Copyright (C) 2015, Amlogic, Inc. All rights reserved.
|
||||
* Copyright (C) 2023, Ferass El Hafidi <funderscore@postmarketos.org>
|
||||
*/
|
||||
#include <image.h>
|
||||
#include <spl.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/arch/gx.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#if CONFIG_IS_ENABLED(FIT_IMAGE_POST_PROCESS)
|
||||
/*
|
||||
* This is only needed for GXBB because on GXL SCP firmware loading
|
||||
* has been moved to BL31.
|
||||
*/
|
||||
inline void send_scp(void *addr, size_t size, const uint8_t *sha2,
|
||||
uint32_t sha2_length)
|
||||
{
|
||||
int i;
|
||||
|
||||
puts("Trying to send the SCP firmware\n");
|
||||
writel(size, GX_MB_SRAM_BASE);
|
||||
|
||||
udelay(500);
|
||||
|
||||
writel(GX_MB_CMD_DATA_LEN, GX_SEC_HIU_MAILBOX_SET_0 + 3 * 3 * 4);
|
||||
while (readl(GX_SEC_HIU_MAILBOX_SET_0 + 3 * 3 * 4))
|
||||
;
|
||||
udelay(500);
|
||||
|
||||
memcpy((void *)GX_MB_SRAM_BASE, (const void *)sha2, sha2_length);
|
||||
writel(GX_MB_CMD_SHA, GX_SEC_HIU_MAILBOX_SET_0 + 3 * 3 * 4);
|
||||
while (readl(GX_SEC_HIU_MAILBOX_STAT_0 + 3 * 3 * 4))
|
||||
;
|
||||
udelay(500);
|
||||
|
||||
for (i = 0; i < size; i += 1024) {
|
||||
if (size >= i + 1024)
|
||||
memcpy((void *)GX_MB_SRAM_BASE,
|
||||
(const void *)(unsigned long)(addr + i), 1024);
|
||||
else if (size > i)
|
||||
memcpy((void *)GX_MB_SRAM_BASE,
|
||||
(const void *)(unsigned long)(addr + i), (size - i));
|
||||
|
||||
writel(GX_MB_CMD_DATA, GX_SEC_HIU_MAILBOX_SET_0 + 3 * 3 * 4);
|
||||
while (readl(GX_SEC_HIU_MAILBOX_STAT_0 + 3 * 3 * 4))
|
||||
;
|
||||
}
|
||||
writel(GX_MB_CMD_OP_SHA, GX_SEC_HIU_MAILBOX_SET_0 + 3 * 3 * 4);
|
||||
|
||||
while (readl(GX_SEC_HIU_MAILBOX_STAT_0 + 3 * 3 * 4))
|
||||
;
|
||||
udelay(500);
|
||||
|
||||
/* We transferred all of the SCP firmware. Running it */
|
||||
writel(GX_MB_CMD_END, GX_SEC_HIU_MAILBOX_SET_0 + 3 * 3 * 4);
|
||||
}
|
||||
|
||||
void board_fit_image_post_process(const void *fit, int node, void **image, size_t *size)
|
||||
{
|
||||
const char *name = fit_get_name(fit, node, NULL);
|
||||
int noffset = 0, value_len;
|
||||
u8 *value;
|
||||
|
||||
if (strcmp("scp", name) && strcmp("bl301", name))
|
||||
return;
|
||||
|
||||
fdt_for_each_subnode(noffset, fit, node) {
|
||||
if (strncmp(fit_get_name(fit, noffset, NULL),
|
||||
FIT_HASH_NODENAME, strlen(FIT_HASH_NODENAME)))
|
||||
continue;
|
||||
|
||||
if (fit_image_hash_get_value(fit, noffset, &value, &value_len))
|
||||
continue;
|
||||
|
||||
/* Send the SCP firmware to the SCP */
|
||||
send_scp(*image, *size, value, value_len);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void meson_power_init(void)
|
||||
{
|
||||
/* TODO: Support more voltages */
|
||||
|
||||
/* Init PWM B */
|
||||
clrsetbits_32(GX_PWM_MISC_REG_AB, 0x7f << 16, (1 << 23) | (1 << 1));
|
||||
|
||||
/* Set voltage */
|
||||
if (CONFIG_IS_ENABLED(MESON_GX_VCCK_1120MV))
|
||||
writel(0x02001a, GX_PWM_PWM_B);
|
||||
else if (CONFIG_IS_ENABLED(MESON_GX_VCCK_1100MV))
|
||||
writel(0x040018, GX_PWM_PWM_B);
|
||||
else if (CONFIG_IS_ENABLED(MESON_GX_VCCK_1000MV))
|
||||
writel(0x0e000e, GX_PWM_PWM_B);
|
||||
|
||||
clrbits_32(GX_PIN_MUX_REG7, 1 << 22);
|
||||
clrsetbits_32(GX_PIN_MUX_REG3, 1 << 22, 1 << 21);
|
||||
|
||||
/* Init PWM D */
|
||||
clrsetbits_32(GX_PWM_MISC_REG_CD, 0x7f << 16, (1 << 23) | (1 << 1));
|
||||
|
||||
/* Set voltage */
|
||||
if (CONFIG_IS_ENABLED(MESON_GX_VDDEE_1100MV))
|
||||
writel(0x040018, GX_PWM_PWM_B);
|
||||
else if (CONFIG_IS_ENABLED(MESON_GX_VDDEE_1000MV))
|
||||
writel(0x0e000e, GX_PWM_PWM_B);
|
||||
|
||||
clrbits_32(GX_PIN_MUX_REG7, 1 << 23);
|
||||
setbits_32(GX_PIN_MUX_REG3, 1 << 20);
|
||||
}
|
||||
39
arch/arm/mach-meson/spl-gxl.c
Normal file
39
arch/arm/mach-meson/spl-gxl.c
Normal file
@@ -0,0 +1,39 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Portions Copyright (C) 2015, Amlogic, Inc. All rights reserved.
|
||||
* Copyright (C) 2023, Ferass El Hafidi <funderscore@postmarketos.org>
|
||||
*/
|
||||
#include <spl.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/arch/gx.h>
|
||||
|
||||
void meson_power_init_gxl(void)
|
||||
{
|
||||
/* TODO: Support more voltages */
|
||||
|
||||
/* Init PWM B */
|
||||
clrsetbits_32(GX_PWM_MISC_REG_AB, 0x7f << 16, (1 << 23) | (1 << 1));
|
||||
|
||||
/* Set voltage */
|
||||
if (CONFIG_IS_ENABLED(MESON_GX_VCCK_1120MV))
|
||||
writel(0x02001a, GX_PWM_PWM_B);
|
||||
else if (CONFIG_IS_ENABLED(MESON_GX_VCCK_1100MV))
|
||||
writel(0x040018, GX_PWM_PWM_B);
|
||||
else if (CONFIG_IS_ENABLED(MESON_GX_VCCK_1000MV))
|
||||
writel(0x0e000e, GX_PWM_PWM_B);
|
||||
|
||||
clrbits_32(GX_PIN_MUX_REG1, 1 << 10);
|
||||
clrsetbits_32(GX_PIN_MUX_REG2, 1 << 5, 1 << 11);
|
||||
|
||||
/* Init PWM D */
|
||||
clrsetbits_32(GX_PWM_MISC_REG_CD, 0x7f << 16, (1 << 23) | (1 << 1));
|
||||
|
||||
/* Set voltage */
|
||||
if (CONFIG_IS_ENABLED(MESON_GX_VDDEE_1100MV))
|
||||
writel(0x040018, GX_PWM_PWM_B);
|
||||
else if (CONFIG_IS_ENABLED(MESON_GX_VDDEE_1000MV))
|
||||
writel(0x0e000e, GX_PWM_PWM_B);
|
||||
|
||||
clrbits_32(GX_PIN_MUX_REG1, (1 << 9) | (1 << 11));
|
||||
setbits_32(GX_PIN_MUX_REG2, 1 << 12);
|
||||
}
|
||||
123
arch/arm/mach-meson/spl.c
Normal file
123
arch/arm/mach-meson/spl.c
Normal file
@@ -0,0 +1,123 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Portions Copyright (C) 2015, Amlogic, Inc. All rights reserved.
|
||||
* Copyright (C) 2023, Ferass El Hafidi <funderscore@postmarketos.org>
|
||||
*/
|
||||
#include <spl.h>
|
||||
#include <hang.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/spl.h>
|
||||
#include <asm/arch/boot.h>
|
||||
#include <vsprintf.h>
|
||||
#include <asm/ptrace.h>
|
||||
#include <asm/system.h>
|
||||
#include <atf_common.h>
|
||||
#include <image.h>
|
||||
#include <asm/arch/gx.h>
|
||||
#include <linux/delay.h>
|
||||
#include <asm/arch/clock-gx.h>
|
||||
|
||||
u32 spl_boot_device(void)
|
||||
{
|
||||
int boot_device = meson_get_boot_device();
|
||||
|
||||
switch (boot_device) {
|
||||
case BOOT_DEVICE_EMMC:
|
||||
return BOOT_DEVICE_MMC2;
|
||||
case BOOT_DEVICE_SD:
|
||||
return BOOT_DEVICE_MMC1;
|
||||
/*
|
||||
* TODO: Get USB DFU to work
|
||||
* Right now we just panic when booted from USB.
|
||||
*/
|
||||
case BOOT_DEVICE_USB:
|
||||
if (CONFIG_IS_ENABLED(YMODEM_SUPPORT))
|
||||
return BOOT_DEVICE_UART;
|
||||
else
|
||||
return BOOT_DEVICE_DFU;
|
||||
}
|
||||
|
||||
panic("Unknown device %d\n", boot_device);
|
||||
return BOOT_DEVICE_NONE; /* Never reached */
|
||||
}
|
||||
|
||||
__weak struct legacy_img_hdr *spl_get_load_buffer(ssize_t offset, size_t size)
|
||||
{
|
||||
return (void *)CONFIG_TEXT_BASE + 0x4000000;
|
||||
}
|
||||
|
||||
__weak void *board_spl_fit_buffer_addr(ulong fit_size, int sectors, int bl_len)
|
||||
{
|
||||
/* HACK: use same fit load buffer address as for mmc raw */
|
||||
return spl_get_load_buffer(0, fit_size);
|
||||
}
|
||||
|
||||
__weak bool spl_load_simple_fit_skip_processing(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* To be defined in dram-${GENERATION}.c */
|
||||
__weak int dram_init(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Placeholder functions to be defined in SoC-specific spl-... file */
|
||||
__weak void meson_power_init(void)
|
||||
{
|
||||
}
|
||||
|
||||
__weak int meson_pll_init(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void board_init_f(ulong dummy)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Restart execution at EL3 */
|
||||
if (current_el() != 3) {
|
||||
struct pt_regs regs = {0};
|
||||
static struct entry_point_info spl_ep_info;
|
||||
|
||||
SET_PARAM_HEAD(&spl_ep_info, ATF_PARAM_BL31, ATF_VERSION_1, 0);
|
||||
spl_ep_info.pc = CONFIG_SPL_TEXT_BASE;
|
||||
spl_ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX, DISABLE_ALL_EXECPTIONS);
|
||||
|
||||
regs.regs[0] = 0xc0000000;
|
||||
regs.regs[1] = (unsigned long)&spl_ep_info;
|
||||
smc_call(®s);
|
||||
}
|
||||
|
||||
meson_power_init();
|
||||
ret = meson_pll_init();
|
||||
if (ret) {
|
||||
debug("meson_pll_init() failed: %d\n", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
ret = dram_init();
|
||||
if (ret) {
|
||||
debug("dram_init() failed: %d\n", ret);
|
||||
hang();
|
||||
}
|
||||
|
||||
if (CONFIG_IS_ENABLED(OF_CONTROL)) {
|
||||
ret = spl_early_init();
|
||||
if (ret) {
|
||||
debug("spl_early_init() failed: %d\n", ret);
|
||||
hang();
|
||||
}
|
||||
}
|
||||
|
||||
spl_init();
|
||||
icache_enable();
|
||||
preloader_console_init();
|
||||
|
||||
#if !CONFIG_IS_ENABLED(WDT_MESON_GXBB)
|
||||
/* Disable watchdog */
|
||||
clrbits_32(GX_WDT_CTRL_REG, (1 << 18) | (1 << 25));
|
||||
#endif
|
||||
}
|
||||
38
board/amlogic/p200/spl-odroid-c2.config
Normal file
38
board/amlogic/p200/spl-odroid-c2.config
Normal file
@@ -0,0 +1,38 @@
|
||||
#
|
||||
# U-Boot SPL fragment for odroid-c2
|
||||
#
|
||||
|
||||
CONFIG_SPL=y
|
||||
CONFIG_SPL_LIBCOMMON_SUPPORT=y
|
||||
CONFIG_SPL_LIBGENERIC_SUPPORT=y
|
||||
CONFIG_SPL_TEXT_BASE=0xd9001000
|
||||
CONFIG_SPL_STACK=0xd9013000
|
||||
CONFIG_SPL_HAS_BSS_LINKER_SECTION=y
|
||||
CONFIG_SPL_BSS_START_ADDR=0xd900c000
|
||||
CONFIG_SPL_HAVE_INIT_STACK=y
|
||||
CONFIG_SPL_BSS_MAX_SIZE=0x1000
|
||||
CONFIG_SPL_SYS_MALLOC_SIMPLE=y
|
||||
# CONFIG_SPL_SHARES_INIT_SP_ADDR is not set
|
||||
# CONFIG_SPL_SERIAL_PRESENT is not set
|
||||
CONFIG_SPL_SHA256=y
|
||||
# CONFIG_SPL_SHA1 is not set
|
||||
|
||||
# Enable MMC and serial drivers
|
||||
CONFIG_SPL_SERIAL=y
|
||||
CONFIG_SPL_DRIVERS_MISC=y
|
||||
CONFIG_SPL_MMC=y
|
||||
CONFIG_SPL_SYS_MMCSD_RAW_MODE=y
|
||||
CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0x100
|
||||
# CONFIG_SYS_MMCSD_FS_BOOT is not set
|
||||
|
||||
# Image things
|
||||
CONFIG_SPL_LOAD_FIT=y
|
||||
CONFIG_SPL_FIT_IMAGE_POST_PROCESS=y
|
||||
CONFIG_SPL_MAX_SIZE=0xb000
|
||||
CONFIG_SPL_PAD_TO=0x1fe00
|
||||
CONFIG_SPL_ATF=y
|
||||
CONFIG_SPL_OF_CONTROL=y
|
||||
# DRAM configuration
|
||||
CONFIG_DRAM_SIZE=2048
|
||||
CONFIG_DRAM_2T_MODE=y
|
||||
CONFIG_DRAM_TWO_IDENTICAL_RANKS=y
|
||||
39
board/amlogic/p200/spl-videostrong-kii-pro.config
Normal file
39
board/amlogic/p200/spl-videostrong-kii-pro.config
Normal file
@@ -0,0 +1,39 @@
|
||||
#
|
||||
# U-Boot SPL fragment for videostrong-kii-pro
|
||||
#
|
||||
|
||||
CONFIG_SPL=y
|
||||
CONFIG_SPL_LIBCOMMON_SUPPORT=y
|
||||
CONFIG_SPL_LIBGENERIC_SUPPORT=y
|
||||
CONFIG_SPL_TEXT_BASE=0xd9001000
|
||||
CONFIG_SPL_STACK=0xd9013000
|
||||
CONFIG_SPL_HAS_BSS_LINKER_SECTION=y
|
||||
CONFIG_SPL_BSS_START_ADDR=0xd900c000
|
||||
CONFIG_SPL_HAVE_INIT_STACK=y
|
||||
CONFIG_SPL_BSS_MAX_SIZE=0x1000
|
||||
CONFIG_SPL_SYS_MALLOC_SIMPLE=y
|
||||
# CONFIG_SPL_SHARES_INIT_SP_ADDR is not set
|
||||
# CONFIG_SPL_SERIAL_PRESENT is not set
|
||||
CONFIG_SPL_SHA256=y
|
||||
# CONFIG_SPL_SHA1 is not set
|
||||
|
||||
# Enable MMC and serial drivers
|
||||
CONFIG_SPL_SERIAL=y
|
||||
CONFIG_SPL_DRIVERS_MISC=y
|
||||
CONFIG_SPL_MMC=y
|
||||
CONFIG_SPL_SYS_MMCSD_RAW_MODE=y
|
||||
CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0x100
|
||||
# CONFIG_SYS_MMCSD_FS_BOOT is not set
|
||||
|
||||
# Image things
|
||||
CONFIG_SPL_LOAD_FIT=y
|
||||
CONFIG_SPL_FIT_IMAGE_POST_PROCESS=y
|
||||
CONFIG_SPL_MAX_SIZE=0xb000
|
||||
CONFIG_SPL_PAD_TO=0x1fe00
|
||||
CONFIG_SPL_ATF=y
|
||||
CONFIG_SPL_OF_CONTROL=y
|
||||
# DRAM configuration
|
||||
CONFIG_DRAM_SIZE=2048
|
||||
CONFIG_DRAM_2T_MODE=y
|
||||
CONFIG_DRAM_TWO_DIFF_RANKS=y
|
||||
|
||||
36
board/amlogic/p212/spl-libretech-cc-1gb.config
Normal file
36
board/amlogic/p212/spl-libretech-cc-1gb.config
Normal file
@@ -0,0 +1,36 @@
|
||||
#
|
||||
# U-Boot SPL fragment for libretech-cc (1 GB variant)
|
||||
#
|
||||
|
||||
CONFIG_SPL=y
|
||||
CONFIG_SPL_LIBCOMMON_SUPPORT=y
|
||||
CONFIG_SPL_LIBGENERIC_SUPPORT=y
|
||||
CONFIG_SPL_TEXT_BASE=0xd9001000
|
||||
CONFIG_SPL_STACK=0xd9013000
|
||||
CONFIG_SPL_HAS_BSS_LINKER_SECTION=y
|
||||
CONFIG_SPL_BSS_START_ADDR=0xd900c000
|
||||
CONFIG_SPL_HAVE_INIT_STACK=y
|
||||
CONFIG_SPL_BSS_MAX_SIZE=0x1000
|
||||
CONFIG_SPL_SYS_MALLOC_SIMPLE=y
|
||||
# CONFIG_SPL_SHARES_INIT_SP_ADDR is not set
|
||||
# CONFIG_SPL_SERIAL_PRESENT is not set
|
||||
CONFIG_SPL_SHA256=y
|
||||
# CONFIG_SPL_SHA1 is not set
|
||||
|
||||
# Enable MMC and serial drivers
|
||||
CONFIG_SPL_SERIAL=y
|
||||
CONFIG_SPL_DRIVERS_MISC=y
|
||||
CONFIG_SPL_MMC=y
|
||||
CONFIG_SPL_SYS_MMCSD_RAW_MODE=y
|
||||
CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0x100
|
||||
# CONFIG_SYS_MMCSD_FS_BOOT is not set
|
||||
|
||||
# Image things
|
||||
CONFIG_SPL_LOAD_FIT=y
|
||||
CONFIG_SPL_MAX_SIZE=0xb000
|
||||
CONFIG_SPL_PAD_TO=0x1fe00
|
||||
CONFIG_SPL_ATF=y
|
||||
CONFIG_SPL_OF_CONTROL=y
|
||||
# DRAM configuration
|
||||
CONFIG_DRAM_2T_MODE=y
|
||||
CONFIG_DRAM_DQS_CORR=y
|
||||
38
board/amlogic/p212/spl-libretech-cc-2gb.config
Normal file
38
board/amlogic/p212/spl-libretech-cc-2gb.config
Normal file
@@ -0,0 +1,38 @@
|
||||
#
|
||||
# U-Boot SPL fragment for libretech-cc (2 GB variant)
|
||||
#
|
||||
|
||||
CONFIG_SPL=y
|
||||
CONFIG_SPL_LIBCOMMON_SUPPORT=y
|
||||
CONFIG_SPL_LIBGENERIC_SUPPORT=y
|
||||
CONFIG_SPL_TEXT_BASE=0xd9001000
|
||||
CONFIG_SPL_STACK=0xd9013000
|
||||
CONFIG_SPL_HAS_BSS_LINKER_SECTION=y
|
||||
CONFIG_SPL_BSS_START_ADDR=0xd900c000
|
||||
CONFIG_SPL_HAVE_INIT_STACK=y
|
||||
CONFIG_SPL_BSS_MAX_SIZE=0x1000
|
||||
CONFIG_SPL_SYS_MALLOC_SIMPLE=y
|
||||
# CONFIG_SPL_SHARES_INIT_SP_ADDR is not set
|
||||
# CONFIG_SPL_SERIAL_PRESENT is not set
|
||||
CONFIG_SPL_SHA256=y
|
||||
# CONFIG_SPL_SHA1 is not set
|
||||
|
||||
# Enable MMC and serial drivers
|
||||
CONFIG_SPL_SERIAL=y
|
||||
CONFIG_SPL_DRIVERS_MISC=y
|
||||
CONFIG_SPL_MMC=y
|
||||
CONFIG_SPL_SYS_MMCSD_RAW_MODE=y
|
||||
CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0x100
|
||||
# CONFIG_SYS_MMCSD_FS_BOOT is not set
|
||||
|
||||
# Image things
|
||||
CONFIG_SPL_LOAD_FIT=y
|
||||
CONFIG_SPL_MAX_SIZE=0xb000
|
||||
CONFIG_SPL_PAD_TO=0x1fe00
|
||||
CONFIG_SPL_ATF=y
|
||||
CONFIG_SPL_OF_CONTROL=y
|
||||
# DRAM configuration
|
||||
CONFIG_DRAM_SIZE=2048
|
||||
CONFIG_DRAM_2T_MODE=y
|
||||
CONFIG_DRAM_DQS_CORR=y
|
||||
CONFIG_DRAM_TWO_IDENTICAL_RANKS=y
|
||||
@@ -12,20 +12,6 @@
|
||||
#include <asm/io.h>
|
||||
#include <asm/arch/eth.h>
|
||||
|
||||
struct efi_fw_image fw_images[] = {
|
||||
{
|
||||
.fw_name = u"AML_A311D_CC_BOOT",
|
||||
.image_index = 1,
|
||||
},
|
||||
};
|
||||
|
||||
struct efi_capsule_update_info update_info = {
|
||||
.dfu_string = "sf 0:0=u-boot-bin raw 0 0x10000",
|
||||
.num_images = ARRAY_SIZE(fw_images),
|
||||
.images = fw_images,
|
||||
};
|
||||
|
||||
|
||||
#if IS_ENABLED(CONFIG_SET_DFU_ALT_INFO)
|
||||
void set_dfu_alt_info(char *interface, char *devstr)
|
||||
{
|
||||
|
||||
@@ -20,19 +20,6 @@
|
||||
#define EFUSE_MAC_OFFSET 52
|
||||
#define EFUSE_MAC_SIZE 6
|
||||
|
||||
struct efi_fw_image fw_images[] = {
|
||||
{
|
||||
.fw_name = u"AML_S805X_AC_BOOT",
|
||||
.image_index = 1,
|
||||
},
|
||||
};
|
||||
|
||||
struct efi_capsule_update_info update_info = {
|
||||
.dfu_string = "sf 0:0=u-boot-bin raw 0 0x10000",
|
||||
.num_images = ARRAY_SIZE(fw_images),
|
||||
.images = fw_images,
|
||||
};
|
||||
|
||||
#if IS_ENABLED(CONFIG_SET_DFU_ALT_INFO)
|
||||
void set_dfu_alt_info(char *interface, char *devstr)
|
||||
{
|
||||
|
||||
@@ -12,20 +12,6 @@
|
||||
#include <asm/io.h>
|
||||
#include <asm/arch/eth.h>
|
||||
|
||||
struct efi_fw_image fw_images[] = {
|
||||
{
|
||||
.fw_name = u"AML_S905D3_CC_BOOT",
|
||||
.image_index = 1,
|
||||
},
|
||||
};
|
||||
|
||||
struct efi_capsule_update_info update_info = {
|
||||
.dfu_string = "sf 0:0=u-boot-bin raw 0 0x10000",
|
||||
.num_images = ARRAY_SIZE(fw_images),
|
||||
.images = fw_images,
|
||||
};
|
||||
|
||||
|
||||
#if IS_ENABLED(CONFIG_SET_DFU_ALT_INFO)
|
||||
void set_dfu_alt_info(char *interface, char *devstr)
|
||||
{
|
||||
|
||||
@@ -185,6 +185,7 @@ static const table_entry_t uimage_type[] = {
|
||||
{ IH_TYPE_STARFIVE_SPL, "sfspl", "StarFive SPL Image" },
|
||||
{ IH_TYPE_TFA_BL31, "tfa-bl31", "TFA BL31 Image", },
|
||||
{ IH_TYPE_STM32IMAGE_V2, "stm32imagev2", "STMicroelectronics STM32 Image V2.0" },
|
||||
{ IH_TYPE_AMLIMAGE, "amlimage", "Amlogic Boot Image" },
|
||||
{ -1, "", "", },
|
||||
};
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@ config SPL_SIZE_LIMIT
|
||||
default 0x11000 if ARCH_MX6 && !MX6_OCRAM_256KB
|
||||
default 0x31000 if ARCH_MX6 && MX6_OCRAM_256KB
|
||||
default 0x30000 if ARCH_MVEBU && ARMADA_32BIT
|
||||
default 0xb000 if ARCH_MESON && MESON_GX
|
||||
default 0x0
|
||||
help
|
||||
Specifies the maximum length of the U-Boot SPL image.
|
||||
|
||||
@@ -78,6 +78,7 @@ Boot Documentation
|
||||
|
||||
boot-flow
|
||||
pre-generated-fip
|
||||
spl
|
||||
|
||||
Board Documentation
|
||||
-------------------
|
||||
|
||||
@@ -98,6 +98,13 @@ The repo also provides the following files used with GXBB boards:
|
||||
The repo also supports the open-source 'gxlimg' signing tool that can be used to sign
|
||||
U-Boot binaries for GXL/GXM/G12A/G12B/SM1 boards: https://github.com/repk/gxlimg
|
||||
|
||||
The following binaries can be replaced with open-source implementations:
|
||||
|
||||
- bl2.bin (GXBB and GXL only)
|
||||
- bl31.img (GXBB, GXL, AXG and G12A only)
|
||||
|
||||
Refer to `Experimental U-Boot SPL Support`_ if you wish to replace them.
|
||||
|
||||
Licensing
|
||||
---------
|
||||
|
||||
@@ -129,3 +136,5 @@ clarified. The current Amlogic distribution licence is below:
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
.. _`Experimental U-Boot SPL Support`: spl.rst
|
||||
|
||||
77
doc/board/amlogic/spl.rst
Normal file
77
doc/board/amlogic/spl.rst
Normal file
@@ -0,0 +1,77 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0+
|
||||
|
||||
Experimental U-Boot SPL Support
|
||||
===============================
|
||||
|
||||
There's some experimental support for some Amlogic SoCs, in U-Boot SPL. It
|
||||
replaces the proprietary bl2.bin blob used for DRAM init. Currently Meson GX
|
||||
SoCs (GXBB, GXL) are supported.
|
||||
|
||||
A subset of Amlogic boards have SPL enabled. These boards have been tested and
|
||||
are known to work to an extent.
|
||||
|
||||
|
||||
Building Arm Trusted Firmware (TF-A)
|
||||
------------------------------------
|
||||
|
||||
This U-Boot SPL port requires the BL31 stage of mainline Arm Trusted
|
||||
Firmware-A firmware. It provides an open source implementation of secure
|
||||
software for Armv8-A. Build it with:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ git clone https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git
|
||||
$ cd trusted-firmware-a
|
||||
$ make CROSS_COMPILE=aarch64-linux-gnu- PLAT=your_soc AML_STDPARAMS=1
|
||||
|
||||
Replace ``your_soc`` with the SoC target you wish to build for. For GXBB it's
|
||||
``gxbb`` and for GXL it's ``gxl``.
|
||||
|
||||
|
||||
Building a bl30_new.bin binary
|
||||
------------------------------
|
||||
|
||||
``bl30_new.bin`` has both ``bl30.bin`` and ``bl301.bin`` binary blobs
|
||||
bundled. The former is the proper system control processor firmware and the
|
||||
latter is a "plug-in" for board-specific DVFS/suspend-resume parameters. For
|
||||
more info you may wish to read this page: `Pre-Generated FIP File Repo`_.
|
||||
|
||||
To build using the FIP file repo, simply issue the following commands:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ cd amlogic-boot-fip/your_board
|
||||
$ make bl30_new.bin
|
||||
|
||||
|
||||
.. _`Pre-Generated FIP File Repo`: pre-generated-fip.rst
|
||||
|
||||
|
||||
U-Boot compilation
|
||||
------------------
|
||||
|
||||
U-Boot SPL is not enabled by default, instead there are config fragments that
|
||||
can be used to enable it, with per-board configuration:
|
||||
|
||||
- ``spl-libretech-cc-1gb.config``: 1 GB LePotato board
|
||||
- ``spl-libretech-cc-2gb.config``: 2 GB LePotato board
|
||||
- ``spl-odroid-c2.config``: ODROID-C2
|
||||
- ``spl-videostrong-kii-pro.config``: Videostrong KII Pro
|
||||
|
||||
Pick one of them then:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ export CROSS_COMPILE=aarch64-linux-gnu-
|
||||
$ export BL31=path/to/tf-a/bl31.bin # Upstream TF-A BL31 binary
|
||||
$ export SCP=path/to/bl30_new.bin # bl30_new.bin binary
|
||||
$ make <yourboardname>_defconfig spl-<yourboardname>.config
|
||||
$ make
|
||||
|
||||
Write to SD:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ DEV=/dev/boot_device
|
||||
$ dd if=u-boot-meson-with-spl.bin of=$DEV conv=fsync,notrunc bs=512 seek=1
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <linux/log2.h>
|
||||
#include "meson_gx_mmc.h"
|
||||
|
||||
#if CONFIG_IS_ENABLED(DM_MMC)
|
||||
bool meson_gx_mmc_is_compatible(struct udevice *dev,
|
||||
enum meson_gx_mmc_compatible family)
|
||||
{
|
||||
@@ -23,6 +24,7 @@ bool meson_gx_mmc_is_compatible(struct udevice *dev,
|
||||
|
||||
return compat == family;
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline void *get_regbase(const struct mmc *mmc)
|
||||
{
|
||||
@@ -67,10 +69,14 @@ static void meson_mmc_config_clock(struct mmc *mmc)
|
||||
* Other SoCs use CLK_CO_PHASE_180 by default.
|
||||
* It needs to find what is a proper value about each SoCs.
|
||||
*/
|
||||
#if CONFIG_IS_ENABLED(DM_MMC)
|
||||
if (meson_gx_mmc_is_compatible(mmc->dev, MMC_COMPATIBLE_SM1))
|
||||
meson_mmc_clk |= CLK_CO_PHASE_270;
|
||||
else
|
||||
meson_mmc_clk |= CLK_CO_PHASE_180;
|
||||
#else /* U-Boot SPL on GX SoCs */
|
||||
meson_mmc_clk |= CLK_CO_PHASE_180;
|
||||
#endif
|
||||
|
||||
/* 180 phase tx clock */
|
||||
meson_mmc_clk |= CLK_TX_PHASE_000;
|
||||
@@ -82,9 +88,14 @@ static void meson_mmc_config_clock(struct mmc *mmc)
|
||||
meson_write(mmc, meson_mmc_clk, MESON_SD_EMMC_CLOCK);
|
||||
}
|
||||
|
||||
#if CONFIG_IS_ENABLED(DM_MMC)
|
||||
static int meson_dm_mmc_set_ios(struct udevice *dev)
|
||||
{
|
||||
struct mmc *mmc = mmc_get_mmc_dev(dev);
|
||||
#else /* U-Boot SPL */
|
||||
static int meson_legacy_mmc_set_ios(struct mmc *mmc)
|
||||
{
|
||||
#endif
|
||||
uint32_t meson_mmc_cfg;
|
||||
|
||||
meson_mmc_config_clock(mmc);
|
||||
@@ -193,10 +204,16 @@ static void meson_mmc_read_response(struct mmc *mmc, struct mmc_cmd *cmd)
|
||||
}
|
||||
}
|
||||
|
||||
#if CONFIG_IS_ENABLED(DM_MMC)
|
||||
static int meson_dm_mmc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
|
||||
struct mmc_data *data)
|
||||
{
|
||||
struct mmc *mmc = mmc_get_mmc_dev(dev);
|
||||
#else /* U-Boot SPL */
|
||||
static int meson_legacy_mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
|
||||
struct mmc_data *data)
|
||||
{
|
||||
#endif
|
||||
struct meson_mmc_plat *pdata = mmc->priv;
|
||||
uint32_t status;
|
||||
ulong start;
|
||||
@@ -235,6 +252,59 @@ static int meson_dm_mmc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if !CONFIG_IS_ENABLED(DM_MMC) /* Non-DM MMC driver for use in U-Boot SPL */
|
||||
struct meson_mmc_plat mmc_plat[2];
|
||||
|
||||
static int meson_legacy_mmc_init(struct mmc *mmc)
|
||||
{
|
||||
/* reset all status bits */
|
||||
meson_write(mmc, STATUS_MASK, MESON_SD_EMMC_STATUS);
|
||||
|
||||
/* disable interrupts */
|
||||
meson_write(mmc, 0, MESON_SD_EMMC_IRQ_EN);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct mmc_ops meson_mmc_ops = {
|
||||
.send_cmd = meson_legacy_mmc_send_cmd,
|
||||
.set_ios = meson_legacy_mmc_set_ios,
|
||||
.init = meson_legacy_mmc_init,
|
||||
};
|
||||
|
||||
struct mmc *meson_mmc_init(int mmc_no)
|
||||
{
|
||||
struct meson_mmc_plat *pdata = &mmc_plat[mmc_no];
|
||||
struct mmc_config *cfg = &pdata->cfg;
|
||||
|
||||
cfg->voltages = MMC_VDD_33_34 | MMC_VDD_32_33 |
|
||||
MMC_VDD_31_32 | MMC_VDD_165_195;
|
||||
cfg->host_caps = MMC_MODE_8BIT | MMC_MODE_4BIT;
|
||||
cfg->f_min = DIV_ROUND_UP(SD_EMMC_CLKSRC_24M, CLK_MAX_DIV);
|
||||
cfg->f_max = 6000000; /* 6 MHz */
|
||||
cfg->b_max = 127; /* max 128 - 1 block */
|
||||
cfg->name = "Meson SD/eMMC";
|
||||
cfg->ops = &meson_mmc_ops;
|
||||
|
||||
if (mmc_no == 0) /* MMC1: SD card */
|
||||
pdata->regbase = (void *)0xd0072000;
|
||||
else if (mmc_no == 1) /* MMC2: eMMC */
|
||||
pdata->regbase = (void *)0xd0074000;
|
||||
|
||||
#if CONFIG_IS_ENABLED(MMC_PWRSEQ)
|
||||
/* Enable power if needed */
|
||||
ret = mmc_pwrseq_get_power(dev, cfg);
|
||||
if (!ret) {
|
||||
ret = pwrseq_set_power(cfg->pwr_dev, true);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
return mmc_create(cfg, pdata);
|
||||
}
|
||||
|
||||
#else /* DM-based driver for use in U-Boot proper */
|
||||
static const struct dm_mmc_ops meson_dm_mmc_ops = {
|
||||
.send_cmd = meson_dm_mmc_send_cmd,
|
||||
.set_ios = meson_dm_mmc_set_ios,
|
||||
@@ -278,10 +348,16 @@ static int meson_mmc_probe(struct udevice *dev)
|
||||
cfg->host_caps = MMC_MODE_8BIT | MMC_MODE_4BIT |
|
||||
MMC_MODE_HS_52MHz | MMC_MODE_HS;
|
||||
cfg->f_min = DIV_ROUND_UP(SD_EMMC_CLKSRC_24M, CLK_MAX_DIV);
|
||||
cfg->f_max = 100000000; /* 100 MHz */
|
||||
cfg->f_max = 40000000; /* 40 MHz */
|
||||
cfg->b_max = 511; /* max 512 - 1 blocks */
|
||||
cfg->name = dev->name;
|
||||
|
||||
if (IS_ENABLED(CONFIG_SPL_BUILD)) {
|
||||
cfg->host_caps &= ~(MMC_MODE_HS_52MHz | MMC_MODE_HS);
|
||||
cfg->f_max = 6000000; /* 6 MHz */
|
||||
cfg->b_max = 127; /* max 128 - 1 block */
|
||||
}
|
||||
|
||||
mmc->priv = pdata;
|
||||
upriv->mmc = mmc;
|
||||
|
||||
@@ -336,3 +412,4 @@ U_BOOT_DRIVER(meson_mmc) = {
|
||||
.of_to_plat = meson_mmc_of_to_plat,
|
||||
.plat_auto = sizeof(struct meson_mmc_plat),
|
||||
};
|
||||
#endif /* CONFIG_IS_ENABLED(DM_MMC) */
|
||||
|
||||
@@ -129,6 +129,7 @@ serial_initfunc(pxa_serial_initialize);
|
||||
serial_initfunc(smh_serial_initialize);
|
||||
serial_initfunc(sh_serial_initialize);
|
||||
serial_initfunc(mtk_serial_initialize);
|
||||
serial_initfunc(meson_serial_initialize);
|
||||
|
||||
/**
|
||||
* serial_register() - Register serial driver with serial driver core
|
||||
@@ -167,6 +168,7 @@ int serial_initialize(void)
|
||||
smh_serial_initialize();
|
||||
sh_serial_initialize();
|
||||
mtk_serial_initialize();
|
||||
meson_serial_initialize();
|
||||
|
||||
serial_assign(default_serial_console()->name);
|
||||
|
||||
|
||||
@@ -3,9 +3,11 @@
|
||||
* (C) Copyright 2016 Beniamino Galvani <b.galvani@gmail.com>
|
||||
*/
|
||||
|
||||
#if CONFIG_IS_ENABLED(DM_SERIAL)
|
||||
#include <dm.h>
|
||||
#include <errno.h>
|
||||
#include <fdtdec.h>
|
||||
#endif
|
||||
#include <errno.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/compiler.h>
|
||||
@@ -25,6 +27,15 @@ struct meson_serial_plat {
|
||||
struct meson_uart *reg;
|
||||
};
|
||||
|
||||
#if !CONFIG_IS_ENABLED(DM_SERIAL)
|
||||
/* UART base address */
|
||||
#if defined(CONFIG_MESON_GX)
|
||||
#define AML_UART_BASE 0xc81004c0
|
||||
#else /* G12A, AXG, ... */
|
||||
#define AML_UART_BASE 0xff803000
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* AML_UART_STATUS bits */
|
||||
#define AML_UART_PARITY_ERR BIT(16)
|
||||
#define AML_UART_FRAME_ERR BIT(17)
|
||||
@@ -51,6 +62,7 @@ struct meson_serial_plat {
|
||||
#define AML_UART_REG5_USE_NEW_BAUD BIT(23) /* default 1 (use new baud rate register) */
|
||||
#define AML_UART_REG5_BAUD_MASK 0x7fffff
|
||||
|
||||
#if CONFIG_IS_ENABLED(DM_SERIAL)
|
||||
static u32 meson_calc_baud_divisor(ulong src_rate, u32 baud)
|
||||
{
|
||||
/*
|
||||
@@ -245,6 +257,111 @@ U_BOOT_DRIVER(serial_meson) = {
|
||||
.plat_auto = sizeof(struct meson_serial_plat),
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
static int meson_serial_init(void)
|
||||
{
|
||||
struct meson_uart *const uart = (struct meson_uart *)AML_UART_BASE;
|
||||
u32 val;
|
||||
|
||||
val = readl(&uart->control);
|
||||
val |= (AML_UART_RX_RST | AML_UART_TX_RST | AML_UART_CLR_ERR);
|
||||
writel(val, &uart->control);
|
||||
val &= ~(AML_UART_RX_RST | AML_UART_TX_RST | AML_UART_CLR_ERR);
|
||||
writel(val, &uart->control);
|
||||
val |= (AML_UART_RX_EN | AML_UART_TX_EN);
|
||||
writel(val, &uart->control);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int meson_serial_stop(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void meson_serial_setbrg(void)
|
||||
{
|
||||
}
|
||||
|
||||
static void meson_serial_putc(const char ch)
|
||||
{
|
||||
struct meson_uart *uart = (struct meson_uart *)AML_UART_BASE;
|
||||
|
||||
/* On '\n' also do '\r' */
|
||||
if (ch == '\n')
|
||||
meson_serial_putc('\r');
|
||||
|
||||
while (readl(&uart->status) & AML_UART_TX_FULL)
|
||||
;
|
||||
|
||||
writel(ch, &uart->wfifo);
|
||||
}
|
||||
|
||||
static void meson_serial_puts(const char *s)
|
||||
{
|
||||
while (*s)
|
||||
meson_serial_putc(*s++);
|
||||
}
|
||||
|
||||
static int meson_serial_getc(void)
|
||||
{
|
||||
struct meson_uart *const uart = (struct meson_uart *)AML_UART_BASE;
|
||||
uint32_t status = readl(&uart->status);
|
||||
|
||||
if (status & AML_UART_RX_EMPTY)
|
||||
return -EAGAIN;
|
||||
|
||||
if (status & AML_UART_ERR) {
|
||||
u32 val = readl(&uart->control);
|
||||
|
||||
/* Clear error */
|
||||
val |= AML_UART_CLR_ERR;
|
||||
writel(val, &uart->control);
|
||||
val &= ~AML_UART_CLR_ERR;
|
||||
writel(val, &uart->control);
|
||||
|
||||
/* Remove spurious byte from fifo */
|
||||
readl(&uart->rfifo);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return readl(&uart->rfifo) & 0xff;
|
||||
}
|
||||
|
||||
static int meson_serial_tstc(void)
|
||||
{
|
||||
struct meson_uart *const uart = (struct meson_uart *)AML_UART_BASE;
|
||||
uint32_t status = readl(&uart->status);
|
||||
|
||||
if (status & AML_UART_RX_EMPTY)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct serial_device meson_serial_device = {
|
||||
.name = "meson_serial",
|
||||
.start = meson_serial_init,
|
||||
.stop = meson_serial_stop,
|
||||
.setbrg = meson_serial_setbrg,
|
||||
.getc = meson_serial_getc,
|
||||
.tstc = meson_serial_tstc,
|
||||
.putc = meson_serial_putc,
|
||||
.puts = meson_serial_puts,
|
||||
};
|
||||
|
||||
void meson_serial_initialize(void)
|
||||
{
|
||||
serial_register(&meson_serial_device);
|
||||
}
|
||||
|
||||
__weak struct serial_device *default_serial_console(void)
|
||||
{
|
||||
return &meson_serial_device;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_DEBUG_UART_MESON
|
||||
|
||||
#include <debug_uart.h>
|
||||
|
||||
@@ -234,6 +234,7 @@ enum image_type_t {
|
||||
IH_TYPE_STARFIVE_SPL, /* StarFive SPL image */
|
||||
IH_TYPE_TFA_BL31, /* TFA BL31 image */
|
||||
IH_TYPE_STM32IMAGE_V2, /* STMicroelectronics STM32 Image V2.0 */
|
||||
IH_TYPE_AMLIMAGE, /* Amlogic Boot Image */
|
||||
|
||||
IH_TYPE_COUNT, /* Number of image types */
|
||||
};
|
||||
|
||||
@@ -110,6 +110,7 @@ ROCKCHIP_OBS = generated/lib/rc4.o rkcommon.o rkimage.o rksd.o rkspi.o
|
||||
|
||||
# common objs for dumpimage and mkimage
|
||||
dumpimage-mkimage-objs := aisimage.o \
|
||||
amlimage.o \
|
||||
atmelimage.o \
|
||||
$(FIT_OBJS-y) \
|
||||
$(FIT_SIG_OBJS-y) \
|
||||
|
||||
255
tools/amlimage.c
Normal file
255
tools/amlimage.c
Normal file
@@ -0,0 +1,255 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
// Copyright Contributors to the U-Boot project.
|
||||
|
||||
#include "imagetool.h"
|
||||
#include <u-boot/sha256.h>
|
||||
|
||||
/*
|
||||
* Image contain data in the following order:
|
||||
* Nonce 16 byte
|
||||
* Header 64 byte
|
||||
* Digest 32 byte
|
||||
* Padding align up to 4K
|
||||
* Payload
|
||||
*/
|
||||
|
||||
#define HEADER_MAGIC 0x4c4d4140 /* @AML */
|
||||
#define HEADER_OFFSET 0x10 /* 16 */
|
||||
#define HEADER_SIZE 0x40 /* 64 */
|
||||
#define PAYLOAD_OFFSET 0x1000 /* 4096 */
|
||||
|
||||
struct amlimage_header {
|
||||
uint32_t magic;
|
||||
uint32_t total_size;
|
||||
uint8_t header_size;
|
||||
uint8_t root_key_index;
|
||||
uint8_t version_major;
|
||||
uint8_t version_minor;
|
||||
uint32_t padding1;
|
||||
uint32_t digest_type;
|
||||
uint32_t digest_offset;
|
||||
uint32_t digest_size;
|
||||
uint32_t data_offset;
|
||||
uint32_t key_type;
|
||||
uint32_t key_offset;
|
||||
uint32_t key_size;
|
||||
uint32_t data_size;
|
||||
uint32_t payload_type;
|
||||
uint32_t payload_offset;
|
||||
uint32_t payload_size;
|
||||
uint32_t padding2;
|
||||
} __packed;
|
||||
|
||||
struct amlimage_variant {
|
||||
const char *name;
|
||||
const struct amlimage_header hdr;
|
||||
};
|
||||
|
||||
#define VARIANT(name, major, minor, size) \
|
||||
{ name, { .magic = HEADER_MAGIC, .header_size = HEADER_SIZE, \
|
||||
.version_major = major, .version_minor = minor, \
|
||||
.payload_size = size, } }
|
||||
|
||||
static const struct amlimage_variant variants[] = {
|
||||
VARIANT("gxbb", 1, 0, 0xb000),
|
||||
VARIANT("gxl", 1, 1, 0xb000),
|
||||
VARIANT("gxm", 1, 1, 0xb000),
|
||||
VARIANT("axg", 1, 1, 0xb000),
|
||||
VARIANT("g12a", 1, 1, 0xf000),
|
||||
VARIANT("g12b", 1, 1, 0xf000),
|
||||
VARIANT("sm1", 1, 1, 0xf000),
|
||||
};
|
||||
|
||||
static const struct amlimage_variant *amlimage_get_variant(const char *name)
|
||||
{
|
||||
if (!name)
|
||||
return NULL;
|
||||
|
||||
for (int i = 0; i < ARRAY_SIZE(variants); i++)
|
||||
if (!strcmp(name, variants[i].name))
|
||||
return &variants[i];
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int amlimage_check_params(struct image_tool_params *params)
|
||||
{
|
||||
const struct amlimage_variant *variant =
|
||||
amlimage_get_variant(params->imagename);
|
||||
int datafile_size;
|
||||
|
||||
if (params->lflag || params->iflag)
|
||||
return EXIT_SUCCESS;
|
||||
|
||||
if (!variant) {
|
||||
fprintf(stderr, "%s: unsupported image name: %s\n",
|
||||
params->cmdname, params->imagename);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
datafile_size = imagetool_get_filesize(params, params->datafile);
|
||||
if (datafile_size < 0) {
|
||||
exit(EXIT_FAILURE);
|
||||
} else if (datafile_size > variant->hdr.payload_size) {
|
||||
fprintf(stderr, "%s: datafile is too large (%#x > %#x)\n",
|
||||
params->cmdname, datafile_size,
|
||||
variant->hdr.payload_size);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
static int amlimage_verify_header(unsigned char *buf, int size,
|
||||
struct image_tool_params *params)
|
||||
{
|
||||
const struct amlimage_header *hdr = (void *)buf + HEADER_OFFSET;
|
||||
|
||||
if (size >= HEADER_OFFSET + HEADER_SIZE + SHA256_SUM_LEN &&
|
||||
hdr->magic == HEADER_MAGIC && hdr->header_size == HEADER_SIZE &&
|
||||
hdr->version_major == 1 && hdr->version_minor <= 1)
|
||||
return 0;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void amlimage_print_header(const void *buf,
|
||||
struct image_tool_params *params)
|
||||
{
|
||||
const struct amlimage_header *hdr = buf + HEADER_OFFSET;
|
||||
uint8_t digest[SHA256_SUM_LEN];
|
||||
sha256_context ctx;
|
||||
bool valid;
|
||||
|
||||
printf("Amlogic Boot Image %" PRIu8 ".%" PRIu8 "\n",
|
||||
hdr->version_major, hdr->version_minor);
|
||||
printf("Total size: %" PRIu32 "\n", hdr->total_size);
|
||||
printf("Digest %" PRIu32 ": %" PRIu32 " @ 0x%" PRIx32 "\n",
|
||||
hdr->digest_type, hdr->digest_size, hdr->digest_offset);
|
||||
printf("Key %" PRIu32 ": %" PRIu32 " @ 0x%" PRIx32 "\n",
|
||||
hdr->key_type, hdr->key_size, hdr->key_offset);
|
||||
printf("Payload %" PRIu32 ": %" PRIu32 " @ 0x%" PRIx32 "\n",
|
||||
hdr->payload_type, hdr->payload_size, hdr->payload_offset);
|
||||
|
||||
if (hdr->digest_type == 0) {
|
||||
/* sha256 digest (normal boot) */
|
||||
sha256_starts(&ctx);
|
||||
|
||||
/* Header and data is used as input for sha256 digest */
|
||||
sha256_update(&ctx, (void *)hdr, hdr->header_size);
|
||||
sha256_update(&ctx, (void *)hdr + hdr->data_offset, hdr->data_size);
|
||||
sha256_finish(&ctx, digest);
|
||||
|
||||
valid = !memcmp((void *)hdr + hdr->digest_offset,
|
||||
digest, SHA256_SUM_LEN);
|
||||
|
||||
printf("Data: %" PRIu32 " @ 0x%" PRIx32 " - %s\n",
|
||||
hdr->data_size, hdr->data_offset, valid ? "OK" : "BAD");
|
||||
} else {
|
||||
/* RSA (secure boot) */
|
||||
printf("Data: %" PRIu32 " @ 0x%" PRIx32 " - Secure Boot\n",
|
||||
hdr->data_size, hdr->data_offset);
|
||||
}
|
||||
}
|
||||
|
||||
static void amlimage_set_header(void *buf, struct stat *sbuf, int ifd,
|
||||
struct image_tool_params *params)
|
||||
{
|
||||
struct amlimage_header *hdr = buf + HEADER_OFFSET;
|
||||
sha256_context ctx;
|
||||
|
||||
/* Use header size as initial size */
|
||||
hdr->total_size = hdr->header_size;
|
||||
|
||||
/* Use sha256 digest (normal boot) */
|
||||
hdr->digest_type = 0;
|
||||
/* The sha256 digest is stored directly following the header */
|
||||
hdr->digest_offset = hdr->total_size;
|
||||
/* Unknown if this is used as block size instead of digest size */
|
||||
hdr->digest_size = 512;
|
||||
hdr->total_size += hdr->digest_size;
|
||||
|
||||
/* Use key as padding so that payload ends up 4K aligned in TZRAM */
|
||||
hdr->key_type = 0;
|
||||
hdr->key_offset = hdr->total_size;
|
||||
hdr->key_size = PAYLOAD_OFFSET - HEADER_OFFSET - hdr->key_offset;
|
||||
hdr->total_size += hdr->key_size;
|
||||
|
||||
/* With padding above payload will have a 0x1000 offset in TZRAM */
|
||||
hdr->payload_type = 0;
|
||||
hdr->payload_offset = hdr->total_size;
|
||||
/* Payload size has already been copied from the variant header */
|
||||
hdr->total_size += hdr->payload_size;
|
||||
|
||||
/* Set the data range to be used as input for sha256 digest */
|
||||
hdr->data_offset = hdr->digest_offset + SHA256_SUM_LEN;
|
||||
hdr->data_size = hdr->total_size - hdr->data_offset;
|
||||
|
||||
sha256_starts(&ctx);
|
||||
/* Header and data is used as input for sha256 digest */
|
||||
sha256_update(&ctx, (void *)hdr, hdr->header_size);
|
||||
sha256_update(&ctx, (void *)hdr + hdr->data_offset, hdr->data_size);
|
||||
/* Write sha256 digest to the 32 bytes directly following the header */
|
||||
sha256_finish(&ctx, (void *)hdr + hdr->digest_offset);
|
||||
}
|
||||
|
||||
static int amlimage_extract_subimage(void *buf,
|
||||
struct image_tool_params *params)
|
||||
{
|
||||
const struct amlimage_header *hdr = buf + HEADER_OFFSET;
|
||||
|
||||
/* Save payload as the subimage */
|
||||
return imagetool_save_subimage(params->outfile,
|
||||
(ulong)hdr + hdr->payload_offset,
|
||||
hdr->payload_size);
|
||||
}
|
||||
|
||||
static int amlimage_check_image_type(uint8_t type)
|
||||
{
|
||||
if (type == IH_TYPE_AMLIMAGE)
|
||||
return EXIT_SUCCESS;
|
||||
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
static int amlimage_vrec_header(struct image_tool_params *params,
|
||||
struct image_type_params *tparams)
|
||||
{
|
||||
const struct amlimage_variant *variant =
|
||||
amlimage_get_variant(params->imagename);
|
||||
const struct amlimage_header *hdr = &variant->hdr;
|
||||
|
||||
/* Use payload offset as header size, datafile will be appended */
|
||||
tparams->header_size = PAYLOAD_OFFSET;
|
||||
|
||||
tparams->hdr = calloc(1, tparams->header_size);
|
||||
if (!tparams->hdr) {
|
||||
fprintf(stderr, "%s: Can't alloc header: %s\n",
|
||||
params->cmdname, strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Start with a copy of the variant header */
|
||||
memcpy(tparams->hdr + HEADER_OFFSET, hdr, hdr->header_size);
|
||||
|
||||
/* Pad up to payload size of the variant header */
|
||||
return hdr->payload_size - params->file_size;
|
||||
}
|
||||
|
||||
/*
|
||||
* amlimage parameters
|
||||
*/
|
||||
U_BOOT_IMAGE_TYPE(
|
||||
amlimage,
|
||||
"Amlogic Boot Image",
|
||||
0,
|
||||
NULL,
|
||||
amlimage_check_params,
|
||||
amlimage_verify_header,
|
||||
amlimage_print_header,
|
||||
amlimage_set_header,
|
||||
amlimage_extract_subimage,
|
||||
amlimage_check_image_type,
|
||||
NULL,
|
||||
amlimage_vrec_header
|
||||
);
|
||||
Reference in New Issue
Block a user