summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/clk/sunxi/Kconfig7
-rw-r--r--drivers/clk/sunxi/Makefile1
-rw-r--r--drivers/clk/sunxi/clk_a10.c2
-rw-r--r--drivers/clk/sunxi/clk_a10s.c2
-rw-r--r--drivers/clk/sunxi/clk_a23.c2
-rw-r--r--drivers/clk/sunxi/clk_a31.c2
-rw-r--r--drivers/clk/sunxi/clk_a64.c4
-rw-r--r--drivers/clk/sunxi/clk_a80.c2
-rw-r--r--drivers/clk/sunxi/clk_a83t.c2
-rw-r--r--drivers/clk/sunxi/clk_f1c100s.c74
-rw-r--r--drivers/clk/sunxi/clk_h3.c4
-rw-r--r--drivers/clk/sunxi/clk_h6.c4
-rw-r--r--drivers/clk/sunxi/clk_h616.c4
-rw-r--r--drivers/clk/sunxi/clk_h6_r.c6
-rw-r--r--drivers/clk/sunxi/clk_r40.c2
-rw-r--r--drivers/clk/sunxi/clk_sunxi.c3
-rw-r--r--drivers/clk/sunxi/clk_v3s.c2
-rw-r--r--drivers/crypto/fsl/fsl_hash.c8
-rw-r--r--drivers/crypto/fsl/jr.c19
-rw-r--r--drivers/ddr/imx/imx8m/ddrphy_utils.c9
-rw-r--r--drivers/gpio/imx_rgpio2p.c14
-rw-r--r--drivers/misc/imx8ulp/s400_api.c41
-rw-r--r--drivers/mmc/Kconfig2
-rw-r--r--drivers/mmc/fsl_esdhc_spl.c2
-rw-r--r--drivers/mtd/nand/raw/mxs_nand.c35
-rw-r--r--drivers/mtd/nand/raw/mxs_nand_spl.c90
-rw-r--r--drivers/mtd/spi/sf-uclass.c33
-rw-r--r--drivers/net/fm/fm.c4
-rw-r--r--drivers/net/pfe_eth/pfe_firmware.c19
-rw-r--r--drivers/net/sni_netsec.c6
-rw-r--r--drivers/pinctrl/pinctrl-uclass.c7
-rw-r--r--drivers/power/pmic/pca9450.c8
-rw-r--r--drivers/power/regulator/Kconfig15
-rw-r--r--drivers/power/regulator/Makefile1
-rw-r--r--drivers/power/regulator/pca9450.c333
-rw-r--r--drivers/serial/Kconfig40
-rw-r--r--drivers/serial/ns16550.c4
-rw-r--r--drivers/spi/spi-uclass.c66
-rw-r--r--drivers/spi/stm32_qspi.c27
-rw-r--r--drivers/tpm/Kconfig9
-rw-r--r--drivers/tpm/Makefile1
-rw-r--r--drivers/tpm/tpm2_tis_core.c7
-rw-r--r--drivers/tpm/tpm2_tis_i2c.c171
-rw-r--r--drivers/usb/common/common.c16
-rw-r--r--drivers/usb/dwc3/dwc3-generic.c4
-rw-r--r--drivers/usb/gadget/max3420_udc.c4
-rw-r--r--drivers/usb/host/xhci-dwc3.c6
47 files changed, 963 insertions, 161 deletions
diff --git a/drivers/clk/sunxi/Kconfig b/drivers/clk/sunxi/Kconfig
index f19908113e..bf11fad6ee 100644
--- a/drivers/clk/sunxi/Kconfig
+++ b/drivers/clk/sunxi/Kconfig
@@ -10,6 +10,13 @@ config CLK_SUNXI
if CLK_SUNXI
+config CLK_SUNIV_F1C100S
+ bool "Clock driver for Allwinner F1C100s"
+ default MACH_SUNIV
+ help
+ This enables common clock driver support for platforms based
+ on Allwinner F1C100s SoC.
+
config CLK_SUN4I_A10
bool "Clock driver for Allwinner A10/A20"
default MACH_SUN4I || MACH_SUN7I
diff --git a/drivers/clk/sunxi/Makefile b/drivers/clk/sunxi/Makefile
index 48a48a2f00..895da02ebe 100644
--- a/drivers/clk/sunxi/Makefile
+++ b/drivers/clk/sunxi/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_CLK_SUNXI) += clk_sunxi.o
obj-$(CONFIG_CLK_SUNXI) += clk_sun6i_rtc.o
+obj-$(CONFIG_CLK_SUNIV_F1C100S) += clk_f1c100s.o
obj-$(CONFIG_CLK_SUN4I_A10) += clk_a10.o
obj-$(CONFIG_CLK_SUN5I_A10S) += clk_a10s.o
obj-$(CONFIG_CLK_SUN6I_A31) += clk_a31.o
diff --git a/drivers/clk/sunxi/clk_a10.c b/drivers/clk/sunxi/clk_a10.c
index 90b929d3d3..db92848aaf 100644
--- a/drivers/clk/sunxi/clk_a10.c
+++ b/drivers/clk/sunxi/clk_a10.c
@@ -31,6 +31,8 @@ static struct ccu_clk_gate a10_gates[] = {
[CLK_AHB_GMAC] = GATE(0x064, BIT(17)),
+ [CLK_APB0_PIO] = GATE(0x068, BIT(5)),
+
[CLK_APB1_I2C0] = GATE(0x06c, BIT(0)),
[CLK_APB1_I2C1] = GATE(0x06c, BIT(1)),
[CLK_APB1_I2C2] = GATE(0x06c, BIT(2)),
diff --git a/drivers/clk/sunxi/clk_a10s.c b/drivers/clk/sunxi/clk_a10s.c
index addf4f4d5c..0c6564ef3b 100644
--- a/drivers/clk/sunxi/clk_a10s.c
+++ b/drivers/clk/sunxi/clk_a10s.c
@@ -25,6 +25,8 @@ static struct ccu_clk_gate a10s_gates[] = {
[CLK_AHB_SPI1] = GATE(0x060, BIT(21)),
[CLK_AHB_SPI2] = GATE(0x060, BIT(22)),
+ [CLK_APB0_PIO] = GATE(0x068, BIT(5)),
+
[CLK_APB1_I2C0] = GATE(0x06c, BIT(0)),
[CLK_APB1_I2C1] = GATE(0x06c, BIT(1)),
[CLK_APB1_I2C2] = GATE(0x06c, BIT(2)),
diff --git a/drivers/clk/sunxi/clk_a23.c b/drivers/clk/sunxi/clk_a23.c
index c45d2c3529..0280fb51e2 100644
--- a/drivers/clk/sunxi/clk_a23.c
+++ b/drivers/clk/sunxi/clk_a23.c
@@ -23,6 +23,8 @@ static struct ccu_clk_gate a23_gates[] = {
[CLK_BUS_EHCI] = GATE(0x060, BIT(26)),
[CLK_BUS_OHCI] = GATE(0x060, BIT(29)),
+ [CLK_BUS_PIO] = GATE(0x068, BIT(5)),
+
[CLK_BUS_I2C0] = GATE(0x06c, BIT(0)),
[CLK_BUS_I2C1] = GATE(0x06c, BIT(1)),
[CLK_BUS_I2C2] = GATE(0x06c, BIT(2)),
diff --git a/drivers/clk/sunxi/clk_a31.c b/drivers/clk/sunxi/clk_a31.c
index 251fc3b705..26d25f3240 100644
--- a/drivers/clk/sunxi/clk_a31.c
+++ b/drivers/clk/sunxi/clk_a31.c
@@ -30,6 +30,8 @@ static struct ccu_clk_gate a31_gates[] = {
[CLK_AHB1_OHCI1] = GATE(0x060, BIT(30)),
[CLK_AHB1_OHCI2] = GATE(0x060, BIT(31)),
+ [CLK_APB1_PIO] = GATE(0x068, BIT(5)),
+
[CLK_APB2_I2C0] = GATE(0x06c, BIT(0)),
[CLK_APB2_I2C1] = GATE(0x06c, BIT(1)),
[CLK_APB2_I2C2] = GATE(0x06c, BIT(2)),
diff --git a/drivers/clk/sunxi/clk_a64.c b/drivers/clk/sunxi/clk_a64.c
index 1004a79503..cbb9168edb 100644
--- a/drivers/clk/sunxi/clk_a64.c
+++ b/drivers/clk/sunxi/clk_a64.c
@@ -14,6 +14,8 @@
#include <linux/bitops.h>
static const struct ccu_clk_gate a64_gates[] = {
+ [CLK_PLL_PERIPH0] = GATE(0x028, BIT(31)),
+
[CLK_BUS_MMC0] = GATE(0x060, BIT(8)),
[CLK_BUS_MMC1] = GATE(0x060, BIT(9)),
[CLK_BUS_MMC2] = GATE(0x060, BIT(10)),
@@ -26,6 +28,8 @@ static const struct ccu_clk_gate a64_gates[] = {
[CLK_BUS_OHCI0] = GATE(0x060, BIT(28)),
[CLK_BUS_OHCI1] = GATE(0x060, BIT(29)),
+ [CLK_BUS_PIO] = GATE(0x068, BIT(5)),
+
[CLK_BUS_I2C0] = GATE(0x06c, BIT(0)),
[CLK_BUS_I2C1] = GATE(0x06c, BIT(1)),
[CLK_BUS_I2C2] = GATE(0x06c, BIT(2)),
diff --git a/drivers/clk/sunxi/clk_a80.c b/drivers/clk/sunxi/clk_a80.c
index 8a0834d83a..1ee1f99a8f 100644
--- a/drivers/clk/sunxi/clk_a80.c
+++ b/drivers/clk/sunxi/clk_a80.c
@@ -25,6 +25,8 @@ static const struct ccu_clk_gate a80_gates[] = {
[CLK_BUS_SPI2] = GATE(0x580, BIT(22)),
[CLK_BUS_SPI3] = GATE(0x580, BIT(23)),
+ [CLK_BUS_PIO] = GATE(0x590, BIT(5)),
+
[CLK_BUS_I2C0] = GATE(0x594, BIT(0)),
[CLK_BUS_I2C1] = GATE(0x594, BIT(1)),
[CLK_BUS_I2C2] = GATE(0x594, BIT(2)),
diff --git a/drivers/clk/sunxi/clk_a83t.c b/drivers/clk/sunxi/clk_a83t.c
index 8c6043f51e..4b57434cfa 100644
--- a/drivers/clk/sunxi/clk_a83t.c
+++ b/drivers/clk/sunxi/clk_a83t.c
@@ -25,6 +25,8 @@ static struct ccu_clk_gate a83t_gates[] = {
[CLK_BUS_EHCI1] = GATE(0x060, BIT(27)),
[CLK_BUS_OHCI0] = GATE(0x060, BIT(29)),
+ [CLK_BUS_PIO] = GATE(0x068, BIT(5)),
+
[CLK_BUS_I2C0] = GATE(0x06c, BIT(0)),
[CLK_BUS_I2C1] = GATE(0x06c, BIT(1)),
[CLK_BUS_I2C2] = GATE(0x06c, BIT(2)),
diff --git a/drivers/clk/sunxi/clk_f1c100s.c b/drivers/clk/sunxi/clk_f1c100s.c
new file mode 100644
index 0000000000..72cf8a6e5c
--- /dev/null
+++ b/drivers/clk/sunxi/clk_f1c100s.c
@@ -0,0 +1,74 @@
+// SPDX-License-Identifier: (GPL-2.0+)
+/*
+ * Copyright (C) 2019 George Hilliard <thirtythreeforty@gmail.com>.
+ */
+
+#include <common.h>
+#include <clk-uclass.h>
+#include <dm.h>
+#include <errno.h>
+#include <clk/sunxi.h>
+#include <dt-bindings/clock/suniv-ccu-f1c100s.h>
+#include <dt-bindings/reset/suniv-ccu-f1c100s.h>
+
+static struct ccu_clk_gate f1c100s_gates[] = {
+ [CLK_BUS_MMC0] = GATE(0x060, BIT(8)),
+ [CLK_BUS_MMC1] = GATE(0x060, BIT(9)),
+ [CLK_BUS_SPI0] = GATE(0x060, BIT(20)),
+ [CLK_BUS_SPI1] = GATE(0x060, BIT(21)),
+ [CLK_BUS_OTG] = GATE(0x060, BIT(24)),
+
+ [CLK_BUS_I2C0] = GATE(0x068, BIT(16)),
+ [CLK_BUS_I2C1] = GATE(0x068, BIT(17)),
+ [CLK_BUS_I2C2] = GATE(0x068, BIT(18)),
+ [CLK_BUS_PIO] = GATE(0x068, BIT(19)),
+
+ [CLK_BUS_UART0] = GATE(0x06c, BIT(20)),
+ [CLK_BUS_UART1] = GATE(0x06c, BIT(21)),
+ [CLK_BUS_UART2] = GATE(0x06c, BIT(22)),
+
+ [CLK_USB_PHY0] = GATE(0x0cc, BIT(1)),
+};
+
+static struct ccu_reset f1c100s_resets[] = {
+ [RST_USB_PHY0] = RESET(0x0cc, BIT(0)),
+
+ [RST_BUS_MMC0] = RESET(0x2c0, BIT(8)),
+ [RST_BUS_MMC1] = RESET(0x2c0, BIT(9)),
+ [RST_BUS_SPI0] = RESET(0x2c0, BIT(20)),
+ [RST_BUS_SPI1] = RESET(0x2c0, BIT(21)),
+ [RST_BUS_OTG] = RESET(0x2c0, BIT(24)),
+
+ [RST_BUS_I2C0] = RESET(0x2d0, BIT(16)),
+ [RST_BUS_I2C1] = RESET(0x2d0, BIT(17)),
+ [RST_BUS_I2C2] = RESET(0x2d0, BIT(18)),
+ [RST_BUS_UART0] = RESET(0x2d0, BIT(20)),
+ [RST_BUS_UART1] = RESET(0x2d0, BIT(21)),
+ [RST_BUS_UART2] = RESET(0x2d0, BIT(22)),
+};
+
+static const struct ccu_desc f1c100s_ccu_desc = {
+ .gates = f1c100s_gates,
+ .resets = f1c100s_resets,
+};
+
+static int f1c100s_clk_bind(struct udevice *dev)
+{
+ return sunxi_reset_bind(dev, ARRAY_SIZE(f1c100s_resets));
+}
+
+static const struct udevice_id f1c100s_clk_ids[] = {
+ { .compatible = "allwinner,suniv-f1c100s-ccu",
+ .data = (ulong)&f1c100s_ccu_desc },
+ { }
+};
+
+U_BOOT_DRIVER(clk_suniv_f1c100s) = {
+ .name = "suniv_f1c100s_ccu",
+ .id = UCLASS_CLK,
+ .of_match = f1c100s_clk_ids,
+ .priv_auto = sizeof(struct ccu_priv),
+ .ops = &sunxi_clk_ops,
+ .probe = sunxi_clk_probe,
+ .bind = f1c100s_clk_bind,
+};
diff --git a/drivers/clk/sunxi/clk_h3.c b/drivers/clk/sunxi/clk_h3.c
index 59afba53ee..08a830bd18 100644
--- a/drivers/clk/sunxi/clk_h3.c
+++ b/drivers/clk/sunxi/clk_h3.c
@@ -14,6 +14,8 @@
#include <linux/bitops.h>
static struct ccu_clk_gate h3_gates[] = {
+ [CLK_PLL_PERIPH0] = GATE(0x028, BIT(31)),
+
[CLK_BUS_MMC0] = GATE(0x060, BIT(8)),
[CLK_BUS_MMC1] = GATE(0x060, BIT(9)),
[CLK_BUS_MMC2] = GATE(0x060, BIT(10)),
@@ -30,6 +32,8 @@ static struct ccu_clk_gate h3_gates[] = {
[CLK_BUS_OHCI2] = GATE(0x060, BIT(30)),
[CLK_BUS_OHCI3] = GATE(0x060, BIT(31)),
+ [CLK_BUS_PIO] = GATE(0x068, BIT(5)),
+
[CLK_BUS_I2C0] = GATE(0x06c, BIT(0)),
[CLK_BUS_I2C1] = GATE(0x06c, BIT(1)),
[CLK_BUS_I2C2] = GATE(0x06c, BIT(2)),
diff --git a/drivers/clk/sunxi/clk_h6.c b/drivers/clk/sunxi/clk_h6.c
index 4a53788352..b320234293 100644
--- a/drivers/clk/sunxi/clk_h6.c
+++ b/drivers/clk/sunxi/clk_h6.c
@@ -14,6 +14,10 @@
#include <linux/bitops.h>
static struct ccu_clk_gate h6_gates[] = {
+ [CLK_PLL_PERIPH0] = GATE(0x020, BIT(31)),
+
+ [CLK_APB1] = GATE_DUMMY,
+
[CLK_BUS_MMC0] = GATE(0x84c, BIT(0)),
[CLK_BUS_MMC1] = GATE(0x84c, BIT(1)),
[CLK_BUS_MMC2] = GATE(0x84c, BIT(2)),
diff --git a/drivers/clk/sunxi/clk_h616.c b/drivers/clk/sunxi/clk_h616.c
index af97d3bb9f..80099727de 100644
--- a/drivers/clk/sunxi/clk_h616.c
+++ b/drivers/clk/sunxi/clk_h616.c
@@ -13,6 +13,10 @@
#include <linux/bitops.h>
static struct ccu_clk_gate h616_gates[] = {
+ [CLK_PLL_PERIPH0] = GATE(0x020, BIT(31) | BIT(27)),
+
+ [CLK_APB1] = GATE_DUMMY,
+
[CLK_BUS_MMC0] = GATE(0x84c, BIT(0)),
[CLK_BUS_MMC1] = GATE(0x84c, BIT(1)),
[CLK_BUS_MMC2] = GATE(0x84c, BIT(2)),
diff --git a/drivers/clk/sunxi/clk_h6_r.c b/drivers/clk/sunxi/clk_h6_r.c
index b9e527e16a..c592886a25 100644
--- a/drivers/clk/sunxi/clk_h6_r.c
+++ b/drivers/clk/sunxi/clk_h6_r.c
@@ -11,6 +11,8 @@
#include <linux/bitops.h>
static struct ccu_clk_gate h6_r_gates[] = {
+ [CLK_R_APB1] = GATE_DUMMY,
+
[CLK_R_APB1_TIMER] = GATE(0x11c, BIT(0)),
[CLK_R_APB1_TWD] = GATE(0x12c, BIT(0)),
[CLK_R_APB1_PWM] = GATE(0x13c, BIT(0)),
@@ -50,8 +52,8 @@ static const struct udevice_id h6_r_clk_ids[] = {
{ }
};
-U_BOOT_DRIVER(clk_sun6i_h6_r) = {
- .name = "sun6i_h6_r_ccu",
+U_BOOT_DRIVER(clk_sun50i_h6_r) = {
+ .name = "sun50i_h6_r_ccu",
.id = UCLASS_CLK,
.of_match = h6_r_clk_ids,
.priv_auto = sizeof(struct ccu_priv),
diff --git a/drivers/clk/sunxi/clk_r40.c b/drivers/clk/sunxi/clk_r40.c
index 4d5b69a976..45633a2a52 100644
--- a/drivers/clk/sunxi/clk_r40.c
+++ b/drivers/clk/sunxi/clk_r40.c
@@ -32,6 +32,8 @@ static struct ccu_clk_gate r40_gates[] = {
[CLK_BUS_GMAC] = GATE(0x064, BIT(17)),
+ [CLK_BUS_PIO] = GATE(0x068, BIT(5)),
+
[CLK_BUS_I2C0] = GATE(0x06c, BIT(0)),
[CLK_BUS_I2C1] = GATE(0x06c, BIT(1)),
[CLK_BUS_I2C2] = GATE(0x06c, BIT(2)),
diff --git a/drivers/clk/sunxi/clk_sunxi.c b/drivers/clk/sunxi/clk_sunxi.c
index 9673b58a49..9a21367a5d 100644
--- a/drivers/clk/sunxi/clk_sunxi.c
+++ b/drivers/clk/sunxi/clk_sunxi.c
@@ -27,6 +27,9 @@ static int sunxi_set_gate(struct clk *clk, bool on)
const struct ccu_clk_gate *gate = priv_to_gate(priv, clk->id);
u32 reg;
+ if ((gate->flags & CCU_CLK_F_DUMMY_GATE))
+ return 0;
+
if (!(gate->flags & CCU_CLK_F_IS_VALID)) {
printf("%s: (CLK#%ld) unhandled\n", __func__, clk->id);
return 0;
diff --git a/drivers/clk/sunxi/clk_v3s.c b/drivers/clk/sunxi/clk_v3s.c
index cce5c658ca..67d215cbba 100644
--- a/drivers/clk/sunxi/clk_v3s.c
+++ b/drivers/clk/sunxi/clk_v3s.c
@@ -20,6 +20,8 @@ static struct ccu_clk_gate v3s_gates[] = {
[CLK_BUS_SPI0] = GATE(0x060, BIT(20)),
[CLK_BUS_OTG] = GATE(0x060, BIT(24)),
+ [CLK_BUS_PIO] = GATE(0x068, BIT(5)),
+
[CLK_BUS_I2C0] = GATE(0x06c, BIT(0)),
[CLK_BUS_I2C1] = GATE(0x06c, BIT(1)),
[CLK_BUS_UART0] = GATE(0x06c, BIT(16)),
diff --git a/drivers/crypto/fsl/fsl_hash.c b/drivers/crypto/fsl/fsl_hash.c
index a52c4ac957..9e6829b7ad 100644
--- a/drivers/crypto/fsl/fsl_hash.c
+++ b/drivers/crypto/fsl/fsl_hash.c
@@ -149,12 +149,20 @@ static int caam_hash_finish(void *hash_ctx, void *dest_buf,
driver_hash[caam_algo].digestsize,
1);
+ flush_dcache_range((ulong)ctx->sg_tbl, (ulong)(ctx->sg_tbl) + len);
+ flush_dcache_range((ulong)ctx->sha_desc,
+ (ulong)(ctx->sha_desc) + (sizeof(uint32_t) * MAX_CAAM_DESCSIZE));
+ flush_dcache_range((ulong)ctx->hash,
+ (ulong)(ctx->hash) + driver_hash[caam_algo].digestsize);
+
ret = run_descriptor_jr(ctx->sha_desc);
if (ret) {
debug("Error %x\n", ret);
return ret;
} else {
+ invalidate_dcache_range((ulong)ctx->hash,
+ (ulong)(ctx->hash) + driver_hash[caam_algo].digestsize);
memcpy(dest_buf, ctx->hash, sizeof(ctx->hash));
}
free(ctx);
diff --git a/drivers/crypto/fsl/jr.c b/drivers/crypto/fsl/jr.c
index 1d951cf0a6..acd29924f7 100644
--- a/drivers/crypto/fsl/jr.c
+++ b/drivers/crypto/fsl/jr.c
@@ -623,7 +623,7 @@ static void kick_trng(int ent_delay, ccsr_sec_t *sec)
static int rng_init(uint8_t sec_idx, ccsr_sec_t *sec)
{
- int ret, gen_sk, ent_delay = RTSDCTL_ENT_DLY_MIN;
+ int ret, gen_sk, ent_delay = RTSDCTL_ENT_DLY;
struct rng4tst __iomem *rng =
(struct rng4tst __iomem *)&sec->rng;
u32 inst_handles;
@@ -652,6 +652,15 @@ static int rng_init(uint8_t sec_idx, ccsr_sec_t *sec)
* the RNG.
*/
ret = instantiate_rng(sec_idx, sec, gen_sk);
+ /*
+ * entropy delay is calculated via self-test method.
+ * self-test are run across different volatge, temp.
+ * if worst case value for ent_dly is identified,
+ * loop can be skipped for that platform.
+ */
+ if (IS_ENABLED(CONFIG_MX6SX))
+ break;
+
} while ((ret == -1) && (ent_delay < RTSDCTL_ENT_DLY_MAX));
if (ret) {
printf("SEC%u: Failed to instantiate RNG\n", sec_idx);
@@ -758,8 +767,14 @@ init:
return -1;
}
#if CONFIG_IS_ENABLED(OF_CONTROL)
- if (ofnode_valid(scu_node))
+ if (ofnode_valid(scu_node)) {
+ if (IS_ENABLED(CONFIG_DM_RNG)) {
+ ret = device_bind_driver(NULL, "caam-rng", "caam-rng", NULL);
+ if (ret)
+ printf("Couldn't bind rng driver (%d)\n", ret);
+ }
return ret;
+ }
#endif
#ifdef CONFIG_FSL_CORENET
diff --git a/drivers/ddr/imx/imx8m/ddrphy_utils.c b/drivers/ddr/imx/imx8m/ddrphy_utils.c
index a54449e5f1..975d553674 100644
--- a/drivers/ddr/imx/imx8m/ddrphy_utils.c
+++ b/drivers/ddr/imx/imx8m/ddrphy_utils.c
@@ -198,9 +198,14 @@ unsigned int lpddr4_mr_read(unsigned int mr_rank, unsigned int mr_addr)
tmp = reg32_read(DRC_PERF_MON_MRR0_DAT(0));
} while ((tmp & 0x8) == 0);
tmp = reg32_read(DRC_PERF_MON_MRR1_DAT(0));
- tmp = tmp & 0xff;
reg32_write(DRC_PERF_MON_MRR0_DAT(0), 0x4);
-
+ while (tmp) { //try to find a significant byte in the word
+ if (tmp & 0xff) {
+ tmp &= 0xff;
+ break;
+ }
+ tmp >>= 8;
+ }
return tmp;
}
diff --git a/drivers/gpio/imx_rgpio2p.c b/drivers/gpio/imx_rgpio2p.c
index 0e2874ca95..175e460aff 100644
--- a/drivers/gpio/imx_rgpio2p.c
+++ b/drivers/gpio/imx_rgpio2p.c
@@ -39,6 +39,14 @@ static int imx_rgpio2p_is_output(struct gpio_regs *regs, int offset)
return val & (1 << offset) ? 1 : 0;
}
+static int imx_rgpio2p_bank_get_direction(struct gpio_regs *regs, int offset)
+{
+ if ((readl(&regs->gpio_pddr) >> offset) & 0x01)
+ return IMX_RGPIO2P_DIRECTION_OUT;
+
+ return IMX_RGPIO2P_DIRECTION_IN;
+}
+
static void imx_rgpio2p_bank_direction(struct gpio_regs *regs, int offset,
enum imx_rgpio2p_direction direction)
{
@@ -67,7 +75,11 @@ static void imx_rgpio2p_bank_set_value(struct gpio_regs *regs, int offset,
static int imx_rgpio2p_bank_get_value(struct gpio_regs *regs, int offset)
{
- return (readl(&regs->gpio_pdir) >> offset) & 0x01;
+ if (imx_rgpio2p_bank_get_direction(regs, offset) ==
+ IMX_RGPIO2P_DIRECTION_IN)
+ return (readl(&regs->gpio_pdir) >> offset) & 0x01;
+
+ return (readl(&regs->gpio_pdor) >> offset) & 0x01;
}
static int imx_rgpio2p_direction_input(struct udevice *dev, unsigned offset)
diff --git a/drivers/misc/imx8ulp/s400_api.c b/drivers/misc/imx8ulp/s400_api.c
index 3ffdeb2ad2..87f5880ccb 100644
--- a/drivers/misc/imx8ulp/s400_api.c
+++ b/drivers/misc/imx8ulp/s400_api.c
@@ -272,6 +272,47 @@ int ahab_release_caam(u32 core_did, u32 *response)
return ret;
}
+int ahab_get_fw_version(u32 *fw_version, u32 *sha1, u32 *response)
+{
+ struct udevice *dev = gd->arch.s400_dev;
+ int size = sizeof(struct imx8ulp_s400_msg);
+ struct imx8ulp_s400_msg msg;
+ int ret;
+
+ if (!dev) {
+ printf("s400 dev is not initialized\n");
+ return -ENODEV;
+ }
+
+ if (!fw_version) {
+ printf("Invalid parameters for f/w version read\n");
+ return -EINVAL;
+ }
+
+ if (!sha1) {
+ printf("Invalid parameters for commit sha1\n");
+ return -EINVAL;
+ }
+
+ msg.version = AHAB_VERSION;
+ msg.tag = AHAB_CMD_TAG;
+ msg.size = 1;
+ msg.command = AHAB_GET_FW_VERSION_CID;
+
+ ret = misc_call(dev, false, &msg, size, &msg, size);
+ if (ret)
+ printf("Error: %s: ret %d, response 0x%x\n",
+ __func__, ret, msg.data[0]);
+
+ if (response)
+ *response = msg.data[0];
+
+ *fw_version = msg.data[1];
+ *sha1 = msg.data[2];
+
+ return ret;
+}
+
int ahab_dump_buffer(u32 *buffer, u32 buffer_length)
{
struct udevice *dev = gd->arch.s400_dev;
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index f04cc44e19..5e2921ce41 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -727,7 +727,7 @@ config ZYNQ_HISPD_BROKEN
config MMC_SUNXI
bool "Allwinner sunxi SD/MMC Host Controller support"
- depends on ARCH_SUNXI && !UART0_PORT_F
+ depends on ARCH_SUNXI
default y
help
This selects support for the SD/MMC Host Controller on
diff --git a/drivers/mmc/fsl_esdhc_spl.c b/drivers/mmc/fsl_esdhc_spl.c
index ea8f4cd669..760f13d240 100644
--- a/drivers/mmc/fsl_esdhc_spl.c
+++ b/drivers/mmc/fsl_esdhc_spl.c
@@ -106,7 +106,7 @@ again:
blk_off = (sector * 512) % mmc->read_bl_len;
blk_cnt = DIV_ROUND_UP(512, mmc->read_bl_len);
err = mmc->block_dev.block_read(&mmc->block_dev, blk_start, blk_cnt, tmp_buf);
- if (err != 1) {
+ if (err != blk_cnt) {
puts("spl: mmc read failed!!\n");
hang();
}
diff --git a/drivers/mtd/nand/raw/mxs_nand.c b/drivers/mtd/nand/raw/mxs_nand.c
index ee5d7fde9c..7893e9d7e3 100644
--- a/drivers/mtd/nand/raw/mxs_nand.c
+++ b/drivers/mtd/nand/raw/mxs_nand.c
@@ -1246,22 +1246,6 @@ int mxs_nand_setup_ecc(struct mtd_info *mtd)
/* Enable BCH complete interrupt */
writel(BCH_CTRL_COMPLETE_IRQ_EN, &bch_regs->hw_bch_ctrl_set);
- /* Hook some operations at the MTD level. */
- if (mtd->_read_oob != mxs_nand_hook_read_oob) {
- nand_info->hooked_read_oob = mtd->_read_oob;
- mtd->_read_oob = mxs_nand_hook_read_oob;
- }
-
- if (mtd->_write_oob != mxs_nand_hook_write_oob) {
- nand_info->hooked_write_oob = mtd->_write_oob;
- mtd->_write_oob = mxs_nand_hook_write_oob;
- }
-
- if (mtd->_block_markbad != mxs_nand_hook_block_markbad) {
- nand_info->hooked_block_markbad = mtd->_block_markbad;
- mtd->_block_markbad = mxs_nand_hook_block_markbad;
- }
-
return 0;
}
@@ -1380,6 +1364,9 @@ int mxs_nand_init_spl(struct nand_chip *nand)
else
nand_info->max_ecc_strength_supported = 40;
+ if (IS_ENABLED(CONFIG_NAND_MXS_USE_MINIMUM_ECC))
+ nand_info->use_minimum_ecc = true;
+
err = mxs_nand_alloc_buffers(nand_info);
if (err)
return err;
@@ -1467,6 +1454,22 @@ int mxs_nand_init_ctrl(struct mxs_nand_info *nand_info)
if (err)
goto err_free_buffers;
+ /* Hook some operations at the MTD level. */
+ if (mtd->_read_oob != mxs_nand_hook_read_oob) {
+ nand_info->hooked_read_oob = mtd->_read_oob;
+ mtd->_read_oob = mxs_nand_hook_read_oob;
+ }
+
+ if (mtd->_write_oob != mxs_nand_hook_write_oob) {
+ nand_info->hooked_write_oob = mtd->_write_oob;
+ mtd->_write_oob = mxs_nand_hook_write_oob;
+ }
+
+ if (mtd->_block_markbad != mxs_nand_hook_block_markbad) {
+ nand_info->hooked_block_markbad = mtd->_block_markbad;
+ mtd->_block_markbad = mxs_nand_hook_block_markbad;
+ }
+
err = nand_register(0, mtd);
if (err)
goto err_free_buffers;
diff --git a/drivers/mtd/nand/raw/mxs_nand_spl.c b/drivers/mtd/nand/raw/mxs_nand_spl.c
index 59a67ee414..2bfb181007 100644
--- a/drivers/mtd/nand/raw/mxs_nand_spl.c
+++ b/drivers/mtd/nand/raw/mxs_nand_spl.c
@@ -218,14 +218,14 @@ void nand_init(void)
mxs_nand_setup_ecc(mtd);
}
-int nand_spl_load_image(uint32_t offs, unsigned int size, void *buf)
+int nand_spl_load_image(uint32_t offs, unsigned int size, void *dst)
{
- struct nand_chip *chip;
- unsigned int page;
+ unsigned int sz;
+ unsigned int block, lastblock;
+ unsigned int page, page_offset;
unsigned int nand_page_per_block;
- unsigned int sz = 0;
+ struct nand_chip *chip;
u8 *page_buf = NULL;
- u32 page_off;
chip = mtd_to_nand(mtd);
if (!chip->numchips)
@@ -235,47 +235,42 @@ int nand_spl_load_image(uint32_t offs, unsigned int size, void *buf)
if (!page_buf)
return -ENOMEM;
- page = offs >> chip->page_shift;
- page_off = offs & (mtd->writesize - 1);
+ /* offs has to be aligned to a page address! */
+ block = offs / mtd->erasesize;
+ lastblock = (offs + size - 1) / mtd->erasesize;
+ page = (offs % mtd->erasesize) / mtd->writesize;
+ page_offset = offs % mtd->writesize;
nand_page_per_block = mtd->erasesize / mtd->writesize;
- debug("%s offset:0x%08x len:%d page:%x\n", __func__, offs, size, page);
-
- while (size) {
- if (mxs_read_page_ecc(mtd, page_buf, page) < 0)
- return -1;
-
- if (size > (mtd->writesize - page_off))
- sz = (mtd->writesize - page_off);
- else
- sz = size;
-
- memcpy(buf, page_buf + page_off, sz);
-
- offs += mtd->writesize;
- page++;
- buf += (mtd->writesize - page_off);
- page_off = 0;
- size -= sz;
-
- /*
- * Check if we have crossed a block boundary, and if so
- * check for bad block.
- */
- if (!(page % nand_page_per_block)) {
- /*
- * Yes, new block. See if this block is good. If not,
- * loop until we find a good block.
- */
- while (is_badblock(mtd, offs, 1)) {
- page = page + nand_page_per_block;
- /* Check i we've reached the end of flash. */
- if (page >= mtd->size >> chip->page_shift) {
+ while (block <= lastblock && size > 0) {
+ if (!is_badblock(mtd, mtd->erasesize * block, 1)) {
+ /* Skip bad blocks */
+ while (page < nand_page_per_block) {
+ int curr_page = nand_page_per_block * block + page;
+
+ if (mxs_read_page_ecc(mtd, page_buf, curr_page) < 0) {
free(page_buf);
- return -ENOMEM;
+ return -EIO;
}
+
+ if (size > (mtd->writesize - page_offset))
+ sz = (mtd->writesize - page_offset);
+ else
+ sz = size;
+
+ memcpy(dst, page_buf + page_offset, sz);
+ dst += sz;
+ size -= sz;
+ page_offset = 0;
+ page++;
}
+
+ page = 0;
+ } else {
+ lastblock++;
}
+
+ block++;
}
free(page_buf);
@@ -294,6 +289,19 @@ void nand_deselect(void)
u32 nand_spl_adjust_offset(u32 sector, u32 offs)
{
- /* Handle the offset adjust in nand_spl_load_image,*/
+ unsigned int block, lastblock;
+
+ block = sector / mtd->erasesize;
+ lastblock = (sector + offs) / mtd->erasesize;
+
+ while (block <= lastblock) {
+ if (is_badblock(mtd, block * mtd->erasesize, 1)) {
+ offs += mtd->erasesize;
+ lastblock++;
+ }
+
+ block++;
+ }
+
return offs;
}
diff --git a/drivers/mtd/spi/sf-uclass.c b/drivers/mtd/spi/sf-uclass.c
index 63d16291ff..e6e650ef8c 100644
--- a/drivers/mtd/spi/sf-uclass.c
+++ b/drivers/mtd/spi/sf-uclass.c
@@ -46,25 +46,12 @@ int spl_flash_get_sw_write_prot(struct udevice *dev)
* TODO(sjg@chromium.org): This is an old-style function. We should remove
* it when all SPI flash drivers use dm
*/
-struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs,
+struct spi_flash *spi_flash_probe(unsigned int busnum, unsigned int cs,
unsigned int max_hz, unsigned int spi_mode)
{
- struct udevice *dev;
-
- if (spi_flash_probe_bus_cs(bus, cs, max_hz, spi_mode, &dev))
- return NULL;
-
- return dev_get_uclass_priv(dev);
-}
-
-int spi_flash_probe_bus_cs(unsigned int busnum, unsigned int cs,
- unsigned int max_hz, unsigned int spi_mode,
- struct udevice **devp)
-{
struct spi_slave *slave;
struct udevice *bus;
char *str;
- int ret;
#if defined(CONFIG_SPL_BUILD) && CONFIG_IS_ENABLED(USE_TINY_PRINTF)
str = "spi_flash";
@@ -74,8 +61,22 @@ int spi_flash_probe_bus_cs(unsigned int busnum, unsigned int cs,
snprintf(name, sizeof(name), "spi_flash@%d:%d", busnum, cs);
str = strdup(name);
#endif
- ret = spi_get_bus_and_cs(busnum, cs, max_hz, spi_mode,
- "jedec_spi_nor", str, &bus, &slave);
+
+ if (_spi_get_bus_and_cs(busnum, cs, max_hz, spi_mode,
+ "jedec_spi_nor", str, &bus, &slave))
+ return NULL;
+
+ return dev_get_uclass_priv(slave->dev);
+}
+
+int spi_flash_probe_bus_cs(unsigned int busnum, unsigned int cs,
+ struct udevice **devp)
+{
+ struct spi_slave *slave;
+ struct udevice *bus;
+ int ret;
+
+ ret = spi_get_bus_and_cs(busnum, cs, &bus, &slave);
if (ret)
return ret;
diff --git a/drivers/net/fm/fm.c b/drivers/net/fm/fm.c
index f825612640..d0b492b5a1 100644
--- a/drivers/net/fm/fm.c
+++ b/drivers/net/fm/fm.c
@@ -388,7 +388,7 @@ int fm_init_common(int index, struct ccsr_fman *reg)
/* speed and mode will be read from DT */
ret = spi_flash_probe_bus_cs(CONFIG_SF_DEFAULT_BUS,
- CONFIG_SF_DEFAULT_CS, 0, 0, &new);
+ CONFIG_SF_DEFAULT_CS, &new);
ucode_flash = dev_get_uclass_priv(new);
#else
@@ -475,7 +475,7 @@ int fm_init_common(int index, struct ccsr_fman *reg)
/* speed and mode will be read from DT */
ret = spi_flash_probe_bus_cs(CONFIG_SF_DEFAULT_BUS, CONFIG_SF_DEFAULT_CS,
- 0, 0, &new);
+ &new);
ucode_flash = dev_get_uclass_priv(new);
#else
diff --git a/drivers/net/pfe_eth/pfe_firmware.c b/drivers/net/pfe_eth/pfe_firmware.c
index 6669048181..82a4aa89a4 100644
--- a/drivers/net/pfe_eth/pfe_firmware.c
+++ b/drivers/net/pfe_eth/pfe_firmware.c
@@ -172,31 +172,20 @@ static int pfe_fit_check(void)
int pfe_spi_flash_init(void)
{
struct spi_flash *pfe_flash;
- struct udevice *new;
int ret = 0;
void *addr = malloc(CONFIG_SYS_LS_PFE_FW_LENGTH);
if (!addr)
return -ENOMEM;
- ret = spi_flash_probe_bus_cs(CONFIG_SYS_FSL_PFE_SPI_BUS,
- CONFIG_SYS_FSL_PFE_SPI_CS,
- CONFIG_SYS_FSL_PFE_SPI_MAX_HZ,
- CONFIG_SYS_FSL_PFE_SPI_MODE,
- &new);
- if (ret) {
- printf("SF: failed to probe spi\n");
- free(addr);
- device_remove(new, DM_REMOVE_NORMAL);
- return ret;
- }
-
+ pfe_flash = spi_flash_probe(CONFIG_SYS_FSL_PFE_SPI_BUS,
+ CONFIG_SYS_FSL_PFE_SPI_CS,
+ CONFIG_SYS_FSL_PFE_SPI_MAX_HZ,
+ CONFIG_SYS_FSL_PFE_SPI_MODE);
- pfe_flash = dev_get_uclass_priv(new);
if (!pfe_flash) {
printf("SF: probe for pfe failed\n");
free(addr);
- device_remove(new, DM_REMOVE_NORMAL);
return -ENODEV;
}
diff --git a/drivers/net/sni_netsec.c b/drivers/net/sni_netsec.c
index 24caacf847..9780f2092b 100644
--- a/drivers/net/sni_netsec.c
+++ b/drivers/net/sni_netsec.c
@@ -621,12 +621,10 @@ static int netsec_stop_gmac(struct netsec_priv *priv)
static void netsec_spi_read(char *buf, loff_t len, loff_t offset)
{
- struct udevice *new;
struct spi_flash *flash;
- spi_flash_probe_bus_cs(CONFIG_SF_DEFAULT_BUS, CONFIG_SF_DEFAULT_CS,
- CONFIG_SF_DEFAULT_SPEED, CONFIG_SF_DEFAULT_MODE, &new);
- flash = dev_get_uclass_priv(new);
+ flash = spi_flash_probe(CONFIG_SF_DEFAULT_BUS, CONFIG_SF_DEFAULT_CS,
+ CONFIG_SF_DEFAULT_SPEED, CONFIG_SF_DEFAULT_MODE);
spi_flash_read(flash, offset, len, buf);
}
diff --git a/drivers/pinctrl/pinctrl-uclass.c b/drivers/pinctrl/pinctrl-uclass.c
index 4462ed20e2..38ce2b5e0a 100644
--- a/drivers/pinctrl/pinctrl-uclass.c
+++ b/drivers/pinctrl/pinctrl-uclass.c
@@ -402,6 +402,13 @@ static int __maybe_unused pinctrl_post_bind(struct udevice *dev)
{
const struct pinctrl_ops *ops = pinctrl_get_ops(dev);
+ /*
+ * Make sure that the pinctrl driver gets probed after binding
+ * as some pinctrl drivers also register the GPIO driver during
+ * probe, and if they are not probed GPIO-s are not registered.
+ */
+ dev_or_flags(dev, DM_FLAG_PROBE_AFTER_BIND);
+
if (!ops) {
dev_dbg(dev, "ops is not set. Do not bind.\n");
return -EINVAL;
diff --git a/drivers/power/pmic/pca9450.c b/drivers/power/pmic/pca9450.c
index 2394b196c5..116ac49a8d 100644
--- a/drivers/power/pmic/pca9450.c
+++ b/drivers/power/pmic/pca9450.c
@@ -19,8 +19,10 @@ DECLARE_GLOBAL_DATA_PTR;
static const struct pmic_child_info pmic_children_info[] = {
/* buck */
{ .prefix = "b", .driver = PCA9450_REGULATOR_DRIVER},
+ { .prefix = "B", .driver = PCA9450_REGULATOR_DRIVER},
/* ldo */
{ .prefix = "l", .driver = PCA9450_REGULATOR_DRIVER},
+ { .prefix = "L", .driver = PCA9450_REGULATOR_DRIVER},
{ },
};
@@ -81,9 +83,9 @@ static struct dm_pmic_ops pca9450_ops = {
};
static const struct udevice_id pca9450_ids[] = {
- { .compatible = "nxp,pca9450a", .data = 0x25, },
- { .compatible = "nxp,pca9450b", .data = 0x25, },
- { .compatible = "nxp,pca9450c", .data = 0x25, },
+ { .compatible = "nxp,pca9450a", .data = NXP_CHIP_TYPE_PCA9450A, },
+ { .compatible = "nxp,pca9450b", .data = NXP_CHIP_TYPE_PCA9450BC, },
+ { .compatible = "nxp,pca9450c", .data = NXP_CHIP_TYPE_PCA9450BC, },
{ }
};
diff --git a/drivers/power/regulator/Kconfig b/drivers/power/regulator/Kconfig
index 9145408b3c..d6cea8ec66 100644
--- a/drivers/power/regulator/Kconfig
+++ b/drivers/power/regulator/Kconfig
@@ -60,6 +60,21 @@ config SPL_DM_REGULATOR_BD71837
This config enables implementation of driver-model regulator uclass
features for regulators on ROHM BD71837 and BD71847 in SPL.
+config DM_REGULATOR_PCA9450
+ bool "Enable Driver Model for NXP PCA9450 regulators"
+ depends on DM_REGULATOR && DM_PMIC_PCA9450
+ help
+ This config enables implementation of driver-model regulator uclass
+ features for regulators on NXP PCA9450 PMICs. PCA9450 contains 6 bucks
+ and 5 LDOS. The driver implements get/set api for value and enable.
+
+config SPL_DM_REGULATOR_PCA9450
+ bool "Enable Driver Model for NXP PCA9450 regulators in SPL"
+ depends on DM_REGULATOR_PCA9450
+ help
+ This config enables implementation of driver-model regulator uclass
+ features for regulators on ROHM PCA9450 in SPL.
+
config DM_REGULATOR_DA9063
bool "Enable Driver Model for REGULATOR DA9063"
depends on DM_REGULATOR && DM_PMIC_DA9063
diff --git a/drivers/power/regulator/Makefile b/drivers/power/regulator/Makefile
index b9883df928..bc736068bc 100644
--- a/drivers/power/regulator/Makefile
+++ b/drivers/power/regulator/Makefile
@@ -11,6 +11,7 @@ obj-$(CONFIG_$(SPL_)DM_REGULATOR_DA9063) += da9063.o
obj-$(CONFIG_DM_REGULATOR_MAX77686) += max77686.o
obj-$(CONFIG_$(SPL_)DM_PMIC_PFUZE100) += pfuze100.o
obj-$(CONFIG_$(SPL_)DM_REGULATOR_BD71837) += bd71837.o
+obj-$(CONFIG_$(SPL_)DM_REGULATOR_PCA9450) += pca9450.o
obj-$(CONFIG_$(SPL_)REGULATOR_PWM) += pwm_regulator.o
obj-$(CONFIG_$(SPL_)DM_REGULATOR_FAN53555) += fan53555.o
obj-$(CONFIG_$(SPL_)DM_REGULATOR_COMMON) += regulator_common.o
diff --git a/drivers/power/regulator/pca9450.c b/drivers/power/regulator/pca9450.c
new file mode 100644
index 0000000000..23badaa332
--- /dev/null
+++ b/drivers/power/regulator/pca9450.c
@@ -0,0 +1,333 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * NXP PCA9450 regulator driver
+ * Copyright (C) 2022 Marek Vasut <marex@denx.de>
+ *
+ * Largely based on:
+ * ROHM BD71837 regulator driver
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <log.h>
+#include <linux/bitops.h>
+#include <power/pca9450.h>
+#include <power/pmic.h>
+#include <power/regulator.h>
+
+#define HW_STATE_CONTROL 0
+#define DEBUG
+
+/**
+ * struct pca9450_vrange - describe linear range of voltages
+ *
+ * @min_volt: smallest voltage in range
+ * @step: how much voltage changes at each selector step
+ * @min_sel: smallest selector in the range
+ * @max_sel: maximum selector in the range
+ */
+struct pca9450_vrange {
+ unsigned int min_volt;
+ unsigned int step;
+ u8 min_sel;
+ u8 max_sel;
+};
+
+/**
+ * struct pca9450_plat - describe regulator control registers
+ *
+ * @name: name of the regulator. Used for matching the dt-entry
+ * @enable_reg: register address used to enable/disable regulator
+ * @enablemask: register mask used to enable/disable regulator
+ * @volt_reg: register address used to configure regulator voltage
+ * @volt_mask: register mask used to configure regulator voltage
+ * @ranges: pointer to ranges of regulator voltages and matching register
+ * values
+ * @numranges: number of voltage ranges pointed by ranges
+ * @dvs: whether the voltage can be changed when regulator is enabled
+ */
+struct pca9450_plat {
+ const char *name;
+ u8 enable_reg;
+ u8 enablemask;
+ u8 volt_reg;
+ u8 volt_mask;
+ struct pca9450_vrange *ranges;
+ unsigned int numranges;
+ bool dvs;
+};
+
+#define PCA_RANGE(_min, _vstep, _sel_low, _sel_hi) \
+{ \
+ .min_volt = (_min), .step = (_vstep), \
+ .min_sel = (_sel_low), .max_sel = (_sel_hi), \
+}
+
+#define PCA_DATA(_name, enreg, enmask, vreg, vmask, _range, _dvs) \
+{ \
+ .name = (_name), .enable_reg = (enreg), .enablemask = (enmask), \
+ .volt_reg = (vreg), .volt_mask = (vmask), .ranges = (_range), \
+ .numranges = ARRAY_SIZE(_range), .dvs = (_dvs), \
+}
+
+static struct pca9450_vrange pca9450_buck123_vranges[] = {
+ PCA_RANGE(600000, 12500, 0, 0x7f),
+};
+
+static struct pca9450_vrange pca9450_buck456_vranges[] = {
+ PCA_RANGE(600000, 25000, 0, 0x70),
+ PCA_RANGE(3400000, 0, 0x71, 0x7f),
+};
+
+static struct pca9450_vrange pca9450_ldo1_vranges[] = {
+ PCA_RANGE(1600000, 100000, 0x0, 0x3),
+ PCA_RANGE(3000000, 100000, 0x4, 0x7),
+};
+
+static struct pca9450_vrange pca9450_ldo2_vranges[] = {
+ PCA_RANGE(800000, 50000, 0x0, 0x7),
+};
+
+static struct pca9450_vrange pca9450_ldo34_vranges[] = {
+ PCA_RANGE(800000, 100000, 0x0, 0x19),
+ PCA_RANGE(3300000, 0, 0x1a, 0x1f),
+};
+
+static struct pca9450_vrange pca9450_ldo5_vranges[] = {
+ PCA_RANGE(1800000, 100000, 0x0, 0xf),
+};
+
+/*
+ * We use enable mask 'HW_STATE_CONTROL' to indicate that this regulator
+ * must not be enabled or disabled by SW. The typical use-case for PCA9450
+ * is powering NXP i.MX8. In this use-case we (for now) only allow control
+ * for BUCK4, BUCK5, BUCK6 which are not boot critical.
+ */
+static struct pca9450_plat pca9450_reg_data[] = {
+ /* Bucks 1-3 which support dynamic voltage scaling */
+ PCA_DATA("BUCK1", PCA9450_BUCK1CTRL, HW_STATE_CONTROL,
+ PCA9450_BUCK1OUT_DVS0, PCA9450_DVS_BUCK_RUN_MASK,
+ pca9450_buck123_vranges, true),
+ PCA_DATA("BUCK2", PCA9450_BUCK2CTRL, HW_STATE_CONTROL,
+ PCA9450_BUCK2OUT_DVS0, PCA9450_DVS_BUCK_RUN_MASK,
+ pca9450_buck123_vranges, true),
+ PCA_DATA("BUCK3", PCA9450_BUCK3CTRL, HW_STATE_CONTROL,
+ PCA9450_BUCK3OUT_DVS0, PCA9450_DVS_BUCK_RUN_MASK,
+ pca9450_buck123_vranges, true),
+ /* Bucks 4-6 which do not support dynamic voltage scaling */
+ PCA_DATA("BUCK4", PCA9450_BUCK4CTRL, HW_STATE_CONTROL,
+ PCA9450_BUCK4OUT, PCA9450_DVS_BUCK_RUN_MASK,
+ pca9450_buck456_vranges, false),
+ PCA_DATA("BUCK5", PCA9450_BUCK5CTRL, HW_STATE_CONTROL,
+ PCA9450_BUCK5OUT, PCA9450_DVS_BUCK_RUN_MASK,
+ pca9450_buck456_vranges, false),
+ PCA_DATA("BUCK6", PCA9450_BUCK6CTRL, HW_STATE_CONTROL,
+ PCA9450_BUCK6OUT, PCA9450_DVS_BUCK_RUN_MASK,
+ pca9450_buck456_vranges, false),
+ /* LDOs */
+ PCA_DATA("LDO1", PCA9450_LDO1CTRL, HW_STATE_CONTROL,
+ PCA9450_LDO1CTRL, PCA9450_LDO12_MASK,
+ pca9450_ldo1_vranges, false),
+ PCA_DATA("LDO2", PCA9450_LDO2CTRL, HW_STATE_CONTROL,
+ PCA9450_LDO2CTRL, PCA9450_LDO12_MASK,
+ pca9450_ldo2_vranges, false),
+ PCA_DATA("LDO3", PCA9450_LDO3CTRL, HW_STATE_CONTROL,
+ PCA9450_LDO3CTRL, PCA9450_LDO34_MASK,
+ pca9450_ldo34_vranges, false),
+ PCA_DATA("LDO4", PCA9450_LDO4CTRL, HW_STATE_CONTROL,
+ PCA9450_LDO4CTRL, PCA9450_LDO34_MASK,
+ pca9450_ldo34_vranges, false),
+ PCA_DATA("LDO5", PCA9450_LDO5CTRL_H, HW_STATE_CONTROL,
+ PCA9450_LDO5CTRL_H, PCA9450_LDO5_MASK,
+ pca9450_ldo5_vranges, false),
+};
+
+static int vrange_find_value(struct pca9450_vrange *r, unsigned int sel,
+ unsigned int *val)
+{
+ if (!val || sel < r->min_sel || sel > r->max_sel)
+ return -EINVAL;
+
+ *val = r->min_volt + r->step * (sel - r->min_sel);
+ return 0;
+}
+
+static int vrange_find_selector(struct pca9450_vrange *r, int val,
+ unsigned int *sel)
+{
+ int ret = -EINVAL;
+ int num_vals = r->max_sel - r->min_sel + 1;
+
+ if (val >= r->min_volt &&
+ val <= r->min_volt + r->step * (num_vals - 1)) {
+ if (r->step) {
+ *sel = r->min_sel + ((val - r->min_volt) / r->step);
+ ret = 0;
+ } else {
+ *sel = r->min_sel;
+ ret = 0;
+ }
+ }
+ return ret;
+}
+
+static int pca9450_get_enable(struct udevice *dev)
+{
+ struct pca9450_plat *plat = dev_get_plat(dev);
+ int val;
+
+ /*
+ * boot critical regulators on pca9450 must not be controlled by sw
+ * due to the 'feature' which leaves power rails down if pca9450 is
+ * reseted to snvs state. hence we can't get the state here.
+ *
+ * if we are alive it means we probably are on run state and
+ * if the regulator can't be controlled we can assume it is
+ * enabled.
+ */
+ if (plat->enablemask == HW_STATE_CONTROL)
+ return 1;
+
+ val = pmic_reg_read(dev->parent, plat->enable_reg);
+ if (val < 0)
+ return val;
+
+ return (val & plat->enablemask);
+}
+
+static int pca9450_set_enable(struct udevice *dev, bool enable)
+{
+ int val = 0;
+ struct pca9450_plat *plat = dev_get_plat(dev);
+
+ /*
+ * boot critical regulators on pca9450 must not be controlled by sw
+ * due to the 'feature' which leaves power rails down if pca9450 is
+ * reseted to snvs state. Hence we can't set the state here.
+ */
+ if (plat->enablemask == HW_STATE_CONTROL)
+ return enable ? 0 : -EINVAL;
+
+ if (enable)
+ val = plat->enablemask;
+
+ return pmic_clrsetbits(dev->parent, plat->enable_reg, plat->enablemask,
+ val);
+}
+
+static int pca9450_get_value(struct udevice *dev)
+{
+ struct pca9450_plat *plat = dev_get_plat(dev);
+ unsigned int reg, tmp;
+ int i, ret;
+
+ ret = pmic_reg_read(dev->parent, plat->volt_reg);
+ if (ret < 0)
+ return ret;
+
+ reg = ret;
+ reg &= plat->volt_mask;
+
+ for (i = 0; i < plat->numranges; i++) {
+ struct pca9450_vrange *r = &plat->ranges[i];
+
+ if (!vrange_find_value(r, reg, &tmp))
+ return tmp;
+ }
+
+ pr_err("Unknown voltage value read from pmic\n");
+
+ return -EINVAL;
+}
+
+static int pca9450_set_value(struct udevice *dev, int uvolt)
+{
+ struct pca9450_plat *plat = dev_get_plat(dev);
+ unsigned int sel;
+ int i, found = 0;
+
+ /*
+ * An under/overshooting may occur if voltage is changed for other
+ * regulators but buck 1,2,3 or 4 when regulator is enabled. Prevent
+ * change to protect the HW
+ */
+ if (!plat->dvs)
+ if (pca9450_get_enable(dev)) {
+ /* If the value is already set, skip the warning. */
+ if (pca9450_get_value(dev) == uvolt)
+ return 0;
+ pr_err("Only DVS bucks can be changed when enabled\n");
+ return -EINVAL;
+ }
+
+ for (i = 0; i < plat->numranges; i++) {
+ struct pca9450_vrange *r = &plat->ranges[i];
+
+ found = !vrange_find_selector(r, uvolt, &sel);
+ if (found) {
+ unsigned int tmp;
+
+ /*
+ * We require exactly the requested value to be
+ * supported - this can be changed later if needed
+ */
+ found = !vrange_find_value(r, sel, &tmp);
+ if (found && tmp == uvolt)
+ break;
+ found = 0;
+ }
+ }
+
+ if (!found)
+ return -EINVAL;
+
+ return pmic_clrsetbits(dev->parent, plat->volt_reg,
+ plat->volt_mask, sel);
+}
+
+static int pca9450_regulator_probe(struct udevice *dev)
+{
+ struct pca9450_plat *plat = dev_get_plat(dev);
+ int i, type;
+
+ type = dev_get_driver_data(dev_get_parent(dev));
+
+ if (type != NXP_CHIP_TYPE_PCA9450A && type != NXP_CHIP_TYPE_PCA9450BC) {
+ debug("Unknown PMIC type\n");
+ return -EINVAL;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(pca9450_reg_data); i++) {
+ if (strcmp(dev->name, pca9450_reg_data[i].name))
+ continue;
+
+ /* PCA9450B/PCA9450C uses BUCK1 and BUCK3 in dual-phase */
+ if (type == NXP_CHIP_TYPE_PCA9450BC &&
+ !strcmp(pca9450_reg_data[i].name, "BUCK3")) {
+ continue;
+ }
+
+ *plat = pca9450_reg_data[i];
+
+ return 0;
+ }
+
+ pr_err("Unknown regulator '%s'\n", dev->name);
+
+ return -ENOENT;
+}
+
+static const struct dm_regulator_ops pca9450_regulator_ops = {
+ .get_value = pca9450_get_value,
+ .set_value = pca9450_set_value,
+ .get_enable = pca9450_get_enable,
+ .set_enable = pca9450_set_enable,
+};
+
+U_BOOT_DRIVER(pca9450_regulator) = {
+ .name = PCA9450_REGULATOR_DRIVER,
+ .id = UCLASS_REGULATOR,
+ .ops = &pca9450_regulator_ops,
+ .probe = pca9450_regulator_probe,
+ .plat_auto = sizeof(struct pca9450_plat),
+};
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 26fa498bbb..45c284a408 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -84,36 +84,10 @@ config VPL_SERIAL_PRESENT
This option enables the full UART in TPL, so if is it disabled,
the full UART driver will be omitted, thus saving space.
-# Logic to allow us to use the imply keyword to set what the default port
-# should be. The default is otherwise 1.
-config CONS_INDEX_0
- bool
-
-config CONS_INDEX_2
- bool
-
-config CONS_INDEX_3
- bool
-
-config CONS_INDEX_4
- bool
-
-config CONS_INDEX_5
- bool
-
-config CONS_INDEX_6
- bool
-
config CONS_INDEX
int "UART used for console"
depends on SPECIFY_CONSOLE_INDEX
range 0 6
- default 0 if CONS_INDEX_0
- default 2 if CONS_INDEX_2
- default 3 if CONS_INDEX_3
- default 4 if CONS_INDEX_4
- default 5 if CONS_INDEX_5
- default 6 if CONS_INDEX_6
default 1
help
Set this to match the UART number of the serial console.
@@ -508,6 +482,20 @@ config DEBUG_UART_BASE
A default should be provided by your board, but if not you will need
to use the correct value here.
+config SPL_DEBUG_UART_BASE
+ hex "Base address of UART for SPL"
+ depends on SPL && DEBUG_UART
+ default DEBUG_UART_BASE
+ help
+ This is the base address of your UART for memory-mapped UARTs for SPL.
+
+config TPL_DEBUG_UART_BASE
+ hex "Base address of UART for TPL"
+ depends on TPL && DEBUG_UART
+ default DEBUG_UART_BASE
+ help
+ This is the base address of your UART for memory-mapped UARTs for TPL.
+
config DEBUG_UART_CLOCK
int "UART input clock"
depends on DEBUG_UART
diff --git a/drivers/serial/ns16550.c b/drivers/serial/ns16550.c
index a4220fd0ae..78bfe6281c 100644
--- a/drivers/serial/ns16550.c
+++ b/drivers/serial/ns16550.c
@@ -325,7 +325,7 @@ int ns16550_tstc(struct ns16550 *com_port)
static inline void _debug_uart_init(void)
{
- struct ns16550 *com_port = (struct ns16550 *)CONFIG_DEBUG_UART_BASE;
+ struct ns16550 *com_port = (struct ns16550 *)CONFIG_VAL(DEBUG_UART_BASE);
int baud_divisor;
/*
@@ -360,7 +360,7 @@ static inline int NS16550_read_baud_divisor(struct ns16550 *com_port)
static inline void _debug_uart_putc(int ch)
{
- struct ns16550 *com_port = (struct ns16550 *)CONFIG_DEBUG_UART_BASE;
+ struct ns16550 *com_port = (struct ns16550 *)CONFIG_VAL(DEBUG_UART_BASE);
while (!(serial_din(&com_port->lsr) & UART_LSR_THRE)) {
#ifdef CONFIG_DEBUG_UART_NS16550_CHECK_ENABLED
diff --git a/drivers/spi/spi-uclass.c b/drivers/spi/spi-uclass.c
index f8ec312d71..f2791c4b88 100644
--- a/drivers/spi/spi-uclass.c
+++ b/drivers/spi/spi-uclass.c
@@ -340,9 +340,65 @@ int spi_find_bus_and_cs(int busnum, int cs, struct udevice **busp,
return ret;
}
-int spi_get_bus_and_cs(int busnum, int cs, int speed, int mode,
- const char *drv_name, const char *dev_name,
- struct udevice **busp, struct spi_slave **devp)
+int spi_get_bus_and_cs(int busnum, int cs, struct udevice **busp,
+ struct spi_slave **devp)
+{
+ struct udevice *bus, *dev;
+ struct dm_spi_bus *bus_data;
+ struct spi_slave *slave;
+ int ret;
+
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+ ret = uclass_first_device_err(UCLASS_SPI, &bus);
+#else
+ ret = uclass_get_device_by_seq(UCLASS_SPI, busnum, &bus);
+#endif
+ if (ret) {
+ log_err("Invalid bus %d (err=%d)\n", busnum, ret);
+ return ret;
+ }
+ ret = spi_find_chip_select(bus, cs, &dev);
+ if (ret) {
+ dev_err(bus, "Invalid chip select %d:%d (err=%d)\n", busnum, cs, ret);
+ return ret;
+ }
+
+ if (!device_active(dev)) {
+ struct spi_slave *slave;
+
+ ret = device_probe(dev);
+ if (ret)
+ goto err;
+ slave = dev_get_parent_priv(dev);
+ slave->dev = dev;
+ }
+
+ slave = dev_get_parent_priv(dev);
+ bus_data = dev_get_uclass_priv(bus);
+
+ /*
+ * In case the operation speed is not yet established by
+ * dm_spi_claim_bus() ensure the bus is configured properly.
+ */
+ if (!bus_data->speed) {
+ ret = spi_claim_bus(slave);
+ if (ret)
+ goto err;
+ }
+ *busp = bus;
+ *devp = slave;
+
+ return 0;
+
+err:
+ log_debug("%s: Error path, device '%s'\n", __func__, dev->name);
+
+ return ret;
+}
+
+int _spi_get_bus_and_cs(int busnum, int cs, int speed, int mode,
+ const char *drv_name, const char *dev_name,
+ struct udevice **busp, struct spi_slave **devp)
{
struct udevice *bus, *dev;
struct dm_spi_slave_plat *plat;
@@ -453,8 +509,8 @@ struct spi_slave *spi_setup_slave(unsigned int busnum, unsigned int cs,
struct udevice *dev;
int ret;
- ret = spi_get_bus_and_cs(busnum, cs, speed, mode, NULL, 0, &dev,
- &slave);
+ ret = _spi_get_bus_and_cs(busnum, cs, speed, mode, NULL, 0, &dev,
+ &slave);
if (ret)
return NULL;
diff --git a/drivers/spi/stm32_qspi.c b/drivers/spi/stm32_qspi.c
index 8f4aabc3d1..ceba413727 100644
--- a/drivers/spi/stm32_qspi.c
+++ b/drivers/spi/stm32_qspi.c
@@ -150,20 +150,19 @@ static int _stm32_qspi_wait_cmd(struct stm32_qspi_priv *priv,
u32 sr;
int ret = 0;
- if (op->data.nbytes) {
- ret = readl_poll_timeout(&priv->regs->sr, sr,
- sr & STM32_QSPI_SR_TCF,
- STM32_QSPI_CMD_TIMEOUT_US);
- if (ret) {
- log_err("cmd timeout (stat:%#x)\n", sr);
- } else if (readl(&priv->regs->sr) & STM32_QSPI_SR_TEF) {
- log_err("transfer error (stat:%#x)\n", sr);
- ret = -EIO;
- }
- /* clear flags */
- writel(STM32_QSPI_FCR_CTCF | STM32_QSPI_FCR_CTEF, &priv->regs->fcr);
+ ret = readl_poll_timeout(&priv->regs->sr, sr,
+ sr & STM32_QSPI_SR_TCF,
+ STM32_QSPI_CMD_TIMEOUT_US);
+ if (ret) {
+ log_err("cmd timeout (stat:%#x)\n", sr);
+ } else if (readl(&priv->regs->sr) & STM32_QSPI_SR_TEF) {
+ log_err("transfer error (stat:%#x)\n", sr);
+ ret = -EIO;
}
+ /* clear flags */
+ writel(STM32_QSPI_FCR_CTCF | STM32_QSPI_FCR_CTEF, &priv->regs->fcr);
+
if (!ret)
ret = _stm32_qspi_wait_for_not_busy(priv);
@@ -256,10 +255,6 @@ static int stm32_qspi_exec_op(struct spi_slave *slave,
op->dummy.buswidth, op->data.buswidth,
op->addr.val, op->data.nbytes);
- ret = _stm32_qspi_wait_for_not_busy(priv);
- if (ret)
- return ret;
-
addr_max = op->addr.val + op->data.nbytes + 1;
if (op->data.dir == SPI_MEM_DATA_IN && op->data.nbytes) {
diff --git a/drivers/tpm/Kconfig b/drivers/tpm/Kconfig
index eceff27d5f..d59102d9a6 100644
--- a/drivers/tpm/Kconfig
+++ b/drivers/tpm/Kconfig
@@ -185,6 +185,15 @@ config TPM2_TIS_SPI
to the device using the standard TPM Interface Specification (TIS)
protocol.
+config TPM2_TIS_I2C
+ bool "Enable support for TPMv2.x I2C chips"
+ depends on TPM_V2 && DM_I2C
+ help
+ This driver supports TPMv2.x devices connected on the I2C bus.
+ The usual TPM operations and the 'tpm' command can be used to talk
+ to the device using the standard TPM Interface Specification (TIS)
+ protocol.
+
config TPM2_FTPM_TEE
bool "TEE based fTPM Interface"
depends on TEE && OPTEE && TPM_V2
diff --git a/drivers/tpm/Makefile b/drivers/tpm/Makefile
index 51725230c7..9540fd7fe7 100644
--- a/drivers/tpm/Makefile
+++ b/drivers/tpm/Makefile
@@ -13,5 +13,6 @@ obj-$(CONFIG_TPM_ST33ZP24_SPI) += tpm_tis_st33zp24_spi.o
obj-$(CONFIG_$(SPL_TPL_)TPM2_CR50_I2C) += cr50_i2c.o
obj-$(CONFIG_TPM2_TIS_SANDBOX) += tpm2_tis_sandbox.o sandbox_common.o
obj-$(CONFIG_TPM2_TIS_SPI) += tpm2_tis_core.o tpm2_tis_spi.o
+obj-$(CONFIG_TPM2_TIS_I2C) += tpm2_tis_core.o tpm2_tis_i2c.o
obj-$(CONFIG_TPM2_FTPM_TEE) += tpm2_ftpm_tee.o
obj-$(CONFIG_TPM2_MMIO) += tpm2_tis_core.o tpm2_tis_mmio.o
diff --git a/drivers/tpm/tpm2_tis_core.c b/drivers/tpm/tpm2_tis_core.c
index 51392c4584..985a816219 100644
--- a/drivers/tpm/tpm2_tis_core.c
+++ b/drivers/tpm/tpm2_tis_core.c
@@ -433,15 +433,16 @@ int tpm_tis_init(struct udevice *dev)
log_err("Driver bug. No bus ops defined\n");
return -1;
}
- ret = tpm_tis_request_locality(dev, 0);
- if (ret)
- return ret;
chip->timeout_a = TIS_SHORT_TIMEOUT_MS;
chip->timeout_b = TIS_LONG_TIMEOUT_MS;
chip->timeout_c = TIS_SHORT_TIMEOUT_MS;
chip->timeout_d = TIS_SHORT_TIMEOUT_MS;
+ ret = tpm_tis_request_locality(dev, 0);
+ if (ret)
+ return ret;
+
/* Disable interrupts */
phy_ops->read32(dev, TPM_INT_ENABLE(chip->locality), &tmp);
tmp |= TPM_INTF_CMD_READY_INT | TPM_INTF_LOCALITY_CHANGE_INT |
diff --git a/drivers/tpm/tpm2_tis_i2c.c b/drivers/tpm/tpm2_tis_i2c.c
new file mode 100644
index 0000000000..99d1cf218d
--- /dev/null
+++ b/drivers/tpm/tpm2_tis_i2c.c
@@ -0,0 +1,171 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2022 IBM Corp.
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <fdtdec.h>
+#include <i2c.h>
+#include <log.h>
+#include <tpm-v2.h>
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/compiler.h>
+#include <linux/types.h>
+#include <linux/unaligned/be_byteshift.h>
+#include <asm-generic/gpio.h>
+
+#include "tpm_tis.h"
+#include "tpm_internal.h"
+
+struct tpm_tis_chip_data {
+ unsigned int pcr_count;
+ unsigned int pcr_select_min;
+};
+
+static uint tpm_tis_i2c_address_to_register(u32 addr)
+{
+ addr &= 0xFFF;
+
+ /*
+ * Adapt register addresses that have changed compared to older TIS
+ * version.
+ */
+ switch (addr) {
+ case TPM_ACCESS(0):
+ return 0x04;
+ case TPM_DID_VID(0):
+ return 0x48;
+ case TPM_RID(0):
+ return 0x4C;
+ default:
+ return addr;
+ }
+}
+
+static int tpm_tis_i2c_read(struct udevice *dev, u32 addr, u16 len, u8 *in)
+{
+ int rc;
+ int count = 0;
+ uint reg = tpm_tis_i2c_address_to_register(addr);
+
+ do {
+ rc = dm_i2c_read(dev, reg, in, len);
+ udelay(SLEEP_DURATION_US);
+ } while (rc && count++ < MAX_COUNT);
+
+ return rc;
+}
+
+static int tpm_tis_i2c_write(struct udevice *dev, u32 addr, u16 len,
+ const u8 *out)
+{
+ int rc;
+ int count = 0;
+ uint reg = tpm_tis_i2c_address_to_register(addr);
+
+ do {
+ rc = dm_i2c_write(dev, reg, out, len);
+ udelay(SLEEP_DURATION_US);
+ } while (rc && count++ < MAX_COUNT);
+
+ return rc;
+}
+
+static int tpm_tis_i2c_read32(struct udevice *dev, u32 addr, u32 *result)
+{
+ __le32 result_le;
+ int rc;
+
+ rc = tpm_tis_i2c_read(dev, addr, sizeof(u32), (u8 *)&result_le);
+ if (!rc)
+ *result = le32_to_cpu(result_le);
+
+ return rc;
+}
+
+static int tpm_tis_i2c_write32(struct udevice *dev, u32 addr, u32 value)
+{
+ __le32 value_le = cpu_to_le32(value);
+
+ return tpm_tis_i2c_write(dev, addr, sizeof(value), (u8 *)&value_le);
+}
+
+static struct tpm_tis_phy_ops phy_ops = {
+ .read_bytes = tpm_tis_i2c_read,
+ .write_bytes = tpm_tis_i2c_write,
+ .read32 = tpm_tis_i2c_read32,
+ .write32 = tpm_tis_i2c_write32,
+};
+
+static int tpm_tis_i2c_probe(struct udevice *udev)
+{
+ struct tpm_tis_chip_data *drv_data = (void *)dev_get_driver_data(udev);
+ struct tpm_chip_priv *priv = dev_get_uclass_priv(udev);
+ int rc;
+ u8 loc = 0;
+
+ tpm_tis_ops_register(udev, &phy_ops);
+
+ /*
+ * Force locality 0. The core driver doesn't actually write the
+ * locality register and instead just reads/writes various access
+ * bits of the selected locality.
+ */
+ rc = dm_i2c_write(udev, 0, &loc, 1);
+ if (rc)
+ return rc;
+
+ rc = tpm_tis_init(udev);
+ if (rc)
+ return rc;
+
+ priv->pcr_count = drv_data->pcr_count;
+ priv->pcr_select_min = drv_data->pcr_select_min;
+ priv->version = TPM_V2;
+
+ return 0;
+}
+
+static int tpm_tis_i2c_remove(struct udevice *udev)
+{
+ return tpm_tis_cleanup(udev);
+}
+
+static const struct tpm_ops tpm_tis_i2c_ops = {
+ .open = tpm_tis_open,
+ .close = tpm_tis_close,
+ .get_desc = tpm_tis_get_desc,
+ .send = tpm_tis_send,
+ .recv = tpm_tis_recv,
+ .cleanup = tpm_tis_cleanup,
+};
+
+static const struct tpm_tis_chip_data tpm_tis_std_chip_data = {
+ .pcr_count = 24,
+ .pcr_select_min = 3,
+};
+
+static const struct udevice_id tpm_tis_i2c_ids[] = {
+ {
+ .compatible = "nuvoton,npct75x",
+ .data = (ulong)&tpm_tis_std_chip_data,
+ },
+ {
+ .compatible = "tcg,tpm-tis-i2c",
+ .data = (ulong)&tpm_tis_std_chip_data,
+ },
+ { }
+};
+
+U_BOOT_DRIVER(tpm_tis_i2c) = {
+ .name = "tpm_tis_i2c",
+ .id = UCLASS_TPM,
+ .of_match = tpm_tis_i2c_ids,
+ .ops = &tpm_tis_i2c_ops,
+ .probe = tpm_tis_i2c_probe,
+ .remove = tpm_tis_i2c_remove,
+ .priv_auto = sizeof(struct tpm_chip),
+};
diff --git a/drivers/usb/common/common.c b/drivers/usb/common/common.c
index ee0c064f1f..cff86a51ae 100644
--- a/drivers/usb/common/common.c
+++ b/drivers/usb/common/common.c
@@ -40,6 +40,22 @@ enum usb_dr_mode usb_get_dr_mode(ofnode node)
return USB_DR_MODE_UNKNOWN;
}
+enum usb_dr_mode usb_get_role_switch_default_mode(ofnode node)
+{
+ const char *dr_mode;
+ int i;
+
+ dr_mode = ofnode_read_string(node, "role-switch-default-mode");
+ if (!dr_mode)
+ return USB_DR_MODE_UNKNOWN;
+
+ for (i = 0; i < ARRAY_SIZE(usb_dr_modes); i++)
+ if (!strcmp(dr_mode, usb_dr_modes[i]))
+ return i;
+
+ return USB_DR_MODE_UNKNOWN;
+}
+
static const char *const speed_names[] = {
[USB_SPEED_UNKNOWN] = "UNKNOWN",
[USB_SPEED_LOW] = "low-speed",
diff --git a/drivers/usb/dwc3/dwc3-generic.c b/drivers/usb/dwc3/dwc3-generic.c
index 6e1a1d066b..c5310e465c 100644
--- a/drivers/usb/dwc3/dwc3-generic.c
+++ b/drivers/usb/dwc3/dwc3-generic.c
@@ -468,9 +468,11 @@ static int dwc3_glue_probe(struct udevice *dev)
ret = generic_phy_init(&phy);
if (ret)
return ret;
- } else if (ret != -ENOENT) {
+ } else if (ret != -ENOENT && ret != -ENODATA) {
debug("could not get phy (err %d)\n", ret);
return ret;
+ } else {
+ phy.dev = NULL;
}
glue->regs = dev_read_addr(dev);
diff --git a/drivers/usb/gadget/max3420_udc.c b/drivers/usb/gadget/max3420_udc.c
index a16095f892..fa655c98dc 100644
--- a/drivers/usb/gadget/max3420_udc.c
+++ b/drivers/usb/gadget/max3420_udc.c
@@ -830,8 +830,8 @@ static int max3420_udc_probe(struct udevice *dev)
cs = slave_pdata->cs;
speed = slave_pdata->max_hz;
mode = slave_pdata->mode;
- spi_get_bus_and_cs(busnum, cs, speed, mode, "spi_generic_drv",
- NULL, &spid, &udc->slave);
+ _spi_get_bus_and_cs(busnum, cs, speed, mode, false, "spi_generic_drv",
+ NULL, &spid, &udc->slave);
udc->dev = dev;
udc->gadget.ep0 = &udc->ep[0].ep_usb;
diff --git a/drivers/usb/host/xhci-dwc3.c b/drivers/usb/host/xhci-dwc3.c
index bec0d98081..1dbd65dfaa 100644
--- a/drivers/usb/host/xhci-dwc3.c
+++ b/drivers/usb/host/xhci-dwc3.c
@@ -209,6 +209,12 @@ static int xhci_dwc3_probe(struct udevice *dev)
writel(reg, &dwc3_reg->g_usb2phycfg[0]);
dr_mode = usb_get_dr_mode(dev_ofnode(dev));
+ if (dr_mode == USB_DR_MODE_OTG &&
+ dev_read_bool(dev, "usb-role-switch")) {
+ dr_mode = usb_get_role_switch_default_mode(dev_ofnode(dev));
+ if (dr_mode == USB_DR_MODE_UNKNOWN)
+ dr_mode = USB_DR_MODE_OTG;
+ }
if (dr_mode == USB_DR_MODE_UNKNOWN)
/* by default set dual role mode to HOST */
dr_mode = USB_DR_MODE_HOST;