summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorEmanuele Ghidoli <emanuele.ghidoli@toradex.com>2023-12-01 14:36:20 +0100
committerEmanuele Ghidoli <emanuele.ghidoli@toradex.com>2023-12-01 14:36:20 +0100
commitff20984bc78933c081ab8f22a84dde8cdb38e8b9 (patch)
treec626e16fdb2e6d51a7dbc27bad5a556a8549ea4a /drivers
parent536d0d5eef241a80a352704d82f2284faac2b046 (diff)
parent71b8c840ca61a4e11b2cdf63b0e6580ecb427912 (diff)
Merge tag '09.01.00.006' into toradex_ti-09.01.00.006
RC Release 09.01.00.006
Diffstat (limited to 'drivers')
-rw-r--r--drivers/clk/ti/clk-k3-pll.c81
-rw-r--r--drivers/clk/ti/clk-k3.c6
-rw-r--r--drivers/dma/ti/Makefile1
-rw-r--r--drivers/dma/ti/k3-psil-am62p.c196
-rw-r--r--drivers/dma/ti/k3-psil-priv.h1
-rw-r--r--drivers/dma/ti/k3-psil.c2
-rw-r--r--drivers/firmware/ti_sci_static_data.h5
-rw-r--r--drivers/misc/k3_avs.c104
-rw-r--r--drivers/mtd/nand/raw/omap_gpmc.c96
-rw-r--r--drivers/mtd/spi/spi-nor-core.c34
-rw-r--r--drivers/net/ti/Kconfig2
-rw-r--r--drivers/net/ti/am65-cpsw-nuss.c182
-rw-r--r--drivers/power/domain/ti-power-domain.c6
-rw-r--r--drivers/ram/Kconfig2
-rw-r--r--drivers/ram/k3-ddrss/k3-ddrss.c3
-rw-r--r--drivers/remoteproc/ti_k3_dsp_rproc.c12
-rw-r--r--drivers/remoteproc/ti_k3_m4_rproc.c1
-rw-r--r--drivers/remoteproc/ti_k3_r5f_rproc.c94
-rw-r--r--drivers/soc/soc_ti_k3.c4
-rw-r--r--drivers/spi/cadence_qspi.c7
-rw-r--r--drivers/usb/musb-new/ti-musb.c1
21 files changed, 693 insertions, 147 deletions
diff --git a/drivers/clk/ti/clk-k3-pll.c b/drivers/clk/ti/clk-k3-pll.c
index bf762c558e..c1158c1329 100644
--- a/drivers/clk/ti/clk-k3-pll.c
+++ b/drivers/clk/ti/clk-k3-pll.c
@@ -25,6 +25,23 @@
#define PLL_16FFT_FREQ_CTRL0 0x30
#define PLL_16FFT_FREQ_CTRL1 0x34
#define PLL_16FFT_DIV_CTRL 0x38
+#define PLL_16FFT_CAL_CTRL 0x60
+#define PLL_16FFT_CAL_STAT 0x64
+
+/* CAL STAT register bits */
+#define PLL_16FFT_CAL_STAT_CAL_LOCK BIT(31)
+
+/* CFG register bits */
+#define PLL_16FFT_CFG_PLL_TYPE_SHIFT (0)
+#define PLL_16FFT_CFG_PLL_TYPE_MASK (0x3 << 0)
+#define PLL_16FFT_CFG_PLL_TYPE_FRACF 1
+
+/* CAL CTRL register bits */
+#define PLL_16FFT_CAL_CTRL_CAL_EN BIT(31)
+#define PLL_16FFT_CAL_CTRL_FAST_CAL BIT(20)
+#define PLL_16FFT_CAL_CTRL_CAL_BYP BIT(15)
+#define PLL_16FFT_CAL_CTRL_CAL_CNT_SHIFT 16
+#define PLL_16FFT_CAL_CTRL_CAL_CNT_MASK (0x7 << 16)
/* CTRL register bits */
#define PLL_16FFT_CTRL_BYPASS_EN BIT(31)
@@ -40,9 +57,14 @@
/* DIV CTRL register bits */
#define PLL_16FFT_DIV_CTRL_REF_DIV_MASK 0x3f
-#define PLL_16FFT_FREQ_CTRL1_FB_DIV_FRAC_BITS 24
+/* HSDIV register bits*/
#define PLL_16FFT_HSDIV_CTRL_CLKOUT_EN BIT(15)
+/* FREQ_CTRL1 bits */
+#define PLL_16FFT_FREQ_CTRL1_FB_DIV_FRAC_BITS 24
+#define PLL_16FFT_FREQ_CTRL1_FB_DIV_FRAC_MASK 0xffffff
+#define PLL_16FFT_FREQ_CTRL1_FB_DIV_FRAC_SHIFT 0
+
/* KICK register magic values */
#define PLL_KICK0_VALUE 0x68ef3490
#define PLL_KICK1_VALUE 0xd172bc5a
@@ -63,18 +85,65 @@ static int ti_pll_wait_for_lock(struct clk *clk)
{
struct ti_pll_clk *pll = to_clk_pll(clk);
u32 stat;
+ u32 cfg;
+ u32 cal;
+ u32 freq_ctrl1;
int i;
+ u32 pllfm;
+ u32 pll_type;
+ int success;
for (i = 0; i < 100000; i++) {
stat = readl(pll->reg + PLL_16FFT_STAT);
- if (stat & PLL_16FFT_STAT_LOCK)
- return 0;
+ if (stat & PLL_16FFT_STAT_LOCK) {
+ success = 1;
+ break;
+ }
}
- printf("%s: pll (%s) failed to lock\n", __func__,
- clk->dev->name);
+ /* Enable calibration if not in fractional mode of the FRACF PLL */
+ freq_ctrl1 = readl(pll->reg + PLL_16FFT_FREQ_CTRL1);
+ pllfm = freq_ctrl1 & PLL_16FFT_FREQ_CTRL1_FB_DIV_FRAC_MASK;
+ pllfm >>= PLL_16FFT_FREQ_CTRL1_FB_DIV_FRAC_SHIFT;
+ cfg = readl(pll->reg + PLL_16FFT_CFG);
+ pll_type = (cfg & PLL_16FFT_CFG_PLL_TYPE_MASK) >> PLL_16FFT_CFG_PLL_TYPE_SHIFT;
+
+ if (success && pll_type == PLL_16FFT_CFG_PLL_TYPE_FRACF && pllfm == 0) {
+ cal = readl(pll->reg + PLL_16FFT_CAL_CTRL);
- return -EBUSY;
+ /* Enable calibration for FRACF */
+ cal |= PLL_16FFT_CAL_CTRL_CAL_EN;
+
+ /* Enable fast cal mode */
+ cal |= PLL_16FFT_CAL_CTRL_FAST_CAL;
+
+ /* Disable calibration bypass */
+ cal &= ~PLL_16FFT_CAL_CTRL_CAL_BYP;
+
+ /* Set CALCNT to 2 */
+ cal &= ~PLL_16FFT_CAL_CTRL_CAL_CNT_MASK;
+ cal |= 2 << PLL_16FFT_CAL_CTRL_CAL_CNT_SHIFT;
+
+ /* Note this register does not readback the written value. */
+ writel(cal, pll->reg + PLL_16FFT_CAL_CTRL);
+
+ success = 0;
+ for (i = 0; i < 100000; i++) {
+ stat = readl(pll->reg + PLL_16FFT_CAL_STAT);
+ if (stat & PLL_16FFT_CAL_STAT_CAL_LOCK) {
+ success = 1;
+ break;
+ }
+ }
+ }
+
+ if (success == 0) {
+ printf("%s: pll (%s) failed to lock\n", __func__,
+ clk->dev->name);
+ return -EBUSY;
+ } else {
+ return 0;
+ }
}
static ulong ti_pll_clk_get_rate(struct clk *clk)
diff --git a/drivers/clk/ti/clk-k3.c b/drivers/clk/ti/clk-k3.c
index 39be0d9c19..81a112e518 100644
--- a/drivers/clk/ti/clk-k3.c
+++ b/drivers/clk/ti/clk-k3.c
@@ -92,6 +92,12 @@ static const struct soc_attr ti_k3_soc_clk_data[] = {
.data = &j784s4_clk_platdata,
},
#endif
+#ifdef CONFIG_SOC_K3_AM62P5
+ {
+ .family = "AM62PX",
+ .data = &am62px_clk_platdata,
+ },
+#endif
{ /* sentinel */ }
};
diff --git a/drivers/dma/ti/Makefile b/drivers/dma/ti/Makefile
index 9e0b13e8c0..e4732518b3 100644
--- a/drivers/dma/ti/Makefile
+++ b/drivers/dma/ti/Makefile
@@ -10,3 +10,4 @@ k3-psil-data-$(CONFIG_SOC_K3_AM642) += k3-psil-am64.o
k3-psil-data-$(CONFIG_SOC_K3_AM625) += k3-psil-am62.o
k3-psil-data-$(CONFIG_SOC_K3_AM62A7) += k3-psil-am62a.o
k3-psil-data-$(CONFIG_SOC_K3_J784S4) += k3-psil-j784s4.o
+k3-psil-data-$(CONFIG_SOC_K3_AM62P5) += k3-psil-am62p.o
diff --git a/drivers/dma/ti/k3-psil-am62p.c b/drivers/dma/ti/k3-psil-am62p.c
new file mode 100644
index 0000000000..fda27a42bf
--- /dev/null
+++ b/drivers/dma/ti/k3-psil-am62p.c
@@ -0,0 +1,196 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com
+ */
+
+#include <linux/kernel.h>
+
+#include "k3-psil-priv.h"
+
+#define PSIL_PDMA_XY_TR(x) \
+ { \
+ .thread_id = x, \
+ .ep_config = { \
+ .ep_type = PSIL_EP_PDMA_XY, \
+ .mapped_channel_id = -1, \
+ .default_flow_id = -1, \
+ }, \
+ }
+
+#define PSIL_PDMA_XY_PKT(x) \
+ { \
+ .thread_id = x, \
+ .ep_config = { \
+ .ep_type = PSIL_EP_PDMA_XY, \
+ .mapped_channel_id = -1, \
+ .default_flow_id = -1, \
+ .pkt_mode = 1, \
+ }, \
+ }
+
+#define PSIL_ETHERNET(x, ch, flow_base, flow_cnt) \
+ { \
+ .thread_id = x, \
+ .ep_config = { \
+ .ep_type = PSIL_EP_NATIVE, \
+ .pkt_mode = 1, \
+ .needs_epib = 1, \
+ .psd_size = 16, \
+ .mapped_channel_id = ch, \
+ .flow_start = flow_base, \
+ .flow_num = flow_cnt, \
+ .default_flow_id = flow_base, \
+ }, \
+ }
+
+#define PSIL_SAUL(x, ch, flow_base, flow_cnt, default_flow, tx) \
+ { \
+ .thread_id = x, \
+ .ep_config = { \
+ .ep_type = PSIL_EP_NATIVE, \
+ .pkt_mode = 1, \
+ .needs_epib = 1, \
+ .psd_size = 64, \
+ .mapped_channel_id = ch, \
+ .flow_start = flow_base, \
+ .flow_num = flow_cnt, \
+ .default_flow_id = default_flow, \
+ .notdpkt = tx, \
+ }, \
+ }
+
+#define PSIL_PDMA_MCASP(x) \
+ { \
+ .thread_id = x, \
+ .ep_config = { \
+ .ep_type = PSIL_EP_PDMA_XY, \
+ .pdma_acc32 = 1, \
+ .pdma_burst = 1, \
+ }, \
+ }
+
+#define PSIL_CSI2RX(x) \
+ { \
+ .thread_id = x, \
+ .ep_config = { \
+ .ep_type = PSIL_EP_NATIVE, \
+ }, \
+ }
+
+/* PSI-L source thread IDs, used for RX (DMA_DEV_TO_MEM) */
+static struct psil_ep am62p_src_ep_map[] = {
+ /* SAUL */
+ PSIL_SAUL(0x7504, 20, 35, 8, 35, 0),
+ PSIL_SAUL(0x7505, 21, 35, 8, 36, 0),
+ PSIL_SAUL(0x7506, 22, 43, 8, 43, 0),
+ PSIL_SAUL(0x7507, 23, 43, 8, 44, 0),
+ /* PDMA_MAIN0 - SPI0-3 */
+ PSIL_PDMA_XY_PKT(0x4302),
+ PSIL_PDMA_XY_PKT(0x4303),
+ PSIL_PDMA_XY_PKT(0x4304),
+ PSIL_PDMA_XY_PKT(0x4305),
+ PSIL_PDMA_XY_PKT(0x4306),
+ PSIL_PDMA_XY_PKT(0x4307),
+ PSIL_PDMA_XY_PKT(0x4308),
+ PSIL_PDMA_XY_PKT(0x4309),
+ PSIL_PDMA_XY_PKT(0x430a),
+ PSIL_PDMA_XY_PKT(0x430b),
+ PSIL_PDMA_XY_PKT(0x430c),
+ PSIL_PDMA_XY_PKT(0x430d),
+ /* PDMA_MAIN1 - UART0-6 */
+ PSIL_PDMA_XY_PKT(0x4400),
+ PSIL_PDMA_XY_PKT(0x4401),
+ PSIL_PDMA_XY_PKT(0x4402),
+ PSIL_PDMA_XY_PKT(0x4403),
+ PSIL_PDMA_XY_PKT(0x4404),
+ PSIL_PDMA_XY_PKT(0x4405),
+ PSIL_PDMA_XY_PKT(0x4406),
+ /* PDMA_MAIN2 - MCASP0-2 */
+ PSIL_PDMA_MCASP(0x4500),
+ PSIL_PDMA_MCASP(0x4501),
+ PSIL_PDMA_MCASP(0x4502),
+ /* CPSW3G */
+ PSIL_ETHERNET(0x4600, 19, 19, 16),
+ /* CSI2RX */
+ PSIL_CSI2RX(0x5000),
+ PSIL_CSI2RX(0x5001),
+ PSIL_CSI2RX(0x5002),
+ PSIL_CSI2RX(0x5003),
+ PSIL_CSI2RX(0x5004),
+ PSIL_CSI2RX(0x5005),
+ PSIL_CSI2RX(0x5006),
+ PSIL_CSI2RX(0x5007),
+ PSIL_CSI2RX(0x5008),
+ PSIL_CSI2RX(0x5009),
+ PSIL_CSI2RX(0x500a),
+ PSIL_CSI2RX(0x500b),
+ PSIL_CSI2RX(0x500c),
+ PSIL_CSI2RX(0x500d),
+ PSIL_CSI2RX(0x500e),
+ PSIL_CSI2RX(0x500f),
+ PSIL_CSI2RX(0x5010),
+ PSIL_CSI2RX(0x5011),
+ PSIL_CSI2RX(0x5012),
+ PSIL_CSI2RX(0x5013),
+ PSIL_CSI2RX(0x5014),
+ PSIL_CSI2RX(0x5015),
+ PSIL_CSI2RX(0x5016),
+ PSIL_CSI2RX(0x5017),
+ PSIL_CSI2RX(0x5018),
+ PSIL_CSI2RX(0x5019),
+ PSIL_CSI2RX(0x501a),
+ PSIL_CSI2RX(0x501b),
+ PSIL_CSI2RX(0x501c),
+ PSIL_CSI2RX(0x501d),
+ PSIL_CSI2RX(0x501e),
+ PSIL_CSI2RX(0x501f),
+};
+
+/* PSI-L destination thread IDs, used for TX (DMA_MEM_TO_DEV) */
+static struct psil_ep am62p_dst_ep_map[] = {
+ /* SAUL */
+ PSIL_SAUL(0xf500, 27, 83, 8, 83, 1),
+ PSIL_SAUL(0xf501, 28, 91, 8, 91, 1),
+ /* PDMA_MAIN0 - SPI0-3 */
+ PSIL_PDMA_XY_PKT(0xc302),
+ PSIL_PDMA_XY_PKT(0xc303),
+ PSIL_PDMA_XY_PKT(0xc304),
+ PSIL_PDMA_XY_PKT(0xc305),
+ PSIL_PDMA_XY_PKT(0xc306),
+ PSIL_PDMA_XY_PKT(0xc307),
+ PSIL_PDMA_XY_PKT(0xc308),
+ PSIL_PDMA_XY_PKT(0xc309),
+ PSIL_PDMA_XY_PKT(0xc30a),
+ PSIL_PDMA_XY_PKT(0xc30b),
+ PSIL_PDMA_XY_PKT(0xc30c),
+ PSIL_PDMA_XY_PKT(0xc30d),
+ /* PDMA_MAIN1 - UART0-6 */
+ PSIL_PDMA_XY_PKT(0xc400),
+ PSIL_PDMA_XY_PKT(0xc401),
+ PSIL_PDMA_XY_PKT(0xc402),
+ PSIL_PDMA_XY_PKT(0xc403),
+ PSIL_PDMA_XY_PKT(0xc404),
+ PSIL_PDMA_XY_PKT(0xc405),
+ PSIL_PDMA_XY_PKT(0xc406),
+ /* PDMA_MAIN2 - MCASP0-2 */
+ PSIL_PDMA_MCASP(0xc500),
+ PSIL_PDMA_MCASP(0xc501),
+ PSIL_PDMA_MCASP(0xc502),
+ /* CPSW3G */
+ PSIL_ETHERNET(0xc600, 19, 19, 8),
+ PSIL_ETHERNET(0xc601, 20, 27, 8),
+ PSIL_ETHERNET(0xc602, 21, 35, 8),
+ PSIL_ETHERNET(0xc603, 22, 43, 8),
+ PSIL_ETHERNET(0xc604, 23, 51, 8),
+ PSIL_ETHERNET(0xc605, 24, 59, 8),
+ PSIL_ETHERNET(0xc606, 25, 67, 8),
+ PSIL_ETHERNET(0xc607, 26, 75, 8),
+};
+
+struct psil_ep_map am62p_ep_map = {
+ .name = "am62p",
+ .src = am62p_src_ep_map,
+ .src_count = ARRAY_SIZE(am62p_src_ep_map),
+ .dst = am62p_dst_ep_map,
+ .dst_count = ARRAY_SIZE(am62p_dst_ep_map),
+};
diff --git a/drivers/dma/ti/k3-psil-priv.h b/drivers/dma/ti/k3-psil-priv.h
index 39f1e0150d..aa283d8c58 100644
--- a/drivers/dma/ti/k3-psil-priv.h
+++ b/drivers/dma/ti/k3-psil-priv.h
@@ -44,5 +44,6 @@ extern struct psil_ep_map am64_ep_map;
extern struct psil_ep_map am62_ep_map;
extern struct psil_ep_map am62a_ep_map;
extern struct psil_ep_map j784s4_ep_map;
+extern struct psil_ep_map am62p_ep_map;
#endif /* K3_PSIL_PRIV_H_ */
diff --git a/drivers/dma/ti/k3-psil.c b/drivers/dma/ti/k3-psil.c
index 7f91154e85..bb0408fc08 100644
--- a/drivers/dma/ti/k3-psil.c
+++ b/drivers/dma/ti/k3-psil.c
@@ -30,6 +30,8 @@ struct psil_endpoint_config *psil_get_ep_config(u32 thread_id)
soc_ep_map = &am62a_ep_map;
else if (IS_ENABLED(CONFIG_SOC_K3_J784S4))
soc_ep_map = &j784s4_ep_map;
+ else if (IS_ENABLED(CONFIG_SOC_K3_AM62P5))
+ soc_ep_map = &am62p_ep_map;
}
if (thread_id & K3_PSIL_DST_THREAD_ID_OFFSET && soc_ep_map->dst) {
diff --git a/drivers/firmware/ti_sci_static_data.h b/drivers/firmware/ti_sci_static_data.h
index a0a41ffcce..00da76a3cb 100644
--- a/drivers/firmware/ti_sci_static_data.h
+++ b/drivers/firmware/ti_sci_static_data.h
@@ -84,7 +84,8 @@ static struct ti_sci_resource_static_data rm_static_data[] = {
};
#endif /* CONFIG_SOC_K3_J721S2 */
-#if IS_ENABLED(CONFIG_SOC_K3_AM625) || IS_ENABLED(CONFIG_SOC_K3_AM62A7)
+#if IS_ENABLED(CONFIG_SOC_K3_AM625) || IS_ENABLED(CONFIG_SOC_K3_AM62A7) || \
+ IS_ENABLED(CONFIG_SOC_K3_AM62P5)
static struct ti_sci_resource_static_data rm_static_data[] = {
/* BC channels */
@@ -96,7 +97,7 @@ static struct ti_sci_resource_static_data rm_static_data[] = {
},
{ },
};
-#endif /* CONFIG_SOC_K3_AM625 || CONFIG_SOC_K3_AM62A7 */
+#endif /* CONFIG_SOC_K3_AM625 || CONFIG_SOC_K3_AM62A7 || CONFIG_SOC_K3_AM62P5 */
#if IS_ENABLED(CONFIG_SOC_K3_J784S4)
static struct ti_sci_resource_static_data rm_static_data[] = {
diff --git a/drivers/misc/k3_avs.c b/drivers/misc/k3_avs.c
index 840148d090..dbf79040e0 100644
--- a/drivers/misc/k3_avs.c
+++ b/drivers/misc/k3_avs.c
@@ -15,6 +15,7 @@
#include <k3-avs.h>
#include <dm/device_compat.h>
#include <linux/bitops.h>
+#include <linux/delay.h>
#include <power/regulator.h>
#define AM6_VTM_DEVINFO(i) (priv->base + 0x100 + 0x20 * (i))
@@ -25,11 +26,28 @@
#define AM6_VTM_OPP_SHIFT(opp) (8 * (opp))
#define AM6_VTM_OPP_MASK 0xff
+#define K3_VTM_DEVINFO_PWR0_OFFSET 0x4
+#define K3_VTM_DEVINFO_PWR0_TEMPSENS_CT_MASK 0xf0
+#define K3_VTM_TMPSENS0_CTRL_OFFSET 0x300
+#define K3_VTM_TMPSENS_STAT_OFFSET 0x8
+#define K3_VTM_ANYMAXT_OUTRG_ALERT_EN 0x1
+#define K3_VTM_LOW_TEMP_OFFSET 0x10
+#define K3_VTM_MISC_CTRL2_OFFSET 0x10
+#define K3_VTM_MISC_CTRL1_OFFSET 0xc
+#define K3_VTM_TMPSENS_CTRL1_SOC BIT(5)
+#define K3_VTM_TMPSENS_CTRL_CLRZ BIT(6)
+#define K3_VTM_TMPSENS_CTRL_MAXT_OUTRG_EN BIT(11)
+#define K3_VTM_ADC_COUNT_FOR_123C 0x2f8
+#define K3_VTM_ADC_COUNT_FOR_105C 0x288
+#define K3_VTM_ADC_WA_VALUE 0x2c
+#define K3_VTM_FUSE_MASK 0xc0000000
+
#define VD_FLAG_INIT_DONE BIT(0)
struct k3_avs_privdata {
void *base;
struct vd_config *vd_config;
+ struct udevice *dev;
};
struct opp {
@@ -237,6 +255,88 @@ static int k3_avs_configure(struct udevice *dev, struct k3_avs_privdata *priv)
return 0;
}
+/* k3_avs_program_tshut : Program thermal shutdown value for SOC
+ * set the values corresponding to thresholds to ~123C and 105C
+ * This is optional feature, Few times OS driver takes care of
+ * tshut programing.
+ */
+
+static void k3_avs_program_tshut(struct k3_avs_privdata *priv)
+{
+ int cnt, id, val;
+ int workaround_needed = 0;
+ u32 ctrl_offset;
+ void __iomem *cfg2_base;
+ void __iomem *fuse_base;
+
+ cfg2_base = (void __iomem *)devfdt_get_addr_index(priv->dev, 1);
+ if (IS_ERR(cfg2_base)) {
+ dev_err(priv->dev, "cfg base is not defined\n");
+ return;
+ }
+
+ /*
+ * Some of TI's J721E SoCs require a software trimming procedure
+ * for the temperature monitors to function properly. To determine
+ * if this particular SoC is NOT affected, both bits in the
+ * WKUP_SPARE_FUSE0[31:30] will be set (0xC0000000) indicating
+ * when software trimming should NOT be applied.
+ *
+ * https://www.ti.com/lit/er/sprz455c/sprz455c.pdf
+ * This routine checks if workaround_needed to be applied or not
+ * based upon workaround_needed, adjust fixed value of tshut high and low
+ */
+
+ if (device_is_compatible(priv->dev, "ti,j721e-vtm")) {
+ fuse_base = (void __iomem *)devfdt_get_addr_index(priv->dev, 2);
+ if (IS_ERR(fuse_base)) {
+ dev_err(priv->dev, "fuse-base is not defined for J721E Soc\n");
+ return;
+ }
+
+ if (!((readl(fuse_base) & K3_VTM_FUSE_MASK) == K3_VTM_FUSE_MASK))
+ workaround_needed = 1;
+ }
+
+ dev_dbg(priv->dev, "Work around %sneeded\n", workaround_needed ? "" : "not ");
+
+ /* Get the sensor count in the VTM */
+ val = readl(priv->base + K3_VTM_DEVINFO_PWR0_OFFSET);
+ cnt = val & K3_VTM_DEVINFO_PWR0_TEMPSENS_CT_MASK;
+ cnt >>= __ffs(K3_VTM_DEVINFO_PWR0_TEMPSENS_CT_MASK);
+
+ /* Program the thermal sensors */
+ for (id = 0; id < cnt; id++) {
+ ctrl_offset = K3_VTM_TMPSENS0_CTRL_OFFSET + id * 0x20;
+
+ val = readl(cfg2_base + ctrl_offset);
+ val |= (K3_VTM_TMPSENS_CTRL_MAXT_OUTRG_EN |
+ K3_VTM_TMPSENS_CTRL1_SOC |
+ K3_VTM_TMPSENS_CTRL_CLRZ | BIT(4));
+ writel(val, cfg2_base + ctrl_offset);
+ }
+
+ /*
+ * Program TSHUT thresholds
+ * Step 1: set the thresholds to ~123C and 105C WKUP_VTM_MISC_CTRL2
+ * Step 2: WKUP_VTM_TMPSENS_CTRL_j set the MAXT_OUTRG_EN bit
+ * This is already taken care as per of init
+ * Step 3: WKUP_VTM_MISC_CTRL set the ANYMAXT_OUTRG_ALERT_EN bit
+ */
+
+ /* Low thresholds for tshut*/
+ val = (K3_VTM_ADC_COUNT_FOR_105C - workaround_needed * K3_VTM_ADC_WA_VALUE)
+ << K3_VTM_LOW_TEMP_OFFSET;
+ /* high thresholds */
+ val |= K3_VTM_ADC_COUNT_FOR_123C - workaround_needed * K3_VTM_ADC_WA_VALUE;
+
+ writel(val, cfg2_base + K3_VTM_MISC_CTRL2_OFFSET);
+ /* ramp-up delay from Linux code */
+ mdelay(100);
+ val = readl(cfg2_base + K3_VTM_MISC_CTRL1_OFFSET) | K3_VTM_ANYMAXT_OUTRG_ALERT_EN;
+ writel(val, cfg2_base + K3_VTM_MISC_CTRL1_OFFSET);
+}
+
/**
* k3_avs_probe: parses VD info from VTM, and re-configures the OPP data
*
@@ -255,6 +355,7 @@ static int k3_avs_probe(struct udevice *dev)
int ret;
priv = dev_get_priv(dev);
+ priv->dev = dev;
k3_avs_priv = priv;
@@ -294,6 +395,9 @@ static int k3_avs_probe(struct udevice *dev)
k3_avs_program_voltage(priv, vd, vd->opp);
}
+ if (!device_is_compatible(priv->dev, "ti,am654-avs"))
+ k3_avs_program_tshut(priv);
+
return 0;
}
diff --git a/drivers/mtd/nand/raw/omap_gpmc.c b/drivers/mtd/nand/raw/omap_gpmc.c
index 43f7363b9d..fc8383d84b 100644
--- a/drivers/mtd/nand/raw/omap_gpmc.c
+++ b/drivers/mtd/nand/raw/omap_gpmc.c
@@ -293,7 +293,7 @@ static void __maybe_unused omap_enable_hwecc_bch(struct mtd_info *mtd,
break;
case OMAP_ECC_BCH8_CODE_HW:
bch_type = 1;
- nsectors = chip->ecc.steps;
+ nsectors = 1;
if (mode == NAND_ECC_READ) {
wr_mode = BCH_WRAPMODE_1;
ecc_size0 = BCH8R_ECC_SIZE0;
@@ -306,7 +306,7 @@ static void __maybe_unused omap_enable_hwecc_bch(struct mtd_info *mtd,
break;
case OMAP_ECC_BCH16_CODE_HW:
bch_type = 0x2;
- nsectors = chip->ecc.steps;
+ nsectors = 1;
if (mode == NAND_ECC_READ) {
wr_mode = 0x01;
ecc_size0 = 52; /* ECC bits in nibbles per sector */
@@ -345,17 +345,16 @@ static void __maybe_unused omap_enable_hwecc_bch(struct mtd_info *mtd,
}
/**
- * _omap_calculate_ecc_bch - Generate BCH ECC bytes for one sector
+ * omap_calculate_ecc_bch - Generate BCH ECC bytes for one sector
* @mtd: MTD device structure
* @dat: The pointer to data on which ecc is computed
* @ecc_code: The ecc_code buffer
- * @sector: The sector number (for a multi sector page)
*
* Support calculating of BCH4/8/16 ECC vectors for one sector
* within a page. Sector number is in @sector.
*/
-static int _omap_calculate_ecc_bch(struct mtd_info *mtd, const u8 *dat,
- u8 *ecc_code, int sector)
+static int omap_calculate_ecc_bch(struct mtd_info *mtd, const u8 *dat,
+ u8 *ecc_code)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct omap_nand_info *info = nand_get_controller_data(chip);
@@ -368,7 +367,7 @@ static int _omap_calculate_ecc_bch(struct mtd_info *mtd, const u8 *dat,
case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW:
#endif
case OMAP_ECC_BCH8_CODE_HW:
- ptr = &gpmc_cfg->bch_result_0_3[sector].bch_result_x[3];
+ ptr = &gpmc_cfg->bch_result_0_3[0].bch_result_x[3];
val = readl(ptr);
ecc_code[i++] = (val >> 0) & 0xFF;
ptr--;
@@ -383,21 +382,21 @@ static int _omap_calculate_ecc_bch(struct mtd_info *mtd, const u8 *dat,
break;
case OMAP_ECC_BCH16_CODE_HW:
- val = readl(&gpmc_cfg->bch_result_4_6[sector].bch_result_x[2]);
+ val = readl(&gpmc_cfg->bch_result_4_6[0].bch_result_x[2]);
ecc_code[i++] = (val >> 8) & 0xFF;
ecc_code[i++] = (val >> 0) & 0xFF;
- val = readl(&gpmc_cfg->bch_result_4_6[sector].bch_result_x[1]);
+ val = readl(&gpmc_cfg->bch_result_4_6[0].bch_result_x[1]);
ecc_code[i++] = (val >> 24) & 0xFF;
ecc_code[i++] = (val >> 16) & 0xFF;
ecc_code[i++] = (val >> 8) & 0xFF;
ecc_code[i++] = (val >> 0) & 0xFF;
- val = readl(&gpmc_cfg->bch_result_4_6[sector].bch_result_x[0]);
+ val = readl(&gpmc_cfg->bch_result_4_6[0].bch_result_x[0]);
ecc_code[i++] = (val >> 24) & 0xFF;
ecc_code[i++] = (val >> 16) & 0xFF;
ecc_code[i++] = (val >> 8) & 0xFF;
ecc_code[i++] = (val >> 0) & 0xFF;
for (j = 3; j >= 0; j--) {
- val = readl(&gpmc_cfg->bch_result_0_3[sector].bch_result_x[j]
+ val = readl(&gpmc_cfg->bch_result_0_3[0].bch_result_x[j]
);
ecc_code[i++] = (val >> 24) & 0xFF;
ecc_code[i++] = (val >> 16) & 0xFF;
@@ -431,22 +430,6 @@ static int _omap_calculate_ecc_bch(struct mtd_info *mtd, const u8 *dat,
return 0;
}
-/**
- * omap_calculate_ecc_bch - ECC generator for 1 sector
- * @mtd: MTD device structure
- * @dat: The pointer to data on which ecc is computed
- * @ecc_code: The ecc_code buffer
- *
- * Support calculating of BCH4/8/16 ECC vectors for one sector. This is used
- * when SW based correction is required as ECC is required for one sector
- * at a time.
- */
-static int __maybe_unused omap_calculate_ecc_bch(struct mtd_info *mtd,
- const u_char *dat, u_char *ecc_calc)
-{
- return _omap_calculate_ecc_bch(mtd, dat, ecc_calc, 0);
-}
-
static inline void omap_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
{
struct nand_chip *chip = mtd_to_nand(mtd);
@@ -572,34 +555,6 @@ static void omap_nand_read_prefetch(struct mtd_info *mtd, uint8_t *buf, int len)
#ifdef CONFIG_NAND_OMAP_ELM
-/**
- * omap_calculate_ecc_bch_multi - Generate ECC for multiple sectors
- * @mtd: MTD device structure
- * @dat: The pointer to data on which ecc is computed
- * @ecc_code: The ecc_code buffer
- *
- * Support calculating of BCH4/8/16 ecc vectors for the entire page in one go.
- */
-static int omap_calculate_ecc_bch_multi(struct mtd_info *mtd,
- const u_char *dat, u_char *ecc_calc)
-{
- struct nand_chip *chip = mtd_to_nand(mtd);
- int eccbytes = chip->ecc.bytes;
- unsigned long nsectors;
- int i, ret;
-
- nsectors = ((readl(&gpmc_cfg->ecc_config) >> 4) & 0x7) + 1;
- for (i = 0; i < nsectors; i++) {
- ret = _omap_calculate_ecc_bch(mtd, dat, ecc_calc, i);
- if (ret)
- return ret;
-
- ecc_calc += eccbytes;
- }
-
- return 0;
-}
-
/*
* omap_reverse_list - re-orders list elements in reverse order [internal]
* @list: pointer to start of list
@@ -752,32 +707,38 @@ static int omap_read_page_bch(struct mtd_info *mtd, struct nand_chip *chip,
{
int i, eccsize = chip->ecc.size;
int eccbytes = chip->ecc.bytes;
- int ecctotal = chip->ecc.total;
int eccsteps = chip->ecc.steps;
uint8_t *p = buf;
uint8_t *ecc_calc = chip->buffers->ecccalc;
uint8_t *ecc_code = chip->buffers->ecccode;
uint32_t *eccpos = chip->ecc.layout->eccpos;
uint8_t *oob = chip->oob_poi;
+ uint32_t data_pos;
uint32_t oob_pos;
+ data_pos = 0;
/* oob area start */
oob_pos = (eccsize * eccsteps) + chip->ecc.layout->eccpos[0];
oob += chip->ecc.layout->eccpos[0];
- /* Enable ECC engine */
- chip->ecc.hwctl(mtd, NAND_ECC_READ);
+ for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize,
+ oob += eccbytes) {
+ /* Enable ECC engine */
+ chip->ecc.hwctl(mtd, NAND_ECC_READ);
- /* read entire page */
- chip->cmdfunc(mtd, NAND_CMD_RNDOUT, 0, -1);
- chip->read_buf(mtd, buf, mtd->writesize);
+ /* read data */
+ chip->cmdfunc(mtd, NAND_CMD_RNDOUT, data_pos, -1);
+ chip->read_buf(mtd, p, eccsize);
- /* read all ecc bytes from oob area */
- chip->cmdfunc(mtd, NAND_CMD_RNDOUT, oob_pos, -1);
- chip->read_buf(mtd, oob, ecctotal);
+ /* read respective ecc from oob area */
+ chip->cmdfunc(mtd, NAND_CMD_RNDOUT, oob_pos, -1);
+ chip->read_buf(mtd, oob, eccbytes);
+ /* read syndrome */
+ chip->ecc.calculate(mtd, p, &ecc_calc[i]);
- /* Calculate ecc bytes */
- omap_calculate_ecc_bch_multi(mtd, buf, ecc_calc);
+ data_pos += eccsize;
+ oob_pos += eccbytes;
+ }
for (i = 0; i < chip->ecc.total; i++)
ecc_code[i] = chip->oob_poi[eccpos[i]];
@@ -945,6 +906,7 @@ static int omap_select_ecc_scheme(struct nand_chip *nand,
nand->ecc.hwctl = omap_enable_hwecc_bch;
nand->ecc.correct = omap_correct_data_bch_sw;
nand->ecc.calculate = omap_calculate_ecc_bch;
+ nand->ecc.steps = eccsteps;
/* define ecc-layout */
ecclayout->eccbytes = nand->ecc.bytes * eccsteps;
ecclayout->eccpos[0] = BADBLOCK_MARKER_LENGTH;
@@ -987,6 +949,7 @@ static int omap_select_ecc_scheme(struct nand_chip *nand,
nand->ecc.correct = omap_correct_data_bch;
nand->ecc.calculate = omap_calculate_ecc_bch;
nand->ecc.read_page = omap_read_page_bch;
+ nand->ecc.steps = eccsteps;
/* define ecc-layout */
ecclayout->eccbytes = nand->ecc.bytes * eccsteps;
for (i = 0; i < ecclayout->eccbytes; i++)
@@ -1020,6 +983,7 @@ static int omap_select_ecc_scheme(struct nand_chip *nand,
nand->ecc.correct = omap_correct_data_bch;
nand->ecc.calculate = omap_calculate_ecc_bch;
nand->ecc.read_page = omap_read_page_bch;
+ nand->ecc.steps = eccsteps;
/* define ecc-layout */
ecclayout->eccbytes = nand->ecc.bytes * eccsteps;
for (i = 0; i < ecclayout->eccbytes; i++)
diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c
index 03bf3f0bdd..f7b9c472e9 100644
--- a/drivers/mtd/spi/spi-nor-core.c
+++ b/drivers/mtd/spi/spi-nor-core.c
@@ -2119,6 +2119,36 @@ read_err:
return ret;
}
+/**
+ * spi_nor_read_sfdp_dma_unsafe() - read Serial Flash Discoverable Parameters.
+ * @nor: pointer to a 'struct spi_nor'
+ * @addr: offset in the SFDP area to start reading data from
+ * @len: number of bytes to read
+ * @buf: buffer where the SFDP data are copied into
+ *
+ * Wrap spi_nor_read_sfdp() using a kmalloc'ed bounce buffer as @buf is now not
+ * guaranteed to be dma-safe.
+ *
+ * Return: -ENOMEM if kmalloc() fails, the return code of spi_nor_read_sfdp()
+ * otherwise.
+ */
+static int spi_nor_read_sfdp_dma_unsafe(struct spi_nor *nor, u32 addr,
+ size_t len, void *buf)
+{
+ void *dma_safe_buf;
+ int ret;
+
+ dma_safe_buf = kmalloc(len, GFP_KERNEL);
+ if (!dma_safe_buf)
+ return -ENOMEM;
+
+ ret = spi_nor_read_sfdp(nor, addr, len, dma_safe_buf);
+ memcpy(buf, dma_safe_buf, len);
+ kfree(dma_safe_buf);
+
+ return ret;
+}
+
/* Fast Read settings. */
static void
@@ -2292,7 +2322,7 @@ static int spi_nor_parse_bfpt(struct spi_nor *nor,
bfpt_header->length * sizeof(u32));
addr = SFDP_PARAM_HEADER_PTP(bfpt_header);
memset(&bfpt, 0, sizeof(bfpt));
- err = spi_nor_read_sfdp(nor, addr, len, &bfpt);
+ err = spi_nor_read_sfdp_dma_unsafe(nor, addr, len, &bfpt);
if (err < 0)
return err;
@@ -2618,7 +2648,7 @@ static int spi_nor_parse_sfdp(struct spi_nor *nor,
int i, err;
/* Get the SFDP header. */
- err = spi_nor_read_sfdp(nor, 0, sizeof(header), &header);
+ err = spi_nor_read_sfdp_dma_unsafe(nor, 0, sizeof(header), &header);
if (err < 0)
return err;
diff --git a/drivers/net/ti/Kconfig b/drivers/net/ti/Kconfig
index e13dbc9401..02660e4fbb 100644
--- a/drivers/net/ti/Kconfig
+++ b/drivers/net/ti/Kconfig
@@ -41,8 +41,10 @@ endchoice
config TI_AM65_CPSW_NUSS
bool "TI K3 AM65x MCU CPSW Nuss Ethernet controller driver"
depends on ARCH_K3
+ imply DM_MDIO
imply MISC_INIT_R
imply MISC
+ imply SYSCON
select PHYLIB
help
This driver supports TI K3 MCU CPSW Nuss Ethernet controller
diff --git a/drivers/net/ti/am65-cpsw-nuss.c b/drivers/net/ti/am65-cpsw-nuss.c
index f674b0baa3..51a8167d14 100644
--- a/drivers/net/ti/am65-cpsw-nuss.c
+++ b/drivers/net/ti/am65-cpsw-nuss.c
@@ -15,13 +15,16 @@
#include <dm.h>
#include <dm/device_compat.h>
#include <dm/lists.h>
+#include <dm/pinctrl.h>
#include <dma-uclass.h>
#include <dm/of_access.h>
#include <miiphy.h>
#include <net.h>
#include <phy.h>
#include <power-domain.h>
+#include <regmap.h>
#include <soc.h>
+#include <syscon.h>
#include <linux/bitops.h>
#include <linux/soc/ti/ti-udma.h>
@@ -100,8 +103,6 @@ struct am65_cpsw_common {
fdt_addr_t cpsw_base;
fdt_addr_t mdio_base;
fdt_addr_t ale_base;
- fdt_addr_t gmii_sel;
- fdt_addr_t mac_efuse;
struct clk fclk;
struct power_domain pwrdmn;
@@ -223,23 +224,45 @@ out:
return phy->link;
}
+#define AM65_GMII_SEL_PORT_OFFS(x) (0x4 * ((x) - 1))
+
#define AM65_GMII_SEL_MODE_MII 0
#define AM65_GMII_SEL_MODE_RMII 1
#define AM65_GMII_SEL_MODE_RGMII 2
#define AM65_GMII_SEL_RGMII_IDMODE BIT(4)
-static void am65_cpsw_gmii_sel_k3(struct am65_cpsw_priv *priv,
- phy_interface_t phy_mode, int slave)
+static int am65_cpsw_gmii_sel_k3(struct am65_cpsw_priv *priv,
+ phy_interface_t phy_mode)
{
- struct am65_cpsw_common *common = priv->cpsw_common;
- u32 reg;
- u32 mode = 0;
+ struct udevice *dev = priv->dev;
+ u32 offset, reg, phandle;
bool rgmii_id = false;
+ fdt_addr_t gmii_sel;
+ u32 mode = 0;
+ ofnode node;
+ int ret;
+
+ ret = ofnode_read_u32(dev_ofnode(dev), "phys", &phandle);
+ if (ret)
+ return ret;
+
+ ret = ofnode_read_u32_index(dev_ofnode(dev), "phys", 1, &offset);
+ if (ret)
+ return ret;
- reg = readl(common->gmii_sel);
+ node = ofnode_get_by_phandle(phandle);
+ if (!ofnode_valid(node))
+ return -ENODEV;
+
+ gmii_sel = ofnode_get_addr(node);
+ if (gmii_sel == FDT_ADDR_T_NONE)
+ return -ENODEV;
- dev_dbg(common->dev, "old gmii_sel: %08x\n", reg);
+ gmii_sel += AM65_GMII_SEL_PORT_OFFS(offset);
+ reg = readl(gmii_sel);
+
+ dev_dbg(dev, "old gmii_sel: %08x\n", reg);
switch (phy_mode) {
case PHY_INTERFACE_MODE_RMII:
@@ -258,7 +281,7 @@ static void am65_cpsw_gmii_sel_k3(struct am65_cpsw_priv *priv,
break;
default:
- dev_warn(common->dev,
+ dev_warn(dev,
"Unsupported PHY mode: %u. Defaulting to MII.\n",
phy_mode);
/* fallthrough */
@@ -271,15 +294,19 @@ static void am65_cpsw_gmii_sel_k3(struct am65_cpsw_priv *priv,
mode |= AM65_GMII_SEL_RGMII_IDMODE;
reg = mode;
- dev_dbg(common->dev, "gmii_sel PHY mode: %u, new gmii_sel: %08x\n",
+ dev_dbg(dev, "gmii_sel PHY mode: %u, new gmii_sel: %08x\n",
phy_mode, reg);
- writel(reg, common->gmii_sel);
+ writel(reg, gmii_sel);
- reg = readl(common->gmii_sel);
- if (reg != mode)
- dev_err(common->dev,
+ reg = readl(gmii_sel);
+ if (reg != mode) {
+ dev_err(dev,
"gmii_sel PHY mode NOT SET!: requested: %08x, gmii_sel: %08x\n",
mode, reg);
+ return 0;
+ }
+
+ return 0;
}
static int am65_cpsw_start(struct udevice *dev)
@@ -513,24 +540,45 @@ static void am65_cpsw_stop(struct udevice *dev)
common->started = false;
}
+static int am65_cpsw_am654_get_efuse_macid(struct udevice *dev,
+ int slave, u8 *mac_addr)
+{
+ u32 mac_lo, mac_hi, offset;
+ struct regmap *syscon;
+ int ret;
+
+ syscon = syscon_regmap_lookup_by_phandle(dev, "ti,syscon-efuse");
+ if (IS_ERR(syscon)) {
+ if (PTR_ERR(syscon) == -ENODEV)
+ return 0;
+ return PTR_ERR(syscon);
+ }
+
+ ret = dev_read_u32_index(dev, "ti,syscon-efuse", 1, &offset);
+ if (ret)
+ return ret;
+
+ regmap_read(syscon, offset, &mac_lo);
+ regmap_read(syscon, offset + 4, &mac_hi);
+
+ mac_addr[0] = (mac_hi >> 8) & 0xff;
+ mac_addr[1] = mac_hi & 0xff;
+ mac_addr[2] = (mac_lo >> 24) & 0xff;
+ mac_addr[3] = (mac_lo >> 16) & 0xff;
+ mac_addr[4] = (mac_lo >> 8) & 0xff;
+ mac_addr[5] = mac_lo & 0xff;
+
+ return 0;
+}
+
static int am65_cpsw_read_rom_hwaddr(struct udevice *dev)
{
struct am65_cpsw_priv *priv = dev_get_priv(dev);
- struct am65_cpsw_common *common = priv->cpsw_common;
struct eth_pdata *pdata = dev_get_plat(dev);
- u32 mac_hi, mac_lo;
- if (common->mac_efuse == FDT_ADDR_T_NONE)
- return -1;
-
- mac_lo = readl(common->mac_efuse);
- mac_hi = readl(common->mac_efuse + 4);
- pdata->enetaddr[0] = (mac_hi >> 8) & 0xff;
- pdata->enetaddr[1] = mac_hi & 0xff;
- pdata->enetaddr[2] = (mac_lo >> 24) & 0xff;
- pdata->enetaddr[3] = (mac_lo >> 16) & 0xff;
- pdata->enetaddr[4] = (mac_lo >> 8) & 0xff;
- pdata->enetaddr[5] = mac_lo & 0xff;
+ am65_cpsw_am654_get_efuse_macid(dev,
+ priv->port_id,
+ pdata->enetaddr);
return 0;
}
@@ -558,14 +606,62 @@ static const struct soc_attr k3_mdio_soc_data[] = {
{ /* sentinel */ },
};
+static ofnode am65_cpsw_find_mdio(ofnode parent)
+{
+ ofnode node;
+
+ ofnode_for_each_subnode(node, parent)
+ if (ofnode_device_is_compatible(node, "ti,cpsw-mdio"))
+ return node;
+
+ return ofnode_null();
+}
+
+static int am65_cpsw_mdio_setup(struct udevice *dev)
+{
+ struct am65_cpsw_priv *priv = dev_get_priv(dev);
+ struct am65_cpsw_common *cpsw_common = priv->cpsw_common;
+ struct udevice *mdio_dev;
+ ofnode mdio;
+ int ret;
+
+ mdio = am65_cpsw_find_mdio(dev_ofnode(cpsw_common->dev));
+ if (!ofnode_valid(mdio))
+ return 0;
+
+ /*
+ * The MDIO controller is represented in the DT binding by a
+ * subnode of the MAC controller.
+ *
+ * We don't have a DM driver for the MDIO device yet, and thus any
+ * pinctrl setting on its node will be ignored.
+ *
+ * However, we do need to make sure the pins states tied to the
+ * MDIO node are configured properly. Fortunately, the core DM
+ * does that for use when we get a device, so we can work around
+ * that whole issue by just requesting a dummy MDIO driver to
+ * probe, and our pins will get muxed.
+ */
+ ret = uclass_get_device_by_ofnode(UCLASS_MDIO, mdio, &mdio_dev);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
static int am65_cpsw_mdio_init(struct udevice *dev)
{
struct am65_cpsw_priv *priv = dev_get_priv(dev);
struct am65_cpsw_common *cpsw_common = priv->cpsw_common;
+ int ret;
if (!priv->has_phy || cpsw_common->bus)
return 0;
+ ret = am65_cpsw_mdio_setup(dev);
+ if (ret)
+ return ret;
+
cpsw_common->bus = cpsw_mdio_init(dev->name,
cpsw_common->mdio_base,
cpsw_common->bus_freq,
@@ -683,7 +779,9 @@ static int am65_cpsw_port_probe(struct udevice *dev)
if (ret)
goto out;
- am65_cpsw_gmii_sel_k3(priv, pdata->phy_interface, priv->port_id);
+ ret = am65_cpsw_gmii_sel_k3(priv, pdata->phy_interface);
+ if (ret)
+ goto out;
ret = am65_cpsw_mdio_init(dev);
if (ret)
@@ -707,8 +805,6 @@ static int am65_cpsw_probe_nuss(struct udevice *dev)
cpsw_common->ss_base = dev_read_addr(dev);
if (cpsw_common->ss_base == FDT_ADDR_T_NONE)
return -EINVAL;
- cpsw_common->mac_efuse = devfdt_get_addr_name(dev, "mac_efuse");
- /* no err check - optional */
ret = power_domain_get_by_index(dev, &cpsw_common->pwrdmn, 0);
if (ret) {
@@ -780,19 +876,6 @@ static int am65_cpsw_probe_nuss(struct udevice *dev)
AM65_CPSW_CPSW_NU_PORT_MACSL_OFFSET;
}
- node = dev_read_subnode(dev, "cpsw-phy-sel");
- if (!ofnode_valid(node)) {
- dev_err(dev, "can't find cpsw-phy-sel\n");
- ret = -ENOENT;
- goto out;
- }
-
- cpsw_common->gmii_sel = ofnode_get_addr(node);
- if (cpsw_common->gmii_sel == FDT_ADDR_T_NONE) {
- dev_err(dev, "failed to get gmii_sel base\n");
- goto out;
- }
-
cpsw_common->bus_freq =
dev_read_u32_default(dev, "bus_freq",
AM65_CPSW_MDIO_BUS_FREQ_DEF);
@@ -834,3 +917,14 @@ U_BOOT_DRIVER(am65_cpsw_nuss_port) = {
.plat_auto = sizeof(struct eth_pdata),
.flags = DM_FLAG_ALLOC_PRIV_DMA | DM_FLAG_OS_PREPARE,
};
+
+static const struct udevice_id am65_cpsw_mdio_ids[] = {
+ { .compatible = "ti,cpsw-mdio" },
+ { }
+};
+
+U_BOOT_DRIVER(am65_cpsw_mdio) = {
+ .name = "am65_cpsw_mdio",
+ .id = UCLASS_MDIO,
+ .of_match = am65_cpsw_mdio_ids,
+};
diff --git a/drivers/power/domain/ti-power-domain.c b/drivers/power/domain/ti-power-domain.c
index 0ff174e57e..de6e2b70c8 100644
--- a/drivers/power/domain/ti-power-domain.c
+++ b/drivers/power/domain/ti-power-domain.c
@@ -105,6 +105,12 @@ static const struct soc_attr ti_k3_soc_pd_data[] = {
.data = &j784s4_pd_platdata,
},
#endif
+#ifdef CONFIG_SOC_K3_AM62P5
+ {
+ .family = "AM62PX",
+ .data = &am62px_pd_platdata,
+ },
+#endif
{ /* sentinel */ }
};
diff --git a/drivers/ram/Kconfig b/drivers/ram/Kconfig
index fac8c9314b..81dc2666e8 100644
--- a/drivers/ram/Kconfig
+++ b/drivers/ram/Kconfig
@@ -65,7 +65,7 @@ choice
default K3_J721E_DDRSS if SOC_K3_J721E || SOC_K3_J721S2 || SOC_K3_J784S4
default K3_AM64_DDRSS if SOC_K3_AM642
default K3_AM64_DDRSS if SOC_K3_AM625
- default K3_AM62A_DDRSS if SOC_K3_AM62A7
+ default K3_AM62A_DDRSS if SOC_K3_AM62A7 || SOC_K3_AM62P5
config K3_J721E_DDRSS
bool "Enable J721E DDRSS support"
diff --git a/drivers/ram/k3-ddrss/k3-ddrss.c b/drivers/ram/k3-ddrss/k3-ddrss.c
index 7e445d2b73..75d13df8ad 100644
--- a/drivers/ram/k3-ddrss/k3-ddrss.c
+++ b/drivers/ram/k3-ddrss/k3-ddrss.c
@@ -667,9 +667,6 @@ int k3_ddrss_ddr_fdt_fixup(struct udevice *dev, void *blob, struct bd_info *bd)
u64 size[CONFIG_NR_DRAM_BANKS];
int bank;
- if (ddrss->ecc_reserved_space == 0)
- return 0;
-
for (bank = CONFIG_NR_DRAM_BANKS - 1; bank >= 0; bank--) {
if (ddrss->ecc_reserved_space > bd->bi_dram[bank].size) {
ddrss->ecc_reserved_space -= bd->bi_dram[bank].size;
diff --git a/drivers/remoteproc/ti_k3_dsp_rproc.c b/drivers/remoteproc/ti_k3_dsp_rproc.c
index 42a33a822e..8159b40a14 100644
--- a/drivers/remoteproc/ti_k3_dsp_rproc.c
+++ b/drivers/remoteproc/ti_k3_dsp_rproc.c
@@ -57,6 +57,7 @@ struct k3_dsp_boot_data {
* @data: Pointer to DSP specific boot data structure
* @mem: Array of available memories
* @num_mem: Number of available memories
+ * @in_use: flag to tell if the core is already in use.
*/
struct k3_dsp_privdata {
struct reset_ctl dsp_rst;
@@ -64,6 +65,7 @@ struct k3_dsp_privdata {
struct k3_dsp_boot_data *data;
struct k3_dsp_mem *mem;
int num_mems;
+ bool in_use;
};
/*
@@ -130,6 +132,13 @@ static int k3_dsp_load(struct udevice *dev, ulong addr, ulong size)
void *image_addr = (void *)addr;
int ret;
+ if (dsp->in_use) {
+ dev_err(dev,
+ "Invalid op: Trying to load/start on already running core %d\n",
+ dsp->tsp.proc_id);
+ return -EINVAL;
+ }
+
dev_dbg(dev, "%s addr = 0x%lx, size = 0x%lx\n", __func__, addr, size);
ret = ti_sci_proc_request(&dsp->tsp);
if (ret)
@@ -198,7 +207,7 @@ static int k3_dsp_start(struct udevice *dev)
if (!data->uses_lreset)
ti_sci_proc_power_domain_off(&dsp->tsp);
}
-
+ dsp->in_use = true;
proc_release:
ti_sci_proc_release(&dsp->tsp);
@@ -211,6 +220,7 @@ static int k3_dsp_stop(struct udevice *dev)
dev_dbg(dev, "%s\n", __func__);
+ dsp->in_use = false;
ti_sci_proc_request(&dsp->tsp);
reset_assert(&dsp->dsp_rst);
ti_sci_proc_power_domain_off(&dsp->tsp);
diff --git a/drivers/remoteproc/ti_k3_m4_rproc.c b/drivers/remoteproc/ti_k3_m4_rproc.c
index 15477ec3d9..39e19e0bc3 100644
--- a/drivers/remoteproc/ti_k3_m4_rproc.c
+++ b/drivers/remoteproc/ti_k3_m4_rproc.c
@@ -20,6 +20,7 @@
#include <linux/err.h>
#include <linux/sizes.h>
#include <linux/soc/ti/ti_sci_protocol.h>
+#include <mach/security.h>
#include "ti_sci_proc.h"
#include <mach/security.h>
diff --git a/drivers/remoteproc/ti_k3_r5f_rproc.c b/drivers/remoteproc/ti_k3_r5f_rproc.c
index 31c59f6862..cf3ab59be9 100644
--- a/drivers/remoteproc/ti_k3_r5f_rproc.c
+++ b/drivers/remoteproc/ti_k3_r5f_rproc.c
@@ -46,6 +46,7 @@
/* R5 TI-SCI Processor Control Flags */
#define PROC_BOOT_CTRL_FLAG_R5_CORE_HALT 0x00000001
+#define PROC_BOOT_CTRL_FLAG_R5_LPSC 0x00000002
/* R5 TI-SCI Processor Status Flags */
#define PROC_BOOT_STATUS_FLAG_R5_WFE 0x00000001
@@ -71,6 +72,7 @@ struct k3_r5f_ip_data {
bool tcm_is_double;
bool tcm_ecc_autoinit;
bool is_single_core;
+ bool is_dm_core;
};
/**
@@ -209,19 +211,28 @@ static int k3_r5f_split_release(struct k3_r5f_core *core)
dev_dbg(core->dev, "%s\n", __func__);
- ret = ti_sci_proc_power_domain_on(&core->tsp);
- if (ret) {
- dev_err(core->dev, "module-reset deassert failed, ret = %d\n",
- ret);
- return ret;
- }
+ if (core->ipdata->is_dm_core) {
+ ret = ti_sci_proc_set_control(&core->tsp,
+ PROC_BOOT_CTRL_FLAG_R5_LPSC, 0);
+ if (ret) {
+ dev_err(core->dev, "LPSC on failed, ret = %d\n", ret);
+ return ret;
+ }
+ } else {
+ ret = ti_sci_proc_power_domain_on(&core->tsp);
+ if (ret) {
+ dev_err(core->dev, "module-reset deassert failed, ret = %d\n",
+ ret);
+ return ret;
+ }
- ret = reset_deassert(&core->reset);
- if (ret) {
- dev_err(core->dev, "local-reset deassert failed, ret = %d\n",
- ret);
- if (ti_sci_proc_power_domain_off(&core->tsp))
- dev_warn(core->dev, "module-reset assert back failed\n");
+ ret = reset_deassert(&core->reset);
+ if (ret) {
+ dev_err(core->dev, "local-reset deassert failed, ret = %d\n",
+ ret);
+ if (ti_sci_proc_power_domain_off(&core->tsp))
+ dev_warn(core->dev, "module-reset assert back failed\n");
+ }
}
return ret;
@@ -443,15 +454,24 @@ proc_release:
static int k3_r5f_split_reset(struct k3_r5f_core *core)
{
- int ret;
+ int ret = 0;
dev_dbg(core->dev, "%s\n", __func__);
- if (reset_assert(&core->reset))
- ret = -EINVAL;
+ if (core->ipdata->is_dm_core) {
+ ret = ti_sci_proc_set_control(&core->tsp, 0,
+ PROC_BOOT_CTRL_FLAG_R5_LPSC);
+ if (ret) {
+ dev_err(core->dev, "LPSC off failed, ret = %d\n", ret);
+ return ret;
+ }
+ } else {
+ if (reset_assert(&core->reset))
+ ret = -EINVAL;
- if (ti_sci_proc_power_domain_off(&core->tsp))
- ret = -EINVAL;
+ if (ti_sci_proc_power_domain_off(&core->tsp))
+ ret = -EINVAL;
+ }
return ret;
}
@@ -831,9 +851,21 @@ static int k3_r5f_probe(struct udevice *dev)
return ret;
if (core->in_use) {
- dev_info(dev, "Core %d is already in use. No rproc commands work\n",
- core->tsp.proc_id);
- return 0;
+ /*
+ * If MCU R5F is booted in split mode by ROM code, core0
+ * will run DM firmware and second core sits in WFI.
+ * Shut it down so that it can be probed as split core.
+ */
+ if (core->ipdata->is_dm_core && !is_primary_core(core) &&
+ core->cluster->mode == CLUSTER_MODE_SPLIT) {
+ dev_dbg(dev, "Core %d is in WFI mode, resetting core to use in split-mode.\n",
+ core->tsp.proc_id);
+ k3_r5f_stop(core->dev);
+ } else {
+ dev_info(dev, "Core %d is already in use. No rproc commands work\n",
+ core->tsp.proc_id);
+ return 0;
+ }
}
/* Make sure Local reset is asserted. Redundant? */
@@ -868,26 +900,47 @@ static const struct k3_r5f_ip_data k3_data = {
.tcm_is_double = false,
.tcm_ecc_autoinit = false,
.is_single_core = false,
+ .is_dm_core = false,
};
static const struct k3_r5f_ip_data j7200_j721s2_data = {
.tcm_is_double = true,
.tcm_ecc_autoinit = true,
.is_single_core = false,
+ .is_dm_core = false,
};
static const struct k3_r5f_ip_data am62_data = {
.tcm_is_double = false,
.tcm_ecc_autoinit = false,
.is_single_core = true,
+ .is_dm_core = false,
+};
+
+static const struct k3_r5f_ip_data k3_mcu_data = {
+ .tcm_is_double = false,
+ .tcm_ecc_autoinit = false,
+ .is_single_core = false,
+ .is_dm_core = true,
+};
+
+static const struct k3_r5f_ip_data j7200_mcu_data = {
+ .tcm_is_double = true,
+ .tcm_ecc_autoinit = true,
+ .is_single_core = false,
+ .is_dm_core = true,
};
static const struct udevice_id k3_r5f_rproc_ids[] = {
{ .compatible = "ti,am654-r5f", .data = (ulong)&k3_data, },
{ .compatible = "ti,j721e-r5f", .data = (ulong)&k3_data, },
+ { .compatible = "ti,j721e-mcu-r5f", .data = (ulong)&k3_mcu_data, },
{ .compatible = "ti,j7200-r5f", .data = (ulong)&j7200_j721s2_data, },
+ { .compatible = "ti,j7200-mcu-r5f", .data = (ulong)&j7200_mcu_data, },
{ .compatible = "ti,j721s2-r5f", .data = (ulong)&j7200_j721s2_data, },
+ { .compatible = "ti,j721s2-mcu-r5f", .data = (ulong)&j7200_mcu_data, },
{ .compatible = "ti,am62-r5f", .data = (ulong)&am62_data, },
+ { .compatible = "ti,am64-r5f", .data = (ulong)&j7200_j721s2_data, },
{}
};
@@ -932,6 +985,7 @@ static const struct udevice_id k3_r5fss_ids[] = {
{ .compatible = "ti,j7200-r5fss"},
{ .compatible = "ti,j721s2-r5fss"},
{ .compatible = "ti,am62-r5fss"},
+ { .compatible = "ti,am64-r5fss"},
{}
};
diff --git a/drivers/soc/soc_ti_k3.c b/drivers/soc/soc_ti_k3.c
index 332664e80b..7b9fdba5bc 100644
--- a/drivers/soc/soc_ti_k3.c
+++ b/drivers/soc/soc_ti_k3.c
@@ -48,7 +48,9 @@ static const char *get_family_string(u32 idreg)
case JTAG_ID_PARTNO_J784S4:
family = "J784S4";
break;
-
+ case JTAG_ID_PARTNO_AM62PX:
+ family = "AM62PX";
+ break;
default:
family = "Unknown Silicon";
};
diff --git a/drivers/spi/cadence_qspi.c b/drivers/spi/cadence_qspi.c
index 5abb86610c..298f83d3ed 100644
--- a/drivers/spi/cadence_qspi.c
+++ b/drivers/spi/cadence_qspi.c
@@ -41,6 +41,11 @@ __weak int cadence_qspi_versal_flash_reset(struct udevice *dev)
return 0;
}
+__weak ofnode cadence_qspi_get_subnode(struct udevice *dev)
+{
+ return dev_read_first_subnode(dev);
+}
+
static int cadence_spi_get_temp(int *temp)
{
struct udevice *dev;
@@ -992,7 +997,7 @@ static int cadence_spi_of_to_plat(struct udevice *bus)
plat->is_dma = dev_read_bool(bus, "cdns,is-dma");
/* All other parameters are embedded in the child node */
- subnode = dev_read_first_subnode(bus);
+ subnode = cadence_qspi_get_subnode(bus);
if (!ofnode_valid(subnode)) {
printf("Error: subnode with SPI flash config missing!\n");
return -ENODEV;
diff --git a/drivers/usb/musb-new/ti-musb.c b/drivers/usb/musb-new/ti-musb.c
index 91042935b0..291d6f1e2d 100644
--- a/drivers/usb/musb-new/ti-musb.c
+++ b/drivers/usb/musb-new/ti-musb.c
@@ -302,6 +302,7 @@ static int ti_musb_wrapper_bind(struct udevice *parent)
dr_mode = usb_get_dr_mode(node);
switch (dr_mode) {
case USB_DR_MODE_PERIPHERAL:
+ case USB_DR_MODE_OTG:
/* Bind MUSB device */
ret = device_bind_driver_to_node(parent,
"ti-musb-peripheral",