aboutsummaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/Makefile2
-rw-r--r--drivers/clk/Kconfig4
-rw-r--r--drivers/clk/aspeed/clk_ast2600.c3
-rw-r--r--drivers/clk/renesas/clk-rcar-gen3.c18
-rw-r--r--drivers/clk/renesas/rcar-gen3-cpg.h2
-rw-r--r--drivers/clk/uniphier/clk-uniphier-sys.c5
-rw-r--r--drivers/core/Kconfig7
-rw-r--r--drivers/core/ofnode.c22
-rw-r--r--drivers/ddr/marvell/a38x/ddr3_init.h1
-rw-r--r--drivers/ddr/marvell/a38x/seq_exec.h64
-rw-r--r--drivers/fpga/Kconfig2
-rw-r--r--drivers/fpga/zynqmppl.c12
-rw-r--r--drivers/gpio/sh_pfc.c6
-rw-r--r--drivers/i2c/Kconfig24
-rw-r--r--drivers/input/Makefile1
-rw-r--r--drivers/input/twl6030.c47
-rw-r--r--drivers/mmc/Kconfig12
-rw-r--r--drivers/mmc/Makefile1
-rw-r--r--drivers/mmc/zynq_sdhci.c5
-rw-r--r--drivers/mtd/nand/raw/Kconfig4
-rw-r--r--drivers/mtd/nand/raw/Makefile1
-rw-r--r--drivers/mtd/nand/raw/arasan_nfc.c5
-rw-r--r--drivers/mtd/nand/raw/brcmnand/brcmnand.c353
-rw-r--r--drivers/mtd/nand/raw/kb9202_nand.c134
-rw-r--r--drivers/mtd/nand/raw/nand_bbt.c3
-rw-r--r--drivers/mtd/nand/raw/nand_util.c3
-rw-r--r--drivers/mtd/nand/spi/core.c5
-rw-r--r--drivers/mux/Makefile2
-rw-r--r--drivers/net/mvneta.c4
-rw-r--r--drivers/net/phy/Kconfig3
-rw-r--r--drivers/net/ravb.c6
-rw-r--r--drivers/net/zynq_gem.c2
-rw-r--r--drivers/pci/pci_rom.c10
-rw-r--r--drivers/phy/phy-mtk-tphy.c213
-rw-r--r--drivers/phy/socionext/Kconfig8
-rw-r--r--drivers/phy/socionext/Makefile1
-rw-r--r--drivers/phy/socionext/phy-uniphier-usb3.c168
-rw-r--r--drivers/ram/aspeed/sdram_ast2600.c6
-rw-r--r--drivers/reset/reset-uniphier.c78
-rw-r--r--drivers/rtc/Kconfig18
-rw-r--r--drivers/rtc/Makefile4
-rw-r--r--drivers/serial/Kconfig8
-rw-r--r--drivers/serial/serial_sh.c87
-rw-r--r--drivers/serial/serial_sh.h8
-rw-r--r--drivers/spi/xilinx_spi.c5
-rw-r--r--drivers/spi/zynqmp_gqspi.c5
-rw-r--r--drivers/sysreset/sysreset_mpc83xx.c4
-rw-r--r--drivers/timer/Kconfig7
-rw-r--r--drivers/timer/Makefile1
-rw-r--r--drivers/timer/fttmr010_timer.c92
-rw-r--r--drivers/timer/tsc_timer.c9
-rw-r--r--drivers/tpm/tpm2_tis_sandbox.c2
-rw-r--r--drivers/usb/dwc3/Kconfig9
-rw-r--r--drivers/usb/dwc3/dwc3-generic.c132
-rw-r--r--drivers/usb/dwc3/dwc3-generic.h33
-rw-r--r--drivers/usb/dwc3/dwc3-uniphier.c116
-rw-r--r--drivers/usb/host/xhci-mtk.c49
-rw-r--r--drivers/video/Kconfig30
-rw-r--r--drivers/video/Makefile6
-rw-r--r--drivers/video/console_core.c212
-rw-r--r--drivers/video/console_normal.c177
-rw-r--r--drivers/video/console_rotate.c371
-rw-r--r--drivers/video/console_truetype.c3
-rw-r--r--drivers/video/coreboot.c2
-rw-r--r--drivers/video/efi.c138
-rw-r--r--drivers/video/vidconsole-uclass.c23
-rw-r--r--drivers/video/vidconsole_internal.h120
-rw-r--r--drivers/video/video-uclass.c36
68 files changed, 1892 insertions, 1062 deletions
diff --git a/drivers/Makefile b/drivers/Makefile
index 15d19d0c8a..58be410135 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -18,7 +18,6 @@ obj-$(CONFIG_$(SPL_TPL_)INPUT) += input/
obj-$(CONFIG_$(SPL_TPL_)LED) += led/
obj-$(CONFIG_$(SPL_TPL_)MMC) += mmc/
obj-y += mtd/
-obj-$(CONFIG_$(SPL_)MULTIPLEXER) += mux/
obj-$(CONFIG_$(SPL_TPL_)ETH) += net/
obj-$(CONFIG_$(SPL_TPL_)PCH) += pch/
obj-$(CONFIG_$(SPL_TPL_)PCI) += pci/
@@ -87,6 +86,7 @@ obj-$(CONFIG_FASTBOOT) += fastboot/
obj-$(CONFIG_FWU_MDATA) += fwu-mdata/
obj-y += misc/
obj-$(CONFIG_MMC) += mmc/
+obj-$(CONFIG_MULTIPLEXER) += mux/
obj-$(CONFIG_NVME) += nvme/
obj-$(CONFIG_PCI_ENDPOINT) += pci_endpoint/
obj-y += dfu/
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 09aa97ee8c..42280cbf83 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -185,7 +185,7 @@ config CLK_VERSACLOCK
config CLK_VERSAL
bool "Enable clock driver support for Versal"
depends on (ARCH_VERSAL || ARCH_VERSAL_NET)
- select ZYNQMP_FIRMWARE
+ imply ZYNQMP_FIRMWARE
help
This clock driver adds support for clock realted settings for
Versal platform.
@@ -219,7 +219,7 @@ config CLK_ZYNQ
config CLK_ZYNQMP
bool "Enable clock driver support for ZynqMP"
depends on ARCH_ZYNQMP
- select ZYNQMP_FIRMWARE
+ imply ZYNQMP_FIRMWARE
help
This clock driver adds support for clock realted settings for
ZynqMP platform.
diff --git a/drivers/clk/aspeed/clk_ast2600.c b/drivers/clk/aspeed/clk_ast2600.c
index 0df1dc3718..e5ada5b6d4 100644
--- a/drivers/clk/aspeed/clk_ast2600.c
+++ b/drivers/clk/aspeed/clk_ast2600.c
@@ -538,7 +538,7 @@ static uint32_t ast2600_configure_pll(struct ast2600_scu *scu,
}
p_cfg->reg.b.bypass = 0;
- p_cfg->reg.b.off = 1;
+ p_cfg->reg.b.off = 0;
p_cfg->reg.b.reset = 1;
reg = readl(addr);
@@ -549,7 +549,6 @@ static uint32_t ast2600_configure_pll(struct ast2600_scu *scu,
/* write extend parameter */
writel(p_cfg->ext_reg, addr_ext);
udelay(100);
- p_cfg->reg.b.off = 0;
p_cfg->reg.b.reset = 0;
reg &= ~GENMASK(25, 0);
reg |= p_cfg->reg.w;
diff --git a/drivers/clk/renesas/clk-rcar-gen3.c b/drivers/clk/renesas/clk-rcar-gen3.c
index c121d82de7..1697867ff0 100644
--- a/drivers/clk/renesas/clk-rcar-gen3.c
+++ b/drivers/clk/renesas/clk-rcar-gen3.c
@@ -55,6 +55,7 @@ static int gen3_clk_get_parent(struct gen3_clk_priv *priv, struct clk *clk,
struct cpg_mssr_info *info, struct clk *parent)
{
const struct cpg_core_clk *core;
+ u8 shift;
int ret;
if (!renesas_clk_is_mod(clk)) {
@@ -63,8 +64,9 @@ static int gen3_clk_get_parent(struct gen3_clk_priv *priv, struct clk *clk,
return ret;
if (core->type == CLK_TYPE_GEN3_MDSEL) {
+ shift = priv->cpg_mode & BIT(core->offset) ? 16 : 0;
parent->dev = clk->dev;
- parent->id = core->parent >> (priv->sscg ? 16 : 0);
+ parent->id = core->parent >> shift;
parent->id &= 0xffff;
return 0;
}
@@ -183,6 +185,7 @@ static u64 gen3_clk_get_rate64(struct clk *clk)
priv->cpg_pll_config;
u32 value, div;
u64 rate = 0;
+ u8 shift;
int ret;
debug("%s[%i] Clock: id=%lu\n", __func__, __LINE__, clk->id);
@@ -277,11 +280,11 @@ static u64 gen3_clk_get_rate64(struct clk *clk)
"FIXED");
case CLK_TYPE_GEN3_MDSEL:
- div = (core->div >> (priv->sscg ? 16 : 0)) & 0xffff;
+ shift = priv->cpg_mode & BIT(core->offset) ? 16 : 0;
+ div = (core->div >> shift) & 0xffff;
rate = gen3_clk_get_rate64(&parent) / div;
debug("%s[%i] PE clk: parent=%i div=%u => rate=%llu\n",
- __func__, __LINE__,
- (core->parent >> (priv->sscg ? 16 : 0)) & 0xffff,
+ __func__, __LINE__, (core->parent >> shift) & 0xffff,
div, rate);
return rate;
@@ -407,7 +410,6 @@ static int gen3_clk_probe(struct udevice *dev)
struct cpg_mssr_info *info =
(struct cpg_mssr_info *)dev_get_driver_data(dev);
fdt_addr_t rst_base;
- u32 cpg_mode;
int ret;
priv->base = dev_read_addr_ptr(dev);
@@ -423,15 +425,13 @@ static int gen3_clk_probe(struct udevice *dev)
if (rst_base == FDT_ADDR_T_NONE)
return -EINVAL;
- cpg_mode = readl(rst_base + info->reset_modemr_offset);
+ priv->cpg_mode = readl(rst_base + info->reset_modemr_offset);
priv->cpg_pll_config =
- (struct rcar_gen3_cpg_pll_config *)info->get_pll_config(cpg_mode);
+ (struct rcar_gen3_cpg_pll_config *)info->get_pll_config(priv->cpg_mode);
if (!priv->cpg_pll_config->extal_div)
return -EINVAL;
- priv->sscg = !(cpg_mode & BIT(12));
-
if (info->reg_layout == CLK_REG_LAYOUT_RCAR_GEN2_AND_GEN3) {
priv->info->status_regs = mstpsr;
priv->info->control_regs = smstpcr;
diff --git a/drivers/clk/renesas/rcar-gen3-cpg.h b/drivers/clk/renesas/rcar-gen3-cpg.h
index 200e4adb90..894e376549 100644
--- a/drivers/clk/renesas/rcar-gen3-cpg.h
+++ b/drivers/clk/renesas/rcar-gen3-cpg.h
@@ -132,7 +132,7 @@ struct gen3_clk_priv {
struct cpg_mssr_info *info;
struct clk clk_extal;
struct clk clk_extalr;
- bool sscg;
+ u32 cpg_mode;
const struct rcar_gen3_cpg_pll_config *cpg_pll_config;
};
diff --git a/drivers/clk/uniphier/clk-uniphier-sys.c b/drivers/clk/uniphier/clk-uniphier-sys.c
index ff5d364f59..3b8595fe61 100644
--- a/drivers/clk/uniphier/clk-uniphier-sys.c
+++ b/drivers/clk/uniphier/clk-uniphier-sys.c
@@ -28,7 +28,10 @@ const struct uniphier_clk_data uniphier_pxs2_sys_clk_data[] = {
UNIPHIER_CLK_GATE_SIMPLE(14, 0x2104, 16), /* usb30 (Pro4, Pro5, PXs2) */
UNIPHIER_CLK_GATE_SIMPLE(15, 0x2104, 17), /* usb31 (Pro4, Pro5, PXs2) */
UNIPHIER_CLK_GATE_SIMPLE(16, 0x2104, 19), /* usb30-phy (PXs2) */
+ UNIPHIER_CLK_RATE(17, 25000000), /* usb30-phy2 (PXs2) */
+ UNIPHIER_CLK_RATE(18, 25000000), /* usb30-phy3 (PXs2) */
UNIPHIER_CLK_GATE_SIMPLE(20, 0x2104, 20), /* usb31-phy (PXs2) */
+ UNIPHIER_CLK_RATE(21, 25000000), /* usb31-phy2 (PXs2) */
UNIPHIER_CLK_GATE_SIMPLE(24, 0x2108, 2), /* pcie (Pro5) */
{ /* sentinel */ }
#endif
@@ -44,6 +47,8 @@ const struct uniphier_clk_data uniphier_ld20_sys_clk_data[] = {
UNIPHIER_CLK_GATE_SIMPLE(14, 0x210c, 14), /* usb30 (LD20) */
UNIPHIER_CLK_GATE_SIMPLE(16, 0x210c, 12), /* usb30-phy0 (LD20) */
UNIPHIER_CLK_GATE_SIMPLE(17, 0x210c, 13), /* usb30-phy1 (LD20) */
+ UNIPHIER_CLK_RATE(18, 25000000), /* usb30-phy2 (LD20) */
+ UNIPHIER_CLK_RATE(19, 25000000), /* usb30-phy3 (LD20) */
UNIPHIER_CLK_GATE_SIMPLE(24, 0x210c, 4), /* pcie */
{ /* sentinel */ }
#endif
diff --git a/drivers/core/Kconfig b/drivers/core/Kconfig
index 6fc8854b57..0f755aa702 100644
--- a/drivers/core/Kconfig
+++ b/drivers/core/Kconfig
@@ -301,6 +301,13 @@ config SPL_SIMPLE_BUS
Supports the 'simple-bus' driver, which is used on some systems
in SPL.
+config TPL_SIMPLE_BUS
+ bool "Support simple-bus driver in TPL"
+ depends on TPL_DM && TPL_OF_CONTROL
+ help
+ Supports the 'simple-bus' driver, which is used on some systems
+ in TPL.
+
config SIMPLE_BUS_CORRECT_RANGE
bool "Decode the 'simple-bus' <range> by honoring the #address-cells and #size-cells"
depends on SIMPLE_BUS
diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c
index d08578e9c4..f49ee493d3 100644
--- a/drivers/core/ofnode.c
+++ b/drivers/core/ofnode.c
@@ -1312,24 +1312,36 @@ bool ofnode_pre_reloc(ofnode node)
{
#if defined(CONFIG_SPL_BUILD) || defined(CONFIG_TPL_BUILD)
/* for SPL and TPL the remaining nodes after the fdtgrep 1st pass
- * had property dm-pre-reloc or u-boot,dm-spl/tpl.
+ * had property bootph-all or bootph-pre-sram/bootph-pre-ram.
* They are removed in final dtb (fdtgrep 2nd pass)
*/
return true;
#else
- if (ofnode_read_bool(node, "u-boot,dm-pre-reloc"))
+ if (ofnode_read_bool(node, "bootph-all"))
return true;
- if (ofnode_read_bool(node, "u-boot,dm-pre-proper"))
+ if (ofnode_read_bool(node, "bootph-some-ram"))
return true;
/*
* In regular builds individual spl and tpl handling both
* count as handled pre-relocation for later second init.
*/
- if (ofnode_read_bool(node, "u-boot,dm-spl") ||
- ofnode_read_bool(node, "u-boot,dm-tpl"))
+ if (ofnode_read_bool(node, "bootph-pre-ram") ||
+ ofnode_read_bool(node, "bootph-pre-sram"))
return true;
+ if (IS_ENABLED(CONFIG_OF_TAG_MIGRATE)) {
+ /* detect and handle old tags */
+ if (ofnode_read_bool(node, "u-boot,dm-pre-reloc") ||
+ ofnode_read_bool(node, "u-boot,dm-pre-proper") ||
+ ofnode_read_bool(node, "u-boot,dm-spl") ||
+ ofnode_read_bool(node, "u-boot,dm-tpl") ||
+ ofnode_read_bool(node, "u-boot,dm-vpl")) {
+ gd->flags |= GD_FLG_OF_TAG_MIGRATE;
+ return true;
+ }
+ }
+
return false;
#endif
}
diff --git a/drivers/ddr/marvell/a38x/ddr3_init.h b/drivers/ddr/marvell/a38x/ddr3_init.h
index ba9f7881d5..6854bb49de 100644
--- a/drivers/ddr/marvell/a38x/ddr3_init.h
+++ b/drivers/ddr/marvell/a38x/ddr3_init.h
@@ -9,7 +9,6 @@
#include "ddr_ml_wrapper.h"
#include "mv_ddr_plat.h"
-#include "seq_exec.h"
#include "ddr3_logging_def.h"
#include "ddr3_training_hw_algo.h"
#include "ddr3_training_ip.h"
diff --git a/drivers/ddr/marvell/a38x/seq_exec.h b/drivers/ddr/marvell/a38x/seq_exec.h
deleted file mode 100644
index fe0cb8f75d..0000000000
--- a/drivers/ddr/marvell/a38x/seq_exec.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Copyright (C) Marvell International Ltd. and its affiliates
- */
-
-#ifndef _SEQ_EXEC_H
-#define _SEQ_EXEC_H
-
-#define NA 0xff
-#define DEFAULT_PARAM 0
-#define MV_BOARD_TCLK_ERROR 0xffffffff
-
-#define NO_DATA 0xffffffff
-#define MAX_DATA_ARRAY 5
-#define FIRST_CELL 0
-
-/* Operation types */
-enum mv_op {
- WRITE_OP,
- DELAY_OP,
- POLL_OP,
-};
-
-/* Operation parameters */
-struct op_params {
- u32 unit_base_reg;
- u32 unit_offset;
- u32 mask;
- u32 data[MAX_DATA_ARRAY]; /* data array */
- u8 wait_time; /* msec */
- u16 num_of_loops; /* for polling only */
-};
-
-/*
- * Sequence parameters. Each sequence contains:
- * 1. Sequence id.
- * 2. Sequence size (total amount of operations during the sequence)
- * 3. a series of operations. operations can be write, poll or delay
- * 4. index in the data array (the entry where the relevant data sits)
- */
-struct cfg_seq {
- struct op_params *op_params_ptr;
- u8 cfg_seq_size;
- u8 data_arr_idx;
-};
-
-extern struct cfg_seq serdes_seq_db[];
-
-/*
- * A generic function type for executing an operation (write, poll or delay)
- */
-typedef int (*op_execute_func_ptr)(u32 serdes_num, struct op_params *params,
- u32 data_arr_idx);
-
-/* Specific functions for executing each operation */
-int write_op_execute(u32 serdes_num, struct op_params *params,
- u32 data_arr_idx);
-int delay_op_execute(u32 serdes_num, struct op_params *params,
- u32 data_arr_idx);
-int poll_op_execute(u32 serdes_num, struct op_params *params, u32 data_arr_idx);
-enum mv_op get_cfg_seq_op(struct op_params *params);
-int mv_seq_exec(u32 serdes_num, u32 seq_id);
-
-#endif /*_SEQ_EXEC_H*/
diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig
index 61490d6d8d..62cb77b098 100644
--- a/drivers/fpga/Kconfig
+++ b/drivers/fpga/Kconfig
@@ -75,7 +75,7 @@ config FPGA_XILINX
config FPGA_ZYNQMPPL
bool "Enable Xilinx FPGA driver for ZynqMP"
- depends on FPGA_XILINX
+ depends on FPGA_XILINX && ZYNQMP_FIRMWARE
help
Enable FPGA driver for loading bitstream in BIT and BIN format
on Xilinx Zynq UltraScale+ (ZynqMP) device.
diff --git a/drivers/fpga/zynqmppl.c b/drivers/fpga/zynqmppl.c
index d1491da02c..7b5128fe27 100644
--- a/drivers/fpga/zynqmppl.c
+++ b/drivers/fpga/zynqmppl.c
@@ -332,10 +332,16 @@ static int zynqmp_loads(xilinx_desc *desc, const void *buf, size_t bsize,
buf_lo = lower_32_bits((ulong)buf);
buf_hi = upper_32_bits((ulong)buf);
- ret = xilinx_pm_request(PM_FPGA_LOAD, buf_lo,
+ if ((u32)(uintptr_t)fpga_sec_info->userkey_addr)
+ ret = xilinx_pm_request(PM_FPGA_LOAD, buf_lo,
buf_hi,
- (u32)(uintptr_t)fpga_sec_info->userkey_addr,
- flag, ret_payload);
+ (u32)(uintptr_t)fpga_sec_info->userkey_addr,
+ flag, ret_payload);
+ else
+ ret = xilinx_pm_request(PM_FPGA_LOAD, buf_lo,
+ buf_hi, (u32)bsize,
+ flag, ret_payload);
+
if (ret)
puts("PL FPGA LOAD fail\n");
else
diff --git a/drivers/gpio/sh_pfc.c b/drivers/gpio/sh_pfc.c
index 988f7e9bba..92522b63bb 100644
--- a/drivers/gpio/sh_pfc.c
+++ b/drivers/gpio/sh_pfc.c
@@ -568,10 +568,10 @@ static int sh_gpio_get_value(struct pinmux_info *gpioc, unsigned gpio)
if (!gpioc || get_data_reg(gpioc, gpio, &dr, &bit) != 0)
return -1;
-#if defined(CONFIG_RCAR_GEN3)
- if ((gpioc->gpios[gpio].flags & PINMUX_FLAG_TYPE) == PINMUX_TYPE_INPUT)
+
+ if (IS_ENABLED(CONFIG_RCAR_GEN3) &&
+ ((gpioc->gpios[gpio].flags & PINMUX_FLAG_TYPE) == PINMUX_TYPE_INPUT))
offset += 4;
-#endif
return gpio_read_bit(dr, offset, bit);
}
diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig
index 3279fef1eb..2eae33cd54 100644
--- a/drivers/i2c/Kconfig
+++ b/drivers/i2c/Kconfig
@@ -47,6 +47,16 @@ config SPL_DM_I2C
device (bus child) info is kept as parent platdata. The interface
is defined in include/i2c.h.
+config TPL_DM_I2C
+ bool "Enable Driver Model for I2C drivers in TPL"
+ depends on TPL_DM && DM_I2C
+ help
+ Enable driver model for I2C. The I2C uclass interface: probe, read,
+ write and speed, is implemented with the bus drivers operations,
+ which provide methods for bus setting and data transfer. Each chip
+ device (bus child) info is kept as parent platdata. The interface
+ is defined in include/i2c.h.
+
config VPL_DM_I2C
bool "Enable Driver Model for I2C drivers in VPL"
depends on VPL_DM && DM_I2C
@@ -486,13 +496,13 @@ config SYS_I2C_OMAP24XX
config SYS_I2C_RCAR_I2C
bool "Renesas RCar I2C driver"
- depends on (RCAR_GEN3 || RCAR_GEN2) && DM_I2C
+ depends on (RCAR_GEN2 || RCAR_GEN3) && DM_I2C
help
Support for Renesas RCar I2C controller.
config SYS_I2C_RCAR_IIC
bool "Renesas RCar Gen3 IIC driver"
- depends on (RCAR_GEN3 || RCAR_GEN2) && DM_I2C
+ depends on (RCAR_GEN2 || RCAR_GEN3) && DM_I2C
help
Support for Renesas RCar Gen3 IIC controller.
@@ -508,6 +518,16 @@ config SYS_I2C_ROCKCHIP
config SYS_I2C_SANDBOX
bool "Sandbox I2C driver"
depends on SANDBOX && DM_I2C
+ default y
+ help
+ Enable I2C support for sandbox. This is an emulation of a real I2C
+ bus. Devices can be attached to the bus using the device tree
+ which specifies the driver to use. See sandbox.dts as an example.
+
+config SPL_SYS_I2C_SANDBOX
+ bool "Sandbox I2C driver (SPL)"
+ depends on SPL && SANDBOX && DM_I2C
+ default y
help
Enable I2C support for sandbox. This is an emulation of a real I2C
bus. Devices can be attached to the bus using the device tree
diff --git a/drivers/input/Makefile b/drivers/input/Makefile
index 14c0ea7325..71f315adf6 100644
--- a/drivers/input/Makefile
+++ b/drivers/input/Makefile
@@ -14,5 +14,4 @@ obj-$(CONFIG_APPLE_SPI_KEYB) += apple_spi_kbd.o
obj-$(CONFIG_I8042_KEYB) += i8042.o
obj-$(CONFIG_TEGRA_KEYBOARD) += input.o tegra-kbc.o
obj-$(CONFIG_TWL4030_INPUT) += twl4030.o
-obj-$(CONFIG_TWL6030_INPUT) += twl6030.o
endif
diff --git a/drivers/input/twl6030.c b/drivers/input/twl6030.c
deleted file mode 100644
index 76bd3488fc..0000000000
--- a/drivers/input/twl6030.c
+++ /dev/null
@@ -1,47 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * TWL6030 input
- *
- * Copyright (C) 2016 Paul Kocialkowski <contact@paulk.fr>
- */
-
-#include <twl6030.h>
-
-int twl6030_input_power_button(void)
-{
- u8 value;
-
- twl6030_i2c_read_u8(TWL6030_CHIP_PM, TWL6030_STS_HW_CONDITIONS, &value);
-
- /* Power button is active low. */
- if (value & TWL6030_STS_HW_CONDITIONS_PWRON)
- return 0;
-
- return 1;
-}
-
-int twl6030_input_charger(void)
-{
- u8 value;
-
- twl6030_i2c_read_u8(TWL6030_CHIP_CHARGER, TWL6030_CONTROLLER_STAT1,
- &value);
-
- if (value & TWL6030_CONTROLLER_STAT1_VAC_DET)
- return 1;
-
- return 0;
-}
-
-int twl6030_input_usb(void)
-{
- u8 value;
-
- twl6030_i2c_read_u8(TWL6030_CHIP_CHARGER, TWL6030_CONTROLLER_STAT1,
- &value);
-
- if (value & TWL6030_CONTROLLER_STAT1_VBUS_DET)
- return 1;
-
- return 0;
-}
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index 878f867c62..80641e1393 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -667,18 +667,6 @@ config MMC_SDHCI_S5P
If unsure, say N.
-config MMC_SDHCI_SPEAR
- bool "SDHCI support on ST SPEAr platform"
- depends on MMC_SDHCI
- help
- This selects the Secure Digital Host Controller Interface (SDHCI)
- often referrered to as the HSMMC block in some of the ST SPEAR range
- of SoC
-
- If you have a controller with this interface, say Y here.
-
- If unsure, say N.
-
config MMC_SDHCI_STI
bool "SDHCI support for STMicroelectronics SoC"
depends on MMC_SDHCI && OF_CONTROL
diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
index 3dc757108d..2c65c4765a 100644
--- a/drivers/mmc/Makefile
+++ b/drivers/mmc/Makefile
@@ -70,7 +70,6 @@ obj-$(CONFIG_MMC_SDHCI_NPCM) += npcm_sdhci.o
obj-$(CONFIG_MMC_SDHCI_PIC32) += pic32_sdhci.o
obj-$(CONFIG_MMC_SDHCI_ROCKCHIP) += rockchip_sdhci.o
obj-$(CONFIG_MMC_SDHCI_S5P) += s5p_sdhci.o
-obj-$(CONFIG_MMC_SDHCI_SPEAR) += spear_sdhci.o
obj-$(CONFIG_MMC_SDHCI_STI) += sti_sdhci.o
obj-$(CONFIG_MMC_SDHCI_TANGIER) += tangier_sdhci.o
obj-$(CONFIG_MMC_SDHCI_TEGRA) += tegra_mmc.o
diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c
index 91e309d275..9dc310663f 100644
--- a/drivers/mmc/zynq_sdhci.c
+++ b/drivers/mmc/zynq_sdhci.c
@@ -14,6 +14,7 @@
#include "mmc_private.h"
#include <log.h>
#include <reset.h>
+#include <asm/arch/sys_proto.h>
#include <dm/device_compat.h>
#include <linux/err.h>
#include <linux/libfdt.h>
@@ -988,7 +989,7 @@ static const struct sdhci_ops arasan_ops = {
};
#endif
-#if defined(CONFIG_ARCH_ZYNQMP)
+#if defined(CONFIG_ARCH_ZYNQMP) && defined(CONFIG_ZYNQMP_FIRMWARE)
static int sdhci_zynqmp_set_dynamic_config(struct arasan_sdhci_priv *priv,
struct udevice *dev)
{
@@ -1090,7 +1091,7 @@ static int arasan_sdhci_probe(struct udevice *dev)
host = priv->host;
-#if defined(CONFIG_ARCH_ZYNQMP)
+#if defined(CONFIG_ARCH_ZYNQMP) && defined(CONFIG_ZYNQMP_FIRMWARE)
if (device_is_compatible(dev, "xlnx,zynqmp-8.9a")) {
ret = zynqmp_pm_is_function_supported(PM_IOCTL,
IOCTL_SET_SD_CONFIG);
diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig
index 5b35da45f5..5c7b0d9dcc 100644
--- a/drivers/mtd/nand/raw/Kconfig
+++ b/drivers/mtd/nand/raw/Kconfig
@@ -628,7 +628,8 @@ comment "Generic NAND options"
config SYS_NAND_BLOCK_SIZE
hex "NAND chip eraseblock size"
- depends on ARCH_SUNXI || SPL_NAND_SUPPORT || TPL_NAND_SUPPORT
+ depends on ARCH_SUNXI || SPL_NAND_SUPPORT || TPL_NAND_SUPPORT || \
+ MVEBU_SPL_BOOT_DEVICE_NAND
depends on !NAND_MXS && !NAND_DENALI_DT && !NAND_LPC32XX_MLC && \
!NAND_FSL_IFC && !NAND_MT7621
help
@@ -655,6 +656,7 @@ config SYS_NAND_PAGE_SIZE
hex "NAND chip page size"
depends on ARCH_SUNXI || NAND_OMAP_GPMC || NAND_LPC32XX_SLC || \
SPL_NAND_SIMPLE || (NAND_MXC && SPL_NAND_SUPPORT) || \
+ MVEBU_SPL_BOOT_DEVICE_NAND || \
(NAND_ATMEL && SPL_NAND_SUPPORT) || SPL_GENERATE_ATMEL_PMECC_HEADER
depends on !NAND_MXS && !NAND_DENALI_DT && !NAND_LPC32XX_MLC && !NAND_MT7621
help
diff --git a/drivers/mtd/nand/raw/Makefile b/drivers/mtd/nand/raw/Makefile
index 666323e221..add2b4cf65 100644
--- a/drivers/mtd/nand/raw/Makefile
+++ b/drivers/mtd/nand/raw/Makefile
@@ -56,7 +56,6 @@ obj-$(CONFIG_NAND_DENALI) += denali.o
obj-$(CONFIG_NAND_DENALI_DT) += denali_dt.o
obj-$(CONFIG_NAND_FSL_ELBC) += fsl_elbc_nand.o
obj-$(CONFIG_NAND_FSL_IFC) += fsl_ifc_nand.o
-obj-$(CONFIG_NAND_KB9202) += kb9202_nand.o
obj-$(CONFIG_NAND_KIRKWOOD) += kirkwood_nand.o
obj-$(CONFIG_NAND_KMETER1) += kmeter1_nand.o
obj-$(CONFIG_NAND_LPC32XX_MLC) += lpc32xx_nand_mlc.o
diff --git a/drivers/mtd/nand/raw/arasan_nfc.c b/drivers/mtd/nand/raw/arasan_nfc.c
index 4621bfb03e..99e2681c14 100644
--- a/drivers/mtd/nand/raw/arasan_nfc.c
+++ b/drivers/mtd/nand/raw/arasan_nfc.c
@@ -1230,12 +1230,16 @@ static int arasan_probe(struct udevice *dev)
struct nand_drv *info = &arasan->nand_ctrl;
struct nand_config *nand = &info->config;
struct mtd_info *mtd;
+ ofnode child;
int err = -1;
info->reg = (struct nand_regs *)dev_read_addr(dev);
mtd = nand_to_mtd(nand_chip);
nand_set_controller_data(nand_chip, &arasan->nand_ctrl);
+ ofnode_for_each_subnode(child, dev_ofnode(dev))
+ nand_set_flash_node(nand_chip, child);
+
#ifdef CONFIG_SYS_NAND_NO_SUBPAGE_WRITE
nand_chip->options |= NAND_NO_SUBPAGE_WRITE;
#endif
@@ -1248,7 +1252,6 @@ static int arasan_probe(struct udevice *dev)
/* Buffer read/write routines */
nand_chip->read_buf = arasan_nand_read_buf;
nand_chip->write_buf = arasan_nand_write_buf;
- nand_chip->bbt_options = NAND_BBT_USE_FLASH;
writel(0x0, &info->reg->cmd_reg);
writel(0x0, &info->reg->pgm_reg);
diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.c b/drivers/mtd/nand/raw/brcmnand/brcmnand.c
index 74c9348f7f..efbf9a3120 100644
--- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c
+++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c
@@ -86,6 +86,12 @@ struct brcm_nand_dma_desc {
#define FLASH_DMA_ECC_ERROR (1 << 8)
#define FLASH_DMA_CORR_ERROR (1 << 9)
+/* Bitfields for DMA_MODE */
+#define FLASH_DMA_MODE_STOP_ON_ERROR BIT(1) /* stop in Uncorr ECC error */
+#define FLASH_DMA_MODE_MODE BIT(0) /* link list */
+#define FLASH_DMA_MODE_MASK (FLASH_DMA_MODE_STOP_ON_ERROR | \
+ FLASH_DMA_MODE_MODE)
+
/* 512B flash cache in the NAND controller HW */
#define FC_SHIFT 9U
#define FC_BYTES 512U
@@ -98,6 +104,65 @@ struct brcm_nand_dma_desc {
#define NAND_CTRL_RDY (INTFC_CTLR_READY | INTFC_FLASH_READY)
#define NAND_POLL_STATUS_TIMEOUT_MS 100
+/* flash_dma registers */
+enum flash_dma_reg {
+ FLASH_DMA_REVISION = 0,
+ FLASH_DMA_FIRST_DESC,
+ FLASH_DMA_FIRST_DESC_EXT,
+ FLASH_DMA_CTRL,
+ FLASH_DMA_MODE,
+ FLASH_DMA_STATUS,
+ FLASH_DMA_INTERRUPT_DESC,
+ FLASH_DMA_INTERRUPT_DESC_EXT,
+ FLASH_DMA_ERROR_STATUS,
+ FLASH_DMA_CURRENT_DESC,
+ FLASH_DMA_CURRENT_DESC_EXT,
+};
+
+#ifndef __UBOOT__
+/* flash_dma registers v0*/
+static const u16 flash_dma_regs_v0[] = {
+ [FLASH_DMA_REVISION] = 0x00,
+ [FLASH_DMA_FIRST_DESC] = 0x04,
+ [FLASH_DMA_CTRL] = 0x08,
+ [FLASH_DMA_MODE] = 0x0c,
+ [FLASH_DMA_STATUS] = 0x10,
+ [FLASH_DMA_INTERRUPT_DESC] = 0x14,
+ [FLASH_DMA_ERROR_STATUS] = 0x18,
+ [FLASH_DMA_CURRENT_DESC] = 0x1c,
+};
+
+/* flash_dma registers v1*/
+static const u16 flash_dma_regs_v1[] = {
+ [FLASH_DMA_REVISION] = 0x00,
+ [FLASH_DMA_FIRST_DESC] = 0x04,
+ [FLASH_DMA_FIRST_DESC_EXT] = 0x08,
+ [FLASH_DMA_CTRL] = 0x0c,
+ [FLASH_DMA_MODE] = 0x10,
+ [FLASH_DMA_STATUS] = 0x14,
+ [FLASH_DMA_INTERRUPT_DESC] = 0x18,
+ [FLASH_DMA_INTERRUPT_DESC_EXT] = 0x1c,
+ [FLASH_DMA_ERROR_STATUS] = 0x20,
+ [FLASH_DMA_CURRENT_DESC] = 0x24,
+ [FLASH_DMA_CURRENT_DESC_EXT] = 0x28,
+};
+
+/* flash_dma registers v4 */
+static const u16 flash_dma_regs_v4[] = {
+ [FLASH_DMA_REVISION] = 0x00,
+ [FLASH_DMA_FIRST_DESC] = 0x08,
+ [FLASH_DMA_FIRST_DESC_EXT] = 0x0c,
+ [FLASH_DMA_CTRL] = 0x10,
+ [FLASH_DMA_MODE] = 0x14,
+ [FLASH_DMA_STATUS] = 0x18,
+ [FLASH_DMA_INTERRUPT_DESC] = 0x20,
+ [FLASH_DMA_INTERRUPT_DESC_EXT] = 0x24,
+ [FLASH_DMA_ERROR_STATUS] = 0x28,
+ [FLASH_DMA_CURRENT_DESC] = 0x30,
+ [FLASH_DMA_CURRENT_DESC_EXT] = 0x34,
+};
+#endif /* __UBOOT__ */
+
/* Controller feature flags */
enum {
BRCMNAND_HAS_1K_SECTORS = BIT(0),
@@ -135,6 +200,8 @@ struct brcmnand_controller {
/* List of NAND hosts (one for each chip-select) */
struct list_head host_list;
+ /* flash_dma reg */
+ const u16 *flash_dma_offsets;
struct brcm_nand_dma_desc *dma_desc;
dma_addr_t dma_pa;
@@ -150,6 +217,7 @@ struct brcmnand_controller {
const unsigned int *block_sizes;
unsigned int max_page_size;
const unsigned int *page_sizes;
+ unsigned int page_size_shift;
unsigned int max_oob;
u32 features;
@@ -226,8 +294,38 @@ enum brcmnand_reg {
BRCMNAND_FC_BASE,
};
-/* BRCMNAND v4.0 */
-static const u16 brcmnand_regs_v40[] = {
+/* BRCMNAND v2.1-v2.2 */
+static const u16 brcmnand_regs_v21[] = {
+ [BRCMNAND_CMD_START] = 0x04,
+ [BRCMNAND_CMD_EXT_ADDRESS] = 0x08,
+ [BRCMNAND_CMD_ADDRESS] = 0x0c,
+ [BRCMNAND_INTFC_STATUS] = 0x5c,
+ [BRCMNAND_CS_SELECT] = 0x14,
+ [BRCMNAND_CS_XOR] = 0x18,
+ [BRCMNAND_LL_OP] = 0,
+ [BRCMNAND_CS0_BASE] = 0x40,
+ [BRCMNAND_CS1_BASE] = 0,
+ [BRCMNAND_CORR_THRESHOLD] = 0,
+ [BRCMNAND_CORR_THRESHOLD_EXT] = 0,
+ [BRCMNAND_UNCORR_COUNT] = 0,
+ [BRCMNAND_CORR_COUNT] = 0,
+ [BRCMNAND_CORR_EXT_ADDR] = 0x60,
+ [BRCMNAND_CORR_ADDR] = 0x64,
+ [BRCMNAND_UNCORR_EXT_ADDR] = 0x68,
+ [BRCMNAND_UNCORR_ADDR] = 0x6c,
+ [BRCMNAND_SEMAPHORE] = 0x50,
+ [BRCMNAND_ID] = 0x54,
+ [BRCMNAND_ID_EXT] = 0,
+ [BRCMNAND_LL_RDATA] = 0,
+ [BRCMNAND_OOB_READ_BASE] = 0x20,
+ [BRCMNAND_OOB_READ_10_BASE] = 0,
+ [BRCMNAND_OOB_WRITE_BASE] = 0x30,
+ [BRCMNAND_OOB_WRITE_10_BASE] = 0,
+ [BRCMNAND_FC_BASE] = 0x200,
+};
+
+/* BRCMNAND v3.3-v4.0 */
+static const u16 brcmnand_regs_v33[] = {
[BRCMNAND_CMD_START] = 0x04,
[BRCMNAND_CMD_EXT_ADDRESS] = 0x08,
[BRCMNAND_CMD_ADDRESS] = 0x0c,
@@ -424,6 +522,9 @@ enum {
CFG_BUS_WIDTH = BIT(CFG_BUS_WIDTH_SHIFT),
CFG_DEVICE_SIZE_SHIFT = 24,
+ /* Only for v2.1 */
+ CFG_PAGE_SIZE_SHIFT_v2_1 = 30,
+
/* Only for pre-v7.1 (with no CFG_EXT register) */
CFG_PAGE_SIZE_SHIFT = 20,
CFG_BLK_SIZE_SHIFT = 28,
@@ -459,12 +560,16 @@ static int brcmnand_revision_init(struct brcmnand_controller *ctrl)
{
static const unsigned int block_sizes_v6[] = { 8, 16, 128, 256, 512, 1024, 2048, 0 };
static const unsigned int block_sizes_v4[] = { 16, 128, 8, 512, 256, 1024, 2048, 0 };
- static const unsigned int page_sizes[] = { 512, 2048, 4096, 8192, 0 };
+ static const unsigned int block_sizes_v2_2[] = { 16, 128, 8, 512, 256, 0 };
+ static const unsigned int block_sizes_v2_1[] = { 16, 128, 8, 512, 0 };
+ static const unsigned int page_sizes_v3_4[] = { 512, 2048, 4096, 8192, 0 };
+ static const unsigned int page_sizes_v2_2[] = { 512, 2048, 4096, 0 };
+ static const unsigned int page_sizes_v2_1[] = { 512, 2048, 0 };
ctrl->nand_version = nand_readreg(ctrl, 0) & 0xffff;
- /* Only support v4.0+? */
- if (ctrl->nand_version < 0x0400) {
+ /* Only support v2.1+ */
+ if (ctrl->nand_version < 0x0201) {
dev_err(ctrl->dev, "version %#x not supported\n",
ctrl->nand_version);
return -ENODEV;
@@ -473,14 +578,16 @@ static int brcmnand_revision_init(struct brcmnand_controller *ctrl)
/* Register offsets */
if (ctrl->nand_version >= 0x0702)
ctrl->reg_offsets = brcmnand_regs_v72;
- else if (ctrl->nand_version >= 0x0701)
+ else if (ctrl->nand_version == 0x0701)
ctrl->reg_offsets = brcmnand_regs_v71;
else if (ctrl->nand_version >= 0x0600)
ctrl->reg_offsets = brcmnand_regs_v60;
else if (ctrl->nand_version >= 0x0500)
ctrl->reg_offsets = brcmnand_regs_v50;
- else if (ctrl->nand_version >= 0x0400)
- ctrl->reg_offsets = brcmnand_regs_v40;
+ else if (ctrl->nand_version >= 0x0303)
+ ctrl->reg_offsets = brcmnand_regs_v33;
+ else if (ctrl->nand_version >= 0x0201)
+ ctrl->reg_offsets = brcmnand_regs_v21;
/* Chip-select stride */
if (ctrl->nand_version >= 0x0701)
@@ -494,8 +601,9 @@ static int brcmnand_revision_init(struct brcmnand_controller *ctrl)
} else {
ctrl->cs_offsets = brcmnand_cs_offsets;
- /* v5.0 and earlier has a different CS0 offset layout */
- if (ctrl->nand_version <= 0x0500)
+ /* v3.3-5.0 have a different CS0 offset layout */
+ if (ctrl->nand_version >= 0x0303 &&
+ ctrl->nand_version <= 0x0500)
ctrl->cs0_offsets = brcmnand_cs_offsets_cs0;
}
@@ -505,20 +613,38 @@ static int brcmnand_revision_init(struct brcmnand_controller *ctrl)
ctrl->max_page_size = 16 * 1024;
ctrl->max_block_size = 2 * 1024 * 1024;
} else {
- ctrl->page_sizes = page_sizes;
+ if (ctrl->nand_version >= 0x0304)
+ ctrl->page_sizes = page_sizes_v3_4;
+ else if (ctrl->nand_version >= 0x0202)
+ ctrl->page_sizes = page_sizes_v2_2;
+ else
+ ctrl->page_sizes = page_sizes_v2_1;
+
+ if (ctrl->nand_version >= 0x0202)
+ ctrl->page_size_shift = CFG_PAGE_SIZE_SHIFT;
+ else
+ ctrl->page_size_shift = CFG_PAGE_SIZE_SHIFT_v2_1;
+
if (ctrl->nand_version >= 0x0600)
ctrl->block_sizes = block_sizes_v6;
- else
+ else if (ctrl->nand_version >= 0x0400)
ctrl->block_sizes = block_sizes_v4;
+ else if (ctrl->nand_version >= 0x0202)
+ ctrl->block_sizes = block_sizes_v2_2;
+ else
+ ctrl->block_sizes = block_sizes_v2_1;
if (ctrl->nand_version < 0x0400) {
- ctrl->max_page_size = 4096;
+ if (ctrl->nand_version < 0x0202)
+ ctrl->max_page_size = 2048;
+ else
+ ctrl->max_page_size = 4096;
ctrl->max_block_size = 512 * 1024;
}
}
/* Maximum spare area sector size (per 512B) */
- if (ctrl->nand_version >= 0x0702)
+ if (ctrl->nand_version == 0x0702)
ctrl->max_oob = 128;
else if (ctrl->nand_version >= 0x0600)
ctrl->max_oob = 64;
@@ -553,6 +679,19 @@ static int brcmnand_revision_init(struct brcmnand_controller *ctrl)
return 0;
}
+#ifndef __UBOOT__
+static void brcmnand_flash_dma_revision_init(struct brcmnand_controller *ctrl)
+{
+ /* flash_dma register offsets */
+ if (ctrl->nand_version >= 0x0703)
+ ctrl->flash_dma_offsets = flash_dma_regs_v4;
+ else if (ctrl->nand_version == 0x0602)
+ ctrl->flash_dma_offsets = flash_dma_regs_v0;
+ else
+ ctrl->flash_dma_offsets = flash_dma_regs_v1;
+}
+#endif /* __UBOOT__ */
+
static inline u32 brcmnand_read_reg(struct brcmnand_controller *ctrl,
enum brcmnand_reg reg)
{
@@ -595,6 +734,54 @@ static inline void brcmnand_write_fc(struct brcmnand_controller *ctrl,
__raw_writel(val, ctrl->nand_fc + word * 4);
}
+static void brcmnand_clear_ecc_addr(struct brcmnand_controller *ctrl)
+{
+
+ /* Clear error addresses */
+ brcmnand_write_reg(ctrl, BRCMNAND_UNCORR_ADDR, 0);
+ brcmnand_write_reg(ctrl, BRCMNAND_CORR_ADDR, 0);
+ brcmnand_write_reg(ctrl, BRCMNAND_UNCORR_EXT_ADDR, 0);
+ brcmnand_write_reg(ctrl, BRCMNAND_CORR_EXT_ADDR, 0);
+}
+
+static u64 brcmnand_get_uncorrecc_addr(struct brcmnand_controller *ctrl)
+{
+ u64 err_addr;
+
+ err_addr = brcmnand_read_reg(ctrl, BRCMNAND_UNCORR_ADDR);
+ err_addr |= ((u64)(brcmnand_read_reg(ctrl,
+ BRCMNAND_UNCORR_EXT_ADDR)
+ & 0xffff) << 32);
+
+ return err_addr;
+}
+
+static u64 brcmnand_get_correcc_addr(struct brcmnand_controller *ctrl)
+{
+ u64 err_addr;
+
+ err_addr = brcmnand_read_reg(ctrl, BRCMNAND_CORR_ADDR);
+ err_addr |= ((u64)(brcmnand_read_reg(ctrl,
+ BRCMNAND_CORR_EXT_ADDR)
+ & 0xffff) << 32);
+
+ return err_addr;
+}
+
+static void brcmnand_set_cmd_addr(struct mtd_info *mtd, u64 addr)
+{
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ struct brcmnand_host *host = nand_get_controller_data(chip);
+ struct brcmnand_controller *ctrl = host->ctrl;
+
+ brcmnand_write_reg(ctrl, BRCMNAND_CMD_EXT_ADDRESS,
+ (host->cs << 16) | ((addr >> 32) & 0xffff));
+ (void)brcmnand_read_reg(ctrl, BRCMNAND_CMD_EXT_ADDRESS);
+ brcmnand_write_reg(ctrl, BRCMNAND_CMD_ADDRESS,
+ lower_32_bits(addr));
+ (void)brcmnand_read_reg(ctrl, BRCMNAND_CMD_ADDRESS);
+}
+
static inline u16 brcmnand_cs_offset(struct brcmnand_controller *ctrl, int cs,
enum brcmnand_cs_reg reg)
{
@@ -627,7 +814,10 @@ static void brcmnand_wr_corr_thresh(struct brcmnand_host *host, u8 val)
enum brcmnand_reg reg = BRCMNAND_CORR_THRESHOLD;
int cs = host->cs;
- if (ctrl->nand_version >= 0x0702)
+ if (!ctrl->reg_offsets[reg])
+ return;
+
+ if (ctrl->nand_version == 0x0702)
bits = 7;
else if (ctrl->nand_version >= 0x0600)
bits = 6;
@@ -681,12 +871,14 @@ enum {
static inline u32 brcmnand_spare_area_mask(struct brcmnand_controller *ctrl)
{
- if (ctrl->nand_version >= 0x0702)
+ if (ctrl->nand_version == 0x0702)
return GENMASK(7, 0);
else if (ctrl->nand_version >= 0x0600)
return GENMASK(6, 0);
- else
+ else if (ctrl->nand_version >= 0x0303)
return GENMASK(5, 0);
+ else
+ return GENMASK(4, 0);
}
#define NAND_ACC_CONTROL_ECC_SHIFT 16
@@ -829,20 +1021,6 @@ static inline void brcmnand_set_wp(struct brcmnand_controller *ctrl, bool en)
* Flash DMA
***********************************************************************/
-enum flash_dma_reg {
- FLASH_DMA_REVISION = 0x00,
- FLASH_DMA_FIRST_DESC = 0x04,
- FLASH_DMA_FIRST_DESC_EXT = 0x08,
- FLASH_DMA_CTRL = 0x0c,
- FLASH_DMA_MODE = 0x10,
- FLASH_DMA_STATUS = 0x14,
- FLASH_DMA_INTERRUPT_DESC = 0x18,
- FLASH_DMA_INTERRUPT_DESC_EXT = 0x1c,
- FLASH_DMA_ERROR_STATUS = 0x20,
- FLASH_DMA_CURRENT_DESC = 0x24,
- FLASH_DMA_CURRENT_DESC_EXT = 0x28,
-};
-
static inline bool has_flash_dma(struct brcmnand_controller *ctrl)
{
return ctrl->flash_dma_base;
@@ -858,14 +1036,19 @@ static inline bool flash_dma_buf_ok(const void *buf)
#endif /* __UBOOT__ */
}
-static inline void flash_dma_writel(struct brcmnand_controller *ctrl, u8 offs,
- u32 val)
+static inline void flash_dma_writel(struct brcmnand_controller *ctrl,
+ enum flash_dma_reg dma_reg, u32 val)
{
+ u16 offs = ctrl->flash_dma_offsets[dma_reg];
+
brcmnand_writel(val, ctrl->flash_dma_base + offs);
}
-static inline u32 flash_dma_readl(struct brcmnand_controller *ctrl, u8 offs)
+static inline u32 flash_dma_readl(struct brcmnand_controller *ctrl,
+ enum flash_dma_reg dma_reg)
{
+ u16 offs = ctrl->flash_dma_offsets[dma_reg];
+
return brcmnand_readl(ctrl->flash_dma_base + offs);
}
@@ -1190,9 +1373,12 @@ static void brcmnand_send_cmd(struct brcmnand_host *host, int cmd)
{
struct brcmnand_controller *ctrl = host->ctrl;
int ret;
+ u64 cmd_addr;
+
+ cmd_addr = brcmnand_read_reg(ctrl, BRCMNAND_CMD_ADDRESS);
+
+ dev_dbg(ctrl->dev, "send native cmd %d addr 0x%llx\n", cmd, cmd_addr);
- dev_dbg(ctrl->dev, "send native cmd %d addr_lo 0x%x\n", cmd,
- brcmnand_read_reg(ctrl, BRCMNAND_CMD_ADDRESS));
BUG_ON(ctrl->cmd_pending != 0);
ctrl->cmd_pending = cmd;
@@ -1365,12 +1551,7 @@ static void brcmnand_cmdfunc(struct mtd_info *mtd, unsigned command,
if (!native_cmd)
return;
- brcmnand_write_reg(ctrl, BRCMNAND_CMD_EXT_ADDRESS,
- (host->cs << 16) | ((addr >> 32) & 0xffff));
- (void)brcmnand_read_reg(ctrl, BRCMNAND_CMD_EXT_ADDRESS);
- brcmnand_write_reg(ctrl, BRCMNAND_CMD_ADDRESS, lower_32_bits(addr));
- (void)brcmnand_read_reg(ctrl, BRCMNAND_CMD_ADDRESS);
-
+ brcmnand_set_cmd_addr(mtd, addr);
brcmnand_send_cmd(host, native_cmd);
brcmnand_waitfunc(mtd, chip);
@@ -1542,8 +1723,11 @@ static void brcmnand_dma_run(struct brcmnand_host *host, dma_addr_t desc)
flash_dma_writel(ctrl, FLASH_DMA_FIRST_DESC, lower_32_bits(desc));
(void)flash_dma_readl(ctrl, FLASH_DMA_FIRST_DESC);
- flash_dma_writel(ctrl, FLASH_DMA_FIRST_DESC_EXT, upper_32_bits(desc));
- (void)flash_dma_readl(ctrl, FLASH_DMA_FIRST_DESC_EXT);
+ if (ctrl->nand_version > 0x0602) {
+ flash_dma_writel(ctrl, FLASH_DMA_FIRST_DESC_EXT,
+ upper_32_bits(desc));
+ (void)flash_dma_readl(ctrl, FLASH_DMA_FIRST_DESC_EXT);
+ }
/* Start FLASH_DMA engine */
ctrl->dma_pending = true;
@@ -1600,20 +1784,10 @@ static int brcmnand_read_by_pio(struct mtd_info *mtd, struct nand_chip *chip,
struct brcmnand_controller *ctrl = host->ctrl;
int i, j, ret = 0;
- /* Clear error addresses */
- brcmnand_write_reg(ctrl, BRCMNAND_UNCORR_ADDR, 0);
- brcmnand_write_reg(ctrl, BRCMNAND_CORR_ADDR, 0);
- brcmnand_write_reg(ctrl, BRCMNAND_UNCORR_EXT_ADDR, 0);
- brcmnand_write_reg(ctrl, BRCMNAND_CORR_EXT_ADDR, 0);
-
- brcmnand_write_reg(ctrl, BRCMNAND_CMD_EXT_ADDRESS,
- (host->cs << 16) | ((addr >> 32) & 0xffff));
- (void)brcmnand_read_reg(ctrl, BRCMNAND_CMD_EXT_ADDRESS);
+ brcmnand_clear_ecc_addr(ctrl);
for (i = 0; i < trans; i++, addr += FC_BYTES) {
- brcmnand_write_reg(ctrl, BRCMNAND_CMD_ADDRESS,
- lower_32_bits(addr));
- (void)brcmnand_read_reg(ctrl, BRCMNAND_CMD_ADDRESS);
+ brcmnand_set_cmd_addr(mtd, addr);
/* SPARE_AREA_READ does not use ECC, so just use PAGE_READ */
brcmnand_send_cmd(host, CMD_PAGE_READ);
brcmnand_waitfunc(mtd, chip);
@@ -1633,21 +1807,15 @@ static int brcmnand_read_by_pio(struct mtd_info *mtd, struct nand_chip *chip,
host->hwcfg.sector_size_1k);
if (ret != -EBADMSG) {
- *err_addr = brcmnand_read_reg(ctrl,
- BRCMNAND_UNCORR_ADDR) |
- ((u64)(brcmnand_read_reg(ctrl,
- BRCMNAND_UNCORR_EXT_ADDR)
- & 0xffff) << 32);
+ *err_addr = brcmnand_get_uncorrecc_addr(ctrl);
+
if (*err_addr)
ret = -EBADMSG;
}
if (!ret) {
- *err_addr = brcmnand_read_reg(ctrl,
- BRCMNAND_CORR_ADDR) |
- ((u64)(brcmnand_read_reg(ctrl,
- BRCMNAND_CORR_EXT_ADDR)
- & 0xffff) << 32);
+ *err_addr = brcmnand_get_correcc_addr(ctrl);
+
if (*err_addr)
ret = -EUCLEAN;
}
@@ -1673,11 +1841,13 @@ static int brcmnand_read_by_pio(struct mtd_info *mtd, struct nand_chip *chip,
static int brcmstb_nand_verify_erased_page(struct mtd_info *mtd,
struct nand_chip *chip, void *buf, u64 addr)
{
- int i, sas;
- void *oob = chip->oob_poi;
+ struct mtd_oob_region ecc;
+ int i;
int bitflips = 0;
int page = addr >> chip->page_shift;
int ret;
+ void *ecc_bytes;
+ void *ecc_chunk;
if (!buf) {
#ifndef __UBOOT__
@@ -1689,16 +1859,20 @@ static int brcmstb_nand_verify_erased_page(struct mtd_info *mtd,
chip->pagebuf = -1;
}
- sas = mtd->oobsize / chip->ecc.steps;
-
/* read without ecc for verification */
ret = chip->ecc.read_page_raw(mtd, chip, buf, true, page);
if (ret)
return ret;
- for (i = 0; i < chip->ecc.steps; i++, oob += sas) {
- ret = nand_check_erased_ecc_chunk(buf, chip->ecc.size,
- oob, sas, NULL, 0,
+ for (i = 0; i < chip->ecc.steps; i++) {
+ ecc_chunk = buf + chip->ecc.size * i;
+
+ mtd_ooblayout_ecc(mtd, i, &ecc);
+ ecc_bytes = chip->oob_poi + ecc.offset;
+
+ ret = nand_check_erased_ecc_chunk(ecc_chunk, chip->ecc.size,
+ ecc_bytes, ecc.length,
+ NULL, 0,
chip->ecc.strength);
if (ret < 0)
return ret;
@@ -1721,7 +1895,7 @@ static int brcmnand_read(struct mtd_info *mtd, struct nand_chip *chip,
dev_dbg(ctrl->dev, "read %llx -> %p\n", (unsigned long long)addr, buf);
try_dmaread:
- brcmnand_write_reg(ctrl, BRCMNAND_UNCORR_COUNT, 0);
+ brcmnand_clear_ecc_addr(ctrl);
#ifndef __UBOOT__
if (has_flash_dma(ctrl) && !oob && flash_dma_buf_ok(buf)) {
@@ -1875,15 +2049,9 @@ static int brcmnand_write(struct mtd_info *mtd, struct nand_chip *chip,
}
#endif /* __UBOOT__ */
- brcmnand_write_reg(ctrl, BRCMNAND_CMD_EXT_ADDRESS,
- (host->cs << 16) | ((addr >> 32) & 0xffff));
- (void)brcmnand_read_reg(ctrl, BRCMNAND_CMD_EXT_ADDRESS);
-
for (i = 0; i < trans; i++, addr += FC_BYTES) {
/* full address MUST be set before populating FC */
- brcmnand_write_reg(ctrl, BRCMNAND_CMD_ADDRESS,
- lower_32_bits(addr));
- (void)brcmnand_read_reg(ctrl, BRCMNAND_CMD_ADDRESS);
+ brcmnand_set_cmd_addr(mtd, addr);
if (buf) {
brcmnand_soc_data_bus_prepare(ctrl->soc, false);
@@ -2044,7 +2212,7 @@ static int brcmnand_set_cfg(struct brcmnand_host *host,
(!!(cfg->device_width == 16) << CFG_BUS_WIDTH_SHIFT) |
(device_size << CFG_DEVICE_SIZE_SHIFT);
if (cfg_offs == cfg_ext_offs) {
- tmp |= (page_size << CFG_PAGE_SIZE_SHIFT) |
+ tmp |= (page_size << ctrl->page_size_shift) |
(block_size << CFG_BLK_SIZE_SHIFT);
nand_writereg(ctrl, cfg_offs, tmp);
} else {
@@ -2056,9 +2224,11 @@ static int brcmnand_set_cfg(struct brcmnand_host *host,
tmp = nand_readreg(ctrl, acc_control_offs);
tmp &= ~brcmnand_ecc_level_mask(ctrl);
- tmp |= cfg->ecc_level << NAND_ACC_CONTROL_ECC_SHIFT;
tmp &= ~brcmnand_spare_area_mask(ctrl);
- tmp |= cfg->spare_area_size;
+ if (ctrl->nand_version >= 0x0302) {
+ tmp |= cfg->ecc_level << NAND_ACC_CONTROL_ECC_SHIFT;
+ tmp |= cfg->spare_area_size;
+ }
nand_writereg(ctrl, acc_control_offs, tmp);
brcmnand_set_sector_size_1k(host, cfg->sector_size_1k);
@@ -2345,6 +2515,12 @@ static int brcmnand_init_cs(struct brcmnand_host *host, ofnode dn)
ret = nand_register(0, mtd);
#endif /* __UBOOT__ */
+ /* If OOB is written with ECC enabled it will cause ECC errors */
+ if (is_hamming_ecc(host->ctrl, &host->hwcfg)) {
+ chip->ecc.write_oob = brcmnand_write_oob_raw;
+ chip->ecc.read_oob = brcmnand_read_oob_raw;
+ }
+
return ret;
}
@@ -2438,6 +2614,8 @@ const struct dev_pm_ops brcmnand_pm_ops = {
EXPORT_SYMBOL_GPL(brcmnand_pm_ops);
static const struct of_device_id brcmnand_of_match[] = {
+ { .compatible = "brcm,brcmnand-v2.1" },
+ { .compatible = "brcm,brcmnand-v2.2" },
{ .compatible = "brcm,brcmnand-v4.0" },
{ .compatible = "brcm,brcmnand-v5.0" },
{ .compatible = "brcm,brcmnand-v6.0" },
@@ -2446,6 +2624,7 @@ static const struct of_device_id brcmnand_of_match[] = {
{ .compatible = "brcm,brcmnand-v7.0" },
{ .compatible = "brcm,brcmnand-v7.1" },
{ .compatible = "brcm,brcmnand-v7.2" },
+ { .compatible = "brcm,brcmnand-v7.3" },
{},
};
MODULE_DEVICE_TABLE(of, brcmnand_of_match);
@@ -2576,7 +2755,11 @@ int brcmnand_probe(struct udevice *dev, struct brcmnand_soc *soc)
goto err;
}
- flash_dma_writel(ctrl, FLASH_DMA_MODE, 1); /* linked-list */
+ /* initialize the dma version */
+ brcmnand_flash_dma_revision_init(ctrl);
+
+ /* linked-list and stop on error */
+ flash_dma_writel(ctrl, FLASH_DMA_MODE, FLASH_DMA_MODE_MASK);
flash_dma_writel(ctrl, FLASH_DMA_ERROR_STATUS, 0);
/* Allocate descriptor(s) */
diff --git a/drivers/mtd/nand/raw/kb9202_nand.c b/drivers/mtd/nand/raw/kb9202_nand.c
deleted file mode 100644
index 9d26532c78..0000000000
--- a/drivers/mtd/nand/raw/kb9202_nand.c
+++ /dev/null
@@ -1,134 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * (C) Copyright 2006
- * KwikByte <kb9200_dev@kwikbyte.com>
- *
- * (C) Copyright 2009
- * Matthias Kaehlcke <matthias@kaehlcke.net>
- */
-
-#include <common.h>
-#include <linux/mtd/rawnand.h>
-#include <asm/io.h>
-#include <asm/arch/AT91RM9200.h>
-#include <asm/arch/hardware.h>
-
-#include <nand.h>
-
-/*
- * hardware specific access to control-lines
- */
-
-#define MASK_ALE (1 << 22) /* our ALE is A22 */
-#define MASK_CLE (1 << 21) /* our CLE is A21 */
-
-#define KB9202_NAND_NCE (1 << 28) /* EN* on D28 */
-#define KB9202_NAND_BUSY (1 << 29) /* RB* on D29 */
-
-#define KB9202_SMC2_NWS (1 << 2)
-#define KB9202_SMC2_TDF (1 << 8)
-#define KB9202_SMC2_RWSETUP (1 << 24)
-#define KB9202_SMC2_RWHOLD (1 << 29)
-
-/*
- * Board-specific function to access device control signals
- */
-static void kb9202_nand_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
-{
- struct nand_chip *this = mtd_to_nand(mtd);
-
- if (ctrl & NAND_CTRL_CHANGE) {
- ulong IO_ADDR_W = (ulong) this->IO_ADDR_W;
-
- /* clear ALE and CLE bits */
- IO_ADDR_W &= ~(MASK_ALE | MASK_CLE);
-
- if (ctrl & NAND_CLE)
- IO_ADDR_W |= MASK_CLE;
-
- if (ctrl & NAND_ALE)
- IO_ADDR_W |= MASK_ALE;
-
- this->IO_ADDR_W = (void *) IO_ADDR_W;
-
- if (ctrl & NAND_NCE)
- writel(KB9202_NAND_NCE, AT91C_PIOC_CODR);
- else
- writel(KB9202_NAND_NCE, AT91C_PIOC_SODR);
- }
-
- if (cmd != NAND_CMD_NONE)
- writeb(cmd, this->IO_ADDR_W);
-}
-
-
-/*
- * Board-specific function to access the device ready signal.
- */
-static int kb9202_nand_ready(struct mtd_info *mtd)
-{
- return readl(AT91C_PIOC_PDSR) & KB9202_NAND_BUSY;
-}
-
-
-/*
- * Board-specific NAND init. Copied from include/linux/mtd/nand.h for reference.
- *
- * struct nand_chip - NAND Private Flash Chip Data
- * @IO_ADDR_R: [BOARDSPECIFIC] address to read the 8 I/O lines of the flash device
- * @IO_ADDR_W: [BOARDSPECIFIC] address to write the 8 I/O lines of the flash device
- * @hwcontrol: [BOARDSPECIFIC] hardwarespecific function for accesing control-lines
- * @dev_ready: [BOARDSPECIFIC] hardwarespecific function for accesing device ready/busy line
- * If set to NULL no access to ready/busy is available and the ready/busy information
- * is read from the chip status register
- * @enable_hwecc: [BOARDSPECIFIC] function to enable (reset) hardware ecc generator. Must only
- * be provided if a hardware ECC is available
- * @eccmode: [BOARDSPECIFIC] mode of ecc, see defines
- * @chip_delay: [BOARDSPECIFIC] chip dependent delay for transfering data from array to read regs (tR)
- * @options: [BOARDSPECIFIC] various chip options. They can partly be set to inform nand_scan about
- * special functionality. See the defines for further explanation
-*/
-/*
- * This routine initializes controller and GPIOs.
- */
-int board_nand_init(struct nand_chip *nand)
-{
- unsigned int value;
-
- nand->ecc.mode = NAND_ECC_SOFT;
- nand->cmd_ctrl = kb9202_nand_hwcontrol;
- nand->dev_ready = kb9202_nand_ready;
-
- /* in case running outside of bootloader */
- writel(1 << AT91C_ID_PIOC, AT91C_PMC_PCER);
-
- /* setup nand flash access (allow ample margin) */
- /* 4 wait states, 1 setup, 1 hold, 1 float for 8-bit device */
- writel(AT91C_SMC2_WSEN | KB9202_SMC2_NWS | KB9202_SMC2_TDF |
- AT91C_SMC2_DBW_8 | KB9202_SMC2_RWSETUP | KB9202_SMC2_RWHOLD,
- AT91C_SMC_CSR3);
-
- /* enable internal NAND controller */
- value = readl(AT91C_EBI_CSA);
- value |= AT91C_EBI_CS3A_SMC_SmartMedia;
- writel(value, AT91C_EBI_CSA);
-
- /* enable SMOE/SMWE */
- writel(AT91C_PC1_BFRDY_SMOE | AT91C_PC3_BFBAA_SMWE, AT91C_PIOC_ASR);
- writel(AT91C_PC1_BFRDY_SMOE | AT91C_PC3_BFBAA_SMWE, AT91C_PIOC_PDR);
- writel(AT91C_PC1_BFRDY_SMOE | AT91C_PC3_BFBAA_SMWE, AT91C_PIOC_OER);
-
- /* set NCE to high */
- writel(KB9202_NAND_NCE, AT91C_PIOC_SODR);
-
- /* disable output on pin connected to the busy line of the NAND */
- writel(KB9202_NAND_BUSY, AT91C_PIOC_ODR);
-
- /* enable the PIO to control NCE and BUSY */
- writel(KB9202_NAND_NCE | KB9202_NAND_BUSY, AT91C_PIOC_PER);
-
- /* enable output for NCE */
- writel(KB9202_NAND_NCE, AT91C_PIOC_OER);
-
- return (0);
-}
diff --git a/drivers/mtd/nand/raw/nand_bbt.c b/drivers/mtd/nand/raw/nand_bbt.c
index 911472e91e..cd451870a6 100644
--- a/drivers/mtd/nand/raw/nand_bbt.c
+++ b/drivers/mtd/nand/raw/nand_bbt.c
@@ -1330,6 +1330,7 @@ int nand_isreserved_bbt(struct mtd_info *mtd, loff_t offs)
* @mtd: MTD device structure
* @offs: offset in the device
* @allowbbt: allow access to bad block table region
+ * Return: 0 - good block, 1- bad block, 2 - reserved block
*/
int nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt)
{
@@ -1348,7 +1349,7 @@ int nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt)
case BBT_BLOCK_WORN:
return 1;
case BBT_BLOCK_RESERVED:
- return allowbbt ? 0 : 1;
+ return allowbbt ? 0 : 2;
}
return 1;
}
diff --git a/drivers/mtd/nand/raw/nand_util.c b/drivers/mtd/nand/raw/nand_util.c
index b2345dca7f..72cc24f403 100644
--- a/drivers/mtd/nand/raw/nand_util.c
+++ b/drivers/mtd/nand/raw/nand_util.c
@@ -113,9 +113,10 @@ int nand_erase_opts(struct mtd_info *mtd,
int ret = mtd_block_isbad(mtd, erase.addr);
if (ret > 0) {
if (!opts->quiet)
- printf("\rSkipping bad block at "
+ printf("\rSkipping %s at "
"0x%08llx "
" \n",
+ ret == 1 ? "bad block" : "bbt reserved",
erase.addr);
if (!opts->spread)
diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c
index 134bf22c80..70d8ae531e 100644
--- a/drivers/mtd/nand/spi/core.c
+++ b/drivers/mtd/nand/spi/core.c
@@ -979,8 +979,9 @@ static int spinand_detect(struct spinand_device *spinand)
ret = spinand_manufacturer_detect(spinand);
if (ret) {
- dev_err(spinand->slave->dev, "unknown raw ID %*phN\n",
- SPINAND_MAX_ID_LEN, spinand->id.data);
+ dev_err(spinand->slave->dev, "unknown raw ID %02x %02x %02x %02x\n",
+ spinand->id.data[0], spinand->id.data[1],
+ spinand->id.data[2], spinand->id.data[3]);
return ret;
}
diff --git a/drivers/mux/Makefile b/drivers/mux/Makefile
index 78ebf04c7a..d4e24789d3 100644
--- a/drivers/mux/Makefile
+++ b/drivers/mux/Makefile
@@ -3,5 +3,5 @@
# (C) Copyright 2019
# Jean-Jacques Hiblot <jjhiblot@ti.com>
-obj-$(CONFIG_$(SPL_)MULTIPLEXER) += mux-uclass.o
+obj-$(CONFIG_MULTIPLEXER) += mux-uclass.o
obj-$(CONFIG_$(SPL_)MUX_MMIO) += mmio.o
diff --git a/drivers/net/mvneta.c b/drivers/net/mvneta.c
index 0fbfad11d4..24933473fa 100644
--- a/drivers/net/mvneta.c
+++ b/drivers/net/mvneta.c
@@ -815,7 +815,7 @@ static void mvneta_defaults_set(struct mvneta_port *pp)
mvreg_write(pp, MVNETA_SDMA_CONFIG, val);
/* Enable PHY polling in hardware if not in fixed-link mode */
- if (!CONFIG_IS_ENABLED(PHY_FIXED) ||
+ if (!IS_ENABLED(CONFIG_PHY_FIXED) ||
pp->phydev->phy_id != PHY_FIXED_ID) {
mvreg_write(pp, MVNETA_PHY_ADDR, pp->phydev->addr);
@@ -1176,7 +1176,7 @@ static void mvneta_adjust_link(struct udevice *dev)
* be added). Also, why is ADVERT_FC enabled if we don't enable
* inband AN at all?
*/
- if (CONFIG_IS_ENABLED(PHY_FIXED) &&
+ if (IS_ENABLED(CONFIG_PHY_FIXED) &&
pp->phydev->phy_id == PHY_FIXED_ID)
val = MVNETA_GMAC_IB_BYPASS_AN_EN |
MVNETA_GMAC_SET_FC_EN |
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 5eaff053a0..6806e3c090 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -106,6 +106,9 @@ config PHY_AQUANTIA_FW_NAME
config PHY_ATHEROS
bool "Atheros Ethernet PHYs support"
+config SPL_PHY_ATHEROS
+ bool "Atheros Ethernet PHYs support (SPL)"
+
config PHY_BROADCOM
bool "Broadcom Ethernet PHYs support"
diff --git a/drivers/net/ravb.c b/drivers/net/ravb.c
index 5a835cc06f..0bc50dc733 100644
--- a/drivers/net/ravb.c
+++ b/drivers/net/ravb.c
@@ -310,7 +310,7 @@ static int ravb_phy_config(struct udevice *dev)
struct ravb_priv *eth = dev_get_priv(dev);
struct eth_pdata *pdata = dev_get_plat(dev);
struct phy_device *phydev;
- int mask = 0xffffffff, reg;
+ int reg;
if (dm_gpio_is_valid(&eth->reset_gpio)) {
dm_gpio_set_value(&eth->reset_gpio, 1);
@@ -319,12 +319,10 @@ static int ravb_phy_config(struct udevice *dev)
mdelay(1);
}
- phydev = phy_find_by_mask(eth->bus, mask);
+ phydev = phy_connect(eth->bus, -1, dev, pdata->phy_interface);
if (!phydev)
return -ENODEV;
- phy_connect_dev(phydev, dev, pdata->phy_interface);
-
eth->phydev = phydev;
phydev->supported &= SUPPORTED_100baseT_Full |
diff --git a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c
index cc49788012..211b2c6e55 100644
--- a/drivers/net/zynq_gem.c
+++ b/drivers/net/zynq_gem.c
@@ -738,7 +738,7 @@ static int gem_zynqmp_set_dynamic_config(struct udevice *dev)
u32 pm_info[2];
int ret;
- if (IS_ENABLED(CONFIG_ARCH_ZYNQMP)) {
+ if (IS_ENABLED(CONFIG_ARCH_ZYNQMP) && IS_ENABLED(CONFIG_ZYNQMP_FIRMWARE)) {
if (!zynqmp_pm_is_function_supported(PM_IOCTL,
IOCTL_SET_GEM_CONFIG)) {
ret = ofnode_read_u32_array(dev_ofnode(dev),
diff --git a/drivers/pci/pci_rom.c b/drivers/pci/pci_rom.c
index 47b6e6e5bc..f0dfe63149 100644
--- a/drivers/pci/pci_rom.c
+++ b/drivers/pci/pci_rom.c
@@ -325,7 +325,7 @@ err:
return ret;
}
-int vesa_setup_video_priv(struct vesa_mode_info *vesa,
+int vesa_setup_video_priv(struct vesa_mode_info *vesa, u64 fb,
struct video_priv *uc_priv,
struct video_uc_plat *plat)
{
@@ -348,9 +348,9 @@ int vesa_setup_video_priv(struct vesa_mode_info *vesa,
/* Use double buffering if enabled */
if (IS_ENABLED(CONFIG_VIDEO_COPY) && plat->base)
- plat->copy_base = vesa->phys_base_ptr;
+ plat->copy_base = fb;
else
- plat->base = vesa->phys_base_ptr;
+ plat->base = fb;
log_debug("base = %lx, copy_base = %lx\n", plat->base, plat->copy_base);
plat->size = vesa->bytes_per_scanline * vesa->y_resolution;
@@ -377,7 +377,9 @@ int vesa_setup_video(struct udevice *dev, int (*int15_handler)(void))
return ret;
}
- ret = vesa_setup_video_priv(&mode_info.vesa, uc_priv, plat);
+ ret = vesa_setup_video_priv(&mode_info.vesa,
+ mode_info.vesa.phys_base_ptr, uc_priv,
+ plat);
if (ret) {
if (ret == -ENFILE) {
/*
diff --git a/drivers/phy/phy-mtk-tphy.c b/drivers/phy/phy-mtk-tphy.c
index 2dd964f7b2..1883f9f83e 100644
--- a/drivers/phy/phy-mtk-tphy.c
+++ b/drivers/phy/phy-mtk-tphy.c
@@ -14,6 +14,7 @@
#include <asm/io.h>
#include <dm/device_compat.h>
#include <dm/devres.h>
+#include <linux/bitfield.h>
#include <linux/bitops.h>
#include <linux/delay.h>
@@ -43,19 +44,21 @@
#define U3P_USBPHYACR0 0x000
#define PA0_RG_U2PLL_FORCE_ON BIT(15)
+#define PA0_USB20_PLL_PREDIV GENMASK(7, 6)
#define PA0_RG_USB20_INTR_EN BIT(5)
+#define U3P_USBPHYACR2 0x008
+#define PA2_RG_U2PLL_BW GENMASK(21, 19)
+
#define U3P_USBPHYACR5 0x014
#define PA5_RG_U2_HSTX_SRCAL_EN BIT(15)
#define PA5_RG_U2_HSTX_SRCTRL GENMASK(14, 12)
-#define PA5_RG_U2_HSTX_SRCTRL_VAL(x) ((0x7 & (x)) << 12)
#define PA5_RG_U2_HS_100U_U3_EN BIT(11)
#define U3P_USBPHYACR6 0x018
#define PA6_RG_U2_BC11_SW_EN BIT(23)
#define PA6_RG_U2_OTG_VBUSCMP_EN BIT(20)
#define PA6_RG_U2_SQTH GENMASK(3, 0)
-#define PA6_RG_U2_SQTH_VAL(x) (0xf & (x))
#define U3P_U2PHYACR4 0x020
#define P2C_RG_USB20_GPIO_CTL BIT(9)
@@ -63,6 +66,14 @@
#define P2C_U2_GPIO_CTR_MSK \
(P2C_RG_USB20_GPIO_CTL | P2C_USB20_GPIO_MODE)
+#define U3P_U2PHYA_RESV 0x030
+#define P2R_RG_U2PLL_FBDIV_26M 0x1bb13b
+#define P2R_RG_U2PLL_FBDIV_48M 0x3c0000
+
+#define U3P_U2PHYA_RESV1 0x044
+#define P2R_RG_U2PLL_REFCLK_SEL BIT(5)
+#define P2R_RG_U2PLL_FRA_EN BIT(3)
+
#define U3P_U2PHYDTM0 0x068
#define P2C_FORCE_UART_EN BIT(26)
#define P2C_FORCE_DATAIN BIT(23)
@@ -72,11 +83,9 @@
#define P2C_FORCE_SUSPENDM BIT(18)
#define P2C_FORCE_TERMSEL BIT(17)
#define P2C_RG_DATAIN GENMASK(13, 10)
-#define P2C_RG_DATAIN_VAL(x) ((0xf & (x)) << 10)
#define P2C_RG_DMPULLDOWN BIT(7)
#define P2C_RG_DPPULLDOWN BIT(6)
#define P2C_RG_XCVRSEL GENMASK(5, 4)
-#define P2C_RG_XCVRSEL_VAL(x) ((0x3 & (x)) << 4)
#define P2C_RG_SUSPENDM BIT(3)
#define P2C_RG_TERMSEL BIT(2)
#define P2C_DTM0_PART_MASK \
@@ -104,72 +113,53 @@
#define U3P_U3_PHYA_REG0 0x000
#define P3A_RG_CLKDRV_OFF GENMASK(3, 2)
-#define P3A_RG_CLKDRV_OFF_VAL(x) ((0x3 & (x)) << 2)
#define U3P_U3_PHYA_REG1 0x004
#define P3A_RG_CLKDRV_AMP GENMASK(31, 29)
-#define P3A_RG_CLKDRV_AMP_VAL(x) ((0x7 & (x)) << 29)
#define U3P_U3_PHYA_REG6 0x018
#define P3A_RG_TX_EIDLE_CM GENMASK(31, 28)
-#define P3A_RG_TX_EIDLE_CM_VAL(x) ((0xf & (x)) << 28)
#define U3P_U3_PHYA_REG9 0x024
#define P3A_RG_RX_DAC_MUX GENMASK(5, 1)
-#define P3A_RG_RX_DAC_MUX_VAL(x) ((0x1f & (x)) << 1)
#define U3P_U3_PHYA_DA_REG0 0x100
#define P3A_RG_XTAL_EXT_PE2H GENMASK(17, 16)
-#define P3A_RG_XTAL_EXT_PE2H_VAL(x) ((0x3 & (x)) << 16)
#define P3A_RG_XTAL_EXT_PE1H GENMASK(13, 12)
-#define P3A_RG_XTAL_EXT_PE1H_VAL(x) ((0x3 & (x)) << 12)
#define P3A_RG_XTAL_EXT_EN_U3 GENMASK(11, 10)
-#define P3A_RG_XTAL_EXT_EN_U3_VAL(x) ((0x3 & (x)) << 10)
#define U3P_U3_PHYA_DA_REG4 0x108
#define P3A_RG_PLL_DIVEN_PE2H GENMASK(21, 19)
#define P3A_RG_PLL_BC_PE2H GENMASK(7, 6)
-#define P3A_RG_PLL_BC_PE2H_VAL(x) ((0x3 & (x)) << 6)
#define U3P_U3_PHYA_DA_REG5 0x10c
#define P3A_RG_PLL_BR_PE2H GENMASK(29, 28)
-#define P3A_RG_PLL_BR_PE2H_VAL(x) ((0x3 & (x)) << 28)
#define P3A_RG_PLL_IC_PE2H GENMASK(15, 12)
-#define P3A_RG_PLL_IC_PE2H_VAL(x) ((0xf & (x)) << 12)
#define U3P_U3_PHYA_DA_REG6 0x110
#define P3A_RG_PLL_IR_PE2H GENMASK(19, 16)
-#define P3A_RG_PLL_IR_PE2H_VAL(x) ((0xf & (x)) << 16)
#define U3P_U3_PHYA_DA_REG7 0x114
#define P3A_RG_PLL_BP_PE2H GENMASK(19, 16)
-#define P3A_RG_PLL_BP_PE2H_VAL(x) ((0xf & (x)) << 16)
#define U3P_U3_PHYA_DA_REG20 0x13c
#define P3A_RG_PLL_DELTA1_PE2H GENMASK(31, 16)
-#define P3A_RG_PLL_DELTA1_PE2H_VAL(x) ((0xffff & (x)) << 16)
#define U3P_U3_PHYA_DA_REG25 0x148
#define P3A_RG_PLL_DELTA_PE2H GENMASK(15, 0)
-#define P3A_RG_PLL_DELTA_PE2H_VAL(x) (0xffff & (x))
#define U3P_U3_PHYD_LFPS1 0x00c
#define P3D_RG_FWAKE_TH GENMASK(21, 16)
-#define P3D_RG_FWAKE_TH_VAL(x) ((0x3f & (x)) << 16)
#define U3P_U3_PHYD_CDR1 0x05c
#define P3D_RG_CDR_BIR_LTD1 GENMASK(28, 24)
-#define P3D_RG_CDR_BIR_LTD1_VAL(x) ((0x1f & (x)) << 24)
#define P3D_RG_CDR_BIR_LTD0 GENMASK(12, 8)
-#define P3D_RG_CDR_BIR_LTD0_VAL(x) ((0x1f & (x)) << 8)
#define U3P_U3_PHYD_RXDET1 0x128
#define P3D_RG_RXDET_STB2_SET GENMASK(17, 9)
-#define P3D_RG_RXDET_STB2_SET_VAL(x) ((0x1ff & (x)) << 9)
#define U3P_U3_PHYD_RXDET2 0x12c
#define P3D_RG_RXDET_STB2_SET_P3 GENMASK(8, 0)
-#define P3D_RG_RXDET_STB2_SET_P3_VAL(x) (0x1ff & (x))
#define U3P_SPLLC_XTALCTL3 0x018
#define XC3_RG_U3_XTAL_RX_PWD BIT(9)
@@ -179,66 +169,62 @@
#define PHYD_CTRL_SIGNAL_MODE4 0x1c
/* CDR Charge Pump P-path current adjustment */
#define RG_CDR_BICLTD1_GEN1_MSK GENMASK(23, 20)
-#define RG_CDR_BICLTD1_GEN1_VAL(x) ((0xf & (x)) << 20)
#define RG_CDR_BICLTD0_GEN1_MSK GENMASK(11, 8)
-#define RG_CDR_BICLTD0_GEN1_VAL(x) ((0xf & (x)) << 8)
#define PHYD_DESIGN_OPTION2 0x24
/* Symbol lock count selection */
#define RG_LOCK_CNT_SEL_MSK GENMASK(5, 4)
-#define RG_LOCK_CNT_SEL_VAL(x) ((0x3 & (x)) << 4)
#define PHYD_DESIGN_OPTION9 0x40
/* COMWAK GAP width window */
#define RG_TG_MAX_MSK GENMASK(20, 16)
-#define RG_TG_MAX_VAL(x) ((0x1f & (x)) << 16)
/* COMINIT GAP width window */
#define RG_T2_MAX_MSK GENMASK(13, 8)
-#define RG_T2_MAX_VAL(x) ((0x3f & (x)) << 8)
/* COMWAK GAP width window */
#define RG_TG_MIN_MSK GENMASK(7, 5)
-#define RG_TG_MIN_VAL(x) ((0x7 & (x)) << 5)
/* COMINIT GAP width window */
#define RG_T2_MIN_MSK GENMASK(4, 0)
-#define RG_T2_MIN_VAL(x) (0x1f & (x))
#define ANA_RG_CTRL_SIGNAL1 0x4c
/* TX driver tail current control for 0dB de-empahsis mdoe for Gen1 speed */
#define RG_IDRV_0DB_GEN1_MSK GENMASK(13, 8)
-#define RG_IDRV_0DB_GEN1_VAL(x) ((0x3f & (x)) << 8)
#define ANA_RG_CTRL_SIGNAL4 0x58
#define RG_CDR_BICLTR_GEN1_MSK GENMASK(23, 20)
-#define RG_CDR_BICLTR_GEN1_VAL(x) ((0xf & (x)) << 20)
/* Loop filter R1 resistance adjustment for Gen1 speed */
#define RG_CDR_BR_GEN2_MSK GENMASK(10, 8)
-#define RG_CDR_BR_GEN2_VAL(x) ((0x7 & (x)) << 8)
#define ANA_RG_CTRL_SIGNAL6 0x60
/* I-path capacitance adjustment for Gen1 */
#define RG_CDR_BC_GEN1_MSK GENMASK(28, 24)
-#define RG_CDR_BC_GEN1_VAL(x) ((0x1f & (x)) << 24)
#define RG_CDR_BIRLTR_GEN1_MSK GENMASK(4, 0)
-#define RG_CDR_BIRLTR_GEN1_VAL(x) (0x1f & (x))
#define ANA_EQ_EYE_CTRL_SIGNAL1 0x6c
/* RX Gen1 LEQ tuning step */
#define RG_EQ_DLEQ_LFI_GEN1_MSK GENMASK(11, 8)
-#define RG_EQ_DLEQ_LFI_GEN1_VAL(x) ((0xf & (x)) << 8)
#define ANA_EQ_EYE_CTRL_SIGNAL4 0xd8
#define RG_CDR_BIRLTD0_GEN1_MSK GENMASK(20, 16)
-#define RG_CDR_BIRLTD0_GEN1_VAL(x) ((0x1f & (x)) << 16)
#define ANA_EQ_EYE_CTRL_SIGNAL5 0xdc
#define RG_CDR_BIRLTD0_GEN3_MSK GENMASK(4, 0)
-#define RG_CDR_BIRLTD0_GEN3_VAL(x) (0x1f & (x))
enum mtk_phy_version {
MTK_TPHY_V1 = 1,
MTK_TPHY_V2,
};
+struct tphy_pdata {
+ enum mtk_phy_version version;
+
+ /*
+ * workaround only for mt8195:
+ * u2phy should use integer mode instead of fractional mode of
+ * 48M PLL, fix it by switching PLL to 26M from default 48M
+ */
+ bool sw_pll_48m_to_26m;
+};
+
struct u2phy_banks {
void __iomem *misc;
void __iomem *fmreg;
@@ -269,11 +255,32 @@ struct mtk_phy_instance {
struct mtk_tphy {
struct udevice *dev;
void __iomem *sif_base;
- enum mtk_phy_version version;
+ const struct tphy_pdata *pdata;
struct mtk_phy_instance **phys;
int nphys;
};
+/* workaround only for mt8195 */
+static void u2_phy_pll_26m_set(struct mtk_tphy *tphy,
+ struct mtk_phy_instance *instance)
+{
+ struct u2phy_banks *u2_banks = &instance->u2_banks;
+
+ if (!tphy->pdata->sw_pll_48m_to_26m)
+ return;
+
+ clrsetbits_le32(u2_banks->com + U3P_USBPHYACR0, PA0_USB20_PLL_PREDIV,
+ FIELD_PREP(PA0_USB20_PLL_PREDIV, 0));
+
+ clrsetbits_le32(u2_banks->com + U3P_USBPHYACR2, PA2_RG_U2PLL_BW,
+ FIELD_PREP(PA2_RG_U2PLL_BW, 3));
+
+ writel(P2R_RG_U2PLL_FBDIV_26M, u2_banks->com + U3P_U2PHYA_RESV);
+
+ setbits_le32(u2_banks->com + U3P_U2PHYA_RESV1,
+ P2R_RG_U2PLL_FRA_EN | P2R_RG_U2PLL_REFCLK_SEL);
+}
+
static void u2_phy_instance_init(struct mtk_tphy *tphy,
struct mtk_phy_instance *instance)
{
@@ -282,7 +289,8 @@ static void u2_phy_instance_init(struct mtk_tphy *tphy,
/* switch to USB function, and enable usb pll */
clrsetbits_le32(u2_banks->com + U3P_U2PHYDTM0,
P2C_FORCE_UART_EN | P2C_FORCE_SUSPENDM,
- P2C_RG_XCVRSEL_VAL(1) | P2C_RG_DATAIN_VAL(0));
+ FIELD_PREP(P2C_RG_XCVRSEL, 1) |
+ FIELD_PREP(P2C_RG_DATAIN, 0));
clrbits_le32(u2_banks->com + U3P_U2PHYDTM1, P2C_RG_UART_EN);
setbits_le32(u2_banks->com + U3P_USBPHYACR0, PA0_RG_USB20_INTR_EN);
@@ -295,11 +303,14 @@ static void u2_phy_instance_init(struct mtk_tphy *tphy,
/* DP/DM BC1.1 path Disable */
clrsetbits_le32(u2_banks->com + U3P_USBPHYACR6,
PA6_RG_U2_BC11_SW_EN | PA6_RG_U2_SQTH,
- PA6_RG_U2_SQTH_VAL(2));
+ FIELD_PREP(PA6_RG_U2_SQTH, 2));
/* set HS slew rate */
clrsetbits_le32(u2_banks->com + U3P_USBPHYACR5,
- PA5_RG_U2_HSTX_SRCTRL, PA5_RG_U2_HSTX_SRCTRL_VAL(4));
+ PA5_RG_U2_HSTX_SRCTRL,
+ FIELD_PREP(PA5_RG_U2_HSTX_SRCTRL, 4));
+
+ u2_phy_pll_26m_set(tphy, instance);
dev_dbg(tphy->dev, "%s(%d)\n", __func__, instance->index);
}
@@ -351,28 +362,31 @@ static void u3_phy_instance_init(struct mtk_tphy *tphy,
/* gating XSQ */
clrsetbits_le32(u3_banks->phya + U3P_U3_PHYA_DA_REG0,
- P3A_RG_XTAL_EXT_EN_U3, P3A_RG_XTAL_EXT_EN_U3_VAL(2));
+ P3A_RG_XTAL_EXT_EN_U3,
+ FIELD_PREP(P3A_RG_XTAL_EXT_EN_U3, 2));
clrsetbits_le32(u3_banks->phya + U3P_U3_PHYA_REG9,
- P3A_RG_RX_DAC_MUX, P3A_RG_RX_DAC_MUX_VAL(4));
+ P3A_RG_RX_DAC_MUX, FIELD_PREP(P3A_RG_RX_DAC_MUX, 4));
clrsetbits_le32(u3_banks->phya + U3P_U3_PHYA_REG6,
- P3A_RG_TX_EIDLE_CM, P3A_RG_TX_EIDLE_CM_VAL(0xe));
+ P3A_RG_TX_EIDLE_CM,
+ FIELD_PREP(P3A_RG_TX_EIDLE_CM, 0xe));
clrsetbits_le32(u3_banks->phyd + U3P_U3_PHYD_CDR1,
P3D_RG_CDR_BIR_LTD0 | P3D_RG_CDR_BIR_LTD1,
- P3D_RG_CDR_BIR_LTD0_VAL(0xc) |
- P3D_RG_CDR_BIR_LTD1_VAL(0x3));
+ FIELD_PREP(P3D_RG_CDR_BIR_LTD0, 0xc) |
+ FIELD_PREP(P3D_RG_CDR_BIR_LTD1, 0x3));
clrsetbits_le32(u3_banks->phyd + U3P_U3_PHYD_LFPS1,
- P3D_RG_FWAKE_TH, P3D_RG_FWAKE_TH_VAL(0x34));
+ P3D_RG_FWAKE_TH, FIELD_PREP(P3D_RG_FWAKE_TH, 0x34));
clrsetbits_le32(u3_banks->phyd + U3P_U3_PHYD_RXDET1,
- P3D_RG_RXDET_STB2_SET, P3D_RG_RXDET_STB2_SET_VAL(0x10));
+ P3D_RG_RXDET_STB2_SET,
+ FIELD_PREP(P3D_RG_RXDET_STB2_SET, 0x10));
clrsetbits_le32(u3_banks->phyd + U3P_U3_PHYD_RXDET2,
P3D_RG_RXDET_STB2_SET_P3,
- P3D_RG_RXDET_STB2_SET_P3_VAL(0x10));
+ FIELD_PREP(P3D_RG_RXDET_STB2_SET_P3, 0x10));
dev_dbg(tphy->dev, "%s(%d)\n", __func__, instance->index);
}
@@ -382,50 +396,52 @@ static void pcie_phy_instance_init(struct mtk_tphy *tphy,
{
struct u3phy_banks *u3_banks = &instance->u3_banks;
- if (tphy->version != MTK_TPHY_V1)
+ if (tphy->pdata->version != MTK_TPHY_V1)
return;
clrsetbits_le32(u3_banks->phya + U3P_U3_PHYA_DA_REG0,
P3A_RG_XTAL_EXT_PE1H | P3A_RG_XTAL_EXT_PE2H,
- P3A_RG_XTAL_EXT_PE1H_VAL(0x2) |
- P3A_RG_XTAL_EXT_PE2H_VAL(0x2));
+ FIELD_PREP(P3A_RG_XTAL_EXT_PE1H, 0x2) |
+ FIELD_PREP(P3A_RG_XTAL_EXT_PE2H, 0x2));
/* ref clk drive */
clrsetbits_le32(u3_banks->phya + U3P_U3_PHYA_REG1, P3A_RG_CLKDRV_AMP,
- P3A_RG_CLKDRV_AMP_VAL(0x4));
+ FIELD_PREP(P3A_RG_CLKDRV_AMP, 0x4));
clrsetbits_le32(u3_banks->phya + U3P_U3_PHYA_REG0, P3A_RG_CLKDRV_OFF,
- P3A_RG_CLKDRV_OFF_VAL(0x1));
+ FIELD_PREP(P3A_RG_CLKDRV_OFF, 0x1));
/* SSC delta -5000ppm */
clrsetbits_le32(u3_banks->phya + U3P_U3_PHYA_DA_REG20,
P3A_RG_PLL_DELTA1_PE2H,
- P3A_RG_PLL_DELTA1_PE2H_VAL(0x3c));
+ FIELD_PREP(P3A_RG_PLL_DELTA1_PE2H, 0x3c));
clrsetbits_le32(u3_banks->phya + U3P_U3_PHYA_DA_REG25,
P3A_RG_PLL_DELTA_PE2H,
- P3A_RG_PLL_DELTA_PE2H_VAL(0x36));
+ FIELD_PREP(P3A_RG_PLL_DELTA_PE2H, 0x36));
/* change pll BW 0.6M */
clrsetbits_le32(u3_banks->phya + U3P_U3_PHYA_DA_REG5,
P3A_RG_PLL_BR_PE2H | P3A_RG_PLL_IC_PE2H,
- P3A_RG_PLL_BR_PE2H_VAL(0x1) |
- P3A_RG_PLL_IC_PE2H_VAL(0x1));
+ FIELD_PREP(P3A_RG_PLL_BR_PE2H, 0x1) |
+ FIELD_PREP(P3A_RG_PLL_IC_PE2H, 0x1));
clrsetbits_le32(u3_banks->phya + U3P_U3_PHYA_DA_REG4,
P3A_RG_PLL_DIVEN_PE2H | P3A_RG_PLL_BC_PE2H,
- P3A_RG_PLL_BC_PE2H_VAL(0x3));
+ FIELD_PREP(P3A_RG_PLL_BC_PE2H, 0x3));
clrsetbits_le32(u3_banks->phya + U3P_U3_PHYA_DA_REG6,
- P3A_RG_PLL_IR_PE2H, P3A_RG_PLL_IR_PE2H_VAL(0x2));
+ P3A_RG_PLL_IR_PE2H,
+ FIELD_PREP(P3A_RG_PLL_IR_PE2H, 0x2));
clrsetbits_le32(u3_banks->phya + U3P_U3_PHYA_DA_REG7,
- P3A_RG_PLL_BP_PE2H, P3A_RG_PLL_BP_PE2H_VAL(0xa));
+ P3A_RG_PLL_BP_PE2H,
+ FIELD_PREP(P3A_RG_PLL_BP_PE2H, 0xa));
/* Tx Detect Rx Timing: 10us -> 5us */
clrsetbits_le32(u3_banks->phyd + U3P_U3_PHYD_RXDET1,
P3D_RG_RXDET_STB2_SET,
- P3D_RG_RXDET_STB2_SET_VAL(0x10));
+ FIELD_PREP(P3D_RG_RXDET_STB2_SET, 0x10));
clrsetbits_le32(u3_banks->phyd + U3P_U3_PHYD_RXDET2,
P3D_RG_RXDET_STB2_SET_P3,
- P3D_RG_RXDET_STB2_SET_P3_VAL(0x10));
+ FIELD_PREP(P3D_RG_RXDET_STB2_SET_P3, 0x10));
/* wait for PCIe subsys register to active */
udelay(3000);
@@ -438,36 +454,38 @@ static void sata_phy_instance_init(struct mtk_tphy *tphy,
clrsetbits_le32(u3_banks->phyd + ANA_RG_CTRL_SIGNAL6,
RG_CDR_BIRLTR_GEN1_MSK | RG_CDR_BC_GEN1_MSK,
- RG_CDR_BIRLTR_GEN1_VAL(0x6) |
- RG_CDR_BC_GEN1_VAL(0x1a));
+ FIELD_PREP(RG_CDR_BIRLTR_GEN1_MSK, 0x6) |
+ FIELD_PREP(RG_CDR_BC_GEN1_MSK, 0x1a));
clrsetbits_le32(u3_banks->phyd + ANA_EQ_EYE_CTRL_SIGNAL4,
RG_CDR_BIRLTD0_GEN1_MSK,
- RG_CDR_BIRLTD0_GEN1_VAL(0x18));
+ FIELD_PREP(RG_CDR_BIRLTD0_GEN1_MSK, 0x18));
clrsetbits_le32(u3_banks->phyd + ANA_EQ_EYE_CTRL_SIGNAL5,
RG_CDR_BIRLTD0_GEN3_MSK,
- RG_CDR_BIRLTD0_GEN3_VAL(0x06));
+ FIELD_PREP(RG_CDR_BIRLTD0_GEN3_MSK, 0x06));
clrsetbits_le32(u3_banks->phyd + ANA_RG_CTRL_SIGNAL4,
RG_CDR_BICLTR_GEN1_MSK | RG_CDR_BR_GEN2_MSK,
- RG_CDR_BICLTR_GEN1_VAL(0x0c) |
- RG_CDR_BR_GEN2_VAL(0x07));
+ FIELD_PREP(RG_CDR_BICLTR_GEN1_MSK, 0x0c) |
+ FIELD_PREP(RG_CDR_BR_GEN2_MSK, 0x07));
clrsetbits_le32(u3_banks->phyd + PHYD_CTRL_SIGNAL_MODE4,
RG_CDR_BICLTD0_GEN1_MSK | RG_CDR_BICLTD1_GEN1_MSK,
- RG_CDR_BICLTD0_GEN1_VAL(0x08) |
- RG_CDR_BICLTD1_GEN1_VAL(0x02));
+ FIELD_PREP(RG_CDR_BICLTD0_GEN1_MSK, 0x08) |
+ FIELD_PREP(RG_CDR_BICLTD1_GEN1_MSK, 0x02));
clrsetbits_le32(u3_banks->phyd + PHYD_DESIGN_OPTION2,
RG_LOCK_CNT_SEL_MSK,
- RG_LOCK_CNT_SEL_VAL(0x02));
+ FIELD_PREP(RG_LOCK_CNT_SEL_MSK, 0x02));
clrsetbits_le32(u3_banks->phyd + PHYD_DESIGN_OPTION9,
RG_T2_MIN_MSK | RG_TG_MIN_MSK |
RG_T2_MAX_MSK | RG_TG_MAX_MSK,
- RG_T2_MIN_VAL(0x12) | RG_TG_MIN_VAL(0x04) |
- RG_T2_MAX_VAL(0x31) | RG_TG_MAX_VAL(0x0e));
+ FIELD_PREP(RG_T2_MIN_MSK, 0x12) |
+ FIELD_PREP(RG_TG_MIN_MSK, 0x04) |
+ FIELD_PREP(RG_T2_MAX_MSK, 0x31) |
+ FIELD_PREP(RG_TG_MAX_MSK, 0x0e));
clrsetbits_le32(u3_banks->phyd + ANA_RG_CTRL_SIGNAL1,
RG_IDRV_0DB_GEN1_MSK,
- RG_IDRV_0DB_GEN1_VAL(0x20));
+ FIELD_PREP(RG_IDRV_0DB_GEN1_MSK, 0x20));
clrsetbits_le32(u3_banks->phyd + ANA_EQ_EYE_CTRL_SIGNAL1,
RG_EQ_DLEQ_LFI_GEN1_MSK,
- RG_EQ_DLEQ_LFI_GEN1_VAL(0x03));
+ FIELD_PREP(RG_EQ_DLEQ_LFI_GEN1_MSK, 0x03));
}
static void pcie_phy_instance_power_on(struct mtk_tphy *tphy,
@@ -662,11 +680,14 @@ static int mtk_phy_xlate(struct phy *phy,
return -EINVAL;
}
- if (tphy->version == MTK_TPHY_V1) {
+ switch (tphy->pdata->version) {
+ case MTK_TPHY_V1:
phy_v1_banks_init(tphy, instance);
- } else if (tphy->version == MTK_TPHY_V2) {
+ break;
+ case MTK_TPHY_V2:
phy_v2_banks_init(tphy, instance);
- } else {
+ break;
+ default:
dev_err(phy->dev, "phy version is not supported\n");
return -EINVAL;
}
@@ -696,13 +717,12 @@ static int mtk_tphy_probe(struct udevice *dev)
return -ENOMEM;
tphy->dev = dev;
- tphy->version = dev_get_driver_data(dev);
+ tphy->pdata = (void *)dev_get_driver_data(dev);
/* v1 has shared banks for usb/pcie mode, */
/* but not for sata mode */
- if (tphy->version == MTK_TPHY_V1) {
+ if (tphy->pdata->version == MTK_TPHY_V1)
tphy->sif_base = dev_read_addr_ptr(dev);
- }
dev_for_each_subnode(subnode, dev) {
struct mtk_phy_instance *instance;
@@ -737,9 +757,32 @@ static int mtk_tphy_probe(struct udevice *dev)
return 0;
}
+static struct tphy_pdata tphy_v1_pdata = {
+ .version = MTK_TPHY_V1,
+};
+
+static struct tphy_pdata tphy_v2_pdata = {
+ .version = MTK_TPHY_V2,
+};
+
+static struct tphy_pdata mt8195_pdata = {
+ .version = MTK_TPHY_V2,
+ .sw_pll_48m_to_26m = true,
+};
+
static const struct udevice_id mtk_tphy_id_table[] = {
- { .compatible = "mediatek,generic-tphy-v1", .data = MTK_TPHY_V1, },
- { .compatible = "mediatek,generic-tphy-v2", .data = MTK_TPHY_V2, },
+ {
+ .compatible = "mediatek,generic-tphy-v1",
+ .data = (ulong)&tphy_v1_pdata,
+ },
+ {
+ .compatible = "mediatek,generic-tphy-v2",
+ .data = (ulong)&tphy_v2_pdata,
+ },
+ {
+ .compatible = "mediatek,mt8195-tphy",
+ .data = (ulong)&mt8195_pdata,
+ },
{ }
};
diff --git a/drivers/phy/socionext/Kconfig b/drivers/phy/socionext/Kconfig
index bcd579e98e..de87d5b010 100644
--- a/drivers/phy/socionext/Kconfig
+++ b/drivers/phy/socionext/Kconfig
@@ -10,3 +10,11 @@ config PHY_UNIPHIER_PCIE
help
Enable this to support PHY implemented in PCIe controller
on UniPhier SoCs.
+
+config PHY_UNIPHIER_USB3
+ bool "UniPhier USB3 PHY driver"
+ depends on PHY && ARCH_UNIPHIER
+ imply REGMAP
+ help
+ Enable this to support PHY implemented in USB3 controller
+ on UniPhier SoCs.
diff --git a/drivers/phy/socionext/Makefile b/drivers/phy/socionext/Makefile
index 5484360b70..94d3aa68cf 100644
--- a/drivers/phy/socionext/Makefile
+++ b/drivers/phy/socionext/Makefile
@@ -4,3 +4,4 @@
#
obj-$(CONFIG_PHY_UNIPHIER_PCIE) += phy-uniphier-pcie.o
+obj-$(CONFIG_PHY_UNIPHIER_USB3) += phy-uniphier-usb3.o
diff --git a/drivers/phy/socionext/phy-uniphier-usb3.c b/drivers/phy/socionext/phy-uniphier-usb3.c
new file mode 100644
index 0000000000..1d65b0b08f
--- /dev/null
+++ b/drivers/phy/socionext/phy-uniphier-usb3.c
@@ -0,0 +1,168 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * phy_uniphier_usb3.c - Socionext UniPhier Usb3 PHY driver
+ * Copyright 2019-2023 Socionext, Inc.
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <generic-phy.h>
+
+#include <clk.h>
+#include <reset.h>
+
+struct uniphier_usb3phy_priv {
+ struct clk *clk_link, *clk_phy, *clk_parent, *clk_phyext;
+ struct reset_ctl *rst_link, *rst_phy, *rst_parent;
+};
+
+static int uniphier_usb3phy_init(struct phy *phy)
+{
+ struct uniphier_usb3phy_priv *priv = dev_get_priv(phy->dev);
+ int ret;
+
+ ret = clk_enable(priv->clk_phy);
+ if (ret)
+ return ret;
+
+ ret = reset_deassert(priv->rst_phy);
+ if (ret)
+ goto out_clk;
+
+ if (priv->clk_phyext) {
+ ret = clk_enable(priv->clk_phyext);
+ if (ret)
+ goto out_rst;
+ }
+
+ return 0;
+
+out_rst:
+ reset_assert(priv->rst_phy);
+out_clk:
+ clk_disable(priv->clk_phy);
+
+ return ret;
+}
+
+static int uniphier_usb3phy_exit(struct phy *phy)
+{
+ struct uniphier_usb3phy_priv *priv = dev_get_priv(phy->dev);
+
+ if (priv->clk_phyext)
+ clk_disable(priv->clk_phyext);
+
+ reset_assert(priv->rst_phy);
+ clk_disable(priv->clk_phy);
+
+ return 0;
+}
+
+static int uniphier_usb3phy_probe(struct udevice *dev)
+{
+ struct uniphier_usb3phy_priv *priv = dev_get_priv(dev);
+ int ret;
+
+ priv->clk_link = devm_clk_get(dev, "link");
+ if (IS_ERR(priv->clk_link)) {
+ printf("Failed to get link clock\n");
+ return PTR_ERR(priv->clk_link);
+ }
+
+ priv->clk_phy = devm_clk_get(dev, "phy");
+ if (IS_ERR(priv->clk_link)) {
+ printf("Failed to get phy clock\n");
+ return PTR_ERR(priv->clk_link);
+ }
+
+ priv->clk_parent = devm_clk_get_optional(dev, "gio");
+ if (IS_ERR(priv->clk_parent)) {
+ printf("Failed to get parent clock\n");
+ return PTR_ERR(priv->clk_parent);
+ }
+
+ priv->clk_phyext = devm_clk_get_optional(dev, "phy-ext");
+ if (IS_ERR(priv->clk_phyext)) {
+ printf("Failed to get external phy clock\n");
+ return PTR_ERR(priv->clk_phyext);
+ }
+
+ priv->rst_link = devm_reset_control_get(dev, "link");
+ if (IS_ERR(priv->rst_link)) {
+ printf("Failed to get link reset\n");
+ return PTR_ERR(priv->rst_link);
+ }
+
+ priv->rst_phy = devm_reset_control_get(dev, "phy");
+ if (IS_ERR(priv->rst_phy)) {
+ printf("Failed to get phy reset\n");
+ return PTR_ERR(priv->rst_phy);
+ }
+
+ priv->rst_parent = devm_reset_control_get_optional(dev, "gio");
+ if (IS_ERR(priv->rst_parent)) {
+ printf("Failed to get parent reset\n");
+ return PTR_ERR(priv->rst_parent);
+ }
+
+ if (priv->clk_parent) {
+ ret = clk_enable(priv->clk_parent);
+ if (ret)
+ return ret;
+ }
+ if (priv->rst_parent) {
+ ret = reset_deassert(priv->rst_parent);
+ if (ret)
+ goto out_clk_parent;
+ }
+
+ ret = clk_enable(priv->clk_link);
+ if (ret)
+ goto out_rst_parent;
+
+ ret = reset_deassert(priv->rst_link);
+ if (ret)
+ goto out_clk;
+
+ return 0;
+
+out_clk:
+ clk_disable(priv->clk_link);
+out_rst_parent:
+ if (priv->rst_parent)
+ reset_assert(priv->rst_parent);
+out_clk_parent:
+ if (priv->clk_parent)
+ clk_disable(priv->clk_parent);
+
+ return ret;
+}
+
+static struct phy_ops uniphier_usb3phy_ops = {
+ .init = uniphier_usb3phy_init,
+ .exit = uniphier_usb3phy_exit,
+};
+
+static const struct udevice_id uniphier_usb3phy_ids[] = {
+ { .compatible = "socionext,uniphier-pro4-usb3-ssphy" },
+ { .compatible = "socionext,uniphier-pro5-usb3-hsphy" },
+ { .compatible = "socionext,uniphier-pro5-usb3-ssphy" },
+ { .compatible = "socionext,uniphier-pxs2-usb3-hsphy" },
+ { .compatible = "socionext,uniphier-pxs2-usb3-ssphy" },
+ { .compatible = "socionext,uniphier-ld20-usb3-hsphy" },
+ { .compatible = "socionext,uniphier-ld20-usb3-ssphy" },
+ { .compatible = "socionext,uniphier-pxs3-usb3-hsphy" },
+ { .compatible = "socionext,uniphier-pxs3-usb3-ssphy" },
+ { .compatible = "socionext,uniphier-nx1-usb3-hsphy" },
+ { .compatible = "socionext,uniphier-nx1-usb3-ssphy" },
+ { }
+};
+
+U_BOOT_DRIVER(uniphier_usb3_phy) = {
+ .name = "uniphier-usb3-phy",
+ .id = UCLASS_PHY,
+ .of_match = uniphier_usb3phy_ids,
+ .ops = &uniphier_usb3phy_ops,
+ .probe = uniphier_usb3phy_probe,
+ .priv_auto = sizeof(struct uniphier_usb3phy_priv),
+};
diff --git a/drivers/ram/aspeed/sdram_ast2600.c b/drivers/ram/aspeed/sdram_ast2600.c
index 1876755412..d463933363 100644
--- a/drivers/ram/aspeed/sdram_ast2600.c
+++ b/drivers/ram/aspeed/sdram_ast2600.c
@@ -1089,13 +1089,13 @@ static int ast2600_sdrammc_probe(struct udevice *dev)
}
reg = readl(&priv->scu->mpll);
- reg &= ~(SCU_PLL_BYPASS | SCU_PLL_DIV_MASK |
+ reg &= ~(SCU_PLL_BYPASS | SCU_PLL_OFF | SCU_PLL_DIV_MASK |
SCU_PLL_DENUM_MASK | SCU_PLL_NUM_MASK);
- reg |= (SCU_PLL_RST | SCU_PLL_OFF | SCU_MPLL_FREQ_CFG);
+ reg |= (SCU_PLL_RST | SCU_MPLL_FREQ_CFG);
writel(reg, &priv->scu->mpll);
writel(SCU_MPLL_EXT_CFG, &priv->scu->mpll_ext);
udelay(100);
- reg &= ~(SCU_PLL_RST | SCU_PLL_OFF);
+ reg &= ~SCU_PLL_RST;
writel(reg, &priv->scu->mpll);
while ((readl(&priv->scu->mpll_ext) & BIT(31)) == 0)
diff --git a/drivers/reset/reset-uniphier.c b/drivers/reset/reset-uniphier.c
index 7adae51873..35e3ccebd7 100644
--- a/drivers/reset/reset-uniphier.c
+++ b/drivers/reset/reset-uniphier.c
@@ -2,6 +2,7 @@
/*
* Copyright (C) 2016 Socionext Inc.
* Author: Masahiro Yamada <yamada.masahiro@socionext.com>
+ * Author: Kunihiko Hayashi <hayashi.kunihiko@socionext.com>
*/
#include <common.h>
@@ -9,6 +10,8 @@
#include <log.h>
#include <malloc.h>
#include <reset-uclass.h>
+#include <clk.h>
+#include <reset.h>
#include <dm/device_compat.h>
#include <linux/bitops.h>
#include <linux/io.h>
@@ -178,10 +181,17 @@ static const struct uniphier_reset_data uniphier_pro4_peri_reset_data[] = {
UNIPHIER_RESET_END,
};
+/* Glue reset data */
+static const struct uniphier_reset_data uniphier_pro4_usb3_reset_data[] = {
+ UNIPHIER_RESETX(15, 0, 15)
+};
+
/* core implementaton */
struct uniphier_reset_priv {
void __iomem *base;
const struct uniphier_reset_data *data;
+ struct clk_bulk clks;
+ struct reset_ctl_bulk rsts;
};
static int uniphier_reset_update(struct reset_ctl *reset_ctl, int assert)
@@ -233,10 +243,47 @@ static const struct reset_ops uniphier_reset_ops = {
.rst_deassert = uniphier_reset_deassert,
};
+static int uniphier_reset_rst_init(struct udevice *dev)
+{
+ struct uniphier_reset_priv *priv = dev_get_priv(dev);
+ int ret;
+
+ ret = reset_get_bulk(dev, &priv->rsts);
+ if (ret == -ENOSYS || ret == -ENOENT)
+ return 0;
+ else if (ret)
+ return ret;
+
+ ret = reset_deassert_bulk(&priv->rsts);
+ if (ret)
+ reset_release_bulk(&priv->rsts);
+
+ return ret;
+}
+
+static int uniphier_reset_clk_init(struct udevice *dev)
+{
+ struct uniphier_reset_priv *priv = dev_get_priv(dev);
+ int ret;
+
+ ret = clk_get_bulk(dev, &priv->clks);
+ if (ret == -ENOSYS || ret == -ENOENT)
+ return 0;
+ if (ret)
+ return ret;
+
+ ret = clk_enable_bulk(&priv->clks);
+ if (ret)
+ clk_release_bulk(&priv->clks);
+
+ return ret;
+}
+
static int uniphier_reset_probe(struct udevice *dev)
{
struct uniphier_reset_priv *priv = dev_get_priv(dev);
fdt_addr_t addr;
+ int ret;
addr = dev_read_addr(dev->parent);
if (addr == FDT_ADDR_T_NONE)
@@ -248,7 +295,11 @@ static int uniphier_reset_probe(struct udevice *dev)
priv->data = (void *)dev_get_driver_data(dev);
- return 0;
+ ret = uniphier_reset_clk_init(dev);
+ if (ret)
+ return ret;
+
+ return uniphier_reset_rst_init(dev);
}
static const struct udevice_id uniphier_reset_match[] = {
@@ -355,6 +406,31 @@ static const struct udevice_id uniphier_reset_match[] = {
.compatible = "socionext,uniphier-pxs3-peri-reset",
.data = (ulong)uniphier_pro4_peri_reset_data,
},
+ /* USB glue reset */
+ {
+ .compatible = "socionext,uniphier-pro4-usb3-reset",
+ .data = (ulong)uniphier_pro4_usb3_reset_data,
+ },
+ {
+ .compatible = "socionext,uniphier-pro5-usb3-reset",
+ .data = (ulong)uniphier_pro4_usb3_reset_data,
+ },
+ {
+ .compatible = "socionext,uniphier-pxs2-usb3-reset",
+ .data = (ulong)uniphier_pro4_usb3_reset_data,
+ },
+ {
+ .compatible = "socionext,uniphier-ld20-usb3-reset",
+ .data = (ulong)uniphier_pro4_usb3_reset_data,
+ },
+ {
+ .compatible = "socionext,uniphier-pxs3-usb3-reset",
+ .data = (ulong)uniphier_pro4_usb3_reset_data,
+ },
+ {
+ .compatible = "socionext,uniphier-nx1-usb3-reset",
+ .data = (ulong)uniphier_pro4_usb3_reset_data,
+ },
{ /* sentinel */ }
};
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 35b6ed4d7c..fcfda2847c 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -231,6 +231,24 @@ config RTC_M41T62
Enable driver for ST's M41T62 compatible RTC devices (like RV-4162).
It is a serial (I2C) real-time clock (RTC) with alarm.
+config RTC_SANDBOX
+ bool "Enable sandbox RTC driver"
+ depends on SANDBOX && DM_RTC
+ default y
+ help
+ Enable the sandbox RTC driver. This driver connects to the RTC
+ emulator and is used to test the RTC uclasses and associated code,
+ as well as the I2C subsystem.
+
+config SPL_RTC_SANDBOX
+ bool "Enable sandbox RTC driver (SPL)"
+ depends on SANDBOX && SPL_DM_RTC
+ default y
+ help
+ Enable the sandbox RTC driver. This driver connects to the RTC
+ emulator and is used to test the RTC uclasses and associated code,
+ as well as the I2C subsystem.
+
config RTC_STM32
bool "Enable STM32 RTC driver"
depends on DM_RTC
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index 447551e15a..b6c9029c8f 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -16,7 +16,7 @@ obj-$(CONFIG_RTC_DS3231) += ds3231.o
obj-$(CONFIG_RTC_DS3232) += ds3232.o
obj-$(CONFIG_RTC_EMULATION) += emul_rtc.o
obj-$(CONFIG_RTC_HT1380) += ht1380.o
-obj-$(CONFIG_SANDBOX) += i2c_rtc_emul.o
+obj-$(CONFIG_$(SPL_TPL_)RTC_SANDBOX) += i2c_rtc_emul.o
obj-$(CONFIG_RTC_ISL1208) += isl1208.o
obj-$(CONFIG_RTC_M41T62) += m41t62.o
obj-$(CONFIG_RTC_MC13XXX) += mc13xxx-rtc.o
@@ -35,6 +35,6 @@ obj-$(CONFIG_RTC_RX8025) += rx8025.o
obj-$(CONFIG_RTC_RX8010SJ) += rx8010sj.o
obj-$(CONFIG_RTC_S35392A) += s35392a.o
obj-$(CONFIG_RTC_STM32) += stm32_rtc.o
-obj-$(CONFIG_SANDBOX) += sandbox_rtc.o
+obj-$(CONFIG_$(SPL_TPL_)RTC_SANDBOX) += sandbox_rtc.o
obj-$(CONFIG_RTC_ABX80X) += abx80x.o
obj-$(CONFIG_RTC_ZYNQMP) += zynqmp_rtc.o
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index bb5083201b..10d07daf27 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -415,6 +415,14 @@ config DEBUG_UART_SEMIHOSTING
start up driver model. The driver will be available until the real
driver model serial is running.
+config DEBUG_UART_SCIF
+ bool "Renesas SCIF UART"
+ depends on SH || ARCH_RMOBILE
+ help
+ Select this to enable a debug UART using the serial_sh driver. You
+ will need to provide parameters to make this work. The driver will
+ be available until the real driver-model serial is running.
+
config DEBUG_UART_SIFIVE
bool "SiFive UART"
depends on SIFIVE_SERIAL
diff --git a/drivers/serial/serial_sh.c b/drivers/serial/serial_sh.c
index 4671217b59..e08bdcadc9 100644
--- a/drivers/serial/serial_sh.c
+++ b/drivers/serial/serial_sh.c
@@ -249,9 +249,40 @@ U_BOOT_DRIVER(serial_sh) = {
#endif
.priv_auto = sizeof(struct uart_port),
};
+#endif
-#else /* CONFIG_DM_SERIAL */
+#if !CONFIG_IS_ENABLED(DM_SERIAL) || IS_ENABLED(CONFIG_DEBUG_UART_SCIF)
+#if defined(CFG_SCIF_A)
+ #define SCIF_BASE_PORT PORT_SCIFA
+#elif defined(CFG_SCI)
+ #define SCIF_BASE_PORT PORT_SCI
+#else
+ #define SCIF_BASE_PORT PORT_SCIF
+#endif
+
+static void sh_serial_init_nodm(struct uart_port *port)
+{
+ sh_serial_init_generic(port);
+ serial_setbrg();
+}
+
+static void sh_serial_putc_nondm(struct uart_port *port, const char c)
+{
+ if (c == '\n') {
+ while (1) {
+ if (serial_raw_putc(port, '\r') != -EAGAIN)
+ break;
+ }
+ }
+ while (1) {
+ if (serial_raw_putc(port, c) != -EAGAIN)
+ break;
+ }
+}
+#endif
+
+#if !CONFIG_IS_ENABLED(DM_SERIAL)
#if defined(CONFIG_CONS_SCIF0)
# define SCIF_BASE SCIF0_BASE
#elif defined(CONFIG_CONS_SCIF1)
@@ -274,19 +305,11 @@ U_BOOT_DRIVER(serial_sh) = {
# error "Default SCIF doesn't set....."
#endif
-#if defined(CFG_SCIF_A)
- #define SCIF_BASE_PORT PORT_SCIFA
-#elif defined(CONFIG_SCI)
- #define SCIF_BASE_PORT PORT_SCI
-#else
- #define SCIF_BASE_PORT PORT_SCIF
-#endif
-
static struct uart_port sh_sci = {
.membase = (unsigned char *)SCIF_BASE,
.mapbase = SCIF_BASE,
.type = SCIF_BASE_PORT,
-#ifdef CONFIG_SCIF_USE_EXT_CLK
+#ifdef CFG_SCIF_USE_EXT_CLK
.clk_mode = EXT_CLK,
#endif
};
@@ -301,28 +324,14 @@ static void sh_serial_setbrg(void)
static int sh_serial_init(void)
{
- struct uart_port *port = &sh_sci;
-
- sh_serial_init_generic(port);
- serial_setbrg();
+ sh_serial_init_nodm(&sh_sci);
return 0;
}
static void sh_serial_putc(const char c)
{
- struct uart_port *port = &sh_sci;
-
- if (c == '\n') {
- while (1) {
- if (serial_raw_putc(port, '\r') != -EAGAIN)
- break;
- }
- }
- while (1) {
- if (serial_raw_putc(port, c) != -EAGAIN)
- break;
- }
+ sh_serial_putc_nondm(&sh_sci, c);
}
static int sh_serial_tstc(void)
@@ -367,3 +376,29 @@ __weak struct serial_device *default_serial_console(void)
return &sh_serial_drv;
}
#endif /* CONFIG_DM_SERIAL */
+
+#ifdef CONFIG_DEBUG_UART_SCIF
+#include <debug_uart.h>
+
+static struct uart_port debug_uart_sci = {
+ .membase = (unsigned char *)CONFIG_DEBUG_UART_BASE,
+ .mapbase = CONFIG_DEBUG_UART_BASE,
+ .type = SCIF_BASE_PORT,
+#ifdef CFG_SCIF_USE_EXT_CLK
+ .clk_mode = EXT_CLK,
+#endif
+};
+
+static inline void _debug_uart_init(void)
+{
+ sh_serial_init_nodm(&debug_uart_sci);
+}
+
+static inline void _debug_uart_putc(int c)
+{
+ sh_serial_putc_nondm(&debug_uart_sci, c);
+}
+
+DEBUG_UART_FUNCS
+
+#endif
diff --git a/drivers/serial/serial_sh.h b/drivers/serial/serial_sh.h
index 660aaab663..eb8523dde5 100644
--- a/drivers/serial/serial_sh.h
+++ b/drivers/serial/serial_sh.h
@@ -406,13 +406,13 @@ SCIF_FNS(SCSPTR, 0, 0, 0x24, 16)
SCIF_FNS(SCLSR, 0, 0, 0x28, 16)
#else
-SCIF_FNS(SCFDR, 0x0e, 16, 0x1C, 16)
+SCIF_FNS(SCFDR, 0x0e, 16, 0x1C, 16)
#if defined(CONFIG_CPU_SH7722)
-SCIF_FNS(SCSPTR, 0, 0, 0, 0)
+SCIF_FNS(SCSPTR, 0, 0, 0, 0)
#else
-SCIF_FNS(SCSPTR, 0, 0, 0x20, 16)
+SCIF_FNS(SCSPTR, 0, 0, 0x20, 16)
#endif
-SCIF_FNS(SCLSR, 0, 0, 0x24, 16)
+SCIF_FNS(SCLSR, 0, 0, 0x24, 16)
#endif
SCIF_FNS(DL, 0, 0, 0x0, 0) /* dummy */
#endif
diff --git a/drivers/spi/xilinx_spi.c b/drivers/spi/xilinx_spi.c
index 4e9115dafe..9e6255a172 100644
--- a/drivers/spi/xilinx_spi.c
+++ b/drivers/spi/xilinx_spi.c
@@ -112,10 +112,9 @@ struct xilinx_spi_priv {
static int xilinx_spi_probe(struct udevice *bus)
{
struct xilinx_spi_priv *priv = dev_get_priv(bus);
- struct xilinx_spi_regs *regs = priv->regs;
-
- priv->regs = (struct xilinx_spi_regs *)dev_read_addr(bus);
+ struct xilinx_spi_regs *regs;
+ regs = priv->regs = (struct xilinx_spi_regs *)dev_read_addr(bus);
priv->fifo_depth = dev_read_u32_default(bus, "fifo-size", 0);
writel(SPISSR_RESET_VALUE, &regs->srr);
diff --git a/drivers/spi/zynqmp_gqspi.c b/drivers/spi/zynqmp_gqspi.c
index 335b458cb9..c4aee279aa 100644
--- a/drivers/spi/zynqmp_gqspi.c
+++ b/drivers/spi/zynqmp_gqspi.c
@@ -183,6 +183,11 @@ struct zynqmp_qspi_priv {
const struct spi_mem_op *op;
};
+__weak int zynqmp_mmio_write(const u32 address, const u32 mask, const u32 value)
+{
+ return 0;
+}
+
static int zynqmp_qspi_of_to_plat(struct udevice *bus)
{
struct zynqmp_qspi_plat *plat = dev_get_plat(bus);
diff --git a/drivers/sysreset/sysreset_mpc83xx.c b/drivers/sysreset/sysreset_mpc83xx.c
index c9a0326659..ca48328f7b 100644
--- a/drivers/sysreset/sysreset_mpc83xx.c
+++ b/drivers/sysreset/sysreset_mpc83xx.c
@@ -107,7 +107,7 @@ static int print_83xx_arb_event(bool force, char *buf, int size)
if (!force && !gd->arch.arbiter_event_address)
return 0;
- if (CONFIG_IS_ENABLED(DISPLAY_AER_FULL)) {
+ if (IS_ENABLED(CONFIG_DISPLAY_AER_FULL)) {
res = snprintf(buf, size,
"Arbiter Event Status:\n"
" %s: 0x%08lX\n"
@@ -184,7 +184,7 @@ static int mpc83xx_sysreset_get_status(struct udevice *dev, char *buf, int size)
* TODO(mario.six@gdsys.cc): Move this into a dedicated
* arbiter driver
*/
- if (CONFIG_IS_ENABLED(DISPLAY_AER_FULL) ||
+ if (IS_ENABLED(CONFIG_DISPLAY_AER_FULL) ||
IS_ENABLED(CONFIG_DISPLAY_AER_BRIEF)) {
/*
* If there was a bus monitor reset event, we force the arbiter
diff --git a/drivers/timer/Kconfig b/drivers/timer/Kconfig
index f32bd16227..915b2af160 100644
--- a/drivers/timer/Kconfig
+++ b/drivers/timer/Kconfig
@@ -145,6 +145,13 @@ config DESIGNWARE_APB_TIMER
Enables support for the Designware APB Timer driver. This timer is
present on Altera SoCFPGA SoCs.
+config FTTMR010_TIMER
+ bool "Faraday Technology timer support"
+ depends on TIMER
+ help
+ Select this to enable support for the timer found on
+ devices using Faraday Technology's IP.
+
config GXP_TIMER
bool "HPE GXP Timer"
depends on TIMER
diff --git a/drivers/timer/Makefile b/drivers/timer/Makefile
index 3c92113fc6..cdc20f5e94 100644
--- a/drivers/timer/Makefile
+++ b/drivers/timer/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_$(SPL_)ATMEL_PIT_TIMER) += atmel_pit_timer.o
obj-$(CONFIG_$(SPL_)ATMEL_TCB_TIMER) += atmel_tcb_timer.o
obj-$(CONFIG_CADENCE_TTC_TIMER) += cadence-ttc.o
obj-$(CONFIG_DESIGNWARE_APB_TIMER) += dw-apb-timer.o
+obj-$(CONFIG_FTTMR010_TIMER) += fttmr010_timer.o
obj-$(CONFIG_GXP_TIMER) += gxp-timer.o
obj-$(CONFIG_MPC83XX_TIMER) += mpc83xx_timer.o
obj-$(CONFIG_NOMADIK_MTU_TIMER) += nomadik-mtu-timer.o
diff --git a/drivers/timer/fttmr010_timer.c b/drivers/timer/fttmr010_timer.c
new file mode 100644
index 0000000000..b6289e6461
--- /dev/null
+++ b/drivers/timer/fttmr010_timer.c
@@ -0,0 +1,92 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2009 Faraday Technology
+ * Po-Yu Chuang <ratbert@faraday-tech.com>
+ *
+ * 23/08/2022 Port to DM
+ */
+#include <common.h>
+#include <dm.h>
+#include <log.h>
+#include <timer.h>
+#include <asm/io.h>
+#include <dm/ofnode.h>
+#include <faraday/fttmr010.h>
+#include <asm/global_data.h>
+
+#define TIMER_LOAD_VAL 0xffffffff
+
+struct fttmr010_timer_priv {
+ struct fttmr010 __iomem *regs;
+};
+
+static u64 fttmr010_timer_get_count(struct udevice *dev)
+{
+ struct fttmr010_timer_priv *priv = dev_get_priv(dev);
+ struct fttmr010 *tmr = priv->regs;
+ u32 now = TIMER_LOAD_VAL - readl(&tmr->timer3_counter);
+
+ /* increment tbu if tbl has rolled over */
+ if (now < gd->arch.tbl)
+ gd->arch.tbu++;
+ gd->arch.tbl = now;
+
+ return ((u64)gd->arch.tbu << 32) | gd->arch.tbl;
+}
+
+static int fttmr010_timer_probe(struct udevice *dev)
+{
+ struct fttmr010_timer_priv *priv = dev_get_priv(dev);
+ struct fttmr010 *tmr;
+ unsigned int cr;
+
+ priv->regs = dev_read_addr_ptr(dev);
+ if (!priv->regs)
+ return -EINVAL;
+ tmr = priv->regs;
+
+ debug("Faraday FTTMR010 timer revision 0x%08X\n", readl(&tmr->revision));
+
+ /* disable timers */
+ writel(0, &tmr->cr);
+
+ /* setup timer */
+ writel(TIMER_LOAD_VAL, &tmr->timer3_load);
+ writel(TIMER_LOAD_VAL, &tmr->timer3_counter);
+ writel(0, &tmr->timer3_match1);
+ writel(0, &tmr->timer3_match2);
+
+ /* we don't want timer to issue interrupts */
+ writel(FTTMR010_TM3_MATCH1 |
+ FTTMR010_TM3_MATCH2 |
+ FTTMR010_TM3_OVERFLOW,
+ &tmr->interrupt_mask);
+
+ cr = readl(&tmr->cr);
+ cr |= FTTMR010_TM3_CLOCK; /* use external clock */
+ cr |= FTTMR010_TM3_ENABLE;
+ writel(cr, &tmr->cr);
+
+ gd->arch.tbl = 0;
+ gd->arch.tbu = 0;
+
+ return 0;
+}
+
+static const struct timer_ops fttmr010_timer_ops = {
+ .get_count = fttmr010_timer_get_count,
+};
+
+static const struct udevice_id fttmr010_timer_ids[] = {
+ { .compatible = "faraday,fttmr010-timer" },
+ {}
+};
+
+U_BOOT_DRIVER(fttmr010_timer) = {
+ .name = "fttmr010_timer",
+ .id = UCLASS_TIMER,
+ .of_match = fttmr010_timer_ids,
+ .priv_auto = sizeof(struct fttmr010_timer_priv),
+ .probe = fttmr010_timer_probe,
+ .ops = &fttmr010_timer_ops,
+};
diff --git a/drivers/timer/tsc_timer.c b/drivers/timer/tsc_timer.c
index 192c7b71a5..f86a0b8692 100644
--- a/drivers/timer/tsc_timer.c
+++ b/drivers/timer/tsc_timer.c
@@ -404,6 +404,15 @@ static void tsc_timer_ensure_setup(bool early)
if (!gd->arch.clock_rate) {
unsigned long fast_calibrate;
+ /**
+ * There is no obvious way to obtain this information from EFI
+ * boot services. This value was measured on a Framework Laptop
+ * which has a 12th Gen Intel Core
+ */
+ if (IS_ENABLED(CONFIG_EFI_APP)) {
+ fast_calibrate = 2750;
+ goto done;
+ }
fast_calibrate = native_calibrate_tsc();
if (fast_calibrate)
goto done;
diff --git a/drivers/tpm/tpm2_tis_sandbox.c b/drivers/tpm/tpm2_tis_sandbox.c
index dd94bdc31f..e4004cfcca 100644
--- a/drivers/tpm/tpm2_tis_sandbox.c
+++ b/drivers/tpm/tpm2_tis_sandbox.c
@@ -810,7 +810,7 @@ static int sandbox_tpm2_open(struct udevice *dev)
struct sandbox_tpm2 *tpm = dev_get_priv(dev);
if (tpm->init_done)
- return -EIO;
+ return -EBUSY;
tpm->init_done = true;
diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig
index f010291d02..c0c8c16fd9 100644
--- a/drivers/usb/dwc3/Kconfig
+++ b/drivers/usb/dwc3/Kconfig
@@ -40,7 +40,7 @@ config SPL_USB_DWC3_GENERIC
config USB_DWC3_MESON_G12A
bool "Amlogic Meson G12A USB wrapper"
depends on DM_USB && USB_DWC3 && ARCH_MESON
- imply PHY
+ select PHY
help
Select this for Amlogic Meson G12A Platforms.
This wrapper supports Host and Peripheral operation modes.
@@ -48,14 +48,17 @@ config USB_DWC3_MESON_G12A
config USB_DWC3_MESON_GXL
bool "Amlogic Meson GXL USB wrapper"
depends on DM_USB && USB_DWC3 && ARCH_MESON
- imply PHY
+ select PHY
help
Select this for Amlogic Meson GXL and GXM Platforms.
This wrapper supports Host and Peripheral operation modes.
config USB_DWC3_UNIPHIER
bool "DesignWare USB3 Host Support on UniPhier Platforms"
- depends on ARCH_UNIPHIER && USB_XHCI_DWC3
+ depends on ARCH_UNIPHIER && USB_DWC3
+ select USB_DWC3_GENERIC
+ select PHY
+ select PHY_UNIPHIER_USB3
help
Support of USB2/3 functionality in Socionext UniPhier platforms.
Say 'Y' here if you have one such device.
diff --git a/drivers/usb/dwc3/dwc3-generic.c b/drivers/usb/dwc3/dwc3-generic.c
index ed1b9b630e..66da5a8d6f 100644
--- a/drivers/usb/dwc3/dwc3-generic.c
+++ b/drivers/usb/dwc3/dwc3-generic.c
@@ -28,11 +28,7 @@
#include <usb/xhci.h>
#include <asm/gpio.h>
-struct dwc3_glue_data {
- struct clk_bulk clks;
- struct reset_ctl_bulk resets;
- fdt_addr_t regs;
-};
+#include "dwc3-generic.h"
struct dwc3_generic_plat {
fdt_addr_t base;
@@ -68,10 +64,27 @@ static int dwc3_generic_probe(struct udevice *dev,
#if CONFIG_IS_ENABLED(OF_CONTROL)
dwc3_of_parse(dwc3);
+ /*
+ * There are currently four disparate placement possibilities of DWC3
+ * reference clock phandle in SoC DTs:
+ * - in top level glue node, with generic subnode without clock (ZynqMP)
+ * - in top level generic node, with no subnode (i.MX8MQ)
+ * - in generic subnode, with other clock in top level node (i.MX8MP)
+ * - in both top level node and generic subnode (Rockchip)
+ * Cover all the possibilities here by looking into both nodes, start
+ * with the top level node as that seems to be used in majority of DTs
+ * to reference the clock.
+ */
node = dev_ofnode(dev->parent);
index = ofnode_stringlist_search(node, "clock-names", "ref");
if (index < 0)
index = ofnode_stringlist_search(node, "clock-names", "ref_clk");
+ if (index < 0) {
+ node = dev_ofnode(dev);
+ index = ofnode_stringlist_search(node, "clock-names", "ref");
+ if (index < 0)
+ index = ofnode_stringlist_search(node, "clock-names", "ref_clk");
+ }
if (index >= 0)
dwc3->ref_clk = &glue->clks.clks[index];
#endif
@@ -258,11 +271,6 @@ U_BOOT_DRIVER(dwc3_generic_host) = {
};
#endif
-struct dwc3_glue_ops {
- void (*glue_configure)(struct udevice *dev, int index,
- enum usb_dr_mode mode);
-};
-
void dwc3_imx8mp_glue_configure(struct udevice *dev, int index,
enum usb_dr_mode mode)
{
@@ -398,54 +406,74 @@ struct dwc3_glue_ops ti_ops = {
.glue_configure = dwc3_ti_glue_configure,
};
-static int dwc3_glue_bind(struct udevice *parent)
+static int dwc3_glue_bind_common(struct udevice *parent, ofnode node)
{
- ofnode node;
- int ret;
+ const char *name = ofnode_get_name(node);
+ const char *driver = NULL;
enum usb_dr_mode dr_mode;
+ struct udevice *dev;
+ int ret;
- dr_mode = usb_get_dr_mode(dev_ofnode(parent));
-
- ofnode_for_each_subnode(node, dev_ofnode(parent)) {
- const char *name = ofnode_get_name(node);
- struct udevice *dev;
- const char *driver = NULL;
-
- debug("%s: subnode name: %s\n", __func__, name);
+ debug("%s: subnode name: %s\n", __func__, name);
- /* if the parent node doesn't have a mode check the leaf */
- if (!dr_mode)
- dr_mode = usb_get_dr_mode(node);
+ /* if the parent node doesn't have a mode check the leaf */
+ dr_mode = usb_get_dr_mode(dev_ofnode(parent));
+ if (!dr_mode)
+ dr_mode = usb_get_dr_mode(node);
- switch (dr_mode) {
- case USB_DR_MODE_PERIPHERAL:
- case USB_DR_MODE_OTG:
+ switch (dr_mode) {
+ case USB_DR_MODE_PERIPHERAL:
+ case USB_DR_MODE_OTG:
#if CONFIG_IS_ENABLED(DM_USB_GADGET)
- debug("%s: dr_mode: OTG or Peripheral\n", __func__);
- driver = "dwc3-generic-peripheral";
+ debug("%s: dr_mode: OTG or Peripheral\n", __func__);
+ driver = "dwc3-generic-peripheral";
#endif
- break;
+ break;
#if defined(CONFIG_SPL_USB_HOST) || !defined(CONFIG_SPL_BUILD)
- case USB_DR_MODE_HOST:
- debug("%s: dr_mode: HOST\n", __func__);
- driver = "dwc3-generic-host";
- break;
+ case USB_DR_MODE_HOST:
+ debug("%s: dr_mode: HOST\n", __func__);
+ driver = "dwc3-generic-host";
+ break;
#endif
- default:
- debug("%s: unsupported dr_mode\n", __func__);
- return -ENODEV;
- };
+ default:
+ debug("%s: unsupported dr_mode\n", __func__);
+ return -ENODEV;
+ };
- if (!driver)
- continue;
+ if (!driver)
+ return -ENXIO;
+
+ ret = device_bind_driver_to_node(parent, driver, name,
+ node, &dev);
+ if (ret) {
+ debug("%s: not able to bind usb device mode\n",
+ __func__);
+ return ret;
+ }
+
+ return 0;
+}
- ret = device_bind_driver_to_node(parent, driver, name,
- node, &dev);
- if (ret) {
- debug("%s: not able to bind usb device mode\n",
- __func__);
+int dwc3_glue_bind(struct udevice *parent)
+{
+ struct dwc3_glue_ops *ops = (struct dwc3_glue_ops *)dev_get_driver_data(parent);
+ ofnode node;
+ int ret;
+
+ if (ops && ops->glue_get_ctrl_dev) {
+ ret = ops->glue_get_ctrl_dev(parent, &node);
+ if (ret)
+ return ret;
+
+ return dwc3_glue_bind_common(parent, node);
+ }
+
+ ofnode_for_each_subnode(node, dev_ofnode(parent)) {
+ ret = dwc3_glue_bind_common(parent, node);
+ if (ret == -ENXIO)
+ continue;
+ if (ret)
return ret;
- }
}
return 0;
@@ -493,7 +521,7 @@ static int dwc3_glue_clk_init(struct udevice *dev,
return 0;
}
-static int dwc3_glue_probe(struct udevice *dev)
+int dwc3_glue_probe(struct udevice *dev)
{
struct dwc3_glue_ops *ops = (struct dwc3_glue_ops *)dev_get_driver_data(dev);
struct dwc3_glue_data *glue = dev_get_plat(dev);
@@ -514,7 +542,7 @@ static int dwc3_glue_probe(struct udevice *dev)
phy.dev = NULL;
}
- glue->regs = dev_read_addr(dev);
+ glue->regs = dev_read_addr_size_index(dev, 0, &glue->size);
ret = dwc3_glue_clk_init(dev, glue);
if (ret)
@@ -534,6 +562,12 @@ static int dwc3_glue_probe(struct udevice *dev)
if (ret)
return ret;
+ if (glue->clks.count == 0) {
+ ret = dwc3_glue_clk_init(child, glue);
+ if (ret)
+ return ret;
+ }
+
if (glue->resets.count == 0) {
ret = dwc3_glue_reset_init(child, glue);
if (ret)
@@ -553,7 +587,7 @@ static int dwc3_glue_probe(struct udevice *dev)
return 0;
}
-static int dwc3_glue_remove(struct udevice *dev)
+int dwc3_glue_remove(struct udevice *dev)
{
struct dwc3_glue_data *glue = dev_get_plat(dev);
diff --git a/drivers/usb/dwc3/dwc3-generic.h b/drivers/usb/dwc3/dwc3-generic.h
new file mode 100644
index 0000000000..40902c8923
--- /dev/null
+++ b/drivers/usb/dwc3/dwc3-generic.h
@@ -0,0 +1,33 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * dwc3-generic.h - Generic DWC3 Glue layer header
+ *
+ * Copyright (C) 2016 - 2018 Xilinx, Inc.
+ * Copyright (C) 2023 Socionext Inc.
+ */
+
+#ifndef __DRIVERS_USB_DWC3_GENERIC_H
+#define __DRIVERS_USB_DWC3_GENERIC_H
+
+#include <clk.h>
+#include <reset.h>
+#include <dwc3-uboot.h>
+
+struct dwc3_glue_data {
+ struct clk_bulk clks;
+ struct reset_ctl_bulk resets;
+ fdt_addr_t regs;
+ fdt_size_t size;
+};
+
+struct dwc3_glue_ops {
+ int (*glue_get_ctrl_dev)(struct udevice *parent, ofnode *node);
+ void (*glue_configure)(struct udevice *dev, int index,
+ enum usb_dr_mode mode);
+};
+
+int dwc3_glue_bind(struct udevice *parent);
+int dwc3_glue_probe(struct udevice *dev);
+int dwc3_glue_remove(struct udevice *dev);
+
+#endif
diff --git a/drivers/usb/dwc3/dwc3-uniphier.c b/drivers/usb/dwc3/dwc3-uniphier.c
index 54b52dcd66..ab85428a70 100644
--- a/drivers/usb/dwc3/dwc3-uniphier.c
+++ b/drivers/usb/dwc3/dwc3-uniphier.c
@@ -4,14 +4,17 @@
*
* Copyright (C) 2016-2017 Socionext Inc.
* Author: Masahiro Yamada <yamada.masahiro@socionext.com>
+ * Author: Kunihiko Hayashi <hayashi.kunihiko@socionext.com>
*/
#include <dm.h>
-#include <dm/device_compat.h>
+#include <dm/lists.h>
#include <linux/bitops.h>
-#include <linux/errno.h>
-#include <linux/io.h>
-#include <linux/sizes.h>
+#include <linux/usb/gadget.h>
+
+#include "core.h"
+#include "gadget.h"
+#include "dwc3-generic.h"
#define UNIPHIER_PRO4_DWC3_RESET 0x40
#define UNIPHIER_PRO4_DWC3_RESET_XIOMMU BIT(5)
@@ -27,8 +30,11 @@
#define UNIPHIER_PXS2_DWC3_RESET 0x00
#define UNIPHIER_PXS2_DWC3_RESET_XLINK BIT(15)
-static int uniphier_pro4_dwc3_init(void __iomem *regs)
+static void uniphier_pro4_dwc3_init(struct udevice *dev, int index,
+ enum usb_dr_mode mode)
{
+ struct dwc3_glue_data *glue = dev_get_plat(dev);
+ void *regs = map_physmem(glue->regs, glue->size, MAP_NOCACHE);
u32 tmp;
tmp = readl(regs + UNIPHIER_PRO4_DWC3_RESET);
@@ -36,11 +42,14 @@ static int uniphier_pro4_dwc3_init(void __iomem *regs)
tmp |= UNIPHIER_PRO4_DWC3_RESET_XIOMMU | UNIPHIER_PRO4_DWC3_RESET_XLINK;
writel(tmp, regs + UNIPHIER_PRO4_DWC3_RESET);
- return 0;
+ unmap_physmem(regs, MAP_NOCACHE);
}
-static int uniphier_pro5_dwc3_init(void __iomem *regs)
+static void uniphier_pro5_dwc3_init(struct udevice *dev, int index,
+ enum usb_dr_mode mode)
{
+ struct dwc3_glue_data *glue = dev_get_plat(dev);
+ void *regs = map_physmem(glue->regs, glue->size, MAP_NOCACHE);
u32 tmp;
tmp = readl(regs + UNIPHIER_PRO5_DWC3_RESET);
@@ -49,72 +58,97 @@ static int uniphier_pro5_dwc3_init(void __iomem *regs)
tmp |= UNIPHIER_PRO5_DWC3_RESET_XLINK | UNIPHIER_PRO5_DWC3_RESET_XIOMMU;
writel(tmp, regs + UNIPHIER_PRO5_DWC3_RESET);
- return 0;
+ unmap_physmem(regs, MAP_NOCACHE);
}
-static int uniphier_pxs2_dwc3_init(void __iomem *regs)
+static void uniphier_pxs2_dwc3_init(struct udevice *dev, int index,
+ enum usb_dr_mode mode)
{
+ struct dwc3_glue_data *glue = dev_get_plat(dev);
+ void *regs = map_physmem(glue->regs, glue->size, MAP_NOCACHE);
u32 tmp;
tmp = readl(regs + UNIPHIER_PXS2_DWC3_RESET);
tmp |= UNIPHIER_PXS2_DWC3_RESET_XLINK;
writel(tmp, regs + UNIPHIER_PXS2_DWC3_RESET);
- return 0;
+ unmap_physmem(regs, MAP_NOCACHE);
}
-static int uniphier_dwc3_probe(struct udevice *dev)
+static int dwc3_uniphier_glue_get_ctrl_dev(struct udevice *dev, ofnode *node)
{
- fdt_addr_t base;
- void __iomem *regs;
- int (*init)(void __iomem *regs);
- int ret;
+ struct udevice *child;
+ const char *name;
+ ofnode subnode;
+
+ /*
+ * "controller reset" belongs to glue logic, and it should be
+ * accessible in .glue_configure() before access to the controller
+ * begins.
+ */
+ ofnode_for_each_subnode(subnode, dev_ofnode(dev)) {
+ name = ofnode_get_name(subnode);
+ if (!strncmp(name, "reset", 5))
+ device_bind_driver_to_node(dev, "uniphier-reset",
+ name, subnode, &child);
+ }
+
+ /* Get controller node that is placed separately from the glue node */
+ *node = ofnode_by_compatible(dev_ofnode(dev->parent),
+ "socionext,uniphier-dwc3");
- base = dev_read_addr(dev);
- if (base == FDT_ADDR_T_NONE)
- return -EINVAL;
-
- regs = ioremap(base, SZ_32K);
- if (!regs)
- return -ENOMEM;
+ return 0;
+}
- init = (typeof(init))dev_get_driver_data(dev);
- ret = init(regs);
- if (ret)
- dev_err(dev, "failed to init glue layer\n");
+static const struct dwc3_glue_ops uniphier_pro4_dwc3_ops = {
+ .glue_get_ctrl_dev = dwc3_uniphier_glue_get_ctrl_dev,
+ .glue_configure = uniphier_pro4_dwc3_init,
+};
- iounmap(regs);
+static const struct dwc3_glue_ops uniphier_pro5_dwc3_ops = {
+ .glue_get_ctrl_dev = dwc3_uniphier_glue_get_ctrl_dev,
+ .glue_configure = uniphier_pro5_dwc3_init,
+};
- return ret;
-}
+static const struct dwc3_glue_ops uniphier_pxs2_dwc3_ops = {
+ .glue_get_ctrl_dev = dwc3_uniphier_glue_get_ctrl_dev,
+ .glue_configure = uniphier_pxs2_dwc3_init,
+};
static const struct udevice_id uniphier_dwc3_match[] = {
{
- .compatible = "socionext,uniphier-pro4-dwc3",
- .data = (ulong)uniphier_pro4_dwc3_init,
+ .compatible = "socionext,uniphier-pro4-dwc3-glue",
+ .data = (ulong)&uniphier_pro4_dwc3_ops,
+ },
+ {
+ .compatible = "socionext,uniphier-pro5-dwc3-glue",
+ .data = (ulong)&uniphier_pro5_dwc3_ops,
},
{
- .compatible = "socionext,uniphier-pro5-dwc3",
- .data = (ulong)uniphier_pro5_dwc3_init,
+ .compatible = "socionext,uniphier-pxs2-dwc3-glue",
+ .data = (ulong)&uniphier_pxs2_dwc3_ops,
},
{
- .compatible = "socionext,uniphier-pxs2-dwc3",
- .data = (ulong)uniphier_pxs2_dwc3_init,
+ .compatible = "socionext,uniphier-ld20-dwc3-glue",
+ .data = (ulong)&uniphier_pxs2_dwc3_ops,
},
{
- .compatible = "socionext,uniphier-ld20-dwc3",
- .data = (ulong)uniphier_pxs2_dwc3_init,
+ .compatible = "socionext,uniphier-pxs3-dwc3-glue",
+ .data = (ulong)&uniphier_pxs2_dwc3_ops,
},
{
- .compatible = "socionext,uniphier-pxs3-dwc3",
- .data = (ulong)uniphier_pxs2_dwc3_init,
+ .compatible = "socionext,uniphier-nx1-dwc3-glue",
+ .data = (ulong)&uniphier_pxs2_dwc3_ops,
},
{ /* sentinel */ }
};
-U_BOOT_DRIVER(usb_xhci) = {
+U_BOOT_DRIVER(dwc3_uniphier_wrapper) = {
.name = "uniphier-dwc3",
.id = UCLASS_SIMPLE_BUS,
.of_match = uniphier_dwc3_match,
- .probe = uniphier_dwc3_probe,
+ .bind = dwc3_glue_bind,
+ .probe = dwc3_glue_probe,
+ .remove = dwc3_glue_remove,
+ .plat_auto = sizeof(struct dwc3_glue_data),
};
diff --git a/drivers/usb/host/xhci-mtk.c b/drivers/usb/host/xhci-mtk.c
index 3838a990ec..63dfb793c6 100644
--- a/drivers/usb/host/xhci-mtk.c
+++ b/drivers/usb/host/xhci-mtk.c
@@ -14,8 +14,9 @@
#include <power/regulator.h>
#include <usb.h>
#include <usb/xhci.h>
-#include <linux/errno.h>
+#include <linux/bitfield.h>
#include <linux/compat.h>
+#include <linux/errno.h>
#include <linux/iopoll.h>
/* IPPC (IP Port Control) registers */
@@ -50,6 +51,25 @@
#define IPPC_U3_CTRL(p) (IPPC_U3_CTRL_0P + ((p) * 0x08))
#define IPPC_U2_CTRL(p) (IPPC_U2_CTRL_0P + ((p) * 0x08))
+/* xHCI CSR */
+#define LS_EOF_CFG 0x930
+#define LSEOF_OFFSET 0x89
+
+#define FS_EOF_CFG 0x934
+#define FSEOF_OFFSET 0x2e
+
+#define SS_GEN1_EOF_CFG 0x93c
+#define SSG1EOF_OFFSET 0x78
+
+#define HFCNTR_CFG 0x944
+#define ITP_DELTA_CLK_MASK GENMASK(5, 1)
+#define FRMCNT_LEV1_RANG_MASK GENMASK(19, 8)
+
+#define SS_GEN2_EOF_CFG 0x990
+#define SSG2EOF_OFFSET 0x3c
+
+#define XSEOF_OFFSET_MASK GENMASK(11, 0)
+
struct mtk_xhci {
struct xhci_ctrl ctrl; /* Needs to come first in this struct! */
struct xhci_hccr *hcd;
@@ -65,6 +85,30 @@ struct mtk_xhci {
u32 u2p_dis_msk;
};
+/*
+ * workaround for mt8195:
+ * MT8195 has 4 controllers, the controller1~3's default SOF/ITP interval
+ * is calculated from the frame counter clock 24M, but in fact, the clock
+ * is 48M.
+ */
+static void xhci_mtk_set_frame_interval(struct mtk_xhci *mtk)
+{
+ void __iomem *mac = (void __iomem *)mtk->hcd;
+
+ if (!ofnode_device_is_compatible(dev_ofnode(mtk->dev), "mediatek,mt8195-xhci"))
+ return;
+
+ clrsetbits_le32(mac + HFCNTR_CFG,
+ ITP_DELTA_CLK_MASK | FRMCNT_LEV1_RANG_MASK,
+ FIELD_PREP(ITP_DELTA_CLK_MASK, 0xa) |
+ FIELD_PREP(FRMCNT_LEV1_RANG_MASK, 0x12b));
+
+ clrsetbits_le32(mac + LS_EOF_CFG, XSEOF_OFFSET_MASK, LSEOF_OFFSET);
+ clrsetbits_le32(mac + FS_EOF_CFG, XSEOF_OFFSET_MASK, FSEOF_OFFSET);
+ clrsetbits_le32(mac + SS_GEN1_EOF_CFG, XSEOF_OFFSET_MASK, SSG1EOF_OFFSET);
+ clrsetbits_le32(mac + SS_GEN2_EOF_CFG, XSEOF_OFFSET_MASK, SSG2EOF_OFFSET);
+}
+
static int xhci_mtk_host_enable(struct mtk_xhci *mtk)
{
int u3_ports_disabed = 0;
@@ -278,6 +322,8 @@ static int xhci_mtk_probe(struct udevice *dev)
if (ret)
goto ssusb_init_err;
+ xhci_mtk_set_frame_interval(mtk);
+
mtk->ctrl.quirks = XHCI_MTK_HOST;
hcor = (struct xhci_hcor *)((uintptr_t)mtk->hcd +
HC_LENGTH(xhci_readl(&mtk->hcd->cr_capbase)));
@@ -308,6 +354,7 @@ static int xhci_mtk_remove(struct udevice *dev)
static const struct udevice_id xhci_mtk_ids[] = {
{ .compatible = "mediatek,mtk-xhci" },
+ { .compatible = "mediatek,mt8195-xhci" },
{ }
};
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 2a76d19cc8..60f4a4bf9c 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -16,6 +16,35 @@ config VIDEO
if VIDEO
+config VIDEO_FONT_4X6
+ bool "4 x 6 font size"
+ help
+ Font for video console driver, 4 x 6 pixels.
+ Provides character bitmap data in header file.
+ When selecting multiple fonts, you may want to enable CMD_SELECT_FONT too.
+
+config VIDEO_FONT_8X16
+ bool "8 x 16 font size"
+ default y
+ help
+ Font for video console driver, 8 x 16 pixels
+ Provides character bitmap data in header file.
+ When selecting multiple fonts, you may want to enable CMD_SELECT_FONT too.
+
+config VIDEO_FONT_SUN12X22
+ bool "12 x 22 font size"
+ help
+ Font for video console driver, 12 x 22 pixels
+ Provides character bitmap data in header file.
+ When selecting multiple fonts, you may want to enable CMD_SELECT_FONT too.
+
+config VIDEO_FONT_16X32
+ bool "16 x 32 font size"
+ help
+ Font for video console driver, 16 x 32 pixels
+ Provides character bitmap data in header file.
+ When selecting multiple fonts, you may want to enable CMD_SELECT_FONT too.
+
config VIDEO_LOGO
bool "Show the U-Boot logo on the display"
default y if !SPLASH_SCREEN
@@ -150,6 +179,7 @@ config CONSOLE_ROTATION
config CONSOLE_TRUETYPE
bool "Support a console that uses TrueType fonts"
+ select CMD_SELECT_FONT
help
TrueTrype fonts can provide outline-drawing capability rather than
needing to provide a bitmap for each font and size that is needed.
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index cdb7d9a54d..cb3f373645 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -9,6 +9,12 @@ obj-$(CONFIG_BACKLIGHT_GPIO) += backlight_gpio.o
obj-$(CONFIG_BACKLIGHT_PWM) += pwm_backlight.o
obj-$(CONFIG_CONSOLE_NORMAL) += console_normal.o
obj-$(CONFIG_CONSOLE_ROTATION) += console_rotate.o
+ifdef CONFIG_CONSOLE_NORMAL
+obj-y += console_core.o
+else ifdef CONFIG_CONSOLE_ROTATION
+obj-y += console_core.o
+endif
+obj-$(CONFIG_CONSOLE_ROTATION) += console_core.o
obj-$(CONFIG_CONSOLE_TRUETYPE) += console_truetype.o fonts/
obj-$(CONFIG_DISPLAY) += display-uclass.o
obj-$(CONFIG_VIDEO_MIPI_DSI) += dsi-host-uclass.o
diff --git a/drivers/video/console_core.c b/drivers/video/console_core.c
new file mode 100644
index 0000000000..d4f79c656a
--- /dev/null
+++ b/drivers/video/console_core.c
@@ -0,0 +1,212 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2015 Google, Inc
+ * (C) Copyright 2015
+ * Bernecker & Rainer Industrieelektronik GmbH - http://www.br-automation.com
+ * (C) Copyright 2023 Dzmitry Sankouski <dsankouski@gmail.com>
+ */
+
+#include <video.h>
+#include <video_console.h>
+#include <dm.h>
+#include <video_font.h>
+#include "vidconsole_internal.h"
+
+/**
+ * console_set_font() - prepare vidconsole for chosen font.
+ *
+ * @dev vidconsole device
+ * @fontdata pointer to font data struct
+ */
+static int console_set_font(struct udevice *dev, struct video_fontdata *fontdata)
+{
+ struct console_simple_priv *priv = dev_get_priv(dev);
+ struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev);
+ struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
+
+ debug("console_simple: setting %s font\n", fontdata->name);
+ debug("width: %d\n", fontdata->width);
+ debug("byte width: %d\n", fontdata->byte_width);
+ debug("height: %d\n", fontdata->height);
+
+ priv->fontdata = fontdata;
+ vc_priv->x_charsize = fontdata->width;
+ vc_priv->y_charsize = fontdata->height;
+ if (vid_priv->rot % 2) {
+ vc_priv->cols = vid_priv->ysize / fontdata->width;
+ vc_priv->rows = vid_priv->xsize / fontdata->height;
+ vc_priv->xsize_frac = VID_TO_POS(vid_priv->ysize);
+ } else {
+ vc_priv->cols = vid_priv->xsize / fontdata->width;
+ vc_priv->rows = vid_priv->ysize / fontdata->height;
+ }
+
+ return 0;
+}
+
+int check_bpix_support(int bpix)
+{
+ if (bpix == VIDEO_BPP8 && IS_ENABLED(CONFIG_VIDEO_BPP8))
+ return 0;
+ else if (bpix == VIDEO_BPP16 && IS_ENABLED(CONFIG_VIDEO_BPP16))
+ return 0;
+ else if (bpix == VIDEO_BPP32 && IS_ENABLED(CONFIG_VIDEO_BPP32))
+ return 0;
+ else
+ return -ENOSYS;
+}
+
+inline void fill_pixel_and_goto_next(void **dstp, u32 value, int pbytes, int step)
+{
+ u8 *dst_byte = *dstp;
+
+ if (pbytes == 4) {
+ u32 *dst = *dstp;
+ *dst = value;
+ }
+ if (pbytes == 2) {
+ u16 *dst = *dstp;
+ *dst = value;
+ }
+ if (pbytes == 1) {
+ u8 *dst = *dstp;
+ *dst = value;
+ }
+ *dstp = dst_byte + step;
+}
+
+int fill_char_vertically(uchar *pfont, void **line, struct video_priv *vid_priv,
+ struct video_fontdata *fontdata, bool direction)
+{
+ int step, line_step, pbytes, bitcount, width_remainder, ret;
+ void *dst;
+
+ ret = check_bpix_support(vid_priv->bpix);
+ if (ret)
+ return ret;
+
+ pbytes = VNBYTES(vid_priv->bpix);
+ if (direction) {
+ step = -pbytes;
+ line_step = -vid_priv->line_length;
+ } else {
+ step = pbytes;
+ line_step = vid_priv->line_length;
+ }
+
+ width_remainder = fontdata->width % 8;
+ for (int row = 0; row < fontdata->height; row++) {
+ uchar bits;
+
+ bitcount = 8;
+ dst = *line;
+ for (int col = 0; col < fontdata->byte_width; col++) {
+ if (width_remainder) {
+ bool is_last_col = (fontdata->byte_width - col == 1);
+
+ if (is_last_col)
+ bitcount = width_remainder;
+ }
+ bits = pfont[col];
+
+ for (int bit = 0; bit < bitcount; bit++) {
+ u32 value = (bits & 0x80) ?
+ vid_priv->colour_fg :
+ vid_priv->colour_bg;
+
+ fill_pixel_and_goto_next(&dst,
+ value,
+ pbytes,
+ step
+ );
+ bits <<= 1;
+ }
+ }
+ *line += line_step;
+ pfont += fontdata->byte_width;
+ }
+ return ret;
+}
+
+int fill_char_horizontally(uchar *pfont, void **line, struct video_priv *vid_priv,
+ struct video_fontdata *fontdata, bool direction)
+{
+ int step, line_step, pbytes, bitcount = 8, width_remainder, ret;
+ void *dst;
+ u8 mask;
+
+ ret = check_bpix_support(vid_priv->bpix);
+ if (ret)
+ return ret;
+
+ pbytes = VNBYTES(vid_priv->bpix);
+ if (direction) {
+ step = -pbytes;
+ line_step = vid_priv->line_length;
+ } else {
+ step = pbytes;
+ line_step = -vid_priv->line_length;
+ }
+
+ width_remainder = fontdata->width % 8;
+ for (int col = 0; col < fontdata->byte_width; col++) {
+ mask = 0x80;
+ if (width_remainder) {
+ bool is_last_col = (fontdata->byte_width - col == 1);
+
+ if (is_last_col)
+ bitcount = width_remainder;
+ }
+ for (int bit = 0; bit < bitcount; bit++) {
+ dst = *line;
+ for (int row = 0; row < fontdata->height; row++) {
+ u32 value = (pfont[row * fontdata->byte_width + col]
+ & mask) ? vid_priv->colour_fg : vid_priv->colour_bg;
+
+ fill_pixel_and_goto_next(&dst,
+ value,
+ pbytes,
+ step
+ );
+ }
+ *line += line_step;
+ mask >>= 1;
+ }
+ }
+ return ret;
+}
+
+int console_probe(struct udevice *dev)
+{
+ return console_set_font(dev, fonts);
+}
+
+const char *console_simple_get_font_size(struct udevice *dev, uint *sizep)
+{
+ struct console_simple_priv *priv = dev_get_priv(dev);
+
+ *sizep = priv->fontdata->width;
+
+ return priv->fontdata->name;
+}
+
+int console_simple_get_font(struct udevice *dev, int seq, struct vidfont_info *info)
+{
+ info->name = fonts[seq].name;
+
+ return 0;
+}
+
+int console_simple_select_font(struct udevice *dev, const char *name, uint size)
+{
+ struct video_fontdata *font;
+
+ for (font = fonts; font->name; font++) {
+ if (!strcmp(name, font->name)) {
+ console_set_font(dev, font);
+ return 0;
+ }
+ };
+ printf("no such font: %s, make sure it's name has <width>x<height> format\n", name);
+ return -ENOENT;
+}
diff --git a/drivers/video/console_normal.c b/drivers/video/console_normal.c
index 04f022491e..413c7abee9 100644
--- a/drivers/video/console_normal.c
+++ b/drivers/video/console_normal.c
@@ -1,10 +1,9 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (c) 2015 Google, Inc
- * (C) Copyright 2001-2015
- * DENX Software Engineering -- wd@denx.de
- * Compulab Ltd - http://compulab.co.il/
+ * (C) Copyright 2015
* Bernecker & Rainer Industrieelektronik GmbH - http://www.br-automation.com
+ * (C) Copyright 2023 Dzmitry Sankouski <dsankouski@gmail.com>
*/
#include <common.h>
@@ -12,47 +11,30 @@
#include <video.h>
#include <video_console.h>
#include <video_font.h> /* Get font data, width and height */
+#include "vidconsole_internal.h"
-static int console_normal_set_row(struct udevice *dev, uint row, int clr)
+static int console_set_row(struct udevice *dev, uint row, int clr)
{
struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
- void *line, *end;
- int pixels = VIDEO_FONT_HEIGHT * vid_priv->xsize;
+ struct console_simple_priv *priv = dev_get_priv(dev);
+ struct video_fontdata *fontdata = priv->fontdata;
+ void *line, *dst, *end;
+ int pixels = fontdata->height * vid_priv->xsize;
int ret;
int i;
+ int pbytes;
+
+ ret = check_bpix_support(vid_priv->bpix);
+ if (ret)
+ return ret;
+
+ line = vid_priv->fb + row * fontdata->height * vid_priv->line_length;
+ dst = line;
+ pbytes = VNBYTES(vid_priv->bpix);
+ for (i = 0; i < pixels; i++)
+ fill_pixel_and_goto_next(&dst, clr, pbytes, pbytes);
+ end = dst;
- line = vid_priv->fb + row * VIDEO_FONT_HEIGHT * vid_priv->line_length;
- switch (vid_priv->bpix) {
- case VIDEO_BPP8:
- if (IS_ENABLED(CONFIG_VIDEO_BPP8)) {
- uint8_t *dst = line;
-
- for (i = 0; i < pixels; i++)
- *dst++ = clr;
- end = dst;
- break;
- }
- case VIDEO_BPP16:
- if (IS_ENABLED(CONFIG_VIDEO_BPP16)) {
- uint16_t *dst = line;
-
- for (i = 0; i < pixels; i++)
- *dst++ = clr;
- end = dst;
- break;
- }
- case VIDEO_BPP32:
- if (IS_ENABLED(CONFIG_VIDEO_BPP32)) {
- uint32_t *dst = line;
-
- for (i = 0; i < pixels; i++)
- *dst++ = clr;
- end = dst;
- break;
- }
- default:
- return -ENOSYS;
- }
ret = vidconsole_sync_copy(dev, line, end);
if (ret)
return ret;
@@ -60,18 +42,20 @@ static int console_normal_set_row(struct udevice *dev, uint row, int clr)
return 0;
}
-static int console_normal_move_rows(struct udevice *dev, uint rowdst,
- uint rowsrc, uint count)
+static int console_move_rows(struct udevice *dev, uint rowdst,
+ uint rowsrc, uint count)
{
struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
+ struct console_simple_priv *priv = dev_get_priv(dev);
+ struct video_fontdata *fontdata = priv->fontdata;
void *dst;
void *src;
int size;
int ret;
- dst = vid_priv->fb + rowdst * VIDEO_FONT_HEIGHT * vid_priv->line_length;
- src = vid_priv->fb + rowsrc * VIDEO_FONT_HEIGHT * vid_priv->line_length;
- size = VIDEO_FONT_HEIGHT * vid_priv->line_length * count;
+ dst = vid_priv->fb + rowdst * fontdata->height * vid_priv->line_length;
+ src = vid_priv->fb + rowsrc * fontdata->height * vid_priv->line_length;
+ size = fontdata->height * vid_priv->line_length * count;
ret = vidconsole_memmove(dev, dst, src, size);
if (ret)
return ret;
@@ -79,100 +63,53 @@ static int console_normal_move_rows(struct udevice *dev, uint rowdst,
return 0;
}
-static int console_normal_putc_xy(struct udevice *dev, uint x_frac, uint y,
- char ch)
+static int console_putc_xy(struct udevice *dev, uint x_frac, uint y, char ch)
{
struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev);
struct udevice *vid = dev->parent;
struct video_priv *vid_priv = dev_get_uclass_priv(vid);
- int i, row;
- void *start;
- void *line;
- int ret;
+ struct console_simple_priv *priv = dev_get_priv(dev);
+ struct video_fontdata *fontdata = priv->fontdata;
+ int pbytes = VNBYTES(vid_priv->bpix);
+ int x, linenum, ret;
+ void *start, *line;
+ uchar *pfont = fontdata->video_fontdata +
+ (u8)ch * fontdata->char_pixel_bytes;
- start = vid_priv->fb + y * vid_priv->line_length +
- VID_TO_PIXEL(x_frac) * VNBYTES(vid_priv->bpix);
+ if (x_frac + VID_TO_POS(vc_priv->x_charsize) > vc_priv->xsize_frac)
+ return -EAGAIN;
+ linenum = y;
+ x = VID_TO_PIXEL(x_frac);
+ start = vid_priv->fb + linenum * vid_priv->line_length + x * pbytes;
line = start;
if (x_frac + VID_TO_POS(vc_priv->x_charsize) > vc_priv->xsize_frac)
return -EAGAIN;
- for (row = 0; row < VIDEO_FONT_HEIGHT; row++) {
- unsigned int idx = (u8)ch * VIDEO_FONT_HEIGHT + row;
- uchar bits = video_fontdata[idx];
-
- switch (vid_priv->bpix) {
- case VIDEO_BPP8:
- if (IS_ENABLED(CONFIG_VIDEO_BPP8)) {
- uint8_t *dst = line;
-
- for (i = 0; i < VIDEO_FONT_WIDTH; i++) {
- *dst++ = (bits & 0x80) ?
- vid_priv->colour_fg :
- vid_priv->colour_bg;
- bits <<= 1;
- }
- break;
- }
- case VIDEO_BPP16:
- if (IS_ENABLED(CONFIG_VIDEO_BPP16)) {
- uint16_t *dst = line;
-
- for (i = 0; i < VIDEO_FONT_WIDTH; i++) {
- *dst++ = (bits & 0x80) ?
- vid_priv->colour_fg :
- vid_priv->colour_bg;
- bits <<= 1;
- }
- break;
- }
- case VIDEO_BPP32:
- if (IS_ENABLED(CONFIG_VIDEO_BPP32)) {
- uint32_t *dst = line;
-
- for (i = 0; i < VIDEO_FONT_WIDTH; i++) {
- *dst++ = (bits & 0x80) ?
- vid_priv->colour_fg :
- vid_priv->colour_bg;
- bits <<= 1;
- }
- break;
- }
- default:
- return -ENOSYS;
- }
- line += vid_priv->line_length;
- }
- ret = vidconsole_sync_copy(dev, start, line);
+ ret = fill_char_vertically(pfont, &line, vid_priv, fontdata, NORMAL_DIRECTION);
if (ret)
return ret;
- return VID_TO_POS(VIDEO_FONT_WIDTH);
-}
-
-static int console_normal_probe(struct udevice *dev)
-{
- struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev);
- struct udevice *vid_dev = dev->parent;
- struct video_priv *vid_priv = dev_get_uclass_priv(vid_dev);
-
- vc_priv->x_charsize = VIDEO_FONT_WIDTH;
- vc_priv->y_charsize = VIDEO_FONT_HEIGHT;
- vc_priv->cols = vid_priv->xsize / VIDEO_FONT_WIDTH;
- vc_priv->rows = vid_priv->ysize / VIDEO_FONT_HEIGHT;
+ ret = vidconsole_sync_copy(dev, start, line);
+ if (ret)
+ return ret;
- return 0;
+ return VID_TO_POS(fontdata->width);
}
-struct vidconsole_ops console_normal_ops = {
- .putc_xy = console_normal_putc_xy,
- .move_rows = console_normal_move_rows,
- .set_row = console_normal_set_row,
+struct vidconsole_ops console_ops = {
+ .putc_xy = console_putc_xy,
+ .move_rows = console_move_rows,
+ .set_row = console_set_row,
+ .get_font_size = console_simple_get_font_size,
+ .get_font = console_simple_get_font,
+ .select_font = console_simple_select_font,
};
U_BOOT_DRIVER(vidconsole_normal) = {
- .name = "vidconsole0",
- .id = UCLASS_VIDEO_CONSOLE,
- .ops = &console_normal_ops,
- .probe = console_normal_probe,
+ .name = "vidconsole0",
+ .id = UCLASS_VIDEO_CONSOLE,
+ .ops = &console_ops,
+ .probe = console_probe,
+ .priv_auto = sizeof(struct console_simple_priv),
};
diff --git a/drivers/video/console_rotate.c b/drivers/video/console_rotate.c
index 36c8d0609d..65358a1c6e 100644
--- a/drivers/video/console_rotate.c
+++ b/drivers/video/console_rotate.c
@@ -3,6 +3,7 @@
* Copyright (c) 2015 Google, Inc
* (C) Copyright 2015
* Bernecker & Rainer Industrieelektronik GmbH - http://www.br-automation.com
+ * (C) Copyright 2023 Dzmitry Sankouski <dsankouski@gmail.com>
*/
#include <common.h>
@@ -10,47 +11,25 @@
#include <video.h>
#include <video_console.h>
#include <video_font.h> /* Get font data, width and height */
+#include "vidconsole_internal.h"
static int console_set_row_1(struct udevice *dev, uint row, int clr)
{
struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
+ struct console_simple_priv *priv = dev_get_priv(dev);
+ struct video_fontdata *fontdata = priv->fontdata;
int pbytes = VNBYTES(vid_priv->bpix);
- void *start, *line;
+ void *start, *dst, *line;
int i, j;
int ret;
start = vid_priv->fb + vid_priv->line_length -
- (row + 1) * VIDEO_FONT_HEIGHT * pbytes;
+ (row + 1) * fontdata->height * pbytes;
line = start;
for (j = 0; j < vid_priv->ysize; j++) {
- switch (vid_priv->bpix) {
- case VIDEO_BPP8:
- if (IS_ENABLED(CONFIG_VIDEO_BPP8)) {
- uint8_t *dst = line;
-
- for (i = 0; i < VIDEO_FONT_HEIGHT; i++)
- *dst++ = clr;
- break;
- }
- case VIDEO_BPP16:
- if (IS_ENABLED(CONFIG_VIDEO_BPP16)) {
- uint16_t *dst = line;
-
- for (i = 0; i < VIDEO_FONT_HEIGHT; i++)
- *dst++ = clr;
- break;
- }
- case VIDEO_BPP32:
- if (IS_ENABLED(CONFIG_VIDEO_BPP32)) {
- uint32_t *dst = line;
-
- for (i = 0; i < VIDEO_FONT_HEIGHT; i++)
- *dst++ = clr;
- break;
- }
- default:
- return -ENOSYS;
- }
+ dst = line;
+ for (i = 0; i < fontdata->height; i++)
+ fill_pixel_and_goto_next(&dst, clr, pbytes, pbytes);
line += vid_priv->line_length;
}
ret = vidconsole_sync_copy(dev, start, line);
@@ -61,22 +40,24 @@ static int console_set_row_1(struct udevice *dev, uint row, int clr)
}
static int console_move_rows_1(struct udevice *dev, uint rowdst, uint rowsrc,
- uint count)
+ uint count)
{
struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
+ struct console_simple_priv *priv = dev_get_priv(dev);
+ struct video_fontdata *fontdata = priv->fontdata;
int pbytes = VNBYTES(vid_priv->bpix);
void *dst;
void *src;
int j, ret;
dst = vid_priv->fb + vid_priv->line_length -
- (rowdst + count) * VIDEO_FONT_HEIGHT * pbytes;
+ (rowdst + count) * fontdata->height * pbytes;
src = vid_priv->fb + vid_priv->line_length -
- (rowsrc + count) * VIDEO_FONT_HEIGHT * pbytes;
+ (rowsrc + count) * fontdata->height * pbytes;
for (j = 0; j < vid_priv->ysize; j++) {
ret = vidconsole_memmove(dev, dst, src,
- VIDEO_FONT_HEIGHT * pbytes * count);
+ fontdata->height * pbytes * count);
if (ret)
return ret;
src += vid_priv->line_length;
@@ -91,110 +72,51 @@ static int console_putc_xy_1(struct udevice *dev, uint x_frac, uint y, char ch)
struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev);
struct udevice *vid = dev->parent;
struct video_priv *vid_priv = dev_get_uclass_priv(vid);
- uchar *pfont = video_fontdata + (u8)ch * VIDEO_FONT_HEIGHT;
+ struct console_simple_priv *priv = dev_get_priv(dev);
+ struct video_fontdata *fontdata = priv->fontdata;
int pbytes = VNBYTES(vid_priv->bpix);
- int i, col, x, linenum, ret;
- int mask = 0x80;
+ int x, linenum, ret;
void *start, *line;
+ uchar *pfont = fontdata->video_fontdata +
+ (u8)ch * fontdata->char_pixel_bytes;
+ if (x_frac + VID_TO_POS(vc_priv->x_charsize) > vc_priv->xsize_frac)
+ return -EAGAIN;
linenum = VID_TO_PIXEL(x_frac) + 1;
x = y + 1;
start = vid_priv->fb + linenum * vid_priv->line_length - x * pbytes;
line = start;
- if (x_frac + VID_TO_POS(vc_priv->x_charsize) > vc_priv->xsize_frac)
- return -EAGAIN;
- for (col = 0; col < VIDEO_FONT_HEIGHT; col++) {
- switch (vid_priv->bpix) {
- case VIDEO_BPP8:
- if (IS_ENABLED(CONFIG_VIDEO_BPP8)) {
- uint8_t *dst = line;
-
- for (i = 0; i < VIDEO_FONT_HEIGHT; i++) {
- *dst-- = (pfont[i] & mask) ?
- vid_priv->colour_fg :
- vid_priv->colour_bg;
- }
- break;
- }
- case VIDEO_BPP16:
- if (IS_ENABLED(CONFIG_VIDEO_BPP16)) {
- uint16_t *dst = line;
-
- for (i = 0; i < VIDEO_FONT_HEIGHT; i++) {
- *dst-- = (pfont[i] & mask) ?
- vid_priv->colour_fg :
- vid_priv->colour_bg;
- }
- break;
- }
- case VIDEO_BPP32:
- if (IS_ENABLED(CONFIG_VIDEO_BPP32)) {
- uint32_t *dst = line;
-
- for (i = 0; i < VIDEO_FONT_HEIGHT; i++) {
- *dst-- = (pfont[i] & mask) ?
- vid_priv->colour_fg :
- vid_priv->colour_bg;
- }
- break;
- }
- default:
- return -ENOSYS;
- }
- line += vid_priv->line_length;
- mask >>= 1;
- }
+ ret = fill_char_horizontally(pfont, &line, vid_priv, fontdata, FLIPPED_DIRECTION);
+ if (ret)
+ return ret;
+
/* We draw backwards from 'start, so account for the first line */
ret = vidconsole_sync_copy(dev, start - vid_priv->line_length, line);
if (ret)
return ret;
- return VID_TO_POS(VIDEO_FONT_WIDTH);
+ return VID_TO_POS(fontdata->width);
}
static int console_set_row_2(struct udevice *dev, uint row, int clr)
{
struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
- void *start, *line, *end;
- int pixels = VIDEO_FONT_HEIGHT * vid_priv->xsize;
+ struct console_simple_priv *priv = dev_get_priv(dev);
+ struct video_fontdata *fontdata = priv->fontdata;
+ void *start, *line, *dst, *end;
+ int pixels = fontdata->height * vid_priv->xsize;
int i, ret;
+ int pbytes = VNBYTES(vid_priv->bpix);
start = vid_priv->fb + vid_priv->ysize * vid_priv->line_length -
- (row + 1) * VIDEO_FONT_HEIGHT * vid_priv->line_length;
+ (row + 1) * fontdata->height * vid_priv->line_length;
line = start;
- switch (vid_priv->bpix) {
- case VIDEO_BPP8:
- if (IS_ENABLED(CONFIG_VIDEO_BPP8)) {
- uint8_t *dst = line;
-
- for (i = 0; i < pixels; i++)
- *dst++ = clr;
- end = dst;
- break;
- }
- case VIDEO_BPP16:
- if (IS_ENABLED(CONFIG_VIDEO_BPP16)) {
- uint16_t *dst = line;
-
- for (i = 0; i < pixels; i++)
- *dst++ = clr;
- end = dst;
- break;
- }
- case VIDEO_BPP32:
- if (IS_ENABLED(CONFIG_VIDEO_BPP32)) {
- uint32_t *dst = line;
-
- for (i = 0; i < pixels; i++)
- *dst++ = clr;
- end = dst;
- break;
- }
- default:
- return -ENOSYS;
- }
+ dst = line;
+ for (i = 0; i < pixels; i++)
+ fill_pixel_and_goto_next(&dst, clr, pbytes, pbytes);
+ end = dst;
ret = vidconsole_sync_copy(dev, start, end);
if (ret)
return ret;
@@ -206,17 +128,19 @@ static int console_move_rows_2(struct udevice *dev, uint rowdst, uint rowsrc,
uint count)
{
struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
+ struct console_simple_priv *priv = dev_get_priv(dev);
+ struct video_fontdata *fontdata = priv->fontdata;
void *dst;
void *src;
void *end;
end = vid_priv->fb + vid_priv->ysize * vid_priv->line_length;
- dst = end - (rowdst + count) * VIDEO_FONT_HEIGHT *
+ dst = end - (rowdst + count) * fontdata->height *
vid_priv->line_length;
- src = end - (rowsrc + count) * VIDEO_FONT_HEIGHT *
+ src = end - (rowsrc + count) * fontdata->height *
vid_priv->line_length;
vidconsole_memmove(dev, dst, src,
- VIDEO_FONT_HEIGHT * vid_priv->line_length * count);
+ fontdata->height * vid_priv->line_length * count);
return 0;
}
@@ -226,9 +150,13 @@ static int console_putc_xy_2(struct udevice *dev, uint x_frac, uint y, char ch)
struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev);
struct udevice *vid = dev->parent;
struct video_priv *vid_priv = dev_get_uclass_priv(vid);
+ struct console_simple_priv *priv = dev_get_priv(dev);
+ struct video_fontdata *fontdata = priv->fontdata;
int pbytes = VNBYTES(vid_priv->bpix);
- int i, row, x, linenum, ret;
+ int linenum, x, ret;
void *start, *line;
+ uchar *pfont = fontdata->video_fontdata +
+ (u8)ch * fontdata->char_pixel_bytes;
if (x_frac + VID_TO_POS(vc_priv->x_charsize) > vc_priv->xsize_frac)
return -EAGAIN;
@@ -237,98 +165,33 @@ static int console_putc_xy_2(struct udevice *dev, uint x_frac, uint y, char ch)
start = vid_priv->fb + linenum * vid_priv->line_length + x * pbytes;
line = start;
- for (row = 0; row < VIDEO_FONT_HEIGHT; row++) {
- unsigned int idx = (u8)ch * VIDEO_FONT_HEIGHT + row;
- uchar bits = video_fontdata[idx];
-
- switch (vid_priv->bpix) {
- case VIDEO_BPP8:
- if (IS_ENABLED(CONFIG_VIDEO_BPP8)) {
- uint8_t *dst = line;
-
- for (i = 0; i < VIDEO_FONT_WIDTH; i++) {
- *dst-- = (bits & 0x80) ?
- vid_priv->colour_fg :
- vid_priv->colour_bg;
- bits <<= 1;
- }
- break;
- }
- case VIDEO_BPP16:
- if (IS_ENABLED(CONFIG_VIDEO_BPP16)) {
- uint16_t *dst = line;
-
- for (i = 0; i < VIDEO_FONT_WIDTH; i++) {
- *dst-- = (bits & 0x80) ?
- vid_priv->colour_fg :
- vid_priv->colour_bg;
- bits <<= 1;
- }
- break;
- }
- case VIDEO_BPP32:
- if (IS_ENABLED(CONFIG_VIDEO_BPP32)) {
- uint32_t *dst = line;
-
- for (i = 0; i < VIDEO_FONT_WIDTH; i++) {
- *dst-- = (bits & 0x80) ?
- vid_priv->colour_fg :
- vid_priv->colour_bg;
- bits <<= 1;
- }
- break;
- }
- default:
- return -ENOSYS;
- }
- line -= vid_priv->line_length;
- }
+ ret = fill_char_vertically(pfont, &line, vid_priv, fontdata, FLIPPED_DIRECTION);
+ if (ret)
+ return ret;
+
/* Add 4 bytes to allow for the first pixel writen */
ret = vidconsole_sync_copy(dev, start + 4, line);
if (ret)
return ret;
- return VID_TO_POS(VIDEO_FONT_WIDTH);
+ return VID_TO_POS(fontdata->width);
}
static int console_set_row_3(struct udevice *dev, uint row, int clr)
{
struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
+ struct console_simple_priv *priv = dev_get_priv(dev);
+ struct video_fontdata *fontdata = priv->fontdata;
int pbytes = VNBYTES(vid_priv->bpix);
- void *start, *line;
+ void *start, *dst, *line;
int i, j, ret;
- start = vid_priv->fb + row * VIDEO_FONT_HEIGHT * pbytes;
+ start = vid_priv->fb + row * fontdata->height * pbytes;
line = start;
for (j = 0; j < vid_priv->ysize; j++) {
- switch (vid_priv->bpix) {
- case VIDEO_BPP8:
- if (IS_ENABLED(CONFIG_VIDEO_BPP8)) {
- uint8_t *dst = line;
-
- for (i = 0; i < VIDEO_FONT_HEIGHT; i++)
- *dst++ = clr;
- break;
- }
- case VIDEO_BPP16:
- if (IS_ENABLED(CONFIG_VIDEO_BPP16)) {
- uint16_t *dst = line;
-
- for (i = 0; i < VIDEO_FONT_HEIGHT; i++)
- *dst++ = clr;
- break;
- }
- case VIDEO_BPP32:
- if (IS_ENABLED(CONFIG_VIDEO_BPP32)) {
- uint32_t *dst = line;
-
- for (i = 0; i < VIDEO_FONT_HEIGHT; i++)
- *dst++ = clr;
- break;
- }
- default:
- return -ENOSYS;
- }
+ dst = line;
+ for (i = 0; i < fontdata->height; i++)
+ fill_pixel_and_goto_next(&dst, clr, pbytes, pbytes);
line += vid_priv->line_length;
}
ret = vidconsole_sync_copy(dev, start, line);
@@ -342,17 +205,19 @@ static int console_move_rows_3(struct udevice *dev, uint rowdst, uint rowsrc,
uint count)
{
struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
+ struct console_simple_priv *priv = dev_get_priv(dev);
+ struct video_fontdata *fontdata = priv->fontdata;
int pbytes = VNBYTES(vid_priv->bpix);
void *dst;
void *src;
int j, ret;
- dst = vid_priv->fb + rowdst * VIDEO_FONT_HEIGHT * pbytes;
- src = vid_priv->fb + rowsrc * VIDEO_FONT_HEIGHT * pbytes;
+ dst = vid_priv->fb + rowdst * fontdata->height * pbytes;
+ src = vid_priv->fb + rowsrc * fontdata->height * pbytes;
for (j = 0; j < vid_priv->ysize; j++) {
ret = vidconsole_memmove(dev, dst, src,
- VIDEO_FONT_HEIGHT * pbytes * count);
+ fontdata->height * pbytes * count);
if (ret)
return ret;
src += vid_priv->line_length;
@@ -367,131 +232,79 @@ static int console_putc_xy_3(struct udevice *dev, uint x_frac, uint y, char ch)
struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev);
struct udevice *vid = dev->parent;
struct video_priv *vid_priv = dev_get_uclass_priv(vid);
- uchar *pfont = video_fontdata + (u8)ch * VIDEO_FONT_HEIGHT;
+ struct console_simple_priv *priv = dev_get_priv(dev);
+ struct video_fontdata *fontdata = priv->fontdata;
int pbytes = VNBYTES(vid_priv->bpix);
- int i, col, x, ret;
- int mask = 0x80;
+ int linenum, x, ret;
void *start, *line;
+ uchar *pfont = fontdata->video_fontdata +
+ (u8)ch * fontdata->char_pixel_bytes;
if (x_frac + VID_TO_POS(vc_priv->x_charsize) > vc_priv->xsize_frac)
return -EAGAIN;
- x = vid_priv->ysize - VID_TO_PIXEL(x_frac) - 1;
- start = vid_priv->fb + x * vid_priv->line_length + y * pbytes;
+ x = y;
+ linenum = vid_priv->ysize - VID_TO_PIXEL(x_frac) - 1;
+ start = vid_priv->fb + linenum * vid_priv->line_length + y * pbytes;
line = start;
- for (col = 0; col < VIDEO_FONT_HEIGHT; col++) {
- switch (vid_priv->bpix) {
- case VIDEO_BPP8:
- if (IS_ENABLED(CONFIG_VIDEO_BPP8)) {
- uint8_t *dst = line;
-
- for (i = 0; i < VIDEO_FONT_HEIGHT; i++) {
- *dst++ = (pfont[i] & mask) ?
- vid_priv->colour_fg :
- vid_priv->colour_bg;
- }
- break;
- }
- case VIDEO_BPP16:
- if (IS_ENABLED(CONFIG_VIDEO_BPP16)) {
- uint16_t *dst = line;
-
- for (i = 0; i < VIDEO_FONT_HEIGHT; i++) {
- *dst++ = (pfont[i] & mask) ?
- vid_priv->colour_fg :
- vid_priv->colour_bg;
- }
- break;
- }
- case VIDEO_BPP32:
- if (IS_ENABLED(CONFIG_VIDEO_BPP32)) {
- uint32_t *dst = line;
-
- for (i = 0; i < VIDEO_FONT_HEIGHT; i++) {
- *dst++ = (pfont[i] & mask) ?
- vid_priv->colour_fg :
- vid_priv->colour_bg;
- }
- break;
- }
- default:
- return -ENOSYS;
- }
- line -= vid_priv->line_length;
- mask >>= 1;
- }
+
+ ret = fill_char_horizontally(pfont, &line, vid_priv, fontdata, NORMAL_DIRECTION);
+ if (ret)
+ return ret;
/* Add a line to allow for the first pixels writen */
ret = vidconsole_sync_copy(dev, start + vid_priv->line_length, line);
if (ret)
return ret;
- return VID_TO_POS(VIDEO_FONT_WIDTH);
-}
-
-
-static int console_probe_2(struct udevice *dev)
-{
- struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev);
- struct udevice *vid_dev = dev->parent;
- struct video_priv *vid_priv = dev_get_uclass_priv(vid_dev);
-
- vc_priv->x_charsize = VIDEO_FONT_WIDTH;
- vc_priv->y_charsize = VIDEO_FONT_HEIGHT;
- vc_priv->cols = vid_priv->xsize / VIDEO_FONT_WIDTH;
- vc_priv->rows = vid_priv->ysize / VIDEO_FONT_HEIGHT;
-
- return 0;
-}
-
-static int console_probe_1_3(struct udevice *dev)
-{
- struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev);
- struct udevice *vid_dev = dev->parent;
- struct video_priv *vid_priv = dev_get_uclass_priv(vid_dev);
-
- vc_priv->x_charsize = VIDEO_FONT_WIDTH;
- vc_priv->y_charsize = VIDEO_FONT_HEIGHT;
- vc_priv->cols = vid_priv->ysize / VIDEO_FONT_WIDTH;
- vc_priv->rows = vid_priv->xsize / VIDEO_FONT_HEIGHT;
- vc_priv->xsize_frac = VID_TO_POS(vid_priv->ysize);
-
- return 0;
+ return VID_TO_POS(fontdata->width);
}
struct vidconsole_ops console_ops_1 = {
.putc_xy = console_putc_xy_1,
.move_rows = console_move_rows_1,
.set_row = console_set_row_1,
+ .get_font_size = console_simple_get_font_size,
+ .get_font = console_simple_get_font,
+ .select_font = console_simple_select_font,
};
struct vidconsole_ops console_ops_2 = {
.putc_xy = console_putc_xy_2,
.move_rows = console_move_rows_2,
.set_row = console_set_row_2,
+ .get_font_size = console_simple_get_font_size,
+ .get_font = console_simple_get_font,
+ .select_font = console_simple_select_font,
};
struct vidconsole_ops console_ops_3 = {
.putc_xy = console_putc_xy_3,
.move_rows = console_move_rows_3,
.set_row = console_set_row_3,
+ .get_font_size = console_simple_get_font_size,
+ .get_font = console_simple_get_font,
+ .select_font = console_simple_select_font,
};
U_BOOT_DRIVER(vidconsole_1) = {
.name = "vidconsole1",
.id = UCLASS_VIDEO_CONSOLE,
.ops = &console_ops_1,
- .probe = console_probe_1_3,
+ .probe = console_probe,
+ .priv_auto = sizeof(struct console_simple_priv),
};
U_BOOT_DRIVER(vidconsole_2) = {
.name = "vidconsole2",
.id = UCLASS_VIDEO_CONSOLE,
.ops = &console_ops_2,
- .probe = console_probe_2,
+ .probe = console_probe,
+ .priv_auto = sizeof(struct console_simple_priv),
};
U_BOOT_DRIVER(vidconsole_3) = {
.name = "vidconsole3",
.id = UCLASS_VIDEO_CONSOLE,
.ops = &console_ops_3,
- .probe = console_probe_1_3,
+ .probe = console_probe,
+ .priv_auto = sizeof(struct console_simple_priv),
};
diff --git a/drivers/video/console_truetype.c b/drivers/video/console_truetype.c
index 9cac9a6de4..6b5390136a 100644
--- a/drivers/video/console_truetype.c
+++ b/drivers/video/console_truetype.c
@@ -724,7 +724,7 @@ static int truetype_select_font(struct udevice *dev, const char *name,
return 0;
}
-const char *vidconsole_get_font_size(struct udevice *dev, uint *sizep)
+const char *console_truetype_get_font_size(struct udevice *dev, uint *sizep)
{
struct console_tt_priv *priv = dev_get_priv(dev);
struct console_tt_metrics *met = priv->cur_met;
@@ -773,6 +773,7 @@ struct vidconsole_ops console_truetype_ops = {
.backspace = console_truetype_backspace,
.entry_start = console_truetype_entry_start,
.get_font = console_truetype_get_font,
+ .get_font_size = console_truetype_get_font_size,
.select_font = truetype_select_font,
};
diff --git a/drivers/video/coreboot.c b/drivers/video/coreboot.c
index d2d87c75c8..c586475e41 100644
--- a/drivers/video/coreboot.c
+++ b/drivers/video/coreboot.c
@@ -57,7 +57,7 @@ static int coreboot_video_probe(struct udevice *dev)
goto err;
}
- ret = vesa_setup_video_priv(vesa, uc_priv, plat);
+ ret = vesa_setup_video_priv(vesa, vesa->phys_base_ptr, uc_priv, plat);
if (ret) {
ret = log_msg_ret("setup", ret);
goto err;
diff --git a/drivers/video/efi.c b/drivers/video/efi.c
index b11e42c0eb..28ac15ff61 100644
--- a/drivers/video/efi.c
+++ b/drivers/video/efi.c
@@ -5,6 +5,8 @@
* EFI framebuffer driver based on GOP
*/
+#define LOG_CATEGORY LOGC_EFI
+
#include <common.h>
#include <dm.h>
#include <efi_api.h>
@@ -50,7 +52,19 @@ static void efi_find_pixel_bits(u32 mask, u8 *pos, u8 *size)
*size = len;
}
-static int get_mode_info(struct vesa_mode_info *vesa)
+/**
+ * get_mode_info() - Ask EFI for the mode information
+ *
+ * Gets info from the graphics-output protocol
+ *
+ * @vesa: Place to put the mode information
+ * @fbp: Returns the address of the frame buffer
+ * @infop: Returns a pointer to the mode info
+ * Returns: 0 if OK, -ENOSYS if boot services are not available, -ENOTSUPP if
+ * the protocol is not supported by EFI
+ */
+static int get_mode_info(struct vesa_mode_info *vesa, u64 *fbp,
+ struct efi_gop_mode_info **infop)
{
efi_guid_t efi_gop_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
struct efi_boot_services *boot = efi_get_boot();
@@ -63,41 +77,70 @@ static int get_mode_info(struct vesa_mode_info *vesa)
ret = boot->locate_protocol(&efi_gop_guid, NULL, (void **)&gop);
if (ret)
return log_msg_ret("prot", -ENOTSUPP);
-
mode = gop->mode;
+ log_debug("maxmode %u, mode %u, info %p, size %lx, fb %lx, fb_size %lx\n",
+ mode->max_mode, mode->mode, mode->info, mode->info_size,
+ (ulong)mode->fb_base, (ulong)mode->fb_size);
+
vesa->phys_base_ptr = mode->fb_base;
+ *fbp = mode->fb_base;
vesa->x_resolution = mode->info->width;
vesa->y_resolution = mode->info->height;
+ *infop = mode->info;
return 0;
}
-static int save_vesa_mode(struct vesa_mode_info *vesa)
+/**
+ * get_mode_from_entry() - Obtain fb info from the EFIET_GOP_MODE payload entry
+ *
+ * This gets the mode information provided by the stub to the payload and puts
+ * it into a vesa structure. It also returns the mode information.
+ *
+ * @vesa: Place to put the mode information
+ * @fbp: Returns the address of the frame buffer
+ * @infop: Returns a pointer to the mode info
+ * Returns: 0 if OK, -ve on error
+ */
+static int get_mode_from_entry(struct vesa_mode_info *vesa, u64 *fbp,
+ struct efi_gop_mode_info **infop)
{
- struct efi_entry_gopmode *mode;
- const struct efi_framebuffer *fbinfo;
+ struct efi_gop_mode *mode;
int size;
int ret;
- if (IS_ENABLED(CONFIG_EFI_APP)) {
- ret = get_mode_info(vesa);
- if (ret) {
- printf("EFI graphics output protocol not found\n");
- return -ENXIO;
- }
- } else {
- ret = efi_info_get(EFIET_GOP_MODE, (void **)&mode, &size);
- if (ret == -ENOENT) {
- printf("EFI graphics output protocol mode not found\n");
- return -ENXIO;
- }
- vesa->phys_base_ptr = mode->fb_base;
- vesa->x_resolution = mode->info->width;
- vesa->y_resolution = mode->info->height;
+ ret = efi_info_get(EFIET_GOP_MODE, (void **)&mode, &size);
+ if (ret) {
+ printf("EFI graphics output entry not found\n");
+ return ret;
}
+ vesa->phys_base_ptr = mode->fb_base;
+ *fbp = mode->fb_base;
+ vesa->x_resolution = mode->info->width;
+ vesa->y_resolution = mode->info->height;
+ *infop = mode->info;
- if (mode->info->pixel_format < EFI_GOT_BITMASK) {
- fbinfo = &efi_framebuffer_format_map[mode->info->pixel_format];
+ return 0;
+}
+
+static int save_vesa_mode(struct vesa_mode_info *vesa, u64 *fbp)
+{
+ const struct efi_framebuffer *fbinfo;
+ struct efi_gop_mode_info *info;
+ int ret;
+
+ if (IS_ENABLED(CONFIG_EFI_APP))
+ ret = get_mode_info(vesa, fbp, &info);
+ else
+ ret = get_mode_from_entry(vesa, fbp, &info);
+ if (ret) {
+ printf("EFI graphics output protocol not found (err=%dE)\n",
+ ret);
+ return ret;
+ }
+
+ if (info->pixel_format < EFI_GOT_BITMASK) {
+ fbinfo = &efi_framebuffer_format_map[info->pixel_format];
vesa->red_mask_size = fbinfo->red.size;
vesa->red_mask_pos = fbinfo->red.pos;
vesa->green_mask_size = fbinfo->green.size;
@@ -108,29 +151,28 @@ static int save_vesa_mode(struct vesa_mode_info *vesa)
vesa->reserved_mask_pos = fbinfo->rsvd.pos;
vesa->bits_per_pixel = 32;
- vesa->bytes_per_scanline = mode->info->pixels_per_scanline * 4;
- } else if (mode->info->pixel_format == EFI_GOT_BITMASK) {
- efi_find_pixel_bits(mode->info->pixel_bitmask[0],
+ vesa->bytes_per_scanline = info->pixels_per_scanline * 4;
+ } else if (info->pixel_format == EFI_GOT_BITMASK) {
+ efi_find_pixel_bits(info->pixel_bitmask[0],
&vesa->red_mask_pos,
&vesa->red_mask_size);
- efi_find_pixel_bits(mode->info->pixel_bitmask[1],
+ efi_find_pixel_bits(info->pixel_bitmask[1],
&vesa->green_mask_pos,
&vesa->green_mask_size);
- efi_find_pixel_bits(mode->info->pixel_bitmask[2],
+ efi_find_pixel_bits(info->pixel_bitmask[2],
&vesa->blue_mask_pos,
&vesa->blue_mask_size);
- efi_find_pixel_bits(mode->info->pixel_bitmask[3],
+ efi_find_pixel_bits(info->pixel_bitmask[3],
&vesa->reserved_mask_pos,
&vesa->reserved_mask_size);
vesa->bits_per_pixel = vesa->red_mask_size +
vesa->green_mask_size +
vesa->blue_mask_size +
vesa->reserved_mask_size;
- vesa->bytes_per_scanline = (mode->info->pixels_per_scanline *
+ vesa->bytes_per_scanline = (info->pixels_per_scanline *
vesa->bits_per_pixel) / 8;
} else {
- debug("efi set unknown framebuffer format: %d\n",
- mode->info->pixel_format);
+ log_err("Unknown framebuffer format: %d\n", info->pixel_format);
return -EINVAL;
}
@@ -142,19 +184,20 @@ static int efi_video_probe(struct udevice *dev)
struct video_uc_plat *plat = dev_get_uclass_plat(dev);
struct video_priv *uc_priv = dev_get_uclass_priv(dev);
struct vesa_mode_info *vesa = &mode_info.vesa;
+ u64 fb;
int ret;
/* Initialize vesa_mode_info structure */
- ret = save_vesa_mode(vesa);
+ ret = save_vesa_mode(vesa, &fb);
if (ret)
goto err;
- ret = vesa_setup_video_priv(vesa, uc_priv, plat);
+ ret = vesa_setup_video_priv(vesa, fb, uc_priv, plat);
if (ret)
goto err;
- printf("Video: %dx%dx%d\n", uc_priv->xsize, uc_priv->ysize,
- vesa->bits_per_pixel);
+ printf("Video: %dx%dx%d @ %lx\n", uc_priv->xsize, uc_priv->ysize,
+ vesa->bits_per_pixel, (ulong)fb);
return 0;
@@ -163,6 +206,30 @@ err:
return ret;
}
+static int efi_video_bind(struct udevice *dev)
+{
+ if (IS_ENABLED(CONFIG_VIDEO_COPY)) {
+ struct video_uc_plat *plat = dev_get_uclass_plat(dev);
+ struct vesa_mode_info vesa;
+ int ret;
+ u64 fb;
+
+ /*
+ * Initialise vesa_mode_info structure so we can figure out the
+ * required framebuffer size. If something goes wrong, just do
+ * without a copy framebuffer
+ */
+ ret = save_vesa_mode(&vesa, &fb);
+ if (!ret) {
+ /* this is not reached if the EFI call failed */
+ plat->copy_size = vesa.bytes_per_scanline *
+ vesa.y_resolution;
+ }
+ }
+
+ return 0;
+}
+
static const struct udevice_id efi_video_ids[] = {
{ .compatible = "efi-fb" },
{ }
@@ -172,5 +239,6 @@ U_BOOT_DRIVER(efi_video) = {
.name = "efi_video",
.id = UCLASS_VIDEO,
.of_match = efi_video_ids,
+ .bind = efi_video_bind,
.probe = efi_video_probe,
};
diff --git a/drivers/video/vidconsole-uclass.c b/drivers/video/vidconsole-uclass.c
index 72a13d3052..1225de2333 100644
--- a/drivers/video/vidconsole-uclass.c
+++ b/drivers/video/vidconsole-uclass.c
@@ -575,6 +575,17 @@ int vidconsole_get_font(struct udevice *dev, int seq,
return ops->get_font(dev, seq, info);
}
+int vidconsole_get_font_size(struct udevice *dev, const char **name, uint *sizep)
+{
+ struct vidconsole_ops *ops = vidconsole_get_ops(dev);
+
+ if (!ops->get_font_size)
+ return -ENOSYS;
+
+ *name = ops->get_font_size(dev, sizep);
+ return 0;
+}
+
int vidconsole_select_font(struct udevice *dev, const char *name, uint size)
{
struct vidconsole_ops *ops = vidconsole_get_ops(dev);
@@ -645,6 +656,18 @@ int vidconsole_memmove(struct udevice *dev, void *dst, const void *src,
}
#endif
+int vidconsole_clear_and_reset(struct udevice *dev)
+{
+ int ret;
+
+ ret = video_clear(dev_get_parent(dev));
+ if (ret)
+ return ret;
+ vidconsole_position_cursor(dev, 0, 0);
+
+ return 0;
+}
+
void vidconsole_position_cursor(struct udevice *dev, unsigned col, unsigned row)
{
struct vidconsole_priv *priv = dev_get_uclass_priv(dev);
diff --git a/drivers/video/vidconsole_internal.h b/drivers/video/vidconsole_internal.h
new file mode 100644
index 0000000000..c41edd4524
--- /dev/null
+++ b/drivers/video/vidconsole_internal.h
@@ -0,0 +1,120 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c) 2015 Google, Inc
+ * (C) Copyright 2015
+ * Bernecker & Rainer Industrieelektronik GmbH - http://www.br-automation.com
+ * (C) Copyright 2023 Dzmitry Sankouski <dsankouski@gmail.com>
+ */
+
+#define FLIPPED_DIRECTION 1
+#define NORMAL_DIRECTION 0
+
+/**
+ * struct console_simple_priv - Private data for this driver
+ *
+ * @video_fontdata font graphical representation data
+ */
+struct console_simple_priv {
+ struct video_fontdata *fontdata;
+};
+
+/**
+ * Checks if bits per pixel supported.
+ *
+ * @param bpix framebuffer bits per pixel.
+ *
+ * @returns 0, if supported, or else -ENOSYS.
+ */
+int check_bpix_support(int bpix);
+
+/**
+ * Fill 1 pixel in framebuffer, and go to next one.
+ *
+ * @param dstp a pointer to pointer to framebuffer.
+ * @param value value to write to framebuffer.
+ * @param pbytes framebuffer bytes per pixel.
+ * @param step framebuffer pointer increment. Usually is equal to pbytes,
+ * and may be negative to control filling direction.
+ */
+void fill_pixel_and_goto_next(void **dstp, u32 value, int pbytes, int step);
+
+/**
+ * Fills 1 character in framebuffer vertically. Vertically means we're filling char font data rows
+ * across the lines.
+ *
+ * @param pfont a pointer to character font data.
+ * @param line a pointer to pointer to framebuffer. It's a point for upper left char corner
+ * @param vid_priv driver private data.
+ * @fontdata font graphical representation data
+ * @param direction controls character orientation. Can be normal or flipped.
+ * When normal: When flipped:
+ *|-----------------------------------------------|
+ *| line stepping | |
+ *| | | stepping -> |
+ *| * | | * * * |
+ *| * * v | * |
+ *| * | * |
+ *| * | * * ^ |
+ *| * * * | * | |
+ *| | | |
+ *| stepping -> | line stepping |
+ *|---!!we're starting from upper left char corner|
+ *|-----------------------------------------------|
+ *
+ * @returns 0, if success, or else error code.
+ */
+int fill_char_vertically(uchar *pfont, void **line, struct video_priv *vid_priv,
+ struct video_fontdata *fontdata, bool direction);
+
+/**
+ * Fills 1 character in framebuffer horizontally.
+ * Horizontally means we're filling char font data columns across the lines.
+ *
+ * @param pfont a pointer to character font data.
+ * @param line a pointer to pointer to framebuffer. It's a point for upper left char corner
+ * @param vid_priv driver private data.
+ * @fontdata font graphical representation data
+ * @param direction controls character orientation. Can be normal or flipped.
+ * When normal: When flipped:
+ *|-----------------------------------------------|
+ *| * | line stepping |
+ *| ^ * * * * * | | |
+ *| | * * | v * * |
+ *| | | * * * * * |
+ *| line stepping | * |
+ *| | |
+ *| stepping -> | <- stepping |
+ *|---!!we're starting from upper left char corner|
+ *|-----------------------------------------------|
+ *
+ * @returns 0, if success, or else error code.
+ */
+int fill_char_horizontally(uchar *pfont, void **line, struct video_priv *vid_priv,
+ struct video_fontdata *fontdata, bool direction);
+
+/**
+ * console probe function.
+ *
+ * @param dev a pointer to device.
+ *
+ * @returns 0, if success, or else error code.
+ */
+int console_probe(struct udevice *dev);
+
+/**
+ * Internal function to be used in as ops.
+ * See details in video_console.h get_font_size function
+ **/
+const char *console_simple_get_font_size(struct udevice *dev, uint *sizep);
+
+/**
+ * Internal function to be used in as ops.
+ * See details in video_console.h get_font function
+ **/
+int console_simple_get_font(struct udevice *dev, int seq, struct vidfont_info *info);
+
+/**
+ * Internal function to be used in as ops.
+ * See details in video_console.h select_font function
+ **/
+int console_simple_select_font(struct udevice *dev, const char *name, uint size);
diff --git a/drivers/video/video-uclass.c b/drivers/video/video-uclass.c
index 6aaacff10d..da89f43144 100644
--- a/drivers/video/video-uclass.c
+++ b/drivers/video/video-uclass.c
@@ -78,24 +78,40 @@ void video_set_flush_dcache(struct udevice *dev, bool flush)
priv->flush_dcache = flush;
}
+static ulong alloc_fb_(ulong align, ulong size, ulong *addrp)
+{
+ ulong base;
+
+ align = align ? align : 1 << 20;
+ base = *addrp - size;
+ base &= ~(align - 1);
+ size = *addrp - base;
+ *addrp = base;
+
+ return size;
+}
+
static ulong alloc_fb(struct udevice *dev, ulong *addrp)
{
struct video_uc_plat *plat = dev_get_uclass_plat(dev);
- ulong base, align, size;
+ ulong size;
+
+ if (!plat->size) {
+ if (IS_ENABLED(CONFIG_VIDEO_COPY) && plat->copy_size) {
+ size = alloc_fb_(plat->align, plat->copy_size, addrp);
+ plat->copy_base = *addrp;
+ return size;
+ }
- if (!plat->size)
return 0;
+ }
/* Allow drivers to allocate the frame buffer themselves */
if (plat->base)
return 0;
- align = plat->align ? plat->align : 1 << 20;
- base = *addrp - plat->size;
- base &= ~(align - 1);
- plat->base = base;
- size = *addrp - base;
- *addrp = base;
+ size = alloc_fb_(plat->align, plat->size, addrp);
+ plat->base = *addrp;
return size;
}
@@ -529,8 +545,8 @@ static int video_post_bind(struct udevice *dev)
addr = uc_priv->video_ptr;
size = alloc_fb(dev, &addr);
if (addr < gd->video_bottom) {
- /* Device tree node may need the 'u-boot,dm-pre-reloc' or
- * 'u-boot,dm-pre-proper' tag
+ /* Device tree node may need the 'bootph-all' or
+ * 'bootph-some-ram' tag
*/
printf("Video device '%s' cannot allocate frame buffer memory -ensure the device is set up before relocation\n",
dev->name);