CI result shows no issue:
https://source.denx.de/u-boot/custodians/u-boot-riscv/-/pipelines/22315
----------------------------------------------------------------
- Aspeed: Add AST2700 board (Ibex RISC-V core) support
        - Add timer, dram controller, network support
- Sophgo: Add clock controller support for Milk-V Duo
This commit is contained in:
Tom Rini
2024-09-12 09:03:40 -06:00
50 changed files with 14220 additions and 51 deletions
+10 -2
View File
@@ -46,6 +46,9 @@ config TARGET_TH1520_LPI4A
config TARGET_XILINX_MBV
bool "Support AMD/Xilinx MicroBlaze V"
config TARGET_ASPEED_AST2700_IBEX
bool "Support Ibex RISC-V cores on Aspeed AST2700 SoC"
endchoice
config SYS_ICACHE_OFF
@@ -81,6 +84,7 @@ config SPL_ZERO_MEM_BEFORE_USE
# board-specific options below
source "board/andestech/ae350/Kconfig"
source "board/aspeed/ibex_ast2700/Kconfig"
source "board/emulation/qemu-riscv/Kconfig"
source "board/microchip/mpfs_icicle/Kconfig"
source "board/openpiton/riscv64/Kconfig"
@@ -97,6 +101,7 @@ source "arch/riscv/cpu/andes/Kconfig"
source "arch/riscv/cpu/cv1800b/Kconfig"
source "arch/riscv/cpu/fu540/Kconfig"
source "arch/riscv/cpu/fu740/Kconfig"
source "arch/riscv/cpu/ast2700/Kconfig"
source "arch/riscv/cpu/generic/Kconfig"
source "arch/riscv/cpu/jh7110/Kconfig"
@@ -308,7 +313,10 @@ config TPL_USE_ARCH_STRNCMP
endmenu
config RISCV_ISA_A
def_bool y
bool "Standard extension for Atomic Instructions"
default y
help
Adds "A" to the ISA string passed to the compiler.
config DMA_ADDR_T_64BIT
bool
@@ -450,7 +458,7 @@ config RISCV_PRIV_1_9
memory is configured was also changed.
config STACK_SIZE_SHIFT
int
int "Stack size shift"
default 14
config OF_BOARD_FIXUP
+6
View File
@@ -0,0 +1,6 @@
config RISCV_AST2700
bool
imply CPU
imply CPU_RISCV
help
Run U-Boot on AST2700 with IBex RISC-V CPU integrated.
+1
View File
@@ -0,0 +1 @@
obj-y += cpu.o
+23
View File
@@ -0,0 +1,23 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
* Copyright (C) 2024, Aspeed Technology Inc.
*/
#include <irq_func.h>
#include <asm/cache.h>
/*
* cleanup_before_linux() is called just before we call linux
* it prepares the processor for linux
*
* we disable interrupt and caches.
*/
int cleanup_before_linux(void)
{
disable_interrupts();
cache_flush();
return 0;
}
-2
View File
@@ -44,8 +44,6 @@ SECTIONS
__binman_sym_end = .;
} > .spl_mem
. = ALIGN(8);
_end = .;
_image_binary_end = .;
+1
View File
@@ -11,6 +11,7 @@ dtb-$(CONFIG_TARGET_SIPEED_MAIX) += k210-maix-bit.dtb
dtb-$(CONFIG_TARGET_STARFIVE_VISIONFIVE2) += jh7110-starfive-visionfive-2.dtb
dtb-$(CONFIG_TARGET_TH1520_LPI4A) += th1520-lichee-pi-4a.dtb
dtb-$(CONFIG_TARGET_XILINX_MBV) += xilinx-mbv32.dtb
dtb-$(CONFIG_TARGET_ASPEED_AST2700_IBEX) += ast2700-ibex.dtb
include $(srctree)/scripts/Makefile.dts
+22
View File
@@ -0,0 +1,22 @@
// SPDX-License-Identifier: (GPL-2.0 OR MIT)
/dts-v1/;
#include "ast2700.dtsi"
/ {
chosen {
stdout-path = &uart12;
tick-timer = &ast_ibex_timer;
};
memory@0 {
device_type = "memory";
reg = <0x80000000 0x40000000>;
};
};
&uart12 {
status = "okay";
clock-frequency = <1846153>;
};
+40
View File
@@ -0,0 +1,40 @@
// SPDX-License-Identifier: (GPL-2.0 OR MIT)
/ {
cpus {
bootph-all;
};
memory@80000000 {
bootph-all;
};
soc0: soc@12000000 {
bootph-all;
sdrammc: sdrammc@12c00000 {
bootph-all;
};
syscon0: syscon@12c02000 {
bootph-all;
};
};
soc1: soc@14000000 {
bootph-all;
syscon1: syscon@14c02000 {
bootph-all;
};
uart12: serial@14c33b00 {
bootph-all;
};
ast_ibex_timer: timer {
bootph-all;
};
};
};
+76
View File
@@ -0,0 +1,76 @@
// SPDX-License-Identifier: GPL-2.0+
/ {
model = "Aspeed AST2700 Ibex BootMCU";
compatible = "aspeed,ast2700-ibex";
#address-cells = <1>;
#size-cells = <1>;
cpus {
#address-cells = <1>;
#size-cells = <0>;
cpu@0 {
compatible = "lowrisc,ibex";
device_type = "cpu";
reg = <0>;
comptaible = "riscv";
riscv,isa = "rv32imc";
};
};
memory@80000000 {
reg = <0x80000000 0x80000000>;
};
soc0: soc@12000000 {
compatible = "aspeed,soc1","simple-bus";
#address-cells = <1>;
#size-cells = <1>;
ranges;
sdrammc: sdrammc@12c00000 {
compatible = "aspeed,ast2700-sdrammc";
reg = <0x12c00000 0x3000>, <0x13000000 0x1000>;
aspeed,scu0 = <&syscon0>;
aspeed,scu1 = <&syscon1>;
};
syscon0: syscon@12c02000 {
compatible = "aspeed,ast2700-scu0", "syscon", "simple-mfd";
reg = <0x12c02000 0x1000>;
ranges = <0 0x12c02000 0x1000>;
#address-cells = <1>;
#size-cells = <1>;
};
};
soc1: soc@14000000 {
compatible = "aspeed,soc1","simple-bus";
#address-cells = <1>;
#size-cells = <1>;
ranges;
syscon1: syscon@14c02000 {
compatible = "aspeed,ast2700-scu1", "syscon", "simple-mfd";
reg = <0x14c02000 0x1000>;
ranges = <0 0x14c02000 0x1000>;
#address-cells = <1>;
#size-cells = <1>;
};
uart12: serial@14c33b00 {
compatible = "ns16550a";
reg = <0x14c33b00 0x20>;
reg-shift = <2>;
no-loopback-test;
clock-frequency = <1846153>;
status = "disabled";
};
ast_ibex_timer: timer {
compatible = "aspeed,ast2700-ibex-timer";
clock-frequency = <200000000>;
};
};
};
+16 -24
View File
@@ -5,6 +5,7 @@
*/
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/clock/sophgo,cv1800.h>
/ {
#address-cells = <1>;
@@ -45,13 +46,6 @@
#clock-cells = <0>;
};
sdhci_clk: sdhci-clock {
compatible = "fixed-clock";
clock-frequency = <375000000>;
clock-output-names = "sdhci_clk";
#clock-cells = <0>;
};
eth_csrclk: eth-csrclk {
compatible = "fixed-clock";
clock-frequency = <250000000>;
@@ -66,13 +60,6 @@
#clock-cells = <0x0>;
};
spif_clk: spi-flash-clock {
compatible = "fixed-clock";
clock-frequency = <300000000>;
clock-output-names = "spif_clk";
#clock-cells = <0>;
};
soc {
compatible = "simple-bus";
interrupt-parent = <&plic>;
@@ -163,8 +150,8 @@
compatible = "sophgo,cv1800b-dwmac";
reg = <0x04070000 0x10000>;
interrupts = <31 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&eth_csrclk>, <&eth_ptpclk>;
clock-names = "stmmaceth", "ptp_ref";
clocks = <&clk CLK_ETH0_500M>, <&clk CLK_AXI4_ETH0>;
clock-names = "stmmaceth", "pclk";
status = "disabled";
};
@@ -172,7 +159,8 @@
compatible = "snps,dw-apb-uart";
reg = <0x04140000 0x100>;
interrupts = <44 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&osc>;
clocks = <&clk CLK_UART0>, <&clk CLK_APB_UART0>;
clock-names = "baudclk", "apb_pclk";
reg-shift = <2>;
reg-io-width = <4>;
status = "disabled";
@@ -182,7 +170,8 @@
compatible = "snps,dw-apb-uart";
reg = <0x04150000 0x100>;
interrupts = <45 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&osc>;
clocks = <&clk CLK_UART4>, <&clk CLK_APB_UART4>;
clock-names = "baudclk", "apb_pclk";
reg-shift = <2>;
reg-io-width = <4>;
status = "disabled";
@@ -192,7 +181,8 @@
compatible = "snps,dw-apb-uart";
reg = <0x04160000 0x100>;
interrupts = <46 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&osc>;
clocks = <&clk CLK_UART2>, <&clk CLK_APB_UART2>;
clock-names = "baudclk", "apb_pclk";
reg-shift = <2>;
reg-io-width = <4>;
status = "disabled";
@@ -202,7 +192,8 @@
compatible = "snps,dw-apb-uart";
reg = <0x04170000 0x100>;
interrupts = <47 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&osc>;
clocks = <&clk CLK_UART3>, <&clk CLK_APB_UART3>;
clock-names = "baudclk", "apb_pclk";
reg-shift = <2>;
reg-io-width = <4>;
status = "disabled";
@@ -212,7 +203,8 @@
compatible = "snps,dw-apb-uart";
reg = <0x041c0000 0x100>;
interrupts = <48 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&osc>;
clocks = <&clk CLK_UART4>, <&clk CLK_APB_UART4>;
clock-names = "baudclk", "apb_pclk";
reg-shift = <2>;
reg-io-width = <4>;
status = "disabled";
@@ -222,8 +214,8 @@
compatible = "sophgo,cv1800b-dwcmshc";
reg = <0x4310000 0x1000>;
interrupts = <36 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sdhci_clk>;
clock-names = "core";
clocks = <&clk CLK_AXI4_SD0>, <&clk CLK_SD0>;
clock-names = "core", "bus";
status = "disabled";
};
@@ -232,7 +224,7 @@
reg = <0x10000000 0x10000000>;
#address-cells = <1>;
#size-cells = <0>;
clocks = <&spif_clk>;
clocks = <&clk CLK_AHB_SF>;
interrupts = <95 IRQ_TYPE_LEVEL_HIGH>;
status = "disabled";
};
@@ -0,0 +1,52 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Copyright (C) ASPEED Technology Inc.
*/
#ifndef __ASM_AST2700_FMC_HDR_H__
#define __ASM_AST2700_FMC_HDR_H__
#include <linux/types.h>
#define HDR_MAGIC 0x48545341 /* ASTH */
#define HDR_PB_MAX 30
enum prebuilt_type {
PBT_END_MARK = 0x0,
PBT_DDR4_PMU_TRAIN_IMEM,
PBT_DDR4_PMU_TRAIN_DMEM,
PBT_DDR4_2D_PMU_TRAIN_IMEM,
PBT_DDR4_2D_PMU_TRAIN_DMEM,
PBT_DDR5_PMU_TRAIN_IMEM,
PBT_DDR5_PMU_TRAIN_DMEM,
PBT_DP_FW,
PBT_UEFI_X64_AST2700,
PBT_NUM
};
struct fmc_hdr_preamble {
uint32_t magic;
uint32_t version;
};
struct fmc_hdr_body {
uint32_t fmc_size;
union {
struct {
uint32_t type;
uint32_t size;
} pbs[0];
uint32_t raz[29];
};
};
struct fmc_hdr {
struct fmc_hdr_preamble preamble;
struct fmc_hdr_body body;
} __packed;
int fmc_hdr_get_prebuilt(uint32_t type, uint32_t *ofst, uint32_t *size);
#endif
+145
View File
@@ -0,0 +1,145 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Copyright (c) Aspeed Technology Inc.
*/
#ifndef __ASM_AST2700_SCU_H__
#define __ASM_AST2700_SCU_H__
/* SCU0: CPU-die SCU */
#define SCU0_HWSTRAP 0x010
#define SCU0_HWSTRAP_DIS_RVAS BIT(30)
#define SCU0_HWSTRAP_DIS_WDTFULL BIT(25)
#define SCU0_HWSTRAP_DISARMICE_TZ BIT(22)
#define SCU0_HWSTRAP_DISABLE_XHCI BIT(21)
#define SCU0_HWSTRAP_BOOTEMMCSPEED BIT(20)
#define SCU0_HWSTRAP_VGA_CC BIT(18)
#define SCU0_HWSTRAP_EN_OPROM BIT(17)
#define SCU0_HWSTRAP_DISARMICE BIT(16)
#define SCU0_HWSTRAP_TSPRSNTSEL BIT(9)
#define SCU0_HWSTRAP_DISDEBUG BIT(8)
#define SCU0_HWSTRAP_HCLKHPLL BIT(7)
#define SCU0_HWSTRAP_HCLKSEL GENMASK(6, 5)
#define SCU0_HWSTRAP_CPUHPLL BIT(4)
#define SCU0_HWSTRAP_HPLLFREQ GENMASK(3, 2)
#define SCU0_HWSTRAP_BOOTSPI BIT(1)
#define SCU0_HWSTRAP_HWSTRAP_DISCPU BIT(0)
#define SCU0_DBGCTL 0x0c8
#define SCU0_DBGCTL_MASK GENMASK(14, 0)
#define SCU0_DBGCTL_UARTDBG BIT(1)
#define SCU0_RSTCTL1 0x200
#define SCU0_RSTCTL1_EMMC BIT(17)
#define SCU0_RSTCTL1_HACE BIT(4)
#define SCU0_RSTCTL1_CLR 0x204
#define SCU0_RSTCTL1_CLR_EMMC BIT(17)
#define SCU0_RSTCTL1_CLR_HACE BIT(4)
#define SCU0_CLKGATE1 0x240
#define SCU0_CLKGATE1_EMMC BIT(27)
#define SCU0_CLKGATE1_HACE BIT(13)
#define SCU0_CLKGATE1_DDRPHY BIT(11)
#define SCU0_CLKGATE1_CLR 0x244
#define SCU0_CLKGATE1_CLR_EMMC BIT(27)
#define SCU0_CLKGATE1_CLR_HACE BIT(13)
#define SCU0_CLKGATE1_CLR_DDRPHY BIT(11)
#define SCU0_VGA0_SCRATCH 0x900
#define SCU0_VGA0_SCRATCH_DRAM_INIT BIT(6)
#define SCU0_PCI_MISC70 0xa70
#define SCU0_PCI_MISC70_EN_PCIEXHCI0 BIT(3)
#define SCU0_PCI_MISC70_EN_PCIEEHCI0 BIT(2)
#define SCU0_PCI_MISC70_EN_PCIEVGA0 BIT(0)
#define SCU0_PCI_MISC80 0xa80
#define SCU0_PCI_MISC80_EN_PCIEXHCI1 BIT(3)
#define SCU0_PCI_MISC80_EN_PCIEEHCI1 BIT(2)
#define SCU0_PCI_MISC80_EN_PCIEVGA1 BIT(0)
#define SCU0_PCI_MISCF0 0xaf0
#define SCU0_PCI_MISCF0_EN_PCIEXHCI1 BIT(3)
#define SCU0_PCI_MISCF0_EN_PCIEEHCI1 BIT(2)
#define SCU0_PCI_MISCF0_EN_PCIEVGA1 BIT(0)
#define SCU0_WPROT1 0xe04
#define SCU0_WPROT1_0C8 BIT(18)
/* SCU1: IO-die SCU */
#define SCU1_REVISION 0x000
#define SCU1_REVISION_HWID GENMASK(23, 16)
#define SCU1_REVISION_CHIP_EFUSE GENMASK(15, 8)
#define SCU1_HWSTRAP1 0x010
#define SCU1_HWSTRAP1_DIS_CPTRA BIT(30)
#define SCU1_HWSTRAP1_RECOVERY_USB_PORT GENMASK(29, 28)
#define SCU1_HWSTRAP1_RECOVERY_INTERFACE GENMASK(27, 26)
#define SCU1_HWSTRAP1_RECOVERY_I3C (BIT(26) | BIT(27))
#define SCU1_HWSTRAP1_RECOVERY_I2C BIT(27)
#define SCU1_HWSTRAP1_RECOVERY_USB BIT(26)
#define SCU1_HWSTRAP1_SPI_FLASH_4_BYTE_MODE BIT(25)
#define SCU1_HWSTRAP1_SPI_FLASH_WAIT_READY BIT(24)
#define SCU1_HWSTRAP1_BOOT_UFS BIT(23)
#define SCU1_HWSTRAP1_DIS_ROM BIT(22)
#define SCU1_HWSTRAP1_DIS_CPTRAJTAG BIT(20)
#define SCU1_HWSTRAP1_UARTDBGSEL BIT(19)
#define SCU1_HWSTRAP1_DIS_UARTDBG BIT(18)
#define SCU1_HWSTRAP1_DIS_WDTFULL BIT(17)
#define SCU1_HWSTRAP1_DISDEBUG1 BIT(16)
#define SCU1_HWSTRAP1_LTPI0_IO_DRIVING GENMASK(15, 14)
#define SCU1_HWSTRAP1_ACPI_1 BIT(13)
#define SCU1_HWSTRAP1_ACPI_0 BIT(12)
#define SCU1_HWSTRAP1_BOOT_EMMC_UFS BIT(11)
#define SCU1_HWSTRAP1_DDR4 BIT(10)
#define SCU1_HWSTRAP1_LOW_SECURE BIT(8)
#define SCU1_HWSTRAP1_EN_EMCS BIT(7)
#define SCU1_HWSTRAP1_EN_GPIOPT BIT(6)
#define SCU1_HWSTRAP1_EN_SECBOOT BIT(5)
#define SCU1_HWSTRAP1_EN_RECOVERY_BOOT BIT(4)
#define SCU1_HWSTRAP1_LTPI0_EN BIT(3)
#define SCU1_HWSTRAP1_LTPI_IDX BIT(2)
#define SCU1_HWSTRAP1_LTPI1_EN BIT(1)
#define SCU1_HWSTRAP1_LTPI_MODE BIT(0)
#define SCU1_HWSTRAP2 0x030
#define SCU1_HWSTRAP2_FMC_ABR_SINGLE_FLASH BIT(29)
#define SCU1_HWSTRAP2_FMC_ABR_CS_SWAP_DIS BIT(28)
#define SCU1_HWSTRAP2_SPI_TPM_PCR_EXT_EN BIT(27)
#define SCU1_HWSTRAP2_SPI_TPM_HASH_ALGO GENMASK(26, 25)
#define SCU1_HWSTRAP2_BOOT_SPI_FREQ GENMASK(24, 23)
#define SCU1_HWSTRAP2_RESERVED GENMASK(22, 19)
#define SCU1_HWSTRAP2_FWSPI_CRTM GENMASK(18, 17)
#define SCU1_HWSTRAP2_EN_FWSPIAUX BIT(16)
#define SCU1_HWSTRAP2_FWSPISIZE GENMASK(15, 13)
#define SCU1_HWSTRAP2_DIS_REC BIT(12)
#define SCU1_HWSTRAP2_EN_CPTRA_DBG BIT(11)
#define SCU1_HWSTRAP2_TPM_PCR_INDEX GENMASK(6, 2)
#define SCU1_HWSTRAP2_ROM_CLEAR_SRAM BIT(1)
#define SCU1_HWSTRAP2_ABR BIT(0)
#define SCU1_RSTLOG0 0x050
#define SCU1_RSTLOG0_BMC_CPU BIT(12)
#define SCU1_RSTLOG0_ABR BIT(2)
#define SCU1_RSTLOG0_EXTRSTN BIT(1)
#define SCU1_RSTLOG0_SRST BIT(0)
#define SCU1_MISC1 0x0c0
#define SCU1_MISC1_UARTDBG_ROUTE GENMASK(23, 22)
#define SCU1_MISC1_UART12_ROUTE GENMASK(21, 20)
#define SCU1_DBGCTL 0x0c8
#define SCU1_DBGCTL_MASK GENMASK(7, 0)
#define SCU1_DBGCTL_UARTDBG BIT(6)
#define SCU1_RNG_DATA 0x0f4
#define SCU1_RSTCTL1 0x200
#define SCU1_RSTCTL1_I3C(x) (BIT(16) << (x))
#define SCU1_RSTCTL1_CLR 0x204
#define SCU1_RSTCTL1_CLR_I3C(x) (BIT(16) << (x))
#define SCU1_RSTCTL2 0x220
#define SCU1_RSTCTL2_LTPI1 BIT(22)
#define SCU1_RSTCTL2_LTPI0 BIT(20)
#define SCU1_RSTCTL2_I2C BIT(15)
#define SCU1_RSTCTL2_CPTRA BIT(9)
#define SCU1_RSTCTL2_CLR 0x224
#define SCU1_RSTCTL2_CLR_I2C BIT(15)
#define SCU1_RSTCTL2_CLR_CPTRA BIT(9)
#define SCU1_CLKGATE1 0x240
#define SCU1_CLKGATE1_I3C(x) (BIT(16) << (x))
#define SCU1_CLKGATE1_I2C BIT(15)
#define SCU1_CLKGATE1_CLR 0x244
#define SCU1_CLKGATE1_CLR_I3C(x) (BIT(16) << (x))
#define SCU1_CLKGATE1_CLR_I2C BIT(15)
#define SCU1_CLKGATE2 0x260
#define SCU1_CLKGATE2_LTPI1_TX BIT(19)
#define SCU1_CLKGATE2_LTPI_AHB BIT(10)
#define SCU1_CLKGATE2_LTPI0_TX BIT(9)
#define SCU1_CLKGATE2_CLR 0x264
#endif
+137
View File
@@ -0,0 +1,137 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Copyright (c) Aspeed Technology Inc.
*/
#ifndef __ASM_AST2700_SDRAM_H__
#define __ASM_AST2700_SDRAM_H__
struct sdrammc_regs {
u32 prot_key;
u32 intr_status;
u32 intr_clear;
u32 intr_mask;
u32 mcfg;
u32 mctl;
u32 msts;
u32 error_status;
u32 actime1;
u32 actime2;
u32 actime3;
u32 actime4;
u32 actime5;
u32 actime6;
u32 actime7;
u32 dfi_timing;
u32 dcfg;
u32 dctl;
u32 mrctl;
u32 mrwr;
u32 mrrd;
u32 mr01;
u32 mr23;
u32 mr45;
u32 mr67;
u32 refctl;
u32 refmng_ctl;
u32 refsts;
u32 zqctl;
u32 ecc_addr_range;
u32 ecc_failure_status;
u32 ecc_failure_addr;
u32 ecc_test_control;
u32 ecc_test_status;
u32 arbctl;
u32 enccfg;
u32 protect_lock_set;
u32 protect_lock_status;
u32 protect_lock_reset;
u32 enc_min_addr;
u32 enc_max_addr;
u32 enc_key[4];
u32 enc_iv[3];
u32 bistcfg;
u32 bist_addr;
u32 bist_size;
u32 bist_patt;
u32 bist_res;
u32 bist_fail_addr;
u32 bist_fail_data[4];
u32 reserved2[2];
u32 debug_control;
u32 debug_status;
u32 phy_intf_status;
u32 testcfg;
u32 gfmcfg;
u32 gfm0ctl;
u32 gfm1ctl;
u32 reserved3[0xf8];
};
#define DRAMC_UNLK_KEY 0x1688a8a8
/* offset 0x04 */
#define DRAMC_IRQSTA_PWRCTL_ERR BIT(16)
#define DRAMC_IRQSTA_PHY_ERR BIT(15)
#define DRAMC_IRQSTA_LOWPOWER_DONE BIT(12)
#define DRAMC_IRQSTA_FREQ_CHG_DONE BIT(11)
#define DRAMC_IRQSTA_REF_DONE BIT(10)
#define DRAMC_IRQSTA_ZQ_DONE BIT(9)
#define DRAMC_IRQSTA_BIST_DONE BIT(8)
#define DRAMC_IRQSTA_ECC_RCVY_ERR BIT(5)
#define DRAMC_IRQSTA_ECC_ERR BIT(4)
#define DRAMC_IRQSTA_PROT_ERR BIT(3)
#define DRAMC_IRQSTA_OVERSZ_ERR BIT(2)
#define DRAMC_IRQSTA_MR_DONE BIT(1)
#define DRAMC_IRQSTA_PHY_INIT_DONE BIT(0)
/* offset 0x14 */
#define DRAMC_MCTL_WB_SOFT_RESET BIT(24)
#define DRAMC_MCTL_PHY_CLK_DIS BIT(18)
#define DRAMC_MCTL_PHY_RESET BIT(17)
#define DRAMC_MCTL_PHY_POWER_ON BIT(16)
#define DRAMC_MCTL_FREQ_CHG_START BIT(3)
#define DRAMC_MCTL_PHY_LOWPOWER_START BIT(2)
#define DRAMC_MCTL_SELF_REF_START BIT(1)
#define DRAMC_MCTL_PHY_INIT_START BIT(0)
/* offset 0x40 */
#define DRAMC_DFICFG_WD_POL BIT(18)
#define DRAMC_DFICFG_CKE_OUT BIT(17)
#define DRAMC_DFICFG_RESET BIT(16)
/* offset 0x48 */
#define DRAMC_MRCTL_ERR_STATUS BIT(31)
#define DRAMC_MRCTL_READY_STATUS BIT(30)
#define DRAMC_MRCTL_MR_ADDR BIT(8)
#define DRAMC_MRCTL_CMD_DLL_RST BIT(7)
#define DRAMC_MRCTL_CMD_DQ_SEL BIT(6)
#define DRAMC_MRCTL_CMD_TYPE BIT(2)
#define DRAMC_MRCTL_CMD_WR_CTL BIT(1)
#define DRAMC_MRCTL_CMD_START BIT(0)
/* offset 0xC0 */
#define DRAMC_BISTRES_RUNNING BIT(10)
#define DRAMC_BISTRES_FAIL BIT(9)
#define DRAMC_BISTRES_DONE BIT(8)
#define DRAMC_BISTCFG_INIT_MODE BIT(7)
#define DRAMC_BISTCFG_PMODE GENMASK(6, 4)
#define DRAMC_BISTCFG_BMODE GENMASK(3, 2)
#define DRAMC_BISTCFG_ENABLE BIT(1)
#define DRAMC_BISTCFG_START BIT(0)
#define BIST_PMODE_CRC (3)
#define BIST_BMODE_RW_SWITCH (3)
/* DRAMC048 MR Control Register */
#define MR_TYPE_SHIFT 2
#define MR_RW (0 << MR_TYPE_SHIFT)
#define MR_MPC BIT(2)
#define MR_VREFCS (2 << MR_TYPE_SHIFT)
#define MR_VREFCA (3 << MR_TYPE_SHIFT)
#define MR_ADDRESS_SHIFT 8
#define MR_ADDR(n) (((n) << MR_ADDRESS_SHIFT) | DRAMC_MRCTL_CMD_WR_CTL)
#define MR_NUM_SHIFT 4
#define MR_NUM(n) ((n) << MR_NUM_SHIFT)
#define MR_DLL_RESET BIT(7)
#define MR_1T_MODE BIT(16)
#endif
+82
View File
@@ -0,0 +1,82 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Copyright (c) Aspeed Technology Inc.
*/
#ifndef __ASM_AST2700_SLI_H__
#define __ASM_AST2700_SLI_H__
#define SLI_CPU_ADRBASE 0x12c17000
#define SLI_IOD_ADRBASE 0x14c1e000
#define SLIM_CPU_BASE (SLI_CPU_ADRBASE + 0x000)
#define SLIH_CPU_BASE (SLI_CPU_ADRBASE + 0x200)
#define SLIV_CPU_BASE (SLI_CPU_ADRBASE + 0x400)
#define SLIM_IOD_BASE (SLI_IOD_ADRBASE + 0x000)
#define SLIH_IOD_BASE (SLI_IOD_ADRBASE + 0x200)
#define SLIV_IOD_BASE (SLI_IOD_ADRBASE + 0x400)
#define SLI_CTRL_I 0x00
#define SLIV_RAW_MODE BIT(15)
#define SLI_TX_MODE BIT(14)
#define SLI_RX_PHY_LAH_SEL_REV BIT(13)
#define SLI_RX_PHY_LAH_SEL_NEG BIT(12)
#define SLI_AUTO_SEND_TRN_OFF BIT(8)
#define SLI_CLEAR_BUS BIT(6)
#define SLI_TRANS_EN BIT(5)
#define SLI_CLEAR_RX BIT(2)
#define SLI_CLEAR_TX BIT(1)
#define SLI_RESET_TRIGGER BIT(0)
#define SLI_CTRL_II 0x04
#define SLI_CTRL_III 0x08
#define SLI_CLK_SEL GENMASK(31, 28)
#define SLI_CLK_500M 0x6
#define SLI_CLK_200M 0x3
#define SLI_PHYCLK_SEL GENMASK(27, 24)
#define SLI_PHYCLK_25M 0x0
#define SLI_PHYCLK_800M 0x1
#define SLI_PHYCLK_400M 0x2
#define SLI_PHYCLK_200M 0x3
#define SLI_PHYCLK_788M 0x5
#define SLI_PHYCLK_500M 0x6
#define SLI_PHYCLK_250M 0x7
#define SLIH_PAD_DLY_TX1 GENMASK(23, 18)
#define SLIH_PAD_DLY_TX0 GENMASK(17, 12)
#define SLIH_PAD_DLY_RX1 GENMASK(11, 6)
#define SLIH_PAD_DLY_RX0 GENMASK(5, 0)
#define SLIM_PAD_DLY_RX3 GENMASK(23, 18)
#define SLIM_PAD_DLY_RX2 GENMASK(17, 12)
#define SLIM_PAD_DLY_RX1 GENMASK(11, 6)
#define SLIM_PAD_DLY_RX0 GENMASK(5, 0)
#define SLI_CTRL_IV 0x0c
#define SLIM_PAD_DLY_TX3 GENMASK(23, 18)
#define SLIM_PAD_DLY_TX2 GENMASK(17, 12)
#define SLIM_PAD_DLY_TX1 GENMASK(11, 6)
#define SLIM_PAD_DLY_TX0 GENMASK(5, 0)
#define SLI_INTR_EN 0x10
#define SLI_INTR_STATUS 0x14
#define SLI_INTR_RX_SYNC BIT(15)
#define SLI_INTR_RX_ERR BIT(13)
#define SLI_INTR_RX_NACK BIT(12)
#define SLI_INTR_RX_TRAIN_PKT BIT(10)
#define SLI_INTR_RX_DISCONN BIT(6)
#define SLI_INTR_TX_SUSPEND BIT(4)
#define SLI_INTR_TX_TRAIN BIT(3)
#define SLI_INTR_TX_IDLE BIT(2)
#define SLI_INTR_RX_SUSPEND BIT(1)
#define SLI_INTR_RX_IDLE BIT(0)
#define SLI_INTR_RX_ERRORS \
(SLI_INTR_RX_ERR | SLI_INTR_RX_NACK | SLI_INTR_RX_DISCONN)
#define SLIM_MARB_FUNC_I 0x60
#define SLIM_SLI_MARB_RR BIT(0)
#define SLI_TARGET_PHYCLK SLI_PHYCLK_400M
#define SLIH_DEFAULT_DELAY 11
#if (SLI_TARGET_PHYCLK == SLI_PHYCLK_800M) || (SLI_TARGET_PHYCLK == SLI_PHYCLK_788M)
#define SLIM_DEFAULT_DELAY 5
#define SLIM_LAH_CONFIG 1
#else
#define SLIM_DEFAULT_DELAY 12
#define SLIM_LAH_CONFIG 0
#endif
#endif
int sli_init(void);
+21
View File
@@ -0,0 +1,21 @@
if TARGET_ASPEED_AST2700_IBEX
config SYS_BOARD
default "ibex_ast2700"
config SYS_VENDOR
default "aspeed"
config SYS_CPU
default "ast2700"
config SYS_CONFIG_NAME
default "ibex_ast2700"
config BOARD_SPECIFIC_OPTIONS
def_bool y
select RISCV_AST2700
select SUPPORT_SPL
imply SPL_DRIVERS_MISC
endif
+7
View File
@@ -0,0 +1,7 @@
AST2700 using Ibex RISC-V Core as the boot MCU
M: Chia-Wei, Wang <chiawei_wang@aspeedtech.com>
S: Maintained
F: arch/riscv/include/asm/arch-ast2700/
F: board/aspeed/ibex_ast2700/
F: configs/ibex-ast2700_defconfig
F: include/configs/ibex_ast2700.h
+3
View File
@@ -0,0 +1,3 @@
obj-y += ibex_ast2700.o
obj-y += fmc_hdr.o
obj-y += sli.o
+64
View File
@@ -0,0 +1,64 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (c) Aspeed Technology Inc.
*/
#include <asm/arch/fmc_hdr.h>
#include <asm/io.h>
#include <asm/sections.h>
#include <errno.h>
#include <spl.h>
#include <string.h>
int fmc_hdr_get_prebuilt(uint32_t type, uint32_t *ofst, uint32_t *size)
{
struct fmc_hdr_preamble *preamble;
struct fmc_hdr_body *body;
struct fmc_hdr *hdr;
uint32_t t, s, o;
int i;
if (type >= PBT_NUM)
return -EINVAL;
if (!ofst || !size)
return -EINVAL;
hdr = (struct fmc_hdr *)(_start - sizeof(*hdr));
preamble = &hdr->preamble;
body = &hdr->body;
if (preamble->magic != HDR_MAGIC)
return -EIO;
for (i = 0, o = sizeof(*hdr) + body->fmc_size; i < HDR_PB_MAX; ++i) {
t = body->pbs[i].type;
s = body->pbs[i].size;
/* skip if unrecognized, yet */
if (t >= PBT_NUM) {
o += s;
continue;
}
/* prebuilt end mark */
if (t == 0 && s == 0)
break;
/* return the prebuilt info if found */
if (t == type) {
*ofst = o;
*size = s;
goto found;
}
/* update offset for next prebuilt */
o += s;
}
return -ENODATA;
found:
return 0;
}
+85
View File
@@ -0,0 +1,85 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (c) Aspeed Technology Inc.
*/
#include <asm/io.h>
#include <asm/arch/sli.h>
#include <dm.h>
#include <ram.h>
#include <spl.h>
DECLARE_GLOBAL_DATA_PTR;
int dram_init(void)
{
int ret;
struct udevice *dev;
struct ram_info ram;
ret = uclass_get_device(UCLASS_RAM, 0, &dev);
if (ret) {
printf("cannot get DRAM driver\n");
return ret;
}
ret = ram_get_info(dev, &ram);
if (ret) {
printf("cannot get DRAM information\n");
return ret;
}
gd->ram_size = ram.size;
return 0;
}
int spl_board_init_f(void)
{
sli_init();
dram_init();
return 0;
}
struct legacy_img_hdr *spl_get_load_buffer(ssize_t offset, size_t size)
{
return (struct legacy_img_hdr *)CONFIG_SYS_LOAD_ADDR;
}
void *board_spl_fit_buffer_addr(ulong fit_size, int sectors, int bl_len)
{
return (void *)spl_get_load_buffer(sectors, bl_len);
}
u32 spl_boot_device(void)
{
return BOOT_DEVICE_RAM;
}
int board_init(void)
{
struct udevice *dev;
int i = 0;
int ret;
/*
* Loop over all MISC uclass drivers to call the comphy code
* and init all CP110 devices enabled in the DT
*/
while (1) {
/* Call the comphy code via the MISC uclass driver */
ret = uclass_get_device(UCLASS_MISC, i++, &dev);
/* We're done, once no further CP110 device is found */
if (ret)
break;
}
return 0;
}
int board_late_init(void)
{
return 0;
}
+72
View File
@@ -0,0 +1,72 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (c) Aspeed Technology Inc.
*/
#include <asm/io.h>
#include <asm/arch/sli.h>
#include <asm/arch/scu.h>
#include <linux/bitfield.h>
#include <linux/bitops.h>
#define SLI_POLL_TIMEOUT_US 100
static void sli_clear_interrupt_status(uint32_t base)
{
writel(-1, (void *)base + SLI_INTR_STATUS);
}
static int sli_wait(uint32_t base, uint32_t mask)
{
uint32_t value;
sli_clear_interrupt_status(base);
do {
value = readl((void *)base + SLI_INTR_STATUS);
if (value & SLI_INTR_RX_ERRORS)
return -1;
} while ((value & mask) != mask);
return 0;
}
static int sli_wait_suspend(uint32_t base)
{
return sli_wait(base, SLI_INTR_TX_SUSPEND | SLI_INTR_RX_SUSPEND);
}
/*
* CPU die --- downstream pads ---> I/O die
* CPU die <--- upstream pads ----- I/O die
*
* US/DS PAD[3:0] : SLIM[3:0]
* US/DS PAD[5:4] : SLIH[1:0]
* US/DS PAD[7:6] : SLIV[1:0]
*/
int sli_init(void)
{
uint32_t value;
/* The following training sequence is designed for AST2700A0 */
value = FIELD_GET(SCU1_REVISION_HWID, readl(SCU1_REVISION));
if (value)
return 0;
/* Return if SLI had been calibrated */
value = readl((void *)SLIH_IOD_BASE + SLI_CTRL_III);
value = FIELD_GET(SLI_CLK_SEL, value);
if (value) {
debug("SLI has been initialized\n");
return 0;
}
/* 25MHz PAD delay for AST2700A0 */
value = SLI_RX_PHY_LAH_SEL_NEG | SLI_TRANS_EN | SLI_CLEAR_BUS;
writel(value, (void *)SLIH_IOD_BASE + SLI_CTRL_I);
writel(value, (void *)SLIM_IOD_BASE + SLI_CTRL_I);
writel(value | SLIV_RAW_MODE, (void *)SLIV_IOD_BASE + SLI_CTRL_I);
sli_wait_suspend(SLIH_IOD_BASE);
sli_wait_suspend(SLIH_CPU_BASE);
return 0;
}
+94
View File
@@ -0,0 +1,94 @@
CONFIG_RISCV=y
CONFIG_SYS_DCACHE_OFF=y
# CONFIG_SPL_USE_ARCH_MEMCPY is not set
# CONFIG_SPL_USE_ARCH_MEMMOVE is not set
# CONFIG_SPL_USE_ARCH_MEMSET is not set
CONFIG_TEXT_BASE=0x80000000
CONFIG_SYS_MALLOC_LEN=0xf00
CONFIG_SYS_MALLOC_F_LEN=0xf00
CONFIG_NR_DRAM_BANKS=1
CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y
CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x14bd7800
CONFIG_ENV_SIZE=0x20000
CONFIG_DEFAULT_DEVICE_TREE="ast2700-ibex"
CONFIG_SPL_TEXT_BASE=0x14bc0080
CONFIG_DM_RESET=y
CONFIG_SPL_BSS_START_ADDR=0x14bd7800
CONFIG_SPL_BSS_MAX_SIZE=0x800
CONFIG_SPL_SIZE_LIMIT=0x16000
CONFIG_SPL=y
CONFIG_SYS_MEM_TOP_HIDE=0x10000000
CONFIG_SYS_LOAD_ADDR=0x83000000
CONFIG_BUILD_TARGET=""
CONFIG_TARGET_ASPEED_AST2700_IBEX=y
# CONFIG_RISCV_ISA_F is not set
# CONFIG_RISCV_ISA_A is not set
# CONFIG_SPL_SMP is not set
CONFIG_XIP=y
CONFIG_SPL_XIP=y
# CONFIG_AVAILABLE_HARTS is not set
CONFIG_STACK_SIZE_SHIFT=11
CONFIG_ENV_VARS_UBOOT_CONFIG=y
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
CONFIG_STACK_SIZE=0x100000
CONFIG_FIT=y
CONFIG_FIT_SIGNATURE=y
CONFIG_SPL_LOAD_FIT=y
CONFIG_SPL_LOAD_FIT_ADDRESS=0x200c0000
# CONFIG_BOOTSTD is not set
CONFIG_SYS_BOOTM_LEN=0x4000000
# CONFIG_ARCH_FIXUP_FDT_MEMORY is not set
CONFIG_SYS_CBSIZE=256
CONFIG_SYS_PBSIZE=276
# CONFIG_CONSOLE_FLUSH_SUPPORT is not set
# CONFIG_CONSOLE_MUX is not set
CONFIG_SYS_STDIO_DEREGISTER=y
CONFIG_BOARD_LATE_INIT=y
CONFIG_SPL_MAX_SIZE=0x16000
# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set
CONFIG_SPL_RAM_SUPPORT=y
CONFIG_SPL_RAM_DEVICE=y
# CONFIG_CMD_BOOTD is not set
# CONFIG_CMD_BOOTI is not set
# CONFIG_BOOTM_LINUX is not set
# CONFIG_BOOTM_NETBSD is not set
# CONFIG_BOOTM_PLAN9 is not set
# CONFIG_BOOTM_RTEMS is not set
# CONFIG_BOOTM_VXWORKS is not set
# CONFIG_CMD_ELF is not set
# CONFIG_CMD_FDT is not set
# CONFIG_CMD_IMI is not set
# CONFIG_CMD_XIMG is not set
# CONFIG_CMD_SAVEENV is not set
# CONFIG_CMD_CRC32 is not set
# CONFIG_CMD_LOADS is not set
CONFIG_CMD_SYSBOOT=y
CONFIG_CMD_EXT4=y
CONFIG_CMD_FS_GENERIC=y
CONFIG_DEVICE_TREE_INCLUDES="ast2700-u-boot.dtsi"
# CONFIG_OF_TAG_MIGRATE is not set
CONFIG_SYS_RELOC_GD_ENV_ADDR=y
# CONFIG_NET is not set
CONFIG_SYS_RX_ETH_BUFFER=2
# CONFIG_DM_DEVICE_REMOVE is not set
# CONFIG_DM_SEQ_ALIAS is not set
# CONFIG_BLOCK_CACHE is not set
# CONFIG_CPU is not set
# CONFIG_GPIO is not set
# CONFIG_I2C is not set
CONFIG_MMC=y
CONFIG_SUPPORT_EMMC_BOOT=y
CONFIG_MMC_SDHCI=y
# CONFIG_MTD is not set
# CONFIG_POWER is not set
CONFIG_RAM=y
CONFIG_SPL_RAM=y
CONFIG_ASPEED_RAM=y
# CONFIG_RAM_SIFIVE is not set
CONFIG_SYS_NS16550=y
CONFIG_SYS_NS16550_MEM32=y
CONFIG_AST_IBEX_TIMER=y
CONFIG_VIDEO=y
# CONFIG_VIDEO_LOGO is not set
# CONFIG_RSA is not set
# CONFIG_EFI_LOADER is not set
+2 -1
View File
@@ -1,6 +1,6 @@
CONFIG_RISCV=y
CONFIG_SYS_MALLOC_LEN=0x820000
CONFIG_SYS_MALLOC_F_LEN=0x2000
CONFIG_SYS_MALLOC_F_LEN=0x8000
CONFIG_NR_DRAM_BANKS=1
CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y
CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x82300000
@@ -26,6 +26,7 @@ CONFIG_CMD_FAT=y
CONFIG_CMD_FS_GENERIC=y
CONFIG_ENV_OVERWRITE=y
CONFIG_NET_RANDOM_ETHADDR=y
CONFIG_CLK_SOPHGO_CV1800B=y
CONFIG_MMC=y
CONFIG_MMC_IO_VOLTAGE=y
CONFIG_MMC_UHS_SUPPORT=y
+26
View File
@@ -0,0 +1,26 @@
.. SPDX-License-Identifier: GPL-2.0+
IBex AST2700
============
AST2700 integrates an IBex RISC-V 32-bits CPU as the boot MCU to execute the
first stage bootlaoder, namely SPL.
Build
-----
1. Prepare the toolchains and make sure the $PATH to toolchains is correct.
2. Use `make ibex-ast2700_defconfig` in u-boot root to build the image
Running U-Boot SPL
------------------
The U-Boot SPL will boot in M mode and load the FIT image which includes
the 2nd stage bootloaders executed by the main processor Cortex-A35.
Burn U-Boot to SPI Flash
------------------------
Use SPI flash programmer (e.g. SF100) to program the u-book-spl.bin with the
offset 0x80 bytes to the SPI flash beginning.
+9
View File
@@ -0,0 +1,9 @@
.. SPDX-License-Identifier: GPL-2.0+
Aspeed
======
.. toctree::
:maxdepth: 2
ibex-ast2700
+1
View File
@@ -14,6 +14,7 @@ Board-specific doc
anbernic/index
apple/index
armltd/index
aspeed/index
asus/index
atmel/index
beacon/index
+1
View File
@@ -257,6 +257,7 @@ source "drivers/clk/mvebu/Kconfig"
source "drivers/clk/owl/Kconfig"
source "drivers/clk/qcom/Kconfig"
source "drivers/clk/renesas/Kconfig"
source "drivers/clk/sophgo/Kconfig"
source "drivers/clk/sunxi/Kconfig"
source "drivers/clk/sifive/Kconfig"
source "drivers/clk/starfive/Kconfig"
+1
View File
@@ -44,6 +44,7 @@ obj-$(CONFIG_CLK_QCOM) += qcom/
obj-$(CONFIG_CLK_RENESAS) += renesas/
obj-$(CONFIG_$(SPL_TPL_)CLK_SCMI) += clk_scmi.o
obj-$(CONFIG_CLK_SIFIVE) += sifive/
obj-$(CONFIG_CLK_SOPHGO) += sophgo/
obj-$(CONFIG_CLK_SUNXI) += sunxi/
obj-$(CONFIG_CLK_UNIPHIER) += uniphier/
obj-$(CONFIG_CLK_VERSACLOCK) += clk_versaclock.o
+14
View File
@@ -0,0 +1,14 @@
# SPDX-License-Identifier: GPL-2.0+
#
# Copyright (c) 2024, Kongyang Liu <seashell11234455@gmail.com>
config CLK_SOPHGO
bool
config CLK_SOPHGO_CV1800B
bool "Sophgo CV1800B clock support"
depends on CLK
select CLK_CCF
select CLK_SOPHGO
help
This enables support clock driver for Sophgo CV1800B SoC.
+6
View File
@@ -0,0 +1,6 @@
# SPDX-License-Identifier: GPL-2.0+
#
# Copyright (c) 2024, Kongyang Liu <seashell11234455@gmail.com>
obj-y += clk-ip.o clk-pll.o
obj-$(CONFIG_CLK_SOPHGO_CV1800B) += clk-cv1800b.o
+74
View File
@@ -0,0 +1,74 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Copyright (c) 2024, Kongyang Liu <seashell11234455@gmail.com>
*
*/
#ifndef __CLK_SOPHGO_COMMON_H__
#define __CLK_SOPHGO_COMMON_H__
#include <linux/bitops.h>
#include <linux/io.h>
#define CV1800B_CLK_OSC 1
#define CV1800B_CLK_BYPASS 2
#define CV1800B_CLK_ID_TRANSFORM(_id) ((_id) + 3)
struct cv1800b_clk_regbit {
u32 offset;
u8 shift;
};
struct cv1800b_clk_regfield {
u32 offset;
u8 shift;
u8 width;
};
#define CV1800B_CLK_REGBIT(_offset, _shift) \
{ \
.offset = _offset, \
.shift = _shift, \
}
#define CV1800B_CLK_REGFIELD(_offset, _shift, _width) \
{ \
.offset = _offset, \
.shift = _shift, \
.width = _width, \
}
static inline u32 cv1800b_clk_getbit(void *base, struct cv1800b_clk_regbit *bit)
{
return readl(base + bit->offset) & (BIT(bit->shift));
}
static inline u32 cv1800b_clk_setbit(void *base, struct cv1800b_clk_regbit *bit)
{
return setbits_le32(base + bit->offset, BIT(bit->shift));
}
static inline u32 cv1800b_clk_clrbit(void *base, struct cv1800b_clk_regbit *bit)
{
return clrbits_le32(base + bit->offset, BIT(bit->shift));
}
static inline u32 cv1800b_clk_getfield(void *base,
struct cv1800b_clk_regfield *field)
{
u32 mask = GENMASK(field->shift + field->width - 1, field->shift);
return (readl(base + field->offset) & mask) >> field->shift;
}
static inline void
cv1800b_clk_setfield(void *base, struct cv1800b_clk_regfield *field, u32 val)
{
u32 mask = GENMASK(field->shift + field->width - 1, field->shift);
u32 new_val = (readl(base + field->offset) & ~mask) |
((val << field->shift) & mask);
return writel(new_val, base + field->offset);
}
#endif /* __CLK_SOPHGO_COMMON_H__ */
+754
View File
@@ -0,0 +1,754 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (c) 2024, Kongyang Liu <seashell11234455@gmail.com>
*/
#include <clk-uclass.h>
#include <dm.h>
#include <linux/clk-provider.h>
#include "clk-common.h"
#include "clk-cv1800b.h"
#include "clk-ip.h"
#include "clk-pll.h"
static const char *const clk_cam_parents[] = {
"clk_cam0pll",
"clk_cam0pll_d2",
"clk_cam0pll_d3",
"clk_mipimpll_d3"
};
static const char *const clk_tpu_parents[] = {
"clk_tpll",
"clk_a0pll",
"clk_mipimpll",
"clk_fpll"
};
static const char *const clk_axi4_parents[] = { "clk_fpll", "clk_disppll" };
static const char *const clk_aud_parents[] = { "clk_a0pll", "clk_a24m" };
static const char *const clk_cam0_200_parents[] = { "osc", "clk_disppll" };
static const char *const clk_vip_sys_parents[] = {
"clk_mipimpll",
"clk_cam0pll",
"clk_disppll",
"clk_fpll"
};
static const char *const clk_axi_video_codec_parents[] = {
"clk_a0pll",
"clk_mipimpll",
"clk_cam1pll",
"clk_fpll"
};
static const char *const clk_vc_src0_parents[] = {
"clk_disppll",
"clk_mipimpll",
"clk_cam1pll",
"clk_fpll"
};
static const struct cv1800b_mmux_parent_info clk_c906_0_parents[] = {
{ "clk_tpll", 0, 0 },
{ "clk_a0pll", 0, 1 },
{ "clk_mipimpll", 0, 2 },
{ "clk_mpll", 0, 3 },
{ "clk_fpll", 1, 0 },
};
static const struct cv1800b_mmux_parent_info clk_c906_1_parents[] = {
{ "clk_tpll", 0, 0 },
{ "clk_a0pll", 0, 1 },
{ "clk_disppll", 0, 2 },
{ "clk_mpll", 0, 3 },
{ "clk_fpll", 1, 0 },
};
static const struct cv1800b_mmux_parent_info clk_a53_parents[] = {
{ "clk_tpll", 0, 0 },
{ "clk_a0pll", 0, 1 },
{ "clk_mipimpll", 0, 2 },
{ "clk_mpll", 0, 3 },
{ "clk_fpll", 1, 0 },
};
static struct cv1800b_clk_gate cv1800b_gate_info[] = {
CV1800B_GATE(CLK_XTAL_AP, "clk_xtal_ap", "osc", REG_CLK_EN_0, 3, CLK_IS_CRITICAL),
CV1800B_GATE(CLK_RTC_25M, "clk_rtc_25m", "osc", REG_CLK_EN_0, 8, CLK_IS_CRITICAL),
CV1800B_GATE(CLK_TEMPSEN, "clk_tempsen", "osc", REG_CLK_EN_0, 9, 0),
CV1800B_GATE(CLK_SARADC, "clk_saradc", "osc", REG_CLK_EN_0, 10, 0),
CV1800B_GATE(CLK_EFUSE, "clk_efuse", "osc", REG_CLK_EN_0, 11, 0),
CV1800B_GATE(CLK_APB_EFUSE, "clk_apb_efuse", "osc", REG_CLK_EN_0, 12, 0),
CV1800B_GATE(CLK_DEBUG, "clk_debug", "osc", REG_CLK_EN_0, 13, CLK_IS_CRITICAL),
CV1800B_GATE(CLK_XTAL_MISC, "clk_xtal_misc", "osc", REG_CLK_EN_0, 14, CLK_IS_CRITICAL),
CV1800B_GATE(CLK_APB_WDT, "clk_apb_wdt", "osc", REG_CLK_EN_1, 7, CLK_IS_CRITICAL),
CV1800B_GATE(CLK_WGN, "clk_wgn", "osc", REG_CLK_EN_3, 22, 0),
CV1800B_GATE(CLK_WGN0, "clk_wgn0", "osc", REG_CLK_EN_3, 23, 0),
CV1800B_GATE(CLK_WGN1, "clk_wgn1", "osc", REG_CLK_EN_3, 24, 0),
CV1800B_GATE(CLK_WGN2, "clk_wgn2", "osc", REG_CLK_EN_3, 25, 0),
CV1800B_GATE(CLK_KEYSCAN, "clk_keyscan", "osc", REG_CLK_EN_3, 26, 0),
CV1800B_GATE(CLK_TPU_FAB, "clk_tpu_fab", "clk_mipimpll", REG_CLK_EN_0, 5, 0),
CV1800B_GATE(CLK_AHB_ROM, "clk_ahb_rom", "clk_axi4", REG_CLK_EN_0, 6, 0),
CV1800B_GATE(CLK_AXI4_EMMC, "clk_axi4_emmc", "clk_axi4", REG_CLK_EN_0, 15, 0),
CV1800B_GATE(CLK_AXI4_SD0, "clk_axi4_sd0", "clk_axi4", REG_CLK_EN_0, 18, 0),
CV1800B_GATE(CLK_AXI4_SD1, "clk_axi4_sd1", "clk_axi4", REG_CLK_EN_0, 21, 0),
CV1800B_GATE(CLK_AXI4_ETH0, "clk_axi4_eth0", "clk_axi4", REG_CLK_EN_0, 26, 0),
CV1800B_GATE(CLK_AXI4_ETH1, "clk_axi4_eth1", "clk_axi4", REG_CLK_EN_0, 28, 0),
CV1800B_GATE(CLK_AHB_SF, "clk_ahb_sf", "clk_axi4", REG_CLK_EN_1, 0, 0),
CV1800B_GATE(CLK_SDMA_AXI, "clk_sdma_axi", "clk_axi4", REG_CLK_EN_1, 1, 0),
CV1800B_GATE(CLK_APB_I2C, "clk_apb_i2c", "clk_axi4", REG_CLK_EN_1, 6, 0),
CV1800B_GATE(CLK_APB_SPI0, "clk_apb_spi0", "clk_axi4", REG_CLK_EN_1, 9, 0),
CV1800B_GATE(CLK_APB_SPI1, "clk_apb_spi1", "clk_axi4", REG_CLK_EN_1, 10, 0),
CV1800B_GATE(CLK_APB_SPI2, "clk_apb_spi2", "clk_axi4", REG_CLK_EN_1, 11, 0),
CV1800B_GATE(CLK_APB_SPI3, "clk_apb_spi3", "clk_axi4", REG_CLK_EN_1, 12, 0),
CV1800B_GATE(CLK_APB_UART0, "clk_apb_uart0", "clk_axi4", REG_CLK_EN_1, 15, CLK_IS_CRITICAL),
CV1800B_GATE(CLK_APB_UART1, "clk_apb_uart1", "clk_axi4", REG_CLK_EN_1, 17, 0),
CV1800B_GATE(CLK_APB_UART2, "clk_apb_uart2", "clk_axi4", REG_CLK_EN_1, 19, 0),
CV1800B_GATE(CLK_APB_UART3, "clk_apb_uart3", "clk_axi4", REG_CLK_EN_1, 21, 0),
CV1800B_GATE(CLK_APB_UART4, "clk_apb_uart4", "clk_axi4", REG_CLK_EN_1, 23, 0),
CV1800B_GATE(CLK_APB_I2S0, "clk_apb_i2s0", "clk_axi4", REG_CLK_EN_1, 24, 0),
CV1800B_GATE(CLK_APB_I2S1, "clk_apb_i2s1", "clk_axi4", REG_CLK_EN_1, 25, 0),
CV1800B_GATE(CLK_APB_I2S2, "clk_apb_i2s2", "clk_axi4", REG_CLK_EN_1, 26, 0),
CV1800B_GATE(CLK_APB_I2S3, "clk_apb_i2s3", "clk_axi4", REG_CLK_EN_1, 27, 0),
CV1800B_GATE(CLK_AXI4_USB, "clk_axi4_usb", "clk_axi4", REG_CLK_EN_1, 28, 0),
CV1800B_GATE(CLK_APB_USB, "clk_apb_usb", "clk_axi4", REG_CLK_EN_1, 29, 0),
CV1800B_GATE(CLK_APB_I2C0, "clk_apb_i2c0", "clk_axi4", REG_CLK_EN_3, 17, 0),
CV1800B_GATE(CLK_APB_I2C1, "clk_apb_i2c1", "clk_axi4", REG_CLK_EN_3, 18, 0),
CV1800B_GATE(CLK_APB_I2C2, "clk_apb_i2c2", "clk_axi4", REG_CLK_EN_3, 19, 0),
CV1800B_GATE(CLK_APB_I2C3, "clk_apb_i2c3", "clk_axi4", REG_CLK_EN_3, 20, 0),
CV1800B_GATE(CLK_APB_I2C4, "clk_apb_i2c4", "clk_axi4", REG_CLK_EN_3, 21, 0),
CV1800B_GATE(CLK_AHB_SF1, "clk_ahb_sf1", "clk_axi4", REG_CLK_EN_3, 27, 0),
CV1800B_GATE(CLK_APB_AUDSRC, "clk_apb_audsrc", "clk_axi4", REG_CLK_EN_4, 2, 0),
CV1800B_GATE(CLK_DDR_AXI_REG, "clk_ddr_axi_reg", "clk_axi6", REG_CLK_EN_0, 7,
CLK_IS_CRITICAL),
CV1800B_GATE(CLK_APB_GPIO, "clk_apb_gpio", "clk_axi6", REG_CLK_EN_0, 29, CLK_IS_CRITICAL),
CV1800B_GATE(CLK_APB_GPIO_INTR, "clk_apb_gpio_intr", "clk_axi6", REG_CLK_EN_0, 30,
CLK_IS_CRITICAL),
CV1800B_GATE(CLK_APB_JPEG, "clk_apb_jpeg", "clk_axi6", REG_CLK_EN_2, 13, CLK_IGNORE_UNUSED),
CV1800B_GATE(CLK_APB_H264C, "clk_apb_h264c", "clk_axi6", REG_CLK_EN_2, 14, 0),
CV1800B_GATE(CLK_APB_H265C, "clk_apb_h265c", "clk_axi6", REG_CLK_EN_2, 15, 0),
CV1800B_GATE(CLK_PM, "clk_pm", "clk_axi6", REG_CLK_EN_3, 8, CLK_IS_CRITICAL),
CV1800B_GATE(CLK_CFG_REG_VIP, "clk_cfg_reg_vip", "clk_axi6", REG_CLK_EN_3, 31, 0),
CV1800B_GATE(CLK_CFG_REG_VC, "clk_cfg_reg_vc", "clk_axi6", REG_CLK_EN_4, 0,
CLK_IGNORE_UNUSED),
CV1800B_GATE(CLK_PWM, "clk_pwm", "clk_pwm_src", REG_CLK_EN_1, 8, CLK_IS_CRITICAL),
CV1800B_GATE(CLK_UART0, "clk_uart0", "clk_cam0_200", REG_CLK_EN_1, 14, CLK_IS_CRITICAL),
CV1800B_GATE(CLK_UART1, "clk_uart1", "clk_cam0_200", REG_CLK_EN_1, 16, 0),
CV1800B_GATE(CLK_UART2, "clk_uart2", "clk_cam0_200", REG_CLK_EN_1, 18, 0),
CV1800B_GATE(CLK_UART3, "clk_uart3", "clk_cam0_200", REG_CLK_EN_1, 20, 0),
CV1800B_GATE(CLK_UART4, "clk_uart4", "clk_cam0_200", REG_CLK_EN_1, 22, 0),
CV1800B_GATE(CLK_H264C, "clk_h264c", "clk_axi_video_codec", REG_CLK_EN_2, 10, 0),
CV1800B_GATE(CLK_H265C, "clk_h265c", "clk_axi_video_codec", REG_CLK_EN_2, 11, 0),
CV1800B_GATE(CLK_JPEG, "clk_jpeg", "clk_axi_video_codec", REG_CLK_EN_2, 12,
CLK_IGNORE_UNUSED),
CV1800B_GATE(CLK_CSI_MAC0_VIP, "clk_csi_mac0_vip", "clk_axi_vip", REG_CLK_EN_2, 18, 0),
CV1800B_GATE(CLK_CSI_MAC1_VIP, "clk_csi_mac1_vip", "clk_axi_vip", REG_CLK_EN_2, 19, 0),
CV1800B_GATE(CLK_ISP_TOP_VIP, "clk_isp_top_vip", "clk_axi_vip", REG_CLK_EN_2, 20, 0),
CV1800B_GATE(CLK_IMG_D_VIP, "clk_img_d_vip", "clk_axi_vip", REG_CLK_EN_2, 21, 0),
CV1800B_GATE(CLK_IMG_V_VIP, "clk_img_v_vip", "clk_axi_vip", REG_CLK_EN_2, 22, 0),
CV1800B_GATE(CLK_SC_TOP_VIP, "clk_sc_top_vip", "clk_axi_vip", REG_CLK_EN_2, 23, 0),
CV1800B_GATE(CLK_SC_D_VIP, "clk_sc_d_vip", "clk_axi_vip", REG_CLK_EN_2, 24, 0),
CV1800B_GATE(CLK_SC_V1_VIP, "clk_sc_v1_vip", "clk_axi_vip", REG_CLK_EN_2, 25, 0),
CV1800B_GATE(CLK_SC_V2_VIP, "clk_sc_v2_vip", "clk_axi_vip", REG_CLK_EN_2, 26, 0),
CV1800B_GATE(CLK_SC_V3_VIP, "clk_sc_v3_vip", "clk_axi_vip", REG_CLK_EN_2, 27, 0),
CV1800B_GATE(CLK_DWA_VIP, "clk_dwa_vip", "clk_axi_vip", REG_CLK_EN_2, 28, 0),
CV1800B_GATE(CLK_BT_VIP, "clk_bt_vip", "clk_axi_vip", REG_CLK_EN_2, 29, 0),
CV1800B_GATE(CLK_DISP_VIP, "clk_disp_vip", "clk_axi_vip", REG_CLK_EN_2, 30, 0),
CV1800B_GATE(CLK_DSI_MAC_VIP, "clk_dsi_mac_vip", "clk_axi_vip", REG_CLK_EN_2, 31, 0),
CV1800B_GATE(CLK_LVDS0_VIP, "clk_lvds0_vip", "clk_axi_vip", REG_CLK_EN_3, 0, 0),
CV1800B_GATE(CLK_LVDS1_VIP, "clk_lvds1_vip", "clk_axi_vip", REG_CLK_EN_3, 1, 0),
CV1800B_GATE(CLK_CSI0_RX_VIP, "clk_csi0_rx_vip", "clk_axi_vip", REG_CLK_EN_3, 2, 0),
CV1800B_GATE(CLK_CSI1_RX_VIP, "clk_csi1_rx_vip", "clk_axi_vip", REG_CLK_EN_3, 3, 0),
CV1800B_GATE(CLK_PAD_VI_VIP, "clk_pad_vi_vip", "clk_axi_vip", REG_CLK_EN_3, 4, 0),
CV1800B_GATE(CLK_PAD_VI1_VIP, "clk_pad_vi1_vip", "clk_axi_vip", REG_CLK_EN_3, 30, 0),
CV1800B_GATE(CLK_PAD_VI2_VIP, "clk_pad_vi2_vip", "clk_axi_vip", REG_CLK_EN_4, 7, 0),
CV1800B_GATE(CLK_CSI_BE_VIP, "clk_csi_be_vip", "clk_axi_vip", REG_CLK_EN_4, 8, 0),
CV1800B_GATE(CLK_VIP_IP0, "clk_vip_ip0", "clk_axi_vip", REG_CLK_EN_4, 9, 0),
CV1800B_GATE(CLK_VIP_IP1, "clk_vip_ip1", "clk_axi_vip", REG_CLK_EN_4, 10, 0),
CV1800B_GATE(CLK_VIP_IP2, "clk_vip_ip2", "clk_axi_vip", REG_CLK_EN_4, 11, 0),
CV1800B_GATE(CLK_VIP_IP3, "clk_vip_ip3", "clk_axi_vip", REG_CLK_EN_4, 12, 0),
CV1800B_GATE(CLK_IVE_VIP, "clk_ive_vip", "clk_axi_vip", REG_CLK_EN_4, 17, 0),
CV1800B_GATE(CLK_RAW_VIP, "clk_raw_vip", "clk_axi_vip", REG_CLK_EN_4, 18, 0),
CV1800B_GATE(CLK_OSDC_VIP, "clk_osdc_vip", "clk_axi_vip", REG_CLK_EN_4, 19, 0),
CV1800B_GATE(CLK_CSI_MAC2_VIP, "clk_csi_mac2_vip", "clk_axi_vip", REG_CLK_EN_4, 20, 0),
CV1800B_GATE(CLK_CAM0_VIP, "clk_cam0_vip", "clk_axi_vip", REG_CLK_EN_4, 21, 0),
CV1800B_GATE(CLK_TIMER0, "clk_timer0", "clk_xtal_misc", REG_CLK_EN_3, 9, CLK_IS_CRITICAL),
CV1800B_GATE(CLK_TIMER1, "clk_timer1", "clk_xtal_misc", REG_CLK_EN_3, 10, CLK_IS_CRITICAL),
CV1800B_GATE(CLK_TIMER2, "clk_timer2", "clk_xtal_misc", REG_CLK_EN_3, 11, CLK_IS_CRITICAL),
CV1800B_GATE(CLK_TIMER3, "clk_timer3", "clk_xtal_misc", REG_CLK_EN_3, 12, CLK_IS_CRITICAL),
CV1800B_GATE(CLK_TIMER4, "clk_timer4", "clk_xtal_misc", REG_CLK_EN_3, 13, CLK_IS_CRITICAL),
CV1800B_GATE(CLK_TIMER5, "clk_timer5", "clk_xtal_misc", REG_CLK_EN_3, 14, CLK_IS_CRITICAL),
CV1800B_GATE(CLK_TIMER6, "clk_timer6", "clk_xtal_misc", REG_CLK_EN_3, 15, CLK_IS_CRITICAL),
CV1800B_GATE(CLK_TIMER7, "clk_timer7", "clk_xtal_misc", REG_CLK_EN_3, 16, CLK_IS_CRITICAL),
};
struct cv1800b_clk_div cv1800b_div_info[] = {
CV1800B_DIV(CLK_1M, "clk_1m", "osc", REG_CLK_EN_3, 5,
REG_DIV_CLK_1M, 16, 6, 25, CLK_IS_CRITICAL),
CV1800B_DIV(CLK_EMMC_100K, "clk_emmc_100k", "clk_1m", REG_CLK_EN_0, 17,
REG_DIV_CLK_EMMC_100K, 16, 8, 10, 0),
CV1800B_DIV(CLK_SD0_100K, "clk_sd0_100k", "clk_1m", REG_CLK_EN_0, 20,
REG_DIV_CLK_SD0_100K, 16, 8, 10, 0),
CV1800B_DIV(CLK_SD1_100K, "clk_sd1_100k", "clk_1m", REG_CLK_EN_0, 23,
REG_DIV_CLK_SD1_100K, 16, 8, 10, 0),
CV1800B_DIV(CLK_GPIO_DB, "clk_gpio_db", "clk_1m", REG_CLK_EN_0, 31,
REG_DIV_CLK_GPIO_DB, 16, 16, 10, CLK_IS_CRITICAL)
};
struct cv1800b_clk_bypass_div cv1800b_bypass_div_info[] = {
CV1800B_BYPASS_DIV(CLK_AP_DEBUG, "clk_ap_debug", "clk_fpll", REG_CLK_EN_4, 5,
REG_DIV_CLK_AP_DEBUG, 16, 4, 5, REG_CLK_BYP_1, 4, CLK_IS_CRITICAL),
CV1800B_BYPASS_DIV(CLK_SRC_RTC_SYS_0, "clk_src_rtc_sys_0", "clk_fpll", REG_CLK_EN_4, 6,
REG_DIV_CLK_RTCSYS_SRC_0, 16, 4, 5, REG_CLK_BYP_1, 5, CLK_IS_CRITICAL),
CV1800B_BYPASS_DIV(CLK_CPU_GIC, "clk_cpu_gic", "clk_fpll", REG_CLK_EN_0, 2,
REG_DIV_CLK_CPU_GIC, 16, 4, 5, REG_CLK_BYP_0, 2, CLK_IS_CRITICAL),
CV1800B_BYPASS_DIV(CLK_ETH0_500M, "clk_eth0_500m", "clk_fpll", REG_CLK_EN_0, 25,
REG_DIV_CLK_GPIO_DB, 16, 4, 3, REG_CLK_BYP_0, 9, 0),
CV1800B_BYPASS_DIV(CLK_ETH1_500M, "clk_eth1_500m", "clk_fpll", REG_CLK_EN_0, 27,
REG_DIV_CLK_GPIO_DB, 16, 4, 3, REG_CLK_BYP_0, 10, 0),
CV1800B_BYPASS_DIV(CLK_AXI6, "clk_axi6", "clk_fpll", REG_CLK_EN_2, 2, REG_DIV_CLK_AXI6, 16,
4, 15, REG_CLK_BYP_0, 20, CLK_IS_CRITICAL),
CV1800B_BYPASS_DIV(CLK_SPI, "clk_spi", "clk_fpll", REG_CLK_EN_3, 6, REG_DIV_CLK_SPI, 16, 6,
8, REG_CLK_BYP_0, 30, 0),
CV1800B_BYPASS_DIV(CLK_DISP_SRC_VIP, "clk_disp_src_vip", "clk_disppll", REG_CLK_EN_2, 7,
REG_DIV_CLK_DISP_SRC_VIP, 16, 4, 8, REG_CLK_BYP_0, 25, 0),
CV1800B_BYPASS_DIV(CLK_CPU_AXI0, "clk_cpu_axi0", "clk_axi4", REG_CLK_EN_0, 1,
REG_DIV_CLK_CPU_AXI0, 16, 4, 3, REG_CLK_BYP_0, 1, CLK_IS_CRITICAL),
CV1800B_BYPASS_DIV(CLK_DSI_ESC, "clk_dsi_esc", "clk_axi6", REG_CLK_EN_2, 3,
REG_DIV_CLK_DSI_ESC, 16, 4, 5, REG_CLK_BYP_0, 21, 0),
CV1800B_BYPASS_DIV(CLK_I2C, "clk_i2c", "clk_axi6", REG_CLK_EN_3, 7, REG_DIV_CLK_I2C, 16, 4,
1, REG_CLK_BYP_0, 31, 0),
};
struct cv1800b_clk_fixed_div cv1800b_fixed_div_info[] = {
CV1800B_FIXED_DIV(CLK_CAM0PLL_D2, "clk_cam0pll_d2", "clk_cam0pll",
REG_CAM0PLL_CLK_CSR, 1, 2,
CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED),
CV1800B_FIXED_DIV(CLK_CAM0PLL_D3, "clk_cam0pll_d3", "clk_cam0pll",
REG_CAM0PLL_CLK_CSR, 2, 3,
CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED),
CV1800B_FIXED_DIV(CLK_MIPIMPLL_D3, "clk_mipimpll_d3", "clk_mipimpll",
REG_MIPIMPLL_CLK_CSR, 2, 3,
CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED),
CV1800B_FIXED_DIV(CLK_USB_33K, "clk_usb_33k", "clk_1m",
REG_CLK_EN_1, 31, 3,
0),
};
struct cv1800b_clk_bypass_fixed_div cv1800b_bypass_fixed_div_info[] = {
CV1800B_BYPASS_FIXED_DIV(CLK_USB_125M, "clk_usb_125m", "clk_fpll",
REG_CLK_EN_1, 30, 12,
REG_CLK_BYP_0, 17,
CLK_SET_RATE_PARENT),
CV1800B_BYPASS_FIXED_DIV(CLK_USB_12M, "clk_usb_12m", "clk_fpll",
REG_CLK_EN_2, 0, 125,
REG_CLK_BYP_0, 18,
CLK_SET_RATE_PARENT),
CV1800B_BYPASS_FIXED_DIV(CLK_VC_SRC1, "clk_vc_src1", "clk_fpll",
REG_CLK_EN_3, 28, 2,
REG_CLK_BYP_1, 0,
CLK_SET_RATE_PARENT),
CV1800B_BYPASS_FIXED_DIV(CLK_VC_SRC2, "clk_vc_src2", "clk_fpll",
REG_CLK_EN_4, 3, 3,
REG_CLK_BYP_1, 3,
CLK_SET_RATE_PARENT),
};
struct cv1800b_clk_mux cv1800b_mux_info[] = {
CV1800B_MUX(CLK_CAM0, "clk_cam0", clk_cam_parents,
REG_CLK_EN_2, 16,
REG_CLK_CAM0_SRC_DIV, 16, 6, 0,
REG_CLK_CAM0_SRC_DIV, 8, 2,
CLK_IGNORE_UNUSED),
CV1800B_MUX(CLK_CAM1, "clk_cam1", clk_cam_parents,
REG_CLK_EN_2, 17,
REG_CLK_CAM1_SRC_DIV, 16, 6, 0,
REG_CLK_CAM1_SRC_DIV, 8, 2,
CLK_IGNORE_UNUSED),
};
struct cv1800b_clk_bypass_mux cv1800b_bypass_mux_info[] = {
CV1800B_BYPASS_MUX(CLK_TPU, "clk_tpu", clk_tpu_parents,
REG_CLK_EN_0, 4,
REG_DIV_CLK_TPU, 16, 4, 3,
REG_DIV_CLK_TPU, 8, 2,
REG_CLK_BYP_0, 3,
0),
CV1800B_BYPASS_MUX(CLK_EMMC, "clk_emmc", clk_axi4_parents,
REG_CLK_EN_0, 16,
REG_DIV_CLK_EMMC, 16, 5, 15,
REG_DIV_CLK_EMMC, 8, 2,
REG_CLK_BYP_0, 5,
0),
CV1800B_BYPASS_MUX(CLK_SD0, "clk_sd0", clk_axi4_parents,
REG_CLK_EN_0, 19,
REG_DIV_CLK_SD0, 16, 5, 15,
REG_DIV_CLK_SD0, 8, 2,
REG_CLK_BYP_0, 6,
0),
CV1800B_BYPASS_MUX(CLK_SD1, "clk_sd1", clk_axi4_parents,
REG_CLK_EN_0, 22,
REG_DIV_CLK_SD1, 16, 5, 15,
REG_DIV_CLK_SD1, 8, 2,
REG_CLK_BYP_0, 7,
0),
CV1800B_BYPASS_MUX(CLK_SPI_NAND, "clk_spi_nand", clk_axi4_parents,
REG_CLK_EN_0, 24,
REG_DIV_CLK_SPI_NAND, 16, 5, 8,
REG_DIV_CLK_SPI_NAND, 8, 2,
REG_CLK_BYP_0, 8,
0),
CV1800B_BYPASS_MUX(CLK_AXI4, "clk_axi4", clk_axi4_parents,
REG_CLK_EN_2, 1,
REG_DIV_CLK_AXI4, 16, 4, 5,
REG_DIV_CLK_AXI4, 8, 2,
REG_CLK_BYP_0, 19,
CLK_IS_CRITICAL),
CV1800B_BYPASS_MUX(CLK_PWM_SRC, "clk_pwm_src", clk_axi4_parents,
REG_CLK_EN_4, 4,
REG_DIV_CLK_PWM_SRC_0, 16, 6, 10,
REG_DIV_CLK_PWM_SRC_0, 8, 2,
REG_CLK_BYP_0, 15,
CLK_IS_CRITICAL),
CV1800B_BYPASS_MUX(CLK_AUDSRC, "clk_audsrc", clk_aud_parents,
REG_CLK_EN_4, 1,
REG_DIV_CLK_AUDSRC, 16, 8, 18,
REG_DIV_CLK_AUDSRC, 8, 2,
REG_CLK_BYP_1, 2,
0),
CV1800B_BYPASS_MUX(CLK_SDMA_AUD0, "clk_sdma_aud0", clk_aud_parents,
REG_CLK_EN_1, 2,
REG_DIV_CLK_SDMA_AUD0, 16, 8, 18,
REG_DIV_CLK_SDMA_AUD0, 8, 2,
REG_CLK_BYP_0, 11,
0),
CV1800B_BYPASS_MUX(CLK_SDMA_AUD1, "clk_sdma_aud1", clk_aud_parents,
REG_CLK_EN_1, 3,
REG_DIV_CLK_SDMA_AUD1, 16, 8, 18,
REG_DIV_CLK_SDMA_AUD1, 8, 2,
REG_CLK_BYP_0, 12,
0),
CV1800B_BYPASS_MUX(CLK_SDMA_AUD2, "clk_sdma_aud2", clk_aud_parents,
REG_CLK_EN_1, 3,
REG_DIV_CLK_SDMA_AUD2, 16, 8, 18,
REG_DIV_CLK_SDMA_AUD2, 8, 2,
REG_CLK_BYP_0, 13,
0),
CV1800B_BYPASS_MUX(CLK_SDMA_AUD3, "clk_sdma_aud3", clk_aud_parents,
REG_CLK_EN_1, 3,
REG_DIV_CLK_SDMA_AUD3, 16, 8, 18,
REG_DIV_CLK_SDMA_AUD3, 8, 2,
REG_CLK_BYP_0, 14,
0),
CV1800B_BYPASS_MUX(CLK_CAM0_200, "clk_cam0_200", clk_cam0_200_parents,
REG_CLK_EN_1, 13,
REG_DIV_CLK_CAM0_200, 16, 4, 1,
REG_DIV_CLK_CAM0_200, 8, 2,
REG_CLK_BYP_0, 16,
CLK_IS_CRITICAL),
CV1800B_BYPASS_MUX(CLK_AXI_VIP, "clk_axi_vip", clk_vip_sys_parents,
REG_CLK_EN_2, 4,
REG_DIV_CLK_AXI_VIP, 16, 4, 3,
REG_DIV_CLK_AXI_VIP, 8, 2,
REG_CLK_BYP_0, 22,
0),
CV1800B_BYPASS_MUX(CLK_SRC_VIP_SYS_0, "clk_src_vip_sys_0", clk_vip_sys_parents,
REG_CLK_EN_2, 5,
REG_DIV_CLK_SRC_VIP_SYS_0, 16, 4, 6,
REG_DIV_CLK_SRC_VIP_SYS_0, 8, 2,
REG_CLK_BYP_0, 23,
0),
CV1800B_BYPASS_MUX(CLK_SRC_VIP_SYS_1, "clk_src_vip_sys_1", clk_vip_sys_parents,
REG_CLK_EN_2, 6,
REG_DIV_CLK_SRC_VIP_SYS_1, 16, 4, 6,
REG_DIV_CLK_SRC_VIP_SYS_1, 8, 2,
REG_CLK_BYP_0, 24,
0),
CV1800B_BYPASS_MUX(CLK_SRC_VIP_SYS_2, "clk_src_vip_sys_2", clk_vip_sys_parents,
REG_CLK_EN_3, 29,
REG_DIV_CLK_SRC_VIP_SYS_2, 16, 4, 2,
REG_DIV_CLK_SRC_VIP_SYS_2, 8, 2,
REG_CLK_BYP_1, 1,
0),
CV1800B_BYPASS_MUX(CLK_SRC_VIP_SYS_3, "clk_src_vip_sys_3", clk_vip_sys_parents,
REG_CLK_EN_4, 15,
REG_DIV_CLK_SRC_VIP_SYS_3, 16, 4, 2,
REG_DIV_CLK_SRC_VIP_SYS_3, 8, 2,
REG_CLK_BYP_1, 8,
0),
CV1800B_BYPASS_MUX(CLK_SRC_VIP_SYS_4, "clk_src_vip_sys_4", clk_vip_sys_parents,
REG_CLK_EN_4, 16,
REG_DIV_CLK_SRC_VIP_SYS_4, 16, 4, 3,
REG_DIV_CLK_SRC_VIP_SYS_4, 8, 2,
REG_CLK_BYP_1, 9,
0),
CV1800B_BYPASS_MUX(CLK_AXI_VIDEO_CODEC, "clk_axi_video_codec", clk_axi_video_codec_parents,
REG_CLK_EN_2, 8,
REG_DIV_CLK_AXI_VIDEO_CODEC, 16, 4, 2,
REG_DIV_CLK_AXI_VIDEO_CODEC, 8, 2,
REG_CLK_BYP_0, 26,
0),
CV1800B_BYPASS_MUX(CLK_VC_SRC0, "clk_vc_src0", clk_vc_src0_parents,
REG_CLK_EN_2, 9,
REG_DIV_CLK_VC_SRC0, 16, 4, 2,
REG_DIV_CLK_VC_SRC0, 8, 2,
REG_CLK_BYP_0, 27,
0),
};
struct cv1800b_clk_mmux cv1800b_mmux_info[] = {
CV1800B_MMUX(CLK_C906_0, "clk_c906_0", clk_c906_0_parents,
REG_CLK_EN_4, 13,
REG_DIV_CLK_C906_0_0, 16, 4, 1,
REG_DIV_CLK_C906_0_1, 16, 4, 2,
REG_DIV_CLK_C906_0_0, 8, 2,
REG_DIV_CLK_C906_0_1, 8, 2,
REG_CLK_BYP_1, 6,
REG_CLK_SEL_0, 23,
CLK_IS_CRITICAL | CLK_GET_RATE_NOCACHE),
CV1800B_MMUX(CLK_C906_1, "clk_c906_1", clk_c906_1_parents,
REG_CLK_EN_4, 14,
REG_DIV_CLK_C906_1_0, 16, 4, 2,
REG_DIV_CLK_C906_1_1, 16, 4, 3,
REG_DIV_CLK_C906_1_0, 8, 2,
REG_DIV_CLK_C906_1_1, 8, 2,
REG_CLK_BYP_1, 7,
REG_CLK_SEL_0, 24,
CLK_IS_CRITICAL | CLK_GET_RATE_NOCACHE),
CV1800B_MMUX(CLK_A53, "clk_a53", clk_a53_parents,
REG_CLK_EN_0, 0,
REG_DIV_CLK_A53_0, 16, 4, 1,
REG_DIV_CLK_A53_1, 16, 4, 2,
REG_DIV_CLK_A53_0, 8, 2,
REG_DIV_CLK_A53_1, 8, 2,
REG_CLK_BYP_0, 0,
REG_CLK_SEL_0, 0,
CLK_IS_CRITICAL | CLK_GET_RATE_NOCACHE),
};
static struct cv1800b_clk_audio cv1800b_audio_info[] = {
CV1800B_AUDIO(CLK_A24M, "clk_a24m", "clk_mipimpll",
REG_APLL_FRAC_DIV_CTRL, 0,
REG_APLL_FRAC_DIV_CTRL, 3,
REG_APLL_FRAC_DIV_CTRL, 1,
REG_APLL_FRAC_DIV_CTRL, 2,
REG_APLL_FRAC_DIV_M, 0, 22,
REG_APLL_FRAC_DIV_N, 0, 22,
0),
};
static struct cv1800b_clk_ipll cv1800b_ipll_info[] = {
CV1800B_IPLL(CLK_FPLL, "clk_fpll", "osc", REG_FPLL_CSR,
REG_PLL_G6_CTRL, 8,
REG_PLL_G6_STATUS, 2,
CLK_IS_CRITICAL),
CV1800B_IPLL(CLK_MIPIMPLL, "clk_mipimpll", "osc", REG_MIPIMPLL_CSR,
REG_PLL_G2_CTRL, 0,
REG_PLL_G2_STATUS, 0,
CLK_IS_CRITICAL),
};
static struct cv1800b_clk_fpll cv1800b_fpll_info[] = {
CV1800B_FPLL(CLK_MPLL, "clk_mpll", "osc", REG_MPLL_CSR,
REG_PLL_G6_CTRL, 0,
REG_PLL_G6_STATUS, 0,
REG_PLL_G6_SSC_SYN_CTRL, 2,
REG_PLL_G6_SSC_SYN_CTRL, 0,
REG_MPLL_SSC_SYN_CTRL, REG_MPLL_SSC_SYN_SET,
CLK_IS_CRITICAL),
CV1800B_FPLL(CLK_TPLL, "clk_tpll", "osc", REG_TPLL_CSR,
REG_PLL_G6_CTRL, 4,
REG_PLL_G6_STATUS, 1,
REG_PLL_G6_SSC_SYN_CTRL, 3,
REG_PLL_G6_SSC_SYN_CTRL, 0,
REG_TPLL_SSC_SYN_CTRL, REG_TPLL_SSC_SYN_SET,
CLK_IS_CRITICAL),
CV1800B_FPLL(CLK_A0PLL, "clk_a0pll", "clk_mipimpll", REG_A0PLL_CSR,
REG_PLL_G2_CTRL, 4,
REG_PLL_G2_STATUS, 1,
REG_PLL_G2_SSC_SYN_CTRL, 2,
REG_PLL_G2_SSC_SYN_CTRL, 0,
REG_A0PLL_SSC_SYN_CTRL, REG_A0PLL_SSC_SYN_SET,
CLK_IS_CRITICAL),
CV1800B_FPLL(CLK_DISPPLL, "clk_disppll", "clk_mipimpll", REG_DISPPLL_CSR,
REG_PLL_G2_CTRL, 8,
REG_PLL_G2_STATUS, 2,
REG_PLL_G2_SSC_SYN_CTRL, 3,
REG_PLL_G2_SSC_SYN_CTRL, 0,
REG_DISPPLL_SSC_SYN_CTRL, REG_DISPPLL_SSC_SYN_SET,
CLK_IS_CRITICAL),
CV1800B_FPLL(CLK_CAM0PLL, "clk_cam0pll", "clk_mipimpll", REG_CAM0PLL_CSR,
REG_PLL_G2_CTRL, 12,
REG_PLL_G2_STATUS, 3,
REG_PLL_G2_SSC_SYN_CTRL, 4,
REG_PLL_G2_SSC_SYN_CTRL, 0,
REG_CAM0PLL_SSC_SYN_CTRL, REG_CAM0PLL_SSC_SYN_SET,
CLK_IGNORE_UNUSED),
CV1800B_FPLL(CLK_CAM1PLL, "clk_cam1pll", "clk_mipimpll", REG_CAM1PLL_CSR,
REG_PLL_G2_CTRL, 16,
REG_PLL_G2_STATUS, 4,
REG_PLL_G2_SSC_SYN_CTRL, 5,
REG_PLL_G2_SSC_SYN_CTRL, 0,
REG_CAM1PLL_SSC_SYN_CTRL, REG_CAM1PLL_SSC_SYN_SET,
CLK_IS_CRITICAL),
};
static int cv1800b_register_clk(struct udevice *dev)
{
struct clk osc;
ulong osc_rate;
void *base = devfdt_get_addr_ptr(dev);
int i, ret;
ret = clk_get_by_index(dev, 0, &osc);
if (ret) {
pr_err("Failed to get clock\n");
return ret;
}
osc_rate = clk_get_rate(&osc);
clk_dm(CV1800B_CLK_OSC, clk_register_fixed_rate(NULL, "osc", osc_rate));
clk_dm(CV1800B_CLK_BYPASS, clk_register_fixed_rate(NULL, "bypass", osc_rate));
for (i = 0; i < ARRAY_SIZE(cv1800b_ipll_info); i++) {
struct cv1800b_clk_ipll *ipll = &cv1800b_ipll_info[i];
ipll->base = base;
ret = clk_register(&ipll->clk, "cv1800b_clk_ipll", ipll->name,
ipll->parent_name);
if (ret) {
pr_err("Failed to register ipll %s\n", ipll->name);
return ret;
}
}
for (i = 0; i < ARRAY_SIZE(cv1800b_fpll_info); i++) {
struct cv1800b_clk_fpll *fpll = &cv1800b_fpll_info[i];
fpll->ipll.base = base;
ret = clk_register(&fpll->ipll.clk, "cv1800b_clk_fpll",
fpll->ipll.name, fpll->ipll.parent_name);
if (ret) {
pr_err("Failed to register fpll %s\n", fpll->ipll.name);
return ret;
}
}
for (i = 0; i < ARRAY_SIZE(cv1800b_div_info); i++) {
struct cv1800b_clk_div *div = &cv1800b_div_info[i];
div->base = base;
ret = clk_register(&div->clk, "cv1800b_clk_div", div->name,
div->parent_name);
if (ret) {
pr_err("Failed to register div %s\n", div->name);
return ret;
}
}
for (i = 0; i < ARRAY_SIZE(cv1800b_fixed_div_info); i++) {
struct cv1800b_clk_fixed_div *fixed_div =
&cv1800b_fixed_div_info[i];
fixed_div->base = base;
ret = clk_register(&fixed_div->clk, "cv1800b_clk_fixed_div",
fixed_div->name, fixed_div->parent_name);
if (ret) {
pr_err("Failed to register fixed div %s\n",
fixed_div->name);
return ret;
}
}
for (i = 0; i < ARRAY_SIZE(cv1800b_bypass_fixed_div_info); i++) {
struct cv1800b_clk_bypass_fixed_div *bypass_fixed_div =
&cv1800b_bypass_fixed_div_info[i];
bypass_fixed_div->div.base = base;
ret = clk_register(&bypass_fixed_div->div.clk,
"cv1800b_clk_bypass_fixed_div",
bypass_fixed_div->div.name,
bypass_fixed_div->div.parent_name);
if (ret) {
pr_err("Failed to register bypass fixed div %s\n",
bypass_fixed_div->div.name);
return ret;
}
}
for (i = 0; i < ARRAY_SIZE(cv1800b_mux_info); i++) {
struct cv1800b_clk_mux *mux = &cv1800b_mux_info[i];
int parent;
mux->base = base;
parent = cv1800b_clk_getfield(base, &mux->mux);
ret = clk_register(&mux->clk, "cv1800b_clk_mux", mux->name,
mux->parent_names[parent]);
if (ret) {
pr_err("Failed to register mux %s\n", mux->name);
return ret;
}
}
for (i = 0; i < ARRAY_SIZE(cv1800b_mmux_info); i++) {
struct cv1800b_clk_mmux *mmux = &cv1800b_mmux_info[i];
int clk_sel, parent, idx;
mmux->base = base;
clk_sel = cv1800b_clk_getbit(base, &mmux->clk_sel) ? 0 : 1;
parent = cv1800b_clk_getfield(base, &mmux->mux[clk_sel]);
for (idx = 0; idx < mmux->num_parents; idx++) {
if (clk_sel == mmux->parent_infos[idx].clk_sel &&
parent == mmux->parent_infos[idx].index)
break;
}
ret = clk_register(&mmux->clk, "cv1800b_clk_mmux", mmux->name,
mmux->parent_infos[idx].name);
if (ret) {
pr_err("Failed to register mmux %s\n", mmux->name);
return ret;
}
}
for (i = 0; i < ARRAY_SIZE(cv1800b_audio_info); i++) {
struct cv1800b_clk_audio *audio = &cv1800b_audio_info[i];
audio->base = base;
ret = clk_register(&audio->clk, "cv1800b_clk_audio",
audio->name, audio->parent_name);
if (ret) {
pr_err("Failed to register audio %s\n", audio->name);
return ret;
}
}
for (i = 0; i < ARRAY_SIZE(cv1800b_bypass_mux_info); i++) {
struct cv1800b_clk_bypass_mux *bypass_mux =
&cv1800b_bypass_mux_info[i];
int parent;
bypass_mux->mux.base = base;
parent = cv1800b_clk_getfield(base, &bypass_mux->mux.mux);
ret = clk_register(&bypass_mux->mux.clk,
"cv1800b_clk_bypass_mux",
bypass_mux->mux.name,
bypass_mux->mux.parent_names[parent]);
if (ret) {
pr_err("Failed to register bypass mux %s\n",
bypass_mux->mux.name);
return ret;
}
}
for (i = 0; i < ARRAY_SIZE(cv1800b_bypass_div_info); i++) {
struct cv1800b_clk_bypass_div *bypass_div =
&cv1800b_bypass_div_info[i];
bypass_div->div.base = base;
ret = clk_register(&bypass_div->div.clk,
"cv1800b_clk_bypass_div",
bypass_div->div.name,
bypass_div->div.parent_name);
if (ret) {
pr_err("Failed to register bypass div %s\n",
bypass_div->div.name);
return ret;
}
}
for (i = 0; i < ARRAY_SIZE(cv1800b_gate_info); i++) {
struct cv1800b_clk_gate *gate = &cv1800b_gate_info[i];
gate->base = base;
ret = clk_register(&gate->clk, "cv1800b_clk_gate", gate->name,
gate->parent_name);
if (ret) {
pr_err("Failed to register gate %s\n", gate->name);
return ret;
}
}
return 0;
}
static int cv1800b_clk_probe(struct udevice *dev)
{
return cv1800b_register_clk(dev);
}
static int cv1800b_clk_enable(struct clk *clk)
{
struct clk *c;
int err = clk_get_by_id(CV1800B_CLK_ID_TRANSFORM(clk->id), &c);
if (err)
return err;
return clk_enable(c);
}
static int cv1800b_clk_disable(struct clk *clk)
{
struct clk *c;
int err = clk_get_by_id(CV1800B_CLK_ID_TRANSFORM(clk->id), &c);
if (err)
return err;
return clk_disable(c);
}
static ulong cv1800b_clk_get_rate(struct clk *clk)
{
struct clk *c;
int err = clk_get_by_id(CV1800B_CLK_ID_TRANSFORM(clk->id), &c);
if (err)
return err;
return clk_get_rate(c);
}
static ulong cv1800b_clk_set_rate(struct clk *clk, ulong rate)
{
struct clk *c;
int err = clk_get_by_id(CV1800B_CLK_ID_TRANSFORM(clk->id), &c);
if (err)
return err;
return clk_set_rate(c, rate);
}
static int cv1800b_clk_set_parent(struct clk *clk, struct clk *parent)
{
struct clk *c, *p;
int err = clk_get_by_id(CV1800B_CLK_ID_TRANSFORM(clk->id), &c);
if (err)
return err;
err = clk_get_by_id(CV1800B_CLK_ID_TRANSFORM(parent->id), &p);
if (err)
return err;
return clk_set_parent(c, p);
}
const struct clk_ops cv1800b_clk_ops = {
.enable = cv1800b_clk_enable,
.disable = cv1800b_clk_disable,
.get_rate = cv1800b_clk_get_rate,
.set_rate = cv1800b_clk_set_rate,
.set_parent = cv1800b_clk_set_parent,
};
static const struct udevice_id cv1800b_clk_of_match[] = {
{ .compatible = "sophgo,cv1800-clk" },
{ },
};
U_BOOT_DRIVER(sophgo_clk) = {
.name = "cv1800b_clk",
.id = UCLASS_CLK,
.of_match = cv1800b_clk_of_match,
.probe = cv1800b_clk_probe,
.ops = &cv1800b_clk_ops,
.flags = DM_FLAG_PRE_RELOC,
};
+123
View File
@@ -0,0 +1,123 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2023 Inochi Amaoto <inochiama@outlook.com>
*/
#ifndef _CLK_SOPHGO_CV1800_H_
#define _CLK_SOPHGO_CV1800_H_
#include <dt-bindings/clock/sophgo,cv1800.h>
#define CV1800_CLK_MAX (CLK_XTAL_AP + 1)
#define CV1810_CLK_MAX (CLK_DISP_SRC_VIP + 1)
#define REG_PLL_G2_CTRL 0x800
#define REG_PLL_G2_STATUS 0x804
#define REG_MIPIMPLL_CSR 0x808
#define REG_A0PLL_CSR 0x80C
#define REG_DISPPLL_CSR 0x810
#define REG_CAM0PLL_CSR 0x814
#define REG_CAM1PLL_CSR 0x818
#define REG_PLL_G2_SSC_SYN_CTRL 0x840
#define REG_A0PLL_SSC_SYN_CTRL 0x850
#define REG_A0PLL_SSC_SYN_SET 0x854
#define REG_A0PLL_SSC_SYN_SPAN 0x858
#define REG_A0PLL_SSC_SYN_STEP 0x85C
#define REG_DISPPLL_SSC_SYN_CTRL 0x860
#define REG_DISPPLL_SSC_SYN_SET 0x864
#define REG_DISPPLL_SSC_SYN_SPAN 0x868
#define REG_DISPPLL_SSC_SYN_STEP 0x86C
#define REG_CAM0PLL_SSC_SYN_CTRL 0x870
#define REG_CAM0PLL_SSC_SYN_SET 0x874
#define REG_CAM0PLL_SSC_SYN_SPAN 0x878
#define REG_CAM0PLL_SSC_SYN_STEP 0x87C
#define REG_CAM1PLL_SSC_SYN_CTRL 0x880
#define REG_CAM1PLL_SSC_SYN_SET 0x884
#define REG_CAM1PLL_SSC_SYN_SPAN 0x888
#define REG_CAM1PLL_SSC_SYN_STEP 0x88C
#define REG_APLL_FRAC_DIV_CTRL 0x890
#define REG_APLL_FRAC_DIV_M 0x894
#define REG_APLL_FRAC_DIV_N 0x898
#define REG_MIPIMPLL_CLK_CSR 0x8A0
#define REG_A0PLL_CLK_CSR 0x8A4
#define REG_DISPPLL_CLK_CSR 0x8A8
#define REG_CAM0PLL_CLK_CSR 0x8AC
#define REG_CAM1PLL_CLK_CSR 0x8B0
#define REG_CLK_CAM0_SRC_DIV 0x8C0
#define REG_CLK_CAM1_SRC_DIV 0x8C4
/* top_pll_g6 */
#define REG_PLL_G6_CTRL 0x900
#define REG_PLL_G6_STATUS 0x904
#define REG_MPLL_CSR 0x908
#define REG_TPLL_CSR 0x90C
#define REG_FPLL_CSR 0x910
#define REG_PLL_G6_SSC_SYN_CTRL 0x940
#define REG_DPLL_SSC_SYN_CTRL 0x950
#define REG_DPLL_SSC_SYN_SET 0x954
#define REG_DPLL_SSC_SYN_SPAN 0x958
#define REG_DPLL_SSC_SYN_STEP 0x95C
#define REG_MPLL_SSC_SYN_CTRL 0x960
#define REG_MPLL_SSC_SYN_SET 0x964
#define REG_MPLL_SSC_SYN_SPAN 0x968
#define REG_MPLL_SSC_SYN_STEP 0x96C
#define REG_TPLL_SSC_SYN_CTRL 0x970
#define REG_TPLL_SSC_SYN_SET 0x974
#define REG_TPLL_SSC_SYN_SPAN 0x978
#define REG_TPLL_SSC_SYN_STEP 0x97C
/* clkgen */
#define REG_CLK_EN_0 0x000
#define REG_CLK_EN_1 0x004
#define REG_CLK_EN_2 0x008
#define REG_CLK_EN_3 0x00C
#define REG_CLK_EN_4 0x010
#define REG_CLK_SEL_0 0x020
#define REG_CLK_BYP_0 0x030
#define REG_CLK_BYP_1 0x034
#define REG_DIV_CLK_A53_0 0x040
#define REG_DIV_CLK_A53_1 0x044
#define REG_DIV_CLK_CPU_AXI0 0x048
#define REG_DIV_CLK_CPU_GIC 0x050
#define REG_DIV_CLK_TPU 0x054
#define REG_DIV_CLK_EMMC 0x064
#define REG_DIV_CLK_EMMC_100K 0x06C
#define REG_DIV_CLK_SD0 0x070
#define REG_DIV_CLK_SD0_100K 0x078
#define REG_DIV_CLK_SD1 0x07C
#define REG_DIV_CLK_SD1_100K 0x084
#define REG_DIV_CLK_SPI_NAND 0x088
#define REG_DIV_CLK_ETH0_500M 0x08C
#define REG_DIV_CLK_ETH1_500M 0x090
#define REG_DIV_CLK_GPIO_DB 0x094
#define REG_DIV_CLK_SDMA_AUD0 0x098
#define REG_DIV_CLK_SDMA_AUD1 0x09C
#define REG_DIV_CLK_SDMA_AUD2 0x0A0
#define REG_DIV_CLK_SDMA_AUD3 0x0A4
#define REG_DIV_CLK_CAM0_200 0x0A8
#define REG_DIV_CLK_AXI4 0x0B8
#define REG_DIV_CLK_AXI6 0x0BC
#define REG_DIV_CLK_DSI_ESC 0x0C4
#define REG_DIV_CLK_AXI_VIP 0x0C8
#define REG_DIV_CLK_SRC_VIP_SYS_0 0x0D0
#define REG_DIV_CLK_SRC_VIP_SYS_1 0x0D8
#define REG_DIV_CLK_DISP_SRC_VIP 0x0E0
#define REG_DIV_CLK_AXI_VIDEO_CODEC 0x0E4
#define REG_DIV_CLK_VC_SRC0 0x0EC
#define REG_DIV_CLK_1M 0x0FC
#define REG_DIV_CLK_SPI 0x100
#define REG_DIV_CLK_I2C 0x104
#define REG_DIV_CLK_SRC_VIP_SYS_2 0x110
#define REG_DIV_CLK_AUDSRC 0x118
#define REG_DIV_CLK_PWM_SRC_0 0x120
#define REG_DIV_CLK_AP_DEBUG 0x128
#define REG_DIV_CLK_RTCSYS_SRC_0 0x12C
#define REG_DIV_CLK_C906_0_0 0x130
#define REG_DIV_CLK_C906_0_1 0x134
#define REG_DIV_CLK_C906_1_0 0x138
#define REG_DIV_CLK_C906_1_1 0x13C
#define REG_DIV_CLK_SRC_VIP_SYS_3 0x140
#define REG_DIV_CLK_SRC_VIP_SYS_4 0x144
#endif /* _CLK_SOPHGO_CV1800_H_ */
+594
View File
@@ -0,0 +1,594 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2023 Inochi Amaoto <inochiama@outlook.com>
*/
#include <dm.h>
#include <div64.h>
#include <linux/clk-provider.h>
#include <linux/io.h>
#include "clk-common.h"
#include "clk-ip.h"
static int get_parent_index(struct clk *clk, const char *const *parent_name,
u8 num_parents)
{
const char *name = clk_hw_get_name(clk);
int i;
for (i = 0; i < num_parents; i++) {
if (!strcmp(name, parent_name[i]))
return i;
}
return -1;
}
/* GATE */
#define to_cv1800b_clk_gate(_clk) \
container_of(_clk, struct cv1800b_clk_gate, clk)
static int gate_enable(struct clk *clk)
{
struct cv1800b_clk_gate *gate = to_cv1800b_clk_gate(clk);
return cv1800b_clk_setbit(gate->base, &gate->gate);
}
static int gate_disable(struct clk *clk)
{
struct cv1800b_clk_gate *gate = to_cv1800b_clk_gate(clk);
return cv1800b_clk_clrbit(gate->base, &gate->gate);
}
static ulong gate_get_rate(struct clk *clk)
{
return clk_get_parent_rate(clk);
}
const struct clk_ops cv1800b_clk_gate_ops = {
.disable = gate_disable,
.enable = gate_enable,
.get_rate = gate_get_rate,
};
U_BOOT_DRIVER(cv1800b_clk_gate) = {
.name = "cv1800b_clk_gate",
.id = UCLASS_CLK,
.ops = &cv1800b_clk_gate_ops,
.flags = DM_FLAG_PRE_RELOC,
};
/* DIV */
#define CLK_DIV_EN_FACTOR BIT(3)
#define to_cv1800b_clk_div(_clk) container_of(_clk, struct cv1800b_clk_div, clk)
static int div_enable(struct clk *clk)
{
struct cv1800b_clk_div *div = to_cv1800b_clk_div(clk);
return cv1800b_clk_setbit(div->base, &div->gate);
}
static int div_disable(struct clk *clk)
{
struct cv1800b_clk_div *div = to_cv1800b_clk_div(clk);
return cv1800b_clk_clrbit(div->base, &div->gate);
}
static ulong div_get_rate(struct clk *clk)
{
struct cv1800b_clk_div *div = to_cv1800b_clk_div(clk);
ulong val;
if (div->div_init == 0 ||
readl(div->base + div->div.offset) & CLK_DIV_EN_FACTOR)
val = cv1800b_clk_getfield(div->base, &div->div);
else
val = div->div_init;
return DIV_ROUND_UP_ULL(clk_get_parent_rate(clk), val);
}
static ulong div_set_rate(struct clk *clk, ulong rate)
{
struct cv1800b_clk_div *div = to_cv1800b_clk_div(clk);
ulong parent_rate = clk_get_parent_rate(clk);
u32 val;
val = DIV_ROUND_UP_ULL(parent_rate, rate);
val = min_t(u32, val, clk_div_mask(div->div.width));
cv1800b_clk_setfield(div->base, &div->div, val);
if (div->div_init > 0)
setbits_le32(div->base + div->div.offset, CLK_DIV_EN_FACTOR);
return DIV_ROUND_UP_ULL(parent_rate, val);
}
const struct clk_ops cv1800b_clk_div_ops = {
.disable = div_disable,
.enable = div_enable,
.get_rate = div_get_rate,
.set_rate = div_set_rate,
};
U_BOOT_DRIVER(cv1800b_clk_div) = {
.name = "cv1800b_clk_div",
.id = UCLASS_CLK,
.ops = &cv1800b_clk_div_ops,
.flags = DM_FLAG_PRE_RELOC,
};
#define to_cv1800b_clk_bypass_div(_clk) \
container_of(_clk, struct cv1800b_clk_bypass_div, div.clk)
static ulong bypass_div_get_rate(struct clk *clk)
{
struct cv1800b_clk_bypass_div *div = to_cv1800b_clk_bypass_div(clk);
if (cv1800b_clk_getbit(div->div.base, &div->bypass))
return 0;
return div_get_rate(clk);
}
static ulong bypass_div_set_rate(struct clk *clk, ulong rate)
{
struct cv1800b_clk_bypass_div *div = to_cv1800b_clk_bypass_div(clk);
if (cv1800b_clk_getbit(div->div.base, &div->bypass))
return 0;
return div_set_rate(clk, rate);
}
static int bypass_div_set_parent(struct clk *clk, struct clk *pclk)
{
struct cv1800b_clk_bypass_div *div = to_cv1800b_clk_bypass_div(clk);
if (pclk->id == CV1800B_CLK_BYPASS) {
cv1800b_clk_setbit(div->div.base, &div->bypass);
return 0;
}
if (strcmp(clk_hw_get_name(pclk), div->div.parent_name))
return -EINVAL;
cv1800b_clk_clrbit(div->div.base, &div->bypass);
return 0;
}
const struct clk_ops cv1800b_clk_bypass_div_ops = {
.disable = div_disable,
.enable = div_enable,
.get_rate = bypass_div_get_rate,
.set_rate = bypass_div_set_rate,
.set_parent = bypass_div_set_parent,
};
U_BOOT_DRIVER(cv1800b_clk_bypass_div) = {
.name = "cv1800b_clk_bypass_div",
.id = UCLASS_CLK,
.ops = &cv1800b_clk_bypass_div_ops,
.flags = DM_FLAG_PRE_RELOC,
};
/* FIXED DIV */
#define to_cv1800b_clk_fixed_div(_clk) \
container_of(_clk, struct cv1800b_clk_fixed_div, clk)
static int fixed_div_enable(struct clk *clk)
{
struct cv1800b_clk_fixed_div *div = to_cv1800b_clk_fixed_div(clk);
return cv1800b_clk_setbit(div->base, &div->gate);
}
static int fixed_div_disable(struct clk *clk)
{
struct cv1800b_clk_fixed_div *div = to_cv1800b_clk_fixed_div(clk);
return cv1800b_clk_clrbit(div->base, &div->gate);
}
static ulong fixed_div_get_rate(struct clk *clk)
{
struct cv1800b_clk_fixed_div *div = to_cv1800b_clk_fixed_div(clk);
return DIV_ROUND_UP_ULL(clk_get_parent_rate(clk), div->div);
}
const struct clk_ops cv1800b_clk_fixed_div_ops = {
.disable = fixed_div_disable,
.enable = fixed_div_enable,
.get_rate = fixed_div_get_rate,
};
U_BOOT_DRIVER(cv1800b_clk_fixed_div) = {
.name = "cv1800b_clk_fixed_div",
.id = UCLASS_CLK,
.ops = &cv1800b_clk_fixed_div_ops,
.flags = DM_FLAG_PRE_RELOC,
};
#define to_cv1800b_clk_bypass_fixed_div(_clk) \
container_of(_clk, struct cv1800b_clk_bypass_fixed_div, div.clk)
static ulong bypass_fixed_div_get_rate(struct clk *clk)
{
struct cv1800b_clk_bypass_fixed_div *div =
to_cv1800b_clk_bypass_fixed_div(clk);
if (cv1800b_clk_getbit(div->div.base, &div->bypass))
return 0;
return fixed_div_get_rate(clk);
}
static int bypass_fixed_div_set_parent(struct clk *clk, struct clk *pclk)
{
struct cv1800b_clk_bypass_fixed_div *div =
to_cv1800b_clk_bypass_fixed_div(clk);
if (pclk->id == CV1800B_CLK_BYPASS) {
cv1800b_clk_setbit(div->div.base, &div->bypass);
return 0;
}
if (strcmp(clk_hw_get_name(pclk), div->div.parent_name))
return -EINVAL;
cv1800b_clk_clrbit(div->div.base, &div->bypass);
return 0;
}
const struct clk_ops cv1800b_clk_bypass_fixed_div_ops = {
.disable = fixed_div_disable,
.enable = fixed_div_enable,
.get_rate = bypass_fixed_div_get_rate,
.set_parent = bypass_fixed_div_set_parent,
};
U_BOOT_DRIVER(cv1800b_clk_bypass_fixed_div) = {
.name = "cv1800b_clk_bypass_fixed_div",
.id = UCLASS_CLK,
.ops = &cv1800b_clk_bypass_fixed_div_ops,
.flags = DM_FLAG_PRE_RELOC,
};
/* MUX */
#define to_cv1800b_clk_mux(_clk) container_of(_clk, struct cv1800b_clk_mux, clk)
static int mux_enable(struct clk *clk)
{
struct cv1800b_clk_mux *mux = to_cv1800b_clk_mux(clk);
return cv1800b_clk_setbit(mux->base, &mux->gate);
}
static int mux_disable(struct clk *clk)
{
struct cv1800b_clk_mux *mux = to_cv1800b_clk_mux(clk);
return cv1800b_clk_clrbit(mux->base, &mux->gate);
}
static ulong mux_get_rate(struct clk *clk)
{
struct cv1800b_clk_mux *mux = to_cv1800b_clk_mux(clk);
ulong val;
if (mux->div_init == 0 ||
readl(mux->base + mux->div.offset) & CLK_DIV_EN_FACTOR)
val = cv1800b_clk_getfield(mux->base, &mux->div);
else
val = mux->div_init;
return DIV_ROUND_UP_ULL(clk_get_parent_rate(clk), val);
}
static ulong mux_set_rate(struct clk *clk, ulong rate)
{
struct cv1800b_clk_mux *mux = to_cv1800b_clk_mux(clk);
ulong parent_rate = clk_get_parent_rate(clk);
ulong val;
val = DIV_ROUND_UP_ULL(parent_rate, rate);
val = min_t(u32, val, clk_div_mask(mux->div.width));
cv1800b_clk_setfield(mux->base, &mux->div, val);
if (mux->div_init > 0)
setbits_le32(mux->base + mux->div.offset, CLK_DIV_EN_FACTOR);
return DIV_ROUND_UP_ULL(parent_rate, val);
}
static int mux_set_parent(struct clk *clk, struct clk *pclk)
{
struct cv1800b_clk_mux *mux = to_cv1800b_clk_mux(clk);
int index = get_parent_index(pclk, mux->parent_names, mux->num_parents);
if (index < 0)
return -EINVAL;
cv1800b_clk_setfield(mux->base, &mux->mux, index);
return 0;
}
const struct clk_ops cv1800b_clk_mux_ops = {
.disable = mux_disable,
.enable = mux_enable,
.get_rate = mux_get_rate,
.set_rate = mux_set_rate,
.set_parent = mux_set_parent,
};
U_BOOT_DRIVER(cv1800b_clk_mux) = {
.name = "cv1800b_clk_mux",
.id = UCLASS_CLK,
.ops = &cv1800b_clk_mux_ops,
.flags = DM_FLAG_PRE_RELOC,
};
#define to_cv1800b_clk_bypass_mux(_clk) \
container_of(_clk, struct cv1800b_clk_bypass_mux, mux.clk)
static ulong bypass_mux_get_rate(struct clk *clk)
{
struct cv1800b_clk_bypass_mux *mux = to_cv1800b_clk_bypass_mux(clk);
if (cv1800b_clk_getbit(mux->mux.base, &mux->bypass))
return 0;
return mux_get_rate(clk);
}
static ulong bypass_mux_set_rate(struct clk *clk, ulong rate)
{
struct cv1800b_clk_bypass_mux *mux = to_cv1800b_clk_bypass_mux(clk);
if (cv1800b_clk_getbit(mux->mux.base, &mux->bypass))
return 0;
return mux_set_rate(clk, rate);
}
static int bypass_mux_set_parent(struct clk *clk, struct clk *pclk)
{
struct cv1800b_clk_bypass_mux *mux = to_cv1800b_clk_bypass_mux(clk);
int index;
if (pclk->id == CV1800B_CLK_BYPASS) {
cv1800b_clk_setbit(mux->mux.base, &mux->bypass);
return 0;
}
index = get_parent_index(pclk, mux->mux.parent_names,
mux->mux.num_parents);
if (index < 0)
return -EINVAL;
cv1800b_clk_clrbit(mux->mux.base, &mux->bypass);
cv1800b_clk_setfield(mux->mux.base, &mux->mux.mux, index);
return 0;
}
const struct clk_ops cv1800b_clk_bypass_mux_ops = {
.disable = mux_disable,
.enable = mux_enable,
.get_rate = bypass_mux_get_rate,
.set_rate = bypass_mux_set_rate,
.set_parent = bypass_mux_set_parent,
};
U_BOOT_DRIVER(cv1800b_clk_bypass_mux) = {
.name = "cv1800b_clk_bypass_mux",
.id = UCLASS_CLK,
.ops = &cv1800b_clk_bypass_mux_ops,
.flags = DM_FLAG_PRE_RELOC,
};
/* MMUX */
#define to_cv1800b_clk_mmux(_clk) \
container_of(_clk, struct cv1800b_clk_mmux, clk)
static int mmux_enable(struct clk *clk)
{
struct cv1800b_clk_mmux *mmux = to_cv1800b_clk_mmux(clk);
return cv1800b_clk_setbit(mmux->base, &mmux->gate);
}
static int mmux_disable(struct clk *clk)
{
struct cv1800b_clk_mmux *mmux = to_cv1800b_clk_mmux(clk);
return cv1800b_clk_clrbit(mmux->base, &mmux->gate);
}
static ulong mmux_get_rate(struct clk *clk)
{
struct cv1800b_clk_mmux *mmux = to_cv1800b_clk_mmux(clk);
int clk_sel = 1;
ulong reg, val;
if (cv1800b_clk_getbit(mmux->base, &mmux->bypass))
return 0;
if (cv1800b_clk_getbit(mmux->base, &mmux->clk_sel))
clk_sel = 0;
reg = readl(mmux->base + mmux->div[clk_sel].offset);
if (mmux->div_init[clk_sel] == 0 || reg & CLK_DIV_EN_FACTOR)
val = cv1800b_clk_getfield(mmux->base, &mmux->div[clk_sel]);
else
val = mmux->div_init[clk_sel];
return DIV_ROUND_UP_ULL(clk_get_parent_rate(clk), val);
}
static ulong mmux_set_rate(struct clk *clk, ulong rate)
{
struct cv1800b_clk_mmux *mmux = to_cv1800b_clk_mmux(clk);
int clk_sel = 1;
ulong parent_rate = clk_get_parent_rate(clk);
ulong val;
if (cv1800b_clk_getbit(mmux->base, &mmux->bypass))
return 0;
if (cv1800b_clk_getbit(mmux->base, &mmux->clk_sel))
clk_sel = 0;
val = DIV_ROUND_UP_ULL(parent_rate, rate);
val = min_t(u32, val, clk_div_mask(mmux->div[clk_sel].width));
cv1800b_clk_setfield(mmux->base, &mmux->div[clk_sel], val);
if (mmux->div_init[clk_sel] > 0)
setbits_le32(mmux->base + mmux->div[clk_sel].offset,
CLK_DIV_EN_FACTOR);
return DIV_ROUND_UP_ULL(parent_rate, val);
}
static int mmux_set_parent(struct clk *clk, struct clk *pclk)
{
struct cv1800b_clk_mmux *mmux = to_cv1800b_clk_mmux(clk);
const char *pname = clk_hw_get_name(pclk);
int i;
u8 clk_sel, index;
if (pclk->id == CV1800B_CLK_BYPASS) {
cv1800b_clk_setbit(mmux->base, &mmux->bypass);
return 0;
}
for (i = 0; i < mmux->num_parents; i++) {
if (!strcmp(pname, mmux->parent_infos[i].name))
break;
}
if (i == mmux->num_parents)
return -EINVAL;
clk_sel = mmux->parent_infos[i].clk_sel;
index = mmux->parent_infos[i].index;
cv1800b_clk_clrbit(mmux->base, &mmux->bypass);
if (clk_sel)
cv1800b_clk_clrbit(mmux->base, &mmux->clk_sel);
else
cv1800b_clk_setbit(mmux->base, &mmux->clk_sel);
cv1800b_clk_setfield(mmux->base, &mmux->mux[clk_sel], index);
return 0;
}
const struct clk_ops cv1800b_clk_mmux_ops = {
.disable = mmux_disable,
.enable = mmux_enable,
.get_rate = mmux_get_rate,
.set_rate = mmux_set_rate,
.set_parent = mmux_set_parent,
};
U_BOOT_DRIVER(cv1800b_clk_mmux) = {
.name = "cv1800b_clk_mmux",
.id = UCLASS_CLK,
.ops = &cv1800b_clk_mmux_ops,
.flags = DM_FLAG_PRE_RELOC,
};
/* AUDIO CLK */
#define to_cv1800b_clk_audio(_clk) \
container_of(_clk, struct cv1800b_clk_audio, clk)
static int aclk_enable(struct clk *clk)
{
struct cv1800b_clk_audio *aclk = to_cv1800b_clk_audio(clk);
cv1800b_clk_setbit(aclk->base, &aclk->src_en);
cv1800b_clk_setbit(aclk->base, &aclk->output_en);
return 0;
}
static int aclk_disable(struct clk *clk)
{
struct cv1800b_clk_audio *aclk = to_cv1800b_clk_audio(clk);
cv1800b_clk_clrbit(aclk->base, &aclk->src_en);
cv1800b_clk_clrbit(aclk->base, &aclk->output_en);
return 0;
}
static ulong aclk_get_rate(struct clk *clk)
{
struct cv1800b_clk_audio *aclk = to_cv1800b_clk_audio(clk);
u64 parent_rate = clk_get_parent_rate(clk);
u32 m, n;
if (!cv1800b_clk_getbit(aclk->base, &aclk->div_en))
return 0;
m = cv1800b_clk_getfield(aclk->base, &aclk->m);
n = cv1800b_clk_getfield(aclk->base, &aclk->n);
return DIV_ROUND_UP_ULL(n * parent_rate, m * 2);
}
static u32 gcd(u32 a, u32 b)
{
u32 t;
while (b != 0) {
t = a % b;
a = b;
b = t;
}
return a;
}
static void aclk_determine_mn(ulong parent_rate, ulong rate, u32 *m, u32 *n)
{
u32 tm = parent_rate / 2;
u32 tn = rate;
u32 tcommon = gcd(tm, tn);
*m = tm / tcommon;
*n = tn / tcommon;
}
static ulong aclk_set_rate(struct clk *clk, ulong rate)
{
struct cv1800b_clk_audio *aclk = to_cv1800b_clk_audio(clk);
ulong parent_rate = clk_get_parent_rate(clk);
u32 m, n;
aclk_determine_mn(parent_rate, rate, &m, &n);
cv1800b_clk_setfield(aclk->base, &aclk->m, m);
cv1800b_clk_setfield(aclk->base, &aclk->n, n);
cv1800b_clk_setbit(aclk->base, &aclk->div_en);
cv1800b_clk_setbit(aclk->base, &aclk->div_up);
return DIV_ROUND_UP_ULL(parent_rate * n, m * 2);
}
const struct clk_ops cv1800b_clk_audio_ops = {
.disable = aclk_disable,
.enable = aclk_enable,
.get_rate = aclk_get_rate,
.set_rate = aclk_set_rate,
};
U_BOOT_DRIVER(cv1800b_clk_audio) = {
.name = "cv1800b_clk_audio",
.id = UCLASS_CLK,
.ops = &cv1800b_clk_audio_ops,
.flags = DM_FLAG_PRE_RELOC,
};
+288
View File
@@ -0,0 +1,288 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Copyright (c) 2024, Kongyang Liu <seashell11234455@gmail.com>
*
*/
#ifndef __CLK_SOPHGO_IP_H__
#define __CLK_SOPHGO_IP_H__
#include <clk.h>
#include "clk-common.h"
struct cv1800b_mmux_parent_info {
const char *name;
u8 clk_sel;
u8 index;
};
struct cv1800b_clk_gate {
struct clk clk;
const char *name;
const char *parent_name;
void __iomem *base;
struct cv1800b_clk_regbit gate;
};
struct cv1800b_clk_div {
struct clk clk;
const char *name;
const char *parent_name;
void __iomem *base;
struct cv1800b_clk_regbit gate;
struct cv1800b_clk_regfield div;
int div_init;
};
struct cv1800b_clk_bypass_div {
struct cv1800b_clk_div div;
struct cv1800b_clk_regbit bypass;
};
struct cv1800b_clk_fixed_div {
struct clk clk;
const char *name;
const char *parent_name;
void __iomem *base;
struct cv1800b_clk_regbit gate;
int div;
};
struct cv1800b_clk_bypass_fixed_div {
struct cv1800b_clk_fixed_div div;
struct cv1800b_clk_regbit bypass;
};
struct cv1800b_clk_mux {
struct clk clk;
const char *name;
const char * const *parent_names;
u8 num_parents;
void __iomem *base;
struct cv1800b_clk_regbit gate;
struct cv1800b_clk_regfield div;
int div_init;
struct cv1800b_clk_regfield mux;
};
struct cv1800b_clk_bypass_mux {
struct cv1800b_clk_mux mux;
struct cv1800b_clk_regbit bypass;
};
struct cv1800b_clk_mmux {
struct clk clk;
const char *name;
const struct cv1800b_mmux_parent_info *parent_infos;
u8 num_parents;
void __iomem *base;
struct cv1800b_clk_regbit gate;
struct cv1800b_clk_regfield div[2];
int div_init[2];
struct cv1800b_clk_regfield mux[2];
struct cv1800b_clk_regbit bypass;
struct cv1800b_clk_regbit clk_sel;
};
struct cv1800b_clk_audio {
struct clk clk;
const char *name;
const char *parent_name;
void __iomem *base;
struct cv1800b_clk_regbit src_en;
struct cv1800b_clk_regbit output_en;
struct cv1800b_clk_regbit div_en;
struct cv1800b_clk_regbit div_up;
struct cv1800b_clk_regfield m;
struct cv1800b_clk_regfield n;
};
#define CV1800B_GATE(_id, _name, _parent, \
_gate_offset, _gate_shift, \
_flags) \
{ \
.clk = { \
.id = CV1800B_CLK_ID_TRANSFORM(_id), \
.flags = _flags, \
}, \
.name = _name, \
.parent_name = _parent, \
.gate = CV1800B_CLK_REGBIT(_gate_offset, _gate_shift), \
}
#define CV1800B_DIV(_id, _name, _parent, \
_gate_offset, _gate_shift, \
_div_offset, _div_shift, _div_width, \
_div_init, _flags) \
{ \
.clk = { \
.id = CV1800B_CLK_ID_TRANSFORM(_id), \
.flags = _flags, \
}, \
.name = _name, \
.parent_name = _parent, \
.gate = CV1800B_CLK_REGBIT(_gate_offset, _gate_shift), \
.div = CV1800B_CLK_REGFIELD(_div_offset, _div_shift, \
_div_width), \
.div_init = _div_init, \
}
#define CV1800B_BYPASS_DIV(_id, _name, _parent, \
_gate_offset, _gate_shift, \
_div_offset, _div_shift, \
_div_width, _div_init, \
_bypass_offset, _bypass_shift, \
_flags) \
{ \
.div = CV1800B_DIV(_id, _name, _parent, \
_gate_offset, _gate_shift, \
_div_offset, _div_shift, _div_width, \
_div_init, _flags), \
.bypass = CV1800B_CLK_REGBIT(_bypass_offset, \
_bypass_shift), \
}
#define CV1800B_FIXED_DIV(_id, _name, _parent, \
_gate_offset, _gate_shift, \
_div, _flags) \
{ \
.clk = { \
.id = CV1800B_CLK_ID_TRANSFORM(_id), \
.flags = _flags, \
}, \
.name = _name, \
.parent_name = _parent, \
.gate = CV1800B_CLK_REGBIT(_gate_offset, _gate_shift), \
.div = _div, \
}
#define CV1800B_BYPASS_FIXED_DIV(_id, _name, _parent, \
_gate_offset, _gate_shift, \
_div, \
_bypass_offset, _bypass_shift, \
_flags) \
{ \
.div = CV1800B_FIXED_DIV(_id, _name, _parent, \
_gate_offset, _gate_shift, \
_div, _flags), \
.bypass = CV1800B_CLK_REGBIT(_bypass_offset, \
_bypass_shift) \
}
#define CV1800B_MUX(_id, _name, _parents, \
_gate_offset, _gate_shift, \
_div_offset, _div_shift, _div_width, _div_init, \
_mux_offset, _mux_shift, _mux_width, \
_flags) \
{ \
.clk = { \
.id = CV1800B_CLK_ID_TRANSFORM(_id), \
.flags = _flags, \
}, \
.name = _name, \
.parent_names = _parents, \
.num_parents = ARRAY_SIZE(_parents), \
.gate = CV1800B_CLK_REGBIT(_gate_offset, _gate_shift), \
.div = CV1800B_CLK_REGFIELD(_div_offset, _div_shift, \
_div_width), \
.div_init = _div_init, \
.mux = CV1800B_CLK_REGFIELD(_mux_offset, _mux_shift, \
_mux_width), \
}
#define CV1800B_BYPASS_MUX(_id, _name, _parents, \
_gate_offset, _gate_shift, \
_div_offset, _div_shift, \
_div_width, _div_init, \
_mux_offset, _mux_shift, _mux_width, \
_bypass_offset, _bypass_shift, \
_flags) \
{ \
.mux = CV1800B_MUX(_id, _name, _parents, \
_gate_offset, _gate_shift, \
_div_offset, _div_shift, \
_div_width, _div_init, \
_mux_offset, _mux_shift, _mux_width, \
_flags), \
.bypass = CV1800B_CLK_REGBIT(_bypass_offset, \
_bypass_shift), \
}
#define CV1800B_MMUX(_id, _name, _parents, \
_gate_offset, _gate_shift, \
_div0_offset, _div0_shift, _div0_width, _div0_init,\
_div1_offset, _div1_shift, _div1_width, _div1_init,\
_mux0_offset, _mux0_shift, _mux0_width, \
_mux1_offset, _mux1_shift, _mux1_width, \
_bypass_offset, _bypass_shift, \
_clk_sel_offset, _clk_sel_shift, \
_flags) \
{ \
.clk = { \
.id = CV1800B_CLK_ID_TRANSFORM(_id), \
.flags = _flags, \
}, \
.name = _name, \
.parent_infos = _parents, \
.num_parents = ARRAY_SIZE(_parents), \
.gate = CV1800B_CLK_REGBIT(_gate_offset, _gate_shift), \
.div = { \
CV1800B_CLK_REGFIELD(_div0_offset, _div0_shift, \
_div0_width), \
CV1800B_CLK_REGFIELD(_div1_offset, _div1_shift, \
_div1_width), \
}, \
.div_init = { _div0_init, _div1_init }, \
.mux = { \
CV1800B_CLK_REGFIELD(_mux0_offset, _mux0_shift, \
_mux0_width), \
CV1800B_CLK_REGFIELD(_mux1_offset, _mux1_shift, \
_mux1_width), \
}, \
.bypass = CV1800B_CLK_REGBIT(_bypass_offset, \
_bypass_shift), \
.clk_sel = CV1800B_CLK_REGBIT(_clk_sel_offset, \
_clk_sel_shift), \
}
#define CV1800B_AUDIO(_id, _name, _parent, \
_src_en_offset, _src_en_shift, \
_output_en_offset, _output_en_shift, \
_div_en_offset, _div_en_shift, \
_div_up_offset, _div_up_shift, \
_m_offset, _m_shift, _m_width, \
_n_offset, _n_shift, _n_width, \
_flags) \
{ \
.clk = { \
.id = CV1800B_CLK_ID_TRANSFORM(_id), \
.flags = _flags, \
}, \
.name = _name, \
.parent_name = _parent, \
.src_en = CV1800B_CLK_REGBIT(_src_en_offset, \
_src_en_shift), \
.output_en = CV1800B_CLK_REGBIT(_output_en_offset, \
_output_en_shift), \
.div_en = CV1800B_CLK_REGBIT(_div_en_offset, \
_div_en_shift), \
.div_up = CV1800B_CLK_REGBIT(_div_up_offset, \
_div_up_shift), \
.m = CV1800B_CLK_REGFIELD(_m_offset, _m_shift, \
_m_width), \
.n = CV1800B_CLK_REGFIELD(_n_offset, _n_shift, \
_n_width), \
}
extern const struct clk_ops cv1800b_clk_gate_ops;
extern const struct clk_ops cv1800b_clk_div_ops;
extern const struct clk_ops cv1800b_clk_bypass_div_ops;
extern const struct clk_ops cv1800b_clk_fixed_div_ops;
extern const struct clk_ops cv1800b_clk_bypass_fixed_div_ops;
extern const struct clk_ops cv1800b_clk_mux_ops;
extern const struct clk_ops cv1800b_clk_bypass_mux_ops;
extern const struct clk_ops cv1800b_clk_mmux_ops;
extern const struct clk_ops cv1800b_clk_audio_ops;
#endif /* __CLK_SOPHGO_IP_H__ */
+275
View File
@@ -0,0 +1,275 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (c) 2024, Kongyang Liu <seashell11234455@gmail.com>
*/
#include <clk-uclass.h>
#include <dm.h>
#include <div64.h>
#include <linux/bitfield.h>
#include <linux/clk-provider.h>
#include <linux/kernel.h>
#include "clk-common.h"
#include "clk-pll.h"
#define PLL_PRE_DIV_MIN 1
#define PLL_PRE_DIV_MAX 127
#define PLL_POST_DIV_MIN 1
#define PLL_POST_DIV_MAX 127
#define PLL_DIV_MIN 6
#define PLL_DIV_MAX 127
#define PLL_ICTRL_MIN 0
#define PLL_ICTRL_MAX 7
#define PLL_MODE_MIN 0
#define PLL_MODE_MAX 3
#define FOR_RANGE(x, RANGE) for (x = RANGE##_MIN; x <= RANGE##_MAX; x++)
#define PLL_ICTRL GENMASK(26, 24)
#define PLL_DIV_SEL GENMASK(23, 17)
#define PLL_SEL_MODE GENMASK(16, 15)
#define PLL_POST_DIV_SEL GENMASK(14, 8)
#define PLL_PRE_DIV_SEL GENMASK(6, 0)
#define PLL_MASK_ALL (PLL_ICTRL | PLL_DIV_SEL | PLL_SEL_MODE | PLL_POST_DIV_SEL | PLL_PRE_DIV_SEL)
/* IPLL */
#define to_clk_ipll(dev) container_of(dev, struct cv1800b_clk_ipll, clk)
static int cv1800b_ipll_enable(struct clk *clk)
{
struct cv1800b_clk_ipll *pll = to_clk_ipll(clk);
cv1800b_clk_clrbit(pll->base, &pll->pll_pwd);
return 0;
}
static int cv1800b_ipll_disable(struct clk *clk)
{
struct cv1800b_clk_ipll *pll = to_clk_ipll(clk);
cv1800b_clk_setbit(pll->base, &pll->pll_pwd);
return 0;
}
static ulong cv1800b_ipll_get_rate(struct clk *clk)
{
struct cv1800b_clk_ipll *pll = to_clk_ipll(clk);
ulong parent_rate = clk_get_parent_rate(clk);
u32 reg = readl(pll->base + pll->pll_reg);
u32 pre_div = FIELD_GET(PLL_PRE_DIV_SEL, reg);
u32 post_div = FIELD_GET(PLL_POST_DIV_SEL, reg);
u32 div = FIELD_GET(PLL_DIV_SEL, reg);
return DIV_ROUND_DOWN_ULL(parent_rate * div, pre_div * post_div);
}
static ulong cv1800b_ipll_set_rate(struct clk *clk, ulong rate)
{
struct cv1800b_clk_ipll *pll = to_clk_ipll(clk);
ulong parent_rate = clk_get_parent_rate(clk);
u32 pre_div, post_div, div;
u32 pre_div_sel, post_div_sel, div_sel;
ulong new_rate, best_rate = 0;
u32 mode, ictrl;
u32 test, val;
FOR_RANGE(pre_div, PLL_PRE_DIV)
{
FOR_RANGE(post_div, PLL_POST_DIV)
{
FOR_RANGE(div, PLL_DIV)
{
new_rate =
DIV_ROUND_DOWN_ULL(parent_rate * div, pre_div * post_div);
if (rate - new_rate < rate - best_rate) {
best_rate = new_rate;
pre_div_sel = pre_div;
post_div_sel = post_div;
div_sel = div;
}
}
}
}
FOR_RANGE(mode, PLL_MODE)
{
FOR_RANGE(ictrl, PLL_ICTRL)
{
test = 184 * (1 + mode) * (1 + ictrl) / 2;
if (test > 20 * div_sel && test < 35 * div_sel) {
val = FIELD_PREP(PLL_PRE_DIV_SEL, pre_div_sel) |
FIELD_PREP(PLL_POST_DIV_SEL, post_div_sel) |
FIELD_PREP(PLL_DIV_SEL, div_sel) |
FIELD_PREP(PLL_ICTRL, ictrl) |
FIELD_PREP(PLL_SEL_MODE, mode);
clrsetbits_le32(pll->base + pll->pll_reg, PLL_MASK_ALL, val);
return best_rate;
}
}
}
return -EINVAL;
}
const struct clk_ops cv1800b_ipll_ops = {
.enable = cv1800b_ipll_enable,
.disable = cv1800b_ipll_disable,
.get_rate = cv1800b_ipll_get_rate,
.set_rate = cv1800b_ipll_set_rate,
};
U_BOOT_DRIVER(cv1800b_clk_ipll) = {
.name = "cv1800b_clk_ipll",
.id = UCLASS_CLK,
.ops = &cv1800b_ipll_ops,
.flags = DM_FLAG_PRE_RELOC,
};
/* FPLL */
#define to_clk_fpll(dev) container_of(dev, struct cv1800b_clk_fpll, ipll.clk)
static ulong cv1800b_fpll_get_rate(struct clk *clk)
{
struct cv1800b_clk_fpll *pll = to_clk_fpll(clk);
u32 val, syn_set;
u32 pre_div, post_div, div;
u8 mult = 1;
ulong divisor, remainder, rate;
if (!cv1800b_clk_getbit(pll->ipll.base, &pll->syn.en))
return cv1800b_ipll_get_rate(clk);
syn_set = readl(pll->ipll.base + pll->syn.set);
if (syn_set == 0)
return 0;
val = readl(pll->ipll.base + pll->ipll.pll_reg);
pre_div = FIELD_GET(PLL_PRE_DIV_SEL, val);
post_div = FIELD_GET(PLL_POST_DIV_SEL, val);
div = FIELD_GET(PLL_DIV_SEL, val);
if (cv1800b_clk_getbit(pll->ipll.base, &pll->syn.clk_half))
mult = 2;
divisor = (ulong)pre_div * post_div * syn_set;
rate = (clk_get_parent_rate(clk) * div) << 25;
remainder = rate % divisor;
rate /= divisor;
return rate * mult + DIV_ROUND_CLOSEST_ULL(remainder * mult, divisor);
}
static ulong cv1800b_find_syn(ulong rate, ulong parent_rate, ulong pre_div, ulong post_div,
ulong div, u32 *syn)
{
u32 syn_min = (4 << 26) + 1;
u32 syn_max = U32_MAX;
u32 mid;
ulong new_rate;
u32 mult = 1;
ulong divisor, remainder;
while (syn_min < syn_max) {
mid = ((ulong)syn_min + syn_max) / 2;
divisor = pre_div * post_div * mid;
new_rate = (parent_rate * div) << 25;
remainder = do_div(new_rate, divisor);
new_rate = new_rate * mult + DIV_ROUND_CLOSEST_ULL(remainder * mult, divisor);
if (new_rate > rate) {
syn_max = mid + 1;
} else if (new_rate < rate) {
syn_min = mid - 1;
} else {
syn_min = mid;
break;
}
}
*syn = syn_min;
return new_rate;
}
static ulong cv1800b_fpll_set_rate(struct clk *clk, ulong rate)
{
struct cv1800b_clk_fpll *pll = to_clk_fpll(clk);
ulong parent_rate = clk_get_parent_rate(clk);
u32 pre_div, post_div, div;
u32 pre_div_sel, post_div_sel, div_sel;
u32 syn, syn_sel;
ulong new_rate, best_rate = 0;
u32 mult = 1;
u32 mode, ictrl;
if (!cv1800b_clk_getbit(pll->ipll.base, &pll->syn.en))
return cv1800b_ipll_set_rate(clk, rate);
if (cv1800b_clk_getbit(pll->ipll.base, &pll->syn.clk_half))
mult = 2;
FOR_RANGE(pre_div, PLL_PRE_DIV)
{
FOR_RANGE(post_div, PLL_POST_DIV)
{
FOR_RANGE(div, PLL_DIV)
{
new_rate = cv1800b_find_syn(rate, parent_rate, pre_div, post_div,
div, &syn);
if (rate - new_rate < rate - best_rate) {
best_rate = new_rate;
pre_div_sel = pre_div;
post_div_sel = post_div;
div_sel = div;
syn_sel = syn;
}
}
}
}
FOR_RANGE(mode, PLL_MODE)
{
FOR_RANGE(ictrl, PLL_ICTRL)
{
u32 test = 184 * (1 + mode) * (1 + ictrl) / 2;
if (test > 10 * div_sel && test <= 24 * div_sel) {
u32 val = FIELD_PREP(PLL_PRE_DIV_SEL, pre_div_sel) |
FIELD_PREP(PLL_POST_DIV_SEL, post_div_sel) |
FIELD_PREP(PLL_DIV_SEL, div_sel) |
FIELD_PREP(PLL_ICTRL, ictrl) |
FIELD_PREP(PLL_SEL_MODE, mode);
clrsetbits_le32(pll->ipll.base + pll->ipll.pll_reg, PLL_MASK_ALL,
val);
writel(syn_sel, pll->ipll.base + pll->syn.set);
return best_rate;
}
}
}
return -EINVAL;
}
static int cv1800b_fpll_set_parent(struct clk *clk, struct clk *parent)
{
struct cv1800b_clk_fpll *pll = to_clk_fpll(clk);
if (parent->id == CV1800B_CLK_BYPASS)
cv1800b_clk_setbit(pll->ipll.base, &pll->syn.en);
else
cv1800b_clk_clrbit(pll->ipll.base, &pll->syn.en);
return 0;
}
const struct clk_ops cv1800b_fpll_ops = {
.enable = cv1800b_ipll_enable,
.disable = cv1800b_ipll_disable,
.get_rate = cv1800b_fpll_get_rate,
.set_rate = cv1800b_fpll_set_rate,
.set_parent = cv1800b_fpll_set_parent,
};
U_BOOT_DRIVER(cv1800b_clk_fpll) = {
.name = "cv1800b_clk_fpll",
.id = UCLASS_CLK,
.ops = &cv1800b_fpll_ops,
.flags = DM_FLAG_PRE_RELOC,
};
+74
View File
@@ -0,0 +1,74 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Copyright (c) 2024, Kongyang Liu <seashell11234455@gmail.com>
*
*/
#ifndef __clk_SOPHGO_PLL_H__
#define __clk_SOPHGO_PLL_H__
#include <clk.h>
#include "clk-common.h"
struct cv1800b_clk_synthesizer {
struct cv1800b_clk_regbit en;
struct cv1800b_clk_regbit clk_half;
u32 ctrl;
u32 set;
};
struct cv1800b_clk_ipll {
struct clk clk;
const char *name;
const char *parent_name;
void __iomem *base;
u32 pll_reg;
struct cv1800b_clk_regbit pll_pwd;
struct cv1800b_clk_regbit pll_status;
};
struct cv1800b_clk_fpll {
struct cv1800b_clk_ipll ipll;
struct cv1800b_clk_synthesizer syn;
};
#define CV1800B_IPLL(_id, _name, _parent_name, _pll_reg, _pll_pwd_offset, \
_pll_pwd_shift, _pll_status_offset, _pll_status_shift, \
_flags) \
{ \
.clk = { \
.id = CV1800B_CLK_ID_TRANSFORM(_id), \
.flags = _flags, \
}, \
.name = _name, \
.parent_name = _parent_name, \
.pll_reg = _pll_reg, \
.pll_pwd = CV1800B_CLK_REGBIT(_pll_pwd_offset, _pll_pwd_shift), \
.pll_status = CV1800B_CLK_REGBIT(_pll_status_offset, \
_pll_status_shift), \
}
#define CV1800B_FPLL(_id, _name, _parent_name, _pll_reg, _pll_pwd_offset, \
_pll_pwd_shift, _pll_status_offset, _pll_status_shift, \
_syn_en_offset, _syn_en_shift, _syn_clk_half_offset, \
_syn_clk_half_shift, _syn_ctrl_offset, _syn_set_offset, \
_flags) \
{ \
.ipll = CV1800B_IPLL(_id, _name, _parent_name, _pll_reg, \
_pll_pwd_offset, _pll_pwd_shift, \
_pll_status_offset, _pll_status_shift, \
_flags), \
.syn = { \
.en = CV1800B_CLK_REGBIT(_syn_en_offset, _syn_en_shift),\
.clk_half = CV1800B_CLK_REGBIT(_syn_clk_half_offset, \
_syn_clk_half_shift), \
.ctrl = _syn_ctrl_offset, \
.set = _syn_set_offset, \
}, \
}
extern const struct clk_ops cv1800b_ipll_ops;
extern const struct clk_ops cv1800b_fpll_ops;
#endif /* __clk_SOPHGO_PLL_H__ */
+1
View File
@@ -113,6 +113,7 @@ static int aspeed_mdio_probe(struct udevice *dev)
static const struct udevice_id aspeed_mdio_ids[] = {
{ .compatible = "aspeed,ast2600-mdio" },
{ .compatible = "aspeed,ast2700-mdio" },
{ }
};
+74 -15
View File
@@ -26,6 +26,7 @@
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/printk.h>
#include <linux/bitfield.h>
#include "ftgmac100.h"
@@ -57,6 +58,15 @@
enum ftgmac100_model {
FTGMAC100_MODEL_FARADAY,
FTGMAC100_MODEL_ASPEED,
FTGMAC100_MODEL_ASPEED_AST2700,
};
union ftgmac100_dma_addr {
dma_addr_t addr;
struct {
u32 lo;
u32 hi;
};
};
/**
@@ -96,6 +106,8 @@ struct ftgmac100_data {
/* End of RX/TX ring buffer bits. Depend on model */
u32 rxdes0_edorr_mask;
u32 txdes0_edotr_mask;
bool is_ast2700;
};
/*
@@ -222,7 +234,7 @@ static int ftgmac100_phy_init(struct udevice *dev)
struct phy_device *phydev;
int ret;
if (IS_ENABLED(CONFIG_DM_MDIO))
if (IS_ENABLED(CONFIG_DM_MDIO) && priv->phy_mode != PHY_INTERFACE_MODE_NCSI)
phydev = dm_eth_phy_connect(dev);
else
phydev = phy_connect(priv->bus, priv->phy_addr, dev, priv->phy_mode);
@@ -320,8 +332,9 @@ static int ftgmac100_start(struct udevice *dev)
struct eth_pdata *plat = dev_get_plat(dev);
struct ftgmac100_data *priv = dev_get_priv(dev);
struct ftgmac100 *ftgmac100 = priv->iobase;
union ftgmac100_dma_addr dma_addr = {.hi = 0, .lo = 0};
struct phy_device *phydev = priv->phydev;
unsigned int maccr;
unsigned int maccr, dblac, desc_size;
ulong start, end;
int ret;
int i;
@@ -341,6 +354,7 @@ static int ftgmac100_start(struct udevice *dev)
priv->rx_index = 0;
for (i = 0; i < PKTBUFSTX; i++) {
priv->txdes[i].txdes2 = 0;
priv->txdes[i].txdes3 = 0;
priv->txdes[i].txdes0 = 0;
}
@@ -351,7 +365,14 @@ static int ftgmac100_start(struct udevice *dev)
flush_dcache_range(start, end);
for (i = 0; i < PKTBUFSRX; i++) {
priv->rxdes[i].rxdes3 = (unsigned int)net_rx_packets[i];
unsigned int ip_align = 0;
dma_addr.addr = (dma_addr_t)net_rx_packets[i];
priv->rxdes[i].rxdes2 = FIELD_PREP(FTGMAC100_RXDES2_RXBUF_BADR_HI, dma_addr.hi);
/* For IP alignment */
if ((dma_addr.lo & (PKTALIGN - 1)) == 0)
ip_align = 2;
priv->rxdes[i].rxdes3 = dma_addr.lo + ip_align;
priv->rxdes[i].rxdes0 = 0;
}
priv->rxdes[PKTBUFSRX - 1].rxdes0 = priv->rxdes0_edorr_mask;
@@ -361,10 +382,25 @@ static int ftgmac100_start(struct udevice *dev)
flush_dcache_range(start, end);
/* transmit ring */
writel((u32)priv->txdes, &ftgmac100->txr_badr);
dma_addr.addr = (dma_addr_t)priv->txdes;
writel(dma_addr.lo, &ftgmac100->txr_badr);
writel(dma_addr.hi, &ftgmac100->txr_badr_hi);
/* receive ring */
writel((u32)priv->rxdes, &ftgmac100->rxr_badr);
dma_addr.addr = (dma_addr_t)priv->rxdes;
writel(dma_addr.lo, &ftgmac100->rxr_badr);
writel(dma_addr.hi, &ftgmac100->rxr_badr_hi);
/* Configure TX/RX decsriptor size
* This size is calculated based on cache line.
*/
desc_size = ARCH_DMA_MINALIGN / FTGMAC100_DESC_UNIT;
/* The descriptor size is at least 2 descriptor units. */
if (desc_size < 2)
desc_size = 2;
dblac = readl(&ftgmac100->dblac) & ~GENMASK(19, 12);
dblac |= FTGMAC100_DBLAC_RXDES_SIZE(desc_size) | FTGMAC100_DBLAC_TXDES_SIZE(desc_size);
writel(dblac, &ftgmac100->dblac);
/* poll receive descriptor automatically */
writel(FTGMAC100_APTC_RXPOLL_CNT(1), &ftgmac100->aptc);
@@ -382,6 +418,10 @@ static int ftgmac100_start(struct udevice *dev)
FTGMAC100_MACCR_RX_RUNT |
FTGMAC100_MACCR_RX_BROADPKT;
if (priv->is_ast2700 && (priv->phydev->interface == PHY_INTERFACE_MODE_RMII ||
priv->phydev->interface == PHY_INTERFACE_MODE_NCSI))
maccr |= FTGMAC100_MACCR_RMII_ENABLE;
writel(maccr, &ftgmac100->maccr);
ret = phy_startup(phydev);
@@ -410,6 +450,14 @@ static int ftgmac100_free_pkt(struct udevice *dev, uchar *packet, int length)
ulong des_end = des_start +
roundup(sizeof(*curr_des), ARCH_DMA_MINALIGN);
/*
* Make sure there are no stale data in write-back over this area, which
* might get written into the memory while the ftgmac100 also writes
* into the same memory area.
*/
flush_dcache_range((ulong)net_rx_packets[priv->rx_index],
(ulong)net_rx_packets[priv->rx_index] + PKTSIZE_ALIGN);
/* Release buffer to DMA and flush descriptor */
curr_des->rxdes0 &= ~FTGMAC100_RXDES0_RXPKT_RDY;
flush_dcache_range(des_start, des_end);
@@ -431,9 +479,11 @@ static int ftgmac100_recv(struct udevice *dev, int flags, uchar **packetp)
ulong des_start = ((ulong)curr_des) & ~(ARCH_DMA_MINALIGN - 1);
ulong des_end = des_start +
roundup(sizeof(*curr_des), ARCH_DMA_MINALIGN);
ulong data_start = curr_des->rxdes3;
union ftgmac100_dma_addr data_start = { .lo = 0, .hi = 0 };
ulong data_end;
data_start.hi = FIELD_GET(FTGMAC100_RXDES2_RXBUF_BADR_HI, curr_des->rxdes2);
data_start.lo = curr_des->rxdes3;
invalidate_dcache_range(des_start, des_end);
if (!(curr_des->rxdes0 & FTGMAC100_RXDES0_RXPKT_RDY))
@@ -453,9 +503,9 @@ static int ftgmac100_recv(struct udevice *dev, int flags, uchar **packetp)
__func__, priv->rx_index, rxlen);
/* Invalidate received data */
data_end = data_start + roundup(rxlen, ARCH_DMA_MINALIGN);
invalidate_dcache_range(data_start, data_end);
*packetp = (uchar *)data_start;
data_end = data_start.addr + roundup(rxlen, ARCH_DMA_MINALIGN);
invalidate_dcache_range(data_start.addr, data_end);
*packetp = (uchar *)data_start.addr;
return rxlen;
}
@@ -481,6 +531,7 @@ static int ftgmac100_send(struct udevice *dev, void *packet, int length)
struct ftgmac100_data *priv = dev_get_priv(dev);
struct ftgmac100 *ftgmac100 = priv->iobase;
struct ftgmac100_txdes *curr_des = &priv->txdes[priv->tx_index];
union ftgmac100_dma_addr dma_addr;
ulong des_start = ((ulong)curr_des) & ~(ARCH_DMA_MINALIGN - 1);
ulong des_end = des_start +
roundup(sizeof(*curr_des), ARCH_DMA_MINALIGN);
@@ -499,10 +550,12 @@ static int ftgmac100_send(struct udevice *dev, void *packet, int length)
length = (length < ETH_ZLEN) ? ETH_ZLEN : length;
curr_des->txdes3 = (unsigned int)packet;
dma_addr.addr = (dma_addr_t)packet;
curr_des->txdes2 = FIELD_PREP(FTGMAC100_TXDES2_TXBUF_BADR_HI, dma_addr.hi);
curr_des->txdes3 = dma_addr.lo;
/* Flush data to be sent */
data_start = curr_des->txdes3;
data_start = (ulong)dma_addr.addr;
data_end = data_start + roundup(length, ARCH_DMA_MINALIGN);
flush_dcache_range(data_start, data_end);
@@ -565,6 +618,11 @@ static int ftgmac100_of_to_plat(struct udevice *dev)
if (dev_get_driver_data(dev) == FTGMAC100_MODEL_ASPEED) {
priv->rxdes0_edorr_mask = BIT(30);
priv->txdes0_edotr_mask = BIT(30);
priv->is_ast2700 = false;
} else if (dev_get_driver_data(dev) == FTGMAC100_MODEL_ASPEED_AST2700) {
priv->rxdes0_edorr_mask = BIT(30);
priv->txdes0_edotr_mask = BIT(30);
priv->is_ast2700 = true;
} else {
priv->rxdes0_edorr_mask = BIT(15);
priv->txdes0_edotr_mask = BIT(15);
@@ -655,10 +713,11 @@ static const struct eth_ops ftgmac100_ops = {
};
static const struct udevice_id ftgmac100_ids[] = {
{ .compatible = "faraday,ftgmac100", .data = FTGMAC100_MODEL_FARADAY },
{ .compatible = "aspeed,ast2500-mac", .data = FTGMAC100_MODEL_ASPEED },
{ .compatible = "aspeed,ast2600-mac", .data = FTGMAC100_MODEL_ASPEED },
{ }
{ .compatible = "faraday,ftgmac100", .data = FTGMAC100_MODEL_FARADAY },
{ .compatible = "aspeed,ast2500-mac", .data = FTGMAC100_MODEL_ASPEED },
{ .compatible = "aspeed,ast2600-mac", .data = FTGMAC100_MODEL_ASPEED },
{ .compatible = "aspeed,ast2700-mac", .data = FTGMAC100_MODEL_ASPEED_AST2700 },
{}
};
U_BOOT_DRIVER(ftgmac100) = {
+15 -2
View File
@@ -66,6 +66,13 @@ struct ftgmac100 {
unsigned int rx_runt; /* 0xc0 */
unsigned int rx_crcer_ftl; /* 0xc4 */
unsigned int rx_col_lost; /* 0xc8 */
unsigned int reserved[43]; /* 0xcc - 0x174 */
unsigned int txr_badr_lo; /* 0x178, defined in ast2700 */
unsigned int txr_badr_hi; /* 0x17c, defined in ast2700 */
unsigned int hptxr_badr_lo; /* 0x180, defined in ast2700 */
unsigned int hptxr_badr_hi; /* 0x184, defined in ast2700 */
unsigned int rxr_badr_lo; /* 0x188, defined in ast2700 */
unsigned int rxr_badr_hi; /* 0x18c, defined in ast2700 */
};
/*
@@ -111,6 +118,7 @@ struct ftgmac100 {
#define FTGMAC100_DBLAC_TXBURST_SIZE(x) (((x) & 0x3) << 10)
#define FTGMAC100_DBLAC_RXDES_SIZE(x) (((x) & 0xf) << 12)
#define FTGMAC100_DBLAC_TXDES_SIZE(x) (((x) & 0xf) << 16)
#define FTGMAC100_DESC_UNIT 8
#define FTGMAC100_DBLAC_IFG_CNT(x) (((x) & 0x7) << 20)
#define FTGMAC100_DBLAC_IFG_INC BIT(23)
@@ -157,6 +165,7 @@ struct ftgmac100 {
#define FTGMAC100_MACCR_RX_BROADPKT BIT(17)
#define FTGMAC100_MACCR_DISCARD_CRCERR BIT(18)
#define FTGMAC100_MACCR_FAST_MODE BIT(19)
#define FTGMAC100_MACCR_RMII_ENABLE BIT(20) /* defined in ast2700 */
#define FTGMAC100_MACCR_SW_RST BIT(31)
/*
@@ -183,7 +192,7 @@ struct ftgmac100_txdes {
unsigned int txdes1;
unsigned int txdes2; /* not used by HW */
unsigned int txdes3; /* TXBUF_BADR */
} __aligned(16);
} __aligned(ARCH_DMA_MINALIGN);
#define FTGMAC100_TXDES0_TXBUF_SIZE(x) ((x) & 0x3fff)
#define FTGMAC100_TXDES0_EDOTR BIT(15)
@@ -201,6 +210,8 @@ struct ftgmac100_txdes {
#define FTGMAC100_TXDES1_TX2FIC BIT(30)
#define FTGMAC100_TXDES1_TXIC BIT(31)
#define FTGMAC100_TXDES2_TXBUF_BADR_HI GENMASK(18, 16)
/*
* Receive descriptor, aligned to 16 bytes
*/
@@ -209,7 +220,7 @@ struct ftgmac100_rxdes {
unsigned int rxdes1;
unsigned int rxdes2; /* not used by HW */
unsigned int rxdes3; /* RXBUF_BADR */
} __aligned(16);
} __aligned(ARCH_DMA_MINALIGN);
#define FTGMAC100_RXDES0_VDBC(x) ((x) & 0x3fff)
#define FTGMAC100_RXDES0_EDORR BIT(15)
@@ -240,4 +251,6 @@ struct ftgmac100_rxdes {
#define FTGMAC100_RXDES1_UDP_CHKSUM_ERR BIT(26)
#define FTGMAC100_RXDES1_IP_CHKSUM_ERR BIT(27)
#define FTGMAC100_RXDES2_RXBUF_BADR_HI GENMASK(18, 16)
#endif /* __FTGMAC100_H */
+1 -1
View File
@@ -14,7 +14,7 @@ obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/
obj-$(CONFIG_K3_AM654_DDRSS) += k3-am654-ddrss.o
obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/
obj-$(CONFIG_ARCH_ASPEED) += aspeed/
obj-$(CONFIG_ASPEED_RAM) += aspeed/
obj-$(CONFIG_K3_DDRSS) += k3-ddrss/
obj-$(CONFIG_IMXRT_SDRAM) += imxrt_sdram.o
+23 -4
View File
@@ -1,6 +1,7 @@
menuconfig ASPEED_RAM
bool "ASPEED SDRAM configuration"
depends on RAM && ARCH_ASPEED
depends on RAM
depends on ARCH_ASPEED || TARGET_ASPEED_AST2700_IBEX
default ARCH_ASPEED
help
Configuration options for DDR SDRAM on ASPEED systems.
@@ -8,8 +9,6 @@ menuconfig ASPEED_RAM
RAM initialisation is always built in for the platform. This menu
allows customisation of the configuration used.
if ASPEED_RAM
config ASPEED_DDR4_DUALX8
bool "Enable Dual X8 DDR4 die"
depends on ASPEED_RAM
@@ -74,4 +73,24 @@ config ASPEED_DDR4_1600
select DDR4 target data rate at 1600M
endchoice
endif # End of ASPEED_RAM
choice
prompt "AST2700 DDR target date rate"
default ASPEED_DDR_3200
depends on ASPEED_RAM
depends on TARGET_ASPEED_AST2700_IBEX
config ASPEED_DDR_1600
bool "1600 Mbps"
help
select DDR target data rate at 1600M
config ASPEED_DDR_2400
bool "2400 Mbps"
help
select DDR target data rate at 2400M
config ASPEED_DDR_3200
bool "3200 Mbps"
help
select DDR target data rate at 3200M
endchoice
+1
View File
@@ -2,3 +2,4 @@
#
obj-$(CONFIG_ASPEED_AST2500) += sdram_ast2500.o
obj-$(CONFIG_ASPEED_AST2600) += sdram_ast2600.o
obj-$(CONFIG_TARGET_ASPEED_AST2700_IBEX) += sdram_ast2700.o
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+6
View File
@@ -106,6 +106,12 @@ config AST_TIMER
This is mostly because they all share several registers which
makes it difficult to completely separate them.
config AST_IBEX_TIMER
bool "Aspeed ast2700 Ibex timer"
depends on TIMER
help
Select this to enable a timer support for the Ibex RV32-based MCUs in AST2700.
config ATCPIT100_TIMER
bool "ATCPIT100 timer support"
depends on TIMER
+1
View File
@@ -9,6 +9,7 @@ obj-$(CONFIG_$(SPL_)ANDES_PLMT_TIMER) += andes_plmt_timer.o
obj-$(CONFIG_ARC_TIMER) += arc_timer.o
obj-$(CONFIG_ARM_TWD_TIMER) += arm_twd_timer.o
obj-$(CONFIG_AST_TIMER) += ast_timer.o
obj-$(CONFIG_AST_IBEX_TIMER) += ast_ibex_timer.o
obj-$(CONFIG_ATCPIT100_TIMER) += atcpit100_timer.o
obj-$(CONFIG_$(SPL_)ATMEL_PIT_TIMER) += atmel_pit_timer.o
obj-$(CONFIG_$(SPL_)ATMEL_TCB_TIMER) += atmel_tcb_timer.o
+45
View File
@@ -0,0 +1,45 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (c) 2024 Aspeed Technology Inc.
*/
#include <asm/csr.h>
#include <asm/io.h>
#include <dm.h>
#include <errno.h>
#include <timer.h>
#define CSR_MCYCLE 0xb00
#define CSR_MCYCLEH 0xb80
static u64 ast_ibex_timer_get_count(struct udevice *dev)
{
uint32_t cnt_l, cnt_h;
cnt_l = csr_read(CSR_MCYCLE);
cnt_h = csr_read(CSR_MCYCLEH);
return ((uint64_t)cnt_h << 32) | cnt_l;
}
static int ast_ibex_timer_probe(struct udevice *dev)
{
return 0;
}
static const struct timer_ops ast_ibex_timer_ops = {
.get_count = ast_ibex_timer_get_count,
};
static const struct udevice_id ast_ibex_timer_ids[] = {
{ .compatible = "aspeed,ast2700-ibex-timer" },
{ }
};
U_BOOT_DRIVER(ast_ibex_timer) = {
.name = "ast_ibex_timer",
.id = UCLASS_TIMER,
.of_match = ast_ibex_timer_ids,
.probe = ast_ibex_timer_probe,
.ops = &ast_ibex_timer_ops,
};
+12
View File
@@ -0,0 +1,12 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Copyright (c) Aspeed Technology Inc.
*/
#ifndef __CONFIG_H
#define __CONFIG_H
#define CFG_SYS_UBOOT_BASE CONFIG_TEXT_BASE
#define CFG_SYS_SDRAM_BASE 0x80000000
#endif /* __CONFIG_H */
+176
View File
@@ -0,0 +1,176 @@
/* SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause */
/*
* Copyright (C) 2023 Sophgo Ltd.
*/
#ifndef __DT_BINDINGS_SOPHGO_CV1800_CLK_H__
#define __DT_BINDINGS_SOPHGO_CV1800_CLK_H__
#define CLK_MPLL 0
#define CLK_TPLL 1
#define CLK_FPLL 2
#define CLK_MIPIMPLL 3
#define CLK_A0PLL 4
#define CLK_DISPPLL 5
#define CLK_CAM0PLL 6
#define CLK_CAM1PLL 7
#define CLK_MIPIMPLL_D3 8
#define CLK_CAM0PLL_D2 9
#define CLK_CAM0PLL_D3 10
#define CLK_TPU 11
#define CLK_TPU_FAB 12
#define CLK_AHB_ROM 13
#define CLK_DDR_AXI_REG 14
#define CLK_RTC_25M 15
#define CLK_SRC_RTC_SYS_0 16
#define CLK_TEMPSEN 17
#define CLK_SARADC 18
#define CLK_EFUSE 19
#define CLK_APB_EFUSE 20
#define CLK_DEBUG 21
#define CLK_AP_DEBUG 22
#define CLK_XTAL_MISC 23
#define CLK_AXI4_EMMC 24
#define CLK_EMMC 25
#define CLK_EMMC_100K 26
#define CLK_AXI4_SD0 27
#define CLK_SD0 28
#define CLK_SD0_100K 29
#define CLK_AXI4_SD1 30
#define CLK_SD1 31
#define CLK_SD1_100K 32
#define CLK_SPI_NAND 33
#define CLK_ETH0_500M 34
#define CLK_AXI4_ETH0 35
#define CLK_ETH1_500M 36
#define CLK_AXI4_ETH1 37
#define CLK_APB_GPIO 38
#define CLK_APB_GPIO_INTR 39
#define CLK_GPIO_DB 40
#define CLK_AHB_SF 41
#define CLK_AHB_SF1 42
#define CLK_A24M 43
#define CLK_AUDSRC 44
#define CLK_APB_AUDSRC 45
#define CLK_SDMA_AXI 46
#define CLK_SDMA_AUD0 47
#define CLK_SDMA_AUD1 48
#define CLK_SDMA_AUD2 49
#define CLK_SDMA_AUD3 50
#define CLK_I2C 51
#define CLK_APB_I2C 52
#define CLK_APB_I2C0 53
#define CLK_APB_I2C1 54
#define CLK_APB_I2C2 55
#define CLK_APB_I2C3 56
#define CLK_APB_I2C4 57
#define CLK_APB_WDT 58
#define CLK_PWM_SRC 59
#define CLK_PWM 60
#define CLK_SPI 61
#define CLK_APB_SPI0 62
#define CLK_APB_SPI1 63
#define CLK_APB_SPI2 64
#define CLK_APB_SPI3 65
#define CLK_1M 66
#define CLK_CAM0_200 67
#define CLK_PM 68
#define CLK_TIMER0 69
#define CLK_TIMER1 70
#define CLK_TIMER2 71
#define CLK_TIMER3 72
#define CLK_TIMER4 73
#define CLK_TIMER5 74
#define CLK_TIMER6 75
#define CLK_TIMER7 76
#define CLK_UART0 77
#define CLK_APB_UART0 78
#define CLK_UART1 79
#define CLK_APB_UART1 80
#define CLK_UART2 81
#define CLK_APB_UART2 82
#define CLK_UART3 83
#define CLK_APB_UART3 84
#define CLK_UART4 85
#define CLK_APB_UART4 86
#define CLK_APB_I2S0 87
#define CLK_APB_I2S1 88
#define CLK_APB_I2S2 89
#define CLK_APB_I2S3 90
#define CLK_AXI4_USB 91
#define CLK_APB_USB 92
#define CLK_USB_125M 93
#define CLK_USB_33K 94
#define CLK_USB_12M 95
#define CLK_AXI4 96
#define CLK_AXI6 97
#define CLK_DSI_ESC 98
#define CLK_AXI_VIP 99
#define CLK_SRC_VIP_SYS_0 100
#define CLK_SRC_VIP_SYS_1 101
#define CLK_SRC_VIP_SYS_2 102
#define CLK_SRC_VIP_SYS_3 103
#define CLK_SRC_VIP_SYS_4 104
#define CLK_CSI_BE_VIP 105
#define CLK_CSI_MAC0_VIP 106
#define CLK_CSI_MAC1_VIP 107
#define CLK_CSI_MAC2_VIP 108
#define CLK_CSI0_RX_VIP 109
#define CLK_CSI1_RX_VIP 110
#define CLK_ISP_TOP_VIP 111
#define CLK_IMG_D_VIP 112
#define CLK_IMG_V_VIP 113
#define CLK_SC_TOP_VIP 114
#define CLK_SC_D_VIP 115
#define CLK_SC_V1_VIP 116
#define CLK_SC_V2_VIP 117
#define CLK_SC_V3_VIP 118
#define CLK_DWA_VIP 119
#define CLK_BT_VIP 120
#define CLK_DISP_VIP 121
#define CLK_DSI_MAC_VIP 122
#define CLK_LVDS0_VIP 123
#define CLK_LVDS1_VIP 124
#define CLK_PAD_VI_VIP 125
#define CLK_PAD_VI1_VIP 126
#define CLK_PAD_VI2_VIP 127
#define CLK_CFG_REG_VIP 128
#define CLK_VIP_IP0 129
#define CLK_VIP_IP1 130
#define CLK_VIP_IP2 131
#define CLK_VIP_IP3 132
#define CLK_IVE_VIP 133
#define CLK_RAW_VIP 134
#define CLK_OSDC_VIP 135
#define CLK_CAM0_VIP 136
#define CLK_AXI_VIDEO_CODEC 137
#define CLK_VC_SRC0 138
#define CLK_VC_SRC1 139
#define CLK_VC_SRC2 140
#define CLK_H264C 141
#define CLK_APB_H264C 142
#define CLK_H265C 143
#define CLK_APB_H265C 144
#define CLK_JPEG 145
#define CLK_APB_JPEG 146
#define CLK_CAM0 147
#define CLK_CAM1 148
#define CLK_WGN 149
#define CLK_WGN0 150
#define CLK_WGN1 151
#define CLK_WGN2 152
#define CLK_KEYSCAN 153
#define CLK_CFG_REG_VC 154
#define CLK_C906_0 155
#define CLK_C906_1 156
#define CLK_A53 157
#define CLK_CPU_AXI0 158
#define CLK_CPU_GIC 159
#define CLK_XTAL_AP 160
// Only for CV181x
#define CLK_DISP_SRC_VIP 161
#endif /* __DT_BINDINGS_SOPHGO_CV1800_CLK_H__ */