Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  clk-imx8ulp.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0+
/*
 * Copyright 2021 NXP
 */


#include <dt-bindings/clock/imx8ulp-clock.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/reset-controller.h>
#include <linux/slab.h>

#include "clk.h"

static const char * const pll_pre_sels[] = { "sosc""frosc", };
static const char * const a35_sels[] = { "frosc""spll2""sosc""lvds", };
static const char * const nic_sels[] = { "frosc""spll3_pfd0""sosc""lvds", };
static const char * const pcc3_periph_bus_sels[] = { "dummy""lposc""sosc_div2",
           "frosc_div2""xbar_divbus""spll3_pfd1_div1",
           "spll3_pfd0_div2""spll3_pfd0_div1", };
static const char * const pcc4_periph_bus_sels[] = { "dummy""dummy""lposc",
           "sosc_div2""frosc_div2""xbar_divbus",
           "spll3_vcodiv""spll3_pfd0_div1", };
static const char * const pcc4_periph_plat_sels[] = { "dummy""sosc_div1""frosc_div1",
            "spll3_pfd3_div2""spll3_pfd3_div1",
            "spll3_pfd2_div2""spll3_pfd2_div1",
            "spll3_pfd1_div2", };
static const char * const pcc5_periph_bus_sels[] = { "dummy""dummy""lposc",
           "sosc_div2""frosc_div2""lpav_bus_clk",
           "pll4_vcodiv""pll4_pfd3_div1", };
static const char * const pcc5_periph_plat_sels[] = { "dummy""pll4_pfd3_div2""pll4_pfd2_div2",
            "pll4_pfd2_div1""pll4_pfd1_div2",
            "pll4_pfd1_div1""pll4_pfd0_div2",
            "pll4_pfd0_div1", };
static const char * const hifi_sels[] = { "frosc""pll4""pll4_pfd0""sosc",
      "lvds""dummy""dummy""dummy", };
static const char * const ddr_sels[] = { "frosc""pll4_pfd1""sosc""lvds",
      "pll4""pll4""pll4""pll4", };
static const char * const lpav_sels[] = { "frosc""pll4_pfd1""sosc""lvds", };
static const char * const sai45_sels[] = { "spll3_pfd1_div1""aud_clk1""aud_clk2""sosc", };
static const char * const sai67_sels[] = { "spll1_pfd2_div""spll3_pfd1_div1""aud_clk0""aud_clk1""aud_clk2""sosc""dummy""dummy", };
static const char * const aud_clk1_sels[] = { "ext_aud_mclk2""sai4_rx_bclk""sai4_tx_bclk""sai5_rx_bclk""sai5_tx_bclk""dummy""dummy""dummy", };
static const char * const aud_clk2_sels[] = { "ext_aud_mclk3""sai6_rx_bclk""sai6_tx_bclk""sai7_rx_bclk""sai7_tx_bclk""spdif_rx""dummy""dummy", };
static const char * const enet_ts_sels[] = { "ext_rmii_clk""ext_ts_clk""rosc""ext_aud_mclk""sosc""dummy""dummy""dummy"};
static const char * const xbar_divbus[] = { "xbar_divbus" };
static const char * const nic_per_divplat[] = { "nic_per_divplat" };
static const char * const lpav_axi_div[] = { "lpav_axi_div" };
static const char * const lpav_bus_div[] = { "lpav_bus_div" };

struct pcc_reset_dev {
 void __iomem *base;
 struct reset_controller_dev rcdev;
 const u32 *resets;
 /* Set to imx_ccm_lock to protect register access shared with clock control */
 spinlock_t *lock;
};

#define PCC_SW_RST BIT(28)
#define to_pcc_reset_dev(_rcdev) container_of(_rcdev, struct pcc_reset_dev, rcdev)

static const u32 pcc3_resets[] = {
 0xa8, 0xac, 0xc8, 0xcc, 0xd0,
 0xd4, 0xd8, 0xdc, 0xe0, 0xe4,
 0xe8, 0xec, 0xf0
};

static const u32 pcc4_resets[] = {
 0x4, 0x8, 0xc, 0x10, 0x14,
 0x18, 0x1c, 0x20, 0x24, 0x34,
 0x38, 0x3c, 0x40, 0x44, 0x48,
 0x4c, 0x54
};

static const u32 pcc5_resets[] = {
 0xa0, 0xa4, 0xa8, 0xac, 0xb0,
 0xb4, 0xbc, 0xc0, 0xc8, 0xcc,
 0xd0, 0xf0, 0xf4, 0xf8
};

static int imx8ulp_pcc_assert(struct reset_controller_dev *rcdev, unsigned long id)
{
 struct pcc_reset_dev *pcc_reset = to_pcc_reset_dev(rcdev);
 u32 offset = pcc_reset->resets[id];
 unsigned long flags;
 u32 val;

 spin_lock_irqsave(pcc_reset->lock, flags);

 val = readl(pcc_reset->base + offset);
 val &= ~PCC_SW_RST;
 writel(val, pcc_reset->base + offset);

 spin_unlock_irqrestore(pcc_reset->lock, flags);

 return 0;
}

static int imx8ulp_pcc_deassert(struct reset_controller_dev *rcdev, unsigned long id)
{
 struct pcc_reset_dev *pcc_reset = to_pcc_reset_dev(rcdev);
 u32 offset = pcc_reset->resets[id];
 unsigned long flags;
 u32 val;

 spin_lock_irqsave(pcc_reset->lock, flags);

 val = readl(pcc_reset->base + offset);
 val |= PCC_SW_RST;
 writel(val, pcc_reset->base + offset);

 spin_unlock_irqrestore(pcc_reset->lock, flags);

 return 0;
}

static const struct reset_control_ops imx8ulp_pcc_reset_ops = {
 .assert = imx8ulp_pcc_assert,
 .deassert = imx8ulp_pcc_deassert,
};

static int imx8ulp_pcc_reset_init(struct platform_device *pdev, void __iomem *base,
  const u32 *resets, unsigned int nr_resets)
{
 struct device_node *np = pdev->dev.of_node;
 struct device *dev = &pdev->dev;
 struct pcc_reset_dev *pcc_reset;

 pcc_reset = devm_kzalloc(dev, sizeof(*pcc_reset), GFP_KERNEL);
 if (!pcc_reset)
  return -ENOMEM;

 pcc_reset->base = base;
 pcc_reset->lock = &imx_ccm_lock;
 pcc_reset->resets = resets;
 pcc_reset->rcdev.owner = THIS_MODULE;
 pcc_reset->rcdev.nr_resets = nr_resets;
 pcc_reset->rcdev.ops = &imx8ulp_pcc_reset_ops;
 pcc_reset->rcdev.of_node = np;

 return devm_reset_controller_register(dev, &pcc_reset->rcdev);
}

static int imx8ulp_clk_cgc1_init(struct platform_device *pdev)
{
 struct device *dev = &pdev->dev;
 struct clk_hw_onecell_data *clk_data;
 struct clk_hw **clks;
 void __iomem *base;

 clk_data = devm_kzalloc(dev, struct_size(clk_data, hws, IMX8ULP_CLK_CGC1_END),
      GFP_KERNEL);
 if (!clk_data)
  return -ENOMEM;

 clk_data->num = IMX8ULP_CLK_CGC1_END;
 clks = clk_data->hws;

 clks[IMX8ULP_CLK_DUMMY] = imx_clk_hw_fixed("dummy", 0);

 /* CGC1 */
 base = devm_platform_ioremap_resource(pdev, 0);
 if (WARN_ON(IS_ERR(base)))
  return PTR_ERR(base);

 clks[IMX8ULP_CLK_SPLL2_PRE_SEL] = imx_clk_hw_mux_flags("spll2_pre_sel", base + 0x510, 0, 1, pll_pre_sels, ARRAY_SIZE(pll_pre_sels), CLK_SET_PARENT_GATE);
 clks[IMX8ULP_CLK_SPLL3_PRE_SEL] = imx_clk_hw_mux_flags("spll3_pre_sel", base + 0x610, 0, 1, pll_pre_sels, ARRAY_SIZE(pll_pre_sels), CLK_SET_PARENT_GATE);

 clks[IMX8ULP_CLK_SPLL2] = imx_clk_hw_pllv4(IMX_PLLV4_IMX8ULP_1GHZ, "spll2""spll2_pre_sel", base + 0x500);
 clks[IMX8ULP_CLK_SPLL3] = imx_clk_hw_pllv4(IMX_PLLV4_IMX8ULP, "spll3""spll3_pre_sel", base + 0x600);
 clks[IMX8ULP_CLK_SPLL3_VCODIV] = imx_clk_hw_divider("spll3_vcodiv""spll3", base + 0x604, 0, 6);

 clks[IMX8ULP_CLK_SPLL3_PFD0] = imx_clk_hw_pfdv2(IMX_PFDV2_IMX8ULP, "spll3_pfd0""spll3_vcodiv", base + 0x614, 0);
 clks[IMX8ULP_CLK_SPLL3_PFD1] = imx_clk_hw_pfdv2(IMX_PFDV2_IMX8ULP, "spll3_pfd1""spll3_vcodiv", base + 0x614, 1);
 clks[IMX8ULP_CLK_SPLL3_PFD2] = imx_clk_hw_pfdv2(IMX_PFDV2_IMX8ULP, "spll3_pfd2""spll3_vcodiv", base + 0x614, 2);
 clks[IMX8ULP_CLK_SPLL3_PFD3] = imx_clk_hw_pfdv2(IMX_PFDV2_IMX8ULP, "spll3_pfd3""spll3_vcodiv", base + 0x614, 3);

 clks[IMX8ULP_CLK_SPLL3_PFD0_DIV1_GATE] = imx_clk_hw_gate_dis("spll3_pfd0_div1_gate""spll3_pfd0", base + 0x608, 7);
 clks[IMX8ULP_CLK_SPLL3_PFD0_DIV2_GATE] = imx_clk_hw_gate_dis("spll3_pfd0_div2_gate""spll3_pfd0", base + 0x608, 15);
 clks[IMX8ULP_CLK_SPLL3_PFD1_DIV1_GATE] = imx_clk_hw_gate_dis("spll3_pfd1_div1_gate""spll3_pfd1", base + 0x608, 23);
 clks[IMX8ULP_CLK_SPLL3_PFD1_DIV2_GATE] = imx_clk_hw_gate_dis("spll3_pfd1_div2_gate""spll3_pfd1", base + 0x608, 31);
 clks[IMX8ULP_CLK_SPLL3_PFD2_DIV1_GATE] = imx_clk_hw_gate_dis("spll3_pfd2_div1_gate""spll3_pfd2", base + 0x60c, 7);
 clks[IMX8ULP_CLK_SPLL3_PFD2_DIV2_GATE] = imx_clk_hw_gate_dis("spll3_pfd2_div2_gate""spll3_pfd2", base + 0x60c, 15);
 clks[IMX8ULP_CLK_SPLL3_PFD3_DIV1_GATE] = imx_clk_hw_gate_dis("spll3_pfd3_div1_gate""spll3_pfd3", base + 0x60c, 23);
 clks[IMX8ULP_CLK_SPLL3_PFD3_DIV2_GATE] = imx_clk_hw_gate_dis("spll3_pfd3_div2_gate""spll3_pfd3", base + 0x60c, 31);
 clks[IMX8ULP_CLK_SPLL3_PFD0_DIV1] = imx_clk_hw_divider("spll3_pfd0_div1""spll3_pfd0_div1_gate", base + 0x608, 0, 6);
 clks[IMX8ULP_CLK_SPLL3_PFD0_DIV2] = imx_clk_hw_divider("spll3_pfd0_div2""spll3_pfd0_div2_gate", base + 0x608, 8, 6);
 clks[IMX8ULP_CLK_SPLL3_PFD1_DIV1] = imx_clk_hw_divider("spll3_pfd1_div1""spll3_pfd1_div1_gate", base + 0x608, 16, 6);
 clks[IMX8ULP_CLK_SPLL3_PFD1_DIV2] = imx_clk_hw_divider("spll3_pfd1_div2""spll3_pfd1_div2_gate", base + 0x608, 24, 6);
 clks[IMX8ULP_CLK_SPLL3_PFD2_DIV1] = imx_clk_hw_divider("spll3_pfd2_div1""spll3_pfd2_div1_gate", base + 0x60c, 0, 6);
 clks[IMX8ULP_CLK_SPLL3_PFD2_DIV2] = imx_clk_hw_divider("spll3_pfd2_div2""spll3_pfd2_div2_gate", base + 0x60c, 8, 6);
 clks[IMX8ULP_CLK_SPLL3_PFD3_DIV1] = imx_clk_hw_divider("spll3_pfd3_div1""spll3_pfd3_div1_gate", base + 0x60c, 16, 6);
 clks[IMX8ULP_CLK_SPLL3_PFD3_DIV2] = imx_clk_hw_divider("spll3_pfd3_div2""spll3_pfd3_div2_gate", base + 0x60c, 24, 6);

 clks[IMX8ULP_CLK_A35_SEL] = imx_clk_hw_mux2("a35_sel", base + 0x14, 28, 2, a35_sels, ARRAY_SIZE(a35_sels));
 clks[IMX8ULP_CLK_A35_DIV] = imx_clk_hw_divider_flags("a35_div""a35_sel", base + 0x14, 21, 6, CLK_SET_RATE_PARENT | CLK_IS_CRITICAL);

 clks[IMX8ULP_CLK_NIC_SEL] = imx_clk_hw_mux2("nic_sel", base + 0x34, 28, 2, nic_sels, ARRAY_SIZE(nic_sels));
 clks[IMX8ULP_CLK_NIC_AD_DIVPLAT] = imx_clk_hw_divider_flags("nic_ad_divplat""nic_sel", base + 0x34, 21, 6, CLK_SET_RATE_PARENT | CLK_IS_CRITICAL);
 clks[IMX8ULP_CLK_NIC_PER_DIVPLAT] = imx_clk_hw_divider_flags("nic_per_divplat""nic_ad_divplat", base + 0x34, 14, 6, CLK_SET_RATE_PARENT);
 clks[IMX8ULP_CLK_XBAR_AD_DIVPLAT] = imx_clk_hw_divider_flags("xbar_ad_divplat""nic_ad_divplat", base + 0x38, 14, 6, CLK_SET_RATE_PARENT);
 clks[IMX8ULP_CLK_XBAR_DIVBUS] = imx_clk_hw_divider_flags("xbar_divbus""xbar_ad_divplat", base + 0x38, 7, 6, CLK_SET_RATE_PARENT);
 clks[IMX8ULP_CLK_XBAR_AD_SLOW] = imx_clk_hw_divider_flags("xbar_ad_slow""xbar_divbus", base + 0x38, 0, 6, CLK_SET_RATE_PARENT);

 clks[IMX8ULP_CLK_SOSC_DIV1_GATE] = imx_clk_hw_gate_dis("sosc_div1_gate""sosc", base + 0x108, 7);
 clks[IMX8ULP_CLK_SOSC_DIV2_GATE] = imx_clk_hw_gate_dis("sosc_div2_gate""sosc", base + 0x108, 15);
 clks[IMX8ULP_CLK_SOSC_DIV3_GATE] = imx_clk_hw_gate_dis("sosc_div3_gate""sosc", base + 0x108, 23);
 clks[IMX8ULP_CLK_SOSC_DIV1] = imx_clk_hw_divider("sosc_div1""sosc_div1_gate", base + 0x108, 0, 6);
 clks[IMX8ULP_CLK_SOSC_DIV2] = imx_clk_hw_divider("sosc_div2""sosc_div2_gate", base + 0x108, 8, 6);
 clks[IMX8ULP_CLK_SOSC_DIV3] = imx_clk_hw_divider("sosc_div3""sosc_div3_gate", base + 0x108, 16, 6);

 clks[IMX8ULP_CLK_FROSC_DIV1_GATE] = imx_clk_hw_gate_dis("frosc_div1_gate""frosc"base + 0x208, 7);
 clks[IMX8ULP_CLK_FROSC_DIV2_GATE] = imx_clk_hw_gate_dis("frosc_div2_gate""frosc"base + 0x208, 15);
 clks[IMX8ULP_CLK_FROSC_DIV3_GATE] = imx_clk_hw_gate_dis("frosc_div3_gate""frosc"base + 0x208, 23);
 clks[IMX8ULP_CLK_FROSC_DIV1] = imx_clk_hw_divider("frosc_div1""frosc_div1_gate", base + 0x208, 0, 6);
 clks[IMX8ULP_CLK_FROSC_DIV2] = imx_clk_hw_divider("frosc_div2""frosc_div2_gate", base + 0x208, 8, 6);
 clks[IMX8ULP_CLK_FROSC_DIV3] = imx_clk_hw_divider("frosc_div3""frosc_div3_gate", base + 0x208, 16, 6);
 clks[IMX8ULP_CLK_AUD_CLK1] = imx_clk_hw_mux2("aud_clk1", base + 0x900, 0, 3, aud_clk1_sels, ARRAY_SIZE(aud_clk1_sels));
 clks[IMX8ULP_CLK_SAI4_SEL] = imx_clk_hw_mux2("sai4_sel", base + 0x904, 0, 2, sai45_sels, ARRAY_SIZE(sai45_sels));
 clks[IMX8ULP_CLK_SAI5_SEL] = imx_clk_hw_mux2("sai5_sel", base + 0x904, 8, 2, sai45_sels, ARRAY_SIZE(sai45_sels));
 clks[IMX8ULP_CLK_ENET_TS_SEL] = imx_clk_hw_mux2("enet_ts", base + 0x700, 24, 3, enet_ts_sels, ARRAY_SIZE(enet_ts_sels));

 imx_check_clk_hws(clks, clk_data->num);

 return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, clk_data);
}

static int imx8ulp_clk_cgc2_init(struct platform_device *pdev)
{
 struct device *dev = &pdev->dev;
 struct clk_hw_onecell_data *clk_data;
 struct clk_hw **clks;
 void __iomem *base;

 clk_data = devm_kzalloc(dev, struct_size(clk_data, hws, IMX8ULP_CLK_CGC2_END),
      GFP_KERNEL);
 if (!clk_data)
  return -ENOMEM;

 clk_data->num = IMX8ULP_CLK_CGC2_END;
 clks = clk_data->hws;

 /* CGC2 */
 base = devm_platform_ioremap_resource(pdev, 0);
 if (WARN_ON(IS_ERR(base)))
  return PTR_ERR(base);

 clks[IMX8ULP_CLK_PLL4_PRE_SEL] = imx_clk_hw_mux_flags("pll4_pre_sel", base + 0x610, 0, 1, pll_pre_sels, ARRAY_SIZE(pll_pre_sels), CLK_SET_PARENT_GATE);

 clks[IMX8ULP_CLK_PLL4] = imx_clk_hw_pllv4(IMX_PLLV4_IMX8ULP, "pll4""pll4_pre_sel"base + 0x600);
 clks[IMX8ULP_CLK_PLL4_VCODIV] = imx_clk_hw_divider("pll4_vcodiv""pll4", base + 0x604, 0, 6);

 clks[IMX8ULP_CLK_HIFI_SEL] = imx_clk_hw_mux_flags("hifi_sel", base + 0x14, 28, 3, hifi_sels, ARRAY_SIZE(hifi_sels), CLK_SET_PARENT_GATE);
 clks[IMX8ULP_CLK_HIFI_DIVCORE] = imx_clk_hw_divider("hifi_core_div""hifi_sel", base + 0x14, 21, 6);
 clks[IMX8ULP_CLK_HIFI_DIVPLAT] = imx_clk_hw_divider("hifi_plat_div""hifi_core_div", base + 0x14, 14, 6);

 clks[IMX8ULP_CLK_DDR_SEL] = imx_clk_hw_mux_flags("ddr_sel", base + 0x40, 28, 3, ddr_sels, ARRAY_SIZE(ddr_sels), CLK_GET_RATE_NOCACHE);
 clks[IMX8ULP_CLK_DDR_DIV] = imx_clk_hw_divider_flags("ddr_div""ddr_sel", base + 0x40, 21, 6, CLK_IS_CRITICAL | CLK_GET_RATE_NOCACHE);
 clks[IMX8ULP_CLK_LPAV_AXI_SEL] = imx_clk_hw_mux2("lpav_sel", base + 0x3c, 28, 2, lpav_sels, ARRAY_SIZE(lpav_sels));
 clks[IMX8ULP_CLK_LPAV_AXI_DIV] = imx_clk_hw_divider_flags("lpav_axi_div""lpav_sel", base + 0x3c, 21, 6, CLK_IS_CRITICAL);
 clks[IMX8ULP_CLK_LPAV_AHB_DIV] = imx_clk_hw_divider_flags("lpav_ahb_div""lpav_axi_div", base + 0x3c, 14, 6, CLK_IS_CRITICAL);
 clks[IMX8ULP_CLK_LPAV_BUS_DIV] = imx_clk_hw_divider_flags("lpav_bus_div""lpav_axi_div", base + 0x3c, 7, 6, CLK_IS_CRITICAL);

 clks[IMX8ULP_CLK_PLL4_PFD0] = imx_clk_hw_pfdv2(IMX_PFDV2_IMX8ULP, "pll4_pfd0""pll4_vcodiv", base + 0x614, 0);
 clks[IMX8ULP_CLK_PLL4_PFD1] = imx_clk_hw_pfdv2(IMX_PFDV2_IMX8ULP, "pll4_pfd1""pll4_vcodiv", base + 0x614, 1);
 clks[IMX8ULP_CLK_PLL4_PFD2] = imx_clk_hw_pfdv2(IMX_PFDV2_IMX8ULP, "pll4_pfd2""pll4_vcodiv", base + 0x614, 2);
 clks[IMX8ULP_CLK_PLL4_PFD3] = imx_clk_hw_pfdv2(IMX_PFDV2_IMX8ULP, "pll4_pfd3""pll4_vcodiv", base + 0x614, 3);

 clks[IMX8ULP_CLK_PLL4_PFD0_DIV1_GATE] = imx_clk_hw_gate_dis("pll4_pfd0_div1_gate""pll4_pfd0", base + 0x608, 7);
 clks[IMX8ULP_CLK_PLL4_PFD0_DIV2_GATE] = imx_clk_hw_gate_dis("pll4_pfd0_div2_gate""pll4_pfd0", base + 0x608, 15);
 clks[IMX8ULP_CLK_PLL4_PFD1_DIV1_GATE] = imx_clk_hw_gate_dis("pll4_pfd1_div1_gate""pll4_pfd1", base + 0x608, 23);
 clks[IMX8ULP_CLK_PLL4_PFD1_DIV2_GATE] = imx_clk_hw_gate_dis("pll4_pfd1_div2_gate""pll4_pfd1", base + 0x608, 31);
 clks[IMX8ULP_CLK_PLL4_PFD2_DIV1_GATE] = imx_clk_hw_gate_dis("pll4_pfd2_div1_gate""pll4_pfd2", base + 0x60c, 7);
 clks[IMX8ULP_CLK_PLL4_PFD2_DIV2_GATE] = imx_clk_hw_gate_dis("pll4_pfd2_div2_gate""pll4_pfd2", base + 0x60c, 15);
 clks[IMX8ULP_CLK_PLL4_PFD3_DIV1_GATE] = imx_clk_hw_gate_dis("pll4_pfd3_div1_gate""pll4_pfd3", base + 0x60c, 23);
 clks[IMX8ULP_CLK_PLL4_PFD3_DIV2_GATE] = imx_clk_hw_gate_dis("pll4_pfd3_div2_gate""pll4_pfd3", base + 0x60c, 31);
 clks[IMX8ULP_CLK_PLL4_PFD0_DIV1] = imx_clk_hw_divider_closest("pll4_pfd0_div1""pll4_pfd0_div1_gate", base + 0x608, 0, 6);
 clks[IMX8ULP_CLK_PLL4_PFD0_DIV2] = imx_clk_hw_divider_closest("pll4_pfd0_div2""pll4_pfd0_div2_gate", base + 0x608, 8, 6);
 clks[IMX8ULP_CLK_PLL4_PFD1_DIV1] = imx_clk_hw_divider_closest("pll4_pfd1_div1""pll4_pfd1_div1_gate", base + 0x608, 16, 6);
 clks[IMX8ULP_CLK_PLL4_PFD1_DIV2] = imx_clk_hw_divider_closest("pll4_pfd1_div2""pll4_pfd1_div2_gate", base + 0x608, 24, 6);
 clks[IMX8ULP_CLK_PLL4_PFD2_DIV1] = imx_clk_hw_divider_closest("pll4_pfd2_div1""pll4_pfd2_div1_gate", base + 0x60c, 0, 6);
 clks[IMX8ULP_CLK_PLL4_PFD2_DIV2] = imx_clk_hw_divider_closest("pll4_pfd2_div2""pll4_pfd2_div2_gate", base + 0x60c, 8, 6);
 clks[IMX8ULP_CLK_PLL4_PFD3_DIV1] = imx_clk_hw_divider_closest("pll4_pfd3_div1""pll4_pfd3_div1_gate", base + 0x60c, 16, 6);
 clks[IMX8ULP_CLK_PLL4_PFD3_DIV2] = imx_clk_hw_divider_closest("pll4_pfd3_div2""pll4_pfd3_div2_gate", base + 0x60c, 24, 6);

 clks[IMX8ULP_CLK_CGC2_SOSC_DIV1_GATE] = imx_clk_hw_gate_dis("cgc2_sosc_div1_gate""sosc", base + 0x108, 7);
 clks[IMX8ULP_CLK_CGC2_SOSC_DIV2_GATE] = imx_clk_hw_gate_dis("cgc2_sosc_div2_gate""sosc", base + 0x108, 15);
 clks[IMX8ULP_CLK_CGC2_SOSC_DIV3_GATE] = imx_clk_hw_gate_dis("cgc2_sosc_div3_gate""sosc", base + 0x108, 23);
 clks[IMX8ULP_CLK_CGC2_SOSC_DIV1] = imx_clk_hw_divider("cgc2_sosc_div1""cgc2_sosc_div1_gate", base + 0x108, 0, 6);
 clks[IMX8ULP_CLK_CGC2_SOSC_DIV2] = imx_clk_hw_divider("cgc2_sosc_div2""cgc2_sosc_div2_gate", base + 0x108, 8, 6);
 clks[IMX8ULP_CLK_CGC2_SOSC_DIV3] = imx_clk_hw_divider("cgc2_sosc_div3""cgc2_sosc_div3_gate", base + 0x108, 16, 6);

 clks[IMX8ULP_CLK_CGC2_FROSC_DIV1_GATE] = imx_clk_hw_gate_dis("cgc2_frosc_div1_gate""frosc", base + 0x208, 7);
 clks[IMX8ULP_CLK_CGC2_FROSC_DIV2_GATE] = imx_clk_hw_gate_dis("cgc2_frosc_div2_gate""frosc", base + 0x208, 15);
 clks[IMX8ULP_CLK_CGC2_FROSC_DIV3_GATE] = imx_clk_hw_gate_dis("cgc2_frosc_div3_gate""frosc", base + 0x208, 23);
 clks[IMX8ULP_CLK_CGC2_FROSC_DIV1] = imx_clk_hw_divider("cgc2_frosc_div1""cgc2_frosc_div1_gate", base + 0x208, 0, 6);
 clks[IMX8ULP_CLK_CGC2_FROSC_DIV2] = imx_clk_hw_divider("cgc2_frosc_div2""cgc2_frosc_div2_gate", base + 0x208, 8, 6);
 clks[IMX8ULP_CLK_CGC2_FROSC_DIV3] = imx_clk_hw_divider("cgc2_frosc_div3""cgc2_frosc_div3_gate", base + 0x208, 16, 6);
 clks[IMX8ULP_CLK_AUD_CLK2]  = imx_clk_hw_mux2("aud_clk2", base + 0x900, 0, 3, aud_clk2_sels, ARRAY_SIZE(aud_clk2_sels));
 clks[IMX8ULP_CLK_SAI6_SEL]  = imx_clk_hw_mux2("sai6_sel", base + 0x904, 0, 3, sai67_sels, ARRAY_SIZE(sai67_sels));
 clks[IMX8ULP_CLK_SAI7_SEL]  = imx_clk_hw_mux2("sai7_sel", base + 0x904, 8, 3, sai67_sels, ARRAY_SIZE(sai67_sels));
 clks[IMX8ULP_CLK_SPDIF_SEL] = imx_clk_hw_mux2("spdif_sel", base + 0x910, 0, 3, sai67_sels, ARRAY_SIZE(sai67_sels));
 clks[IMX8ULP_CLK_DSI_PHY_REF] = imx_clk_hw_fixed("dsi_phy_ref", 24000000);

 imx_check_clk_hws(clks, clk_data->num);

 return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, clk_data);
}

static int imx8ulp_clk_pcc3_init(struct platform_device *pdev)
{
 struct device *dev = &pdev->dev;
 struct clk_hw_onecell_data *clk_data;
 struct clk_hw **clks;
 void __iomem *base;
 int ret;

 clk_data = devm_kzalloc(dev, struct_size(clk_data, hws, IMX8ULP_CLK_PCC3_END),
      GFP_KERNEL);
 if (!clk_data)
  return -ENOMEM;

 clk_data->num = IMX8ULP_CLK_PCC3_END;
 clks = clk_data->hws;

 /* PCC3 */
 base = devm_platform_ioremap_resource(pdev, 0);
 if (WARN_ON(IS_ERR(base)))
  return PTR_ERR(base);

 clks[IMX8ULP_CLK_WDOG3] = imx8ulp_clk_hw_composite("wdog3", pcc3_periph_bus_sels, ARRAY_SIZE(pcc3_periph_bus_sels), truetruetrue, base + 0xa8, 1);
 clks[IMX8ULP_CLK_WDOG4] = imx8ulp_clk_hw_composite("wdog4", pcc3_periph_bus_sels, ARRAY_SIZE(pcc3_periph_bus_sels), truetruetrue, base + 0xac, 1);
 clks[IMX8ULP_CLK_LPIT1] = imx8ulp_clk_hw_composite("lpit1", pcc3_periph_bus_sels, ARRAY_SIZE(pcc3_periph_bus_sels), truetruetrue, base + 0xc8, 1);
 clks[IMX8ULP_CLK_TPM4] = imx8ulp_clk_hw_composite("tpm4", pcc3_periph_bus_sels, ARRAY_SIZE(pcc3_periph_bus_sels), truetruetrue, base + 0xcc, 1);
 clks[IMX8ULP_CLK_FLEXIO1] = imx8ulp_clk_hw_composite("flexio1", pcc3_periph_bus_sels, ARRAY_SIZE(pcc3_periph_bus_sels), truetruetrue, base + 0xd4, 1);
 clks[IMX8ULP_CLK_I3C2] = imx8ulp_clk_hw_composite("i3c2", pcc3_periph_bus_sels, ARRAY_SIZE(pcc3_periph_bus_sels), truetruetrue, base + 0xd8, 1);
 clks[IMX8ULP_CLK_LPI2C4] = imx8ulp_clk_hw_composite("lpi2c4", pcc3_periph_bus_sels, ARRAY_SIZE(pcc3_periph_bus_sels), truetruetrue, base + 0xdc, 1);
 clks[IMX8ULP_CLK_LPI2C5] = imx8ulp_clk_hw_composite("lpi2c5", pcc3_periph_bus_sels, ARRAY_SIZE(pcc3_periph_bus_sels), truetruetrue, base + 0xe0, 1);
 clks[IMX8ULP_CLK_LPUART4] = imx8ulp_clk_hw_composite("lpuart4", pcc3_periph_bus_sels, ARRAY_SIZE(pcc3_periph_bus_sels), truetruetrue, base + 0xe4, 1);
 clks[IMX8ULP_CLK_LPUART5] = imx8ulp_clk_hw_composite("lpuart5", pcc3_periph_bus_sels, ARRAY_SIZE(pcc3_periph_bus_sels), truetruetrue, base + 0xe8, 1);
 clks[IMX8ULP_CLK_LPSPI4] = imx8ulp_clk_hw_composite("lpspi4", pcc3_periph_bus_sels, ARRAY_SIZE(pcc3_periph_bus_sels), truetruetrue, base + 0xec, 1);
 clks[IMX8ULP_CLK_LPSPI5] = imx8ulp_clk_hw_composite("lpspi5", pcc3_periph_bus_sels, ARRAY_SIZE(pcc3_periph_bus_sels), truetruetrue, base + 0xf0, 1);

 clks[IMX8ULP_CLK_DMA1_MP] = imx_clk_hw_gate("pcc_dma1_mp""xbar_ad_divplat", base + 0x4, 30);
 clks[IMX8ULP_CLK_DMA1_CH0] = imx_clk_hw_gate("pcc_dma1_ch0""xbar_ad_divplat", base + 0x8, 30);
 clks[IMX8ULP_CLK_DMA1_CH1] = imx_clk_hw_gate("pcc_dma1_ch1""xbar_ad_divplat", base + 0xc, 30);
 clks[IMX8ULP_CLK_DMA1_CH2] = imx_clk_hw_gate("pcc_dma1_ch2""xbar_ad_divplat", base + 0x10, 30);
 clks[IMX8ULP_CLK_DMA1_CH3] = imx_clk_hw_gate("pcc_dma1_ch3""xbar_ad_divplat", base + 0x14, 30);
 clks[IMX8ULP_CLK_DMA1_CH4] = imx_clk_hw_gate("pcc_dma1_ch4""xbar_ad_divplat", base + 0x18, 30);
 clks[IMX8ULP_CLK_DMA1_CH5] = imx_clk_hw_gate("pcc_dma1_ch5""xbar_ad_divplat", base + 0x1c, 30);
 clks[IMX8ULP_CLK_DMA1_CH6] = imx_clk_hw_gate("pcc_dma1_ch6""xbar_ad_divplat", base + 0x20, 30);
 clks[IMX8ULP_CLK_DMA1_CH7] = imx_clk_hw_gate("pcc_dma1_ch7""xbar_ad_divplat", base + 0x24, 30);
 clks[IMX8ULP_CLK_DMA1_CH8] = imx_clk_hw_gate("pcc_dma1_ch8""xbar_ad_divplat", base + 0x28, 30);
 clks[IMX8ULP_CLK_DMA1_CH9] = imx_clk_hw_gate("pcc_dma1_ch9""xbar_ad_divplat", base + 0x2c, 30);
 clks[IMX8ULP_CLK_DMA1_CH10] = imx_clk_hw_gate("pcc_dma1_ch10""xbar_ad_divplat", base + 0x30, 30);
 clks[IMX8ULP_CLK_DMA1_CH11] = imx_clk_hw_gate("pcc_dma1_ch11""xbar_ad_divplat", base + 0x34, 30);
 clks[IMX8ULP_CLK_DMA1_CH12] = imx_clk_hw_gate("pcc_dma1_ch12""xbar_ad_divplat", base + 0x38, 30);
 clks[IMX8ULP_CLK_DMA1_CH13] = imx_clk_hw_gate("pcc_dma1_ch13""xbar_ad_divplat", base + 0x3c, 30);
 clks[IMX8ULP_CLK_DMA1_CH14] = imx_clk_hw_gate("pcc_dma1_ch14""xbar_ad_divplat", base + 0x40, 30);
 clks[IMX8ULP_CLK_DMA1_CH15] = imx_clk_hw_gate("pcc_dma1_ch15""xbar_ad_divplat", base + 0x44, 30);
 clks[IMX8ULP_CLK_DMA1_CH16] = imx_clk_hw_gate("pcc_dma1_ch16""xbar_ad_divplat", base + 0x48, 30);
 clks[IMX8ULP_CLK_DMA1_CH17] = imx_clk_hw_gate("pcc_dma1_ch17""xbar_ad_divplat", base + 0x4c, 30);
 clks[IMX8ULP_CLK_DMA1_CH18] = imx_clk_hw_gate("pcc_dma1_ch18""xbar_ad_divplat", base + 0x50, 30);
 clks[IMX8ULP_CLK_DMA1_CH19] = imx_clk_hw_gate("pcc_dma1_ch19""xbar_ad_divplat", base + 0x54, 30);
 clks[IMX8ULP_CLK_DMA1_CH20] = imx_clk_hw_gate("pcc_dma1_ch20""xbar_ad_divplat", base + 0x58, 30);
 clks[IMX8ULP_CLK_DMA1_CH21] = imx_clk_hw_gate("pcc_dma1_ch21""xbar_ad_divplat", base + 0x5c, 30);
 clks[IMX8ULP_CLK_DMA1_CH22] = imx_clk_hw_gate("pcc_dma1_ch22""xbar_ad_divplat", base + 0x60, 30);
 clks[IMX8ULP_CLK_DMA1_CH23] = imx_clk_hw_gate("pcc_dma1_ch23""xbar_ad_divplat", base + 0x64, 30);
 clks[IMX8ULP_CLK_DMA1_CH24] = imx_clk_hw_gate("pcc_dma1_ch24""xbar_ad_divplat", base + 0x68, 30);
 clks[IMX8ULP_CLK_DMA1_CH25] = imx_clk_hw_gate("pcc_dma1_ch25""xbar_ad_divplat", base + 0x6c, 30);
 clks[IMX8ULP_CLK_DMA1_CH26] = imx_clk_hw_gate("pcc_dma1_ch26""xbar_ad_divplat", base + 0x70, 30);
 clks[IMX8ULP_CLK_DMA1_CH27] = imx_clk_hw_gate("pcc_dma1_ch27""xbar_ad_divplat", base + 0x74, 30);
 clks[IMX8ULP_CLK_DMA1_CH28] = imx_clk_hw_gate("pcc_dma1_ch28""xbar_ad_divplat", base + 0x78, 30);
 clks[IMX8ULP_CLK_DMA1_CH29] = imx_clk_hw_gate("pcc_dma1_ch29""xbar_ad_divplat", base + 0x7c, 30);
 clks[IMX8ULP_CLK_DMA1_CH30] = imx_clk_hw_gate("pcc_dma1_ch30""xbar_ad_divplat", base + 0x80, 30);
 clks[IMX8ULP_CLK_DMA1_CH31] = imx_clk_hw_gate("pcc_dma1_ch31""xbar_ad_divplat", base + 0x84, 30);
 clks[IMX8ULP_CLK_MU0_B] = imx_clk_hw_gate_flags("mu0_b""xbar_ad_divplat", base + 0x88, 30, CLK_IS_CRITICAL);
 clks[IMX8ULP_CLK_MU3_A] = imx_clk_hw_gate("mu3_a""xbar_ad_divplat", base + 0x8c, 30);
 clks[IMX8ULP_CLK_TPM5] = imx_clk_hw_gate_flags("tpm5""sosc_div2",  base + 0xd0, 30, CLK_IS_CRITICAL);

 imx_check_clk_hws(clks, clk_data->num);

 ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, clk_data);
 if (ret)
  return ret;

 imx_register_uart_clocks();

 /* register the pcc3 reset controller */
 return imx8ulp_pcc_reset_init(pdev, base, pcc3_resets, ARRAY_SIZE(pcc3_resets));
}

static int imx8ulp_clk_pcc4_init(struct platform_device *pdev)
{
 struct device *dev = &pdev->dev;
 struct clk_hw_onecell_data *clk_data;
 struct clk_hw **clks;
 void __iomem *base;
 int ret;

 clk_data = devm_kzalloc(dev, struct_size(clk_data, hws, IMX8ULP_CLK_PCC4_END),
      GFP_KERNEL);
 if (!clk_data)
  return -ENOMEM;

 clk_data->num = IMX8ULP_CLK_PCC4_END;
 clks = clk_data->hws;

 /* PCC4 */
 base = devm_platform_ioremap_resource(pdev, 0);
 if (WARN_ON(IS_ERR(base)))
  return PTR_ERR(base);

 clks[IMX8ULP_CLK_FLEXSPI2] = imx8ulp_clk_hw_composite("flexspi2", pcc4_periph_plat_sels, ARRAY_SIZE(pcc4_periph_plat_sels), truetruetrue, base + 0x4, 1);
 clks[IMX8ULP_CLK_TPM6] = imx8ulp_clk_hw_composite("tpm6", pcc4_periph_bus_sels, ARRAY_SIZE(pcc4_periph_bus_sels), truetruetrue, base + 0x8, 1);
 clks[IMX8ULP_CLK_TPM7] = imx8ulp_clk_hw_composite("tpm7", pcc4_periph_bus_sels, ARRAY_SIZE(pcc4_periph_bus_sels), truetruetrue, base + 0xc, 1);
 clks[IMX8ULP_CLK_LPI2C6] = imx8ulp_clk_hw_composite("lpi2c6", pcc4_periph_bus_sels, ARRAY_SIZE(pcc4_periph_bus_sels), truetruetrue, base + 0x10, 1);
 clks[IMX8ULP_CLK_LPI2C7] = imx8ulp_clk_hw_composite("lpi2c7", pcc4_periph_bus_sels, ARRAY_SIZE(pcc4_periph_bus_sels), truetruetrue, base + 0x14, 1);
 clks[IMX8ULP_CLK_LPUART6] = imx8ulp_clk_hw_composite("lpuart6", pcc4_periph_bus_sels, ARRAY_SIZE(pcc4_periph_bus_sels), truetruetrue, base + 0x18, 1);
 clks[IMX8ULP_CLK_LPUART7] = imx8ulp_clk_hw_composite("lpuart7", pcc4_periph_bus_sels, ARRAY_SIZE(pcc4_periph_bus_sels), truetruetrue, base + 0x1c, 1);
 clks[IMX8ULP_CLK_SAI4] = imx8ulp_clk_hw_composite("sai4", xbar_divbus, 1, falsefalsetrue, base + 0x20, 1); /* sai ipg, NOT from sai sel */
 clks[IMX8ULP_CLK_SAI5] = imx8ulp_clk_hw_composite("sai5", xbar_divbus, 1, falsefalsetrue, base + 0x24, 1); /* sai ipg */
 clks[IMX8ULP_CLK_PCTLE] = imx_clk_hw_gate("pctle""xbar_divbus", base + 0x28, 30);
 clks[IMX8ULP_CLK_PCTLF] = imx_clk_hw_gate("pctlf""xbar_divbus", base + 0x2c, 30);
 clks[IMX8ULP_CLK_USDHC0] = imx8ulp_clk_hw_composite("usdhc0", pcc4_periph_plat_sels, ARRAY_SIZE(pcc4_periph_plat_sels), truefalsetrue, base + 0x34, 1);
 clks[IMX8ULP_CLK_USDHC1] = imx8ulp_clk_hw_composite("usdhc1", pcc4_periph_plat_sels, ARRAY_SIZE(pcc4_periph_plat_sels), truefalsetrue, base + 0x38, 1);
 clks[IMX8ULP_CLK_USDHC2] = imx8ulp_clk_hw_composite("usdhc2", pcc4_periph_plat_sels, ARRAY_SIZE(pcc4_periph_plat_sels), truefalsetrue, base + 0x3c, 1);
 clks[IMX8ULP_CLK_USB0] = imx8ulp_clk_hw_composite("usb0", nic_per_divplat, 1, falsefalsetrue, base + 0x40, 1);
 clks[IMX8ULP_CLK_USB0_PHY] = imx8ulp_clk_hw_composite("usb0_phy", xbar_divbus, 1, falsefalsetrue, base + 0x44, 1);
 clks[IMX8ULP_CLK_USB1] = imx8ulp_clk_hw_composite("usb1", nic_per_divplat, 1, falsefalsetrue, base + 0x48, 1);
 clks[IMX8ULP_CLK_USB1_PHY] = imx8ulp_clk_hw_composite("usb1_phy", xbar_divbus, 1, falsefalsetrue, base + 0x4c, 1);
 clks[IMX8ULP_CLK_USB_XBAR] = imx_clk_hw_gate("usb_xbar""xbar_divbus", base + 0x50, 30);
 clks[IMX8ULP_CLK_ENET] = imx8ulp_clk_hw_composite("enet", nic_per_divplat, 1, falsefalsetrue, base + 0x54, 1);
 clks[IMX8ULP_CLK_RGPIOE] = imx_clk_hw_gate("rgpioe""nic_per_divplat", base + 0x78, 30);
 clks[IMX8ULP_CLK_RGPIOF] = imx_clk_hw_gate("rgpiof""nic_per_divplat", base + 0x7c, 30);

 imx_check_clk_hws(clks, clk_data->num);

 ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, clk_data);
 if (ret)
  return ret;

 /* register the pcc4 reset controller */
 return imx8ulp_pcc_reset_init(pdev, base, pcc4_resets, ARRAY_SIZE(pcc4_resets));

}

static int imx8ulp_clk_pcc5_init(struct platform_device *pdev)
{
 struct device *dev = &pdev->dev;
 struct clk_hw_onecell_data *clk_data;
 struct clk_hw **clks;
 void __iomem *base;
 int ret;

 clk_data = devm_kzalloc(dev, struct_size(clk_data, hws, IMX8ULP_CLK_PCC5_END),
      GFP_KERNEL);
 if (!clk_data)
  return -ENOMEM;

 clk_data->num = IMX8ULP_CLK_PCC5_END;
 clks = clk_data->hws;

 /* PCC5 */
 base = devm_platform_ioremap_resource(pdev, 0);
 if (WARN_ON(IS_ERR(base)))
  return PTR_ERR(base);

 clks[IMX8ULP_CLK_DMA2_MP] = imx_clk_hw_gate("pcc_dma2_mp""lpav_axi_div", base + 0x0, 30);
 clks[IMX8ULP_CLK_DMA2_CH0] = imx_clk_hw_gate("pcc_dma2_ch0""lpav_axi_div", base + 0x4, 30);
 clks[IMX8ULP_CLK_DMA2_CH1] = imx_clk_hw_gate("pcc_dma2_ch1""lpav_axi_div", base + 0x8, 30);
 clks[IMX8ULP_CLK_DMA2_CH2] = imx_clk_hw_gate("pcc_dma2_ch2""lpav_axi_div", base + 0xc, 30);
 clks[IMX8ULP_CLK_DMA2_CH3] = imx_clk_hw_gate("pcc_dma2_ch3""lpav_axi_div", base + 0x10, 30);
 clks[IMX8ULP_CLK_DMA2_CH4] = imx_clk_hw_gate("pcc_dma2_ch4""lpav_axi_div", base + 0x14, 30);
 clks[IMX8ULP_CLK_DMA2_CH5] = imx_clk_hw_gate("pcc_dma2_ch5""lpav_axi_div", base + 0x18, 30);
 clks[IMX8ULP_CLK_DMA2_CH6] = imx_clk_hw_gate("pcc_dma2_ch6""lpav_axi_div", base + 0x1c, 30);
 clks[IMX8ULP_CLK_DMA2_CH7] = imx_clk_hw_gate("pcc_dma2_ch7""lpav_axi_div", base + 0x20, 30);
 clks[IMX8ULP_CLK_DMA2_CH8] = imx_clk_hw_gate("pcc_dma2_ch8""lpav_axi_div", base + 0x24, 30);
 clks[IMX8ULP_CLK_DMA2_CH9] = imx_clk_hw_gate("pcc_dma2_ch9""lpav_axi_div", base + 0x28, 30);
 clks[IMX8ULP_CLK_DMA2_CH10] = imx_clk_hw_gate("pcc_dma2_ch10""lpav_axi_div", base + 0x2c, 30);
 clks[IMX8ULP_CLK_DMA2_CH11] = imx_clk_hw_gate("pcc_dma2_ch11""lpav_axi_div", base + 0x30, 30);
 clks[IMX8ULP_CLK_DMA2_CH12] = imx_clk_hw_gate("pcc_dma2_ch12""lpav_axi_div", base + 0x34, 30);
 clks[IMX8ULP_CLK_DMA2_CH13] = imx_clk_hw_gate("pcc_dma2_ch13""lpav_axi_div", base + 0x38, 30);
 clks[IMX8ULP_CLK_DMA2_CH14] = imx_clk_hw_gate("pcc_dma2_ch14""lpav_axi_div", base + 0x3c, 30);
 clks[IMX8ULP_CLK_DMA2_CH15] = imx_clk_hw_gate("pcc_dma2_ch15""lpav_axi_div", base + 0x40, 30);
 clks[IMX8ULP_CLK_DMA2_CH16] = imx_clk_hw_gate("pcc_dma2_ch16""lpav_axi_div", base + 0x44, 30);
 clks[IMX8ULP_CLK_DMA2_CH17] = imx_clk_hw_gate("pcc_dma2_ch17""lpav_axi_div", base + 0x48, 30);
 clks[IMX8ULP_CLK_DMA2_CH18] = imx_clk_hw_gate("pcc_dma2_ch18""lpav_axi_div", base + 0x4c, 30);
 clks[IMX8ULP_CLK_DMA2_CH19] = imx_clk_hw_gate("pcc_dma2_ch19""lpav_axi_div", base + 0x50, 30);
 clks[IMX8ULP_CLK_DMA2_CH20] = imx_clk_hw_gate("pcc_dma2_ch20""lpav_axi_div", base + 0x54, 30);
 clks[IMX8ULP_CLK_DMA2_CH21] = imx_clk_hw_gate("pcc_dma2_ch21""lpav_axi_div", base + 0x58, 30);
 clks[IMX8ULP_CLK_DMA2_CH22] = imx_clk_hw_gate("pcc_dma2_ch22""lpav_axi_div", base + 0x5c, 30);
 clks[IMX8ULP_CLK_DMA2_CH23] = imx_clk_hw_gate("pcc_dma2_ch23""lpav_axi_div", base + 0x60, 30);
 clks[IMX8ULP_CLK_DMA2_CH24] = imx_clk_hw_gate("pcc_dma2_ch24""lpav_axi_div", base + 0x64, 30);
 clks[IMX8ULP_CLK_DMA2_CH25] = imx_clk_hw_gate("pcc_dma2_ch25""lpav_axi_div", base + 0x68, 30);
 clks[IMX8ULP_CLK_DMA2_CH26] = imx_clk_hw_gate("pcc_dma2_ch26""lpav_axi_div", base + 0x6c, 30);
 clks[IMX8ULP_CLK_DMA2_CH27] = imx_clk_hw_gate("pcc_dma2_ch27""lpav_axi_div", base + 0x70, 30);
 clks[IMX8ULP_CLK_DMA2_CH28] = imx_clk_hw_gate("pcc_dma2_ch28""lpav_axi_div", base + 0x74, 30);
 clks[IMX8ULP_CLK_DMA2_CH29] = imx_clk_hw_gate("pcc_dma2_ch29""lpav_axi_div", base + 0x78, 30);
 clks[IMX8ULP_CLK_DMA2_CH30] = imx_clk_hw_gate("pcc_dma2_ch30""lpav_axi_div", base + 0x7c, 30);
 clks[IMX8ULP_CLK_DMA2_CH31] = imx_clk_hw_gate("pcc_dma2_ch31""lpav_axi_div", base + 0x80, 30);

 clks[IMX8ULP_CLK_AVD_SIM] = imx_clk_hw_gate("avd_sim""lpav_bus_div", base + 0x94, 30);
 clks[IMX8ULP_CLK_TPM8] = imx8ulp_clk_hw_composite("tpm8", pcc5_periph_bus_sels, ARRAY_SIZE(pcc5_periph_bus_sels), truetruetrue, base + 0xa0, 1);
 clks[IMX8ULP_CLK_MU2_B] = imx_clk_hw_gate("mu2_b""lpav_bus_div", base + 0x84, 30);
 clks[IMX8ULP_CLK_MU3_B] = imx_clk_hw_gate("mu3_b""lpav_bus_div", base + 0x88, 30);
 clks[IMX8ULP_CLK_SAI6] = imx8ulp_clk_hw_composite("sai6", lpav_bus_div, 1, falsefalsetrue, base + 0xa4, 1);
 clks[IMX8ULP_CLK_SAI7] = imx8ulp_clk_hw_composite("sai7", lpav_bus_div, 1, falsefalsetrue, base + 0xa8, 1);
 clks[IMX8ULP_CLK_SPDIF] = imx8ulp_clk_hw_composite("spdif", lpav_bus_div, 1, falsefalsetrue, base + 0xac, 1);
 clks[IMX8ULP_CLK_ISI] = imx8ulp_clk_hw_composite("isi", lpav_axi_div, 1, falsefalsetrue, base + 0xb0, 1);
 clks[IMX8ULP_CLK_CSI_REGS] = imx8ulp_clk_hw_composite("csi_regs", lpav_bus_div, 1, falsefalsetrue, base + 0xb4, 1);
 clks[IMX8ULP_CLK_CSI] = imx8ulp_clk_hw_composite("csi", pcc5_periph_plat_sels, ARRAY_SIZE(pcc5_periph_plat_sels), truetruetrue, base + 0xbc, 1);
 clks[IMX8ULP_CLK_DSI] = imx8ulp_clk_hw_composite("dsi", pcc5_periph_plat_sels, ARRAY_SIZE(pcc5_periph_plat_sels), truetruetrue, base + 0xc0, 1);
 clks[IMX8ULP_CLK_WDOG5] = imx8ulp_clk_hw_composite("wdog5", pcc5_periph_bus_sels, ARRAY_SIZE(pcc5_periph_bus_sels), truetruetrue, base + 0xc8, 1);
 clks[IMX8ULP_CLK_EPDC] = imx8ulp_clk_hw_composite("epdc", pcc5_periph_plat_sels, ARRAY_SIZE(pcc5_periph_plat_sels), truetruetrue, base + 0xcc, 1);
 clks[IMX8ULP_CLK_PXP] = imx8ulp_clk_hw_composite("pxp", lpav_axi_div, 1, falsefalsetrue, base + 0xd0, 1);
 clks[IMX8ULP_CLK_GPU2D] = imx8ulp_clk_hw_composite("gpu2d", pcc5_periph_plat_sels, ARRAY_SIZE(pcc5_periph_plat_sels), truetruetrue, base + 0xf0, 1);
 clks[IMX8ULP_CLK_GPU3D] = imx8ulp_clk_hw_composite("gpu3d", pcc5_periph_plat_sels, ARRAY_SIZE(pcc5_periph_plat_sels), truetruetrue, base + 0xf4, 1);
 clks[IMX8ULP_CLK_DC_NANO] = imx8ulp_clk_hw_composite("dc_nano", pcc5_periph_plat_sels, ARRAY_SIZE(pcc5_periph_plat_sels), truetruetrue, base + 0xf8, 1);
 clks[IMX8ULP_CLK_CSI_CLK_UI] = imx8ulp_clk_hw_composite("csi_clk_ui", pcc5_periph_plat_sels, ARRAY_SIZE(pcc5_periph_plat_sels), truetruetrue, base + 0x10c, 1);
 clks[IMX8ULP_CLK_CSI_CLK_ESC] = imx8ulp_clk_hw_composite("csi_clk_esc", pcc5_periph_plat_sels, ARRAY_SIZE(pcc5_periph_plat_sels), truetruetrue, base + 0x110, 1);
 clks[IMX8ULP_CLK_RGPIOD] = imx_clk_hw_gate("rgpiod""lpav_axi_div", base + 0x114, 30);
 clks[IMX8ULP_CLK_DSI_TX_ESC] = imx_clk_hw_fixed_factor("mipi_dsi_tx_esc""dsi", 1, 4);

 imx_check_clk_hws(clks, clk_data->num);

 ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, clk_data);
 if (ret)
  return ret;

 /* register the pcc5 reset controller */
 return imx8ulp_pcc_reset_init(pdev, base, pcc5_resets, ARRAY_SIZE(pcc5_resets));
}

static int imx8ulp_clk_probe(struct platform_device *pdev)
{
 int (*probe)(struct platform_device *pdev);

 probe = of_device_get_match_data(&pdev->dev);

 if (probe)
  return probe(pdev);

 return 0;
}

static const struct of_device_id imx8ulp_clk_dt_ids[] = {
 { .compatible = "fsl,imx8ulp-pcc3", .data = imx8ulp_clk_pcc3_init },
 { .compatible = "fsl,imx8ulp-pcc4", .data = imx8ulp_clk_pcc4_init },
 { .compatible = "fsl,imx8ulp-pcc5", .data = imx8ulp_clk_pcc5_init },
 { .compatible = "fsl,imx8ulp-cgc2", .data = imx8ulp_clk_cgc2_init },
 { .compatible = "fsl,imx8ulp-cgc1", .data = imx8ulp_clk_cgc1_init },
 { /* sentinel */ },
};
MODULE_DEVICE_TABLE(of, imx8ulp_clk_dt_ids);

static struct platform_driver imx8ulp_clk_driver = {
 .probe = imx8ulp_clk_probe,
 .driver = {
  .name  = KBUILD_MODNAME,
  .suppress_bind_attrs = true,
  .of_match_table = imx8ulp_clk_dt_ids,
 },
};
module_platform_driver(imx8ulp_clk_driver);

MODULE_AUTHOR("Peng Fan ");
MODULE_DESCRIPTION("NXP i.MX8ULP clock driver");
MODULE_LICENSE("GPL v2");

Messung V0.5
C=97 H=95 G=95

¤ Dauer der Verarbeitung: 0.23 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge