u-boot/drivers/clk/imx/clk-imx8qm.c
Tom Rini d678a59d2d Revert "Merge patch series "arm: dts: am62-beagleplay: Fix Beagleplay Ethernet""
When bringing in the series 'arm: dts: am62-beagleplay: Fix Beagleplay
Ethernet"' I failed to notice that b4 noticed it was based on next and
so took that as the base commit and merged that part of next to master.

This reverts commit c8ffd1356d, reversing
changes made to 2ee6f3a5f7.

Reported-by: Jonas Karlman <jonas@kwiboo.se>
Signed-off-by: Tom Rini <trini@konsulko.com>
2024-05-19 08:16:36 -06:00

362 lines
7.8 KiB
C

// SPDX-License-Identifier: GPL-2.0
/*
* Copyright 2018 NXP
* Peng Fan <peng.fan@nxp.com>
*/
#include <common.h>
#include <clk-uclass.h>
#include <dm.h>
#include <log.h>
#include <firmware/imx/sci/sci.h>
#include <asm/arch/clock.h>
#include <dt-bindings/clock/imx8qm-clock.h>
#include <dt-bindings/soc/imx_rsrc.h>
#include <misc.h>
#include "clk-imx8.h"
#if IS_ENABLED(CONFIG_CMD_CLK)
struct imx8_clks imx8_clk_names[] = {
{ IMX8QM_A53_DIV, "A53_DIV" },
{ IMX8QM_UART0_CLK, "UART0" },
{ IMX8QM_UART1_CLK, "UART1" },
{ IMX8QM_UART2_CLK, "UART2" },
{ IMX8QM_UART3_CLK, "UART3" },
{ IMX8QM_SDHC0_CLK, "SDHC0" },
{ IMX8QM_SDHC1_CLK, "SDHC1" },
{ IMX8QM_SDHC2_CLK, "SDHC2" },
{ IMX8QM_ENET0_AHB_CLK, "ENET0_AHB" },
{ IMX8QM_ENET0_IPG_CLK, "ENET0_IPG" },
{ IMX8QM_ENET0_REF_DIV, "ENET0_REF" },
{ IMX8QM_ENET0_PTP_CLK, "ENET0_PTP" },
{ IMX8QM_ENET1_AHB_CLK, "ENET1_AHB" },
{ IMX8QM_ENET1_IPG_CLK, "ENET1_IPG" },
{ IMX8QM_ENET1_REF_DIV, "ENET1_REF" },
{ IMX8QM_ENET1_PTP_CLK, "ENET1_PTP" },
};
int num_clks = ARRAY_SIZE(imx8_clk_names);
#endif
ulong imx8_clk_get_rate(struct clk *clk)
{
sc_pm_clk_t pm_clk;
ulong rate;
u16 resource;
int ret;
debug("%s(#%lu)\n", __func__, clk->id);
switch (clk->id) {
case IMX8QM_A53_DIV:
resource = SC_R_A53;
pm_clk = SC_PM_CLK_CPU;
break;
case IMX8QM_I2C0_IPG_CLK:
case IMX8QM_I2C0_CLK:
case IMX8QM_I2C0_DIV:
resource = SC_R_I2C_0;
pm_clk = SC_PM_CLK_PER;
break;
case IMX8QM_I2C1_IPG_CLK:
case IMX8QM_I2C1_CLK:
case IMX8QM_I2C1_DIV:
resource = SC_R_I2C_1;
pm_clk = SC_PM_CLK_PER;
break;
case IMX8QM_I2C2_IPG_CLK:
case IMX8QM_I2C2_CLK:
case IMX8QM_I2C2_DIV:
resource = SC_R_I2C_2;
pm_clk = SC_PM_CLK_PER;
break;
case IMX8QM_I2C3_IPG_CLK:
case IMX8QM_I2C3_CLK:
case IMX8QM_I2C3_DIV:
resource = SC_R_I2C_3;
pm_clk = SC_PM_CLK_PER;
break;
case IMX8QM_SDHC0_IPG_CLK:
case IMX8QM_SDHC0_CLK:
case IMX8QM_SDHC0_DIV:
resource = SC_R_SDHC_0;
pm_clk = SC_PM_CLK_PER;
break;
case IMX8QM_SDHC1_IPG_CLK:
case IMX8QM_SDHC1_CLK:
case IMX8QM_SDHC1_DIV:
resource = SC_R_SDHC_1;
pm_clk = SC_PM_CLK_PER;
break;
case IMX8QM_SDHC2_IPG_CLK:
case IMX8QM_SDHC2_CLK:
case IMX8QM_SDHC2_DIV:
resource = SC_R_SDHC_2;
pm_clk = SC_PM_CLK_PER;
break;
case IMX8QM_UART0_CLK:
case IMX8QM_UART0_IPG_CLK:
resource = SC_R_UART_0;
pm_clk = SC_PM_CLK_PER;
break;
case IMX8QM_UART1_CLK:
case IMX8QM_UART1_IPG_CLK:
resource = SC_R_UART_1;
pm_clk = SC_PM_CLK_PER;
break;
case IMX8QM_UART2_CLK:
case IMX8QM_UART2_IPG_CLK:
resource = SC_R_UART_2;
pm_clk = SC_PM_CLK_PER;
break;
case IMX8QM_UART3_CLK:
case IMX8QM_UART3_IPG_CLK:
resource = SC_R_UART_3;
pm_clk = SC_PM_CLK_PER;
break;
case IMX8QM_ENET0_IPG_CLK:
case IMX8QM_ENET0_AHB_CLK:
case IMX8QM_ENET0_REF_DIV:
case IMX8QM_ENET0_PTP_CLK:
resource = SC_R_ENET_0;
pm_clk = SC_PM_CLK_PER;
break;
case IMX8QM_ENET1_IPG_CLK:
case IMX8QM_ENET1_AHB_CLK:
case IMX8QM_ENET1_REF_DIV:
case IMX8QM_ENET1_PTP_CLK:
resource = SC_R_ENET_1;
pm_clk = SC_PM_CLK_PER;
break;
default:
if (clk->id < IMX8QM_UART0_IPG_CLK ||
clk->id >= IMX8QM_CLK_END) {
printf("%s(Invalid clk ID #%lu)\n",
__func__, clk->id);
return -EINVAL;
}
return -EINVAL;
};
ret = sc_pm_get_clock_rate(-1, resource, pm_clk,
(sc_pm_clock_rate_t *)&rate);
if (ret) {
printf("%s err %d\n", __func__, ret);
return ret;
}
return rate;
}
ulong imx8_clk_set_rate(struct clk *clk, unsigned long rate)
{
sc_pm_clk_t pm_clk;
u32 new_rate = rate;
u16 resource;
int ret;
debug("%s(#%lu), rate: %lu\n", __func__, clk->id, rate);
switch (clk->id) {
case IMX8QM_I2C0_IPG_CLK:
case IMX8QM_I2C0_CLK:
case IMX8QM_I2C0_DIV:
resource = SC_R_I2C_0;
pm_clk = SC_PM_CLK_PER;
break;
case IMX8QM_I2C1_IPG_CLK:
case IMX8QM_I2C1_CLK:
case IMX8QM_I2C1_DIV:
resource = SC_R_I2C_1;
pm_clk = SC_PM_CLK_PER;
break;
case IMX8QM_I2C2_IPG_CLK:
case IMX8QM_I2C2_CLK:
case IMX8QM_I2C2_DIV:
resource = SC_R_I2C_2;
pm_clk = SC_PM_CLK_PER;
break;
case IMX8QM_I2C3_IPG_CLK:
case IMX8QM_I2C3_CLK:
case IMX8QM_I2C3_DIV:
resource = SC_R_I2C_3;
pm_clk = SC_PM_CLK_PER;
break;
case IMX8QM_UART0_CLK:
case IMX8QM_UART0_IPG_CLK:
resource = SC_R_UART_0;
pm_clk = SC_PM_CLK_PER;
break;
case IMX8QM_UART1_CLK:
case IMX8QM_UART1_IPG_CLK:
resource = SC_R_UART_1;
pm_clk = SC_PM_CLK_PER;
break;
case IMX8QM_UART2_CLK:
case IMX8QM_UART2_IPG_CLK:
resource = SC_R_UART_2;
pm_clk = SC_PM_CLK_PER;
break;
case IMX8QM_UART3_CLK:
case IMX8QM_UART3_IPG_CLK:
resource = SC_R_UART_3;
pm_clk = SC_PM_CLK_PER;
break;
case IMX8QM_SDHC0_IPG_CLK:
case IMX8QM_SDHC0_CLK:
case IMX8QM_SDHC0_DIV:
resource = SC_R_SDHC_0;
pm_clk = SC_PM_CLK_PER;
break;
case IMX8QM_SDHC1_IPG_CLK:
case IMX8QM_SDHC1_CLK:
case IMX8QM_SDHC1_DIV:
resource = SC_R_SDHC_1;
pm_clk = SC_PM_CLK_PER;
break;
case IMX8QM_SDHC2_IPG_CLK:
case IMX8QM_SDHC2_CLK:
case IMX8QM_SDHC2_DIV:
resource = SC_R_SDHC_2;
pm_clk = SC_PM_CLK_PER;
break;
case IMX8QM_ENET0_IPG_CLK:
case IMX8QM_ENET0_AHB_CLK:
case IMX8QM_ENET0_REF_DIV:
case IMX8QM_ENET0_PTP_CLK:
case IMX8QM_ENET0_ROOT_DIV:
resource = SC_R_ENET_0;
pm_clk = SC_PM_CLK_PER;
break;
case IMX8QM_ENET1_IPG_CLK:
case IMX8QM_ENET1_AHB_CLK:
case IMX8QM_ENET1_REF_DIV:
case IMX8QM_ENET1_PTP_CLK:
case IMX8QM_ENET1_ROOT_DIV:
resource = SC_R_ENET_1;
pm_clk = SC_PM_CLK_PER;
break;
default:
if (clk->id < IMX8QM_UART0_IPG_CLK ||
clk->id >= IMX8QM_CLK_END) {
printf("%s(Invalid clk ID #%lu)\n",
__func__, clk->id);
return -EINVAL;
}
return -EINVAL;
};
ret = sc_pm_set_clock_rate(-1, resource, pm_clk, &new_rate);
if (ret) {
printf("%s err %d\n", __func__, ret);
return ret;
}
return new_rate;
}
int __imx8_clk_enable(struct clk *clk, bool enable)
{
sc_pm_clk_t pm_clk;
u16 resource;
int ret;
debug("%s(#%lu)\n", __func__, clk->id);
switch (clk->id) {
case IMX8QM_I2C0_IPG_CLK:
case IMX8QM_I2C0_CLK:
case IMX8QM_I2C0_DIV:
resource = SC_R_I2C_0;
pm_clk = SC_PM_CLK_PER;
break;
case IMX8QM_I2C1_IPG_CLK:
case IMX8QM_I2C1_CLK:
case IMX8QM_I2C1_DIV:
resource = SC_R_I2C_1;
pm_clk = SC_PM_CLK_PER;
break;
case IMX8QM_I2C2_IPG_CLK:
case IMX8QM_I2C2_CLK:
case IMX8QM_I2C2_DIV:
resource = SC_R_I2C_2;
pm_clk = SC_PM_CLK_PER;
break;
case IMX8QM_I2C3_IPG_CLK:
case IMX8QM_I2C3_CLK:
case IMX8QM_I2C3_DIV:
resource = SC_R_I2C_3;
pm_clk = SC_PM_CLK_PER;
break;
case IMX8QM_UART0_CLK:
case IMX8QM_UART0_IPG_CLK:
resource = SC_R_UART_0;
pm_clk = SC_PM_CLK_PER;
break;
case IMX8QM_UART1_CLK:
case IMX8QM_UART1_IPG_CLK:
resource = SC_R_UART_1;
pm_clk = SC_PM_CLK_PER;
break;
case IMX8QM_UART2_CLK:
case IMX8QM_UART2_IPG_CLK:
resource = SC_R_UART_2;
pm_clk = SC_PM_CLK_PER;
break;
case IMX8QM_UART3_CLK:
case IMX8QM_UART3_IPG_CLK:
resource = SC_R_UART_3;
pm_clk = SC_PM_CLK_PER;
break;
case IMX8QM_SDHC0_IPG_CLK:
case IMX8QM_SDHC0_CLK:
case IMX8QM_SDHC0_DIV:
resource = SC_R_SDHC_0;
pm_clk = SC_PM_CLK_PER;
break;
case IMX8QM_SDHC1_IPG_CLK:
case IMX8QM_SDHC1_CLK:
case IMX8QM_SDHC1_DIV:
resource = SC_R_SDHC_1;
pm_clk = SC_PM_CLK_PER;
break;
case IMX8QM_SDHC2_IPG_CLK:
case IMX8QM_SDHC2_CLK:
case IMX8QM_SDHC2_DIV:
resource = SC_R_SDHC_2;
pm_clk = SC_PM_CLK_PER;
break;
case IMX8QM_ENET0_IPG_CLK:
case IMX8QM_ENET0_AHB_CLK:
case IMX8QM_ENET0_REF_DIV:
case IMX8QM_ENET0_PTP_CLK:
resource = SC_R_ENET_0;
pm_clk = SC_PM_CLK_PER;
break;
case IMX8QM_ENET1_IPG_CLK:
case IMX8QM_ENET1_AHB_CLK:
case IMX8QM_ENET1_REF_DIV:
case IMX8QM_ENET1_PTP_CLK:
resource = SC_R_ENET_1;
pm_clk = SC_PM_CLK_PER;
break;
default:
if (clk->id < IMX8QM_UART0_IPG_CLK ||
clk->id >= IMX8QM_CLK_END) {
printf("%s(Invalid clk ID #%lu)\n",
__func__, clk->id);
return -EINVAL;
}
return -EINVAL;
}
ret = sc_pm_clock_enable(-1, resource, pm_clk, enable, 0);
if (ret) {
printf("%s err %d\n", __func__, ret);
return ret;
}
return 0;
}