Merge branches 'clk-fixes', 'clk-renesas', 'clk-rpi', 'clk-eswin' and 'clk-mediatek' into clk-next

- ESWIN eic700 SoC clk support
 - Econet EN751221 SoC clock/reset support

* clk-fixes:
  clk: spacemit: ccu_mix: fix inverted condition in ccu_mix_trigger_fc()
  clk: microchip: mpfs-ccc: fix out of bounds access during output registration
  clk: qcom: dispcc-sm8450: use RCG2 ops for DPTX1 AUX clock source

* clk-renesas:
  clk: renesas: Add support for RZ/G3L SoC
  dt-bindings: clock: renesas,rzg2l-cpg: Document RZ/G3L SoC
  clk: renesas: rzg2l: Re-enable critical module clocks during resume
  clk: renesas: rzg2l: Add rzg2l_mod_clock_init_mstop_helper()
  clk: renesas: rzg2l: Add helper for mod clock enable/disable
  clk: renesas: r9a0{7g04[34],8g045}: Add critical reset entries
  clk: renesas: rzg2l: Add support for critical resets
  clk: renesas: r9a09g056: Remove entries for WDT{0,2,3}
  clk: renesas: r9a06g032: Enable watchdog reset sources
  clk: renesas: cpg-mssr: Use struct_size() helper
  clk: renesas: r9a09g047: Add PCIe clocks and reset
  clk: renesas: r9a09g057: Add PCIe clocks and reset
  clk: renesas: r9a09g056: Add PCIe clocks and reset
  clk: renesas: r9a09g047: Add entries for the RSPIs
  clk: renesas: r9a09g056: Add clock and reset entries for RTC
  clk: renesas: r9a09g057: Remove entries for WDT{0,2,3}
  clk: renesas: r9a09g056: Fix ordering of module clocks array
  clk: renesas: r9a09g057: Fix ordering of module clocks array

* clk-rpi:
  clk: bcm: rpi: Manage clock rate in prepare/unprepare callbacks

* clk-eswin:
  MAINTAINERS: Add entry for ESWIN EIC7700 clock driver
  clk: eswin: Add eic7700 clock driver
  clk: divider: Add devm_clk_hw_register_divider_parent_data
  dt-bindings: clock: eswin: Documentation for eic7700 SoC

* clk-mediatek:
  clk: airoha: Add econet EN751221 clock/reset support to en7523-scu
  dt-bindings: clock, reset: Add econet EN751221
This commit is contained in:
Stephen Boyd
2026-04-16 10:07:47 -07:00
32 changed files with 3751 additions and 104 deletions
@@ -32,6 +32,7 @@ properties:
- enum:
- airoha,en7523-scu
- airoha,en7581-scu
- econet,en751221-scu
reg:
items:
@@ -67,7 +68,9 @@ allOf:
- if:
properties:
compatible:
const: airoha,en7581-scu
enum:
- airoha,en7581-scu
- econet,en751221-scu
then:
properties:
reg:
@@ -98,3 +101,4 @@ examples:
#reset-cells = <1>;
};
};
@@ -0,0 +1,46 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/clock/eswin,eic7700-clock.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Eswin EIC7700 SoC clock controller
maintainers:
- Yifeng Huang <huangyifeng@eswincomputing.com>
- Xuyang Dong <dongxuyang@eswincomputing.com>
description:
The clock controller generates and supplies clock to all the modules
for eic7700 SoC.
properties:
compatible:
const: eswin,eic7700-clock
reg:
maxItems: 1
clocks:
items:
- description: External 24MHz oscillator clock
'#clock-cells':
const: 1
required:
- compatible
- reg
- clocks
- '#clock-cells'
additionalProperties: false
examples:
- |
clock-controller@51828000 {
compatible = "eswin,eic7700-clock";
reg = <0x51828000 0x300>;
clocks = <&xtal24m>;
#clock-cells = <1>;
};
@@ -28,19 +28,30 @@ properties:
- renesas,r9a07g044-cpg # RZ/G2{L,LC}
- renesas,r9a07g054-cpg # RZ/V2L
- renesas,r9a08g045-cpg # RZ/G3S
- renesas,r9a08g046-cpg # RZ/G3L
- renesas,r9a09g011-cpg # RZ/V2M
reg:
maxItems: 1
clocks:
maxItems: 1
minItems: 1
items:
- description: Clock source to CPG can be either from external clock
input (EXCLK) or crystal oscillator (XIN/XOUT).
- description: ETH0 TXC clock input
- description: ETH0 RXC clock input
- description: ETH1 TXC clock input
- description: ETH1 RXC clock input
clock-names:
description:
Clock source to CPG can be either from external clock input (EXCLK) or
crystal oscillator (XIN/XOUT).
const: extal
minItems: 1
items:
- const: extal
- const: eth0_txc_tx_clk
- const: eth0_rxc_rx_clk
- const: eth1_txc_tx_clk
- const: eth1_rxc_rx_clk
'#clock-cells':
description: |
@@ -74,6 +85,25 @@ required:
- '#power-domain-cells'
- '#reset-cells'
allOf:
- if:
properties:
compatible:
contains:
const: renesas,r9a08g046-cpg
then:
properties:
clocks:
minItems: 5
clock-names:
minItems: 5
else:
properties:
clocks:
maxItems: 1
clock-names:
maxItems: 1
additionalProperties: false
examples:
@@ -61,6 +61,7 @@ select:
- cirrus,ep7209-syscon2
- cirrus,ep7209-syscon3
- cnxt,cx92755-uc
- econet,en751221-chip-scu
- freecom,fsg-cs2-system-controller
- fsl,imx93-aonmix-ns-syscfg
- fsl,imx93-wakeupmix-syscfg
@@ -173,6 +174,7 @@ properties:
- cirrus,ep7209-syscon2
- cirrus,ep7209-syscon3
- cnxt,cx92755-uc
- econet,en751221-chip-scu
- freecom,fsg-cs2-system-controller
- fsl,imx93-aonmix-ns-syscfg
- fsl,imx93-wakeupmix-syscfg
+10
View File
@@ -9096,6 +9096,8 @@ F: arch/mips/boot/dts/econet/
F: arch/mips/econet/
F: drivers/clocksource/timer-econet-en751221.c
F: drivers/irqchip/irq-econet-en751221.c
F: include/dt-bindings/clock/econet,en751221-scu.h
F: include/dt-bindings/reset/econet,en751221-scu.h
ECRYPT FILE SYSTEM
M: Tyler Hicks <code@tyhicks.com>
@@ -9495,6 +9497,14 @@ T: git https://github.com/eswincomputing/linux-next.git
F: Documentation/devicetree/bindings/riscv/eswin.yaml
F: arch/riscv/boot/dts/eswin/
ESWIN EIC7700 CLOCK DRIVER
M: Yifeng Huang <huangyifeng@eswincomputing.com>
M: Xuyang Dong <dongxuyang@eswincomputing.com>
S: Maintained
F: Documentation/devicetree/bindings/clock/eswin,eic7700-clock.yaml
F: drivers/clk/eswin/
F: include/dt-bindings/clock/eswin,eic7700-clock.h
ET131X NETWORK DRIVER
M: Mark Einon <mark.einon@gmail.com>
S: Odd Fixes
+4 -3
View File
@@ -218,13 +218,13 @@ config COMMON_CLK_CS2000_CP
If you say yes here you get support for the CS2000 clock multiplier.
config COMMON_CLK_EN7523
bool "Clock driver for Airoha EN7523 SoC system clocks"
bool "Clock driver for Airoha/EcoNet SoC system clocks"
depends on OF
depends on ARCH_AIROHA || COMPILE_TEST
depends on ARCH_AIROHA || ECONET || COMPILE_TEST
default ARCH_AIROHA
help
This driver provides the fixed clocks and gates present on Airoha
ARM silicon.
and EcoNet silicon.
config COMMON_CLK_EP93XX
tristate "Clock driver for Cirrus Logic ep93xx SoC"
@@ -504,6 +504,7 @@ source "drivers/clk/analogbits/Kconfig"
source "drivers/clk/aspeed/Kconfig"
source "drivers/clk/baikal-t1/Kconfig"
source "drivers/clk/bcm/Kconfig"
source "drivers/clk/eswin/Kconfig"
source "drivers/clk/hisilicon/Kconfig"
source "drivers/clk/imgtec/Kconfig"
source "drivers/clk/imx/Kconfig"
+1
View File
@@ -120,6 +120,7 @@ obj-$(CONFIG_CLK_BAIKAL_T1) += baikal-t1/
obj-y += bcm/
obj-$(CONFIG_ARCH_BERLIN) += berlin/
obj-$(CONFIG_ARCH_DAVINCI) += davinci/
obj-$(CONFIG_COMMON_CLK_ESWIN) += eswin/
obj-$(CONFIG_ARCH_HISI) += hisilicon/
obj-y += imgtec/
obj-y += imx/
+34 -4
View File
@@ -289,16 +289,31 @@ static int raspberrypi_fw_dumb_determine_rate(struct clk_hw *hw,
static int raspberrypi_fw_prepare(struct clk_hw *hw)
{
const struct raspberrypi_clk_data *data = clk_hw_to_data(hw);
struct raspberrypi_clk_variant *variant = data->variant;
struct raspberrypi_clk *rpi = data->rpi;
u32 state = RPI_FIRMWARE_STATE_ENABLE_BIT;
int ret;
ret = raspberrypi_clock_property(rpi->firmware, data,
RPI_FIRMWARE_SET_CLOCK_STATE, &state);
if (ret)
if (ret) {
dev_err_ratelimited(rpi->dev,
"Failed to set clock %s state to on: %d\n",
clk_hw_get_name(hw), ret);
return ret;
}
/*
* For clocks marked with 'maximize', restore the rate to the
* maximum after enabling. This compensates for the rate being
* set to minimum during unprepare (see raspberrypi_fw_unprepare).
*/
if (variant->maximize) {
unsigned long min_rate, max_rate;
clk_hw_get_rate_range(hw, &min_rate, &max_rate);
ret = raspberrypi_fw_set_rate(hw, max_rate, 0);
}
return ret;
}
@@ -307,9 +322,27 @@ static void raspberrypi_fw_unprepare(struct clk_hw *hw)
{
const struct raspberrypi_clk_data *data = clk_hw_to_data(hw);
struct raspberrypi_clk *rpi = data->rpi;
unsigned long min_rate, max_rate;
u32 state = 0;
int ret;
clk_hw_get_rate_range(hw, &min_rate, &max_rate);
/*
* Setting the rate in unprepare is a deviation from the usual CCF
* behavior, where unprepare only gates the clock. However, this is
* needed, as RPI_FIRMWARE_SET_CLOCK_STATE doesn't actually power off
* the clock on current firmware versions. Setting the rate to minimum
* before disabling the clock is the only way to achieve meaningful
* power savings.
*
* This is safe because no consumer should rely on the rate of an
* unprepared clock. Any consumer must call clk_prepare() before use,
* at which point the rate is either restored to maximum (for clocks
* with the 'maximize' flag) or re-established by the consumer.
*/
raspberrypi_fw_set_rate(hw, min_rate, 0);
ret = raspberrypi_clock_property(rpi->firmware, data,
RPI_FIRMWARE_SET_CLOCK_STATE, &state);
if (ret)
@@ -387,9 +420,6 @@ static struct clk_hw *raspberrypi_clk_register(struct raspberrypi_clk *rpi,
}
}
if (variant->maximize)
variant->min_rate = max_rate;
if (variant->min_rate) {
unsigned long rate;
+218 -5
View File
@@ -1,5 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
#include <linux/bitfield.h>
#include <linux/delay.h>
#include <linux/clk-provider.h>
#include <linux/io.h>
@@ -11,6 +12,8 @@
#include <dt-bindings/clock/en7523-clk.h>
#include <dt-bindings/reset/airoha,en7523-reset.h>
#include <dt-bindings/reset/airoha,en7581-reset.h>
#include <dt-bindings/clock/econet,en751221-scu.h>
#include <dt-bindings/reset/econet,en751221-scu.h>
#define RST_NR_PER_BANK 32
@@ -33,15 +36,50 @@
#define REG_RESET_CONTROL_PCIEHB BIT(29)
#define REG_RESET_CONTROL_PCIE1 BIT(27)
#define REG_RESET_CONTROL_PCIE2 BIT(26)
#define REG_HIR 0x064
#define REG_HIR_MASK GENMASK(31, 16)
/* EN7581 */
#define REG_NP_SCU_PCIC 0x88
#define REG_NP_SCU_SSTR 0x9c
#define REG_PCIE_XSI0_SEL_MASK GENMASK(14, 13)
#define REG_PCIE_XSI1_SEL_MASK GENMASK(12, 11)
#define REG_CRYPTO_CLKSRC2 0x20c
/* EN751221 */
#define EN751221_REG_SPI_DIV 0x0cc
#define EN751221_REG_SPI_DIV_MASK GENMASK(31, 8)
#define EN751221_SPI_BASE 500000000
#define EN751221_SPI_BASE_EN7526C 400000000
#define EN751221_SPI_DIV_DEFAULT 40
#define EN751221_REG_BUS 0x284
#define EN751221_REG_BUS_MASK GENMASK(21, 12)
#define EN751221_REG_SSR3 0x094
#define EN751221_REG_SSR3_GSW_MASK GENMASK(9, 8)
#define REG_RST_CTRL2 0x830
#define REG_RST_CTRL1 0x834
#define EN751221_REG_RST_DMT 0x84
#define EN751221_REG_RST_USB 0xec
#define EN751221_MAX_CLKS 5
enum en_hir {
HIR_UNKNOWN = -1,
HIR_TC3169 = 0,
HIR_TC3182 = 1,
HIR_RT65168 = 2,
HIR_RT63165 = 3,
HIR_RT63365 = 4,
HIR_MT751020 = 5,
HIR_MT7505 = 6,
HIR_EN751221 = 7,
HIR_EN7526C = 8,
HIR_EN751627 = 9,
HIR_EN7580 = 10,
HIR_EN7528 = 11,
HIR_EN7523 = 12,
HIR_EN7581 = 13,
HIR_MAX = 14,
};
struct en_clk_desc {
int id;
@@ -93,6 +131,8 @@ static const u32 bus7581_base[] = { 600000000, 540000000 };
static const u32 npu7581_base[] = { 800000000, 750000000, 720000000, 600000000 };
static const u32 crypto_base[] = { 540000000, 480000000 };
static const u32 emmc7581_base[] = { 200000000, 150000000 };
/* EN751221 */
static const u32 gsw751221_base[] = { 500000000, 250000000, 400000000, 200000000 };
static const struct en_clk_desc en7523_base_clks[] = {
{
@@ -300,6 +340,13 @@ static const u16 en7581_rst_ofs[] = {
REG_RST_CTRL1,
};
static const u16 en751221_rst_ofs[] = {
REG_RST_CTRL2,
REG_RST_CTRL1,
EN751221_REG_RST_DMT,
EN751221_REG_RST_USB,
};
static const u16 en7523_rst_map[] = {
/* RST_CTRL2 */
[EN7523_XPON_PHY_RST] = 0,
@@ -405,8 +452,61 @@ static const u16 en7581_rst_map[] = {
[EN7581_XPON_MAC_RST] = RST_NR_PER_BANK + 31,
};
static const u16 en751221_rst_map[] = {
/* RST_CTRL2 */
[EN751221_XPON_PHY_RST] = 0,
[EN751221_GFAST_RST] = 1,
[EN751221_CPU_TIMER2_RST] = 2,
[EN751221_UART3_RST] = 3,
[EN751221_UART4_RST] = 4,
[EN751221_UART5_RST] = 5,
[EN751221_I2C2_RST] = 6,
[EN751221_XSI_MAC_RST] = 7,
[EN751221_XSI_PHY_RST] = 8,
/* RST_CTRL1 */
[EN751221_PCM1_ZSI_ISI_RST] = RST_NR_PER_BANK + 0,
[EN751221_FE_QDMA1_RST] = RST_NR_PER_BANK + 1,
[EN751221_FE_QDMA2_RST] = RST_NR_PER_BANK + 2,
[EN751221_FE_UNZIP_RST] = RST_NR_PER_BANK + 3,
[EN751221_PCM2_RST] = RST_NR_PER_BANK + 4,
[EN751221_PTM_MAC_RST] = RST_NR_PER_BANK + 5,
[EN751221_CRYPTO_RST] = RST_NR_PER_BANK + 6,
[EN751221_SAR_RST] = RST_NR_PER_BANK + 7,
[EN751221_TIMER_RST] = RST_NR_PER_BANK + 8,
[EN751221_INTC_RST] = RST_NR_PER_BANK + 9,
[EN751221_BONDING_RST] = RST_NR_PER_BANK + 10,
[EN751221_PCM1_RST] = RST_NR_PER_BANK + 11,
[EN751221_UART_RST] = RST_NR_PER_BANK + 12,
[EN751221_GPIO_RST] = RST_NR_PER_BANK + 13,
[EN751221_GDMA_RST] = RST_NR_PER_BANK + 14,
[EN751221_I2C_MASTER_RST] = RST_NR_PER_BANK + 16,
[EN751221_PCM2_ZSI_ISI_RST] = RST_NR_PER_BANK + 17,
[EN751221_SFC_RST] = RST_NR_PER_BANK + 18,
[EN751221_UART2_RST] = RST_NR_PER_BANK + 19,
[EN751221_GDMP_RST] = RST_NR_PER_BANK + 20,
[EN751221_FE_RST] = RST_NR_PER_BANK + 21,
[EN751221_USB_HOST_P0_RST] = RST_NR_PER_BANK + 22,
[EN751221_GSW_RST] = RST_NR_PER_BANK + 23,
[EN751221_SFC2_PCM_RST] = RST_NR_PER_BANK + 25,
[EN751221_PCIE0_RST] = RST_NR_PER_BANK + 26,
[EN751221_PCIE1_RST] = RST_NR_PER_BANK + 27,
[EN751221_CPU_TIMER_RST] = RST_NR_PER_BANK + 28,
[EN751221_PCIE_HB_RST] = RST_NR_PER_BANK + 29,
[EN751221_SIMIF_RST] = RST_NR_PER_BANK + 30,
[EN751221_XPON_MAC_RST] = RST_NR_PER_BANK + 31,
/* RST_DMT */
[EN751221_DMT_RST] = 2 * RST_NR_PER_BANK + 0,
/* RST_USB */
[EN751221_USB_PHY_P0_RST] = 3 * RST_NR_PER_BANK + 6,
[EN751221_USB_PHY_P1_RST] = 3 * RST_NR_PER_BANK + 7,
};
static int en7581_reset_register(struct device *dev, void __iomem *base,
const u16 *rst_map, int nr_resets);
const u16 *rst_map, int nr_resets,
const u16 *rst_reg_ofs);
static u32 en7523_get_base_rate(const struct en_clk_desc *desc, u32 val)
{
@@ -604,7 +704,8 @@ static int en7523_clk_hw_init(struct platform_device *pdev,
en7523_register_clocks(&pdev->dev, clk_data, base, np_base);
return en7581_reset_register(&pdev->dev, np_base, en7523_rst_map,
ARRAY_SIZE(en7523_rst_map));
ARRAY_SIZE(en7523_rst_map),
en7581_rst_ofs);
}
static void en7581_register_clocks(struct device *dev, struct clk_hw_onecell_data *clk_data,
@@ -705,7 +806,8 @@ static const struct reset_control_ops en7581_reset_ops = {
};
static int en7581_reset_register(struct device *dev, void __iomem *base,
const u16 *rst_map, int nr_resets)
const u16 *rst_map, int nr_resets,
const u16 *rst_reg_ofs)
{
struct en_rst_data *rst_data;
@@ -713,7 +815,7 @@ static int en7581_reset_register(struct device *dev, void __iomem *base,
if (!rst_data)
return -ENOMEM;
rst_data->bank_ofs = en7581_rst_ofs;
rst_data->bank_ofs = rst_reg_ofs;
rst_data->idx_map = rst_map;
rst_data->base = base;
@@ -752,7 +854,107 @@ static int en7581_clk_hw_init(struct platform_device *pdev,
writel(val | 3, base + REG_NP_SCU_PCIC);
return en7581_reset_register(&pdev->dev, base, en7581_rst_map,
ARRAY_SIZE(en7581_rst_map));
ARRAY_SIZE(en7581_rst_map),
en7581_rst_ofs);
}
static enum en_hir get_hw_id(void __iomem *np_base)
{
u32 val = FIELD_GET(REG_HIR_MASK, readl(np_base + REG_HIR));
if (val < HIR_MAX)
return (enum en_hir)val;
pr_warn("Unable to determine EcoNet SoC\n");
return HIR_UNKNOWN;
}
static void en751221_try_register_clk(struct device *dev, int key,
struct clk_hw_onecell_data *clk_data,
const char *name, u32 rate)
{
struct clk_hw *hw;
if (WARN_ON_ONCE(key >= EN751221_MAX_CLKS))
return;
hw = clk_hw_register_fixed_rate(dev, name, NULL, 0, rate);
if (IS_ERR(hw))
pr_err("Failed to register clk %s: %pe\n", name, hw);
else
clk_data->hws[key] = hw;
}
static void en751221_register_clocks(struct device *dev,
struct clk_hw_onecell_data *clk_data,
struct regmap *map, void __iomem *np_base)
{
enum en_hir hid = get_hw_id(np_base);
struct clk_hw *hw;
u32 rate;
u32 div;
int err;
/* PCI */
hw = en7523_register_pcie_clk(dev, np_base);
clk_data->hws[EN751221_CLK_PCIE] = hw;
/* SPI */
rate = EN751221_SPI_BASE;
if (hid == HIR_EN7526C)
rate = EN751221_SPI_BASE_EN7526C;
err = regmap_read(map, EN751221_REG_SPI_DIV, &div);
if (err) {
pr_err("Failed reading fixed clk div %s: %d\n",
"spi", err);
} else {
div = FIELD_GET(EN751221_REG_SPI_DIV_MASK, div) * 2;
if (!div)
div = EN751221_SPI_DIV_DEFAULT;
en751221_try_register_clk(dev, EN751221_CLK_SPI, clk_data,
"spi", rate / div);
}
/* BUS */
rate = FIELD_GET(EN751221_REG_BUS_MASK,
readl(np_base + EN751221_REG_BUS));
rate *= 1000000;
en751221_try_register_clk(dev, EN751221_CLK_BUS, clk_data, "bus",
rate);
/* CPU */
en751221_try_register_clk(dev, EN751221_CLK_CPU, clk_data, "cpu",
rate * 4);
/* GSW */
rate = FIELD_GET(EN751221_REG_SSR3_GSW_MASK,
readl(np_base + EN751221_REG_SSR3));
en751221_try_register_clk(dev, EN751221_CLK_GSW, clk_data, "gsw",
gsw751221_base[rate]);
}
static int en751221_clk_hw_init(struct platform_device *pdev,
struct clk_hw_onecell_data *clk_data)
{
struct regmap *map;
void __iomem *base;
map = syscon_regmap_lookup_by_compatible("econet,en751221-chip-scu");
if (IS_ERR(map))
return PTR_ERR(map);
base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(base))
return PTR_ERR(base);
en751221_register_clocks(&pdev->dev, clk_data, map, base);
return en7581_reset_register(&pdev->dev, base, en751221_rst_map,
ARRAY_SIZE(en751221_rst_map),
en751221_rst_ofs);
}
static int en7523_clk_probe(struct platform_device *pdev)
@@ -799,9 +1001,20 @@ static const struct en_clk_soc_data en7581_data = {
.hw_init = en7581_clk_hw_init,
};
static const struct en_clk_soc_data en751221_data = {
.num_clocks = EN751221_MAX_CLKS,
.pcie_ops = {
.is_enabled = en7523_pci_is_enabled,
.prepare = en7523_pci_prepare,
.unprepare = en7523_pci_unprepare,
},
.hw_init = en751221_clk_hw_init,
};
static const struct of_device_id of_match_clk_en7523[] = {
{ .compatible = "airoha,en7523-scu", .data = &en7523_data },
{ .compatible = "airoha,en7581-scu", .data = &en7581_data },
{ .compatible = "econet,en751221-scu", .data = &en751221_data },
{ /* sentinel */ }
};
+15
View File
@@ -0,0 +1,15 @@
# SPDX-License-Identifier: GPL-2.0
config COMMON_CLK_ESWIN
bool
config COMMON_CLK_EIC7700
tristate "EIC7700 Clock Driver"
depends on ARCH_ESWIN || COMPILE_TEST
select COMMON_CLK_ESWIN
default ARCH_ESWIN
help
This driver provides support for clock controller on ESWIN EIC7700
SoC. The clock controller generates and supplies clocks to various
peripherals within the SoC.
Say yes here to support the clock controller on the EIC7700 SoC.
+8
View File
@@ -0,0 +1,8 @@
# SPDX-License-Identifier: GPL-2.0
#
# Eswin Clock specific Makefile
#
obj-$(CONFIG_COMMON_CLK_ESWIN) += clk.o
obj-$(CONFIG_COMMON_CLK_EIC7700) += clk-eic7700.o
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+340
View File
@@ -0,0 +1,340 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright 2026, Beijing ESWIN Computing Technology Co., Ltd..
* All rights reserved.
*
* Authors:
* Yifeng Huang <huangyifeng@eswincomputing.com>
* Xuyang Dong <dongxuyang@eswincomputing.com>
*/
#ifndef __ESWIN_COMMON_H__
#define __ESWIN_COMMON_H__
#define APLL_HIGH_FREQ 983040000
#define APLL_LOW_FREQ 225792000
#define PLL_HIGH_FREQ 1800000000
#define PLL_LOW_FREQ 24000000
/*
* ESWIN_PRIV_DIV_MIN_2: If ESWIN_PRIV_DIV_MIN_2 is set, the minimum value of
* the register is 2, i.e. the minimum division ratio is 2.
*/
#define ESWIN_PRIV_DIV_MIN_2 BIT(0)
enum eswin_clk_type {
CLK_FIXED_FACTOR,
CLK_MUX,
CLK_DIVIDER,
CLK_GATE,
};
struct eswin_clock_data {
void __iomem *base;
struct clk_hw *original_clk;
struct notifier_block pll_nb;
spinlock_t lock; /* protect register read-modify-write cycle */
struct clk_hw_onecell_data clk_data;
};
struct eswin_divider_clock {
struct clk_hw hw;
unsigned int id;
const char *name;
const struct clk_parent_data *parent_data;
void __iomem *ctrl_reg; /* register address of the divider clock */
unsigned long flags;
unsigned long reg; /* register offset */
u8 shift;
u8 width;
unsigned long div_flags;
unsigned long priv_flag;
spinlock_t *lock; /* protect register read-modify-write cycle */
};
struct eswin_fixed_rate_clock {
struct clk_hw hw;
unsigned int id;
const char *name;
unsigned long flags;
unsigned long rate;
};
struct eswin_fixed_factor_clock {
struct clk_hw hw;
unsigned int id;
const char *name;
const struct clk_parent_data *parent_data;
unsigned long mult;
unsigned long div;
unsigned long flags;
};
struct eswin_gate_clock {
struct clk_hw hw;
unsigned int id;
const char *name;
const struct clk_parent_data *parent_data;
unsigned long flags;
unsigned long reg;
u8 bit_idx;
u8 gate_flags;
};
struct eswin_mux_clock {
struct clk_hw hw;
unsigned int id;
const char *name;
const struct clk_parent_data *parent_data;
u8 num_parents;
unsigned long flags;
unsigned long reg;
u8 shift;
u8 width;
u8 mux_flags;
u32 *table;
};
struct eswin_pll_clock {
struct clk_hw hw;
u32 id;
const char *name;
const struct clk_parent_data *parent_data;
const u32 ctrl_reg0;
const u8 fbdiv_shift;
const u32 ctrl_reg1;
const u8 frac_shift;
const u32 ctrl_reg2;
const u32 status_reg;
const u8 lock_shift;
const u8 lock_width;
const u64 max_rate;
const u64 min_rate;
};
struct eswin_clk_pll {
struct clk_hw hw;
u32 id;
void __iomem *ctrl_reg0;
u8 fbdiv_shift;
void __iomem *ctrl_reg1;
u8 frac_shift;
void __iomem *ctrl_reg2;
void __iomem *status_reg;
u8 lock_shift;
u8 lock_width;
u64 max_rate;
u64 min_rate;
};
struct eswin_clk_info {
unsigned int type;
unsigned int pid;
unsigned int id;
struct clk_hw hw;
union {
struct eswin_divider_clock div;
struct eswin_fixed_factor_clock factor;
struct eswin_gate_clock gate;
struct eswin_mux_clock mux;
} data;
};
struct eswin_clock_data *eswin_clk_init(struct platform_device *pdev,
size_t nr_clks);
int eswin_clk_register_fixed_rate(struct device *dev,
struct eswin_fixed_rate_clock *clks,
int nums, struct eswin_clock_data *data);
int eswin_clk_register_pll(struct device *dev, struct eswin_pll_clock *clks,
int nums, struct eswin_clock_data *data);
int eswin_clk_register_fixed_factor(struct device *dev,
struct eswin_fixed_factor_clock *clks,
int nums, struct eswin_clock_data *data);
int eswin_clk_register_mux(struct device *dev, struct eswin_mux_clock *clks,
int nums, struct eswin_clock_data *data);
int eswin_clk_register_divider(struct device *dev,
struct eswin_divider_clock *clks,
int nums, struct eswin_clock_data *data);
int eswin_clk_register_gate(struct device *dev, struct eswin_gate_clock *clks,
int nums, struct eswin_clock_data *data);
int eswin_clk_register_clks(struct device *dev, struct eswin_clk_info *clks,
int nums, struct eswin_clock_data *data);
struct clk_hw *eswin_register_clkdiv(struct device *dev, unsigned int id,
const char *name,
const struct clk_hw *parent_hw,
unsigned long flags, void __iomem *reg,
u8 shift, u8 width,
unsigned long clk_divider_flags,
unsigned long priv_flag, spinlock_t *lock);
#define ESWIN_DIV(_id, _name, _pdata, _flags, _reg, _shift, _width, \
_dflags, _pflag) \
{ \
.id = _id, \
.name = _name, \
.parent_data = _pdata, \
.flags = _flags, \
.reg = _reg, \
.shift = _shift, \
.width = _width, \
.div_flags = _dflags, \
.priv_flag = _pflag, \
}
#define ESWIN_DIV_TYPE(_id, _name, _pid, _flags, _reg, _shift, _width, \
_dflags, _pflag) \
{ \
.type = CLK_DIVIDER, \
.pid = _pid, \
.id = _id, \
.data = { \
.div = { \
.name = _name, \
.flags = _flags, \
.reg = _reg, \
.shift = _shift, \
.width = _width, \
.div_flags = _dflags, \
.priv_flag = _pflag, \
}, \
}, \
}
#define ESWIN_FACTOR(_id, _name, _pdata, _mult, _div, _flags) \
{ \
.id = _id, \
.name = _name, \
.parent_data = _pdata, \
.mult = _mult, \
.div = _div, \
.flags = _flags, \
}
#define ESWIN_FACTOR_TYPE(_id, _name, _pid, _mult, _div, _flags) \
{ \
.type = CLK_FIXED_FACTOR, \
.pid = _pid, \
.id = _id, \
.data = { \
.factor = { \
.name = _name, \
.mult = _mult, \
.div = _div, \
.flags = _flags, \
}, \
}, \
}
#define ESWIN_FIXED(_id, _name, _flags, _rate) \
{ \
.id = _id, \
.name = _name, \
.flags = _flags, \
.rate = _rate, \
}
#define ESWIN_GATE(_id, _name, _pdata, _flags, _reg, _idx, _gflags) \
{ \
.id = _id, \
.name = _name, \
.parent_data = _pdata, \
.flags = _flags, \
.reg = _reg, \
.bit_idx = _idx, \
.gate_flags = _gflags, \
}
#define ESWIN_GATE_TYPE(_id, _name, _pid, _flags, _reg, _idx, _gflags) \
{ \
.type = CLK_GATE, \
.pid = _pid, \
.id = _id, \
.data = { \
.gate = { \
.name = _name, \
.flags = _flags, \
.reg = _reg, \
.bit_idx = _idx, \
.gate_flags = _gflags, \
}, \
}, \
}
#define ESWIN_MUX(_id, _name, _pdata, _num_parents, _flags, _reg, \
_shift, _width, _mflags) \
{ \
.id = _id, \
.name = _name, \
.parent_data = _pdata, \
.num_parents = _num_parents, \
.flags = _flags, \
.reg = _reg, \
.shift = _shift, \
.width = _width, \
.mux_flags = _mflags, \
.table = NULL, \
}
#define ESWIN_MUX_TBL(_id, _name, _pdata, _num_parents, _flags, _reg, \
_shift, _width, _mflags, _table) \
{ \
.id = _id, \
.name = _name, \
.parent_data = _pdata, \
.num_parents = _num_parents, \
.flags = _flags, \
.reg = _reg, \
.shift = _shift, \
.width = _width, \
.mux_flags = _mflags, \
.table = _table, \
}
#define ESWIN_MUX_TYPE(_id, _name, _pdata, _num_parents, _flags, _reg, \
_shift, _width, _mflags, _table) \
{ \
.type = CLK_MUX, \
.id = _id, \
.data = { \
.mux = { \
.name = _name, \
.parent_data = _pdata, \
.num_parents = _num_parents, \
.flags = _flags, \
.reg = _reg, \
.shift = _shift, \
.width = _width, \
.mux_flags = _mflags, \
.table = _table, \
}, \
}, \
}
#define ESWIN_PLL(_id, _name, _pdata, _reg0, _fb_shift, _reg1, \
_frac_shift, _reg2, _reg, _lock_shift, _lock_width, \
_max_rate, _min_rate) \
{ \
.id = _id, \
.name = _name, \
.parent_data = _pdata, \
.ctrl_reg0 = _reg0, \
.fbdiv_shift = _fb_shift, \
.ctrl_reg1 = _reg1, \
.frac_shift = _frac_shift, \
.ctrl_reg2 = _reg2, \
.status_reg = _reg, \
.lock_shift = _lock_shift, \
.lock_width = _lock_width, \
.max_rate = _max_rate, \
.min_rate = _min_rate, \
}
#endif /* __ESWIN_COMMON_H__ */
+6 -1
View File
@@ -39,6 +39,7 @@ config CLK_RENESAS
select CLK_R9A07G044 if ARCH_R9A07G044
select CLK_R9A07G054 if ARCH_R9A07G054
select CLK_R9A08G045 if ARCH_R9A08G045
select CLK_R9A08G046 if ARCH_R9A08G046
select CLK_R9A09G011 if ARCH_R9A09G011
select CLK_R9A09G047 if ARCH_R9A09G047
select CLK_R9A09G056 if ARCH_R9A09G056
@@ -194,6 +195,10 @@ config CLK_R9A08G045
bool "RZ/G3S clock support" if COMPILE_TEST
select CLK_RZG2L
config CLK_R9A08G046
bool "RZ/G3L clock support" if COMPILE_TEST
select CLK_RZG2L
config CLK_R9A09G011
bool "RZ/V2M clock support" if COMPILE_TEST
select CLK_RZG2L
@@ -250,7 +255,7 @@ config CLK_RCAR_USB2_CLOCK_SEL
This is a driver for R-Car USB2 clock selector
config CLK_RZG2L
bool "RZ/{G2L,G2UL,G3S,V2L} family clock support" if COMPILE_TEST
bool "RZ/{G2{L,UL},G3{S,L},V2L} family clock support" if COMPILE_TEST
select RESET_CONTROLLER
config CLK_RZV2H
+1
View File
@@ -36,6 +36,7 @@ obj-$(CONFIG_CLK_R9A07G043) += r9a07g043-cpg.o
obj-$(CONFIG_CLK_R9A07G044) += r9a07g044-cpg.o
obj-$(CONFIG_CLK_R9A07G054) += r9a07g044-cpg.o
obj-$(CONFIG_CLK_R9A08G045) += r9a08g045-cpg.o
obj-$(CONFIG_CLK_R9A08G046) += r9a08g046-cpg.o
obj-$(CONFIG_CLK_R9A09G011) += r9a09g011-cpg.o
obj-$(CONFIG_CLK_R9A09G047) += r9a09g047-cpg.o
obj-$(CONFIG_CLK_R9A09G056) += r9a09g056-cpg.o
+3 -2
View File
@@ -1342,8 +1342,9 @@ static int __init r9a06g032_clocks_probe(struct platform_device *pdev)
/* Clear potentially pending resets */
writel(R9A06G032_SYSCTRL_WDA7RST_0 | R9A06G032_SYSCTRL_WDA7RST_1,
clocks->reg + R9A06G032_SYSCTRL_RSTCTRL);
/* Allow software reset */
writel(R9A06G032_SYSCTRL_SWRST | R9A06G032_SYSCTRL_RSTEN_MRESET_EN,
/* Allow watchdog and software resets */
writel(R9A06G032_SYSCTRL_WDA7RST_0 | R9A06G032_SYSCTRL_WDA7RST_1 |
R9A06G032_SYSCTRL_SWRST | R9A06G032_SYSCTRL_RSTEN_MRESET_EN,
clocks->reg + R9A06G032_SYSCTRL_RSTEN);
error = devm_register_sys_off_handler(dev, SYS_OFF_MODE_RESTART, SYS_OFF_PRIO_HIGH,
+9
View File
@@ -379,6 +379,11 @@ static const unsigned int r9a07g043_crit_mod_clks[] __initconst = {
MOD_CLK_BASE + R9A07G043_DMAC_ACLK,
};
static const unsigned int r9a07g043_crit_resets[] = {
R9A07G043_DMAC_ARESETN,
R9A07G043_DMAC_RST_ASYNC,
};
#ifdef CONFIG_ARM64
static const unsigned int r9a07g043_no_pm_mod_clks[] = {
MOD_CLK_BASE + R9A07G043_CRU_SYSCLK,
@@ -420,5 +425,9 @@ const struct rzg2l_cpg_info r9a07g043_cpg_info = {
.num_resets = R9A07G043_IAX45_RESETN + 1, /* Last reset ID + 1 */
#endif
/* Critical Resets */
.crit_resets = r9a07g043_crit_resets,
.num_crit_resets = ARRAY_SIZE(r9a07g043_crit_resets),
.has_clk_mon_regs = true,
};
+13
View File
@@ -489,6 +489,11 @@ static const unsigned int r9a07g044_crit_mod_clks[] __initconst = {
MOD_CLK_BASE + R9A07G044_DMAC_ACLK,
};
static const unsigned int r9a07g044_crit_resets[] = {
R9A07G044_DMAC_ARESETN,
R9A07G044_DMAC_RST_ASYNC,
};
static const unsigned int r9a07g044_no_pm_mod_clks[] = {
MOD_CLK_BASE + R9A07G044_CRU_SYSCLK,
MOD_CLK_BASE + R9A07G044_CRU_VCLK,
@@ -519,6 +524,10 @@ const struct rzg2l_cpg_info r9a07g044_cpg_info = {
.resets = r9a07g044_resets,
.num_resets = R9A07G044_TSU_PRESETN + 1, /* Last reset ID + 1 */
/* Critical Resets */
.crit_resets = r9a07g044_crit_resets,
.num_crit_resets = ARRAY_SIZE(r9a07g044_crit_resets),
.has_clk_mon_regs = true,
};
#endif
@@ -548,6 +557,10 @@ const struct rzg2l_cpg_info r9a07g054_cpg_info = {
.resets = r9a07g044_resets,
.num_resets = R9A07G054_STPAI_ARESETN + 1, /* Last reset ID + 1 */
/* Critical Resets */
.crit_resets = r9a07g044_crit_resets,
.num_crit_resets = ARRAY_SIZE(r9a07g044_crit_resets),
.has_clk_mon_regs = true,
};
#endif
+9
View File
@@ -361,6 +361,11 @@ static const unsigned int r9a08g045_crit_mod_clks[] __initconst = {
MOD_CLK_BASE + R9A08G045_VBAT_BCLK,
};
static const unsigned int r9a08g045_crit_resets[] = {
R9A08G045_DMAC_ARESETN,
R9A08G045_DMAC_RST_ASYNC,
};
static const unsigned int r9a08g045_no_pm_mod_clks[] = {
MOD_CLK_BASE + R9A08G045_PCI_CLKL1PM,
};
@@ -389,5 +394,9 @@ const struct rzg2l_cpg_info r9a08g045_cpg_info = {
.resets = r9a08g045_resets,
.num_resets = R9A08G045_VBAT_BRESETN + 1, /* Last reset ID + 1 */
/* Critical Resets */
.crit_resets = r9a08g045_crit_resets,
.num_crit_resets = ARRAY_SIZE(r9a08g045_crit_resets),
.has_clk_mon_regs = true,
};

Some files were not shown because too many files have changed in this diff Show More