mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-11 23:47:24 +00:00
222 lines
5.8 KiB
C
222 lines
5.8 KiB
C
|
// SPDX-License-Identifier: GPL-2.0+
|
||
|
/*
|
||
|
* Copyright (C) 2022
|
||
|
* Author(s): Jesse Taube <Mr.Bossman075@gmail.com>
|
||
|
*/
|
||
|
|
||
|
#include <common.h>
|
||
|
#include <clk.h>
|
||
|
#include <clk-uclass.h>
|
||
|
#include <dm.h>
|
||
|
#include <log.h>
|
||
|
#include <asm/arch/clock.h>
|
||
|
#include <asm/arch/imx-regs.h>
|
||
|
#include <dt-bindings/clock/imxrt1170-clock.h>
|
||
|
|
||
|
#include "clk.h"
|
||
|
|
||
|
static ulong imxrt1170_clk_get_rate(struct clk *clk)
|
||
|
{
|
||
|
struct clk *c;
|
||
|
int ret;
|
||
|
|
||
|
debug("%s(#%lu)\n", __func__, clk->id);
|
||
|
|
||
|
ret = clk_get_by_id(clk->id, &c);
|
||
|
if (ret)
|
||
|
return ret;
|
||
|
|
||
|
return clk_get_rate(c);
|
||
|
}
|
||
|
|
||
|
static ulong imxrt1170_clk_set_rate(struct clk *clk, ulong rate)
|
||
|
{
|
||
|
struct clk *c;
|
||
|
int ret;
|
||
|
|
||
|
debug("%s(#%lu), rate: %lu\n", __func__, clk->id, rate);
|
||
|
|
||
|
ret = clk_get_by_id(clk->id, &c);
|
||
|
if (ret)
|
||
|
return ret;
|
||
|
|
||
|
return clk_set_rate(c, rate);
|
||
|
}
|
||
|
|
||
|
static int __imxrt1170_clk_enable(struct clk *clk, bool enable)
|
||
|
{
|
||
|
struct clk *c;
|
||
|
int ret;
|
||
|
|
||
|
debug("%s(#%lu) en: %d\n", __func__, clk->id, enable);
|
||
|
|
||
|
ret = clk_get_by_id(clk->id, &c);
|
||
|
if (ret)
|
||
|
return ret;
|
||
|
|
||
|
if (enable)
|
||
|
ret = clk_enable(c);
|
||
|
else
|
||
|
ret = clk_disable(c);
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
static int imxrt1170_clk_disable(struct clk *clk)
|
||
|
{
|
||
|
return __imxrt1170_clk_enable(clk, 0);
|
||
|
}
|
||
|
|
||
|
static int imxrt1170_clk_enable(struct clk *clk)
|
||
|
{
|
||
|
return __imxrt1170_clk_enable(clk, 1);
|
||
|
}
|
||
|
|
||
|
static int imxrt1170_clk_set_parent(struct clk *clk, struct clk *parent)
|
||
|
{
|
||
|
struct clk *c, *cp;
|
||
|
int ret;
|
||
|
|
||
|
debug("%s(#%lu), parent: %lu\n", __func__, clk->id, parent->id);
|
||
|
|
||
|
ret = clk_get_by_id(clk->id, &c);
|
||
|
if (ret)
|
||
|
return ret;
|
||
|
|
||
|
ret = clk_get_by_id(parent->id, &cp);
|
||
|
if (ret)
|
||
|
return ret;
|
||
|
|
||
|
return clk_set_parent(c, cp);
|
||
|
}
|
||
|
|
||
|
static struct clk_ops imxrt1170_clk_ops = {
|
||
|
.set_rate = imxrt1170_clk_set_rate,
|
||
|
.get_rate = imxrt1170_clk_get_rate,
|
||
|
.enable = imxrt1170_clk_enable,
|
||
|
.disable = imxrt1170_clk_disable,
|
||
|
.set_parent = imxrt1170_clk_set_parent,
|
||
|
};
|
||
|
|
||
|
static const char * const lpuart1_sels[] = {"rcosc48M_div2", "osc", "rcosc400M", "rcosc16M",
|
||
|
"pll3_div2", "pll1_div5", "pll2_sys", "pll2_pfd3"};
|
||
|
static const char * const gpt1_sels[] = {"rcosc48M_div2", "osc", "rcosc400M", "rcosc16M",
|
||
|
"pll3_div2", "pll1_div5", "pll3_pfd2", "pll3_pfd3"};
|
||
|
static const char * const usdhc1_sels[] = {"rcosc48M_div2", "osc", "rcosc400M", "rcosc16M",
|
||
|
"pll2_pfd2", "pll2_pfd0", "pll1_div5", "pll_arm"};
|
||
|
static const char * const semc_sels[] = {"rcosc48M_div2", "osc", "rcosc400M", "rcosc16M",
|
||
|
"pll1_div5", "pll2_sys", "pll2_pfd2", "pll3_pfd0"};
|
||
|
|
||
|
static int imxrt1170_clk_probe(struct udevice *dev)
|
||
|
{
|
||
|
void *base;
|
||
|
|
||
|
/* Anatop clocks */
|
||
|
base = (void *)ofnode_get_addr(ofnode_by_compatible(ofnode_null(), "fsl,imxrt-anatop"));
|
||
|
|
||
|
|
||
|
|
||
|
clk_dm(IMXRT1170_CLK_RCOSC_48M,
|
||
|
imx_clk_fixed_factor("rcosc48M", "rcosc16M", 3, 1));
|
||
|
clk_dm(IMXRT1170_CLK_RCOSC_400M,
|
||
|
imx_clk_fixed_factor("rcosc400M", "rcosc16M", 25, 1));
|
||
|
clk_dm(IMXRT1170_CLK_RCOSC_48M_DIV2,
|
||
|
imx_clk_fixed_factor("rcosc48M_div2", "rcosc48M", 1, 2));
|
||
|
|
||
|
|
||
|
clk_dm(IMXRT1170_CLK_PLL_ARM,
|
||
|
imx_clk_pllv3(IMX_PLLV3_SYS, "pll_arm", "osc",
|
||
|
base + 0x200, 0xff));
|
||
|
clk_dm(IMXRT1170_CLK_PLL3,
|
||
|
imx_clk_pllv3(IMX_PLLV3_GENERICV2, "pll3_sys", "osc",
|
||
|
base + 0x210, 1));
|
||
|
clk_dm(IMXRT1170_CLK_PLL2,
|
||
|
imx_clk_pllv3(IMX_PLLV3_GENERICV2, "pll2_sys", "osc",
|
||
|
base + 0x240, 1));
|
||
|
|
||
|
clk_dm(IMXRT1170_CLK_PLL3_PFD0,
|
||
|
imx_clk_pfd("pll3_pfd0", "pll3_sys", base + 0x230, 0));
|
||
|
clk_dm(IMXRT1170_CLK_PLL3_PFD1,
|
||
|
imx_clk_pfd("pll3_pfd1", "pll3_sys", base + 0x230, 1));
|
||
|
clk_dm(IMXRT1170_CLK_PLL3_PFD2,
|
||
|
imx_clk_pfd("pll3_pfd2", "pll3_sys", base + 0x230, 2));
|
||
|
clk_dm(IMXRT1170_CLK_PLL3_PFD3,
|
||
|
imx_clk_pfd("pll3_pfd3", "pll3_sys", base + 0x230, 3));
|
||
|
|
||
|
clk_dm(IMXRT1170_CLK_PLL2_PFD0,
|
||
|
imx_clk_pfd("pll2_pfd0", "pll2_sys", base + 0x270, 0));
|
||
|
clk_dm(IMXRT1170_CLK_PLL2_PFD1,
|
||
|
imx_clk_pfd("pll2_pfd1", "pll2_sys", base + 0x270, 1));
|
||
|
clk_dm(IMXRT1170_CLK_PLL2_PFD2,
|
||
|
imx_clk_pfd("pll2_pfd2", "pll2_sys", base + 0x270, 2));
|
||
|
clk_dm(IMXRT1170_CLK_PLL2_PFD3,
|
||
|
imx_clk_pfd("pll2_pfd3", "pll2_sys", base + 0x270, 3));
|
||
|
|
||
|
clk_dm(IMXRT1170_CLK_PLL3_DIV2,
|
||
|
imx_clk_fixed_factor("pll3_div2", "pll3_sys", 1, 2));
|
||
|
|
||
|
/* CCM clocks */
|
||
|
base = dev_read_addr_ptr(dev);
|
||
|
if (base == (void *)FDT_ADDR_T_NONE)
|
||
|
return -EINVAL;
|
||
|
|
||
|
clk_dm(IMXRT1170_CLK_LPUART1_SEL,
|
||
|
imx_clk_mux("lpuart1_sel", base + (25 * 0x80), 8, 3,
|
||
|
lpuart1_sels, ARRAY_SIZE(lpuart1_sels)));
|
||
|
clk_dm(IMXRT1170_CLK_LPUART1,
|
||
|
imx_clk_divider("lpuart1", "lpuart1_sel",
|
||
|
base + (25 * 0x80), 0, 8));
|
||
|
|
||
|
clk_dm(IMXRT1170_CLK_USDHC1_SEL,
|
||
|
imx_clk_mux("usdhc1_sel", base + (58 * 0x80), 8, 3,
|
||
|
usdhc1_sels, ARRAY_SIZE(usdhc1_sels)));
|
||
|
clk_dm(IMXRT1170_CLK_USDHC1,
|
||
|
imx_clk_divider("usdhc1", "usdhc1_sel",
|
||
|
base + (58 * 0x80), 0, 8));
|
||
|
|
||
|
clk_dm(IMXRT1170_CLK_GPT1_SEL,
|
||
|
imx_clk_mux("gpt1_sel", base + (14 * 0x80), 8, 3,
|
||
|
gpt1_sels, ARRAY_SIZE(gpt1_sels)));
|
||
|
clk_dm(IMXRT1170_CLK_GPT1,
|
||
|
imx_clk_divider("gpt1", "gpt1_sel",
|
||
|
base + (14 * 0x80), 0, 8));
|
||
|
|
||
|
clk_dm(IMXRT1170_CLK_SEMC_SEL,
|
||
|
imx_clk_mux("semc_sel", base + (4 * 0x80), 8, 3,
|
||
|
semc_sels, ARRAY_SIZE(semc_sels)));
|
||
|
clk_dm(IMXRT1170_CLK_SEMC,
|
||
|
imx_clk_divider("semc", "semc_sel",
|
||
|
base + (4 * 0x80), 0, 8));
|
||
|
struct clk *clk, *clk1;
|
||
|
|
||
|
clk_get_by_id(IMXRT1170_CLK_PLL2_PFD2, &clk);
|
||
|
|
||
|
clk_get_by_id(IMXRT1170_CLK_SEMC_SEL, &clk1);
|
||
|
clk_enable(clk1);
|
||
|
clk_set_parent(clk1, clk);
|
||
|
|
||
|
clk_get_by_id(IMXRT1170_CLK_SEMC, &clk);
|
||
|
clk_enable(clk);
|
||
|
clk_set_rate(clk, 132000000UL);
|
||
|
|
||
|
clk_get_by_id(IMXRT1170_CLK_GPT1, &clk);
|
||
|
clk_enable(clk);
|
||
|
clk_set_rate(clk, 32000000UL);
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static const struct udevice_id imxrt1170_clk_ids[] = {
|
||
|
{ .compatible = "fsl,imxrt1170-ccm" },
|
||
|
{ },
|
||
|
};
|
||
|
|
||
|
U_BOOT_DRIVER(imxrt1170_clk) = {
|
||
|
.name = "clk_imxrt1170",
|
||
|
.id = UCLASS_CLK,
|
||
|
.of_match = imxrt1170_clk_ids,
|
||
|
.ops = &imxrt1170_clk_ops,
|
||
|
.probe = imxrt1170_clk_probe,
|
||
|
.flags = DM_FLAG_PRE_RELOC,
|
||
|
};
|