Merge branches 'clk-cleanup', 'clk-mediatek', 'clk-kunit', 'clk-xilinx' and 'clk-fixed-gate' into clk-next

- Various clk driver cleanups
 - MediaTek MT6735 SoC clks
 - MediaTek MT7620, MT7628 and MT7688 MMC clks
 - KUnit tests for clk-assigned-rates{,-u64}
 - Add a driver for gated fixed rate clocks

* clk-cleanup:
  clk: clk-loongson2: Fix potential buffer overflow in flexible-array member access
  clk: Fix invalid execution of clk_set_rate
  clk: clk-loongson2: Fix memory corruption bug in struct loongson2_clk_provider
  clk: lan966x: make it selectable for ARCH_LAN969X
  clk: clk-apple-nco: Add NULL check in applnco_probe
  clk: starfive: jh7110-pll: Mark the probe function as __init
  clk: sophgo: avoid integer overflow in sg2042_pll_recalc_rate()
  clk: tegra: use clamp() in tegra_bpmp_clk_determine_rate()
  clk: cdce925: make regmap_cdce925_bus constant
  clk: Drop explicit initialization of struct i2c_device_id::driver_data to 0
  clk: clk-qoriq: Replace of_node_put() with __free()
  clk: Remove unused clk_hw_rate_is_protected

* clk-mediatek:
  clk: en7523: map io region in a single block
  clk: en7523: move en7581_reset_register() in en7581_clk_hw_init()
  clk: en7523: fix estimation of fixed rate for EN7581
  clk: en7523: introduce chip_scu regmap
  clk: en7523: move clock_register in hw_init callback
  clk: en7523: remove REG_PCIE*_{MEM,MEM_MASK} configuration
  dt-bindings: clock: airoha: Update reg mapping for EN7581 SoC.
  clk: mediatek: Add drivers for MT6735 syscon clock and reset controllers
  dt-bindings: clock: mediatek: Add bindings for MT6735 syscon clock and reset controllers
  clk: mediatek: mt6735-apmixedsys: Fix an error handling path in clk_mt6735_apmixed_probe()
  clk: ralink: mtmips: add mmc related clocks for SoCs MT7620, MT7628 and MT7688
  clk: ralink: mtmips: fix clocks probe order in oldest ralink SoCs
  clk: ralink: mtmips: fix clock plan for Ralink SoC RT3883
  clk: mediatek: clk-mt8188-topckgen: Remove univpll from parents of mfg_core_tmp
  clk: mediatek: Add drivers for MediaTek MT6735 main clock and reset drivers
  dt-bindings: clock: Add MediaTek MT6735 clock and reset bindings
  clk: mediatek: drop two dead config options

* clk-kunit:
  clk: Allow kunit tests to run without OF_OVERLAY enabled
  clk: test: Add KUnit tests for clock-assigned-rates{-u64} DT properties
  of: kunit: Extract some overlay boiler plate into macros
  clk: test: Add test managed of_clk_add_hw_provider()

* clk-xilinx:
  clk: clocking-wizard: move dynamic reconfig setup behind flag
  dt-bindings: clock: xilinx: describe whether dynamic reconfig is enabled
  clk: clocking-wizard: move clock registration to separate function
  clk: clocking-wizard: use devres versions of clk_hw API
  clk: clocking-wizard: use newer clk_hw API
  clk: clocking-wizard: simplify probe/remove with devres helpers

* clk-fixed-gate:
  clk: clk-gpio: add driver for gated-fixed-clocks
  clk: clk-gpio: use dev_err_probe for gpio-get failure
  clk: clk-gpio: update documentation for gpio-gate clock
  dt-bindings: clocks: add binding for gated-fixed-clocks
This commit is contained in:
Stephen Boyd
2024-11-18 20:00:03 -08:00
58 changed files with 2625 additions and 341 deletions
@@ -34,8 +34,10 @@ properties:
- airoha,en7581-scu
reg:
minItems: 2
maxItems: 4
items:
- description: scu base address
- description: misc scu base address
minItems: 1
"#clock-cells":
description:
@@ -60,9 +62,7 @@ allOf:
then:
properties:
reg:
items:
- description: scu base address
- description: misc scu base address
minItems: 2
'#reset-cells': false
@@ -73,11 +73,7 @@ allOf:
then:
properties:
reg:
items:
- description: scu base address
- description: misc scu base address
- description: reset base address
- description: pb scu base address
maxItems: 1
additionalProperties: false
@@ -96,12 +92,9 @@ examples:
#address-cells = <2>;
#size-cells = <2>;
scuclk: clock-controller@1fa20000 {
scuclk: clock-controller@1fb00000 {
compatible = "airoha,en7581-scu";
reg = <0x0 0x1fa20000 0x0 0x400>,
<0x0 0x1fb00000 0x0 0x90>,
<0x0 0x1fb00830 0x0 0x8>,
<0x0 0x1fbe3400 0x0 0xfc>;
reg = <0x0 0x1fb00000 0x0 0x970>;
#clock-cells = <1>;
#reset-cells = <1>;
};
@@ -0,0 +1,49 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/clock/gated-fixed-clock.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Gated Fixed clock
maintainers:
- Heiko Stuebner <heiko@sntech.de>
properties:
compatible:
const: gated-fixed-clock
"#clock-cells":
const: 0
clock-frequency: true
clock-output-names:
maxItems: 1
enable-gpios:
description:
Contains a single GPIO specifier for the GPIO that enables and disables
the oscillator.
maxItems: 1
vdd-supply:
description: handle of the regulator that provides the supply voltage
required:
- compatible
- "#clock-cells"
- clock-frequency
- vdd-supply
additionalProperties: false
examples:
- |
clock-1000000000 {
compatible = "gated-fixed-clock";
#clock-cells = <0>;
clock-frequency = <1000000000>;
vdd-supply = <&reg_vdd>;
};
...
@@ -12,7 +12,8 @@ maintainers:
description:
The Mediatek apmixedsys controller provides PLLs to the system.
The clock values can be found in <dt-bindings/clock/mt*-clk.h>.
The clock values can be found in <dt-bindings/clock/mt*-clk.h>
and <dt-bindings/clock/mediatek,mt*-apmixedsys.h>.
properties:
compatible:
@@ -34,6 +35,7 @@ properties:
- enum:
- mediatek,mt2701-apmixedsys
- mediatek,mt2712-apmixedsys
- mediatek,mt6735-apmixedsys
- mediatek,mt6765-apmixedsys
- mediatek,mt6779-apmixed
- mediatek,mt6795-apmixedsys
@@ -11,9 +11,10 @@ maintainers:
description:
The Mediatek infracfg controller provides various clocks and reset outputs
to the system. The clock values can be found in <dt-bindings/clock/mt*-clk.h>,
and reset values in <dt-bindings/reset/mt*-reset.h> and
<dt-bindings/reset/mt*-resets.h>.
to the system. The clock values can be found in <dt-bindings/clock/mt*-clk.h>
and <dt-bindings/clock/mediatek,mt*-infracfg.h>, and reset values in
<dt-bindings/reset/mt*-reset.h>, <dt-bindings/reset/mt*-resets.h> and
<dt-bindings/reset/mediatek,mt*-infracfg.h>.
properties:
compatible:
@@ -22,6 +23,7 @@ properties:
- enum:
- mediatek,mt2701-infracfg
- mediatek,mt2712-infracfg
- mediatek,mt6735-infracfg
- mediatek,mt6765-infracfg
- mediatek,mt6795-infracfg
- mediatek,mt6779-infracfg_ao
@@ -20,6 +20,7 @@ properties:
- enum:
- mediatek,mt2701-pericfg
- mediatek,mt2712-pericfg
- mediatek,mt6735-pericfg
- mediatek,mt6765-pericfg
- mediatek,mt6795-pericfg
- mediatek,mt7622-pericfg
@@ -28,6 +28,10 @@ properties:
- mediatek,mt2712-mfgcfg
- mediatek,mt2712-vdecsys
- mediatek,mt2712-vencsys
- mediatek,mt6735-imgsys
- mediatek,mt6735-mfgcfg
- mediatek,mt6735-vdecsys
- mediatek,mt6735-vencsys
- mediatek,mt6765-camsys
- mediatek,mt6765-imgsys
- mediatek,mt6765-mipi0a
@@ -12,7 +12,8 @@ maintainers:
description:
The Mediatek topckgen controller provides various clocks to the system.
The clock values can be found in <dt-bindings/clock/mt*-clk.h>.
The clock values can be found in <dt-bindings/clock/mt*-clk.h> and
<dt-bindings/clock/mediatek,mt*-topckgen.h>.
properties:
compatible:
@@ -31,6 +32,7 @@ properties:
- enum:
- mediatek,mt2701-topckgen
- mediatek,mt2712-topckgen
- mediatek,mt6735-topckgen
- mediatek,mt6765-topckgen
- mediatek,mt6779-topckgen
- mediatek,mt6795-topckgen
@@ -39,6 +39,11 @@ properties:
- const: clk_in1
- const: s_axi_aclk
xlnx,static-config:
$ref: /schemas/types.yaml#/definitions/flag
description:
Indicate whether the core has been configured without support for dynamic
runtime reconfguration of the clocking primitive MMCM/PLL.
xlnx,speed-grade:
$ref: /schemas/types.yaml#/definitions/uint32
@@ -70,6 +75,7 @@ examples:
compatible = "xlnx,clocking-wizard";
reg = <0xb0000000 0x10000>;
#clock-cells = <1>;
xlnx,static-config;
xlnx,speed-grade = <1>;
xlnx,nr-outputs = <6>;
clock-names = "clk_in1", "s_axi_aclk";
+26
View File
@@ -14528,6 +14528,32 @@ S: Maintained
F: Documentation/devicetree/bindings/mmc/mtk-sd.yaml
F: drivers/mmc/host/mtk-sd.c
MEDIATEK MT6735 CLOCK & RESET DRIVERS
M: Yassine Oudjana <y.oudjana@protonmail.com>
L: linux-clk@vger.kernel.org
L: linux-mediatek@lists.infradead.org (moderated for non-subscribers)
S: Maintained
F: drivers/clk/mediatek/clk-mt6735-apmixedsys.c
F: drivers/clk/mediatek/clk-mt6735-imgsys.c
F: drivers/clk/mediatek/clk-mt6735-infracfg.c
F: drivers/clk/mediatek/clk-mt6735-mfgcfg.c
F: drivers/clk/mediatek/clk-mt6735-pericfg.c
F: drivers/clk/mediatek/clk-mt6735-topckgen.c
F: drivers/clk/mediatek/clk-mt6735-vdecsys.c
F: drivers/clk/mediatek/clk-mt6735-vencsys.c
F: include/dt-bindings/clock/mediatek,mt6735-apmixedsys.h
F: include/dt-bindings/clock/mediatek,mt6735-imgsys.h
F: include/dt-bindings/clock/mediatek,mt6735-infracfg.h
F: include/dt-bindings/clock/mediatek,mt6735-mfgcfg.h
F: include/dt-bindings/clock/mediatek,mt6735-pericfg.h
F: include/dt-bindings/clock/mediatek,mt6735-topckgen.h
F: include/dt-bindings/clock/mediatek,mt6735-vdecsys.h
F: include/dt-bindings/clock/mediatek,mt6735-vencsys.h
F: include/dt-bindings/reset/mediatek,mt6735-infracfg.h
F: include/dt-bindings/reset/mediatek,mt6735-mfgcfg.h
F: include/dt-bindings/reset/mediatek,mt6735-pericfg.h
F: include/dt-bindings/reset/mediatek,mt6735-vdecsys.h
MEDIATEK MT76 WIRELESS LAN DRIVER
M: Felix Fietkau <nbd@nbd.name>
M: Lorenzo Bianconi <lorenzo@kernel.org>
+1
View File
@@ -1,5 +1,6 @@
CONFIG_KUNIT=y
CONFIG_OF=y
CONFIG_OF_OVERLAY=y
CONFIG_COMMON_CLK=y
CONFIG_CLK_KUNIT_TEST=y
CONFIG_CLK_FIXED_RATE_KUNIT_TEST=y
-2
View File
@@ -517,7 +517,6 @@ config CLK_KUNIT_TEST
tristate "Basic Clock Framework Kunit Tests" if !KUNIT_ALL_TESTS
depends on KUNIT
default KUNIT_ALL_TESTS
select OF_OVERLAY if OF
select DTC
help
Kunit tests for the common clock framework.
@@ -526,7 +525,6 @@ config CLK_FIXED_RATE_KUNIT_TEST
tristate "Basic fixed rate clk type KUnit test" if !KUNIT_ALL_TESTS
depends on KUNIT
default KUNIT_ALL_TESTS
select OF_OVERLAY if OF
select DTC
help
KUnit tests for the basic fixed rate clk type.
+14
View File
@@ -4,6 +4,20 @@ obj-$(CONFIG_HAVE_CLK) += clk-devres.o clk-bulk.o clkdev.o
obj-$(CONFIG_COMMON_CLK) += clk.o
obj-$(CONFIG_CLK_KUNIT_TEST) += clk-test.o
clk-test-y := clk_test.o \
kunit_clk_assigned_rates_u64_one.dtbo.o \
kunit_clk_assigned_rates_u64_one_consumer.dtbo.o \
kunit_clk_assigned_rates_u64_multiple.dtbo.o \
kunit_clk_assigned_rates_u64_multiple_consumer.dtbo.o \
kunit_clk_assigned_rates_multiple.dtbo.o \
kunit_clk_assigned_rates_multiple_consumer.dtbo.o \
kunit_clk_assigned_rates_null.dtbo.o \
kunit_clk_assigned_rates_null_consumer.dtbo.o \
kunit_clk_assigned_rates_one.dtbo.o \
kunit_clk_assigned_rates_one_consumer.dtbo.o \
kunit_clk_assigned_rates_without.dtbo.o \
kunit_clk_assigned_rates_without_consumer.dtbo.o \
kunit_clk_assigned_rates_zero.dtbo.o \
kunit_clk_assigned_rates_zero_consumer.dtbo.o \
kunit_clk_parent_data_test.dtbo.o
obj-$(CONFIG_COMMON_CLK) += clk-divider.o
obj-$(CONFIG_COMMON_CLK) += clk-fixed-factor.o
+212 -103
View File
@@ -3,8 +3,10 @@
#include <linux/delay.h>
#include <linux/clk-provider.h>
#include <linux/io.h>
#include <linux/mfd/syscon.h>
#include <linux/platform_device.h>
#include <linux/property.h>
#include <linux/regmap.h>
#include <linux/reset-controller.h>
#include <dt-bindings/clock/en7523-clk.h>
#include <dt-bindings/reset/airoha,en7581-reset.h>
@@ -31,19 +33,14 @@
#define REG_RESET_CONTROL_PCIE1 BIT(27)
#define REG_RESET_CONTROL_PCIE2 BIT(26)
/* EN7581 */
#define REG_PCIE0_MEM 0x00
#define REG_PCIE0_MEM_MASK 0x04
#define REG_PCIE1_MEM 0x08
#define REG_PCIE1_MEM_MASK 0x0c
#define REG_PCIE2_MEM 0x10
#define REG_PCIE2_MEM_MASK 0x14
#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
#define REG_RST_CTRL2 0x00
#define REG_RST_CTRL1 0x04
#define REG_RST_CTRL2 0x830
#define REG_RST_CTRL1 0x834
struct en_clk_desc {
int id;
@@ -79,12 +76,8 @@ struct en_rst_data {
struct en_clk_soc_data {
const struct clk_ops pcie_ops;
struct {
const u16 *bank_ofs;
const u16 *idx_map;
u16 idx_map_nr;
} reset;
int (*hw_init)(struct platform_device *pdev, void __iomem *np_base);
int (*hw_init)(struct platform_device *pdev,
struct clk_hw_onecell_data *clk_data);
};
static const u32 gsw_base[] = { 400000000, 500000000 };
@@ -92,6 +85,10 @@ static const u32 emi_base[] = { 333000000, 400000000 };
static const u32 bus_base[] = { 500000000, 540000000 };
static const u32 slic_base[] = { 100000000, 3125000 };
static const u32 npu_base[] = { 333000000, 400000000, 500000000 };
/* EN7581 */
static const u32 emi7581_base[] = { 540000000, 480000000, 400000000, 300000000 };
static const u32 npu7581_base[] = { 800000000, 750000000, 720000000, 600000000 };
static const u32 crypto_base[] = { 540000000, 480000000 };
static const struct en_clk_desc en7523_base_clks[] = {
{
@@ -189,6 +186,102 @@ static const struct en_clk_desc en7523_base_clks[] = {
}
};
static const struct en_clk_desc en7581_base_clks[] = {
{
.id = EN7523_CLK_GSW,
.name = "gsw",
.base_reg = REG_GSW_CLK_DIV_SEL,
.base_bits = 1,
.base_shift = 8,
.base_values = gsw_base,
.n_base_values = ARRAY_SIZE(gsw_base),
.div_bits = 3,
.div_shift = 0,
.div_step = 1,
.div_offset = 1,
}, {
.id = EN7523_CLK_EMI,
.name = "emi",
.base_reg = REG_EMI_CLK_DIV_SEL,
.base_bits = 2,
.base_shift = 8,
.base_values = emi7581_base,
.n_base_values = ARRAY_SIZE(emi7581_base),
.div_bits = 3,
.div_shift = 0,
.div_step = 1,
.div_offset = 1,
}, {
.id = EN7523_CLK_BUS,
.name = "bus",
.base_reg = REG_BUS_CLK_DIV_SEL,
.base_bits = 1,
.base_shift = 8,
.base_values = bus_base,
.n_base_values = ARRAY_SIZE(bus_base),
.div_bits = 3,
.div_shift = 0,
.div_step = 1,
.div_offset = 1,
}, {
.id = EN7523_CLK_SLIC,
.name = "slic",
.base_reg = REG_SPI_CLK_FREQ_SEL,
.base_bits = 1,
.base_shift = 0,
.base_values = slic_base,
.n_base_values = ARRAY_SIZE(slic_base),
.div_reg = REG_SPI_CLK_DIV_SEL,
.div_bits = 5,
.div_shift = 24,
.div_val0 = 20,
.div_step = 2,
}, {
.id = EN7523_CLK_SPI,
.name = "spi",
.base_reg = REG_SPI_CLK_DIV_SEL,
.base_value = 400000000,
.div_bits = 5,
.div_shift = 8,
.div_val0 = 40,
.div_step = 2,
}, {
.id = EN7523_CLK_NPU,
.name = "npu",
.base_reg = REG_NPU_CLK_DIV_SEL,
.base_bits = 2,
.base_shift = 8,
.base_values = npu7581_base,
.n_base_values = ARRAY_SIZE(npu7581_base),
.div_bits = 3,
.div_shift = 0,
.div_step = 1,
.div_offset = 1,
}, {
.id = EN7523_CLK_CRYPTO,
.name = "crypto",
.base_reg = REG_CRYPTO_CLKSRC2,
.base_bits = 1,
.base_shift = 0,
.base_values = crypto_base,
.n_base_values = ARRAY_SIZE(crypto_base),
}
};
static const u16 en7581_rst_ofs[] = {
REG_RST_CTRL2,
REG_RST_CTRL1,
@@ -252,15 +345,11 @@ static const u16 en7581_rst_map[] = {
[EN7581_XPON_MAC_RST] = RST_NR_PER_BANK + 31,
};
static unsigned int en7523_get_base_rate(void __iomem *base, unsigned int i)
static u32 en7523_get_base_rate(const struct en_clk_desc *desc, u32 val)
{
const struct en_clk_desc *desc = &en7523_base_clks[i];
u32 val;
if (!desc->base_bits)
return desc->base_value;
val = readl(base + desc->base_reg);
val >>= desc->base_shift;
val &= (1 << desc->base_bits) - 1;
@@ -270,16 +359,11 @@ static unsigned int en7523_get_base_rate(void __iomem *base, unsigned int i)
return desc->base_values[val];
}
static u32 en7523_get_div(void __iomem *base, int i)
static u32 en7523_get_div(const struct en_clk_desc *desc, u32 val)
{
const struct en_clk_desc *desc = &en7523_base_clks[i];
u32 reg, val;
if (!desc->div_bits)
return 1;
reg = desc->div_reg ? desc->div_reg : desc->base_reg;
val = readl(base + reg);
val >>= desc->div_shift;
val &= (1 << desc->div_bits) - 1;
@@ -412,32 +496,6 @@ static void en7581_pci_disable(struct clk_hw *hw)
usleep_range(1000, 2000);
}
static int en7581_clk_hw_init(struct platform_device *pdev,
void __iomem *np_base)
{
void __iomem *pb_base;
u32 val;
pb_base = devm_platform_ioremap_resource(pdev, 3);
if (IS_ERR(pb_base))
return PTR_ERR(pb_base);
val = readl(np_base + REG_NP_SCU_SSTR);
val &= ~(REG_PCIE_XSI0_SEL_MASK | REG_PCIE_XSI1_SEL_MASK);
writel(val, np_base + REG_NP_SCU_SSTR);
val = readl(np_base + REG_NP_SCU_PCIC);
writel(val | 3, np_base + REG_NP_SCU_PCIC);
writel(0x20000000, pb_base + REG_PCIE0_MEM);
writel(0xfc000000, pb_base + REG_PCIE0_MEM_MASK);
writel(0x24000000, pb_base + REG_PCIE1_MEM);
writel(0xfc000000, pb_base + REG_PCIE1_MEM_MASK);
writel(0x28000000, pb_base + REG_PCIE2_MEM);
writel(0xfc000000, pb_base + REG_PCIE2_MEM_MASK);
return 0;
}
static void en7523_register_clocks(struct device *dev, struct clk_hw_onecell_data *clk_data,
void __iomem *base, void __iomem *np_base)
{
@@ -447,9 +505,12 @@ static void en7523_register_clocks(struct device *dev, struct clk_hw_onecell_dat
for (i = 0; i < ARRAY_SIZE(en7523_base_clks); i++) {
const struct en_clk_desc *desc = &en7523_base_clks[i];
u32 reg = desc->div_reg ? desc->div_reg : desc->base_reg;
u32 val = readl(base + desc->base_reg);
rate = en7523_get_base_rate(base, i);
rate /= en7523_get_div(base, i);
rate = en7523_get_base_rate(desc, val);
val = readl(base + reg);
rate /= en7523_get_div(desc, val);
hw = clk_hw_register_fixed_rate(dev, desc->name, NULL, 0, rate);
if (IS_ERR(hw)) {
@@ -467,6 +528,68 @@ static void en7523_register_clocks(struct device *dev, struct clk_hw_onecell_dat
clk_data->num = EN7523_NUM_CLOCKS;
}
static int en7523_clk_hw_init(struct platform_device *pdev,
struct clk_hw_onecell_data *clk_data)
{
void __iomem *base, *np_base;
base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(base))
return PTR_ERR(base);
np_base = devm_platform_ioremap_resource(pdev, 1);
if (IS_ERR(np_base))
return PTR_ERR(np_base);
en7523_register_clocks(&pdev->dev, clk_data, base, np_base);
return 0;
}
static void en7581_register_clocks(struct device *dev, struct clk_hw_onecell_data *clk_data,
struct regmap *map, void __iomem *base)
{
struct clk_hw *hw;
u32 rate;
int i;
for (i = 0; i < ARRAY_SIZE(en7581_base_clks); i++) {
const struct en_clk_desc *desc = &en7581_base_clks[i];
u32 val, reg = desc->div_reg ? desc->div_reg : desc->base_reg;
int err;
err = regmap_read(map, desc->base_reg, &val);
if (err) {
pr_err("Failed reading fixed clk rate %s: %d\n",
desc->name, err);
continue;
}
rate = en7523_get_base_rate(desc, val);
err = regmap_read(map, reg, &val);
if (err) {
pr_err("Failed reading fixed clk div %s: %d\n",
desc->name, err);
continue;
}
rate /= en7523_get_div(desc, val);
hw = clk_hw_register_fixed_rate(dev, desc->name, NULL, 0, rate);
if (IS_ERR(hw)) {
pr_err("Failed to register clk %s: %ld\n",
desc->name, PTR_ERR(hw));
continue;
}
clk_data->hws[desc->id] = hw;
}
hw = en7523_register_pcie_clk(dev, base);
clk_data->hws[EN7523_CLK_PCIE] = hw;
clk_data->num = EN7523_NUM_CLOCKS;
}
static int en7523_reset_update(struct reset_controller_dev *rcdev,
unsigned long id, bool assert)
{
@@ -516,38 +639,27 @@ static int en7523_reset_xlate(struct reset_controller_dev *rcdev,
return rst_data->idx_map[reset_spec->args[0]];
}
static const struct reset_control_ops en7523_reset_ops = {
static const struct reset_control_ops en7581_reset_ops = {
.assert = en7523_reset_assert,
.deassert = en7523_reset_deassert,
.status = en7523_reset_status,
};
static int en7523_reset_register(struct platform_device *pdev,
const struct en_clk_soc_data *soc_data)
static int en7581_reset_register(struct device *dev, void __iomem *base)
{
struct device *dev = &pdev->dev;
struct en_rst_data *rst_data;
void __iomem *base;
/* no reset lines available */
if (!soc_data->reset.idx_map_nr)
return 0;
base = devm_platform_ioremap_resource(pdev, 2);
if (IS_ERR(base))
return PTR_ERR(base);
rst_data = devm_kzalloc(dev, sizeof(*rst_data), GFP_KERNEL);
if (!rst_data)
return -ENOMEM;
rst_data->bank_ofs = soc_data->reset.bank_ofs;
rst_data->idx_map = soc_data->reset.idx_map;
rst_data->bank_ofs = en7581_rst_ofs;
rst_data->idx_map = en7581_rst_map;
rst_data->base = base;
rst_data->rcdev.nr_resets = soc_data->reset.idx_map_nr;
rst_data->rcdev.nr_resets = ARRAY_SIZE(en7581_rst_map);
rst_data->rcdev.of_xlate = en7523_reset_xlate;
rst_data->rcdev.ops = &en7523_reset_ops;
rst_data->rcdev.ops = &en7581_reset_ops;
rst_data->rcdev.of_node = dev->of_node;
rst_data->rcdev.of_reset_n_cells = 1;
rst_data->rcdev.owner = THIS_MODULE;
@@ -556,28 +668,38 @@ static int en7523_reset_register(struct platform_device *pdev,
return devm_reset_controller_register(dev, &rst_data->rcdev);
}
static int en7523_clk_probe(struct platform_device *pdev)
static int en7581_clk_hw_init(struct platform_device *pdev,
struct clk_hw_onecell_data *clk_data)
{
struct device_node *node = pdev->dev.of_node;
const struct en_clk_soc_data *soc_data;
struct clk_hw_onecell_data *clk_data;
void __iomem *base, *np_base;
int r;
struct regmap *map;
void __iomem *base;
u32 val;
map = syscon_regmap_lookup_by_compatible("airoha,en7581-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);
np_base = devm_platform_ioremap_resource(pdev, 1);
if (IS_ERR(np_base))
return PTR_ERR(np_base);
en7581_register_clocks(&pdev->dev, clk_data, map, base);
soc_data = device_get_match_data(&pdev->dev);
if (soc_data->hw_init) {
r = soc_data->hw_init(pdev, np_base);
if (r)
return r;
}
val = readl(base + REG_NP_SCU_SSTR);
val &= ~(REG_PCIE_XSI0_SEL_MASK | REG_PCIE_XSI1_SEL_MASK);
writel(val, base + REG_NP_SCU_SSTR);
val = readl(base + REG_NP_SCU_PCIC);
writel(val | 3, base + REG_NP_SCU_PCIC);
return en7581_reset_register(&pdev->dev, base);
}
static int en7523_clk_probe(struct platform_device *pdev)
{
struct device_node *node = pdev->dev.of_node;
const struct en_clk_soc_data *soc_data;
struct clk_hw_onecell_data *clk_data;
int r;
clk_data = devm_kzalloc(&pdev->dev,
struct_size(clk_data, hws, EN7523_NUM_CLOCKS),
@@ -585,21 +707,12 @@ static int en7523_clk_probe(struct platform_device *pdev)
if (!clk_data)
return -ENOMEM;
en7523_register_clocks(&pdev->dev, clk_data, base, np_base);
r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data);
soc_data = device_get_match_data(&pdev->dev);
r = soc_data->hw_init(pdev, clk_data);
if (r)
return dev_err_probe(&pdev->dev, r, "Could not register clock provider: %s\n",
pdev->name);
return r;
r = en7523_reset_register(pdev, soc_data);
if (r) {
of_clk_del_provider(node);
return dev_err_probe(&pdev->dev, r, "Could not register reset controller: %s\n",
pdev->name);
}
return 0;
return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data);
}
static const struct en_clk_soc_data en7523_data = {
@@ -608,6 +721,7 @@ static const struct en_clk_soc_data en7523_data = {
.prepare = en7523_pci_prepare,
.unprepare = en7523_pci_unprepare,
},
.hw_init = en7523_clk_hw_init,
};
static const struct en_clk_soc_data en7581_data = {
@@ -616,11 +730,6 @@ static const struct en_clk_soc_data en7581_data = {
.enable = en7581_pci_enable,
.disable = en7581_pci_disable,
},
.reset = {
.bank_ofs = en7581_rst_ofs,
.idx_map = en7581_rst_map,
.idx_map_nr = ARRAY_SIZE(en7581_rst_map),
},
.hw_init = en7581_clk_hw_init,
};
+191 -14
View File
@@ -17,13 +17,15 @@
#include <linux/device.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
/**
* DOC: basic gpio gated clock which can be enabled and disabled
* with gpio output
* Traits of this clock:
* prepare - clk_(un)prepare only ensures parent is (un)prepared
* enable - clk_enable and clk_disable are functional & control gpio
* prepare - clk_(un)prepare are functional and control a gpio that can sleep
* enable - clk_enable and clk_disable are functional & control
* non-sleeping gpio
* rate - inherits rate from parent. No clk_set_rate support
* parent - fixed parent. No clk_set_parent support
*/
@@ -199,7 +201,6 @@ static int gpio_clk_driver_probe(struct platform_device *pdev)
struct gpio_desc *gpiod;
struct clk_hw *hw;
bool is_mux;
int ret;
is_mux = of_device_is_compatible(node, "gpio-mux-clock");
@@ -211,17 +212,9 @@ static int gpio_clk_driver_probe(struct platform_device *pdev)
gpio_name = is_mux ? "select" : "enable";
gpiod = devm_gpiod_get(dev, gpio_name, GPIOD_OUT_LOW);
if (IS_ERR(gpiod)) {
ret = PTR_ERR(gpiod);
if (ret == -EPROBE_DEFER)
pr_debug("%pOFn: %s: GPIOs not yet available, retry later\n",
node, __func__);
else
pr_err("%pOFn: %s: Can't get '%s' named GPIO property\n",
node, __func__,
gpio_name);
return ret;
}
if (IS_ERR(gpiod))
return dev_err_probe(dev, PTR_ERR(gpiod),
"Can't get '%s' named GPIO property\n", gpio_name);
if (is_mux)
hw = clk_hw_register_gpio_mux(dev, gpiod);
@@ -247,3 +240,187 @@ static struct platform_driver gpio_clk_driver = {
},
};
builtin_platform_driver(gpio_clk_driver);
/**
* DOC: gated fixed clock, controlled with a gpio output and a regulator
* Traits of this clock:
* prepare - clk_prepare and clk_unprepare are function & control regulator
* optionally a gpio that can sleep
* enable - clk_enable and clk_disable are functional & control gpio
* rate - rate is fixed and set on clock registration
* parent - fixed clock is a root clock and has no parent
*/
/**
* struct clk_gated_fixed - Gateable fixed rate clock
* @clk_gpio: instance of clk_gpio for gate-gpio
* @supply: supply regulator
* @rate: fixed rate
*/
struct clk_gated_fixed {
struct clk_gpio clk_gpio;
struct regulator *supply;
unsigned long rate;
};
#define to_clk_gated_fixed(_clk_gpio) container_of(_clk_gpio, struct clk_gated_fixed, clk_gpio)
static unsigned long clk_gated_fixed_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
return to_clk_gated_fixed(to_clk_gpio(hw))->rate;
}
static int clk_gated_fixed_prepare(struct clk_hw *hw)
{
struct clk_gated_fixed *clk = to_clk_gated_fixed(to_clk_gpio(hw));
if (!clk->supply)
return 0;
return regulator_enable(clk->supply);
}
static void clk_gated_fixed_unprepare(struct clk_hw *hw)
{
struct clk_gated_fixed *clk = to_clk_gated_fixed(to_clk_gpio(hw));
if (!clk->supply)
return;
regulator_disable(clk->supply);
}
static int clk_gated_fixed_is_prepared(struct clk_hw *hw)
{
struct clk_gated_fixed *clk = to_clk_gated_fixed(to_clk_gpio(hw));
if (!clk->supply)
return true;
return regulator_is_enabled(clk->supply);
}
/*
* Fixed gated clock with non-sleeping gpio.
*
* Prepare operation turns on the supply regulator
* and the enable operation switches the enable-gpio.
*/
static const struct clk_ops clk_gated_fixed_ops = {
.prepare = clk_gated_fixed_prepare,
.unprepare = clk_gated_fixed_unprepare,
.is_prepared = clk_gated_fixed_is_prepared,
.enable = clk_gpio_gate_enable,
.disable = clk_gpio_gate_disable,
.is_enabled = clk_gpio_gate_is_enabled,
.recalc_rate = clk_gated_fixed_recalc_rate,
};
static int clk_sleeping_gated_fixed_prepare(struct clk_hw *hw)
{
int ret;
ret = clk_gated_fixed_prepare(hw);
if (ret)
return ret;
ret = clk_sleeping_gpio_gate_prepare(hw);
if (ret)
clk_gated_fixed_unprepare(hw);
return ret;
}
static void clk_sleeping_gated_fixed_unprepare(struct clk_hw *hw)
{
clk_gated_fixed_unprepare(hw);
clk_sleeping_gpio_gate_unprepare(hw);
}
/*
* Fixed gated clock with non-sleeping gpio.
*
* Enabling the supply regulator and switching the enable-gpio happens
* both in the prepare step.
* is_prepared only needs to check the gpio state, as toggling the
* gpio is the last step when preparing.
*/
static const struct clk_ops clk_sleeping_gated_fixed_ops = {
.prepare = clk_sleeping_gated_fixed_prepare,
.unprepare = clk_sleeping_gated_fixed_unprepare,
.is_prepared = clk_sleeping_gpio_gate_is_prepared,
.recalc_rate = clk_gated_fixed_recalc_rate,
};
static int clk_gated_fixed_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct clk_gated_fixed *clk;
const struct clk_ops *ops;
const char *clk_name;
u32 rate;
int ret;
clk = devm_kzalloc(dev, sizeof(*clk), GFP_KERNEL);
if (!clk)
return -ENOMEM;
ret = device_property_read_u32(dev, "clock-frequency", &rate);
if (ret)
return dev_err_probe(dev, ret, "Failed to get clock-frequency\n");
clk->rate = rate;
ret = device_property_read_string(dev, "clock-output-names", &clk_name);
if (ret)
clk_name = fwnode_get_name(dev->fwnode);
clk->supply = devm_regulator_get_optional(dev, "vdd");
if (IS_ERR(clk->supply)) {
if (PTR_ERR(clk->supply) != -ENODEV)
return dev_err_probe(dev, PTR_ERR(clk->supply),
"Failed to get regulator\n");
clk->supply = NULL;
}
clk->clk_gpio.gpiod = devm_gpiod_get_optional(dev, "enable",
GPIOD_OUT_LOW);
if (IS_ERR(clk->clk_gpio.gpiod))
return dev_err_probe(dev, PTR_ERR(clk->clk_gpio.gpiod),
"Failed to get gpio\n");
if (gpiod_cansleep(clk->clk_gpio.gpiod))
ops = &clk_sleeping_gated_fixed_ops;
else
ops = &clk_gated_fixed_ops;
clk->clk_gpio.hw.init = CLK_HW_INIT_NO_PARENT(clk_name, ops, 0);
/* register the clock */
ret = devm_clk_hw_register(dev, &clk->clk_gpio.hw);
if (ret)
return dev_err_probe(dev, ret,
"Failed to register clock\n");
ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get,
&clk->clk_gpio.hw);
if (ret)
return dev_err_probe(dev, ret,
"Failed to register clock provider\n");
return 0;
}
static const struct of_device_id gated_fixed_clk_match_table[] = {
{ .compatible = "gated-fixed-clock" },
{ /* sentinel */ }
};
static struct platform_driver gated_fixed_clk_driver = {
.probe = clk_gated_fixed_probe,
.driver = {
.name = "gated-fixed-clk",
.of_match_table = gated_fixed_clk_match_table,
},
};
builtin_platform_driver(gated_fixed_clk_driver);
+30
View File
@@ -203,5 +203,35 @@ int of_clk_hw_register_kunit(struct kunit *test, struct device_node *node, struc
}
EXPORT_SYMBOL_GPL(of_clk_hw_register_kunit);
KUNIT_DEFINE_ACTION_WRAPPER(of_clk_del_provider_wrapper,
of_clk_del_provider, struct device_node *);
/**
* of_clk_add_hw_provider_kunit() - Test managed of_clk_add_hw_provider()
* @test: The test context
* @np: Device node pointer associated with clock provider
* @get: Callback for decoding clk_hw
* @data: Context pointer for @get callback.
*
* Just like of_clk_add_hw_provider(), except the clk_hw provider is managed by
* the test case and is automatically unregistered after the test case
* concludes.
*
* Return: 0 on success or a negative errno value on failure.
*/
int of_clk_add_hw_provider_kunit(struct kunit *test, struct device_node *np,
struct clk_hw *(*get)(struct of_phandle_args *clkspec, void *data),
void *data)
{
int ret;
ret = of_clk_add_hw_provider(np, get, data);
if (ret)
return ret;
return kunit_add_action_or_reset(test, of_clk_del_provider_wrapper, np);
}
EXPORT_SYMBOL_GPL(of_clk_add_hw_provider_kunit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("KUnit helpers for clk providers and consumers");
+321
View File
@@ -4,6 +4,7 @@
*/
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/clk/clk-conf.h>
#include <linux/of.h>
#include <linux/platform_device.h>
@@ -15,6 +16,7 @@
#include <kunit/platform_device.h>
#include <kunit/test.h>
#include "kunit_clk_assigned_rates.h"
#include "clk_parent_data_test.h"
static const struct clk_ops empty_clk_ops = { };
@@ -3108,7 +3110,326 @@ static struct kunit_suite clk_register_clk_parent_data_device_suite = {
.test_cases = clk_register_clk_parent_data_device_test_cases,
};
struct clk_assigned_rates_context {
struct clk_dummy_context clk0;
struct clk_dummy_context clk1;
};
/*
* struct clk_assigned_rates_test_param - Test parameters for clk_assigned_rates test
* @desc: Test description
* @overlay_begin: Pointer to start of DT overlay to apply for test
* @overlay_end: Pointer to end of DT overlay to apply for test
* @rate0: Initial rate of first clk
* @rate1: Initial rate of second clk
* @consumer_test: true if a consumer is being tested
*/
struct clk_assigned_rates_test_param {
const char *desc;
u8 *overlay_begin;
u8 *overlay_end;
unsigned long rate0;
unsigned long rate1;
bool consumer_test;
};
#define TEST_PARAM_OVERLAY(overlay_name) \
.overlay_begin = of_overlay_begin(overlay_name), \
.overlay_end = of_overlay_end(overlay_name)
static void
clk_assigned_rates_register_clk(struct kunit *test,
struct clk_dummy_context *ctx,
struct device_node *np, const char *name,
unsigned long rate)
{
struct clk_init_data init = { };
init.name = name;
init.ops = &clk_dummy_rate_ops;
ctx->hw.init = &init;
ctx->rate = rate;
KUNIT_ASSERT_EQ(test, 0, of_clk_hw_register_kunit(test, np, &ctx->hw));
KUNIT_ASSERT_EQ(test, ctx->rate, rate);
}
/*
* Does most of the work of the test:
*
* 1. Apply the overlay to test
* 2. Register the clk or clks to test
* 3. Register the clk provider
* 4. Apply clk defaults to the consumer device if this is a consumer test
*
* The tests will set different test_param values to test different scenarios
* and validate that in their test functions.
*/
static int clk_assigned_rates_test_init(struct kunit *test)
{
struct device_node *np, *consumer;
struct clk_hw_onecell_data *data;
struct clk_assigned_rates_context *ctx;
u32 clk_cells;
const struct clk_assigned_rates_test_param *test_param;
test_param = test->param_value;
KUNIT_ASSERT_EQ(test, 0, __of_overlay_apply_kunit(test,
test_param->overlay_begin,
test_param->overlay_end));
KUNIT_ASSERT_NOT_ERR_OR_NULL(test,
ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL));
test->priv = ctx;
KUNIT_ASSERT_NOT_ERR_OR_NULL(test,
np = of_find_compatible_node(NULL, NULL, "test,clk-assigned-rates"));
of_node_put_kunit(test, np);
KUNIT_ASSERT_EQ(test, 0, of_property_read_u32(np, "#clock-cells", &clk_cells));
/* Only support #clock-cells = <0> or <1> */
KUNIT_ASSERT_LT(test, clk_cells, 2);
clk_assigned_rates_register_clk(test, &ctx->clk0, np,
"test_assigned_rate0", test_param->rate0);
if (clk_cells == 0) {
KUNIT_ASSERT_EQ(test, 0,
of_clk_add_hw_provider_kunit(test, np, of_clk_hw_simple_get,
&ctx->clk0.hw));
} else if (clk_cells == 1) {
clk_assigned_rates_register_clk(test, &ctx->clk1, np,
"test_assigned_rate1", test_param->rate1);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test,
data = kunit_kzalloc(test, struct_size(data, hws, 2), GFP_KERNEL));
data->num = 2;
data->hws[0] = &ctx->clk0.hw;
data->hws[1] = &ctx->clk1.hw;
KUNIT_ASSERT_EQ(test, 0,
of_clk_add_hw_provider_kunit(test, np, of_clk_hw_onecell_get, data));
}
/* Consumers are optional */
if (test_param->consumer_test) {
KUNIT_ASSERT_NOT_ERR_OR_NULL(test,
consumer = of_find_compatible_node(NULL, NULL, "test,clk-consumer"));
of_node_put_kunit(test, consumer);
KUNIT_ASSERT_EQ(test, 0, of_clk_set_defaults(consumer, false));
}
return 0;
}
static void clk_assigned_rates_assigns_one(struct kunit *test)
{
struct clk_assigned_rates_context *ctx = test->priv;
KUNIT_EXPECT_EQ(test, ctx->clk0.rate, ASSIGNED_RATES_0_RATE);
}
static void clk_assigned_rates_assigns_multiple(struct kunit *test)
{
struct clk_assigned_rates_context *ctx = test->priv;
KUNIT_EXPECT_EQ(test, ctx->clk0.rate, ASSIGNED_RATES_0_RATE);
KUNIT_EXPECT_EQ(test, ctx->clk1.rate, ASSIGNED_RATES_1_RATE);
}
static void clk_assigned_rates_skips(struct kunit *test)
{
struct clk_assigned_rates_context *ctx = test->priv;
const struct clk_assigned_rates_test_param *test_param = test->param_value;
KUNIT_EXPECT_NE(test, ctx->clk0.rate, ASSIGNED_RATES_0_RATE);
KUNIT_EXPECT_EQ(test, ctx->clk0.rate, test_param->rate0);
}
OF_OVERLAY_DECLARE(kunit_clk_assigned_rates_one);
OF_OVERLAY_DECLARE(kunit_clk_assigned_rates_one_consumer);
OF_OVERLAY_DECLARE(kunit_clk_assigned_rates_u64_one);
OF_OVERLAY_DECLARE(kunit_clk_assigned_rates_u64_one_consumer);
/* Test cases that assign one rate */
static const struct clk_assigned_rates_test_param clk_assigned_rates_assigns_one_test_params[] = {
{
/*
* Test that a single cell assigned-clock-rates property
* assigns the rate when the property is in the provider.
*/
.desc = "provider assigns",
TEST_PARAM_OVERLAY(kunit_clk_assigned_rates_one),
},
{
/*
* Test that a single cell assigned-clock-rates property
* assigns the rate when the property is in the consumer.
*/
.desc = "consumer assigns",
TEST_PARAM_OVERLAY(kunit_clk_assigned_rates_one_consumer),
.consumer_test = true,
},
{
/*
* Test that a single cell assigned-clock-rates-u64 property
* assigns the rate when the property is in the provider.
*/
.desc = "provider assigns u64",
TEST_PARAM_OVERLAY(kunit_clk_assigned_rates_u64_one),
},
{
/*
* Test that a single cell assigned-clock-rates-u64 property
* assigns the rate when the property is in the consumer.
*/
.desc = "consumer assigns u64",
TEST_PARAM_OVERLAY(kunit_clk_assigned_rates_u64_one_consumer),
.consumer_test = true,
},
};
KUNIT_ARRAY_PARAM_DESC(clk_assigned_rates_assigns_one,
clk_assigned_rates_assigns_one_test_params, desc)
OF_OVERLAY_DECLARE(kunit_clk_assigned_rates_multiple);
OF_OVERLAY_DECLARE(kunit_clk_assigned_rates_multiple_consumer);
OF_OVERLAY_DECLARE(kunit_clk_assigned_rates_u64_multiple);
OF_OVERLAY_DECLARE(kunit_clk_assigned_rates_u64_multiple_consumer);
/* Test cases that assign multiple rates */
static const struct clk_assigned_rates_test_param clk_assigned_rates_assigns_multiple_test_params[] = {
{
/*
* Test that a multiple cell assigned-clock-rates property
* assigns the rates when the property is in the provider.
*/
.desc = "provider assigns",
TEST_PARAM_OVERLAY(kunit_clk_assigned_rates_multiple),
},
{
/*
* Test that a multiple cell assigned-clock-rates property
* assigns the rates when the property is in the consumer.
*/
.desc = "consumer assigns",
TEST_PARAM_OVERLAY(kunit_clk_assigned_rates_multiple_consumer),
.consumer_test = true,
},
{
/*
* Test that a single cell assigned-clock-rates-u64 property
* assigns the rate when the property is in the provider.
*/
.desc = "provider assigns u64",
TEST_PARAM_OVERLAY(kunit_clk_assigned_rates_u64_multiple),
},
{
/*
* Test that a multiple cell assigned-clock-rates-u64 property
* assigns the rates when the property is in the consumer.
*/
.desc = "consumer assigns u64",
TEST_PARAM_OVERLAY(kunit_clk_assigned_rates_u64_multiple_consumer),
.consumer_test = true,
},
};
KUNIT_ARRAY_PARAM_DESC(clk_assigned_rates_assigns_multiple,
clk_assigned_rates_assigns_multiple_test_params,
desc)
OF_OVERLAY_DECLARE(kunit_clk_assigned_rates_without);
OF_OVERLAY_DECLARE(kunit_clk_assigned_rates_without_consumer);
OF_OVERLAY_DECLARE(kunit_clk_assigned_rates_zero);
OF_OVERLAY_DECLARE(kunit_clk_assigned_rates_zero_consumer);
OF_OVERLAY_DECLARE(kunit_clk_assigned_rates_null);
OF_OVERLAY_DECLARE(kunit_clk_assigned_rates_null_consumer);
/* Test cases that skip changing the rate due to malformed DT */
static const struct clk_assigned_rates_test_param clk_assigned_rates_skips_test_params[] = {
{
/*
* Test that an assigned-clock-rates property without an assigned-clocks
* property fails when the property is in the provider.
*/
.desc = "provider missing assigned-clocks",
TEST_PARAM_OVERLAY(kunit_clk_assigned_rates_without),
.rate0 = 3000,
},
{
/*
* Test that an assigned-clock-rates property without an assigned-clocks
* property fails when the property is in the consumer.
*/
.desc = "consumer missing assigned-clocks",
TEST_PARAM_OVERLAY(kunit_clk_assigned_rates_without_consumer),
.rate0 = 3000,
.consumer_test = true,
},
{
/*
* Test that an assigned-clock-rates property of zero doesn't
* set a rate when the property is in the provider.
*/
.desc = "provider assigned-clock-rates of zero",
TEST_PARAM_OVERLAY(kunit_clk_assigned_rates_zero),
.rate0 = 3000,
},
{
/*
* Test that an assigned-clock-rates property of zero doesn't
* set a rate when the property is in the consumer.
*/
.desc = "consumer assigned-clock-rates of zero",
TEST_PARAM_OVERLAY(kunit_clk_assigned_rates_zero_consumer),
.rate0 = 3000,
.consumer_test = true,
},
{
/*
* Test that an assigned-clocks property with a null phandle
* doesn't set a rate when the property is in the provider.
*/
.desc = "provider assigned-clocks null phandle",
TEST_PARAM_OVERLAY(kunit_clk_assigned_rates_null),
.rate0 = 3000,
},
{
/*
* Test that an assigned-clocks property with a null phandle
* doesn't set a rate when the property is in the consumer.
*/
.desc = "provider assigned-clocks null phandle",
TEST_PARAM_OVERLAY(kunit_clk_assigned_rates_null_consumer),
.rate0 = 3000,
.consumer_test = true,
},
};
KUNIT_ARRAY_PARAM_DESC(clk_assigned_rates_skips,
clk_assigned_rates_skips_test_params,
desc)
static struct kunit_case clk_assigned_rates_test_cases[] = {
KUNIT_CASE_PARAM(clk_assigned_rates_assigns_one,
clk_assigned_rates_assigns_one_gen_params),
KUNIT_CASE_PARAM(clk_assigned_rates_assigns_multiple,
clk_assigned_rates_assigns_multiple_gen_params),
KUNIT_CASE_PARAM(clk_assigned_rates_skips,
clk_assigned_rates_skips_gen_params),
{}
};
/*
* Test suite for assigned-clock-rates{-u64} DT property.
*/
static struct kunit_suite clk_assigned_rates_suite = {
.name = "clk_assigned_rates",
.test_cases = clk_assigned_rates_test_cases,
.init = clk_assigned_rates_test_init,
};
kunit_test_suites(
&clk_assigned_rates_suite,
&clk_leaf_mux_set_rate_parent_test_suite,
&clk_test_suite,
&clk_multiple_parents_mux_test_suite,
+8
View File
@@ -0,0 +1,8 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _KUNIT_CLK_ASSIGNED_RATES_H
#define _KUNIT_CLK_ASSIGNED_RATES_H
#define ASSIGNED_RATES_0_RATE 1600000
#define ASSIGNED_RATES_1_RATE 9700000
#endif
@@ -0,0 +1,16 @@
// SPDX-License-Identifier: GPL-2.0
/dts-v1/;
/plugin/;
#include "kunit_clk_assigned_rates.h"
&{/} {
clk: kunit-clock {
compatible = "test,clk-assigned-rates";
#clock-cells = <1>;
assigned-clocks = <&clk 0>,
<&clk 1>;
assigned-clock-rates = <ASSIGNED_RATES_0_RATE>,
<ASSIGNED_RATES_1_RATE>;
};
};
@@ -0,0 +1,20 @@
// SPDX-License-Identifier: GPL-2.0
/dts-v1/;
/plugin/;
#include "kunit_clk_assigned_rates.h"
&{/} {
clk: kunit-clock {
compatible = "test,clk-assigned-rates";
#clock-cells = <1>;
};
kunit-clock-consumer {
compatible = "test,clk-consumer";
assigned-clocks = <&clk 0>,
<&clk 1>;
assigned-clock-rates = <ASSIGNED_RATES_0_RATE>,
<ASSIGNED_RATES_1_RATE>;
};
};
@@ -0,0 +1,14 @@
// SPDX-License-Identifier: GPL-2.0
/dts-v1/;
/plugin/;
#include "kunit_clk_assigned_rates.h"
&{/} {
clk: kunit-clock {
compatible = "test,clk-assigned-rates";
#clock-cells = <0>;
assigned-clocks = <0>;
assigned-clock-rates = <ASSIGNED_RATES_0_RATE>;
};
};

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