diff options
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/clk/imx/clk-imx8mp.c | 37 | ||||
| -rw-r--r-- | drivers/ddr/imx/imx8ulp/Kconfig | 2 | ||||
| -rw-r--r-- | drivers/ddr/imx/imx8ulp/ddr_init.c | 55 | ||||
| -rw-r--r-- | drivers/misc/Kconfig | 2 | ||||
| -rw-r--r-- | drivers/misc/sentinel/fuse.c | 32 | ||||
| -rw-r--r-- | drivers/misc/sentinel/s400_api.c | 71 | ||||
| -rw-r--r-- | drivers/net/dwc_eth_qos.c | 21 | ||||
| -rw-r--r-- | drivers/net/dwc_eth_qos_imx.c | 164 | ||||
| -rw-r--r-- | drivers/net/fec_mxc.c | 36 | ||||
| -rw-r--r-- | drivers/power/pmic/pca9450.c | 1 | ||||
| -rw-r--r-- | drivers/power/regulator/pca9450.c | 11 |
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; |
