summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/clk/imx/clk-imx8mp.c37
-rw-r--r--drivers/ddr/imx/imx8ulp/Kconfig2
-rw-r--r--drivers/ddr/imx/imx8ulp/ddr_init.c55
-rw-r--r--drivers/misc/Kconfig2
-rw-r--r--drivers/misc/sentinel/fuse.c32
-rw-r--r--drivers/misc/sentinel/s400_api.c71
-rw-r--r--drivers/net/dwc_eth_qos.c21
-rw-r--r--drivers/net/dwc_eth_qos_imx.c164
-rw-r--r--drivers/net/fec_mxc.c36
-rw-r--r--drivers/power/pmic/pca9450.c1
-rw-r--r--drivers/power/regulator/pca9450.c11
11 files changed, 369 insertions, 63 deletions
diff --git a/drivers/clk/imx/clk-imx8mp.c b/drivers/clk/imx/clk-imx8mp.c
index ffbc1d1ba9f..09bef596f22 100644
--- a/drivers/clk/imx/clk-imx8mp.c
+++ b/drivers/clk/imx/clk-imx8mp.c
@@ -70,6 +70,14 @@ static const char *imx8mp_i2c6_sels[] = {"clock-osc-24m", "sys_pll1_160m", "sys_
"sys_pll3_out", "audio_pll1_out", "video_pll1_out",
"audio_pll2_out", "sys_pll1_133m", };
+static const char *imx8mp_enet_qos_sels[] = {"clock-osc-24m", "sys_pll2_125m", "sys_pll2_50m",
+ "sys_pll2_100m", "sys_pll1_160m", "audio_pll1_out",
+ "video_pll1_out", "clk_ext4", };
+
+static const char *imx8mp_enet_qos_timer_sels[] = {"clock-osc-24m", "sys_pll2_100m", "audio_pll1_out",
+ "clk_ext1", "clk_ext2", "clk_ext3",
+ "clk_ext4", "video_pll1_out", };
+
static const char *imx8mp_usdhc1_sels[] = {"clock-osc-24m", "sys_pll1_400m", "sys_pll1_800m",
"sys_pll2_500m", "sys_pll3_out", "sys_pll1_266m",
"audio_pll2_out", "sys_pll1_100m", };
@@ -122,6 +130,22 @@ static const char *imx8mp_gic_sels[] = {"clock-osc-24m", "sys_pll2_200m", "sys_p
"sys_pll2_100m", "sys_pll1_800m",
"sys_pll2_500m", "clk_ext4", "audio_pll2_out" };
+static const char *imx8mp_pwm1_sels[] = {"clock-osc-24m", "sys_pll2_100m", "sys_pll1_160m",
+ "sys_pll1_40m", "sys_pll3_out", "clk_ext1",
+ "sys_pll1_80m", "video_pll1_out", };
+
+static const char *imx8mp_pwm2_sels[] = {"clock-osc-24m", "sys_pll2_100m", "sys_pll1_160m",
+ "sys_pll1_40m", "sys_pll3_out", "clk_ext1",
+ "sys_pll1_80m", "video_pll1_out", };
+
+static const char *imx8mp_pwm3_sels[] = {"clock-osc-24m", "sys_pll2_100m", "sys_pll1_160m",
+ "sys_pll1_40m", "sys_pll3_out", "clk_ext2",
+ "sys_pll1_80m", "video_pll1_out", };
+
+static const char *imx8mp_pwm4_sels[] = {"clock-osc-24m", "sys_pll2_100m", "sys_pll1_160m",
+ "sys_pll1_40m", "sys_pll3_out", "clk_ext2",
+ "sys_pll1_80m", "video_pll1_out", };
+
static const char *imx8mp_ecspi1_sels[] = {"clock-osc-24m", "sys_pll2_200m", "sys_pll1_40m",
"sys_pll1_160m", "sys_pll1_800m", "sys_pll3_out",
"sys_pll2_250m", "audio_pll2_out", };
@@ -250,6 +274,8 @@ static int imx8mp_clk_probe(struct udevice *dev)
clk_dm(IMX8MP_CLK_DRAM_APB, imx8m_clk_composite_critical("dram_apb", imx8mp_dram_apb_sels, base + 0xa080));
clk_dm(IMX8MP_CLK_I2C5, imx8m_clk_composite("i2c5", imx8mp_i2c5_sels, base + 0xa480));
clk_dm(IMX8MP_CLK_I2C6, imx8m_clk_composite("i2c6", imx8mp_i2c6_sels, base + 0xa500));
+ clk_dm(IMX8MP_CLK_ENET_QOS, imx8m_clk_composite("enet_qos", imx8mp_enet_qos_sels, base + 0xa880));
+ clk_dm(IMX8MP_CLK_ENET_QOS_TIMER, imx8m_clk_composite("enet_qos_timer", imx8mp_enet_qos_timer_sels, base + 0xa900));
clk_dm(IMX8MP_CLK_ENET_REF, imx8m_clk_composite("enet_ref", imx8mp_enet_ref_sels, base + 0xa980));
clk_dm(IMX8MP_CLK_ENET_TIMER, imx8m_clk_composite("enet_timer", imx8mp_enet_timer_sels, base + 0xaa00));
clk_dm(IMX8MP_CLK_ENET_PHY_REF, imx8m_clk_composite("enet_phy_ref", imx8mp_enet_phy_ref_sels, base + 0xaa80));
@@ -270,6 +296,10 @@ static int imx8mp_clk_probe(struct udevice *dev)
clk_dm(IMX8MP_CLK_GIC, imx8m_clk_composite_critical("gic", imx8mp_gic_sels, base + 0xb200));
clk_dm(IMX8MP_CLK_ECSPI1, imx8m_clk_composite("ecspi1", imx8mp_ecspi1_sels, base + 0xb280));
clk_dm(IMX8MP_CLK_ECSPI2, imx8m_clk_composite("ecspi2", imx8mp_ecspi2_sels, base + 0xb300));
+ clk_dm(IMX8MP_CLK_PWM1, imx8m_clk_composite_critical("pwm1", imx8mp_pwm1_sels, base + 0xb380));
+ clk_dm(IMX8MP_CLK_PWM2, imx8m_clk_composite_critical("pwm2", imx8mp_pwm2_sels, base + 0xb400));
+ clk_dm(IMX8MP_CLK_PWM3, imx8m_clk_composite_critical("pwm3", imx8mp_pwm3_sels, base + 0xb480));
+ clk_dm(IMX8MP_CLK_PWM4, imx8m_clk_composite_critical("pwm4", imx8mp_pwm4_sels, base + 0xb500));
clk_dm(IMX8MP_CLK_ECSPI3, imx8m_clk_composite("ecspi3", imx8mp_ecspi3_sels, base + 0xc180));
clk_dm(IMX8MP_CLK_WDOG, imx8m_clk_composite("wdog", imx8mp_wdog_sels, base + 0xb900));
@@ -292,10 +322,17 @@ static int imx8mp_clk_probe(struct udevice *dev)
clk_dm(IMX8MP_CLK_I2C2_ROOT, imx_clk_gate4("i2c2_root_clk", "i2c2", base + 0x4180, 0));
clk_dm(IMX8MP_CLK_I2C3_ROOT, imx_clk_gate4("i2c3_root_clk", "i2c3", base + 0x4190, 0));
clk_dm(IMX8MP_CLK_I2C4_ROOT, imx_clk_gate4("i2c4_root_clk", "i2c4", base + 0x41a0, 0));
+ clk_dm(IMX8MP_CLK_PWM1_ROOT, imx_clk_gate4("pwm1_root_clk", "pwm1", base + 0x4280, 0));
+ clk_dm(IMX8MP_CLK_PWM2_ROOT, imx_clk_gate4("pwm2_root_clk", "pwm2", base + 0x4290, 0));
+ clk_dm(IMX8MP_CLK_PWM3_ROOT, imx_clk_gate4("pwm3_root_clk", "pwm3", base + 0x42a0, 0));
+ clk_dm(IMX8MP_CLK_PWM4_ROOT, imx_clk_gate4("pwm4_root_clk", "pwm4", base + 0x42b0, 0));
+ clk_dm(IMX8MP_CLK_QOS_ROOT, imx_clk_gate4("qos_root_clk", "ipg_root", base + 0x42c0, 0));
+ clk_dm(IMX8MP_CLK_QOS_ENET_ROOT, imx_clk_gate4("qos_enet_root_clk", "ipg_root", base + 0x42e0, 0));
clk_dm(IMX8MP_CLK_QSPI_ROOT, imx_clk_gate4("qspi_root_clk", "qspi", base + 0x42f0, 0));
clk_dm(IMX8MP_CLK_I2C5_ROOT, imx_clk_gate2("i2c5_root_clk", "i2c5", base + 0x4330, 0));
clk_dm(IMX8MP_CLK_I2C6_ROOT, imx_clk_gate2("i2c6_root_clk", "i2c6", base + 0x4340, 0));
clk_dm(IMX8MP_CLK_SIM_ENET_ROOT, imx_clk_gate4("sim_enet_root_clk", "enet_axi", base + 0x4400, 0));
+ clk_dm(IMX8MP_CLK_ENET_QOS_ROOT, imx_clk_gate4("enet_qos_root_clk", "sim_enet_root_clk", base + 0x43b0, 0));
clk_dm(IMX8MP_CLK_UART1_ROOT, imx_clk_gate4("uart1_root_clk", "uart1", base + 0x4490, 0));
clk_dm(IMX8MP_CLK_UART2_ROOT, imx_clk_gate4("uart2_root_clk", "uart2", base + 0x44a0, 0));
clk_dm(IMX8MP_CLK_UART3_ROOT, imx_clk_gate4("uart3_root_clk", "uart3", base + 0x44b0, 0));
diff --git a/drivers/ddr/imx/imx8ulp/Kconfig b/drivers/ddr/imx/imx8ulp/Kconfig
index 42848863aae..5448c33838c 100644
--- a/drivers/ddr/imx/imx8ulp/Kconfig
+++ b/drivers/ddr/imx/imx8ulp/Kconfig
@@ -13,6 +13,6 @@ config SAVED_DRAM_TIMING_BASE
help
The DRAM config timing data need to be saved into sram
for low power use.
- default 0x2006c000
+ default 0x20055000
endmenu
diff --git a/drivers/ddr/imx/imx8ulp/ddr_init.c b/drivers/ddr/imx/imx8ulp/ddr_init.c
index a5a9fd8d7c8..c362a2da338 100644
--- a/drivers/ddr/imx/imx8ulp/ddr_init.c
+++ b/drivers/ddr/imx/imx8ulp/ddr_init.c
@@ -31,6 +31,7 @@
#define DENALI_CTL_25 (DDR_CTL_BASE_ADDR + 4 * 25)
#define DENALI_PHY_1624 (DDR_PHY_BASE_ADDR + 4 * 1624)
+#define DENALI_PHY_1625 (DDR_PHY_BASE_ADDR + 4 * 1625)
#define DENALI_PHY_1537 (DDR_PHY_BASE_ADDR + 4 * 1537)
#define PHY_FREQ_SEL_MULTICAST_EN(X) ((X) << 8)
#define PHY_FREQ_SEL_INDEX(X) ((X) << 16)
@@ -82,25 +83,39 @@ int ddr_calibration(unsigned int fsp_table[3])
u32 int_status_init, phy_freq_req, phy_freq_type;
u32 lock_0, lock_1, lock_2;
u32 freq_chg_pt, freq_chg_cnt;
+ u32 is_lpddr4 = 0;
if (IS_ENABLED(CONFIG_IMX8ULP_DRAM_PHY_PLL_BYPASS)) {
ddr_enable_pll_bypass();
freq_chg_cnt = 0;
freq_chg_pt = 0;
} else {
- reg_val = readl(DENALI_CTL_250);
- if (((reg_val >> 16) & 0x3) == 1)
- freq_chg_cnt = 2;
- else
- freq_chg_cnt = 3;
-
- reg_val = readl(DENALI_PI_12);
- if (reg_val == 0x3) {
- freq_chg_pt = 1;
- } else if (reg_val == 0x7) {
- freq_chg_pt = 2;
+ reg_val = (readl(DENALI_CTL_00)>>8)&0xf;
+ if(reg_val == 0x7) {
+ /* LPDDR3 type */
+ set_ddr_clk(fsp_table[1] >> 1);
+ freq_chg_cnt = 0;
+ freq_chg_pt = 0;
+ } else if(reg_val == 0xb) {
+ /* LPDDR4/4x type */
+ is_lpddr4 = 1;
+ reg_val = readl(DENALI_CTL_250);
+ if (((reg_val >> 16) & 0x3) == 1)
+ freq_chg_cnt = 2;
+ else
+ freq_chg_cnt = 3;
+
+ reg_val = readl(DENALI_PI_12);
+ if(reg_val == 0x3)
+ freq_chg_pt = 1;
+ else if(reg_val == 0x7)
+ freq_chg_pt = 2;
+ else {
+ printf("frequency map(0x%x) is wrong, please check!\r\n", reg_val);
+ return -1;
+ }
} else {
- printf("frequency map(0x%x) is wrong, please check!\r\n", reg_val);
+ printf("Incorrect DDR type configured!\r\n");
return -1;
}
}
@@ -179,6 +194,22 @@ int ddr_calibration(unsigned int fsp_table[3])
}
debug("De-Skew PLL is locked and ready\n");
+
+ /* Change LPDDR4 FREQ1 to bypass mode if it is lower than 200MHz */
+ if(is_lpddr4 && fsp_table[1] < 400) {
+ /* Set FREQ1 to bypass mode */
+ reg_val = PHY_FREQ_SEL_MULTICAST_EN(0) | PHY_FREQ_SEL_INDEX(0);
+ writel(reg_val, DENALI_PHY_1537);
+
+ /* PHY_PLL_BYPASS=0x1 (DENALI_PHY_1624) */
+ reg_val =readl(DENALI_PHY_1624) | 0x1;
+ writel(reg_val, DENALI_PHY_1624);
+
+ /* DENALI_PHY_1625: bypass mode in PHY PLL */
+ reg_val =readl(DENALI_PHY_1625) & ~0xf;
+ writel(reg_val, DENALI_PHY_1625);
+ }
+
return 0;
}
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index b5707a15c50..4e1ae03e9fd 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -348,7 +348,7 @@ config NPCM_HOST
config SPL_MXC_OCOTP
bool "Enable MXC OCOTP driver in SPL"
- depends on SPL_MISC && (ARCH_IMX8M || ARCH_MX6 || ARCH_MX7 || ARCH_MX7ULP || ARCH_VF610)
+ depends on SPL_DRIVERS_MISC && (ARCH_IMX8M || ARCH_MX6 || ARCH_MX7 || ARCH_MX7ULP || ARCH_VF610)
default y
help
If you say Y here, you will get support for the One Time
diff --git a/drivers/misc/sentinel/fuse.c b/drivers/misc/sentinel/fuse.c
index e2b68757664..99342d33c06 100644
--- a/drivers/misc/sentinel/fuse.c
+++ b/drivers/misc/sentinel/fuse.c
@@ -60,6 +60,11 @@ struct fsb_map_entry fsb_mapping_table[] = {
{ 46, 8 },
};
+/* None ECC banks such like Redundancy or Bit protect */
+u32 nonecc_fuse_banks[] = {
+ 0, 1, 8, 12, 16, 22, 24, 25, 26, 27, 36, 41, 51, 56
+};
+
struct s400_map_entry s400_api_mapping_table[] = {
{ 1, 8 }, /* LOCK */
{ 2, 8 }, /* ECID */
@@ -67,6 +72,16 @@ struct s400_map_entry s400_api_mapping_table[] = {
{ 15, 8 }, /* OEM SRK HASH */
{ 23, 1, 4, 2 }, /* OTFAD */
{ 25, 8 }, /* Test config2 */
+ { 26, 8 }, /* PMU */
+ { 27, 8 }, /* Test flow/USB */
+ { 32, 8 }, /* GP1 */
+ { 33, 8 }, /* GP2 */
+ { 34, 8 }, /* GP3 */
+ { 35, 8 }, /* GP4 */
+ { 36, 8 }, /* GP5 */
+ { 49, 8 }, /* GP8 */
+ { 50, 8 }, /* GP9 */
+ { 51, 8 }, /* GP10 */
};
#elif defined(CONFIG_ARCH_IMX9)
#define FSB_OTP_SHADOW 0x8000
@@ -270,11 +285,26 @@ int fuse_prog(u32 bank, u32 word, u32 val)
{
u32 res;
int ret;
+ bool lock = false;
if (bank >= FUSE_BANKS || word >= WORDS_PER_BANKS || !val)
return -EINVAL;
- ret = ahab_write_fuse((bank * 8 + word), val, false, &res);
+ /* Lock 8ULP ECC fuse word, so second programming will return failure.
+ * iMX9 OTP can protect ECC fuse, so not need it
+ */
+#if defined(CONFIG_IMX8ULP)
+ u32 i;
+ for (i = 0; i < ARRAY_SIZE(nonecc_fuse_banks); i++) {
+ if (nonecc_fuse_banks[i] == bank)
+ break;
+ }
+
+ if (i == ARRAY_SIZE(nonecc_fuse_banks))
+ lock = true;
+#endif
+
+ ret = ahab_write_fuse((bank * 8 + word), val, lock, &res);
if (ret) {
printf("ahab write fuse failed %d, 0x%x\n", ret, res);
return ret;
diff --git a/drivers/misc/sentinel/s400_api.c b/drivers/misc/sentinel/s400_api.c
index 65032f77362..6c0d0b3f18a 100644
--- a/drivers/misc/sentinel/s400_api.c
+++ b/drivers/misc/sentinel/s400_api.c
@@ -29,7 +29,7 @@ int ahab_release_rdc(u8 core_id, u8 xrdc, u32 *response)
msg.version = AHAB_VERSION;
msg.tag = AHAB_CMD_TAG;
msg.size = 2;
- msg.command = AHAB_RELEASE_RDC_REQ_CID;
+ msg.command = ELE_RELEASE_RDC_REQ;
switch (xrdc) {
case 0:
msg.data[0] = (0x74 << 8) | core_id;
@@ -74,7 +74,7 @@ int ahab_auth_oem_ctnr(ulong ctnr_addr, u32 *response)
msg.version = AHAB_VERSION;
msg.tag = AHAB_CMD_TAG;
msg.size = 3;
- msg.command = AHAB_AUTH_OEM_CTNR_CID;
+ msg.command = ELE_OEM_CNTN_AUTH_REQ;
msg.data[0] = upper_32_bits(ctnr_addr);
msg.data[1] = lower_32_bits(ctnr_addr);
@@ -104,7 +104,7 @@ int ahab_release_container(u32 *response)
msg.version = AHAB_VERSION;
msg.tag = AHAB_CMD_TAG;
msg.size = 1;
- msg.command = AHAB_RELEASE_CTNR_CID;
+ msg.command = ELE_RELEASE_CONTAINER_REQ;
ret = misc_call(dev, false, &msg, size, &msg, size);
if (ret)
@@ -132,7 +132,7 @@ int ahab_verify_image(u32 img_id, u32 *response)
msg.version = AHAB_VERSION;
msg.tag = AHAB_CMD_TAG;
msg.size = 2;
- msg.command = AHAB_VERIFY_IMG_CID;
+ msg.command = ELE_VERIFY_IMAGE_REQ;
msg.data[0] = 1 << img_id;
ret = misc_call(dev, false, &msg, size, &msg, size);
@@ -161,7 +161,7 @@ int ahab_forward_lifecycle(u16 life_cycle, u32 *response)
msg.version = AHAB_VERSION;
msg.tag = AHAB_CMD_TAG;
msg.size = 2;
- msg.command = AHAB_FWD_LIFECYCLE_UP_REQ_CID;
+ msg.command = ELE_FWD_LIFECYCLE_UP_REQ;
msg.data[0] = life_cycle;
ret = misc_call(dev, false, &msg, size, &msg, size);
@@ -201,7 +201,7 @@ int ahab_read_common_fuse(u16 fuse_id, u32 *fuse_words, u32 fuse_num, u32 *respo
msg.version = AHAB_VERSION;
msg.tag = AHAB_CMD_TAG;
msg.size = 2;
- msg.command = AHAB_READ_FUSE_REQ_CID;
+ msg.command = ELE_READ_FUSE_REQ;
msg.data[0] = fuse_id;
ret = misc_call(dev, false, &msg, size, &msg, size);
@@ -238,7 +238,7 @@ int ahab_write_fuse(u16 fuse_id, u32 fuse_val, bool lock, u32 *response)
msg.version = AHAB_VERSION;
msg.tag = AHAB_CMD_TAG;
msg.size = 3;
- msg.command = AHAB_WRITE_FUSE_REQ_CID;
+ msg.command = ELE_WRITE_FUSE_REQ;
msg.data[0] = (32 << 16) | (fuse_id << 5);
if (lock)
msg.data[0] |= (1 << 31);
@@ -271,7 +271,7 @@ int ahab_release_caam(u32 core_did, u32 *response)
msg.version = AHAB_VERSION;
msg.tag = AHAB_CMD_TAG;
msg.size = 2;
- msg.command = AHAB_CAAM_RELEASE_CID;
+ msg.command = ELE_RELEASE_CAAM_REQ;
msg.data[0] = core_did;
ret = misc_call(dev, false, &msg, size, &msg, size);
@@ -310,7 +310,7 @@ int ahab_get_fw_version(u32 *fw_version, u32 *sha1, u32 *response)
msg.version = AHAB_VERSION;
msg.tag = AHAB_CMD_TAG;
msg.size = 1;
- msg.command = AHAB_GET_FW_VERSION_CID;
+ msg.command = ELE_GET_FW_VERSION_REQ;
ret = misc_call(dev, false, &msg, size, &msg, size);
if (ret)
@@ -341,7 +341,7 @@ int ahab_dump_buffer(u32 *buffer, u32 buffer_length)
msg.version = AHAB_VERSION;
msg.tag = AHAB_CMD_TAG;
msg.size = 1;
- msg.command = AHAB_LOG_CID;
+ msg.command = ELE_DUMP_DEBUG_BUFFER_REQ;
ret = misc_call(dev, false, &msg, size, &msg, size);
if (ret) {
@@ -375,7 +375,7 @@ int ahab_get_info(struct sentinel_get_info_data *info, u32 *response)
msg.version = AHAB_VERSION;
msg.tag = AHAB_CMD_TAG;
msg.size = 4;
- msg.command = AHAB_GET_INFO_CID;
+ msg.command = ELE_GET_INFO_REQ;
msg.data[0] = upper_32_bits((ulong)info);
msg.data[1] = lower_32_bits((ulong)info);
msg.data[2] = sizeof(struct sentinel_get_info_data);
@@ -406,7 +406,7 @@ int ahab_get_fw_status(u32 *status, u32 *response)
msg.version = AHAB_VERSION;
msg.tag = AHAB_CMD_TAG;
msg.size = 1;
- msg.command = AHAB_GET_FW_STATUS_CID;
+ msg.command = ELE_GET_FW_STATUS_REQ;
ret = misc_call(dev, false, &msg, size, &msg, size);
if (ret)
@@ -436,7 +436,7 @@ int ahab_release_m33_trout(void)
msg.version = AHAB_VERSION;
msg.tag = AHAB_CMD_TAG;
msg.size = 1;
- msg.command = 0xd3;
+ msg.command = ELE_ENABLE_RTC_REQ;
ret = misc_call(dev, false, &msg, size, &msg, size);
if (ret)
@@ -445,3 +445,48 @@ int ahab_release_m33_trout(void)
return ret;
}
+
+int ahab_get_events(u32 *events, u32 *events_cnt, u32 *response)
+{
+ struct udevice *dev = gd->arch.s400_dev;
+ int size = sizeof(struct sentinel_msg);
+ struct sentinel_msg msg;
+ int ret, i = 0;
+ u32 actual_events;
+
+ if (!dev) {
+ printf("s400 dev is not initialized\n");
+ return -ENODEV;
+ }
+
+ if (!events || !events_cnt || *events_cnt == 0) {
+ printf("Invalid parameters for %s\n", __func__);
+ return -EINVAL;
+ }
+
+ msg.version = AHAB_VERSION;
+ msg.tag = AHAB_CMD_TAG;
+ msg.size = 1;
+ msg.command = ELE_GET_EVENTS_REQ;
+
+ 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];
+
+ if (!ret) {
+ actual_events = msg.data[1] & 0xffff;
+ if (*events_cnt < actual_events)
+ actual_events = *events_cnt;
+
+ for (; i < actual_events; i++)
+ events[i] = msg.data[i + 2];
+
+ *events_cnt = actual_events;
+ }
+
+ return ret;
+}
diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c
index 112deb546de..ec58697b311 100644
--- a/drivers/net/dwc_eth_qos.c
+++ b/drivers/net/dwc_eth_qos.c
@@ -108,7 +108,7 @@ void eqos_flush_desc_generic(void *desc)
flush_dcache_range(start, end);
}
-void eqos_inval_buffer_tegra186(void *buf, size_t size)
+static void eqos_inval_buffer_tegra186(void *buf, size_t size)
{
unsigned long start = (unsigned long)buf & ~(ARCH_DMA_MINALIGN - 1);
unsigned long end = ALIGN(start + size, ARCH_DMA_MINALIGN);
@@ -761,6 +761,12 @@ static int eqos_start(struct udevice *dev)
eqos->reg_access_ok = true;
+ /*
+ * Assert the SWR first, the actually reset the MAC and to latch in
+ * e.g. i.MX8M Plus GPR[1] content, which selects interface mode.
+ */
+ setbits_le32(&eqos->dma_regs->mode, EQOS_DMA_MODE_SWR);
+
ret = wait_for_bit_le32(&eqos->dma_regs->mode,
EQOS_DMA_MODE_SWR, false,
eqos->config->swr_wait, false);
@@ -1383,7 +1389,6 @@ static int eqos_probe_resources_tegra186(struct udevice *dev)
if (ret) {
pr_err("clk_get_by_name(ptp_ref) failed: %d", ret);
goto err_free_clk_rx;
- return ret;
}
ret = clk_get_by_name(dev, "tx", &eqos->clk_tx);
@@ -1412,13 +1417,6 @@ err_free_reset_eqos:
return ret;
}
-/* board-specific Ethernet Interface initializations. */
-__weak int board_interface_eth_init(struct udevice *dev,
- phy_interface_t interface_type)
-{
- return 0;
-}
-
static int eqos_probe_resources_stm32(struct udevice *dev)
{
struct eqos_priv *eqos = dev_get_priv(dev);
@@ -1501,7 +1499,7 @@ static int eqos_remove_resources_tegra186(struct udevice *dev)
static int eqos_remove_resources_stm32(struct udevice *dev)
{
- struct eqos_priv *eqos = dev_get_priv(dev);
+ struct eqos_priv * __maybe_unused eqos = dev_get_priv(dev);
debug("%s(dev=%p):\n", __func__, dev);
@@ -1513,9 +1511,6 @@ static int eqos_remove_resources_stm32(struct udevice *dev)
clk_free(&eqos->clk_ck);
#endif
- if (dm_gpio_is_valid(&eqos->phy_reset_gpio))
- dm_gpio_free(dev, &eqos->phy_reset_gpio);
-
debug("%s: OK\n", __func__);
return 0;
}
diff --git a/drivers/net/dwc_eth_qos_imx.c b/drivers/net/dwc_eth_qos_imx.c
index 42cb164ad14..60f3f3f5a10 100644
--- a/drivers/net/dwc_eth_qos_imx.c
+++ b/drivers/net/dwc_eth_qos_imx.c
@@ -7,6 +7,7 @@
#include <clk.h>
#include <cpu_func.h>
#include <dm.h>
+#include <dm/device_compat.h>
#include <errno.h>
#include <eth_phy.h>
#include <log.h>
@@ -32,20 +33,18 @@ __weak u32 imx_get_eqos_csr_clk(void)
return 100 * 1000000;
}
-__weak int imx_eqos_txclk_set_rate(unsigned long rate)
-{
- return 0;
-}
-
static ulong eqos_get_tick_clk_rate_imx(struct udevice *dev)
{
- return imx_get_eqos_csr_clk();
+ struct eqos_priv *eqos = dev_get_priv(dev);
+
+ return clk_get_rate(&eqos->clk_master_bus);
}
static int eqos_probe_resources_imx(struct udevice *dev)
{
struct eqos_priv *eqos = dev_get_priv(dev);
phy_interface_t interface;
+ int ret;
debug("%s(dev=%p):\n", __func__, dev);
@@ -56,6 +55,122 @@ static int eqos_probe_resources_imx(struct udevice *dev)
return -EINVAL;
}
+ ret = board_interface_eth_init(dev, interface);
+ if (ret)
+ return -EINVAL;
+
+ eqos->max_speed = dev_read_u32_default(dev, "max-speed", 0);
+
+ ret = clk_get_by_name(dev, "stmmaceth", &eqos->clk_master_bus);
+ if (ret) {
+ dev_dbg(dev, "clk_get_by_name(master_bus) failed: %d", ret);
+ goto err_probe;
+ }
+
+ ret = clk_get_by_name(dev, "ptp_ref", &eqos->clk_ptp_ref);
+ if (ret) {
+ dev_dbg(dev, "clk_get_by_name(ptp_ref) failed: %d", ret);
+ goto err_free_clk_master_bus;
+ }
+
+ ret = clk_get_by_name(dev, "tx", &eqos->clk_tx);
+ if (ret) {
+ dev_dbg(dev, "clk_get_by_name(tx) failed: %d", ret);
+ goto err_free_clk_ptp_ref;
+ }
+
+ ret = clk_get_by_name(dev, "pclk", &eqos->clk_ck);
+ if (ret) {
+ dev_dbg(dev, "clk_get_by_name(pclk) failed: %d", ret);
+ goto err_free_clk_tx;
+ }
+
+ debug("%s: OK\n", __func__);
+ return 0;
+
+err_free_clk_tx:
+ clk_free(&eqos->clk_tx);
+err_free_clk_ptp_ref:
+ clk_free(&eqos->clk_ptp_ref);
+err_free_clk_master_bus:
+ clk_free(&eqos->clk_master_bus);
+err_probe:
+
+ debug("%s: returns %d\n", __func__, ret);
+ return ret;
+}
+
+static int eqos_remove_resources_imx(struct udevice *dev)
+{
+ struct eqos_priv *eqos = dev_get_priv(dev);
+
+ debug("%s(dev=%p):\n", __func__, dev);
+
+ clk_free(&eqos->clk_ck);
+ clk_free(&eqos->clk_tx);
+ clk_free(&eqos->clk_ptp_ref);
+ clk_free(&eqos->clk_master_bus);
+
+ debug("%s: OK\n", __func__);
+ return 0;
+}
+
+static int eqos_start_clks_imx(struct udevice *dev)
+{
+ struct eqos_priv *eqos = dev_get_priv(dev);
+ int ret;
+
+ debug("%s(dev=%p):\n", __func__, dev);
+
+ ret = clk_enable(&eqos->clk_master_bus);
+ if (ret < 0) {
+ dev_dbg(dev, "clk_enable(clk_master_bus) failed: %d", ret);
+ goto err;
+ }
+
+ ret = clk_enable(&eqos->clk_ptp_ref);
+ if (ret < 0) {
+ dev_dbg(dev, "clk_enable(clk_ptp_ref) failed: %d", ret);
+ goto err_disable_clk_master_bus;
+ }
+
+ ret = clk_enable(&eqos->clk_tx);
+ if (ret < 0) {
+ dev_dbg(dev, "clk_enable(clk_tx) failed: %d", ret);
+ goto err_disable_clk_ptp_ref;
+ }
+
+ ret = clk_enable(&eqos->clk_ck);
+ if (ret < 0) {
+ dev_dbg(dev, "clk_enable(clk_ck) failed: %d", ret);
+ goto err_disable_clk_tx;
+ }
+
+ debug("%s: OK\n", __func__);
+ return 0;
+
+err_disable_clk_tx:
+ clk_disable(&eqos->clk_tx);
+err_disable_clk_ptp_ref:
+ clk_disable(&eqos->clk_ptp_ref);
+err_disable_clk_master_bus:
+ clk_disable(&eqos->clk_master_bus);
+err:
+ debug("%s: FAILED: %d\n", __func__, ret);
+ return ret;
+}
+
+static int eqos_stop_clks_imx(struct udevice *dev)
+{
+ struct eqos_priv *eqos = dev_get_priv(dev);
+
+ debug("%s(dev=%p):\n", __func__, dev);
+
+ clk_disable(&eqos->clk_ck);
+ clk_disable(&eqos->clk_tx);
+ clk_disable(&eqos->clk_ptp_ref);
+ clk_disable(&eqos->clk_master_bus);
+
debug("%s: OK\n", __func__);
return 0;
}
@@ -68,22 +183,29 @@ static int eqos_set_tx_clk_speed_imx(struct udevice *dev)
debug("%s(dev=%p):\n", __func__, dev);
- switch (eqos->phy->speed) {
- case SPEED_1000:
- rate = 125 * 1000 * 1000;
- break;
- case SPEED_100:
- rate = 25 * 1000 * 1000;
- break;
- case SPEED_10:
- rate = 2.5 * 1000 * 1000;
- break;
- default:
+ if (eqos->phy->interface == PHY_INTERFACE_MODE_RMII)
+ rate = 5000; /* 5000 kHz = 5 MHz */
+ else
+ rate = 2500; /* 2500 kHz = 2.5 MHz */
+
+ if (eqos->phy->speed == SPEED_1000 &&
+ (eqos->phy->interface == PHY_INTERFACE_MODE_RGMII ||
+ eqos->phy->interface == PHY_INTERFACE_MODE_RGMII_ID ||
+ eqos->phy->interface == PHY_INTERFACE_MODE_RGMII_RXID ||
+ eqos->phy->interface == PHY_INTERFACE_MODE_RGMII_TXID)) {
+ rate *= 50; /* Use 50x base rate i.e. 125 MHz */
+ } else if (eqos->phy->speed == SPEED_100) {
+ rate *= 10; /* Use 10x base rate */
+ } else if (eqos->phy->speed == SPEED_10) {
+ rate *= 1; /* Use base rate */
+ } else {
pr_err("invalid speed %d", eqos->phy->speed);
return -EINVAL;
}
- ret = imx_eqos_txclk_set_rate(rate);
+ rate *= 1000; /* clk_set_rate() operates in Hz */
+
+ ret = clk_set_rate(&eqos->clk_tx, rate);
if (ret < 0) {
pr_err("imx (tx_clk, %lu) failed: %d", rate, ret);
return ret;
@@ -107,11 +229,11 @@ static struct eqos_ops eqos_imx_ops = {
.eqos_inval_buffer = eqos_inval_buffer_generic,
.eqos_flush_buffer = eqos_flush_buffer_generic,
.eqos_probe_resources = eqos_probe_resources_imx,
- .eqos_remove_resources = eqos_null_ops,
+ .eqos_remove_resources = eqos_remove_resources_imx,
.eqos_stop_resets = eqos_null_ops,
.eqos_start_resets = eqos_null_ops,
- .eqos_stop_clks = eqos_null_ops,
- .eqos_start_clks = eqos_null_ops,
+ .eqos_stop_clks = eqos_stop_clks_imx,
+ .eqos_start_clks = eqos_start_clks_imx,
.eqos_calibrate_pads = eqos_null_ops,
.eqos_disable_calibration = eqos_null_ops,
.eqos_set_tx_clk_speed = eqos_set_tx_clk_speed_imx,
diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c
index 1a6c18a441f..ac937676f9c 100644
--- a/drivers/net/fec_mxc.c
+++ b/drivers/net/fec_mxc.c
@@ -1196,6 +1196,33 @@ static void fec_gpio_reset(struct fec_priv *priv)
}
#endif
+static int fecmxc_set_ref_clk(struct clk *clk_ref, phy_interface_t interface)
+{
+ unsigned int freq;
+ int ret;
+
+ if (!CONFIG_IS_ENABLED(CLK_CCF))
+ return 0;
+
+ if (interface == PHY_INTERFACE_MODE_MII)
+ freq = 25000000;
+ else if (interface == PHY_INTERFACE_MODE_RMII)
+ freq = 50000000;
+ else if (interface == PHY_INTERFACE_MODE_RGMII ||
+ interface == PHY_INTERFACE_MODE_RGMII_ID ||
+ interface == PHY_INTERFACE_MODE_RGMII_RXID ||
+ interface == PHY_INTERFACE_MODE_RGMII_TXID)
+ freq = 125000000;
+ else
+ return -EINVAL;
+
+ ret = clk_set_rate(clk_ref, freq);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
static int fecmxc_probe(struct udevice *dev)
{
bool dm_mii_bus = true;
@@ -1205,6 +1232,10 @@ static int fecmxc_probe(struct udevice *dev)
uint32_t start;
int ret;
+ ret = board_interface_eth_init(dev, pdata->phy_interface);
+ if (ret)
+ return ret;
+
if (IS_ENABLED(CONFIG_IMX_MODULE_FUSE)) {
if (enet_fused((ulong)priv->eth)) {
printf("SoC fuse indicates Ethernet@0x%lx is unavailable.\n", (ulong)priv->eth);
@@ -1253,6 +1284,11 @@ static int fecmxc_probe(struct udevice *dev)
ret = clk_get_by_name(dev, "enet_clk_ref", &priv->clk_ref);
if (!ret) {
+ ret = fecmxc_set_ref_clk(&priv->clk_ref,
+ pdata->phy_interface);
+ if (ret)
+ return ret;
+
ret = clk_enable(&priv->clk_ref);
if (ret)
return ret;
diff --git a/drivers/power/pmic/pca9450.c b/drivers/power/pmic/pca9450.c
index 2427abfb7a5..e99ece8fb08 100644
--- a/drivers/power/pmic/pca9450.c
+++ b/drivers/power/pmic/pca9450.c
@@ -120,6 +120,7 @@ static const struct udevice_id pca9450_ids[] = {
{ .compatible = "nxp,pca9450a", .data = NXP_CHIP_TYPE_PCA9450A, },
{ .compatible = "nxp,pca9450b", .data = NXP_CHIP_TYPE_PCA9450BC, },
{ .compatible = "nxp,pca9450c", .data = NXP_CHIP_TYPE_PCA9450BC, },
+ { .compatible = "nxp,pca9451a", .data = NXP_CHIP_TYPE_PCA9451A, },
{ }
};
diff --git a/drivers/power/regulator/pca9450.c b/drivers/power/regulator/pca9450.c
index fe1869397cd..7ca20d1f7f8 100644
--- a/drivers/power/regulator/pca9450.c
+++ b/drivers/power/regulator/pca9450.c
@@ -276,7 +276,8 @@ static int pca9450_regulator_probe(struct udevice *dev)
type = dev_get_driver_data(dev_get_parent(dev));
- if (type != NXP_CHIP_TYPE_PCA9450A && type != NXP_CHIP_TYPE_PCA9450BC) {
+ if (type != NXP_CHIP_TYPE_PCA9450A && type != NXP_CHIP_TYPE_PCA9450BC &&
+ type != NXP_CHIP_TYPE_PCA9451A) {
debug("Unknown PMIC type\n");
return -EINVAL;
}
@@ -291,6 +292,14 @@ static int pca9450_regulator_probe(struct udevice *dev)
continue;
}
+ /* PCA9451A uses BUCK3 in dual-phase and don't have LDO2 and LDO3 */
+ if (type == NXP_CHIP_TYPE_PCA9451A &&
+ (!strcmp(pca9450_reg_data[i].name, "BUCK3") ||
+ !strcmp(pca9450_reg_data[i].name, "LDO2") ||
+ !strcmp(pca9450_reg_data[i].name, "LDO3"))) {
+ continue;
+ }
+
*plat = pca9450_reg_data[i];
return 0;