* Re: [PATCH v3 2/2] clk: amlogic: Add A9 peripherals clock controller driver
From: Jerome Brunet @ 2026-06-10 12:49 UTC (permalink / raw)
To: Jian Hu via B4 Relay
Cc: Neil Armstrong, Michael Turquette, Stephen Boyd, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Xianwei Zhao, Kevin Hilman,
Martin Blumenstingl, jian.hu, linux-amlogic, linux-clk,
devicetree, linux-kernel, linux-arm-kernel
In-Reply-To: <20260610-a9_peripherals-v3-2-d07a78085f71@amlogic.com>
On mer. 10 juin 2026 at 16:14, Jian Hu via B4 Relay <devnull+jian.hu.amlogic.com@kernel.org> wrote:
> From: Jian Hu <jian.hu@amlogic.com>
>
> Add the peripherals clock controller driver for the Amlogic A9 SoC family.
>
> Signed-off-by: Jian Hu <jian.hu@amlogic.com>
> ---
> drivers/clk/meson/Kconfig | 15 +
> drivers/clk/meson/Makefile | 1 +
> drivers/clk/meson/a9-peripherals.c | 1925 ++++++++++++++++++++++++++++++++++++
> 3 files changed, 1941 insertions(+)
>
> diff --git a/drivers/clk/meson/Kconfig b/drivers/clk/meson/Kconfig
> index cf8cf3f9e4ee..86d2e270e1b8 100644
> --- a/drivers/clk/meson/Kconfig
> +++ b/drivers/clk/meson/Kconfig
> @@ -132,6 +132,21 @@ config COMMON_CLK_A1_PERIPHERALS
> device, A1 SoC Family. Say Y if you want A1 Peripherals clock
> controller to work.
>
> +config COMMON_CLK_A9_PERIPHERALS
> + tristate "Amlogic A9 SoC peripherals clock controller support"
> + depends on ARM64 || COMPILE_TEST
> + default ARCH_MESON
> + select COMMON_CLK_MESON_REGMAP
> + select COMMON_CLK_MESON_CLKC_UTILS
> + select COMMON_CLK_MESON_DUALDIV
> + select COMMON_CLK_MESON_VID_PLL_DIV
> + imply COMMON_CLK_SCMI
> + imply COMMON_CLK_A9_PLL
> + help
> + Support for the peripherals clock controller on Amlogic A311Y3 based
> + device, AKA A9. Peripherals are required by most peripheral to operate.
> + Say Y if you want A9 peripherals clock controller to work.
> +
> config COMMON_CLK_C3_PLL
> tristate "Amlogic C3 PLL clock controller"
> depends on ARM64
> diff --git a/drivers/clk/meson/Makefile b/drivers/clk/meson/Makefile
> index c6719694a242..bccd9ace9201 100644
> --- a/drivers/clk/meson/Makefile
> +++ b/drivers/clk/meson/Makefile
> @@ -19,6 +19,7 @@ obj-$(CONFIG_COMMON_CLK_AXG) += axg.o axg-aoclk.o
> obj-$(CONFIG_COMMON_CLK_AXG_AUDIO) += axg-audio.o
> obj-$(CONFIG_COMMON_CLK_A1_PLL) += a1-pll.o
> obj-$(CONFIG_COMMON_CLK_A1_PERIPHERALS) += a1-peripherals.o
> +obj-$(CONFIG_COMMON_CLK_A9_PERIPHERALS) += a9-peripherals.o
> obj-$(CONFIG_COMMON_CLK_C3_PLL) += c3-pll.o
> obj-$(CONFIG_COMMON_CLK_C3_PERIPHERALS) += c3-peripherals.o
> obj-$(CONFIG_COMMON_CLK_GXBB) += gxbb.o gxbb-aoclk.o
> diff --git a/drivers/clk/meson/a9-peripherals.c b/drivers/clk/meson/a9-peripherals.c
> new file mode 100644
> index 000000000000..fef48613e186
> --- /dev/null
> +++ b/drivers/clk/meson/a9-peripherals.c
> @@ -0,0 +1,1925 @@
> +// SPDX-License-Identifier: (GPL-2.0-only OR MIT)
> +/*
> + * Copyright (C) 2026 Amlogic, Inc. All rights reserved
> + */
> +
> +#include <dt-bindings/clock/amlogic,a9-peripherals-clkc.h>
> +#include <linux/clk-provider.h>
> +#include <linux/platform_device.h>
> +#include "clk-regmap.h"
> +#include "clk-dualdiv.h"
> +#include "meson-clkc-utils.h"
> +#include "vid-pll-div.h"
> +
> +#define SYS_CLK_EN0_REG0 0x30
> +#define SYS_CLK_EN0_REG1 0x34
> +#define SYS_CLK_EN0_REG2 0x38
> +#define SYS_CLK_EN0_REG3 0x3c
> +#define SD_EMMC_CLK_CTRL0 0x90
> +#define SD_EMMC_CLK_CTRL1 0x94
> +#define PWM_CLK_H_CTRL 0xbc
> +#define PWM_CLK_I_CTRL 0xc0
> +#define PWM_CLK_J_CTRL 0xc4
> +#define PWM_CLK_K_CTRL 0xc8
> +#define PWM_CLK_L_CTRL 0xcc
> +#define PWM_CLK_M_CTRL 0xd0
> +#define PWM_CLK_N_CTRL 0xd4
> +#define SPISG_CLK_CTRL 0x100
> +#define SPISG_CLK_CTRL1 0x104
> +#define SAR_CLK_CTRL 0x150
> +#define AMFC_CLK_CTRL 0x154
> +#define NNA_CLK_CTRL 0x15c
> +#define USB_CLK_CTRL 0x160
> +#define PCIE_TL_CLK_CTRL 0x164
> +#define CMPR_CLK_CTRL 0x168
> +#define DEWARP_CLK_CTRL 0x16c
> +#define SC_CLK_CTRL 0x170
> +#define DPTX_CLK_CTRL 0x178
> +#define ISP_CLK_CTRL 0x17c
> +#define CVE_CLK_CTRL 0x180
> +#define PP_CLK_CTRL 0x184
> +#define GLB_CLK_CTRL 0x188
> +#define USB_CLK_CTRL0 0x18c
> +#define USB_CLK_CTRL1 0x190
> +#define CAN_CLK_CTRL 0x194
> +#define CAN_CLK_CTRL1 0x198
> +#define I3C_CLK_CTRL 0x19c
> +#define TS_CLK_CTRL 0x1a0
> +#define ETH_CLK_CTRL 0x1a4
> +#define GEN_CLK_CTRL 0x1a8
> +#define CLK12_24_CTRL 0x1ac
> +#define MALI_CLK_CTRL 0x200
> +#define MALI_STACK_CLK_CTRL 0x204
> +#define DSPA_CLK_CTRL 0x220
> +#define HEVCF_CLK_CTRL 0x240
> +#define HCODEC_CLK_CTRL 0x244
> +#define VPU_CLK_CTRL 0x260
> +#define VAPB_CLK_CTRL 0x268
> +#define VPU_CLKB_CTRL 0x280
> +#define HDMI_CLK_CTRL 0x284
> +#define HTX_CLK_CTRL 0x28c
> +#define HTX_CLK_CTRL1 0x290
> +#define HRX_CLK_CTRL 0x294
> +#define HRX_CLK_CTRL1 0x298
> +#define HRX_CLK_CTRL2 0x29c
> +#define HRX_CLK_CTRL3 0x2a0
> +#define VID_LOCK_CLK_CTRL 0x2a4
> +#define VDIN_MEAS_CLK_CTRL 0x2a8
> +#define VID_PLL_CLK_DIV 0x2b0
> +#define VID_CLK_CTRL 0x2c0
> +#define VID_CLK_CTRL2 0x2c4
> +#define VID_CLK_DIV 0x2c8
> +#define VIID_CLK_DIV 0x2cc
> +#define VIID_CLK_CTRL 0x2d0
> +#define MIPI_CSI_PHY_CLK_CTRL 0x2e0
> +#define DSI_MEAS_CLK_CTRL 0x2f4
> +
> +#define A9_COMP_SEL(_name, _reg, _shift, _mask, _pdata, _table) \
> + MESON_COMP_SEL(a9_, _name, _reg, _shift, _mask, _pdata, _table, 0, 0)
> +
> +#define A9_COMP_DIV(_name, _reg, _shift, _width) \
> + MESON_COMP_DIV(a9_, _name, _reg, _shift, _width, 0, CLK_SET_RATE_PARENT)
> +
> +#define A9_COMP_GATE(_name, _reg, _bit, _iflags) \
> + MESON_COMP_GATE(a9_, _name, _reg, _bit, CLK_SET_RATE_PARENT | (_iflags))
> +
> +static const struct clk_parent_data a9_sys_pclk_parents = { .fw_name = "sys" };
> +
> +#define A9_SYS_PCLK(_name, _reg, _bit) \
> + MESON_PCLK(a9_##_name, _reg, _bit, &a9_sys_pclk_parents, 0)
> +
> +static A9_SYS_PCLK(sys_am_axi, SYS_CLK_EN0_REG0, 0);
> +static A9_SYS_PCLK(sys_dos, SYS_CLK_EN0_REG0, 1);
> +static A9_SYS_PCLK(sys_mipi_dsi, SYS_CLK_EN0_REG0, 3);
> +static A9_SYS_PCLK(sys_eth_phy, SYS_CLK_EN0_REG0, 4);
> +static A9_SYS_PCLK(sys_amfc, SYS_CLK_EN0_REG0, 5);
> +static A9_SYS_PCLK(sys_mali, SYS_CLK_EN0_REG0, 6);
> +static A9_SYS_PCLK(sys_nna, SYS_CLK_EN0_REG0, 7);
> +static A9_SYS_PCLK(sys_eth_axi, SYS_CLK_EN0_REG0, 8);
> +static A9_SYS_PCLK(sys_dp_apb, SYS_CLK_EN0_REG0, 9);
> +static A9_SYS_PCLK(sys_edptx_apb, SYS_CLK_EN0_REG0, 10);
> +static A9_SYS_PCLK(sys_u3hsg, SYS_CLK_EN0_REG0, 11);
> +static A9_SYS_PCLK(sys_aucpu, SYS_CLK_EN0_REG0, 14);
> +static A9_SYS_PCLK(sys_glb, SYS_CLK_EN0_REG0, 15);
> +static A9_SYS_PCLK(sys_combo_dphy_apb, SYS_CLK_EN0_REG0, 17);
> +static A9_SYS_PCLK(sys_hdmirx_apb, SYS_CLK_EN0_REG0, 18);
> +static A9_SYS_PCLK(sys_hdmirx_pclk, SYS_CLK_EN0_REG0, 19);
> +static A9_SYS_PCLK(sys_mipi_dsi_phy, SYS_CLK_EN0_REG0, 20);
> +static A9_SYS_PCLK(sys_can0, SYS_CLK_EN0_REG0, 21);
> +static A9_SYS_PCLK(sys_can1, SYS_CLK_EN0_REG0, 22);
> +static A9_SYS_PCLK(sys_sd_emmc_a, SYS_CLK_EN0_REG0, 24);
> +static A9_SYS_PCLK(sys_sd_emmc_b, SYS_CLK_EN0_REG0, 25);
> +static A9_SYS_PCLK(sys_sd_emmc_c, SYS_CLK_EN0_REG0, 26);
> +static A9_SYS_PCLK(sys_sc, SYS_CLK_EN0_REG0, 27);
> +static A9_SYS_PCLK(sys_acodec, SYS_CLK_EN0_REG0, 28);
> +static A9_SYS_PCLK(sys_mipi_isp, SYS_CLK_EN0_REG0, 29);
> +static A9_SYS_PCLK(sys_msr, SYS_CLK_EN0_REG0, 30);
> +static A9_SYS_PCLK(sys_audio, SYS_CLK_EN0_REG1, 0);
> +static A9_SYS_PCLK(sys_mipi_dsi_b, SYS_CLK_EN0_REG1, 1);
> +static A9_SYS_PCLK(sys_mipi_dsi1_phy, SYS_CLK_EN0_REG1, 2);
> +static A9_SYS_PCLK(sys_eth, SYS_CLK_EN0_REG1, 3);
> +static A9_SYS_PCLK(sys_eth_1g_mac, SYS_CLK_EN0_REG1, 4);
> +static A9_SYS_PCLK(sys_uart_a, SYS_CLK_EN0_REG1, 5);
> +static A9_SYS_PCLK(sys_uart_f, SYS_CLK_EN0_REG1, 10);
> +static A9_SYS_PCLK(sys_ts_a55, SYS_CLK_EN0_REG1, 11);
> +static A9_SYS_PCLK(sys_eth_1g_axi, SYS_CLK_EN0_REG1, 12);
> +static A9_SYS_PCLK(sys_ts_dos, SYS_CLK_EN0_REG1, 13);
> +static A9_SYS_PCLK(sys_u3drd_b, SYS_CLK_EN0_REG1, 14);
> +static A9_SYS_PCLK(sys_ts_core, SYS_CLK_EN0_REG1, 15);
> +static A9_SYS_PCLK(sys_ts_pll, SYS_CLK_EN0_REG1, 16);
> +static A9_SYS_PCLK(sys_csi_dig_clkin, SYS_CLK_EN0_REG1, 18);
> +static A9_SYS_PCLK(sys_cve, SYS_CLK_EN0_REG1, 19);
> +static A9_SYS_PCLK(sys_ge2d, SYS_CLK_EN0_REG1, 20);
> +static A9_SYS_PCLK(sys_spisg, SYS_CLK_EN0_REG1, 21);
> +static A9_SYS_PCLK(sys_u3drd_1, SYS_CLK_EN0_REG1, 22);
> +static A9_SYS_PCLK(sys_u2h, SYS_CLK_EN0_REG1, 23);
> +static A9_SYS_PCLK(sys_pcie_mac_a, SYS_CLK_EN0_REG1, 24);
> +static A9_SYS_PCLK(sys_u3drd_a, SYS_CLK_EN0_REG1, 25);
> +static A9_SYS_PCLK(sys_u2drd, SYS_CLK_EN0_REG1, 26);
> +static A9_SYS_PCLK(sys_pcie_phy, SYS_CLK_EN0_REG1, 27);
> +static A9_SYS_PCLK(sys_pcie_mac_b, SYS_CLK_EN0_REG1, 28);
> +static A9_SYS_PCLK(sys_periph, SYS_CLK_EN0_REG1, 29);
> +static A9_SYS_PCLK(sys_pio, SYS_CLK_EN0_REG2, 0);
> +static A9_SYS_PCLK(sys_i3c, SYS_CLK_EN0_REG2, 1);
> +static A9_SYS_PCLK(sys_i2c_m_e, SYS_CLK_EN0_REG2, 2);
> +static A9_SYS_PCLK(sys_i2c_m_f, SYS_CLK_EN0_REG2, 3);
> +static A9_SYS_PCLK(sys_hdmitx_apb, SYS_CLK_EN0_REG2, 4);
> +static A9_SYS_PCLK(sys_i2c_m_i, SYS_CLK_EN0_REG2, 5);
> +static A9_SYS_PCLK(sys_i2c_m_g, SYS_CLK_EN0_REG2, 6);
> +static A9_SYS_PCLK(sys_i2c_m_h, SYS_CLK_EN0_REG2, 7);
> +static A9_SYS_PCLK(sys_hdmi20_aes, SYS_CLK_EN0_REG2, 9);
> +static A9_SYS_PCLK(sys_csi2_host, SYS_CLK_EN0_REG2, 16);
> +static A9_SYS_PCLK(sys_csi2_adapt, SYS_CLK_EN0_REG2, 17);
> +static A9_SYS_PCLK(sys_dspa, SYS_CLK_EN0_REG2, 21);
> +static A9_SYS_PCLK(sys_pp_dma, SYS_CLK_EN0_REG2, 22);
> +static A9_SYS_PCLK(sys_pp_wrapper, SYS_CLK_EN0_REG2, 23);
> +static A9_SYS_PCLK(sys_vpu_intr, SYS_CLK_EN0_REG2, 25);
> +static A9_SYS_PCLK(sys_csi2_phy, SYS_CLK_EN0_REG2, 27);
> +static A9_SYS_PCLK(sys_saradc, SYS_CLK_EN0_REG2, 28);
> +static A9_SYS_PCLK(sys_pwm_j, SYS_CLK_EN0_REG2, 30);
> +static A9_SYS_PCLK(sys_pwm_i, SYS_CLK_EN0_REG2, 31);
> +static A9_SYS_PCLK(sys_pwm_h, SYS_CLK_EN0_REG3, 0);
> +static A9_SYS_PCLK(sys_pwm_n, SYS_CLK_EN0_REG3, 8);
> +static A9_SYS_PCLK(sys_pwm_m, SYS_CLK_EN0_REG3, 9);
> +static A9_SYS_PCLK(sys_pwm_l, SYS_CLK_EN0_REG3, 10);
> +static A9_SYS_PCLK(sys_pwm_k, SYS_CLK_EN0_REG3, 11);
> +
> +/* Channel 5 is unconnected. */
> +static u32 a9_sd_emmc_parents_val_table[] = { 0, 1, 2, 3, 4, 6, 7 };
> +static const struct clk_parent_data a9_sd_emmc_parents[] = {
> + { .fw_name = "xtal", },
> + { .fw_name = "fdiv2", },
> + { .fw_name = "fdiv3", },
> + { .fw_name = "hifi0", },
> + { .fw_name = "fdiv2p5", },
> + { .fw_name = "gp1", },
> + { .fw_name = "gp0", }
> +};
> +
> +static A9_COMP_SEL(sd_emmc_a, SD_EMMC_CLK_CTRL0, 9, 0x7, a9_sd_emmc_parents,
> + a9_sd_emmc_parents_val_table);
> +static A9_COMP_DIV(sd_emmc_a, SD_EMMC_CLK_CTRL0, 0, 7);
> +static A9_COMP_GATE(sd_emmc_a, SD_EMMC_CLK_CTRL0, 8, 0);
> +
> +static A9_COMP_SEL(sd_emmc_b, SD_EMMC_CLK_CTRL0, 25, 0x7, a9_sd_emmc_parents,
> + a9_sd_emmc_parents_val_table);
> +static A9_COMP_DIV(sd_emmc_b, SD_EMMC_CLK_CTRL0, 16, 7);
> +static A9_COMP_GATE(sd_emmc_b, SD_EMMC_CLK_CTRL0, 24, 0);
> +
> +static A9_COMP_SEL(sd_emmc_c, SD_EMMC_CLK_CTRL1, 9, 0x7, a9_sd_emmc_parents,
> + a9_sd_emmc_parents_val_table);
> +static A9_COMP_DIV(sd_emmc_c, SD_EMMC_CLK_CTRL1, 0, 7);
> +static A9_COMP_GATE(sd_emmc_c, SD_EMMC_CLK_CTRL1, 8, 0);
> +
> +static const struct clk_parent_data a9_pwm_parents[] = {
> + { .fw_name = "xtal", },
> + { .fw_name = "fdiv5", },
> + { .fw_name = "fdiv4", },
> + { .fw_name = "fdiv3", }
> +};
> +
> +static A9_COMP_SEL(pwm_h, PWM_CLK_H_CTRL, 9, 0x7, a9_pwm_parents, NULL);
> +static A9_COMP_DIV(pwm_h, PWM_CLK_H_CTRL, 0, 8);
> +static A9_COMP_GATE(pwm_h, PWM_CLK_H_CTRL, 8, 0);
> +
> +static A9_COMP_SEL(pwm_i, PWM_CLK_I_CTRL, 9, 0x7, a9_pwm_parents, NULL);
> +static A9_COMP_DIV(pwm_i, PWM_CLK_I_CTRL, 0, 8);
> +static A9_COMP_GATE(pwm_i, PWM_CLK_I_CTRL, 8, 0);
> +
> +static A9_COMP_SEL(pwm_j, PWM_CLK_J_CTRL, 9, 0x7, a9_pwm_parents, NULL);
> +static A9_COMP_DIV(pwm_j, PWM_CLK_J_CTRL, 0, 8);
> +static A9_COMP_GATE(pwm_j, PWM_CLK_J_CTRL, 8, 0);
> +
> +static A9_COMP_SEL(pwm_k, PWM_CLK_K_CTRL, 9, 0x7, a9_pwm_parents, NULL);
> +static A9_COMP_DIV(pwm_k, PWM_CLK_K_CTRL, 0, 8);
> +static A9_COMP_GATE(pwm_k, PWM_CLK_K_CTRL, 8, 0);
> +
> +static A9_COMP_SEL(pwm_l, PWM_CLK_L_CTRL, 9, 0x7, a9_pwm_parents, NULL);
> +static A9_COMP_DIV(pwm_l, PWM_CLK_L_CTRL, 0, 8);
> +static A9_COMP_GATE(pwm_l, PWM_CLK_L_CTRL, 8, 0);
> +
> +static A9_COMP_SEL(pwm_m, PWM_CLK_M_CTRL, 9, 0x7, a9_pwm_parents, NULL);
> +static A9_COMP_DIV(pwm_m, PWM_CLK_M_CTRL, 0, 8);
> +static A9_COMP_GATE(pwm_m, PWM_CLK_M_CTRL, 8, 0);
> +
> +static A9_COMP_SEL(pwm_n, PWM_CLK_N_CTRL, 9, 0x7, a9_pwm_parents, NULL);
> +static A9_COMP_DIV(pwm_n, PWM_CLK_N_CTRL, 0, 8);
> +static A9_COMP_GATE(pwm_n, PWM_CLK_N_CTRL, 8, 0);
> +
> +static const struct clk_parent_data a9_spisg_parents[] = {
> + { .fw_name = "xtal", },
> + { .fw_name = "sys", },
> + { .fw_name = "fdiv4", },
> + { .fw_name = "fdiv3", },
> + { .fw_name = "fdiv2", },
> + { .fw_name = "fdiv5", },
> + { .fw_name = "fdiv7", },
> + { .fw_name = "gp0", }
> +};
> +
> +static A9_COMP_SEL(spisg, SPISG_CLK_CTRL, 9, 0x7, a9_spisg_parents, NULL);
> +static A9_COMP_DIV(spisg, SPISG_CLK_CTRL, 0, 6);
> +static A9_COMP_GATE(spisg, SPISG_CLK_CTRL, 8, 0);
> +
> +static A9_COMP_SEL(spisg1, SPISG_CLK_CTRL, 25, 0x7, a9_spisg_parents, NULL);
> +static A9_COMP_DIV(spisg1, SPISG_CLK_CTRL, 16, 6);
> +static A9_COMP_GATE(spisg1, SPISG_CLK_CTRL, 24, 0);
> +
> +static A9_COMP_SEL(spisg2, SPISG_CLK_CTRL1, 9, 0x7, a9_spisg_parents, NULL);
> +static A9_COMP_DIV(spisg2, SPISG_CLK_CTRL1, 0, 6);
> +static A9_COMP_GATE(spisg2, SPISG_CLK_CTRL1, 8, 0);
> +
> +static const struct clk_parent_data a9_saradc_parents[] = {
> + { .fw_name = "xtal", },
> + { .fw_name = "sys", }
> +};
> +
> +static A9_COMP_SEL(saradc, SAR_CLK_CTRL, 9, 0x7, a9_saradc_parents, NULL);
> +static A9_COMP_DIV(saradc, SAR_CLK_CTRL, 0, 8);
> +static A9_COMP_GATE(saradc, SAR_CLK_CTRL, 8, 0);
> +
> +static const struct clk_parent_data a9_amfc_parents[] = {
> + { .fw_name = "xtal", },
> + { .fw_name = "sys", },
> + { .fw_name = "fdiv2", },
> + { .fw_name = "fdiv2p5", },
> + { .fw_name = "fdiv3", },
> + { .fw_name = "fdiv4", },
> + { .fw_name = "fdiv5", },
> + { .fw_name = "fdiv7", }
> +};
> +
> +static A9_COMP_SEL(amfc, AMFC_CLK_CTRL, 9, 0x7, a9_amfc_parents, NULL);
> +static A9_COMP_DIV(amfc, AMFC_CLK_CTRL, 0, 6);
> +static A9_COMP_GATE(amfc, AMFC_CLK_CTRL, 8, 0);
> +
> +static const struct clk_parent_data a9_nna_parents[] = {
> + { .fw_name = "xtal", },
> + { .fw_name = "fdiv2p5", },
> + { .fw_name = "fdiv4", },
> + { .fw_name = "fdiv3", },
> + { .fw_name = "fdiv5", },
> + { .fw_name = "fdiv2", },
> + { .fw_name = "gp2", },
> + { .fw_name = "hifi0", }
> +};
> +
> +static A9_COMP_SEL(nna, NNA_CLK_CTRL, 9, 0x7, a9_nna_parents, NULL);
> +static A9_COMP_DIV(nna, NNA_CLK_CTRL, 0, 7);
> +static A9_COMP_GATE(nna, NNA_CLK_CTRL, 8, 0);
> +
> +/* Channel 5 and 6 are unconnected. */
> +static u32 a9_usb_250m_parents_val_table[] = { 0, 1, 2, 3, 4, 7 };
> +static const struct clk_parent_data a9_usb_250m_parents[] = {
> + { .fw_name = "fdiv4", },
> + { .fw_name = "fdiv3", },
> + { .fw_name = "fdiv5", },
> + { .fw_name = "fdiv2", },
> + { .fw_name = "fdiv7", },
> + { .fw_name = "fdiv2p5", }
> +};
> +
> +static A9_COMP_SEL(usb_250m, USB_CLK_CTRL, 9, 0x7, a9_usb_250m_parents,
> + a9_usb_250m_parents_val_table);
> +static A9_COMP_DIV(usb_250m, USB_CLK_CTRL, 0, 7);
> +static A9_COMP_GATE(usb_250m, USB_CLK_CTRL, 8, 0);
> +
> +static const struct clk_parent_data a9_usb_48m_pre_parents[] = {
> + { .fw_name = "gp0", },
> + { .fw_name = "gp1", },
> + { .fw_name = "gp2", },
> + { .fw_name = "fdiv2", },
> +};
> +
> +static A9_COMP_SEL(usb_48m_pre, USB_CLK_CTRL, 25, 0x3, a9_usb_48m_pre_parents,
> + NULL);
> +static A9_COMP_DIV(usb_48m_pre, USB_CLK_CTRL, 16, 7);
> +static A9_COMP_GATE(usb_48m_pre, USB_CLK_CTRL, 24, 0);
> +
> +static const struct clk_parent_data a9_pcie_tl_parents[] = {
> + { .fw_name = "fdiv4", },
> + { .fw_name = "fdiv3", },
> + { .fw_name = "fdiv5", },
> + { .fw_name = "fdiv2", },
> + { .fw_name = "fdiv2p5", },
> + { .fw_name = "gp0", },
> + { .fw_name = "sys", },
> + { .fw_name = "xtal", }
> +};
> +
> +static A9_COMP_SEL(pcie_tl, PCIE_TL_CLK_CTRL, 9, 0x7, a9_pcie_tl_parents,
> + NULL);
> +static A9_COMP_DIV(pcie_tl, PCIE_TL_CLK_CTRL, 0, 7);
> +static A9_COMP_GATE(pcie_tl, PCIE_TL_CLK_CTRL, 8, 0);
> +
> +static A9_COMP_SEL(pcie1_tl, PCIE_TL_CLK_CTRL, 25, 0x7, a9_pcie_tl_parents,
> + NULL);
> +static A9_COMP_DIV(pcie1_tl, PCIE_TL_CLK_CTRL, 16, 7);
> +static A9_COMP_GATE(pcie1_tl, PCIE_TL_CLK_CTRL, 24, 0);
> +
> +static const struct clk_parent_data a9_cmpr_parents[] = {
> + { .fw_name = "xtal", },
> + { .fw_name = "fdiv2p5", },
> + { .fw_name = "fdiv3", },
> + { .fw_name = "fdiv4", },
> + { .fw_name = "fdiv5", },
> + { .fw_name = "fdiv7", },
> + { .fw_name = "hifi0", },
> + { .fw_name = "gp1", }
> +};
> +
> +static A9_COMP_SEL(cmpr, CMPR_CLK_CTRL, 25, 0x7, a9_cmpr_parents, NULL);
> +static A9_COMP_DIV(cmpr, CMPR_CLK_CTRL, 16, 7);
> +static A9_COMP_GATE(cmpr, CMPR_CLK_CTRL, 24, 0);
> +
> +static const struct clk_parent_data a9_dewarpa_parents[] = {
> + { .fw_name = "fdiv2p5", },
> + { .fw_name = "fdiv3", },
> + { .fw_name = "fdiv4", },
> + { .fw_name = "fdiv5", },
> + { .fw_name = "fdiv7", },
> + { .fw_name = "gp0", },
> + { .fw_name = "hifi0", },
> + { .fw_name = "gp1", }
> +};
> +
> +static A9_COMP_SEL(dewarpa, DEWARP_CLK_CTRL, 9, 0x7, a9_dewarpa_parents, NULL);
> +static A9_COMP_DIV(dewarpa, DEWARP_CLK_CTRL, 0, 7);
> +static A9_COMP_GATE(dewarpa, DEWARP_CLK_CTRL, 8, 0);
> +
> +static const struct clk_parent_data a9_sc_parents[] = {
> + { .fw_name = "fdiv2", },
> + { .fw_name = "fdiv3", },
> + { .fw_name = "fdiv5", },
> + { .fw_name = "xtal", }
> +};
> +
> +static A9_COMP_SEL(sc_pre, SC_CLK_CTRL, 9, 0x7, a9_sc_parents, NULL);
> +static A9_COMP_DIV(sc_pre, SC_CLK_CTRL, 0, 8);
> +static A9_COMP_GATE(sc_pre, SC_CLK_CTRL, 8, 0);
> +
> +static struct clk_regmap a9_sc = {
> + .data = &(struct clk_regmap_div_data) {
> + .offset = SC_CLK_CTRL,
> + .shift = 16,
> + .width = 4,
> + },
> + .hw.init = CLK_HW_INIT_HW("sc", &a9_sc_pre.hw,
> + &clk_regmap_divider_ops, CLK_SET_RATE_PARENT),
> +};
> +
> +static const struct clk_parent_data a9_dptx_apb2_parents[] = {
> + { .fw_name = "xtal", },
> + { .fw_name = "sys", },
> + { .fw_name = "fdiv4", },
> + { .fw_name = "fdiv5", }
> +};
> +
> +static A9_COMP_SEL(dptx_apb2, DPTX_CLK_CTRL, 9, 0x7, a9_dptx_apb2_parents, NULL);
> +static A9_COMP_DIV(dptx_apb2, DPTX_CLK_CTRL, 0, 7);
> +static A9_COMP_GATE(dptx_apb2, DPTX_CLK_CTRL, 8, 0);
> +
> +static const struct clk_parent_data a9_dptx_aud_parents[] = {
> + { .fw_name = "xtal", },
> + { .fw_name = "sys", },
> + { .fw_name = "fdiv3", },
> + { .fw_name = "fdiv4", }
> +};
> +
> +static A9_COMP_SEL(dptx_aud, DPTX_CLK_CTRL, 25, 0x7, a9_dptx_aud_parents, NULL);
> +static A9_COMP_DIV(dptx_aud, DPTX_CLK_CTRL, 16, 7);
> +static A9_COMP_GATE(dptx_aud, DPTX_CLK_CTRL, 24, 0);
> +
> +static const struct clk_parent_data a9_isp_parents[] = {
> + { .fw_name = "fdiv2p5", },
> + { .fw_name = "fdiv3", },
> + { .fw_name = "fdiv4", },
> + { .fw_name = "fdiv5", },
> + { .fw_name = "gp0", },
> + { .fw_name = "hifi0", },
> + { .fw_name = "fdiv2", },
> + { .fw_name = "xtal", }
> +};
> +
> +static A9_COMP_SEL(isp, ISP_CLK_CTRL, 9, 0x7, a9_isp_parents, NULL);
> +static A9_COMP_DIV(isp, ISP_CLK_CTRL, 0, 7);
> +static A9_COMP_GATE(isp, ISP_CLK_CTRL, 8, 0);
> +
> +static const struct clk_parent_data a9_cve_vge_parents[] = {
> + { .fw_name = "xtal", },
> + { .fw_name = "fdiv2p5", },
> + { .fw_name = "fdiv3", },
> + { .fw_name = "fdiv4", },
> + { .fw_name = "hifi0", },
> + { .fw_name = "fdiv5", },
> + { .fw_name = "gp0", },
> + { .fw_name = "rtc", }
> +};
> +
> +static A9_COMP_SEL(cve, CVE_CLK_CTRL, 9, 0x7, a9_cve_vge_parents, NULL);
> +static A9_COMP_DIV(cve, CVE_CLK_CTRL, 0, 7);
> +static A9_COMP_GATE(cve, CVE_CLK_CTRL, 8, 0);
> +
> +static A9_COMP_SEL(vge, CVE_CLK_CTRL, 25, 0x7, a9_cve_vge_parents, NULL);
> +static A9_COMP_DIV(vge, CVE_CLK_CTRL, 16, 7);
> +static A9_COMP_GATE(vge, CVE_CLK_CTRL, 24, 0);
> +
> +static const struct clk_parent_data a9_pp_parents[] = {
> + { .fw_name = "fdiv4", },
> + { .fw_name = "fdiv3", },
> + { .fw_name = "fdiv5", },
> + { .fw_name = "fdiv2", },
> + { .fw_name = "fdiv2p5", },
> + { .fw_name = "gp0", },
> + { .fw_name = "sys", },
> + { .fw_name = "xtal", }
> +};
> +
> +static A9_COMP_SEL(pp, PP_CLK_CTRL, 9, 0x7, a9_pp_parents, NULL);
> +static A9_COMP_DIV(pp, PP_CLK_CTRL, 0, 6);
> +static A9_COMP_GATE(pp, PP_CLK_CTRL, 8, 0);
> +
> +/* Channel 6 is unconnected. */
> +static u32 a9_glb_parents_val_table[] = { 0, 1, 2, 3, 4, 5, 7 };
> +static struct clk_regmap a9_dspa;
What is this ?
> +
> +static const struct clk_parent_data a9_glb_parents[] = {
> + { .fw_name = "xtal", },
> + { .hw = &a9_dspa.hw },
> + { .fw_name = "fdiv3", },
> + { .fw_name = "fdiv4", },
> + { .fw_name = "fdiv5", },
> + { .hw = &a9_isp.hw },
> + { .fw_name = "rtc", }
> +};
> +
> +static A9_COMP_SEL(glb, GLB_CLK_CTRL, 9, 0x7, a9_glb_parents,
> + a9_glb_parents_val_table);
> +static A9_COMP_DIV(glb, GLB_CLK_CTRL, 0, 7);
> +static A9_COMP_GATE(glb, GLB_CLK_CTRL, 8, 0);
> +
> +static struct clk_regmap a9_usb_48m_dualdiv_in = {
> + .data = &(struct clk_regmap_gate_data) {
> + .offset = USB_CLK_CTRL,
> + .bit_idx = 31,
> + },
> + .hw.init = CLK_HW_INIT_HW("usb_48m_dualdiv_in", &a9_usb_48m_pre.hw,
> + &clk_regmap_gate_ops, 0),
Same comment as on the AO controller
> +};
> +
> +static const struct meson_clk_dualdiv_param a9_usb_48m_dualdiv_div_table[] = {
> + { 733, 732, 8, 11, 1 },
> + { /* sentinel */ }
> +};
> +
> +static struct clk_regmap a9_usb_48m_dualdiv_div = {
> + .data = &(struct meson_clk_dualdiv_data) {
> + .n1 = {
> + .reg_off = USB_CLK_CTRL0,
> + .shift = 0,
> + .width = 12,
> + },
> + .n2 = {
> + .reg_off = USB_CLK_CTRL0,
> + .shift = 12,
> + .width = 12,
> + },
> + .m1 = {
> + .reg_off = USB_CLK_CTRL1,
> + .shift = 0,
> + .width = 12,
> + },
> + .m2 = {
> + .reg_off = USB_CLK_CTRL1,
> + .shift = 12,
> + .width = 12,
> + },
> + .dual = {
> + .reg_off = USB_CLK_CTRL0,
> + .shift = 28,
> + .width = 1,
> + },
> + .table = a9_usb_48m_dualdiv_div_table,
> + },
> + .hw.init = CLK_HW_INIT_HW("usb_48m_dualdiv_div", &a9_usb_48m_dualdiv_in.hw,
> + &meson_clk_dualdiv_ops, 0),
> +};
> +
> +static struct clk_regmap a9_usb_48m_dualdiv_sel = {
> + .data = &(struct clk_regmap_mux_data) {
> + .offset = USB_CLK_CTRL1,
> + .mask = 0x1,
> + .shift = 24,
> + },
> + .hw.init = CLK_HW_INIT_PARENTS_HW("usb_48m_dualdiv_sel",
> + ((const struct clk_hw *[]) {
> + &a9_usb_48m_dualdiv_in.hw,
> + &a9_usb_48m_dualdiv_div.hw,
> + }), &clk_regmap_mux_ops, CLK_SET_RATE_PARENT),
> +};
> +
> +static struct clk_regmap a9_usb_48m_dualdiv = {
> + .data = &(struct clk_regmap_gate_data) {
> + .offset = USB_CLK_CTRL0,
> + .bit_idx = 30,
> + },
> + .hw.init = CLK_HW_INIT_HW("usb_48m_dualdiv", &a9_usb_48m_dualdiv_sel.hw,
> + &clk_regmap_gate_ops, CLK_SET_RATE_PARENT),
> +};
> +
> +static struct clk_regmap a9_usb_48m = {
> + .data = &(struct clk_regmap_mux_data) {
> + .offset = USB_CLK_CTRL1,
> + .mask = 0x3,
> + .shift = 30,
> + },
> + .hw.init = CLK_HW_INIT_PARENTS_HW("usb_48m",
> + ((const struct clk_hw *[]) {
> + &a9_usb_48m_pre.hw,
> + &a9_usb_48m_dualdiv.hw,
> + }), &clk_regmap_mux_ops, CLK_SET_RATE_PARENT),
> +};
> +
> +/* Channel 3 is unconnected. */
You meant 3rd I guess but this is misleading and confusing with the
table bellow. Channel 2 would be more appropriate I think, since those
are 0-based.
> +static u32 a9_can_pe_parents_val_table[] = { 0, 1, 3 };
> +static const struct clk_parent_data a9_can_pe_parents[] = {
> + { .fw_name = "sys", },
> + { .fw_name = "xtal", },
> + { .fw_name = "fdiv5", }
> +};
> +
> +static A9_COMP_SEL(can_pe, CAN_CLK_CTRL, 9, 0x7, a9_can_pe_parents,
> + a9_can_pe_parents_val_table);
> +static A9_COMP_DIV(can_pe, CAN_CLK_CTRL, 0, 7);
> +static A9_COMP_GATE(can_pe, CAN_CLK_CTRL, 8, 0);
> +
> +static A9_COMP_SEL(can1_pe, CAN_CLK_CTRL, 25, 0x7, a9_can_pe_parents,
> + a9_can_pe_parents_val_table);
> +static A9_COMP_DIV(can1_pe, CAN_CLK_CTRL, 16, 7);
> +static A9_COMP_GATE(can1_pe, CAN_CLK_CTRL, 24, 0);
> +
> +static const struct clk_parent_data a9_can_filter_parents[] = {
> + { .fw_name = "sys", },
> + { .fw_name = "xtal", },
> + { .fw_name = "fdiv4", },
> + { .fw_name = "fdiv5", }
> +};
> +
> +static A9_COMP_SEL(can_filter, CAN_CLK_CTRL1, 9, 0x7, a9_can_filter_parents,
> + NULL);
> +static A9_COMP_DIV(can_filter, CAN_CLK_CTRL1, 0, 7);
> +static A9_COMP_GATE(can_filter, CAN_CLK_CTRL1, 8, 0);
> +
> +static A9_COMP_SEL(can1_filter, CAN_CLK_CTRL1, 25, 0x7, a9_can_filter_parents,
> + NULL);
> +static A9_COMP_DIV(can1_filter, CAN_CLK_CTRL1, 16, 7);
> +static A9_COMP_GATE(can1_filter, CAN_CLK_CTRL1, 24, 0);
> +
> +static const struct clk_parent_data a9_i3c_parents[] = {
> + { .fw_name = "sys", },
> + { .fw_name = "xtal", },
> + { .fw_name = "fdiv5", }
> +};
> +
> +static A9_COMP_SEL(i3c, I3C_CLK_CTRL, 9, 0x7, a9_i3c_parents, NULL);
> +static A9_COMP_DIV(i3c, I3C_CLK_CTRL, 0, 8);
> +static A9_COMP_GATE(i3c, I3C_CLK_CTRL, 8, 0);
> +
> +static struct clk_regmap a9_ts_div = {
> + .data = &(struct clk_regmap_div_data) {
> + .offset = TS_CLK_CTRL,
> + .shift = 0,
> + .width = 8,
> + },
> + .hw.init = CLK_HW_INIT_FW_NAME("ts_div", "xtal",
> + &clk_regmap_divider_ops, 0),
> +};
> +
> +static struct clk_regmap a9_ts = {
> + .data = &(struct clk_regmap_gate_data) {
> + .offset = TS_CLK_CTRL,
> + .bit_idx = 8,
> + },
> + .hw.init = CLK_HW_INIT_HW("ts", &a9_ts_div.hw,
> + &clk_regmap_gate_ops, CLK_SET_RATE_PARENT),
> +};
> +
> +static struct clk_fixed_factor a9_eth_125m_div = {
> + .mult = 1,
> + .div = 8,
> + .hw.init = CLK_HW_INIT_FW_NAME("eth_125m_div", "fdiv2",
> + &clk_fixed_factor_ops, 0),
> +};
> +
> +static struct clk_regmap a9_eth_125m = {
> + .data = &(struct clk_regmap_gate_data) {
> + .offset = ETH_CLK_CTRL,
> + .bit_idx = 7,
> + },
> + .hw.init = CLK_HW_INIT_HW("eth_125m", &a9_eth_125m_div.hw,
> + &clk_regmap_gate_ops, CLK_SET_RATE_PARENT),
> +};
> +
> +/*
> + * Channel 1, 2, 3, 4, 5 and 6 are unconnected,
> + * ext_rmii connects external PAD. Do not automatically reparent.
> + */
> +static u32 a9_eth_rmii_parents_val_table[] = { 0, 7 };
> +static const struct clk_parent_data a9_eth_rmii_parents[] = {
> + { .fw_name = "fdiv2", },
> + { .fw_name = "ext_rmii", }
> +};
> +
> +static struct clk_regmap a9_eth_rmii_sel = {
> + .data = &(struct clk_regmap_mux_data) {
> + .offset = ETH_CLK_CTRL,
> + .mask = 0x7,
> + .shift = 9,
> + .table = a9_eth_rmii_parents_val_table,
> + },
> + .hw.init = CLK_HW_INIT_PARENTS_DATA("eth_rmii_sel",
> + a9_eth_rmii_parents,
> + &clk_regmap_mux_ops, CLK_SET_RATE_NO_REPARENT),
> +};
> +
> +static struct clk_regmap a9_eth_rmii_div = {
> + .data = &(struct clk_regmap_div_data) {
> + .offset = ETH_CLK_CTRL,
> + .shift = 0,
> + .width = 7,
> + },
> + .hw.init = CLK_HW_INIT_HW("eth_rmii_div", &a9_eth_rmii_sel.hw,
> + &clk_regmap_divider_ops, CLK_SET_RATE_PARENT),
> +};
> +
> +static struct clk_regmap a9_eth_rmii = {
> + .data = &(struct clk_regmap_gate_data) {
> + .offset = ETH_CLK_CTRL,
> + .bit_idx = 8,
> + },
> + .hw.init = CLK_HW_INIT_HW("eth_rmii", &a9_eth_rmii_div.hw,
> + &clk_regmap_gate_ops, CLK_SET_RATE_PARENT),
> +};
> +
> +/*
> + * Channel 3(ddr_dpll_pt_clk) is manged by the DDR module;
> + * channel 12(msr_clk) is manged by clock measures module.
> + * channel 16(audio_dac1_clk) is manged by audio module.
Some why can't you expose those then ? gen clk is used for debugging
AFAIK. The clock above are worth debugging I think
Please be consistent with the CaSing.
> + * Channel 10, 11, 13, 14 are not connected.
> + */
> +static u32 a9_gen_parents_val_table[] = { 0, 1, 2, 4, 5, 6, 7, 8, 9, 15, 17, 18,
> + 19, 20, 21, 22, 23, 24, 25, 26};
> +static struct clk_regmap a9_vid_pll;
> +
> +static const struct clk_parent_data a9_gen_parents[] = {
> + { .fw_name = "xtal" },
> + { .fw_name = "rtc" },
> + { .fw_name = "sysplldiv16" },
> + { .hw = &a9_vid_pll.hw },
> + { .fw_name = "gp0" },
> + { .fw_name = "hifi1" },
> + { .fw_name = "hifi0" },
> + { .fw_name = "gp1" },
> + { .fw_name = "gp2" },
> + { .fw_name = "dsudiv16" },
> + { .fw_name = "cpudiv16" },
> + { .fw_name = "a78div16" },
> + { .fw_name = "fdiv2" },
> + { .fw_name = "fdiv2p5" },
> + { .fw_name = "fdiv3" },
> + { .fw_name = "fdiv4" },
> + { .fw_name = "fdiv5" },
> + { .fw_name = "fdiv7" },
> + { .fw_name = "mclk0" },
> + { .fw_name = "mclk1" }
> +};
> +
> +static A9_COMP_SEL(gen, GEN_CLK_CTRL, 12, 0x1f, a9_gen_parents,
> + a9_gen_parents_val_table);
> +static A9_COMP_DIV(gen, GEN_CLK_CTRL, 0, 11);
> +static A9_COMP_GATE(gen, GEN_CLK_CTRL, 11, 0);
> +
> +static struct clk_regmap a9_24m_in = {
> + .data = &(struct clk_regmap_gate_data) {
> + .offset = CLK12_24_CTRL,
> + .bit_idx = 11,
> + },
> + .hw.init = CLK_HW_INIT_FW_NAME("24m_in", "xtal",
> + &clk_regmap_gate_ops, 0),
> +};
> +
> +static struct clk_regmap a9_12_24m = {
> + .data = &(struct clk_regmap_div_data) {
> + .offset = CLK12_24_CTRL,
> + .shift = 10,
> + .width = 1,
> + },
> + .hw.init = CLK_HW_INIT_HW("12_24m", &a9_24m_in.hw,
> + &clk_regmap_divider_ops, 0),
> +};
> +
> +static const struct clk_parent_data a9_mali_parents[] = {
> + { .fw_name = "xtal", },
> + { .fw_name = "gp1", },
> + { .fw_name = "fdiv2", },
> + { .fw_name = "fdiv2p5", },
> + { .fw_name = "fdiv3", },
> + { .fw_name = "fdiv4", },
> + { .fw_name = "fdiv5", },
> + { .fw_name = "fdiv7", }
> +};
> +
> +static A9_COMP_SEL(mali_0, MALI_CLK_CTRL, 9, 0x7, a9_mali_parents, NULL);
> +static A9_COMP_DIV(mali_0, MALI_CLK_CTRL, 0, 7);
> +static A9_COMP_GATE(mali_0, MALI_CLK_CTRL, 8, CLK_SET_RATE_GATE);
> +
> +static A9_COMP_SEL(mali_1, MALI_CLK_CTRL, 25, 0x7, a9_mali_parents, NULL);
> +static A9_COMP_DIV(mali_1, MALI_CLK_CTRL, 16, 7);
> +static A9_COMP_GATE(mali_1, MALI_CLK_CTRL, 24, CLK_SET_RATE_GATE);
> +
> +static struct clk_regmap a9_mali = {
> + .data = &(struct clk_regmap_mux_data){
> + .offset = MALI_CLK_CTRL,
> + .mask = 0x1,
> + .shift = 31,
> + },
> + .hw.init = CLK_HW_INIT_PARENTS_HW("mali",
> + ((const struct clk_hw *[]) {
> + &a9_mali_0.hw,
> + &a9_mali_1.hw,
> + }), &clk_regmap_mux_ops, CLK_SET_RATE_PARENT),
> +};
> +
> +static A9_COMP_SEL(mali_stack_0, MALI_STACK_CLK_CTRL, 9, 0x7, a9_mali_parents,
> + NULL);
> +static A9_COMP_DIV(mali_stack_0, MALI_STACK_CLK_CTRL, 0, 7);
> +static A9_COMP_GATE(mali_stack_0, MALI_STACK_CLK_CTRL, 8, CLK_SET_RATE_GATE);
> +
> +static A9_COMP_SEL(mali_stack_1, MALI_STACK_CLK_CTRL, 25, 0x7, a9_mali_parents,
> + NULL);
> +static A9_COMP_DIV(mali_stack_1, MALI_STACK_CLK_CTRL, 16, 7);
> +static A9_COMP_GATE(mali_stack_1, MALI_STACK_CLK_CTRL, 24, CLK_SET_RATE_GATE);
> +
> +static struct clk_regmap a9_mali_stack = {
> + .data = &(struct clk_regmap_mux_data){
> + .offset = MALI_STACK_CLK_CTRL,
> + .mask = 0x1,
> + .shift = 31,
> + },
> + .hw.init = CLK_HW_INIT_PARENTS_HW("mali_stack",
> + ((const struct clk_hw *[]) {
> + &a9_mali_stack_0.hw,
> + &a9_mali_stack_1.hw,
> + }), &clk_regmap_mux_ops, CLK_SET_RATE_PARENT),
> +};
> +
> +static const struct clk_parent_data a9_dspa_parents[] = {
> + { .fw_name = "xtal", },
> + { .fw_name = "fdiv2p5", },
> + { .fw_name = "fdiv3", },
> + { .fw_name = "fdiv5", },
> + { .fw_name = "gp2", },
> + { .fw_name = "fdiv4", },
> + { .fw_name = "hifi0", },
> + { .fw_name = "rtc", }
> +};
> +
> +static A9_COMP_SEL(dspa_0, DSPA_CLK_CTRL, 9, 0x7, a9_dspa_parents, NULL);
> +static A9_COMP_DIV(dspa_0, DSPA_CLK_CTRL, 0, 7);
> +static A9_COMP_GATE(dspa_0, DSPA_CLK_CTRL, 8, CLK_SET_RATE_GATE);
> +
> +static A9_COMP_SEL(dspa_1, DSPA_CLK_CTRL, 25, 0x7, a9_dspa_parents, NULL);
> +static A9_COMP_DIV(dspa_1, DSPA_CLK_CTRL, 16, 7);
> +static A9_COMP_GATE(dspa_1, DSPA_CLK_CTRL, 24, CLK_SET_RATE_GATE);
> +
> +static struct clk_regmap a9_dspa = {
> + .data = &(struct clk_regmap_mux_data){
> + .offset = DSPA_CLK_CTRL,
> + .mask = 0x1,
> + .shift = 31,
> + },
> + .hw.init = CLK_HW_INIT_PARENTS_HW("dspa",
> + ((const struct clk_hw *[]) {
> + &a9_dspa_0.hw,
> + &a9_dspa_1.hw,
> + }), &clk_regmap_mux_ops, CLK_SET_RATE_PARENT),
> +};
> +
> +static const struct clk_parent_data a9_hevcf_parents[] = {
> + { .fw_name = "fdiv2p5", },
> + { .fw_name = "fdiv3", },
> + { .fw_name = "fdiv4", },
> + { .fw_name = "fdiv5", },
> + { .fw_name = "fdiv7", },
> + { .fw_name = "hifi0", },
> + { .fw_name = "gp1", },
> + { .fw_name = "xtal", }
> +};
> +
> +static A9_COMP_SEL(hevcf_0, HEVCF_CLK_CTRL, 9, 0x7, a9_hevcf_parents, NULL);
> +static A9_COMP_DIV(hevcf_0, HEVCF_CLK_CTRL, 0, 7);
> +static A9_COMP_GATE(hevcf_0, HEVCF_CLK_CTRL, 8, CLK_SET_RATE_GATE);
> +
> +static A9_COMP_SEL(hevcf_1, HEVCF_CLK_CTRL, 25, 0x7, a9_hevcf_parents, NULL);
> +static A9_COMP_DIV(hevcf_1, HEVCF_CLK_CTRL, 16, 7);
> +static A9_COMP_GATE(hevcf_1, HEVCF_CLK_CTRL, 24, CLK_SET_RATE_GATE);
> +
> +static struct clk_regmap a9_hevcf = {
> + .data = &(struct clk_regmap_mux_data){
> + .offset = HEVCF_CLK_CTRL,
> + .mask = 0x1,
> + .shift = 31,
> + },
> + .hw.init = CLK_HW_INIT_PARENTS_HW("hevcf",
> + ((const struct clk_hw *[]) {
> + &a9_hevcf_0.hw,
> + &a9_hevcf_1.hw,
> + }), &clk_regmap_mux_ops, CLK_SET_RATE_PARENT),
> +};
> +
> +static const struct clk_parent_data a9_hcodec_parents[] = {
> + { .fw_name = "fdiv2p5", },
> + { .fw_name = "fdiv3", },
> + { .fw_name = "fdiv4", },
> + { .fw_name = "fdiv5", },
> + { .fw_name = "fdiv7", },
> + { .fw_name = "hifi0", },
> + { .fw_name = "gp0", },
> + { .fw_name = "xtal", }
> +};
> +
> +static A9_COMP_SEL(hcodec_0, HCODEC_CLK_CTRL, 9, 0x7, a9_hcodec_parents, NULL);
> +static A9_COMP_DIV(hcodec_0, HCODEC_CLK_CTRL, 0, 7);
> +static A9_COMP_GATE(hcodec_0, HCODEC_CLK_CTRL, 8, CLK_SET_RATE_GATE);
> +
> +static A9_COMP_SEL(hcodec_1, HCODEC_CLK_CTRL, 25, 0x7, a9_hcodec_parents, NULL);
> +static A9_COMP_DIV(hcodec_1, HCODEC_CLK_CTRL, 16, 7);
> +static A9_COMP_GATE(hcodec_1, HCODEC_CLK_CTRL, 24, CLK_SET_RATE_GATE);
> +
> +static struct clk_regmap a9_hcodec = {
> + .data = &(struct clk_regmap_mux_data){
> + .offset = HCODEC_CLK_CTRL,
> + .mask = 0x1,
> + .shift = 31,
> + },
> + .hw.init = CLK_HW_INIT_PARENTS_HW("hcodec",
> + ((const struct clk_hw *[]) {
> + &a9_hcodec_0.hw,
> + &a9_hcodec_1.hw,
> + }), &clk_regmap_mux_ops, CLK_SET_RATE_PARENT),
> +};
> +
> +static const struct clk_parent_data a9_vpu_parents[] = {
> + { .fw_name = "fdiv3", },
> + { .fw_name = "fdiv4", },
> + { .fw_name = "fdiv5", },
> + { .fw_name = "vid1", },
> + { .fw_name = "fdiv2", },
> + { .hw = &a9_vid_pll.hw },
> + { .fw_name = "vid2", },
> + { .fw_name = "gp1", }
> +};
> +
> +static A9_COMP_SEL(vpu_0, VPU_CLK_CTRL, 9, 0x7, a9_vpu_parents, NULL);
> +static A9_COMP_DIV(vpu_0, VPU_CLK_CTRL, 0, 7);
> +static A9_COMP_GATE(vpu_0, VPU_CLK_CTRL, 8, CLK_SET_RATE_GATE);
> +
> +static A9_COMP_SEL(vpu_1, VPU_CLK_CTRL, 25, 0x7, a9_vpu_parents, NULL);
> +static A9_COMP_DIV(vpu_1, VPU_CLK_CTRL, 16, 7);
> +static A9_COMP_GATE(vpu_1, VPU_CLK_CTRL, 24, CLK_SET_RATE_GATE);
> +
> +static struct clk_regmap a9_vpu = {
> + .data = &(struct clk_regmap_mux_data){
> + .offset = VPU_CLK_CTRL,
> + .mask = 0x1,
> + .shift = 31,
> + },
> + .hw.init = CLK_HW_INIT_PARENTS_HW("vpu",
> + ((const struct clk_hw *[]) {
> + &a9_vpu_0.hw,
> + &a9_vpu_1.hw,
> + }), &clk_regmap_mux_ops, CLK_SET_RATE_PARENT),
> +};
> +
> +static const struct clk_parent_data a9_vapb_parents[] = {
> + { .fw_name = "fdiv4", },
> + { .fw_name = "fdiv3", },
> + { .fw_name = "fdiv5", },
> + { .fw_name = "fdiv7", },
> + { .fw_name = "fdiv2", },
> + { .hw = &a9_vid_pll.hw },
> + { .fw_name = "hifi0", },
> + { .fw_name = "fdiv2p5", }
> +};
> +
> +static A9_COMP_SEL(vapb_0, VAPB_CLK_CTRL, 9, 0x7, a9_vapb_parents, NULL);
> +static A9_COMP_DIV(vapb_0, VAPB_CLK_CTRL, 0, 7);
> +static A9_COMP_GATE(vapb_0, VAPB_CLK_CTRL, 8, CLK_SET_RATE_GATE);
> +
> +static A9_COMP_SEL(vapb_1, VAPB_CLK_CTRL, 25, 0x7, a9_vapb_parents, NULL);
> +static A9_COMP_DIV(vapb_1, VAPB_CLK_CTRL, 16, 7);
> +static A9_COMP_GATE(vapb_1, VAPB_CLK_CTRL, 24, CLK_SET_RATE_GATE);
> +
> +static struct clk_regmap a9_vapb = {
> + .data = &(struct clk_regmap_mux_data){
> + .offset = VAPB_CLK_CTRL,
> + .mask = 0x1,
> + .shift = 31,
> + },
> + .hw.init = CLK_HW_INIT_PARENTS_HW("vapb",
> + ((const struct clk_hw *[]) {
> + &a9_vapb_0.hw,
> + &a9_vapb_1.hw,
> + }), &clk_regmap_mux_ops, CLK_SET_RATE_PARENT),
> +};
> +
> +static struct clk_regmap a9_ge2d = {
> + .data = &(struct clk_regmap_gate_data) {
> + .offset = VAPB_CLK_CTRL,
> + .bit_idx = 30,
> + },
> + .hw.init = CLK_HW_INIT_HW("ge2d", &a9_vapb.hw,
> + &clk_regmap_gate_ops, 0),
> +};
> +
> +static const struct clk_parent_data a9_vpu_clkb_tmp_parents[] = {
> + { .hw = &a9_vpu.hw },
> + { .fw_name = "fdiv4", },
> + { .fw_name = "fdiv5", },
> + { .fw_name = "fdiv7", }
> +};
> +
> +static A9_COMP_SEL(vpu_clkb_tmp, VPU_CLKB_CTRL, 25, 0x7, a9_vpu_clkb_tmp_parents,
> + NULL);
> +static A9_COMP_DIV(vpu_clkb_tmp, VPU_CLKB_CTRL, 16, 4);
> +static A9_COMP_GATE(vpu_clkb_tmp, VPU_CLKB_CTRL, 24, 0);
> +
> +static struct clk_regmap a9_vpu_clkb_div = {
> + .data = &(struct clk_regmap_div_data) {
> + .offset = VPU_CLKB_CTRL,
> + .shift = 0,
> + .width = 8,
> + },
> + .hw.init = CLK_HW_INIT_HW("vpu_clkb_div", &a9_vpu_clkb_tmp.hw,
> + &clk_regmap_divider_ops, 0),
> +};
> +
> +static struct clk_regmap a9_vpu_clkb = {
> + .data = &(struct clk_regmap_gate_data) {
> + .offset = VPU_CLKB_CTRL,
> + .bit_idx = 8,
> + },
> + .hw.init = CLK_HW_INIT_HW("vpu_clkb", &a9_vpu_clkb_div.hw,
> + &clk_regmap_gate_ops, CLK_SET_RATE_PARENT),
> +};
> +
> +static const struct clk_parent_data a9_hdmi_parents[] = {
> + { .fw_name = "xtal", },
> + { .fw_name = "fdiv4", },
> + { .fw_name = "fdiv3", },
> + { .fw_name = "fdiv5", }
> +};
> +
> +static A9_COMP_SEL(hdmitx_sys, HDMI_CLK_CTRL, 9, 0x7, a9_hdmi_parents, NULL);
> +static A9_COMP_DIV(hdmitx_sys, HDMI_CLK_CTRL, 0, 7);
> +static A9_COMP_GATE(hdmitx_sys, HDMI_CLK_CTRL, 8, 0);
> +
> +static A9_COMP_SEL(hdmitx_prif, HTX_CLK_CTRL, 9, 0x7, a9_hdmi_parents, NULL);
> +static A9_COMP_DIV(hdmitx_prif, HTX_CLK_CTRL, 0, 7);
> +static A9_COMP_GATE(hdmitx_prif, HTX_CLK_CTRL, 8, 0);
> +
> +static A9_COMP_SEL(hdmitx_200m, HTX_CLK_CTRL, 25, 0x7, a9_hdmi_parents, NULL);
> +static A9_COMP_DIV(hdmitx_200m, HTX_CLK_CTRL, 16, 7);
> +static A9_COMP_GATE(hdmitx_200m, HTX_CLK_CTRL, 24, 0);
> +
> +static A9_COMP_SEL(hdmitx_aud, HTX_CLK_CTRL1, 9, 0x7, a9_hdmi_parents, NULL);
> +static A9_COMP_DIV(hdmitx_aud, HTX_CLK_CTRL1, 0, 7);
> +static A9_COMP_GATE(hdmitx_aud, HTX_CLK_CTRL1, 8, 0);
> +
> +static A9_COMP_SEL(hdmirx_5m, HRX_CLK_CTRL, 9, 0x7, a9_hdmi_parents,
> + NULL);
> +static A9_COMP_DIV(hdmirx_5m, HRX_CLK_CTRL, 0, 7);
> +static A9_COMP_GATE(hdmirx_5m, HRX_CLK_CTRL, 8, 0);
> +
> +static A9_COMP_SEL(hdmirx_2m, HRX_CLK_CTRL, 25, 0x7, a9_hdmi_parents,
> + NULL);
> +static A9_COMP_DIV(hdmirx_2m, HRX_CLK_CTRL, 16, 7);
> +static A9_COMP_GATE(hdmirx_2m, HRX_CLK_CTRL, 24, 0);
> +
> +static A9_COMP_SEL(hdmirx_cfg, HRX_CLK_CTRL1, 9, 0x7, a9_hdmi_parents,
> + NULL);
> +static A9_COMP_DIV(hdmirx_cfg, HRX_CLK_CTRL1, 0, 7);
> +static A9_COMP_GATE(hdmirx_cfg, HRX_CLK_CTRL1, 8, 0);
> +
> +static A9_COMP_SEL(hdmirx_hdcp2x, HRX_CLK_CTRL1, 25, 0x7, a9_hdmi_parents,
> + NULL);
> +static A9_COMP_DIV(hdmirx_hdcp2x, HRX_CLK_CTRL1, 16, 7);
> +static A9_COMP_GATE(hdmirx_hdcp2x, HRX_CLK_CTRL1, 24, 0);
> +
> +static A9_COMP_SEL(hdmirx_acr_ref, HRX_CLK_CTRL2, 25, 0x7, a9_hdmi_parents,
> + NULL);
> +static A9_COMP_DIV(hdmirx_acr_ref, HRX_CLK_CTRL2, 16, 7);
> +static A9_COMP_GATE(hdmirx_acr_ref, HRX_CLK_CTRL2, 24, 0);
> +
> +static A9_COMP_SEL(hdmirx_meter, HRX_CLK_CTRL3, 9, 0x7, a9_hdmi_parents,
> + NULL);
> +static A9_COMP_DIV(hdmirx_meter, HRX_CLK_CTRL3, 0, 7);
> +static A9_COMP_GATE(hdmirx_meter, HRX_CLK_CTRL3, 8, 0);
> +
> +static struct clk_regmap a9_enc, a9_enc1;
What is this again ?? and please come up with better names.
> +
> +static const struct clk_parent_data a9_vid_lock_parents[] = {
> + { .fw_name = "xtal", },
> + { .hw = &a9_enc.hw },
> + { .hw = &a9_enc1.hw }
> +};
> +
> +static A9_COMP_SEL(vid_lock, VID_LOCK_CLK_CTRL, 9, 0x7, a9_vid_lock_parents,
> + NULL);
> +static A9_COMP_DIV(vid_lock, VID_LOCK_CLK_CTRL, 0, 7);
> +static A9_COMP_GATE(vid_lock, VID_LOCK_CLK_CTRL, 8, 0);
> +
> +static const struct clk_parent_data a9_vdin_meas_parents[] = {
> + { .fw_name = "xtal", },
> + { .fw_name = "fdiv4", },
> + { .fw_name = "fdiv3", },
> + { .fw_name = "fdiv5", }
> +};
> +
> +static A9_COMP_SEL(vdin_meas, VDIN_MEAS_CLK_CTRL, 9, 0x7, a9_vdin_meas_parents,
> + NULL);
> +static A9_COMP_DIV(vdin_meas, VDIN_MEAS_CLK_CTRL, 0, 7);
> +static A9_COMP_GATE(vdin_meas, VDIN_MEAS_CLK_CTRL, 8, 0);
> +
> +static struct clk_regmap a9_vid_pll_div = {
> + .data = &(struct meson_vid_pll_div_data){
> + .val = {
> + .reg_off = VID_PLL_CLK_DIV,
> + .shift = 0,
> + .width = 15,
> + },
> + .sel = {
> + .reg_off = VID_PLL_CLK_DIV,
> + .shift = 16,
> + .width = 2,
> + },
> + },
> + .hw.init = CLK_HW_INIT_FW_NAME("vid_pll_div", "hdmiout2",
> + &meson_vid_pll_div_ro_ops, 0),
> +};
> +
> +static struct clk_regmap a9_vid_pll_sel = {
> + .data = &(struct clk_regmap_mux_data){
> + .offset = VID_PLL_CLK_DIV,
> + .mask = 0x1,
> + .shift = 18,
> + },
> + .hw.init = CLK_HW_INIT_PARENTS_DATA("vid_pll_sel",
> + ((const struct clk_parent_data []) {
> + { .hw = &a9_vid_pll_div.hw },
> + { .fw_name = "hdmiout2" }
> + }), &clk_regmap_mux_ops, CLK_SET_RATE_PARENT),
> +};
> +
> +static struct clk_regmap a9_vid_pll = {
> + .data = &(struct clk_regmap_gate_data){
> + .offset = VID_PLL_CLK_DIV,
> + .bit_idx = 19,
> + },
> + .hw.init = CLK_HW_INIT_HW("vid_pll", &a9_vid_pll_sel.hw,
> + &clk_regmap_gate_ops, CLK_SET_RATE_PARENT),
> +};
> +
> +static struct clk_regmap a9_vid_pll_vclk = {
> + .data = &(struct clk_regmap_mux_data){
> + .offset = HDMI_CLK_CTRL,
> + .mask = 0x1,
> + .shift = 15,
> + },
> + .hw.init = CLK_HW_INIT_PARENTS_DATA("vid_pll_vclk",
> + ((const struct clk_parent_data []) {
> + { .hw = &a9_vid_pll.hw },
> + { .fw_name = "hdmipix" }
> + }), &clk_regmap_mux_ops, 0),
> +};
> +
> +static const struct clk_parent_data a9_vclk_parents[] = {
> + { .hw = &a9_vid_pll_vclk.hw },
> + { .fw_name = "pix0", },
> + { .fw_name = "vid1", },
> + { .fw_name = "pix1", },
> + { .fw_name = "fdiv3", },
> + { .fw_name = "fdiv4", },
> + { .fw_name = "fdiv5", },
> + { .fw_name = "vid2", }
> +};
> +
> +static struct clk_regmap a9_vclk_sel = {
> + .data = &(struct clk_regmap_mux_data){
> + .offset = VID_CLK_CTRL,
> + .mask = 0x7,
> + .shift = 16,
> + },
> + .hw.init = CLK_HW_INIT_PARENTS_DATA("vclk_sel", a9_vclk_parents,
> + &clk_regmap_mux_ops, 0),
> +};
> +
> +static struct clk_regmap a9_vclk_in = {
> + .data = &(struct clk_regmap_gate_data){
> + .offset = VID_CLK_DIV,
> + .bit_idx = 16,
> + },
> + .hw.init = CLK_HW_INIT_HW("vclk_in", &a9_vclk_sel.hw,
> + &clk_regmap_gate_ops, CLK_SET_RATE_PARENT),
> +};
> +
> +static struct clk_regmap a9_vclk_div = {
> + .data = &(struct clk_regmap_div_data){
> + .offset = VID_CLK_DIV,
> + .shift = 0,
> + .width = 8,
> + },
> + .hw.init = CLK_HW_INIT_HW("vclk_div", &a9_vclk_in.hw,
> + &clk_regmap_divider_ops, CLK_SET_RATE_PARENT),
> +};
> +
> +static struct clk_regmap a9_vclk = {
> + .data = &(struct clk_regmap_gate_data){
> + .offset = VID_CLK_CTRL,
> + .bit_idx = 19,
> + },
> + .hw.init = CLK_HW_INIT_HW("vclk", &a9_vclk_div.hw,
> + &clk_regmap_gate_ops, CLK_SET_RATE_PARENT),
> +};
> +
> +static struct clk_regmap a9_vclk_div1_en = {
> + .data = &(struct clk_regmap_gate_data){
> + .offset = VID_CLK_CTRL,
> + .bit_idx = 0,
> + },
> + .hw.init = CLK_HW_INIT_HW("vclk_div1_en", &a9_vclk.hw,
> + &clk_regmap_gate_ops, CLK_SET_RATE_PARENT),
> +};
> +
> +static struct clk_regmap a9_vclk_div2_en = {
> + .data = &(struct clk_regmap_gate_data){
> + .offset = VID_CLK_CTRL,
> + .bit_idx = 1,
> + },
> + .hw.init = CLK_HW_INIT_HW("vclk_div2_en", &a9_vclk.hw,
> + &clk_regmap_gate_ops, CLK_SET_RATE_PARENT),
> +};
Looks to me all this div_en / div repeating pattern would be easier to review
with tiny macro .
> +
> +static struct clk_fixed_factor a9_vclk_div2 = {
> + .mult = 1,
> + .div = 2,
> + .hw.init = CLK_HW_INIT_HW("vclk_div2", &a9_vclk_div2_en.hw,
> + &clk_fixed_factor_ops, CLK_SET_RATE_PARENT),
> +};
> +
> +static struct clk_regmap a9_vclk_div4_en = {
> + .data = &(struct clk_regmap_gate_data){
> + .offset = VID_CLK_CTRL,
> + .bit_idx = 2,
> + },
> + .hw.init = CLK_HW_INIT_HW("vclk_div4_en", &a9_vclk.hw,
> + &clk_regmap_gate_ops, CLK_SET_RATE_PARENT),
> +};
> +
> +static struct clk_fixed_factor a9_vclk_div4 = {
> + .mult = 1,
> + .div = 4,
> + .hw.init = CLK_HW_INIT_HW("vclk_div4", &a9_vclk_div4_en.hw,
> + &clk_fixed_factor_ops, CLK_SET_RATE_PARENT),
> +};
> +
> +static struct clk_regmap a9_vclk_div6_en = {
> + .data = &(struct clk_regmap_gate_data){
> + .offset = VID_CLK_CTRL,
> + .bit_idx = 3,
> + },
> + .hw.init = CLK_HW_INIT_HW("vclk_div6_en", &a9_vclk.hw,
> + &clk_regmap_gate_ops, CLK_SET_RATE_PARENT),
> +};
> +
> +static struct clk_fixed_factor a9_vclk_div6 = {
> + .mult = 1,
> + .div = 6,
> + .hw.init = CLK_HW_INIT_HW("vclk_div6", &a9_vclk_div6_en.hw,
> + &clk_fixed_factor_ops, CLK_SET_RATE_PARENT),
> +};
> +
> +static struct clk_regmap a9_vclk_div12_en = {
> + .data = &(struct clk_regmap_gate_data){
> + .offset = VID_CLK_CTRL,
> + .bit_idx = 4,
> + },
> + .hw.init = CLK_HW_INIT_HW("vclk_div12_en", &a9_vclk.hw,
> + &clk_regmap_gate_ops, CLK_SET_RATE_PARENT),
> +};
> +
> +static struct clk_fixed_factor a9_vclk_div12 = {
> + .mult = 1,
> + .div = 12,
> + .hw.init = CLK_HW_INIT_HW("vclk_div12", &a9_vclk_div12_en.hw,
> + &clk_fixed_factor_ops, CLK_SET_RATE_PARENT),
> +};
> +
> +static struct clk_regmap a9_vclk2_sel = {
> + .data = &(struct clk_regmap_mux_data){
> + .offset = VIID_CLK_CTRL,
> + .mask = 0x7,
> + .shift = 16,
> + },
> + .hw.init = CLK_HW_INIT_PARENTS_DATA("vclk2_sel", a9_vclk_parents,
> + &clk_regmap_mux_ops, 0),
> +};
> +
> +static struct clk_regmap a9_vclk2_in = {
> + .data = &(struct clk_regmap_gate_data){
> + .offset = VIID_CLK_DIV,
> + .bit_idx = 16,
> + },
> + .hw.init = CLK_HW_INIT_HW("vclk2_in", &a9_vclk2_sel.hw,
> + &clk_regmap_gate_ops, CLK_SET_RATE_PARENT),
> +};
> +
> +static struct clk_regmap a9_vclk2_div = {
> + .data = &(struct clk_regmap_div_data){
> + .offset = VIID_CLK_DIV,
> + .shift = 0,
> + .width = 8,
> + },
> + .hw.init = CLK_HW_INIT_HW("vclk2_div", &a9_vclk2_in.hw,
> + &clk_regmap_divider_ops, CLK_SET_RATE_PARENT),
> +};
> +
> +static struct clk_regmap a9_vclk2 = {
> + .data = &(struct clk_regmap_gate_data){
> + .offset = VIID_CLK_CTRL,
> + .bit_idx = 19,
> + },
> + .hw.init = CLK_HW_INIT_HW("vclk2", &a9_vclk2_div.hw,
> + &clk_regmap_gate_ops, CLK_SET_RATE_PARENT),
> +};
> +
> +static struct clk_regmap a9_vclk2_div1_en = {
> + .data = &(struct clk_regmap_gate_data){
> + .offset = VIID_CLK_CTRL,
> + .bit_idx = 0,
> + },
> + .hw.init = CLK_HW_INIT_HW("vclk2_div1_en", &a9_vclk2.hw,
> + &clk_regmap_gate_ops, CLK_SET_RATE_PARENT),
> +};
> +
> +static struct clk_regmap a9_vclk2_div2_en = {
> + .data = &(struct clk_regmap_gate_data){
> + .offset = VIID_CLK_CTRL,
> + .bit_idx = 1,
> + },
> + .hw.init = CLK_HW_INIT_HW("vclk2_div2_en", &a9_vclk2.hw,
> + &clk_regmap_gate_ops, CLK_SET_RATE_PARENT),
> +};
> +
> +static struct clk_fixed_factor a9_vclk2_div2 = {
> + .mult = 1,
> + .div = 2,
> + .hw.init = CLK_HW_INIT_HW("vclk2_div2", &a9_vclk2_div2_en.hw,
> + &clk_fixed_factor_ops, CLK_SET_RATE_PARENT),
> +};
> +
> +static struct clk_regmap a9_vclk2_div4_en = {
> + .data = &(struct clk_regmap_gate_data){
> + .offset = VIID_CLK_CTRL,
> + .bit_idx = 2,
> + },
> + .hw.init = CLK_HW_INIT_HW("vclk2_div4_en", &a9_vclk2.hw,
> + &clk_regmap_gate_ops, CLK_SET_RATE_PARENT),
> +};
> +
> +static struct clk_fixed_factor a9_vclk2_div4 = {
> + .mult = 1,
> + .div = 4,
> + .hw.init = CLK_HW_INIT_HW("vclk2_div4", &a9_vclk2_div4_en.hw,
> + &clk_fixed_factor_ops, CLK_SET_RATE_PARENT),
> +};
> +
> +static struct clk_regmap a9_vclk2_div6_en = {
> + .data = &(struct clk_regmap_gate_data){
> + .offset = VIID_CLK_CTRL,
> + .bit_idx = 3,
> + },
> + .hw.init = CLK_HW_INIT_HW("vclk2_div6_en", &a9_vclk2.hw,
> + &clk_regmap_gate_ops, CLK_SET_RATE_PARENT),
> +};
> +
> +static struct clk_fixed_factor a9_vclk2_div6 = {
> + .mult = 1,
> + .div = 6,
> + .hw.init = CLK_HW_INIT_HW("vclk2_div6", &a9_vclk2_div6_en.hw,
> + &clk_fixed_factor_ops, CLK_SET_RATE_PARENT),
> +};
> +
> +static struct clk_regmap a9_vclk2_div12_en = {
> + .data = &(struct clk_regmap_gate_data){
> + .offset = VIID_CLK_CTRL,
> + .bit_idx = 4,
> + },
> + .hw.init = CLK_HW_INIT_HW("vclk2_div12_en", &a9_vclk2.hw,
> + &clk_regmap_gate_ops, CLK_SET_RATE_PARENT),
> +};
> +
> +static struct clk_fixed_factor a9_vclk2_div12 = {
> + .mult = 1,
> + .div = 12,
> + .hw.init = CLK_HW_INIT_HW("vclk2_div12", &a9_vclk2_div12_en.hw,
> + &clk_fixed_factor_ops, CLK_SET_RATE_PARENT),
> +};
> +
> +/* Channel 5, 6 and 7 are unconnected */
> +static u32 a9_vid_parents_val_table[] = { 0, 1, 2, 3, 4, 8, 9, 10, 11, 12 };
> +static const struct clk_hw *a9_vid_parents[] = {
> + &a9_vclk_div1_en.hw,
> + &a9_vclk_div2.hw,
> + &a9_vclk_div4.hw,
> + &a9_vclk_div6.hw,
> + &a9_vclk_div12.hw,
> + &a9_vclk2_div1_en.hw,
> + &a9_vclk2_div2.hw,
> + &a9_vclk2_div4.hw,
> + &a9_vclk2_div6.hw,
> + &a9_vclk2_div12.hw
> +};
> +
> +static struct clk_regmap a9_vdac_sel = {
> + .data = &(struct clk_regmap_mux_data){
> + .offset = VIID_CLK_DIV,
> + .mask = 0xf,
> + .shift = 28,
> + .table = a9_vid_parents_val_table,
> + },
> + .hw.init = CLK_HW_INIT_PARENTS_HW("vdac_sel", a9_vid_parents
> + , &clk_regmap_mux_ops, 0),
> +};
> +
> +static struct clk_regmap a9_vdac = {
> + .data = &(struct clk_regmap_gate_data){
> + .offset = VID_CLK_CTRL2,
> + .bit_idx = 4,
> + },
> + .hw.init = CLK_HW_INIT_HW("vdac", &a9_vdac_sel.hw,
> + &clk_regmap_gate_ops, CLK_SET_RATE_PARENT),
> +};
> +
> +static struct clk_regmap a9_enc_sel = {
Should this be enc0 then ? for consistency ?
Same applies to similar instance (it is the same discussion we already
had on the T7 I believe)
> + .data = &(struct clk_regmap_mux_data){
> + .offset = VIID_CLK_DIV,
> + .mask = 0xf,
> + .shift = 12,
> + .table = a9_vid_parents_val_table,
> + },
> + .hw.init = CLK_HW_INIT_PARENTS_HW("enc_sel", a9_vid_parents
> + , &clk_regmap_mux_ops, 0),
> +};
> +
> +static struct clk_regmap a9_enc = {
> + .data = &(struct clk_regmap_gate_data){
> + .offset = VID_CLK_CTRL2,
> + .bit_idx = 10,
> + },
> + .hw.init = CLK_HW_INIT_HW("enc", &a9_enc_sel.hw,
> + &clk_regmap_gate_ops, CLK_SET_RATE_PARENT),
> +};
> +
> +static struct clk_regmap a9_enc1_sel = {
> + .data = &(struct clk_regmap_mux_data){
> + .offset = VIID_CLK_DIV,
> + .mask = 0xf,
> + .shift = 8,
> + .table = a9_vid_parents_val_table,
> + },
> + .hw.init = CLK_HW_INIT_PARENTS_HW("enc1_sel", a9_vid_parents
> + , &clk_regmap_mux_ops, 0),
> +};
> +
> +static struct clk_regmap a9_enc1 = {
> + .data = &(struct clk_regmap_gate_data){
> + .offset = VID_CLK_CTRL2,
> + .bit_idx = 11,
> + },
> + .hw.init = CLK_HW_INIT_HW("enc1", &a9_enc1_sel.hw,
> + &clk_regmap_gate_ops, CLK_SET_RATE_PARENT),
> +};
> +
> +static struct clk_regmap a9_hdmitx_pixel_sel = {
> + .data = &(struct clk_regmap_mux_data){
> + .offset = HDMI_CLK_CTRL,
> + .mask = 0xf,
> + .shift = 16,
> + .table = a9_vid_parents_val_table,
> + },
> + .hw.init = CLK_HW_INIT_PARENTS_HW("hdmitx_pixel_sel", a9_vid_parents
> + , &clk_regmap_mux_ops, 0),
> +};
> +
> +static struct clk_regmap a9_hdmitx_pixel = {
> + .data = &(struct clk_regmap_gate_data){
> + .offset = VID_CLK_CTRL2,
> + .bit_idx = 5,
> + },
> + .hw.init = CLK_HW_INIT_HW("hdmitx_pixel", &a9_hdmitx_pixel_sel.hw,
> + &clk_regmap_gate_ops, CLK_SET_RATE_PARENT),
> +};
> +
> +static struct clk_regmap a9_hdmitx_fe_sel = {
> + .data = &(struct clk_regmap_mux_data){
> + .offset = HDMI_CLK_CTRL,
> + .mask = 0xf,
> + .shift = 20,
> + .table = a9_vid_parents_val_table,
> + },
> + .hw.init = CLK_HW_INIT_PARENTS_HW("hdmitx_fe_sel", a9_vid_parents
> + , &clk_regmap_mux_ops, 0),
> +};
> +
> +static struct clk_regmap a9_hdmitx_fe = {
> + .data = &(struct clk_regmap_gate_data){
> + .offset = VID_CLK_CTRL2,
> + .bit_idx = 9,
> + },
> + .hw.init = CLK_HW_INIT_HW("hdmitx_fe", &a9_hdmitx_fe_sel.hw,
> + &clk_regmap_gate_ops, CLK_SET_RATE_PARENT),
> +};
> +
> +static struct clk_regmap a9_hdmitx1_pixel_sel = {
> + .data = &(struct clk_regmap_mux_data){
> + .offset = HDMI_CLK_CTRL,
> + .mask = 0xf,
> + .shift = 24,
> + .table = a9_vid_parents_val_table,
> + },
> + .hw.init = CLK_HW_INIT_PARENTS_HW("hdmitx1_pixel_sel", a9_vid_parents
> + , &clk_regmap_mux_ops, 0),
> +};
> +
> +static struct clk_regmap a9_hdmitx1_pixel = {
> + .data = &(struct clk_regmap_gate_data){
> + .offset = VID_CLK_CTRL2,
> + .bit_idx = 12,
> + },
> + .hw.init = CLK_HW_INIT_HW("hdmitx1_pixel", &a9_hdmitx1_pixel_sel.hw,
> + &clk_regmap_gate_ops, CLK_SET_RATE_PARENT),
> +};
> +
> +static struct clk_regmap a9_hdmitx1_fe_sel = {
> + .data = &(struct clk_regmap_mux_data){
> + .offset = HDMI_CLK_CTRL,
> + .mask = 0xf,
> + .shift = 28,
> + .table = a9_vid_parents_val_table,
> + },
> + .hw.init = CLK_HW_INIT_PARENTS_HW("hdmitx1_fe_sel", a9_vid_parents
> + , &clk_regmap_mux_ops, 0),
> +};
> +
> +static struct clk_regmap a9_hdmitx1_fe = {
> + .data = &(struct clk_regmap_gate_data){
> + .offset = VID_CLK_CTRL2,
> + .bit_idx = 13,
> + },
> + .hw.init = CLK_HW_INIT_HW("hdmitx1_fe", &a9_hdmitx1_fe_sel.hw,
> + &clk_regmap_gate_ops, CLK_SET_RATE_PARENT),
> +};
> +
> +static const struct clk_parent_data a9_csi_phy_parents[] = {
> + { .fw_name = "fdiv2p5", },
> + { .fw_name = "fdiv3", },
> + { .fw_name = "fdiv4", },
> + { .fw_name = "fdiv5", },
> + { .fw_name = "gp0", },
> + { .fw_name = "hifi0", },
> + { .fw_name = "fdiv2", },
> + { .fw_name = "xtal", }
> +};
> +
> +static A9_COMP_SEL(csi_phy, MIPI_CSI_PHY_CLK_CTRL, 9, 0x7,
> + a9_csi_phy_parents, NULL);
> +static A9_COMP_DIV(csi_phy, MIPI_CSI_PHY_CLK_CTRL, 0, 7);
> +static A9_COMP_GATE(csi_phy, MIPI_CSI_PHY_CLK_CTRL, 8, 0);
> +
> +static const struct clk_parent_data a9_dsi_meas_parents[] = {
> + { .fw_name = "xtal", },
> + { .fw_name = "fdiv4", },
> + { .fw_name = "fdiv3", },
> + { .fw_name = "fdiv5", },
> + { .hw = &a9_vid_pll.hw },
> + { .fw_name = "gp0", },
> + { .fw_name = "vid1", },
> + { .fw_name = "vid2", }
> +};
> +
> +static A9_COMP_SEL(dsi_meas, DSI_MEAS_CLK_CTRL, 9, 0x7,
> + a9_dsi_meas_parents, NULL);
> +static A9_COMP_DIV(dsi_meas, DSI_MEAS_CLK_CTRL, 0, 7);
> +static A9_COMP_GATE(dsi_meas, DSI_MEAS_CLK_CTRL, 8, 0);
> +
> +static A9_COMP_SEL(dsi_b_meas, DSI_MEAS_CLK_CTRL, 25, 0x7,
> + a9_dsi_meas_parents, NULL);
> +static A9_COMP_DIV(dsi_b_meas, DSI_MEAS_CLK_CTRL, 16, 7);
> +static A9_COMP_GATE(dsi_b_meas, DSI_MEAS_CLK_CTRL, 24, 0);
> +
> +static struct clk_hw *a9_peripherals_hw_clks[] = {
> + [CLKID_SYS_AM_AXI] = &a9_sys_am_axi.hw,
> + [CLKID_SYS_DOS] = &a9_sys_dos.hw,
> + [CLKID_SYS_MIPI_DSI] = &a9_sys_mipi_dsi.hw,
> + [CLKID_SYS_ETH_PHY] = &a9_sys_eth_phy.hw,
> + [CLKID_SYS_AMFC] = &a9_sys_amfc.hw,
> + [CLKID_SYS_MALI] = &a9_sys_mali.hw,
> + [CLKID_SYS_NNA] = &a9_sys_nna.hw,
> + [CLKID_SYS_ETH_AXI] = &a9_sys_eth_axi.hw,
> + [CLKID_SYS_DP_APB] = &a9_sys_dp_apb.hw,
> + [CLKID_SYS_EDPTX_APB] = &a9_sys_edptx_apb.hw,
> + [CLKID_SYS_U3HSG] = &a9_sys_u3hsg.hw,
> + [CLKID_SYS_AUCPU] = &a9_sys_aucpu.hw,
> + [CLKID_SYS_GLB] = &a9_sys_glb.hw,
> + [CLKID_SYS_COMBO_DPHY_APB] = &a9_sys_combo_dphy_apb.hw,
> + [CLKID_SYS_HDMIRX_APB] = &a9_sys_hdmirx_apb.hw,
> + [CLKID_SYS_HDMIRX_PCLK] = &a9_sys_hdmirx_pclk.hw,
> + [CLKID_SYS_MIPI_DSI_PHY] = &a9_sys_mipi_dsi_phy.hw,
> + [CLKID_SYS_CAN0] = &a9_sys_can0.hw,
> + [CLKID_SYS_CAN1] = &a9_sys_can1.hw,
> + [CLKID_SYS_SD_EMMC_A] = &a9_sys_sd_emmc_a.hw,
> + [CLKID_SYS_SD_EMMC_B] = &a9_sys_sd_emmc_b.hw,
> + [CLKID_SYS_SD_EMMC_C] = &a9_sys_sd_emmc_c.hw,
> + [CLKID_SYS_SC] = &a9_sys_sc.hw,
> + [CLKID_SYS_ACODEC] = &a9_sys_acodec.hw,
> + [CLKID_SYS_MIPI_ISP] = &a9_sys_mipi_isp.hw,
> + [CLKID_SYS_MSR] = &a9_sys_msr.hw,
> + [CLKID_SYS_AUDIO] = &a9_sys_audio.hw,
> + [CLKID_SYS_MIPI_DSI_B] = &a9_sys_mipi_dsi_b.hw,
> + [CLKID_SYS_MIPI_DSI1_PHY] = &a9_sys_mipi_dsi1_phy.hw,
> + [CLKID_SYS_ETH] = &a9_sys_eth.hw,
> + [CLKID_SYS_ETH_1G_MAC] = &a9_sys_eth_1g_mac.hw,
> + [CLKID_SYS_UART_A] = &a9_sys_uart_a.hw,
> + [CLKID_SYS_UART_F] = &a9_sys_uart_f.hw,
> + [CLKID_SYS_TS_A55] = &a9_sys_ts_a55.hw,
> + [CLKID_SYS_ETH_1G_AXI] = &a9_sys_eth_1g_axi.hw,
> + [CLKID_SYS_TS_DOS] = &a9_sys_ts_dos.hw,
> + [CLKID_SYS_U3DRD_B] = &a9_sys_u3drd_b.hw,
> + [CLKID_SYS_TS_CORE] = &a9_sys_ts_core.hw,
> + [CLKID_SYS_TS_PLL] = &a9_sys_ts_pll.hw,
> + [CLKID_SYS_CSI_DIG_CLKIN] = &a9_sys_csi_dig_clkin.hw,
> + [CLKID_SYS_CVE] = &a9_sys_cve.hw,
> + [CLKID_SYS_GE2D] = &a9_sys_ge2d.hw,
> + [CLKID_SYS_SPISG] = &a9_sys_spisg.hw,
> + [CLKID_SYS_U3DRD_1] = &a9_sys_u3drd_1.hw,
> + [CLKID_SYS_U2H] = &a9_sys_u2h.hw,
> + [CLKID_SYS_PCIE_MAC_A] = &a9_sys_pcie_mac_a.hw,
> + [CLKID_SYS_U3DRD_A] = &a9_sys_u3drd_a.hw,
> + [CLKID_SYS_U2DRD] = &a9_sys_u2drd.hw,
> + [CLKID_SYS_PCIE_PHY] = &a9_sys_pcie_phy.hw,
> + [CLKID_SYS_PCIE_MAC_B] = &a9_sys_pcie_mac_b.hw,
> + [CLKID_SYS_PERIPH] = &a9_sys_periph.hw,
> + [CLKID_SYS_PIO] = &a9_sys_pio.hw,
> + [CLKID_SYS_I3C] = &a9_sys_i3c.hw,
> + [CLKID_SYS_I2C_M_E] = &a9_sys_i2c_m_e.hw,
> + [CLKID_SYS_I2C_M_F] = &a9_sys_i2c_m_f.hw,
> + [CLKID_SYS_HDMITX_APB] = &a9_sys_hdmitx_apb.hw,
> + [CLKID_SYS_I2C_M_I] = &a9_sys_i2c_m_i.hw,
> + [CLKID_SYS_I2C_M_G] = &a9_sys_i2c_m_g.hw,
> + [CLKID_SYS_I2C_M_H] = &a9_sys_i2c_m_h.hw,
> + [CLKID_SYS_HDMI20_AES] = &a9_sys_hdmi20_aes.hw,
> + [CLKID_SYS_CSI2_HOST] = &a9_sys_csi2_host.hw,
> + [CLKID_SYS_CSI2_ADAPT] = &a9_sys_csi2_adapt.hw,
> + [CLKID_SYS_DSPA] = &a9_sys_dspa.hw,
> + [CLKID_SYS_PP_DMA] = &a9_sys_pp_dma.hw,
> + [CLKID_SYS_PP_WRAPPER] = &a9_sys_pp_wrapper.hw,
> + [CLKID_SYS_VPU_INTR] = &a9_sys_vpu_intr.hw,
> + [CLKID_SYS_CSI2_PHY] = &a9_sys_csi2_phy.hw,
> + [CLKID_SYS_SARADC] = &a9_sys_saradc.hw,
> + [CLKID_SYS_PWM_J] = &a9_sys_pwm_j.hw,
> + [CLKID_SYS_PWM_I] = &a9_sys_pwm_i.hw,
> + [CLKID_SYS_PWM_H] = &a9_sys_pwm_h.hw,
> + [CLKID_SYS_PWM_N] = &a9_sys_pwm_n.hw,
> + [CLKID_SYS_PWM_M] = &a9_sys_pwm_m.hw,
> + [CLKID_SYS_PWM_L] = &a9_sys_pwm_l.hw,
> + [CLKID_SYS_PWM_K] = &a9_sys_pwm_k.hw,
> + [CLKID_SD_EMMC_A_SEL] = &a9_sd_emmc_a_sel.hw,
> + [CLKID_SD_EMMC_A_DIV] = &a9_sd_emmc_a_div.hw,
> + [CLKID_SD_EMMC_A] = &a9_sd_emmc_a.hw,
> + [CLKID_SD_EMMC_B_SEL] = &a9_sd_emmc_b_sel.hw,
> + [CLKID_SD_EMMC_B_DIV] = &a9_sd_emmc_b_div.hw,
> + [CLKID_SD_EMMC_B] = &a9_sd_emmc_b.hw,
> + [CLKID_SD_EMMC_C_SEL] = &a9_sd_emmc_c_sel.hw,
> + [CLKID_SD_EMMC_C_DIV] = &a9_sd_emmc_c_div.hw,
> + [CLKID_SD_EMMC_C] = &a9_sd_emmc_c.hw,
> + [CLKID_PWM_H_SEL] = &a9_pwm_h_sel.hw,
> + [CLKID_PWM_H_DIV] = &a9_pwm_h_div.hw,
> + [CLKID_PWM_H] = &a9_pwm_h.hw,
> + [CLKID_PWM_I_SEL] = &a9_pwm_i_sel.hw,
> + [CLKID_PWM_I_DIV] = &a9_pwm_i_div.hw,
> + [CLKID_PWM_I] = &a9_pwm_i.hw,
> + [CLKID_PWM_J_SEL] = &a9_pwm_j_sel.hw,
> + [CLKID_PWM_J_DIV] = &a9_pwm_j_div.hw,
> + [CLKID_PWM_J] = &a9_pwm_j.hw,
> + [CLKID_PWM_K_SEL] = &a9_pwm_k_sel.hw,
> + [CLKID_PWM_K_DIV] = &a9_pwm_k_div.hw,
> + [CLKID_PWM_K] = &a9_pwm_k.hw,
> + [CLKID_PWM_L_SEL] = &a9_pwm_l_sel.hw,
> + [CLKID_PWM_L_DIV] = &a9_pwm_l_div.hw,
> + [CLKID_PWM_L] = &a9_pwm_l.hw,
> + [CLKID_PWM_M_SEL] = &a9_pwm_m_sel.hw,
> + [CLKID_PWM_M_DIV] = &a9_pwm_m_div.hw,
> + [CLKID_PWM_M] = &a9_pwm_m.hw,
> + [CLKID_PWM_N_SEL] = &a9_pwm_n_sel.hw,
> + [CLKID_PWM_N_DIV] = &a9_pwm_n_div.hw,
> + [CLKID_PWM_N] = &a9_pwm_n.hw,
> + [CLKID_SPISG_SEL] = &a9_spisg_sel.hw,
> + [CLKID_SPISG_DIV] = &a9_spisg_div.hw,
> + [CLKID_SPISG] = &a9_spisg.hw,
> + [CLKID_SPISG1_SEL] = &a9_spisg1_sel.hw,
> + [CLKID_SPISG1_DIV] = &a9_spisg1_div.hw,
> + [CLKID_SPISG1] = &a9_spisg1.hw,
> + [CLKID_SPISG2_SEL] = &a9_spisg2_sel.hw,
> + [CLKID_SPISG2_DIV] = &a9_spisg2_div.hw,
> + [CLKID_SPISG2] = &a9_spisg2.hw,
> + [CLKID_SARADC_SEL] = &a9_saradc_sel.hw,
> + [CLKID_SARADC_DIV] = &a9_saradc_div.hw,
> + [CLKID_SARADC] = &a9_saradc.hw,
> + [CLKID_AMFC_SEL] = &a9_amfc_sel.hw,
> + [CLKID_AMFC_DIV] = &a9_amfc_div.hw,
> + [CLKID_AMFC] = &a9_amfc.hw,
> + [CLKID_NNA_SEL] = &a9_nna_sel.hw,
> + [CLKID_NNA_DIV] = &a9_nna_div.hw,
> + [CLKID_NNA] = &a9_nna.hw,
> + [CLKID_USB_250M_SEL] = &a9_usb_250m_sel.hw,
> + [CLKID_USB_250M_DIV] = &a9_usb_250m_div.hw,
> + [CLKID_USB_250M] = &a9_usb_250m.hw,
> + [CLKID_USB_48M_PRE_SEL] = &a9_usb_48m_pre_sel.hw,
> + [CLKID_USB_48M_PRE_DIV] = &a9_usb_48m_pre_div.hw,
> + [CLKID_USB_48M_PRE] = &a9_usb_48m_pre.hw,
> + [CLKID_PCIE_TL_SEL] = &a9_pcie_tl_sel.hw,
> + [CLKID_PCIE_TL_DIV] = &a9_pcie_tl_div.hw,
> + [CLKID_PCIE_TL] = &a9_pcie_tl.hw,
> + [CLKID_PCIE1_TL_SEL] = &a9_pcie1_tl_sel.hw,
> + [CLKID_PCIE1_TL_DIV] = &a9_pcie1_tl_div.hw,
> + [CLKID_PCIE1_TL] = &a9_pcie1_tl.hw,
> + [CLKID_CMPR_SEL] = &a9_cmpr_sel.hw,
> + [CLKID_CMPR_DIV] = &a9_cmpr_div.hw,
> + [CLKID_CMPR] = &a9_cmpr.hw,
> + [CLKID_DEWARPA_SEL] = &a9_dewarpa_sel.hw,
> + [CLKID_DEWARPA_DIV] = &a9_dewarpa_div.hw,
> + [CLKID_DEWARPA] = &a9_dewarpa.hw,
> + [CLKID_SC_PRE_SEL] = &a9_sc_pre_sel.hw,
> + [CLKID_SC_PRE_DIV] = &a9_sc_pre_div.hw,
> + [CLKID_SC_PRE] = &a9_sc_pre.hw,
> + [CLKID_SC] = &a9_sc.hw,
> + [CLKID_DPTX_APB2_SEL] = &a9_dptx_apb2_sel.hw,
> + [CLKID_DPTX_APB2_DIV] = &a9_dptx_apb2_div.hw,
> + [CLKID_DPTX_APB2] = &a9_dptx_apb2.hw,
> + [CLKID_DPTX_AUD_SEL] = &a9_dptx_aud_sel.hw,
> + [CLKID_DPTX_AUD_DIV] = &a9_dptx_aud_div.hw,
> + [CLKID_DPTX_AUD] = &a9_dptx_aud.hw,
> + [CLKID_ISP_SEL] = &a9_isp_sel.hw,
> + [CLKID_ISP_DIV] = &a9_isp_div.hw,
> + [CLKID_ISP] = &a9_isp.hw,
> + [CLKID_CVE_SEL] = &a9_cve_sel.hw,
> + [CLKID_CVE_DIV] = &a9_cve_div.hw,
> + [CLKID_CVE] = &a9_cve.hw,
> + [CLKID_VGE_SEL] = &a9_vge_sel.hw,
> + [CLKID_VGE_DIV] = &a9_vge_div.hw,
> + [CLKID_VGE] = &a9_vge.hw,
> + [CLKID_PP_SEL] = &a9_pp_sel.hw,
> + [CLKID_PP_DIV] = &a9_pp_div.hw,
> + [CLKID_PP] = &a9_pp.hw,
> + [CLKID_GLB_SEL] = &a9_glb_sel.hw,
> + [CLKID_GLB_DIV] = &a9_glb_div.hw,
> + [CLKID_GLB] = &a9_glb.hw,
> + [CLKID_USB_48M_DUALDIV_IN] = &a9_usb_48m_dualdiv_in.hw,
> + [CLKID_USB_48M_DUALDIV_DIV] = &a9_usb_48m_dualdiv_div.hw,
> + [CLKID_USB_48M_DUALDIV_SEL] = &a9_usb_48m_dualdiv_sel.hw,
> + [CLKID_USB_48M_DUALDIV] = &a9_usb_48m_dualdiv.hw,
> + [CLKID_USB_48M] = &a9_usb_48m.hw,
> + [CLKID_CAN_PE_SEL] = &a9_can_pe_sel.hw,
> + [CLKID_CAN_PE_DIV] = &a9_can_pe_div.hw,
> + [CLKID_CAN_PE] = &a9_can_pe.hw,
> + [CLKID_CAN1_PE_SEL] = &a9_can1_pe_sel.hw,
> + [CLKID_CAN1_PE_DIV] = &a9_can1_pe_div.hw,
> + [CLKID_CAN1_PE] = &a9_can1_pe.hw,
> + [CLKID_CAN_FILTER_SEL] = &a9_can_filter_sel.hw,
> + [CLKID_CAN_FILTER_DIV] = &a9_can_filter_div.hw,
> + [CLKID_CAN_FILTER] = &a9_can_filter.hw,
> + [CLKID_CAN1_FILTER_SEL] = &a9_can1_filter_sel.hw,
> + [CLKID_CAN1_FILTER_DIV] = &a9_can1_filter_div.hw,
> + [CLKID_CAN1_FILTER] = &a9_can1_filter.hw,
> + [CLKID_I3C_SEL] = &a9_i3c_sel.hw,
> + [CLKID_I3C_DIV] = &a9_i3c_div.hw,
> + [CLKID_I3C] = &a9_i3c.hw,
> + [CLKID_TS_DIV] = &a9_ts_div.hw,
> + [CLKID_TS] = &a9_ts.hw,
> + [CLKID_ETH_125M_DIV] = &a9_eth_125m_div.hw,
> + [CLKID_ETH_125M] = &a9_eth_125m.hw,
> + [CLKID_ETH_RMII_SEL] = &a9_eth_rmii_sel.hw,
> + [CLKID_ETH_RMII_DIV] = &a9_eth_rmii_div.hw,
> + [CLKID_ETH_RMII] = &a9_eth_rmii.hw,
> + [CLKID_GEN_SEL] = &a9_gen_sel.hw,
> + [CLKID_GEN_DIV] = &a9_gen_div.hw,
> + [CLKID_GEN] = &a9_gen.hw,
> + [CLKID_CLK24M_IN] = &a9_24m_in.hw,
> + [CLKID_CLK12_24M] = &a9_12_24m.hw,
> + [CLKID_MALI_0_SEL] = &a9_mali_0_sel.hw,
> + [CLKID_MALI_0_DIV] = &a9_mali_0_div.hw,
> + [CLKID_MALI_0] = &a9_mali_0.hw,
> + [CLKID_MALI_1_SEL] = &a9_mali_1_sel.hw,
> + [CLKID_MALI_1_DIV] = &a9_mali_1_div.hw,
> + [CLKID_MALI_1] = &a9_mali_1.hw,
> + [CLKID_MALI] = &a9_mali.hw,
> + [CLKID_MALI_STACK_0_SEL] = &a9_mali_stack_0_sel.hw,
> + [CLKID_MALI_STACK_0_DIV] = &a9_mali_stack_0_div.hw,
> + [CLKID_MALI_STACK_0] = &a9_mali_stack_0.hw,
> + [CLKID_MALI_STACK_1_SEL] = &a9_mali_stack_1_sel.hw,
> + [CLKID_MALI_STACK_1_DIV] = &a9_mali_stack_1_div.hw,
> + [CLKID_MALI_STACK_1] = &a9_mali_stack_1.hw,
> + [CLKID_MALI_STACK] = &a9_mali_stack.hw,
> + [CLKID_DSPA_0_SEL] = &a9_dspa_0_sel.hw,
> + [CLKID_DSPA_0_DIV] = &a9_dspa_0_div.hw,
> + [CLKID_DSPA_0] = &a9_dspa_0.hw,
> + [CLKID_DSPA_1_SEL] = &a9_dspa_1_sel.hw,
> + [CLKID_DSPA_1_DIV] = &a9_dspa_1_div.hw,
> + [CLKID_DSPA_1] = &a9_dspa_1.hw,
> + [CLKID_DSPA] = &a9_dspa.hw,
> + [CLKID_HEVCF_0_SEL] = &a9_hevcf_0_sel.hw,
> + [CLKID_HEVCF_0_DIV] = &a9_hevcf_0_div.hw,
> + [CLKID_HEVCF_0] = &a9_hevcf_0.hw,
> + [CLKID_HEVCF_1_SEL] = &a9_hevcf_1_sel.hw,
> + [CLKID_HEVCF_1_DIV] = &a9_hevcf_1_div.hw,
> + [CLKID_HEVCF_1] = &a9_hevcf_1.hw,
> + [CLKID_HEVCF] = &a9_hevcf.hw,
> + [CLKID_HCODEC_0_SEL] = &a9_hcodec_0_sel.hw,
> + [CLKID_HCODEC_0_DIV] = &a9_hcodec_0_div.hw,
> + [CLKID_HCODEC_0] = &a9_hcodec_0.hw,
> + [CLKID_HCODEC_1_SEL] = &a9_hcodec_1_sel.hw,
> + [CLKID_HCODEC_1_DIV] = &a9_hcodec_1_div.hw,
> + [CLKID_HCODEC_1] = &a9_hcodec_1.hw,
> + [CLKID_HCODEC] = &a9_hcodec.hw,
> + [CLKID_VPU_0_SEL] = &a9_vpu_0_sel.hw,
> + [CLKID_VPU_0_DIV] = &a9_vpu_0_div.hw,
> + [CLKID_VPU_0] = &a9_vpu_0.hw,
> + [CLKID_VPU_1_SEL] = &a9_vpu_1_sel.hw,
> + [CLKID_VPU_1_DIV] = &a9_vpu_1_div.hw,
> + [CLKID_VPU_1] = &a9_vpu_1.hw,
> + [CLKID_VPU] = &a9_vpu.hw,
> + [CLKID_VAPB_0_SEL] = &a9_vapb_0_sel.hw,
> + [CLKID_VAPB_0_DIV] = &a9_vapb_0_div.hw,
> + [CLKID_VAPB_0] = &a9_vapb_0.hw,
> + [CLKID_VAPB_1_SEL] = &a9_vapb_1_sel.hw,
> + [CLKID_VAPB_1_DIV] = &a9_vapb_1_div.hw,
> + [CLKID_VAPB_1] = &a9_vapb_1.hw,
> + [CLKID_VAPB] = &a9_vapb.hw,
> + [CLKID_GE2D] = &a9_ge2d.hw,
> + [CLKID_VPU_CLKB_TMP_SEL] = &a9_vpu_clkb_tmp_sel.hw,
> + [CLKID_VPU_CLKB_TMP_DIV] = &a9_vpu_clkb_tmp_div.hw,
> + [CLKID_VPU_CLKB_TMP] = &a9_vpu_clkb_tmp.hw,
> + [CLKID_VPU_CLKB_DIV] = &a9_vpu_clkb_div.hw,
> + [CLKID_VPU_CLKB] = &a9_vpu_clkb.hw,
> + [CLKID_HDMITX_SYS_SEL] = &a9_hdmitx_sys_sel.hw,
> + [CLKID_HDMITX_SYS_DIV] = &a9_hdmitx_sys_div.hw,
> + [CLKID_HDMITX_SYS] = &a9_hdmitx_sys.hw,
> + [CLKID_HDMITX_PRIF_SEL] = &a9_hdmitx_prif_sel.hw,
> + [CLKID_HDMITX_PRIF_DIV] = &a9_hdmitx_prif_div.hw,
> + [CLKID_HDMITX_PRIF] = &a9_hdmitx_prif.hw,
> + [CLKID_HDMITX_200M_SEL] = &a9_hdmitx_200m_sel.hw,
> + [CLKID_HDMITX_200M_DIV] = &a9_hdmitx_200m_div.hw,
> + [CLKID_HDMITX_200M] = &a9_hdmitx_200m.hw,
> + [CLKID_HDMITX_AUD_SEL] = &a9_hdmitx_aud_sel.hw,
> + [CLKID_HDMITX_AUD_DIV] = &a9_hdmitx_aud_div.hw,
> + [CLKID_HDMITX_AUD] = &a9_hdmitx_aud.hw,
> + [CLKID_HDMIRX_5M_SEL] = &a9_hdmirx_5m_sel.hw,
> + [CLKID_HDMIRX_5M_DIV] = &a9_hdmirx_5m_div.hw,
> + [CLKID_HDMIRX_5M] = &a9_hdmirx_5m.hw,
> + [CLKID_HDMIRX_2M_SEL] = &a9_hdmirx_2m_sel.hw,
> + [CLKID_HDMIRX_2M_DIV] = &a9_hdmirx_2m_div.hw,
> + [CLKID_HDMIRX_2M] = &a9_hdmirx_2m.hw,
> + [CLKID_HDMIRX_CFG_SEL] = &a9_hdmirx_cfg_sel.hw,
> + [CLKID_HDMIRX_CFG_DIV] = &a9_hdmirx_cfg_div.hw,
> + [CLKID_HDMIRX_CFG] = &a9_hdmirx_cfg.hw,
> + [CLKID_HDMIRX_HDCP2X_SEL] = &a9_hdmirx_hdcp2x_sel.hw,
> + [CLKID_HDMIRX_HDCP2X_DIV] = &a9_hdmirx_hdcp2x_div.hw,
> + [CLKID_HDMIRX_HDCP2X] = &a9_hdmirx_hdcp2x.hw,
> + [CLKID_HDMIRX_ACR_REF_SEL] = &a9_hdmirx_acr_ref_sel.hw,
> + [CLKID_HDMIRX_ACR_REF_DIV] = &a9_hdmirx_acr_ref_div.hw,
> + [CLKID_HDMIRX_ACR_REF] = &a9_hdmirx_acr_ref.hw,
> + [CLKID_HDMIRX_METER_SEL] = &a9_hdmirx_meter_sel.hw,
> + [CLKID_HDMIRX_METER_DIV] = &a9_hdmirx_meter_div.hw,
> + [CLKID_HDMIRX_METER] = &a9_hdmirx_meter.hw,
> + [CLKID_VID_LOCK_SEL] = &a9_vid_lock_sel.hw,
> + [CLKID_VID_LOCK_DIV] = &a9_vid_lock_div.hw,
> + [CLKID_VID_LOCK] = &a9_vid_lock.hw,
> + [CLKID_VDIN_MEAS_SEL] = &a9_vdin_meas_sel.hw,
> + [CLKID_VDIN_MEAS_DIV] = &a9_vdin_meas_div.hw,
> + [CLKID_VDIN_MEAS] = &a9_vdin_meas.hw,
> + [CLKID_VID_PLL_DIV] = &a9_vid_pll_div.hw,
> + [CLKID_VID_PLL_SEL] = &a9_vid_pll_sel.hw,
> + [CLKID_VID_PLL] = &a9_vid_pll.hw,
> + [CLKID_VID_PLL_VCLK] = &a9_vid_pll_vclk.hw,
> + [CLKID_VCLK_SEL] = &a9_vclk_sel.hw,
> + [CLKID_VCLK_IN] = &a9_vclk_in.hw,
> + [CLKID_VCLK_DIV] = &a9_vclk_div.hw,
> + [CLKID_VCLK] = &a9_vclk.hw,
> + [CLKID_VCLK_DIV1_EN] = &a9_vclk_div1_en.hw,
> + [CLKID_VCLK_DIV2_EN] = &a9_vclk_div2_en.hw,
> + [CLKID_VCLK_DIV2] = &a9_vclk_div2.hw,
> + [CLKID_VCLK_DIV4_EN] = &a9_vclk_div4_en.hw,
> + [CLKID_VCLK_DIV4] = &a9_vclk_div4.hw,
> + [CLKID_VCLK_DIV6_EN] = &a9_vclk_div6_en.hw,
> + [CLKID_VCLK_DIV6] = &a9_vclk_div6.hw,
> + [CLKID_VCLK_DIV12_EN] = &a9_vclk_div12_en.hw,
> + [CLKID_VCLK_DIV12] = &a9_vclk_div12.hw,
> + [CLKID_VCLK2_SEL] = &a9_vclk2_sel.hw,
> + [CLKID_VCLK2_IN] = &a9_vclk2_in.hw,
> + [CLKID_VCLK2_DIV] = &a9_vclk2_div.hw,
> + [CLKID_VCLK2] = &a9_vclk2.hw,
> + [CLKID_VCLK2_DIV1_EN] = &a9_vclk2_div1_en.hw,
> + [CLKID_VCLK2_DIV2_EN] = &a9_vclk2_div2_en.hw,
> + [CLKID_VCLK2_DIV2] = &a9_vclk2_div2.hw,
> + [CLKID_VCLK2_DIV4_EN] = &a9_vclk2_div4_en.hw,
> + [CLKID_VCLK2_DIV4] = &a9_vclk2_div4.hw,
> + [CLKID_VCLK2_DIV6_EN] = &a9_vclk2_div6_en.hw,
> + [CLKID_VCLK2_DIV6] = &a9_vclk2_div6.hw,
> + [CLKID_VCLK2_DIV12_EN] = &a9_vclk2_div12_en.hw,
> + [CLKID_VCLK2_DIV12] = &a9_vclk2_div12.hw,
> + [CLKID_VDAC_SEL] = &a9_vdac_sel.hw,
> + [CLKID_VDAC] = &a9_vdac.hw,
> + [CLKID_ENC_SEL] = &a9_enc_sel.hw,
> + [CLKID_ENC] = &a9_enc.hw,
> + [CLKID_ENC1_SEL] = &a9_enc1_sel.hw,
> + [CLKID_ENC1] = &a9_enc1.hw,
> + [CLKID_HDMITX_PIXEL_SEL] = &a9_hdmitx_pixel_sel.hw,
> + [CLKID_HDMITX_PIXEL] = &a9_hdmitx_pixel.hw,
> + [CLKID_HDMITX_FE_SEL] = &a9_hdmitx_fe_sel.hw,
> + [CLKID_HDMITX_FE] = &a9_hdmitx_fe.hw,
> + [CLKID_HDMITX1_PIXEL_SEL] = &a9_hdmitx1_pixel_sel.hw,
> + [CLKID_HDMITX1_PIXEL] = &a9_hdmitx1_pixel.hw,
> + [CLKID_HDMITX1_FE_SEL] = &a9_hdmitx1_fe_sel.hw,
> + [CLKID_HDMITX1_FE] = &a9_hdmitx1_fe.hw,
> + [CLKID_CSI_PHY_SEL] = &a9_csi_phy_sel.hw,
> + [CLKID_CSI_PHY_DIV] = &a9_csi_phy_div.hw,
> + [CLKID_CSI_PHY] = &a9_csi_phy.hw,
> + [CLKID_DSI_MEAS_SEL] = &a9_dsi_meas_sel.hw,
> + [CLKID_DSI_MEAS_DIV] = &a9_dsi_meas_div.hw,
> + [CLKID_DSI_MEAS] = &a9_dsi_meas.hw,
> + [CLKID_DSI_B_MEAS_SEL] = &a9_dsi_b_meas_sel.hw,
> + [CLKID_DSI_B_MEAS_DIV] = &a9_dsi_b_meas_div.hw,
> + [CLKID_DSI_B_MEAS] = &a9_dsi_b_meas.hw,
> +};
> +
> +static const struct meson_clkc_data a9_peripherals_clkc_data = {
> + .hw_clks = {
> + .hws = a9_peripherals_hw_clks,
> + .num = ARRAY_SIZE(a9_peripherals_hw_clks),
> + },
> +};
> +
> +static const struct of_device_id a9_peripherals_clkc_match_table[] = {
> + {
> + .compatible = "amlogic,a9-peripherals-clkc",
> + .data = &a9_peripherals_clkc_data,
> + },
> + { /* sentinel */ }
> +};
> +
> +MODULE_DEVICE_TABLE(of, a9_peripherals_clkc_match_table);
> +
> +static struct platform_driver a9_peripherals_clkc_driver = {
> + .probe = meson_clkc_mmio_probe,
> + .driver = {
> + .name = "a9-peripherals-clkc",
> + .of_match_table = a9_peripherals_clkc_match_table,
> + },
> +};
> +module_platform_driver(a9_peripherals_clkc_driver);
> +
> +MODULE_DESCRIPTION("Amlogic A9 Peripherals Clock Controller driver");
> +MODULE_AUTHOR("Jian Hu <jian.hu@amlogic.com>");
> +MODULE_LICENSE("GPL");
> +MODULE_IMPORT_NS("CLK_MESON");
--
Jerome
^ permalink raw reply
* Re: [PATCH v4 2/2] cpu/hotplug: Fix NULL kobject warning in cpuhp_smt_enable()
From: Catalin Marinas @ 2026-06-10 12:43 UTC (permalink / raw)
To: Jinjie Ruan
Cc: will, corbet, skhan, punit.agrawal, mrigendra.chaubey,
suzuki.poulose, chenl311, fengchengwen, maz, timothy.hayes,
lpieralisi, arnd, gshan, jic23, dietmar.eggemann, sudeep.holla,
pierre.gondois, linux-arm-kernel, linux-doc, linux-kernel
In-Reply-To: <20260610075202.3597031-3-ruanjinjie@huawei.com>
On Wed, Jun 10, 2026 at 03:52:02PM +0800, Jinjie Ruan wrote:
> diff --git a/Documentation/arch/arm64/cpu-hotplug.rst b/Documentation/arch/arm64/cpu-hotplug.rst
> index 8fb438bf7781..7c3379b704aa 100644
> --- a/Documentation/arch/arm64/cpu-hotplug.rst
> +++ b/Documentation/arch/arm64/cpu-hotplug.rst
> @@ -47,11 +47,12 @@ ever have can be described at boot. There are no power-domain considerations
> as such devices are emulated.
>
> CPU Hotplug on virtual systems is supported. It is distinct from physical
> -CPU Hotplug as all resources are described as ``present``, but CPUs may be
> -marked as disabled by firmware. Only the CPU's online/offline behaviour is
> -influenced by firmware. An example is where a virtual machine boots with a
> -single CPU, and additional CPUs are added once a cloud orchestrator deploys
> -the workload.
> +CPU Hotplug as all vCPU resources are statically described in the firmware
> +configuration tables (e.g. MADT), meaning their maximum possible count is
> +known at boot. However, vCPUs that are not enabled at boot are not marked
> +as ``present`` by the kernel until they are hotplugged. An example is where
> +a virtual machine boots with a single CPU, and additional CPUs are added
> +once a cloud orchestrator deploys the workload.
>
> For a virtual machine, the VMM (e.g. Qemu) plays the part of firmware.
>
> @@ -60,16 +61,19 @@ brought online. Firmware can enforce its policy via PSCI's return codes. e.g.
> ``DENIED``.
>
> The ACPI tables must describe all the resources of the virtual machine. CPUs
> -that firmware wishes to disable either from boot (or later) should not be
> -``enabled`` in the MADT GICC structures, but should have the ``online capable``
> -bit set, to indicate they can be enabled later. The boot CPU must be marked as
> -``enabled``. The 'always on' GICR structure must be used to describe the
> -redistributors.
> +that are hot-pluggable must have the ``online capable`` bit set and the
> +``enabled`` bit cleared in the MADT GICC structures to indicate they can be
> +enabled later. The boot CPU must be marked as ``enabled`` with its
> +``online capable`` bit cleared. The 'always on' GICR structure must be used
> +to describe the redistributors.
>
> CPUs described as ``online capable`` but not ``enabled`` can be set to enabled
> by the DSDT's Processor object's _STA method. On virtual systems the _STA method
> -must always report the CPU as ``present``. Changes to the firmware policy can
> -be notified to the OS via device-check or eject-request.
> +must always set the ``ACPI_STA_DEVICE_PRESENT`` bit, while toggling the
> +``ACPI_STA_DEVICE_ENABLED`` bit to reflect its plug status. The kernel will
> +then dynamically mark the vCPU as ``present`` within the OS when the
> +``ACPI_STA_DEVICE_ENABLED`` bit becomes set during hot-add. Changes to the
> +firmware policy can be notified to the OS via device-check or eject-request.
The doc update looks fine as well, thanks for clarifying. My reviewed-by
stands.
--
Catalin
^ permalink raw reply
* Re: [PATCH] bus: vexpress-config: fix device_node refcount leak in vexpress_syscfg_probe()
From: Liviu Dudau @ 2026-06-10 12:38 UTC (permalink / raw)
To: Weigang He
Cc: Sudeep Holla, Lorenzo Pieralisi, Rob Herring, linux-arm-kernel,
linux-kernel
In-Reply-To: <20260610033054.2117363-1-geoffreyhe2@gmail.com>
On Wed, Jun 10, 2026 at 01:30:54PM +1000, Weigang He wrote:
> vexpress_syscfg_probe() iterates the "arm,vexpress,config-bus"
> compatible nodes and, for each one, takes a reference to the bridge
> phandle via of_parse_phandle():
>
> bridge_np = of_parse_phandle(node, "arm,vexpress,config-bridge", 0);
>
> bridge_np is only compared against pdev->dev.parent->of_node and is
> never released - neither on the "continue" path when it does not match,
> nor on the path that calls of_platform_populate() and falls through to
> the next loop iteration. Each matching iteration leaks one device_node
> reference; the leak repeats on every probe (driver bind/unbind, module
> reload, or EPROBE_DEFER retry).
>
> This is a regression of commit 557e37c05f28 ("bus: vexpress-config: add
> missing of_node_put after calling of_parse_phandle"), which fixed the
> equivalent leak in the predecessor function vexpress_config_populate().
> Commit a5a38765ac79 ("bus: vexpress-config: simplify config bus
> probing") removed that function and inlined the loop into the probe
> routine, but did not carry over the of_node_put().
>
> Use the __free(device_node) cleanup attribute on bridge_np so the
> reference is released automatically at the end of each loop iteration.
>
> Found by static analysis tool CodeQL.
>
> Fixes: a5a38765ac79 ("bus: vexpress-config: simplify config bus probing")
> Signed-off-by: Weigang He <geoffreyhe2@gmail.com>
Reviewed-by: Liviu Dudau <liviu.dudau@arm.com>
Thanks for the fix!
Best regards,
Liviu
> ---
> drivers/bus/vexpress-config.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/bus/vexpress-config.c b/drivers/bus/vexpress-config.c
> index 64ee920721ee7..cc247483d3823 100644
> --- a/drivers/bus/vexpress-config.c
> +++ b/drivers/bus/vexpress-config.c
> @@ -390,9 +390,9 @@ static int vexpress_syscfg_probe(struct platform_device *pdev)
> }
>
> for_each_compatible_node(node, NULL, "arm,vexpress,config-bus") {
> - struct device_node *bridge_np;
> + struct device_node *bridge_np __free(device_node) =
> + of_parse_phandle(node, "arm,vexpress,config-bridge", 0);
>
> - bridge_np = of_parse_phandle(node, "arm,vexpress,config-bridge", 0);
> if (bridge_np != pdev->dev.parent->of_node)
> continue;
>
>
> base-commit: 0f61b1860cc3f52aef9036d7235ed1f017632193
> --
> 2.43.0
>
--
====================
| I would like to |
| fix the world, |
| but they're not |
| giving me the |
\ source code! /
---------------
¯\_(ツ)_/¯
^ permalink raw reply
* Re: [PATCHv2] arm64/entry: Fix arm64-specific rseq brokenness
From: Will Deacon @ 2026-06-10 12:37 UTC (permalink / raw)
To: Mathias Stearn
Cc: Jinjie Ruan, Mark Rutland, linux-arm-kernel, Catalin Marinas,
Peter Zijlstra, Thomas Gleixner, ckennelly, dvyukov, linux-kernel,
mathieu.desnoyers
In-Reply-To: <CAHnCjA1dGNH07YkWupg1THAmBhW=o4C+uhHbbcRX4edMj2rmEg@mail.gmail.com>
On Tue, Jun 09, 2026 at 02:04:23PM +0200, Mathias Stearn wrote:
> Did the arm64-specific fix to rseq not get backportted to 7.0? We just
> ran our test suite against 7.0.10 which has the other rseq fixes and
> everything was fine on x86_64, but arm64 was frequently segfaulting.
>
> I had an AI agent look into this and it reported:
> """
> The fix (commits b9eac6a9d93c, 82f572449cfe, 99428157dcf3,
> 411c1cf43039) first appeared in v7.1-rc1 and will be included in
> v7.1.0.
>
> The three commits backported to linux-7.0.y:
> - 663121edad54 — "rseq: Revert to historical performance killing behaviour"
> - d242126fd21a — "rseq: Implement read only ABI enforcement for
> optimized RSEQ V2 mode"
> - fb742945d61a — "rseq: Reenable performance optimizations conditionally"
>
> The arm64-specific fix (411c1cf43039 "arm64/entry: Fix arm64-specific
> rseq brokenness") was not backported to any stable branch — it will
> only appear in v7.1.0.
> """
>
> Is it possible to get 411c1cf43039 backported to 7.0 or was it omitted
> intentionally?
You can send a backport to the stable maintainers:
https://docs.kernel.org/process/stable-kernel-rules.html#procedure-for-submitting-patches-to-the-stable-tree
(see option 3)
Will
^ permalink raw reply
* Re: [PATCH v2 1/2] soc: aspeed: add BMC-side PCIe BMC device driver
From: Andrew Jeffery @ 2026-06-10 12:33 UTC (permalink / raw)
To: Grégoire Layet, joel
Cc: andrew, jacky_chou, yh_chung, ninad, linux-aspeed,
linux-arm-kernel, linux-kernel
In-Reply-To: <af322e76d34ad504e0bdec470293a017b489cfd7.1780929570.git.gregoire.layet@9elements.com>
Hello Grégoire,
On Mon, 2026-06-08 at 14:51 +0000, Grégoire Layet wrote:
> Taken from ASPEED 6.18 Kernel SDK
It's probably best to use ASPEED's SDK as a source of inspiration for
fixing obscure bugs, but not send drivers directly extracted from it.
>
> Add support for VUART over PCIe between BMC and host.
> This add BMC side driver.
>
> Signed-off-by: Jacky Chou <jacky_chou@aspeedtech.com>
> Signed-off-by: aspeedyh <yh_chung@aspeedtech.com>
> Signed-off-by: Grégoire Layet <gregoire.layet@9elements.com>
> Tested-by: Grégoire Layet <gregoire.layet@9elements.com>
> ---
> drivers/soc/aspeed/Kconfig | 7 ++
> drivers/soc/aspeed/Makefile | 1 +
> drivers/soc/aspeed/aspeed-bmc-dev.c | 187 ++++++++++++++++++++++++++++
We should avoid adding more drivers in drivers/soc/aspeed where we can.
Is this really necessary?
> 3 files changed, 195 insertions(+)
> create mode 100644 drivers/soc/aspeed/aspeed-bmc-dev.c
>
> diff --git a/drivers/soc/aspeed/Kconfig b/drivers/soc/aspeed/Kconfig
> index f579ee0b5afa..3e1fcf3c3268 100644
> --- a/drivers/soc/aspeed/Kconfig
> +++ b/drivers/soc/aspeed/Kconfig
> @@ -4,6 +4,13 @@ if ARCH_ASPEED || COMPILE_TEST
>
> menu "ASPEED SoC drivers"
>
> +config ASPEED_BMC_DEV
> + tristate "ASPEED BMC Device"
> + default n
> + help
> + Enable support for the ASPEED AST2600 BMC Device.
> + This exposes the PCIe-to-LPC bridge of the BMC to the host over PCIe.
> +
> config ASPEED_LPC_CTRL
> tristate "ASPEED LPC firmware cycle control"
> select REGMAP
> diff --git a/drivers/soc/aspeed/Makefile b/drivers/soc/aspeed/Makefile
> index b35d74592964..fab0d247df66 100644
> --- a/drivers/soc/aspeed/Makefile
> +++ b/drivers/soc/aspeed/Makefile
> @@ -1,4 +1,5 @@
> # SPDX-License-Identifier: GPL-2.0-only
> +obj-$(CONFIG_ASPEED_BMC_DEV) += aspeed-bmc-dev.o
> obj-$(CONFIG_ASPEED_LPC_CTRL) += aspeed-lpc-ctrl.o
> obj-$(CONFIG_ASPEED_LPC_SNOOP) += aspeed-lpc-snoop.o
> obj-$(CONFIG_ASPEED_UART_ROUTING) += aspeed-uart-routing.o
> diff --git a/drivers/soc/aspeed/aspeed-bmc-dev.c b/drivers/soc/aspeed/aspeed-bmc-dev.c
> new file mode 100644
> index 000000000000..7a204b543c97
> --- /dev/null
> +++ b/drivers/soc/aspeed/aspeed-bmc-dev.c
> @@ -0,0 +1,187 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +// Copyright (C) ASPEED Technology Inc.
> +
> +#include <linux/init.h>
> +#include <linux/module.h>
> +#include <linux/kernel.h>
> +#include <linux/errno.h>
> +
> +#include <linux/of_address.h>
> +#include <linux/platform_device.h>
> +
> +#include <linux/regmap.h>
> +#include <linux/interrupt.h>
> +#include <linux/mfd/syscon.h>
> +
> +#define SCU_TRIGGER_MSI
> +
> +/* AST2600 SCU */
> +#define ASPEED_SCU04 0x04
> +#define AST2600A3_SCU04 0x05030303
> +#define ASPEED_SCUC20 0xC20
> +#define ASPEED_SCUC24 0xC24
These could all use properly descriptive names.
Pinctrl is an exception because of how the documentation is structured.
> +#define MSI_ROUTING_MASK GENMASK(11, 10)
> +#define PCIDEV1_INTX_MSI_HOST2BMC_EN BIT(18)
> +#define MSI_ROUTING_PCIe2LPC_PCIDEV0 (0x1 << 10)
> +#define MSI_ROUTING_PCIe2LPC_PCIDEV1 (0x2 << 10)
> +
> +#define ASPEED_SCU_PCIE_CONF_CTRL 0xC20
> +#define SCU_PCIE_CONF_BMC_DEV_EN BIT(8)
> +#define SCU_PCIE_CONF_BMC_DEV_EN_MMIO BIT(9)
> +#define SCU_PCIE_CONF_BMC_DEV_EN_MSI BIT(11)
> +#define SCU_PCIE_CONF_BMC_DEV_EN_IRQ BIT(13)
> +#define SCU_PCIE_CONF_BMC_DEV_EN_DMA BIT(14)
> +#define SCU_PCIE_CONF_BMC_DEV_EN_E2L BIT(15)
> +#define SCU_PCIE_CONF_BMC_DEV_EN_LPC_DECODE BIT(21)
> +
> +#define ASPEED_SCU_BMC_DEV_CLASS 0xC68
> +
> +
> +struct aspeed_platform {
> + int (*init)(struct platform_device *pdev);
> +};
> +
> +struct aspeed_bmc_device {
> + struct device *dev;
> + int id;
> + void __iomem *reg_base;
> +
> + int pcie2lpc;
> + int irq;
> +
> + const struct aspeed_platform *platform;
> +
> + struct regmap *scu;
> + int pcie_irq;
> +};
> +
> +
> +static int aspeed_ast2600_init(struct platform_device *pdev)
> +{
> + struct aspeed_bmc_device *bmc_device = platform_get_drvdata(pdev);
> + struct device *dev = &pdev->dev;
> + u32 pcie_config_ctl = SCU_PCIE_CONF_BMC_DEV_EN_IRQ |
> + SCU_PCIE_CONF_BMC_DEV_EN_MMIO | SCU_PCIE_CONF_BMC_DEV_EN;
> + u32 scu_id;
> +
> + bmc_device->scu = syscon_regmap_lookup_by_phandle(dev->of_node, "aspeed,scu");
We should rather look at auxbus for the SCU.
> + if (IS_ERR(bmc_device->scu)) {
> + dev_err(&pdev->dev, "failed to find SCU regmap\n");
> + return PTR_ERR(bmc_device->scu);
> + }
> +
> + if (bmc_device->pcie2lpc)
> + pcie_config_ctl |= SCU_PCIE_CONF_BMC_DEV_EN_E2L |
> + SCU_PCIE_CONF_BMC_DEV_EN_LPC_DECODE;
> +
> + regmap_update_bits(bmc_device->scu, ASPEED_SCU_PCIE_CONF_CTRL,
> + pcie_config_ctl, pcie_config_ctl);
> +
> + /* update class code to others as it is a MFD device */
> + regmap_write(bmc_device->scu, ASPEED_SCU_BMC_DEV_CLASS, 0xff000000);
> +
> +#ifdef SCU_TRIGGER_MSI
I don't see that this needs to be a CPP test. This could be a C test.
The construct would be optimised because of the constant and we'd get
compile time coverage of both sides without additional configuration.
Have you tested both sides?
> + //SCUC24[17]: Enable PCI device 1 INTx/MSI from SCU560[15]. Will be added in next version
> + regmap_update_bits(bmc_device->scu, ASPEED_SCUC20, BIT(11) | BIT(14), BIT(11) | BIT(14));
These bits need descriptive macros.
> +
> + regmap_read(bmc_device->scu, ASPEED_SCU04, &scu_id);
> + if (scu_id == AST2600A3_SCU04)
> + regmap_update_bits(bmc_device->scu, ASPEED_SCUC24,
> + PCIDEV1_INTX_MSI_HOST2BMC_EN | MSI_ROUTING_MASK,
> + PCIDEV1_INTX_MSI_HOST2BMC_EN | MSI_ROUTING_PCIe2LPC_PCIDEV1);
> + else
> + regmap_update_bits(bmc_device->scu, ASPEED_SCUC24,
> + BIT(17) | BIT(14) | BIT(11), BIT(17) | BIT(14) | BIT(11));
As do these
> +#else
> + //SCUC24[18]: Enable PCI device 1 INTx/MSI from Host-to-BMC controller.
> + regmap_update_bits(bmc_device->scu, 0xc24, BIT(18) | BIT(14), BIT(18) | BIT(14));
And these.
> +#endif
> +
> +
> + return 0;
> +}
> +
> +
> +static struct aspeed_platform ast2600_plaform = {
> + .init = aspeed_ast2600_init
> +};
> +
> +
> +static const struct of_device_id aspeed_bmc_device_of_matches[] = {
> + { .compatible = "aspeed,ast2600-bmc-device", .data = &ast2600_plaform },
This compatible isn't documented in this series and isn't present in
linux-next at a87737435cfa ("Add linux-next specific files for
20260608"). You'll need to address that if it's reasonable to continue
down this path. I expect you'll want to avoid it, and define any
necessary properties on the SCU node rather than add further children.
> + {},
> +};
> +MODULE_DEVICE_TABLE(of, aspeed_bmc_device_of_matches);
> +
> +static int aspeed_bmc_device_probe(struct platform_device *pdev)
> +{
> + struct aspeed_bmc_device *bmc_device;
> + struct device *dev = &pdev->dev;
This shortcut is defined but inconsistently used.
> + const void *md = of_device_get_match_data(dev);
I think we can do without this, see below.
> + int ret = 0;
> +
> + if (!md)
> + return -ENODEV;
> +
> + bmc_device = devm_kzalloc(&pdev->dev, sizeof(struct aspeed_bmc_device), GFP_KERNEL);
> + if (!bmc_device)
> + return -ENOMEM;
> + dev_set_drvdata(dev, bmc_device);
> +
> + bmc_device->platform = md;
> +
> + bmc_device->id = of_alias_get_id(dev->of_node, "bmcdev");
> + if (bmc_device->id < 0)
> + bmc_device->id = 0;
> +
> + bmc_device->dev = dev;
> + bmc_device->reg_base = devm_platform_ioremap_resource(pdev, 0);
> + if (IS_ERR(bmc_device->reg_base))
> + return PTR_ERR(bmc_device->reg_base);
> +
> + bmc_device->irq = platform_get_irq(pdev, 0);
This seems unnecessary.
> + if (bmc_device->irq < 0) {
> + dev_err(&pdev->dev, "platform get of irq[=%d] failed!\n", bmc_device->irq);
> + return bmc_device->irq;
> + }
> +
> + if (of_property_read_bool(dev->of_node, "pcie2lpc"))
This property isn't documented.
> + bmc_device->pcie2lpc = 1;
> +
> + ret = bmc_device->platform->init(pdev);
The driver only supports one SoC, this indirection seems unnecessary
right now. We can add that later when there's a need to differentiate.
I'd rather you call the setup function directly for now.
> + if (ret) {
> + dev_err(dev, "Initialize bmc device failed\n");
> + goto out;
> + }
> +
> + dev_info(dev, "aspeed bmc device: driver successfully loaded.\n");
> +
> + return 0;
> +
> +out:
> + dev_warn(dev, "aspeed bmc device: driver init failed (ret=%d)!\n", ret);
> + return ret;
> +}
> +
> +static void aspeed_bmc_device_remove(struct platform_device *pdev)
> +{
> + struct aspeed_bmc_device *bmc_device = platform_get_drvdata(pdev);
> +
> + devm_free_irq(&pdev->dev, bmc_device->irq, bmc_device);
> + devm_kfree(&pdev->dev, bmc_device);
These are unnecessary due to cleanup of devres on release.
Andrew
^ permalink raw reply
* Re: [PATCH v3 2/2] clk: amlogic: Add A9 AO clock controller driver
From: Jerome Brunet @ 2026-06-10 12:30 UTC (permalink / raw)
To: Jian Hu via B4 Relay
Cc: Neil Armstrong, Michael Turquette, Stephen Boyd, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Xianwei Zhao, Kevin Hilman,
Martin Blumenstingl, jian.hu, linux-amlogic, linux-clk,
devicetree, linux-kernel, linux-arm-kernel
In-Reply-To: <20260610-a9_aoclk-v3-2-b7592d6c31e2@amlogic.com>
On mer. 10 juin 2026 at 16:23, Jian Hu via B4 Relay <devnull+jian.hu.amlogic.com@kernel.org> wrote:
> From: Jian Hu <jian.hu@amlogic.com>
>
> Add the Always-on clock controller driver for the Amlogic A9 SoC family.
>
> Signed-off-by: Jian Hu <jian.hu@amlogic.com>
> ---
> drivers/clk/meson/Kconfig | 13 ++
> drivers/clk/meson/Makefile | 1 +
> drivers/clk/meson/a9-aoclk.c | 431 +++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 445 insertions(+)
>
> diff --git a/drivers/clk/meson/Kconfig b/drivers/clk/meson/Kconfig
> index cf8cf3f9e4ee..b71299898197 100644
> --- a/drivers/clk/meson/Kconfig
> +++ b/drivers/clk/meson/Kconfig
> @@ -132,6 +132,19 @@ config COMMON_CLK_A1_PERIPHERALS
> device, A1 SoC Family. Say Y if you want A1 Peripherals clock
> controller to work.
>
> +config COMMON_CLK_A9_AO
> + tristate "Amlogic A9 SoC AO clock controller support"
> + depends on ARM64 || COMPILE_TEST
> + default ARCH_MESON
> + select COMMON_CLK_MESON_REGMAP
> + select COMMON_CLK_MESON_CLKC_UTILS
> + select COMMON_CLK_MESON_DUALDIV
> + imply COMMON_CLK_SCMI
> + help
> + Support for the AO clock controller on Amlogic A311Y3 based
> + device, AKA A9.
> + Say Y if you want A9 AO clock controller to work.
> +
> config COMMON_CLK_C3_PLL
> tristate "Amlogic C3 PLL clock controller"
> depends on ARM64
> diff --git a/drivers/clk/meson/Makefile b/drivers/clk/meson/Makefile
> index c6719694a242..f89d027c282c 100644
> --- a/drivers/clk/meson/Makefile
> +++ b/drivers/clk/meson/Makefile
> @@ -19,6 +19,7 @@ obj-$(CONFIG_COMMON_CLK_AXG) += axg.o axg-aoclk.o
> obj-$(CONFIG_COMMON_CLK_AXG_AUDIO) += axg-audio.o
> obj-$(CONFIG_COMMON_CLK_A1_PLL) += a1-pll.o
> obj-$(CONFIG_COMMON_CLK_A1_PERIPHERALS) += a1-peripherals.o
> +obj-$(CONFIG_COMMON_CLK_A9_AO) += a9-aoclk.o
> obj-$(CONFIG_COMMON_CLK_C3_PLL) += c3-pll.o
> obj-$(CONFIG_COMMON_CLK_C3_PERIPHERALS) += c3-peripherals.o
> obj-$(CONFIG_COMMON_CLK_GXBB) += gxbb.o gxbb-aoclk.o
> diff --git a/drivers/clk/meson/a9-aoclk.c b/drivers/clk/meson/a9-aoclk.c
> new file mode 100644
> index 000000000000..dd9fd8d24702
> --- /dev/null
> +++ b/drivers/clk/meson/a9-aoclk.c
> @@ -0,0 +1,431 @@
> +// SPDX-License-Identifier: (GPL-2.0-only OR MIT)
> +/*
> + * Copyright (C) 2026 Amlogic, Inc. All rights reserved
> + */
> +
> +#include <dt-bindings/clock/amlogic,a9-aoclkc.h>
> +#include <linux/clk-provider.h>
> +#include <linux/platform_device.h>
> +#include "clk-regmap.h"
> +#include "clk-dualdiv.h"
> +#include "meson-clkc-utils.h"
> +
> +#define AO_OSCIN_CTRL 0x00
> +#define AO_SYS_CLK0 0x04
> +#define AO_PWM_CLK_A_CTRL 0x1c
> +#define AO_PWM_CLK_B_CTRL 0x20
> +#define AO_PWM_CLK_C_CTRL 0x24
> +#define AO_PWM_CLK_D_CTRL 0x28
> +#define AO_PWM_CLK_E_CTRL 0x2c
> +#define AO_PWM_CLK_F_CTRL 0x30
> +#define AO_PWM_CLK_G_CTRL 0x34
> +#define AO_CEC_CTRL0 0x38
> +#define AO_CEC_CTRL1 0x3c
> +#define AO_RTC_BY_OSCIN_CTRL0 0x50
> +#define AO_RTC_BY_OSCIN_CTRL1 0x54
> +
> +#define A9_COMP_SEL(_name, _reg, _shift, _mask, _pdata) \
> + MESON_COMP_SEL(a9_ao_, _name, _reg, _shift, _mask, _pdata, NULL, 0, 0)
> +
> +#define A9_COMP_DIV(_name, _reg, _shift, _width) \
> + MESON_COMP_DIV(a9_ao_, _name, _reg, _shift, _width, 0, CLK_SET_RATE_PARENT)
> +
> +#define A9_COMP_GATE(_name, _reg, _bit) \
> + MESON_COMP_GATE(a9_ao_, _name, _reg, _bit, CLK_SET_RATE_PARENT)
> +
> +static struct clk_regmap a9_ao_xtal_in = {
> + .data = &(struct clk_regmap_gate_data){
> + .offset = AO_OSCIN_CTRL,
> + .bit_idx = 3,
> + },
> + .hw.init = &(struct clk_init_data) {
> + .name = "ao_xtal_in",
> + .ops = &clk_regmap_gate_ops,
> + .parent_data = &(const struct clk_parent_data) {
> + .fw_name = "xtal",
> + },
> + .num_parents = 1,
> + /*
> + * ao_sys can select different clock sources. One possible clock path is:
> + * ao_xtal_in->ao_xtal->ao_sys-> ao sys gate clocks
> + *
> + * ao_xtal_in is in the parent chain of AO sys gate clocks.
> + * Since some downstream clocks are marked CLK_IS_CRITICAL,
> + * ao_xtal_in must remain enabled and is therefore marked
> + * CLK_IS_CRITICAL as well.
> + */
> + .flags = CLK_IS_CRITICAL,
Please allow some time for me to reply before reposting.
See my answer on v2.
> + },
> +};
> +
> +static struct clk_regmap a9_ao_xtal = {
> + .data = &(struct clk_regmap_mux_data) {
> + .offset = AO_OSCIN_CTRL,
> + .mask = 0x1,
> + .shift = 0,
> + },
> + /* ext_32k is from external PAD, do not automatically reparent */
> + .hw.init = CLK_HW_INIT_PARENTS_DATA("ao_xtal",
> + ((const struct clk_parent_data []) {
> + { .hw = &a9_ao_xtal_in.hw },
> + { .fw_name = "ext_32k" }
> + }), &clk_regmap_mux_ops, CLK_SET_RATE_NO_REPARENT),
I hope my view on this is clear as well.
Let me know if it isn't
> +};
> +
> +static struct clk_regmap a9_ao_sys = {
> + .data = &(struct clk_regmap_mux_data) {
> + .offset = AO_OSCIN_CTRL,
> + .mask = 0x1,
> + .shift = 1,
> + },
> + .hw.init = CLK_HW_INIT_PARENTS_DATA("ao_sys",
> + ((const struct clk_parent_data []) {
> + { .hw = &a9_ao_xtal.hw },
> + { .fw_name = "sys" }
> + }), &clk_regmap_mux_ops, 0),
> +};
> +
> +static const struct clk_parent_data a9_ao_pclk_parents = { .hw = &a9_ao_sys.hw };
> +
> +#define A9_AO_PCLK(_name, _bit, _flags) \
> + MESON_PCLK(a9_ao_sys_##_name, AO_SYS_CLK0, _bit, \
> + &a9_ao_pclk_parents, _flags)
> +
> +/*
> + * A9 integrates a low-power microprocessor (Always-on CPU: AOCPU). Some AO sys
> + * clocks control the AOCPU modules. Mark the AOCPU-related clocks with
> + * CLK_IS_CRITICAL to avoid them being disabled and impacting AOCPU functionality.
> + * AOCPU-related clocks list:
> + * - clktree
> + * - rst_ctrl
> + * - pad
> + * - irq
> + * - pwrctrl
> + * - aocpu
> + * - sram
> + */
> +static A9_AO_PCLK(i3c, 0, 0);
> +static A9_AO_PCLK(rtc_reg, 1, 0);
> +static A9_AO_PCLK(clktree, 2, CLK_IS_CRITICAL);
> +static A9_AO_PCLK(rst_ctrl, 3, CLK_IS_CRITICAL);
> +static A9_AO_PCLK(pad, 4, CLK_IS_CRITICAL);
> +static A9_AO_PCLK(rtc_dig, 5, 0);
> +static A9_AO_PCLK(irq, 6, CLK_IS_CRITICAL);
> +static A9_AO_PCLK(pwrctrl, 7, CLK_IS_CRITICAL);
> +static A9_AO_PCLK(pwm_a, 8, 0);
> +static A9_AO_PCLK(pwm_b, 9, 0);
> +static A9_AO_PCLK(pwm_c, 10, 0);
> +static A9_AO_PCLK(pwm_d, 11, 0);
> +static A9_AO_PCLK(pwm_e, 12, 0);
> +static A9_AO_PCLK(pwm_f, 13, 0);
> +static A9_AO_PCLK(pwm_g, 14, 0);
> +static A9_AO_PCLK(i2c_a, 15, 0);
> +static A9_AO_PCLK(i2c_b, 16, 0);
> +static A9_AO_PCLK(i2c_c, 17, 0);
> +static A9_AO_PCLK(i2c_d, 18, 0);
> +static A9_AO_PCLK(sed, 19, 0);
> +static A9_AO_PCLK(ir_ctrl, 20, 0);
> +static A9_AO_PCLK(uart_b, 21, 0);
> +static A9_AO_PCLK(uart_c, 22, 0);
> +static A9_AO_PCLK(uart_d, 23, 0);
> +static A9_AO_PCLK(uart_e, 24, 0);
> +static A9_AO_PCLK(spisg_0, 25, 0);
> +static A9_AO_PCLK(rtc_secure, 26, 0);
> +static A9_AO_PCLK(cec, 27, 0);
> +static A9_AO_PCLK(aocpu, 28, CLK_IS_CRITICAL);
> +static A9_AO_PCLK(sram, 29, CLK_IS_CRITICAL);
> +static A9_AO_PCLK(spisg_1, 30, 0);
> +static A9_AO_PCLK(spisg_2, 31, 0);
> +
> +static const struct clk_parent_data a9_ao_pwm_parents[] = {
> + { .hw = &a9_ao_xtal.hw },
> + { .fw_name = "fdiv5", },
> + { .fw_name = "fdiv4", },
> + { .fw_name = "fdiv3", }
> +};
> +
> +static A9_COMP_SEL(pwm_a, AO_PWM_CLK_A_CTRL, 9, 0x7, a9_ao_pwm_parents);
> +static A9_COMP_DIV(pwm_a, AO_PWM_CLK_A_CTRL, 0, 8);
> +static A9_COMP_GATE(pwm_a, AO_PWM_CLK_A_CTRL, 8);
> +
> +static A9_COMP_SEL(pwm_b, AO_PWM_CLK_B_CTRL, 9, 0x7, a9_ao_pwm_parents);
> +static A9_COMP_DIV(pwm_b, AO_PWM_CLK_B_CTRL, 0, 8);
> +static A9_COMP_GATE(pwm_b, AO_PWM_CLK_B_CTRL, 8);
> +
> +static A9_COMP_SEL(pwm_c, AO_PWM_CLK_C_CTRL, 9, 0x7, a9_ao_pwm_parents);
> +static A9_COMP_DIV(pwm_c, AO_PWM_CLK_C_CTRL, 0, 8);
> +static A9_COMP_GATE(pwm_c, AO_PWM_CLK_C_CTRL, 8);
> +
> +static A9_COMP_SEL(pwm_d, AO_PWM_CLK_D_CTRL, 9, 0x7, a9_ao_pwm_parents);
> +static A9_COMP_DIV(pwm_d, AO_PWM_CLK_D_CTRL, 0, 8);
> +static A9_COMP_GATE(pwm_d, AO_PWM_CLK_D_CTRL, 8);
> +
> +static A9_COMP_SEL(pwm_e, AO_PWM_CLK_E_CTRL, 9, 0x7, a9_ao_pwm_parents);
> +static A9_COMP_DIV(pwm_e, AO_PWM_CLK_E_CTRL, 0, 8);
> +static A9_COMP_GATE(pwm_e, AO_PWM_CLK_E_CTRL, 8);
> +
> +static A9_COMP_SEL(pwm_f, AO_PWM_CLK_F_CTRL, 9, 0x7, a9_ao_pwm_parents);
> +static A9_COMP_DIV(pwm_f, AO_PWM_CLK_F_CTRL, 0, 8);
> +static A9_COMP_GATE(pwm_f, AO_PWM_CLK_F_CTRL, 8);
> +
> +static A9_COMP_SEL(pwm_g, AO_PWM_CLK_G_CTRL, 9, 0x7, a9_ao_pwm_parents);
> +static A9_COMP_DIV(pwm_g, AO_PWM_CLK_G_CTRL, 0, 8);
> +static A9_COMP_GATE(pwm_g, AO_PWM_CLK_G_CTRL, 8);
> +
> +static struct clk_regmap a9_ao_rtc_dualdiv_in = {
> + .data = &(struct clk_regmap_gate_data){
> + .offset = AO_RTC_BY_OSCIN_CTRL0,
> + .bit_idx = 31,
> + },
> + .hw.init = CLK_HW_INIT_HW("ao_rtc_dualdiv_in", &a9_ao_xtal.hw,
> + &clk_regmap_gate_ops, 0),
> +};
> +
> +static const struct meson_clk_dualdiv_param a9_ao_dualdiv_table[] = {
> + { 733, 732, 8, 11, 1 },
> + { /* sentinel */ }
> +};
> +
> +static struct clk_regmap a9_ao_rtc_dualdiv_div = {
> + .data = &(struct meson_clk_dualdiv_data){
> + .n1 = {
> + .reg_off = AO_RTC_BY_OSCIN_CTRL0,
> + .shift = 0,
> + .width = 12,
> + },
> + .n2 = {
> + .reg_off = AO_RTC_BY_OSCIN_CTRL0,
> + .shift = 12,
> + .width = 12,
> + },
> + .m1 = {
> + .reg_off = AO_RTC_BY_OSCIN_CTRL1,
> + .shift = 0,
> + .width = 12,
> + },
> + .m2 = {
> + .reg_off = AO_RTC_BY_OSCIN_CTRL1,
> + .shift = 12,
> + .width = 12,
> + },
> + .dual = {
> + .reg_off = AO_RTC_BY_OSCIN_CTRL0,
> + .shift = 28,
> + .width = 1,
> + },
> + .table = a9_ao_dualdiv_table,
> + },
> + .hw.init = CLK_HW_INIT_HW("a9_ao_rtc_dualdiv_div", &a9_ao_rtc_dualdiv_in.hw,
> + &meson_clk_dualdiv_ops, 0),
> +};
> +
> +static struct clk_regmap a9_ao_rtc_dualdiv_sel = {
> + .data = &(struct clk_regmap_mux_data) {
> + .offset = AO_RTC_BY_OSCIN_CTRL1,
> + .mask = 0x1,
> + .shift = 24,
> + },
> + .hw.init = CLK_HW_INIT_PARENTS_HW("ao_rtc_dualdiv_sel",
> + ((const struct clk_hw *[]) {
> + &a9_ao_rtc_dualdiv_div.hw,
> + &a9_ao_rtc_dualdiv_in.hw,
> + }), &clk_regmap_mux_ops, CLK_SET_RATE_PARENT),
> +};
> +
> +static struct clk_regmap a9_ao_rtc_dualdiv = {
> + .data = &(struct clk_regmap_gate_data){
> + .offset = AO_RTC_BY_OSCIN_CTRL0,
> + .bit_idx = 30,
> + },
> + .hw.init = CLK_HW_INIT_HW("ao_rtc_dualdiv", &a9_ao_rtc_dualdiv_sel.hw,
> + &clk_regmap_gate_ops, CLK_SET_RATE_PARENT),
> +};
> +
> +static struct clk_regmap a9_ao_rtc = {
> + .data = &(struct clk_regmap_mux_data) {
> + .offset = AO_RTC_BY_OSCIN_CTRL1,
> + .mask = 0x1,
> + .shift = 30,
> + },
> + .hw.init = CLK_HW_INIT_PARENTS_HW("ao_rtc",
> + ((const struct clk_hw *[]) {
> + &a9_ao_xtal.hw,
> + &a9_ao_rtc_dualdiv.hw,
> + }), &clk_regmap_mux_ops, CLK_SET_RATE_PARENT),
> +};
> +
> +static struct clk_regmap a9_ao_cec_dualdiv_in = {
> + .data = &(struct clk_regmap_gate_data){
> + .offset = AO_CEC_CTRL0,
> + .bit_idx = 31,
> + },
> + .hw.init = CLK_HW_INIT_HW("ao_cec_dualdiv_in", &a9_ao_xtal.hw,
> + &clk_regmap_gate_ops, 0),
> +};
> +
> +static struct clk_regmap a9_ao_cec_dualdiv_div = {
> + .data = &(struct meson_clk_dualdiv_data){
> + .n1 = {
> + .reg_off = AO_CEC_CTRL0,
> + .shift = 0,
> + .width = 12,
> + },
> + .n2 = {
> + .reg_off = AO_CEC_CTRL0,
> + .shift = 12,
> + .width = 12,
> + },
> + .m1 = {
> + .reg_off = AO_CEC_CTRL1,
> + .shift = 0,
> + .width = 12,
> + },
> + .m2 = {
> + .reg_off = AO_CEC_CTRL1,
> + .shift = 12,
> + .width = 12,
> + },
> + .dual = {
> + .reg_off = AO_CEC_CTRL0,
> + .shift = 28,
> + .width = 1,
> + },
> + .table = a9_ao_dualdiv_table,
> + },
> + .hw.init = CLK_HW_INIT_HW("ao_cec_dualdiv_div", &a9_ao_cec_dualdiv_in.hw,
> + &meson_clk_dualdiv_ops, 0),
> +};
> +
> +static struct clk_regmap a9_ao_cec_dualdiv_sel = {
> + .data = &(struct clk_regmap_mux_data) {
> + .offset = AO_CEC_CTRL1,
> + .mask = 0x1,
> + .shift = 24,
> + },
> + .hw.init = CLK_HW_INIT_PARENTS_HW("ao_cec_dualdiv_sel",
> + ((const struct clk_hw *[]) {
> + &a9_ao_cec_dualdiv_div.hw,
> + &a9_ao_cec_dualdiv_in.hw,
> + }), &clk_regmap_mux_ops, CLK_SET_RATE_PARENT),
> +};
> +
> +static struct clk_regmap a9_ao_cec_dualdiv = {
> + .data = &(struct clk_regmap_gate_data){
> + .offset = AO_CEC_CTRL0,
> + .bit_idx = 30,
> + },
> + .hw.init = CLK_HW_INIT_HW("ao_cec_dualdiv", &a9_ao_cec_dualdiv_sel.hw,
> + &clk_regmap_gate_ops, CLK_SET_RATE_PARENT),
> +};
> +
> +static struct clk_regmap a9_ao_cec = {
> + .data = &(struct clk_regmap_mux_data) {
> + .offset = AO_CEC_CTRL1,
> + .mask = 0x1,
> + .shift = 30,
> + },
> + .hw.init = CLK_HW_INIT_PARENTS_HW("ao_cec",
> + ((const struct clk_hw *[]) {
> + &a9_ao_cec_dualdiv.hw,
> + &a9_ao_rtc.hw,
> + }), &clk_regmap_mux_ops, CLK_SET_RATE_PARENT),
> +};
> +
> +static struct clk_hw *a9_ao_hw_clks[] = {
> + [CLKID_AO_XTAL_IN] = &a9_ao_xtal_in.hw,
> + [CLKID_AO_XTAL] = &a9_ao_xtal.hw,
> + [CLKID_AO_SYS] = &a9_ao_sys.hw,
> + [CLKID_AO_SYS_I3C] = &a9_ao_sys_i3c.hw,
> + [CLKID_AO_SYS_RTC_REG] = &a9_ao_sys_rtc_reg.hw,
> + [CLKID_AO_SYS_CLKTREE] = &a9_ao_sys_clktree.hw,
> + [CLKID_AO_SYS_RST_CTRL] = &a9_ao_sys_rst_ctrl.hw,
> + [CLKID_AO_SYS_PAD] = &a9_ao_sys_pad.hw,
> + [CLKID_AO_SYS_RTC_DIG] = &a9_ao_sys_rtc_dig.hw,
> + [CLKID_AO_SYS_IRQ] = &a9_ao_sys_irq.hw,
> + [CLKID_AO_SYS_PWRCTRL] = &a9_ao_sys_pwrctrl.hw,
> + [CLKID_AO_SYS_PWM_A] = &a9_ao_sys_pwm_a.hw,
> + [CLKID_AO_SYS_PWM_B] = &a9_ao_sys_pwm_b.hw,
> + [CLKID_AO_SYS_PWM_C] = &a9_ao_sys_pwm_c.hw,
> + [CLKID_AO_SYS_PWM_D] = &a9_ao_sys_pwm_d.hw,
> + [CLKID_AO_SYS_PWM_E] = &a9_ao_sys_pwm_e.hw,
> + [CLKID_AO_SYS_PWM_F] = &a9_ao_sys_pwm_f.hw,
> + [CLKID_AO_SYS_PWM_G] = &a9_ao_sys_pwm_g.hw,
> + [CLKID_AO_SYS_I2C_A] = &a9_ao_sys_i2c_a.hw,
> + [CLKID_AO_SYS_I2C_B] = &a9_ao_sys_i2c_b.hw,
> + [CLKID_AO_SYS_I2C_C] = &a9_ao_sys_i2c_c.hw,
> + [CLKID_AO_SYS_I2C_D] = &a9_ao_sys_i2c_d.hw,
> + [CLKID_AO_SYS_SED] = &a9_ao_sys_sed.hw,
> + [CLKID_AO_SYS_IR_CTRL] = &a9_ao_sys_ir_ctrl.hw,
> + [CLKID_AO_SYS_UART_B] = &a9_ao_sys_uart_b.hw,
> + [CLKID_AO_SYS_UART_C] = &a9_ao_sys_uart_c.hw,
> + [CLKID_AO_SYS_UART_D] = &a9_ao_sys_uart_d.hw,
> + [CLKID_AO_SYS_UART_E] = &a9_ao_sys_uart_e.hw,
> + [CLKID_AO_SYS_SPISG_0] = &a9_ao_sys_spisg_0.hw,
> + [CLKID_AO_SYS_RTC_SECURE] = &a9_ao_sys_rtc_secure.hw,
> + [CLKID_AO_SYS_CEC] = &a9_ao_sys_cec.hw,
> + [CLKID_AO_SYS_AOCPU] = &a9_ao_sys_aocpu.hw,
> + [CLKID_AO_SYS_SRAM] = &a9_ao_sys_sram.hw,
> + [CLKID_AO_SYS_SPISG_1] = &a9_ao_sys_spisg_1.hw,
> + [CLKID_AO_SYS_SPISG_2] = &a9_ao_sys_spisg_2.hw,
> + [CLKID_AO_PWM_A_SEL] = &a9_ao_pwm_a_sel.hw,
> + [CLKID_AO_PWM_A_DIV] = &a9_ao_pwm_a_div.hw,
> + [CLKID_AO_PWM_A] = &a9_ao_pwm_a.hw,
> + [CLKID_AO_PWM_B_SEL] = &a9_ao_pwm_b_sel.hw,
> + [CLKID_AO_PWM_B_DIV] = &a9_ao_pwm_b_div.hw,
> + [CLKID_AO_PWM_B] = &a9_ao_pwm_b.hw,
> + [CLKID_AO_PWM_C_SEL] = &a9_ao_pwm_c_sel.hw,
> + [CLKID_AO_PWM_C_DIV] = &a9_ao_pwm_c_div.hw,
> + [CLKID_AO_PWM_C] = &a9_ao_pwm_c.hw,
> + [CLKID_AO_PWM_D_SEL] = &a9_ao_pwm_d_sel.hw,
> + [CLKID_AO_PWM_D_DIV] = &a9_ao_pwm_d_div.hw,
> + [CLKID_AO_PWM_D] = &a9_ao_pwm_d.hw,
> + [CLKID_AO_PWM_E_SEL] = &a9_ao_pwm_e_sel.hw,
> + [CLKID_AO_PWM_E_DIV] = &a9_ao_pwm_e_div.hw,
> + [CLKID_AO_PWM_E] = &a9_ao_pwm_e.hw,
> + [CLKID_AO_PWM_F_SEL] = &a9_ao_pwm_f_sel.hw,
> + [CLKID_AO_PWM_F_DIV] = &a9_ao_pwm_f_div.hw,
> + [CLKID_AO_PWM_F] = &a9_ao_pwm_f.hw,
> + [CLKID_AO_PWM_G_SEL] = &a9_ao_pwm_g_sel.hw,
> + [CLKID_AO_PWM_G_DIV] = &a9_ao_pwm_g_div.hw,
> + [CLKID_AO_PWM_G] = &a9_ao_pwm_g.hw,
> + [CLKID_AO_RTC_DUALDIV_IN] = &a9_ao_rtc_dualdiv_in.hw,
> + [CLKID_AO_RTC_DUALDIV_DIV] = &a9_ao_rtc_dualdiv_div.hw,
> + [CLKID_AO_RTC_DUALDIV_SEL] = &a9_ao_rtc_dualdiv_sel.hw,
> + [CLKID_AO_RTC_DUALDIV] = &a9_ao_rtc_dualdiv.hw,
> + [CLKID_AO_RTC] = &a9_ao_rtc.hw,
> + [CLKID_AO_CEC_DUALDIV_IN] = &a9_ao_cec_dualdiv_in.hw,
> + [CLKID_AO_CEC_DUALDIV_DIV] = &a9_ao_cec_dualdiv_div.hw,
> + [CLKID_AO_CEC_DUALDIV_SEL] = &a9_ao_cec_dualdiv_sel.hw,
> + [CLKID_AO_CEC_DUALDIV] = &a9_ao_cec_dualdiv.hw,
> + [CLKID_AO_CEC] = &a9_ao_cec.hw,
> +};
> +
> +static const struct meson_clkc_data a9_ao_clkc_data = {
> + .hw_clks = {
> + .hws = a9_ao_hw_clks,
> + .num = ARRAY_SIZE(a9_ao_hw_clks),
> + },
> +};
> +
> +static const struct of_device_id a9_ao_clkc_match_table[] = {
> + {
> + .compatible = "amlogic,a9-aoclkc",
> + .data = &a9_ao_clkc_data,
> + },
> + { }
> +};
> +MODULE_DEVICE_TABLE(of, a9_ao_clkc_match_table);
> +
> +static struct platform_driver a9_ao_clkc_driver = {
> + .probe = meson_clkc_mmio_probe,
> + .driver = {
> + .name = "a9-aoclkc",
> + .of_match_table = a9_ao_clkc_match_table,
> + },
> +};
> +module_platform_driver(a9_ao_clkc_driver);
> +
> +MODULE_DESCRIPTION("Amlogic A9 Always-ON Clock Controller driver");
> +MODULE_AUTHOR("Jian Hu <jian.hu@amlogic.com>");
> +MODULE_LICENSE("GPL");
> +MODULE_IMPORT_NS("CLK_MESON");
--
Jerome
^ permalink raw reply
* Re: [PATCH] arm64/hw_breakpoint: reject unaligned watchpoints that would truncate BAS
From: Will Deacon @ 2026-06-10 12:30 UTC (permalink / raw)
To: Breno Leitao
Cc: Mark Rutland, Catalin Marinas, Pratyush Anand, linux-arm-kernel,
linux-perf-users, linux-kernel, clm, leo.bras, kernel-team
In-Reply-To: <aiaqbmQSksKB6dTZ@gmail.com>
On Mon, Jun 08, 2026 at 05:14:22AM -0700, Breno Leitao wrote:
> On Fri, May 29, 2026 at 03:53:58PM +0100, Will Deacon wrote:
> > Hi Breno,
> >
> > Thanks for sending this out.
> >
> > On Thu, Apr 30, 2026 at 02:40:10AM -0700, Breno Leitao wrote:
> > > hw_breakpoint_arch_parse() positions the BAS bit pattern in
> > > hw->ctrl.len with
> > >
> > > offset = hw->address & alignment_mask; /* 0..7 */
> > > hw->ctrl.len <<= offset;
> > >
> > > ctrl.len is an 8-bit bitfield (struct arch_hw_breakpoint_ctrl::len is
> > > u32 :8), so the shift silently drops any bits past bit 7. For
> > > non-compat AArch64 watchpoints the offset is unbounded relative to
> > > ctrl.len: a perf_event_open(PERF_TYPE_BREAKPOINT) caller asking for
> > > HW_BREAKPOINT_W with bp_addr=page+1 and bp_len=HW_BREAKPOINT_LEN_8
> > > ends up with 0xff << 1 = 0x1fe, stored as 0xfe. The kernel programs
> > > WCR.BAS=0xfe and the hardware watches bytes [1..7] instead of the
> > > requested [1..8] -- the eighth byte is silently dropped. The
> > > syscall still returns success, leaving userspace to discover the
> > > gap by empirical probing.
> > >
> > > The same class affects HW_BREAKPOINT_LEN_{2,4} when offset pushes the
> > > high BAS bit past bit 7 (e.g. LEN_4 with offset=5 yields 0xe0
> > > instead of 0x1e0). No memory-safety impact -- the value is masked
> > > into 8 bits before encoding -- but debuggers and perf users observe
> > > missed events on bytes they thought they were watching.
> > >
> > > The AArch32 branch immediately above already rejects unrepresentable
> > > (offset, len) combinations via an explicit switch. Mirror that for
> > > the non-compat branch by checking that the shifted pattern fits in
> > > the BAS field, returning -EINVAL when it does not.
> > >
> > > Reproducer:
> > >
> > > struct perf_event_attr a = {
> > > .type = PERF_TYPE_BREAKPOINT, .size = sizeof(a),
> > > .bp_type = HW_BREAKPOINT_W,
> > > .bp_addr = (uintptr_t)(buf + 1),
> > > .bp_len = HW_BREAKPOINT_LEN_8,
> > > .exclude_kernel = 1, .exclude_hv = 1,
> > > };
> > > int fd = perf_event_open(&a, 0, -1, -1, 0);
> > > /* before this fix: succeeds, watches 7 bytes (buf+1..buf+7) */
> > > /* after this fix: fails with EINVAL */
> > >
> > > Signed-off-by: Breno Leitao <leitao@debian.org>
> > > Fixes: b08fb180bb88 ("arm64: Allow hw watchpoint at varied offset from base address")
> >
> > Oh man, this has been broken for nearly a decade :/
> >
> > I think we probably should've stuck with the old behaviour of rejecting
> > unaligned base addresses, but it's too late now. Damn.
> >
> > > arch/arm64/kernel/hw_breakpoint.c | 9 +++++++++
> > > 1 file changed, 9 insertions(+)
> > >
> > > diff --git a/arch/arm64/kernel/hw_breakpoint.c b/arch/arm64/kernel/hw_breakpoint.c
> > > index ab76b36dce820..b8a1402119f3a 100644
> > > --- a/arch/arm64/kernel/hw_breakpoint.c
> > > +++ b/arch/arm64/kernel/hw_breakpoint.c
> > > @@ -559,6 +559,15 @@ int hw_breakpoint_arch_parse(struct perf_event *bp,
> > > else
> > > alignment_mask = 0x7;
> > > offset = hw->address & alignment_mask;
> > > +
> > > + /*
> > > + * BAS is an 8-bit field in WCR/BCR; the shift below would
> > > + * silently drop the high bits of ctrl.len when offset + len
> > > + * exceeds 8, programming hardware to watch fewer bytes than
> > > + * the user requested.
> > > + */
> > > + if (((u32)hw->ctrl.len << offset) > 0xff)
> >
> > nit: Use ARM_BREAKPOINT_LEN_8 instead of 0xff
> >
> > > + return -EINVAL;
> > > }
> >
> > I must confess, I'm very nervous about breaking userspace here. If GDB
> > is triggering this path, then this patch will change an unreliable
> > watchpoint into a hard error (which probably means GDB exits). Have you
> > looked to see what GDB and/or any other debuggers do?
> >
> > I had a quick peek and found the bugzilla entry which motivated the
> > buggy change in the first place:
> >
> > https://sourceware.org/bugzilla/show_bug.cgi?id=20207
> >
> > and it looks like the aarch64_align_watchpoint() function does try to
> > spill into multiple watchpoints, so perhaps your patch is ok. I'd
> > appreciate your opinion, though.
>
> It won't, for two independent reasons.
Sorry, not sure I understand you here when you say "it won't". GDB won't
spill or something else?
> The new -EINVAL is unreachable from GDB; only a raw perf_event_open() passing
> an unaligned base with an oversized bp_len hits it, which is the bug.
Why isn't it reachable via hw_break_set() => {ptrace_hbp_set_addr(),
ptrace_hbp_set_ctrl()} ?
> Second, even if a debugger did hand the kernel such a request, GDB
> already treats EINVAL on NT_ARM_HW_WATCH as a downgrade signal, not a
> fatal error. aarch64_linux_set_debug_regs() catches it, clears
> kernel_supports_any_contiguous_range, calls aarch64_downgrade_regs()
> (which rounds the BAS up to a legacy 0x01/03/0f/ff mask and aligns the
> base down), and retries. That fallback is exactly the PR-20207 path.
>
> Confirmed on a Grace box: with the patch applied (under virtme-ng), the
> reproducer's unaligned LEN_8 now returns -EINVAL while aligned LEN_8
> still succeeds, and GDB still inserts the watchpoint and it still fires
> on every write.
Thanks for testing it, that's somewhat reassuring.
> GDB in fact downgrades on the current kernel independently of this patch, so
> behaviour is unchanged for it.
That sounds like a bug?
Will
^ permalink raw reply
* Re: [PATCH v2 2/2] clk: amlogic: Add A9 AO clock controller driver
From: Jerome Brunet @ 2026-06-10 12:26 UTC (permalink / raw)
To: Jian Hu
Cc: Jian Hu via B4 Relay, Neil Armstrong, Michael Turquette,
Stephen Boyd, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Xianwei Zhao, Kevin Hilman, Martin Blumenstingl, linux-amlogic,
linux-clk, devicetree, linux-kernel, linux-arm-kernel
In-Reply-To: <67fcf9bc-0ac7-4812-aa7c-4d42d8f1c162@amlogic.com>
On mer. 10 juin 2026 at 12:18, Jian Hu <jian.hu@amlogic.com> wrote:
> Hi Jerome,
>
> Thanks for your review
>
> On 6/3/2026 10:29 PM, Jerome Brunet wrote:
>> [ EXTERNAL EMAIL ]
>>
>> On Wed 03 Jun 2026 at 20:17, Jian Hu via B4 Relay <devnull+jian.hu.amlogic.com@kernel.org> wrote:
>>
>>> From: Jian Hu <jian.hu@amlogic.com>
>>>
>>> Add the Always-on clock controller driver for the Amlogic A9 SoC family.
>>>
>>> Signed-off-by: Jian Hu <jian.hu@amlogic.com>
>>> ---
>>> drivers/clk/meson/Kconfig | 13 ++
>>> drivers/clk/meson/Makefile | 1 +
>>> drivers/clk/meson/a9-aoclk.c | 419 +++++++++++++++++++++++++++++++++++++++++++
>>> 3 files changed, 433 insertions(+)
>>>
>>> diff --git a/drivers/clk/meson/Kconfig b/drivers/clk/meson/Kconfig
>>> index cf8cf3f9e4ee..625e6788b940 100644
>>> --- a/drivers/clk/meson/Kconfig
>>> +++ b/drivers/clk/meson/Kconfig
>>> @@ -132,6 +132,19 @@ config COMMON_CLK_A1_PERIPHERALS
>>> device, A1 SoC Family. Say Y if you want A1 Peripherals clock
>>> controller to work.
>>>
>>> +config COMMON_CLK_A9_AO
>>> + tristate "Amlogic A9 SoC AO clock controller support"
>>> + depends on ARM64
>>> + default ARCH_MESON || COMPILE_TEST
>>> + select COMMON_CLK_MESON_REGMAP
>>> + select COMMON_CLK_MESON_CLKC_UTILS
>>> + select COMMON_CLK_MESON_DUALDIV
>>> + imply COMMON_CLK_SCMI
>>> + help
>>> + Support for the AO clock controller on Amlogic A311Y3 based
>>> + device, AKA A9.
>>> + Say Y if you want A9 AO clock controller to work.
>>> +
>>> config COMMON_CLK_C3_PLL
>>> tristate "Amlogic C3 PLL clock controller"
>>> depends on ARM64
>>> diff --git a/drivers/clk/meson/Makefile b/drivers/clk/meson/Makefile
>>> index c6719694a242..f89d027c282c 100644
>>> --- a/drivers/clk/meson/Makefile
>>> +++ b/drivers/clk/meson/Makefile
>>> @@ -19,6 +19,7 @@ obj-$(CONFIG_COMMON_CLK_AXG) += axg.o axg-aoclk.o
>>> obj-$(CONFIG_COMMON_CLK_AXG_AUDIO) += axg-audio.o
>>> obj-$(CONFIG_COMMON_CLK_A1_PLL) += a1-pll.o
>>> obj-$(CONFIG_COMMON_CLK_A1_PERIPHERALS) += a1-peripherals.o
>>> +obj-$(CONFIG_COMMON_CLK_A9_AO) += a9-aoclk.o
>>> obj-$(CONFIG_COMMON_CLK_C3_PLL) += c3-pll.o
>>> obj-$(CONFIG_COMMON_CLK_C3_PERIPHERALS) += c3-peripherals.o
>>> obj-$(CONFIG_COMMON_CLK_GXBB) += gxbb.o gxbb-aoclk.o
>>> diff --git a/drivers/clk/meson/a9-aoclk.c b/drivers/clk/meson/a9-aoclk.c
>>> new file mode 100644
>>> index 000000000000..b7b3ca231a42
>>> --- /dev/null
>>> +++ b/drivers/clk/meson/a9-aoclk.c
>>> @@ -0,0 +1,419 @@
>>> +// SPDX-License-Identifier: (GPL-2.0-only OR MIT)
>>> +/*
>>> + * Copyright (C) 2026 Amlogic, Inc. All rights reserved
>>> + */
>>> +
>>> +#include <dt-bindings/clock/amlogic,a9-aoclkc.h>
>>> +#include <linux/clk-provider.h>
>>> +#include <linux/platform_device.h>
>>> +#include "clk-regmap.h"
>>> +#include "clk-dualdiv.h"
>>> +#include "meson-clkc-utils.h"
>>> +
>>> +#define AO_OSCIN_CTRL 0x00
>>> +#define AO_SYS_CLK0 0x04
>>> +#define AO_PWM_CLK_A_CTRL 0x1c
>>> +#define AO_PWM_CLK_B_CTRL 0x20
>>> +#define AO_PWM_CLK_C_CTRL 0x24
>>> +#define AO_PWM_CLK_D_CTRL 0x28
>>> +#define AO_PWM_CLK_E_CTRL 0x2c
>>> +#define AO_PWM_CLK_F_CTRL 0x30
>>> +#define AO_PWM_CLK_G_CTRL 0x34
>>> +#define AO_CEC_CTRL0 0x38
>>> +#define AO_CEC_CTRL1 0x3c
>>> +#define AO_RTC_BY_OSCIN_CTRL0 0x50
>>> +#define AO_RTC_BY_OSCIN_CTRL1 0x54
>>> +
>>> +#define A9_COMP_SEL(_name, _reg, _shift, _mask, _pdata) \
>>> + MESON_COMP_SEL(a9_ao_, _name, _reg, _shift, _mask, _pdata, NULL, 0, 0)
>>> +
>>> +#define A9_COMP_DIV(_name, _reg, _shift, _width) \
>>> + MESON_COMP_DIV(a9_ao_, _name, _reg, _shift, _width, 0, CLK_SET_RATE_PARENT)
>>> +
>>> +#define A9_COMP_GATE(_name, _reg, _bit) \
>>> + MESON_COMP_GATE(a9_ao_, _name, _reg, _bit, CLK_SET_RATE_PARENT)
>>> +
>>> +static struct clk_regmap a9_ao_xtal_in = {
>>> + .data = &(struct clk_regmap_gate_data){
>>> + .offset = AO_OSCIN_CTRL,
>>> + .bit_idx = 3,
>>> + },
>>> + /*
>>> + * It may be ao_sys's parent clock, its child clocks mark
>>> + * CLK_IS_CRITICAL, So mark CLK_IS_CRITICAL for it.
>>> + */
>> I don't really get what you mean ... Could you rephrase ?
>
>
> The AO sys gate clock chain may be:
>
> ao_xtal_in->ao_xtal->ao_sys-> AO sys gate clocks
>
> "ao_xtal_in" is part of the parent chain of the AO sys gate clocks.
>
> Some of its downstream clocks are marked with CLK_IS_CRITICAL. To ensure
> those clocks remain functional, ao_xtal_in must not be disabled and is
> therefore marked as CLK_IS_CRITICAL as well.
If any of the downstream clocks are critical and marked as such, there is not
need to mark this one as well.
You should only mark the clocks that are actually critical with the flag
and let CCF figure out the dependencies.
>
>
> I will rephrase it like this in the next version:
>
> /*
> * ao_sys can select different clock sources. One possible clock
> path is:
> * ao_xtal_in->ao_xtal->ao_sys-> ao sys gate clocks
> *
> * ao_xtal_in is in the parent chain of AO sys gate clocks.
> * Since some downstream clocks are marked CLK_IS_CRITICAL,
> * ao_xtal_in must remain enabled and is therefore marked
> * CLK_IS_CRITICAL as well.
> */
>
>>> + .hw.init = CLK_HW_INIT_FW_NAME("ao_xtal_in", "xtal",
>>> + &clk_regmap_gate_ops, CLK_IS_CRITICAL),
>> I'm honestly not sure about this. It is correct, sure and the macro exist to be
>> used but ... It does not really help readability here, does it ?
>>
>> (I know that was a feedback you've got on v1)
>>
>> Other than that, this looks good to me.
>>
> Ok, I will use the original clk_init_data for this one.
Well my comment applies to whole thing really.
There are surely ways in which the macro but the way we statically
declare things, it adds a level of indirection that makes things harder
to review IMO.
>
>
> [ ... ]
>
>> --
>> Jerome
--
Jerome
^ permalink raw reply
* Re: [PATCH v2 0/7] KVM: arm64: Forward FFA_NOTIFICATION* calls to TrustZone
From: Will Deacon @ 2026-06-10 12:23 UTC (permalink / raw)
To: Vincent Donnefort
Cc: Sebastian Ene, catalin.marinas, maz, oupton, joey.gouly, korneld,
kvmarm, linux-arm-kernel, linux-kernel, android-kvm,
mrigendra.chaubey, perlarsen, suzuki.poulose, yuzenghui
In-Reply-To: <ailVcN-bxY30-XBF@google.com>
On Wed, Jun 10, 2026 at 01:15:44PM +0100, Vincent Donnefort wrote:
> On Wed, Jun 10, 2026 at 11:15:14AM +0100, Will Deacon wrote:
> > On Wed, Jun 10, 2026 at 10:26:59AM +0100, Vincent Donnefort wrote:
> > > On Mon, Jun 08, 2026 at 04:55:42PM +0000, Sebastian Ene wrote:
> > > > Remove the FFA_NOTIFICATION* calls from the blocklist used by the pKVM
> > > > FF-A proxy. This restriction was preventing the use of asynchronous
> > > > signaling mechanisms defined by the Arm FF-A specification to
> > > > communicate with the secure services.
> > > > While these calls are markes as optional, there is no reason why the
> > > > hypervisor proxy would block them because:
> > > >
> > > > 1. Host is the Sole Non-Secure Endpoint: The Host operates as the
> > > > only Non-Secure VM ID (VM ID 0) recognized by the Secure World.
> > > > Because all forwarded notifications are inherently attributed to
> > > > the Host by the SPMC, there is no risk of VM ID spoofing
> > > > originating from the Normal World.
> > > >
> > > > 2. No Memory Pointers or Addresses: The FFA_NOTIFICATION_* ABIs
> > > > operate strictly via register-based parameters, passing only
> > > > VM IDs, VCPU IDs, flags, and bitmaps. Because these calls do
> > > > not contain memory addresses, offsets, or pointers, forwarding
> > > > them doesn't pose a risk of memory-based confused deputy attack
> > > > (e.g., tricking the SPMC into overwriting protected memory).
> > > >
> > > > While the pKVM proxy behaves as a relayer, it doesn't currently have its
> > > > own FF-A ID(only the host has the ID 0). The behavior of the setup
> > > > flow is covered by the spec in the: '10.9 Notification support without
> > > > a Hypervisor'.
> > >
> > > As it is only a relayer. Is it really important to check SBZ arguments and
> > > fields on behalf of Trustzone? It doesn't feel it brings any security. If the
> > > host passes broken arguments, I don't believe this puts pKVM at risk. Does it?
> >
> > I think the problem would be if an update to FF-A allocated some of the
> > currently SBZ bits to implement some functionality that we would want
> > to filter at EL2.
>
> I suppose that would bump the FF-A version and the proxy would reject it?
Maybe? I don't think they'd _have_ to bump the version number.
> If we really want to check for those arguments to be 0:
>
> * Shouldn't we extend this check to other FF-A invocations?
yes, that's what the diff was doing in the reply here:
https://lore.kernel.org/all/af3fW468-f1KXCrC@google.com/
but, as I said here:
https://lore.kernel.org/all/ahmxiFXXTupafbXw@willie-the-truck/
I don't particularly like the table-driven indirection (the checks
should just be inlined).
> * Do we really want to also look into the !SBZ arguments to verify what we can?
> (I'm thinking about the checks on flags)
For known arguments, we only need to verify things that can affect EL2.
I suspect we don't care about a bunch of it.
Will
^ permalink raw reply
* Re: [PATCH v2 0/7] KVM: arm64: Forward FFA_NOTIFICATION* calls to TrustZone
From: Vincent Donnefort @ 2026-06-10 12:15 UTC (permalink / raw)
To: Will Deacon
Cc: Sebastian Ene, catalin.marinas, maz, oupton, joey.gouly, korneld,
kvmarm, linux-arm-kernel, linux-kernel, android-kvm,
mrigendra.chaubey, perlarsen, suzuki.poulose, yuzenghui
In-Reply-To: <aik5MtvOlnQDmzjr@willie-the-truck>
On Wed, Jun 10, 2026 at 11:15:14AM +0100, Will Deacon wrote:
> On Wed, Jun 10, 2026 at 10:26:59AM +0100, Vincent Donnefort wrote:
> > On Mon, Jun 08, 2026 at 04:55:42PM +0000, Sebastian Ene wrote:
> > > Remove the FFA_NOTIFICATION* calls from the blocklist used by the pKVM
> > > FF-A proxy. This restriction was preventing the use of asynchronous
> > > signaling mechanisms defined by the Arm FF-A specification to
> > > communicate with the secure services.
> > > While these calls are markes as optional, there is no reason why the
> > > hypervisor proxy would block them because:
> > >
> > > 1. Host is the Sole Non-Secure Endpoint: The Host operates as the
> > > only Non-Secure VM ID (VM ID 0) recognized by the Secure World.
> > > Because all forwarded notifications are inherently attributed to
> > > the Host by the SPMC, there is no risk of VM ID spoofing
> > > originating from the Normal World.
> > >
> > > 2. No Memory Pointers or Addresses: The FFA_NOTIFICATION_* ABIs
> > > operate strictly via register-based parameters, passing only
> > > VM IDs, VCPU IDs, flags, and bitmaps. Because these calls do
> > > not contain memory addresses, offsets, or pointers, forwarding
> > > them doesn't pose a risk of memory-based confused deputy attack
> > > (e.g., tricking the SPMC into overwriting protected memory).
> > >
> > > While the pKVM proxy behaves as a relayer, it doesn't currently have its
> > > own FF-A ID(only the host has the ID 0). The behavior of the setup
> > > flow is covered by the spec in the: '10.9 Notification support without
> > > a Hypervisor'.
> >
> > As it is only a relayer. Is it really important to check SBZ arguments and
> > fields on behalf of Trustzone? It doesn't feel it brings any security. If the
> > host passes broken arguments, I don't believe this puts pKVM at risk. Does it?
>
> I think the problem would be if an update to FF-A allocated some of the
> currently SBZ bits to implement some functionality that we would want
> to filter at EL2.
I suppose that would bump the FF-A version and the proxy would reject it?
If we really want to check for those arguments to be 0:
* Shouldn't we extend this check to other FF-A invocations?
* Do we really want to also look into the !SBZ arguments to verify what we can?
(I'm thinking about the checks on flags)
>
> Will
^ permalink raw reply
* Re: [PATCH v1] arm64: errata: Mitigate TLBI errata on NVIDIA Olympus CPU
From: Will Deacon @ 2026-06-10 12:14 UTC (permalink / raw)
To: Catalin Marinas, linux-arm-kernel, Mark Rutland,
Shanker Donthineni
Cc: kernel-team, Will Deacon, linux-kernel, linux-doc, Vikram Sethi,
Jason Sequeira, Alok Mooley, Rich Wiley
In-Reply-To: <20260609234044.3945938-1-sdonthineni@nvidia.com>
On Tue, 09 Jun 2026 18:40:44 -0500, Shanker Donthineni wrote:
> NVIDIA Olympus cores are affected by the TLBI completion issue tracked as
> CVE-2025-10263. The existing ARM64_ERRATUM_4118414 handling already uses
> ARM64_WORKAROUND_REPEAT_TLBI to issue an additional broadcast TLBI;DSB
> sequence and ensure affected memory write effects are globally observed.
>
> Add MIDR_NVIDIA_OLYMPUS to the repeat-TLBI match list so the same
> mitigation is enabled on affected Olympus systems. Also document the
> NVIDIA Olympus erratum in the arm64 silicon errata table and list it in
> the Kconfig help text.
>
> [...]
Applied to arm64 (for-next/errata), thanks!
[1/1] arm64: errata: Mitigate TLBI errata on NVIDIA Olympus CPU
https://git.kernel.org/arm64/c/ec7216f92e4e
Cheers,
--
Will
https://fixes.arm64.dev
https://next.arm64.dev
https://will.arm64.dev
^ permalink raw reply
* Re: [PATCH 0/3] arm64: errata: Mitigate TLBI errata on various Arm CPUs
From: Will Deacon @ 2026-06-10 12:14 UTC (permalink / raw)
To: linux-arm-kernel, Mark Rutland
Cc: catalin.marinas, kernel-team, Will Deacon, easwar.hariharan
In-Reply-To: <20260609101203.1512409-1-mark.rutland@arm.com>
On Tue, 09 Jun 2026 11:12:00 +0100, Mark Rutland wrote:
> A number of CPUs developed by Arm suffer from errata whereby a broadcast
> TLBI;DSB sequence may complete before the global observation of writes
> which are translated by an affected TLB entry.
>
> The ARM64_WORKAROUND_REPEAT_TLBI workaround is sufficient to mitigate
> the issue. This series enables the workaround on affected parts,
> requiring the addition of MIDR values for C1-Ultra and C1-Premium.
>
> [...]
Applied to arm64 (for-next/errata), thanks!
[1/3] arm64: cputype: Add C1-Ultra definitions
https://git.kernel.org/arm64/c/60349e64a6c6
[2/3] arm64: cputype: Add C1-Premium definitions
https://git.kernel.org/arm64/c/d28413bfc5a2
[3/3] arm64: errata: Mitigate TLBI errata on various Arm CPUs
https://git.kernel.org/arm64/c/cfd391e74134
I also pushed a patch on top to enable the workaround for Microsoft
Azure Cobalt 100 CPUs, as fb091ff39479 claims that is bug-compatible
with N2 r0p0 (+Easwar in case I got the erratum number wrong in the
documentation).
Cheers,
--
Will
https://fixes.arm64.dev
https://next.arm64.dev
https://will.arm64.dev
^ permalink raw reply
* [PATCH v2] usb: gadget: aspeed_udc: check endpoint DMA allocation
From: Ruoyu Wang @ 2026-06-10 12:10 UTC (permalink / raw)
To: Neal Liu, Greg Kroah-Hartman
Cc: Joel Stanley, Andrew Jeffery, linux-aspeed, linux-usb,
linux-arm-kernel, linux-kernel, Ruoyu Wang
In-Reply-To: <20260608081948.3-1-ruoyuw560@gmail.com>
ast_udc_probe() allocates a coherent DMA buffer used as the backing store
for endpoint buffers. ast_udc_init_ep() derives per-endpoint buffer
pointers from udc->ep0_buf, so a failed allocation is dereferenced during
probe.
Check the allocation before endpoint setup. The existing probe error path
called ast_udc_remove(), which unregisters the gadget unconditionally and
is not safe before usb_add_gadget_udc() succeeds. Add a local cleanup
helper for probe failures so pre-registration failures only unwind the
resources that were actually initialized.
This was found by a local static analysis checker for unchecked allocator
returns while scanning Linux 6.16. The change was checked by applying it
to current mainline and by running checkpatch. I do not have access to
Aspeed UDC hardware, so no runtime testing was performed.
Fixes: 055276c13205 ("usb: gadget: add Aspeed ast2600 udc driver")
Signed-off-by: Ruoyu Wang <ruoyuw560@gmail.com>
---
Note: a 2022 patch attempted to add only a NULL check for this
allocation:
https://lore.kernel.org/all/20221213025120.23149-1-jiasheng@iscas.ac.cn/
This version also fixes the probe unwind path so the clock is disabled
on allocation failure and usb_del_gadget_udc() is not called before the
gadget has been registered.
v1:
https://lore.kernel.org/all/20260608081948.3-1-ruoyuw560@gmail.com/
Changes in v2:
- Simplify the allocation-failure cleanup path as suggested by Andrew
Jeffery: disable the clock in the allocation-failure branch and let
err_cleanup fall through to err.
diff --git a/drivers/usb/gadget/udc/aspeed_udc.c b/drivers/usb/gadget/udc/aspeed_udc.c
--- a/drivers/usb/gadget/udc/aspeed_udc.c
+++ b/drivers/usb/gadget/udc/aspeed_udc.c
@@ -1434,25 +1434,12 @@ static void ast_udc_init_hw(struct ast_u
ast_udc_write(udc, 0, AST_UDC_EP0_CTRL);
}
-static void ast_udc_remove(struct platform_device *pdev)
+static void ast_udc_cleanup(struct platform_device *pdev)
{
struct ast_udc_dev *udc = platform_get_drvdata(pdev);
unsigned long flags;
u32 ctrl;
- usb_del_gadget_udc(&udc->gadget);
- if (udc->driver) {
- /*
- * This is broken as only some cleanup is skipped, *udev is
- * freed and the register mapping goes away. Any further usage
- * probably crashes. Also the device is unbound, so the skipped
- * cleanup is never catched up later.
- */
- dev_alert(&pdev->dev,
- "Driver is busy and still going away. Fasten your seat belts!\n");
- return;
- }
-
spin_lock_irqsave(&udc->lock, flags);
/* Disable upstream port connection */
@@ -1472,6 +1459,26 @@ static void ast_udc_remove(struct platfo
udc->ep0_buf = NULL;
}
+static void ast_udc_remove(struct platform_device *pdev)
+{
+ struct ast_udc_dev *udc = platform_get_drvdata(pdev);
+
+ usb_del_gadget_udc(&udc->gadget);
+ if (udc->driver) {
+ /*
+ * This is broken as only some cleanup is skipped, *udev is
+ * freed and the register mapping goes away. Any further usage
+ * probably crashes. Also the device is unbound, so the skipped
+ * cleanup is never catched up later.
+ */
+ dev_alert(&pdev->dev,
+ "Driver is busy and still going away. Fasten your seat belts!\n");
+ return;
+ }
+
+ ast_udc_cleanup(pdev);
+}
+
static int ast_udc_probe(struct platform_device *pdev)
{
enum usb_device_speed max_speed;
@@ -1524,6 +1531,12 @@ static int ast_udc_probe(struct platform
AST_UDC_NUM_ENDPOINTS,
&udc->ep0_buf_dma, GFP_KERNEL);
+ if (!udc->ep0_buf) {
+ clk_disable_unprepare(udc->clk);
+ rc = -ENOMEM;
+ goto err;
+ }
+
udc->gadget.speed = USB_SPEED_UNKNOWN;
udc->gadget.max_speed = USB_SPEED_HIGH;
udc->creq = udc->reg + AST_UDC_SETUP0;
@@ -1553,20 +1566,20 @@ static int ast_udc_probe(struct platform
udc->irq = platform_get_irq(pdev, 0);
if (udc->irq < 0) {
rc = udc->irq;
- goto err;
+ goto err_cleanup;
}
rc = devm_request_irq(&pdev->dev, udc->irq, ast_udc_isr, 0,
KBUILD_MODNAME, udc);
if (rc) {
dev_err(&pdev->dev, "Failed to request interrupt\n");
- goto err;
+ goto err_cleanup;
}
rc = usb_add_gadget_udc(&pdev->dev, &udc->gadget);
if (rc) {
dev_err(&pdev->dev, "Failed to add gadget udc\n");
- goto err;
+ goto err_cleanup;
}
dev_info(&pdev->dev, "Initialized udc in USB%s mode\n",
@@ -1574,9 +1587,10 @@ static int ast_udc_probe(struct platform
return 0;
+err_cleanup:
+ ast_udc_cleanup(pdev);
err:
dev_err(&pdev->dev, "Failed to udc probe, rc:0x%x\n", rc);
- ast_udc_remove(pdev);
return rc;
}
^ permalink raw reply
* Re: [PATCH v2 1/7] KVM: arm64: Support FFA_NOTIFICATION_BITMAP_CREATE in host handler
From: Vincent Donnefort @ 2026-06-10 11:59 UTC (permalink / raw)
To: Sebastian Ene
Cc: catalin.marinas, maz, oupton, will, joey.gouly, korneld, kvmarm,
linux-arm-kernel, linux-kernel, android-kvm, mrigendra.chaubey,
perlarsen, suzuki.poulose, yuzenghui
In-Reply-To: <aiklq5QvztNk8FZR@google.com>
On Wed, Jun 10, 2026 at 09:51:55AM +0100, Vincent Donnefort wrote:
> Hi Seb,
>
> On Mon, Jun 08, 2026 at 04:55:43PM +0000, Sebastian Ene wrote:
> > Allow FF-A notification bitmap creation messages to be forwarded to
> > Trustzone from the host and introduce a helper to check for SBZ
> > register fields.
> >
> > Signed-off-by: Sebastian Ene <sebastianene@google.com>
> > ---
> > arch/arm64/kvm/hyp/nvhe/ffa.c | 36 ++++++++++++++++++++++++++++++++++-
> > 1 file changed, 35 insertions(+), 1 deletion(-)
> >
> > diff --git a/arch/arm64/kvm/hyp/nvhe/ffa.c b/arch/arm64/kvm/hyp/nvhe/ffa.c
> > index 1af722771178..c20d45191085 100644
> > --- a/arch/arm64/kvm/hyp/nvhe/ffa.c
> > +++ b/arch/arm64/kvm/hyp/nvhe/ffa.c
> > @@ -71,6 +71,18 @@ static u32 hyp_ffa_version;
> > static bool has_version_negotiated;
> > static hyp_spinlock_t version_lock;
> >
> > +static bool ffa_check_unused_args_sbz(struct kvm_cpu_context *ctxt, int first_reg)
> > +{
> > + int reg;
> > +
> > + for (reg = first_reg; reg < 17; reg++) {
>
> The upper limit should probably be something like ARRAY_SIZE(ctx->regs.regs) - first_reg?
I wasn't really inspired this morning on the cruiser...
But nonetheless, that 17 should probably be a #define somewhere?
>
> > + if (cpu_reg(ctxt, reg))
> > + return true;
> > + }
> > +
> > + return false;
> > +}
> > +
> > static void ffa_to_smccc_error(struct arm_smccc_1_2_regs *res, u64 ffa_errno)
> > {
> > *res = (struct arm_smccc_1_2_regs) {
> > @@ -676,7 +688,6 @@ static bool ffa_call_supported(u64 func_id)
> > case FFA_MEM_DONATE:
> > case FFA_MEM_RETRIEVE_REQ:
> > /* Optional notification interfaces added in FF-A 1.1 */
> > - case FFA_NOTIFICATION_BITMAP_CREATE:
> > case FFA_NOTIFICATION_BITMAP_DESTROY:
> > case FFA_NOTIFICATION_BIND:
> > case FFA_NOTIFICATION_UNBIND:
> > @@ -862,6 +873,26 @@ static void do_ffa_part_get(struct arm_smccc_1_2_regs *res,
> > hyp_spin_unlock(&host_buffers.lock);
> > }
> >
> > +static void do_ffa_notif_bitmap_create(struct arm_smccc_1_2_regs *res,
> > + struct kvm_cpu_context *ctxt)
> > +{
> > + DECLARE_REG(u32, vmid, ctxt, 1);
> > + struct arm_smccc_1_2_regs *args;
> > +
> > + if (ffa_check_unused_args_sbz(ctxt, 3)) {
>
> Is that expected we start at 3 but only read 0 and 1?
Ha, we do not read 2 but nonetheless it is useful!
>
> > + ffa_to_smccc_res(res, FFA_RET_INVALID_PARAMETERS);
> > + return;
> > + }
> > +
> > + if (vmid != HOST_FFA_ID) {
> > + ffa_to_smccc_res(res, FFA_RET_INVALID_PARAMETERS);
> > + return;
> > + }
> > +
> > + args = (void *)&ctxt->regs.regs[0];
> > + arm_smccc_1_2_smc(args, res);
>
> Should be hyp_smccc_1_2_smc()
>
> > +}
> > +
> > bool kvm_host_ffa_handler(struct kvm_cpu_context *host_ctxt, u32 func_id)
> > {
> > struct arm_smccc_1_2_regs res;
> > @@ -920,6 +951,9 @@ bool kvm_host_ffa_handler(struct kvm_cpu_context *host_ctxt, u32 func_id)
> > case FFA_PARTITION_INFO_GET:
> > do_ffa_part_get(&res, host_ctxt);
> > goto out_handled;
> > + case FFA_NOTIFICATION_BITMAP_CREATE:
> > + do_ffa_notif_bitmap_create(&res, host_ctxt);
> > + goto out_handled;
> > }
> >
> > if (ffa_call_supported(func_id))
> > --
> > 2.54.0.1064.gd145956f57-goog
> >
^ permalink raw reply
* iio: adc: KASAN wild-memory-access in complete() on early IRQ
From: Jaeyoung Chung @ 2026-06-10 11:57 UTC (permalink / raw)
To: Jonathan Cameron, David Lechner, Nuno Sá, Andy Shevchenko,
Vladimir Zapolskiy, Piotr Wojtaszczyk
Cc: Jaeyoung Chung, linux-iio, linux-arm-kernel, linux-kernel,
Sangyun Kim, Kyungwook Boo
Hi,
lpc32xx_adc_probe() in drivers/iio/adc/lpc32xx_adc.c and
spear_adc_probe() in drivers/iio/adc/spear_adc.c register their
interrupt handler with devm_request_irq() before they initialize
st->completion with init_completion(). If an interrupt arrives after
devm_request_irq() and before init_completion(), the handler calls
complete() on an uninitialized completion, causing a kernel panic.
The probe path, in lpc32xx_adc_probe():
iodev = devm_iio_device_alloc(&pdev->dev, sizeof(*st)); /* st kzalloc-zeroed */
...
retval = devm_request_irq(&pdev->dev, irq, lpc32xx_adc_isr, 0,
LPC32XXAD_NAME, st); /* register handler */
...
init_completion(&st->completion); /* initialize completion */
spear_adc_probe() has the same ordering: devm_request_irq() for
spear_adc_isr() before init_completion(&st->completion).
Both interrupt handlers, lpc32xx_adc_isr() and spear_adc_isr(), call
complete():
complete(&st->completion);
If the device raises an interrupt before init_completion() runs,
complete() acquires the uninitialized wait.lock and walks the zeroed
task_list in swake_up_locked(). The zeroed task_list makes list_empty()
return false, so swake_up_locked() dereferences a NULL list entry,
triggering a KASAN wild-memory-access.
Suggested fix: move init_completion(&st->completion) above
devm_request_irq(), so the completion is valid before the handler can run.
Reported-by: Sangyun Kim <sangyun.kim@snu.ac.kr>
Reported-by: Kyungwook Boo <bookyungwook@gmail.com>
Thanks,
Jaeyoung Chung
^ permalink raw reply
* spi: uniphier: KASAN wild-memory-access in complete() on early IRQ
From: Jaeyoung Chung @ 2026-06-10 11:56 UTC (permalink / raw)
To: Mark Brown, Kunihiko Hayashi, Masami Hiramatsu
Cc: Jaeyoung Chung, linux-spi, linux-arm-kernel, linux-kernel,
Sangyun Kim, Kyungwook Boo
Hi,
uniphier_spi_probe() in drivers/spi/spi-uniphier.c registers the
interrupt handler uniphier_spi_handler() with devm_request_irq() before
it initializes priv->xfer_done with init_completion(). If an interrupt
arrives after devm_request_irq() and before init_completion(), the
handler calls complete() on an uninitialized completion, causing a
kernel panic.
The probe path, in uniphier_spi_probe():
host = spi_alloc_host(&pdev->dev, sizeof(*priv)); /* priv kzalloc-zeroed */
...
ret = devm_request_irq(&pdev->dev, irq, uniphier_spi_handler,
0, "uniphier-spi", priv); /* register handler */
...
init_completion(&priv->xfer_done); /* initialize completion */
The interrupt handler uniphier_spi_handler() calls complete() on its
done path:
done:
complete(&priv->xfer_done);
If the device raises an interrupt before init_completion() runs,
complete() acquires the uninitialized wait.lock and walks the zeroed
task_list in swake_up_locked(). The zeroed task_list makes list_empty()
return false, so swake_up_locked() dereferences a NULL list entry,
triggering a KASAN wild-memory-access.
Suggested fix: move init_completion(&priv->xfer_done) above
devm_request_irq(), so the completion is valid before the handler can run.
Reported-by: Sangyun Kim <sangyun.kim@snu.ac.kr>
Reported-by: Kyungwook Boo <bookyungwook@gmail.com>
Thanks,
Jaeyoung Chung
^ permalink raw reply
* Re: [PATCH v17 21/28] drm/tests: bridge: Add KUnit tests for bridge chain format selection
From: Jani Nikula @ 2026-06-10 11:54 UTC (permalink / raw)
To: Nicolas Frattaroli, Harry Wentland, Leo Li, Rodrigo Siqueira,
Alex Deucher, Christian König, David Airlie, Simona Vetter,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Sandy Huang, Heiko Stübner,
Andy Yan, Rodrigo Vivi, Joonas Lahtinen, Tvrtko Ursulin,
Dmitry Baryshkov, Sascha Hauer, Rob Herring, Jonathan Corbet,
Shuah Khan, Daniel Stone
Cc: kernel, amd-gfx, dri-devel, linux-kernel, linux-arm-kernel,
linux-rockchip, intel-gfx, intel-xe, linux-doc, wayland-devel
In-Reply-To: <gnicb4WkT1S4aQIC2G_naw@collabora.com>
On Wed, 10 Jun 2026, Nicolas Frattaroli <nicolas.frattaroli@collabora.com> wrote:
> If you don't want __maybe_unused, then sure, I'll move them into a new
> .c file. Though I think the two are roughly equivalent in that I don't
> think anyone is really trying to minimise the size of their KUnit
> binaries.
I think placing arrays in headers is bad practice, and we shouldn't set
that example, kunit or not.
> I'll send a patch to move them to a .c
Thanks.
BR,
Jani.
--
Jani Nikula, Intel
^ permalink raw reply
* Re: [PATCH] arm64: dts: lx2160a-rev2: avoid 32-bit pcie window system ram overlap
From: Arnd Bergmann @ 2026-06-10 11:51 UTC (permalink / raw)
To: Josua Mayer, Frank Li, Rob Herring, Krzysztof Kozlowski,
Conor Dooley
Cc: linux-arm-kernel, devicetree, linux-kernel
In-Reply-To: <20260610-lx2160-pcie-fix-ranges-32bit-v1-1-98086fc5fb6b@solid-run.com>
On Wed, Jun 10, 2026, at 13:45, Josua Mayer wrote:
> A 3GB non-prefetchable PCIe bus window can overlap with inbound DMA
> addresses for low system RAM, so DMA transactions may be routed to a BAR
> on the same host bridge instead of memory.
>
> Change the 32-bit non-prefetchable PCIe window back from 3GB to 1GB on all
> controllers, avoiding that overlap while keeping the added 64-bit
> prefetchable region.
>
> This partially reverts commit 9ed301397090 ("arm64: dts: lx2160a-rev2:
> extend 32-bit and add 64-bit pci regions").
>
> Fixes: 9ed301397090 ("arm64: dts: lx2160a-rev2: extend 32-bit and add
> 64-bit pci regions")
> Reported-by: Arnd Bergmann <arnd@arndb.de>
> Closes:
> https://lore.kernel.org/r/9e6326f6-dad1-4169-a63c-e62ee5b341f2@app.fastmail.com
> Signed-off-by: Josua Mayer <josua@solid-run.com>
Looks good to me, thanks for the fix!
Acked-by: Arnd Bergmann <arnd@arndb.de>
^ permalink raw reply
* Re: [PATCH 1/3] dt-bindings: serial: Add binding for Cortina-Access UART
From: Krzysztof Kozlowski @ 2026-06-10 11:51 UTC (permalink / raw)
To: Jason Li, jason.li, Greg Kroah-Hartman, Jiri Slaby
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Catalin Marinas,
Will Deacon, Arnd Bergmann, linux-serial, linux-arm-kernel,
devicetree, linux-kernel
In-Reply-To: <20260610112821.3030099-3-jason.li@cortina-access.com>
On 10/06/2026 13:28, Jason Li wrote:
> +
> +allOf:
> + - $ref: serial.yaml#
> +
> +properties:
> + compatible:
> + const: cortina-access,serial
Aren't writing bindings very clear about that? Please, take your time to
read through the docs, so we will not need to repeat basic guidance. It
is documented there on purpose.
Best regards,
Krzysztof
^ permalink raw reply
* Re: [PATCH 3/3] arm64: dts: cortina-access: Add DTS for CA8289 SoC and Venus board
From: Krzysztof Kozlowski @ 2026-06-10 11:49 UTC (permalink / raw)
To: Jason Li, jason.li, Greg Kroah-Hartman, Jiri Slaby
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Catalin Marinas,
Will Deacon, Arnd Bergmann, linux-serial, linux-arm-kernel,
devicetree, linux-kernel
In-Reply-To: <20260610112821.3030099-5-jason.li@cortina-access.com>
On 10/06/2026 13:28, Jason Li wrote:
> Add SoC DTSI for the Cortina-Access CA8289 (Venus) and a board DTS for
> the Venus engineering board. The description covers the minimum set of
> hardware nodes needed to boot a kernel with an INITRD rootfs: CPUs,
> GIC, timer, PSCI, fixed clock and UART.
>
> Signed-off-by: Jason Li <jason.li@cortina-access.com>
> Assisted-by: Claude:claude-opus-4-8
SoB should be the last tag.
Also, it does not match From field.
> ---
> MAINTAINERS | 1 +
> arch/arm64/Kconfig.platforms | 10 ++
> arch/arm64/boot/dts/Makefile | 1 +
> arch/arm64/boot/dts/cortina-access/Makefile | 2 +
> .../dts/cortina-access/ca8289-engboard.dts | 31 +++++
> .../boot/dts/cortina-access/ca8289-soc.dtsi | 118 ++++++++++++++++++
> 6 files changed, 163 insertions(+)
> create mode 100644 arch/arm64/boot/dts/cortina-access/Makefile
> create mode 100644 arch/arm64/boot/dts/cortina-access/ca8289-engboard.dts
> create mode 100644 arch/arm64/boot/dts/cortina-access/ca8289-soc.dtsi
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 515d89d96472..ebfdb9c267cc 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -2826,6 +2826,7 @@ L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
> S: Maintained
> F: Documentation/devicetree/bindings/arm/cortina-access.yaml
> F: Documentation/devicetree/bindings/serial/cortina-access,serial.yaml
> +F: arch/arm64/boot/dts/cortina-access/
>
> ARM/CORTINA SYSTEMS GEMINI ARM ARCHITECTURE
> M: Hans Ulli Kroll <ulli.kroll@googlemail.com>
> diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms
> index dc995a732117..ba6dda0660c3 100644
> --- a/arch/arm64/Kconfig.platforms
> +++ b/arch/arm64/Kconfig.platforms
> @@ -134,6 +134,16 @@ config ARCH_CIX
> This enables support for the Cixtech SoC family,
> like P1(sky1).
>
> +config ARCH_CORTINA_ACCESS
> + bool "Cortina-Access SoC Family"
> + select GPIOLIB
> + select PINCTRL
> + help
> + This enables support for Cortina-Access SoCs. The family
> + includes ARMv8-based devices targeting networking and access
> + applications.
> + If you have a Cortina-Access board, say Y here.
> +
> config ARCH_EXYNOS
> bool "Samsung Exynos SoC family"
> select COMMON_CLK_SAMSUNG
> diff --git a/arch/arm64/boot/dts/Makefile b/arch/arm64/boot/dts/Makefile
> index 98ec8f1b76e4..a599f525fb9a 100644
> --- a/arch/arm64/boot/dts/Makefile
> +++ b/arch/arm64/boot/dts/Makefile
> @@ -16,6 +16,7 @@ subdir-y += broadcom
> subdir-y += bst
> subdir-y += cavium
> subdir-y += cix
> +subdir-y += cortina-access
> subdir-y += exynos
> subdir-y += freescale
> subdir-y += hisilicon
> diff --git a/arch/arm64/boot/dts/cortina-access/Makefile b/arch/arm64/boot/dts/cortina-access/Makefile
> new file mode 100644
> index 000000000000..554893f381fe
> --- /dev/null
> +++ b/arch/arm64/boot/dts/cortina-access/Makefile
> @@ -0,0 +1,2 @@
> +# SPDX-License-Identifier: GPL-2.0
> +dtb-$(CONFIG_ARCH_CORTINA_ACCESS) += ca8289-engboard.dtb
> diff --git a/arch/arm64/boot/dts/cortina-access/ca8289-engboard.dts b/arch/arm64/boot/dts/cortina-access/ca8289-engboard.dts
> new file mode 100644
> index 000000000000..c8289a0f8269
> --- /dev/null
> +++ b/arch/arm64/boot/dts/cortina-access/ca8289-engboard.dts
> @@ -0,0 +1,31 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * dts file for Cortina Access Venus Engineering Board
> + *
> + * Copyright (C) 2026, Cortina Access Inc.
> + *
> + */
> +
> +/dts-v1/;
> +
> +#include "ca8289-soc.dtsi"
> +
> +/ {
> + model = "Cortina Access Venus Engineering Board";
> + compatible = "cortina-access,ca8289-engboard";
> + #address-cells = <2>;
> + #size-cells = <2>;
> +
> + aliases {
> + serial0 = &uart0;
> + };
> +
> + chosen {
> + stdout-path = "serial0:115200n8";
> + };
> +
> + memory@0 { /* 512MB */
> + device_type = "memory";
> + reg = <0x00000000 0x00000000 0x0 0x20000000>;
> + };
> +};
> diff --git a/arch/arm64/boot/dts/cortina-access/ca8289-soc.dtsi b/arch/arm64/boot/dts/cortina-access/ca8289-soc.dtsi
> new file mode 100644
> index 000000000000..8e7ffcf4ccab
> --- /dev/null
> +++ b/arch/arm64/boot/dts/cortina-access/ca8289-soc.dtsi
> @@ -0,0 +1,118 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * dts file for Cortina Access CA8289 SoC
> + *
> + * Copyright (C) 2026, Cortina Access Inc.
> + */
> +
> +#include <dt-bindings/interrupt-controller/arm-gic.h>
> +#include <dt-bindings/interrupt-controller/irq.h>
> +
> +/ {
> + cpus {
> + #address-cells = <2>;
> + #size-cells = <0>;
> +
> + cpu0: cpu@0 {
> + compatible = "arm,cortex-a55", "arm,armv8";
> + device_type = "cpu";
> + reg = <0x0 0x0>;
> + enable-method = "psci";
> + };
Missing blank lines. Look at existing code how this is supposed to look
like.
> + cpu1: cpu@100 {
> + compatible = "arm,cortex-a55", "arm,armv8";
> + device_type = "cpu";
> + reg = <0x0 0x100>;
> + enable-method = "psci";
> + };
> + cpu2: cpu@200 {
> + compatible = "arm,cortex-a55", "arm,armv8";
> + device_type = "cpu";
> + reg = <0x0 0x200>;
> + enable-method = "psci";
> + };
> + cpu3: cpu@300 {
> + compatible = "arm,cortex-a55", "arm,armv8";
> + device_type = "cpu";
> + reg = <0x0 0x300>;
> + enable-method = "psci";
> + };
> + cpu-map {
> + cluster0 {
> + core0 {
> + cpu = <&cpu0>;
> + };
> + core1 {
> + cpu = <&cpu1>;
> + };
> + core2 {
> + cpu = <&cpu2>;
> + };
> + core3 {
> + cpu = <&cpu3>;
> + };
> + };
> + };
> + };
> +
> + psci {
> + compatible = "arm,psci-0.2";
> + method = "smc";
> + };
> +
> + gic: interrupt-controller@4f8000000 {
And now you repeat basic mistakes:
1. Pointed out by W=1 dtbs_check build
2. Fixed long time in every source
3. Explicitly documented in writing bindings and DTS coding style
> + compatible = "arm,gic-v3";
> + #interrupt-cells = <3>;
> + interrupt-controller;
> + #redistributor-regions = <1>;
> + reg = <0x00000004 0xF8000000 0 0x10000>,
> + <0x00000004 0xF8040000 0 0x80000>;
Read DTS coding style.
> + };
> +
> + apb_pclk: apb-pclk {
Nope, drop entire node.
> + compatible = "fixed-clock";
> + #clock-cells = <0>;
> + clock-frequency = <125000000>;
> + };
> +
> + reserved-memory {
> + #address-cells = <2>;
> + #size-cells = <2>;
> + ranges;
> +
> + /* TrustZone reserved region; must not be mapped by the kernel */
> + tz_pool: tz-buffer@f000000 {
> + reg = <0x0 0x0F000000 0x0 0x1000000>;
> + no-map;
> + };
> + };
> +
> + /* See Documentation/devicetree/bindings/timer/arm,arch_timer.yaml */
> + timer {
> + compatible = "arm,armv8-timer";
> + interrupt-parent = <&gic>;
> + interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_LOW>,
> + <GIC_PPI 14 IRQ_TYPE_LEVEL_LOW>,
> + <GIC_PPI 11 IRQ_TYPE_LEVEL_LOW>,
> + <GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>;
> + clock-frequency = <25000000>;
> + };
> +
> + uart0: serial@f4329188 {
> + device_type = "serial";
> + compatible = "cortina-access,serial";
> + reg = <0x00000000 0xf4329188 0x0 0x30>;
This is AI slop. Whatever Claude convinced you to do, it is nothing like
upstream kernel source.
Best regards,
Krzysztof
^ permalink raw reply
* Re: [PATCH 1/3] dt-bindings: serial: Add binding for Cortina-Access UART
From: Krzysztof Kozlowski @ 2026-06-10 11:46 UTC (permalink / raw)
To: Jason Li, jason.li, Greg Kroah-Hartman, Jiri Slaby
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Catalin Marinas,
Will Deacon, Arnd Bergmann, linux-serial, linux-arm-kernel,
devicetree, linux-kernel
In-Reply-To: <20260610112821.3030099-3-jason.li@cortina-access.com>
On 10/06/2026 13:28, Jason Li wrote:
> Add DT binding schema for the Cortina-Access UART controller.
> This IP is integrated into most CAXXXX SoC family members.
>
> Also add the vendor prefix for Cortina Access, Inc. and the
> top-level ARM board binding document for the CA8289 (Venus) SoC.
>
> Signed-off-by: Jason Li <jason.li@cortina-access.com>
> Assisted-by: Claude:claude-opus-4-8
> ---
> .../bindings/arm/cortina-access.yaml | 29 ++++++++++++
> .../serial/cortina-access,serial.yaml | 46 +++++++++++++++++++
> .../devicetree/bindings/vendor-prefixes.yaml | 2 +
> MAINTAINERS | 7 +++
This is somehow complete mess. serial and arm together?
Please carefully read submitting patches (both documents!) and don't
send AI-assisted slop.
You must not combine independent works together.
> 4 files changed, 84 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/arm/cortina-access.yaml
> create mode 100644 Documentation/devicetree/bindings/serial/cortina-access,serial.yaml
>
> diff --git a/Documentation/devicetree/bindings/arm/cortina-access.yaml b/Documentation/devicetree/bindings/arm/cortina-access.yaml
> new file mode 100644
> index 000000000000..ec0320ed0c0b
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/arm/cortina-access.yaml
> @@ -0,0 +1,29 @@
> +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/arm/cortina-access.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Cortina-Access SoC boards
> +
> +maintainers:
> + - Jason Li <jason.li@cortina-access.com>
> +
> +description:
> + Boards based on Cortina-Access ARMv8 SoCs targeting networking and
> + access applications.
> +
> +properties:
> + $nodename:
> + const: /
> + compatible:
> + oneOf:
> + - description: Cortina-Access CA8289 (Venus) engineering board
> + const: cortina-access,ca8289-engboard
> +
> + - description: Cortina-Access CA8289 (Venus) reference board
> + const: cortina-access,ca8289-refboard
Where is the SoC? This looks like very poor contribution. If you opened
any existing recent board binding you would see it is done differently.
Best regards,
Krzysztof
^ permalink raw reply
* [PATCH] arm64: dts: lx2160a-rev2: avoid 32-bit pcie window system ram overlap
From: Josua Mayer @ 2026-06-10 11:45 UTC (permalink / raw)
To: Frank Li, Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: linux-arm-kernel, devicetree, linux-kernel, Arnd Bergmann,
Josua Mayer
A 3GB non-prefetchable PCIe bus window can overlap with inbound DMA
addresses for low system RAM, so DMA transactions may be routed to a BAR
on the same host bridge instead of memory.
Change the 32-bit non-prefetchable PCIe window back from 3GB to 1GB on all
controllers, avoiding that overlap while keeping the added 64-bit
prefetchable region.
This partially reverts commit 9ed301397090 ("arm64: dts: lx2160a-rev2:
extend 32-bit and add 64-bit pci regions").
Fixes: 9ed301397090 ("arm64: dts: lx2160a-rev2: extend 32-bit and add 64-bit pci regions")
Reported-by: Arnd Bergmann <arnd@arndb.de>
Closes: https://lore.kernel.org/r/9e6326f6-dad1-4169-a63c-e62ee5b341f2@app.fastmail.com
Signed-off-by: Josua Mayer <josua@solid-run.com>
---
arch/arm64/boot/dts/freescale/fsl-lx2160a-rev2.dtsi | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/arch/arm64/boot/dts/freescale/fsl-lx2160a-rev2.dtsi b/arch/arm64/boot/dts/freescale/fsl-lx2160a-rev2.dtsi
index 3570399f9b21c..3d2637fee2d35 100644
--- a/arch/arm64/boot/dts/freescale/fsl-lx2160a-rev2.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-lx2160a-rev2.dtsi
@@ -17,7 +17,7 @@ &pcie1 {
ranges = /* 16-Bit IO Window */
<0x81000000 0x00 0x00000000 0x80 0x00010000 0x00 0x00010000>,
/* 32-Bit - non-prefetchable */
- <0x82000000 0x00 0x40000000 0x80 0x40000000 0x00 0xc0000000>,
+ <0x82000000 0x00 0x40000000 0x80 0x40000000 0x00 0x40000000>,
/* 64-Bit - prefetchable - 16GB */
<0xC3000000 0x84 0x00000000 0x84 0x00000000 0x04 0x00000000>;
@@ -37,7 +37,7 @@ &pcie2 {
ranges = /* 16-Bit IO Window */
<0x81000000 0x00 0x00000000 0x88 0x00010000 0x00 0x00010000>,
/* 32-Bit - non-prefetchable */
- <0x82000000 0x00 0x40000000 0x88 0x40000000 0x00 0xc0000000>,
+ <0x82000000 0x00 0x40000000 0x88 0x40000000 0x00 0x40000000>,
/* 64-Bit - prefetchable - 16GB */
<0xC3000000 0x8c 0x00000000 0x8c 0x00000000 0x04 0x00000000>;
@@ -57,7 +57,7 @@ &pcie3 {
ranges = /* 16-Bit IO Window */
<0x81000000 0x00 0x00000000 0x90 0x00010000 0x00 0x00010000>,
/* 32-Bit - non-prefetchable */
- <0x82000000 0x00 0x40000000 0x90 0x40000000 0x00 0xc0000000>,
+ <0x82000000 0x00 0x40000000 0x90 0x40000000 0x00 0x40000000>,
/* 64-Bit - prefetchable - 16GB */
<0xC3000000 0x94 0x00000000 0x94 0x00000000 0x04 0x00000000>;
@@ -78,7 +78,7 @@ &pcie4 {
ranges = /* 16-Bit IO Window */
<0x81000000 0x00 0x00000000 0x98 0x00010000 0x00 0x00010000>,
/* 32-Bit - non-prefetchable */
- <0x82000000 0x00 0x40000000 0x98 0x40000000 0x00 0xc0000000>,
+ <0x82000000 0x00 0x40000000 0x98 0x40000000 0x00 0x40000000>,
/* 64-Bit - prefetchable - 16GB */
<0xC3000000 0x9c 0x00000000 0x9c 0x00000000 0x04 0x00000000>;
@@ -98,7 +98,7 @@ &pcie5 {
ranges = /* 16-Bit IO Window */
<0x81000000 0x00 0x00000000 0xa0 0x00010000 0x00 0x00010000>,
/* 32-Bit - non-prefetchable */
- <0x82000000 0x00 0x40000000 0xa0 0x40000000 0x00 0xc0000000>,
+ <0x82000000 0x00 0x40000000 0xa0 0x40000000 0x00 0x40000000>,
/* 64-Bit - prefetchable - 16GB */
<0xC3000000 0xa4 0x00000000 0xa4 0x00000000 0x04 0x00000000>;
@@ -118,7 +118,7 @@ &pcie6 {
ranges = /* 16-Bit IO Window */
<0x81000000 0x00 0x00000000 0xa8 0x00010000 0x00 0x00010000>,
/* 32-Bit - non-prefetchable */
- <0x82000000 0x00 0x40000000 0xa8 0x40000000 0x00 0xc0000000>,
+ <0x82000000 0x00 0x40000000 0xa8 0x40000000 0x00 0x40000000>,
/* 64-Bit - prefetchable - 16GB */
<0xC3000000 0xac 0x00000000 0xac 0x00000000 0x04 0x00000000>;
---
base-commit: c10cfc952215644956284a42fa7b7860dfbcb5f5
change-id: 20260610-lx2160-pcie-fix-ranges-32bit-0868570e495f
Best regards,
--
Josua Mayer <josua@solid-run.com>
^ permalink raw reply related
* Re: [PATCH] usb: gadget: aspeed_udc: check endpoint DMA allocation
From: Andrew Jeffery @ 2026-06-10 11:45 UTC (permalink / raw)
To: Ruoyu Wang, Neal Liu, Greg Kroah-Hartman
Cc: Joel Stanley, linux-aspeed, linux-usb, linux-arm-kernel,
linux-kernel
In-Reply-To: <20260608081948.3-1-ruoyuw560@gmail.com>
On Mon, 2026-06-08 at 16:19 +0800, Ruoyu Wang wrote:
> ast_udc_probe() allocates a coherent DMA buffer used as the backing store
> for endpoint buffers. ast_udc_init_ep() derives per-endpoint buffer
> pointers from udc->ep0_buf, so a failed allocation is dereferenced during
> probe.
>
> Check the allocation before endpoint setup. The existing probe error path
> called ast_udc_remove(), which unregisters the gadget unconditionally and
> is not safe before usb_add_gadget_udc() succeeds. Add a local cleanup
> helper for probe failures so pre-registration failures only unwind the
> resources that were actually initialized.
>
> This was found by a local static analysis checker for unchecked allocator
> returns while scanning Linux 6.16. The change was checked by applying it
> to current mainline and by running checkpatch. I do not have access to
> Aspeed UDC hardware, so no runtime testing was performed.
>
> Fixes: 055276c13205 ("usb: gadget: add Aspeed ast2600 udc driver")
> Signed-off-by: Ruoyu Wang <ruoyuw560@gmail.com>
> ---
> Note: a 2022 patch attempted to add only a NULL check for this
> allocation:
> https://lore.kernel.org/all/20221213025120.23149-1-jiasheng@iscas.ac.cn/
>
> This version also fixes the probe unwind path so the clock is disabled
> on allocation failure and usb_del_gadget_udc() is not called before the
> gadget has been registered.
>
> diff --git a/drivers/usb/gadget/udc/aspeed_udc.c b/drivers/usb/gadget/udc/aspeed_udc.c
> index 7fc6696b7..809a7d5b7 100644
> --- a/drivers/usb/gadget/udc/aspeed_udc.c
> +++ b/drivers/usb/gadget/udc/aspeed_udc.c
> @@ -1434,11 +1434,34 @@ static void ast_udc_init_hw(struct ast_udc_dev *udc)
> ast_udc_write(udc, 0, AST_UDC_EP0_CTRL);
> }
>
> +static void ast_udc_cleanup(struct platform_device *pdev)
> +{
> + struct ast_udc_dev *udc = platform_get_drvdata(pdev);
> + unsigned long flags;
> + u32 ctrl;
> +
> + spin_lock_irqsave(&udc->lock, flags);
> +
> + /* Disable upstream port connection */
> + ctrl = ast_udc_read(udc, AST_UDC_FUNC_CTRL) & ~USB_UPSTREAM_EN;
> + ast_udc_write(udc, ctrl, AST_UDC_FUNC_CTRL);
> +
> + clk_disable_unprepare(udc->clk);
> +
> + spin_unlock_irqrestore(&udc->lock, flags);
> +
> + if (udc->ep0_buf)
> + dma_free_coherent(&pdev->dev,
> + AST_UDC_EP_DMA_SIZE * AST_UDC_NUM_ENDPOINTS,
> + udc->ep0_buf,
> + udc->ep0_buf_dma);
> +
> + udc->ep0_buf = NULL;
> +}
> +
> static void ast_udc_remove(struct platform_device *pdev)
> {
> struct ast_udc_dev *udc = platform_get_drvdata(pdev);
> - unsigned long flags;
> - u32 ctrl;
>
> usb_del_gadget_udc(&udc->gadget);
> if (udc->driver) {
> @@ -1453,23 +1476,7 @@ static void ast_udc_remove(struct platform_device *pdev)
> return;
> }
>
> - spin_lock_irqsave(&udc->lock, flags);
> -
> - /* Disable upstream port connection */
> - ctrl = ast_udc_read(udc, AST_UDC_FUNC_CTRL) & ~USB_UPSTREAM_EN;
> - ast_udc_write(udc, ctrl, AST_UDC_FUNC_CTRL);
> -
> - clk_disable_unprepare(udc->clk);
> -
> - spin_unlock_irqrestore(&udc->lock, flags);
> -
> - if (udc->ep0_buf)
> - dma_free_coherent(&pdev->dev,
> - AST_UDC_EP_DMA_SIZE * AST_UDC_NUM_ENDPOINTS,
> - udc->ep0_buf,
> - udc->ep0_buf_dma);
> -
> - udc->ep0_buf = NULL;
> + ast_udc_cleanup(pdev);
> }
>
> static int ast_udc_probe(struct platform_device *pdev)
> @@ -1523,6 +1530,10 @@ static int ast_udc_probe(struct platform_device *pdev)
> AST_UDC_EP_DMA_SIZE *
> AST_UDC_NUM_ENDPOINTS,
> &udc->ep0_buf_dma, GFP_KERNEL);
> + if (!udc->ep0_buf) {
> + rc = -ENOMEM;
> + goto err_disable_clk;
> + }
>
> udc->gadget.speed = USB_SPEED_UNKNOWN;
> udc->gadget.max_speed = USB_SPEED_HIGH;
> @@ -1553,20 +1564,20 @@ static int ast_udc_probe(struct platform_device *pdev)
> udc->irq = platform_get_irq(pdev, 0);
> if (udc->irq < 0) {
> rc = udc->irq;
> - goto err;
> + goto err_cleanup;
> }
>
> rc = devm_request_irq(&pdev->dev, udc->irq, ast_udc_isr, 0,
> KBUILD_MODNAME, udc);
> if (rc) {
> dev_err(&pdev->dev, "Failed to request interrupt\n");
> - goto err;
> + goto err_cleanup;
> }
>
> rc = usb_add_gadget_udc(&pdev->dev, &udc->gadget);
> if (rc) {
> dev_err(&pdev->dev, "Failed to add gadget udc\n");
> - goto err;
> + goto err_cleanup;
> }
>
> dev_info(&pdev->dev, "Initialized udc in USB%s mode\n",
> @@ -1574,9 +1585,14 @@ static int ast_udc_probe(struct platform_device *pdev)
>
> return 0;
>
> +err_disable_clk:
> + clk_disable_unprepare(udc->clk);
> + goto err;
> +err_cleanup:
> + ast_udc_cleanup(pdev);
> + goto err;
> err:
That last goto is unnecessary.
However, I find it unsettling that in a patch fixing resource handling
we add a mildly convoluted cleanup path, with portions jumping over
each other in this way.
The err_disable_clk label is only used once, and itself jumps down to
the err label. This is the case because beyond its goto we free udc-
>ep0_buf in ast_udc_cleanup(). I think it would make more sense to move
the call to clk_disable_unprepare() into the conditional body of the
allocation failure test, then change its goto label to 'err'. That way
the above hunk becomes:
+err_cleanup:
+ ast_udc_cleanup(pdev);
err:
...
Which seems a bit more natural.
Andrew
> dev_err(&pdev->dev, "Failed to udc probe, rc:0x%x\n", rc);
> - ast_udc_remove(pdev);
>
> return rc;
> }
^ permalink raw reply
* Re: [PATCH v17 21/28] drm/tests: bridge: Add KUnit tests for bridge chain format selection
From: Nicolas Frattaroli @ 2026-06-10 11:42 UTC (permalink / raw)
To: Harry Wentland, Leo Li, Rodrigo Siqueira, Alex Deucher,
Christian König, David Airlie, Simona Vetter,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Sandy Huang, Heiko Stübner,
Andy Yan, Rodrigo Vivi, Joonas Lahtinen, Tvrtko Ursulin,
Dmitry Baryshkov, Sascha Hauer, Rob Herring, Jonathan Corbet,
Shuah Khan, Daniel Stone, Jani Nikula
Cc: kernel, amd-gfx, dri-devel, linux-kernel, linux-arm-kernel,
linux-rockchip, intel-gfx, intel-xe, linux-doc, wayland-devel
In-Reply-To: <04ff70850213ae0f75486b1a27a7edb6fb4e71c3@intel.com>
On Wednesday, 10 June 2026 12:32:29 Central European Summer Time Jani Nikula wrote:
> On Tue, 09 Jun 2026, Nicolas Frattaroli <nicolas.frattaroli@collabora.com> wrote:
> > diff --git a/drivers/gpu/drm/tests/drm_bridge_test.c b/drivers/gpu/drm/tests/drm_bridge_test.c
> > index 64b665580a88..92f142ca6695 100644
> > --- a/drivers/gpu/drm/tests/drm_bridge_test.c
> > +++ b/drivers/gpu/drm/tests/drm_bridge_test.c
> > @@ -2,15 +2,23 @@
> > /*
> > * Kunit test for drm_bridge functions
> > */
> > +#include <linux/cleanup.h>
> > +#include <linux/media-bus-format.h>
> > +
> > #include <drm/drm_atomic_state_helper.h>
> > +#include <drm/drm_atomic_uapi.h>
> > #include <drm/drm_bridge.h>
> > #include <drm/drm_bridge_connector.h>
> > #include <drm/drm_bridge_helper.h>
> > +#include <drm/drm_edid.h>
> > #include <drm/drm_kunit_helpers.h>
> > +#include <drm/drm_managed.h>
> >
> > #include <kunit/device.h>
> > #include <kunit/test.h>
> >
> > +#include "drm_kunit_edid.h"
>
> So here's the problem with adding *any* arrays into headers: every
> compilation unit that includes them duplicates all the arrays. It's only
> really okay for single use.
>
> And, in this case, most of the included arrays are unused, leading to
> build failures:
>
> CC [M] drivers/gpu/drm/tests/drm_bridge_test.o
> In file included from ../drivers/gpu/drm/tests/drm_bridge_test.c:21:
> ../drivers/gpu/drm/tests/drm_kunit_edid.h:958:28: error: ‘test_edid_hdmi_4k_rgb_yuv420_dc_max_340mhz’ defined but not used [-Werror=unused-const-variable=]
> 958 | static const unsigned char test_edid_hdmi_4k_rgb_yuv420_dc_max_340mhz[] = {
> | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> ../drivers/gpu/drm/tests/drm_kunit_edid.h:726:28: error: ‘test_edid_hdmi_1080p_rgb_yuv_dc_max_340mhz’ defined but not used [-Werror=unused-const-variable=]
> 726 | static const unsigned char test_edid_hdmi_1080p_rgb_yuv_dc_max_340mhz[] = {
> | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> ../drivers/gpu/drm/tests/drm_kunit_edid.h:612:28: error: ‘test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz’ defined but not used [-Werror=unused-const-variable=]
> 612 | static const unsigned char test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz[] = {
> | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> ../drivers/gpu/drm/tests/drm_kunit_edid.h:498:28: error: ‘test_edid_hdmi_1080p_rgb_max_340mhz’ defined but not used [-Werror=unused-const-variable=]
> 498 | static const unsigned char test_edid_hdmi_1080p_rgb_max_340mhz[] = {
> | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> ../drivers/gpu/drm/tests/drm_kunit_edid.h:390:28: error: ‘test_edid_hdmi_1080p_rgb_max_200mhz_hdr’ defined but not used [-Werror=unused-const-variable=]
> 390 | static const unsigned char test_edid_hdmi_1080p_rgb_max_200mhz_hdr[] = {
> | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> ../drivers/gpu/drm/tests/drm_kunit_edid.h:271:28: error: ‘test_edid_hdmi_1080p_rgb_max_200mhz’ defined but not used [-Werror=unused-const-variable=]
> 271 | static const unsigned char test_edid_hdmi_1080p_rgb_max_200mhz[] = {
> | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> ../drivers/gpu/drm/tests/drm_kunit_edid.h:163:28: error: ‘test_edid_hdmi_1080p_rgb_max_100mhz’ defined but not used [-Werror=unused-const-variable=]
> 163 | static const unsigned char test_edid_hdmi_1080p_rgb_max_100mhz[] = {
> | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> ../drivers/gpu/drm/tests/drm_kunit_edid.h:57:28: error: ‘test_edid_dvi_1080p’ defined but not used [-Werror=unused-const-variable=]
> 57 | static const unsigned char test_edid_dvi_1080p[] = {
> | ^~~~~~~~~~~~~~~~~~~
> cc1: all warnings being treated as errors
>
> This breaks the build for me, I don't know how it didn't for any of you.
It broke the build for me in the past[1], but then I couldn't repro
it anymore when challenged on my fix[2].
>
> Reverting these two fixes it:
>
> ce1d0139adac ("drm/tests: bridge: Add test for HDMI output bus formats helper")
> 082fbc179c01 ("drm/tests: bridge: Add KUnit tests for bridge chain format selection")
>
> I think the proper fix would be to move the arrays into a .c file, and
> only have declarations in the headers. But that needs to happen real
> soon or the commits need to be reverted.
If you don't want __maybe_unused, then sure, I'll move them into a new
.c file. Though I think the two are roughly equivalent in that I don't
think anyone is really trying to minimise the size of their KUnit
binaries.
I'll send a patch to move them to a .c
[1]: https://lore.kernel.org/dri-devel/20260121-color-format-v7-20-ef790dae780c@collabora.com/
[2]: https://lore.kernel.org/dri-devel/20260210-didactic-okapi-of-modernism-ff00d9@houat/
Kind regards,
Nicolas Frattaroli
>
> BR,
> Jani.
>
>
>
^ permalink raw reply
* Re: [PATCH v4 1/2] arm64: smp: Fix hot-unplug tearing by forcing unregistration
From: Catalin Marinas @ 2026-06-10 11:38 UTC (permalink / raw)
To: Jinjie Ruan
Cc: will, corbet, skhan, punit.agrawal, mrigendra.chaubey,
suzuki.poulose, chenl311, fengchengwen, maz, timothy.hayes,
lpieralisi, arnd, gshan, jic23, dietmar.eggemann, sudeep.holla,
pierre.gondois, linux-arm-kernel, linux-doc, linux-kernel
In-Reply-To: <20260610075202.3597031-2-ruanjinjie@huawei.com>
On Wed, Jun 10, 2026 at 03:52:01PM +0800, Jinjie Ruan wrote:
> Sashiko review pointed out the following issue[1].
>
> Commit eba4675008a6 ("arm64: arch_register_cpu() variant to check if
> an ACPI handle is now available.") introduced architectural safety
> blocks inside arch_unregister_cpu(). If a hot-unplug operation is
> determined to be a physical hardware removal (where _STA evaluates to
> !ACPI_STA_DEVICE_PRESENT), or if firmware evaluation fails, it aborts
> the unregistration transaction early to protect unreadied arm64
> infrastructure.
>
> However, returning early from arch_unregister_cpu() causes a catastrophic
> state tearing because the generic ACPI layer (acpi_processor_post_eject())
> unconditionally continues its cleanup flow. This leaves the stale sysfs
> device leaked in the memory, deadlocking any subsequent hot-add attempts
> on the same CPU.
>
> Fix it by simplifying arch_unregister_cpu() to always proceed with
> the unregistration, as a pr_err_once() warning is sufficient to make
> it more visible for currently not supported physical CPU removal.
> Also remove the redundant NULL check on acpi_handle as it cannot be
> NULL when calling arch_unregister_cpu().
>
> [1]: https://sashiko.dev/#/patchset/20260520022023.126670-1-ruanjinjie@huawei.com
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Cc: Jonathan Cameron <jic23@kernel.org>
> Cc: James Morse <james.morse@arm.com>
> Cc: stable@vger.kernel.org
> Fixes: eba4675008a6e ("arm64: arch_register_cpu() variant to check if an ACPI handle is now available.")
> Suggested-by: Catalin Marinas <catalin.marinas@arm.com>
> Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox