mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-05 00:20:32 +00:00
clk: renesas: Updates for v5.12 (take two)
- Add I2c and Ethernet (RAVB) clocks on R-Car V3U, - Fix a kerneldoc issue. -----BEGIN PGP SIGNATURE----- iHUEABYIAB0WIQQ9qaHoIs/1I4cXmEiKwlD9ZEnxcAUCYBPNNQAKCRCKwlD9ZEnx cE5/AP4wtn6wqUlIVFdrZd9se011gEB13lP/VMJ925OyOOLnLAD+O37MJnfNF/tJ oLmSuf84d/k4mQR3K4p+xjs/AU2W3As= =7ufY -----END PGP SIGNATURE----- Merge tag 'renesas-clk-for-v5.12-tag2' of git://git.kernel.org/pub/scm/linux/kernel/git/geert/renesas-drivers into clk-renesas Pull Renesas clk driver updates from Geert Uytterhoeven: - Add I2c and Ethernet (RAVB) clocks on R-Car V3U - Fix a kerneldoc issue - Add timer (TMU) clocks on most R-Car Gen3 SoCs - Add video-related (FCPVD/VSPD/VSPX), watchdog (RWDT), serial (HSCIF), pincontrol/GPIO (PFC/GPIO), SPI (MSIOF), SDHI, and DMA (SYS-DMAC) clocks on R-Car V3U - Add support for the USB 2.0 clock selector on RZ/G2 SoCs - Minor fixes and improvements * tag 'renesas-clk-for-v5.12-tag2' of git://git.kernel.org/pub/scm/linux/kernel/git/geert/renesas-drivers: (21 commits) clk: renesas: cpg-mssr: Fix formatting issues for 'smstpcr_saved's documentation clk: renesas: r8a779a0: Add RAVB clocks clk: renesas: r8a779a0: Add I2C clocks dt-bindings: clock: renesas: rcar-usb2-clock-sel: Add support for RZ/G2 M/N/H clk: renesas: r8a779a0: Add SYS-DMAC clocks clk: renesas: r8a779a0: Add SDHI support clk: renesas: rcar-gen3: Factor out CPG library clk: renesas: rcar-gen3: Remove cpg_quirks access when registering SD clock clk: renesas: r8a779a0: Add MSIOF clocks clk: renesas: r8a779a0: Add PFC/GPIO clocks clk: renesas: r8a779a0: Fix parent of CBFUSA clock clk: renesas: r8a779a0: Remove non-existent S2 clock clk: renesas: r8a779a0: Add HSCIF support clk: renesas: r8a779a0: Add RWDT clocks clk: renesas: r8a779a0: Add VSPX clock support clk: renesas: r8a779a0: Add VSPD clock support clk: renesas: r8a779a0: Add FCPVD clock support clk: renesas: r8a77995: Add TMU clocks clk: renesas: r8a77990: Add TMU clocks clk: renesas: r8a77965: Add TMU clocks ...
This commit is contained in:
commit
7907e69f31
12 changed files with 406 additions and 264 deletions
|
@ -35,6 +35,9 @@ properties:
|
|||
compatible:
|
||||
items:
|
||||
- enum:
|
||||
- renesas,r8a774a1-rcar-usb2-clock-sel # RZ/G2M
|
||||
- renesas,r8a774b1-rcar-usb2-clock-sel # RZ/G2N
|
||||
- renesas,r8a774e1-rcar-usb2-clock-sel # RZ/G2H
|
||||
- renesas,r8a7795-rcar-usb2-clock-sel # R-Car H3
|
||||
- renesas,r8a7796-rcar-usb2-clock-sel # R-Car M3-W
|
||||
- renesas,r8a77961-rcar-usb2-clock-sel # R-Car M3-W+
|
||||
|
|
|
@ -148,6 +148,7 @@ config CLK_R8A77995
|
|||
|
||||
config CLK_R8A779A0
|
||||
bool "R-Car V3U clock support" if COMPILE_TEST
|
||||
select CLK_RCAR_CPG_LIB
|
||||
select CLK_RENESAS_CPG_MSSR
|
||||
|
||||
config CLK_R9A06G032
|
||||
|
@ -162,12 +163,16 @@ config CLK_SH73A0
|
|||
|
||||
|
||||
# Family
|
||||
config CLK_RCAR_CPG_LIB
|
||||
bool "CPG/MSSR library functions" if COMPILE_TEST
|
||||
|
||||
config CLK_RCAR_GEN2_CPG
|
||||
bool "R-Car Gen2 CPG clock support" if COMPILE_TEST
|
||||
select CLK_RENESAS_CPG_MSSR
|
||||
|
||||
config CLK_RCAR_GEN3_CPG
|
||||
bool "R-Car Gen3 and RZ/G2 CPG clock support" if COMPILE_TEST
|
||||
select CLK_RCAR_CPG_LIB
|
||||
select CLK_RENESAS_CPG_MSSR
|
||||
|
||||
config CLK_RCAR_USB2_CLOCK_SEL
|
||||
|
|
|
@ -32,6 +32,7 @@ obj-$(CONFIG_CLK_R9A06G032) += r9a06g032-clocks.o
|
|||
obj-$(CONFIG_CLK_SH73A0) += clk-sh73a0.o
|
||||
|
||||
# Family
|
||||
obj-$(CONFIG_CLK_RCAR_CPG_LIB) += rcar-cpg-lib.o
|
||||
obj-$(CONFIG_CLK_RCAR_GEN2_CPG) += rcar-gen2-cpg.o
|
||||
obj-$(CONFIG_CLK_RCAR_GEN3_CPG) += rcar-gen3-cpg.o
|
||||
obj-$(CONFIG_CLK_RCAR_USB2_CLOCK_SEL) += rcar-usb2-clock-sel.o
|
||||
|
|
|
@ -128,6 +128,11 @@ static const struct cpg_core_clk r8a7796_core_clks[] __initconst = {
|
|||
|
||||
static struct mssr_mod_clk r8a7796_mod_clks[] __initdata = {
|
||||
DEF_MOD("fdp1-0", 119, R8A7796_CLK_S0D1),
|
||||
DEF_MOD("tmu4", 121, R8A7796_CLK_S0D6),
|
||||
DEF_MOD("tmu3", 122, R8A7796_CLK_S3D2),
|
||||
DEF_MOD("tmu2", 123, R8A7796_CLK_S3D2),
|
||||
DEF_MOD("tmu1", 124, R8A7796_CLK_S3D2),
|
||||
DEF_MOD("tmu0", 125, R8A7796_CLK_CP),
|
||||
DEF_MOD("scif5", 202, R8A7796_CLK_S3D4),
|
||||
DEF_MOD("scif4", 203, R8A7796_CLK_S3D4),
|
||||
DEF_MOD("scif3", 204, R8A7796_CLK_S3D4),
|
||||
|
|
|
@ -123,6 +123,11 @@ static const struct cpg_core_clk r8a77965_core_clks[] __initconst = {
|
|||
|
||||
static const struct mssr_mod_clk r8a77965_mod_clks[] __initconst = {
|
||||
DEF_MOD("fdp1-0", 119, R8A77965_CLK_S0D1),
|
||||
DEF_MOD("tmu4", 121, R8A77965_CLK_S0D6),
|
||||
DEF_MOD("tmu3", 122, R8A77965_CLK_S3D2),
|
||||
DEF_MOD("tmu2", 123, R8A77965_CLK_S3D2),
|
||||
DEF_MOD("tmu1", 124, R8A77965_CLK_S3D2),
|
||||
DEF_MOD("tmu0", 125, R8A77965_CLK_CP),
|
||||
DEF_MOD("scif5", 202, R8A77965_CLK_S3D4),
|
||||
DEF_MOD("scif4", 203, R8A77965_CLK_S3D4),
|
||||
DEF_MOD("scif3", 204, R8A77965_CLK_S3D4),
|
||||
|
|
|
@ -124,6 +124,11 @@ static const struct cpg_core_clk r8a77990_core_clks[] __initconst = {
|
|||
};
|
||||
|
||||
static const struct mssr_mod_clk r8a77990_mod_clks[] __initconst = {
|
||||
DEF_MOD("tmu4", 121, R8A77990_CLK_S0D6C),
|
||||
DEF_MOD("tmu3", 122, R8A77990_CLK_S3D2C),
|
||||
DEF_MOD("tmu2", 123, R8A77990_CLK_S3D2C),
|
||||
DEF_MOD("tmu1", 124, R8A77990_CLK_S3D2C),
|
||||
DEF_MOD("tmu0", 125, R8A77990_CLK_CP),
|
||||
DEF_MOD("scif5", 202, R8A77990_CLK_S3D4C),
|
||||
DEF_MOD("scif4", 203, R8A77990_CLK_S3D4C),
|
||||
DEF_MOD("scif3", 204, R8A77990_CLK_S3D4C),
|
||||
|
|
|
@ -111,6 +111,11 @@ static const struct cpg_core_clk r8a77995_core_clks[] __initconst = {
|
|||
};
|
||||
|
||||
static const struct mssr_mod_clk r8a77995_mod_clks[] __initconst = {
|
||||
DEF_MOD("tmu4", 121, R8A77995_CLK_S1D4C),
|
||||
DEF_MOD("tmu3", 122, R8A77995_CLK_S3D2C),
|
||||
DEF_MOD("tmu2", 123, R8A77995_CLK_S3D2C),
|
||||
DEF_MOD("tmu1", 124, R8A77995_CLK_S3D2C),
|
||||
DEF_MOD("tmu0", 125, R8A77995_CLK_CP),
|
||||
DEF_MOD("scif5", 202, R8A77995_CLK_S3D4C),
|
||||
DEF_MOD("scif4", 203, R8A77995_CLK_S3D4C),
|
||||
DEF_MOD("scif3", 204, R8A77995_CLK_S3D4C),
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
#include <dt-bindings/clock/r8a779a0-cpg-mssr.h>
|
||||
|
||||
#include "rcar-cpg-lib.h"
|
||||
#include "renesas-cpg-mssr.h"
|
||||
|
||||
enum rcar_r8a779a0_clk_types {
|
||||
|
@ -32,6 +33,7 @@ enum rcar_r8a779a0_clk_types {
|
|||
CLK_TYPE_R8A779A0_PLL1,
|
||||
CLK_TYPE_R8A779A0_PLL2X_3X, /* PLL[23][01] */
|
||||
CLK_TYPE_R8A779A0_PLL5,
|
||||
CLK_TYPE_R8A779A0_SD,
|
||||
CLK_TYPE_R8A779A0_MDSEL, /* Select parent/divider using mode pin */
|
||||
CLK_TYPE_R8A779A0_OSC, /* OSC EXTAL predivider and fixed divider */
|
||||
};
|
||||
|
@ -69,7 +71,6 @@ enum clk_ids {
|
|||
CLK_PLL5_DIV2,
|
||||
CLK_PLL5_DIV4,
|
||||
CLK_S1,
|
||||
CLK_S2,
|
||||
CLK_S3,
|
||||
CLK_SDSRC,
|
||||
CLK_RPCSRC,
|
||||
|
@ -83,6 +84,9 @@ enum clk_ids {
|
|||
DEF_BASE(_name, _id, CLK_TYPE_R8A779A0_PLL2X_3X, CLK_MAIN, \
|
||||
.offset = _offset)
|
||||
|
||||
#define DEF_SD(_name, _id, _parent, _offset) \
|
||||
DEF_BASE(_name, _id, CLK_TYPE_R8A779A0_SD, _parent, .offset = _offset)
|
||||
|
||||
#define DEF_MDSEL(_name, _id, _md, _parent0, _div0, _parent1, _div1) \
|
||||
DEF_BASE(_name, _id, CLK_TYPE_R8A779A0_MDSEL, \
|
||||
(_parent0) << 16 | (_parent1), \
|
||||
|
@ -114,6 +118,7 @@ static const struct cpg_core_clk r8a779a0_core_clks[] __initconst = {
|
|||
DEF_FIXED(".pll5_div4", CLK_PLL5_DIV4, CLK_PLL5_DIV2, 2, 1),
|
||||
DEF_FIXED(".s1", CLK_S1, CLK_PLL1_DIV2, 2, 1),
|
||||
DEF_FIXED(".s3", CLK_S3, CLK_PLL1_DIV2, 4, 1),
|
||||
DEF_FIXED(".sdsrc", CLK_SDSRC, CLK_PLL5_DIV4, 1, 1),
|
||||
DEF_RATE(".oco", CLK_OCO, 32768),
|
||||
|
||||
/* Core Clock Outputs */
|
||||
|
@ -137,7 +142,10 @@ static const struct cpg_core_clk r8a779a0_core_clks[] __initconst = {
|
|||
DEF_FIXED("icu", R8A779A0_CLK_ICU, CLK_PLL5_DIV4, 2, 1),
|
||||
DEF_FIXED("icud2", R8A779A0_CLK_ICUD2, CLK_PLL5_DIV4, 4, 1),
|
||||
DEF_FIXED("vcbus", R8A779A0_CLK_VCBUS, CLK_PLL5_DIV4, 1, 1),
|
||||
DEF_FIXED("cbfusa", R8A779A0_CLK_CBFUSA, CLK_MAIN, 2, 1),
|
||||
DEF_FIXED("cbfusa", R8A779A0_CLK_CBFUSA, CLK_EXTAL, 2, 1),
|
||||
DEF_FIXED("cp", R8A779A0_CLK_CP, CLK_EXTAL, 2, 1),
|
||||
|
||||
DEF_SD("sd0", R8A779A0_CLK_SD0, CLK_SDSRC, 0x870),
|
||||
|
||||
DEF_DIV6P1("mso", R8A779A0_CLK_MSO, CLK_PLL5_DIV4, 0x87c),
|
||||
DEF_DIV6P1("canfd", R8A779A0_CLK_CANFD, CLK_PLL5_DIV4, 0x878),
|
||||
|
@ -148,14 +156,42 @@ static const struct cpg_core_clk r8a779a0_core_clks[] __initconst = {
|
|||
};
|
||||
|
||||
static const struct mssr_mod_clk r8a779a0_mod_clks[] __initconst = {
|
||||
DEF_MOD("avb0", 211, R8A779A0_CLK_S3D2),
|
||||
DEF_MOD("avb1", 212, R8A779A0_CLK_S3D2),
|
||||
DEF_MOD("avb2", 213, R8A779A0_CLK_S3D2),
|
||||
DEF_MOD("avb3", 214, R8A779A0_CLK_S3D2),
|
||||
DEF_MOD("avb4", 215, R8A779A0_CLK_S3D2),
|
||||
DEF_MOD("avb5", 216, R8A779A0_CLK_S3D2),
|
||||
DEF_MOD("csi40", 331, R8A779A0_CLK_CSI0),
|
||||
DEF_MOD("csi41", 400, R8A779A0_CLK_CSI0),
|
||||
DEF_MOD("csi42", 401, R8A779A0_CLK_CSI0),
|
||||
DEF_MOD("csi43", 402, R8A779A0_CLK_CSI0),
|
||||
DEF_MOD("fcpvd0", 508, R8A779A0_CLK_S3D1),
|
||||
DEF_MOD("fcpvd1", 509, R8A779A0_CLK_S3D1),
|
||||
DEF_MOD("hscif0", 514, R8A779A0_CLK_S1D2),
|
||||
DEF_MOD("hscif1", 515, R8A779A0_CLK_S1D2),
|
||||
DEF_MOD("hscif2", 516, R8A779A0_CLK_S1D2),
|
||||
DEF_MOD("hscif3", 517, R8A779A0_CLK_S1D2),
|
||||
DEF_MOD("i2c0", 518, R8A779A0_CLK_S1D4),
|
||||
DEF_MOD("i2c1", 519, R8A779A0_CLK_S1D4),
|
||||
DEF_MOD("i2c2", 520, R8A779A0_CLK_S1D4),
|
||||
DEF_MOD("i2c3", 521, R8A779A0_CLK_S1D4),
|
||||
DEF_MOD("i2c4", 522, R8A779A0_CLK_S1D4),
|
||||
DEF_MOD("i2c5", 523, R8A779A0_CLK_S1D4),
|
||||
DEF_MOD("i2c6", 524, R8A779A0_CLK_S1D4),
|
||||
DEF_MOD("msi0", 618, R8A779A0_CLK_MSO),
|
||||
DEF_MOD("msi1", 619, R8A779A0_CLK_MSO),
|
||||
DEF_MOD("msi2", 620, R8A779A0_CLK_MSO),
|
||||
DEF_MOD("msi3", 621, R8A779A0_CLK_MSO),
|
||||
DEF_MOD("msi4", 622, R8A779A0_CLK_MSO),
|
||||
DEF_MOD("msi5", 623, R8A779A0_CLK_MSO),
|
||||
DEF_MOD("scif0", 702, R8A779A0_CLK_S1D8),
|
||||
DEF_MOD("scif1", 703, R8A779A0_CLK_S1D8),
|
||||
DEF_MOD("scif3", 704, R8A779A0_CLK_S1D8),
|
||||
DEF_MOD("scif4", 705, R8A779A0_CLK_S1D8),
|
||||
DEF_MOD("sdhi0", 706, R8A779A0_CLK_SD0),
|
||||
DEF_MOD("sydm1", 709, R8A779A0_CLK_S1D2),
|
||||
DEF_MOD("sydm2", 710, R8A779A0_CLK_S1D2),
|
||||
DEF_MOD("vin00", 730, R8A779A0_CLK_S1D1),
|
||||
DEF_MOD("vin01", 731, R8A779A0_CLK_S1D1),
|
||||
DEF_MOD("vin02", 800, R8A779A0_CLK_S1D1),
|
||||
|
@ -188,10 +224,19 @@ static const struct mssr_mod_clk r8a779a0_mod_clks[] __initconst = {
|
|||
DEF_MOD("vin35", 827, R8A779A0_CLK_S1D1),
|
||||
DEF_MOD("vin36", 828, R8A779A0_CLK_S1D1),
|
||||
DEF_MOD("vin37", 829, R8A779A0_CLK_S1D1),
|
||||
DEF_MOD("vspd0", 830, R8A779A0_CLK_S3D1),
|
||||
DEF_MOD("vspd1", 831, R8A779A0_CLK_S3D1),
|
||||
DEF_MOD("rwdt", 907, R8A779A0_CLK_R),
|
||||
DEF_MOD("pfc0", 915, R8A779A0_CLK_CP),
|
||||
DEF_MOD("pfc1", 916, R8A779A0_CLK_CP),
|
||||
DEF_MOD("pfc2", 917, R8A779A0_CLK_CP),
|
||||
DEF_MOD("pfc3", 918, R8A779A0_CLK_CP),
|
||||
DEF_MOD("vspx0", 1028, R8A779A0_CLK_S1D1),
|
||||
DEF_MOD("vspx1", 1029, R8A779A0_CLK_S1D1),
|
||||
DEF_MOD("vspx2", 1030, R8A779A0_CLK_S1D1),
|
||||
DEF_MOD("vspx3", 1031, R8A779A0_CLK_S1D1),
|
||||
};
|
||||
|
||||
static spinlock_t cpg_lock;
|
||||
|
||||
static const struct rcar_r8a779a0_cpg_pll_config *cpg_pll_config __initdata;
|
||||
static unsigned int cpg_clk_extalr __initdata;
|
||||
static u32 cpg_mode __initdata;
|
||||
|
@ -230,6 +275,12 @@ static struct clk * __init rcar_r8a779a0_cpg_clk_register(struct device *dev,
|
|||
div = cpg_pll_config->pll5_div;
|
||||
break;
|
||||
|
||||
case CLK_TYPE_R8A779A0_SD:
|
||||
return cpg_sd_clk_register(core->name, base, core->offset,
|
||||
__clk_get_name(parent), notifiers,
|
||||
false);
|
||||
break;
|
||||
|
||||
case CLK_TYPE_R8A779A0_MDSEL:
|
||||
/*
|
||||
* Clock selectable between two parents and two fixed dividers
|
||||
|
@ -261,6 +312,10 @@ static struct clk * __init rcar_r8a779a0_cpg_clk_register(struct device *dev,
|
|||
__clk_get_name(parent), 0, mult, div);
|
||||
}
|
||||
|
||||
static const unsigned int r8a779a0_crit_mod_clks[] __initconst = {
|
||||
MOD_CLK_ID(907), /* RWDT */
|
||||
};
|
||||
|
||||
/*
|
||||
* CPG Clock Data
|
||||
*/
|
||||
|
@ -311,6 +366,10 @@ const struct cpg_mssr_info r8a779a0_cpg_mssr_info __initconst = {
|
|||
.num_mod_clks = ARRAY_SIZE(r8a779a0_mod_clks),
|
||||
.num_hw_mod_clks = 15 * 32,
|
||||
|
||||
/* Critical Module Clocks */
|
||||
.crit_mod_clks = r8a779a0_crit_mod_clks,
|
||||
.num_crit_mod_clks = ARRAY_SIZE(r8a779a0_crit_mod_clks),
|
||||
|
||||
/* Callbacks */
|
||||
.init = r8a779a0_cpg_mssr_init,
|
||||
.cpg_clk_register = rcar_r8a779a0_cpg_clk_register,
|
||||
|
|
270
drivers/clk/renesas/rcar-cpg-lib.c
Normal file
270
drivers/clk/renesas/rcar-cpg-lib.c
Normal file
|
@ -0,0 +1,270 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* R-Car Gen3 Clock Pulse Generator Library
|
||||
*
|
||||
* Copyright (C) 2015-2018 Glider bvba
|
||||
* Copyright (C) 2019 Renesas Electronics Corp.
|
||||
*
|
||||
* Based on clk-rcar-gen3.c
|
||||
*
|
||||
* Copyright (C) 2015 Renesas Electronics Corp.
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/sys_soc.h>
|
||||
|
||||
#include "rcar-cpg-lib.h"
|
||||
|
||||
spinlock_t cpg_lock;
|
||||
|
||||
void cpg_reg_modify(void __iomem *reg, u32 clear, u32 set)
|
||||
{
|
||||
unsigned long flags;
|
||||
u32 val;
|
||||
|
||||
spin_lock_irqsave(&cpg_lock, flags);
|
||||
val = readl(reg);
|
||||
val &= ~clear;
|
||||
val |= set;
|
||||
writel(val, reg);
|
||||
spin_unlock_irqrestore(&cpg_lock, flags);
|
||||
};
|
||||
|
||||
static int cpg_simple_notifier_call(struct notifier_block *nb,
|
||||
unsigned long action, void *data)
|
||||
{
|
||||
struct cpg_simple_notifier *csn =
|
||||
container_of(nb, struct cpg_simple_notifier, nb);
|
||||
|
||||
switch (action) {
|
||||
case PM_EVENT_SUSPEND:
|
||||
csn->saved = readl(csn->reg);
|
||||
return NOTIFY_OK;
|
||||
|
||||
case PM_EVENT_RESUME:
|
||||
writel(csn->saved, csn->reg);
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
void cpg_simple_notifier_register(struct raw_notifier_head *notifiers,
|
||||
struct cpg_simple_notifier *csn)
|
||||
{
|
||||
csn->nb.notifier_call = cpg_simple_notifier_call;
|
||||
raw_notifier_chain_register(notifiers, &csn->nb);
|
||||
}
|
||||
|
||||
/*
|
||||
* SDn Clock
|
||||
*/
|
||||
#define CPG_SD_STP_HCK BIT(9)
|
||||
#define CPG_SD_STP_CK BIT(8)
|
||||
|
||||
#define CPG_SD_STP_MASK (CPG_SD_STP_HCK | CPG_SD_STP_CK)
|
||||
#define CPG_SD_FC_MASK (0x7 << 2 | 0x3 << 0)
|
||||
|
||||
#define CPG_SD_DIV_TABLE_DATA(stp_hck, sd_srcfc, sd_fc, sd_div) \
|
||||
{ \
|
||||
.val = ((stp_hck) ? CPG_SD_STP_HCK : 0) | \
|
||||
((sd_srcfc) << 2) | \
|
||||
((sd_fc) << 0), \
|
||||
.div = (sd_div), \
|
||||
}
|
||||
|
||||
struct sd_div_table {
|
||||
u32 val;
|
||||
unsigned int div;
|
||||
};
|
||||
|
||||
struct sd_clock {
|
||||
struct clk_hw hw;
|
||||
const struct sd_div_table *div_table;
|
||||
struct cpg_simple_notifier csn;
|
||||
unsigned int div_num;
|
||||
unsigned int cur_div_idx;
|
||||
};
|
||||
|
||||
/* SDn divider
|
||||
* sd_srcfc sd_fc div
|
||||
* stp_hck (div) (div) = sd_srcfc x sd_fc
|
||||
*---------------------------------------------------------
|
||||
* 0 0 (1) 1 (4) 4 : SDR104 / HS200 / HS400 (8 TAP)
|
||||
* 0 1 (2) 1 (4) 8 : SDR50
|
||||
* 1 2 (4) 1 (4) 16 : HS / SDR25
|
||||
* 1 3 (8) 1 (4) 32 : NS / SDR12
|
||||
* 1 4 (16) 1 (4) 64
|
||||
* 0 0 (1) 0 (2) 2
|
||||
* 0 1 (2) 0 (2) 4 : SDR104 / HS200 / HS400 (4 TAP)
|
||||
* 1 2 (4) 0 (2) 8
|
||||
* 1 3 (8) 0 (2) 16
|
||||
* 1 4 (16) 0 (2) 32
|
||||
*
|
||||
* NOTE: There is a quirk option to ignore the first row of the dividers
|
||||
* table when searching for suitable settings. This is because HS400 on
|
||||
* early ES versions of H3 and M3-W requires a specific setting to work.
|
||||
*/
|
||||
static const struct sd_div_table cpg_sd_div_table[] = {
|
||||
/* CPG_SD_DIV_TABLE_DATA(stp_hck, sd_srcfc, sd_fc, sd_div) */
|
||||
CPG_SD_DIV_TABLE_DATA(0, 0, 1, 4),
|
||||
CPG_SD_DIV_TABLE_DATA(0, 1, 1, 8),
|
||||
CPG_SD_DIV_TABLE_DATA(1, 2, 1, 16),
|
||||
CPG_SD_DIV_TABLE_DATA(1, 3, 1, 32),
|
||||
CPG_SD_DIV_TABLE_DATA(1, 4, 1, 64),
|
||||
CPG_SD_DIV_TABLE_DATA(0, 0, 0, 2),
|
||||
CPG_SD_DIV_TABLE_DATA(0, 1, 0, 4),
|
||||
CPG_SD_DIV_TABLE_DATA(1, 2, 0, 8),
|
||||
CPG_SD_DIV_TABLE_DATA(1, 3, 0, 16),
|
||||
CPG_SD_DIV_TABLE_DATA(1, 4, 0, 32),
|
||||
};
|
||||
|
||||
#define to_sd_clock(_hw) container_of(_hw, struct sd_clock, hw)
|
||||
|
||||
static int cpg_sd_clock_enable(struct clk_hw *hw)
|
||||
{
|
||||
struct sd_clock *clock = to_sd_clock(hw);
|
||||
|
||||
cpg_reg_modify(clock->csn.reg, CPG_SD_STP_MASK,
|
||||
clock->div_table[clock->cur_div_idx].val &
|
||||
CPG_SD_STP_MASK);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void cpg_sd_clock_disable(struct clk_hw *hw)
|
||||
{
|
||||
struct sd_clock *clock = to_sd_clock(hw);
|
||||
|
||||
cpg_reg_modify(clock->csn.reg, 0, CPG_SD_STP_MASK);
|
||||
}
|
||||
|
||||
static int cpg_sd_clock_is_enabled(struct clk_hw *hw)
|
||||
{
|
||||
struct sd_clock *clock = to_sd_clock(hw);
|
||||
|
||||
return !(readl(clock->csn.reg) & CPG_SD_STP_MASK);
|
||||
}
|
||||
|
||||
static unsigned long cpg_sd_clock_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct sd_clock *clock = to_sd_clock(hw);
|
||||
|
||||
return DIV_ROUND_CLOSEST(parent_rate,
|
||||
clock->div_table[clock->cur_div_idx].div);
|
||||
}
|
||||
|
||||
static int cpg_sd_clock_determine_rate(struct clk_hw *hw,
|
||||
struct clk_rate_request *req)
|
||||
{
|
||||
unsigned long best_rate = ULONG_MAX, diff_min = ULONG_MAX;
|
||||
struct sd_clock *clock = to_sd_clock(hw);
|
||||
unsigned long calc_rate, diff;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < clock->div_num; i++) {
|
||||
calc_rate = DIV_ROUND_CLOSEST(req->best_parent_rate,
|
||||
clock->div_table[i].div);
|
||||
if (calc_rate < req->min_rate || calc_rate > req->max_rate)
|
||||
continue;
|
||||
|
||||
diff = calc_rate > req->rate ? calc_rate - req->rate
|
||||
: req->rate - calc_rate;
|
||||
if (diff < diff_min) {
|
||||
best_rate = calc_rate;
|
||||
diff_min = diff;
|
||||
}
|
||||
}
|
||||
|
||||
if (best_rate == ULONG_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
req->rate = best_rate;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cpg_sd_clock_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct sd_clock *clock = to_sd_clock(hw);
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < clock->div_num; i++)
|
||||
if (rate == DIV_ROUND_CLOSEST(parent_rate,
|
||||
clock->div_table[i].div))
|
||||
break;
|
||||
|
||||
if (i >= clock->div_num)
|
||||
return -EINVAL;
|
||||
|
||||
clock->cur_div_idx = i;
|
||||
|
||||
cpg_reg_modify(clock->csn.reg, CPG_SD_STP_MASK | CPG_SD_FC_MASK,
|
||||
clock->div_table[i].val &
|
||||
(CPG_SD_STP_MASK | CPG_SD_FC_MASK));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct clk_ops cpg_sd_clock_ops = {
|
||||
.enable = cpg_sd_clock_enable,
|
||||
.disable = cpg_sd_clock_disable,
|
||||
.is_enabled = cpg_sd_clock_is_enabled,
|
||||
.recalc_rate = cpg_sd_clock_recalc_rate,
|
||||
.determine_rate = cpg_sd_clock_determine_rate,
|
||||
.set_rate = cpg_sd_clock_set_rate,
|
||||
};
|
||||
|
||||
struct clk * __init cpg_sd_clk_register(const char *name,
|
||||
void __iomem *base, unsigned int offset, const char *parent_name,
|
||||
struct raw_notifier_head *notifiers, bool skip_first)
|
||||
{
|
||||
struct clk_init_data init;
|
||||
struct sd_clock *clock;
|
||||
struct clk *clk;
|
||||
u32 val;
|
||||
|
||||
clock = kzalloc(sizeof(*clock), GFP_KERNEL);
|
||||
if (!clock)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
init.name = name;
|
||||
init.ops = &cpg_sd_clock_ops;
|
||||
init.flags = CLK_SET_RATE_PARENT;
|
||||
init.parent_names = &parent_name;
|
||||
init.num_parents = 1;
|
||||
|
||||
clock->csn.reg = base + offset;
|
||||
clock->hw.init = &init;
|
||||
clock->div_table = cpg_sd_div_table;
|
||||
clock->div_num = ARRAY_SIZE(cpg_sd_div_table);
|
||||
|
||||
if (skip_first) {
|
||||
clock->div_table++;
|
||||
clock->div_num--;
|
||||
}
|
||||
|
||||
val = readl(clock->csn.reg) & ~CPG_SD_FC_MASK;
|
||||
val |= CPG_SD_STP_MASK | (clock->div_table[0].val & CPG_SD_FC_MASK);
|
||||
writel(val, clock->csn.reg);
|
||||
|
||||
clk = clk_register(NULL, &clock->hw);
|
||||
if (IS_ERR(clk))
|
||||
goto free_clock;
|
||||
|
||||
cpg_simple_notifier_register(notifiers, &clock->csn);
|
||||
return clk;
|
||||
|
||||
free_clock:
|
||||
kfree(clock);
|
||||
return clk;
|
||||
}
|
||||
|
||||
|
33
drivers/clk/renesas/rcar-cpg-lib.h
Normal file
33
drivers/clk/renesas/rcar-cpg-lib.h
Normal file
|
@ -0,0 +1,33 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* R-Car Gen3 Clock Pulse Generator Library
|
||||
*
|
||||
* Copyright (C) 2015-2018 Glider bvba
|
||||
* Copyright (C) 2019 Renesas Electronics Corp.
|
||||
*
|
||||
* Based on clk-rcar-gen3.c
|
||||
*
|
||||
* Copyright (C) 2015 Renesas Electronics Corp.
|
||||
*/
|
||||
|
||||
#ifndef __CLK_RENESAS_RCAR_CPG_LIB_H__
|
||||
#define __CLK_RENESAS_RCAR_CPG_LIB_H__
|
||||
|
||||
extern spinlock_t cpg_lock;
|
||||
|
||||
struct cpg_simple_notifier {
|
||||
struct notifier_block nb;
|
||||
void __iomem *reg;
|
||||
u32 saved;
|
||||
};
|
||||
|
||||
void cpg_simple_notifier_register(struct raw_notifier_head *notifiers,
|
||||
struct cpg_simple_notifier *csn);
|
||||
|
||||
void cpg_reg_modify(void __iomem *reg, u32 clear, u32 set);
|
||||
|
||||
struct clk * __init cpg_sd_clk_register(const char *name,
|
||||
void __iomem *base, unsigned int offset, const char *parent_name,
|
||||
struct raw_notifier_head *notifiers, bool skip_first);
|
||||
|
||||
#endif
|
|
@ -23,6 +23,7 @@
|
|||
#include <linux/sys_soc.h>
|
||||
|
||||
#include "renesas-cpg-mssr.h"
|
||||
#include "rcar-cpg-lib.h"
|
||||
#include "rcar-gen3-cpg.h"
|
||||
|
||||
#define CPG_PLL0CR 0x00d8
|
||||
|
@ -31,52 +32,6 @@
|
|||
|
||||
#define CPG_RCKCR_CKSEL BIT(15) /* RCLK Clock Source Select */
|
||||
|
||||
static spinlock_t cpg_lock;
|
||||
|
||||
static void cpg_reg_modify(void __iomem *reg, u32 clear, u32 set)
|
||||
{
|
||||
unsigned long flags;
|
||||
u32 val;
|
||||
|
||||
spin_lock_irqsave(&cpg_lock, flags);
|
||||
val = readl(reg);
|
||||
val &= ~clear;
|
||||
val |= set;
|
||||
writel(val, reg);
|
||||
spin_unlock_irqrestore(&cpg_lock, flags);
|
||||
};
|
||||
|
||||
struct cpg_simple_notifier {
|
||||
struct notifier_block nb;
|
||||
void __iomem *reg;
|
||||
u32 saved;
|
||||
};
|
||||
|
||||
static int cpg_simple_notifier_call(struct notifier_block *nb,
|
||||
unsigned long action, void *data)
|
||||
{
|
||||
struct cpg_simple_notifier *csn =
|
||||
container_of(nb, struct cpg_simple_notifier, nb);
|
||||
|
||||
switch (action) {
|
||||
case PM_EVENT_SUSPEND:
|
||||
csn->saved = readl(csn->reg);
|
||||
return NOTIFY_OK;
|
||||
|
||||
case PM_EVENT_RESUME:
|
||||
writel(csn->saved, csn->reg);
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
static void cpg_simple_notifier_register(struct raw_notifier_head *notifiers,
|
||||
struct cpg_simple_notifier *csn)
|
||||
{
|
||||
csn->nb.notifier_call = cpg_simple_notifier_call;
|
||||
raw_notifier_chain_register(notifiers, &csn->nb);
|
||||
}
|
||||
|
||||
/*
|
||||
* Z Clock & Z2 Clock
|
||||
*
|
||||
|
@ -215,217 +170,6 @@ static struct clk * __init cpg_z_clk_register(const char *name,
|
|||
return clk;
|
||||
}
|
||||
|
||||
/*
|
||||
* SDn Clock
|
||||
*/
|
||||
#define CPG_SD_STP_HCK BIT(9)
|
||||
#define CPG_SD_STP_CK BIT(8)
|
||||
|
||||
#define CPG_SD_STP_MASK (CPG_SD_STP_HCK | CPG_SD_STP_CK)
|
||||
#define CPG_SD_FC_MASK (0x7 << 2 | 0x3 << 0)
|
||||
|
||||
#define CPG_SD_DIV_TABLE_DATA(stp_hck, sd_srcfc, sd_fc, sd_div) \
|
||||
{ \
|
||||
.val = ((stp_hck) ? CPG_SD_STP_HCK : 0) | \
|
||||
((sd_srcfc) << 2) | \
|
||||
((sd_fc) << 0), \
|
||||
.div = (sd_div), \
|
||||
}
|
||||
|
||||
struct sd_div_table {
|
||||
u32 val;
|
||||
unsigned int div;
|
||||
};
|
||||
|
||||
struct sd_clock {
|
||||
struct clk_hw hw;
|
||||
const struct sd_div_table *div_table;
|
||||
struct cpg_simple_notifier csn;
|
||||
unsigned int div_num;
|
||||
unsigned int cur_div_idx;
|
||||
};
|
||||
|
||||
/* SDn divider
|
||||
* sd_srcfc sd_fc div
|
||||
* stp_hck (div) (div) = sd_srcfc x sd_fc
|
||||
*---------------------------------------------------------
|
||||
* 0 0 (1) 1 (4) 4 : SDR104 / HS200 / HS400 (8 TAP)
|
||||
* 0 1 (2) 1 (4) 8 : SDR50
|
||||
* 1 2 (4) 1 (4) 16 : HS / SDR25
|
||||
* 1 3 (8) 1 (4) 32 : NS / SDR12
|
||||
* 1 4 (16) 1 (4) 64
|
||||
* 0 0 (1) 0 (2) 2
|
||||
* 0 1 (2) 0 (2) 4 : SDR104 / HS200 / HS400 (4 TAP)
|
||||
* 1 2 (4) 0 (2) 8
|
||||
* 1 3 (8) 0 (2) 16
|
||||
* 1 4 (16) 0 (2) 32
|
||||
*
|
||||
* NOTE: There is a quirk option to ignore the first row of the dividers
|
||||
* table when searching for suitable settings. This is because HS400 on
|
||||
* early ES versions of H3 and M3-W requires a specific setting to work.
|
||||
*/
|
||||
static const struct sd_div_table cpg_sd_div_table[] = {
|
||||
/* CPG_SD_DIV_TABLE_DATA(stp_hck, sd_srcfc, sd_fc, sd_div) */
|
||||
CPG_SD_DIV_TABLE_DATA(0, 0, 1, 4),
|
||||
CPG_SD_DIV_TABLE_DATA(0, 1, 1, 8),
|
||||
CPG_SD_DIV_TABLE_DATA(1, 2, 1, 16),
|
||||
CPG_SD_DIV_TABLE_DATA(1, 3, 1, 32),
|
||||
CPG_SD_DIV_TABLE_DATA(1, 4, 1, 64),
|
||||
CPG_SD_DIV_TABLE_DATA(0, 0, 0, 2),
|
||||
CPG_SD_DIV_TABLE_DATA(0, 1, 0, 4),
|
||||
CPG_SD_DIV_TABLE_DATA(1, 2, 0, 8),
|
||||
CPG_SD_DIV_TABLE_DATA(1, 3, 0, 16),
|
||||
CPG_SD_DIV_TABLE_DATA(1, 4, 0, 32),
|
||||
};
|
||||
|
||||
#define to_sd_clock(_hw) container_of(_hw, struct sd_clock, hw)
|
||||
|
||||
static int cpg_sd_clock_enable(struct clk_hw *hw)
|
||||
{
|
||||
struct sd_clock *clock = to_sd_clock(hw);
|
||||
|
||||
cpg_reg_modify(clock->csn.reg, CPG_SD_STP_MASK,
|
||||
clock->div_table[clock->cur_div_idx].val &
|
||||
CPG_SD_STP_MASK);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void cpg_sd_clock_disable(struct clk_hw *hw)
|
||||
{
|
||||
struct sd_clock *clock = to_sd_clock(hw);
|
||||
|
||||
cpg_reg_modify(clock->csn.reg, 0, CPG_SD_STP_MASK);
|
||||
}
|
||||
|
||||
static int cpg_sd_clock_is_enabled(struct clk_hw *hw)
|
||||
{
|
||||
struct sd_clock *clock = to_sd_clock(hw);
|
||||
|
||||
return !(readl(clock->csn.reg) & CPG_SD_STP_MASK);
|
||||
}
|
||||
|
||||
static unsigned long cpg_sd_clock_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct sd_clock *clock = to_sd_clock(hw);
|
||||
|
||||
return DIV_ROUND_CLOSEST(parent_rate,
|
||||
clock->div_table[clock->cur_div_idx].div);
|
||||
}
|
||||
|
||||
static int cpg_sd_clock_determine_rate(struct clk_hw *hw,
|
||||
struct clk_rate_request *req)
|
||||
{
|
||||
unsigned long best_rate = ULONG_MAX, diff_min = ULONG_MAX;
|
||||
struct sd_clock *clock = to_sd_clock(hw);
|
||||
unsigned long calc_rate, diff;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < clock->div_num; i++) {
|
||||
calc_rate = DIV_ROUND_CLOSEST(req->best_parent_rate,
|
||||
clock->div_table[i].div);
|
||||
if (calc_rate < req->min_rate || calc_rate > req->max_rate)
|
||||
continue;
|
||||
|
||||
diff = calc_rate > req->rate ? calc_rate - req->rate
|
||||
: req->rate - calc_rate;
|
||||
if (diff < diff_min) {
|
||||
best_rate = calc_rate;
|
||||
diff_min = diff;
|
||||
}
|
||||
}
|
||||
|
||||
if (best_rate == ULONG_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
req->rate = best_rate;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cpg_sd_clock_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct sd_clock *clock = to_sd_clock(hw);
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < clock->div_num; i++)
|
||||
if (rate == DIV_ROUND_CLOSEST(parent_rate,
|
||||
clock->div_table[i].div))
|
||||
break;
|
||||
|
||||
if (i >= clock->div_num)
|
||||
return -EINVAL;
|
||||
|
||||
clock->cur_div_idx = i;
|
||||
|
||||
cpg_reg_modify(clock->csn.reg, CPG_SD_STP_MASK | CPG_SD_FC_MASK,
|
||||
clock->div_table[i].val &
|
||||
(CPG_SD_STP_MASK | CPG_SD_FC_MASK));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct clk_ops cpg_sd_clock_ops = {
|
||||
.enable = cpg_sd_clock_enable,
|
||||
.disable = cpg_sd_clock_disable,
|
||||
.is_enabled = cpg_sd_clock_is_enabled,
|
||||
.recalc_rate = cpg_sd_clock_recalc_rate,
|
||||
.determine_rate = cpg_sd_clock_determine_rate,
|
||||
.set_rate = cpg_sd_clock_set_rate,
|
||||
};
|
||||
|
||||
static u32 cpg_quirks __initdata;
|
||||
|
||||
#define PLL_ERRATA BIT(0) /* Missing PLL0/2/4 post-divider */
|
||||
#define RCKCR_CKSEL BIT(1) /* Manual RCLK parent selection */
|
||||
#define SD_SKIP_FIRST BIT(2) /* Skip first clock in SD table */
|
||||
|
||||
static struct clk * __init cpg_sd_clk_register(const char *name,
|
||||
void __iomem *base, unsigned int offset, const char *parent_name,
|
||||
struct raw_notifier_head *notifiers)
|
||||
{
|
||||
struct clk_init_data init;
|
||||
struct sd_clock *clock;
|
||||
struct clk *clk;
|
||||
u32 val;
|
||||
|
||||
clock = kzalloc(sizeof(*clock), GFP_KERNEL);
|
||||
if (!clock)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
init.name = name;
|
||||
init.ops = &cpg_sd_clock_ops;
|
||||
init.flags = CLK_SET_RATE_PARENT;
|
||||
init.parent_names = &parent_name;
|
||||
init.num_parents = 1;
|
||||
|
||||
clock->csn.reg = base + offset;
|
||||
clock->hw.init = &init;
|
||||
clock->div_table = cpg_sd_div_table;
|
||||
clock->div_num = ARRAY_SIZE(cpg_sd_div_table);
|
||||
|
||||
if (cpg_quirks & SD_SKIP_FIRST) {
|
||||
clock->div_table++;
|
||||
clock->div_num--;
|
||||
}
|
||||
|
||||
val = readl(clock->csn.reg) & ~CPG_SD_FC_MASK;
|
||||
val |= CPG_SD_STP_MASK | (clock->div_table[0].val & CPG_SD_FC_MASK);
|
||||
writel(val, clock->csn.reg);
|
||||
|
||||
clk = clk_register(NULL, &clock->hw);
|
||||
if (IS_ERR(clk))
|
||||
goto free_clock;
|
||||
|
||||
cpg_simple_notifier_register(notifiers, &clock->csn);
|
||||
return clk;
|
||||
|
||||
free_clock:
|
||||
kfree(clock);
|
||||
return clk;
|
||||
}
|
||||
|
||||
struct rpc_clock {
|
||||
struct clk_divider div;
|
||||
struct clk_gate gate;
|
||||
|
@ -518,6 +262,12 @@ static struct clk * __init cpg_rpcd2_clk_register(const char *name,
|
|||
static const struct rcar_gen3_cpg_pll_config *cpg_pll_config __initdata;
|
||||
static unsigned int cpg_clk_extalr __initdata;
|
||||
static u32 cpg_mode __initdata;
|
||||
static u32 cpg_quirks __initdata;
|
||||
|
||||
#define PLL_ERRATA BIT(0) /* Missing PLL0/2/4 post-divider */
|
||||
#define RCKCR_CKSEL BIT(1) /* Manual RCLK parent selection */
|
||||
#define SD_SKIP_FIRST BIT(2) /* Skip first clock in SD table */
|
||||
|
||||
|
||||
static const struct soc_device_attribute cpg_quirks_match[] __initconst = {
|
||||
{
|
||||
|
@ -613,7 +363,8 @@ struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev,
|
|||
|
||||
case CLK_TYPE_GEN3_SD:
|
||||
return cpg_sd_clk_register(core->name, base, core->offset,
|
||||
__clk_get_name(parent), notifiers);
|
||||
__clk_get_name(parent), notifiers,
|
||||
cpg_quirks & SD_SKIP_FIRST);
|
||||
|
||||
case CLK_TYPE_GEN3_R:
|
||||
if (cpg_quirks & RCKCR_CKSEL) {
|
||||
|
|
|
@ -136,8 +136,8 @@ static const u16 srstclr_for_v3u[] = {
|
|||
* @control_regs: Pointer to control registers array
|
||||
* @reset_regs: Pointer to reset registers array
|
||||
* @reset_clear_regs: Pointer to reset clearing registers array
|
||||
* @smstpcr_saved[].mask: Mask of SMSTPCR[] bits under our control
|
||||
* @smstpcr_saved[].val: Saved values of SMSTPCR[]
|
||||
* @smstpcr_saved: [].mask: Mask of SMSTPCR[] bits under our control
|
||||
* [].val: Saved values of SMSTPCR[]
|
||||
* @clks: Array containing all Core and Module Clocks
|
||||
*/
|
||||
struct cpg_mssr_priv {
|
||||
|
|
Loading…
Reference in a new issue