1commit d3211978913e7ee651bf47cfb393daccb8be4fdb 2Author: zhaoxc0502 <zhaoxc0502@thundersoft.com> 3Date: Wed Aug 10 11:43:26 2022 +0800 4 5 drivers_clk 6 7 Change-Id: Iad3fba6c51f290df25555d1136fd2cc4761d3324 8 9diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig 10index c715d4681..3853ce51b 100644 11--- a/drivers/clk/Kconfig 12+++ b/drivers/clk/Kconfig 13@@ -374,6 +374,7 @@ source "drivers/clk/mvebu/Kconfig" 14 source "drivers/clk/qcom/Kconfig" 15 source "drivers/clk/renesas/Kconfig" 16 source "drivers/clk/rockchip/Kconfig" 17+source "drivers/clk/s32/Kconfig" 18 source "drivers/clk/samsung/Kconfig" 19 source "drivers/clk/sifive/Kconfig" 20 source "drivers/clk/sprd/Kconfig" 21diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile 22index da8fcf147..8a52da49c 100644 23--- a/drivers/clk/Makefile 24+++ b/drivers/clk/Makefile 25@@ -102,6 +102,7 @@ obj-$(CONFIG_COMMON_CLK_PXA) += pxa/ 26 obj-$(CONFIG_COMMON_CLK_QCOM) += qcom/ 27 obj-y += renesas/ 28 obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/ 29+obj-$(CONFIG_ARCH_S32) += s32/ 30 obj-$(CONFIG_COMMON_CLK_SAMSUNG) += samsung/ 31 obj-$(CONFIG_CLK_SIFIVE) += sifive/ 32 obj-$(CONFIG_ARCH_SIRF) += sirf/ 33diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c 34index 61c78714c..18cfdbaab 100644 35--- a/drivers/clk/clk.c 36+++ b/drivers/clk/clk.c 37@@ -807,8 +807,7 @@ static void clk_core_unprepare(struct clk_core *core) 38 if (!core) 39 return; 40 41- if (WARN(core->prepare_count == 0, 42- "%s already unprepared\n", core->name)) 43+ if (core->prepare_count == 0) 44 return; 45 46 if (WARN(core->prepare_count == 1 && core->flags & CLK_IS_CRITICAL, 47@@ -949,7 +948,7 @@ static void clk_core_disable(struct clk_core *core) 48 if (!core) 49 return; 50 51- if (WARN(core->enable_count == 0, "%s already disabled\n", core->name)) 52+ if (core->enable_count == 0) 53 return; 54 55 if (WARN(core->enable_count == 1 && core->flags & CLK_IS_CRITICAL, 56@@ -1008,8 +1007,7 @@ static int clk_core_enable(struct clk_core *core) 57 if (!core) 58 return 0; 59 60- if (WARN(core->prepare_count == 0, 61- "Enabling unprepared %s\n", core->name)) 62+ if (core->prepare_count == 0) 63 return -ESHUTDOWN; 64 65 if (core->enable_count == 0) { 66@@ -2495,7 +2493,8 @@ static int clk_core_set_parent_nolock(struct clk_core *core, 67 if (!core) 68 return 0; 69 70- if (core->parent == parent) 71+ if ((core->parent == parent) && 72+ !(core->flags & CLK_SET_PARENT_NOCACHE)) 73 return 0; 74 75 /* verify ops for multi-parent clks */ 76diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile 77index dd6a737d0..c4a188768 100644 78--- a/drivers/clk/imx/Makefile 79+++ b/drivers/clk/imx/Makefile 80@@ -23,12 +23,17 @@ obj-$(CONFIG_MXC_CLK) += mxc-clk.o 81 82 obj-$(CONFIG_CLK_IMX8MM) += clk-imx8mm.o 83 obj-$(CONFIG_CLK_IMX8MN) += clk-imx8mn.o 84-obj-$(CONFIG_CLK_IMX8MP) += clk-imx8mp.o 85+obj-$(CONFIG_CLK_IMX8MP) += clk-imx8mp.o clk-blk-ctrl.o 86 obj-$(CONFIG_CLK_IMX8MQ) += clk-imx8mq.o 87 88 obj-$(CONFIG_MXC_CLK_SCU) += clk-imx-scu.o clk-imx-lpcg-scu.o 89-clk-imx-scu-$(CONFIG_CLK_IMX8QXP) += clk-scu.o clk-imx8qxp.o 90+clk-imx-scu-$(CONFIG_CLK_IMX8QXP) += clk-scu.o clk-imx8qxp.o \ 91+ clk-imx8qxp-rsrc.o clk-imx8qm-rsrc.o \ 92+ clk-imx8dxl-rsrc.o 93 clk-imx-lpcg-scu-$(CONFIG_CLK_IMX8QXP) += clk-lpcg-scu.o clk-imx8qxp-lpcg.o 94+obj-$(CONFIG_CLK_IMX8QXP) += clk-imx8qxp-acm.o clk-imx8qm-acm.o clk-imx8dxl-acm.o clk-imx-acm-utils.o 95+ 96+obj-$(CONFIG_CLK_IMX8ULP) += clk-imx8ulp.o 97 98 obj-$(CONFIG_CLK_IMX1) += clk-imx1.o 99 obj-$(CONFIG_CLK_IMX25) += clk-imx25.o 100diff --git a/drivers/clk/imx/clk-composite-7ulp.c b/drivers/clk/imx/clk-composite-7ulp.c 101index 7c4f31b31..6cc1b8bb8 100644 102--- a/drivers/clk/imx/clk-composite-7ulp.c 103+++ b/drivers/clk/imx/clk-composite-7ulp.c 104@@ -8,6 +8,7 @@ 105 #include <linux/bits.h> 106 #include <linux/clk-provider.h> 107 #include <linux/err.h> 108+#include <linux/io.h> 109 #include <linux/slab.h> 110 111 #include "clk.h" 112@@ -22,17 +23,61 @@ 113 #define PCG_PCD_WIDTH 3 114 #define PCG_PCD_MASK 0x7 115 116-struct clk_hw *imx7ulp_clk_hw_composite(const char *name, 117+#define SW_RST BIT(28) 118+ 119+static int pcc_gate_enable(struct clk_hw *hw) 120+{ 121+ struct clk_gate *gate = to_clk_gate(hw); 122+ unsigned long flags; 123+ u32 val; 124+ int ret; 125+ 126+ ret = clk_gate_ops.enable(hw); 127+ if (ret) 128+ return ret; 129+ 130+ spin_lock_irqsave(gate->lock, flags); 131+ /* 132+ * release the sw reset for peripherals associated with 133+ * with this pcc clock. 134+ */ 135+ val = readl(gate->reg); 136+ val |= SW_RST; 137+ writel(val, gate->reg); 138+ 139+ spin_unlock_irqrestore(gate->lock, flags); 140+ 141+ return 0; 142+} 143+ 144+static void pcc_gate_disable(struct clk_hw *hw) 145+{ 146+ clk_gate_ops.disable(hw); 147+} 148+ 149+static int pcc_gate_is_enabled(struct clk_hw *hw) 150+{ 151+ return clk_gate_ops.is_enabled(hw); 152+} 153+ 154+static const struct clk_ops pcc_gate_ops = { 155+ .enable = pcc_gate_enable, 156+ .disable = pcc_gate_disable, 157+ .is_enabled = pcc_gate_is_enabled, 158+}; 159+ 160+static struct clk_hw *imx_ulp_clk_hw_composite(const char *name, 161 const char * const *parent_names, 162 int num_parents, bool mux_present, 163 bool rate_present, bool gate_present, 164- void __iomem *reg) 165+ void __iomem *reg, bool has_swrst) 166 { 167 struct clk_hw *mux_hw = NULL, *fd_hw = NULL, *gate_hw = NULL; 168 struct clk_fractional_divider *fd = NULL; 169 struct clk_gate *gate = NULL; 170 struct clk_mux *mux = NULL; 171 struct clk_hw *hw; 172+ u32 val; 173 174 if (mux_present) { 175 mux = kzalloc(sizeof(*mux), GFP_KERNEL); 176@@ -42,6 +87,8 @@ struct clk_hw *imx7ulp_clk_hw_composite(const char *name, 177 mux->reg = reg; 178 mux->shift = PCG_PCS_SHIFT; 179 mux->mask = PCG_PCS_MASK; 180+ if (has_swrst) 181+ mux->lock = &imx_ccm_lock; 182 } 183 184 if (rate_present) { 185@@ -59,6 +106,8 @@ struct clk_hw *imx7ulp_clk_hw_composite(const char *name, 186 fd->nwidth = PCG_PCD_WIDTH; 187 fd->nmask = PCG_PCD_MASK; 188 fd->flags = CLK_FRAC_DIVIDER_ZERO_BASED; 189+ if (has_swrst) 190+ fd->lock = &imx_ccm_lock; 191 } 192 193 if (gate_present) { 194@@ -71,13 +120,27 @@ struct clk_hw *imx7ulp_clk_hw_composite(const char *name, 195 gate_hw = &gate->hw; 196 gate->reg = reg; 197 gate->bit_idx = PCG_CGC_SHIFT; 198+ if (has_swrst) 199+ gate->lock = &imx_ccm_lock; 200+ /* 201+ * make sure clock is gated during clock tree initialization, 202+ * the HW ONLY allow clock parent/rate changed with clock gated, 203+ * during clock tree initialization, clocks could be enabled 204+ * by bootloader, so the HW status will mismatch with clock tree 205+ * prepare count, then clock core driver will allow parent/rate 206+ * change since the prepare count is zero, but HW actually 207+ * prevent the parent/rate change due to the clock is enabled. 208+ */ 209+ val = readl_relaxed(reg); 210+ val &= ~(1 << PCG_CGC_SHIFT); 211+ writel_relaxed(val, reg); 212 } 213 214 hw = clk_hw_register_composite(NULL, name, parent_names, num_parents, 215 mux_hw, &clk_mux_ops, fd_hw, 216 &clk_fractional_divider_ops, gate_hw, 217- &clk_gate_ops, CLK_SET_RATE_GATE | 218- CLK_SET_PARENT_GATE); 219+ has_swrst ? &pcc_gate_ops : &clk_gate_ops, CLK_SET_RATE_GATE | 220+ CLK_SET_PARENT_GATE | CLK_SET_RATE_NO_REPARENT); 221 if (IS_ERR(hw)) { 222 kfree(mux); 223 kfree(fd); 224@@ -86,3 +149,19 @@ struct clk_hw *imx7ulp_clk_hw_composite(const char *name, 225 226 return hw; 227 } 228+ 229+struct clk_hw *imx7ulp_clk_hw_composite(const char *name, const char * const *parent_names, 230+ int num_parents, bool mux_present, bool rate_present, 231+ bool gate_present, void __iomem *reg) 232+{ 233+ return imx_ulp_clk_hw_composite(name, parent_names, num_parents, mux_present, rate_present, 234+ gate_present, reg, false); 235+} 236+ 237+struct clk_hw *imx8ulp_clk_hw_composite(const char *name, const char * const *parent_names, 238+ int num_parents, bool mux_present, bool rate_present, 239+ bool gate_present, void __iomem *reg, bool has_swrst) 240+{ 241+ return imx_ulp_clk_hw_composite(name, parent_names, num_parents, mux_present, rate_present, 242+ gate_present, reg, has_swrst); 243+} 244diff --git a/drivers/clk/imx/clk-composite-8m.c b/drivers/clk/imx/clk-composite-8m.c 245index 04e728538..fec34169a 100644 246--- a/drivers/clk/imx/clk-composite-8m.c 247+++ b/drivers/clk/imx/clk-composite-8m.c 248@@ -223,14 +223,19 @@ struct clk_hw *imx8m_clk_hw_composite_flags(const char *name, 249 div->lock = &imx_ccm_lock; 250 div->flags = CLK_DIVIDER_ROUND_CLOSEST; 251 252- gate = kzalloc(sizeof(*gate), GFP_KERNEL); 253- if (!gate) 254- goto fail; 255- 256- gate_hw = &gate->hw; 257- gate->reg = reg; 258- gate->bit_idx = PCG_CGC_SHIFT; 259- gate->lock = &imx_ccm_lock; 260+ /* skip registering the gate ops if M4 is enabled */ 261+ if (imx_src_is_m4_enabled()) { 262+ gate_hw = NULL; 263+ } else { 264+ gate = kzalloc(sizeof(*gate), GFP_KERNEL); 265+ if (!gate) 266+ goto fail; 267+ 268+ gate_hw = &gate->hw; 269+ gate->reg = reg; 270+ gate->bit_idx = PCG_CGC_SHIFT; 271+ gate->lock = &imx_ccm_lock; 272+ } 273 274 hw = clk_hw_register_composite(NULL, name, parent_names, num_parents, 275 mux_hw, mux_ops, div_hw, 276diff --git a/drivers/clk/imx/clk-gate2.c b/drivers/clk/imx/clk-gate2.c 277index 7eed7083f..0f8fb0341 100644 278--- a/drivers/clk/imx/clk-gate2.c 279+++ b/drivers/clk/imx/clk-gate2.c 280@@ -8,11 +8,13 @@ 281 282 #include <linux/clk-provider.h> 283 #include <linux/export.h> 284+#include <linux/imx_sema4.h> 285 #include <linux/module.h> 286 #include <linux/slab.h> 287 #include <linux/io.h> 288 #include <linux/err.h> 289 #include <linux/string.h> 290+#include <soc/imx/src.h> 291 #include "clk.h" 292 293 /** 294@@ -37,10 +39,54 @@ struct clk_gate2 { 295 296 #define to_clk_gate2(_hw) container_of(_hw, struct clk_gate2, hw) 297 298+static void clk_gate2_do_hardware(struct clk_gate2 *gate, bool enable) 299+{ 300+ u32 reg; 301+ 302+ reg = readl(gate->reg); 303+ if (enable) 304+ reg |= gate->cgr_val << gate->bit_idx; 305+ else 306+ reg &= ~(gate->cgr_val << gate->bit_idx); 307+ writel(reg, gate->reg); 308+} 309+ 310+static void clk_gate2_do_shared_clks(struct clk_hw *hw, bool enable) 311+{ 312+ struct clk_gate2 *gate = to_clk_gate2(hw); 313+ 314+ if (imx_src_is_m4_enabled() && clk_on_imx6sx()) { 315+#ifdef CONFIG_SOC_IMX6SX 316+ if (!amp_power_mutex || !shared_mem) { 317+ if (enable) 318+ clk_gate2_do_hardware(gate, enable); 319+ return; 320+ } 321+ 322+ imx_sema4_mutex_lock(amp_power_mutex); 323+ if (shared_mem->ca9_valid != SHARED_MEM_MAGIC_NUMBER || 324+ shared_mem->cm4_valid != SHARED_MEM_MAGIC_NUMBER) { 325+ imx_sema4_mutex_unlock(amp_power_mutex); 326+ return; 327+ } 328+ 329+ if (!imx_update_shared_mem(hw, enable)) { 330+ imx_sema4_mutex_unlock(amp_power_mutex); 331+ return; 332+ } 333+ 334+ clk_gate2_do_hardware(gate, enable); 335+ 336+ imx_sema4_mutex_unlock(amp_power_mutex); 337+#endif 338+ } else { 339+ clk_gate2_do_hardware(gate, enable); 340+ } 341+} 342+ 343 static int clk_gate2_enable(struct clk_hw *hw) 344 { 345 struct clk_gate2 *gate = to_clk_gate2(hw); 346- u32 reg; 347 unsigned long flags; 348 int ret = 0; 349 350@@ -49,15 +95,7 @@ static int clk_gate2_enable(struct clk_hw *hw) 351 if (gate->share_count && (*gate->share_count)++ > 0) 352 goto out; 353 354- if (gate->flags & IMX_CLK_GATE2_SINGLE_BIT) { 355- ret = clk_gate_ops.enable(hw); 356- } else { 357- reg = readl(gate->reg); 358- reg &= ~(3 << gate->bit_idx); 359- reg |= gate->cgr_val << gate->bit_idx; 360- writel(reg, gate->reg); 361- } 362- 363+ clk_gate2_do_shared_clks(hw, true); 364 out: 365 spin_unlock_irqrestore(gate->lock, flags); 366 367@@ -67,7 +105,6 @@ static int clk_gate2_enable(struct clk_hw *hw) 368 static void clk_gate2_disable(struct clk_hw *hw) 369 { 370 struct clk_gate2 *gate = to_clk_gate2(hw); 371- u32 reg; 372 unsigned long flags; 373 374 spin_lock_irqsave(gate->lock, flags); 375@@ -79,23 +116,16 @@ static void clk_gate2_disable(struct clk_hw *hw) 376 goto out; 377 } 378 379- if (gate->flags & IMX_CLK_GATE2_SINGLE_BIT) { 380- clk_gate_ops.disable(hw); 381- } else { 382- reg = readl(gate->reg); 383- reg &= ~(3 << gate->bit_idx); 384- writel(reg, gate->reg); 385- } 386- 387+ clk_gate2_do_shared_clks(hw, false); 388 out: 389 spin_unlock_irqrestore(gate->lock, flags); 390 } 391 392-static int clk_gate2_reg_is_enabled(void __iomem *reg, u8 bit_idx) 393+static int clk_gate2_reg_is_enabled(void __iomem *reg, u8 bit_idx, u8 cgr_val) 394 { 395 u32 val = readl(reg); 396 397- if (((val >> bit_idx) & 1) == 1) 398+ if (((val >> bit_idx) & cgr_val) == 1) 399 return 1; 400 401 return 0; 402@@ -104,29 +134,27 @@ static int clk_gate2_reg_is_enabled(void __iomem *reg, u8 bit_idx) 403 static int clk_gate2_is_enabled(struct clk_hw *hw) 404 { 405 struct clk_gate2 *gate = to_clk_gate2(hw); 406+ unsigned long flags; 407+ int ret; 408 409- if (gate->flags & IMX_CLK_GATE2_SINGLE_BIT) 410- return clk_gate_ops.is_enabled(hw); 411+ spin_lock_irqsave(gate->lock, flags); 412+ 413+ ret = clk_gate2_reg_is_enabled(gate->reg, gate->bit_idx, gate->cgr_val); 414+ 415+ spin_unlock_irqrestore(gate->lock, flags); 416 417- return clk_gate2_reg_is_enabled(gate->reg, gate->bit_idx); 418+ return ret; 419 } 420 421 static void clk_gate2_disable_unused(struct clk_hw *hw) 422 { 423 struct clk_gate2 *gate = to_clk_gate2(hw); 424 unsigned long flags; 425- u32 reg; 426- 427- if (gate->flags & IMX_CLK_GATE2_SINGLE_BIT) 428- return; 429 430 spin_lock_irqsave(gate->lock, flags); 431 432- if (!gate->share_count || *gate->share_count == 0) { 433- reg = readl(gate->reg); 434- reg &= ~(3 << gate->bit_idx); 435- writel(reg, gate->reg); 436- } 437+ if (!gate->share_count || *gate->share_count == 0) 438+ clk_gate2_do_shared_clks(hw, false); 439 440 spin_unlock_irqrestore(gate->lock, flags); 441 } 442diff --git a/drivers/clk/imx/clk-imx-acm-utils.c b/drivers/clk/imx/clk-imx-acm-utils.c 443new file mode 100644 444index 000000000..b923e117d 445--- /dev/null 446+++ b/drivers/clk/imx/clk-imx-acm-utils.c 447@@ -0,0 +1,78 @@ 448+// SPDX-License-Identifier: GPL-2.0+ 449+// Copyright 2020 NXP 450+ 451+#include <linux/pm_runtime.h> 452+#include <linux/pm_domain.h> 453+#include "clk-imx-acm-utils.h" 454+ 455+/** 456+ * clk_imx_acm_attach_pm_domains 457+ */ 458+int clk_imx_acm_attach_pm_domains(struct device *dev, 459+ struct clk_imx_acm_pm_domains *dev_pm) 460+{ 461+ int ret; 462+ int i; 463+ 464+ dev_pm->num_domains = of_count_phandle_with_args(dev->of_node, "power-domains", 465+ "#power-domain-cells"); 466+ if (dev_pm->num_domains <= 1) 467+ return 0; 468+ 469+ dev_pm->pd_dev = devm_kmalloc_array(dev, dev_pm->num_domains, 470+ sizeof(*dev_pm->pd_dev), 471+ GFP_KERNEL); 472+ if (!dev_pm->pd_dev) 473+ return -ENOMEM; 474+ 475+ dev_pm->pd_dev_link = devm_kmalloc_array(dev, 476+ dev_pm->num_domains, 477+ sizeof(*dev_pm->pd_dev_link), 478+ GFP_KERNEL); 479+ if (!dev_pm->pd_dev_link) 480+ return -ENOMEM; 481+ 482+ for (i = 0; i < dev_pm->num_domains; i++) { 483+ dev_pm->pd_dev[i] = dev_pm_domain_attach_by_id(dev, i); 484+ if (IS_ERR(dev_pm->pd_dev[i])) 485+ return PTR_ERR(dev_pm->pd_dev[i]); 486+ 487+ dev_pm->pd_dev_link[i] = device_link_add(dev, 488+ dev_pm->pd_dev[i], 489+ DL_FLAG_STATELESS | 490+ DL_FLAG_PM_RUNTIME | 491+ DL_FLAG_RPM_ACTIVE); 492+ if (IS_ERR(dev_pm->pd_dev_link[i])) { 493+ dev_pm_domain_detach(dev_pm->pd_dev[i], false); 494+ ret = PTR_ERR(dev_pm->pd_dev_link[i]); 495+ goto detach_pm; 496+ } 497+ } 498+ return 0; 499+ 500+detach_pm: 501+ while (--i >= 0) { 502+ device_link_del(dev_pm->pd_dev_link[i]); 503+ dev_pm_domain_detach(dev_pm->pd_dev[i], false); 504+ } 505+ return ret; 506+} 507+ 508+/** 509+ * fsl_dev_detach_pm_domains 510+ */ 511+int clk_imx_acm_detach_pm_domains(struct device *dev, 512+ struct clk_imx_acm_pm_domains *dev_pm) 513+{ 514+ int i; 515+ 516+ if (dev_pm->num_domains <= 1) 517+ return 0; 518+ 519+ for (i = 0; i < dev_pm->num_domains; i++) { 520+ device_link_del(dev_pm->pd_dev_link[i]); 521+ dev_pm_domain_detach(dev_pm->pd_dev[i], false); 522+ } 523+ 524+ return 0; 525+} 526diff --git a/drivers/clk/imx/clk-imx-acm-utils.h b/drivers/clk/imx/clk-imx-acm-utils.h 527new file mode 100644 528index 000000000..662e0d123 529--- /dev/null 530+++ b/drivers/clk/imx/clk-imx-acm-utils.h 531@@ -0,0 +1,19 @@ 532+/* SPDX-License-Identifier: GPL-2.0 */ 533+/* Copyright 2020 NXP */ 534+ 535+#ifndef _CLK_IMX_ACM_UTILS_H 536+#define _CLK_IMX_ACM_UTILS_H 537+ 538+#include <linux/device.h> 539+ 540+struct clk_imx_acm_pm_domains { 541+ struct device **pd_dev; 542+ struct device_link **pd_dev_link; 543+ int num_domains; 544+}; 545+ 546+int clk_imx_acm_attach_pm_domains(struct device *dev, 547+ struct clk_imx_acm_pm_domains *dev_pm); 548+int clk_imx_acm_detach_pm_domains(struct device *dev, 549+ struct clk_imx_acm_pm_domains *dev_pm); 550+#endif /* _CLK_IMX_ACM_UTILS_H */ 551diff --git a/drivers/clk/imx/clk-imx8dxl-acm.c b/drivers/clk/imx/clk-imx8dxl-acm.c 552new file mode 100644 553index 000000000..b11254522 554--- /dev/null 555+++ b/drivers/clk/imx/clk-imx8dxl-acm.c 556@@ -0,0 +1,235 @@ 557+// SPDX-License-Identifier: GPL-2.0+ 558+/* 559+ * Copyright 2019~2020 NXP 560+ */ 561+ 562+#include <linux/clk-provider.h> 563+#include <linux/err.h> 564+#include <linux/io.h> 565+#include <linux/module.h> 566+#include <linux/of.h> 567+#include <linux/of_device.h> 568+#include <linux/platform_device.h> 569+#include <linux/slab.h> 570+#include <linux/pm_domain.h> 571+#include <linux/pm_runtime.h> 572+ 573+#include "clk.h" 574+#include "clk-scu.h" 575+#include "clk-imx-acm-utils.h" 576+ 577+#include <dt-bindings/clock/imx8-clock.h> 578+ 579+struct imx8dxl_acm_priv { 580+ struct clk_imx_acm_pm_domains dev_pm; 581+ void __iomem *reg; 582+ u32 regs[0x20]; 583+}; 584+ 585+static const char *aud_clk_sels[] = { 586+ "aud_rec_clk0_lpcg_clk", 587+ "aud_rec_clk1_lpcg_clk", 588+ "ext_aud_mclk0", 589+ "ext_aud_mclk1", 590+ "dummy", 591+ "dummy", 592+ "dummy", 593+ "dummy", 594+ "spdif0_rx", 595+ "sai0_rx_bclk", 596+ "sai0_tx_bclk", 597+ "sai1_rx_bclk", 598+ "sai1_tx_bclk", 599+ "sai2_rx_bclk", 600+ "sai3_rx_bclk", 601+}; 602+ 603+static const char *mclk_out_sels[] = { 604+ "aud_rec_clk0_lpcg_clk", 605+ "aud_rec_clk1_lpcg_clk", 606+ "dummy", 607+ "dummy", 608+ "spdif0_rx", 609+ "dummy", 610+ "dummy", 611+ "dummy", 612+}; 613+ 614+static const char *sai_mclk_sels[] = { 615+ "aud_pll_div_clk0_lpcg_clk", 616+ "aud_pll_div_clk1_lpcg_clk", 617+ "acm_aud_clk0_sel", 618+ "acm_aud_clk1_sel", 619+}; 620+ 621+static const char *spdif_mclk_sels[] = { 622+ "aud_pll_div_clk0_lpcg_clk", 623+ "aud_pll_div_clk1_lpcg_clk", 624+ "acm_aud_clk0_sel", 625+ "acm_aud_clk1_sel", 626+}; 627+ 628+static const char *mqs_mclk_sels[] = { 629+ "aud_pll_div_clk0_lpcg_clk", 630+ "aud_pll_div_clk1_lpcg_clk", 631+ "acm_aud_clk0_sel", 632+ "acm_aud_clk1_sel", 633+}; 634+ 635+static int imx8dxl_acm_clk_probe(struct platform_device *pdev) 636+{ 637+ struct device *dev = &pdev->dev; 638+ struct device_node *np = dev->of_node; 639+ struct clk_onecell_data *clk_data; 640+ struct imx8dxl_acm_priv *priv; 641+ struct resource *res; 642+ struct clk **clks; 643+ void __iomem *base; 644+ int ret; 645+ int i; 646+ 647+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 648+ base = devm_ioremap(dev, res->start, resource_size(res)); 649+ if (!base) 650+ return -ENOMEM; 651+ 652+ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); 653+ if (!priv) 654+ return -ENOMEM; 655+ 656+ priv->reg = base; 657+ 658+ platform_set_drvdata(pdev, priv); 659+ 660+ clk_data = devm_kzalloc(&pdev->dev, sizeof(*clk_data), GFP_KERNEL); 661+ if (!clk_data) 662+ return -ENOMEM; 663+ 664+ clk_data->clks = devm_kcalloc(&pdev->dev, IMX_ADMA_ACM_CLK_END, 665+ sizeof(*clk_data->clks), GFP_KERNEL); 666+ if (!clk_data->clks) 667+ return -ENOMEM; 668+ 669+ clk_data->clk_num = IMX_ADMA_ACM_CLK_END; 670+ 671+ clks = clk_data->clks; 672+ 673+ ret = clk_imx_acm_attach_pm_domains(&pdev->dev, &priv->dev_pm); 674+ if (ret) 675+ return ret; 676+ 677+ pm_runtime_enable(&pdev->dev); 678+ pm_runtime_get_sync(&pdev->dev); 679+ 680+ clks[IMX_ADMA_EXT_AUD_MCLK0] = imx_clk_fixed("ext_aud_mclk0", 0); 681+ clks[IMX_ADMA_EXT_AUD_MCLK1] = imx_clk_fixed("ext_aud_mclk1", 0); 682+ clks[IMX_ADMA_SPDIF0_RX] = imx_clk_fixed("spdif0_rx", 0); 683+ clks[IMX_ADMA_SAI0_RX_BCLK] = imx_clk_fixed("sai0_rx_bclk", 0); 684+ clks[IMX_ADMA_SAI0_TX_BCLK] = imx_clk_fixed("sai0_tx_bclk", 0); 685+ clks[IMX_ADMA_SAI1_RX_BCLK] = imx_clk_fixed("sai1_rx_bclk", 0); 686+ clks[IMX_ADMA_SAI1_TX_BCLK] = imx_clk_fixed("sai1_tx_bclk", 0); 687+ clks[IMX_ADMA_SAI2_RX_BCLK] = imx_clk_fixed("sai2_rx_bclk", 0); 688+ clks[IMX_ADMA_SAI3_RX_BCLK] = imx_clk_fixed("sai3_rx_bclk", 0); 689+ 690+ clks[IMX_ADMA_ACM_AUD_CLK0_SEL] = imx_dev_clk_mux(dev, "acm_aud_clk0_sel", base+0x000000, 0, 5, aud_clk_sels, ARRAY_SIZE(aud_clk_sels)); 691+ clks[IMX_ADMA_ACM_AUD_CLK1_SEL] = imx_dev_clk_mux(dev, "acm_aud_clk1_sel", base+0x010000, 0, 5, aud_clk_sels, ARRAY_SIZE(aud_clk_sels)); 692+ 693+ clks[IMX_ADMA_ACM_MCLKOUT0_SEL] = imx_dev_clk_mux(dev, "acm_mclkout0_sel", base+0x020000, 0, 3, mclk_out_sels, ARRAY_SIZE(mclk_out_sels)); 694+ clks[IMX_ADMA_ACM_MCLKOUT1_SEL] = imx_dev_clk_mux(dev, "acm_mclkout1_sel", base+0x030000, 0, 3, mclk_out_sels, ARRAY_SIZE(mclk_out_sels)); 695+ 696+ clks[IMX_ADMA_ACM_SAI0_MCLK_SEL] = imx_dev_clk_mux(dev, "acm_sai0_mclk_sel", base+0x0E0000, 0, 2, sai_mclk_sels, ARRAY_SIZE(sai_mclk_sels)); 697+ clks[IMX_ADMA_ACM_SAI1_MCLK_SEL] = imx_dev_clk_mux(dev, "acm_sai1_mclk_sel", base+0x0F0000, 0, 2, sai_mclk_sels, ARRAY_SIZE(sai_mclk_sels)); 698+ clks[IMX_ADMA_ACM_SAI2_MCLK_SEL] = imx_dev_clk_mux(dev, "acm_sai2_mclk_sel", base+0x100000, 0, 2, sai_mclk_sels, ARRAY_SIZE(sai_mclk_sels)); 699+ clks[IMX_ADMA_ACM_SAI3_MCLK_SEL] = imx_dev_clk_mux(dev, "acm_sai3_mclk_sel", base+0x110000, 0, 2, sai_mclk_sels, ARRAY_SIZE(sai_mclk_sels)); 700+ 701+ clks[IMX_ADMA_ACM_SPDIF0_TX_CLK_SEL] = imx_dev_clk_mux(dev, "acm_spdif0_mclk_sel", base+0x1A0000, 0, 2, spdif_mclk_sels, ARRAY_SIZE(spdif_mclk_sels)); 702+ clks[IMX_ADMA_ACM_MQS_TX_CLK_SEL] = imx_dev_clk_mux(dev, "acm_mqs_mclk_sel", base+0x1C0000, 0, 2, mqs_mclk_sels, ARRAY_SIZE(mqs_mclk_sels)); 703+ 704+ for (i = 0; i < clk_data->clk_num; i++) { 705+ if (IS_ERR(clks[i])) 706+ pr_warn("i.MX clk %u: register failed with %ld\n", 707+ i, PTR_ERR(clks[i])); 708+ } 709+ 710+ ret = of_clk_add_provider(np, of_clk_src_onecell_get, clk_data); 711+ 712+ pm_runtime_put_sync(&pdev->dev); 713+ 714+ return ret; 715+} 716+ 717+static int imx8dxl_acm_clk_remove(struct platform_device *pdev) 718+{ 719+ struct imx8dxl_acm_priv *priv = dev_get_drvdata(&pdev->dev); 720+ 721+ pm_runtime_disable(&pdev->dev); 722+ 723+ clk_imx_acm_detach_pm_domains(&pdev->dev, &priv->dev_pm); 724+ 725+ return 0; 726+} 727+ 728+static const struct of_device_id imx8dxl_acm_match[] = { 729+ { .compatible = "nxp,imx8dxl-acm", }, 730+ { /* sentinel */ } 731+}; 732+ 733+static int __maybe_unused imx8dxl_acm_runtime_suspend(struct device *dev) 734+{ 735+ struct imx8dxl_acm_priv *priv = dev_get_drvdata(dev); 736+ 737+ priv->regs[0] = readl_relaxed(priv->reg + 0x000000); 738+ priv->regs[1] = readl_relaxed(priv->reg + 0x010000); 739+ priv->regs[2] = readl_relaxed(priv->reg + 0x020000); 740+ priv->regs[3] = readl_relaxed(priv->reg + 0x030000); 741+ priv->regs[14] = readl_relaxed(priv->reg + 0x0E0000); 742+ priv->regs[15] = readl_relaxed(priv->reg + 0x0F0000); 743+ priv->regs[16] = readl_relaxed(priv->reg + 0x100000); 744+ priv->regs[17] = readl_relaxed(priv->reg + 0x110000); 745+ priv->regs[26] = readl_relaxed(priv->reg + 0x1A0000); 746+ priv->regs[28] = readl_relaxed(priv->reg + 0x1C0000); 747+ 748+ return 0; 749+} 750+ 751+static int __maybe_unused imx8dxl_acm_runtime_resume(struct device *dev) 752+{ 753+ struct imx8dxl_acm_priv *priv = dev_get_drvdata(dev); 754+ 755+ writel_relaxed(priv->regs[0], priv->reg + 0x000000); 756+ writel_relaxed(priv->regs[1], priv->reg + 0x010000); 757+ writel_relaxed(priv->regs[2], priv->reg + 0x020000); 758+ writel_relaxed(priv->regs[3], priv->reg + 0x030000); 759+ writel_relaxed(priv->regs[14], priv->reg + 0x0E0000); 760+ writel_relaxed(priv->regs[15], priv->reg + 0x0F0000); 761+ writel_relaxed(priv->regs[16], priv->reg + 0x100000); 762+ writel_relaxed(priv->regs[17], priv->reg + 0x110000); 763+ writel_relaxed(priv->regs[26], priv->reg + 0x1A0000); 764+ writel_relaxed(priv->regs[28], priv->reg + 0x1C0000); 765+ 766+ return 0; 767+} 768+ 769+const struct dev_pm_ops imx8dxl_acm_pm_ops = { 770+ SET_RUNTIME_PM_OPS(imx8dxl_acm_runtime_suspend, 771+ imx8dxl_acm_runtime_resume, NULL) 772+ SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, 773+ pm_runtime_force_resume) 774+}; 775+ 776+static struct platform_driver imx8dxl_acm_clk_driver = { 777+ .driver = { 778+ .name = "imx8dxl-acm", 779+ .of_match_table = imx8dxl_acm_match, 780+ .pm = &imx8dxl_acm_pm_ops, 781+ .suppress_bind_attrs = true, 782+ }, 783+ .probe = imx8dxl_acm_clk_probe, 784+ .remove = imx8dxl_acm_clk_remove, 785+}; 786+ 787+static int __init imx8dxl_acm_init(void) 788+{ 789+ return platform_driver_register(&imx8dxl_acm_clk_driver); 790+} 791+fs_initcall(imx8dxl_acm_init); 792diff --git a/drivers/clk/imx/clk-imx8dxl-rsrc.c b/drivers/clk/imx/clk-imx8dxl-rsrc.c 793new file mode 100644 794index 000000000..084bad519 795--- /dev/null 796+++ b/drivers/clk/imx/clk-imx8dxl-rsrc.c 797@@ -0,0 +1,65 @@ 798+// SPDX-License-Identifier: GPL-2.0+ 799+/* 800+ * Copyright 2019~2020 NXP 801+ */ 802+ 803+#include <dt-bindings/firmware/imx/rsrc.h> 804+ 805+#include "clk-scu.h" 806+ 807+/* Keep sorted in the ascending order */ 808+static u32 imx8dxl_clk_scu_rsrc_table[] = { 809+ IMX_SC_R_SPI_0, 810+ IMX_SC_R_SPI_1, 811+ IMX_SC_R_SPI_2, 812+ IMX_SC_R_SPI_3, 813+ IMX_SC_R_UART_0, 814+ IMX_SC_R_UART_1, 815+ IMX_SC_R_UART_2, 816+ IMX_SC_R_UART_3, 817+ IMX_SC_R_I2C_0, 818+ IMX_SC_R_I2C_1, 819+ IMX_SC_R_I2C_2, 820+ IMX_SC_R_I2C_3, 821+ IMX_SC_R_ADC_0, 822+ IMX_SC_R_FTM_0, 823+ IMX_SC_R_FTM_1, 824+ IMX_SC_R_CAN_0, 825+ IMX_SC_R_LCD_0, 826+ IMX_SC_R_LCD_0_PWM_0, 827+ IMX_SC_R_PWM_0, 828+ IMX_SC_R_PWM_1, 829+ IMX_SC_R_PWM_2, 830+ IMX_SC_R_PWM_3, 831+ IMX_SC_R_PWM_4, 832+ IMX_SC_R_PWM_5, 833+ IMX_SC_R_PWM_6, 834+ IMX_SC_R_PWM_7, 835+ IMX_SC_R_GPT_0, 836+ IMX_SC_R_GPT_1, 837+ IMX_SC_R_GPT_2, 838+ IMX_SC_R_GPT_3, 839+ IMX_SC_R_GPT_4, 840+ IMX_SC_R_FSPI_0, 841+ IMX_SC_R_FSPI_1, 842+ IMX_SC_R_SDHC_0, 843+ IMX_SC_R_SDHC_1, 844+ IMX_SC_R_SDHC_2, 845+ IMX_SC_R_ENET_0, 846+ IMX_SC_R_ENET_1, 847+ IMX_SC_R_USB_1, 848+ IMX_SC_R_NAND, 849+ IMX_SC_R_M4_0_I2C, 850+ IMX_SC_R_M4_0_UART, 851+ IMX_SC_R_ELCDIF_PLL, 852+ IMX_SC_R_AUDIO_PLL_0, 853+ IMX_SC_R_AUDIO_PLL_1, 854+ IMX_SC_R_AUDIO_CLK_0, 855+ IMX_SC_R_AUDIO_CLK_1, 856+ IMX_SC_R_A35 857+}; 858+ 859+const struct imx_clk_scu_rsrc_table imx_clk_scu_rsrc_imx8dxl = { 860+ .rsrc = imx8dxl_clk_scu_rsrc_table, 861+ .num = ARRAY_SIZE(imx8dxl_clk_scu_rsrc_table), 862+}; 863diff --git a/drivers/clk/imx/clk-imx8mm.c b/drivers/clk/imx/clk-imx8mm.c 864index 711bd2294..61db2de25 100644 865--- a/drivers/clk/imx/clk-imx8mm.c 866+++ b/drivers/clk/imx/clk-imx8mm.c 867@@ -4,7 +4,9 @@ 868 */ 869 870 #include <dt-bindings/clock/imx8mm-clock.h> 871+#include <linux/clk.h> 872 #include <linux/clk-provider.h> 873+#include <linux/debugfs.h> 874 #include <linux/err.h> 875 #include <linux/io.h> 876 #include <linux/module.h> 877@@ -12,6 +14,7 @@ 878 #include <linux/platform_device.h> 879 #include <linux/slab.h> 880 #include <linux/types.h> 881+#include <soc/imx/soc.h> 882 883 #include "clk.h" 884 885@@ -291,6 +294,34 @@ static const char *imx8mm_clko2_sels[] = {"osc_24m", "sys_pll2_200m", "sys_pll1_ 886 static struct clk_hw_onecell_data *clk_hw_data; 887 static struct clk_hw **hws; 888 889+static int imx_clk_init_on(struct device_node *np, 890+ struct clk_hw * const clks[]) 891+{ 892+ u32 *array; 893+ int i, ret, elems; 894+ 895+ elems = of_property_count_u32_elems(np, "init-on-array"); 896+ if (elems < 0) 897+ return elems; 898+ array = kcalloc(elems, sizeof(elems), GFP_KERNEL); 899+ if (!array) 900+ return -ENOMEM; 901+ 902+ ret = of_property_read_u32_array(np, "init-on-array", array, elems); 903+ if (ret) 904+ return ret; 905+ 906+ for (i = 0; i < elems; i++) { 907+ ret = clk_prepare_enable(clks[array[i]]->clk); 908+ if (ret) 909+ pr_err("clk_prepare_enable failed %d\n", array[i]); 910+ } 911+ 912+ kfree(array); 913+ 914+ return 0; 915+} 916+ 917 static int imx8mm_clocks_probe(struct platform_device *pdev) 918 { 919 struct device *dev = &pdev->dev; 920@@ -298,6 +329,8 @@ static int imx8mm_clocks_probe(struct platform_device *pdev) 921 void __iomem *base; 922 int ret; 923 924+ check_m4_enabled(); 925+ 926 clk_hw_data = kzalloc(struct_size(clk_hw_data, hws, 927 IMX8MM_CLK_END), GFP_KERNEL); 928 if (WARN_ON(!clk_hw_data)) 929@@ -361,45 +394,29 @@ static int imx8mm_clocks_probe(struct platform_device *pdev) 930 hws[IMX8MM_SYS_PLL3_OUT] = imx_clk_hw_gate("sys_pll3_out", "sys_pll3_bypass", base + 0x114, 11); 931 932 /* SYS PLL1 fixed output */ 933- hws[IMX8MM_SYS_PLL1_40M_CG] = imx_clk_hw_gate("sys_pll1_40m_cg", "sys_pll1", base + 0x94, 27); 934- hws[IMX8MM_SYS_PLL1_80M_CG] = imx_clk_hw_gate("sys_pll1_80m_cg", "sys_pll1", base + 0x94, 25); 935- hws[IMX8MM_SYS_PLL1_100M_CG] = imx_clk_hw_gate("sys_pll1_100m_cg", "sys_pll1", base + 0x94, 23); 936- hws[IMX8MM_SYS_PLL1_133M_CG] = imx_clk_hw_gate("sys_pll1_133m_cg", "sys_pll1", base + 0x94, 21); 937- hws[IMX8MM_SYS_PLL1_160M_CG] = imx_clk_hw_gate("sys_pll1_160m_cg", "sys_pll1", base + 0x94, 19); 938- hws[IMX8MM_SYS_PLL1_200M_CG] = imx_clk_hw_gate("sys_pll1_200m_cg", "sys_pll1", base + 0x94, 17); 939- hws[IMX8MM_SYS_PLL1_266M_CG] = imx_clk_hw_gate("sys_pll1_266m_cg", "sys_pll1", base + 0x94, 15); 940- hws[IMX8MM_SYS_PLL1_400M_CG] = imx_clk_hw_gate("sys_pll1_400m_cg", "sys_pll1", base + 0x94, 13); 941 hws[IMX8MM_SYS_PLL1_OUT] = imx_clk_hw_gate("sys_pll1_out", "sys_pll1", base + 0x94, 11); 942 943- hws[IMX8MM_SYS_PLL1_40M] = imx_clk_hw_fixed_factor("sys_pll1_40m", "sys_pll1_40m_cg", 1, 20); 944- hws[IMX8MM_SYS_PLL1_80M] = imx_clk_hw_fixed_factor("sys_pll1_80m", "sys_pll1_80m_cg", 1, 10); 945- hws[IMX8MM_SYS_PLL1_100M] = imx_clk_hw_fixed_factor("sys_pll1_100m", "sys_pll1_100m_cg", 1, 8); 946- hws[IMX8MM_SYS_PLL1_133M] = imx_clk_hw_fixed_factor("sys_pll1_133m", "sys_pll1_133m_cg", 1, 6); 947- hws[IMX8MM_SYS_PLL1_160M] = imx_clk_hw_fixed_factor("sys_pll1_160m", "sys_pll1_160m_cg", 1, 5); 948- hws[IMX8MM_SYS_PLL1_200M] = imx_clk_hw_fixed_factor("sys_pll1_200m", "sys_pll1_200m_cg", 1, 4); 949- hws[IMX8MM_SYS_PLL1_266M] = imx_clk_hw_fixed_factor("sys_pll1_266m", "sys_pll1_266m_cg", 1, 3); 950- hws[IMX8MM_SYS_PLL1_400M] = imx_clk_hw_fixed_factor("sys_pll1_400m", "sys_pll1_400m_cg", 1, 2); 951+ hws[IMX8MM_SYS_PLL1_40M] = imx_clk_hw_fixed_factor("sys_pll1_40m", "sys_pll1_out", 1, 20); 952+ hws[IMX8MM_SYS_PLL1_80M] = imx_clk_hw_fixed_factor("sys_pll1_80m", "sys_pll1_out", 1, 10); 953+ hws[IMX8MM_SYS_PLL1_100M] = imx_clk_hw_fixed_factor("sys_pll1_100m", "sys_pll1_out", 1, 8); 954+ hws[IMX8MM_SYS_PLL1_133M] = imx_clk_hw_fixed_factor("sys_pll1_133m", "sys_pll1_out", 1, 6); 955+ hws[IMX8MM_SYS_PLL1_160M] = imx_clk_hw_fixed_factor("sys_pll1_160m", "sys_pll1_out", 1, 5); 956+ hws[IMX8MM_SYS_PLL1_200M] = imx_clk_hw_fixed_factor("sys_pll1_200m", "sys_pll1_out", 1, 4); 957+ hws[IMX8MM_SYS_PLL1_266M] = imx_clk_hw_fixed_factor("sys_pll1_266m", "sys_pll1_out", 1, 3); 958+ hws[IMX8MM_SYS_PLL1_400M] = imx_clk_hw_fixed_factor("sys_pll1_400m", "sys_pll1_out", 1, 2); 959 hws[IMX8MM_SYS_PLL1_800M] = imx_clk_hw_fixed_factor("sys_pll1_800m", "sys_pll1_out", 1, 1); 960 961 /* SYS PLL2 fixed output */ 962- hws[IMX8MM_SYS_PLL2_50M_CG] = imx_clk_hw_gate("sys_pll2_50m_cg", "sys_pll2", base + 0x104, 27); 963- hws[IMX8MM_SYS_PLL2_100M_CG] = imx_clk_hw_gate("sys_pll2_100m_cg", "sys_pll2", base + 0x104, 25); 964- hws[IMX8MM_SYS_PLL2_125M_CG] = imx_clk_hw_gate("sys_pll2_125m_cg", "sys_pll2", base + 0x104, 23); 965- hws[IMX8MM_SYS_PLL2_166M_CG] = imx_clk_hw_gate("sys_pll2_166m_cg", "sys_pll2", base + 0x104, 21); 966- hws[IMX8MM_SYS_PLL2_200M_CG] = imx_clk_hw_gate("sys_pll2_200m_cg", "sys_pll2", base + 0x104, 19); 967- hws[IMX8MM_SYS_PLL2_250M_CG] = imx_clk_hw_gate("sys_pll2_250m_cg", "sys_pll2", base + 0x104, 17); 968- hws[IMX8MM_SYS_PLL2_333M_CG] = imx_clk_hw_gate("sys_pll2_333m_cg", "sys_pll2", base + 0x104, 15); 969- hws[IMX8MM_SYS_PLL2_500M_CG] = imx_clk_hw_gate("sys_pll2_500m_cg", "sys_pll2", base + 0x104, 13); 970 hws[IMX8MM_SYS_PLL2_OUT] = imx_clk_hw_gate("sys_pll2_out", "sys_pll2", base + 0x104, 11); 971 972- hws[IMX8MM_SYS_PLL2_50M] = imx_clk_hw_fixed_factor("sys_pll2_50m", "sys_pll2_50m_cg", 1, 20); 973- hws[IMX8MM_SYS_PLL2_100M] = imx_clk_hw_fixed_factor("sys_pll2_100m", "sys_pll2_100m_cg", 1, 10); 974- hws[IMX8MM_SYS_PLL2_125M] = imx_clk_hw_fixed_factor("sys_pll2_125m", "sys_pll2_125m_cg", 1, 8); 975- hws[IMX8MM_SYS_PLL2_166M] = imx_clk_hw_fixed_factor("sys_pll2_166m", "sys_pll2_166m_cg", 1, 6); 976- hws[IMX8MM_SYS_PLL2_200M] = imx_clk_hw_fixed_factor("sys_pll2_200m", "sys_pll2_200m_cg", 1, 5); 977- hws[IMX8MM_SYS_PLL2_250M] = imx_clk_hw_fixed_factor("sys_pll2_250m", "sys_pll2_250m_cg", 1, 4); 978- hws[IMX8MM_SYS_PLL2_333M] = imx_clk_hw_fixed_factor("sys_pll2_333m", "sys_pll2_333m_cg", 1, 3); 979- hws[IMX8MM_SYS_PLL2_500M] = imx_clk_hw_fixed_factor("sys_pll2_500m", "sys_pll2_500m_cg", 1, 2); 980+ hws[IMX8MM_SYS_PLL2_50M] = imx_clk_hw_fixed_factor("sys_pll2_50m", "sys_pll2_out", 1, 20); 981+ hws[IMX8MM_SYS_PLL2_100M] = imx_clk_hw_fixed_factor("sys_pll2_100m", "sys_pll2_out", 1, 10); 982+ hws[IMX8MM_SYS_PLL2_125M] = imx_clk_hw_fixed_factor("sys_pll2_125m", "sys_pll2_out", 1, 8); 983+ hws[IMX8MM_SYS_PLL2_166M] = imx_clk_hw_fixed_factor("sys_pll2_166m", "sys_pll2_out", 1, 6); 984+ hws[IMX8MM_SYS_PLL2_200M] = imx_clk_hw_fixed_factor("sys_pll2_200m", "sys_pll2_out", 1, 5); 985+ hws[IMX8MM_SYS_PLL2_250M] = imx_clk_hw_fixed_factor("sys_pll2_250m", "sys_pll2_out", 1, 4); 986+ hws[IMX8MM_SYS_PLL2_333M] = imx_clk_hw_fixed_factor("sys_pll2_333m", "sys_pll2_out", 1, 3); 987+ hws[IMX8MM_SYS_PLL2_500M] = imx_clk_hw_fixed_factor("sys_pll2_500m", "sys_pll2_out", 1, 2); 988 hws[IMX8MM_SYS_PLL2_1000M] = imx_clk_hw_fixed_factor("sys_pll2_1000m", "sys_pll2_out", 1, 1); 989 990 np = dev->of_node; 991@@ -437,7 +454,7 @@ static int imx8mm_clocks_probe(struct platform_device *pdev) 992 /* BUS */ 993 hws[IMX8MM_CLK_MAIN_AXI] = imx8m_clk_hw_composite_bus_critical("main_axi", imx8mm_main_axi_sels, base + 0x8800); 994 hws[IMX8MM_CLK_ENET_AXI] = imx8m_clk_hw_composite_bus("enet_axi", imx8mm_enet_axi_sels, base + 0x8880); 995- hws[IMX8MM_CLK_NAND_USDHC_BUS] = imx8m_clk_hw_composite_bus_critical("nand_usdhc_bus", imx8mm_nand_usdhc_sels, base + 0x8900); 996+ hws[IMX8MM_CLK_NAND_USDHC_BUS] = imx8m_clk_hw_composite("nand_usdhc_bus", imx8mm_nand_usdhc_sels, base + 0x8900); 997 hws[IMX8MM_CLK_VPU_BUS] = imx8m_clk_hw_composite_bus("vpu_bus", imx8mm_vpu_bus_sels, base + 0x8980); 998 hws[IMX8MM_CLK_DISP_AXI] = imx8m_clk_hw_composite_bus("disp_axi", imx8mm_disp_axi_sels, base + 0x8a00); 999 hws[IMX8MM_CLK_DISP_APB] = imx8m_clk_hw_composite_bus("disp_apb", imx8mm_disp_apb_sels, base + 0x8a80); 1000@@ -565,7 +582,7 @@ static int imx8mm_clocks_probe(struct platform_device *pdev) 1001 hws[IMX8MM_CLK_SAI5_IPG] = imx_clk_hw_gate2_shared2("sai5_ipg_clk", "ipg_audio_root", base + 0x4370, 0, &share_count_sai5); 1002 hws[IMX8MM_CLK_SAI6_ROOT] = imx_clk_hw_gate2_shared2("sai6_root_clk", "sai6", base + 0x4380, 0, &share_count_sai6); 1003 hws[IMX8MM_CLK_SAI6_IPG] = imx_clk_hw_gate2_shared2("sai6_ipg_clk", "ipg_audio_root", base + 0x4380, 0, &share_count_sai6); 1004- hws[IMX8MM_CLK_SNVS_ROOT] = imx_clk_hw_gate4("snvs_root_clk", "ipg_root", base + 0x4470, 0); 1005+ hws[IMX8MM_CLK_SNVS_ROOT] = imx_clk_hw_gate2_flags("snvs_root_clk", "ipg_root", base + 0x4470, 0, CLK_IS_CRITICAL); 1006 hws[IMX8MM_CLK_UART1_ROOT] = imx_clk_hw_gate4("uart1_root_clk", "uart1", base + 0x4490, 0); 1007 hws[IMX8MM_CLK_UART2_ROOT] = imx_clk_hw_gate4("uart2_root_clk", "uart2", base + 0x44a0, 0); 1008 hws[IMX8MM_CLK_UART3_ROOT] = imx_clk_hw_gate4("uart3_root_clk", "uart3", base + 0x44b0, 0); 1009@@ -615,6 +632,12 @@ static int imx8mm_clocks_probe(struct platform_device *pdev) 1010 goto unregister_hws; 1011 } 1012 1013+ imx_clk_init_on(np, hws); 1014+ 1015+ clk_set_parent(hws[IMX8MM_CLK_CSI1_CORE]->clk, hws[IMX8MM_SYS_PLL2_1000M]->clk); 1016+ clk_set_parent(hws[IMX8MM_CLK_CSI1_PHY_REF]->clk, hws[IMX8MM_SYS_PLL2_1000M]->clk); 1017+ clk_set_parent(hws[IMX8MM_CLK_CSI1_ESC]->clk, hws[IMX8MM_SYS_PLL1_800M]->clk); 1018+ 1019 imx_register_uart_clocks(4); 1020 1021 return 0; 1022@@ -645,6 +668,81 @@ static struct platform_driver imx8mm_clk_driver = { 1023 }; 1024 module_platform_driver(imx8mm_clk_driver); 1025 1026+/* 1027+ * Debugfs interface for audio PLL K divider change dynamically. 1028+ * Monitor control for the Audio PLL K-Divider 1029+ */ 1030+#ifdef CONFIG_DEBUG_FS 1031+ 1032+#define KDIV_MASK GENMASK(15, 0) 1033+#define MDIV_SHIFT 12 1034+#define MDIV_MASK GENMASK(21, 12) 1035+#define PDIV_SHIFT 4 1036+#define PDIV_MASK GENMASK(9, 4) 1037+#define SDIV_SHIFT 0 1038+#define SDIV_MASK GENMASK(2, 0) 1039+ 1040+static int pll_delta_k_set(void *data, u64 val) 1041+{ 1042+ struct clk_hw *hw; 1043+ short int delta_k; 1044+ 1045+ hw = data; 1046+ delta_k = (short int) (val & KDIV_MASK); 1047+ 1048+ clk_set_delta_k(hw, val); 1049+ 1050+ pr_debug("the delta k is %d\n", delta_k); 1051+ return 0; 1052+} 1053+DEFINE_DEBUGFS_ATTRIBUTE(delta_k_fops, NULL, pll_delta_k_set, "%lld\n"); 1054+ 1055+static int pll_setting_show(struct seq_file *s, void *data) 1056+{ 1057+ struct clk_hw *hw; 1058+ u32 pll_div_ctrl0, pll_div_ctrl1; 1059+ u32 mdiv, pdiv, sdiv, kdiv; 1060+ 1061+ hw = s->private;; 1062+ 1063+ clk_get_pll_setting(hw, &pll_div_ctrl0, &pll_div_ctrl1); 1064+ mdiv = (pll_div_ctrl0 & MDIV_MASK) >> MDIV_SHIFT; 1065+ pdiv = (pll_div_ctrl0 & PDIV_MASK) >> PDIV_SHIFT; 1066+ sdiv = (pll_div_ctrl0 & SDIV_MASK) >> SDIV_SHIFT; 1067+ kdiv = (pll_div_ctrl1 & KDIV_MASK); 1068+ 1069+ seq_printf(s, "Mdiv: 0x%x; Pdiv: 0x%x; Sdiv: 0x%x; Kdiv: 0x%x\n", 1070+ mdiv, pdiv, sdiv, kdiv); 1071+ 1072+ return 0; 1073+} 1074+DEFINE_SHOW_ATTRIBUTE(pll_setting); 1075+ 1076+static int __init pll_debug_init(void) 1077+{ 1078+ struct dentry *root, *audio_pll1, *audio_pll2; 1079+ 1080+ if (of_machine_is_compatible("fsl,imx8mm") && hws) { 1081+ /* create a root dir for audio pll monitor */ 1082+ root = debugfs_create_dir("audio_pll_monitor", NULL); 1083+ audio_pll1 = debugfs_create_dir("audio_pll1", root); 1084+ audio_pll2 = debugfs_create_dir("audio_pll2", root); 1085+ 1086+ debugfs_create_file_unsafe("delta_k", 0444, audio_pll1, 1087+ hws[IMX8MM_AUDIO_PLL1], &delta_k_fops); 1088+ debugfs_create_file("pll_parameter", 0x444, audio_pll1, 1089+ hws[IMX8MM_AUDIO_PLL1], &pll_setting_fops); 1090+ debugfs_create_file_unsafe("delta_k", 0444, audio_pll2, 1091+ hws[IMX8MM_AUDIO_PLL2], &delta_k_fops); 1092+ debugfs_create_file("pll_parameter", 0x444, audio_pll2, 1093+ hws[IMX8MM_AUDIO_PLL2], &pll_setting_fops); 1094+ } 1095+ 1096+ return 0; 1097+} 1098+late_initcall(pll_debug_init); 1099+#endif /* CONFIG_DEBUG_FS */ 1100+ 1101 MODULE_AUTHOR("Bai Ping <ping.bai@nxp.com>"); 1102 MODULE_DESCRIPTION("NXP i.MX8MM clock driver"); 1103 MODULE_LICENSE("GPL v2"); 1104diff --git a/drivers/clk/imx/clk-imx8qm-acm.c b/drivers/clk/imx/clk-imx8qm-acm.c 1105new file mode 100644 1106index 000000000..d531294e7 1107--- /dev/null 1108+++ b/drivers/clk/imx/clk-imx8qm-acm.c 1109@@ -0,0 +1,297 @@ 1110+// SPDX-License-Identifier: GPL-2.0+ 1111+/* 1112+ * Copyright 2018 NXP 1113+ * Dong Aisheng <aisheng.dong@nxp.com> 1114+ */ 1115+ 1116+#include <linux/clk-provider.h> 1117+#include <linux/err.h> 1118+#include <linux/io.h> 1119+#include <linux/module.h> 1120+#include <linux/of.h> 1121+#include <linux/of_device.h> 1122+#include <linux/platform_device.h> 1123+#include <linux/slab.h> 1124+#include <linux/pm_domain.h> 1125+#include <linux/pm_runtime.h> 1126+ 1127+#include "clk.h" 1128+#include "clk-scu.h" 1129+#include "clk-imx-acm-utils.h" 1130+ 1131+#include <dt-bindings/clock/imx8-clock.h> 1132+ 1133+struct imx8qm_acm_priv { 1134+ struct clk_imx_acm_pm_domains dev_pm; 1135+ void __iomem *reg; 1136+ u32 regs[32]; 1137+}; 1138+ 1139+static const char *aud_clk_sels[] = { 1140+ "aud_rec_clk0_lpcg_clk", 1141+ "aud_rec_clk1_lpcg_clk", 1142+ "dummy", 1143+ "hdmi_rx_mclk", 1144+ "ext_aud_mclk0", 1145+ "ext_aud_mclk1", 1146+ "esai0_rx_clk", 1147+ "esai0_rx_hf_clk", 1148+ "esai0_tx_clk", 1149+ "esai0_tx_hf_clk", 1150+ "esai1_rx_clk", 1151+ "esai1_rx_hf_clk", 1152+ "esai1_tx_clk", 1153+ "esai1_tx_hf_clk", 1154+ "spdif0_rx", 1155+ "spdif1_rx", 1156+ "sai0_rx_bclk", 1157+ "sai0_tx_bclk", 1158+ "sai1_rx_bclk", 1159+ "sai1_tx_bclk", 1160+ "sai2_rx_bclk", 1161+ "sai3_rx_bclk", 1162+ "sai4_rx_bclk", 1163+}; 1164+ 1165+static const char *mclk_out_sels[] = { 1166+ "aud_rec_clk0_lpcg_clk", 1167+ "aud_rec_clk1_lpcg_clk", 1168+ "dummy", 1169+ "hdmi_rx_mclk", 1170+ "spdif0_rx", 1171+ "spdif1_rx", 1172+ "sai4_rx_bclk", 1173+ "sai6_rx_bclk", 1174+}; 1175+ 1176+static const char *sai_mclk_sels[] = { 1177+ "aud_pll_div_clk0_lpcg_clk", 1178+ "aud_pll_div_clk1_lpcg_clk", 1179+ "acm_aud_clk0_sel", 1180+ "acm_aud_clk1_sel", 1181+}; 1182+ 1183+static const char *asrc_mux_clk_sels[] = { 1184+ "sai4_rx_bclk", 1185+ "sai5_tx_bclk", 1186+ "dummy", 1187+ "dummy", 1188+}; 1189+ 1190+static const char *esai_mclk_sels[] = { 1191+ "aud_pll_div_clk0_lpcg_clk", 1192+ "aud_pll_div_clk1_lpcg_clk", 1193+ "acm_aud_clk0_sel", 1194+ "acm_aud_clk1_sel", 1195+}; 1196+ 1197+static const char *spdif_mclk_sels[] = { 1198+ "aud_pll_div_clk0_lpcg_clk", 1199+ "aud_pll_div_clk1_lpcg_clk", 1200+ "acm_aud_clk0_sel", 1201+ "acm_aud_clk1_sel", 1202+}; 1203+ 1204+static const char *mqs_mclk_sels[] = { 1205+ "aud_pll_div_clk0_lpcg_clk", 1206+ "aud_pll_div_clk1_lpcg_clk", 1207+ "acm_aud_clk0_sel", 1208+ "acm_aud_clk1_sel", 1209+}; 1210+ 1211+static int imx8qm_acm_clk_probe(struct platform_device *pdev) 1212+{ 1213+ struct device *dev = &pdev->dev; 1214+ struct device_node *np = dev->of_node; 1215+ struct clk_onecell_data *clk_data; 1216+ struct imx8qm_acm_priv *priv; 1217+ struct resource *res; 1218+ struct clk **clks; 1219+ void __iomem *base; 1220+ int ret; 1221+ int i; 1222+ 1223+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1224+ base = devm_ioremap(dev, res->start, resource_size(res)); 1225+ if (!base) 1226+ return -ENOMEM; 1227+ 1228+ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); 1229+ if (!priv) 1230+ return -ENOMEM; 1231+ 1232+ priv->reg = base; 1233+ 1234+ platform_set_drvdata(pdev, priv); 1235+ 1236+ clk_data = devm_kzalloc(&pdev->dev, sizeof(*clk_data), GFP_KERNEL); 1237+ if (!clk_data) 1238+ return -ENOMEM; 1239+ 1240+ clk_data->clks = devm_kcalloc(&pdev->dev, IMX_ADMA_ACM_CLK_END, 1241+ sizeof(*clk_data->clks), GFP_KERNEL); 1242+ if (!clk_data->clks) 1243+ return -ENOMEM; 1244+ 1245+ clk_data->clk_num = IMX_ADMA_ACM_CLK_END; 1246+ 1247+ clks = clk_data->clks; 1248+ 1249+ ret = clk_imx_acm_attach_pm_domains(&pdev->dev, &priv->dev_pm); 1250+ if (ret) 1251+ return ret; 1252+ 1253+ pm_runtime_enable(&pdev->dev); 1254+ pm_runtime_get_sync(&pdev->dev); 1255+ 1256+ clks[IMX_ADMA_EXT_AUD_MCLK0] = imx_clk_fixed("ext_aud_mclk0", 0); 1257+ clks[IMX_ADMA_EXT_AUD_MCLK1] = imx_clk_fixed("ext_aud_mclk1", 0); 1258+ clks[IMX_ADMA_ESAI0_RX_CLK] = imx_clk_fixed("esai0_rx_clk", 0); 1259+ clks[IMX_ADMA_ESAI0_RX_HF_CLK] = imx_clk_fixed("esai0_rx_hf_clk", 0); 1260+ clks[IMX_ADMA_ESAI0_TX_CLK] = imx_clk_fixed("esai0_tx_clk", 0); 1261+ clks[IMX_ADMA_ESAI0_TX_HF_CLK] = imx_clk_fixed("esai0_tx_hf_clk", 0); 1262+ clks[IMX_ADMA_ESAI1_RX_CLK] = imx_clk_fixed("esai1_rx_clk", 0); 1263+ clks[IMX_ADMA_ESAI1_RX_HF_CLK] = imx_clk_fixed("esai1_rx_hf_clk", 0); 1264+ clks[IMX_ADMA_ESAI1_TX_CLK] = imx_clk_fixed("esai1_tx_clk", 0); 1265+ clks[IMX_ADMA_ESAI1_TX_HF_CLK] = imx_clk_fixed("esai1_tx_hf_clk", 0); 1266+ clks[IMX_ADMA_SPDIF0_RX] = imx_clk_fixed("spdif0_rx", 0); 1267+ clks[IMX_ADMA_SPDIF1_RX] = imx_clk_fixed("spdif1_rx", 0); 1268+ clks[IMX_ADMA_SAI0_RX_BCLK] = imx_clk_fixed("sai0_rx_bclk", 0); 1269+ clks[IMX_ADMA_SAI0_TX_BCLK] = imx_clk_fixed("sai0_tx_bclk", 0); 1270+ clks[IMX_ADMA_SAI1_RX_BCLK] = imx_clk_fixed("sai1_rx_bclk", 0); 1271+ clks[IMX_ADMA_SAI1_TX_BCLK] = imx_clk_fixed("sai1_tx_bclk", 0); 1272+ clks[IMX_ADMA_SAI2_RX_BCLK] = imx_clk_fixed("sai2_rx_bclk", 0); 1273+ clks[IMX_ADMA_SAI3_RX_BCLK] = imx_clk_fixed("sai3_rx_bclk", 0); 1274+ clks[IMX_ADMA_SAI4_RX_BCLK] = imx_clk_fixed("sai4_rx_bclk", 0); 1275+ clks[IMX_ADMA_SAI5_TX_BCLK] = imx_clk_fixed("sai5_tx_bclk", 0); 1276+ clks[IMX_ADMA_SAI6_RX_BCLK] = imx_clk_fixed("sai6_rx_bclk", 0); 1277+ clks[IMX_ADMA_HDMI_RX_MCLK] = imx_clk_fixed("hdmi_rx_mclk", 0); 1278+ 1279+ 1280+ clks[IMX_ADMA_ACM_AUD_CLK0_SEL] = imx_dev_clk_mux(dev, "acm_aud_clk0_sel", base+0x000000, 0, 5, aud_clk_sels, ARRAY_SIZE(aud_clk_sels)); 1281+ clks[IMX_ADMA_ACM_AUD_CLK1_SEL] = imx_dev_clk_mux(dev, "acm_aud_clk1_sel", base+0x010000, 0, 5, aud_clk_sels, ARRAY_SIZE(aud_clk_sels)); 1282+ 1283+ clks[IMX_ADMA_ACM_MCLKOUT0_SEL] = imx_dev_clk_mux(dev, "acm_mclkout0_sel", base+0x020000, 0, 3, mclk_out_sels, ARRAY_SIZE(mclk_out_sels)); 1284+ clks[IMX_ADMA_ACM_MCLKOUT1_SEL] = imx_dev_clk_mux(dev, "acm_mclkout1_sel", base+0x030000, 0, 3, mclk_out_sels, ARRAY_SIZE(mclk_out_sels)); 1285+ 1286+ clks[IMX_ADMA_ACM_ASRC0_MUX_CLK_SEL] = imx_dev_clk_mux(dev, "acm_asrc0_mclk_sel", base+0x040000, 0, 2, asrc_mux_clk_sels, ARRAY_SIZE(asrc_mux_clk_sels)); 1287+ 1288+ clks[IMX_ADMA_ACM_ESAI0_MCLK_SEL] = imx_dev_clk_mux(dev, "acm_esai0_mclk_sel", base+0x060000, 0, 2, esai_mclk_sels, ARRAY_SIZE(esai_mclk_sels)); 1289+ clks[IMX_ADMA_ACM_ESAI1_MCLK_SEL] = imx_dev_clk_mux(dev, "acm_esai1_mclk_sel", base+0x070000, 0, 2, esai_mclk_sels, ARRAY_SIZE(esai_mclk_sels)); 1290+ clks[IMX_ADMA_ACM_SAI0_MCLK_SEL] = imx_dev_clk_mux(dev, "acm_sai0_mclk_sel", base+0x0E0000, 0, 2, sai_mclk_sels, ARRAY_SIZE(sai_mclk_sels)); 1291+ clks[IMX_ADMA_ACM_SAI1_MCLK_SEL] = imx_dev_clk_mux(dev, "acm_sai1_mclk_sel", base+0x0F0000, 0, 2, sai_mclk_sels, ARRAY_SIZE(sai_mclk_sels)); 1292+ clks[IMX_ADMA_ACM_SAI2_MCLK_SEL] = imx_dev_clk_mux(dev, "acm_sai2_mclk_sel", base+0x100000, 0, 2, sai_mclk_sels, ARRAY_SIZE(sai_mclk_sels)); 1293+ clks[IMX_ADMA_ACM_SAI3_MCLK_SEL] = imx_dev_clk_mux(dev, "acm_sai3_mclk_sel", base+0x110000, 0, 2, sai_mclk_sels, ARRAY_SIZE(sai_mclk_sels)); 1294+ clks[IMX_ADMA_ACM_SAI4_MCLK_SEL] = imx_dev_clk_mux(dev, "acm_sai4_mclk_sel", base+0x120000, 0, 2, sai_mclk_sels, ARRAY_SIZE(sai_mclk_sels)); 1295+ clks[IMX_ADMA_ACM_SAI5_MCLK_SEL] = imx_dev_clk_mux(dev, "acm_sai5_mclk_sel", base+0x130000, 0, 2, sai_mclk_sels, ARRAY_SIZE(sai_mclk_sels)); 1296+ clks[IMX_ADMA_ACM_SAI6_MCLK_SEL] = imx_dev_clk_mux(dev, "acm_sai6_mclk_sel", base+0x140000, 0, 2, sai_mclk_sels, ARRAY_SIZE(sai_mclk_sels)); 1297+ clks[IMX_ADMA_ACM_SAI7_MCLK_SEL] = imx_dev_clk_mux(dev, "acm_sai7_mclk_sel", base+0x150000, 0, 2, sai_mclk_sels, ARRAY_SIZE(sai_mclk_sels)); 1298+ 1299+ clks[IMX_ADMA_ACM_SPDIF0_TX_CLK_SEL] = imx_dev_clk_mux(dev, "acm_spdif0_mclk_sel", base+0x1A0000, 0, 2, spdif_mclk_sels, ARRAY_SIZE(spdif_mclk_sels)); 1300+ clks[IMX_ADMA_ACM_SPDIF1_TX_CLK_SEL] = imx_dev_clk_mux(dev, "acm_spdif1_mclk_sel", base+0x1B0000, 0, 2, spdif_mclk_sels, ARRAY_SIZE(spdif_mclk_sels)); 1301+ clks[IMX_ADMA_ACM_MQS_TX_CLK_SEL] = imx_dev_clk_mux(dev, "acm_mqs_mclk_sel", base+0x1C0000, 0, 2, mqs_mclk_sels, ARRAY_SIZE(mqs_mclk_sels)); 1302+ 1303+ for (i = 0; i < clk_data->clk_num; i++) { 1304+ if (IS_ERR(clks[i])) 1305+ pr_warn("i.MX clk %u: register failed with %ld\n", 1306+ i, PTR_ERR(clks[i])); 1307+ } 1308+ 1309+ ret = of_clk_add_provider(np, of_clk_src_onecell_get, clk_data); 1310+ 1311+ pm_runtime_put_sync(&pdev->dev); 1312+ 1313+ return ret; 1314+} 1315+ 1316+static int imx8qm_acm_clk_remove(struct platform_device *pdev) 1317+{ 1318+ struct imx8qm_acm_priv *priv = dev_get_drvdata(&pdev->dev); 1319+ 1320+ pm_runtime_disable(&pdev->dev); 1321+ 1322+ clk_imx_acm_detach_pm_domains(&pdev->dev, &priv->dev_pm); 1323+ 1324+ return 0; 1325+} 1326+ 1327+static const struct of_device_id imx8qm_acm_match[] = { 1328+ { .compatible = "nxp,imx8qm-acm", }, 1329+ { /* sentinel */ } 1330+}; 1331+ 1332+static int __maybe_unused imx8qm_acm_runtime_suspend(struct device *dev) 1333+{ 1334+ struct imx8qm_acm_priv *priv = dev_get_drvdata(dev); 1335+ 1336+ priv->regs[0] = readl_relaxed(priv->reg + 0x000000); 1337+ priv->regs[1] = readl_relaxed(priv->reg + 0x010000); 1338+ priv->regs[2] = readl_relaxed(priv->reg + 0x020000); 1339+ priv->regs[3] = readl_relaxed(priv->reg + 0x030000); 1340+ priv->regs[4] = readl_relaxed(priv->reg + 0x040000); 1341+ priv->regs[6] = readl_relaxed(priv->reg + 0x060000); 1342+ priv->regs[7] = readl_relaxed(priv->reg + 0x070000); 1343+ priv->regs[14] = readl_relaxed(priv->reg + 0x0E0000); 1344+ priv->regs[15] = readl_relaxed(priv->reg + 0x0F0000); 1345+ priv->regs[16] = readl_relaxed(priv->reg + 0x100000); 1346+ priv->regs[17] = readl_relaxed(priv->reg + 0x110000); 1347+ priv->regs[18] = readl_relaxed(priv->reg + 0x120000); 1348+ priv->regs[19] = readl_relaxed(priv->reg + 0x130000); 1349+ priv->regs[20] = readl_relaxed(priv->reg + 0x140000); 1350+ priv->regs[21] = readl_relaxed(priv->reg + 0x150000); 1351+ priv->regs[26] = readl_relaxed(priv->reg + 0x1A0000); 1352+ priv->regs[27] = readl_relaxed(priv->reg + 0x1B0000); 1353+ priv->regs[28] = readl_relaxed(priv->reg + 0x1C0000); 1354+ 1355+ return 0; 1356+} 1357+ 1358+static int __maybe_unused imx8qm_acm_runtime_resume(struct device *dev) 1359+{ 1360+ struct imx8qm_acm_priv *priv = dev_get_drvdata(dev); 1361+ 1362+ writel_relaxed(priv->regs[0], priv->reg + 0x000000); 1363+ writel_relaxed(priv->regs[1], priv->reg + 0x010000); 1364+ writel_relaxed(priv->regs[2], priv->reg + 0x020000); 1365+ writel_relaxed(priv->regs[3], priv->reg + 0x030000); 1366+ writel_relaxed(priv->regs[4], priv->reg + 0x040000); 1367+ writel_relaxed(priv->regs[6], priv->reg + 0x060000); 1368+ writel_relaxed(priv->regs[7], priv->reg + 0x070000); 1369+ writel_relaxed(priv->regs[14], priv->reg + 0x0E0000); 1370+ writel_relaxed(priv->regs[15], priv->reg + 0x0F0000); 1371+ writel_relaxed(priv->regs[16], priv->reg + 0x100000); 1372+ writel_relaxed(priv->regs[17], priv->reg + 0x110000); 1373+ writel_relaxed(priv->regs[18], priv->reg + 0x120000); 1374+ writel_relaxed(priv->regs[19], priv->reg + 0x130000); 1375+ writel_relaxed(priv->regs[20], priv->reg + 0x140000); 1376+ writel_relaxed(priv->regs[21], priv->reg + 0x150000); 1377+ writel_relaxed(priv->regs[26], priv->reg + 0x1A0000); 1378+ writel_relaxed(priv->regs[27], priv->reg + 0x1B0000); 1379+ writel_relaxed(priv->regs[28], priv->reg + 0x1C0000); 1380+ 1381+ return 0; 1382+} 1383+ 1384+static const struct dev_pm_ops imx8qm_acm_pm_ops = { 1385+ SET_RUNTIME_PM_OPS(imx8qm_acm_runtime_suspend, 1386+ imx8qm_acm_runtime_resume, NULL) 1387+ SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, 1388+ pm_runtime_force_resume) 1389+}; 1390+ 1391+static struct platform_driver imx8qm_acm_clk_driver = { 1392+ .driver = { 1393+ .name = "imx8qm-acm", 1394+ .of_match_table = imx8qm_acm_match, 1395+ .pm = &imx8qm_acm_pm_ops, 1396+ .suppress_bind_attrs = true, 1397+ }, 1398+ .probe = imx8qm_acm_clk_probe, 1399+ .remove = imx8qm_acm_clk_remove, 1400+}; 1401+ 1402+static int __init imx8qm_acm_init(void) 1403+{ 1404+ return platform_driver_register(&imx8qm_acm_clk_driver); 1405+} 1406+fs_initcall(imx8qm_acm_init); 1407diff --git a/drivers/clk/imx/clk-imx8qm-rsrc.c b/drivers/clk/imx/clk-imx8qm-rsrc.c 1408new file mode 100644 1409index 000000000..5943f51c4 1410--- /dev/null 1411+++ b/drivers/clk/imx/clk-imx8qm-rsrc.c 1412@@ -0,0 +1,117 @@ 1413+// SPDX-License-Identifier: GPL-2.0+ 1414+/* 1415+ * Copyright 2019 NXP 1416+ * Dong Aisheng <aisheng.dong@nxp.com> 1417+ */ 1418+ 1419+#include <dt-bindings/firmware/imx/rsrc.h> 1420+ 1421+#include "clk-scu.h" 1422+ 1423+/* Keep sorted in the ascending order */ 1424+static u32 imx8qm_clk_scu_rsrc_table[] = { 1425+ IMX_SC_R_A53, 1426+ IMX_SC_R_A72, 1427+ IMX_SC_R_DC_0_VIDEO0, 1428+ IMX_SC_R_DC_0_VIDEO1, 1429+ IMX_SC_R_DC_0, 1430+ IMX_SC_R_DC_0_PLL_0, 1431+ IMX_SC_R_DC_0_PLL_1, 1432+ IMX_SC_R_DC_1_VIDEO0, 1433+ IMX_SC_R_DC_1_VIDEO1, 1434+ IMX_SC_R_DC_1, 1435+ IMX_SC_R_DC_1_PLL_0, 1436+ IMX_SC_R_DC_1_PLL_1, 1437+ IMX_SC_R_SPI_0, 1438+ IMX_SC_R_SPI_1, 1439+ IMX_SC_R_SPI_2, 1440+ IMX_SC_R_SPI_3, 1441+ IMX_SC_R_UART_0, 1442+ IMX_SC_R_UART_1, 1443+ IMX_SC_R_UART_2, 1444+ IMX_SC_R_UART_3, 1445+ IMX_SC_R_UART_4, 1446+ IMX_SC_R_EMVSIM_0, 1447+ IMX_SC_R_EMVSIM_1, 1448+ IMX_SC_R_I2C_0, 1449+ IMX_SC_R_I2C_1, 1450+ IMX_SC_R_I2C_2, 1451+ IMX_SC_R_I2C_3, 1452+ IMX_SC_R_I2C_4, 1453+ IMX_SC_R_ADC_0, 1454+ IMX_SC_R_ADC_1, 1455+ IMX_SC_R_FTM_0, 1456+ IMX_SC_R_FTM_1, 1457+ IMX_SC_R_CAN_0, 1458+ IMX_SC_R_CAN_1, 1459+ IMX_SC_R_CAN_2, 1460+ IMX_SC_R_GPU_0_PID0, 1461+ IMX_SC_R_GPU_1_PID0, 1462+ IMX_SC_R_PWM_0, 1463+ IMX_SC_R_PWM_1, 1464+ IMX_SC_R_PWM_2, 1465+ IMX_SC_R_PWM_3, 1466+ IMX_SC_R_PWM_4, 1467+ IMX_SC_R_PWM_5, 1468+ IMX_SC_R_PWM_6, 1469+ IMX_SC_R_PWM_7, 1470+ IMX_SC_R_GPT_0, 1471+ IMX_SC_R_GPT_1, 1472+ IMX_SC_R_GPT_2, 1473+ IMX_SC_R_GPT_3, 1474+ IMX_SC_R_GPT_4, 1475+ IMX_SC_R_FSPI_0, 1476+ IMX_SC_R_FSPI_1, 1477+ IMX_SC_R_SDHC_0, 1478+ IMX_SC_R_SDHC_1, 1479+ IMX_SC_R_SDHC_2, 1480+ IMX_SC_R_ENET_0, 1481+ IMX_SC_R_ENET_1, 1482+ IMX_SC_R_USB_2, 1483+ IMX_SC_R_NAND, 1484+ IMX_SC_R_LVDS_0, 1485+ IMX_SC_R_LVDS_0_PWM_0, 1486+ IMX_SC_R_LVDS_0_I2C_0, 1487+ IMX_SC_R_LVDS_0_I2C_1, 1488+ IMX_SC_R_LVDS_1, 1489+ IMX_SC_R_LVDS_1_PWM_0, 1490+ IMX_SC_R_LVDS_1_I2C_0, 1491+ IMX_SC_R_LVDS_1_I2C_1, 1492+ IMX_SC_R_M4_0_I2C, 1493+ IMX_SC_R_M4_1_I2C, 1494+ IMX_SC_R_AUDIO_PLL_0, 1495+ IMX_SC_R_VPU_UART, 1496+ IMX_SC_R_VPUCORE, 1497+ IMX_SC_R_MIPI_0, 1498+ IMX_SC_R_MIPI_0_PWM_0, 1499+ IMX_SC_R_MIPI_0_I2C_0, 1500+ IMX_SC_R_MIPI_0_I2C_1, 1501+ IMX_SC_R_MIPI_1, 1502+ IMX_SC_R_MIPI_1_PWM_0, 1503+ IMX_SC_R_MIPI_1_I2C_0, 1504+ IMX_SC_R_MIPI_1_I2C_1, 1505+ IMX_SC_R_CSI_0, 1506+ IMX_SC_R_CSI_0_PWM_0, 1507+ IMX_SC_R_CSI_0_I2C_0, 1508+ IMX_SC_R_CSI_1, 1509+ IMX_SC_R_CSI_1_PWM_0, 1510+ IMX_SC_R_CSI_1_I2C_0, 1511+ IMX_SC_R_HDMI, 1512+ IMX_SC_R_HDMI_I2S, 1513+ IMX_SC_R_HDMI_I2C_0, 1514+ IMX_SC_R_HDMI_PLL_0, 1515+ IMX_SC_R_HDMI_RX, 1516+ IMX_SC_R_HDMI_RX_BYPASS, 1517+ IMX_SC_R_HDMI_RX_I2C_0, 1518+ IMX_SC_R_AUDIO_PLL_1, 1519+ IMX_SC_R_AUDIO_CLK_0, 1520+ IMX_SC_R_AUDIO_CLK_1, 1521+ IMX_SC_R_HDMI_RX_PWM_0, 1522+ IMX_SC_R_HDMI_PLL_1, 1523+ IMX_SC_R_VPU, 1524+}; 1525+ 1526+const struct imx_clk_scu_rsrc_table imx_clk_scu_rsrc_imx8qm = { 1527+ .rsrc = imx8qm_clk_scu_rsrc_table, 1528+ .num = ARRAY_SIZE(imx8qm_clk_scu_rsrc_table), 1529+}; 1530diff --git a/drivers/clk/imx/clk-imx8qxp-acm.c b/drivers/clk/imx/clk-imx8qxp-acm.c 1531new file mode 100644 1532index 000000000..8968061cf 1533--- /dev/null 1534+++ b/drivers/clk/imx/clk-imx8qxp-acm.c 1535@@ -0,0 +1,258 @@ 1536+// SPDX-License-Identifier: GPL-2.0+ 1537+/* 1538+ * Copyright 2018 NXP 1539+ * Dong Aisheng <aisheng.dong@nxp.com> 1540+ */ 1541+ 1542+#include <linux/clk-provider.h> 1543+#include <linux/err.h> 1544+#include <linux/io.h> 1545+#include <linux/module.h> 1546+#include <linux/of.h> 1547+#include <linux/of_device.h> 1548+#include <linux/platform_device.h> 1549+#include <linux/slab.h> 1550+#include <linux/pm_domain.h> 1551+#include <linux/pm_runtime.h> 1552+ 1553+#include "clk.h" 1554+#include "clk-scu.h" 1555+#include "clk-imx-acm-utils.h" 1556+ 1557+#include <dt-bindings/clock/imx8-clock.h> 1558+ 1559+struct imx8qxp_acm_priv { 1560+ struct clk_imx_acm_pm_domains dev_pm; 1561+ void __iomem *reg; 1562+ u32 regs[0x20]; 1563+}; 1564+ 1565+static const char *aud_clk_sels[] = { 1566+ "aud_rec_clk0_lpcg_clk", 1567+ "aud_rec_clk1_lpcg_clk", 1568+ "ext_aud_mclk0", 1569+ "ext_aud_mclk1", 1570+ "esai0_rx_clk", 1571+ "esai0_rx_hf_clk", 1572+ "esai0_tx_clk", 1573+ "esai0_tx_hf_clk", 1574+ "spdif0_rx", 1575+ "sai0_rx_bclk", 1576+ "sai0_tx_bclk", 1577+ "sai1_rx_bclk", 1578+ "sai1_tx_bclk", 1579+ "sai2_rx_bclk", 1580+ "sai3_rx_bclk", 1581+}; 1582+ 1583+static const char *mclk_out_sels[] = { 1584+ "aud_rec_clk0_lpcg_clk", 1585+ "aud_rec_clk1_lpcg_clk", 1586+ "dummy", 1587+ "dummy", 1588+ "spdif0_rx", 1589+ "dummy", 1590+ "dummy", 1591+ "sai4_rx_bclk", 1592+}; 1593+ 1594+static const char *sai_mclk_sels[] = { 1595+ "aud_pll_div_clk0_lpcg_clk", 1596+ "aud_pll_div_clk1_lpcg_clk", 1597+ "acm_aud_clk0_sel", 1598+ "acm_aud_clk1_sel", 1599+}; 1600+ 1601+static const char *esai_mclk_sels[] = { 1602+ "aud_pll_div_clk0_lpcg_clk", 1603+ "aud_pll_div_clk1_lpcg_clk", 1604+ "acm_aud_clk0_sel", 1605+ "acm_aud_clk1_sel", 1606+}; 1607+ 1608+static const char *spdif_mclk_sels[] = { 1609+ "aud_pll_div_clk0_lpcg_clk", 1610+ "aud_pll_div_clk1_lpcg_clk", 1611+ "acm_aud_clk0_sel", 1612+ "acm_aud_clk1_sel", 1613+}; 1614+ 1615+static const char *mqs_mclk_sels[] = { 1616+ "aud_pll_div_clk0_lpcg_clk", 1617+ "aud_pll_div_clk1_lpcg_clk", 1618+ "acm_aud_clk0_sel", 1619+ "acm_aud_clk1_sel", 1620+}; 1621+ 1622+static int imx8qxp_acm_clk_probe(struct platform_device *pdev) 1623+{ 1624+ struct device *dev = &pdev->dev; 1625+ struct device_node *np = dev->of_node; 1626+ struct clk_onecell_data *clk_data; 1627+ struct imx8qxp_acm_priv *priv; 1628+ struct resource *res; 1629+ struct clk **clks; 1630+ void __iomem *base; 1631+ int ret; 1632+ int i; 1633+ 1634+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1635+ base = devm_ioremap(dev, res->start, resource_size(res)); 1636+ if (!base) 1637+ return -ENOMEM; 1638+ 1639+ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); 1640+ if (!priv) 1641+ return -ENOMEM; 1642+ 1643+ priv->reg = base; 1644+ 1645+ platform_set_drvdata(pdev, priv); 1646+ 1647+ clk_data = devm_kzalloc(&pdev->dev, sizeof(*clk_data), GFP_KERNEL); 1648+ if (!clk_data) 1649+ return -ENOMEM; 1650+ 1651+ clk_data->clks = devm_kcalloc(&pdev->dev, IMX_ADMA_ACM_CLK_END, 1652+ sizeof(*clk_data->clks), GFP_KERNEL); 1653+ if (!clk_data->clks) 1654+ return -ENOMEM; 1655+ 1656+ clk_data->clk_num = IMX_ADMA_ACM_CLK_END; 1657+ 1658+ clks = clk_data->clks; 1659+ 1660+ ret = clk_imx_acm_attach_pm_domains(&pdev->dev, &priv->dev_pm); 1661+ if (ret) 1662+ return ret; 1663+ 1664+ pm_runtime_enable(&pdev->dev); 1665+ pm_runtime_get_sync(&pdev->dev); 1666+ 1667+ clks[IMX_ADMA_EXT_AUD_MCLK0] = imx_clk_fixed("ext_aud_mclk0", 0); 1668+ clks[IMX_ADMA_EXT_AUD_MCLK1] = imx_clk_fixed("ext_aud_mclk1", 0); 1669+ clks[IMX_ADMA_ESAI0_RX_CLK] = imx_clk_fixed("esai0_rx_clk", 0); 1670+ clks[IMX_ADMA_ESAI0_RX_HF_CLK] = imx_clk_fixed("esai0_rx_hf_clk", 0); 1671+ clks[IMX_ADMA_ESAI0_TX_CLK] = imx_clk_fixed("esai0_tx_clk", 0); 1672+ clks[IMX_ADMA_ESAI0_TX_HF_CLK] = imx_clk_fixed("esai0_tx_hf_clk", 0); 1673+ clks[IMX_ADMA_SPDIF0_RX] = imx_clk_fixed("spdif0_rx", 0); 1674+ clks[IMX_ADMA_SAI0_RX_BCLK] = imx_clk_fixed("sai0_rx_bclk", 0); 1675+ clks[IMX_ADMA_SAI0_TX_BCLK] = imx_clk_fixed("sai0_tx_bclk", 0); 1676+ clks[IMX_ADMA_SAI1_RX_BCLK] = imx_clk_fixed("sai1_rx_bclk", 0); 1677+ clks[IMX_ADMA_SAI1_TX_BCLK] = imx_clk_fixed("sai1_tx_bclk", 0); 1678+ clks[IMX_ADMA_SAI2_RX_BCLK] = imx_clk_fixed("sai2_rx_bclk", 0); 1679+ clks[IMX_ADMA_SAI3_RX_BCLK] = imx_clk_fixed("sai3_rx_bclk", 0); 1680+ clks[IMX_ADMA_SAI4_RX_BCLK] = imx_clk_fixed("sai4_rx_bclk", 0); 1681+ 1682+ 1683+ clks[IMX_ADMA_ACM_AUD_CLK0_SEL] = imx_dev_clk_mux(dev, "acm_aud_clk0_sel", base+0x000000, 0, 5, aud_clk_sels, ARRAY_SIZE(aud_clk_sels)); 1684+ clks[IMX_ADMA_ACM_AUD_CLK1_SEL] = imx_dev_clk_mux(dev, "acm_aud_clk1_sel", base+0x010000, 0, 5, aud_clk_sels, ARRAY_SIZE(aud_clk_sels)); 1685+ 1686+ clks[IMX_ADMA_ACM_MCLKOUT0_SEL] = imx_dev_clk_mux(dev, "acm_mclkout0_sel", base+0x020000, 0, 3, mclk_out_sels, ARRAY_SIZE(mclk_out_sels)); 1687+ clks[IMX_ADMA_ACM_MCLKOUT1_SEL] = imx_dev_clk_mux(dev, "acm_mclkout1_sel", base+0x030000, 0, 3, mclk_out_sels, ARRAY_SIZE(mclk_out_sels)); 1688+ 1689+ clks[IMX_ADMA_ACM_ESAI0_MCLK_SEL] = imx_dev_clk_mux(dev, "acm_esai0_mclk_sel", base+0x060000, 0, 2, esai_mclk_sels, ARRAY_SIZE(esai_mclk_sels)); 1690+ clks[IMX_ADMA_ACM_SAI0_MCLK_SEL] = imx_dev_clk_mux(dev, "acm_sai0_mclk_sel", base+0x0E0000, 0, 2, sai_mclk_sels, ARRAY_SIZE(sai_mclk_sels)); 1691+ clks[IMX_ADMA_ACM_SAI1_MCLK_SEL] = imx_dev_clk_mux(dev, "acm_sai1_mclk_sel", base+0x0F0000, 0, 2, sai_mclk_sels, ARRAY_SIZE(sai_mclk_sels)); 1692+ clks[IMX_ADMA_ACM_SAI2_MCLK_SEL] = imx_dev_clk_mux(dev, "acm_sai2_mclk_sel", base+0x100000, 0, 2, sai_mclk_sels, ARRAY_SIZE(sai_mclk_sels)); 1693+ clks[IMX_ADMA_ACM_SAI3_MCLK_SEL] = imx_dev_clk_mux(dev, "acm_sai3_mclk_sel", base+0x110000, 0, 2, sai_mclk_sels, ARRAY_SIZE(sai_mclk_sels)); 1694+ clks[IMX_ADMA_ACM_SAI4_MCLK_SEL] = imx_dev_clk_mux(dev, "acm_sai4_mclk_sel", base+0x140000, 0, 2, sai_mclk_sels, ARRAY_SIZE(sai_mclk_sels)); 1695+ clks[IMX_ADMA_ACM_SAI5_MCLK_SEL] = imx_dev_clk_mux(dev, "acm_sai5_mclk_sel", base+0x150000, 0, 2, sai_mclk_sels, ARRAY_SIZE(sai_mclk_sels)); 1696+ 1697+ clks[IMX_ADMA_ACM_SPDIF0_TX_CLK_SEL] = imx_dev_clk_mux(dev, "acm_spdif0_mclk_sel", base+0x1A0000, 0, 2, spdif_mclk_sels, ARRAY_SIZE(spdif_mclk_sels)); 1698+ clks[IMX_ADMA_ACM_MQS_TX_CLK_SEL] = imx_dev_clk_mux(dev, "acm_mqs_mclk_sel", base+0x1C0000, 0, 2, mqs_mclk_sels, ARRAY_SIZE(mqs_mclk_sels)); 1699+ 1700+ for (i = 0; i < clk_data->clk_num; i++) { 1701+ if (IS_ERR(clks[i])) 1702+ pr_warn("i.MX clk %u: register failed with %ld\n", 1703+ i, PTR_ERR(clks[i])); 1704+ } 1705+ 1706+ ret = of_clk_add_provider(np, of_clk_src_onecell_get, clk_data); 1707+ 1708+ pm_runtime_put_sync(&pdev->dev); 1709+ 1710+ return ret; 1711+} 1712+ 1713+static int imx8qxp_acm_clk_remove(struct platform_device *pdev) 1714+{ 1715+ struct imx8qxp_acm_priv *priv = dev_get_drvdata(&pdev->dev); 1716+ 1717+ pm_runtime_disable(&pdev->dev); 1718+ 1719+ clk_imx_acm_detach_pm_domains(&pdev->dev, &priv->dev_pm); 1720+ 1721+ return 0; 1722+} 1723+ 1724+static const struct of_device_id imx8qxp_acm_match[] = { 1725+ { .compatible = "nxp,imx8qxp-acm", }, 1726+ { /* sentinel */ } 1727+}; 1728+ 1729+static int __maybe_unused imx8qxp_acm_runtime_suspend(struct device *dev) 1730+{ 1731+ struct imx8qxp_acm_priv *priv = dev_get_drvdata(dev); 1732+ 1733+ priv->regs[0] = readl_relaxed(priv->reg + 0x000000); 1734+ priv->regs[1] = readl_relaxed(priv->reg + 0x010000); 1735+ priv->regs[2] = readl_relaxed(priv->reg + 0x020000); 1736+ priv->regs[3] = readl_relaxed(priv->reg + 0x030000); 1737+ priv->regs[6] = readl_relaxed(priv->reg + 0x060000); 1738+ priv->regs[14] = readl_relaxed(priv->reg + 0x0E0000); 1739+ priv->regs[15] = readl_relaxed(priv->reg + 0x0F0000); 1740+ priv->regs[16] = readl_relaxed(priv->reg + 0x100000); 1741+ priv->regs[17] = readl_relaxed(priv->reg + 0x110000); 1742+ priv->regs[20] = readl_relaxed(priv->reg + 0x140000); 1743+ priv->regs[21] = readl_relaxed(priv->reg + 0x150000); 1744+ priv->regs[26] = readl_relaxed(priv->reg + 0x1A0000); 1745+ priv->regs[28] = readl_relaxed(priv->reg + 0x1C0000); 1746+ 1747+ return 0; 1748+} 1749+ 1750+static int __maybe_unused imx8qxp_acm_runtime_resume(struct device *dev) 1751+{ 1752+ struct imx8qxp_acm_priv *priv = dev_get_drvdata(dev); 1753+ 1754+ writel_relaxed(priv->regs[0], priv->reg + 0x000000); 1755+ writel_relaxed(priv->regs[1], priv->reg + 0x010000); 1756+ writel_relaxed(priv->regs[2], priv->reg + 0x020000); 1757+ writel_relaxed(priv->regs[3], priv->reg + 0x030000); 1758+ writel_relaxed(priv->regs[6], priv->reg + 0x060000); 1759+ writel_relaxed(priv->regs[14], priv->reg + 0x0E0000); 1760+ writel_relaxed(priv->regs[15], priv->reg + 0x0F0000); 1761+ writel_relaxed(priv->regs[16], priv->reg + 0x100000); 1762+ writel_relaxed(priv->regs[17], priv->reg + 0x110000); 1763+ writel_relaxed(priv->regs[20], priv->reg + 0x140000); 1764+ writel_relaxed(priv->regs[21], priv->reg + 0x150000); 1765+ writel_relaxed(priv->regs[26], priv->reg + 0x1A0000); 1766+ writel_relaxed(priv->regs[28], priv->reg + 0x1C0000); 1767+ 1768+ return 0; 1769+} 1770+ 1771+const struct dev_pm_ops imx8qxp_acm_pm_ops = { 1772+ SET_RUNTIME_PM_OPS(imx8qxp_acm_runtime_suspend, 1773+ imx8qxp_acm_runtime_resume, NULL) 1774+ SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, 1775+ pm_runtime_force_resume) 1776+}; 1777+ 1778+static struct platform_driver imx8qxp_acm_clk_driver = { 1779+ .driver = { 1780+ .name = "imx8qxp-acm", 1781+ .of_match_table = imx8qxp_acm_match, 1782+ .pm = &imx8qxp_acm_pm_ops, 1783+ .suppress_bind_attrs = true, 1784+ }, 1785+ .probe = imx8qxp_acm_clk_probe, 1786+ .remove = imx8qxp_acm_clk_remove, 1787+}; 1788+ 1789+static int __init imx8qxp_acm_init(void) 1790+{ 1791+ return platform_driver_register(&imx8qxp_acm_clk_driver); 1792+} 1793+fs_initcall(imx8qxp_acm_init); 1794diff --git a/drivers/clk/imx/clk-imx8qxp-lpcg.c b/drivers/clk/imx/clk-imx8qxp-lpcg.c 1795index 522c03a12..0b43a8345 100644 1796--- a/drivers/clk/imx/clk-imx8qxp-lpcg.c 1797+++ b/drivers/clk/imx/clk-imx8qxp-lpcg.c 1798@@ -9,216 +9,106 @@ 1799 #include <linux/io.h> 1800 #include <linux/module.h> 1801 #include <linux/of.h> 1802+#include <linux/of_address.h> 1803 #include <linux/of_device.h> 1804 #include <linux/platform_device.h> 1805+#include <linux/pm_runtime.h> 1806 #include <linux/slab.h> 1807 1808 #include "clk-scu.h" 1809-#include "clk-imx8qxp-lpcg.h" 1810 1811-#include <dt-bindings/clock/imx8-clock.h> 1812- 1813-/* 1814- * struct imx8qxp_lpcg_data - Description of one LPCG clock 1815- * @id: clock ID 1816- * @name: clock name 1817- * @parent: parent clock name 1818- * @flags: common clock flags 1819- * @offset: offset of this LPCG clock 1820- * @bit_idx: bit index of this LPCG clock 1821- * @hw_gate: whether supports HW autogate 1822- * 1823- * This structure describes one LPCG clock 1824- */ 1825-struct imx8qxp_lpcg_data { 1826- int id; 1827- char *name; 1828- char *parent; 1829- unsigned long flags; 1830- u32 offset; 1831- u8 bit_idx; 1832- bool hw_gate; 1833-}; 1834- 1835-/* 1836- * struct imx8qxp_ss_lpcg - Description of one subsystem LPCG clocks 1837- * @lpcg: LPCG clocks array of one subsystem 1838- * @num_lpcg: the number of LPCG clocks 1839- * @num_max: the maximum number of LPCG clocks 1840- * 1841- * This structure describes each subsystem LPCG clocks information 1842- * which then will be used to create respective LPCGs clocks 1843- */ 1844-struct imx8qxp_ss_lpcg { 1845- const struct imx8qxp_lpcg_data *lpcg; 1846- u8 num_lpcg; 1847- u8 num_max; 1848-}; 1849- 1850-static const struct imx8qxp_lpcg_data imx8qxp_lpcg_adma[] = { 1851- { IMX_ADMA_LPCG_UART0_IPG_CLK, "uart0_lpcg_ipg_clk", "dma_ipg_clk_root", 0, ADMA_LPUART_0_LPCG, 16, 0, }, 1852- { IMX_ADMA_LPCG_UART0_BAUD_CLK, "uart0_lpcg_baud_clk", "uart0_clk", 0, ADMA_LPUART_0_LPCG, 0, 0, }, 1853- { IMX_ADMA_LPCG_UART1_IPG_CLK, "uart1_lpcg_ipg_clk", "dma_ipg_clk_root", 0, ADMA_LPUART_1_LPCG, 16, 0, }, 1854- { IMX_ADMA_LPCG_UART1_BAUD_CLK, "uart1_lpcg_baud_clk", "uart1_clk", 0, ADMA_LPUART_1_LPCG, 0, 0, }, 1855- { IMX_ADMA_LPCG_UART2_IPG_CLK, "uart2_lpcg_ipg_clk", "dma_ipg_clk_root", 0, ADMA_LPUART_2_LPCG, 16, 0, }, 1856- { IMX_ADMA_LPCG_UART2_BAUD_CLK, "uart2_lpcg_baud_clk", "uart2_clk", 0, ADMA_LPUART_2_LPCG, 0, 0, }, 1857- { IMX_ADMA_LPCG_UART3_IPG_CLK, "uart3_lpcg_ipg_clk", "dma_ipg_clk_root", 0, ADMA_LPUART_3_LPCG, 16, 0, }, 1858- { IMX_ADMA_LPCG_UART3_BAUD_CLK, "uart3_lpcg_baud_clk", "uart3_clk", 0, ADMA_LPUART_3_LPCG, 0, 0, }, 1859- { IMX_ADMA_LPCG_I2C0_IPG_CLK, "i2c0_lpcg_ipg_clk", "dma_ipg_clk_root", 0, ADMA_LPI2C_0_LPCG, 16, 0, }, 1860- { IMX_ADMA_LPCG_I2C0_CLK, "i2c0_lpcg_clk", "i2c0_clk", 0, ADMA_LPI2C_0_LPCG, 0, 0, }, 1861- { IMX_ADMA_LPCG_I2C1_IPG_CLK, "i2c1_lpcg_ipg_clk", "dma_ipg_clk_root", 0, ADMA_LPI2C_1_LPCG, 16, 0, }, 1862- { IMX_ADMA_LPCG_I2C1_CLK, "i2c1_lpcg_clk", "i2c1_clk", 0, ADMA_LPI2C_1_LPCG, 0, 0, }, 1863- { IMX_ADMA_LPCG_I2C2_IPG_CLK, "i2c2_lpcg_ipg_clk", "dma_ipg_clk_root", 0, ADMA_LPI2C_2_LPCG, 16, 0, }, 1864- { IMX_ADMA_LPCG_I2C2_CLK, "i2c2_lpcg_clk", "i2c2_clk", 0, ADMA_LPI2C_2_LPCG, 0, 0, }, 1865- { IMX_ADMA_LPCG_I2C3_IPG_CLK, "i2c3_lpcg_ipg_clk", "dma_ipg_clk_root", 0, ADMA_LPI2C_3_LPCG, 16, 0, }, 1866- { IMX_ADMA_LPCG_I2C3_CLK, "i2c3_lpcg_clk", "i2c3_clk", 0, ADMA_LPI2C_3_LPCG, 0, 0, }, 1867- 1868- { IMX_ADMA_LPCG_DSP_CORE_CLK, "dsp_lpcg_core_clk", "dma_ipg_clk_root", 0, ADMA_HIFI_LPCG, 28, 0, }, 1869- { IMX_ADMA_LPCG_DSP_IPG_CLK, "dsp_lpcg_ipg_clk", "dma_ipg_clk_root", 0, ADMA_HIFI_LPCG, 20, 0, }, 1870- { IMX_ADMA_LPCG_DSP_ADB_CLK, "dsp_lpcg_adb_clk", "dma_ipg_clk_root", 0, ADMA_HIFI_LPCG, 16, 0, }, 1871- { IMX_ADMA_LPCG_OCRAM_IPG_CLK, "ocram_lpcg_ipg_clk", "dma_ipg_clk_root", 0, ADMA_OCRAM_LPCG, 16, 0, }, 1872-}; 1873- 1874-static const struct imx8qxp_ss_lpcg imx8qxp_ss_adma = { 1875- .lpcg = imx8qxp_lpcg_adma, 1876- .num_lpcg = ARRAY_SIZE(imx8qxp_lpcg_adma), 1877- .num_max = IMX_ADMA_LPCG_CLK_END, 1878-}; 1879- 1880-static const struct imx8qxp_lpcg_data imx8qxp_lpcg_conn[] = { 1881- { IMX_CONN_LPCG_SDHC0_PER_CLK, "sdhc0_lpcg_per_clk", "sdhc0_clk", 0, CONN_USDHC_0_LPCG, 0, 0, }, 1882- { IMX_CONN_LPCG_SDHC0_IPG_CLK, "sdhc0_lpcg_ipg_clk", "conn_ipg_clk_root", 0, CONN_USDHC_0_LPCG, 16, 0, }, 1883- { IMX_CONN_LPCG_SDHC0_HCLK, "sdhc0_lpcg_ahb_clk", "conn_axi_clk_root", 0, CONN_USDHC_0_LPCG, 20, 0, }, 1884- { IMX_CONN_LPCG_SDHC1_PER_CLK, "sdhc1_lpcg_per_clk", "sdhc1_clk", 0, CONN_USDHC_1_LPCG, 0, 0, }, 1885- { IMX_CONN_LPCG_SDHC1_IPG_CLK, "sdhc1_lpcg_ipg_clk", "conn_ipg_clk_root", 0, CONN_USDHC_1_LPCG, 16, 0, }, 1886- { IMX_CONN_LPCG_SDHC1_HCLK, "sdhc1_lpcg_ahb_clk", "conn_axi_clk_root", 0, CONN_USDHC_1_LPCG, 20, 0, }, 1887- { IMX_CONN_LPCG_SDHC2_PER_CLK, "sdhc2_lpcg_per_clk", "sdhc2_clk", 0, CONN_USDHC_2_LPCG, 0, 0, }, 1888- { IMX_CONN_LPCG_SDHC2_IPG_CLK, "sdhc2_lpcg_ipg_clk", "conn_ipg_clk_root", 0, CONN_USDHC_2_LPCG, 16, 0, }, 1889- { IMX_CONN_LPCG_SDHC2_HCLK, "sdhc2_lpcg_ahb_clk", "conn_axi_clk_root", 0, CONN_USDHC_2_LPCG, 20, 0, }, 1890- { IMX_CONN_LPCG_ENET0_ROOT_CLK, "enet0_ipg_root_clk", "enet0_clk", 0, CONN_ENET_0_LPCG, 0, 0, }, 1891- { IMX_CONN_LPCG_ENET0_TX_CLK, "enet0_tx_clk", "enet0_clk", 0, CONN_ENET_0_LPCG, 4, 0, }, 1892- { IMX_CONN_LPCG_ENET0_AHB_CLK, "enet0_ahb_clk", "conn_axi_clk_root", 0, CONN_ENET_0_LPCG, 8, 0, }, 1893- { IMX_CONN_LPCG_ENET0_IPG_S_CLK, "enet0_ipg_s_clk", "conn_ipg_clk_root", 0, CONN_ENET_0_LPCG, 20, 0, }, 1894- { IMX_CONN_LPCG_ENET0_IPG_CLK, "enet0_ipg_clk", "enet0_ipg_s_clk", 0, CONN_ENET_0_LPCG, 16, 0, }, 1895- { IMX_CONN_LPCG_ENET1_ROOT_CLK, "enet1_ipg_root_clk", "enet1_clk", 0, CONN_ENET_1_LPCG, 0, 0, }, 1896- { IMX_CONN_LPCG_ENET1_TX_CLK, "enet1_tx_clk", "enet1_clk", 0, CONN_ENET_1_LPCG, 4, 0, }, 1897- { IMX_CONN_LPCG_ENET1_AHB_CLK, "enet1_ahb_clk", "conn_axi_clk_root", 0, CONN_ENET_1_LPCG, 8, 0, }, 1898- { IMX_CONN_LPCG_ENET1_IPG_S_CLK, "enet1_ipg_s_clk", "conn_ipg_clk_root", 0, CONN_ENET_1_LPCG, 20, 0, }, 1899- { IMX_CONN_LPCG_ENET1_IPG_CLK, "enet1_ipg_clk", "enet0_ipg_s_clk", 0, CONN_ENET_1_LPCG, 16, 0, }, 1900-}; 1901- 1902-static const struct imx8qxp_ss_lpcg imx8qxp_ss_conn = { 1903- .lpcg = imx8qxp_lpcg_conn, 1904- .num_lpcg = ARRAY_SIZE(imx8qxp_lpcg_conn), 1905- .num_max = IMX_CONN_LPCG_CLK_END, 1906-}; 1907- 1908-static const struct imx8qxp_lpcg_data imx8qxp_lpcg_lsio[] = { 1909- { IMX_LSIO_LPCG_PWM0_IPG_CLK, "pwm0_lpcg_ipg_clk", "pwm0_clk", 0, LSIO_PWM_0_LPCG, 0, 0, }, 1910- { IMX_LSIO_LPCG_PWM0_IPG_HF_CLK, "pwm0_lpcg_ipg_hf_clk", "pwm0_clk", 0, LSIO_PWM_0_LPCG, 4, 0, }, 1911- { IMX_LSIO_LPCG_PWM0_IPG_S_CLK, "pwm0_lpcg_ipg_s_clk", "pwm0_clk", 0, LSIO_PWM_0_LPCG, 16, 0, }, 1912- { IMX_LSIO_LPCG_PWM0_IPG_SLV_CLK, "pwm0_lpcg_ipg_slv_clk", "lsio_bus_clk_root", 0, LSIO_PWM_0_LPCG, 20, 0, }, 1913- { IMX_LSIO_LPCG_PWM0_IPG_MSTR_CLK, "pwm0_lpcg_ipg_mstr_clk", "pwm0_clk", 0, LSIO_PWM_0_LPCG, 24, 0, }, 1914- { IMX_LSIO_LPCG_PWM1_IPG_CLK, "pwm1_lpcg_ipg_clk", "pwm1_clk", 0, LSIO_PWM_1_LPCG, 0, 0, }, 1915- { IMX_LSIO_LPCG_PWM1_IPG_HF_CLK, "pwm1_lpcg_ipg_hf_clk", "pwm1_clk", 0, LSIO_PWM_1_LPCG, 4, 0, }, 1916- { IMX_LSIO_LPCG_PWM1_IPG_S_CLK, "pwm1_lpcg_ipg_s_clk", "pwm1_clk", 0, LSIO_PWM_1_LPCG, 16, 0, }, 1917- { IMX_LSIO_LPCG_PWM1_IPG_SLV_CLK, "pwm1_lpcg_ipg_slv_clk", "lsio_bus_clk_root", 0, LSIO_PWM_1_LPCG, 20, 0, }, 1918- { IMX_LSIO_LPCG_PWM1_IPG_MSTR_CLK, "pwm1_lpcg_ipg_mstr_clk", "pwm1_clk", 0, LSIO_PWM_1_LPCG, 24, 0, }, 1919- { IMX_LSIO_LPCG_PWM2_IPG_CLK, "pwm2_lpcg_ipg_clk", "pwm2_clk", 0, LSIO_PWM_2_LPCG, 0, 0, }, 1920- { IMX_LSIO_LPCG_PWM2_IPG_HF_CLK, "pwm2_lpcg_ipg_hf_clk", "pwm2_clk", 0, LSIO_PWM_2_LPCG, 4, 0, }, 1921- { IMX_LSIO_LPCG_PWM2_IPG_S_CLK, "pwm2_lpcg_ipg_s_clk", "pwm2_clk", 0, LSIO_PWM_2_LPCG, 16, 0, }, 1922- { IMX_LSIO_LPCG_PWM2_IPG_SLV_CLK, "pwm2_lpcg_ipg_slv_clk", "lsio_bus_clk_root", 0, LSIO_PWM_2_LPCG, 20, 0, }, 1923- { IMX_LSIO_LPCG_PWM2_IPG_MSTR_CLK, "pwm2_lpcg_ipg_mstr_clk", "pwm2_clk", 0, LSIO_PWM_2_LPCG, 24, 0, }, 1924- { IMX_LSIO_LPCG_PWM3_IPG_CLK, "pwm3_lpcg_ipg_clk", "pwm3_clk", 0, LSIO_PWM_3_LPCG, 0, 0, }, 1925- { IMX_LSIO_LPCG_PWM3_IPG_HF_CLK, "pwm3_lpcg_ipg_hf_clk", "pwm3_clk", 0, LSIO_PWM_3_LPCG, 4, 0, }, 1926- { IMX_LSIO_LPCG_PWM3_IPG_S_CLK, "pwm3_lpcg_ipg_s_clk", "pwm3_clk", 0, LSIO_PWM_3_LPCG, 16, 0, }, 1927- { IMX_LSIO_LPCG_PWM3_IPG_SLV_CLK, "pwm3_lpcg_ipg_slv_clk", "lsio_bus_clk_root", 0, LSIO_PWM_3_LPCG, 20, 0, }, 1928- { IMX_LSIO_LPCG_PWM3_IPG_MSTR_CLK, "pwm3_lpcg_ipg_mstr_clk", "pwm3_clk", 0, LSIO_PWM_3_LPCG, 24, 0, }, 1929- { IMX_LSIO_LPCG_PWM4_IPG_CLK, "pwm4_lpcg_ipg_clk", "pwm4_clk", 0, LSIO_PWM_4_LPCG, 0, 0, }, 1930- { IMX_LSIO_LPCG_PWM4_IPG_HF_CLK, "pwm4_lpcg_ipg_hf_clk", "pwm4_clk", 0, LSIO_PWM_4_LPCG, 4, 0, }, 1931- { IMX_LSIO_LPCG_PWM4_IPG_S_CLK, "pwm4_lpcg_ipg_s_clk", "pwm4_clk", 0, LSIO_PWM_4_LPCG, 16, 0, }, 1932- { IMX_LSIO_LPCG_PWM4_IPG_SLV_CLK, "pwm4_lpcg_ipg_slv_clk", "lsio_bus_clk_root", 0, LSIO_PWM_4_LPCG, 20, 0, }, 1933- { IMX_LSIO_LPCG_PWM4_IPG_MSTR_CLK, "pwm4_lpcg_ipg_mstr_clk", "pwm4_clk", 0, LSIO_PWM_4_LPCG, 24, 0, }, 1934- { IMX_LSIO_LPCG_PWM5_IPG_CLK, "pwm5_lpcg_ipg_clk", "pwm5_clk", 0, LSIO_PWM_5_LPCG, 0, 0, }, 1935- { IMX_LSIO_LPCG_PWM5_IPG_HF_CLK, "pwm5_lpcg_ipg_hf_clk", "pwm5_clk", 0, LSIO_PWM_5_LPCG, 4, 0, }, 1936- { IMX_LSIO_LPCG_PWM5_IPG_S_CLK, "pwm5_lpcg_ipg_s_clk", "pwm5_clk", 0, LSIO_PWM_5_LPCG, 16, 0, }, 1937- { IMX_LSIO_LPCG_PWM5_IPG_SLV_CLK, "pwm5_lpcg_ipg_slv_clk", "lsio_bus_clk_root", 0, LSIO_PWM_5_LPCG, 20, 0, }, 1938- { IMX_LSIO_LPCG_PWM5_IPG_MSTR_CLK, "pwm5_lpcg_ipg_mstr_clk", "pwm5_clk", 0, LSIO_PWM_5_LPCG, 24, 0, }, 1939- { IMX_LSIO_LPCG_PWM6_IPG_CLK, "pwm6_lpcg_ipg_clk", "pwm6_clk", 0, LSIO_PWM_6_LPCG, 0, 0, }, 1940- { IMX_LSIO_LPCG_PWM6_IPG_HF_CLK, "pwm6_lpcg_ipg_hf_clk", "pwm6_clk", 0, LSIO_PWM_6_LPCG, 4, 0, }, 1941- { IMX_LSIO_LPCG_PWM6_IPG_S_CLK, "pwm6_lpcg_ipg_s_clk", "pwm6_clk", 0, LSIO_PWM_6_LPCG, 16, 0, }, 1942- { IMX_LSIO_LPCG_PWM6_IPG_SLV_CLK, "pwm6_lpcg_ipg_slv_clk", "lsio_bus_clk_root", 0, LSIO_PWM_6_LPCG, 20, 0, }, 1943- { IMX_LSIO_LPCG_PWM6_IPG_MSTR_CLK, "pwm6_lpcg_ipg_mstr_clk", "pwm6_clk", 0, LSIO_PWM_6_LPCG, 24, 0, }, 1944-}; 1945- 1946-static const struct imx8qxp_ss_lpcg imx8qxp_ss_lsio = { 1947- .lpcg = imx8qxp_lpcg_lsio, 1948- .num_lpcg = ARRAY_SIZE(imx8qxp_lpcg_lsio), 1949- .num_max = IMX_LSIO_LPCG_CLK_END, 1950-}; 1951+#define IMX_LPCG_MAX_CLKS 8 1952 1953 static int imx8qxp_lpcg_clk_probe(struct platform_device *pdev) 1954 { 1955- struct device *dev = &pdev->dev; 1956- struct device_node *np = dev->of_node; 1957+ struct device_node *np = pdev->dev.of_node; 1958+ const char *output_names[IMX_LPCG_MAX_CLKS]; 1959+ const char *parent_names[IMX_LPCG_MAX_CLKS]; 1960+ unsigned int bit_offset[IMX_LPCG_MAX_CLKS]; 1961 struct clk_hw_onecell_data *clk_data; 1962- const struct imx8qxp_ss_lpcg *ss_lpcg; 1963- const struct imx8qxp_lpcg_data *lpcg; 1964+ struct clk_hw **clk_hws; 1965 struct resource *res; 1966- struct clk_hw **clks; 1967 void __iomem *base; 1968+ bool autogate; 1969+ int count; 1970+ int ret; 1971 int i; 1972 1973- ss_lpcg = of_device_get_match_data(dev); 1974- if (!ss_lpcg) 1975- return -ENODEV; 1976- 1977- /* 1978- * Please don't replace this with devm_platform_ioremap_resource. 1979- * 1980- * devm_platform_ioremap_resource calls devm_ioremap_resource which 1981- * differs from devm_ioremap by also calling devm_request_mem_region 1982- * and preventing other mappings in the same area. 1983- * 1984- * On imx8 the LPCG nodes map entire subsystems and overlap 1985- * peripherals, this means that using devm_platform_ioremap_resource 1986- * will cause many devices to fail to probe including serial ports. 1987- */ 1988 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1989- if (!res) 1990+ base = devm_ioremap_resource(&pdev->dev, res); 1991+ if (IS_ERR(base)) 1992+ return PTR_ERR(base); 1993+ 1994+ count = of_property_count_u32_elems(np, "bit-offset"); 1995+ if (count < 0) { 1996+ dev_err(&pdev->dev, "failed to count clocks\n"); 1997 return -EINVAL; 1998- base = devm_ioremap(dev, res->start, resource_size(res)); 1999- if (!base) 2000- return -ENOMEM; 2001+ } 2002 2003- clk_data = devm_kzalloc(&pdev->dev, struct_size(clk_data, hws, 2004- ss_lpcg->num_max), GFP_KERNEL); 2005+ clk_data = devm_kzalloc(&pdev->dev, struct_size(clk_data, hws, count), 2006+ GFP_KERNEL); 2007 if (!clk_data) 2008 return -ENOMEM; 2009 2010- clk_data->num = ss_lpcg->num_max; 2011- clks = clk_data->hws; 2012+ clk_data->num = count; 2013+ clk_hws = clk_data->hws; 2014 2015- for (i = 0; i < ss_lpcg->num_lpcg; i++) { 2016- lpcg = ss_lpcg->lpcg + i; 2017- clks[lpcg->id] = imx_clk_lpcg_scu(lpcg->name, lpcg->parent, 2018- lpcg->flags, base + lpcg->offset, 2019- lpcg->bit_idx, lpcg->hw_gate); 2020+ ret = of_property_read_u32_array(np, "bit-offset", bit_offset, 2021+ clk_data->num); 2022+ if (ret < 0) { 2023+ dev_err(&pdev->dev, "failed to read clocks bit-offset\n"); 2024+ return -EINVAL; 2025 } 2026 2027+ ret = of_clk_parent_fill(np, parent_names, clk_data->num); 2028+ if (ret != clk_data->num) { 2029+ dev_err(&pdev->dev, "failed to get clock parent names\n"); 2030+ return -EINVAL; 2031+ } 2032+ 2033+ ret = of_property_read_string_array(np, "clock-output-names", 2034+ output_names, clk_data->num); 2035+ if (ret != clk_data->num) { 2036+ dev_err(&pdev->dev, "failed to read clock-output-names\n"); 2037+ return -EINVAL; 2038+ } 2039+ 2040+ autogate = of_property_read_bool(np, "hw-autogate"); 2041+ 2042+ pm_runtime_get_noresume(&pdev->dev); 2043+ pm_runtime_set_active(&pdev->dev); 2044+ pm_runtime_set_autosuspend_delay(&pdev->dev, 500); 2045+ pm_runtime_use_autosuspend(&pdev->dev); 2046+ pm_runtime_enable(&pdev->dev); 2047+ 2048 for (i = 0; i < clk_data->num; i++) { 2049- if (IS_ERR(clks[i])) 2050- pr_warn("i.MX clk %u: register failed with %ld\n", 2051- i, PTR_ERR(clks[i])); 2052+ if (bit_offset[i] > 31) { 2053+ dev_warn(&pdev->dev, "invalid bit offset of clock %d\n", 2054+ i); 2055+ return -EINVAL; 2056+ } 2057+ 2058+ clk_hws[i] = imx_clk_lpcg_scu_dev(&pdev->dev, output_names[i], 2059+ parent_names[i], 0, base, 2060+ bit_offset[i], autogate); 2061+ if (IS_ERR(clk_hws[i])) { 2062+ dev_warn(&pdev->dev, "failed to register clock %d\n", 2063+ i); 2064+ return -EINVAL; 2065+ } 2066 } 2067 2068- return of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_data); 2069+ ret = devm_of_clk_add_hw_provider(&pdev->dev, of_clk_hw_onecell_get, 2070+ clk_data); 2071+ 2072+ pm_runtime_mark_last_busy(&pdev->dev); 2073+ pm_runtime_put_autosuspend(&pdev->dev); 2074+ 2075+ return ret; 2076 } 2077 2078 static const struct of_device_id imx8qxp_lpcg_match[] = { 2079- { .compatible = "fsl,imx8qxp-lpcg-adma", &imx8qxp_ss_adma, }, 2080- { .compatible = "fsl,imx8qxp-lpcg-conn", &imx8qxp_ss_conn, }, 2081- { .compatible = "fsl,imx8qxp-lpcg-lsio", &imx8qxp_ss_lsio, }, 2082+ { .compatible = "fsl,imx8qxp-lpcg", NULL }, 2083 { /* sentinel */ } 2084 }; 2085 2086@@ -226,6 +116,7 @@ static struct platform_driver imx8qxp_lpcg_clk_driver = { 2087 .driver = { 2088 .name = "imx8qxp-lpcg-clk", 2089 .of_match_table = imx8qxp_lpcg_match, 2090+ .pm = &imx_clk_lpcg_scu_pm_ops, 2091 .suppress_bind_attrs = true, 2092 }, 2093 .probe = imx8qxp_lpcg_clk_probe, 2094diff --git a/drivers/clk/imx/clk-imx8qxp-lpcg.h b/drivers/clk/imx/clk-imx8qxp-lpcg.h 2095index 2a37ce57c..e4458780e 100644 2096--- a/drivers/clk/imx/clk-imx8qxp-lpcg.h 2097+++ b/drivers/clk/imx/clk-imx8qxp-lpcg.h 2098@@ -42,7 +42,6 @@ 2099 #define CONN_ENET_0_LPCG 0x30000 2100 #define CONN_ENET_1_LPCG 0x40000 2101 #define CONN_DTCP_LPCG 0x50000 2102-#define CONN_MLB_LPCG 0x60000 2103 #define CONN_USB_2_LPCG 0x70000 2104 #define CONN_USB_3_LPCG 0x80000 2105 #define CONN_NAND_LPCG 0x90000 2106@@ -99,4 +98,49 @@ 2107 #define ADMA_FLEXCAN_1_LPCG 0x1ce0000 2108 #define ADMA_FLEXCAN_2_LPCG 0x1cf0000 2109 2110+/* CM40 SS */ 2111+#define CM40_I2C_LPCG 0x60000 2112+ 2113+/* HSIO SS */ 2114+#define HSIO_PCIEA_LPCG 0x00000 2115+#define HSIO_PCIEB_LPCG 0x10000 2116+#define HSIO_SATA0_LPCG 0x20000 2117+#define HSIO_PHYX2_LPCG 0x30000 2118+#define HSIO_PHYX1_LPCG 0x40000 2119+#define HSIO_CRR_0_LPCG 0x50000 2120+#define HSIO_CRR_1_LPCG 0x60000 2121+#define HSIO_CRR_2_LPCG 0x70000 2122+#define HSIO_CRR_3_LPCG 0x80000 2123+#define HSIO_CRR_4_LPCG 0x90000 2124+#define HSIO_CRR_5_LPCG 0xa0000 2125+#define HSIO_GPIO_LPCG 0xb0000 2126+ 2127+/* IMG SS */ 2128+#define IMG_PDMA0_LPCG 0x00000 2129+#define IMG_PDMA1_LPCG 0x10000 2130+#define IMG_PDMA2_LPCG 0x20000 2131+#define IMG_PDMA3_LPCG 0x30000 2132+#define IMG_PDMA4_LPCG 0x40000 2133+#define IMG_PDMA5_LPCG 0x50000 2134+#define IMG_PDMA6_LPCG 0x60000 2135+#define IMG_PDMA7_LPCG 0x70000 2136+#define IMG_MIPI_CSI0_LPCG 0x80000 2137+#define IMG_MIPI_CSI1_LPCG 0x90000 2138+ 2139+/* CSI SS */ 2140+#define CSI_CSI0_CORE_LPCG 0x18 2141+#define CSI_CSI0_ESC_LPCG 0x1C 2142+#define CSI_CSI0_I2C0_LPCG 0x14 2143+#define CSI_CSI1_CORE_LPCG 0x18 2144+#define CSI_CSI1_ESC_LPCG 0x1C 2145+#define CSI_CSI1_I2C0_LPCG 0x14 2146+ 2147+/* Parallel Interface SS */ 2148+#define PI_PI0_PIXEL_LPCG 0x18 2149+#define PI_PI0_IPG_LPCG 0x04 2150+#define PI_PI0_MISC_LPCG 0x1C 2151+ 2152+/* DC0 SS */ 2153+/* TODO: ADD DC LPCGs */ 2154+ 2155 #endif /* _IMX8QXP_LPCG_H */ 2156diff --git a/drivers/clk/imx/clk-imx8qxp-rsrc.c b/drivers/clk/imx/clk-imx8qxp-rsrc.c 2157new file mode 100644 2158index 000000000..947d5a64c 2159--- /dev/null 2160+++ b/drivers/clk/imx/clk-imx8qxp-rsrc.c 2161@@ -0,0 +1,91 @@ 2162+// SPDX-License-Identifier: GPL-2.0+ 2163+/* 2164+ * Copyright 2019 NXP 2165+ * Dong Aisheng <aisheng.dong@nxp.com> 2166+ */ 2167+ 2168+#include <dt-bindings/firmware/imx/rsrc.h> 2169+ 2170+#include "clk-scu.h" 2171+ 2172+/* Keep sorted in the ascending order */ 2173+static u32 imx8qxp_clk_scu_rsrc_table[] = { 2174+ IMX_SC_R_DC_0_VIDEO0, 2175+ IMX_SC_R_DC_0_VIDEO1, 2176+ IMX_SC_R_DC_0, 2177+ IMX_SC_R_DC_0_PLL_0, 2178+ IMX_SC_R_DC_0_PLL_1, 2179+ IMX_SC_R_SPI_0, 2180+ IMX_SC_R_SPI_1, 2181+ IMX_SC_R_SPI_2, 2182+ IMX_SC_R_SPI_3, 2183+ IMX_SC_R_UART_0, 2184+ IMX_SC_R_UART_1, 2185+ IMX_SC_R_UART_2, 2186+ IMX_SC_R_UART_3, 2187+ IMX_SC_R_I2C_0, 2188+ IMX_SC_R_I2C_1, 2189+ IMX_SC_R_I2C_2, 2190+ IMX_SC_R_I2C_3, 2191+ IMX_SC_R_ADC_0, 2192+ IMX_SC_R_FTM_0, 2193+ IMX_SC_R_FTM_1, 2194+ IMX_SC_R_CAN_0, 2195+ IMX_SC_R_GPU_0_PID0, 2196+ IMX_SC_R_LCD_0, 2197+ IMX_SC_R_LCD_0_PWM_0, 2198+ IMX_SC_R_PWM_0, 2199+ IMX_SC_R_PWM_1, 2200+ IMX_SC_R_PWM_2, 2201+ IMX_SC_R_PWM_3, 2202+ IMX_SC_R_PWM_4, 2203+ IMX_SC_R_PWM_5, 2204+ IMX_SC_R_PWM_6, 2205+ IMX_SC_R_PWM_7, 2206+ IMX_SC_R_GPT_0, 2207+ IMX_SC_R_GPT_1, 2208+ IMX_SC_R_GPT_2, 2209+ IMX_SC_R_GPT_3, 2210+ IMX_SC_R_GPT_4, 2211+ IMX_SC_R_FSPI_0, 2212+ IMX_SC_R_FSPI_1, 2213+ IMX_SC_R_SDHC_0, 2214+ IMX_SC_R_SDHC_1, 2215+ IMX_SC_R_SDHC_2, 2216+ IMX_SC_R_ENET_0, 2217+ IMX_SC_R_ENET_1, 2218+ IMX_SC_R_USB_2, 2219+ IMX_SC_R_NAND, 2220+ IMX_SC_R_LVDS_0, 2221+ IMX_SC_R_LVDS_1, 2222+ IMX_SC_R_M4_0_UART, 2223+ IMX_SC_R_M4_0_I2C, 2224+ IMX_SC_R_ELCDIF_PLL, 2225+ IMX_SC_R_AUDIO_PLL_0, 2226+ IMX_SC_R_PI_0, 2227+ IMX_SC_R_PI_0_PWM_0, 2228+ IMX_SC_R_PI_0_I2C_0, 2229+ IMX_SC_R_PI_0_PLL, 2230+ IMX_SC_R_MIPI_0, 2231+ IMX_SC_R_MIPI_0_PWM_0, 2232+ IMX_SC_R_MIPI_0_I2C_0, 2233+ IMX_SC_R_MIPI_0_I2C_1, 2234+ IMX_SC_R_MIPI_1, 2235+ IMX_SC_R_MIPI_1_PWM_0, 2236+ IMX_SC_R_MIPI_1_I2C_0, 2237+ IMX_SC_R_MIPI_1_I2C_1, 2238+ IMX_SC_R_CSI_0, 2239+ IMX_SC_R_CSI_0_PWM_0, 2240+ IMX_SC_R_CSI_0_I2C_0, 2241+ IMX_SC_R_AUDIO_PLL_1, 2242+ IMX_SC_R_AUDIO_CLK_0, 2243+ IMX_SC_R_AUDIO_CLK_1, 2244+ IMX_SC_R_A35, 2245+ IMX_SC_R_VPU_DEC_0, 2246+ IMX_SC_R_VPU_ENC_0, 2247+}; 2248+ 2249+const struct imx_clk_scu_rsrc_table imx_clk_scu_rsrc_imx8qxp = { 2250+ .rsrc = imx8qxp_clk_scu_rsrc_table, 2251+ .num = ARRAY_SIZE(imx8qxp_clk_scu_rsrc_table), 2252+}; 2253diff --git a/drivers/clk/imx/clk-imx8qxp.c b/drivers/clk/imx/clk-imx8qxp.c 2254index 8c14e0bbe..29a8affda 100644 2255--- a/drivers/clk/imx/clk-imx8qxp.c 2256+++ b/drivers/clk/imx/clk-imx8qxp.c 2257@@ -9,139 +9,295 @@ 2258 #include <linux/io.h> 2259 #include <linux/module.h> 2260 #include <linux/of.h> 2261+#include <linux/of_device.h> 2262 #include <linux/platform_device.h> 2263 #include <linux/slab.h> 2264 2265+#include <dt-bindings/firmware/imx/rsrc.h> 2266+ 2267 #include "clk-scu.h" 2268 2269-#include <dt-bindings/clock/imx8-clock.h> 2270-#include <dt-bindings/firmware/imx/rsrc.h> 2271+static const char *pll0_sels[] = { 2272+ "clk_dummy", 2273+ "pi_dpll_clk", 2274+ "clk_dummy", 2275+ "clk_dummy", 2276+ "clk_dummy", 2277+}; 2278+ 2279+static const char *enet0_rgmii_txc_sels[] = { 2280+ "enet0_ref_div", 2281+ "clk_dummy", 2282+}; 2283+ 2284+static const char *enet1_rgmii_txc_sels[] __maybe_unused = { 2285+ "enet1_ref_div", 2286+ "clk_dummy", 2287+}; 2288+ 2289+static const char *dc0_sels[] = { 2290+ "clk_dummy", 2291+ "clk_dummy", 2292+ "dc0_pll0_clk", 2293+ "dc0_pll1_clk", 2294+ "dc0_bypass0_clk", 2295+}; 2296+ 2297+static const char *dc1_sels[] = { 2298+ "clk_dummy", 2299+ "clk_dummy", 2300+ "dc1_pll0_clk", 2301+ "dc1_pll1_clk", 2302+ "dc1_bypass0_clk", 2303+}; 2304+ 2305+static const char *hdmi_sels[] = { 2306+ "clk_dummy", 2307+ "hdmi_dig_pll_clk", 2308+ "clk_dummy", 2309+ "clk_dummy", 2310+ "hdmi_av_pll_clk", 2311+}; 2312+ 2313+static const char *hdmi_rx_sels[] = { 2314+ "clk_dummy", 2315+ "hdmi_rx_dig_pll_clk", 2316+ "clk_dummy", 2317+ "clk_dummy", 2318+ "hdmi_rx_bypass_clk", 2319+}; 2320+ 2321+static const char *lcd_pxl_sels[] = { 2322+ "dummy", 2323+ "dummy", 2324+ "dummy", 2325+ "dummy", 2326+ "lcd_pxl_bypass_div_clk", 2327+}; 2328+ 2329+static const char *mipi_sels[] = { 2330+ "dummy", 2331+ "dummy", 2332+ "mipi_pll_div2_clk", 2333+ "dummy", 2334+ "dummy", 2335+}; 2336+ 2337+static const char *lcd_sels[] = { 2338+ "clk_dummy", 2339+ "clk_dummy", 2340+ "clk_dummy", 2341+ "clk_dummy", 2342+ "elcdif_pll", 2343+}; 2344+ 2345+static const struct of_device_id imx8qxp_match[] = { 2346+ { .compatible = "fsl,scu-clk", }, 2347+ { .compatible = "fsl,imx8qxp-clk", &imx_clk_scu_rsrc_imx8qxp, }, 2348+ { .compatible = "fsl,imx8qm-clk", &imx_clk_scu_rsrc_imx8qm, }, 2349+ { .compatible = "fsl,imx8dxl-clk", &imx_clk_scu_rsrc_imx8dxl, }, 2350+ { /* sentinel */ } 2351+}; 2352 2353 static int imx8qxp_clk_probe(struct platform_device *pdev) 2354 { 2355+ const struct of_device_id *of_id = 2356+ of_match_device(imx8qxp_match, &pdev->dev); 2357 struct device_node *ccm_node = pdev->dev.of_node; 2358- struct clk_hw_onecell_data *clk_data; 2359- struct clk_hw **clks; 2360- int ret, i; 2361+ int ret; 2362 2363- ret = imx_clk_scu_init(); 2364+ ret = imx_clk_scu_init(ccm_node, of_id->data); 2365 if (ret) 2366 return ret; 2367 2368- clk_data = devm_kzalloc(&pdev->dev, struct_size(clk_data, hws, 2369- IMX_SCU_CLK_END), GFP_KERNEL); 2370- if (!clk_data) 2371- return -ENOMEM; 2372- 2373- clk_data->num = IMX_SCU_CLK_END; 2374- clks = clk_data->hws; 2375- 2376- /* Fixed clocks */ 2377- clks[IMX_CLK_DUMMY] = clk_hw_register_fixed_rate(NULL, "dummy", NULL, 0, 0); 2378- clks[IMX_ADMA_IPG_CLK_ROOT] = clk_hw_register_fixed_rate(NULL, "dma_ipg_clk_root", NULL, 0, 120000000); 2379- clks[IMX_CONN_AXI_CLK_ROOT] = clk_hw_register_fixed_rate(NULL, "conn_axi_clk_root", NULL, 0, 333333333); 2380- clks[IMX_CONN_AHB_CLK_ROOT] = clk_hw_register_fixed_rate(NULL, "conn_ahb_clk_root", NULL, 0, 166666666); 2381- clks[IMX_CONN_IPG_CLK_ROOT] = clk_hw_register_fixed_rate(NULL, "conn_ipg_clk_root", NULL, 0, 83333333); 2382- clks[IMX_DC_AXI_EXT_CLK] = clk_hw_register_fixed_rate(NULL, "dc_axi_ext_clk_root", NULL, 0, 800000000); 2383- clks[IMX_DC_AXI_INT_CLK] = clk_hw_register_fixed_rate(NULL, "dc_axi_int_clk_root", NULL, 0, 400000000); 2384- clks[IMX_DC_CFG_CLK] = clk_hw_register_fixed_rate(NULL, "dc_cfg_clk_root", NULL, 0, 100000000); 2385- clks[IMX_MIPI_IPG_CLK] = clk_hw_register_fixed_rate(NULL, "mipi_ipg_clk_root", NULL, 0, 120000000); 2386- clks[IMX_IMG_AXI_CLK] = clk_hw_register_fixed_rate(NULL, "img_axi_clk_root", NULL, 0, 400000000); 2387- clks[IMX_IMG_IPG_CLK] = clk_hw_register_fixed_rate(NULL, "img_ipg_clk_root", NULL, 0, 200000000); 2388- clks[IMX_IMG_PXL_CLK] = clk_hw_register_fixed_rate(NULL, "img_pxl_clk_root", NULL, 0, 600000000); 2389- clks[IMX_HSIO_AXI_CLK] = clk_hw_register_fixed_rate(NULL, "hsio_axi_clk_root", NULL, 0, 400000000); 2390- clks[IMX_HSIO_PER_CLK] = clk_hw_register_fixed_rate(NULL, "hsio_per_clk_root", NULL, 0, 133333333); 2391- clks[IMX_LSIO_MEM_CLK] = clk_hw_register_fixed_rate(NULL, "lsio_mem_clk_root", NULL, 0, 200000000); 2392- clks[IMX_LSIO_BUS_CLK] = clk_hw_register_fixed_rate(NULL, "lsio_bus_clk_root", NULL, 0, 100000000); 2393- 2394 /* ARM core */ 2395- clks[IMX_A35_CLK] = imx_clk_scu("a35_clk", IMX_SC_R_A35, IMX_SC_PM_CLK_CPU); 2396+ imx_clk_scu("a35_clk", IMX_SC_R_A35, IMX_SC_PM_CLK_CPU); 2397+ imx_clk_scu("a53_clk", IMX_SC_R_A53, IMX_SC_PM_CLK_CPU); 2398+ imx_clk_scu("a72_clk", IMX_SC_R_A72, IMX_SC_PM_CLK_CPU); 2399 2400 /* LSIO SS */ 2401- clks[IMX_LSIO_PWM0_CLK] = imx_clk_scu("pwm0_clk", IMX_SC_R_PWM_0, IMX_SC_PM_CLK_PER); 2402- clks[IMX_LSIO_PWM1_CLK] = imx_clk_scu("pwm1_clk", IMX_SC_R_PWM_1, IMX_SC_PM_CLK_PER); 2403- clks[IMX_LSIO_PWM2_CLK] = imx_clk_scu("pwm2_clk", IMX_SC_R_PWM_2, IMX_SC_PM_CLK_PER); 2404- clks[IMX_LSIO_PWM3_CLK] = imx_clk_scu("pwm3_clk", IMX_SC_R_PWM_3, IMX_SC_PM_CLK_PER); 2405- clks[IMX_LSIO_PWM4_CLK] = imx_clk_scu("pwm4_clk", IMX_SC_R_PWM_4, IMX_SC_PM_CLK_PER); 2406- clks[IMX_LSIO_PWM5_CLK] = imx_clk_scu("pwm5_clk", IMX_SC_R_PWM_5, IMX_SC_PM_CLK_PER); 2407- clks[IMX_LSIO_PWM6_CLK] = imx_clk_scu("pwm6_clk", IMX_SC_R_PWM_6, IMX_SC_PM_CLK_PER); 2408- clks[IMX_LSIO_PWM7_CLK] = imx_clk_scu("pwm7_clk", IMX_SC_R_PWM_7, IMX_SC_PM_CLK_PER); 2409- clks[IMX_LSIO_GPT0_CLK] = imx_clk_scu("gpt0_clk", IMX_SC_R_GPT_0, IMX_SC_PM_CLK_PER); 2410- clks[IMX_LSIO_GPT1_CLK] = imx_clk_scu("gpt1_clk", IMX_SC_R_GPT_1, IMX_SC_PM_CLK_PER); 2411- clks[IMX_LSIO_GPT2_CLK] = imx_clk_scu("gpt2_clk", IMX_SC_R_GPT_2, IMX_SC_PM_CLK_PER); 2412- clks[IMX_LSIO_GPT3_CLK] = imx_clk_scu("gpt3_clk", IMX_SC_R_GPT_3, IMX_SC_PM_CLK_PER); 2413- clks[IMX_LSIO_GPT4_CLK] = imx_clk_scu("gpt4_clk", IMX_SC_R_GPT_4, IMX_SC_PM_CLK_PER); 2414- clks[IMX_LSIO_FSPI0_CLK] = imx_clk_scu("fspi0_clk", IMX_SC_R_FSPI_0, IMX_SC_PM_CLK_PER); 2415- clks[IMX_LSIO_FSPI1_CLK] = imx_clk_scu("fspi1_clk", IMX_SC_R_FSPI_1, IMX_SC_PM_CLK_PER); 2416- 2417- /* ADMA SS */ 2418- clks[IMX_ADMA_UART0_CLK] = imx_clk_scu("uart0_clk", IMX_SC_R_UART_0, IMX_SC_PM_CLK_PER); 2419- clks[IMX_ADMA_UART1_CLK] = imx_clk_scu("uart1_clk", IMX_SC_R_UART_1, IMX_SC_PM_CLK_PER); 2420- clks[IMX_ADMA_UART2_CLK] = imx_clk_scu("uart2_clk", IMX_SC_R_UART_2, IMX_SC_PM_CLK_PER); 2421- clks[IMX_ADMA_UART3_CLK] = imx_clk_scu("uart3_clk", IMX_SC_R_UART_3, IMX_SC_PM_CLK_PER); 2422- clks[IMX_ADMA_SPI0_CLK] = imx_clk_scu("spi0_clk", IMX_SC_R_SPI_0, IMX_SC_PM_CLK_PER); 2423- clks[IMX_ADMA_SPI1_CLK] = imx_clk_scu("spi1_clk", IMX_SC_R_SPI_1, IMX_SC_PM_CLK_PER); 2424- clks[IMX_ADMA_SPI2_CLK] = imx_clk_scu("spi2_clk", IMX_SC_R_SPI_2, IMX_SC_PM_CLK_PER); 2425- clks[IMX_ADMA_SPI3_CLK] = imx_clk_scu("spi3_clk", IMX_SC_R_SPI_3, IMX_SC_PM_CLK_PER); 2426- clks[IMX_ADMA_CAN0_CLK] = imx_clk_scu("can0_clk", IMX_SC_R_CAN_0, IMX_SC_PM_CLK_PER); 2427- clks[IMX_ADMA_I2C0_CLK] = imx_clk_scu("i2c0_clk", IMX_SC_R_I2C_0, IMX_SC_PM_CLK_PER); 2428- clks[IMX_ADMA_I2C1_CLK] = imx_clk_scu("i2c1_clk", IMX_SC_R_I2C_1, IMX_SC_PM_CLK_PER); 2429- clks[IMX_ADMA_I2C2_CLK] = imx_clk_scu("i2c2_clk", IMX_SC_R_I2C_2, IMX_SC_PM_CLK_PER); 2430- clks[IMX_ADMA_I2C3_CLK] = imx_clk_scu("i2c3_clk", IMX_SC_R_I2C_3, IMX_SC_PM_CLK_PER); 2431- clks[IMX_ADMA_FTM0_CLK] = imx_clk_scu("ftm0_clk", IMX_SC_R_FTM_0, IMX_SC_PM_CLK_PER); 2432- clks[IMX_ADMA_FTM1_CLK] = imx_clk_scu("ftm1_clk", IMX_SC_R_FTM_1, IMX_SC_PM_CLK_PER); 2433- clks[IMX_ADMA_ADC0_CLK] = imx_clk_scu("adc0_clk", IMX_SC_R_ADC_0, IMX_SC_PM_CLK_PER); 2434- clks[IMX_ADMA_PWM_CLK] = imx_clk_scu("pwm_clk", IMX_SC_R_LCD_0_PWM_0, IMX_SC_PM_CLK_PER); 2435- clks[IMX_ADMA_LCD_CLK] = imx_clk_scu("lcd_clk", IMX_SC_R_LCD_0, IMX_SC_PM_CLK_PER); 2436+ imx_clk_scu("pwm0_clk", IMX_SC_R_PWM_0, IMX_SC_PM_CLK_PER); 2437+ imx_clk_scu("pwm1_clk", IMX_SC_R_PWM_1, IMX_SC_PM_CLK_PER); 2438+ imx_clk_scu("pwm2_clk", IMX_SC_R_PWM_2, IMX_SC_PM_CLK_PER); 2439+ imx_clk_scu("pwm3_clk", IMX_SC_R_PWM_3, IMX_SC_PM_CLK_PER); 2440+ imx_clk_scu("pwm4_clk", IMX_SC_R_PWM_4, IMX_SC_PM_CLK_PER); 2441+ imx_clk_scu("pwm5_clk", IMX_SC_R_PWM_5, IMX_SC_PM_CLK_PER); 2442+ imx_clk_scu("pwm6_clk", IMX_SC_R_PWM_6, IMX_SC_PM_CLK_PER); 2443+ imx_clk_scu("pwm7_clk", IMX_SC_R_PWM_7, IMX_SC_PM_CLK_PER); 2444+ imx_clk_scu("gpt1_clk", IMX_SC_R_GPT_1, IMX_SC_PM_CLK_PER); 2445+ imx_clk_scu("gpt2_clk", IMX_SC_R_GPT_2, IMX_SC_PM_CLK_PER); 2446+ imx_clk_scu("gpt3_clk", IMX_SC_R_GPT_3, IMX_SC_PM_CLK_PER); 2447+ imx_clk_scu("gpt4_clk", IMX_SC_R_GPT_4, IMX_SC_PM_CLK_PER); 2448+ imx_clk_scu("fspi0_clk", IMX_SC_R_FSPI_0, IMX_SC_PM_CLK_PER); 2449+ imx_clk_scu("fspi1_clk", IMX_SC_R_FSPI_1, IMX_SC_PM_CLK_PER); 2450+ 2451+ /* DMA SS */ 2452+ imx_clk_scu("uart0_clk", IMX_SC_R_UART_0, IMX_SC_PM_CLK_PER); 2453+ imx_clk_scu("uart1_clk", IMX_SC_R_UART_1, IMX_SC_PM_CLK_PER); 2454+ imx_clk_scu("uart2_clk", IMX_SC_R_UART_2, IMX_SC_PM_CLK_PER); 2455+ imx_clk_scu("uart3_clk", IMX_SC_R_UART_3, IMX_SC_PM_CLK_PER); 2456+ imx_clk_scu("uart4_clk", IMX_SC_R_UART_4, IMX_SC_PM_CLK_PER); 2457+ imx_clk_scu("sim0_clk", IMX_SC_R_EMVSIM_0, IMX_SC_PM_CLK_PER); 2458+ imx_clk_scu("spi0_clk", IMX_SC_R_SPI_0, IMX_SC_PM_CLK_PER); 2459+ imx_clk_scu("spi1_clk", IMX_SC_R_SPI_1, IMX_SC_PM_CLK_PER); 2460+ imx_clk_scu("spi2_clk", IMX_SC_R_SPI_2, IMX_SC_PM_CLK_PER); 2461+ imx_clk_scu("spi3_clk", IMX_SC_R_SPI_3, IMX_SC_PM_CLK_PER); 2462+ imx_clk_scu("can0_clk", IMX_SC_R_CAN_0, IMX_SC_PM_CLK_PER); 2463+ imx_clk_scu("can1_clk", IMX_SC_R_CAN_1, IMX_SC_PM_CLK_PER); 2464+ imx_clk_scu("can2_clk", IMX_SC_R_CAN_2, IMX_SC_PM_CLK_PER); 2465+ imx_clk_scu("i2c0_clk", IMX_SC_R_I2C_0, IMX_SC_PM_CLK_PER); 2466+ imx_clk_scu("i2c1_clk", IMX_SC_R_I2C_1, IMX_SC_PM_CLK_PER); 2467+ imx_clk_scu("i2c2_clk", IMX_SC_R_I2C_2, IMX_SC_PM_CLK_PER); 2468+ imx_clk_scu("i2c3_clk", IMX_SC_R_I2C_3, IMX_SC_PM_CLK_PER); 2469+ imx_clk_scu("i2c4_clk", IMX_SC_R_I2C_4, IMX_SC_PM_CLK_PER); 2470+ imx_clk_scu("ftm0_clk", IMX_SC_R_FTM_0, IMX_SC_PM_CLK_PER); 2471+ imx_clk_scu("ftm1_clk", IMX_SC_R_FTM_1, IMX_SC_PM_CLK_PER); 2472+ imx_clk_scu("adc0_clk", IMX_SC_R_ADC_0, IMX_SC_PM_CLK_PER); 2473+ imx_clk_scu("pwm_clk", IMX_SC_R_LCD_0_PWM_0, IMX_SC_PM_CLK_PER); 2474+ imx_clk_scu("elcdif_pll", IMX_SC_R_ELCDIF_PLL, IMX_SC_PM_CLK_PLL); 2475+ imx_clk_scu2("lcd_clk", lcd_sels, ARRAY_SIZE(lcd_sels), IMX_SC_R_LCD_0, IMX_SC_PM_CLK_PER); 2476+ imx_clk_scu2("lcd_pxl_clk", lcd_pxl_sels, ARRAY_SIZE(lcd_pxl_sels), IMX_SC_R_LCD_0, IMX_SC_PM_CLK_MISC0); 2477+ imx_clk_scu("lcd_pxl_bypass_div_clk", IMX_SC_R_LCD_0, IMX_SC_PM_CLK_BYPASS); 2478+ 2479+ 2480+ /* Audio SS */ 2481+ imx_clk_scu("audio_pll0_clk", IMX_SC_R_AUDIO_PLL_0, IMX_SC_PM_CLK_PLL); 2482+ imx_clk_scu("audio_pll1_clk", IMX_SC_R_AUDIO_PLL_1, IMX_SC_PM_CLK_PLL); 2483+ imx_clk_scu("audio_pll_div_clk0_clk", IMX_SC_R_AUDIO_PLL_0, IMX_SC_PM_CLK_MISC0); 2484+ imx_clk_scu("audio_pll_div_clk1_clk", IMX_SC_R_AUDIO_PLL_1, IMX_SC_PM_CLK_MISC0); 2485+ imx_clk_scu("audio_rec_clk0_clk", IMX_SC_R_AUDIO_PLL_0, IMX_SC_PM_CLK_MISC1); 2486+ imx_clk_scu("audio_rec_clk1_clk", IMX_SC_R_AUDIO_PLL_1, IMX_SC_PM_CLK_MISC1); 2487 2488 /* Connectivity */ 2489- clks[IMX_CONN_SDHC0_CLK] = imx_clk_scu("sdhc0_clk", IMX_SC_R_SDHC_0, IMX_SC_PM_CLK_PER); 2490- clks[IMX_CONN_SDHC1_CLK] = imx_clk_scu("sdhc1_clk", IMX_SC_R_SDHC_1, IMX_SC_PM_CLK_PER); 2491- clks[IMX_CONN_SDHC2_CLK] = imx_clk_scu("sdhc2_clk", IMX_SC_R_SDHC_2, IMX_SC_PM_CLK_PER); 2492- clks[IMX_CONN_ENET0_ROOT_CLK] = imx_clk_scu("enet0_clk", IMX_SC_R_ENET_0, IMX_SC_PM_CLK_PER); 2493- clks[IMX_CONN_ENET0_BYPASS_CLK] = imx_clk_scu("enet0_bypass_clk", IMX_SC_R_ENET_0, IMX_SC_PM_CLK_BYPASS); 2494- clks[IMX_CONN_ENET0_RGMII_CLK] = imx_clk_scu("enet0_rgmii_clk", IMX_SC_R_ENET_0, IMX_SC_PM_CLK_MISC0); 2495- clks[IMX_CONN_ENET1_ROOT_CLK] = imx_clk_scu("enet1_clk", IMX_SC_R_ENET_1, IMX_SC_PM_CLK_PER); 2496- clks[IMX_CONN_ENET1_BYPASS_CLK] = imx_clk_scu("enet1_bypass_clk", IMX_SC_R_ENET_1, IMX_SC_PM_CLK_BYPASS); 2497- clks[IMX_CONN_ENET1_RGMII_CLK] = imx_clk_scu("enet1_rgmii_clk", IMX_SC_R_ENET_1, IMX_SC_PM_CLK_MISC0); 2498- clks[IMX_CONN_GPMI_BCH_IO_CLK] = imx_clk_scu("gpmi_io_clk", IMX_SC_R_NAND, IMX_SC_PM_CLK_MST_BUS); 2499- clks[IMX_CONN_GPMI_BCH_CLK] = imx_clk_scu("gpmi_bch_clk", IMX_SC_R_NAND, IMX_SC_PM_CLK_PER); 2500- clks[IMX_CONN_USB2_ACLK] = imx_clk_scu("usb3_aclk_div", IMX_SC_R_USB_2, IMX_SC_PM_CLK_PER); 2501- clks[IMX_CONN_USB2_BUS_CLK] = imx_clk_scu("usb3_bus_div", IMX_SC_R_USB_2, IMX_SC_PM_CLK_MST_BUS); 2502- clks[IMX_CONN_USB2_LPM_CLK] = imx_clk_scu("usb3_lpm_div", IMX_SC_R_USB_2, IMX_SC_PM_CLK_MISC); 2503+ imx_clk_scu("sdhc0_clk", IMX_SC_R_SDHC_0, IMX_SC_PM_CLK_PER); 2504+ imx_clk_scu("sdhc1_clk", IMX_SC_R_SDHC_1, IMX_SC_PM_CLK_PER); 2505+ imx_clk_scu("sdhc2_clk", IMX_SC_R_SDHC_2, IMX_SC_PM_CLK_PER); 2506+ if (of_id->data == &imx_clk_scu_rsrc_imx8dxl) { 2507+ imx_clk_divider_gpr_scu("enet0_ref_div", "conn_enet0_root_clk", IMX_SC_R_ENET_0, IMX_SC_C_CLKDIV); 2508+ } else { 2509+ imx_clk_scu("enet0_root_clk", IMX_SC_R_ENET_0, IMX_SC_PM_CLK_PER); 2510+ imx_clk_divider_gpr_scu("enet0_ref_div", "enet0_root_clk", IMX_SC_R_ENET_0, IMX_SC_C_CLKDIV); 2511+ } 2512+ imx_clk_mux_gpr_scu("enet0_rgmii_txc_sel", enet0_rgmii_txc_sels, ARRAY_SIZE(enet0_rgmii_txc_sels), IMX_SC_R_ENET_0, IMX_SC_C_TXCLK); 2513+ imx_clk_scu("enet0_bypass_clk", IMX_SC_R_ENET_0, IMX_SC_PM_CLK_BYPASS); 2514+ imx_clk_gate_gpr_scu("enet0_ref_50_clk", "clk_dummy", IMX_SC_R_ENET_0, IMX_SC_C_DISABLE_50, true); 2515+ imx_clk_scu("enet1_root_clk", IMX_SC_R_ENET_1, IMX_SC_PM_CLK_PER); 2516+ 2517+ if (of_id->data != &imx_clk_scu_rsrc_imx8dxl) { 2518+ imx_clk_scu("enet0_rgmii_rx_clk", IMX_SC_R_ENET_0, IMX_SC_PM_CLK_MISC0); 2519+ imx_clk_scu("enet1_rgmii_rx_clk", IMX_SC_R_ENET_1, IMX_SC_PM_CLK_MISC0); 2520+ imx_clk_divider_gpr_scu("enet1_ref_div", "enet1_root_clk", IMX_SC_R_ENET_1, IMX_SC_C_CLKDIV); 2521+ imx_clk_mux_gpr_scu("enet1_rgmii_txc_sel", enet1_rgmii_txc_sels, ARRAY_SIZE(enet1_rgmii_txc_sels), IMX_SC_R_ENET_1, IMX_SC_C_TXCLK); 2522+ } 2523+ imx_clk_scu("enet1_bypass_clk", IMX_SC_R_ENET_1, IMX_SC_PM_CLK_BYPASS); 2524+ imx_clk_gate_gpr_scu("enet1_ref_50_clk", "clk_dummy", IMX_SC_R_ENET_1, IMX_SC_C_DISABLE_50, true); 2525+ imx_clk_scu("gpmi_io_clk", IMX_SC_R_NAND, IMX_SC_PM_CLK_MST_BUS); 2526+ imx_clk_scu("gpmi_bch_clk", IMX_SC_R_NAND, IMX_SC_PM_CLK_PER); 2527+ imx_clk_scu("usb3_aclk_div", IMX_SC_R_USB_2, IMX_SC_PM_CLK_PER); 2528+ imx_clk_scu("usb3_bus_div", IMX_SC_R_USB_2, IMX_SC_PM_CLK_MST_BUS); 2529+ imx_clk_scu("usb3_lpm_div", IMX_SC_R_USB_2, IMX_SC_PM_CLK_MISC); 2530 2531 /* Display controller SS */ 2532- clks[IMX_DC0_DISP0_CLK] = imx_clk_scu("dc0_disp0_clk", IMX_SC_R_DC_0, IMX_SC_PM_CLK_MISC0); 2533- clks[IMX_DC0_DISP1_CLK] = imx_clk_scu("dc0_disp1_clk", IMX_SC_R_DC_0, IMX_SC_PM_CLK_MISC1); 2534+ imx_clk_scu2("dc0_disp0_clk", dc0_sels, ARRAY_SIZE(dc0_sels), IMX_SC_R_DC_0, IMX_SC_PM_CLK_MISC0); 2535+ imx_clk_scu2("dc0_disp1_clk", dc0_sels, ARRAY_SIZE(dc0_sels), IMX_SC_R_DC_0, IMX_SC_PM_CLK_MISC1); 2536+ imx_clk_scu("dc0_pll0_clk", IMX_SC_R_DC_0_PLL_0, IMX_SC_PM_CLK_PLL); 2537+ imx_clk_scu("dc0_pll1_clk", IMX_SC_R_DC_0_PLL_1, IMX_SC_PM_CLK_PLL); 2538+ imx_clk_scu("dc0_bypass0_clk", IMX_SC_R_DC_0_VIDEO0, IMX_SC_PM_CLK_BYPASS); 2539+ imx_clk_scu("dc0_bypass1_clk", IMX_SC_R_DC_0_VIDEO1, IMX_SC_PM_CLK_BYPASS); 2540+ 2541+ imx_clk_scu2("dc1_disp0_clk", dc1_sels, ARRAY_SIZE(dc1_sels), IMX_SC_R_DC_1, IMX_SC_PM_CLK_MISC0); 2542+ imx_clk_scu2("dc1_disp1_clk", dc1_sels, ARRAY_SIZE(dc1_sels), IMX_SC_R_DC_1, IMX_SC_PM_CLK_MISC1); 2543+ imx_clk_scu("dc1_pll0_clk", IMX_SC_R_DC_1_PLL_0, IMX_SC_PM_CLK_PLL); 2544+ imx_clk_scu("dc1_pll1_clk", IMX_SC_R_DC_1_PLL_1, IMX_SC_PM_CLK_PLL); 2545+ imx_clk_scu("dc1_bypass0_clk", IMX_SC_R_DC_1_VIDEO0, IMX_SC_PM_CLK_BYPASS); 2546+ imx_clk_scu("dc1_bypass1_clk", IMX_SC_R_DC_1_VIDEO1, IMX_SC_PM_CLK_BYPASS); 2547 2548 /* MIPI-LVDS SS */ 2549- clks[IMX_MIPI0_I2C0_CLK] = imx_clk_scu("mipi0_i2c0_clk", IMX_SC_R_MIPI_0_I2C_0, IMX_SC_PM_CLK_MISC2); 2550- clks[IMX_MIPI0_I2C1_CLK] = imx_clk_scu("mipi0_i2c1_clk", IMX_SC_R_MIPI_0_I2C_1, IMX_SC_PM_CLK_MISC2); 2551+ imx_clk_scu("mipi0_bypass_clk", IMX_SC_R_MIPI_0, IMX_SC_PM_CLK_BYPASS); 2552+ imx_clk_scu("mipi0_pixel_clk", IMX_SC_R_MIPI_0, IMX_SC_PM_CLK_PER); 2553+ imx_clk_scu("lvds0_pixel_clk", IMX_SC_R_LVDS_0, IMX_SC_PM_CLK_MISC2); 2554+ imx_clk_scu("lvds0_bypass_clk", IMX_SC_R_LVDS_0, IMX_SC_PM_CLK_BYPASS); 2555+ imx_clk_scu("lvds0_phy_clk", IMX_SC_R_LVDS_0, IMX_SC_PM_CLK_MISC3); 2556+ imx_clk_scu2("mipi0_dsi_tx_esc_clk", mipi_sels, ARRAY_SIZE(mipi_sels), IMX_SC_R_MIPI_0, IMX_SC_PM_CLK_MST_BUS); 2557+ imx_clk_scu2("mipi0_dsi_rx_esc_clk", mipi_sels, ARRAY_SIZE(mipi_sels), IMX_SC_R_MIPI_0, IMX_SC_PM_CLK_SLV_BUS); 2558+ imx_clk_scu2("mipi0_dsi_phy_clk", mipi_sels, ARRAY_SIZE(mipi_sels), IMX_SC_R_MIPI_0, IMX_SC_PM_CLK_PHY); 2559+ imx_clk_scu("mipi0_i2c0_clk", IMX_SC_R_MIPI_0_I2C_0, IMX_SC_PM_CLK_MISC2); 2560+ imx_clk_scu("mipi0_i2c1_clk", IMX_SC_R_MIPI_0_I2C_1, IMX_SC_PM_CLK_MISC2); 2561+ imx_clk_scu("mipi0_pwm_clk", IMX_SC_R_MIPI_0_PWM_0, IMX_SC_PM_CLK_PER); 2562+ 2563+ imx_clk_scu("mipi1_bypass_clk", IMX_SC_R_MIPI_1, IMX_SC_PM_CLK_BYPASS); 2564+ imx_clk_scu("mipi1_pixel_clk", IMX_SC_R_MIPI_1, IMX_SC_PM_CLK_PER); 2565+ imx_clk_scu("lvds1_pixel_clk", IMX_SC_R_LVDS_1, IMX_SC_PM_CLK_MISC2); 2566+ imx_clk_scu("lvds1_bypass_clk", IMX_SC_R_LVDS_1, IMX_SC_PM_CLK_BYPASS); 2567+ imx_clk_scu("lvds1_phy_clk", IMX_SC_R_LVDS_1, IMX_SC_PM_CLK_MISC3); 2568+ imx_clk_scu2("mipi1_dsi_tx_esc_clk", mipi_sels, ARRAY_SIZE(mipi_sels), IMX_SC_R_MIPI_1, IMX_SC_PM_CLK_MST_BUS); 2569+ imx_clk_scu2("mipi1_dsi_rx_esc_clk", mipi_sels, ARRAY_SIZE(mipi_sels), IMX_SC_R_MIPI_1, IMX_SC_PM_CLK_SLV_BUS); 2570+ imx_clk_scu2("mipi1_dsi_phy_clk", mipi_sels, ARRAY_SIZE(mipi_sels), IMX_SC_R_MIPI_1, IMX_SC_PM_CLK_PHY); 2571+ imx_clk_scu("mipi1_i2c0_clk", IMX_SC_R_MIPI_1_I2C_0, IMX_SC_PM_CLK_MISC2); 2572+ imx_clk_scu("mipi1_i2c1_clk", IMX_SC_R_MIPI_1_I2C_1, IMX_SC_PM_CLK_MISC2); 2573+ imx_clk_scu("mipi1_pwm_clk", IMX_SC_R_MIPI_1_PWM_0, IMX_SC_PM_CLK_PER); 2574+ 2575+ imx_clk_scu("lvds0_i2c0_clk", IMX_SC_R_LVDS_0_I2C_0, IMX_SC_PM_CLK_PER); 2576+ imx_clk_scu("lvds0_pwm0_clk", IMX_SC_R_LVDS_0_PWM_0, IMX_SC_PM_CLK_PER); 2577+ 2578+ imx_clk_scu("lvds1_i2c0_clk", IMX_SC_R_LVDS_1_I2C_0, IMX_SC_PM_CLK_PER); 2579+ imx_clk_scu("lvds1_pwm0_clk", IMX_SC_R_LVDS_1_PWM_0, IMX_SC_PM_CLK_PER); 2580 2581 /* MIPI CSI SS */ 2582- clks[IMX_CSI0_CORE_CLK] = imx_clk_scu("mipi_csi0_core_clk", IMX_SC_R_CSI_0, IMX_SC_PM_CLK_PER); 2583- clks[IMX_CSI0_ESC_CLK] = imx_clk_scu("mipi_csi0_esc_clk", IMX_SC_R_CSI_0, IMX_SC_PM_CLK_MISC); 2584- clks[IMX_CSI0_I2C0_CLK] = imx_clk_scu("mipi_csi0_i2c0_clk", IMX_SC_R_CSI_0_I2C_0, IMX_SC_PM_CLK_PER); 2585- clks[IMX_CSI0_PWM0_CLK] = imx_clk_scu("mipi_csi0_pwm0_clk", IMX_SC_R_CSI_0_PWM_0, IMX_SC_PM_CLK_PER); 2586+ imx_clk_scu("mipi_csi0_core_clk", IMX_SC_R_CSI_0, IMX_SC_PM_CLK_PER); 2587+ imx_clk_scu("mipi_csi0_esc_clk", IMX_SC_R_CSI_0, IMX_SC_PM_CLK_MISC); 2588+ imx_clk_scu("mipi_csi0_i2c0_clk", IMX_SC_R_CSI_0_I2C_0, IMX_SC_PM_CLK_PER); 2589+ imx_clk_scu("mipi_csi0_pwm0_clk", IMX_SC_R_CSI_0_PWM_0, IMX_SC_PM_CLK_PER); 2590+ imx_clk_scu("mipi_csi1_core_clk", IMX_SC_R_CSI_1, IMX_SC_PM_CLK_PER); 2591+ imx_clk_scu("mipi_csi1_esc_clk", IMX_SC_R_CSI_1, IMX_SC_PM_CLK_MISC); 2592+ imx_clk_scu("mipi_csi1_i2c0_clk", IMX_SC_R_CSI_1_I2C_0, IMX_SC_PM_CLK_PER); 2593+ imx_clk_scu("mipi_csi1_pwm0_clk", IMX_SC_R_CSI_1_PWM_0, IMX_SC_PM_CLK_PER); 2594+ 2595+ /* Parallel Interface SS */ 2596+ imx_clk_scu("pi_dpll_clk", IMX_SC_R_PI_0_PLL, IMX_SC_PM_CLK_PLL); 2597+ imx_clk_scu2("pi_per_div_clk", pll0_sels, ARRAY_SIZE(pll0_sels), IMX_SC_R_PI_0, IMX_SC_PM_CLK_PER); 2598+ imx_clk_scu("pi_mclk_div_clk", IMX_SC_R_PI_0, IMX_SC_PM_CLK_MISC0); 2599+ imx_clk_scu("pi_i2c0_div_clk", IMX_SC_R_PI_0_I2C_0, IMX_SC_PM_CLK_PER); 2600 2601 /* GPU SS */ 2602- clks[IMX_GPU0_CORE_CLK] = imx_clk_scu("gpu_core0_clk", IMX_SC_R_GPU_0_PID0, IMX_SC_PM_CLK_PER); 2603- clks[IMX_GPU0_SHADER_CLK] = imx_clk_scu("gpu_shader0_clk", IMX_SC_R_GPU_0_PID0, IMX_SC_PM_CLK_MISC); 2604+ imx_clk_scu("gpu_core0_clk", IMX_SC_R_GPU_0_PID0, IMX_SC_PM_CLK_PER); 2605+ imx_clk_scu("gpu_shader0_clk", IMX_SC_R_GPU_0_PID0, IMX_SC_PM_CLK_MISC); 2606 2607- for (i = 0; i < clk_data->num; i++) { 2608- if (IS_ERR(clks[i])) 2609- pr_warn("i.MX clk %u: register failed with %ld\n", 2610- i, PTR_ERR(clks[i])); 2611- } 2612+ imx_clk_scu("gpu_core1_clk", IMX_SC_R_GPU_1_PID0, IMX_SC_PM_CLK_PER); 2613+ imx_clk_scu("gpu_shader1_clk", IMX_SC_R_GPU_1_PID0, IMX_SC_PM_CLK_MISC); 2614+ /* CM40 SS */ 2615+ imx_clk_scu("cm40_i2c_div", IMX_SC_R_M4_0_I2C, IMX_SC_PM_CLK_PER); 2616+ imx_clk_scu("cm40_lpuart_div", IMX_SC_R_M4_0_UART, IMX_SC_PM_CLK_PER); 2617 2618- return of_clk_add_hw_provider(ccm_node, of_clk_hw_onecell_get, clk_data); 2619-} 2620+ /* CM41 SS */ 2621+ imx_clk_scu("cm41_i2c_div", IMX_SC_R_M4_1_I2C, IMX_SC_PM_CLK_PER); 2622 2623-static const struct of_device_id imx8qxp_match[] = { 2624- { .compatible = "fsl,scu-clk", }, 2625- { .compatible = "fsl,imx8qxp-clk", }, 2626- { /* sentinel */ } 2627-}; 2628+ /* HDMI TX SS */ 2629+ imx_clk_scu("hdmi_dig_pll_clk", IMX_SC_R_HDMI_PLL_0, IMX_SC_PM_CLK_PLL); 2630+ imx_clk_scu("hdmi_av_pll_clk", IMX_SC_R_HDMI_PLL_1, IMX_SC_PM_CLK_PLL); 2631+ imx_clk_scu2("hdmi_pixel_mux_clk", hdmi_sels, ARRAY_SIZE(hdmi_sels), IMX_SC_R_HDMI, IMX_SC_PM_CLK_MISC0); 2632+ imx_clk_scu2("hdmi_pixel_link_clk", hdmi_sels, ARRAY_SIZE(hdmi_sels), IMX_SC_R_HDMI, IMX_SC_PM_CLK_MISC1); 2633+ imx_clk_scu("hdmi_ipg_clk", IMX_SC_R_HDMI, IMX_SC_PM_CLK_MISC4); 2634+ imx_clk_scu("hdmi_i2c0_clk", IMX_SC_R_HDMI_I2C_0, IMX_SC_PM_CLK_MISC2); 2635+ imx_clk_scu("hdmi_hdp_core_clk", IMX_SC_R_HDMI, IMX_SC_PM_CLK_MISC2); 2636+ imx_clk_scu2("hdmi_pxl_clk", hdmi_sels, ARRAY_SIZE(hdmi_sels), IMX_SC_R_HDMI, IMX_SC_PM_CLK_MISC3); 2637+ imx_clk_scu("hdmi_i2s_bypass_clk", IMX_SC_R_HDMI_I2S, IMX_SC_PM_CLK_BYPASS); 2638+ imx_clk_scu("hdmi_i2s_clk", IMX_SC_R_HDMI_I2S, IMX_SC_PM_CLK_MISC0); 2639+ 2640+ /* HDMI RX SS */ 2641+ imx_clk_scu("hdmi_rx_i2s_bypass_clk", IMX_SC_R_HDMI_RX_BYPASS, IMX_SC_PM_CLK_MISC0); 2642+ imx_clk_scu("hdmi_rx_spdif_bypass_clk", IMX_SC_R_HDMI_RX_BYPASS, IMX_SC_PM_CLK_MISC1); 2643+ imx_clk_scu("hdmi_rx_bypass_clk", IMX_SC_R_HDMI_RX_BYPASS, IMX_SC_PM_CLK_MISC2); 2644+ imx_clk_scu("hdmi_rx_i2c0_clk", IMX_SC_R_HDMI_RX_I2C_0, IMX_SC_PM_CLK_MISC2); 2645+ imx_clk_scu("hdmi_rx_pwm_clk", IMX_SC_R_HDMI_RX_PWM_0, IMX_SC_PM_CLK_MISC2); 2646+ imx_clk_scu("hdmi_rx_spdif_clk", IMX_SC_R_HDMI_RX, IMX_SC_PM_CLK_MISC0); 2647+ imx_clk_scu2("hdmi_rx_hd_ref_clk", hdmi_rx_sels, ARRAY_SIZE(hdmi_rx_sels), IMX_SC_R_HDMI_RX, IMX_SC_PM_CLK_MISC1); 2648+ imx_clk_scu2("hdmi_rx_hd_core_clk", hdmi_rx_sels, ARRAY_SIZE(hdmi_rx_sels), IMX_SC_R_HDMI_RX, IMX_SC_PM_CLK_MISC2); 2649+ imx_clk_scu2("hdmi_rx_pxl_clk", hdmi_rx_sels, ARRAY_SIZE(hdmi_rx_sels), IMX_SC_R_HDMI_RX, IMX_SC_PM_CLK_MISC3); 2650+ imx_clk_scu("hdmi_rx_i2s_clk", IMX_SC_R_HDMI_RX, IMX_SC_PM_CLK_MISC4); 2651+ 2652+ return of_clk_add_hw_provider(ccm_node, imx_scu_of_clk_src_get, imx_scu_clks); 2653+} 2654 2655 static struct platform_driver imx8qxp_clk_driver = { 2656 .driver = { 2657@@ -151,7 +307,12 @@ static struct platform_driver imx8qxp_clk_driver = { 2658 }, 2659 .probe = imx8qxp_clk_probe, 2660 }; 2661-module_platform_driver(imx8qxp_clk_driver); 2662+ 2663+static int __init imx8qxp_clk_driver_init(void) 2664+{ 2665+ return platform_driver_register(&imx8qxp_clk_driver); 2666+} 2667+subsys_initcall_sync(imx8qxp_clk_driver_init); 2668 2669 MODULE_AUTHOR("Aisheng Dong <aisheng.dong@nxp.com>"); 2670 MODULE_DESCRIPTION("NXP i.MX8QXP clock driver"); 2671diff --git a/drivers/clk/imx/clk-lpcg-scu.c b/drivers/clk/imx/clk-lpcg-scu.c 2672index 1f0e44f92..a2a78a3df 100644 2673--- a/drivers/clk/imx/clk-lpcg-scu.c 2674+++ b/drivers/clk/imx/clk-lpcg-scu.c 2675@@ -6,6 +6,7 @@ 2676 2677 #include <linux/bits.h> 2678 #include <linux/clk-provider.h> 2679+#include <linux/delay.h> 2680 #include <linux/err.h> 2681 #include <linux/io.h> 2682 #include <linux/slab.h> 2683@@ -34,10 +35,38 @@ struct clk_lpcg_scu { 2684 void __iomem *reg; 2685 u8 bit_idx; 2686 bool hw_gate; 2687+ 2688+ /* for state save&restore */ 2689+ u32 state; 2690 }; 2691 2692 #define to_clk_lpcg_scu(_hw) container_of(_hw, struct clk_lpcg_scu, hw) 2693 2694+/* e10858 -LPCG clock gating register synchronization errata */ 2695+static void do_lpcg_workaround(u32 rate, void __iomem *reg, u32 val) 2696+{ 2697+ writel(val, reg); 2698+ 2699+ if (rate >= 24000000 || rate == 0) { 2700+ u32 reg1; 2701+ 2702+ /* 2703+ * The time taken to access the LPCG registers from the AP core 2704+ * through the interconnect is longer than the minimum delay 2705+ * of 4 clock cycles required by the errata. 2706+ * Adding a readl will provide sufficient delay to prevent 2707+ * back-to-back writes. 2708+ */ 2709+ reg1 = readl(reg); 2710+ } else { 2711+ /* 2712+ * For clocks running below 24MHz, wait a minimum of 2713+ * 4 clock cycles. 2714+ */ 2715+ ndelay(4 * (DIV_ROUND_UP(1000000000, rate))); 2716+ } 2717+} 2718+ 2719 static int clk_lpcg_scu_enable(struct clk_hw *hw) 2720 { 2721 struct clk_lpcg_scu *clk = to_clk_lpcg_scu(hw); 2722@@ -54,7 +83,8 @@ static int clk_lpcg_scu_enable(struct clk_hw *hw) 2723 val |= CLK_GATE_SCU_LPCG_HW_SEL; 2724 2725 reg |= val << clk->bit_idx; 2726- writel(reg, clk->reg); 2727+ 2728+ do_lpcg_workaround(clk_hw_get_rate(hw), clk->reg, reg); 2729 2730 spin_unlock_irqrestore(&imx_lpcg_scu_lock, flags); 2731 2732@@ -71,7 +101,7 @@ static void clk_lpcg_scu_disable(struct clk_hw *hw) 2733 2734 reg = readl_relaxed(clk->reg); 2735 reg &= ~(CLK_GATE_SCU_LPCG_MASK << clk->bit_idx); 2736- writel(reg, clk->reg); 2737+ do_lpcg_workaround(clk_hw_get_rate(hw), clk->reg, reg); 2738 2739 spin_unlock_irqrestore(&imx_lpcg_scu_lock, flags); 2740 } 2741@@ -81,9 +111,9 @@ static const struct clk_ops clk_lpcg_scu_ops = { 2742 .disable = clk_lpcg_scu_disable, 2743 }; 2744 2745-struct clk_hw *imx_clk_lpcg_scu(const char *name, const char *parent_name, 2746- unsigned long flags, void __iomem *reg, 2747- u8 bit_idx, bool hw_gate) 2748+struct clk_hw *__imx_clk_lpcg_scu(struct device *dev, const char *name, 2749+ const char *parent_name, unsigned long flags, 2750+ void __iomem *reg, u8 bit_idx, bool hw_gate) 2751 { 2752 struct clk_lpcg_scu *clk; 2753 struct clk_init_data init; 2754@@ -107,11 +137,47 @@ struct clk_hw *imx_clk_lpcg_scu(const char *name, const char *parent_name, 2755 clk->hw.init = &init; 2756 2757 hw = &clk->hw; 2758- ret = clk_hw_register(NULL, hw); 2759+ ret = clk_hw_register(dev, hw); 2760 if (ret) { 2761 kfree(clk); 2762- hw = ERR_PTR(ret); 2763+ return ERR_PTR(ret); 2764 } 2765 2766+ if (dev) 2767+ dev_set_drvdata(dev, clk); 2768+ 2769 return hw; 2770 } 2771+ 2772+int __maybe_unused imx_clk_lpcg_scu_suspend(struct device *dev) 2773+{ 2774+ struct clk_lpcg_scu *clk = dev_get_drvdata(dev); 2775+ 2776+ if (!strncmp("hdmi_lpcg", clk_hw_get_name(&clk->hw), strlen("hdmi_lpcg"))) 2777+ return 0; 2778+ 2779+ clk->state = readl_relaxed(clk->reg); 2780+ dev_dbg(dev, "save lpcg state 0x%x\n", clk->state); 2781+ 2782+ return 0; 2783+} 2784+ 2785+int __maybe_unused imx_clk_lpcg_scu_resume(struct device *dev) 2786+{ 2787+ struct clk_lpcg_scu *clk = dev_get_drvdata(dev); 2788+ 2789+ if (!strncmp("hdmi_lpcg", clk_hw_get_name(&clk->hw), strlen("hdmi_lpcg"))) 2790+ return 0; 2791+ 2792+ /* FIXME: double write in case a failure */ 2793+ writel(clk->state, clk->reg); 2794+ do_lpcg_workaround(0, clk->reg, clk->state); 2795+ dev_dbg(dev, "restore lpcg state 0x%x\n", clk->state); 2796+ 2797+ return 0; 2798+} 2799+ 2800+const struct dev_pm_ops imx_clk_lpcg_scu_pm_ops = { 2801+ SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(imx_clk_lpcg_scu_suspend, 2802+ imx_clk_lpcg_scu_resume) 2803+}; 2804diff --git a/drivers/clk/imx/clk-pfd.c b/drivers/clk/imx/clk-pfd.c 2805index 5d2a9a3be..6c39b8c5a 100644 2806--- a/drivers/clk/imx/clk-pfd.c 2807+++ b/drivers/clk/imx/clk-pfd.c 2808@@ -5,9 +5,11 @@ 2809 */ 2810 2811 #include <linux/clk-provider.h> 2812+#include <linux/imx_sema4.h> 2813 #include <linux/io.h> 2814 #include <linux/slab.h> 2815 #include <linux/err.h> 2816+#include <soc/imx/src.h> 2817 #include "clk.h" 2818 2819 /** 2820@@ -32,20 +34,57 @@ struct clk_pfd { 2821 #define CLR 0x8 2822 #define OTG 0xc 2823 2824-static int clk_pfd_enable(struct clk_hw *hw) 2825+static void clk_pfd_do_hardware(struct clk_pfd *pfd, bool enable) 2826+{ 2827+ if (enable) 2828+ writel_relaxed(1 << ((pfd->idx + 1) * 8 - 1), pfd->reg + CLR); 2829+ else 2830+ writel_relaxed(1 << ((pfd->idx + 1) * 8 - 1), pfd->reg + SET); 2831+} 2832+ 2833+static void clk_pfd_do_shared_clks(struct clk_hw *hw, bool enable) 2834 { 2835 struct clk_pfd *pfd = to_clk_pfd(hw); 2836 2837- writel_relaxed(1 << ((pfd->idx + 1) * 8 - 1), pfd->reg + CLR); 2838+ if (imx_src_is_m4_enabled() && clk_on_imx6sx()) { 2839+#ifdef CONFIG_SOC_IMX6SX 2840+ if (!amp_power_mutex || !shared_mem) { 2841+ if (enable) 2842+ clk_pfd_do_hardware(pfd, enable); 2843+ return; 2844+ } 2845+ 2846+ imx_sema4_mutex_lock(amp_power_mutex); 2847+ if (shared_mem->ca9_valid != SHARED_MEM_MAGIC_NUMBER || 2848+ shared_mem->cm4_valid != SHARED_MEM_MAGIC_NUMBER) { 2849+ imx_sema4_mutex_unlock(amp_power_mutex); 2850+ return; 2851+ } 2852+ 2853+ if (!imx_update_shared_mem(hw, enable)) { 2854+ imx_sema4_mutex_unlock(amp_power_mutex); 2855+ return; 2856+ } 2857+ 2858+ clk_pfd_do_hardware(pfd, enable); 2859+ 2860+ imx_sema4_mutex_unlock(amp_power_mutex); 2861+#endif 2862+ } else { 2863+ clk_pfd_do_hardware(pfd, enable); 2864+ } 2865+} 2866+ 2867+static int clk_pfd_enable(struct clk_hw *hw) 2868+{ 2869+ clk_pfd_do_shared_clks(hw, true); 2870 2871 return 0; 2872 } 2873 2874 static void clk_pfd_disable(struct clk_hw *hw) 2875 { 2876- struct clk_pfd *pfd = to_clk_pfd(hw); 2877- 2878- writel_relaxed(1 << ((pfd->idx + 1) * 8 - 1), pfd->reg + SET); 2879+ clk_pfd_do_shared_clks(hw, false); 2880 } 2881 2882 static unsigned long clk_pfd_recalc_rate(struct clk_hw *hw, 2883diff --git a/drivers/clk/imx/clk-pfdv2.c b/drivers/clk/imx/clk-pfdv2.c 2884index 6b744c842..42505669c 100644 2885--- a/drivers/clk/imx/clk-pfdv2.c 2886+++ b/drivers/clk/imx/clk-pfdv2.c 2887@@ -161,8 +161,17 @@ static int clk_pfdv2_set_rate(struct clk_hw *hw, unsigned long rate, 2888 if (!rate) 2889 return -EINVAL; 2890 2891- /* PFD can NOT change rate without gating */ 2892- WARN_ON(clk_pfdv2_is_enabled(hw)); 2893+ /* 2894+ * PFD can NOT change rate without gating. 2895+ * as the PFDs may enabled in HW by default but no 2896+ * consumer used it, the enable count is '0', so the 2897+ * 'SET_RATE_GATE' can NOT help on blocking the set_rate 2898+ * ops especially for 'assigned-clock-xxx'. In order 2899+ * to simplify the case, just disable the PFD if it is 2900+ * enabled in HW but not in SW. 2901+ */ 2902+ if (clk_pfdv2_is_enabled(hw)) 2903+ clk_pfdv2_disable(hw); 2904 2905 tmp = tmp * 18 + rate / 2; 2906 do_div(tmp, rate); 2907@@ -191,8 +200,8 @@ static const struct clk_ops clk_pfdv2_ops = { 2908 .is_enabled = clk_pfdv2_is_enabled, 2909 }; 2910 2911-struct clk_hw *imx_clk_hw_pfdv2(const char *name, const char *parent_name, 2912- void __iomem *reg, u8 idx) 2913+struct clk_hw *imx_clk_hw_pfdv2(enum imx_pfdv2_type type, const char *name, 2914+ const char *parent_name, void __iomem *reg, u8 idx) 2915 { 2916 struct clk_init_data init; 2917 struct clk_pfdv2 *pfd; 2918@@ -214,7 +223,10 @@ struct clk_hw *imx_clk_hw_pfdv2(const char *name, const char *parent_name, 2919 init.ops = &clk_pfdv2_ops; 2920 init.parent_names = &parent_name; 2921 init.num_parents = 1; 2922- init.flags = CLK_SET_RATE_GATE | CLK_SET_RATE_PARENT; 2923+ if (type == IMX_PFDV2_IMX7ULP) 2924+ init.flags = CLK_SET_RATE_GATE | CLK_SET_RATE_PARENT; 2925+ else 2926+ init.flags = CLK_SET_RATE_GATE; 2927 2928 pfd->hw.init = &init; 2929 2930diff --git a/drivers/clk/imx/clk-pll14xx.c b/drivers/clk/imx/clk-pll14xx.c 2931index aba36e421..f7cfc5fea 100644 2932--- a/drivers/clk/imx/clk-pll14xx.c 2933+++ b/drivers/clk/imx/clk-pll14xx.c 2934@@ -137,9 +137,12 @@ static unsigned long clk_pll1443x_recalc_rate(struct clk_hw *hw, 2935 unsigned long parent_rate) 2936 { 2937 struct clk_pll14xx *pll = to_clk_pll14xx(hw); 2938+ const struct imx_pll14xx_rate_table *rate_table = pll->rate_table; 2939 u32 mdiv, pdiv, sdiv, pll_div_ctl0, pll_div_ctl1; 2940 short int kdiv; 2941 u64 fvco = parent_rate; 2942+ long rate = 0; 2943+ int i; 2944 2945 pll_div_ctl0 = readl_relaxed(pll->base + 4); 2946 pll_div_ctl1 = readl_relaxed(pll->base + 8); 2947@@ -148,13 +151,25 @@ static unsigned long clk_pll1443x_recalc_rate(struct clk_hw *hw, 2948 sdiv = (pll_div_ctl0 & SDIV_MASK) >> SDIV_SHIFT; 2949 kdiv = pll_div_ctl1 & KDIV_MASK; 2950 2951+ /* 2952+ * Sometimes, the recalculated rate has deviation due to 2953+ * the frac part. So find the accurate pll rate from the table 2954+ * first, if no match rate in the table, use the rate calculated 2955+ * from the equation below. 2956+ */ 2957+ for (i = 0; i < pll->rate_count; i++) { 2958+ if (rate_table[i].pdiv == pdiv && rate_table[i].mdiv == mdiv && 2959+ rate_table[i].sdiv == sdiv && rate_table[i].kdiv == kdiv) 2960+ rate = rate_table[i].rate; 2961+ } 2962+ 2963 /* fvco = (m * 65536 + k) * Fin / (p * 65536) */ 2964 fvco *= (mdiv * 65536 + kdiv); 2965 pdiv *= 65536; 2966 2967 do_div(fvco, pdiv << sdiv); 2968 2969- return fvco; 2970+ return rate ? (unsigned long) rate : (unsigned long)fvco; 2971 } 2972 2973 static inline bool clk_pll14xx_mp_change(const struct imx_pll14xx_rate_table *rate, 2974@@ -360,6 +375,26 @@ static void clk_pll14xx_unprepare(struct clk_hw *hw) 2975 writel_relaxed(val, pll->base + GNRL_CTL); 2976 } 2977 2978+void clk_set_delta_k(struct clk_hw *hw, short int delta_k) 2979+{ 2980+ struct clk_pll14xx *pll = to_clk_pll14xx(hw); 2981+ short int k; 2982+ u32 val; 2983+ 2984+ val = readl_relaxed(pll->base + 8); 2985+ k = (val & KDIV_MASK) + delta_k; 2986+ writel_relaxed(k << KDIV_SHIFT, pll->base + 8); 2987+} 2988+ 2989+void clk_get_pll_setting(struct clk_hw *hw, u32 *pll_div_ctrl0, 2990+ u32 *pll_div_ctrl1) 2991+{ 2992+ struct clk_pll14xx *pll = to_clk_pll14xx(hw); 2993+ 2994+ *pll_div_ctrl0 = readl_relaxed(pll->base + 4); 2995+ *pll_div_ctrl1 = readl_relaxed(pll->base + 8); 2996+} 2997+ 2998 static const struct clk_ops clk_pll1416x_ops = { 2999 .prepare = clk_pll14xx_prepare, 3000 .unprepare = clk_pll14xx_unprepare, 3001diff --git a/drivers/clk/imx/clk-pllv3.c b/drivers/clk/imx/clk-pllv3.c 3002index 20ee9611b..5fd4765e6 100644 3003--- a/drivers/clk/imx/clk-pllv3.c 3004+++ b/drivers/clk/imx/clk-pllv3.c 3005@@ -8,9 +8,11 @@ 3006 #include <linux/delay.h> 3007 #include <linux/io.h> 3008 #include <linux/iopoll.h> 3009+#include <linux/imx_sema4.h> 3010 #include <linux/slab.h> 3011 #include <linux/jiffies.h> 3012 #include <linux/err.h> 3013+#include <soc/imx/src.h> 3014 #include "clk.h" 3015 3016 #define PLL_NUM_OFFSET 0x10 3017@@ -65,36 +67,82 @@ static int clk_pllv3_wait_lock(struct clk_pllv3 *pll) 3018 if ((pll->powerup_set && !val) || (!pll->powerup_set && val)) 3019 return 0; 3020 3021- return readl_relaxed_poll_timeout(pll->base, val, val & BM_PLL_LOCK, 3022- 500, PLL_LOCK_TIMEOUT); 3023+ if (!(imx_src_is_m4_enabled() && clk_on_imx6sx())) 3024+ return readl_relaxed_poll_timeout(pll->base, val, val & BM_PLL_LOCK, 3025+ 500, PLL_LOCK_TIMEOUT); 3026+ else 3027+ return readl_relaxed_poll_timeout_atomic(pll->base, val, val & BM_PLL_LOCK, 3028+ 10, PLL_LOCK_TIMEOUT); 3029 } 3030 3031-static int clk_pllv3_prepare(struct clk_hw *hw) 3032+static int clk_pllv3_do_hardware(struct clk_hw *hw, bool enable) 3033 { 3034 struct clk_pllv3 *pll = to_clk_pllv3(hw); 3035+ int ret; 3036 u32 val; 3037 3038 val = readl_relaxed(pll->base); 3039- if (pll->powerup_set) 3040- val |= pll->power_bit; 3041- else 3042- val &= ~pll->power_bit; 3043- writel_relaxed(val, pll->base); 3044+ if (enable) { 3045+ if (pll->powerup_set) 3046+ val |= pll->power_bit; 3047+ else 3048+ val &= ~pll->power_bit; 3049+ writel_relaxed(val, pll->base); 3050+ 3051+ ret = clk_pllv3_wait_lock(pll); 3052+ if (ret) 3053+ return ret; 3054+ } else { 3055+ if (pll->powerup_set) 3056+ val &= ~pll->power_bit; 3057+ else 3058+ val |= pll->power_bit; 3059+ writel_relaxed(val, pll->base); 3060+ } 3061 3062- return clk_pllv3_wait_lock(pll); 3063+ return 0; 3064 } 3065 3066-static void clk_pllv3_unprepare(struct clk_hw *hw) 3067+static void clk_pllv3_do_shared_clks(struct clk_hw *hw, bool enable) 3068 { 3069- struct clk_pllv3 *pll = to_clk_pllv3(hw); 3070- u32 val; 3071+ if (imx_src_is_m4_enabled() && clk_on_imx6sx()) { 3072+#ifdef CONFIG_SOC_IMX6SX 3073+ if (!amp_power_mutex || !shared_mem) { 3074+ if (enable) 3075+ clk_pllv3_do_hardware(hw, enable); 3076+ return; 3077+ } 3078+ 3079+ imx_sema4_mutex_lock(amp_power_mutex); 3080+ if (shared_mem->ca9_valid != SHARED_MEM_MAGIC_NUMBER || 3081+ shared_mem->cm4_valid != SHARED_MEM_MAGIC_NUMBER) { 3082+ imx_sema4_mutex_unlock(amp_power_mutex); 3083+ return; 3084+ } 3085+ 3086+ if (!imx_update_shared_mem(hw, enable)) { 3087+ imx_sema4_mutex_unlock(amp_power_mutex); 3088+ return; 3089+ } 3090+ clk_pllv3_do_hardware(hw, enable); 3091+ 3092+ imx_sema4_mutex_unlock(amp_power_mutex); 3093+#endif 3094+ } else { 3095+ clk_pllv3_do_hardware(hw, enable); 3096+ } 3097+} 3098 3099- val = readl_relaxed(pll->base); 3100- if (pll->powerup_set) 3101- val &= ~pll->power_bit; 3102- else 3103- val |= pll->power_bit; 3104- writel_relaxed(val, pll->base); 3105+static int clk_pllv3_prepare(struct clk_hw *hw) 3106+{ 3107+ clk_pllv3_do_shared_clks(hw, true); 3108+ 3109+ return 0; 3110+} 3111+ 3112+static void clk_pllv3_unprepare(struct clk_hw *hw) 3113+{ 3114+ clk_pllv3_do_shared_clks(hw, false); 3115 } 3116 3117 static int clk_pllv3_is_prepared(struct clk_hw *hw) 3118diff --git a/drivers/clk/imx/clk-pllv4.c b/drivers/clk/imx/clk-pllv4.c 3119index 8ec703f27..3c750ccbe 100644 3120--- a/drivers/clk/imx/clk-pllv4.c 3121+++ b/drivers/clk/imx/clk-pllv4.c 3122@@ -23,14 +23,17 @@ 3123 3124 /* PLL Configuration Register (xPLLCFG) */ 3125 #define PLL_CFG_OFFSET 0x08 3126+#define IMX8ULP_PLL_CFG_OFFSET 0x10 3127 #define BP_PLL_MULT 16 3128 #define BM_PLL_MULT (0x7f << 16) 3129 3130 /* PLL Numerator Register (xPLLNUM) */ 3131 #define PLL_NUM_OFFSET 0x10 3132+#define IMX8ULP_PLL_NUM_OFFSET 0x1c 3133 3134 /* PLL Denominator Register (xPLLDENOM) */ 3135 #define PLL_DENOM_OFFSET 0x14 3136+#define IMX8ULP_PLL_DENOM_OFFSET 0x18 3137 3138 #define MAX_MFD 0x3fffffff 3139 #define DEFAULT_MFD 1000000 3140@@ -38,6 +41,9 @@ 3141 struct clk_pllv4 { 3142 struct clk_hw hw; 3143 void __iomem *base; 3144+ u32 cfg_offset; 3145+ u32 num_offset; 3146+ u32 denom_offset; 3147 }; 3148 3149 /* Valid PLL MULT Table */ 3150@@ -72,12 +78,12 @@ static unsigned long clk_pllv4_recalc_rate(struct clk_hw *hw, 3151 u32 mult, mfn, mfd; 3152 u64 temp64; 3153 3154- mult = readl_relaxed(pll->base + PLL_CFG_OFFSET); 3155+ mult = readl_relaxed(pll->base + pll->cfg_offset); 3156 mult &= BM_PLL_MULT; 3157 mult >>= BP_PLL_MULT; 3158 3159- mfn = readl_relaxed(pll->base + PLL_NUM_OFFSET); 3160- mfd = readl_relaxed(pll->base + PLL_DENOM_OFFSET); 3161+ mfn = readl_relaxed(pll->base + pll->num_offset); 3162+ mfd = readl_relaxed(pll->base + pll->denom_offset); 3163 temp64 = parent_rate; 3164 temp64 *= mfn; 3165 do_div(temp64, mfd); 3166@@ -165,13 +171,13 @@ static int clk_pllv4_set_rate(struct clk_hw *hw, unsigned long rate, 3167 do_div(temp64, parent_rate); 3168 mfn = temp64; 3169 3170- val = readl_relaxed(pll->base + PLL_CFG_OFFSET); 3171+ val = readl_relaxed(pll->base + pll->cfg_offset); 3172 val &= ~BM_PLL_MULT; 3173 val |= mult << BP_PLL_MULT; 3174- writel_relaxed(val, pll->base + PLL_CFG_OFFSET); 3175+ writel_relaxed(val, pll->base + pll->cfg_offset); 3176 3177- writel_relaxed(mfn, pll->base + PLL_NUM_OFFSET); 3178- writel_relaxed(mfd, pll->base + PLL_DENOM_OFFSET); 3179+ writel_relaxed(mfn, pll->base + pll->num_offset); 3180+ writel_relaxed(mfd, pll->base + pll->denom_offset); 3181 3182 return 0; 3183 } 3184@@ -207,8 +213,8 @@ static const struct clk_ops clk_pllv4_ops = { 3185 .is_prepared = clk_pllv4_is_prepared, 3186 }; 3187 3188-struct clk_hw *imx_clk_hw_pllv4(const char *name, const char *parent_name, 3189- void __iomem *base) 3190+struct clk_hw *imx_clk_hw_pllv4(enum imx_pllv4_type type, const char *name, 3191+ const char *parent_name, void __iomem *base) 3192 { 3193 struct clk_pllv4 *pll; 3194 struct clk_hw *hw; 3195@@ -221,6 +227,16 @@ struct clk_hw *imx_clk_hw_pllv4(const char *name, const char *parent_name, 3196 3197 pll->base = base; 3198 3199+ if (type == IMX_PLLV4_IMX8ULP) { 3200+ pll->cfg_offset = IMX8ULP_PLL_CFG_OFFSET; 3201+ pll->num_offset = IMX8ULP_PLL_NUM_OFFSET; 3202+ pll->denom_offset = IMX8ULP_PLL_DENOM_OFFSET; 3203+ } else { 3204+ pll->cfg_offset = PLL_CFG_OFFSET; 3205+ pll->num_offset = PLL_NUM_OFFSET; 3206+ pll->denom_offset = PLL_DENOM_OFFSET; 3207+ } 3208+ 3209 init.name = name; 3210 init.ops = &clk_pllv4_ops; 3211 init.parent_names = &parent_name; 3212diff --git a/drivers/clk/imx/clk-scu.c b/drivers/clk/imx/clk-scu.c 3213index b8b207274..bd71f24f8 100644 3214--- a/drivers/clk/imx/clk-scu.c 3215+++ b/drivers/clk/imx/clk-scu.c 3216@@ -6,16 +6,41 @@ 3217 3218 #include <dt-bindings/firmware/imx/rsrc.h> 3219 #include <linux/arm-smccc.h> 3220+#include <linux/bsearch.h> 3221 #include <linux/clk-provider.h> 3222 #include <linux/err.h> 3223+#include <linux/firmware/imx/svc/rm.h> 3224+#include <linux/of_platform.h> 3225+#include <linux/platform_device.h> 3226+#include <linux/pm_domain.h> 3227+#include <linux/pm_runtime.h> 3228 #include <linux/slab.h> 3229+#include <linux/syscalls.h> 3230+#include <xen/xen.h> 3231 3232 #include "clk-scu.h" 3233 3234 #define IMX_SIP_CPUFREQ 0xC2000001 3235 #define IMX_SIP_SET_CPUFREQ 0x00 3236+#define MAX_CLUSTER_NUM 2 3237 3238 static struct imx_sc_ipc *ccm_ipc_handle; 3239+static const struct imx_clk_scu_rsrc_table *rsrc_table; 3240+struct device_node *pd_np; 3241+u32 clock_cells; 3242+ 3243+struct imx_scu_clk_node { 3244+ const char *name; 3245+ u32 rsrc; 3246+ u8 clk_type; 3247+ const char * const *parents; 3248+ int num_parents; 3249+ 3250+ struct clk_hw *hw; 3251+ struct list_head node; 3252+}; 3253+ 3254+struct list_head imx_scu_clks[IMX_SC_R_LAST]; 3255 3256 /* 3257 * struct clk_scu - Description of one SCU clock 3258@@ -27,6 +52,26 @@ struct clk_scu { 3259 struct clk_hw hw; 3260 u16 rsrc_id; 3261 u8 clk_type; 3262+ 3263+ /* for state save&restore */ 3264+ struct clk_hw *parent; 3265+ u8 parent_index; 3266+ bool is_enabled; 3267+ u32 rate; 3268+}; 3269+ 3270+/* 3271+ * struct clk_gpr_scu - Description of one gate SCU clock 3272+ * @hw: the common clk_hw 3273+ * @rsrc_id: resource ID of this SCU clock 3274+ * @gpr_id: GPR ID index to control the divider 3275+ */ 3276+struct clk_gpr_scu { 3277+ struct clk_hw hw; 3278+ u16 rsrc_id; 3279+ u8 gpr_id; 3280+ u8 flags; 3281+ bool gate_invert; 3282 }; 3283 3284 /* 3285@@ -54,6 +99,9 @@ struct resp_get_clock_rate { 3286 __le32 rate; 3287 }; 3288 3289+#define to_clk_mux_gpr_scu(_hw) container_of(_hw, struct clk_mux_gpr_scu, hw) 3290+#define to_clk_gpr_scu(_hw) container_of(_hw, struct clk_gpr_scu, hw) 3291+ 3292 /* 3293 * struct imx_sc_msg_get_clock_rate - clock get rate protocol 3294 * @hdr: SCU protocol header 3295@@ -128,9 +176,48 @@ static inline struct clk_scu *to_clk_scu(struct clk_hw *hw) 3296 return container_of(hw, struct clk_scu, hw); 3297 } 3298 3299-int imx_clk_scu_init(void) 3300+static int imx_scu_clk_search_cmp(const void *rsrc, const void *rsrc_p) 3301 { 3302- return imx_scu_get_handle(&ccm_ipc_handle); 3303+ return *(u32 *)rsrc - *(u32 *)rsrc_p; 3304+} 3305+ 3306+bool imx_scu_clk_is_valid(u32 rsrc_id) 3307+{ 3308+ void *p; 3309+ 3310+ if (!rsrc_table) 3311+ return true; 3312+ 3313+ p = bsearch(&rsrc_id, rsrc_table->rsrc, rsrc_table->num, 3314+ sizeof(rsrc_table->rsrc[0]), imx_scu_clk_search_cmp); 3315+ return p != NULL; 3316+} 3317+ 3318+int imx_clk_scu_init(struct device_node *np, const void *data) 3319+{ 3320+ struct platform_device *pd_dev; 3321+ int ret, i; 3322+ 3323+ ret = imx_scu_get_handle(&ccm_ipc_handle); 3324+ if (ret) 3325+ return ret; 3326+ 3327+ if (of_property_read_u32(np, "#clock-cells", &clock_cells)) 3328+ return -EINVAL; 3329+ 3330+ if (clock_cells == 2) { 3331+ for (i = 0; i < IMX_SC_R_LAST; i++) 3332+ INIT_LIST_HEAD(&imx_scu_clks[i]); 3333+ 3334+ pd_np = of_find_compatible_node(NULL, NULL, "fsl,scu-pd"); 3335+ pd_dev = of_find_device_by_node(pd_np); 3336+ if (!pd_dev || !device_is_bound(&pd_dev->dev)) 3337+ return -EPROBE_DEFER; 3338+ 3339+ rsrc_table = data; 3340+ } 3341+ 3342+ return 0; 3343 } 3344 3345 /* 3346@@ -192,8 +279,10 @@ static int clk_scu_atf_set_cpu_rate(struct clk_hw *hw, unsigned long rate, 3347 struct arm_smccc_res res; 3348 unsigned long cluster_id; 3349 3350- if (clk->rsrc_id == IMX_SC_R_A35) 3351+ if (clk->rsrc_id == IMX_SC_R_A35 || clk->rsrc_id == IMX_SC_R_A53) 3352 cluster_id = 0; 3353+ else if (clk->rsrc_id == IMX_SC_R_A72) 3354+ cluster_id = 1; 3355 else 3356 return -EINVAL; 3357 3358@@ -254,6 +343,8 @@ static u8 clk_scu_get_parent(struct clk_hw *hw) 3359 return 0; 3360 } 3361 3362+ clk->parent_index = msg.data.resp.parent; 3363+ 3364 return msg.data.resp.parent; 3365 } 3366 3367@@ -262,6 +353,7 @@ static int clk_scu_set_parent(struct clk_hw *hw, u8 index) 3368 struct clk_scu *clk = to_clk_scu(hw); 3369 struct imx_sc_msg_set_clock_parent msg; 3370 struct imx_sc_rpc_msg *hdr = &msg.hdr; 3371+ int ret; 3372 3373 hdr->ver = IMX_SC_RPC_VERSION; 3374 hdr->svc = IMX_SC_RPC_SVC_PM; 3375@@ -272,7 +364,16 @@ static int clk_scu_set_parent(struct clk_hw *hw, u8 index) 3376 msg.clk = clk->clk_type; 3377 msg.parent = index; 3378 3379- return imx_scu_call_rpc(ccm_ipc_handle, &msg, true); 3380+ ret = imx_scu_call_rpc(ccm_ipc_handle, &msg, true); 3381+ if (ret) { 3382+ pr_err("%s: failed to set clock parent %d\n", 3383+ clk_hw_get_name(hw), ret); 3384+ return ret; 3385+ } 3386+ 3387+ clk->parent_index = index; 3388+ 3389+ return 0; 3390 } 3391 3392 static int sc_pm_clock_enable(struct imx_sc_ipc *ipc, u16 resource, 3393@@ -344,8 +445,15 @@ static const struct clk_ops clk_scu_cpu_ops = { 3394 .unprepare = clk_scu_unprepare, 3395 }; 3396 3397-struct clk_hw *__imx_clk_scu(const char *name, const char * const *parents, 3398- int num_parents, u32 rsrc_id, u8 clk_type) 3399+static const struct clk_ops clk_scu_pi_ops = { 3400+ .recalc_rate = clk_scu_recalc_rate, 3401+ .round_rate = clk_scu_round_rate, 3402+ .set_rate = clk_scu_set_rate, 3403+}; 3404+ 3405+struct clk_hw *__imx_clk_scu(struct device *dev, const char *name, 3406+ const char * const *parents, int num_parents, 3407+ u32 rsrc_id, u8 clk_type) 3408 { 3409 struct clk_init_data init; 3410 struct clk_scu *clk; 3411@@ -361,8 +469,10 @@ struct clk_hw *__imx_clk_scu(const char *name, const char * const *parents, 3412 3413 init.name = name; 3414 init.ops = &clk_scu_ops; 3415- if (rsrc_id == IMX_SC_R_A35) 3416+ if (rsrc_id == IMX_SC_R_A35 || rsrc_id == IMX_SC_R_A53 || rsrc_id == IMX_SC_R_A72) 3417 init.ops = &clk_scu_cpu_ops; 3418+ else if (rsrc_id == IMX_SC_R_PI_0_PLL) 3419+ init.ops = &clk_scu_pi_ops; 3420 else 3421 init.ops = &clk_scu_ops; 3422 init.parent_names = parents; 3423@@ -375,14 +485,429 @@ struct clk_hw *__imx_clk_scu(const char *name, const char * const *parents, 3424 * clock status from HW instead of using the possible invalid 3425 * cached rate. 3426 */ 3427- init.flags = CLK_GET_RATE_NOCACHE; 3428+ init.flags = CLK_GET_RATE_NOCACHE | CLK_SET_PARENT_NOCACHE; 3429+ clk->hw.init = &init; 3430+ 3431+ hw = &clk->hw; 3432+ ret = clk_hw_register(dev, hw); 3433+ if (ret) { 3434+ kfree(clk); 3435+ return ERR_PTR(ret); 3436+ } 3437+ 3438+ if (dev) 3439+ dev_set_drvdata(dev, clk); 3440+ 3441+ return hw; 3442+} 3443+ 3444+struct clk_hw *imx_scu_of_clk_src_get(struct of_phandle_args *clkspec, 3445+ void *data) 3446+{ 3447+ unsigned int rsrc = clkspec->args[0]; 3448+ unsigned int idx = clkspec->args[1]; 3449+ struct list_head *scu_clks = data; 3450+ struct imx_scu_clk_node *clk; 3451+ 3452+ list_for_each_entry(clk, &scu_clks[rsrc], node) { 3453+ if (clk->clk_type == idx) 3454+ return clk->hw; 3455+ } 3456+ 3457+ return ERR_PTR(-ENODEV); 3458+} 3459+ 3460+static int imx_clk_scu_probe(struct platform_device *pdev) 3461+{ 3462+ struct device *dev = &pdev->dev; 3463+ struct imx_scu_clk_node *clk = dev_get_platdata(dev); 3464+ struct clk_hw *hw; 3465+ int ret; 3466+ 3467+ if (!((clk->rsrc == IMX_SC_R_A35) || (clk->rsrc == IMX_SC_R_A53) || 3468+ (clk->rsrc == IMX_SC_R_A72))) { 3469+ pm_runtime_set_suspended(dev); 3470+ pm_runtime_set_autosuspend_delay(dev, 50); 3471+ pm_runtime_use_autosuspend(&pdev->dev); 3472+ pm_runtime_enable(dev); 3473+ 3474+ ret = pm_runtime_get_sync(dev); 3475+ if (ret) { 3476+ pm_genpd_remove_device(dev); 3477+ pm_runtime_disable(dev); 3478+ return ret; 3479+ } 3480+ } 3481+ 3482+ hw = __imx_clk_scu(dev, clk->name, clk->parents, clk->num_parents, 3483+ clk->rsrc, clk->clk_type); 3484+ if (IS_ERR(hw)) { 3485+ pm_runtime_disable(dev); 3486+ return PTR_ERR(hw); 3487+ } 3488+ 3489+ clk->hw = hw; 3490+ list_add_tail(&clk->node, &imx_scu_clks[clk->rsrc]); 3491+ 3492+ if (!((clk->rsrc == IMX_SC_R_A35) || (clk->rsrc == IMX_SC_R_A53) || 3493+ (clk->rsrc == IMX_SC_R_A72))) { 3494+ pm_runtime_mark_last_busy(&pdev->dev); 3495+ pm_runtime_put_autosuspend(&pdev->dev); 3496+ } 3497+ 3498+ dev_dbg(dev, "register SCU clock rsrc:%d type:%d\n", clk->rsrc, 3499+ clk->clk_type); 3500+ 3501+ return 0; 3502+} 3503+ 3504+int __maybe_unused imx_clk_scu_suspend(struct device *dev) 3505+{ 3506+ struct clk_scu *clk = dev_get_drvdata(dev); 3507+ u32 rsrc_id = clk->rsrc_id; 3508+ 3509+ if ((rsrc_id == IMX_SC_R_A35) || (rsrc_id == IMX_SC_R_A53) || 3510+ (rsrc_id == IMX_SC_R_A72)) 3511+ return 0; 3512+ 3513+ clk->parent = clk_hw_get_parent(&clk->hw); 3514+ 3515+ /* DC SS needs to handle bypass clock using non-cached clock rate */ 3516+ if (clk->rsrc_id == IMX_SC_R_DC_0_VIDEO0 || 3517+ clk->rsrc_id == IMX_SC_R_DC_0_VIDEO1 || 3518+ clk->rsrc_id == IMX_SC_R_DC_1_VIDEO0 || 3519+ clk->rsrc_id == IMX_SC_R_DC_1_VIDEO1) 3520+ clk->rate = clk_scu_recalc_rate(&clk->hw, 0); 3521+ else 3522+ clk->rate = clk_hw_get_rate(&clk->hw); 3523+ 3524+ clk->is_enabled = clk_hw_is_enabled(&clk->hw); 3525+ 3526+ if (clk->parent) 3527+ dev_dbg(dev, "save parent %s idx %u\n", clk_hw_get_name(clk->parent), 3528+ clk->parent_index); 3529+ 3530+ if (clk->rate) 3531+ dev_dbg(dev, "save rate %d\n", clk->rate); 3532+ 3533+ if (clk->is_enabled) 3534+ dev_dbg(dev, "save enabled state\n"); 3535+ 3536+ return 0; 3537+} 3538+ 3539+int __maybe_unused imx_clk_scu_resume(struct device *dev) 3540+{ 3541+ struct clk_scu *clk = dev_get_drvdata(dev); 3542+ u32 rsrc_id = clk->rsrc_id; 3543+ int ret = 0; 3544+ 3545+ if ((rsrc_id == IMX_SC_R_A35) || (rsrc_id == IMX_SC_R_A53) || 3546+ (rsrc_id == IMX_SC_R_A72)) 3547+ return 0; 3548+ 3549+ if (clk->parent) { 3550+ ret = clk_scu_set_parent(&clk->hw, clk->parent_index); 3551+ dev_dbg(dev, "restore parent %s idx %u %s\n", 3552+ clk_hw_get_name(clk->parent), 3553+ clk->parent_index, !ret ? "success" : "failed"); 3554+ } 3555+ 3556+ if (clk->rate) { 3557+ ret = clk_scu_set_rate(&clk->hw, clk->rate, 0); 3558+ dev_dbg(dev, "restore rate %d %s\n", clk->rate, 3559+ !ret ? "success" : "failed"); 3560+ } 3561+ 3562+ if (clk->is_enabled && rsrc_id != IMX_SC_R_PI_0_PLL) { 3563+ ret = clk_scu_prepare(&clk->hw); 3564+ dev_dbg(dev, "restore enabled state %s\n", 3565+ !ret ? "success" : "failed"); 3566+ } 3567+ 3568+ return ret; 3569+} 3570+ 3571+const struct dev_pm_ops imx_clk_scu_pm_ops = { 3572+ SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(imx_clk_scu_suspend, 3573+ imx_clk_scu_resume) 3574+}; 3575+ 3576+static struct platform_driver imx_clk_scu_driver = { 3577+ .driver = { 3578+ .name = "imx-scu-clk", 3579+ .suppress_bind_attrs = true, 3580+ .pm = &imx_clk_scu_pm_ops, 3581+ }, 3582+ .probe = imx_clk_scu_probe, 3583+}; 3584+ 3585+static int __init imx_clk_scu_driver_init(void) 3586+{ 3587+ return platform_driver_register(&imx_clk_scu_driver); 3588+} 3589+subsys_initcall_sync(imx_clk_scu_driver_init); 3590+ 3591+static int imx_clk_scu_attach_pd(struct device *dev, u32 rsrc_id) 3592+{ 3593+ struct of_phandle_args genpdspec = { 3594+ .np = pd_np, 3595+ .args_count = 1, 3596+ .args[0] = rsrc_id, 3597+ }; 3598+ 3599+ if ((rsrc_id == IMX_SC_R_A35) || (rsrc_id == IMX_SC_R_A53) || 3600+ (rsrc_id == IMX_SC_R_A72)) 3601+ return 0; 3602+ 3603+ /* 3604+ * Temp fix to avoid the uart clk attached pd power off uart_0 3605+ */ 3606+ if (rsrc_id == IMX_SC_R_UART_0 && xen_initial_domain()) 3607+ return 0; 3608+ 3609+ return of_genpd_add_device(&genpdspec, dev); 3610+} 3611+ 3612+static bool imx_clk_is_resource_owned(u32 rsrc) 3613+{ 3614+ /* 3615+ * A-core resources are special. SCFW reports they are not "owned" by 3616+ * current partition but linux can still adjust them for cpufreq. 3617+ * 3618+ * So force this to return false when running as a VM guest and always 3619+ * true otherwise. 3620+ */ 3621+ if (rsrc == IMX_SC_R_A53 || rsrc == IMX_SC_R_A72 || 3622+ rsrc == IMX_SC_R_A35) { 3623+ if (xen_domain() && !xen_initial_domain()) 3624+ return false; 3625+ return true; 3626+ } 3627+ 3628+ return imx_sc_rm_is_resource_owned(ccm_ipc_handle, rsrc); 3629+} 3630+ 3631+struct clk_hw *imx_clk_scu_alloc_dev(const char *name, 3632+ const char * const *parents, 3633+ int num_parents, u32 rsrc_id, u8 clk_type) 3634+{ 3635+ struct imx_scu_clk_node clk = { 3636+ .name = name, 3637+ .rsrc = rsrc_id, 3638+ .clk_type = clk_type, 3639+ .parents = parents, 3640+ .num_parents = num_parents, 3641+ }; 3642+ struct platform_device *pdev; 3643+ int ret; 3644+ 3645+ if (!imx_scu_clk_is_valid(rsrc_id)) 3646+ return NULL; 3647+ 3648+ if (!imx_clk_is_resource_owned(rsrc_id)) 3649+ return NULL; 3650+ 3651+ pdev = platform_device_alloc(name, PLATFORM_DEVID_NONE); 3652+ if (!pdev) { 3653+ pr_err("%s: failed to allocate scu clk dev rsrc %d type %d\n", 3654+ name, rsrc_id, clk_type); 3655+ return ERR_PTR(-ENOMEM); 3656+ } 3657+ 3658+ ret = platform_device_add_data(pdev, &clk, sizeof(clk)); 3659+ if (ret) { 3660+ platform_device_put(pdev); 3661+ return ERR_PTR(-ENOMEM); 3662+ } 3663+ 3664+ pdev->driver_override = "imx-scu-clk"; 3665+ 3666+ ret = imx_clk_scu_attach_pd(&pdev->dev, rsrc_id); 3667+ if (ret) 3668+ pr_warn("%s: failed to attached the power domain %d\n", 3669+ name, ret); 3670+ 3671+ platform_device_add(pdev); 3672+ 3673+ /* For API backwards compatiblilty, simply return NULL for success */ 3674+ return NULL; 3675+} 3676+ 3677+static unsigned long clk_gpr_div_scu_recalc_rate(struct clk_hw *hw, 3678+ unsigned long parent_rate) 3679+{ 3680+ struct clk_gpr_scu *clk = to_clk_gpr_scu(hw); 3681+ unsigned long rate = 0; 3682+ u32 val; 3683+ int err; 3684+ 3685+ err = imx_sc_misc_get_control(ccm_ipc_handle, clk->rsrc_id, 3686+ clk->gpr_id, &val); 3687+ 3688+ rate = val ? parent_rate / 2 : parent_rate; 3689+ 3690+ return err ? 0 : rate; 3691+} 3692+ 3693+static long clk_gpr_div_scu_round_rate(struct clk_hw *hw, unsigned long rate, 3694+ unsigned long *prate) 3695+{ 3696+ if (rate < *prate) 3697+ rate = *prate / 2; 3698+ else 3699+ rate = *prate; 3700+ 3701+ return rate; 3702+} 3703+ 3704+static int clk_gpr_div_scu_set_rate(struct clk_hw *hw, unsigned long rate, 3705+ unsigned long parent_rate) 3706+{ 3707+ struct clk_gpr_scu *clk = to_clk_gpr_scu(hw); 3708+ uint32_t val; 3709+ int err; 3710+ 3711+ val = (rate < parent_rate) ? 1 : 0; 3712+ err = imx_sc_misc_set_control(ccm_ipc_handle, clk->rsrc_id, 3713+ clk->gpr_id, val); 3714+ 3715+ return err ? -EINVAL : 0; 3716+} 3717+ 3718+static const struct clk_ops clk_gpr_div_scu_ops = { 3719+ .recalc_rate = clk_gpr_div_scu_recalc_rate, 3720+ .round_rate = clk_gpr_div_scu_round_rate, 3721+ .set_rate = clk_gpr_div_scu_set_rate, 3722+}; 3723+ 3724+static u8 clk_gpr_mux_scu_get_parent(struct clk_hw *hw) 3725+{ 3726+ struct clk_gpr_scu *clk= to_clk_gpr_scu(hw); 3727+ u32 val = 0; 3728+ 3729+ imx_sc_misc_get_control(ccm_ipc_handle, clk->rsrc_id, 3730+ clk->gpr_id, &val); 3731+ 3732+ return (u8)val; 3733+} 3734+ 3735+static int clk_gpr_mux_scu_set_parent(struct clk_hw *hw, u8 index) 3736+{ 3737+ struct clk_gpr_scu *clk= to_clk_gpr_scu(hw); 3738+ 3739+ imx_sc_misc_set_control(ccm_ipc_handle, clk->rsrc_id, 3740+ clk->gpr_id, index); 3741+ 3742+ return 0; 3743+} 3744+ 3745+static const struct clk_ops clk_gpr_mux_scu_ops = { 3746+ .get_parent = clk_gpr_mux_scu_get_parent, 3747+ .set_parent = clk_gpr_mux_scu_set_parent, 3748+}; 3749+ 3750+static int clk_gpr_gate_scu_prepare(struct clk_hw *hw) 3751+{ 3752+ struct clk_gpr_scu *clk = to_clk_gpr_scu(hw); 3753+ 3754+ return imx_sc_misc_set_control(ccm_ipc_handle, clk->rsrc_id, 3755+ clk->gpr_id, !clk->gate_invert); 3756+} 3757+ 3758+static void clk_gpr_gate_scu_unprepare(struct clk_hw *hw) 3759+{ 3760+ struct clk_gpr_scu *clk = to_clk_gpr_scu(hw); 3761+ int ret; 3762+ 3763+ ret = imx_sc_misc_set_control(ccm_ipc_handle, clk->rsrc_id, 3764+ clk->gpr_id, clk->gate_invert); 3765+ if (ret) 3766+ pr_err("%s: clk unprepare failed %d\n", clk_hw_get_name(hw), 3767+ ret); 3768+} 3769+ 3770+static int clk_gpr_gate_scu_is_prepared(struct clk_hw *hw) 3771+{ 3772+ struct clk_gpr_scu *clk= to_clk_gpr_scu(hw); 3773+ int ret; 3774+ u32 val; 3775+ 3776+ ret = imx_sc_misc_get_control(ccm_ipc_handle, clk->rsrc_id, 3777+ clk->gpr_id, &val); 3778+ if (ret) 3779+ return ret; 3780+ 3781+ return clk->gate_invert ? !val : val; 3782+} 3783+ 3784+static struct clk_ops clk_gpr_gate_scu_ops = { 3785+ .prepare = clk_gpr_gate_scu_prepare, 3786+ .unprepare = clk_gpr_gate_scu_unprepare, 3787+ .is_prepared = clk_gpr_gate_scu_is_prepared, 3788+}; 3789+ 3790+struct clk_hw *__imx_clk_gpr_scu(const char *name, const char * const *parent_name, 3791+ int num_parents, u32 rsrc_id, u8 gpr_id, u8 flags, 3792+ bool invert) 3793+{ 3794+ struct imx_scu_clk_node *clk_node; 3795+ struct clk_gpr_scu *clk; 3796+ struct clk_hw *hw; 3797+ struct clk_init_data init; 3798+ int ret; 3799+ 3800+ if (rsrc_id >= IMX_SC_R_LAST) 3801+ return NULL; 3802+ 3803+ if (gpr_id >= IMX_SC_C_LAST) 3804+ return NULL; 3805+ 3806+ if (!imx_scu_clk_is_valid(rsrc_id)) 3807+ return ERR_PTR(-EINVAL); 3808+ 3809+ clk = kzalloc(sizeof(*clk), GFP_KERNEL); 3810+ if (!clk) 3811+ return ERR_PTR(-ENOMEM); 3812+ 3813+ clk_node = kzalloc(sizeof(*clk_node), GFP_KERNEL); 3814+ if (!clk_node) { 3815+ kfree(clk); 3816+ return ERR_PTR(-ENOMEM); 3817+ }; 3818+ 3819+ /* struct clk_gate_scu assignments */ 3820+ clk->rsrc_id = rsrc_id; 3821+ clk->gpr_id = gpr_id; 3822+ clk->flags = flags; 3823+ clk->gate_invert = invert; 3824+ 3825+ if (flags & IMX_SCU_GPR_CLK_GATE) 3826+ init.ops = &clk_gpr_gate_scu_ops; 3827+ 3828+ if (flags & IMX_SCU_GPR_CLK_DIV) 3829+ init.ops = &clk_gpr_div_scu_ops; 3830+ 3831+ if (flags & IMX_SCU_GPR_CLK_MUX) 3832+ init.ops = &clk_gpr_mux_scu_ops; 3833+ 3834+ init.flags = 0; 3835+ init.name = name; 3836+ init.parent_names = parent_name; 3837+ init.num_parents = num_parents; 3838+ 3839 clk->hw.init = &init; 3840 3841 hw = &clk->hw; 3842 ret = clk_hw_register(NULL, hw); 3843 if (ret) { 3844 kfree(clk); 3845+ kfree(clk_node); 3846 hw = ERR_PTR(ret); 3847+ } else { 3848+ clk_node->hw = hw; 3849+ clk_node->clk_type = gpr_id; 3850+ list_add_tail(&clk_node->node, &imx_scu_clks[rsrc_id]); 3851 } 3852 3853 return hw; 3854diff --git a/drivers/clk/imx/clk-scu.h b/drivers/clk/imx/clk-scu.h 3855index 2bcfaf06a..50f883199 100644 3856--- a/drivers/clk/imx/clk-scu.h 3857+++ b/drivers/clk/imx/clk-scu.h 3858@@ -8,25 +8,95 @@ 3859 #define __IMX_CLK_SCU_H 3860 3861 #include <linux/firmware/imx/sci.h> 3862+#include <linux/of.h> 3863 3864-int imx_clk_scu_init(void); 3865+#define IMX_SCU_GPR_CLK_GATE BIT(0) 3866+#define IMX_SCU_GPR_CLK_DIV BIT(1) 3867+#define IMX_SCU_GPR_CLK_MUX BIT(2) 3868 3869-struct clk_hw *__imx_clk_scu(const char *name, const char * const *parents, 3870- int num_parents, u32 rsrc_id, u8 clk_type); 3871+struct imx_clk_scu_rsrc_table { 3872+ const u32 *rsrc; 3873+ u8 num; 3874+}; 3875+ 3876+extern u32 clock_cells; 3877+extern struct list_head imx_scu_clks[]; 3878+extern const struct dev_pm_ops imx_clk_lpcg_scu_pm_ops; 3879+extern const struct imx_clk_scu_rsrc_table imx_clk_scu_rsrc_imx8qxp; 3880+extern const struct imx_clk_scu_rsrc_table imx_clk_scu_rsrc_imx8qm; 3881+extern const struct imx_clk_scu_rsrc_table imx_clk_scu_rsrc_imx8dxl; 3882+ 3883+int imx_clk_scu_init(struct device_node *np, const void *data); 3884+struct clk_hw *imx_scu_of_clk_src_get(struct of_phandle_args *clkspec, 3885+ void *data); 3886+struct clk_hw *imx_clk_scu_alloc_dev(const char *name, 3887+ const char * const *parents, 3888+ int num_parents, u32 rsrc_id, u8 clk_type); 3889+ 3890+struct clk_hw *__imx_clk_scu(struct device *dev, const char *name, 3891+ const char * const *parents, int num_parents, 3892+ u32 rsrc_id, u8 clk_type); 3893+ 3894+struct clk_hw *__imx_clk_lpcg_scu(struct device *dev, const char *name, 3895+ const char *parent_name, unsigned long flags, 3896+ void __iomem *reg, u8 bit_idx, bool hw_gate); 3897+ 3898+struct clk_hw *__imx_clk_gpr_scu(const char *name, const char * const *parent_name, 3899+ int num_parents, u32 rsrc_id, u8 gpr_id, u8 flags, 3900+ bool invert); 3901 3902 static inline struct clk_hw *imx_clk_scu(const char *name, u32 rsrc_id, 3903 u8 clk_type) 3904 { 3905- return __imx_clk_scu(name, NULL, 0, rsrc_id, clk_type); 3906+ if (clock_cells == 2) 3907+ return imx_clk_scu_alloc_dev(name, NULL, 0, rsrc_id, clk_type); 3908+ else 3909+ return __imx_clk_scu(NULL, name, NULL, 0, rsrc_id, clk_type); 3910 } 3911 3912 static inline struct clk_hw *imx_clk_scu2(const char *name, const char * const *parents, 3913 int num_parents, u32 rsrc_id, u8 clk_type) 3914 { 3915- return __imx_clk_scu(name, parents, num_parents, rsrc_id, clk_type); 3916+ if (clock_cells == 2) 3917+ return imx_clk_scu_alloc_dev(name, parents, num_parents, rsrc_id, clk_type); 3918+ else 3919+ return __imx_clk_scu(NULL, name, parents, num_parents, rsrc_id, clk_type); 3920 } 3921 3922-struct clk_hw *imx_clk_lpcg_scu(const char *name, const char *parent_name, 3923- unsigned long flags, void __iomem *reg, 3924- u8 bit_idx, bool hw_gate); 3925+static inline struct clk_hw *imx_clk_lpcg_scu_dev(struct device *dev, const char *name, 3926+ const char *parent_name, unsigned long flags, 3927+ void __iomem *reg, u8 bit_idx, bool hw_gate) 3928+{ 3929+ return __imx_clk_lpcg_scu(dev, name, parent_name, flags, reg, 3930+ bit_idx, hw_gate); 3931+} 3932+ 3933+static inline struct clk_hw *imx_clk_lpcg_scu(const char *name, const char *parent_name, 3934+ unsigned long flags, void __iomem *reg, 3935+ u8 bit_idx, bool hw_gate) 3936+{ 3937+ return __imx_clk_lpcg_scu(NULL, name, parent_name, flags, reg, 3938+ bit_idx, hw_gate); 3939+} 3940+ 3941+static inline struct clk_hw *imx_clk_gate_gpr_scu(const char *name, const char *parent_name, 3942+ u32 rsrc_id, u8 gpr_id, bool invert) 3943+{ 3944+ return __imx_clk_gpr_scu(name, &parent_name, 1, rsrc_id, gpr_id, 3945+ IMX_SCU_GPR_CLK_GATE, invert); 3946+} 3947+ 3948+static inline struct clk_hw *imx_clk_divider_gpr_scu(const char *name, const char *parent_name, 3949+ u32 rsrc_id, u8 gpr_id) 3950+{ 3951+ return __imx_clk_gpr_scu(name, &parent_name, 1, rsrc_id, gpr_id, 3952+ IMX_SCU_GPR_CLK_DIV, 0); 3953+} 3954+ 3955+static inline struct clk_hw *imx_clk_mux_gpr_scu(const char *name, const char * const *parent_names, 3956+ int num_parents, u32 rsrc_id, u8 gpr_id) 3957+{ 3958+ return __imx_clk_gpr_scu(name, parent_names, num_parents, rsrc_id, 3959+ gpr_id, IMX_SCU_GPR_CLK_MUX, 0); 3960+} 3961 #endif 3962diff --git a/drivers/clk/imx/clk.c b/drivers/clk/imx/clk.c 3963index 7cc669934..c323ddbbb 100644 3964--- a/drivers/clk/imx/clk.c 3965+++ b/drivers/clk/imx/clk.c 3966@@ -17,6 +17,8 @@ 3967 DEFINE_SPINLOCK(imx_ccm_lock); 3968 EXPORT_SYMBOL_GPL(imx_ccm_lock); 3969 3970+bool uart_from_osc; 3971+ 3972 void imx_unregister_clocks(struct clk *clks[], unsigned int count) 3973 { 3974 unsigned int i; 3975@@ -207,6 +209,14 @@ static int __init imx_clk_disable_uart(void) 3976 return 0; 3977 } 3978 late_initcall_sync(imx_clk_disable_uart); 3979+ 3980+static int __init setup_uart_clk(char *uart_rate) 3981+{ 3982+ uart_from_osc = true; 3983+ return 1; 3984+} 3985+__setup("uart_from_osc", setup_uart_clk); 3986+ 3987 #endif 3988 3989 MODULE_LICENSE("GPL v2"); 3990diff --git a/drivers/clk/imx/clk.h b/drivers/clk/imx/clk.h 3991index c66e00e87..7f82eea83 100644 3992--- a/drivers/clk/imx/clk.h 3993+++ b/drivers/clk/imx/clk.h 3994@@ -5,8 +5,7 @@ 3995 #include <linux/bits.h> 3996 #include <linux/spinlock.h> 3997 #include <linux/clk-provider.h> 3998- 3999-#define IMX_CLK_GATE2_SINGLE_BIT 1 4000+#include <soc/imx/src.h> 4001 4002 extern spinlock_t imx_ccm_lock; 4003 4004@@ -24,6 +23,9 @@ void imx_unregister_clocks(struct clk *clks[], unsigned int count); 4005 void imx_unregister_hw_clocks(struct clk_hw *hws[], unsigned int count); 4006 4007 extern void imx_cscmr1_fixup(u32 *val); 4008+extern struct imx_sema4_mutex *amp_power_mutex; 4009+extern struct imx_shared_mem *shared_mem; 4010+extern bool uart_from_osc; 4011 4012 enum imx_pllv1_type { 4013 IMX_PLLV1_IMX1, 4014@@ -44,6 +46,16 @@ enum imx_pll14xx_type { 4015 PLL_1443X, 4016 }; 4017 4018+enum imx_pllv4_type { 4019+ IMX_PLLV4_IMX7ULP, 4020+ IMX_PLLV4_IMX8ULP, 4021+}; 4022+ 4023+enum imx_pfdv2_type { 4024+ IMX_PFDV2_IMX7ULP, 4025+ IMX_PFDV2_IMX8ULP, 4026+}; 4027+ 4028 /* NOTE: Rate table should be kept sorted in descending order. */ 4029 struct imx_pll14xx_rate_table { 4030 unsigned int rate; 4031@@ -173,6 +185,25 @@ enum imx_pllv3_type { 4032 IMX_PLLV3_AV_IMX7, 4033 }; 4034 4035+#define MAX_SHARED_CLK_NUMBER 100 4036+#define SHARED_MEM_MAGIC_NUMBER 0x12345678 4037+#define MCC_POWER_SHMEM_NUMBER (6) 4038+ 4039+struct imx_shared_clk { 4040+ struct clk *self; 4041+ struct clk *parent; 4042+ void *m4_clk; 4043+ void *m4_clk_parent; 4044+ u8 ca9_enabled; 4045+ u8 cm4_enabled; 4046+}; 4047+ 4048+struct imx_shared_mem { 4049+ u32 ca9_valid; 4050+ u32 cm4_valid; 4051+ struct imx_shared_clk imx_clk[MAX_SHARED_CLK_NUMBER]; 4052+}; 4053+ 4054 struct clk_hw *imx_clk_hw_pllv3(enum imx_pllv3_type type, const char *name, 4055 const char *parent_name, void __iomem *base, u32 div_mask); 4056 4057@@ -193,8 +224,8 @@ struct clk_hw *imx_clk_hw_pllv3(enum imx_pllv3_type type, const char *name, 4058 .kdiv = (_k), \ 4059 } 4060 4061-struct clk_hw *imx_clk_hw_pllv4(const char *name, const char *parent_name, 4062- void __iomem *base); 4063+struct clk_hw *imx_clk_hw_pllv4(enum imx_pllv4_type type, const char *name, 4064+ const char *parent_name, void __iomem *base); 4065 4066 struct clk_hw *clk_hw_register_gate2(struct device *dev, const char *name, 4067 const char *parent_name, unsigned long flags, 4068@@ -217,8 +248,8 @@ struct clk_hw *imx_clk_hw_gate_exclusive(const char *name, const char *parent, 4069 struct clk_hw *imx_clk_hw_pfd(const char *name, const char *parent_name, 4070 void __iomem *reg, u8 idx); 4071 4072-struct clk_hw *imx_clk_hw_pfdv2(const char *name, const char *parent_name, 4073- void __iomem *reg, u8 idx); 4074+struct clk_hw *imx_clk_hw_pfdv2(enum imx_pfdv2_type type, const char *name, 4075+ const char *parent_name, void __iomem *reg, u8 idx); 4076 4077 struct clk_hw *imx_clk_hw_busy_divider(const char *name, const char *parent_name, 4078 void __iomem *reg, u8 shift, u8 width, 4079@@ -228,12 +259,25 @@ struct clk_hw *imx_clk_hw_busy_mux(const char *name, void __iomem *reg, u8 shift 4080 u8 width, void __iomem *busy_reg, u8 busy_shift, 4081 const char * const *parent_names, int num_parents); 4082 4083+int imx_update_shared_mem(struct clk_hw *hw, bool enable); 4084+ 4085+static inline int clk_on_imx6sx(void) 4086+{ 4087+ return of_machine_is_compatible("fsl,imx6sx"); 4088+} 4089+ 4090 struct clk_hw *imx7ulp_clk_hw_composite(const char *name, 4091 const char * const *parent_names, 4092 int num_parents, bool mux_present, 4093 bool rate_present, bool gate_present, 4094 void __iomem *reg); 4095 4096+struct clk_hw *imx8ulp_clk_hw_composite(const char *name, 4097+ const char * const *parent_names, 4098+ int num_parents, bool mux_present, 4099+ bool rate_present, bool gate_present, 4100+ void __iomem *reg, bool has_swrst); 4101+ 4102 struct clk_hw *imx_clk_hw_fixup_divider(const char *name, const char *parent, 4103 void __iomem *reg, u8 shift, u8 width, 4104 void (*fixup)(u32 *val)); 4105@@ -286,6 +330,15 @@ static inline struct clk_hw *imx_clk_hw_divider(const char *name, 4106 reg, shift, width, 0, &imx_ccm_lock); 4107 } 4108 4109+static inline struct clk_hw *imx_clk_hw_divider_closest(const char *name, 4110+ const char *parent, 4111+ void __iomem *reg, u8 shift, 4112+ u8 width) 4113+{ 4114+ return clk_hw_register_divider(NULL, name, parent, 0, 4115+ reg, shift, width, CLK_DIVIDER_ROUND_CLOSEST, &imx_ccm_lock); 4116+} 4117+ 4118 static inline struct clk_hw *imx_clk_hw_divider_flags(const char *name, 4119 const char *parent, 4120 void __iomem *reg, u8 shift, 4121@@ -383,10 +436,8 @@ static inline struct clk_hw *imx_dev_clk_hw_gate_shared(struct device *dev, 4122 void __iomem *reg, u8 shift, 4123 unsigned int *share_count) 4124 { 4125- return clk_hw_register_gate2(NULL, name, parent, CLK_SET_RATE_PARENT | 4126- CLK_OPS_PARENT_ENABLE, reg, shift, 0x3, 4127- IMX_CLK_GATE2_SINGLE_BIT, 4128- &imx_ccm_lock, share_count); 4129+ return clk_hw_register_gate2(dev, name, parent, CLK_SET_RATE_PARENT, reg, 4130+ shift, 0x1, 0, &imx_ccm_lock, share_count); 4131 } 4132 4133 static inline struct clk *imx_clk_gate2_cgr(const char *name, 4134@@ -399,7 +450,17 @@ static inline struct clk *imx_clk_gate2_cgr(const char *name, 4135 static inline struct clk_hw *imx_clk_hw_gate3(const char *name, const char *parent, 4136 void __iomem *reg, u8 shift) 4137 { 4138- return clk_hw_register_gate(NULL, name, parent, 4139+ /* 4140+ * per design team's suggestion, clk root is NOT consuming 4141+ * much power, and clk root enable/disable does NOT have domain 4142+ * control, so they suggest to leave clk root always on when 4143+ * M4 is enabled. 4144+ */ 4145+ if (imx_src_is_m4_enabled()) 4146+ return clk_hw_register_fixed_factor(NULL, name, parent, 4147+ CLK_SET_RATE_PARENT, 1, 1); 4148+ else 4149+ return clk_hw_register_gate(NULL, name, parent, 4150 CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE, 4151 reg, shift, 0, &imx_ccm_lock); 4152 } 4153@@ -454,6 +515,15 @@ static inline struct clk_hw *imx_dev_clk_hw_mux(struct device *dev, 4154 reg, shift, width, 0, &imx_ccm_lock); 4155 } 4156 4157+static inline struct clk *imx_dev_clk_mux(struct device *dev, const char *name, 4158+ void __iomem *reg, u8 shift, u8 width, 4159+ const char * const *parents, int num_parents) 4160+{ 4161+ return clk_register_mux(dev, name, parents, num_parents, 4162+ CLK_SET_RATE_NO_REPARENT | CLK_SET_PARENT_GATE, 4163+ reg, shift, width, 0, &imx_ccm_lock); 4164+} 4165+ 4166 static inline struct clk *imx_clk_mux2(const char *name, void __iomem *reg, 4167 u8 shift, u8 width, const char * const *parents, 4168 int num_parents) 4169@@ -601,4 +671,7 @@ struct clk_hw *imx_clk_hw_divider_gate(const char *name, const char *parent_name 4170 unsigned long flags, void __iomem *reg, u8 shift, u8 width, 4171 u8 clk_divider_flags, const struct clk_div_table *table, 4172 spinlock_t *lock); 4173+ 4174+void clk_set_delta_k(struct clk_hw *hw, short int delta_k); 4175+void clk_get_pll_setting(struct clk_hw *hw, u32 *pll_div_ctrl0, u32 *pll_div_ctrl1); 4176 #endif 4177diff --git a/drivers/clk/s32/Kconfig b/drivers/clk/s32/Kconfig 4178new file mode 100644 4179index 000000000..c28bdbbfa 4180--- /dev/null 4181+++ b/drivers/clk/s32/Kconfig 4182@@ -0,0 +1,4 @@ 4183+config ARCH_S32_CLK 4184+ bool "Enable S32 CLK Framework" 4185+ help 4186+ Support for the Clock Framework on S32 SoCs. 4187diff --git a/drivers/clk/s32/Makefile b/drivers/clk/s32/Makefile 4188new file mode 100644 4189index 000000000..169b8b590 4190--- /dev/null 4191+++ b/drivers/clk/s32/Makefile 4192@@ -0,0 +1,2 @@ 4193+obj-$(CONFIG_ARCH_S32_CLK) += clk-core.o 4194+obj-$(CONFIG_ARCH_S32_CLK) += s32v234/ 4195diff --git a/drivers/clk/s32/clk-core.c b/drivers/clk/s32/clk-core.c 4196new file mode 100644 4197index 000000000..a8cca66f7 4198--- /dev/null 4199+++ b/drivers/clk/s32/clk-core.c 4200@@ -0,0 +1,53 @@ 4201+// SPDX-License-Identifier: GPL-2.0-or-later 4202+/* 4203+ * Copyright 2015 Freescale Semiconductor, Inc. 4204+ * Copyright 2017 NXP 4205+ */ 4206+ 4207+#include <linux/clk.h> 4208+#include <linux/err.h> 4209+#include <linux/of.h> 4210+#include <linux/slab.h> 4211+#include <linux/spinlock.h> 4212+#include "clk.h" 4213+ 4214+void __init s32_check_clocks(struct clk *clks[], unsigned int count) 4215+{ 4216+ unsigned int i; 4217+ 4218+ for (i = 0; i < count; i++) 4219+ if (IS_ERR(clks[i])) 4220+ pr_err("S32 clk %u: register failed with %ld\n", 4221+ i, PTR_ERR(clks[i])); 4222+} 4223+ 4224+static struct clk * __init s32_obtain_fixed_clock_from_dt(const char *name) 4225+{ 4226+ struct of_phandle_args phandle; 4227+ struct clk *clk = ERR_PTR(-ENODEV); 4228+ char *path; 4229+ 4230+ path = kasprintf(GFP_KERNEL, "/clocks/%s", name); 4231+ if (!path) 4232+ return ERR_PTR(-ENOMEM); 4233+ 4234+ phandle.np = of_find_node_by_path(path); 4235+ kfree(path); 4236+ 4237+ if (phandle.np) { 4238+ clk = of_clk_get_from_provider(&phandle); 4239+ of_node_put(phandle.np); 4240+ } 4241+ return clk; 4242+} 4243+ 4244+struct clk * __init s32_obtain_fixed_clock( 4245+ const char *name, unsigned long rate) 4246+{ 4247+ struct clk *clk; 4248+ 4249+ clk = s32_obtain_fixed_clock_from_dt(name); 4250+ if (IS_ERR(clk)) 4251+ clk = s32_clk_fixed(name, rate); 4252+ return clk; 4253+} 4254diff --git a/drivers/clk/s32/clk.h b/drivers/clk/s32/clk.h 4255new file mode 100644 4256index 000000000..831006411 4257--- /dev/null 4258+++ b/drivers/clk/s32/clk.h 4259@@ -0,0 +1,55 @@ 4260+/* SPDX-License-Identifier: GPL-2.0-or-later */ 4261+/* 4262+ * Copyright 2015-2016 Freescale Semiconductor, Inc. 4263+ * Copyright 2017-2018 NXP 4264+ */ 4265+ 4266+#ifndef __MACH_S32_CLK_H 4267+#define __MACH_S32_CLK_H 4268+ 4269+#include <linux/spinlock.h> 4270+#include <linux/clk-provider.h> 4271+ 4272+#define PNAME(x) \ 4273+ static const char *x[] __initconst 4274+ 4275+void s32_check_clocks(struct clk *clks[], unsigned int count); 4276+ 4277+struct clk *s32_obtain_fixed_clock( 4278+ const char *name, unsigned long rate); 4279+ 4280+static inline struct clk *s32_clk_fixed(const char *name, unsigned long rate) 4281+{ 4282+ return clk_register_fixed_rate(NULL, name, NULL, 0, rate); 4283+} 4284+ 4285+static inline struct clk *s32_clk_divider(const char *name, const char *parent, 4286+ void __iomem *reg, u8 shift, u8 width, 4287+ spinlock_t *lock) 4288+{ 4289+ struct clk *tmp_clk = clk_register_divider(NULL, name, parent, 4290+ CLK_SET_RATE_PARENT, 4291+ reg, shift, width, 0, lock); 4292+ 4293+ return tmp_clk; 4294+} 4295+ 4296+static inline struct clk *s32_clk_mux(const char *name, void __iomem *reg, 4297+ u8 shift, u8 width, const char **parents, 4298+ u8 num_parents, spinlock_t *lock) 4299+{ 4300+ return clk_register_mux(NULL, name, parents, num_parents, 4301+ CLK_SET_RATE_NO_REPARENT, reg, shift, 4302+ width, 0, lock); 4303+} 4304+ 4305+static inline struct clk *s32_clk_fixed_factor(const char *name, 4306+ const char *parent, 4307+ unsigned int mult, 4308+ unsigned int div) 4309+{ 4310+ return clk_register_fixed_factor(NULL, name, parent, 4311+ CLK_SET_RATE_PARENT, mult, div); 4312+} 4313+ 4314+#endif 4315diff --git a/drivers/clk/s32/s32v234/Makefile b/drivers/clk/s32/s32v234/Makefile 4316new file mode 100644 4317index 000000000..7ddf9f4b5 4318--- /dev/null 4319+++ b/drivers/clk/s32/s32v234/Makefile 4320@@ -0,0 +1 @@ 4321+obj-$(CONFIG_ARCH_S32_CLK) += clk.o clk-plldig.o clk-dfs.o 4322diff --git a/drivers/clk/s32/s32v234/clk-dfs.c b/drivers/clk/s32/s32v234/clk-dfs.c 4323new file mode 100644 4324index 000000000..2bd569e13 4325--- /dev/null 4326+++ b/drivers/clk/s32/s32v234/clk-dfs.c 4327@@ -0,0 +1,236 @@ 4328+/* 4329+ * Copyright 2015-2016 Freescale Semiconductor, Inc. 4330+ * Copyright 2017-2018 NXP 4331+ * 4332+ * The code contained herein is licensed under the GNU General Public 4333+ * License. You may obtain a copy of the GNU General Public License 4334+ * Version 2 or later at the following locations: 4335+ * 4336+ * http://www.opensource.org/licenses/gpl-license.html 4337+ * http://www.gnu.org/copyleft/gpl.html 4338+ */ 4339+ 4340+#include <linux/clk.h> 4341+#include <linux/clk-provider.h> 4342+#include <linux/io.h> 4343+#include <linux/slab.h> 4344+#include <linux/err.h> 4345+#include "clk.h" 4346+ 4347+/** 4348+ * struct clk_dfs - S32 DFS clock 4349+ * @clk_hw: clock source 4350+ * @reg: DFS register address 4351+ * @idx: the index of DFS encoded in the register 4352+ * 4353+ * DFS clock found on S32 series. Each register for DFS has 4 clk_dfs 4354+ * data encoded, and member idx is used to specify the one. 4355+ * Only ARMPLL(3 DFS), ENETPLL(4 DFS) and DDRPLL(3 DFS) has DFS outputs. 4356+ */ 4357+struct clk_dfs { 4358+ struct clk_hw hw; 4359+ void __iomem *reg; 4360+ enum s32v234_plldig_type plltype; 4361+ u8 idx; 4362+ u32 mfn; 4363+}; 4364+ 4365+#define to_clk_dfs(_hw) container_of(_hw, struct clk_dfs, hw) 4366+ 4367+static int get_pllx_dfs_nr(enum s32v234_plldig_type plltype) 4368+{ 4369+ switch (plltype) { 4370+ case S32_PLLDIG_ARM: 4371+ return ARMPLL_DFS_NR; 4372+ case S32_PLLDIG_ENET: 4373+ return ENETPLL_DFS_NR; 4374+ case S32_PLLDIG_DDR: 4375+ return DDRPLL_DFS_NR; 4376+ case S32_PLLDIG_PERIPH: 4377+ case S32_PLLDIG_VIDEO: 4378+ pr_warn("Current selected PLL has no DFS\n"); 4379+ break; 4380+ } 4381+ 4382+ return -EINVAL; 4383+} 4384+static unsigned long get_pllx_dfsy_max_rate(enum s32v234_plldig_type plltype, 4385+ int dfsno) 4386+{ 4387+ switch (plltype) { 4388+ case S32_PLLDIG_ARM: 4389+ switch (dfsno) { 4390+ case 0: 4391+ return ARMPLL_DFS0_MAX_RATE; 4392+ case 1: 4393+ return ARMPLL_DFS1_MAX_RATE; 4394+ case 2: 4395+ return ARMPLL_DFS2_MAX_RATE; 4396+ } 4397+ break; 4398+ case S32_PLLDIG_ENET: 4399+ switch (dfsno) { 4400+ case 0: 4401+ return ENETPLL_DFS0_MAX_RATE; 4402+ case 1: 4403+ return ENETPLL_DFS1_MAX_RATE; 4404+ case 2: 4405+ return ENETPLL_DFS2_MAX_RATE; 4406+ case 3: 4407+ return ENETPLL_DFS3_MAX_RATE; 4408+ } 4409+ break; 4410+ case S32_PLLDIG_DDR: 4411+ switch (dfsno) { 4412+ case 0: 4413+ return DDRPLL_DFS0_MAX_RATE; 4414+ case 1: 4415+ return DDRPLL_DFS1_MAX_RATE; 4416+ case 2: 4417+ return DDRPLL_DFS2_MAX_RATE; 4418+ } 4419+ break; 4420+ case S32_PLLDIG_PERIPH: 4421+ case S32_PLLDIG_VIDEO: 4422+ pr_warn("Current selected PLL has no DFS."); 4423+ break; 4424+ default: 4425+ pr_warn("Unsupported PLL. Use %d or %d\n", 4426+ S32_PLLDIG_ARM, S32_PLLDIG_VIDEO); 4427+ break; 4428+ } 4429+ 4430+ return -EINVAL; 4431+} 4432+static int clk_dfs_enable(struct clk_hw *hw) 4433+{ 4434+ /* 4435+ * TODO: When SOC is available, this function 4436+ * should be tested and implemented for DFS 4437+ * if it is possible 4438+ */ 4439+ return 0; 4440+} 4441+ 4442+static void clk_dfs_disable(struct clk_hw *hw) 4443+{ 4444+ /* 4445+ * TODO: When SOC is available, this function 4446+ * should be tested and implemented for DFS 4447+ * if it is possible 4448+ */ 4449+} 4450+ 4451+static unsigned long clk_dfs_recalc_rate(struct clk_hw *hw, 4452+ unsigned long parent_rate) 4453+{ 4454+ struct clk_dfs *dfs = to_clk_dfs(hw); 4455+ u32 mfn, mfi, rate; 4456+ u32 dvport = readl_relaxed(DFS_DVPORTn(dfs->reg, dfs->idx)); 4457+ 4458+ mfn = (dvport & DFS_DVPORTn_MFN_MASK) >> DFS_DVPORTn_MFN_OFFSET; 4459+ mfi = (dvport & DFS_DVPORTn_MFI_MASK) >> DFS_DVPORTn_MFI_OFFSET; 4460+ mfi <<= 8; 4461+ rate = parent_rate / (mfi + mfn); 4462+ rate <<= 8; 4463+ 4464+ return rate; 4465+} 4466+ 4467+static long clk_dfs_round_rate(struct clk_hw *hw, unsigned long rate, 4468+ unsigned long *prate) 4469+{ 4470+ struct clk_dfs *dfs = to_clk_dfs(hw); 4471+ unsigned long max_allowed_rate; 4472+ 4473+ max_allowed_rate = get_pllx_dfsy_max_rate(dfs->plltype, dfs->idx); 4474+ 4475+ if (rate > max_allowed_rate) 4476+ rate = max_allowed_rate; 4477+ 4478+ return rate; 4479+} 4480+ 4481+static int clk_dfs_set_rate(struct clk_hw *hw, unsigned long rate, 4482+ unsigned long parent_rate) 4483+{ 4484+ struct clk_dfs *dfs = to_clk_dfs(hw); 4485+ u32 mfi; 4486+ u32 portreset = readl_relaxed(DFS_PORTRESET(dfs->reg)); 4487+ 4488+ writel_relaxed(DFS_CTRL_DLL_RESET, DFS_CTRL(dfs->reg)); 4489+ writel_relaxed(portreset | ~DFS_PORTRESET_PORTRESET_SET(dfs->idx), 4490+ DFS_PORTRESET(dfs->reg)); 4491+ 4492+ mfi = parent_rate/rate; 4493+ writel_relaxed(DFS_DVPORTn_MFI_SET(mfi) | 4494+ DFS_DVPORTn_MFN_SET(dfs->mfn), 4495+ DFS_DVPORTn(dfs->reg, dfs->idx)); 4496+ 4497+ writel_relaxed(~DFS_CTRL_DLL_RESET, DFS_CTRL(dfs->reg)); 4498+ 4499+ while (readl_relaxed(DFS_PORTSR(dfs->reg)) & (1 << (dfs->idx))) 4500+ ; 4501+ 4502+ return 0; 4503+} 4504+ 4505+static int clk_dfs_is_enabled(struct clk_hw *hw) 4506+{ 4507+ struct clk_dfs *dfs = to_clk_dfs(hw); 4508+ 4509+ /* Check if current DFS output port is locked */ 4510+ if (readl_relaxed(DFS_PORTSR(dfs->reg)) & (1 << (dfs->idx))) 4511+ return 0; 4512+ 4513+ return 1; 4514+} 4515+ 4516+static const struct clk_ops clk_dfs_ops = { 4517+ .enable = clk_dfs_enable, 4518+ .disable = clk_dfs_disable, 4519+ .recalc_rate = clk_dfs_recalc_rate, 4520+ .round_rate = clk_dfs_round_rate, 4521+ .set_rate = clk_dfs_set_rate, 4522+ .is_enabled = clk_dfs_is_enabled, 4523+}; 4524+ 4525+struct clk *s32v234_clk_dfs(enum s32v234_plldig_type type, const char *name, 4526+ const char *parent_name, void __iomem *reg, 4527+ u8 idx, u32 mfn) 4528+{ 4529+ struct clk_dfs *dfs; 4530+ struct clk *clk; 4531+ struct clk_init_data init; 4532+ 4533+ /* PERIPH and VIDEO PLL do not have DFS */ 4534+ if (type == S32_PLLDIG_PERIPH || type == S32_PLLDIG_VIDEO) 4535+ return ERR_PTR(-EINVAL); 4536+ 4537+ /* check if DFS index is valid for current pll */ 4538+ if (idx >= get_pllx_dfs_nr(type)) 4539+ return ERR_PTR(-EINVAL); 4540+ 4541+ dfs = kzalloc(sizeof(*dfs), GFP_KERNEL); 4542+ if (!dfs) 4543+ return ERR_PTR(-ENOMEM); 4544+ 4545+ dfs->reg = reg; 4546+ dfs->idx = idx; 4547+ dfs->mfn = mfn; 4548+ dfs->plltype = type; 4549+ 4550+ init.name = name; 4551+ init.ops = &clk_dfs_ops; 4552+ init.flags = 0; 4553+ init.parent_names = &parent_name; 4554+ init.num_parents = 1; 4555+ 4556+ dfs->hw.init = &init; 4557+ 4558+ clk = clk_register(NULL, &dfs->hw); 4559+ if (IS_ERR(clk)) 4560+ kfree(dfs); 4561+ 4562+ return clk; 4563+} 4564diff --git a/drivers/clk/s32/s32v234/clk-plldig.c b/drivers/clk/s32/s32v234/clk-plldig.c 4565new file mode 100644 4566index 000000000..6ed23974e 4567--- /dev/null 4568+++ b/drivers/clk/s32/s32v234/clk-plldig.c 4569@@ -0,0 +1,240 @@ 4570+// SPDX-License-Identifier: GPL-2.0-or-later 4571+/* 4572+ * Copyright 2015-2016 Freescale Semiconductor, Inc. 4573+ * Copyright 2017-2018 NXP 4574+ */ 4575+ 4576+#include <linux/clk.h> 4577+#include <linux/clk-provider.h> 4578+#include <linux/delay.h> 4579+#include <linux/io.h> 4580+#include <linux/slab.h> 4581+#include <linux/jiffies.h> 4582+#include <linux/err.h> 4583+#include "clk.h" 4584+ 4585+/* 4586+ * struct clk_plldig - S32 PLLDIG clock 4587+ * @clk_hw: clock source 4588+ * @base: base address of PLL registers 4589+ * @plldv_mfd: multiplication loop factor divider 4590+ * @plldv_rfdphi: PHI reduced frequency divider 4591+ * @plldv_rfdphi1: PHI reduced frequency divider 4592+ * 4593+ * PLLDIG clock version 1, found on S32 series. 4594+ */ 4595+struct clk_plldig { 4596+ struct clk_hw hw; 4597+ void __iomem *base; 4598+ enum s32v234_plldig_type type; 4599+ u32 plldv_mfd; 4600+ u32 pllfd_mfn; 4601+ u32 plldv_rfdphi; 4602+ u32 plldv_rfdphi1; 4603+}; 4604+ 4605+#define to_clk_plldig(_hw) container_of(_hw, struct clk_plldig, hw) 4606+ 4607+static unsigned long get_pllx_max_vco_rate(enum s32v234_plldig_type plltype) 4608+{ 4609+ switch (plltype) { 4610+ case S32_PLLDIG_PERIPH: 4611+ return PERIPHPLL_MAX_VCO_RATE; 4612+ default: 4613+ pr_warn("Unsupported PLL.\n"); 4614+ return -EINVAL; 4615+ } 4616+} 4617+ 4618+static unsigned long get_pllx_phiy_max_rate(enum s32v234_plldig_type plltype, 4619+ unsigned int phino) 4620+{ 4621+ switch (plltype) { 4622+ case S32_PLLDIG_PERIPH: 4623+ switch (phino) { 4624+ case 0: 4625+ return PERIPHPLL_MAX_PHI0_MAX_RATE; 4626+ case 1: 4627+ return PERIPHPLL_MAX_PHI1_MAX_RATE; 4628+ default: 4629+ break; 4630+ } 4631+ break; 4632+ default: 4633+ pr_warn("Unsupported PLL.\n"); 4634+ break; 4635+ } 4636+ return -EINVAL; 4637+} 4638+ 4639+static int clk_plldig_prepare(struct clk_hw *hw) 4640+{ 4641+ return 0; 4642+} 4643+ 4644+static void clk_plldig_unprepare(struct clk_hw *hw) 4645+{ 4646+} 4647+ 4648+static unsigned long clk_plldig_recalc_rate(struct clk_hw *hw, 4649+ unsigned long parent_rate) 4650+{ 4651+ struct clk_plldig *pll = to_clk_plldig(hw); 4652+ u32 plldv = readl_relaxed(PLLDIG_PLLDV(pll->base)); 4653+ u32 pllfd = readl_relaxed(PLLDIG_PLLFD(pll->base)); 4654+ u32 prediv, mfd, mfn, vco; 4655+ 4656+ prediv = (plldv & PLLDIG_PLLDV_PREDIV_MASK) 4657+ >> PLLDIG_PLLDV_PREDIV_OFFSET; 4658+ mfd = (plldv & PLLDIG_PLLDV_MFD_MASK); 4659+ 4660+ mfn = (pllfd & PLLDIG_PLLFD_MFN_MASK); 4661+ 4662+ if (prediv == 0) 4663+ prediv = 1; 4664+ 4665+ /* 4666+ * This formula is from platform reference manual 4667+ * (Rev. 1, 6/2015), PLLDIG chapter. 4668+ */ 4669+ vco = (parent_rate / prediv) * (mfd + mfn / 20480); 4670+ 4671+ return vco; 4672+} 4673+ 4674+static long clk_plldig_round_rate(struct clk_hw *hw, unsigned long rate, 4675+ unsigned long *prate) 4676+{ 4677+ struct clk_plldig *pll = to_clk_plldig(hw); 4678+ unsigned long max_allowed_rate = get_pllx_max_vco_rate(pll->type); 4679+ 4680+ if (rate > max_allowed_rate) 4681+ rate = max_allowed_rate; 4682+ else if (rate < MIN_VCO_RATE) 4683+ rate = MIN_VCO_RATE; 4684+ 4685+ return rate; 4686+} 4687+ 4688+static int clk_plldig_set_rate(struct clk_hw *hw, unsigned long rate, 4689+ unsigned long parent_rate) 4690+{ 4691+ struct clk_plldig *pll = to_clk_plldig(hw); 4692+ u32 pllfd, prediv; 4693+ 4694+ unsigned long max_allowed_rate = get_pllx_max_vco_rate(pll->type); 4695+ unsigned long phi0_max_rate = get_pllx_phiy_max_rate(pll->type, 0); 4696+ unsigned long phi1_max_rate = get_pllx_phiy_max_rate(pll->type, 1); 4697+ 4698+ if (rate < MIN_VCO_RATE || rate > max_allowed_rate) 4699+ return -EINVAL; 4700+ 4701+ if (((rate / pll->plldv_rfdphi) > phi0_max_rate) || 4702+ ((rate / pll->plldv_rfdphi) > phi1_max_rate)) 4703+ return -EINVAL; 4704+ 4705+ pllfd = readl_relaxed(PLLDIG_PLLFD(pll->base)); 4706+ prediv = (parent_rate / rate) * 4707+ (pll->plldv_mfd + pll->pllfd_mfn / 20480); 4708+ 4709+ writel_relaxed(PLLDIG_PLLDV_RFDPHI1_SET(pll->plldv_rfdphi1) | 4710+ PLLDIG_PLLDV_RFDPHI_SET(pll->plldv_rfdphi) | 4711+ PLLDIG_PLLDV_PREDIV_SET(prediv) | 4712+ PLLDIG_PLLDV_MFD_SET(pll->plldv_mfd), 4713+ PLLDIG_PLLDV(pll->base)); 4714+ 4715+ writel_relaxed(pllfd | PLLDIG_PLLFD_MFN_SET(pll->pllfd_mfn), 4716+ PLLDIG_PLLFD(pll->base)); 4717+ 4718+ /* 4719+ * To be implemented the wait_lock or an equivalent state 4720+ * return clk_plldig_wait_lock(pll); 4721+ */ 4722+ return 0; 4723+} 4724+ 4725+static const struct clk_ops clk_plldig_ops = { 4726+ .prepare = clk_plldig_prepare, 4727+ .unprepare = clk_plldig_unprepare, 4728+ .recalc_rate = clk_plldig_recalc_rate, 4729+ .round_rate = clk_plldig_round_rate, 4730+ .set_rate = clk_plldig_set_rate, 4731+}; 4732+ 4733+struct clk *s32v234_clk_plldig_phi(enum s32v234_plldig_type type, 4734+ const char *name, const char *parent, 4735+ void __iomem *base, u32 phi) 4736+{ 4737+ u32 plldv, rfd_phi; 4738+ 4739+ if (!base) 4740+ return ERR_PTR(-ENOMEM); 4741+ 4742+ plldv = readl_relaxed(PLLDIG_PLLDV(base)); 4743+ 4744+ switch (phi) { 4745+ /* PHI0 */ 4746+ case 0: 4747+ rfd_phi = (plldv & PLLDIG_PLLDV_RFDPHI_MASK) 4748+ >> PLLDIG_PLLDV_RFDPHI_OFFSET; 4749+ break; 4750+ /* PHI1 */ 4751+ case 1: 4752+ rfd_phi = (plldv & PLLDIG_PLLDV_RFDPHI1_MASK) 4753+ >> PLLDIG_PLLDV_RFDPHI1_OFFSET; 4754+ 4755+ if (rfd_phi == 0) 4756+ rfd_phi = 1; 4757+ 4758+ break; 4759+ default: 4760+ return ERR_PTR(-EINVAL); 4761+ } 4762+ 4763+ return clk_register_fixed_factor(NULL, name, parent, 4764+ CLK_SET_RATE_PARENT, 1, rfd_phi); 4765+} 4766+ 4767+struct clk *s32v234_clk_plldig(enum s32v234_plldig_type type, const char *name, 4768+ const char *parent_name, void __iomem *base, 4769+ u32 plldv_mfd, u32 pllfd_mfn, 4770+ u32 plldv_rfdphi, u32 plldv_rfdphi1) 4771+{ 4772+ struct clk_plldig *pll; 4773+ const struct clk_ops *ops; 4774+ struct clk *clk; 4775+ struct clk_init_data init; 4776+ 4777+ if (plldv_rfdphi > PLLDIG_PLLDV_RFDPHI_MAXVALUE) 4778+ return ERR_PTR(-EINVAL); 4779+ 4780+ if (plldv_rfdphi1 > PLLDIG_PLLDV_RFDPHI1_MAXVALUE) 4781+ return ERR_PTR(-EINVAL); 4782+ 4783+ pll = kzalloc(sizeof(*pll), GFP_KERNEL); 4784+ if (!pll) 4785+ return ERR_PTR(-ENOMEM); 4786+ 4787+ ops = &clk_plldig_ops; 4788+ 4789+ pll->base = base; 4790+ pll->type = type; 4791+ pll->plldv_mfd = plldv_mfd; 4792+ pll->pllfd_mfn = pllfd_mfn; 4793+ pll->plldv_rfdphi = plldv_rfdphi; 4794+ pll->plldv_rfdphi1 = plldv_rfdphi1; 4795+ 4796+ init.name = name; 4797+ init.ops = ops; 4798+ init.flags = 0; 4799+ init.parent_names = &parent_name; 4800+ init.num_parents = 1; 4801+ 4802+ pll->hw.init = &init; 4803+ 4804+ clk = clk_register(NULL, &pll->hw); 4805+ if (IS_ERR(clk)) 4806+ kfree(pll); 4807+ 4808+ return clk; 4809+} 4810diff --git a/drivers/clk/s32/s32v234/clk.c b/drivers/clk/s32/s32v234/clk.c 4811new file mode 100644 4812index 000000000..ad88c6b45 4813--- /dev/null 4814+++ b/drivers/clk/s32/s32v234/clk.c 4815@@ -0,0 +1,299 @@ 4816+// SPDX-License-Identifier: GPL-2.0-or-later 4817+/* 4818+ * Copyright 2015-2016 Freescale Semiconductor, Inc. 4819+ * Copyright 2017-2018 NXP 4820+ */ 4821+ 4822+#include <linux/of_address.h> 4823+#include <linux/clk.h> 4824+#include <dt-bindings/clock/s32v234-clock.h> 4825+ 4826+#include "clk.h" 4827+ 4828+static void __iomem *mc_cgm0_base; 4829+static void __iomem *mc_cgm1_base; 4830+static void __iomem *mc_cgm2_base; 4831+static void __iomem *mc_cgm3_base; 4832+static void __iomem *mc_me_base; 4833+static void __iomem *src_base; 4834+ 4835+DEFINE_SPINLOCK(s32v234_lock); 4836+ 4837+/* sources for multiplexer clocks, this is used multiple times */ 4838+PNAME(osc_sels) = {"firc", "fxosc", }; 4839+ 4840+PNAME(sys_sels) = {"firc", "fxosc", "armpll_dfs0", }; 4841+ 4842+PNAME(can_sels) = {"firc", "fxosc", "dummy", 4843+ "periphpll_phi0_div5", }; 4844+ 4845+PNAME(lin_sels) = {"firc", "fxosc", "dummy", 4846+ "periphpll_phi0_div3", "dummy", "dummy", 4847+ "dummy", "dummy", "sys6",}; 4848+ 4849+PNAME(sdhc_sels) = {"firc", "fxosc", "dummy", "dummy", 4850+ "enetpll_dfs3",}; 4851+ 4852+PNAME(enet_sels) = {"firc", "fxosc", "dummy", 4853+ "dummy", "enetpll_phi0",}; 4854+ 4855+PNAME(enet_time_sels) = {"firc", "fxosc", "dummy", 4856+ "dummy", "enetpll_phi0",}; 4857+ 4858+static struct clk *clk[S32V234_CLK_END]; 4859+static struct clk_onecell_data clk_data; 4860+ 4861+static void __init s32v234_clocks_init(struct device_node *mc_cgm0_node) 4862+{ 4863+ struct device_node *np; 4864+ 4865+ clk[S32V234_CLK_DUMMY] = s32_clk_fixed("dummy", 0); 4866+ clk[S32V234_CLK_FXOSC] = s32_obtain_fixed_clock("fxosc", 0); 4867+ clk[S32V234_CLK_FIRC] = s32_obtain_fixed_clock("firc", 0); 4868+ 4869+ np = of_find_compatible_node(NULL, NULL, "fsl,s32v234-mc_me"); 4870+ mc_me_base = of_iomap(np, 0); 4871+ if (WARN_ON(!mc_me_base)) 4872+ return; 4873+ 4874+ np = of_find_compatible_node(NULL, NULL, "fsl,s32v234-src"); 4875+ src_base = of_iomap(np, 0); 4876+ if (WARN_ON(!src_base)) 4877+ return; 4878+ 4879+ np = of_find_compatible_node(NULL, NULL, "fsl,s32v234-mc_cgm1"); 4880+ mc_cgm1_base = of_iomap(np, 0); 4881+ if (WARN_ON(!mc_cgm1_base)) 4882+ return; 4883+ 4884+ np = of_find_compatible_node(NULL, NULL, "fsl,s32v234-mc_cgm2"); 4885+ mc_cgm2_base = of_iomap(np, 0); 4886+ if (WARN_ON(!mc_cgm2_base)) 4887+ return; 4888+ 4889+ np = of_find_compatible_node(NULL, NULL, "fsl,s32v234-mc_cgm3"); 4890+ mc_cgm3_base = of_iomap(np, 0); 4891+ if (WARN_ON(!mc_cgm3_base)) 4892+ return; 4893+ 4894+ np = mc_cgm0_node; 4895+ mc_cgm0_base = of_iomap(np, 0); 4896+ if (WARN_ON(!mc_cgm0_base)) 4897+ return; 4898+ 4899+ enable_cpumodes_onperipheralconfig(mc_me_base, MC_ME_RUN_PCn_DRUN | 4900+ MC_ME_RUN_PCn_RUN0 | 4901+ MC_ME_RUN_PCn_RUN1 | 4902+ MC_ME_RUN_PCn_RUN2 | 4903+ MC_ME_RUN_PCn_RUN3, 4904+ 0); 4905+ 4906+ /* turn on XOSC and FIRC */ 4907+ enable_clocks_sources(MC_ME_MODE_MC_MVRON, MC_ME_MODE_MC_XOSCON | 4908+ MC_ME_MODE_MC_FIRCON, 4909+ MC_ME_RUNn_MC(mc_me_base, 0)); 4910+ 4911+ /* transition the core to RUN0 mode */ 4912+ entry_to_target_mode(mc_me_base, MC_ME_MCTL_RUN0); 4913+ 4914+ clk[S32V234_CLK_ARMPLL_SRC_SEL] = s32_clk_mux("armpll_sel", 4915+ SRC_GPR1, SRC_GPR1_ARMPLL_SRC_SEL_OFFSET, 4916+ SRC_GPR1_XPLL_SRC_SEL_SIZE, 4917+ osc_sels, ARRAY_SIZE(osc_sels), &s32v234_lock); 4918+ 4919+ clk[S32V234_CLK_PERIPHPLL_SRC_SEL] = s32_clk_mux("periphpll_sel", 4920+ SRC_GPR1, SRC_GPR1_PERIPHPLL_SRC_SEL_OFFSET, 4921+ SRC_GPR1_XPLL_SRC_SEL_SIZE, 4922+ osc_sels, ARRAY_SIZE(osc_sels), &s32v234_lock); 4923+ 4924+ clk[S32V234_CLK_ENETPLL_SRC_SEL] = s32_clk_mux("enetpll_sel", 4925+ SRC_GPR1, SRC_GPR1_ENETPLL_SRC_SEL_OFFSET, 4926+ SRC_GPR1_XPLL_SRC_SEL_SIZE, 4927+ osc_sels, ARRAY_SIZE(osc_sels), &s32v234_lock); 4928+ 4929+ /* ARM_PLL */ 4930+ clk[S32V234_CLK_ARMPLL_VCO] = s32v234_clk_plldig(S32_PLLDIG_ARM, 4931+ "armpll_vco", "armpll_sel", ARMPLL_PLLDIG(mc_cgm0_base), 4932+ ARMPLL_PLLDIG_PLLDV_MFD, ARMPLL_PLLDIG_PLLDV_MFN, 4933+ ARMPLL_PLLDIG_PLLDV_RFDPHI0, ARMPLL_PLLDIG_PLLDV_RFDPHI1); 4934+ 4935+ clk[S32V234_CLK_ARMPLL_PHI0] = s32v234_clk_plldig_phi(S32_PLLDIG_ARM, 4936+ "armpll_phi0", "armpll_vco", 4937+ ARMPLL_PLLDIG(mc_cgm0_base), 0); 4938+ 4939+ clk[S32V234_CLK_ARMPLL_PHI1] = s32v234_clk_plldig_phi(S32_PLLDIG_ARM, 4940+ "armpll_phi1", "armpll_vco", 4941+ ARMPLL_PLLDIG(mc_cgm0_base), 1); 4942+ 4943+ clk[S32V234_CLK_ARMPLL_DFS0] = s32v234_clk_dfs(S32_PLLDIG_ARM, 4944+ "armpll_dfs0", "armpll_phi1", 4945+ ARMPLL_PLLDIG_DFS(mc_cgm0_base), 0, 4946+ ARMPLL_PLLDIG_DFS0_MFN); 4947+ 4948+ clk[S32V234_CLK_ARMPLL_DFS1] = s32v234_clk_dfs(S32_PLLDIG_ARM, 4949+ "armpll_dfs1", "armpll_phi1", 4950+ ARMPLL_PLLDIG_DFS(mc_cgm0_base), 1, 4951+ ARMPLL_PLLDIG_DFS1_MFN); 4952+ 4953+ clk[S32V234_CLK_ARMPLL_DFS2] = s32v234_clk_dfs(S32_PLLDIG_ARM, 4954+ "armpll_dfs2", "armpll_phi1", 4955+ ARMPLL_PLLDIG_DFS(mc_cgm0_base), 2, 4956+ ARMPLL_PLLDIG_DFS2_MFN); 4957+ 4958+ clk[S32V234_CLK_SYS_SEL] = s32_clk_mux("sys_sel", 4959+ MC_ME_RUNn_MC(mc_me_base, 0), 4960+ MC_ME_MODE_MC_SYSCLK_OFFSET, 4961+ MC_ME_MODE_MC_SYSCLK_SIZE, 4962+ sys_sels, ARRAY_SIZE(sys_sels), &s32v234_lock); 4963+ 4964+ clk[S32V234_CLK_SYS3] = s32_clk_divider("sys3", "sys_sel", 4965+ CGM_SC_DCn(mc_cgm0_base, 0), MC_CGM_SC_DCn_PREDIV_OFFSET, 4966+ MC_CGM_SC_DCn_PREDIV_SIZE, &s32v234_lock); 4967+ 4968+ clk[S32V234_CLK_SYS6] = s32_clk_divider("sys6", "sys_sel", 4969+ CGM_SC_DCn(mc_cgm0_base, 1), MC_CGM_SC_DCn_PREDIV_OFFSET, 4970+ MC_CGM_SC_DCn_PREDIV_SIZE, &s32v234_lock); 4971+ 4972+ clk[S32V234_CLK_SYS6_DIV2] = s32_clk_divider("sys6_div2", "sys_sel", 4973+ CGM_SC_DCn(mc_cgm0_base, 2), MC_CGM_SC_DCn_PREDIV_OFFSET, 4974+ MC_CGM_SC_DCn_PREDIV_SIZE, &s32v234_lock); 4975+ 4976+ /* PERIPH_PLL */ 4977+ clk[S32V234_CLK_PERIPHPLL_VCO] = s32v234_clk_plldig(S32_PLLDIG_PERIPH, 4978+ "periphpll_vco", "periphpll_sel", 4979+ PERIPHPLL_PLLDIG(mc_cgm0_base), 4980+ PERIPHPLL_PLLDIG_PLLDV_MFD, PERIPHPLL_PLLDIG_PLLDV_MFN, 4981+ PERIPHPLL_PLLDIG_PLLDV_RFDPHI0, 4982+ PERIPHPLL_PLLDIG_PLLDV_RFDPHI1); 4983+ 4984+ clk[S32V234_CLK_PERIPHPLL_PHI0] = 4985+ s32v234_clk_plldig_phi(S32_PLLDIG_PERIPH, 4986+ "periphpll_phi0", "periphpll_vco", 4987+ PERIPHPLL_PLLDIG(mc_cgm0_base), 0); 4988+ 4989+ clk[S32V234_CLK_PERIPHPLL_PHI1] = 4990+ s32v234_clk_plldig_phi(S32_PLLDIG_PERIPH, 4991+ "periphpll_phi1", "periphpll_vco", 4992+ PERIPHPLL_PLLDIG(mc_cgm0_base), 1); 4993+ 4994+ clk[S32V234_CLK_PERIPHPLL_PHI0_DIV3] = s32_clk_fixed_factor( 4995+ "periphpll_phi0_div3", "periphpll_phi0", 1, 3); 4996+ 4997+ clk[S32V234_CLK_PERIPHPLL_PHI0_DIV5] = s32_clk_fixed_factor( 4998+ "periphpll_phi0_div5", "periphpll_phi0", 1, 5); 4999+ 5000+ clk[S32V234_CLK_CAN_SEL] = s32_clk_mux("can_sel", 5001+ CGM_ACn_SC(mc_cgm0_base, 6), 5002+ MC_CGM_ACn_SEL_OFFSET, 5003+ MC_CGM_ACn_SEL_SIZE, 5004+ can_sels, ARRAY_SIZE(can_sels), &s32v234_lock); 5005+ 5006+ /* CAN Clock */ 5007+ clk[S32V234_CLK_CAN] = s32_clk_divider("can", "can_sel", 5008+ CGM_ACn_DCm(mc_cgm0_base, 6, 0), 5009+ MC_CGM_ACn_DCm_PREDIV_OFFSET, 5010+ MC_CGM_ACn_DCm_PREDIV_SIZE, &s32v234_lock); 5011+ 5012+ /* Lin Clock */ 5013+ clk[S32V234_CLK_LIN_SEL] = s32_clk_mux("lin_sel", 5014+ CGM_ACn_SC(mc_cgm0_base, 3), 5015+ MC_CGM_ACn_SEL_OFFSET, 5016+ MC_CGM_ACn_SEL_SIZE, 5017+ lin_sels, ARRAY_SIZE(lin_sels), &s32v234_lock); 5018+ 5019+ clk[S32V234_CLK_LIN] = s32_clk_divider("lin", "lin_sel", 5020+ CGM_ACn_DCm(mc_cgm0_base, 3, 0), 5021+ MC_CGM_ACn_DCm_PREDIV_OFFSET, 5022+ MC_CGM_ACn_DCm_PREDIV_SIZE, &s32v234_lock); 5023+ 5024+ clk[S32V234_CLK_LIN_IPG] = s32_clk_fixed_factor("lin_ipg", 5025+ "lin", 1, 2); 5026+ 5027+ /* enable PERIPHPLL */ 5028+ enable_clocks_sources(0, MC_ME_MODE_MC_PERIPHPLL, 5029+ MC_ME_RUNn_MC(mc_me_base, 0)); 5030+ 5031+ /* ENET_PLL */ 5032+ clk[S32V234_CLK_ENETPLL_VCO] = s32v234_clk_plldig(S32_PLLDIG_ENET, 5033+ "enetpll_vco", "enetpll_sel", ENETPLL_PLLDIG(mc_cgm0_base), 5034+ ENETPLL_PLLDIG_PLLDV_MFD, ENETPLL_PLLDIG_PLLDV_MFN, 5035+ ENETPLL_PLLDIG_PLLDV_RFDPHI0, ENETPLL_PLLDIG_PLLDV_RFDPHI1); 5036+ 5037+ clk[S32V234_CLK_ENETPLL_PHI0] = s32v234_clk_plldig_phi(S32_PLLDIG_ENET, 5038+ "enetpll_phi0", "enetpll_vco", 5039+ ENETPLL_PLLDIG(mc_cgm0_base), 0); 5040+ 5041+ clk[S32V234_CLK_ENETPLL_PHI1] = s32v234_clk_plldig_phi(S32_PLLDIG_ENET, 5042+ "enetpll_phi1", "enetpll_vco", 5043+ ENETPLL_PLLDIG(mc_cgm0_base), 1); 5044+ 5045+ clk[S32V234_CLK_ENETPLL_DFS0] = s32v234_clk_dfs(S32_PLLDIG_ENET, 5046+ "enetpll_dfs0", "enetpll_phi1", 5047+ ENETPLL_PLLDIG_DFS(mc_cgm0_base), 0, 5048+ ENETPLL_PLLDIG_DFS0_MFN); 5049+ 5050+ clk[S32V234_CLK_ENETPLL_DFS1] = s32v234_clk_dfs(S32_PLLDIG_ENET, 5051+ "enetpll_dfs1", "enetpll_phi1", 5052+ ENETPLL_PLLDIG_DFS(mc_cgm0_base), 1, 5053+ ENETPLL_PLLDIG_DFS1_MFN); 5054+ 5055+ clk[S32V234_CLK_ENETPLL_DFS2] = s32v234_clk_dfs(S32_PLLDIG_ENET, 5056+ "enetpll_dfs2", "enetpll_phi1", 5057+ ENETPLL_PLLDIG_DFS(mc_cgm0_base), 2, 5058+ ENETPLL_PLLDIG_DFS2_MFN); 5059+ 5060+ clk[S32V234_CLK_ENETPLL_DFS3] = s32v234_clk_dfs(S32_PLLDIG_ENET, 5061+ "enetpll_dfs3", "enetpll_phi1", 5062+ ENETPLL_PLLDIG_DFS(mc_cgm0_base), 3, 5063+ ENETPLL_PLLDIG_DFS3_MFN); 5064+ 5065+ /* ENET Clock */ 5066+ clk[S32V234_CLK_ENET_SEL] = s32_clk_mux("enet_sel", 5067+ CGM_ACn_SC(mc_cgm2_base, 2), 5068+ MC_CGM_ACn_SEL_OFFSET, 5069+ MC_CGM_ACn_SEL_SIZE, 5070+ enet_sels, ARRAY_SIZE(enet_sels), &s32v234_lock); 5071+ 5072+ clk[S32V234_CLK_ENET_TIME_SEL] = s32_clk_mux("enet_time_sel", 5073+ CGM_ACn_SC(mc_cgm0_base, 7), 5074+ MC_CGM_ACn_SEL_OFFSET, 5075+ MC_CGM_ACn_SEL_SIZE, 5076+ enet_time_sels, ARRAY_SIZE(enet_time_sels), &s32v234_lock); 5077+ 5078+ clk[S32V234_CLK_ENET] = s32_clk_divider("enet", "enet_sel", 5079+ CGM_ACn_DCm(mc_cgm2_base, 2, 0), 5080+ MC_CGM_ACn_DCm_PREDIV_OFFSET, 5081+ MC_CGM_ACn_DCm_PREDIV_SIZE, &s32v234_lock); 5082+ 5083+ clk[S32V234_CLK_ENET_TIME] = s32_clk_divider("enet_time", 5084+ "enet_time_sel", 5085+ CGM_ACn_DCm(mc_cgm0_base, 7, 1), 5086+ MC_CGM_ACn_DCm_PREDIV_OFFSET, 5087+ MC_CGM_ACn_DCm_PREDIV_SIZE, &s32v234_lock); 5088+ 5089+ /* SDHC Clock */ 5090+ clk[S32V234_CLK_SDHC_SEL] = s32_clk_mux("sdhc_sel", 5091+ CGM_ACn_SC(mc_cgm0_base, 15), 5092+ MC_CGM_ACn_SEL_OFFSET, 5093+ MC_CGM_ACn_SEL_SIZE, 5094+ sdhc_sels, ARRAY_SIZE(sdhc_sels), &s32v234_lock); 5095+ 5096+ clk[S32V234_CLK_SDHC] = s32_clk_divider("sdhc", "sdhc_sel", 5097+ CGM_ACn_DCm(mc_cgm0_base, 15, 0), 5098+ MC_CGM_ACn_DCm_PREDIV_OFFSET, 5099+ MC_CGM_ACn_DCm_PREDIV_SIZE, &s32v234_lock); 5100+ 5101+ /* set the system clock */ 5102+ enable_sysclock(MC_ME_MODE_MC_SYSCLK(0x2), 5103+ MC_ME_RUNn_MC(mc_me_base, 0)); 5104+ 5105+ /* transition the core to RUN0 mode */ 5106+ entry_to_target_mode(mc_me_base, MC_ME_MCTL_RUN0); 5107+ 5108+ /* Add the clocks to provider list */ 5109+ clk_data.clks = clk; 5110+ clk_data.clk_num = ARRAY_SIZE(clk); 5111+ of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); 5112+} 5113+ 5114+CLK_OF_DECLARE(S32V234, "fsl,s32v234-mc_cgm0", s32v234_clocks_init); 5115diff --git a/drivers/clk/s32/s32v234/clk.h b/drivers/clk/s32/s32v234/clk.h 5116new file mode 100644 5117index 000000000..82a222483 5118--- /dev/null 5119+++ b/drivers/clk/s32/s32v234/clk.h 5120@@ -0,0 +1,31 @@ 5121+/* SPDX-License-Identifier: GPL-2.0-or-later */ 5122+/* 5123+ * Copyright 2015-2016 Freescale Semiconductor, Inc. 5124+ * Copyright 2017-2018 NXP 5125+ */ 5126+ 5127+#ifndef __MACH_S32V234_CLK_H 5128+#define __MACH_S32V234_CLK_H 5129+ 5130+#include <linux/spinlock.h> 5131+#include <linux/clk-provider.h> 5132+#include "mc_cgm.h" 5133+#include "mc_me.h" 5134+#include "pll.h" 5135+#include "src.h" 5136+#include "dfs.h" 5137+#include "../clk.h" 5138+ 5139+struct clk *s32v234_clk_plldig(enum s32v234_plldig_type type, const char *name, 5140+ const char *parent_name, void __iomem *base, 5141+ u32 plldv_mfd, u32 plldv_mfn, 5142+ u32 plldv_rfdphi, u32 plldv_rfdphi1); 5143+ 5144+struct clk *s32v234_clk_plldig_phi(enum s32v234_plldig_type type, 5145+ const char *name, const char *parent, 5146+ void __iomem *base, u32 phi); 5147+ 5148+struct clk *s32v234_clk_dfs(enum s32v234_plldig_type type, const char *name, 5149+ const char *parent_name, 5150+ void __iomem *reg, u8 idx, u32 mfn); 5151+#endif 5152diff --git a/drivers/clk/s32/s32v234/dfs.h b/drivers/clk/s32/s32v234/dfs.h 5153new file mode 100644 5154index 000000000..be3104f7a 5155--- /dev/null 5156+++ b/drivers/clk/s32/s32v234/dfs.h 5157@@ -0,0 +1,78 @@ 5158+/* 5159+ * Copyright (C) 2016 Freescale Semiconductor, Inc. 5160+ * Copyright 2018 NXP 5161+ * 5162+ * This program is free software; you can redistribute it and/or modify 5163+ * it under the terms of the GNU General Public License as published by 5164+ * the Free Software Foundation; either version 2 of the License, or 5165+ * (at your option) any later version. 5166+ */ 5167+#ifndef _DFS_S32V234_H 5168+#define _DFS_S32V234_H 5169+ 5170+/* DFS Control Register (DFS_CTRL) */ 5171+#define DFS_CTRL(base) ((base) + 0x00000018) 5172+#define DFS_CTRL_DLL_LOLIE (1 << 0) 5173+#define DFS_CTRL_DLL_RESET (1 << 1) 5174+ 5175+/* DFS Port Status (DFS_PORTSR) */ 5176+#define DFS_PORTSR(base) ((base) + 0x0000000C) 5177+#define DFS_PORTSR_MASK (0x0000000F) 5178+#define DFS_PORTSR_OFFSET (28) 5179+ 5180+/* DFS Port Reset Register (DFS_PORTRESET) */ 5181+#define DFS_PORTRESET(base) ((base) + 0x00000014) 5182+#define DFS_PORTRESET_PORTRESET_SET(val) \ 5183+ (DFS_PORTRESET_PORTRESET_MASK | \ 5184+ (((val) & DFS_PORTRESET_PORTRESET_MAXVAL) \ 5185+ << DFS_PORTRESET_PORTRESET_OFFSET)) 5186+#define DFS_PORTRESET_PORTRESET_MAXVAL (0xF) 5187+#define DFS_PORTRESET_PORTRESET_MASK (0x0000000F) 5188+#define DFS_PORTRESET_PORTRESET_OFFSET (28) 5189+ 5190+/* DFS Divide Register Portn (DFS_DVPORTn) */ 5191+#define DFS_DVPORTn(base, n) ((base) + (0x0000001C + \ 5192+ ((n) * sizeof(u32)))) 5193+#define DFS_DVPORTn_MFI_SET(val) (DFS_DVPORTn_MFI_MASK & \ 5194+ (((val) & DFS_DVPORTn_MFI_MAXVAL) \ 5195+ << DFS_DVPORTn_MFI_OFFSET)) 5196+#define DFS_DVPORTn_MFN_SET(val) (DFS_DVPORTn_MFN_MASK & \ 5197+ (((val) & DFS_DVPORTn_MFN_MAXVAL) \ 5198+ << DFS_DVPORTn_MFN_OFFSET)) 5199+#define DFS_DVPORTn_MFI_MASK (0x0000FF00) 5200+#define DFS_DVPORTn_MFN_MASK (0x000000FF) 5201+#define DFS_DVPORTn_MFI_MAXVAL (0xFF) 5202+#define DFS_DVPORTn_MFN_MAXVAL (0xFF) 5203+#define DFS_DVPORTn_MFI_OFFSET (8) 5204+#define DFS_DVPORTn_MFN_OFFSET (0) 5205+#define DFS_MAXNUMBER (4) 5206+ 5207+/* 5208+ * Naming convention for PLL: 5209+ * ARMPLL - PLL0 5210+ * PERIPHPLL - PLL1 5211+ * ENETPLL - PLL2 5212+ * DDRPLL - PLL3 5213+ * VIDEOPLL - PLL4 5214+ */ 5215+ 5216+/* The max values for PLL DFS is in Hz */ 5217+/* ARMPLL */ 5218+#define ARMPLL_DFS0_MAX_RATE (266000000) 5219+#define ARMPLL_DFS1_MAX_RATE (600000000) 5220+#define ARMPLL_DFS2_MAX_RATE (600000000) 5221+/* ENETPLL */ 5222+#define ENETPLL_DFS0_MAX_RATE (350000000) 5223+#define ENETPLL_DFS1_MAX_RATE (350000000) 5224+#define ENETPLL_DFS2_MAX_RATE (416000000) 5225+#define ENETPLL_DFS3_MAX_RATE (104000000) 5226+/* DDRPLL */ 5227+#define DDRPLL_DFS0_MAX_RATE (500000000) 5228+#define DDRPLL_DFS1_MAX_RATE (500000000) 5229+#define DDRPLL_DFS2_MAX_RATE (350000000) 5230+ 5231+#define ARMPLL_DFS_NR (3) 5232+#define ENETPLL_DFS_NR (4) 5233+#define DDRPLL_DFS_NR (3) 5234+ 5235+#endif 5236diff --git a/drivers/clk/s32/s32v234/mc_cgm.h b/drivers/clk/s32/s32v234/mc_cgm.h 5237new file mode 100644 5238index 000000000..aeac68771 5239--- /dev/null 5240+++ b/drivers/clk/s32/s32v234/mc_cgm.h 5241@@ -0,0 +1,70 @@ 5242+/* SPDX-License-Identifier: GPL-2.0-or-later */ 5243+/* 5244+ * Copyright (C) 2016 Freescale Semiconductor, Inc. 5245+ * Copyright (C) 2017 NXP 5246+ */ 5247+#ifndef _MC_CGM_H 5248+#define _MC_CGM_H 5249+ 5250+#define ARMPLL_PLLDIG(mc_cgm) (mc_cgm) 5251+#define ARMPLL_PLLDIG_DFS(mc_cgm) ((mc_cgm) + 0x40) 5252+#define ARMPLL_PLLDIG_PLLDV_MFD (50) 5253+#define ARMPLL_PLLDIG_PLLDV_MFN (0) 5254+#define ARMPLL_PLLDIG_PLLDV_RFDPHI0 (1) 5255+#define ARMPLL_PLLDIG_PLLDV_RFDPHI1 (1) 5256+#define ARMPLL_PLLDIG_DFS0_MFN (195) 5257+#define ARMPLL_PLLDIG_DFS1_MFN (171) 5258+#define ARMPLL_PLLDIG_DFS2_MFN (171) 5259+ 5260+#define PERIPHPLL_PLLDIG(mc_cgm) ((mc_cgm) + 0x80) 5261+#define PERIPHPLL_PLLDIG_PLLDV_MFD (30) 5262+#define PERIPHPLL_PLLDIG_PLLDV_MFN (0) 5263+#define PERIPHPLL_PLLDIG_PLLDV_RFDPHI0 (0x1) 5264+#define PERIPHPLL_PLLDIG_PLLDV_RFDPHI1 (0x1) 5265+ 5266+#define ENETPLL_PLLDIG(mc_cgm) ((mc_cgm) + 0x100) 5267+#define ENETPLL_PLLDIG_DFS(mc_cgm) ((mc_cgm) + 0x100 + 0x40) 5268+#define ENETPLL_PLLDIG_PLLDV_MFD (50) 5269+#define ENETPLL_PLLDIG_PLLDV_MFN (0) 5270+#define ENETPLL_PLLDIG_PLLDV_RFDPHI0 (0x1) 5271+#define ENETPLL_PLLDIG_PLLDV_RFDPHI1 (0x1) 5272+#define ENETPLL_PLLDIG_DFS0_MFN (220) 5273+#define ENETPLL_PLLDIG_DFS1_MFN (220) 5274+#define ENETPLL_PLLDIG_DFS2_MFN (33) 5275+#define ENETPLL_PLLDIG_DFS3_MFN (1) 5276+ 5277+/* MC_CGM_SC_SS */ 5278+#define CGM_SC_SS(mc_cgm) (((mc_cgm) + 0x7E4)) 5279+ 5280+/* MC_CGM_SC_DCn */ 5281+#define CGM_SC_DCn(mc_cgm, dc) (((mc_cgm) + 0x7E8) + ((dc) * 0x4)) 5282+ 5283+#define MC_CGM_SC_DCn_PREDIV_OFFSET (16) 5284+#define MC_CGM_SC_DCn_PREDIV_SIZE (3) 5285+#define MC_CGM_SC_DCn_DE (1 << 31) 5286+#define MC_CGM_SC_SEL_OFFSET (24) 5287+#define MC_CGM_SC_SEL_SIZE (4) 5288+ 5289+/* MC_CGM_ACn_DCm */ 5290+#define CGM_ACn_DCm(mc_cgm, ac, dc) (((mc_cgm) + 0x808) + ((ac) * 0x20)\ 5291+ + ((dc) * 0x4)) 5292+ 5293+#define MC_CGM_ACn_DCm_PREDIV(val) (MC_CGM_ACn_DCm_PREDIV_MASK & \ 5294+ ((val) \ 5295+ << MC_CGM_ACn_DCm_PREDIV_OFFSET)) 5296+#define MC_CGM_ACn_DCm_PREDIV_MASK (0x001F0000) 5297+#define MC_CGM_ACn_DCm_PREDIV_OFFSET (16) 5298+#define MC_CGM_ACn_DCm_PREDIV_SIZE (5) 5299+#define MC_CGM_ACn_DCm_DE (1 << 31) 5300+ 5301+/* MC_CGM_ACn_SC/MC_CGM_ACn_SS */ 5302+#define CGM_ACn_SC(mc_cgm, ac) (((mc_cgm) + 0x800) + ((ac) * 0x20)) 5303+#define CGM_ACn_SS(mc_cgm, ac) (((mc_cgm) + 0x804) + ((ac) * 0x24)) 5304+#define MC_CGM_ACn_SEL_MASK (0x07000000) 5305+#define MC_CGM_ACn_SEL_SET(source) (MC_CGM_ACn_SEL_MASK & \ 5306+ (((source) & 0x7) \ 5307+ << MC_CGM_ACn_SEL_OFFSET)) 5308+#define MC_CGM_ACn_SEL_OFFSET (24) 5309+#define MC_CGM_ACn_SEL_SIZE (4) 5310+ 5311+#endif 5312diff --git a/drivers/clk/s32/s32v234/mc_me.h b/drivers/clk/s32/s32v234/mc_me.h 5313new file mode 100644 5314index 000000000..718f1d1a0 5315--- /dev/null 5316+++ b/drivers/clk/s32/s32v234/mc_me.h 5317@@ -0,0 +1,110 @@ 5318+/* SPDX-License-Identifier: GPL-2.0-or-later */ 5319+/* 5320+ * Copyright (C) 2016 Freescale Semiconductor, Inc. 5321+ * Copyright (C) 2017 NXP 5322+ */ 5323+ 5324+#ifndef _MC_ME_H 5325+#define _MC_ME_H 5326+ 5327+/* MC_ME registers definitions */ 5328+/* MC_ME_GS */ 5329+ #define MC_ME_GS(mc_me) ((mc_me) + 0x00000000) 5330+ 5331+/* MC_ME_MCTL */ 5332+#define MC_ME_MCTL(mc_me) ((mc_me) + 0x00000004) 5333+#define MC_ME_MCTL_RESET (0x0 << 28) 5334+#define MC_ME_MCTL_TEST (0x1 << 28) 5335+#define MC_ME_MCTL_DRUN (0x3 << 28) 5336+#define MC_ME_MCTL_RUN0 (0x4 << 28) 5337+#define MC_ME_MCTL_RUN1 (0x5 << 28) 5338+#define MC_ME_MCTL_RUN2 (0x6 << 28) 5339+#define MC_ME_MCTL_RUN3 (0x7 << 28) 5340+ 5341+#define MC_ME_GS_S_MTRANS (1 << 27) 5342+ 5343+#define MC_ME_MCTL_KEY (0x00005AF0) 5344+#define MC_ME_MCTL_INVERTEDKEY (0x0000A50F) 5345+ 5346+/* 5347+ * MC_ME_RESET_MC/MC_ME_TEST_MC 5348+ * MC_ME_DRUN_MC 5349+ * MC_ME_RUNn_MC 5350+ */ 5351+#define MC_ME_RESET_MC(mc_me) ((mc_me) + 0x00000020) 5352+#define MC_ME_TEST_MC(mc_me) ((mc_me) + 0x00000024) 5353+#define MC_ME_DRUN_MC(mc_me) ((mc_me) + 0x0000002C) 5354+#define MC_ME_RUNn_MC(mc_me, n) ((mc_me) + 0x00000030 + 0x4 * (n)) 5355+#define MC_ME_MODE_MC_SYSCLK_OFFSET (0) 5356+#define MC_ME_MODE_MC_SYSCLK_SIZE (0x3) 5357+#define MC_ME_MODE_MC_SYSCLK(val) (MC_ME_MODE_MC_SYSCLK_MASK & (val)) 5358+#define MC_ME_MODE_MC_SYSCLK_MASK (0x0000000F) 5359+#define MC_ME_MODE_MC_FIRCON (1 << 4) 5360+#define MC_ME_MODE_MC_XOSCON (1 << 5) 5361+#define MC_ME_MODE_MC_ARMPLL (1 << 6) 5362+#define MC_ME_MODE_MC_PERIPHPLL (1 << 7) 5363+#define MC_ME_MODE_MC_ENETPLL (1 << 8) 5364+#define MC_ME_MODE_MC_DDRPLL (1 << 9) 5365+#define MC_ME_MODE_MC_VIDEOPLL (1 << 10) 5366+#define MC_ME_MODE_MC_MVRON (1 << 20) 5367+ 5368+/* MC_ME_DRUN_SEC_CC_I */ 5369+#define MC_ME_DRUN_SEC_CC_I(mc_me) ((mc_me) + 0x260) 5370+/* MC_ME_RUNn_SEC_CC_I */ 5371+#define MC_ME_RUNn_SEC_CC_I(mc_me, n) ((mc_me) + 0x270 + (n) * 0x10) 5372+#define MC_ME_MODE_SEC_CC_I_SYSCLK1_OFFSET (4) 5373+#define MC_ME_MODE_SEC_CC_I_SYSCLK2_OFFSET (8) 5374+#define MC_ME_MODE_SEC_CC_I_SYSCLK3_OFFSET (12) 5375+/* Consider only the defined clocks */ 5376+#define MC_ME_MODE_SEC_CC_I_SYSCLK1_SIZE (0x3) 5377+#define MC_ME_MODE_SEC_CC_I_SYSCLK2_SIZE (0x3) 5378+#define MC_ME_MODE_SEC_CC_I_SYSCLK3_SIZE (0x3) 5379+ 5380+/* MC_ME_RUN_PCn */ 5381+#define MC_ME_RUN_PCn(mc_me, n) (mc_me + 0x00000080 + 0x4 * (n)) 5382+ 5383+#define MC_ME_RUN_PCn_MAX_IDX (7) 5384+#define MC_ME_RUN_PCn_RESET (1 << 0) 5385+#define MC_ME_RUN_PCn_TEST (1 << 1) 5386+#define MC_ME_RUN_PCn_DRUN (1 << 3) 5387+#define MC_ME_RUN_PCn_RUN0 (1 << 4) 5388+#define MC_ME_RUN_PCn_RUN1 (1 << 5) 5389+#define MC_ME_RUN_PCn_RUN2 (1 << 6) 5390+#define MC_ME_RUN_PCn_RUN3 (1 << 7) 5391+ 5392+#define MC_ME_PCTLn(mc_me, n) (mc_me + 0xC0 + 4 * (n >> 2) + \ 5393+ (3 - (n) % 4)) 5394+ 5395+static inline void entry_to_target_mode(void __iomem *mc_me, u32 mode) 5396+{ 5397+ writel_relaxed(mode | MC_ME_MCTL_KEY, MC_ME_MCTL(mc_me)); 5398+ writel_relaxed(mode | MC_ME_MCTL_INVERTEDKEY, MC_ME_MCTL(mc_me)); 5399+ while ((readl_relaxed(MC_ME_GS(mc_me)) & 5400+ MC_ME_GS_S_MTRANS) != 0x00000000) 5401+ ; 5402+} 5403+ 5404+static inline void enable_cpumodes_onperipheralconfig(void __iomem *mc_me, 5405+ u32 modes, u32 run_pc_idx) 5406+{ 5407+ WARN_ON(run_pc_idx > MC_ME_RUN_PCn_MAX_IDX); 5408+ if (run_pc_idx > MC_ME_RUN_PCn_MAX_IDX) 5409+ return; 5410+ 5411+ writel_relaxed(modes, MC_ME_RUN_PCn(mc_me, run_pc_idx)); 5412+} 5413+ 5414+static inline void enable_clocks_sources(u32 flags, u32 clks, 5415+ void __iomem *xrun_mc_addr) 5416+{ 5417+ writel_relaxed(readl_relaxed(xrun_mc_addr) | flags | clks, 5418+ xrun_mc_addr); 5419+} 5420+ 5421+static inline void enable_sysclock(u32 clk, void __iomem *xrun_mc_addr) 5422+{ 5423+ writel_relaxed(readl_relaxed(xrun_mc_addr) & clk, 5424+ xrun_mc_addr); 5425+} 5426+ 5427+#endif 5428diff --git a/drivers/clk/s32/s32v234/pll.h b/drivers/clk/s32/s32v234/pll.h 5429new file mode 100644 5430index 000000000..b7bcc50f0 5431--- /dev/null 5432+++ b/drivers/clk/s32/s32v234/pll.h 5433@@ -0,0 +1,78 @@ 5434+/* SPDX-License-Identifier: GPL-2.0-or-later */ 5435+/* 5436+ * Copyright (C) 2016 Freescale Semiconductor, Inc. 5437+ * Copyright (C) 2017-2018 NXP 5438+ */ 5439+#ifndef _PLL_S32V234_H 5440+#define _PLL_S32V234_H 5441+ 5442+/* PLLDIG PLL Divider Register (PLLDIG_PLLDV) */ 5443+#define PLLDIG_PLLDV(base) ((base) + 0x00000028) 5444+#define PLLDIG_PLLDV_MFD_SET(val) (PLLDIG_PLLDV_MFD_MASK & (val)) 5445+#define PLLDIG_PLLDV_MFD_MASK (0x000000FF) 5446+ 5447+#define PLLDIG_PLLDV_RFDPHI_SET(val) (PLLDIG_PLLDV_RFDPHI_MASK & \ 5448+ (((val) & \ 5449+ PLLDIG_PLLDV_RFDPHI_MAXVALUE) \ 5450+ << PLLDIG_PLLDV_RFDPHI_OFFSET)) 5451+#define PLLDIG_PLLDV_RFDPHI_MASK (0x003F0000) 5452+#define PLLDIG_PLLDV_RFDPHI_MAXVALUE (0x3F) 5453+ 5454+#define PLLDIG_PLLDV_RFDPHI_OFFSET (16) 5455+ 5456+#define PLLDIG_PLLDV_RFDPHI1_SET(val) (PLLDIG_PLLDV_RFDPHI1_MASK & \ 5457+ (((val) & \ 5458+ PLLDIG_PLLDV_RFDPHI1_MAXVALUE) \ 5459+ << PLLDIG_PLLDV_RFDPHI1_OFFSET)) 5460+#define PLLDIG_PLLDV_RFDPHI1_MASK (0x7E000000) 5461+#define PLLDIG_PLLDV_RFDPHI1_MAXVALUE (0x3F) 5462+#define PLLDIG_PLLDV_RFDPHI1_OFFSET (25) 5463+ 5464+#define PLLDIG_PLLDV_PREDIV_SET(val) (PLLDIG_PLLDV_PREDIV_MASK & \ 5465+ (((val) & \ 5466+ PLLDIG_PLLDV_PREDIV_MAXVALUE) \ 5467+ << PLLDIG_PLLDV_PREDIV_OFFSET)) 5468+#define PLLDIG_PLLDV_PREDIV_MASK (0x00007000) 5469+#define PLLDIG_PLLDV_PREDIV_MAXVALUE (0x7) 5470+#define PLLDIG_PLLDV_PREDIV_OFFSET (12) 5471+ 5472+/* PLLDIG PLL Fractional Divide Register (PLLDIG_PLLFD) */ 5473+#define PLLDIG_PLLFD(base) ((base) + 0x00000030) 5474+#define PLLDIG_PLLFD_MFN_SET(val) (PLLDIG_PLLFD_MFN_MASK & (val)) 5475+#define PLLDIG_PLLFD_MFN_MASK (0x00007FFF) 5476+ 5477+/* PLL Calibration Register 1 (PLLDIG_PLLCAL1) */ 5478+#define PLLDIG_PLLCAL1(base) ((base) + 0x00000038) 5479+#define PLLDIG_PLLCAL1_NDAC1_SET(val) (PLLDIG_PLLCAL1_NDAC1_MASK & \ 5480+ ((val) \ 5481+ << PLLDIG_PLLCAL1_NDAC1_OFFSET)) 5482+#define PLLDIG_PLLCAL1_NDAC1_OFFSET (24) 5483+#define PLLDIG_PLLCAL1_NDAC1_MASK (0x7F000000) 5484+ 5485+/* Naming convention for PLL: 5486+ * ARMPLL - PLL0 5487+ * PERIPHPLL - PLL1 5488+ * ENETPLL - PLL2 5489+ * DDRPLL - PLL3 5490+ * VIDEOPLL - PLL4 5491+ */ 5492+/* The min,max values for PLL VCO (Hz) */ 5493+#define PERIPHPLL_MAX_VCO_RATE (1200000000) 5494+ 5495+/* The min,max values for PLL PHI0 and PHI1 outputs (Hz) */ 5496+#define PERIPHPLL_MAX_PHI0_MAX_RATE (400000000) 5497+#define PERIPHPLL_MAX_PHI1_MAX_RATE (100000000) 5498+ 5499+/* The maximum value for PLL VCO according to data sheet */ 5500+#define MAX_VCO_RATE (1300000000) 5501+#define MIN_VCO_RATE (650000000) 5502+ 5503+enum s32v234_plldig_type { 5504+ S32_PLLDIG_ARM, 5505+ S32_PLLDIG_PERIPH, 5506+ S32_PLLDIG_ENET, 5507+ S32_PLLDIG_DDR, 5508+ S32_PLLDIG_VIDEO, 5509+}; 5510+ 5511+#endif 5512diff --git a/drivers/clk/s32/s32v234/src.h b/drivers/clk/s32/s32v234/src.h 5513new file mode 100644 5514index 000000000..39fa973b7 5515--- /dev/null 5516+++ b/drivers/clk/s32/s32v234/src.h 5517@@ -0,0 +1,17 @@ 5518+/* SPDX-License-Identifier: GPL-2.0-or-later */ 5519+/* 5520+ * Copyright (C) 2016 Freescale Semiconductor, Inc. 5521+ */ 5522+#ifndef _SRC_H 5523+#define _SRC_H 5524+ 5525+/* Source Reset Control: General Purpose Register 1 */ 5526+#define SRC_GPR1 (src_base + 0x100) 5527+#define SRC_GPR1_ARMPLL_SRC_SEL_OFFSET (27) 5528+#define SRC_GPR1_ENETPLL_SRC_SEL_OFFSET (28) 5529+#define SRC_GPR1_DDRPLL_SRC_SEL_OFFSET (29) 5530+#define SRC_GPR1_PERIPHPLL_SRC_SEL_OFFSET (30) 5531+#define SRC_GPR1_VIDEOPLL_SRC_SEL_OFFSET (31) 5532+#define SRC_GPR1_XPLL_SRC_SEL_SIZE (1) 5533+ 5534+#endif 5535