Merge branches 'clk-socfpga', 'clk-renesas', 'clk-cleanup', 'clk-samsung' and 'clk-mediatek' into clk-next

* clk-socfpga:
  clk: socfpga: agilex5: add clock driver for Agilex5

* clk-renesas: (35 commits)
  clk: renesas: r9a09g077: Add SPI module clocks
  clk: renesas: r9a09g056: Add USB3.0 clocks/resets
  clk: renesas: r9a09g057: Add USB3.0 clocks/resets
  clk: renesas: r9a09g047: Add RSCI clocks/resets
  dt-bindings: clock: renesas,r9a09g056-cpg: Add USB3.0 core clocks
  dt-bindings: clock: renesas,r9a09g057-cpg: Add USB3.0 core clocks
  clk: renesas: r9a06g032: Fix memory leak in error path
  clk: renesas: r9a09g077: Use devm_ helpers for divider clock registration
  clk: renesas: r9a09g077: Remove stray blank line
  clk: renesas: r9a09g077: Propagate rate changes to parent clocks
  clk: renesas: r8a779a0: Add 3DGE module clock
  clk: renesas: r8a779a0: Add ZG Core clock
  clk: renesas: rcar-gen4: Add support for clock dividers in FRQCRB
  dt-bindings: clock: r8a779a0: Add ZG core clock
  clk: renesas: r9a09g056: Add clock and reset entries for ISP
  clk: renesas: r9a09g056: Add support for PLLVDO, CRU clocks, and resets
  clk: renesas: r9a09g056: Add clocks and resets for DSI and LCDC modules
  clk: renesas: r9a09g077: Add TSU module clock
  clk: renesas: r9a09g057: Add clock and reset entries for DSI and LCDC
  clk: renesas: rzv2h: Add support for DSI clocks
  ...

* clk-cleanup:
  clk: keystone: fix compile testing
  clk: keystone: syscon-clk: fix regmap leak on probe failure
  clk: samsung: exynos-clkout: Assign .num before accessing .hws
  clk: actions: Fix discarding const qualifier by 'container_of' macro
  clk: spacemit: Set clk_hw_onecell_data::num before using flex array
  clk: spacemit: fix comment typo
  clk: keystone: Fix discarded const qualifiers
  clk: sprd: sc9860: Simplify with of_device_get_match_data()

* clk-samsung:
  firmware: exynos-acpm: add empty method to allow compile test
  MAINTAINERS: add ACPM clock bindings and driver
  clk: samsung: add Exynos ACPM clock driver
  firmware: exynos-acpm: register ACPM clocks pdev
  firmware: exynos-acpm: add DVFS protocol
  dt-bindings: firmware: google,gs101-acpm-ipc: add ACPM clocks
  clk: samsung: clk-pll: simplify samsung_pll_lock_wait()
  clk: samsung: exynosautov920: add block mfc clock support
  clk: samsung: exynosautov920: add clock support
  dt-bindings: clock: exynosautov920: add mfc clock definitions
  dt-bindings: clock: exynosautov920: add m2m clock definitions
  dt-bindings: clock: google,gs101-clock: add power-domains

* clk-mediatek:
  clk: en7523: Add reset-controller support for EN7523 SoC
  dt-bindings: clock: airoha: Add reset support to EN7523 clock binding
This commit is contained in:
Stephen Boyd
2025-12-03 10:22:24 -08:00
50 changed files with 1936 additions and 136 deletions

View File

@@ -64,8 +64,6 @@ allOf:
reg:
minItems: 2
'#reset-cells': false
- if:
properties:
compatible:
@@ -85,6 +83,7 @@ examples:
reg = <0x1fa20000 0x400>,
<0x1fb00000 0x1000>;
#clock-cells = <1>;
#reset-cells = <1>;
};
- |

View File

@@ -46,6 +46,9 @@ properties:
"#clock-cells":
const: 1
power-domains:
maxItems: 1
reg:
maxItems: 1

View File

@@ -38,6 +38,8 @@ properties:
- samsung,exynosautov920-cmu-hsi0
- samsung,exynosautov920-cmu-hsi1
- samsung,exynosautov920-cmu-hsi2
- samsung,exynosautov920-cmu-m2m
- samsung,exynosautov920-cmu-mfc
- samsung,exynosautov920-cmu-misc
- samsung,exynosautov920-cmu-peric0
- samsung,exynosautov920-cmu-peric1
@@ -226,6 +228,46 @@ allOf:
- const: embd
- const: ethernet
- if:
properties:
compatible:
contains:
const: samsung,exynosautov920-cmu-m2m
then:
properties:
clocks:
items:
- description: External reference clock (38.4 MHz)
- description: CMU_M2M NOC clock (from CMU_TOP)
- description: CMU_M2M JPEG clock (from CMU_TOP)
clock-names:
items:
- const: oscclk
- const: noc
- const: jpeg
- if:
properties:
compatible:
contains:
const: samsung,exynosautov920-cmu-mfc
then:
properties:
clocks:
items:
- description: External reference clock (38.4 MHz)
- description: CMU_MFC MFC clock (from CMU_TOP)
- description: CMU_MFC WFD clock (from CMU_TOP)
clock-names:
items:
- const: oscclk
- const: mfc
- const: wfd
required:
- compatible
- "#clock-cells"

View File

@@ -24,6 +24,15 @@ properties:
compatible:
const: google,gs101-acpm-ipc
"#clock-cells":
const: 1
description:
Clocks that are variable and index based. These clocks don't provide
an entire range of values between the limits but only discrete points
within the range. The firmware also manages the voltage scaling
appropriately with the clock scaling. The argument is the ID of the
clock contained by the firmware messages.
mboxes:
maxItems: 1
@@ -45,6 +54,7 @@ properties:
required:
- compatible
- "#clock-cells"
- mboxes
- shmem
@@ -56,6 +66,7 @@ examples:
power-management {
compatible = "google,gs101-acpm-ipc";
#clock-cells = <1>;
mboxes = <&ap2apm_mailbox>;
shmem = <&apm_sram>;

View File

@@ -10601,7 +10601,7 @@ F: Documentation/devicetree/bindings/soc/google/google,gs101-pmu-intr-gen.yaml
F: arch/arm64/boot/dts/exynos/google/
F: drivers/clk/samsung/clk-gs101.c
F: drivers/phy/samsung/phy-gs101-ufs.c
F: include/dt-bindings/clock/google,gs101.h
F: include/dt-bindings/clock/google,gs101*
K: [gG]oogle.?[tT]ensor
GPD FAN DRIVER
@@ -22761,6 +22761,7 @@ L: linux-kernel@vger.kernel.org
L: linux-samsung-soc@vger.kernel.org
S: Supported
F: Documentation/devicetree/bindings/firmware/google,gs101-acpm-ipc.yaml
F: drivers/clk/samsung/clk-acpm.c
F: drivers/firmware/samsung/exynos-acpm*
F: include/linux/firmware/samsung/exynos-acpm-protocol.h

View File

@@ -125,8 +125,7 @@ obj-$(CONFIG_ARCH_HISI) += hisilicon/
obj-y += imgtec/
obj-y += imx/
obj-y += ingenic/
obj-$(CONFIG_ARCH_K3) += keystone/
obj-$(CONFIG_ARCH_KEYSTONE) += keystone/
obj-y += keystone/
obj-y += mediatek/
obj-$(CONFIG_ARCH_MESON) += meson/
obj-y += microchip/

View File

@@ -32,7 +32,7 @@ struct owl_clk_desc {
};
static inline struct owl_clk_common *
hw_to_owl_clk_common(const struct clk_hw *hw)
hw_to_owl_clk_common(struct clk_hw *hw)
{
return container_of(hw, struct owl_clk_common, hw);
}

View File

@@ -108,7 +108,7 @@ struct owl_composite {
}, \
}
static inline struct owl_composite *hw_to_owl_comp(const struct clk_hw *hw)
static inline struct owl_composite *hw_to_owl_comp(struct clk_hw *hw)
{
struct owl_clk_common *common = hw_to_owl_clk_common(hw);

View File

@@ -49,7 +49,7 @@ struct owl_divider {
}, \
}
static inline struct owl_divider *hw_to_owl_divider(const struct clk_hw *hw)
static inline struct owl_divider *hw_to_owl_divider(struct clk_hw *hw)
{
struct owl_clk_common *common = hw_to_owl_clk_common(hw);

View File

@@ -57,7 +57,7 @@ struct owl_factor {
#define div_mask(d) ((1 << ((d)->width)) - 1)
static inline struct owl_factor *hw_to_owl_factor(const struct clk_hw *hw)
static inline struct owl_factor *hw_to_owl_factor(struct clk_hw *hw)
{
struct owl_clk_common *common = hw_to_owl_clk_common(hw);

View File

@@ -56,7 +56,7 @@ struct owl_gate {
}, \
} \
static inline struct owl_gate *hw_to_owl_gate(const struct clk_hw *hw)
static inline struct owl_gate *hw_to_owl_gate(struct clk_hw *hw)
{
struct owl_clk_common *common = hw_to_owl_clk_common(hw);

View File

@@ -44,7 +44,7 @@ struct owl_mux {
}, \
}
static inline struct owl_mux *hw_to_owl_mux(const struct clk_hw *hw)
static inline struct owl_mux *hw_to_owl_mux(struct clk_hw *hw)
{
struct owl_clk_common *common = hw_to_owl_clk_common(hw);

View File

@@ -98,7 +98,7 @@ struct owl_pll {
#define mul_mask(m) ((1 << ((m)->width)) - 1)
static inline struct owl_pll *hw_to_owl_pll(const struct clk_hw *hw)
static inline struct owl_pll *hw_to_owl_pll(struct clk_hw *hw)
{
struct owl_clk_common *common = hw_to_owl_clk_common(hw);

View File

@@ -9,6 +9,7 @@
#include <linux/regmap.h>
#include <linux/reset-controller.h>
#include <dt-bindings/clock/en7523-clk.h>
#include <dt-bindings/reset/airoha,en7523-reset.h>
#include <dt-bindings/reset/airoha,en7581-reset.h>
#define RST_NR_PER_BANK 32
@@ -299,6 +300,53 @@ static const u16 en7581_rst_ofs[] = {
REG_RST_CTRL1,
};
static const u16 en7523_rst_map[] = {
/* RST_CTRL2 */
[EN7523_XPON_PHY_RST] = 0,
[EN7523_XSI_MAC_RST] = 7,
[EN7523_XSI_PHY_RST] = 8,
[EN7523_NPU_RST] = 9,
[EN7523_I2S_RST] = 10,
[EN7523_TRNG_RST] = 11,
[EN7523_TRNG_MSTART_RST] = 12,
[EN7523_DUAL_HSI0_RST] = 13,
[EN7523_DUAL_HSI1_RST] = 14,
[EN7523_HSI_RST] = 15,
[EN7523_DUAL_HSI0_MAC_RST] = 16,
[EN7523_DUAL_HSI1_MAC_RST] = 17,
[EN7523_HSI_MAC_RST] = 18,
[EN7523_WDMA_RST] = 19,
[EN7523_WOE0_RST] = 20,
[EN7523_WOE1_RST] = 21,
[EN7523_HSDMA_RST] = 22,
[EN7523_I2C2RBUS_RST] = 23,
[EN7523_TDMA_RST] = 24,
/* RST_CTRL1 */
[EN7523_PCM1_ZSI_ISI_RST] = RST_NR_PER_BANK + 0,
[EN7523_FE_PDMA_RST] = RST_NR_PER_BANK + 1,
[EN7523_FE_QDMA_RST] = RST_NR_PER_BANK + 2,
[EN7523_PCM_SPIWP_RST] = RST_NR_PER_BANK + 4,
[EN7523_CRYPTO_RST] = RST_NR_PER_BANK + 6,
[EN7523_TIMER_RST] = RST_NR_PER_BANK + 8,
[EN7523_PCM1_RST] = RST_NR_PER_BANK + 11,
[EN7523_UART_RST] = RST_NR_PER_BANK + 12,
[EN7523_GPIO_RST] = RST_NR_PER_BANK + 13,
[EN7523_GDMA_RST] = RST_NR_PER_BANK + 14,
[EN7523_I2C_MASTER_RST] = RST_NR_PER_BANK + 16,
[EN7523_PCM2_ZSI_ISI_RST] = RST_NR_PER_BANK + 17,
[EN7523_SFC_RST] = RST_NR_PER_BANK + 18,
[EN7523_UART2_RST] = RST_NR_PER_BANK + 19,
[EN7523_GDMP_RST] = RST_NR_PER_BANK + 20,
[EN7523_FE_RST] = RST_NR_PER_BANK + 21,
[EN7523_USB_HOST_P0_RST] = RST_NR_PER_BANK + 22,
[EN7523_GSW_RST] = RST_NR_PER_BANK + 23,
[EN7523_SFC2_PCM_RST] = RST_NR_PER_BANK + 25,
[EN7523_PCIE0_RST] = RST_NR_PER_BANK + 26,
[EN7523_PCIE1_RST] = RST_NR_PER_BANK + 27,
[EN7523_PCIE_HB_RST] = RST_NR_PER_BANK + 29,
[EN7523_XPON_MAC_RST] = RST_NR_PER_BANK + 31,
};
static const u16 en7581_rst_map[] = {
/* RST_CTRL2 */
[EN7581_XPON_PHY_RST] = 0,
@@ -357,6 +405,9 @@ static const u16 en7581_rst_map[] = {
[EN7581_XPON_MAC_RST] = RST_NR_PER_BANK + 31,
};
static int en7581_reset_register(struct device *dev, void __iomem *base,
const u16 *rst_map, int nr_resets);
static u32 en7523_get_base_rate(const struct en_clk_desc *desc, u32 val)
{
if (!desc->base_bits)
@@ -552,7 +603,8 @@ static int en7523_clk_hw_init(struct platform_device *pdev,
en7523_register_clocks(&pdev->dev, clk_data, base, np_base);
return 0;
return en7581_reset_register(&pdev->dev, np_base, en7523_rst_map,
ARRAY_SIZE(en7523_rst_map));
}
static void en7581_register_clocks(struct device *dev, struct clk_hw_onecell_data *clk_data,
@@ -652,7 +704,8 @@ static const struct reset_control_ops en7581_reset_ops = {
.status = en7523_reset_status,
};
static int en7581_reset_register(struct device *dev, void __iomem *base)
static int en7581_reset_register(struct device *dev, void __iomem *base,
const u16 *rst_map, int nr_resets)
{
struct en_rst_data *rst_data;
@@ -661,10 +714,10 @@ static int en7581_reset_register(struct device *dev, void __iomem *base)
return -ENOMEM;
rst_data->bank_ofs = en7581_rst_ofs;
rst_data->idx_map = en7581_rst_map;
rst_data->idx_map = rst_map;
rst_data->base = base;
rst_data->rcdev.nr_resets = ARRAY_SIZE(en7581_rst_map);
rst_data->rcdev.nr_resets = nr_resets;
rst_data->rcdev.of_xlate = en7523_reset_xlate;
rst_data->rcdev.ops = &en7581_reset_ops;
rst_data->rcdev.of_node = dev->of_node;
@@ -698,7 +751,8 @@ static int en7581_clk_hw_init(struct platform_device *pdev,
val = readl(base + REG_NP_SCU_PCIC);
writel(val | 3, base + REG_NP_SCU_PCIC);
return en7581_reset_register(&pdev->dev, base);
return en7581_reset_register(&pdev->dev, base, en7581_rst_map,
ARRAY_SIZE(en7581_rst_map));
}
static int en7523_clk_probe(struct platform_device *pdev)

View File

@@ -496,8 +496,8 @@ static int ti_sci_scan_clocks_from_fw(struct sci_clk_provider *provider)
static int _cmp_sci_clk_list(void *priv, const struct list_head *a,
const struct list_head *b)
{
struct sci_clk *ca = container_of(a, struct sci_clk, node);
struct sci_clk *cb = container_of(b, struct sci_clk, node);
const struct sci_clk *ca = container_of(a, struct sci_clk, node);
const struct sci_clk *cb = container_of(b, struct sci_clk, node);
return _cmp_sci_clk(ca, &cb);
}

View File

@@ -129,7 +129,7 @@ static int ti_syscon_gate_clk_probe(struct platform_device *pdev)
if (IS_ERR(base))
return PTR_ERR(base);
regmap = regmap_init_mmio(dev, base, &ti_syscon_regmap_cfg);
regmap = devm_regmap_init_mmio(dev, base, &ti_syscon_regmap_cfg);
if (IS_ERR(regmap))
return dev_err_probe(dev, PTR_ERR(regmap),
"failed to get regmap\n");

View File

@@ -26,7 +26,7 @@
enum clk_ids {
/* Core Clock Outputs exported to DT */
LAST_DT_CORE_CLK = R8A779A0_CLK_OSC,
LAST_DT_CORE_CLK = R8A779A0_CLK_ZG,
/* External Input Clocks */
CLK_EXTAL,
@@ -39,6 +39,7 @@ enum clk_ids {
CLK_PLL21,
CLK_PLL30,
CLK_PLL31,
CLK_PLL4,
CLK_PLL5,
CLK_PLL1_DIV2,
CLK_PLL20_DIV2,
@@ -65,6 +66,7 @@ enum clk_ids {
#define CPG_PLL21CR 0x0838 /* PLL21 Control Register */
#define CPG_PLL30CR 0x083c /* PLL30 Control Register */
#define CPG_PLL31CR 0x0840 /* PLL31 Control Register */
#define CPG_PLL4CR 0x0844 /* PLL4 Control Register */
static const struct cpg_core_clk r8a779a0_core_clks[] __initconst = {
/* External Clock Inputs */
@@ -79,6 +81,7 @@ static const struct cpg_core_clk r8a779a0_core_clks[] __initconst = {
DEF_PLL(".pll21", CLK_PLL21, CPG_PLL21CR),
DEF_PLL(".pll30", CLK_PLL30, CPG_PLL30CR),
DEF_PLL(".pll31", CLK_PLL31, CPG_PLL31CR),
DEF_PLL(".pll4", CLK_PLL4, CPG_PLL4CR),
DEF_FIXED(".pll1_div2", CLK_PLL1_DIV2, CLK_PLL1, 2, 1),
DEF_FIXED(".pll20_div2", CLK_PLL20_DIV2, CLK_PLL20, 2, 1),
@@ -98,6 +101,7 @@ static const struct cpg_core_clk r8a779a0_core_clks[] __initconst = {
/* Core Clock Outputs */
DEF_GEN4_Z("z0", R8A779A0_CLK_Z0, CLK_TYPE_GEN4_Z, CLK_PLL20, 2, 0),
DEF_GEN4_Z("z1", R8A779A0_CLK_Z1, CLK_TYPE_GEN4_Z, CLK_PLL21, 2, 8),
DEF_GEN4_Z("zg", R8A779A0_CLK_ZG, CLK_TYPE_GEN4_Z, CLK_PLL4, 2, 88),
DEF_FIXED("zx", R8A779A0_CLK_ZX, CLK_PLL20_DIV2, 2, 1),
DEF_FIXED("s1d1", R8A779A0_CLK_S1D1, CLK_S1, 1, 1),
DEF_FIXED("s1d2", R8A779A0_CLK_S1D2, CLK_S1, 2, 1),
@@ -138,6 +142,7 @@ static const struct cpg_core_clk r8a779a0_core_clks[] __initconst = {
};
static const struct mssr_mod_clk r8a779a0_mod_clks[] __initconst = {
DEF_MOD("3dge", 0, R8A779A0_CLK_ZG),
DEF_MOD("isp0", 16, R8A779A0_CLK_S1D1),
DEF_MOD("isp1", 17, R8A779A0_CLK_S1D1),
DEF_MOD("isp2", 18, R8A779A0_CLK_S1D1),

View File

@@ -1333,9 +1333,9 @@ static int __init r9a06g032_clocks_probe(struct platform_device *pdev)
if (IS_ERR(mclk))
return PTR_ERR(mclk);
clocks->reg = of_iomap(np, 0);
if (WARN_ON(!clocks->reg))
return -ENOMEM;
clocks->reg = devm_of_iomap(dev, np, 0, NULL);
if (IS_ERR(clocks->reg))
return PTR_ERR(clocks->reg);
r9a06g032_init_h2mode(clocks);

View File

@@ -16,7 +16,7 @@
enum clk_ids {
/* Core Clock Outputs exported to DT */
LAST_DT_CORE_CLK = R9A09G047_USB3_0_CLKCORE,
LAST_DT_CORE_CLK = R9A09G047_USB2_0_CLK_CORE1,
/* External Input Clocks */
CLK_AUDIO_EXTAL,
@@ -44,6 +44,9 @@ enum clk_ids {
CLK_PLLCLN_DIV8,
CLK_PLLCLN_DIV16,
CLK_PLLCLN_DIV20,
CLK_PLLCLN_DIV64,
CLK_PLLCLN_DIV256,
CLK_PLLCLN_DIV1024,
CLK_PLLDTY_ACPU,
CLK_PLLDTY_ACPU_DIV2,
CLK_PLLDTY_ACPU_DIV4,
@@ -142,6 +145,9 @@ static const struct cpg_core_clk r9a09g047_core_clks[] __initconst = {
DEF_FIXED(".pllcln_div8", CLK_PLLCLN_DIV8, CLK_PLLCLN, 1, 8),
DEF_FIXED(".pllcln_div16", CLK_PLLCLN_DIV16, CLK_PLLCLN, 1, 16),
DEF_FIXED(".pllcln_div20", CLK_PLLCLN_DIV20, CLK_PLLCLN, 1, 20),
DEF_FIXED(".pllcln_div64", CLK_PLLCLN_DIV64, CLK_PLLCLN, 1, 64),
DEF_FIXED(".pllcln_div256", CLK_PLLCLN_DIV256, CLK_PLLCLN, 1, 256),
DEF_FIXED(".pllcln_div1024", CLK_PLLCLN_DIV1024, CLK_PLLCLN, 1, 1024),
DEF_DDIV(".plldty_acpu", CLK_PLLDTY_ACPU, CLK_PLLDTY, CDDIV0_DIVCTL2, dtable_2_64),
DEF_FIXED(".plldty_acpu_div2", CLK_PLLDTY_ACPU_DIV2, CLK_PLLDTY_ACPU, 1, 2),
@@ -177,6 +183,8 @@ static const struct cpg_core_clk r9a09g047_core_clks[] __initconst = {
CDDIV1_DIVCTL3, dtable_1_8),
DEF_FIXED("iotop_0_shclk", R9A09G047_IOTOP_0_SHCLK, CLK_PLLCM33_DIV16, 1, 1),
DEF_FIXED("spi_clk_spi", R9A09G047_SPI_CLK_SPI, CLK_PLLCM33_XSPI, 1, 2),
DEF_FIXED("usb2_0_clk_core0", R9A09G047_USB2_0_CLK_CORE0, CLK_QEXTAL, 1, 1),
DEF_FIXED("usb2_0_clk_core1", R9A09G047_USB2_0_CLK_CORE1, CLK_QEXTAL, 1, 1),
DEF_FIXED("gbeth_0_clk_ptp_ref_i", R9A09G047_GBETH_0_CLK_PTP_REF_I,
CLK_PLLETH_DIV_125_FIX, 1, 1),
DEF_FIXED("gbeth_1_clk_ptp_ref_i", R9A09G047_GBETH_1_CLK_PTP_REF_I,
@@ -216,6 +224,106 @@ static const struct rzv2h_mod_clk r9a09g047_mod_clks[] __initconst = {
BUS_MSTOP(5, BIT(13))),
DEF_MOD("wdt_3_clk_loco", CLK_QEXTAL, 5, 2, 2, 18,
BUS_MSTOP(5, BIT(13))),
DEF_MOD("rsci0_pclk", CLK_PLLCLN_DIV16, 5, 13, 2, 29,
BUS_MSTOP(11, BIT(3))),
DEF_MOD("rsci0_tclk", CLK_PLLCLN_DIV16, 5, 14, 2, 30,
BUS_MSTOP(11, BIT(3))),
DEF_MOD("rsci0_ps_ps3_n", CLK_PLLCLN_DIV1024, 5, 15, 2, 31,
BUS_MSTOP(11, BIT(3))),
DEF_MOD("rsci0_ps_ps2_n", CLK_PLLCLN_DIV256, 6, 0, 3, 0,
BUS_MSTOP(11, BIT(3))),
DEF_MOD("rsci0_ps_ps1_n", CLK_PLLCLN_DIV64, 6, 1, 3, 1,
BUS_MSTOP(11, BIT(3))),
DEF_MOD("rsci1_pclk", CLK_PLLCLN_DIV16, 6, 2, 3, 2,
BUS_MSTOP(11, BIT(4))),
DEF_MOD("rsci1_tclk", CLK_PLLCLN_DIV16, 6, 3, 3, 3,
BUS_MSTOP(11, BIT(4))),
DEF_MOD("rsci1_ps_ps3_n", CLK_PLLCLN_DIV1024, 6, 4, 3, 4,
BUS_MSTOP(11, BIT(4))),
DEF_MOD("rsci1_ps_ps2_n", CLK_PLLCLN_DIV256, 6, 5, 3, 5,
BUS_MSTOP(11, BIT(4))),
DEF_MOD("rsci1_ps_ps1_n", CLK_PLLCLN_DIV64, 6, 6, 3, 6,
BUS_MSTOP(11, BIT(4))),
DEF_MOD("rsci2_pclk", CLK_PLLCLN_DIV16, 6, 7, 3, 7,
BUS_MSTOP(11, BIT(5))),
DEF_MOD("rsci2_tclk", CLK_PLLCLN_DIV16, 6, 8, 3, 8,
BUS_MSTOP(11, BIT(5))),
DEF_MOD("rsci2_ps_ps3_n", CLK_PLLCLN_DIV1024, 6, 9, 3, 9,
BUS_MSTOP(11, BIT(5))),
DEF_MOD("rsci2_ps_ps2_n", CLK_PLLCLN_DIV256, 6, 10, 3, 10,
BUS_MSTOP(11, BIT(5))),
DEF_MOD("rsci2_ps_ps1_n", CLK_PLLCLN_DIV64, 6, 11, 3, 11,
BUS_MSTOP(11, BIT(5))),
DEF_MOD("rsci3_pclk", CLK_PLLCLN_DIV16, 6, 12, 3, 12,
BUS_MSTOP(11, BIT(6))),
DEF_MOD("rsci3_tclk", CLK_PLLCLN_DIV16, 6, 13, 3, 13,
BUS_MSTOP(11, BIT(6))),
DEF_MOD("rsci3_ps_ps3_n", CLK_PLLCLN_DIV1024, 6, 14, 3, 14,
BUS_MSTOP(11, BIT(6))),
DEF_MOD("rsci3_ps_ps2_n", CLK_PLLCLN_DIV256, 6, 15, 3, 15,
BUS_MSTOP(11, BIT(6))),
DEF_MOD("rsci3_ps_ps1_n", CLK_PLLCLN_DIV64, 7, 0, 3, 16,
BUS_MSTOP(11, BIT(6))),
DEF_MOD("rsci4_pclk", CLK_PLLCLN_DIV16, 7, 1, 3, 17,
BUS_MSTOP(11, BIT(7))),
DEF_MOD("rsci4_tclk", CLK_PLLCLN_DIV16, 7, 2, 3, 18,
BUS_MSTOP(11, BIT(7))),
DEF_MOD("rsci4_ps_ps3_n", CLK_PLLCLN_DIV1024, 7, 3, 3, 19,
BUS_MSTOP(11, BIT(7))),
DEF_MOD("rsci4_ps_ps2_n", CLK_PLLCLN_DIV256, 7, 4, 3, 20,
BUS_MSTOP(11, BIT(7))),
DEF_MOD("rsci4_ps_ps1_n", CLK_PLLCLN_DIV64, 7, 5, 3, 21,
BUS_MSTOP(11, BIT(7))),
DEF_MOD("rsci5_pclk", CLK_PLLCLN_DIV16, 7, 6, 3, 22,
BUS_MSTOP(11, BIT(8))),
DEF_MOD("rsci5_tclk", CLK_PLLCLN_DIV16, 7, 7, 3, 23,
BUS_MSTOP(11, BIT(8))),
DEF_MOD("rsci5_ps_ps3_n", CLK_PLLCLN_DIV1024, 7, 8, 3, 24,
BUS_MSTOP(11, BIT(8))),
DEF_MOD("rsci5_ps_ps2_n", CLK_PLLCLN_DIV256, 7, 9, 3, 25,
BUS_MSTOP(11, BIT(8))),
DEF_MOD("rsci5_ps_ps1_n", CLK_PLLCLN_DIV64, 7, 10, 3, 26,
BUS_MSTOP(11, BIT(8))),
DEF_MOD("rsci6_pclk", CLK_PLLCLN_DIV16, 7, 11, 3, 27,
BUS_MSTOP(11, BIT(9))),
DEF_MOD("rsci6_tclk", CLK_PLLCLN_DIV16, 7, 12, 3, 28,
BUS_MSTOP(11, BIT(9))),
DEF_MOD("rsci6_ps_ps3_n", CLK_PLLCLN_DIV1024, 7, 13, 3, 29,
BUS_MSTOP(11, BIT(9))),
DEF_MOD("rsci6_ps_ps2_n", CLK_PLLCLN_DIV256, 7, 14, 3, 30,
BUS_MSTOP(11, BIT(9))),
DEF_MOD("rsci6_ps_ps1_n", CLK_PLLCLN_DIV64, 7, 15, 3, 31,
BUS_MSTOP(11, BIT(9))),
DEF_MOD("rsci7_pclk", CLK_PLLCLN_DIV16, 8, 0, 4, 0,
BUS_MSTOP(11, BIT(10))),
DEF_MOD("rsci7_tclk", CLK_PLLCLN_DIV16, 8, 1, 4, 1,
BUS_MSTOP(11, BIT(10))),
DEF_MOD("rsci7_ps_ps3_n", CLK_PLLCLN_DIV1024, 8, 2, 4, 2,
BUS_MSTOP(11, BIT(10))),
DEF_MOD("rsci7_ps_ps2_n", CLK_PLLCLN_DIV256, 8, 3, 4, 3,
BUS_MSTOP(11, BIT(10))),
DEF_MOD("rsci7_ps_ps1_n", CLK_PLLCLN_DIV64, 8, 4, 4, 4,
BUS_MSTOP(11, BIT(10))),
DEF_MOD("rsci8_pclk", CLK_PLLCLN_DIV16, 8, 5, 4, 5,
BUS_MSTOP(11, BIT(11))),
DEF_MOD("rsci8_tclk", CLK_PLLCLN_DIV16, 8, 6, 4, 6,
BUS_MSTOP(11, BIT(11))),
DEF_MOD("rsci8_ps_ps3_n", CLK_PLLCLN_DIV1024, 8, 7, 4, 7,
BUS_MSTOP(11, BIT(11))),
DEF_MOD("rsci8_ps_ps2_n", CLK_PLLCLN_DIV256, 8, 8, 4, 8,
BUS_MSTOP(11, BIT(11))),
DEF_MOD("rsci8_ps_ps1_n", CLK_PLLCLN_DIV64, 8, 9, 4, 9,
BUS_MSTOP(11, BIT(11))),
DEF_MOD("rsci9_pclk", CLK_PLLCLN_DIV16, 8, 10, 4, 10,
BUS_MSTOP(11, BIT(12))),
DEF_MOD("rsci9_tclk", CLK_PLLCLN_DIV16, 8, 11, 4, 11,
BUS_MSTOP(11, BIT(12))),
DEF_MOD("rsci9_ps_ps3_n", CLK_PLLCLN_DIV1024, 8, 12, 4, 12,
BUS_MSTOP(11, BIT(12))),
DEF_MOD("rsci9_ps_ps2_n", CLK_PLLCLN_DIV256, 8, 13, 4, 13,
BUS_MSTOP(11, BIT(12))),
DEF_MOD("rsci9_ps_ps1_n", CLK_PLLCLN_DIV64, 8, 14, 4, 14,
BUS_MSTOP(11, BIT(12))),
DEF_MOD("scif_0_clk_pck", CLK_PLLCM33_DIV16, 8, 15, 4, 15,
BUS_MSTOP(3, BIT(14))),
DEF_MOD("i3c_0_pclkrw", CLK_PLLCLN_DIV16, 9, 0, 4, 16,
@@ -282,6 +390,16 @@ static const struct rzv2h_mod_clk r9a09g047_mod_clks[] __initconst = {
BUS_MSTOP(7, BIT(12))),
DEF_MOD("usb3_0_pclk_usbtst", CLK_PLLDTY_ACPU_DIV4, 11, 0, 5, 16,
BUS_MSTOP(7, BIT(14))),
DEF_MOD("usb2_0_u2h0_hclk", CLK_PLLDTY_DIV8, 11, 3, 5, 19,
BUS_MSTOP(7, BIT(7))),
DEF_MOD("usb2_0_u2h1_hclk", CLK_PLLDTY_DIV8, 11, 4, 5, 20,
BUS_MSTOP(7, BIT(8))),
DEF_MOD("usb2_0_u2p_exr_cpuclk", CLK_PLLDTY_ACPU_DIV4, 11, 5, 5, 21,
BUS_MSTOP(7, BIT(9))),
DEF_MOD("usb2_0_pclk_usbtst0", CLK_PLLDTY_ACPU_DIV4, 11, 6, 5, 22,
BUS_MSTOP(7, BIT(10))),
DEF_MOD("usb2_0_pclk_usbtst1", CLK_PLLDTY_ACPU_DIV4, 11, 7, 5, 23,
BUS_MSTOP(7, BIT(11))),
DEF_MOD_MUX_EXTERNAL("gbeth_0_clk_tx_i", CLK_SMUX2_GBE0_TXCLK, 11, 8, 5, 24,
BUS_MSTOP(8, BIT(5)), 1),
DEF_MOD_MUX_EXTERNAL("gbeth_0_clk_rx_i", CLK_SMUX2_GBE0_RXCLK, 11, 9, 5, 25,
@@ -339,6 +457,26 @@ static const struct rzv2h_reset r9a09g047_resets[] __initconst = {
DEF_RST(7, 6, 3, 7), /* WDT_1_RESET */
DEF_RST(7, 7, 3, 8), /* WDT_2_RESET */
DEF_RST(7, 8, 3, 9), /* WDT_3_RESET */
DEF_RST(8, 1, 3, 18), /* RSCI0_PRESETN */
DEF_RST(8, 2, 3, 19), /* RSCI0_TRESETN */
DEF_RST(8, 3, 3, 20), /* RSCI1_PRESETN */
DEF_RST(8, 4, 3, 21), /* RSCI1_TRESETN */
DEF_RST(8, 5, 3, 22), /* RSCI2_PRESETN */
DEF_RST(8, 6, 3, 23), /* RSCI2_TRESETN */
DEF_RST(8, 7, 3, 24), /* RSCI3_PRESETN */
DEF_RST(8, 8, 3, 25), /* RSCI3_TRESETN */
DEF_RST(8, 9, 3, 26), /* RSCI4_PRESETN */
DEF_RST(8, 10, 3, 27), /* RSCI4_TRESETN */
DEF_RST(8, 11, 3, 28), /* RSCI5_PRESETN */
DEF_RST(8, 12, 3, 29), /* RSCI5_TRESETN */
DEF_RST(8, 13, 3, 30), /* RSCI6_PRESETN */
DEF_RST(8, 14, 3, 31), /* RSCI6_TRESETN */
DEF_RST(8, 15, 4, 0), /* RSCI7_PRESETN */
DEF_RST(9, 0, 4, 1), /* RSCI7_TRESETN */
DEF_RST(9, 1, 4, 2), /* RSCI8_PRESETN */
DEF_RST(9, 2, 4, 3), /* RSCI8_TRESETN */
DEF_RST(9, 3, 4, 4), /* RSCI9_PRESETN */
DEF_RST(9, 4, 4, 5), /* RSCI9_TRESETN */
DEF_RST(9, 5, 4, 6), /* SCIF_0_RST_SYSTEM_N */
DEF_RST(9, 6, 4, 7), /* I3C_0_PRESETN */
DEF_RST(9, 7, 4, 8), /* I3C_0_TRESETN */
@@ -359,6 +497,10 @@ static const struct rzv2h_reset r9a09g047_resets[] __initconst = {
DEF_RST(10, 8, 4, 25), /* SDHI_1_IXRST */
DEF_RST(10, 9, 4, 26), /* SDHI_2_IXRST */
DEF_RST(10, 10, 4, 27), /* USB3_0_ARESETN */
DEF_RST(10, 12, 4, 29), /* USB2_0_U2H0_HRESETN */
DEF_RST(10, 13, 4, 30), /* USB2_0_U2H1_HRESETN */
DEF_RST(10, 14, 4, 31), /* USB2_0_U2P_EXL_SYSRST */
DEF_RST(10, 15, 5, 0), /* USB2_0_PRESETN */
DEF_RST(11, 0, 5, 1), /* GBETH_0_ARESETN_I */
DEF_RST(11, 1, 5, 2), /* GBETH_1_ARESETN_I */
DEF_RST(12, 5, 5, 22), /* CRU_0_PRESETN */

View File

@@ -6,6 +6,7 @@
*/
#include <linux/clk-provider.h>
#include <linux/clk/renesas.h>
#include <linux/device.h>
#include <linux/init.h>
#include <linux/kernel.h>
@@ -16,7 +17,7 @@
enum clk_ids {
/* Core Clock Outputs exported to DT */
LAST_DT_CORE_CLK = R9A09G056_SPI_CLK_SPI,
LAST_DT_CORE_CLK = R9A09G056_USB3_0_CLKCORE,
/* External Input Clocks */
CLK_AUDIO_EXTAL,
@@ -28,7 +29,9 @@ enum clk_ids {
CLK_PLLCLN,
CLK_PLLDTY,
CLK_PLLCA55,
CLK_PLLVDO,
CLK_PLLETH,
CLK_PLLDSI,
CLK_PLLGPU,
/* Internal Core Clocks */
@@ -47,6 +50,10 @@ enum clk_ids {
CLK_PLLDTY_ACPU_DIV2,
CLK_PLLDTY_ACPU_DIV4,
CLK_PLLDTY_DIV8,
CLK_PLLDTY_DIV16,
CLK_PLLVDO_CRU0,
CLK_PLLVDO_CRU1,
CLK_PLLVDO_ISP,
CLK_PLLETH_DIV_250_FIX,
CLK_PLLETH_DIV_125_FIX,
CLK_CSDIV_PLLETH_GBE0,
@@ -55,6 +62,9 @@ enum clk_ids {
CLK_SMUX2_GBE0_RXCLK,
CLK_SMUX2_GBE1_TXCLK,
CLK_SMUX2_GBE1_RXCLK,
CLK_CDIV4_PLLETH_LPCLK,
CLK_PLLETH_LPCLK_GEAR,
CLK_PLLDSI_GEAR,
CLK_PLLGPU_GEAR,
/* Module Clocks */
@@ -69,6 +79,12 @@ static const struct clk_div_table dtable_1_8[] = {
{0, 0},
};
static const struct clk_div_table dtable_2_4[] = {
{0, 2},
{1, 4},
{0, 0},
};
static const struct clk_div_table dtable_2_16[] = {
{0, 2},
{1, 4},
@@ -77,6 +93,26 @@ static const struct clk_div_table dtable_2_16[] = {
{0, 0},
};
static const struct clk_div_table dtable_2_32[] = {
{0, 2},
{1, 4},
{2, 6},
{3, 8},
{4, 10},
{5, 12},
{6, 14},
{7, 16},
{8, 18},
{9, 20},
{10, 22},
{11, 24},
{12, 26},
{13, 28},
{14, 30},
{15, 32},
{0, 0},
};
static const struct clk_div_table dtable_2_64[] = {
{0, 2},
{1, 4},
@@ -93,6 +129,17 @@ static const struct clk_div_table dtable_2_100[] = {
{0, 0},
};
static const struct clk_div_table dtable_16_128[] = {
{0, 16},
{1, 32},
{2, 64},
{3, 128},
{0, 0},
};
RZV2H_CPG_PLL_DSI_LIMITS(rzv2n_cpg_pll_dsi_limits);
#define PLLDSI PLL_PACK_LIMITS(0xc0, 1, 0, &rzv2n_cpg_pll_dsi_limits)
/* Mux clock tables */
static const char * const smux2_gbe0_rxclk[] = { ".plleth_gbe0", "et0_rxclk" };
static const char * const smux2_gbe0_txclk[] = { ".plleth_gbe0", "et0_txclk" };
@@ -112,7 +159,9 @@ static const struct cpg_core_clk r9a09g056_core_clks[] __initconst = {
DEF_FIXED(".pllcln", CLK_PLLCLN, CLK_QEXTAL, 200, 3),
DEF_FIXED(".plldty", CLK_PLLDTY, CLK_QEXTAL, 200, 3),
DEF_PLL(".pllca55", CLK_PLLCA55, CLK_QEXTAL, PLLCA55),
DEF_FIXED(".pllvdo", CLK_PLLVDO, CLK_QEXTAL, 105, 2),
DEF_FIXED(".plleth", CLK_PLLETH, CLK_QEXTAL, 125, 3),
DEF_PLLDSI(".plldsi", CLK_PLLDSI, CLK_QEXTAL, PLLDSI),
DEF_PLL(".pllgpu", CLK_PLLGPU, CLK_QEXTAL, PLLGPU),
/* Internal Core Clocks */
@@ -134,6 +183,11 @@ static const struct cpg_core_clk r9a09g056_core_clks[] __initconst = {
DEF_FIXED(".plldty_acpu_div2", CLK_PLLDTY_ACPU_DIV2, CLK_PLLDTY_ACPU, 1, 2),
DEF_FIXED(".plldty_acpu_div4", CLK_PLLDTY_ACPU_DIV4, CLK_PLLDTY_ACPU, 1, 4),
DEF_FIXED(".plldty_div8", CLK_PLLDTY_DIV8, CLK_PLLDTY, 1, 8),
DEF_FIXED(".plldty_div16", CLK_PLLDTY_DIV16, CLK_PLLDTY, 1, 16),
DEF_DDIV(".pllvdo_cru0", CLK_PLLVDO_CRU0, CLK_PLLVDO, CDDIV3_DIVCTL3, dtable_2_4),
DEF_DDIV(".pllvdo_cru1", CLK_PLLVDO_CRU1, CLK_PLLVDO, CDDIV4_DIVCTL0, dtable_2_4),
DEF_DDIV(".pllvdo_isp", CLK_PLLVDO_ISP, CLK_PLLVDO, CDDIV2_DIVCTL3, dtable_2_64),
DEF_FIXED(".plleth_250_fix", CLK_PLLETH_DIV_250_FIX, CLK_PLLETH, 1, 4),
DEF_FIXED(".plleth_125_fix", CLK_PLLETH_DIV_125_FIX, CLK_PLLETH_DIV_250_FIX, 1, 2),
@@ -145,6 +199,12 @@ static const struct cpg_core_clk r9a09g056_core_clks[] __initconst = {
DEF_SMUX(".smux2_gbe0_rxclk", CLK_SMUX2_GBE0_RXCLK, SSEL0_SELCTL3, smux2_gbe0_rxclk),
DEF_SMUX(".smux2_gbe1_txclk", CLK_SMUX2_GBE1_TXCLK, SSEL1_SELCTL0, smux2_gbe1_txclk),
DEF_SMUX(".smux2_gbe1_rxclk", CLK_SMUX2_GBE1_RXCLK, SSEL1_SELCTL1, smux2_gbe1_rxclk),
DEF_FIXED(".cdiv4_plleth_lpclk", CLK_CDIV4_PLLETH_LPCLK, CLK_PLLETH, 1, 4),
DEF_CSDIV(".plleth_lpclk_gear", CLK_PLLETH_LPCLK_GEAR, CLK_CDIV4_PLLETH_LPCLK,
CSDIV0_DIVCTL2, dtable_16_128),
DEF_PLLDSI_DIV(".plldsi_gear", CLK_PLLDSI_GEAR, CLK_PLLDSI,
CSDIV1_DIVCTL2, dtable_2_32),
DEF_DDIV(".pllgpu_gear", CLK_PLLGPU_GEAR, CLK_PLLGPU, CDDIV3_DIVCTL1, dtable_2_64),
@@ -166,6 +226,8 @@ static const struct cpg_core_clk r9a09g056_core_clks[] __initconst = {
CLK_PLLETH_DIV_125_FIX, 1, 1),
DEF_FIXED_MOD_STATUS("spi_clk_spi", R9A09G056_SPI_CLK_SPI, CLK_PLLCM33_XSPI, 1, 2,
FIXED_MOD_CONF_XSPI),
DEF_FIXED("usb3_0_ref_alt_clk_p", R9A09G056_USB3_0_REF_ALT_CLK_P, CLK_QEXTAL, 1, 1),
DEF_FIXED("usb3_0_core_clk", R9A09G056_USB3_0_CLKCORE, CLK_QEXTAL, 1, 1),
};
static const struct rzv2h_mod_clk r9a09g056_mod_clks[] __initconst = {
@@ -259,6 +321,10 @@ static const struct rzv2h_mod_clk r9a09g056_mod_clks[] __initconst = {
BUS_MSTOP(8, BIT(4))),
DEF_MOD("sdhi_2_aclk", CLK_PLLDTY_ACPU_DIV4, 10, 14, 5, 14,
BUS_MSTOP(8, BIT(4))),
DEF_MOD("usb3_0_aclk", CLK_PLLDTY_DIV8, 10, 15, 5, 15,
BUS_MSTOP(7, BIT(12))),
DEF_MOD("usb3_0_pclk_usbtst", CLK_PLLDTY_ACPU_DIV4, 11, 0, 5, 16,
BUS_MSTOP(7, BIT(14))),
DEF_MOD("usb2_0_u2h0_hclk", CLK_PLLDTY_DIV8, 11, 3, 5, 19,
BUS_MSTOP(7, BIT(7))),
DEF_MOD("usb2_0_u2p_exr_cpuclk", CLK_PLLDTY_ACPU_DIV4, 11, 5, 5, 21,
@@ -289,6 +355,42 @@ static const struct rzv2h_mod_clk r9a09g056_mod_clks[] __initconst = {
BUS_MSTOP(8, BIT(6))),
DEF_MOD("gbeth_1_aclk_i", CLK_PLLDTY_DIV8, 12, 3, 6, 3,
BUS_MSTOP(8, BIT(6))),
DEF_MOD("cru_0_aclk", CLK_PLLDTY_ACPU_DIV2, 13, 2, 6, 18,
BUS_MSTOP(9, BIT(4))),
DEF_MOD_NO_PM("cru_0_vclk", CLK_PLLVDO_CRU0, 13, 3, 6, 19,
BUS_MSTOP(9, BIT(4))),
DEF_MOD("cru_0_pclk", CLK_PLLDTY_DIV16, 13, 4, 6, 20,
BUS_MSTOP(9, BIT(4))),
DEF_MOD("cru_1_aclk", CLK_PLLDTY_ACPU_DIV2, 13, 5, 6, 21,
BUS_MSTOP(9, BIT(5))),
DEF_MOD_NO_PM("cru_1_vclk", CLK_PLLVDO_CRU1, 13, 6, 6, 22,
BUS_MSTOP(9, BIT(5))),
DEF_MOD("cru_1_pclk", CLK_PLLDTY_DIV16, 13, 7, 6, 23,
BUS_MSTOP(9, BIT(5))),
DEF_MOD("isp_0_reg_aclk", CLK_PLLDTY_ACPU_DIV2, 14, 2, 7, 2,
BUS_MSTOP(9, BIT(8))),
DEF_MOD("isp_0_pclk", CLK_PLLDTY_DIV16, 14, 3, 7, 3,
BUS_MSTOP(9, BIT(8))),
DEF_MOD("isp_0_vin_aclk", CLK_PLLDTY_ACPU_DIV2, 14, 4, 7, 4,
BUS_MSTOP(9, BIT(9))),
DEF_MOD("isp_0_isp_sclk", CLK_PLLVDO_ISP, 14, 5, 7, 5,
BUS_MSTOP(9, BIT(9))),
DEF_MOD("dsi_0_pclk", CLK_PLLDTY_DIV16, 14, 8, 7, 8,
BUS_MSTOP(9, BIT(14) | BIT(15))),
DEF_MOD("dsi_0_aclk", CLK_PLLDTY_ACPU_DIV2, 14, 9, 7, 9,
BUS_MSTOP(9, BIT(14) | BIT(15))),
DEF_MOD("dsi_0_vclk1", CLK_PLLDSI_GEAR, 14, 10, 7, 10,
BUS_MSTOP(9, BIT(14) | BIT(15))),
DEF_MOD("dsi_0_lpclk", CLK_PLLETH_LPCLK_GEAR, 14, 11, 7, 11,
BUS_MSTOP(9, BIT(14) | BIT(15))),
DEF_MOD("dsi_0_pllref_clk", CLK_QEXTAL, 14, 12, 7, 12,
BUS_MSTOP(9, BIT(14) | BIT(15))),
DEF_MOD("lcdc_0_clk_a", CLK_PLLDTY_ACPU_DIV2, 14, 13, 7, 13,
BUS_MSTOP(10, BIT(1) | BIT(2) | BIT(3))),
DEF_MOD("lcdc_0_clk_p", CLK_PLLDTY_DIV16, 14, 14, 7, 14,
BUS_MSTOP(10, BIT(1) | BIT(2) | BIT(3))),
DEF_MOD("lcdc_0_clk_d", CLK_PLLDSI_GEAR, 14, 15, 7, 15,
BUS_MSTOP(10, BIT(1) | BIT(2) | BIT(3))),
DEF_MOD("gpu_0_clk", CLK_PLLGPU_GEAR, 15, 0, 7, 16,
BUS_MSTOP(3, BIT(4))),
DEF_MOD("gpu_0_axi_clk", CLK_PLLDTY_ACPU_DIV2, 15, 1, 7, 17,
@@ -330,11 +432,25 @@ static const struct rzv2h_reset r9a09g056_resets[] __initconst = {
DEF_RST(10, 7, 4, 24), /* SDHI_0_IXRST */
DEF_RST(10, 8, 4, 25), /* SDHI_1_IXRST */
DEF_RST(10, 9, 4, 26), /* SDHI_2_IXRST */
DEF_RST(10, 10, 4, 27), /* USB3_0_ARESETN */
DEF_RST(10, 12, 4, 29), /* USB2_0_U2H0_HRESETN */
DEF_RST(10, 14, 4, 31), /* USB2_0_U2P_EXL_SYSRST */
DEF_RST(10, 15, 5, 0), /* USB2_0_PRESETN */
DEF_RST(11, 0, 5, 1), /* GBETH_0_ARESETN_I */
DEF_RST(11, 1, 5, 2), /* GBETH_1_ARESETN_I */
DEF_RST(12, 5, 5, 22), /* CRU_0_PRESETN */
DEF_RST(12, 6, 5, 23), /* CRU_0_ARESETN */
DEF_RST(12, 7, 5, 24), /* CRU_0_S_RESETN */
DEF_RST(12, 8, 5, 25), /* CRU_1_PRESETN */
DEF_RST(12, 9, 5, 26), /* CRU_1_ARESETN */
DEF_RST(12, 10, 5, 27), /* CRU_1_S_RESETN */
DEF_RST(13, 1, 6, 2), /* ISP_0_VIN_ARESETN */
DEF_RST(13, 2, 6, 3), /* ISP_0_REG_ARESETN */
DEF_RST(13, 3, 6, 4), /* ISP_0_ISP_SRESETN */
DEF_RST(13, 4, 6, 5), /* ISP_0_PRESETN */
DEF_RST(13, 7, 6, 8), /* DSI_0_PRESETN */
DEF_RST(13, 8, 6, 9), /* DSI_0_ARESETN */
DEF_RST(13, 12, 6, 13), /* LCDC_0_RESET_N */
DEF_RST(13, 13, 6, 14), /* GPU_0_RESETN */
DEF_RST(13, 14, 6, 15), /* GPU_0_AXI_RESETN */
DEF_RST(13, 15, 6, 16), /* GPU_0_ACE_RESETN */

View File

@@ -6,6 +6,7 @@
*/
#include <linux/clk-provider.h>
#include <linux/clk/renesas.h>
#include <linux/device.h>
#include <linux/init.h>
#include <linux/kernel.h>
@@ -16,7 +17,7 @@
enum clk_ids {
/* Core Clock Outputs exported to DT */
LAST_DT_CORE_CLK = R9A09G057_SPI_CLK_SPI,
LAST_DT_CORE_CLK = R9A09G057_USB3_1_CLKCORE,
/* External Input Clocks */
CLK_AUDIO_EXTAL,
@@ -30,6 +31,7 @@ enum clk_ids {
CLK_PLLCA55,
CLK_PLLVDO,
CLK_PLLETH,
CLK_PLLDSI,
CLK_PLLGPU,
/* Internal Core Clocks */
@@ -55,6 +57,7 @@ enum clk_ids {
CLK_PLLVDO_CRU1,
CLK_PLLVDO_CRU2,
CLK_PLLVDO_CRU3,
CLK_PLLVDO_ISP,
CLK_PLLETH_DIV_250_FIX,
CLK_PLLETH_DIV_125_FIX,
CLK_CSDIV_PLLETH_GBE0,
@@ -63,6 +66,9 @@ enum clk_ids {
CLK_SMUX2_GBE0_RXCLK,
CLK_SMUX2_GBE1_TXCLK,
CLK_SMUX2_GBE1_RXCLK,
CLK_CDIV4_PLLETH_LPCLK,
CLK_PLLETH_LPCLK_GEAR,
CLK_PLLDSI_GEAR,
CLK_PLLGPU_GEAR,
/* Module Clocks */
@@ -91,6 +97,26 @@ static const struct clk_div_table dtable_2_16[] = {
{0, 0},
};
static const struct clk_div_table dtable_2_32[] = {
{0, 2},
{1, 4},
{2, 6},
{3, 8},
{4, 10},
{5, 12},
{6, 14},
{7, 16},
{8, 18},
{9, 20},
{10, 22},
{11, 24},
{12, 26},
{13, 28},
{14, 30},
{15, 32},
{0, 0},
};
static const struct clk_div_table dtable_2_64[] = {
{0, 2},
{1, 4},
@@ -107,6 +133,17 @@ static const struct clk_div_table dtable_2_100[] = {
{0, 0},
};
static const struct clk_div_table dtable_16_128[] = {
{0, 16},
{1, 32},
{2, 64},
{3, 128},
{0, 0},
};
RZV2H_CPG_PLL_DSI_LIMITS(rzv2h_cpg_pll_dsi_limits);
#define PLLDSI PLL_PACK_LIMITS(0xc0, 1, 0, &rzv2h_cpg_pll_dsi_limits)
/* Mux clock tables */
static const char * const smux2_gbe0_rxclk[] = { ".plleth_gbe0", "et0_rxclk" };
static const char * const smux2_gbe0_txclk[] = { ".plleth_gbe0", "et0_txclk" };
@@ -128,6 +165,7 @@ static const struct cpg_core_clk r9a09g057_core_clks[] __initconst = {
DEF_PLL(".pllca55", CLK_PLLCA55, CLK_QEXTAL, PLLCA55),
DEF_FIXED(".pllvdo", CLK_PLLVDO, CLK_QEXTAL, 105, 2),
DEF_FIXED(".plleth", CLK_PLLETH, CLK_QEXTAL, 125, 3),
DEF_PLLDSI(".plldsi", CLK_PLLDSI, CLK_QEXTAL, PLLDSI),
DEF_PLL(".pllgpu", CLK_PLLGPU, CLK_QEXTAL, PLLGPU),
/* Internal Core Clocks */
@@ -157,6 +195,7 @@ static const struct cpg_core_clk r9a09g057_core_clks[] __initconst = {
DEF_DDIV(".pllvdo_cru1", CLK_PLLVDO_CRU1, CLK_PLLVDO, CDDIV4_DIVCTL0, dtable_2_4),
DEF_DDIV(".pllvdo_cru2", CLK_PLLVDO_CRU2, CLK_PLLVDO, CDDIV4_DIVCTL1, dtable_2_4),
DEF_DDIV(".pllvdo_cru3", CLK_PLLVDO_CRU3, CLK_PLLVDO, CDDIV4_DIVCTL2, dtable_2_4),
DEF_DDIV(".pllvdo_isp", CLK_PLLVDO_ISP, CLK_PLLVDO, CDDIV2_DIVCTL3, dtable_2_64),
DEF_FIXED(".plleth_250_fix", CLK_PLLETH_DIV_250_FIX, CLK_PLLETH, 1, 4),
DEF_FIXED(".plleth_125_fix", CLK_PLLETH_DIV_125_FIX, CLK_PLLETH_DIV_250_FIX, 1, 2),
@@ -168,6 +207,12 @@ static const struct cpg_core_clk r9a09g057_core_clks[] __initconst = {
DEF_SMUX(".smux2_gbe0_rxclk", CLK_SMUX2_GBE0_RXCLK, SSEL0_SELCTL3, smux2_gbe0_rxclk),
DEF_SMUX(".smux2_gbe1_txclk", CLK_SMUX2_GBE1_TXCLK, SSEL1_SELCTL0, smux2_gbe1_txclk),
DEF_SMUX(".smux2_gbe1_rxclk", CLK_SMUX2_GBE1_RXCLK, SSEL1_SELCTL1, smux2_gbe1_rxclk),
DEF_FIXED(".cdiv4_plleth_lpclk", CLK_CDIV4_PLLETH_LPCLK, CLK_PLLETH, 1, 4),
DEF_CSDIV(".plleth_lpclk_gear", CLK_PLLETH_LPCLK_GEAR, CLK_CDIV4_PLLETH_LPCLK,
CSDIV0_DIVCTL2, dtable_16_128),
DEF_PLLDSI_DIV(".plldsi_gear", CLK_PLLDSI_GEAR, CLK_PLLDSI,
CSDIV1_DIVCTL2, dtable_2_32),
DEF_DDIV(".pllgpu_gear", CLK_PLLGPU_GEAR, CLK_PLLGPU, CDDIV3_DIVCTL1, dtable_2_64),
@@ -190,6 +235,10 @@ static const struct cpg_core_clk r9a09g057_core_clks[] __initconst = {
CLK_PLLETH_DIV_125_FIX, 1, 1),
DEF_FIXED_MOD_STATUS("spi_clk_spi", R9A09G057_SPI_CLK_SPI, CLK_PLLCM33_XSPI, 1, 2,
FIXED_MOD_CONF_XSPI),
DEF_FIXED("usb3_0_ref_alt_clk_p", R9A09G057_USB3_0_REF_ALT_CLK_P, CLK_QEXTAL, 1, 1),
DEF_FIXED("usb3_0_core_clk", R9A09G057_USB3_0_CLKCORE, CLK_QEXTAL, 1, 1),
DEF_FIXED("usb3_1_ref_alt_clk_p", R9A09G057_USB3_1_REF_ALT_CLK_P, CLK_QEXTAL, 1, 1),
DEF_FIXED("usb3_1_core_clk", R9A09G057_USB3_1_CLKCORE, CLK_QEXTAL, 1, 1),
};
static const struct rzv2h_mod_clk r9a09g057_mod_clks[] __initconst = {
@@ -239,6 +288,8 @@ static const struct rzv2h_mod_clk r9a09g057_mod_clks[] __initconst = {
BUS_MSTOP(5, BIT(13))),
DEF_MOD("wdt_3_clk_loco", CLK_QEXTAL, 5, 2, 2, 18,
BUS_MSTOP(5, BIT(13))),
DEF_MOD("rtc_0_clk_rtc", CLK_PLLCM33_DIV16, 5, 3, 2, 19,
BUS_MSTOP(3, BIT(11) | BIT(12))),
DEF_MOD("rspi_0_pclk", CLK_PLLCLN_DIV8, 5, 4, 2, 20,
BUS_MSTOP(11, BIT(0))),
DEF_MOD("rspi_0_pclk_sfr", CLK_PLLCLN_DIV8, 5, 5, 2, 21,
@@ -313,6 +364,14 @@ static const struct rzv2h_mod_clk r9a09g057_mod_clks[] __initconst = {
BUS_MSTOP(8, BIT(4))),
DEF_MOD("sdhi_2_aclk", CLK_PLLDTY_ACPU_DIV4, 10, 14, 5, 14,
BUS_MSTOP(8, BIT(4))),
DEF_MOD("usb3_0_aclk", CLK_PLLDTY_DIV8, 10, 15, 5, 15,
BUS_MSTOP(7, BIT(12))),
DEF_MOD("usb3_0_pclk_usbtst", CLK_PLLDTY_ACPU_DIV4, 11, 0, 5, 16,
BUS_MSTOP(7, BIT(14))),
DEF_MOD("usb3_1_aclk", CLK_PLLDTY_DIV8, 11, 1, 5, 17,
BUS_MSTOP(7, BIT(13))),
DEF_MOD("usb3_1_pclk_usbtst", CLK_PLLDTY_ACPU_DIV4, 11, 2, 5, 18,
BUS_MSTOP(7, BIT(15))),
DEF_MOD("usb2_0_u2h0_hclk", CLK_PLLDTY_DIV8, 11, 3, 5, 19,
BUS_MSTOP(7, BIT(7))),
DEF_MOD("usb2_0_u2h1_hclk", CLK_PLLDTY_DIV8, 11, 4, 5, 20,
@@ -371,12 +430,40 @@ static const struct rzv2h_mod_clk r9a09g057_mod_clks[] __initconst = {
BUS_MSTOP(9, BIT(7))),
DEF_MOD("cru_3_pclk", CLK_PLLDTY_DIV16, 13, 13, 6, 29,
BUS_MSTOP(9, BIT(7))),
DEF_MOD("isp_0_reg_aclk", CLK_PLLDTY_ACPU_DIV2, 14, 2, 7, 2,
BUS_MSTOP(9, BIT(8))),
DEF_MOD("isp_0_pclk", CLK_PLLDTY_DIV16, 14, 3, 7, 3,
BUS_MSTOP(9, BIT(8))),
DEF_MOD("isp_0_vin_aclk", CLK_PLLDTY_ACPU_DIV2, 14, 4, 7, 4,
BUS_MSTOP(9, BIT(9))),
DEF_MOD("isp_0_isp_sclk", CLK_PLLVDO_ISP, 14, 5, 7, 5,
BUS_MSTOP(9, BIT(9))),
DEF_MOD("dsi_0_pclk", CLK_PLLDTY_DIV16, 14, 8, 7, 8,
BUS_MSTOP(9, BIT(14) | BIT(15))),
DEF_MOD("dsi_0_aclk", CLK_PLLDTY_ACPU_DIV2, 14, 9, 7, 9,
BUS_MSTOP(9, BIT(14) | BIT(15))),
DEF_MOD("dsi_0_vclk1", CLK_PLLDSI_GEAR, 14, 10, 7, 10,
BUS_MSTOP(9, BIT(14) | BIT(15))),
DEF_MOD("dsi_0_lpclk", CLK_PLLETH_LPCLK_GEAR, 14, 11, 7, 11,
BUS_MSTOP(9, BIT(14) | BIT(15))),
DEF_MOD("dsi_0_pllref_clk", CLK_QEXTAL, 14, 12, 7, 12,
BUS_MSTOP(9, BIT(14) | BIT(15))),
DEF_MOD("lcdc_0_clk_a", CLK_PLLDTY_ACPU_DIV2, 14, 13, 7, 13,
BUS_MSTOP(10, BIT(1) | BIT(2) | BIT(3))),
DEF_MOD("lcdc_0_clk_p", CLK_PLLDTY_DIV16, 14, 14, 7, 14,
BUS_MSTOP(10, BIT(1) | BIT(2) | BIT(3))),
DEF_MOD("lcdc_0_clk_d", CLK_PLLDSI_GEAR, 14, 15, 7, 15,
BUS_MSTOP(10, BIT(1) | BIT(2) | BIT(3))),
DEF_MOD("gpu_0_clk", CLK_PLLGPU_GEAR, 15, 0, 7, 16,
BUS_MSTOP(3, BIT(4))),
DEF_MOD("gpu_0_axi_clk", CLK_PLLDTY_ACPU_DIV2, 15, 1, 7, 17,
BUS_MSTOP(3, BIT(4))),
DEF_MOD("gpu_0_ace_clk", CLK_PLLDTY_ACPU_DIV2, 15, 2, 7, 18,
BUS_MSTOP(3, BIT(4))),
DEF_MOD("tsu_0_pclk", CLK_QEXTAL, 16, 9, 8, 9,
BUS_MSTOP(5, BIT(2))),
DEF_MOD("tsu_1_pclk", CLK_QEXTAL, 16, 10, 8, 10,
BUS_MSTOP(2, BIT(15))),
};
static const struct rzv2h_reset r9a09g057_resets[] __initconst = {
@@ -401,6 +488,8 @@ static const struct rzv2h_reset r9a09g057_resets[] __initconst = {
DEF_RST(7, 6, 3, 7), /* WDT_1_RESET */
DEF_RST(7, 7, 3, 8), /* WDT_2_RESET */
DEF_RST(7, 8, 3, 9), /* WDT_3_RESET */
DEF_RST(7, 9, 3, 10), /* RTC_0_RST_RTC */
DEF_RST(7, 10, 3, 11), /* RTC_0_RST_RTC_V */
DEF_RST(7, 11, 3, 12), /* RSPI_0_PRESETN */
DEF_RST(7, 12, 3, 13), /* RSPI_0_TRESETN */
DEF_RST(7, 13, 3, 14), /* RSPI_1_PRESETN */
@@ -424,6 +513,8 @@ static const struct rzv2h_reset r9a09g057_resets[] __initconst = {
DEF_RST(10, 7, 4, 24), /* SDHI_0_IXRST */
DEF_RST(10, 8, 4, 25), /* SDHI_1_IXRST */
DEF_RST(10, 9, 4, 26), /* SDHI_2_IXRST */
DEF_RST(10, 10, 4, 27), /* USB3_0_ARESETN */
DEF_RST(10, 11, 4, 28), /* USB3_1_ARESETN */
DEF_RST(10, 12, 4, 29), /* USB2_0_U2H0_HRESETN */
DEF_RST(10, 13, 4, 30), /* USB2_0_U2H1_HRESETN */
DEF_RST(10, 14, 4, 31), /* USB2_0_U2P_EXL_SYSRST */
@@ -442,9 +533,18 @@ static const struct rzv2h_reset r9a09g057_resets[] __initconst = {
DEF_RST(12, 14, 5, 31), /* CRU_3_PRESETN */
DEF_RST(12, 15, 6, 0), /* CRU_3_ARESETN */
DEF_RST(13, 0, 6, 1), /* CRU_3_S_RESETN */
DEF_RST(13, 1, 6, 2), /* ISP_0_VIN_ARESETN */
DEF_RST(13, 2, 6, 3), /* ISP_0_REG_ARESETN */
DEF_RST(13, 3, 6, 4), /* ISP_0_ISP_SRESETN */
DEF_RST(13, 4, 6, 5), /* ISP_0_PRESETN */
DEF_RST(13, 7, 6, 8), /* DSI_0_PRESETN */
DEF_RST(13, 8, 6, 9), /* DSI_0_ARESETN */
DEF_RST(13, 12, 6, 13), /* LCDC_0_RESET_N */
DEF_RST(13, 13, 6, 14), /* GPU_0_RESETN */
DEF_RST(13, 14, 6, 15), /* GPU_0_AXI_RESETN */
DEF_RST(13, 15, 6, 16), /* GPU_0_ACE_RESETN */
DEF_RST(15, 7, 7, 8), /* TSU_0_PRESETN */
DEF_RST(15, 8, 7, 9), /* TSU_1_PRESETN */
};
const struct rzv2h_cpg_info r9a09g057_cpg_info __initconst = {

View File

@@ -46,8 +46,12 @@
#define DIVCA55C2 CONF_PACK(SCKCR2, 10, 1)
#define DIVCA55C3 CONF_PACK(SCKCR2, 11, 1)
#define DIVCA55S CONF_PACK(SCKCR2, 12, 1)
#define DIVSPI3ASYNC CONF_PACK(SCKCR2, 16, 2)
#define DIVSCI5ASYNC CONF_PACK(SCKCR2, 18, 2)
#define DIVSPI0ASYNC CONF_PACK(SCKCR3, 0, 2)
#define DIVSPI1ASYNC CONF_PACK(SCKCR3, 2, 2)
#define DIVSPI2ASYNC CONF_PACK(SCKCR3, 4, 2)
#define DIVSCI0ASYNC CONF_PACK(SCKCR3, 6, 2)
#define DIVSCI1ASYNC CONF_PACK(SCKCR3, 8, 2)
#define DIVSCI2ASYNC CONF_PACK(SCKCR3, 10, 2)
@@ -56,7 +60,6 @@
#define SEL_PLL CONF_PACK(SCKCR, 22, 1)
enum rzt2h_clk_types {
CLK_TYPE_RZT2H_DIV = CLK_TYPE_CUSTOM, /* Clock with divider */
CLK_TYPE_RZT2H_MUX, /* Clock with clock source selector */
@@ -94,6 +97,10 @@ enum clk_ids {
CLK_SCI3ASYNC,
CLK_SCI4ASYNC,
CLK_SCI5ASYNC,
CLK_SPI0ASYNC,
CLK_SPI1ASYNC,
CLK_SPI2ASYNC,
CLK_SPI3ASYNC,
/* Module Clocks */
MOD_CLK_BASE,
@@ -154,6 +161,15 @@ static const struct cpg_core_clk r9a09g077_core_clks[] __initconst = {
DEF_DIV(".sci5async", CLK_SCI5ASYNC, CLK_PLL4D1, DIVSCI5ASYNC,
dtable_24_25_30_32),
DEF_DIV(".spi0async", CLK_SPI0ASYNC, CLK_PLL4D1, DIVSPI0ASYNC,
dtable_24_25_30_32),
DEF_DIV(".spi1async", CLK_SPI1ASYNC, CLK_PLL4D1, DIVSPI1ASYNC,
dtable_24_25_30_32),
DEF_DIV(".spi2async", CLK_SPI2ASYNC, CLK_PLL4D1, DIVSPI2ASYNC,
dtable_24_25_30_32),
DEF_DIV(".spi3async", CLK_SPI3ASYNC, CLK_PLL4D1, DIVSPI3ASYNC,
dtable_24_25_30_32),
/* Core output clk */
DEF_DIV("CA55C0", R9A09G077_CLK_CA55C0, CLK_SEL_CLK_PLL0, DIVCA55C0,
dtable_1_2),
@@ -188,6 +204,13 @@ static const struct mssr_mod_clk r9a09g077_mod_clks[] __initconst = {
DEF_MOD("sci4fck", 12, CLK_SCI4ASYNC),
DEF_MOD("iic0", 100, R9A09G077_CLK_PCLKL),
DEF_MOD("iic1", 101, R9A09G077_CLK_PCLKL),
DEF_MOD("spi0", 104, CLK_SPI0ASYNC),
DEF_MOD("spi1", 105, CLK_SPI1ASYNC),
DEF_MOD("spi2", 106, CLK_SPI2ASYNC),
DEF_MOD("adc0", 206, R9A09G077_CLK_PCLKH),
DEF_MOD("adc1", 207, R9A09G077_CLK_PCLKH),
DEF_MOD("adc2", 225, R9A09G077_CLK_PCLKM),
DEF_MOD("tsu", 307, R9A09G077_CLK_PCLKL),
DEF_MOD("gmac0", 400, R9A09G077_CLK_PCLKM),
DEF_MOD("ethsw", 401, R9A09G077_CLK_PCLKM),
DEF_MOD("ethss", 403, R9A09G077_CLK_PCLKM),
@@ -196,6 +219,7 @@ static const struct mssr_mod_clk r9a09g077_mod_clks[] __initconst = {
DEF_MOD("gmac2", 417, R9A09G077_CLK_PCLKAM),
DEF_MOD("sci5fck", 600, CLK_SCI5ASYNC),
DEF_MOD("iic2", 601, R9A09G077_CLK_PCLKL),
DEF_MOD("spi3", 602, CLK_SPI3ASYNC),
DEF_MOD("sdhi0", 1212, R9A09G077_CLK_PCLKAM),
DEF_MOD("sdhi1", 1213, R9A09G077_CLK_PCLKAM),
};
@@ -216,27 +240,28 @@ r9a09g077_cpg_div_clk_register(struct device *dev,
parent_name = __clk_get_name(parent);
if (core->dtable)
clk_hw = clk_hw_register_divider_table(dev, core->name,
parent_name, 0,
addr,
GET_SHIFT(core->conf),
GET_WIDTH(core->conf),
core->flag,
core->dtable,
&pub->rmw_lock);
clk_hw = devm_clk_hw_register_divider_table(dev, core->name,
parent_name,
CLK_SET_RATE_PARENT,
addr,
GET_SHIFT(core->conf),
GET_WIDTH(core->conf),
core->flag,
core->dtable,
&pub->rmw_lock);
else
clk_hw = clk_hw_register_divider(dev, core->name,
parent_name, 0,
addr,
GET_SHIFT(core->conf),
GET_WIDTH(core->conf),
core->flag, &pub->rmw_lock);
clk_hw = devm_clk_hw_register_divider(dev, core->name,
parent_name,
CLK_SET_RATE_PARENT,
addr,
GET_SHIFT(core->conf),
GET_WIDTH(core->conf),
core->flag, &pub->rmw_lock);
if (IS_ERR(clk_hw))
return ERR_CAST(clk_hw);
return clk_hw->clk;
}
static struct clk * __init

View File

@@ -35,7 +35,7 @@ void cpg_reg_modify(void __iomem *reg, u32 clear, u32 set)
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)

View File

@@ -257,7 +257,7 @@ static struct clk * __init cpg_pll_clk_register(const char *name,
}
/*
* Z0 Clock & Z1 Clock
* Z0, Z1 and ZG Clock
*/
#define CPG_FRQCRB 0x00000804
#define CPG_FRQCRB_KICK BIT(31)
@@ -389,9 +389,14 @@ static struct clk * __init cpg_z_clk_register(const char *name,
if (offset < 32) {
zclk->reg = reg + CPG_FRQCRC0;
} else {
} else if (offset < 64) {
zclk->reg = reg + CPG_FRQCRC1;
offset -= 32;
} else if (offset < 96) {
zclk->reg = reg + CPG_FRQCRB;
offset -= 64;
} else {
return ERR_PTR(-EINVAL);
}
zclk->kick_reg = reg + CPG_FRQCRB;
zclk->hw.init = &init;

View File

@@ -40,8 +40,10 @@
#define WARN_DEBUG(x) do { } while (0)
#endif
#define RZT2H_RESET_REG_READ_COUNT 7
/*
* Module Standby and Software Reset register offets.
* Module Standby and Software Reset register offsets.
*
* If the registers exist, these are valid for SH-Mobile, R-Mobile,
* R-Car Gen2, R-Car Gen3, and RZ/G1.
@@ -137,6 +139,22 @@ static const u16 srcr_for_gen4[] = {
0x2C60, 0x2C64, 0x2C68, 0x2C6C, 0x2C70, 0x2C74,
};
static const u16 mrcr_for_rzt2h[] = {
0x240, /* MRCTLA */
0x244, /* Reserved */
0x248, /* Reserved */
0x24C, /* Reserved */
0x250, /* MRCTLE */
0x254, /* Reserved */
0x258, /* Reserved */
0x25C, /* Reserved */
0x260, /* MRCTLI */
0x264, /* Reserved */
0x268, /* Reserved */
0x26C, /* Reserved */
0x270, /* MRCTLM */
};
/*
* Software Reset Clearing Register offsets
*/
@@ -290,10 +308,21 @@ static int cpg_mstp_clock_endisable(struct clk_hw *hw, bool enable)
spin_unlock_irqrestore(&priv->pub.rmw_lock, flags);
if (!enable || priv->reg_layout == CLK_REG_LAYOUT_RZ_A ||
priv->reg_layout == CLK_REG_LAYOUT_RZ_T2H)
if (!enable || priv->reg_layout == CLK_REG_LAYOUT_RZ_A)
return 0;
if (priv->reg_layout == CLK_REG_LAYOUT_RZ_T2H) {
/*
* For the RZ/T2H case, it is necessary to perform a read-back after
* accessing the MSTPCRm register and to dummy-read any register of
* the IP at least seven times. Instead of memory-mapping the IP
* register, we simply add a delay after the read operation.
*/
cpg_rzt2h_mstp_read(hw, priv->control_regs[reg]);
udelay(10);
return 0;
}
error = readl_poll_timeout_atomic(priv->pub.base0 + priv->status_regs[reg],
value, !(value & bitmask), 0, 10);
if (error)
@@ -451,7 +480,7 @@ static void __init cpg_mssr_register_core_clk(const struct cpg_core_clk *core,
break;
}
if (IS_ERR_OR_NULL(clk))
if (IS_ERR(clk))
goto fail;
dev_dbg(dev, "Core clock %pC at %lu Hz\n", clk, clk_get_rate(clk));
@@ -676,53 +705,56 @@ static int __init cpg_mssr_add_clk_domain(struct device *dev,
#define rcdev_to_priv(x) container_of(x, struct cpg_mssr_priv, rcdev)
static int cpg_mssr_reset(struct reset_controller_dev *rcdev,
unsigned long id)
static int cpg_mssr_reset_operate(struct reset_controller_dev *rcdev,
const char *func, bool set, unsigned long id)
{
struct cpg_mssr_priv *priv = rcdev_to_priv(rcdev);
unsigned int reg = id / 32;
unsigned int bit = id % 32;
const u16 off = set ? priv->reset_regs[reg] : priv->reset_clear_regs[reg];
u32 bitmask = BIT(bit);
dev_dbg(priv->dev, "reset %u%02u\n", reg, bit);
if (func)
dev_dbg(priv->dev, "%s %u%02u\n", func, reg, bit);
/* Reset module */
writel(bitmask, priv->pub.base0 + priv->reset_regs[reg]);
/* Wait for at least one cycle of the RCLK clock (@ ca. 32 kHz) */
udelay(35);
/* Release module from reset state */
writel(bitmask, priv->pub.base0 + priv->reset_clear_regs[reg]);
writel(bitmask, priv->pub.base0 + off);
readl(priv->pub.base0 + off);
barrier_data(priv->pub.base0 + off);
return 0;
}
static int cpg_mssr_assert(struct reset_controller_dev *rcdev, unsigned long id)
static int cpg_mssr_reset(struct reset_controller_dev *rcdev,
unsigned long id)
{
struct cpg_mssr_priv *priv = rcdev_to_priv(rcdev);
unsigned int reg = id / 32;
unsigned int bit = id % 32;
u32 bitmask = BIT(bit);
dev_dbg(priv->dev, "assert %u%02u\n", reg, bit);
/* Reset module */
cpg_mssr_reset_operate(rcdev, "reset", true, id);
writel(bitmask, priv->pub.base0 + priv->reset_regs[reg]);
return 0;
/*
* On R-Car Gen4, delay after SRCR has been written is 1ms.
* On older SoCs, delay after SRCR has been written is 35us
* (one cycle of the RCLK clock @ ca. 32 kHz).
*/
if (priv->reg_layout == CLK_REG_LAYOUT_RCAR_GEN4)
usleep_range(1000, 2000);
else
usleep_range(35, 1000);
/* Release module from reset state */
return cpg_mssr_reset_operate(rcdev, NULL, false, id);
}
static int cpg_mssr_assert(struct reset_controller_dev *rcdev, unsigned long id)
{
return cpg_mssr_reset_operate(rcdev, "assert", true, id);
}
static int cpg_mssr_deassert(struct reset_controller_dev *rcdev,
unsigned long id)
{
struct cpg_mssr_priv *priv = rcdev_to_priv(rcdev);
unsigned int reg = id / 32;
unsigned int bit = id % 32;
u32 bitmask = BIT(bit);
dev_dbg(priv->dev, "deassert %u%02u\n", reg, bit);
writel(bitmask, priv->pub.base0 + priv->reset_clear_regs[reg]);
return 0;
return cpg_mssr_reset_operate(rcdev, "deassert", false, id);
}
static int cpg_mssr_status(struct reset_controller_dev *rcdev,
@@ -736,6 +768,72 @@ static int cpg_mssr_status(struct reset_controller_dev *rcdev,
return !!(readl(priv->pub.base0 + priv->reset_regs[reg]) & bitmask);
}
static int cpg_mrcr_set_reset_state(struct reset_controller_dev *rcdev,
unsigned long id, bool set)
{
struct cpg_mssr_priv *priv = rcdev_to_priv(rcdev);
unsigned int reg = id / 32;
unsigned int bit = id % 32;
u32 bitmask = BIT(bit);
void __iomem *reg_addr;
unsigned long flags;
unsigned int i;
u32 val;
dev_dbg(priv->dev, "%s %u%02u\n", set ? "assert" : "deassert", reg, bit);
spin_lock_irqsave(&priv->pub.rmw_lock, flags);
reg_addr = priv->pub.base0 + priv->reset_regs[reg];
/* Read current value and modify */
val = readl(reg_addr);
if (set)
val |= bitmask;
else
val &= ~bitmask;
writel(val, reg_addr);
/*
* For secure processing after release from a module reset, one must
* perform multiple dummy reads of the same register.
*/
for (i = 0; !set && i < RZT2H_RESET_REG_READ_COUNT; i++)
readl(reg_addr);
/* Verify the operation */
val = readl(reg_addr);
if (set == !(bitmask & val)) {
dev_err(priv->dev, "Reset register %u%02u operation failed\n", reg, bit);
spin_unlock_irqrestore(&priv->pub.rmw_lock, flags);
return -EIO;
}
spin_unlock_irqrestore(&priv->pub.rmw_lock, flags);
return 0;
}
static int cpg_mrcr_reset(struct reset_controller_dev *rcdev, unsigned long id)
{
int ret;
ret = cpg_mrcr_set_reset_state(rcdev, id, true);
if (ret)
return ret;
return cpg_mrcr_set_reset_state(rcdev, id, false);
}
static int cpg_mrcr_assert(struct reset_controller_dev *rcdev, unsigned long id)
{
return cpg_mrcr_set_reset_state(rcdev, id, true);
}
static int cpg_mrcr_deassert(struct reset_controller_dev *rcdev, unsigned long id)
{
return cpg_mrcr_set_reset_state(rcdev, id, false);
}
static const struct reset_control_ops cpg_mssr_reset_ops = {
.reset = cpg_mssr_reset,
.assert = cpg_mssr_assert,
@@ -743,6 +841,13 @@ static const struct reset_control_ops cpg_mssr_reset_ops = {
.status = cpg_mssr_status,
};
static const struct reset_control_ops cpg_mrcr_reset_ops = {
.reset = cpg_mrcr_reset,
.assert = cpg_mrcr_assert,
.deassert = cpg_mrcr_deassert,
.status = cpg_mssr_status,
};
static int cpg_mssr_reset_xlate(struct reset_controller_dev *rcdev,
const struct of_phandle_args *reset_spec)
{
@@ -760,11 +865,23 @@ static int cpg_mssr_reset_xlate(struct reset_controller_dev *rcdev,
static int cpg_mssr_reset_controller_register(struct cpg_mssr_priv *priv)
{
priv->rcdev.ops = &cpg_mssr_reset_ops;
/*
* RZ/T2H (and family) has the Module Reset Control Registers
* which allows control resets of certain modules.
* The number of resets is not equal to the number of module clocks.
*/
if (priv->reg_layout == CLK_REG_LAYOUT_RZ_T2H) {
priv->rcdev.ops = &cpg_mrcr_reset_ops;
priv->rcdev.nr_resets = ARRAY_SIZE(mrcr_for_rzt2h) * 32;
} else {
priv->rcdev.ops = &cpg_mssr_reset_ops;
priv->rcdev.nr_resets = priv->num_mod_clks;
}
priv->rcdev.of_node = priv->dev->of_node;
priv->rcdev.of_reset_n_cells = 1;
priv->rcdev.of_xlate = cpg_mssr_reset_xlate;
priv->rcdev.nr_resets = priv->num_mod_clks;
return devm_reset_controller_register(priv->dev, &priv->rcdev);
}
@@ -1169,6 +1286,7 @@ static int __init cpg_mssr_common_init(struct device *dev,
priv->control_regs = stbcr;
} else if (priv->reg_layout == CLK_REG_LAYOUT_RZ_T2H) {
priv->control_regs = mstpcr_for_rzt2h;
priv->reset_regs = mrcr_for_rzt2h;
} else if (priv->reg_layout == CLK_REG_LAYOUT_RCAR_GEN4) {
priv->status_regs = mstpsr_for_gen4;
priv->control_regs = mstpcr_for_gen4;
@@ -1265,8 +1383,7 @@ static int __init cpg_mssr_probe(struct platform_device *pdev)
goto reserve_exit;
/* Reset Controller not supported for Standby Control SoCs */
if (priv->reg_layout == CLK_REG_LAYOUT_RZ_A ||
priv->reg_layout == CLK_REG_LAYOUT_RZ_T2H)
if (priv->reg_layout == CLK_REG_LAYOUT_RZ_A)
goto reserve_exit;
error = cpg_mssr_reset_controller_register(priv);

View File

@@ -1177,7 +1177,7 @@ rzg2l_cpg_register_core_clk(const struct cpg_core_clk *core,
goto fail;
}
if (IS_ERR_OR_NULL(clk))
if (IS_ERR(clk))
goto fail;
dev_dbg(dev, "Core clock %pC at %lu Hz\n", clk, clk_get_rate(clk));

View File

@@ -14,9 +14,14 @@
#include <linux/bitfield.h>
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/clk/renesas.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/iopoll.h>
#include <linux/limits.h>
#include <linux/math.h>
#include <linux/math64.h>
#include <linux/minmax.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/of.h>
@@ -26,6 +31,7 @@
#include <linux/refcount.h>
#include <linux/reset-controller.h>
#include <linux/string_choices.h>
#include <linux/units.h>
#include <dt-bindings/clock/renesas-cpg-mssr.h>
@@ -47,13 +53,15 @@
#define CPG_PLL_STBY(x) ((x))
#define CPG_PLL_STBY_RESETB BIT(0)
#define CPG_PLL_STBY_SSC_EN BIT(2)
#define CPG_PLL_STBY_RESETB_WEN BIT(16)
#define CPG_PLL_STBY_SSC_EN_WEN BIT(18)
#define CPG_PLL_CLK1(x) ((x) + 0x004)
#define CPG_PLL_CLK1_KDIV(x) ((s16)FIELD_GET(GENMASK(31, 16), (x)))
#define CPG_PLL_CLK1_MDIV(x) FIELD_GET(GENMASK(15, 6), (x))
#define CPG_PLL_CLK1_PDIV(x) FIELD_GET(GENMASK(5, 0), (x))
#define CPG_PLL_CLK1_KDIV GENMASK(31, 16)
#define CPG_PLL_CLK1_MDIV GENMASK(15, 6)
#define CPG_PLL_CLK1_PDIV GENMASK(5, 0)
#define CPG_PLL_CLK2(x) ((x) + 0x008)
#define CPG_PLL_CLK2_SDIV(x) FIELD_GET(GENMASK(2, 0), (x))
#define CPG_PLL_CLK2_SDIV GENMASK(2, 0)
#define CPG_PLL_MON(x) ((x) + 0x010)
#define CPG_PLL_MON_RESETB BIT(0)
#define CPG_PLL_MON_LOCK BIT(4)
@@ -65,6 +73,22 @@
#define CPG_CLKSTATUS0 (0x700)
/* On RZ/G3E SoC we have two DSI PLLs */
#define MAX_CPG_DSI_PLL 2
/**
* struct rzv2h_pll_dsi_info - PLL DSI information, holds the limits and parameters
*
* @pll_dsi_limits: PLL DSI parameters limits
* @pll_dsi_parameters: Calculated PLL DSI parameters
* @req_pll_dsi_rate: Requested PLL DSI rate
*/
struct rzv2h_pll_dsi_info {
const struct rzv2h_pll_limits *pll_dsi_limits;
struct rzv2h_pll_div_pars pll_dsi_parameters;
unsigned long req_pll_dsi_rate;
};
/**
* struct rzv2h_cpg_priv - Clock Pulse Generator Private Data
*
@@ -80,6 +104,7 @@
* @ff_mod_status_ops: Fixed Factor Module Status Clock operations
* @mstop_count: Array of mstop values
* @rcdev: Reset controller entity
* @pll_dsi_info: Array of PLL DSI information, holds the limits and parameters
*/
struct rzv2h_cpg_priv {
struct device *dev;
@@ -98,6 +123,8 @@ struct rzv2h_cpg_priv {
atomic_t *mstop_count;
struct reset_controller_dev rcdev;
struct rzv2h_pll_dsi_info pll_dsi_info[MAX_CPG_DSI_PLL];
};
#define rcdev_to_priv(x) container_of(x, struct rzv2h_cpg_priv, rcdev)
@@ -168,6 +195,460 @@ struct rzv2h_ff_mod_status_clk {
#define to_rzv2h_ff_mod_status_clk(_hw) \
container_of(_hw, struct rzv2h_ff_mod_status_clk, fix.hw)
/**
* struct rzv2h_plldsi_div_clk - PLL DSI DDIV clock
*
* @dtable: divider table
* @priv: CPG private data
* @hw: divider clk
* @ddiv: divider configuration
*/
struct rzv2h_plldsi_div_clk {
const struct clk_div_table *dtable;
struct rzv2h_cpg_priv *priv;
struct clk_hw hw;
struct ddiv ddiv;
};
#define to_plldsi_div_clk(_hw) \
container_of(_hw, struct rzv2h_plldsi_div_clk, hw)
#define RZ_V2H_OSC_CLK_IN_MEGA (24 * MEGA)
#define RZV2H_MAX_DIV_TABLES (16)
/**
* rzv2h_get_pll_pars - Finds the best combination of PLL parameters
* for a given frequency.
*
* @limits: Pointer to the structure containing the limits for the PLL parameters
* @pars: Pointer to the structure where the best calculated PLL parameters values
* will be stored
* @freq_millihz: Target output frequency in millihertz
*
* This function calculates the best set of PLL parameters (M, K, P, S) to achieve
* the desired frequency.
* There is no direct formula to calculate the PLL parameters, as it's an open
* system of equations, therefore this function uses an iterative approach to
* determine the best solution. The best solution is one that minimizes the error
* (desired frequency - actual frequency).
*
* Return: true if a valid set of parameters values is found, false otherwise.
*/
bool rzv2h_get_pll_pars(const struct rzv2h_pll_limits *limits,
struct rzv2h_pll_pars *pars, u64 freq_millihz)
{
u64 fout_min_millihz = mul_u32_u32(limits->fout.min, MILLI);
u64 fout_max_millihz = mul_u32_u32(limits->fout.max, MILLI);
struct rzv2h_pll_pars p, best;
if (freq_millihz > fout_max_millihz ||
freq_millihz < fout_min_millihz)
return false;
/* Initialize best error to maximum possible value */
best.error_millihz = S64_MAX;
for (p.p = limits->p.min; p.p <= limits->p.max; p.p++) {
u32 fref = RZ_V2H_OSC_CLK_IN_MEGA / p.p;
u16 divider;
for (divider = 1 << limits->s.min, p.s = limits->s.min;
p.s <= limits->s.max; p.s++, divider <<= 1) {
for (p.m = limits->m.min; p.m <= limits->m.max; p.m++) {
u64 output_m, output_k_range;
s64 pll_k, output_k;
u64 fvco, output;
/*
* The frequency generated by the PLL + divider
* is calculated as follows:
*
* With:
* Freq = Ffout = Ffvco / 2^(pll_s)
* Ffvco = (pll_m + (pll_k / 65536)) * Ffref
* Ffref = 24MHz / pll_p
*
* Freq can also be rewritten as:
* Freq = Ffvco / 2^(pll_s)
* = ((pll_m + (pll_k / 65536)) * Ffref) / 2^(pll_s)
* = (pll_m * Ffref) / 2^(pll_s) + ((pll_k / 65536) * Ffref) / 2^(pll_s)
* = output_m + output_k
*
* Every parameter has been determined at this
* point, but pll_k.
*
* Considering that:
* limits->k.min <= pll_k <= limits->k.max
* Then:
* -0.5 <= (pll_k / 65536) < 0.5
* Therefore:
* -Ffref / (2 * 2^(pll_s)) <= output_k < Ffref / (2 * 2^(pll_s))
*/
/* Compute output M component (in mHz) */
output_m = DIV_ROUND_CLOSEST_ULL(mul_u32_u32(p.m, fref) * MILLI,
divider);
/* Compute range for output K (in mHz) */
output_k_range = DIV_ROUND_CLOSEST_ULL(mul_u32_u32(fref, MILLI),
2 * divider);
/*
* No point in continuing if we can't achieve
* the desired frequency
*/
if (freq_millihz < (output_m - output_k_range) ||
freq_millihz >= (output_m + output_k_range)) {
continue;
}
/*
* Compute the K component
*
* Since:
* Freq = output_m + output_k
* Then:
* output_k = Freq - output_m
* = ((pll_k / 65536) * Ffref) / 2^(pll_s)
* Therefore:
* pll_k = (output_k * 65536 * 2^(pll_s)) / Ffref
*/
output_k = freq_millihz - output_m;
pll_k = div_s64(output_k * 65536ULL * divider,
fref);
pll_k = DIV_S64_ROUND_CLOSEST(pll_k, MILLI);
/* Validate K value within allowed limits */
if (pll_k < limits->k.min ||
pll_k > limits->k.max)
continue;
p.k = pll_k;
/* Compute (Ffvco * 65536) */
fvco = mul_u32_u32(p.m * 65536 + p.k, fref);
if (fvco < mul_u32_u32(limits->fvco.min, 65536) ||
fvco > mul_u32_u32(limits->fvco.max, 65536))
continue;
/* PLL_M component of (output * 65536 * PLL_P) */
output = mul_u32_u32(p.m * 65536, RZ_V2H_OSC_CLK_IN_MEGA);
/* PLL_K component of (output * 65536 * PLL_P) */
output += p.k * RZ_V2H_OSC_CLK_IN_MEGA;
/* Make it in mHz */
output *= MILLI;
output = DIV_U64_ROUND_CLOSEST(output, 65536 * p.p * divider);
/* Check output frequency against limits */
if (output < fout_min_millihz ||
output > fout_max_millihz)
continue;
p.error_millihz = freq_millihz - output;
p.freq_millihz = output;
/* If an exact match is found, return immediately */
if (p.error_millihz == 0) {
*pars = p;
return true;
}
/* Update best match if error is smaller */
if (abs(best.error_millihz) > abs(p.error_millihz))
best = p;
}
}
}
/* If no valid parameters were found, return false */
if (best.error_millihz == S64_MAX)
return false;
*pars = best;
return true;
}
EXPORT_SYMBOL_NS_GPL(rzv2h_get_pll_pars, "RZV2H_CPG");
/*
* rzv2h_get_pll_divs_pars - Finds the best combination of PLL parameters
* and divider value for a given frequency.
*
* @limits: Pointer to the structure containing the limits for the PLL parameters
* @pars: Pointer to the structure where the best calculated PLL parameters and
* divider values will be stored
* @table: Pointer to the array of valid divider values
* @table_size: Size of the divider values array
* @freq_millihz: Target output frequency in millihertz
*
* This function calculates the best set of PLL parameters (M, K, P, S) and divider
* value to achieve the desired frequency. See rzv2h_get_pll_pars() for more details
* on how the PLL parameters are calculated.
*
* freq_millihz is the desired frequency generated by the PLL followed by a
* a gear.
*/
bool rzv2h_get_pll_divs_pars(const struct rzv2h_pll_limits *limits,
struct rzv2h_pll_div_pars *pars,
const u8 *table, u8 table_size, u64 freq_millihz)
{
struct rzv2h_pll_div_pars p, best;
best.div.error_millihz = S64_MAX;
p.div.error_millihz = S64_MAX;
for (unsigned int i = 0; i < table_size; i++) {
if (!rzv2h_get_pll_pars(limits, &p.pll, freq_millihz * table[i]))
continue;
p.div.divider_value = table[i];
p.div.freq_millihz = DIV_U64_ROUND_CLOSEST(p.pll.freq_millihz, table[i]);
p.div.error_millihz = freq_millihz - p.div.freq_millihz;
if (p.div.error_millihz == 0) {
*pars = p;
return true;
}
if (abs(best.div.error_millihz) > abs(p.div.error_millihz))
best = p;
}
if (best.div.error_millihz == S64_MAX)
return false;
*pars = best;
return true;
}
EXPORT_SYMBOL_NS_GPL(rzv2h_get_pll_divs_pars, "RZV2H_CPG");
static unsigned long rzv2h_cpg_plldsi_div_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct rzv2h_plldsi_div_clk *dsi_div = to_plldsi_div_clk(hw);
struct rzv2h_cpg_priv *priv = dsi_div->priv;
struct ddiv ddiv = dsi_div->ddiv;
u32 div;
div = readl(priv->base + ddiv.offset);
div >>= ddiv.shift;
div &= clk_div_mask(ddiv.width);
div = dsi_div->dtable[div].div;
return DIV_ROUND_CLOSEST_ULL(parent_rate, div);
}
static int rzv2h_cpg_plldsi_div_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct rzv2h_plldsi_div_clk *dsi_div = to_plldsi_div_clk(hw);
struct pll_clk *pll_clk = to_pll(clk_hw_get_parent(hw));
struct rzv2h_cpg_priv *priv = dsi_div->priv;
u8 table[RZV2H_MAX_DIV_TABLES] = { 0 };
struct rzv2h_pll_div_pars *dsi_params;
struct rzv2h_pll_dsi_info *dsi_info;
const struct clk_div_table *div;
unsigned int i = 0;
u64 rate_millihz;
dsi_info = &priv->pll_dsi_info[pll_clk->pll.instance];
dsi_params = &dsi_info->pll_dsi_parameters;
rate_millihz = mul_u32_u32(req->rate, MILLI);
if (rate_millihz == dsi_params->div.error_millihz + dsi_params->div.freq_millihz)
goto exit_determine_rate;
for (div = dsi_div->dtable; div->div; div++) {
if (i >= RZV2H_MAX_DIV_TABLES)
return -EINVAL;
table[i++] = div->div;
}
if (!rzv2h_get_pll_divs_pars(dsi_info->pll_dsi_limits, dsi_params, table, i,
rate_millihz)) {
dev_err(priv->dev, "failed to determine rate for req->rate: %lu\n",
req->rate);
return -EINVAL;
}
exit_determine_rate:
req->rate = DIV_ROUND_CLOSEST_ULL(dsi_params->div.freq_millihz, MILLI);
req->best_parent_rate = req->rate * dsi_params->div.divider_value;
dsi_info->req_pll_dsi_rate = req->best_parent_rate;
return 0;
}
static int rzv2h_cpg_plldsi_div_set_rate(struct clk_hw *hw,
unsigned long rate,
unsigned long parent_rate)
{
struct rzv2h_plldsi_div_clk *dsi_div = to_plldsi_div_clk(hw);
struct pll_clk *pll_clk = to_pll(clk_hw_get_parent(hw));
struct rzv2h_cpg_priv *priv = dsi_div->priv;
struct rzv2h_pll_div_pars *dsi_params;
struct rzv2h_pll_dsi_info *dsi_info;
struct ddiv ddiv = dsi_div->ddiv;
const struct clk_div_table *clkt;
bool divider_found = false;
u32 val, shift;
dsi_info = &priv->pll_dsi_info[pll_clk->pll.instance];
dsi_params = &dsi_info->pll_dsi_parameters;
for (clkt = dsi_div->dtable; clkt->div; clkt++) {
if (clkt->div == dsi_params->div.divider_value) {
divider_found = true;
break;
}
}
if (!divider_found)
return -EINVAL;
shift = ddiv.shift;
val = readl(priv->base + ddiv.offset) | DDIV_DIVCTL_WEN(shift);
val &= ~(clk_div_mask(ddiv.width) << shift);
val |= clkt->val << shift;
writel(val, priv->base + ddiv.offset);
return 0;
}
static const struct clk_ops rzv2h_cpg_plldsi_div_ops = {
.recalc_rate = rzv2h_cpg_plldsi_div_recalc_rate,
.determine_rate = rzv2h_cpg_plldsi_div_determine_rate,
.set_rate = rzv2h_cpg_plldsi_div_set_rate,
};
static struct clk * __init
rzv2h_cpg_plldsi_div_clk_register(const struct cpg_core_clk *core,
struct rzv2h_cpg_priv *priv)
{
struct rzv2h_plldsi_div_clk *clk_hw_data;
struct clk **clks = priv->clks;
struct clk_init_data init;
const struct clk *parent;
const char *parent_name;
struct clk_hw *clk_hw;
int ret;
parent = clks[core->parent];
if (IS_ERR(parent))
return ERR_CAST(parent);
clk_hw_data = devm_kzalloc(priv->dev, sizeof(*clk_hw_data), GFP_KERNEL);
if (!clk_hw_data)
return ERR_PTR(-ENOMEM);
clk_hw_data->priv = priv;
clk_hw_data->ddiv = core->cfg.ddiv;
clk_hw_data->dtable = core->dtable;
parent_name = __clk_get_name(parent);
init.name = core->name;
init.ops = &rzv2h_cpg_plldsi_div_ops;
init.flags = core->flag;
init.parent_names = &parent_name;
init.num_parents = 1;
clk_hw = &clk_hw_data->hw;
clk_hw->init = &init;
ret = devm_clk_hw_register(priv->dev, clk_hw);
if (ret)
return ERR_PTR(ret);
return clk_hw->clk;
}
static int rzv2h_cpg_plldsi_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct pll_clk *pll_clk = to_pll(hw);
struct rzv2h_cpg_priv *priv = pll_clk->priv;
struct rzv2h_pll_dsi_info *dsi_info;
u64 rate_millihz;
dsi_info = &priv->pll_dsi_info[pll_clk->pll.instance];
/* check if the divider has already invoked the algorithm */
if (req->rate == dsi_info->req_pll_dsi_rate)
return 0;
/* If the req->rate doesn't match we do the calculation assuming there is no divider */
rate_millihz = mul_u32_u32(req->rate, MILLI);
if (!rzv2h_get_pll_pars(dsi_info->pll_dsi_limits,
&dsi_info->pll_dsi_parameters.pll, rate_millihz)) {
dev_err(priv->dev,
"failed to determine rate for req->rate: %lu\n",
req->rate);
return -EINVAL;
}
req->rate = DIV_ROUND_CLOSEST_ULL(dsi_info->pll_dsi_parameters.pll.freq_millihz, MILLI);
dsi_info->req_pll_dsi_rate = req->rate;
return 0;
}
static int rzv2h_cpg_pll_set_rate(struct pll_clk *pll_clk,
struct rzv2h_pll_pars *params,
bool ssc_disable)
{
struct rzv2h_cpg_priv *priv = pll_clk->priv;
u16 offset = pll_clk->pll.offset;
u32 val;
int ret;
/* Put PLL into standby mode */
writel(CPG_PLL_STBY_RESETB_WEN, priv->base + CPG_PLL_STBY(offset));
ret = readl_poll_timeout_atomic(priv->base + CPG_PLL_MON(offset),
val, !(val & CPG_PLL_MON_LOCK),
100, 2000);
if (ret) {
dev_err(priv->dev, "Failed to put PLLDSI into standby mode");
return ret;
}
/* Output clock setting 1 */
writel(FIELD_PREP(CPG_PLL_CLK1_KDIV, (u16)params->k) |
FIELD_PREP(CPG_PLL_CLK1_MDIV, params->m) |
FIELD_PREP(CPG_PLL_CLK1_PDIV, params->p),
priv->base + CPG_PLL_CLK1(offset));
/* Output clock setting 2 */
val = readl(priv->base + CPG_PLL_CLK2(offset));
writel((val & ~CPG_PLL_CLK2_SDIV) | FIELD_PREP(CPG_PLL_CLK2_SDIV, params->s),
priv->base + CPG_PLL_CLK2(offset));
/* Put PLL to normal mode */
if (ssc_disable)
val = CPG_PLL_STBY_SSC_EN_WEN;
else
val = CPG_PLL_STBY_SSC_EN_WEN | CPG_PLL_STBY_SSC_EN;
writel(val | CPG_PLL_STBY_RESETB_WEN | CPG_PLL_STBY_RESETB,
priv->base + CPG_PLL_STBY(offset));
/* PLL normal mode transition, output clock stability check */
ret = readl_poll_timeout_atomic(priv->base + CPG_PLL_MON(offset),
val, (val & CPG_PLL_MON_LOCK),
100, 2000);
if (ret) {
dev_err(priv->dev, "Failed to put PLLDSI into normal mode");
return ret;
}
return 0;
}
static int rzv2h_cpg_plldsi_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct pll_clk *pll_clk = to_pll(hw);
struct rzv2h_pll_dsi_info *dsi_info;
struct rzv2h_cpg_priv *priv = pll_clk->priv;
dsi_info = &priv->pll_dsi_info[pll_clk->pll.instance];
return rzv2h_cpg_pll_set_rate(pll_clk, &dsi_info->pll_dsi_parameters.pll, true);
}
static int rzv2h_cpg_pll_clk_is_enabled(struct clk_hw *hw)
{
struct pll_clk *pll_clk = to_pll(hw);
@@ -231,12 +712,19 @@ static unsigned long rzv2h_cpg_pll_clk_recalc_rate(struct clk_hw *hw,
clk1 = readl(priv->base + CPG_PLL_CLK1(pll.offset));
clk2 = readl(priv->base + CPG_PLL_CLK2(pll.offset));
rate = mul_u64_u32_shr(parent_rate, (CPG_PLL_CLK1_MDIV(clk1) << 16) +
CPG_PLL_CLK1_KDIV(clk1), 16 + CPG_PLL_CLK2_SDIV(clk2));
rate = mul_u64_u32_shr(parent_rate, (FIELD_GET(CPG_PLL_CLK1_MDIV, clk1) << 16) +
(s16)FIELD_GET(CPG_PLL_CLK1_KDIV, clk1),
16 + FIELD_GET(CPG_PLL_CLK2_SDIV, clk2));
return DIV_ROUND_CLOSEST_ULL(rate, CPG_PLL_CLK1_PDIV(clk1));
return DIV_ROUND_CLOSEST_ULL(rate, FIELD_GET(CPG_PLL_CLK1_PDIV, clk1));
}
static const struct clk_ops rzv2h_cpg_plldsi_ops = {
.recalc_rate = rzv2h_cpg_pll_clk_recalc_rate,
.determine_rate = rzv2h_cpg_plldsi_determine_rate,
.set_rate = rzv2h_cpg_plldsi_set_rate,
};
static const struct clk_ops rzv2h_cpg_pll_ops = {
.is_enabled = rzv2h_cpg_pll_clk_is_enabled,
.enable = rzv2h_cpg_pll_clk_enable,
@@ -263,6 +751,10 @@ rzv2h_cpg_pll_clk_register(const struct cpg_core_clk *core,
if (!pll_clk)
return ERR_PTR(-ENOMEM);
if (core->type == CLK_TYPE_PLLDSI)
priv->pll_dsi_info[core->cfg.pll.instance].pll_dsi_limits =
core->cfg.pll.limits;
parent_name = __clk_get_name(parent);
init.name = core->name;
init.ops = ops;
@@ -587,11 +1079,17 @@ rzv2h_cpg_register_core_clk(const struct cpg_core_clk *core,
case CLK_TYPE_SMUX:
clk = rzv2h_cpg_mux_clk_register(core, priv);
break;
case CLK_TYPE_PLLDSI:
clk = rzv2h_cpg_pll_clk_register(core, priv, &rzv2h_cpg_plldsi_ops);
break;
case CLK_TYPE_PLLDSI_DIV:
clk = rzv2h_cpg_plldsi_div_clk_register(core, priv);
break;
default:
goto fail;
}
if (IS_ERR_OR_NULL(clk))
if (IS_ERR(clk))
goto fail;
dev_dbg(dev, "Core clock %pC at %lu Hz\n", clk, clk_get_rate(clk));

View File

@@ -16,20 +16,28 @@
*
* @offset: STBY register offset
* @has_clkn: Flag to indicate if CLK1/2 are accessible or not
* @instance: PLL instance number
*/
struct pll {
unsigned int offset:9;
unsigned int has_clkn:1;
unsigned int instance:2;
const struct rzv2h_pll_limits *limits;
};
#define PLL_PACK(_offset, _has_clkn) \
#define PLL_PACK_LIMITS(_offset, _has_clkn, _instance, _limits) \
((struct pll){ \
.offset = _offset, \
.has_clkn = _has_clkn \
.has_clkn = _has_clkn, \
.instance = _instance, \
.limits = _limits \
})
#define PLLCA55 PLL_PACK(0x60, 1)
#define PLLGPU PLL_PACK(0x120, 1)
#define PLL_PACK(_offset, _has_clkn, _instance) \
PLL_PACK_LIMITS(_offset, _has_clkn, _instance, NULL)
#define PLLCA55 PLL_PACK(0x60, 1, 0)
#define PLLGPU PLL_PACK(0x120, 1, 0)
/**
* struct ddiv - Structure for dynamic switching divider
@@ -115,9 +123,11 @@ struct fixed_mod_conf {
#define CPG_SSEL1 (0x304)
#define CPG_CDDIV0 (0x400)
#define CPG_CDDIV1 (0x404)
#define CPG_CDDIV2 (0x408)
#define CPG_CDDIV3 (0x40C)
#define CPG_CDDIV4 (0x410)
#define CPG_CSDIV0 (0x500)
#define CPG_CSDIV1 (0x504)
#define CDDIV0_DIVCTL1 DDIV_PACK(CPG_CDDIV0, 4, 3, 1)
#define CDDIV0_DIVCTL2 DDIV_PACK(CPG_CDDIV0, 8, 3, 2)
@@ -125,6 +135,7 @@ struct fixed_mod_conf {
#define CDDIV1_DIVCTL1 DDIV_PACK(CPG_CDDIV1, 4, 2, 5)
#define CDDIV1_DIVCTL2 DDIV_PACK(CPG_CDDIV1, 8, 2, 6)
#define CDDIV1_DIVCTL3 DDIV_PACK(CPG_CDDIV1, 12, 2, 7)
#define CDDIV2_DIVCTL3 DDIV_PACK(CPG_CDDIV2, 12, 3, 11)
#define CDDIV3_DIVCTL1 DDIV_PACK(CPG_CDDIV3, 4, 3, 13)
#define CDDIV3_DIVCTL2 DDIV_PACK(CPG_CDDIV3, 8, 3, 14)
#define CDDIV3_DIVCTL3 DDIV_PACK(CPG_CDDIV3, 12, 1, 15)
@@ -134,7 +145,9 @@ struct fixed_mod_conf {
#define CSDIV0_DIVCTL0 DDIV_PACK(CPG_CSDIV0, 0, 2, CSDIV_NO_MON)
#define CSDIV0_DIVCTL1 DDIV_PACK(CPG_CSDIV0, 4, 2, CSDIV_NO_MON)
#define CSDIV0_DIVCTL2 DDIV_PACK(CPG_CSDIV0, 8, 2, CSDIV_NO_MON)
#define CSDIV0_DIVCTL3 DDIV_PACK_NO_RMW(CPG_CSDIV0, 12, 2, CSDIV_NO_MON)
#define CSDIV1_DIVCTL2 DDIV_PACK(CPG_CSDIV1, 8, 4, CSDIV_NO_MON)
#define SSEL0_SELCTL2 SMUX_PACK(CPG_SSEL0, 8, 1)
#define SSEL0_SELCTL3 SMUX_PACK(CPG_SSEL0, 12, 1)
@@ -188,6 +201,8 @@ enum clk_types {
CLK_TYPE_PLL,
CLK_TYPE_DDIV, /* Dynamic Switching Divider */
CLK_TYPE_SMUX, /* Static Mux */
CLK_TYPE_PLLDSI, /* PLLDSI */
CLK_TYPE_PLLDSI_DIV, /* PLLDSI divider */
};
#define DEF_TYPE(_name, _id, _type...) \
@@ -218,6 +233,14 @@ enum clk_types {
.num_parents = ARRAY_SIZE(_parent_names), \
.flag = CLK_SET_RATE_PARENT, \
.mux_flags = CLK_MUX_HIWORD_MASK)
#define DEF_PLLDSI(_name, _id, _parent, _pll_packed) \
DEF_TYPE(_name, _id, CLK_TYPE_PLLDSI, .parent = _parent, .cfg.pll = _pll_packed)
#define DEF_PLLDSI_DIV(_name, _id, _parent, _ddiv_packed, _dtable) \
DEF_TYPE(_name, _id, CLK_TYPE_PLLDSI_DIV, \
.cfg.ddiv = _ddiv_packed, \
.dtable = _dtable, \
.parent = _parent, \
.flag = CLK_SET_RATE_PARENT)
/**
* struct rzv2h_mod_clk - Module Clocks definitions

View File

@@ -95,6 +95,16 @@ config EXYNOS_CLKOUT
status of the certains clocks from SoC, but it could also be tied to
other devices as an input clock.
config EXYNOS_ACPM_CLK
tristate "Clock driver controlled via ACPM interface"
depends on EXYNOS_ACPM_PROTOCOL || (COMPILE_TEST && !EXYNOS_ACPM_PROTOCOL)
help
This driver provides support for clocks that are controlled by
firmware that implements the ACPM interface.
This driver uses the ACPM interface to interact with the firmware
providing all the clock controlls.
config TESLA_FSD_COMMON_CLK
bool "Tesla FSD clock controller support" if COMPILE_TEST
depends on COMMON_CLK_SAMSUNG

View File

@@ -28,6 +28,7 @@ obj-$(CONFIG_EXYNOS_ARM64_COMMON_CLK) += clk-exynos990.o
obj-$(CONFIG_EXYNOS_ARM64_COMMON_CLK) += clk-exynosautov9.o
obj-$(CONFIG_EXYNOS_ARM64_COMMON_CLK) += clk-exynosautov920.o
obj-$(CONFIG_EXYNOS_ARM64_COMMON_CLK) += clk-gs101.o
obj-$(CONFIG_EXYNOS_ACPM_CLK) += clk-acpm.o
obj-$(CONFIG_S3C64XX_COMMON_CLK) += clk-s3c64xx.o
obj-$(CONFIG_S5PV210_COMMON_CLK) += clk-s5pv210.o clk-s5pv210-audss.o
obj-$(CONFIG_TESLA_FSD_COMMON_CLK) += clk-fsd.o

View File

@@ -0,0 +1,185 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Samsung Exynos ACPM protocol based clock driver.
*
* Copyright 2025 Linaro Ltd.
*/
#include <linux/array_size.h>
#include <linux/clk-provider.h>
#include <linux/container_of.h>
#include <linux/device/devres.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/firmware/samsung/exynos-acpm-protocol.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/types.h>
struct acpm_clk {
u32 id;
struct clk_hw hw;
unsigned int mbox_chan_id;
const struct acpm_handle *handle;
};
struct acpm_clk_variant {
const char *name;
};
struct acpm_clk_driver_data {
const struct acpm_clk_variant *clks;
unsigned int nr_clks;
unsigned int mbox_chan_id;
};
#define to_acpm_clk(clk) container_of(clk, struct acpm_clk, hw)
#define ACPM_CLK(cname) \
{ \
.name = cname, \
}
static const struct acpm_clk_variant gs101_acpm_clks[] = {
ACPM_CLK("mif"),
ACPM_CLK("int"),
ACPM_CLK("cpucl0"),
ACPM_CLK("cpucl1"),
ACPM_CLK("cpucl2"),
ACPM_CLK("g3d"),
ACPM_CLK("g3dl2"),
ACPM_CLK("tpu"),
ACPM_CLK("intcam"),
ACPM_CLK("tnr"),
ACPM_CLK("cam"),
ACPM_CLK("mfc"),
ACPM_CLK("disp"),
ACPM_CLK("bo"),
};
static const struct acpm_clk_driver_data acpm_clk_gs101 = {
.clks = gs101_acpm_clks,
.nr_clks = ARRAY_SIZE(gs101_acpm_clks),
.mbox_chan_id = 0,
};
static unsigned long acpm_clk_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct acpm_clk *clk = to_acpm_clk(hw);
return clk->handle->ops.dvfs_ops.get_rate(clk->handle,
clk->mbox_chan_id, clk->id);
}
static int acpm_clk_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
/*
* We can't figure out what rate it will be, so just return the
* rate back to the caller. acpm_clk_recalc_rate() will be called
* after the rate is set and we'll know what rate the clock is
* running at then.
*/
return 0;
}
static int acpm_clk_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct acpm_clk *clk = to_acpm_clk(hw);
return clk->handle->ops.dvfs_ops.set_rate(clk->handle,
clk->mbox_chan_id, clk->id, rate);
}
static const struct clk_ops acpm_clk_ops = {
.recalc_rate = acpm_clk_recalc_rate,
.determine_rate = acpm_clk_determine_rate,
.set_rate = acpm_clk_set_rate,
};
static int acpm_clk_register(struct device *dev, struct acpm_clk *aclk,
const char *name)
{
struct clk_init_data init = {};
init.name = name;
init.ops = &acpm_clk_ops;
aclk->hw.init = &init;
return devm_clk_hw_register(dev, &aclk->hw);
}
static int acpm_clk_probe(struct platform_device *pdev)
{
const struct acpm_handle *acpm_handle;
struct clk_hw_onecell_data *clk_data;
struct clk_hw **hws;
struct device *dev = &pdev->dev;
struct acpm_clk *aclks;
unsigned int mbox_chan_id;
int i, err, count;
acpm_handle = devm_acpm_get_by_node(dev, dev->parent->of_node);
if (IS_ERR(acpm_handle))
return dev_err_probe(dev, PTR_ERR(acpm_handle),
"Failed to get acpm handle\n");
count = acpm_clk_gs101.nr_clks;
mbox_chan_id = acpm_clk_gs101.mbox_chan_id;
clk_data = devm_kzalloc(dev, struct_size(clk_data, hws, count),
GFP_KERNEL);
if (!clk_data)
return -ENOMEM;
clk_data->num = count;
hws = clk_data->hws;
aclks = devm_kcalloc(dev, count, sizeof(*aclks), GFP_KERNEL);
if (!aclks)
return -ENOMEM;
for (i = 0; i < count; i++) {
struct acpm_clk *aclk = &aclks[i];
/*
* The code assumes the clock IDs start from zero,
* are sequential and do not have gaps.
*/
aclk->id = i;
aclk->handle = acpm_handle;
aclk->mbox_chan_id = mbox_chan_id;
hws[i] = &aclk->hw;
err = acpm_clk_register(dev, aclk,
acpm_clk_gs101.clks[i].name);
if (err)
return dev_err_probe(dev, err,
"Failed to register clock\n");
}
return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
clk_data);
}
static const struct platform_device_id acpm_clk_id[] = {
{ "gs101-acpm-clk" },
{}
};
MODULE_DEVICE_TABLE(platform, acpm_clk_id);
static struct platform_driver acpm_clk_driver = {
.driver = {
.name = "acpm-clocks",
},
.probe = acpm_clk_probe,
.id_table = acpm_clk_id,
};
module_platform_driver(acpm_clk_driver);
MODULE_AUTHOR("Tudor Ambarus <tudor.ambarus@linaro.org>");
MODULE_DESCRIPTION("Samsung Exynos ACPM clock driver");
MODULE_LICENSE("GPL");

View File

@@ -175,6 +175,7 @@ static int exynos_clkout_probe(struct platform_device *pdev)
clkout->mux.shift = EXYNOS_CLKOUT_MUX_SHIFT;
clkout->mux.lock = &clkout->slock;
clkout->data.num = EXYNOS_CLKOUT_NR_CLKS;
clkout->data.hws[0] = clk_hw_register_composite(NULL, "clkout",
parent_names, parent_count, &clkout->mux.hw,
&clk_mux_ops, NULL, NULL, &clkout->gate.hw,
@@ -185,7 +186,6 @@ static int exynos_clkout_probe(struct platform_device *pdev)
goto err_unmap;
}
clkout->data.num = EXYNOS_CLKOUT_NR_CLKS;
ret = of_clk_add_hw_provider(clkout->np, of_clk_hw_onecell_get, &clkout->data);
if (ret)
goto err_clk_unreg;

View File

@@ -27,6 +27,8 @@
#define CLKS_NR_HSI0 (CLK_DOUT_HSI0_PCIE_APB + 1)
#define CLKS_NR_HSI1 (CLK_MOUT_HSI1_USBDRD + 1)
#define CLKS_NR_HSI2 (CLK_DOUT_HSI2_ETHERNET_PTP + 1)
#define CLKS_NR_M2M (CLK_DOUT_M2M_NOCP + 1)
#define CLKS_NR_MFC (CLK_DOUT_MFC_NOCP + 1)
/* ---- CMU_TOP ------------------------------------------------------------ */
@@ -1821,6 +1823,88 @@ static const struct samsung_cmu_info hsi2_cmu_info __initconst = {
.clk_name = "noc",
};
/* ---- CMU_M2M --------------------------------------------------------- */
/* Register Offset definitions for CMU_M2M (0x1a800000) */
#define PLL_CON0_MUX_CLKCMU_M2M_JPEG_USER 0x600
#define PLL_CON0_MUX_CLKCMU_M2M_NOC_USER 0x610
#define CLK_CON_DIV_DIV_CLK_M2M_NOCP 0x1800
static const unsigned long m2m_clk_regs[] __initconst = {
PLL_CON0_MUX_CLKCMU_M2M_JPEG_USER,
PLL_CON0_MUX_CLKCMU_M2M_NOC_USER,
CLK_CON_DIV_DIV_CLK_M2M_NOCP,
};
/* List of parent clocks for Muxes in CMU_M2M */
PNAME(mout_clkcmu_m2m_noc_user_p) = { "oscclk", "dout_clkcmu_m2m_noc" };
PNAME(mout_clkcmu_m2m_jpeg_user_p) = { "oscclk", "dout_clkcmu_m2m_jpeg" };
static const struct samsung_mux_clock m2m_mux_clks[] __initconst = {
MUX(CLK_MOUT_M2M_JPEG_USER, "mout_clkcmu_m2m_jpeg_user",
mout_clkcmu_m2m_jpeg_user_p, PLL_CON0_MUX_CLKCMU_M2M_JPEG_USER, 4, 1),
MUX(CLK_MOUT_M2M_NOC_USER, "mout_clkcmu_m2m_noc_user",
mout_clkcmu_m2m_noc_user_p, PLL_CON0_MUX_CLKCMU_M2M_NOC_USER, 4, 1),
};
static const struct samsung_div_clock m2m_div_clks[] __initconst = {
DIV(CLK_DOUT_M2M_NOCP, "dout_m2m_nocp",
"mout_clkcmu_m2m_noc_user", CLK_CON_DIV_DIV_CLK_M2M_NOCP,
0, 3),
};
static const struct samsung_cmu_info m2m_cmu_info __initconst = {
.mux_clks = m2m_mux_clks,
.nr_mux_clks = ARRAY_SIZE(m2m_mux_clks),
.div_clks = m2m_div_clks,
.nr_div_clks = ARRAY_SIZE(m2m_div_clks),
.nr_clk_ids = CLKS_NR_M2M,
.clk_regs = m2m_clk_regs,
.nr_clk_regs = ARRAY_SIZE(m2m_clk_regs),
.clk_name = "noc",
};
/* ---- CMU_MFC --------------------------------------------------------- */
/* Register Offset definitions for CMU_MFC (0x19c00000) */
#define PLL_CON0_MUX_CLKCMU_MFC_MFC_USER 0x600
#define PLL_CON0_MUX_CLKCMU_MFC_WFD_USER 0x610
#define CLK_CON_DIV_DIV_CLK_MFC_NOCP 0x1800
static const unsigned long mfc_clk_regs[] __initconst = {
PLL_CON0_MUX_CLKCMU_MFC_MFC_USER,
PLL_CON0_MUX_CLKCMU_MFC_WFD_USER,
CLK_CON_DIV_DIV_CLK_MFC_NOCP,
};
/* List of parent clocks for Muxes in CMU_MFC */
PNAME(mout_clkcmu_mfc_mfc_user_p) = { "oscclk", "dout_clkcmu_mfc_mfc" };
PNAME(mout_clkcmu_mfc_wfd_user_p) = { "oscclk", "dout_clkcmu_mfc_wfd" };
static const struct samsung_mux_clock mfc_mux_clks[] __initconst = {
MUX(CLK_MOUT_MFC_MFC_USER, "mout_clkcmu_mfc_mfc_user",
mout_clkcmu_mfc_mfc_user_p, PLL_CON0_MUX_CLKCMU_MFC_MFC_USER, 4, 1),
MUX(CLK_MOUT_MFC_WFD_USER, "mout_clkcmu_mfc_wfd_user",
mout_clkcmu_mfc_wfd_user_p, PLL_CON0_MUX_CLKCMU_MFC_WFD_USER, 4, 1),
};
static const struct samsung_div_clock mfc_div_clks[] __initconst = {
DIV(CLK_DOUT_MFC_NOCP, "dout_mfc_nocp",
"mout_clkcmu_mfc_mfc_user", CLK_CON_DIV_DIV_CLK_MFC_NOCP,
0, 3),
};
static const struct samsung_cmu_info mfc_cmu_info __initconst = {
.mux_clks = mfc_mux_clks,
.nr_mux_clks = ARRAY_SIZE(mfc_mux_clks),
.div_clks = mfc_div_clks,
.nr_div_clks = ARRAY_SIZE(mfc_div_clks),
.nr_clk_ids = CLKS_NR_MFC,
.clk_regs = mfc_clk_regs,
.nr_clk_regs = ARRAY_SIZE(mfc_clk_regs),
.clk_name = "noc",
};
static int __init exynosautov920_cmu_probe(struct platform_device *pdev)
{
const struct samsung_cmu_info *info;
@@ -1851,6 +1935,12 @@ static const struct of_device_id exynosautov920_cmu_of_match[] = {
}, {
.compatible = "samsung,exynosautov920-cmu-hsi2",
.data = &hsi2_cmu_info,
}, {
.compatible = "samsung,exynosautov920-cmu-m2m",
.data = &m2m_cmu_info,
}, {
.compatible = "samsung,exynosautov920-cmu-mfc",
.data = &mfc_cmu_info,
},
{ }
};

View File

@@ -11,14 +11,12 @@
#include <linux/iopoll.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/timekeeping.h>
#include <linux/clk-provider.h>
#include <linux/io.h>
#include "clk.h"
#include "clk-pll.h"
#define PLL_TIMEOUT_US 20000U
#define PLL_TIMEOUT_LOOPS 1000000U
#define PLL_TIMEOUT_LOOPS 20000U
struct samsung_clk_pll {
struct clk_hw hw;
@@ -71,20 +69,11 @@ static int samsung_pll_determine_rate(struct clk_hw *hw,
return 0;
}
static bool pll_early_timeout = true;
static int __init samsung_pll_disable_early_timeout(void)
{
pll_early_timeout = false;
return 0;
}
arch_initcall(samsung_pll_disable_early_timeout);
/* Wait until the PLL is locked */
static int samsung_pll_lock_wait(struct samsung_clk_pll *pll,
unsigned int reg_mask)
{
int i, ret;
int ret;
u32 val;
/*
@@ -93,25 +82,15 @@ static int samsung_pll_lock_wait(struct samsung_clk_pll *pll,
* initialized, another when the timekeeping is suspended. udelay() also
* cannot be used when the clocksource is not running on arm64, since
* the current timer is used as cycle counter. So a simple busy loop
* is used here in that special cases. The limit of iterations has been
* derived from experimental measurements of various PLLs on multiple
* Exynos SoC variants. Single register read time was usually in range
* 0.4...1.5 us, never less than 0.4 us.
* is used here.
* The limit of iterations has been derived from experimental
* measurements of various PLLs on multiple Exynos SoC variants. Single
* register read time was usually in range 0.4...1.5 us, never less than
* 0.4 us.
*/
if (pll_early_timeout || timekeeping_suspended) {
i = PLL_TIMEOUT_LOOPS;
while (i-- > 0) {
if (readl_relaxed(pll->con_reg) & reg_mask)
return 0;
cpu_relax();
}
ret = -ETIMEDOUT;
} else {
ret = readl_relaxed_poll_timeout_atomic(pll->con_reg, val,
val & reg_mask, 0, PLL_TIMEOUT_US);
}
ret = readl_relaxed_poll_timeout_atomic(pll->con_reg, val,
val & reg_mask, 0,
PLL_TIMEOUT_LOOPS);
if (ret < 0)
pr_err("Could not lock PLL %s\n", clk_hw_get_name(&pll->hw));

View File

@@ -1018,6 +1018,8 @@ static int spacemit_ccu_register(struct device *dev,
if (!clk_data)
return -ENOMEM;
clk_data->num = data->num;
for (i = 0; i < data->num; i++) {
struct clk_hw *hw = data->hws[i];
struct ccu_common *common;
@@ -1044,8 +1046,6 @@ static int spacemit_ccu_register(struct device *dev,
clk_data->hws[i] = hw;
}
clk_data->num = data->num;
ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, clk_data);
if (ret)
dev_err(dev, "failed to add clock hardware provider (%d)\n", ret);

View File

@@ -220,4 +220,4 @@ extern const struct clk_ops spacemit_ccu_div_gate_ops;
extern const struct clk_ops spacemit_ccu_mux_gate_ops;
extern const struct clk_ops spacemit_ccu_mux_div_ops;
extern const struct clk_ops spacemit_ccu_mux_div_gate_ops;
#endif /* _CCU_DIV_H_ */
#endif /* _CCU_MIX_H_ */

View File

@@ -2021,17 +2021,13 @@ MODULE_DEVICE_TABLE(of, sprd_sc9860_clk_ids);
static int sc9860_clk_probe(struct platform_device *pdev)
{
const struct of_device_id *match;
const struct sprd_clk_desc *desc;
int ret;
match = of_match_node(sprd_sc9860_clk_ids, pdev->dev.of_node);
if (!match) {
pr_err("%s: of_match_node() failed", __func__);
desc = device_get_match_data(&pdev->dev);
if (!desc)
return -ENODEV;
}
desc = match->data;
ret = sprd_clk_regmap_init(pdev, desc);
if (ret)
return ret;

View File

@@ -1,4 +1,6 @@
# SPDX-License-Identifier: GPL-2.0-only
acpm-protocol-objs := exynos-acpm.o exynos-acpm-pmic.o
acpm-protocol-objs := exynos-acpm.o
acpm-protocol-objs += exynos-acpm-pmic.o
acpm-protocol-objs += exynos-acpm-dvfs.o
obj-$(CONFIG_EXYNOS_ACPM_PROTOCOL) += acpm-protocol.o

View File

@@ -0,0 +1,80 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright 2020 Samsung Electronics Co., Ltd.
* Copyright 2020 Google LLC.
* Copyright 2025 Linaro Ltd.
*/
#include <linux/bitfield.h>
#include <linux/firmware/samsung/exynos-acpm-protocol.h>
#include <linux/ktime.h>
#include <linux/types.h>
#include <linux/units.h>
#include "exynos-acpm.h"
#include "exynos-acpm-dvfs.h"
#define ACPM_DVFS_ID GENMASK(11, 0)
#define ACPM_DVFS_REQ_TYPE GENMASK(15, 0)
#define ACPM_DVFS_FREQ_REQ 0
#define ACPM_DVFS_FREQ_GET 1
static void acpm_dvfs_set_xfer(struct acpm_xfer *xfer, u32 *cmd, size_t cmdlen,
unsigned int acpm_chan_id, bool response)
{
xfer->acpm_chan_id = acpm_chan_id;
xfer->txd = cmd;
xfer->txlen = cmdlen;
if (response) {
xfer->rxd = cmd;
xfer->rxlen = cmdlen;
}
}
static void acpm_dvfs_init_set_rate_cmd(u32 cmd[4], unsigned int clk_id,
unsigned long rate)
{
cmd[0] = FIELD_PREP(ACPM_DVFS_ID, clk_id);
cmd[1] = rate / HZ_PER_KHZ;
cmd[2] = FIELD_PREP(ACPM_DVFS_REQ_TYPE, ACPM_DVFS_FREQ_REQ);
cmd[3] = ktime_to_ms(ktime_get());
}
int acpm_dvfs_set_rate(const struct acpm_handle *handle,
unsigned int acpm_chan_id, unsigned int clk_id,
unsigned long rate)
{
struct acpm_xfer xfer = {0};
u32 cmd[4];
acpm_dvfs_init_set_rate_cmd(cmd, clk_id, rate);
acpm_dvfs_set_xfer(&xfer, cmd, sizeof(cmd), acpm_chan_id, false);
return acpm_do_xfer(handle, &xfer);
}
static void acpm_dvfs_init_get_rate_cmd(u32 cmd[4], unsigned int clk_id)
{
cmd[0] = FIELD_PREP(ACPM_DVFS_ID, clk_id);
cmd[2] = FIELD_PREP(ACPM_DVFS_REQ_TYPE, ACPM_DVFS_FREQ_GET);
cmd[3] = ktime_to_ms(ktime_get());
}
unsigned long acpm_dvfs_get_rate(const struct acpm_handle *handle,
unsigned int acpm_chan_id, unsigned int clk_id)
{
struct acpm_xfer xfer;
unsigned int cmd[4] = {0};
int ret;
acpm_dvfs_init_get_rate_cmd(cmd, clk_id);
acpm_dvfs_set_xfer(&xfer, cmd, sizeof(cmd), acpm_chan_id, true);
ret = acpm_do_xfer(handle, &xfer);
if (ret)
return 0;
return xfer.rxd[1] * HZ_PER_KHZ;
}

View File

@@ -0,0 +1,21 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright 2020 Samsung Electronics Co., Ltd.
* Copyright 2020 Google LLC.
* Copyright 2025 Linaro Ltd.
*/
#ifndef __EXYNOS_ACPM_DVFS_H__
#define __EXYNOS_ACPM_DVFS_H__
#include <linux/types.h>
struct acpm_handle;
int acpm_dvfs_set_rate(const struct acpm_handle *handle,
unsigned int acpm_chan_id, unsigned int id,
unsigned long rate);
unsigned long acpm_dvfs_get_rate(const struct acpm_handle *handle,
unsigned int acpm_chan_id,
unsigned int clk_id);
#endif /* __EXYNOS_ACPM_DVFS_H__ */

View File

@@ -29,6 +29,7 @@
#include <linux/types.h>
#include "exynos-acpm.h"
#include "exynos-acpm-dvfs.h"
#include "exynos-acpm-pmic.h"
#define ACPM_PROTOCOL_SEQNUM GENMASK(21, 16)
@@ -176,9 +177,11 @@ struct acpm_info {
/**
* struct acpm_match_data - of_device_id data.
* @initdata_base: offset in SRAM where the channels configuration resides.
* @acpm_clk_dev_name: base name for the ACPM clocks device that we're registering.
*/
struct acpm_match_data {
loff_t initdata_base;
const char *acpm_clk_dev_name;
};
#define client_to_acpm_chan(c) container_of(c, struct acpm_chan, cl)
@@ -590,8 +593,12 @@ static int acpm_channels_init(struct acpm_info *acpm)
*/
static void acpm_setup_ops(struct acpm_info *acpm)
{
struct acpm_dvfs_ops *dvfs_ops = &acpm->handle.ops.dvfs_ops;
struct acpm_pmic_ops *pmic_ops = &acpm->handle.ops.pmic_ops;
dvfs_ops->set_rate = acpm_dvfs_set_rate;
dvfs_ops->get_rate = acpm_dvfs_get_rate;
pmic_ops->read_reg = acpm_pmic_read_reg;
pmic_ops->bulk_read = acpm_pmic_bulk_read;
pmic_ops->write_reg = acpm_pmic_write_reg;
@@ -599,9 +606,15 @@ static void acpm_setup_ops(struct acpm_info *acpm)
pmic_ops->update_reg = acpm_pmic_update_reg;
}
static void acpm_clk_pdev_unregister(void *data)
{
platform_device_unregister(data);
}
static int acpm_probe(struct platform_device *pdev)
{
const struct acpm_match_data *match_data;
struct platform_device *acpm_clk_pdev;
struct device *dev = &pdev->dev;
struct device_node *shmem;
struct acpm_info *acpm;
@@ -642,6 +655,18 @@ static int acpm_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, acpm);
acpm_clk_pdev = platform_device_register_data(dev,
match_data->acpm_clk_dev_name,
PLATFORM_DEVID_NONE, NULL, 0);
if (IS_ERR(acpm_clk_pdev))
return dev_err_probe(dev, PTR_ERR(acpm_clk_pdev),
"Failed to register ACPM clocks device.\n");
ret = devm_add_action_or_reset(dev, acpm_clk_pdev_unregister,
acpm_clk_pdev);
if (ret)
return dev_err_probe(dev, ret, "Failed to add devm action.\n");
return devm_of_platform_populate(dev);
}
@@ -741,6 +766,7 @@ EXPORT_SYMBOL_GPL(devm_acpm_get_by_node);
static const struct acpm_match_data acpm_gs101 = {
.initdata_base = ACPM_GS101_INITDATA_BASE,
.acpm_clk_dev_name = "gs101-acpm-clk",
};
static const struct of_device_id acpm_match[] = {

View File

@@ -0,0 +1,26 @@
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
/*
* Copyright 2025 Linaro Ltd.
*
* Device Tree binding constants for Google gs101 ACPM clock controller.
*/
#ifndef _DT_BINDINGS_CLOCK_GOOGLE_GS101_ACPM_H
#define _DT_BINDINGS_CLOCK_GOOGLE_GS101_ACPM_H
#define GS101_CLK_ACPM_DVFS_MIF 0
#define GS101_CLK_ACPM_DVFS_INT 1
#define GS101_CLK_ACPM_DVFS_CPUCL0 2
#define GS101_CLK_ACPM_DVFS_CPUCL1 3
#define GS101_CLK_ACPM_DVFS_CPUCL2 4
#define GS101_CLK_ACPM_DVFS_G3D 5
#define GS101_CLK_ACPM_DVFS_G3DL2 6
#define GS101_CLK_ACPM_DVFS_TPU 7
#define GS101_CLK_ACPM_DVFS_INTCAM 8
#define GS101_CLK_ACPM_DVFS_TNR 9
#define GS101_CLK_ACPM_DVFS_CAM 10
#define GS101_CLK_ACPM_DVFS_MFC 11
#define GS101_CLK_ACPM_DVFS_DISP 12
#define GS101_CLK_ACPM_DVFS_BO 13
#endif /* _DT_BINDINGS_CLOCK_GOOGLE_GS101_ACPM_H */

View File

@@ -51,5 +51,6 @@
#define R8A779A0_CLK_CBFUSA 40
#define R8A779A0_CLK_R 41
#define R8A779A0_CLK_OSC 42
#define R8A779A0_CLK_ZG 43
#endif /* __DT_BINDINGS_CLOCK_R8A779A0_CPG_MSSR_H__ */

View File

@@ -22,5 +22,7 @@
#define R9A09G047_GBETH_1_CLK_PTP_REF_I 11
#define R9A09G047_USB3_0_REF_ALT_CLK_P 12
#define R9A09G047_USB3_0_CLKCORE 13
#define R9A09G047_USB2_0_CLK_CORE0 14
#define R9A09G047_USB2_0_CLK_CORE1 15
#endif /* __DT_BINDINGS_CLOCK_RENESAS_R9A09G047_CPG_H__ */

View File

@@ -21,5 +21,7 @@
#define R9A09G056_GBETH_0_CLK_PTP_REF_I 10
#define R9A09G056_GBETH_1_CLK_PTP_REF_I 11
#define R9A09G056_SPI_CLK_SPI 12
#define R9A09G056_USB3_0_REF_ALT_CLK_P 13
#define R9A09G056_USB3_0_CLKCORE 14
#endif /* __DT_BINDINGS_CLOCK_RENESAS_R9A09G056_CPG_H__ */

View File

@@ -22,5 +22,9 @@
#define R9A09G057_GBETH_0_CLK_PTP_REF_I 11
#define R9A09G057_GBETH_1_CLK_PTP_REF_I 12
#define R9A09G057_SPI_CLK_SPI 13
#define R9A09G057_USB3_0_REF_ALT_CLK_P 14
#define R9A09G057_USB3_0_CLKCORE 15
#define R9A09G057_USB3_1_REF_ALT_CLK_P 16
#define R9A09G057_USB3_1_CLKCORE 17
#endif /* __DT_BINDINGS_CLOCK_RENESAS_R9A09G057_CPG_H__ */

View File

@@ -295,4 +295,14 @@
#define CLK_DOUT_HSI2_ETHERNET 6
#define CLK_DOUT_HSI2_ETHERNET_PTP 7
/* CMU_M2M */
#define CLK_MOUT_M2M_JPEG_USER 1
#define CLK_MOUT_M2M_NOC_USER 2
#define CLK_DOUT_M2M_NOCP 3
/* CMU_MFC */
#define CLK_MOUT_MFC_MFC_USER 1
#define CLK_MOUT_MFC_WFD_USER 2
#define CLK_DOUT_MFC_NOCP 3
#endif /* _DT_BINDINGS_CLOCK_EXYNOSAUTOV920_H */

View File

@@ -0,0 +1,61 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (C) 2024 iopsys Software Solutions AB.
* Copyright (C) 2025 Genexis AB.
*
* Author: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
*
* based on
* include/dt-bindings/reset/airoha,en7581-reset.h
* by Lorenzo Bianconi <lorenzo@kernel.org>
*/
#ifndef __DT_BINDINGS_RESET_CONTROLLER_AIROHA_EN7523_H_
#define __DT_BINDINGS_RESET_CONTROLLER_AIROHA_EN7523_H_
/* RST_CTRL2 */
#define EN7523_XPON_PHY_RST 0
#define EN7523_XSI_MAC_RST 1
#define EN7523_XSI_PHY_RST 2
#define EN7523_NPU_RST 3
#define EN7523_I2S_RST 4
#define EN7523_TRNG_RST 5
#define EN7523_TRNG_MSTART_RST 6
#define EN7523_DUAL_HSI0_RST 7
#define EN7523_DUAL_HSI1_RST 8
#define EN7523_HSI_RST 9
#define EN7523_DUAL_HSI0_MAC_RST 10
#define EN7523_DUAL_HSI1_MAC_RST 11
#define EN7523_HSI_MAC_RST 12
#define EN7523_WDMA_RST 13
#define EN7523_WOE0_RST 14
#define EN7523_WOE1_RST 15
#define EN7523_HSDMA_RST 16
#define EN7523_I2C2RBUS_RST 17
#define EN7523_TDMA_RST 18
/* RST_CTRL1 */
#define EN7523_PCM1_ZSI_ISI_RST 19
#define EN7523_FE_PDMA_RST 20
#define EN7523_FE_QDMA_RST 21
#define EN7523_PCM_SPIWP_RST 22
#define EN7523_CRYPTO_RST 23
#define EN7523_TIMER_RST 24
#define EN7523_PCM1_RST 25
#define EN7523_UART_RST 26
#define EN7523_GPIO_RST 27
#define EN7523_GDMA_RST 28
#define EN7523_I2C_MASTER_RST 29
#define EN7523_PCM2_ZSI_ISI_RST 30
#define EN7523_SFC_RST 31
#define EN7523_UART2_RST 32
#define EN7523_GDMP_RST 33
#define EN7523_FE_RST 34
#define EN7523_USB_HOST_P0_RST 35
#define EN7523_GSW_RST 36
#define EN7523_SFC2_PCM_RST 37
#define EN7523_PCIE0_RST 38
#define EN7523_PCIE1_RST 39
#define EN7523_PCIE_HB_RST 40
#define EN7523_XPON_MAC_RST 41
#endif /* __DT_BINDINGS_RESET_CONTROLLER_AIROHA_EN7523_H_ */

View File

@@ -10,7 +10,9 @@
#ifndef __LINUX_CLK_RENESAS_H_
#define __LINUX_CLK_RENESAS_H_
#include <linux/clk-provider.h>
#include <linux/types.h>
#include <linux/units.h>
struct device;
struct device_node;
@@ -32,4 +34,147 @@ void cpg_mssr_detach_dev(struct generic_pm_domain *unused, struct device *dev);
#define cpg_mssr_attach_dev NULL
#define cpg_mssr_detach_dev NULL
#endif
/**
* struct rzv2h_pll_limits - PLL parameter constraints
*
* This structure defines the minimum and maximum allowed values for
* various parameters used to configure a PLL. These limits ensure
* the PLL operates within valid and stable ranges.
*
* @fout: Output frequency range (in MHz)
* @fout.min: Minimum allowed output frequency
* @fout.max: Maximum allowed output frequency
*
* @fvco: PLL oscillation frequency range (in MHz)
* @fvco.min: Minimum allowed VCO frequency
* @fvco.max: Maximum allowed VCO frequency
*
* @m: Main-divider range
* @m.min: Minimum main-divider value
* @m.max: Maximum main-divider value
*
* @p: Pre-divider range
* @p.min: Minimum pre-divider value
* @p.max: Maximum pre-divider value
*
* @s: Divider range
* @s.min: Minimum divider value
* @s.max: Maximum divider value
*
* @k: Delta-sigma modulator range (signed)
* @k.min: Minimum delta-sigma value
* @k.max: Maximum delta-sigma value
*/
struct rzv2h_pll_limits {
struct {
u32 min;
u32 max;
} fout;
struct {
u32 min;
u32 max;
} fvco;
struct {
u16 min;
u16 max;
} m;
struct {
u8 min;
u8 max;
} p;
struct {
u8 min;
u8 max;
} s;
struct {
s16 min;
s16 max;
} k;
};
/**
* struct rzv2h_pll_pars - PLL configuration parameters
*
* This structure contains the configuration parameters for the
* Phase-Locked Loop (PLL), used to achieve a specific output frequency.
*
* @m: Main divider value
* @p: Pre-divider value
* @s: Output divider value
* @k: Delta-sigma modulation value
* @freq_millihz: Calculated PLL output frequency in millihertz
* @error_millihz: Frequency error from target in millihertz (signed)
*/
struct rzv2h_pll_pars {
u16 m;
u8 p;
u8 s;
s16 k;
u64 freq_millihz;
s64 error_millihz;
};
/**
* struct rzv2h_pll_div_pars - PLL parameters with post-divider
*
* This structure is used for PLLs that include an additional post-divider
* stage after the main PLL block. It contains both the PLL configuration
* parameters and the resulting frequency/error values after the divider.
*
* @pll: Main PLL configuration parameters (see struct rzv2h_pll_pars)
*
* @div: Post-divider configuration and result
* @div.divider_value: Divider applied to the PLL output
* @div.freq_millihz: Output frequency after divider in millihertz
* @div.error_millihz: Frequency error from target in millihertz (signed)
*/
struct rzv2h_pll_div_pars {
struct rzv2h_pll_pars pll;
struct {
u8 divider_value;
u64 freq_millihz;
s64 error_millihz;
} div;
};
#define RZV2H_CPG_PLL_DSI_LIMITS(name) \
static const struct rzv2h_pll_limits (name) = { \
.fout = { .min = 25 * MEGA, .max = 375 * MEGA }, \
.fvco = { .min = 1600 * MEGA, .max = 3200 * MEGA }, \
.m = { .min = 64, .max = 533 }, \
.p = { .min = 1, .max = 4 }, \
.s = { .min = 0, .max = 6 }, \
.k = { .min = -32768, .max = 32767 }, \
} \
#ifdef CONFIG_CLK_RZV2H
bool rzv2h_get_pll_pars(const struct rzv2h_pll_limits *limits,
struct rzv2h_pll_pars *pars, u64 freq_millihz);
bool rzv2h_get_pll_divs_pars(const struct rzv2h_pll_limits *limits,
struct rzv2h_pll_div_pars *pars,
const u8 *table, u8 table_size, u64 freq_millihz);
#else
static inline bool rzv2h_get_pll_pars(const struct rzv2h_pll_limits *limits,
struct rzv2h_pll_pars *pars,
u64 freq_millihz)
{
return false;
}
static inline bool rzv2h_get_pll_divs_pars(const struct rzv2h_pll_limits *limits,
struct rzv2h_pll_div_pars *pars,
const u8 *table, u8 table_size,
u64 freq_millihz)
{
return false;
}
#endif
#endif

View File

@@ -13,6 +13,15 @@
struct acpm_handle;
struct device_node;
struct acpm_dvfs_ops {
int (*set_rate)(const struct acpm_handle *handle,
unsigned int acpm_chan_id, unsigned int clk_id,
unsigned long rate);
unsigned long (*get_rate)(const struct acpm_handle *handle,
unsigned int acpm_chan_id,
unsigned int clk_id);
};
struct acpm_pmic_ops {
int (*read_reg)(const struct acpm_handle *handle,
unsigned int acpm_chan_id, u8 type, u8 reg, u8 chan,
@@ -32,6 +41,7 @@ struct acpm_pmic_ops {
};
struct acpm_ops {
struct acpm_dvfs_ops dvfs_ops;
struct acpm_pmic_ops pmic_ops;
};
@@ -45,7 +55,16 @@ struct acpm_handle {
struct device;
#if IS_ENABLED(CONFIG_EXYNOS_ACPM_PROTOCOL)
const struct acpm_handle *devm_acpm_get_by_node(struct device *dev,
struct device_node *np);
#else
static inline const struct acpm_handle *devm_acpm_get_by_node(struct device *dev,
struct device_node *np)
{
return NULL;
}
#endif
#endif /* __EXYNOS_ACPM_PROTOCOL_H */