mirror of
https://github.com/u-boot/u-boot.git
synced 2024-11-30 08:03:32 +08:00
CI: https://source.denx.de/u-boot/custodians/u-boot-riscv/-/pipelines/20596 - RISC-V: cmd: Add SBI implementation ID and extension ID - Board: Rename spl_soc_init to spl_dram_init - Board: milkv_duo: Add SPI NOR flash, Ethernet, Sysreset support
This commit is contained in:
commit
62825d48c4
@ -1,6 +1,7 @@
|
||||
config RISCV_NDS
|
||||
bool
|
||||
select ARCH_EARLY_INIT_R
|
||||
select SYS_CACHE_SHIFT_6
|
||||
imply CPU
|
||||
imply CPU_RISCV
|
||||
imply RISCV_TIMER if (RISCV_SMODE || SPL_RISCV_SMODE)
|
||||
|
@ -7,7 +7,7 @@
|
||||
#include <dm.h>
|
||||
#include <log.h>
|
||||
|
||||
int spl_soc_init(void)
|
||||
int spl_dram_init(void)
|
||||
{
|
||||
int ret;
|
||||
struct udevice *dev;
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
#define CSR_U74_FEATURE_DISABLE 0x7c1
|
||||
|
||||
int spl_soc_init(void)
|
||||
int spl_dram_init(void)
|
||||
{
|
||||
int ret;
|
||||
struct udevice *dev;
|
||||
|
@ -28,7 +28,7 @@ static bool check_ddr_size(phys_size_t size)
|
||||
}
|
||||
}
|
||||
|
||||
int spl_soc_init(void)
|
||||
int spl_dram_init(void)
|
||||
{
|
||||
int ret;
|
||||
struct udevice *dev;
|
||||
|
@ -29,6 +29,11 @@
|
||||
};
|
||||
};
|
||||
|
||||
ðernet0 {
|
||||
status = "okay";
|
||||
phy-mode = "rmii";
|
||||
};
|
||||
|
||||
&osc {
|
||||
clock-frequency = <25000000>;
|
||||
};
|
||||
@ -41,6 +46,19 @@
|
||||
no-sdio;
|
||||
};
|
||||
|
||||
&spif {
|
||||
status = "okay";
|
||||
|
||||
spiflash@0 {
|
||||
compatible = "jedec,spi-nor";
|
||||
reg = <0>;
|
||||
spi-max-frequency = <75000000>;
|
||||
spi-tx-bus-width = <4>;
|
||||
spi-rx-bus-width = <4>;
|
||||
m25p,fast-read;
|
||||
};
|
||||
};
|
||||
|
||||
&uart0 {
|
||||
status = "okay";
|
||||
};
|
||||
|
@ -52,6 +52,27 @@
|
||||
#clock-cells = <0>;
|
||||
};
|
||||
|
||||
eth_csrclk: eth-csrclk {
|
||||
compatible = "fixed-clock";
|
||||
clock-frequency = <250000000>;
|
||||
clock-output-names = "eth_csrclk";
|
||||
#clock-cells = <0x0>;
|
||||
};
|
||||
|
||||
eth_ptpclk: eth-ptpclk {
|
||||
compatible = "fixed-clock";
|
||||
clock-frequency = <50000000>;
|
||||
clock-output-names = "eth_ptpclk";
|
||||
#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>;
|
||||
@ -138,6 +159,15 @@
|
||||
};
|
||||
};
|
||||
|
||||
ethernet0: ethernet@4070000 {
|
||||
compatible = "sophgo,cv1800b-dwmac";
|
||||
reg = <0x04070000 0x10000>;
|
||||
interrupts = <31 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <ð_csrclk>, <ð_ptpclk>;
|
||||
clock-names = "stmmaceth", "ptp_ref";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
uart0: serial@4140000 {
|
||||
compatible = "snps,dw-apb-uart";
|
||||
reg = <0x04140000 0x100>;
|
||||
@ -197,6 +227,16 @@
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
spif: spi-nor@10000000 {
|
||||
compatible = "sophgo,cv1800b-spif";
|
||||
reg = <0x10000000 0x10000000>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
clocks = <&spif_clk>;
|
||||
interrupts = <95 IRQ_TYPE_LEVEL_HIGH>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
plic: interrupt-controller@70000000 {
|
||||
reg = <0x70000000 0x4000000>;
|
||||
interrupts-extended = <&cpu0_intc 11>, <&cpu0_intc 9>;
|
||||
|
@ -9,6 +9,6 @@
|
||||
#ifndef _SPL_SIFIVE_H
|
||||
#define _SPL_SIFIVE_H
|
||||
|
||||
int spl_soc_init(void);
|
||||
int spl_dram_init(void);
|
||||
|
||||
#endif /* _SPL_SIFIVE_H */
|
||||
|
@ -9,6 +9,6 @@
|
||||
#ifndef _SPL_SIFIVE_H
|
||||
#define _SPL_SIFIVE_H
|
||||
|
||||
int spl_soc_init(void);
|
||||
int spl_dram_init(void);
|
||||
|
||||
#endif /* _SPL_SIFIVE_H */
|
||||
|
@ -7,6 +7,6 @@
|
||||
#ifndef _SPL_STARFIVE_H
|
||||
#define _SPL_STARFIVE_H
|
||||
|
||||
int spl_soc_init(void);
|
||||
int spl_dram_init(void);
|
||||
|
||||
#endif /* _SPL_STARFIVE_H */
|
||||
|
@ -34,6 +34,7 @@ enum sbi_ext_id {
|
||||
SBI_EXT_NACL = 0x4E41434C,
|
||||
SBI_EXT_STA = 0x535441,
|
||||
SBI_EXT_DBTR = 0x44425452,
|
||||
SBI_EXT_SSE = 0x535345,
|
||||
};
|
||||
|
||||
enum sbi_ext_base_fid {
|
||||
|
@ -27,9 +27,9 @@ int spl_board_init_f(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = spl_soc_init();
|
||||
ret = spl_dram_init();
|
||||
if (ret) {
|
||||
debug("FU540 SPL init failed: %d\n", ret);
|
||||
debug("FU540 DRAM init failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -134,9 +134,9 @@ int spl_board_init_f(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = spl_soc_init();
|
||||
ret = spl_dram_init();
|
||||
if (ret) {
|
||||
debug("HiFive Unmatched FU740 SPL init failed: %d\n", ret);
|
||||
debug("HiFive Unmatched FU740 DRAM init failed: %d\n", ret);
|
||||
goto end;
|
||||
}
|
||||
|
||||
|
@ -2,4 +2,5 @@
|
||||
#
|
||||
# Copyright (c) 2024, Kongyang Liu <seashell11234455@gmail.com>
|
||||
|
||||
obj-y := board.o
|
||||
obj-y += board.o
|
||||
obj-$(CONFIG_NET) += ethernet.o
|
||||
|
@ -3,7 +3,17 @@
|
||||
* Copyright (c) 2024, Kongyang Liu <seashell11234455@gmail.com>
|
||||
*/
|
||||
|
||||
#include <dm/lists.h>
|
||||
|
||||
#include "ethernet.h"
|
||||
|
||||
int board_init(void)
|
||||
{
|
||||
if (IS_ENABLED(CONFIG_SYSRESET_CV1800B))
|
||||
device_bind_driver(gd->dm_root, "cv1800b_sysreset", "sysreset", NULL);
|
||||
|
||||
if (IS_ENABLED(CONFIG_NET))
|
||||
cv1800b_ephy_init();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
79
board/sophgo/milkv_duo/ethernet.c
Normal file
79
board/sophgo/milkv_duo/ethernet.c
Normal file
@ -0,0 +1,79 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (c) 2024, Kongyang Liu <seashell11234455@gmail.com>
|
||||
*/
|
||||
|
||||
#include <linux/io.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/mii.h>
|
||||
|
||||
#define REG_EPHY_TOP_WRAP (u32 *)0x03009800
|
||||
#define REG_EPHY_BASE (u32 *)0x03009000
|
||||
|
||||
#define REG_EPHY_CTL REG_EPHY_TOP_WRAP
|
||||
#define REG_EPHY_APB_RW_SEL REG_EPHY_TOP_WRAP + 1
|
||||
|
||||
/* Page 0 register */
|
||||
#define REG_PHY_ID1 REG_EPHY_BASE + MII_PHYSID1
|
||||
#define REG_PHY_ID2 REG_EPHY_BASE + MII_PHYSID2
|
||||
#define REG_PHY_PAGE_SEL REG_EPHY_BASE + 0x1f
|
||||
|
||||
/* Page 5 register */
|
||||
#define REG_PD_EN_CTL REG_EPHY_BASE + 0x10
|
||||
|
||||
/* REG_EPHY_CTL */
|
||||
#define REG_EPHY_SHUTDOWN BIT(0)
|
||||
#define REG_EPHY_ANA_RST_N BIT(1)
|
||||
#define REG_EPHY_DIG_RST_N BIT(2)
|
||||
#define REG_EPHY_MAIN_RST_N BIT(3)
|
||||
|
||||
/* REG_PD_EN_CTL */
|
||||
#define REG_EN_ETH_TXRT BIT(0)
|
||||
#define REG_EN_ETH_CLK100M BIT(1)
|
||||
#define REG_EN_ETH_CLK125M BIT(2)
|
||||
#define REG_EN_ETH_PLL_LCKDET BIT(3)
|
||||
#define REG_EN_ETH_RXADC BIT(4)
|
||||
#define REG_EN_ETH_RXPGA BIT(5)
|
||||
#define REG_EN_ETH_RXRT BIT(6)
|
||||
#define REG_EN_ETH_TXCROSSOVER BIT(7)
|
||||
#define REG_PD_ETH_PLL BIT(8)
|
||||
#define REG_PD_ETH_TXDAC BIT(9)
|
||||
#define REG_PD_ETH_TXDACBST BIT(10)
|
||||
#define REG_PD_ETH_TXECHO BIT(11)
|
||||
#define REG_PD_ETH_TXDRV_NMOS BIT(12)
|
||||
#define REG_PD_ETH_TXLDO BIT(13)
|
||||
|
||||
void cv1800b_ephy_init(void)
|
||||
{
|
||||
u32 reg;
|
||||
u32 phy_id = 1;
|
||||
|
||||
/* enable direct memory access for phy register */
|
||||
writel(1, REG_EPHY_APB_RW_SEL);
|
||||
|
||||
reg = readl(REG_EPHY_CTL);
|
||||
reg &= ~REG_EPHY_SHUTDOWN;
|
||||
reg |= REG_EPHY_ANA_RST_N | REG_EPHY_DIG_RST_N | REG_EPHY_MAIN_RST_N;
|
||||
writel(reg, REG_EPHY_CTL);
|
||||
|
||||
/* switch to page 5 */
|
||||
writel(5 << 8, REG_PHY_PAGE_SEL);
|
||||
reg = readl(REG_PD_EN_CTL);
|
||||
reg &= ~(REG_PD_ETH_TXLDO | REG_PD_ETH_TXDRV_NMOS | REG_PD_ETH_TXDAC | REG_PD_ETH_PLL);
|
||||
reg |= REG_EN_ETH_TXRT | REG_EN_ETH_CLK100M | REG_EN_ETH_CLK125M
|
||||
| REG_EN_ETH_PLL_LCKDET | REG_EN_ETH_RXADC | REG_EN_ETH_RXPGA | REG_EN_ETH_RXRT;
|
||||
writel(reg, REG_PD_EN_CTL);
|
||||
|
||||
/* switch to page 0 */
|
||||
writel(0 << 8, REG_PHY_PAGE_SEL);
|
||||
/*
|
||||
* As the phy_id in the cv1800b PHY register is initialized to 0, it
|
||||
* is necessary to manually initialize the phy_id to an arbitrary
|
||||
* value so that it could corresponds to the generic PHY driver.
|
||||
*/
|
||||
writel(phy_id >> 16, REG_PHY_ID1);
|
||||
writel(phy_id & 0xffff, REG_PHY_ID2);
|
||||
|
||||
/* switch to MDIO control */
|
||||
writel(0, REG_EPHY_APB_RW_SEL);
|
||||
}
|
11
board/sophgo/milkv_duo/ethernet.h
Normal file
11
board/sophgo/milkv_duo/ethernet.h
Normal file
@ -0,0 +1,11 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright (c) 2024, Kongyang Liu <seashell11234455@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef __CV1800B_ETHERNET_H
|
||||
#define __CV1800B_ETHERNET_H
|
||||
|
||||
void cv1800b_ephy_init(void);
|
||||
|
||||
#endif
|
@ -285,9 +285,9 @@ int spl_board_init_f(void)
|
||||
|
||||
jh7110_jtag_init();
|
||||
|
||||
ret = spl_soc_init();
|
||||
ret = spl_dram_init();
|
||||
if (ret) {
|
||||
debug("JH7110 SPL init failed: %d\n", ret);
|
||||
debug("JH7110 DRAM init failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -29,6 +29,8 @@ static struct sbi_imp implementations[] = {
|
||||
{ 6, "Coffer" },
|
||||
{ 7, "Xen Project" },
|
||||
{ 8, "PolarFire Hart Software Services" },
|
||||
{ 9, "coreboot" },
|
||||
{ 10, "oreboot" },
|
||||
};
|
||||
|
||||
static struct sbi_ext extensions[] = {
|
||||
@ -54,6 +56,7 @@ static struct sbi_ext extensions[] = {
|
||||
{ SBI_EXT_NACL, "Nested Acceleration Extension" },
|
||||
{ SBI_EXT_STA, "Steal-time Accounting Extension" },
|
||||
{ SBI_EXT_DBTR, "Debug Trigger Extension" },
|
||||
{ SBI_EXT_SSE, "Supervisor Software Events" },
|
||||
};
|
||||
|
||||
static int do_sbi(struct cmd_tbl *cmdtp, int flag, int argc,
|
||||
|
@ -19,14 +19,24 @@ CONFIG_HUSH_PARSER=y
|
||||
CONFIG_SYS_PROMPT="milkv_duo# "
|
||||
CONFIG_CMD_MMC=y
|
||||
CONFIG_CMD_PART=y
|
||||
CONFIG_CMD_POWEROFF=y
|
||||
CONFIG_CMD_DHCP=y
|
||||
CONFIG_CMD_PXE=y
|
||||
CONFIG_CMD_FAT=y
|
||||
CONFIG_CMD_FS_GENERIC=y
|
||||
CONFIG_ENV_OVERWRITE=y
|
||||
CONFIG_NET_RANDOM_ETHADDR=y
|
||||
CONFIG_MMC=y
|
||||
CONFIG_MMC_IO_VOLTAGE=y
|
||||
CONFIG_MMC_UHS_SUPPORT=y
|
||||
CONFIG_MMC_SDHCI=y
|
||||
CONFIG_MMC_SDHCI_ADMA=y
|
||||
CONFIG_MMC_SDHCI_CV1800B=y
|
||||
CONFIG_ETH_DESIGNWARE=y
|
||||
CONFIG_SYS_NS16550=y
|
||||
CONFIG_SYS_NS16550_MEM32=y
|
||||
CONFIG_SYSRESET=y
|
||||
CONFIG_SYSRESET_CV1800B=y
|
||||
CONFIG_SPI_FLASH_MACRONIX=y
|
||||
CONFIG_SPI=y
|
||||
CONFIG_CV1800B_SPIF=y
|
||||
|
@ -12,6 +12,8 @@
|
||||
#define MMC_MAX_CLOCK 375000000
|
||||
#define TUNE_MAX_PHCODE 128
|
||||
|
||||
#define PHY_TX_SRC_INVERT BIT(8)
|
||||
|
||||
struct cv1800b_sdhci_plat {
|
||||
struct mmc_config cfg;
|
||||
struct mmc mmc;
|
||||
@ -19,7 +21,7 @@ struct cv1800b_sdhci_plat {
|
||||
|
||||
static void cv1800b_set_tap_delay(struct sdhci_host *host, u16 tap)
|
||||
{
|
||||
sdhci_writel(host, tap << 16, SDHCI_PHY_TX_RX_DLY);
|
||||
sdhci_writel(host, PHY_TX_SRC_INVERT | tap << 16, SDHCI_PHY_TX_RX_DLY);
|
||||
}
|
||||
|
||||
static void cv1800b_sdhci_reset(struct sdhci_host *host, u8 mask)
|
||||
|
@ -871,6 +871,7 @@ static const struct udevice_id designware_eth_ids[] = {
|
||||
{ .compatible = "amlogic,meson6-dwmac" },
|
||||
{ .compatible = "st,stm32-dwmac" },
|
||||
{ .compatible = "snps,arc-dwmac-3.70a" },
|
||||
{ .compatible = "sophgo,cv1800b-dwmac" },
|
||||
{ }
|
||||
};
|
||||
|
||||
|
@ -168,6 +168,14 @@ config CF_SPI
|
||||
Enable the ColdFire SPI driver. This driver can be used on
|
||||
some m68k SoCs.
|
||||
|
||||
config CV1800B_SPIF
|
||||
bool "Sophgo cv1800b SPI Flash Controller driver"
|
||||
depends on SPI_MEM
|
||||
help
|
||||
Enable the Sophgo cv1800b SPI Flash Controller driver. This driver
|
||||
can be used to access the SPI NOR flash on platforms embedding this
|
||||
Sophgo cv1800b IP core.
|
||||
|
||||
config DAVINCI_SPI
|
||||
bool "Davinci & Keystone SPI driver"
|
||||
depends on ARCH_DAVINCI || ARCH_KEYSTONE
|
||||
|
@ -30,6 +30,7 @@ obj-$(CONFIG_BCM63XX_SPI) += bcm63xx_spi.o
|
||||
obj-$(CONFIG_BCMSTB_SPI) += bcmstb_spi.o
|
||||
obj-$(CONFIG_CF_SPI) += cf_spi.o
|
||||
obj-$(CONFIG_CORTINA_SFLASH) += ca_sflash.o
|
||||
obj-$(CONFIG_CV1800B_SPIF) += cv1800b_spif.o
|
||||
obj-$(CONFIG_DAVINCI_SPI) += davinci_spi.o
|
||||
obj-$(CONFIG_DESIGNWARE_SPI) += designware_spi.o
|
||||
obj-$(CONFIG_EXYNOS_SPI) += exynos_spi.o
|
||||
|
321
drivers/spi/cv1800b_spif.c
Normal file
321
drivers/spi/cv1800b_spif.c
Normal file
@ -0,0 +1,321 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (c) 2024, Kongyang Liu <seashell11234455@gmail.com>
|
||||
*/
|
||||
|
||||
#include <clk.h>
|
||||
#include <dm.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <spi-mem.h>
|
||||
#include <spi.h>
|
||||
#include <spi_flash.h>
|
||||
#include <wait_bit.h>
|
||||
|
||||
#define CV1800B_SPI_CTRL_SCK_DIV_MASK GENMASK(10, 0)
|
||||
#define CV1800B_SPI_CTRL_CPHA BIT(12)
|
||||
#define CV1800B_SPI_CTRL_CPOL BIT(13)
|
||||
|
||||
#define CV1800B_SPI_CE_MANUAL BIT(0)
|
||||
#define CV1800B_SPI_CE_MANUAL_EN BIT(1)
|
||||
#define CV1800B_SPI_CE_ENABLE (CV1800B_SPI_CE_MANUAL | \
|
||||
CV1800B_SPI_CE_MANUAL_EN)
|
||||
#define CV1800B_SPI_CE_DISABLE CV1800B_SPI_CE_MANUAL_EN
|
||||
#define CV1800B_SPI_CE_HARDWARE 0
|
||||
|
||||
#define CV1800B_SPI_DLY_CTRL_NEG_SAMPLE BIT(14)
|
||||
|
||||
#define CV1800B_SPI_TRAN_MODE_RX BIT(0)
|
||||
#define CV1800B_SPI_TRAN_MODE_TX BIT(1)
|
||||
#define CV1800B_SPI_TRAN_FAST_MODE BIT(3)
|
||||
#define CV1800B_SPI_TRAN_BUS_WIDTH_1_BIT 0x0
|
||||
#define CV1800B_SPI_TRAN_BUS_WIDTH_2_BIT BIT(4)
|
||||
#define CV1800B_SPI_TRAN_BUS_WIDTH_4_BIT BIT(5)
|
||||
#define CV1800B_SPI_TRAN_ADDR_3_BYTES (3 << 8)
|
||||
#define CV1800B_SPI_TRAN_ADDR_4_BYTES (4 << 8)
|
||||
#define CV1800B_SPI_TRAN_WITH_CMD BIT(11)
|
||||
#define CV1800B_SPI_TRAN_GO_BUSY BIT(15)
|
||||
#define CV1800B_SPI_TRAN_DUMMY_CYC_MASK GENMASK(19, 16)
|
||||
#define CV1800B_SPI_TRAN_DUMMY_CYC_OFFSET 16
|
||||
#define CV1800B_SPI_TRAN_BYTE4_EN BIT(20)
|
||||
#define CV1800B_SPI_TRAN_BYTE4_CMD BIT(21)
|
||||
|
||||
#define CV1800B_SPI_FF_PT_AVAILABLE_MASK GENMASK(3, 0)
|
||||
|
||||
#define CV1800B_SPI_INT_TRAN_DONE BIT(0)
|
||||
#define CV1800B_SPI_INT_RD_FIFO BIT(2)
|
||||
#define CV1800B_SPI_INT_WR_FIFO BIT(3)
|
||||
|
||||
#define CV1800B_FIFO_CAPACITY 8
|
||||
#define CV1800B_DEFAULT_DIV 4
|
||||
|
||||
struct cv1800b_spif_regs {
|
||||
u32 spi_ctrl;
|
||||
u32 ce_ctrl;
|
||||
u32 dly_ctrl;
|
||||
u32 dmmr_ctrl;
|
||||
u32 tran_csr;
|
||||
u32 tran_num;
|
||||
u32 ff_port;
|
||||
u32 reserved0;
|
||||
u32 ff_pt;
|
||||
u32 reserved1;
|
||||
u32 int_sts;
|
||||
u32 int_en;
|
||||
};
|
||||
|
||||
struct cv1800b_spi_priv {
|
||||
struct cv1800b_spif_regs *regs;
|
||||
uint clk_freq;
|
||||
uint mode;
|
||||
int div;
|
||||
};
|
||||
|
||||
static int cv1800b_spi_probe(struct udevice *bus)
|
||||
{
|
||||
struct cv1800b_spi_priv *priv = dev_get_priv(bus);
|
||||
struct clk clkdev;
|
||||
int ret;
|
||||
|
||||
priv->regs = (struct cv1800b_spif_regs *)dev_read_addr_ptr(bus);
|
||||
if (priv->regs == 0)
|
||||
return -EINVAL;
|
||||
|
||||
ret = clk_get_by_index(bus, 0, &clkdev);
|
||||
if (ret)
|
||||
return ret;
|
||||
priv->clk_freq = clk_get_rate(&clkdev);
|
||||
|
||||
/* DMMR mode is enabled by default, disable it */
|
||||
writel(0, &priv->regs->dmmr_ctrl);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void cv1800b_spi_config_dmmr(struct cv1800b_spi_priv *priv, struct spi_nor *flash)
|
||||
{
|
||||
struct cv1800b_spif_regs *regs = priv->regs;
|
||||
u32 read_cmd = flash->read_opcode;
|
||||
u32 val;
|
||||
|
||||
val = CV1800B_SPI_TRAN_MODE_RX | CV1800B_SPI_TRAN_WITH_CMD;
|
||||
|
||||
switch (read_cmd) {
|
||||
case SPINOR_OP_READ_4B:
|
||||
case SPINOR_OP_READ_FAST_4B:
|
||||
case SPINOR_OP_READ_1_1_2_4B:
|
||||
case SPINOR_OP_READ_1_1_4_4B:
|
||||
val |= CV1800B_SPI_TRAN_ADDR_4_BYTES |
|
||||
CV1800B_SPI_TRAN_BYTE4_EN | CV1800B_SPI_TRAN_BYTE4_CMD;
|
||||
break;
|
||||
case SPINOR_OP_READ:
|
||||
case SPINOR_OP_READ_FAST:
|
||||
case SPINOR_OP_READ_1_1_2:
|
||||
case SPINOR_OP_READ_1_1_4:
|
||||
val |= CV1800B_SPI_TRAN_ADDR_3_BYTES;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (read_cmd) {
|
||||
case SPINOR_OP_READ_FAST:
|
||||
case SPINOR_OP_READ_FAST_4B:
|
||||
val |= CV1800B_SPI_TRAN_FAST_MODE;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (read_cmd) {
|
||||
case SPINOR_OP_READ_1_1_2:
|
||||
case SPINOR_OP_READ_1_1_2_4B:
|
||||
val |= CV1800B_SPI_TRAN_BUS_WIDTH_2_BIT;
|
||||
break;
|
||||
case SPINOR_OP_READ_1_1_4:
|
||||
case SPINOR_OP_READ_1_1_4_4B:
|
||||
val |= CV1800B_SPI_TRAN_BUS_WIDTH_4_BIT;
|
||||
break;
|
||||
}
|
||||
|
||||
val |= (flash->read_dummy & CV1800B_SPI_TRAN_DUMMY_CYC_MASK)
|
||||
<< CV1800B_SPI_TRAN_DUMMY_CYC_OFFSET;
|
||||
writel(val, ®s->tran_csr);
|
||||
}
|
||||
|
||||
static void cv1800b_set_clk_div(struct cv1800b_spi_priv *priv, u32 div)
|
||||
{
|
||||
struct cv1800b_spif_regs *regs = priv->regs;
|
||||
u32 neg_sample = 0;
|
||||
|
||||
clrsetbits_le32(®s->spi_ctrl, CV1800B_SPI_CTRL_SCK_DIV_MASK, div);
|
||||
|
||||
if (div < CV1800B_DEFAULT_DIV)
|
||||
neg_sample = CV1800B_SPI_DLY_CTRL_NEG_SAMPLE;
|
||||
clrsetbits_le32(®s->dly_ctrl, CV1800B_SPI_DLY_CTRL_NEG_SAMPLE, neg_sample);
|
||||
}
|
||||
|
||||
static int cv1800b_spi_transfer(struct cv1800b_spi_priv *priv,
|
||||
u8 *din, const u8 *dout, uint len, ulong flags)
|
||||
{
|
||||
struct cv1800b_spif_regs *regs = priv->regs;
|
||||
u32 tran_csr;
|
||||
u32 xfer_size, off;
|
||||
u32 fifo_cnt;
|
||||
u32 interrupt_mask;
|
||||
|
||||
if (din) {
|
||||
/* Slow down on receiving */
|
||||
cv1800b_set_clk_div(priv, CV1800B_DEFAULT_DIV);
|
||||
interrupt_mask = CV1800B_SPI_INT_RD_FIFO;
|
||||
} else {
|
||||
interrupt_mask = CV1800B_SPI_INT_WR_FIFO;
|
||||
}
|
||||
|
||||
writel(0, ®s->ff_pt);
|
||||
writel(len, ®s->tran_num);
|
||||
|
||||
tran_csr = CV1800B_SPI_TRAN_GO_BUSY;
|
||||
if (din) {
|
||||
tran_csr |= CV1800B_SPI_TRAN_MODE_RX;
|
||||
} else {
|
||||
tran_csr |= CV1800B_SPI_TRAN_MODE_TX;
|
||||
if (!(flags & SPI_XFER_BEGIN) && (priv->mode & SPI_TX_QUAD))
|
||||
tran_csr |= CV1800B_SPI_TRAN_BUS_WIDTH_4_BIT;
|
||||
}
|
||||
writel(tran_csr, ®s->tran_csr);
|
||||
|
||||
wait_for_bit_le32(®s->int_sts, interrupt_mask, true, 3000, false);
|
||||
|
||||
off = 0;
|
||||
while (off < len) {
|
||||
xfer_size = min_t(u32, len - off, CV1800B_FIFO_CAPACITY);
|
||||
|
||||
fifo_cnt = readl(®s->ff_pt) & CV1800B_SPI_FF_PT_AVAILABLE_MASK;
|
||||
if (din)
|
||||
xfer_size = min(xfer_size, fifo_cnt);
|
||||
else
|
||||
xfer_size = min(xfer_size, CV1800B_FIFO_CAPACITY - fifo_cnt);
|
||||
|
||||
while (xfer_size--) {
|
||||
if (din)
|
||||
din[off++] = readb(®s->ff_port);
|
||||
else
|
||||
writeb(dout[off++], ®s->ff_port);
|
||||
}
|
||||
}
|
||||
|
||||
wait_for_bit_le32(®s->int_sts, CV1800B_SPI_INT_TRAN_DONE, true, 3000, false);
|
||||
writel(0, ®s->ff_pt);
|
||||
clrbits_le32(®s->int_sts, CV1800B_SPI_INT_TRAN_DONE | interrupt_mask);
|
||||
|
||||
if (din)
|
||||
cv1800b_set_clk_div(priv, priv->div);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cv1800b_spi_xfer(struct udevice *dev, unsigned int bitlen,
|
||||
const void *dout, void *din, unsigned long flags)
|
||||
{
|
||||
struct udevice *bus = dev->parent;
|
||||
struct cv1800b_spi_priv *priv = dev_get_priv(bus);
|
||||
struct cv1800b_spif_regs *regs = priv->regs;
|
||||
|
||||
if (bitlen == 0)
|
||||
goto out;
|
||||
|
||||
if (bitlen % 8) {
|
||||
flags |= SPI_XFER_END;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (flags & SPI_XFER_BEGIN)
|
||||
writel(CV1800B_SPI_CE_DISABLE, ®s->ce_ctrl);
|
||||
|
||||
if (din || dout)
|
||||
cv1800b_spi_transfer(priv, din, dout, bitlen / 8, flags);
|
||||
|
||||
out:
|
||||
if (flags & SPI_XFER_END)
|
||||
writel(CV1800B_SPI_CE_ENABLE, ®s->ce_ctrl);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cv1800b_spi_set_speed(struct udevice *bus, uint speed)
|
||||
{
|
||||
struct cv1800b_spi_priv *priv = dev_get_priv(bus);
|
||||
|
||||
priv->div = DIV_ROUND_CLOSEST(priv->clk_freq, speed * 2) - 1;
|
||||
if (priv->div <= 0)
|
||||
priv->div = CV1800B_DEFAULT_DIV;
|
||||
|
||||
cv1800b_set_clk_div(priv, priv->div);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cv1800b_spi_set_mode(struct udevice *bus, uint mode)
|
||||
{
|
||||
struct cv1800b_spi_priv *priv = dev_get_priv(bus);
|
||||
struct cv1800b_spif_regs *regs = priv->regs;
|
||||
u32 val = 0;
|
||||
|
||||
if (mode & SPI_CPHA)
|
||||
val |= CV1800B_SPI_CTRL_CPHA;
|
||||
if (mode & SPI_CPOL)
|
||||
val |= CV1800B_SPI_CTRL_CPOL;
|
||||
clrsetbits_le32(®s->spi_ctrl, CV1800B_SPI_CTRL_CPHA | CV1800B_SPI_CTRL_CPOL, val);
|
||||
|
||||
priv->mode = mode;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cv1800b_spi_exec_op(struct spi_slave *slave, const struct spi_mem_op *op)
|
||||
{
|
||||
struct udevice *bus = slave->dev->parent;
|
||||
struct cv1800b_spi_priv *priv = dev_get_priv(bus);
|
||||
struct cv1800b_spif_regs *regs = priv->regs;
|
||||
struct spi_nor *flash = dev_get_uclass_priv(slave->dev);
|
||||
u32 old_tran_csr;
|
||||
|
||||
if (!(op->data.nbytes > 0 && op->data.dir == SPI_MEM_DATA_IN) ||
|
||||
!(op->addr.nbytes > 0 && op->addr.nbytes <= 4))
|
||||
return -ENOTSUPP;
|
||||
|
||||
old_tran_csr = readl(®s->tran_csr);
|
||||
writel(CV1800B_SPI_CE_HARDWARE, ®s->ce_ctrl);
|
||||
|
||||
cv1800b_spi_config_dmmr(priv, flash);
|
||||
|
||||
writel(1, ®s->dmmr_ctrl);
|
||||
memcpy(op->data.buf.in, (void *)priv->regs + op->addr.val, op->data.nbytes);
|
||||
writel(0, ®s->dmmr_ctrl);
|
||||
|
||||
writel(CV1800B_SPI_CE_ENABLE, ®s->ce_ctrl);
|
||||
writel(old_tran_csr, ®s->tran_csr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct spi_controller_mem_ops cv1800b_spi_mem_ops = {
|
||||
.exec_op = cv1800b_spi_exec_op,
|
||||
};
|
||||
|
||||
static const struct dm_spi_ops cv1800b_spi_ops = {
|
||||
.xfer = cv1800b_spi_xfer,
|
||||
.mem_ops = &cv1800b_spi_mem_ops,
|
||||
.set_speed = cv1800b_spi_set_speed,
|
||||
.set_mode = cv1800b_spi_set_mode,
|
||||
};
|
||||
|
||||
static const struct udevice_id cv1800b_spi_ids[] = {
|
||||
{ .compatible = "sophgo,cv1800b-spif" },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(cv1800b_spi) = {
|
||||
.name = "cv1800b_spif",
|
||||
.id = UCLASS_SPI,
|
||||
.of_match = cv1800b_spi_ids,
|
||||
.ops = &cv1800b_spi_ops,
|
||||
.priv_auto = sizeof(struct cv1800b_spi_priv),
|
||||
.probe = cv1800b_spi_probe,
|
||||
};
|
@ -59,6 +59,11 @@ config SYSRESET_CMD_POWEROFF
|
||||
|
||||
endif
|
||||
|
||||
config SYSRESET_CV1800B
|
||||
bool "Enable support for Sophgo cv1800b System Reset"
|
||||
help
|
||||
Enable system reset support for Sophgo cv1800b SoC.
|
||||
|
||||
config POWEROFF_GPIO
|
||||
bool "Enable support for GPIO poweroff driver"
|
||||
depends on DM_GPIO
|
||||
|
@ -7,6 +7,7 @@ obj-$(CONFIG_ARCH_ASPEED) += sysreset_ast.o
|
||||
obj-$(CONFIG_ARCH_ROCKCHIP) += sysreset_rockchip.o
|
||||
obj-$(CONFIG_ARCH_STI) += sysreset_sti.o
|
||||
obj-$(CONFIG_SANDBOX) += sysreset_sandbox.o
|
||||
obj-$(CONFIG_SYSRESET_CV1800B) += sysreset_cv1800b.o
|
||||
obj-$(CONFIG_POWEROFF_GPIO) += poweroff_gpio.o
|
||||
obj-$(CONFIG_SYSRESET_GPIO) += sysreset_gpio.o
|
||||
obj-$(CONFIG_$(SPL_TPL_)SYSRESET_MAX77663) += sysreset_max77663.o
|
||||
|
64
drivers/sysreset/sysreset_cv1800b.c
Normal file
64
drivers/sysreset/sysreset_cv1800b.c
Normal file
@ -0,0 +1,64 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (c) 2024, Kongyang Liu <seashell11234455@gmail.com>
|
||||
*/
|
||||
|
||||
#include <dm.h>
|
||||
#include <stdbool.h>
|
||||
#include <sysreset.h>
|
||||
#include <wait_bit.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/errno.h>
|
||||
|
||||
#define REG_RTC_BASE (void *)0x05026000
|
||||
#define REG_RTC_CTRL_BASE (void *)0x05025000
|
||||
#define REG_RTC_EN_SHDN_REQ (REG_RTC_BASE + 0xc0)
|
||||
#define REG_RTC_EN_PWR_CYC_REQ (REG_RTC_BASE + 0xc8)
|
||||
#define REG_RTC_EN_WARM_RST_REQ (REG_RTC_BASE + 0xcc)
|
||||
#define REG_RTC_CTRL_UNLOCKKEY (REG_RTC_CTRL_BASE + 0x4)
|
||||
#define REG_RTC_CTRL (REG_RTC_CTRL_BASE + 0x8)
|
||||
|
||||
#define CTRL_UNLOCKKEY_MAGIC 0xAB18
|
||||
|
||||
/* REG_RTC_CTRL */
|
||||
#define BIT_REQ_SHDN BIT(0)
|
||||
#define BIT_REQ_PWR_CYC BIT(3)
|
||||
#define BIT_REQ_WARM_RST BIT(4)
|
||||
|
||||
static struct {
|
||||
void *pre_req_reg;
|
||||
u32 req_bit;
|
||||
} reset_info[SYSRESET_COUNT] = {
|
||||
[SYSRESET_WARM] = { REG_RTC_EN_WARM_RST_REQ, BIT_REQ_WARM_RST },
|
||||
[SYSRESET_COLD] = { REG_RTC_EN_WARM_RST_REQ, BIT_REQ_WARM_RST },
|
||||
[SYSRESET_POWER] = { REG_RTC_EN_PWR_CYC_REQ, BIT_REQ_PWR_CYC },
|
||||
[SYSRESET_POWER_OFF] = { REG_RTC_EN_SHDN_REQ, BIT_REQ_SHDN },
|
||||
};
|
||||
|
||||
static int cv1800b_sysreset_request(struct udevice *dev, enum sysreset_t type)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
writel(1, reset_info[type].pre_req_reg);
|
||||
writel(CTRL_UNLOCKKEY_MAGIC, REG_RTC_CTRL_UNLOCKKEY);
|
||||
reg = readl(REG_RTC_CTRL);
|
||||
writel(0xFFFF0800 | reset_info[type].req_bit, REG_RTC_CTRL);
|
||||
|
||||
return -EINPROGRESS;
|
||||
}
|
||||
|
||||
static struct sysreset_ops cv1800b_sysreset = {
|
||||
.request = cv1800b_sysreset_request,
|
||||
};
|
||||
|
||||
static const struct udevice_id cv1800b_sysreset_ids[] = {
|
||||
{ .compatible = "sophgo,cv1800b-sysreset", },
|
||||
{},
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(sysreset_cv1800b) = {
|
||||
.name = "cv1800b_sysreset",
|
||||
.id = UCLASS_SYSRESET,
|
||||
.ops = &cv1800b_sysreset,
|
||||
.of_match = cv1800b_sysreset_ids
|
||||
};
|
Loading…
Reference in New Issue
Block a user