From 4617721c502b2ddaa4e324e86da4997edf738fa5 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Wed, 2 Sep 2026 09:55:01 -0400 Subject: ftrace: Synchronize the initialization of ftrace_ops There's some internal state that ftrace_ops needs to have set, but since it can be declared outside of the ftrace.c code, it calls ftrace_ops_init() on the ops in every global function. The issue is that if two tasks call it on the same ops at the same time it is possible to have the initialization of one corrupt the initialization of the other call. Create a ops_mutex to use to synchronize every initialization of the ftrace_ops. The mutex is taken within checking the ftrace_ops flag that states it was initializied but the flag is checked again after the mutex has been taken. Checking first outside the mutex allows it to shortcut having to take the mutex. But then the check needs to be done again after the mute is taken in case of races. Cc: stable@vger.kernel.org Link: https://patch.msgid.link/20260902095501.6b59af20@gandalf.local.home Fixes: f04f24fb7e48d ("ftrace, kprobes: Fix a deadlock on ftrace_regex_lock") Reported-by: sashiko-bot@kernel.org Close: https://lore.kernel.org/all/20260829025528.49A831F000E9@smtp.kernel.org/ Signed-off-by: Steven Rostedt --- drivers/soc/amlogic/Kconfig | 39 + drivers/soc/amlogic/Makefile | 5 + drivers/soc/amlogic/meson-canvas.c | 208 +++++ drivers/soc/amlogic/meson-clk-measure.c | 1361 +++++++++++++++++++++++++++++++ drivers/soc/amlogic/meson-gx-socinfo.c | 223 +++++ drivers/soc/amlogic/meson-mx-socinfo.c | 176 ++++ 6 files changed, 2012 insertions(+) create mode 100644 drivers/soc/amlogic/Kconfig create mode 100644 drivers/soc/amlogic/Makefile create mode 100644 drivers/soc/amlogic/meson-canvas.c create mode 100644 drivers/soc/amlogic/meson-clk-measure.c create mode 100644 drivers/soc/amlogic/meson-gx-socinfo.c create mode 100644 drivers/soc/amlogic/meson-mx-socinfo.c (limited to 'drivers/soc/amlogic') diff --git a/drivers/soc/amlogic/Kconfig b/drivers/soc/amlogic/Kconfig new file mode 100644 index 000000000..d08e398bd --- /dev/null +++ b/drivers/soc/amlogic/Kconfig @@ -0,0 +1,39 @@ +# SPDX-License-Identifier: GPL-2.0-only +menu "Amlogic SoC drivers" + +config MESON_CANVAS + tristate "Amlogic Meson Canvas driver" + depends on ARCH_MESON || COMPILE_TEST + default n + help + Say yes to support the canvas IP for Amlogic SoCs. + +config MESON_CLK_MEASURE + tristate "Amlogic Meson SoC Clock Measure driver" + depends on ARCH_MESON || COMPILE_TEST + default ARCH_MESON + select REGMAP_MMIO + help + Say yes to support of Measuring a set of internal SoC clocks + from the debugfs interface. + +config MESON_GX_SOCINFO + bool "Amlogic Meson GX SoC Information driver" + depends on (ARM64 && ARCH_MESON) || COMPILE_TEST + default ARCH_MESON + select SOC_BUS + help + Say yes to support decoding of Amlogic Meson GX SoC family + information about the type, package and version. + +config MESON_MX_SOCINFO + bool "Amlogic Meson MX SoC Information driver" + depends on (ARM && ARCH_MESON) || COMPILE_TEST + default ARCH_MESON + select SOC_BUS + help + Say yes to support decoding of Amlogic Meson6, Meson8, + Meson8b and Meson8m2 SoC family information about the type + and version. + +endmenu diff --git a/drivers/soc/amlogic/Makefile b/drivers/soc/amlogic/Makefile new file mode 100644 index 000000000..c25f835e6 --- /dev/null +++ b/drivers/soc/amlogic/Makefile @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0-only +obj-$(CONFIG_MESON_CANVAS) += meson-canvas.o +obj-$(CONFIG_MESON_CLK_MEASURE) += meson-clk-measure.o +obj-$(CONFIG_MESON_GX_SOCINFO) += meson-gx-socinfo.o +obj-$(CONFIG_MESON_MX_SOCINFO) += meson-mx-socinfo.o diff --git a/drivers/soc/amlogic/meson-canvas.c b/drivers/soc/amlogic/meson-canvas.c new file mode 100644 index 000000000..79681afea --- /dev/null +++ b/drivers/soc/amlogic/meson-canvas.c @@ -0,0 +1,208 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2018 BayLibre, SAS + * Copyright (C) 2015 Amlogic, Inc. All rights reserved. + * Copyright (C) 2014 Endless Mobile + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define NUM_CANVAS 256 + +/* DMC Registers */ +#define DMC_CAV_LUT_DATAL 0x00 + #define CANVAS_WIDTH_LBIT 29 + #define CANVAS_WIDTH_LWID 3 +#define DMC_CAV_LUT_DATAH 0x04 + #define CANVAS_WIDTH_HBIT 0 + #define CANVAS_HEIGHT_BIT 9 + #define CANVAS_WRAP_BIT 22 + #define CANVAS_BLKMODE_BIT 24 + #define CANVAS_ENDIAN_BIT 26 +#define DMC_CAV_LUT_ADDR 0x08 + #define CANVAS_LUT_WR_EN BIT(9) + #define CANVAS_LUT_RD_EN BIT(8) + +struct meson_canvas { + struct device *dev; + void __iomem *reg_base; + spinlock_t lock; /* canvas device lock */ + u8 used[NUM_CANVAS]; + bool supports_endianness; +}; + +static void canvas_write(struct meson_canvas *canvas, u32 reg, u32 val) +{ + writel_relaxed(val, canvas->reg_base + reg); +} + +static u32 canvas_read(struct meson_canvas *canvas, u32 reg) +{ + return readl_relaxed(canvas->reg_base + reg); +} + +struct meson_canvas *meson_canvas_get(struct device *dev) +{ + struct device_node *canvas_node; + struct platform_device *canvas_pdev; + struct meson_canvas *canvas; + + canvas_node = of_parse_phandle(dev->of_node, "amlogic,canvas", 0); + if (!canvas_node) + return ERR_PTR(-ENODEV); + + canvas_pdev = of_find_device_by_node(canvas_node); + of_node_put(canvas_node); + if (!canvas_pdev) + return ERR_PTR(-EPROBE_DEFER); + + /* + * If priv is NULL, it's probably because the canvas hasn't + * properly initialized. Bail out with -EINVAL because, in the + * current state, this driver probe cannot return -EPROBE_DEFER + */ + canvas = dev_get_drvdata(&canvas_pdev->dev); + put_device(&canvas_pdev->dev); + if (!canvas) + return ERR_PTR(-EINVAL); + + return canvas; +} +EXPORT_SYMBOL_GPL(meson_canvas_get); + +int meson_canvas_config(struct meson_canvas *canvas, u8 canvas_index, + u32 addr, u32 stride, u32 height, + unsigned int wrap, + unsigned int blkmode, + unsigned int endian) +{ + unsigned long flags; + + if (endian && !canvas->supports_endianness) { + dev_err(canvas->dev, + "Endianness is not supported on this SoC\n"); + return -EINVAL; + } + + spin_lock_irqsave(&canvas->lock, flags); + if (!canvas->used[canvas_index]) { + dev_err(canvas->dev, + "Trying to setup non allocated canvas %u\n", + canvas_index); + spin_unlock_irqrestore(&canvas->lock, flags); + return -EINVAL; + } + + canvas_write(canvas, DMC_CAV_LUT_DATAL, + ((addr + 7) >> 3) | + (((stride + 7) >> 3) << CANVAS_WIDTH_LBIT)); + + canvas_write(canvas, DMC_CAV_LUT_DATAH, + ((((stride + 7) >> 3) >> CANVAS_WIDTH_LWID) << + CANVAS_WIDTH_HBIT) | + (height << CANVAS_HEIGHT_BIT) | + (wrap << CANVAS_WRAP_BIT) | + (blkmode << CANVAS_BLKMODE_BIT) | + (endian << CANVAS_ENDIAN_BIT)); + + canvas_write(canvas, DMC_CAV_LUT_ADDR, + CANVAS_LUT_WR_EN | canvas_index); + + /* Force a read-back to make sure everything is flushed. */ + canvas_read(canvas, DMC_CAV_LUT_DATAH); + spin_unlock_irqrestore(&canvas->lock, flags); + + return 0; +} +EXPORT_SYMBOL_GPL(meson_canvas_config); + +int meson_canvas_alloc(struct meson_canvas *canvas, u8 *canvas_index) +{ + int i; + unsigned long flags; + + spin_lock_irqsave(&canvas->lock, flags); + for (i = 0; i < NUM_CANVAS; ++i) { + if (!canvas->used[i]) { + canvas->used[i] = 1; + spin_unlock_irqrestore(&canvas->lock, flags); + *canvas_index = i; + return 0; + } + } + spin_unlock_irqrestore(&canvas->lock, flags); + + dev_err(canvas->dev, "No more canvas available\n"); + return -ENODEV; +} +EXPORT_SYMBOL_GPL(meson_canvas_alloc); + +int meson_canvas_free(struct meson_canvas *canvas, u8 canvas_index) +{ + unsigned long flags; + + spin_lock_irqsave(&canvas->lock, flags); + if (!canvas->used[canvas_index]) { + dev_err(canvas->dev, + "Trying to free unused canvas %u\n", canvas_index); + spin_unlock_irqrestore(&canvas->lock, flags); + return -EINVAL; + } + canvas->used[canvas_index] = 0; + spin_unlock_irqrestore(&canvas->lock, flags); + + return 0; +} +EXPORT_SYMBOL_GPL(meson_canvas_free); + +static int meson_canvas_probe(struct platform_device *pdev) +{ + struct meson_canvas *canvas; + struct device *dev = &pdev->dev; + + canvas = devm_kzalloc(dev, sizeof(*canvas), GFP_KERNEL); + if (!canvas) + return -ENOMEM; + + canvas->reg_base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(canvas->reg_base)) + return PTR_ERR(canvas->reg_base); + + canvas->supports_endianness = of_device_get_match_data(dev); + + canvas->dev = dev; + spin_lock_init(&canvas->lock); + dev_set_drvdata(dev, canvas); + + return 0; +} + +static const struct of_device_id canvas_dt_match[] = { + { .compatible = "amlogic,meson8-canvas", .data = (void *)false, }, + { .compatible = "amlogic,meson8b-canvas", .data = (void *)false, }, + { .compatible = "amlogic,meson8m2-canvas", .data = (void *)false, }, + { .compatible = "amlogic,canvas", .data = (void *)true, }, + {} +}; +MODULE_DEVICE_TABLE(of, canvas_dt_match); + +static struct platform_driver meson_canvas_driver = { + .probe = meson_canvas_probe, + .driver = { + .name = "amlogic-canvas", + .of_match_table = canvas_dt_match, + }, +}; +module_platform_driver(meson_canvas_driver); + +MODULE_DESCRIPTION("Amlogic Canvas driver"); +MODULE_AUTHOR("Maxime Jourdan "); +MODULE_LICENSE("GPL"); diff --git a/drivers/soc/amlogic/meson-clk-measure.c b/drivers/soc/amlogic/meson-clk-measure.c new file mode 100644 index 000000000..8a1a9fed0 --- /dev/null +++ b/drivers/soc/amlogic/meson-clk-measure.c @@ -0,0 +1,1361 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2018 BayLibre, SAS + * Author: Neil Armstrong + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static DEFINE_MUTEX(measure_lock); + +#define MSR_DURATION GENMASK(15, 0) +#define MSR_ENABLE BIT(16) +#define MSR_CONT BIT(17) /* continuous measurement */ +#define MSR_INTR BIT(18) /* interrupts */ +#define MSR_RUN BIT(19) +#define MSR_CLK_SRC GENMASK(26, 20) +#define MSR_BUSY BIT(31) + +#define MSR_VAL_MASK GENMASK(15, 0) + +#define DIV_MIN 32 +#define DIV_STEP 32 +#define DIV_MAX 640 + +struct meson_msr_id { + struct meson_msr *priv; + unsigned int id; + const char *name; +}; + +struct msr_reg_offset { + unsigned int duty_val; + unsigned int freq_ctrl; + unsigned int duty_ctrl; + unsigned int freq_val; +}; + +struct meson_msr_data { + struct meson_msr_id *msr_table; + unsigned int msr_count; + const struct msr_reg_offset *reg; +}; + +struct meson_msr { + struct regmap *regmap; + struct meson_msr_data data; + struct dentry *debugfs_root; +}; + +#define CLK_MSR_ID(__id, __name) \ + [__id] = {.id = __id, .name = __name,} + +static const struct meson_msr_id clk_msr_m8[] = { + CLK_MSR_ID(0, "ring_osc_out_ee0"), + CLK_MSR_ID(1, "ring_osc_out_ee1"), + CLK_MSR_ID(2, "ring_osc_out_ee2"), + CLK_MSR_ID(3, "a9_ring_osck"), + CLK_MSR_ID(6, "vid_pll"), + CLK_MSR_ID(7, "clk81"), + CLK_MSR_ID(8, "encp"), + CLK_MSR_ID(9, "encl"), + CLK_MSR_ID(11, "eth_rmii"), + CLK_MSR_ID(13, "amclk"), + CLK_MSR_ID(14, "fec_clk_0"), + CLK_MSR_ID(15, "fec_clk_1"), + CLK_MSR_ID(16, "fec_clk_2"), + CLK_MSR_ID(18, "a9_clk_div16"), + CLK_MSR_ID(19, "hdmi_sys"), + CLK_MSR_ID(20, "rtc_osc_clk_out"), + CLK_MSR_ID(21, "i2s_clk_in_src0"), + CLK_MSR_ID(22, "clk_rmii_from_pad"), + CLK_MSR_ID(23, "hdmi_ch0_tmds"), + CLK_MSR_ID(24, "lvds_fifo"), + CLK_MSR_ID(26, "sc_clk_int"), + CLK_MSR_ID(28, "sar_adc"), + CLK_MSR_ID(30, "mpll_clk_test_out"), + CLK_MSR_ID(31, "audac_clkpi"), + CLK_MSR_ID(32, "vdac"), + CLK_MSR_ID(33, "sdhc_rx"), + CLK_MSR_ID(34, "sdhc_sd"), + CLK_MSR_ID(35, "mali"), + CLK_MSR_ID(36, "hdmi_tx_pixel"), + CLK_MSR_ID(38, "vdin_meas"), + CLK_MSR_ID(39, "pcm_sclk"), + CLK_MSR_ID(40, "pcm_mclk"), + CLK_MSR_ID(41, "eth_rx_tx"), + CLK_MSR_ID(42, "pwm_d"), + CLK_MSR_ID(43, "pwm_c"), + CLK_MSR_ID(44, "pwm_b"), + CLK_MSR_ID(45, "pwm_a"), + CLK_MSR_ID(46, "pcm2_sclk"), + CLK_MSR_ID(47, "ddr_dpll_pt"), + CLK_MSR_ID(48, "pwm_f"), + CLK_MSR_ID(49, "pwm_e"), + CLK_MSR_ID(59, "hcodec"), + CLK_MSR_ID(60, "usb_32k_alt"), + CLK_MSR_ID(61, "gpio"), + CLK_MSR_ID(62, "vid2_pll"), + CLK_MSR_ID(63, "mipi_csi_cfg"), +}; + +static const struct meson_msr_id clk_msr_gx[] = { + CLK_MSR_ID(0, "ring_osc_out_ee_0"), + CLK_MSR_ID(1, "ring_osc_out_ee_1"), + CLK_MSR_ID(2, "ring_osc_out_ee_2"), + CLK_MSR_ID(3, "a53_ring_osc"), + CLK_MSR_ID(4, "gp0_pll"), + CLK_MSR_ID(6, "enci"), + CLK_MSR_ID(7, "clk81"), + CLK_MSR_ID(8, "encp"), + CLK_MSR_ID(9, "encl"), + CLK_MSR_ID(10, "vdac"), + CLK_MSR_ID(11, "rgmii_tx"), + CLK_MSR_ID(12, "pdm"), + CLK_MSR_ID(13, "amclk"), + CLK_MSR_ID(14, "fec_0"), + CLK_MSR_ID(15, "fec_1"), + CLK_MSR_ID(16, "fec_2"), + CLK_MSR_ID(17, "sys_pll_div16"), + CLK_MSR_ID(18, "sys_cpu_div16"), + CLK_MSR_ID(19, "hdmitx_sys"), + CLK_MSR_ID(20, "rtc_osc_out"), + CLK_MSR_ID(21, "i2s_in_src0"), + CLK_MSR_ID(22, "eth_phy_ref"), + CLK_MSR_ID(23, "hdmi_todig"), + CLK_MSR_ID(26, "sc_int"), + CLK_MSR_ID(28, "sar_adc"), + CLK_MSR_ID(31, "mpll_test_out"), + CLK_MSR_ID(32, "vdec"), + CLK_MSR_ID(35, "mali"), + CLK_MSR_ID(36, "hdmi_tx_pixel"), + CLK_MSR_ID(37, "i958"), + CLK_MSR_ID(38, "vdin_meas"), + CLK_MSR_ID(39, "pcm_sclk"), + CLK_MSR_ID(40, "pcm_mclk"), + CLK_MSR_ID(41, "eth_rx_or_rmii"), + CLK_MSR_ID(42, "mp0_out"), + CLK_MSR_ID(43, "fclk_div5"), + CLK_MSR_ID(44, "pwm_b"), + CLK_MSR_ID(45, "pwm_a"), + CLK_MSR_ID(46, "vpu"), + CLK_MSR_ID(47, "ddr_dpll_pt"), + CLK_MSR_ID(48, "mp1_out"), + CLK_MSR_ID(49, "mp2_out"), + CLK_MSR_ID(50, "mp3_out"), + CLK_MSR_ID(51, "nand_core"), + CLK_MSR_ID(52, "sd_emmc_b"), + CLK_MSR_ID(53, "sd_emmc_a"), + CLK_MSR_ID(55, "vid_pll_div_out"), + CLK_MSR_ID(56, "cci"), + CLK_MSR_ID(57, "wave420l_c"), + CLK_MSR_ID(58, "wave420l_b"), + CLK_MSR_ID(59, "hcodec"), + CLK_MSR_ID(60, "alt_32k"), + CLK_MSR_ID(61, "gpio_msr"), + CLK_MSR_ID(62, "hevc"), + CLK_MSR_ID(66, "vid_lock"), + CLK_MSR_ID(70, "pwm_f"), + CLK_MSR_ID(71, "pwm_e"), + CLK_MSR_ID(72, "pwm_d"), + CLK_MSR_ID(73, "pwm_c"), + CLK_MSR_ID(75, "aoclkx2_int"), + CLK_MSR_ID(76, "aoclk_int"), + CLK_MSR_ID(77, "rng_ring_osc_0"), + CLK_MSR_ID(78, "rng_ring_osc_1"), + CLK_MSR_ID(79, "rng_ring_osc_2"), + CLK_MSR_ID(80, "rng_ring_osc_3"), + CLK_MSR_ID(81, "vapb"), + CLK_MSR_ID(82, "ge2d"), +}; + +static const struct meson_msr_id clk_msr_axg[] = { + CLK_MSR_ID(0, "ring_osc_out_ee_0"), + CLK_MSR_ID(1, "ring_osc_out_ee_1"), + CLK_MSR_ID(2, "ring_osc_out_ee_2"), + CLK_MSR_ID(3, "a53_ring_osc"), + CLK_MSR_ID(4, "gp0_pll"), + CLK_MSR_ID(5, "gp1_pll"), + CLK_MSR_ID(7, "clk81"), + CLK_MSR_ID(9, "encl"), + CLK_MSR_ID(17, "sys_pll_div16"), + CLK_MSR_ID(18, "sys_cpu_div16"), + CLK_MSR_ID(20, "rtc_osc_out"), + CLK_MSR_ID(23, "mmc_clk"), + CLK_MSR_ID(28, "sar_adc"), + CLK_MSR_ID(31, "mpll_test_out"), + CLK_MSR_ID(40, "mod_eth_tx_clk"), + CLK_MSR_ID(41, "mod_eth_rx_clk_rmii"), + CLK_MSR_ID(42, "mp0_out"), + CLK_MSR_ID(43, "fclk_div5"), + CLK_MSR_ID(44, "pwm_b"), + CLK_MSR_ID(45, "pwm_a"), + CLK_MSR_ID(46, "vpu"), + CLK_MSR_ID(47, "ddr_dpll_pt"), + CLK_MSR_ID(48, "mp1_out"), + CLK_MSR_ID(49, "mp2_out"), + CLK_MSR_ID(50, "mp3_out"), + CLK_MSR_ID(51, "sd_emmm_c"), + CLK_MSR_ID(52, "sd_emmc_b"), + CLK_MSR_ID(61, "gpio_msr"), + CLK_MSR_ID(66, "audio_slv_lrclk_c"), + CLK_MSR_ID(67, "audio_slv_lrclk_b"), + CLK_MSR_ID(68, "audio_slv_lrclk_a"), + CLK_MSR_ID(69, "audio_slv_sclk_c"), + CLK_MSR_ID(70, "audio_slv_sclk_b"), + CLK_MSR_ID(71, "audio_slv_sclk_a"), + CLK_MSR_ID(72, "pwm_d"), + CLK_MSR_ID(73, "pwm_c"), + CLK_MSR_ID(74, "wifi_beacon"), + CLK_MSR_ID(75, "tdmin_lb_lrcl"), + CLK_MSR_ID(76, "tdmin_lb_sclk"), + CLK_MSR_ID(77, "rng_ring_osc_0"), + CLK_MSR_ID(78, "rng_ring_osc_1"), + CLK_MSR_ID(79, "rng_ring_osc_2"), + CLK_MSR_ID(80, "rng_ring_osc_3"), + CLK_MSR_ID(81, "vapb"), + CLK_MSR_ID(82, "ge2d"), + CLK_MSR_ID(84, "audio_resample"), + CLK_MSR_ID(85, "audio_pdm_sys"), + CLK_MSR_ID(86, "audio_spdifout"), + CLK_MSR_ID(87, "audio_spdifin"), + CLK_MSR_ID(88, "audio_lrclk_f"), + CLK_MSR_ID(89, "audio_lrclk_e"), + CLK_MSR_ID(90, "audio_lrclk_d"), + CLK_MSR_ID(91, "audio_lrclk_c"), + CLK_MSR_ID(92, "audio_lrclk_b"), + CLK_MSR_ID(93, "audio_lrclk_a"), + CLK_MSR_ID(94, "audio_sclk_f"), + CLK_MSR_ID(95, "audio_sclk_e"), + CLK_MSR_ID(96, "audio_sclk_d"), + CLK_MSR_ID(97, "audio_sclk_c"), + CLK_MSR_ID(98, "audio_sclk_b"), + CLK_MSR_ID(99, "audio_sclk_a"), + CLK_MSR_ID(100, "audio_mclk_f"), + CLK_MSR_ID(101, "audio_mclk_e"), + CLK_MSR_ID(102, "audio_mclk_d"), + CLK_MSR_ID(103, "audio_mclk_c"), + CLK_MSR_ID(104, "audio_mclk_b"), + CLK_MSR_ID(105, "audio_mclk_a"), + CLK_MSR_ID(106, "pcie_refclk_n"), + CLK_MSR_ID(107, "pcie_refclk_p"), + CLK_MSR_ID(108, "audio_locker_out"), + CLK_MSR_ID(109, "audio_locker_in"), +}; + +static const struct meson_msr_id clk_msr_g12a[] = { + CLK_MSR_ID(0, "ring_osc_out_ee_0"), + CLK_MSR_ID(1, "ring_osc_out_ee_1"), + CLK_MSR_ID(2, "ring_osc_out_ee_2"), + CLK_MSR_ID(3, "sys_cpu_ring_osc"), + CLK_MSR_ID(4, "gp0_pll"), + CLK_MSR_ID(6, "enci"), + CLK_MSR_ID(7, "clk81"), + CLK_MSR_ID(8, "encp"), + CLK_MSR_ID(9, "encl"), + CLK_MSR_ID(10, "vdac"), + CLK_MSR_ID(11, "eth_tx"), + CLK_MSR_ID(12, "hifi_pll"), + CLK_MSR_ID(13, "mod_tcon"), + CLK_MSR_ID(14, "fec_0"), + CLK_MSR_ID(15, "fec_1"), + CLK_MSR_ID(16, "fec_2"), + CLK_MSR_ID(17, "sys_pll_div16"), + CLK_MSR_ID(18, "sys_cpu_div16"), + CLK_MSR_ID(19, "lcd_an_ph2"), + CLK_MSR_ID(20, "rtc_osc_out"), + CLK_MSR_ID(21, "lcd_an_ph3"), + CLK_MSR_ID(22, "eth_phy_ref"), + CLK_MSR_ID(23, "mpll_50m"), + CLK_MSR_ID(24, "eth_125m"), + CLK_MSR_ID(25, "eth_rmii"), + CLK_MSR_ID(26, "sc_int"), + CLK_MSR_ID(27, "in_mac"), + CLK_MSR_ID(28, "sar_adc"), + CLK_MSR_ID(29, "pcie_inp"), + CLK_MSR_ID(30, "pcie_inn"), + CLK_MSR_ID(31, "mpll_test_out"), + CLK_MSR_ID(32, "vdec"), + CLK_MSR_ID(33, "sys_cpu_ring_osc_1"), + CLK_MSR_ID(34, "eth_mpll_50m"), + CLK_MSR_ID(35, "mali"), + CLK_MSR_ID(36, "hdmi_tx_pixel"), + CLK_MSR_ID(37, "cdac"), + CLK_MSR_ID(38, "vdin_meas"), + CLK_MSR_ID(39, "bt656"), + CLK_MSR_ID(41, "eth_rx_or_rmii"), + CLK_MSR_ID(42, "mp0_out"), + CLK_MSR_ID(43, "fclk_div5"), + CLK_MSR_ID(44, "pwm_b"), + CLK_MSR_ID(45, "pwm_a"), + CLK_MSR_ID(46, "vpu"), + CLK_MSR_ID(47, "ddr_dpll_pt"), + CLK_MSR_ID(48, "mp1_out"), + CLK_MSR_ID(49, "mp2_out"), + CLK_MSR_ID(50, "mp3_out"), + CLK_MSR_ID(51, "sd_emmc_c"), + CLK_MSR_ID(52, "sd_emmc_b"), + CLK_MSR_ID(53, "sd_emmc_a"), + CLK_MSR_ID(54, "vpu_clkc"), + CLK_MSR_ID(55, "vid_pll_div_out"), + CLK_MSR_ID(56, "wave420l_a"), + CLK_MSR_ID(57, "wave420l_c"), + CLK_MSR_ID(58, "wave420l_b"), + CLK_MSR_ID(59, "hcodec"), + CLK_MSR_ID(61, "gpio_msr"), + CLK_MSR_ID(62, "hevcb"), + CLK_MSR_ID(63, "dsi_meas"), + CLK_MSR_ID(64, "spicc_1"), + CLK_MSR_ID(65, "spicc_0"), + CLK_MSR_ID(66, "vid_lock"), + CLK_MSR_ID(67, "dsi_phy"), + CLK_MSR_ID(68, "hdcp22_esm"), + CLK_MSR_ID(69, "hdcp22_skp"), + CLK_MSR_ID(70, "pwm_f"), + CLK_MSR_ID(71, "pwm_e"), + CLK_MSR_ID(72, "pwm_d"), + CLK_MSR_ID(73, "pwm_c"), + CLK_MSR_ID(75, "hevcf"), + CLK_MSR_ID(77, "rng_ring_osc_0"), + CLK_MSR_ID(78, "rng_ring_osc_1"), + CLK_MSR_ID(79, "rng_ring_osc_2"), + CLK_MSR_ID(80, "rng_ring_osc_3"), + CLK_MSR_ID(81, "vapb"), + CLK_MSR_ID(82, "ge2d"), + CLK_MSR_ID(83, "co_rx"), + CLK_MSR_ID(84, "co_tx"), + CLK_MSR_ID(89, "hdmi_todig"), + CLK_MSR_ID(90, "hdmitx_sys"), + CLK_MSR_ID(91, "sys_cpub_div16"), + CLK_MSR_ID(92, "sys_pll_cpub_div16"), + CLK_MSR_ID(94, "eth_phy_rx"), + CLK_MSR_ID(95, "eth_phy_pll"), + CLK_MSR_ID(96, "vpu_b"), + CLK_MSR_ID(97, "cpu_b_tmp"), + CLK_MSR_ID(98, "ts"), + CLK_MSR_ID(99, "ring_osc_out_ee_3"), + CLK_MSR_ID(100, "ring_osc_out_ee_4"), + CLK_MSR_ID(101, "ring_osc_out_ee_5"), + CLK_MSR_ID(102, "ring_osc_out_ee_6"), + CLK_MSR_ID(103, "ring_osc_out_ee_7"), + CLK_MSR_ID(104, "ring_osc_out_ee_8"), + CLK_MSR_ID(105, "ring_osc_out_ee_9"), + CLK_MSR_ID(106, "ephy_test"), + CLK_MSR_ID(107, "au_dac_g128x"), + CLK_MSR_ID(108, "audio_locker_out"), + CLK_MSR_ID(109, "audio_locker_in"), + CLK_MSR_ID(110, "audio_tdmout_c_sclk"), + CLK_MSR_ID(111, "audio_tdmout_b_sclk"), + CLK_MSR_ID(112, "audio_tdmout_a_sclk"), + CLK_MSR_ID(113, "audio_tdmin_lb_sclk"), + CLK_MSR_ID(114, "audio_tdmin_c_sclk"), + CLK_MSR_ID(115, "audio_tdmin_b_sclk"), + CLK_MSR_ID(116, "audio_tdmin_a_sclk"), + CLK_MSR_ID(117, "audio_resample"), + CLK_MSR_ID(118, "audio_pdm_sys"), + CLK_MSR_ID(119, "audio_spdifout_b"), + CLK_MSR_ID(120, "audio_spdifout"), + CLK_MSR_ID(121, "audio_spdifin"), + CLK_MSR_ID(122, "audio_pdm_dclk"), +}; + +static const struct meson_msr_id clk_msr_sm1[] = { + CLK_MSR_ID(0, "ring_osc_out_ee_0"), + CLK_MSR_ID(1, "ring_osc_out_ee_1"), + CLK_MSR_ID(2, "ring_osc_out_ee_2"), + CLK_MSR_ID(3, "ring_osc_out_ee_3"), + CLK_MSR_ID(4, "gp0_pll"), + CLK_MSR_ID(5, "gp1_pll"), + CLK_MSR_ID(6, "enci"), + CLK_MSR_ID(7, "clk81"), + CLK_MSR_ID(8, "encp"), + CLK_MSR_ID(9, "encl"), + CLK_MSR_ID(10, "vdac"), + CLK_MSR_ID(11, "eth_tx"), + CLK_MSR_ID(12, "hifi_pll"), + CLK_MSR_ID(13, "mod_tcon"), + CLK_MSR_ID(14, "fec_0"), + CLK_MSR_ID(15, "fec_1"), + CLK_MSR_ID(16, "fec_2"), + CLK_MSR_ID(17, "sys_pll_div16"), + CLK_MSR_ID(18, "sys_cpu_div16"), + CLK_MSR_ID(19, "lcd_an_ph2"), + CLK_MSR_ID(20, "rtc_osc_out"), + CLK_MSR_ID(21, "lcd_an_ph3"), + CLK_MSR_ID(22, "eth_phy_ref"), + CLK_MSR_ID(23, "mpll_50m"), + CLK_MSR_ID(24, "eth_125m"), + CLK_MSR_ID(25, "eth_rmii"), + CLK_MSR_ID(26, "sc_int"), + CLK_MSR_ID(27, "in_mac"), + CLK_MSR_ID(28, "sar_adc"), + CLK_MSR_ID(29, "pcie_inp"), + CLK_MSR_ID(30, "pcie_inn"), + CLK_MSR_ID(31, "mpll_test_out"), + CLK_MSR_ID(32, "vdec"), + CLK_MSR_ID(34, "eth_mpll_50m"), + CLK_MSR_ID(35, "mali"), + CLK_MSR_ID(36, "hdmi_tx_pixel"), + CLK_MSR_ID(37, "cdac"), + CLK_MSR_ID(38, "vdin_meas"), + CLK_MSR_ID(39, "bt656"), + CLK_MSR_ID(40, "arm_ring_osc_out_4"), + CLK_MSR_ID(41, "eth_rx_or_rmii"), + CLK_MSR_ID(42, "mp0_out"), + CLK_MSR_ID(43, "fclk_div5"), + CLK_MSR_ID(44, "pwm_b"), + CLK_MSR_ID(45, "pwm_a"), + CLK_MSR_ID(46, "vpu"), + CLK_MSR_ID(47, "ddr_dpll_pt"), + CLK_MSR_ID(48, "mp1_out"), + CLK_MSR_ID(49, "mp2_out"), + CLK_MSR_ID(50, "mp3_out"), + CLK_MSR_ID(51, "sd_emmc_c"), + CLK_MSR_ID(52, "sd_emmc_b"), + CLK_MSR_ID(53, "sd_emmc_a"), + CLK_MSR_ID(54, "vpu_clkc"), + CLK_MSR_ID(55, "vid_pll_div_out"), + CLK_MSR_ID(56, "wave420l_a"), + CLK_MSR_ID(57, "wave420l_c"), + CLK_MSR_ID(58, "wave420l_b"), + CLK_MSR_ID(59, "hcodec"), + CLK_MSR_ID(60, "arm_ring_osc_out_5"), + CLK_MSR_ID(61, "gpio_msr"), + CLK_MSR_ID(62, "hevcb"), + CLK_MSR_ID(63, "dsi_meas"), + CLK_MSR_ID(64, "spicc_1"), + CLK_MSR_ID(65, "spicc_0"), + CLK_MSR_ID(66, "vid_lock"), + CLK_MSR_ID(67, "dsi_phy"), + CLK_MSR_ID(68, "hdcp22_esm"), + CLK_MSR_ID(69, "hdcp22_skp"), + CLK_MSR_ID(70, "pwm_f"), + CLK_MSR_ID(71, "pwm_e"), + CLK_MSR_ID(72, "pwm_d"), + CLK_MSR_ID(73, "pwm_c"), + CLK_MSR_ID(74, "arm_ring_osc_out_6"), + CLK_MSR_ID(75, "hevcf"), + CLK_MSR_ID(76, "arm_ring_osc_out_7"), + CLK_MSR_ID(77, "rng_ring_osc_0"), + CLK_MSR_ID(78, "rng_ring_osc_1"), + CLK_MSR_ID(79, "rng_ring_osc_2"), + CLK_MSR_ID(80, "rng_ring_osc_3"), + CLK_MSR_ID(81, "vapb"), + CLK_MSR_ID(82, "ge2d"), + CLK_MSR_ID(83, "co_rx"), + CLK_MSR_ID(84, "co_tx"), + CLK_MSR_ID(85, "arm_ring_osc_out_8"), + CLK_MSR_ID(86, "arm_ring_osc_out_9"), + CLK_MSR_ID(87, "mipi_dsi_phy"), + CLK_MSR_ID(88, "cis2_adapt"), + CLK_MSR_ID(89, "hdmi_todig"), + CLK_MSR_ID(90, "hdmitx_sys"), + CLK_MSR_ID(91, "nna_core"), + CLK_MSR_ID(92, "nna_axi"), + CLK_MSR_ID(93, "vad"), + CLK_MSR_ID(94, "eth_phy_rx"), + CLK_MSR_ID(95, "eth_phy_pll"), + CLK_MSR_ID(96, "vpu_b"), + CLK_MSR_ID(97, "cpu_b_tmp"), + CLK_MSR_ID(98, "ts"), + CLK_MSR_ID(99, "arm_ring_osc_out_10"), + CLK_MSR_ID(100, "arm_ring_osc_out_11"), + CLK_MSR_ID(101, "arm_ring_osc_out_12"), + CLK_MSR_ID(102, "arm_ring_osc_out_13"), + CLK_MSR_ID(103, "arm_ring_osc_out_14"), + CLK_MSR_ID(104, "arm_ring_osc_out_15"), + CLK_MSR_ID(105, "arm_ring_osc_out_16"), + CLK_MSR_ID(106, "ephy_test"), + CLK_MSR_ID(107, "au_dac_g128x"), + CLK_MSR_ID(108, "audio_locker_out"), + CLK_MSR_ID(109, "audio_locker_in"), + CLK_MSR_ID(110, "audio_tdmout_c_sclk"), + CLK_MSR_ID(111, "audio_tdmout_b_sclk"), + CLK_MSR_ID(112, "audio_tdmout_a_sclk"), + CLK_MSR_ID(113, "audio_tdmin_lb_sclk"), + CLK_MSR_ID(114, "audio_tdmin_c_sclk"), + CLK_MSR_ID(115, "audio_tdmin_b_sclk"), + CLK_MSR_ID(116, "audio_tdmin_a_sclk"), + CLK_MSR_ID(117, "audio_resample"), + CLK_MSR_ID(118, "audio_pdm_sys"), + CLK_MSR_ID(119, "audio_spdifout_b"), + CLK_MSR_ID(120, "audio_spdifout"), + CLK_MSR_ID(121, "audio_spdifin"), + CLK_MSR_ID(122, "audio_pdm_dclk"), + CLK_MSR_ID(123, "audio_resampled"), + CLK_MSR_ID(124, "earcrx_pll"), + CLK_MSR_ID(125, "earcrx_pll_test"), + CLK_MSR_ID(126, "csi_phy0"), + CLK_MSR_ID(127, "csi2_data"), +}; + +static const struct meson_msr_id clk_msr_c3[] = { + CLK_MSR_ID(0, "sys_clk"), + CLK_MSR_ID(1, "axi_clk"), + CLK_MSR_ID(2, "rtc_clk"), + CLK_MSR_ID(3, "p20_usb2_ckout"), + CLK_MSR_ID(4, "eth_mpll_test"), + CLK_MSR_ID(5, "sys_pll"), + CLK_MSR_ID(6, "cpu_clk_div16"), + CLK_MSR_ID(7, "ts_pll"), + CLK_MSR_ID(8, "fclk_div2"), + CLK_MSR_ID(9, "fclk_div2p5"), + CLK_MSR_ID(10, "fclk_div3"), + CLK_MSR_ID(11, "fclk_div4"), + CLK_MSR_ID(12, "fclk_div5"), + CLK_MSR_ID(13, "fclk_div7"), + CLK_MSR_ID(15, "fclk_50m"), + CLK_MSR_ID(16, "sys_oscin32k_i"), + CLK_MSR_ID(17, "mclk_pll"), + CLK_MSR_ID(19, "hifi_pll"), + CLK_MSR_ID(20, "gp0_pll"), + CLK_MSR_ID(21, "gp1_pll"), + CLK_MSR_ID(22, "eth_mppll_50m_ckout"), + CLK_MSR_ID(23, "sys_pll_div16"), + CLK_MSR_ID(24, "ddr_dpll_pt_clk"), + CLK_MSR_ID(26, "nna_core"), + CLK_MSR_ID(27, "rtc_sec_pulse_out"), + CLK_MSR_ID(28, "rtc_osc_clk_out"), + CLK_MSR_ID(29, "debug_in_clk"), + CLK_MSR_ID(30, "mod_eth_phy_ref_clk"), + CLK_MSR_ID(31, "mod_eth_tx_clk"), + CLK_MSR_ID(32, "eth_125m"), + CLK_MSR_ID(33, "eth_rmii"), + CLK_MSR_ID(34, "co_clkin_to_mac"), + CLK_MSR_ID(36, "co_rx_clk"), + CLK_MSR_ID(37, "co_tx_clk"), + CLK_MSR_ID(38, "eth_phy_rxclk"), + CLK_MSR_ID(39, "eth_phy_plltxclk"), + CLK_MSR_ID(40, "ephy_test_clk"), + CLK_MSR_ID(66, "vapb"), + CLK_MSR_ID(67, "ge2d"), + CLK_MSR_ID(68, "dewarpa"), + CLK_MSR_ID(70, "mipi_dsi_meas"), + CLK_MSR_ID(71, "dsi_phy"), + CLK_MSR_ID(79, "rama"), + CLK_MSR_ID(94, "vc9000e_core"), + CLK_MSR_ID(95, "vc9000e_sys"), + CLK_MSR_ID(96, "vc9000e_aclk"), + CLK_MSR_ID(97, "hcodec"), + CLK_MSR_ID(106, "deskew_pll_clk_div32_out"), + CLK_MSR_ID(107, "mipi_csi_phy_clk_out[0]"), + CLK_MSR_ID(108, "mipi_csi_phy_clk_out[1]"), + CLK_MSR_ID(110, "spifc"), + CLK_MSR_ID(111, "saradc"), + CLK_MSR_ID(112, "ts"), + CLK_MSR_ID(113, "sd_emmc_c"), + CLK_MSR_ID(114, "sd_emmc_b"), + CLK_MSR_ID(115, "sd_emmc_a"), + CLK_MSR_ID(116, "gpio_msr_clk"), + CLK_MSR_ID(117, "spicc_b"), + CLK_MSR_ID(118, "spicc_a"), + CLK_MSR_ID(122, "mod_audio_pdm_dclk_o"), + CLK_MSR_ID(124, "o_earcrx_dmac_clk"), + CLK_MSR_ID(125, "o_earcrx_cmdc_clk"), + CLK_MSR_ID(126, "o_earctx_dmac_clk"), + CLK_MSR_ID(127, "o_earctx_cmdc_clk"), + CLK_MSR_ID(128, "o_tohdmitx_bclk"), + CLK_MSR_ID(129, "o_tohdmitx_mclk"), + CLK_MSR_ID(130, "o_tohdmitx_spdif_clk"), + CLK_MSR_ID(131, "o_toacodec_bclk"), + CLK_MSR_ID(132, "o_toacodec_mclk"), + CLK_MSR_ID(133, "o_spdifout_b_mst_clk"), + CLK_MSR_ID(134, "o_spdifout_mst_clk"), + CLK_MSR_ID(135, "o_spdifin_mst_clk"), + CLK_MSR_ID(136, "o_audio_mclk"), + CLK_MSR_ID(137, "o_vad_clk"), + CLK_MSR_ID(138, "o_tdmout_d_sclk"), + CLK_MSR_ID(139, "o_tdmout_c_sclk"), + CLK_MSR_ID(140, "o_tdmout_b_sclk"), + CLK_MSR_ID(141, "o_tdmout_a_sclk"), + CLK_MSR_ID(142, "o_tdminb_1b_sclk"), + CLK_MSR_ID(143, "o_tdmin_1b_sclk"), + CLK_MSR_ID(144, "o_tdmin_d_sclk"), + CLK_MSR_ID(145, "o_tdmin_c_sclk"), + CLK_MSR_ID(146, "o_tdmin_b_sclk"), + CLK_MSR_ID(147, "o_tdmin_a_sclk"), + CLK_MSR_ID(148, "o_resampleb_clk"), + CLK_MSR_ID(149, "o_resamplea_clk"), + CLK_MSR_ID(150, "o_pdmb_sysclk"), + CLK_MSR_ID(151, "o_pdmb_dclk"), + CLK_MSR_ID(152, "o_pdm_sysclk"), + CLK_MSR_ID(153, "o_pdm_dclk"), + CLK_MSR_ID(154, "c_alockerb_out_clk"), + CLK_MSR_ID(155, "c_alockerb_in_clk"), + CLK_MSR_ID(156, "c_alocker_out_clk"), + CLK_MSR_ID(157, "c_alocker_in_clk"), + CLK_MSR_ID(158, "audio_mst_clk[34]"), + CLK_MSR_ID(159, "audio_mst_clk[35]"), + CLK_MSR_ID(160, "pwm_n"), + CLK_MSR_ID(161, "pwm_m"), + CLK_MSR_ID(162, "pwm_l"), + CLK_MSR_ID(163, "pwm_k"), + CLK_MSR_ID(164, "pwm_j"), + CLK_MSR_ID(165, "pwm_i"), + CLK_MSR_ID(166, "pwm_h"), + CLK_MSR_ID(167, "pwm_g"), + CLK_MSR_ID(168, "pwm_f"), + CLK_MSR_ID(169, "pwm_e"), + CLK_MSR_ID(170, "pwm_d"), + CLK_MSR_ID(171, "pwm_c"), + CLK_MSR_ID(172, "pwm_b"), + CLK_MSR_ID(173, "pwm_a"), + CLK_MSR_ID(174, "AU_DAC1_CLK_TO_GPIO"), + CLK_MSR_ID(175, "AU_ADC_CLK_TO_GPIO"), + CLK_MSR_ID(176, "rng_ring_osc_clk[0]"), + CLK_MSR_ID(177, "rng_ring_osc_clk[1]"), + CLK_MSR_ID(178, "rng_ring_osc_clk[2]"), + CLK_MSR_ID(179, "rng_ring_osc_clk[3]"), + CLK_MSR_ID(180, "sys_cpu_ring_osc_clk[0]"), + CLK_MSR_ID(181, "sys_cpu_ring_osc_clk[1]"), + CLK_MSR_ID(182, "sys_cpu_ring_osc_clk[2]"), + CLK_MSR_ID(183, "sys_cpu_ring_osc_clk[3]"), + CLK_MSR_ID(184, "sys_cpu_ring_osc_clk[4]"), + CLK_MSR_ID(185, "sys_cpu_ring_osc_clk[5]"), + CLK_MSR_ID(186, "sys_cpu_ring_osc_clk[6]"), + CLK_MSR_ID(187, "sys_cpu_ring_osc_clk[7]"), + CLK_MSR_ID(188, "sys_cpu_ring_osc_clk[8]"), + CLK_MSR_ID(189, "sys_cpu_ring_osc_clk[9]"), + CLK_MSR_ID(190, "sys_cpu_ring_osc_clk[10]"), + CLK_MSR_ID(191, "sys_cpu_ring_osc_clk[11]"), + CLK_MSR_ID(192, "am_ring_osc_clk_out[12](dmc)"), + CLK_MSR_ID(193, "am_ring_osc_clk_out[13](rama)"), + CLK_MSR_ID(194, "am_ring_osc_clk_out[14](nna)"), + CLK_MSR_ID(195, "am_ring_osc_clk_out[15](nna)"), + CLK_MSR_ID(200, "rng_ring_osc_clk_1[0]"), + CLK_MSR_ID(201, "rng_ring_osc_clk_1[1]"), + CLK_MSR_ID(202, "rng_ring_osc_clk_1[2]"), + CLK_MSR_ID(203, "rng_ring_osc_clk_1[3]"), + +}; + +static const struct meson_msr_id clk_msr_s4[] = { + CLK_MSR_ID(0, "sys_clk"), + CLK_MSR_ID(1, "axi_clk"), + CLK_MSR_ID(2, "rtc_clk"), + CLK_MSR_ID(5, "mali"), + CLK_MSR_ID(6, "cpu_clk_div16"), + CLK_MSR_ID(7, "ceca_clk"), + CLK_MSR_ID(8, "cecb_clk"), + CLK_MSR_ID(10, "fclk_div5"), + CLK_MSR_ID(11, "mpll0"), + CLK_MSR_ID(12, "mpll1"), + CLK_MSR_ID(13, "mpll2"), + CLK_MSR_ID(14, "mpll3"), + CLK_MSR_ID(15, "fclk_50m"), + CLK_MSR_ID(16, "pcie_clk_inp"), + CLK_MSR_ID(17, "pcie_clk_inn"), + CLK_MSR_ID(18, "mpll_clk_test_out"), + CLK_MSR_ID(19, "hifi_pll"), + CLK_MSR_ID(20, "gp0_pll"), + CLK_MSR_ID(21, "gp1_pll"), + CLK_MSR_ID(22, "eth_mppll_50m_ckout"), + CLK_MSR_ID(23, "sys_pll_div16"), + CLK_MSR_ID(24, "ddr_dpll_pt_clk"), + CLK_MSR_ID(30, "mod_eth_phy_ref_clk"), + CLK_MSR_ID(31, "mod_eth_tx_clk"), + CLK_MSR_ID(32, "eth_125m"), + CLK_MSR_ID(33, "eth_rmii"), + CLK_MSR_ID(34, "co_clkin_to_mac"), + CLK_MSR_ID(35, "mod_eth_rx_clk_rmii"), + CLK_MSR_ID(36, "co_rx_clk"), + CLK_MSR_ID(37, "co_tx_clk"), + CLK_MSR_ID(38, "eth_phy_rxclk"), + CLK_MSR_ID(39, "eth_phy_plltxclk"), + CLK_MSR_ID(40, "ephy_test_clk"), + CLK_MSR_ID(50, "vid_pll_div_clk_out"), + CLK_MSR_ID(51, "enci"), + CLK_MSR_ID(52, "encp"), + CLK_MSR_ID(53, "encl"), + CLK_MSR_ID(54, "vdac"), + CLK_MSR_ID(55, "cdac_clk_c"), + CLK_MSR_ID(56, "mod_tcon_clko"), + CLK_MSR_ID(57, "lcd_an_clk_ph2"), + CLK_MSR_ID(58, "lcd_an_clk_ph3"), + CLK_MSR_ID(59, "hdmitx_pixel"), + CLK_MSR_ID(60, "vdin_meas"), + CLK_MSR_ID(61, "vpu"), + CLK_MSR_ID(62, "vpu_clkb"), + CLK_MSR_ID(63, "vpu_clkb_tmp"), + CLK_MSR_ID(64, "vpu_clkc"), + CLK_MSR_ID(65, "vid_lock"), + CLK_MSR_ID(66, "vapb"), + CLK_MSR_ID(67, "ge2d"), + CLK_MSR_ID(68, "cts_hdcp22_esmclk"), + CLK_MSR_ID(69, "cts_hdcp22_skpclk"), + CLK_MSR_ID(76, "hdmitx_tmds"), + CLK_MSR_ID(77, "hdmitx_sys_clk"), + CLK_MSR_ID(78, "hdmitx_fe_clk"), + CLK_MSR_ID(79, "rama"), + CLK_MSR_ID(93, "vdec"), + CLK_MSR_ID(99, "hevcf"), + CLK_MSR_ID(100, "demod_core"), + CLK_MSR_ID(101, "adc_extclk_in"), + CLK_MSR_ID(102, "cts_demod_core_t2_clk"), + CLK_MSR_ID(103, "adc_dpll_intclk"), + CLK_MSR_ID(104, "adc_dpll_clk_b3"), + CLK_MSR_ID(105, "s2_adc_clk"), + CLK_MSR_ID(106, "deskew_pll_clk_div32_out"), + CLK_MSR_ID(110, "sc"), + CLK_MSR_ID(111, "sar_adc"), + CLK_MSR_ID(113, "sd_emmc_c"), + CLK_MSR_ID(114, "sd_emmc_b"), + CLK_MSR_ID(115, "sd_emmc_a"), + CLK_MSR_ID(116, "gpio_msr_clk"), + CLK_MSR_ID(118, "spicc0"), + CLK_MSR_ID(121, "ts"), + CLK_MSR_ID(130, "audio_vad_clk"), + CLK_MSR_ID(131, "acodec_dac_clk_x128"), + CLK_MSR_ID(132, "audio_locker_in_clk"), + CLK_MSR_ID(133, "audio_locker_out_clk"), + CLK_MSR_ID(134, "audio_tdmout_c_sclk"), + CLK_MSR_ID(135, "audio_tdmout_b_sclk"), + CLK_MSR_ID(136, "audio_tdmout_a_sclk"), + CLK_MSR_ID(137, "audio_tdmin_lb_sclk"), + CLK_MSR_ID(138, "audio_tdmin_c_sclk"), + CLK_MSR_ID(139, "audio_tdmin_b_sclk"), + CLK_MSR_ID(140, "audio_tdmin_a_sclk"), + CLK_MSR_ID(141, "audio_resamplea_clk"), + CLK_MSR_ID(142, "audio_pdm_sysclk"), + CLK_MSR_ID(143, "audio_spdifout_b_mst_clk"), + CLK_MSR_ID(144, "audio_spdifout_mst_clk"), + CLK_MSR_ID(145, "audio_spdifin_mst_clk"), + CLK_MSR_ID(146, "audio_pdm_dclk"), + CLK_MSR_ID(147, "audio_resampleb_clk"), + CLK_MSR_ID(160, "pwm_j"), + CLK_MSR_ID(161, "pwm_i"), + CLK_MSR_ID(162, "pwm_h"), + CLK_MSR_ID(163, "pwm_g"), + CLK_MSR_ID(164, "pwm_f"), + CLK_MSR_ID(165, "pwm_e"), + CLK_MSR_ID(166, "pwm_d"), + CLK_MSR_ID(167, "pwm_c"), + CLK_MSR_ID(168, "pwm_b"), + CLK_MSR_ID(169, "pwm_a"), + CLK_MSR_ID(176, "rng_ring_0"), + CLK_MSR_ID(177, "rng_ring_1"), + CLK_MSR_ID(178, "rng_ring_2"), + CLK_MSR_ID(179, "rng_ring_3"), + CLK_MSR_ID(180, "dmc_osc_ring(LVT16)"), + CLK_MSR_ID(181, "gpu_osc_ring0(LVT16)"), + CLK_MSR_ID(182, "gpu_osc_ring1(ULVT16)"), + CLK_MSR_ID(183, "gpu_osc_ring2(SLVT16)"), + CLK_MSR_ID(184, "vpu_osc_ring0(SVT24)"), + CLK_MSR_ID(185, "vpu_osc_ring1(LVT20)"), + CLK_MSR_ID(186, "vpu_osc_ring2(LVT16)"), + CLK_MSR_ID(187, "dos_osc_ring0(SVT24)"), + CLK_MSR_ID(188, "dos_osc_ring1(SVT16)"), + CLK_MSR_ID(189, "dos_osc_ring2(LVT16)"), + CLK_MSR_ID(190, "dos_osc_ring3(ULVT20)"), + CLK_MSR_ID(192, "axi_sram_osc_ring(SVT16)"), + CLK_MSR_ID(193, "demod_osc_ring0"), + CLK_MSR_ID(194, "demod_osc_ring1"), + CLK_MSR_ID(195, "sar_osc_ring"), + CLK_MSR_ID(196, "sys_cpu_osc_ring0"), + CLK_MSR_ID(197, "sys_cpu_osc_ring1"), + CLK_MSR_ID(198, "sys_cpu_osc_ring2"), + CLK_MSR_ID(199, "sys_cpu_osc_ring3"), + CLK_MSR_ID(200, "sys_cpu_osc_ring4"), + CLK_MSR_ID(201, "sys_cpu_osc_ring5"), + CLK_MSR_ID(202, "sys_cpu_osc_ring6"), + CLK_MSR_ID(203, "sys_cpu_osc_ring7"), + CLK_MSR_ID(204, "sys_cpu_osc_ring8"), + CLK_MSR_ID(205, "sys_cpu_osc_ring9"), + CLK_MSR_ID(206, "sys_cpu_osc_ring10"), + CLK_MSR_ID(207, "sys_cpu_osc_ring11"), + CLK_MSR_ID(208, "sys_cpu_osc_ring12"), + CLK_MSR_ID(209, "sys_cpu_osc_ring13"), + CLK_MSR_ID(210, "sys_cpu_osc_ring14"), + CLK_MSR_ID(211, "sys_cpu_osc_ring15"), + CLK_MSR_ID(212, "sys_cpu_osc_ring16"), + CLK_MSR_ID(213, "sys_cpu_osc_ring17"), + CLK_MSR_ID(214, "sys_cpu_osc_ring18"), + CLK_MSR_ID(215, "sys_cpu_osc_ring19"), + CLK_MSR_ID(216, "sys_cpu_osc_ring20"), + CLK_MSR_ID(217, "sys_cpu_osc_ring21"), + CLK_MSR_ID(218, "sys_cpu_osc_ring22"), + CLK_MSR_ID(219, "sys_cpu_osc_ring23"), + CLK_MSR_ID(220, "sys_cpu_osc_ring24"), + CLK_MSR_ID(221, "sys_cpu_osc_ring25"), + CLK_MSR_ID(222, "sys_cpu_osc_ring26"), + CLK_MSR_ID(223, "sys_cpu_osc_ring27"), + +}; + +static const struct meson_msr_id clk_msr_a1[] = { + CLK_MSR_ID(0, "tdmout_b_sclk"), + CLK_MSR_ID(1, "tdmout_a_sclk"), + CLK_MSR_ID(2, "tdmin_lb_sclk"), + CLK_MSR_ID(3, "tdmin_b_sclk"), + CLK_MSR_ID(4, "tdmin_a_sclk"), + CLK_MSR_ID(5, "vad"), + CLK_MSR_ID(6, "resamplea"), + CLK_MSR_ID(7, "pdm_sysclk"), + CLK_MSR_ID(8, "pdm_dclk"), + CLK_MSR_ID(9, "locker_out"), + CLK_MSR_ID(10, "locker_in"), + CLK_MSR_ID(11, "spdifin"), + CLK_MSR_ID(12, "tdmin_vad"), + CLK_MSR_ID(13, "au_adc"), + CLK_MSR_ID(14, "au_dac"), + CLK_MSR_ID(16, "spicc_a"), + CLK_MSR_ID(17, "spifc"), + CLK_MSR_ID(18, "sd_emmc_a"), + CLK_MSR_ID(19, "dmcx4"), + CLK_MSR_ID(20, "dmc"), + CLK_MSR_ID(21, "psram"), + CLK_MSR_ID(22, "cecb"), + CLK_MSR_ID(23, "ceca"), + CLK_MSR_ID(24, "ts"), + CLK_MSR_ID(25, "pwm_f"), + CLK_MSR_ID(26, "pwm_e"), + CLK_MSR_ID(27, "pwm_d"), + CLK_MSR_ID(28, "pwm_c"), + CLK_MSR_ID(29, "pwm_b"), + CLK_MSR_ID(30, "pwm_a"), + CLK_MSR_ID(31, "saradc"), + CLK_MSR_ID(32, "usb_bus"), + CLK_MSR_ID(33, "dsp_b"), + CLK_MSR_ID(34, "dsp_a"), + CLK_MSR_ID(35, "axi"), + CLK_MSR_ID(36, "sys"), + CLK_MSR_ID(40, "rng_ring_osc0"), + CLK_MSR_ID(41, "rng_ring_osc1"), + CLK_MSR_ID(42, "rng_ring_osc2"), + CLK_MSR_ID(43, "rng_ring_osc3"), + CLK_MSR_ID(44, "dds_out"), + CLK_MSR_ID(45, "cpu_clk_div16"), + CLK_MSR_ID(46, "gpio_msr"), + CLK_MSR_ID(50, "osc_ring_cpu0"), + CLK_MSR_ID(51, "osc_ring_cpu1"), + CLK_MSR_ID(54, "osc_ring_top0"), + CLK_MSR_ID(55, "osc_ring_top1"), + CLK_MSR_ID(56, "osc_ring_ddr"), + CLK_MSR_ID(57, "osc_ring_dmc"), + CLK_MSR_ID(58, "osc_ring_dspa"), + CLK_MSR_ID(59, "osc_ring_dspb"), + CLK_MSR_ID(60, "osc_ring_rama"), + CLK_MSR_ID(61, "osc_ring_ramb"), +}; + +static const struct meson_msr_id clk_msr_t7[] = { + CLK_MSR_ID(0, "sys"), + CLK_MSR_ID(1, "axi"), + CLK_MSR_ID(2, "rtc"), + CLK_MSR_ID(3, "dspa"), + CLK_MSR_ID(4, "dspb"), + CLK_MSR_ID(5, "mali"), + CLK_MSR_ID(6, "sys_cpu_clk_div16"), + CLK_MSR_ID(7, "ceca"), + CLK_MSR_ID(8, "cecb"), + CLK_MSR_ID(10, "fclk_div5"), + CLK_MSR_ID(11, "mpll0"), + CLK_MSR_ID(12, "mpll1"), + CLK_MSR_ID(13, "mpll2"), + CLK_MSR_ID(14, "mpll3"), + CLK_MSR_ID(15, "mpll_50m"), + CLK_MSR_ID(16, "pcie_inp"), + CLK_MSR_ID(17, "pcie_inn"), + CLK_MSR_ID(18, "mpll_test_out"), + CLK_MSR_ID(19, "hifi_pll"), + CLK_MSR_ID(20, "gp0_pll"), + CLK_MSR_ID(21, "gp1_pll"), + CLK_MSR_ID(22, "eth_mppll_50m"), + CLK_MSR_ID(23, "sys_pll_div16"), + CLK_MSR_ID(24, "ddr_dpll_pt"), + CLK_MSR_ID(25, "earcrx_pll"), + CLK_MSR_ID(26, "paie1_clk_inp"), + CLK_MSR_ID(27, "paie1_clk_inn"), + CLK_MSR_ID(28, "amlgdc"), + CLK_MSR_ID(29, "gdc"), + CLK_MSR_ID(30, "mod_eth_phy_ref"), + CLK_MSR_ID(31, "mod_eth_tx"), + CLK_MSR_ID(32, "eth_clk125Mhz"), + CLK_MSR_ID(33, "eth_clk_rmii"), + CLK_MSR_ID(34, "co_clkin_to_mac"), + CLK_MSR_ID(35, "mod_eth_rx_clk_rmii"), + CLK_MSR_ID(36, "co_rx"), + CLK_MSR_ID(37, "co_tx"), + CLK_MSR_ID(38, "eth_phy_rxclk"), + CLK_MSR_ID(39, "eth_phy_plltxclk"), + CLK_MSR_ID(40, "ephy_test"), + CLK_MSR_ID(41, "dsi_b_meas"), + CLK_MSR_ID(42, "hdmirx_apl"), + CLK_MSR_ID(43, "hdmirx_tmds"), + CLK_MSR_ID(44, "hdmirx_cable"), + CLK_MSR_ID(45, "hdmirx_apll_clk_audio"), + CLK_MSR_ID(46, "hdmirx_5m"), + CLK_MSR_ID(47, "hdmirx_2m"), + CLK_MSR_ID(48, "hdmirx_cfg"), + CLK_MSR_ID(49, "hdmirx_hdcp2x_eclk"), + CLK_MSR_ID(50, "vid_pll0_div"), + CLK_MSR_ID(51, "hdmi_vid_pll"), + CLK_MSR_ID(54, "vdac_clk"), + CLK_MSR_ID(55, "vpu_clk_buf"), + CLK_MSR_ID(56, "mod_tcon_clko"), + CLK_MSR_ID(57, "lcd_an_clk_ph2"), + CLK_MSR_ID(58, "lcd_an_clk_ph3"), + CLK_MSR_ID(59, "hdmi_tx_pixel"), + CLK_MSR_ID(60, "vdin_meas"), + CLK_MSR_ID(61, "vpu_clk"), + CLK_MSR_ID(62, "vpu_clkb"), + CLK_MSR_ID(63, "vpu_clkb_tmp"), + CLK_MSR_ID(64, "vpu_clkc"), + CLK_MSR_ID(65, "vid_lock"), + CLK_MSR_ID(66, "vapbclk"), + CLK_MSR_ID(67, "ge2d"), + CLK_MSR_ID(68, "aud_pll"), + CLK_MSR_ID(69, "aud_sck"), + CLK_MSR_ID(70, "dsi_a_meas"), + CLK_MSR_ID(72, "mipi_csi_phy"), + CLK_MSR_ID(73, "mipi_isp"), + CLK_MSR_ID(76, "hdmitx_tmds"), + CLK_MSR_ID(77, "hdmitx_sys"), + CLK_MSR_ID(78, "hdmitx_fe"), + CLK_MSR_ID(80, "hdmitx_prif"), + CLK_MSR_ID(81, "hdmitx_200m"), + CLK_MSR_ID(82, "hdmitx_aud"), + CLK_MSR_ID(83, "hdmitx_pnx"), + CLK_MSR_ID(84, "spicc5"), + CLK_MSR_ID(85, "spicc4"), + CLK_MSR_ID(86, "spicc3"), + CLK_MSR_ID(87, "spicc2"), + CLK_MSR_ID(93, "vdec"), + CLK_MSR_ID(94, "wave521_aclk"), + CLK_MSR_ID(95, "wave521_cclk"), + CLK_MSR_ID(96, "wave521_bclk"), + CLK_MSR_ID(97, "hcodec"), + CLK_MSR_ID(98, "hevcb"), + CLK_MSR_ID(99, "hevcf"), + CLK_MSR_ID(100, "hdmi_aud_pll"), + CLK_MSR_ID(101, "hdmi_acr_ref"), + CLK_MSR_ID(102, "hdmi_meter"), + CLK_MSR_ID(103, "hdmi_vid"), + CLK_MSR_ID(104, "hdmi_aud"), + CLK_MSR_ID(105, "hdmi_dsd"), + CLK_MSR_ID(108, "dsi1_phy"), + CLK_MSR_ID(109, "dsi0_phy"), + CLK_MSR_ID(110, "smartcard"), + CLK_MSR_ID(111, "sar_adc"), + CLK_MSR_ID(113, "sd_emmc_c"), + CLK_MSR_ID(114, "sd_emmc_b"), + CLK_MSR_ID(115, "sd_emmc_a"), + CLK_MSR_ID(116, "gpio_msr"), + CLK_MSR_ID(117, "spicc1"), + CLK_MSR_ID(118, "spicc0"), + CLK_MSR_ID(119, "anakin"), + CLK_MSR_ID(121, "ts_clk(temp sensor)"), + CLK_MSR_ID(122, "ts_a73"), + CLK_MSR_ID(123, "ts_a53"), + CLK_MSR_ID(124, "ts_nna"), + CLK_MSR_ID(130, "audio_vad"), + CLK_MSR_ID(131, "acodec_dac_clk_x128"), + CLK_MSR_ID(132, "audio_locker_in"), + CLK_MSR_ID(133, "audio_locker_out"), + CLK_MSR_ID(134, "audio_tdmout_c_sclk"), + CLK_MSR_ID(135, "audio_tdmout_b_sclk"), + CLK_MSR_ID(136, "audio_tdmout_a_sclk"), + CLK_MSR_ID(137, "audio_tdmin_lb_sclk"), + CLK_MSR_ID(138, "audio_tdmin_c_sclk"), + CLK_MSR_ID(139, "audio_tdmin_b_sclk"), + CLK_MSR_ID(140, "audio_tdmin_a_sclk"), + CLK_MSR_ID(141, "audio_resamplea"), + CLK_MSR_ID(142, "audio_pdm_sysclk"), + CLK_MSR_ID(143, "audio_spdifoutb_mst"), + CLK_MSR_ID(144, "audio_spdifout_mst"), + CLK_MSR_ID(145, "audio_spdifin_mst"), + CLK_MSR_ID(146, "audio_pdm_dclk"), + CLK_MSR_ID(147, "audio_resampleb"), + CLK_MSR_ID(148, "earcrx_pll_dmac"), + CLK_MSR_ID(156, "pwm_ao_h"), + CLK_MSR_ID(157, "pwm_ao_g"), + CLK_MSR_ID(158, "pwm_ao_f"), + CLK_MSR_ID(159, "pwm_ao_e"), + CLK_MSR_ID(160, "pwm_ao_d"), + CLK_MSR_ID(161, "pwm_ao_c"), + CLK_MSR_ID(162, "pwm_ao_b"), + CLK_MSR_ID(163, "pwm_ao_a"), + CLK_MSR_ID(164, "pwm_f"), + CLK_MSR_ID(165, "pwm_e"), + CLK_MSR_ID(166, "pwm_d"), + CLK_MSR_ID(167, "pwm_c"), + CLK_MSR_ID(168, "pwm_b"), + CLK_MSR_ID(169, "pwm_a"), + CLK_MSR_ID(170, "aclkm"), + CLK_MSR_ID(171, "mclk_pll"), + CLK_MSR_ID(172, "a73_sys_pll_div16"), + CLK_MSR_ID(173, "a73_cpu_clk_div16"), + CLK_MSR_ID(176, "rng_ring_0"), + CLK_MSR_ID(177, "rng_ring_1"), + CLK_MSR_ID(178, "rng_ring_2"), + CLK_MSR_ID(179, "rng_ring_3"), + CLK_MSR_ID(180, "am_ring_out0"), + CLK_MSR_ID(181, "am_ring_out1"), + CLK_MSR_ID(182, "am_ring_out2"), + CLK_MSR_ID(183, "am_ring_out3"), + CLK_MSR_ID(184, "am_ring_out4"), + CLK_MSR_ID(185, "am_ring_out5"), + CLK_MSR_ID(186, "am_ring_out6"), + CLK_MSR_ID(187, "am_ring_out7"), + CLK_MSR_ID(188, "am_ring_out8"), + CLK_MSR_ID(189, "am_ring_out9"), + CLK_MSR_ID(190, "am_ring_out10"), + CLK_MSR_ID(191, "am_ring_out11"), + CLK_MSR_ID(192, "am_ring_out12"), + CLK_MSR_ID(193, "am_ring_out13"), + CLK_MSR_ID(194, "am_ring_out14"), + CLK_MSR_ID(195, "am_ring_out15"), + CLK_MSR_ID(196, "am_ring_out16"), + CLK_MSR_ID(197, "am_ring_out17"), + CLK_MSR_ID(198, "am_ring_out18"), + CLK_MSR_ID(199, "am_ring_out19"), + CLK_MSR_ID(200, "mipi_csi_phy0"), + CLK_MSR_ID(201, "mipi_csi_phy1"), + CLK_MSR_ID(202, "mipi_csi_phy2"), + CLK_MSR_ID(203, "mipi_csi_phy3"), + CLK_MSR_ID(204, "vid_pll1_div"), + CLK_MSR_ID(205, "vid_pll2_div"), + CLK_MSR_ID(206, "am_ring_out20"), + CLK_MSR_ID(207, "am_ring_out21"), + CLK_MSR_ID(208, "am_ring_out22"), + CLK_MSR_ID(209, "am_ring_out23"), + CLK_MSR_ID(210, "am_ring_out24"), + CLK_MSR_ID(211, "am_ring_out25"), + CLK_MSR_ID(212, "am_ring_out26"), + CLK_MSR_ID(213, "am_ring_out27"), + CLK_MSR_ID(214, "am_ring_out28"), + CLK_MSR_ID(215, "am_ring_out29"), + CLK_MSR_ID(216, "am_ring_out30"), + CLK_MSR_ID(217, "am_ring_out31"), + CLK_MSR_ID(218, "am_ring_out32"), + CLK_MSR_ID(219, "enc0_if"), + CLK_MSR_ID(220, "enc2"), + CLK_MSR_ID(221, "enc1"), + CLK_MSR_ID(222, "enc0") +}; + +static int meson_measure_id(struct meson_msr_id *clk_msr_id, + unsigned int duration) +{ + struct meson_msr *priv = clk_msr_id->priv; + const struct msr_reg_offset *reg = priv->data.reg; + unsigned int val; + int ret; + + ret = mutex_lock_interruptible(&measure_lock); + if (ret) + return ret; + + regmap_write(priv->regmap, reg->freq_ctrl, 0); + + /* Set measurement duration */ + regmap_update_bits(priv->regmap, reg->freq_ctrl, MSR_DURATION, + FIELD_PREP(MSR_DURATION, duration - 1)); + + /* Set ID */ + regmap_update_bits(priv->regmap, reg->freq_ctrl, MSR_CLK_SRC, + FIELD_PREP(MSR_CLK_SRC, clk_msr_id->id)); + + /* Enable & Start */ + regmap_update_bits(priv->regmap, reg->freq_ctrl, + MSR_RUN | MSR_ENABLE, + MSR_RUN | MSR_ENABLE); + + ret = regmap_read_poll_timeout(priv->regmap, reg->freq_ctrl, + val, !(val & MSR_BUSY), 10, 10000); + if (ret) { + mutex_unlock(&measure_lock); + return ret; + } + + /* Disable */ + regmap_update_bits(priv->regmap, reg->freq_ctrl, MSR_ENABLE, 0); + + /* Get the value in multiple of gate time counts */ + regmap_read(priv->regmap, reg->freq_val, &val); + + mutex_unlock(&measure_lock); + + if (val >= MSR_VAL_MASK) + return -EINVAL; + + return DIV_ROUND_CLOSEST_ULL((val & MSR_VAL_MASK) * 1000000ULL, + duration); +} + +static int meson_measure_best_id(struct meson_msr_id *clk_msr_id, + unsigned int *precision) +{ + unsigned int duration = DIV_MAX; + int ret; + + /* Start from max duration and down to min duration */ + do { + ret = meson_measure_id(clk_msr_id, duration); + if (ret >= 0) + *precision = (2 * 1000000) / duration; + else + duration -= DIV_STEP; + } while (duration >= DIV_MIN && ret == -EINVAL); + + return ret; +} + +static int clk_msr_show(struct seq_file *s, void *data) +{ + struct meson_msr_id *clk_msr_id = s->private; + unsigned int precision = 0; + int val; + + val = meson_measure_best_id(clk_msr_id, &precision); + if (val < 0) + return val; + + seq_printf(s, "%d\t+/-%dHz\n", val, precision); + + return 0; +} +DEFINE_SHOW_ATTRIBUTE(clk_msr); + +static int clk_msr_summary_show(struct seq_file *s, void *data) +{ + struct meson_msr_id *msr_table = s->private; + unsigned int msr_count = msr_table->priv->data.msr_count; + unsigned int precision = 0; + int val, i; + + seq_puts(s, " clock rate precision\n"); + seq_puts(s, "---------------------------------------------\n"); + + for (i = 0 ; i < msr_count ; ++i) { + if (!msr_table[i].name) + continue; + + val = meson_measure_best_id(&msr_table[i], &precision); + if (val < 0) + return val; + + seq_printf(s, " %-20s %10d +/-%dHz\n", + msr_table[i].name, val, precision); + } + + return 0; +} +DEFINE_SHOW_ATTRIBUTE(clk_msr_summary); + +static struct regmap_config meson_clk_msr_regmap_config = { + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, +}; + +static int meson_msr_probe(struct platform_device *pdev) +{ + const struct meson_msr_data *match_data; + struct meson_msr *priv; + struct dentry *root, *clks; + struct resource *res; + void __iomem *base; + int i; + + priv = devm_kzalloc(&pdev->dev, sizeof(struct meson_msr), + GFP_KERNEL); + if (!priv) + return -ENOMEM; + + match_data = device_get_match_data(&pdev->dev); + if (!match_data) { + dev_err(&pdev->dev, "failed to get match data\n"); + return -ENODEV; + } + + priv->data.msr_table = devm_kcalloc(&pdev->dev, + match_data->msr_count, + sizeof(struct meson_msr_id), + GFP_KERNEL); + if (!priv->data.msr_table) + return -ENOMEM; + + memcpy(priv->data.msr_table, match_data->msr_table, + match_data->msr_count * sizeof(struct meson_msr_id)); + priv->data.msr_count = match_data->msr_count; + + base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); + if (IS_ERR(base)) + return PTR_ERR(base); + + meson_clk_msr_regmap_config.max_register = resource_size(res) - 4; + priv->regmap = devm_regmap_init_mmio(&pdev->dev, base, + &meson_clk_msr_regmap_config); + if (IS_ERR(priv->regmap)) + return PTR_ERR(priv->regmap); + + priv->data.reg = devm_kzalloc(&pdev->dev, sizeof(struct msr_reg_offset), + GFP_KERNEL); + if (!priv->data.reg) + return -ENOMEM; + + memcpy((void *)priv->data.reg, match_data->reg, + sizeof(struct msr_reg_offset)); + + root = debugfs_create_dir("meson-clk-msr", NULL); + priv->debugfs_root = root; + clks = debugfs_create_dir("clks", root); + + debugfs_create_file("measure_summary", 0444, root, + priv->data.msr_table, &clk_msr_summary_fops); + + for (i = 0 ; i < priv->data.msr_count ; ++i) { + if (!priv->data.msr_table[i].name) + continue; + + priv->data.msr_table[i].priv = priv; + + debugfs_create_file(priv->data.msr_table[i].name, 0444, clks, + &priv->data.msr_table[i], &clk_msr_fops); + } + + platform_set_drvdata(pdev, priv); + + return 0; +} + +static void meson_msr_remove(struct platform_device *pdev) +{ + struct meson_msr *priv = platform_get_drvdata(pdev); + + if (!IS_ERR_OR_NULL(priv->debugfs_root)) + debugfs_remove_recursive(priv->debugfs_root); +} + +static const struct msr_reg_offset msr_reg_offset = { + .duty_val = 0x0, + .freq_ctrl = 0x4, + .duty_ctrl = 0x8, + .freq_val = 0xc, +}; + +static const struct meson_msr_data clk_msr_gx_data = { + .msr_table = (void *)clk_msr_gx, + .msr_count = ARRAY_SIZE(clk_msr_gx), + .reg = &msr_reg_offset, +}; + +static const struct meson_msr_data clk_msr_m8_data = { + .msr_table = (void *)clk_msr_m8, + .msr_count = ARRAY_SIZE(clk_msr_m8), + .reg = &msr_reg_offset, +}; + +static const struct meson_msr_data clk_msr_axg_data = { + .msr_table = (void *)clk_msr_axg, + .msr_count = ARRAY_SIZE(clk_msr_axg), + .reg = &msr_reg_offset, +}; + +static const struct meson_msr_data clk_msr_g12a_data = { + .msr_table = (void *)clk_msr_g12a, + .msr_count = ARRAY_SIZE(clk_msr_g12a), + .reg = &msr_reg_offset, +}; + +static const struct meson_msr_data clk_msr_sm1_data = { + .msr_table = (void *)clk_msr_sm1, + .msr_count = ARRAY_SIZE(clk_msr_sm1), + .reg = &msr_reg_offset, +}; + +static const struct msr_reg_offset msr_reg_offset_v2 = { + .freq_ctrl = 0x0, + .duty_ctrl = 0x4, + .freq_val = 0x8, + .duty_val = 0x18, +}; + +static const struct meson_msr_data clk_msr_c3_data = { + .msr_table = (void *)clk_msr_c3, + .msr_count = ARRAY_SIZE(clk_msr_c3), + .reg = &msr_reg_offset_v2, +}; + +static const struct meson_msr_data clk_msr_s4_data = { + .msr_table = (void *)clk_msr_s4, + .msr_count = ARRAY_SIZE(clk_msr_s4), + .reg = &msr_reg_offset_v2, +}; + +static const struct meson_msr_data clk_msr_a1_data = { + .msr_table = (void *)clk_msr_a1, + .msr_count = ARRAY_SIZE(clk_msr_a1), + .reg = &msr_reg_offset_v2, +}; + +static const struct meson_msr_data clk_msr_t7_data = { + .msr_table = (void *)clk_msr_t7, + .msr_count = ARRAY_SIZE(clk_msr_t7), + .reg = &msr_reg_offset_v2, +}; + +static const struct of_device_id meson_msr_match_table[] = { + { + .compatible = "amlogic,meson-gx-clk-measure", + .data = &clk_msr_gx_data, + }, + { + .compatible = "amlogic,meson8-clk-measure", + .data = &clk_msr_m8_data, + }, + { + .compatible = "amlogic,meson8b-clk-measure", + .data = &clk_msr_m8_data, + }, + { + .compatible = "amlogic,meson-axg-clk-measure", + .data = &clk_msr_axg_data, + }, + { + .compatible = "amlogic,meson-g12a-clk-measure", + .data = &clk_msr_g12a_data, + }, + { + .compatible = "amlogic,meson-sm1-clk-measure", + .data = &clk_msr_sm1_data, + }, + { + .compatible = "amlogic,c3-clk-measure", + .data = &clk_msr_c3_data, + }, + { + .compatible = "amlogic,s4-clk-measure", + .data = &clk_msr_s4_data, + }, + { + .compatible = "amlogic,a1-clk-measure", + .data = &clk_msr_a1_data, + }, + { + .compatible = "amlogic,t7-clk-measure", + .data = &clk_msr_t7_data, + }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, meson_msr_match_table); + +static struct platform_driver meson_msr_driver = { + .probe = meson_msr_probe, + .remove = meson_msr_remove, + .driver = { + .name = "meson_msr", + .of_match_table = meson_msr_match_table, + }, +}; +module_platform_driver(meson_msr_driver); +MODULE_DESCRIPTION("Amlogic Meson SoC Clock Measure driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/soc/amlogic/meson-gx-socinfo.c b/drivers/soc/amlogic/meson-gx-socinfo.c new file mode 100644 index 000000000..c20f685e5 --- /dev/null +++ b/drivers/soc/amlogic/meson-gx-socinfo.c @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2017 BayLibre, SAS + * Author: Neil Armstrong + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define AO_SEC_SD_CFG8 0xe0 +#define AO_SEC_SOCINFO_OFFSET AO_SEC_SD_CFG8 + +#define SOCINFO_MAJOR GENMASK(31, 24) +#define SOCINFO_PACK GENMASK(23, 16) +#define SOCINFO_MINOR GENMASK(15, 8) +#define SOCINFO_MISC GENMASK(7, 0) + +static const struct meson_gx_soc_id { + const char *name; + unsigned int id; +} soc_ids[] = { + { "GXBB", 0x1f }, + { "GXTVBB", 0x20 }, + { "GXL", 0x21 }, + { "GXM", 0x22 }, + { "TXL", 0x23 }, + { "TXLX", 0x24 }, + { "AXG", 0x25 }, + { "GXLX", 0x26 }, + { "TXHD", 0x27 }, + { "G12A", 0x28 }, + { "G12B", 0x29 }, + { "SM1", 0x2b }, + { "A1", 0x2c }, + { "T7", 0x36 }, + { "S4", 0x37 }, + { "A5", 0x3c }, + { "C3", 0x3d }, + { "A4", 0x40 }, + { "S7", 0x46 }, + { "S7D", 0x47 }, + { "S6", 0x48 }, +}; + +static const struct meson_gx_package_id { + const char *name; + unsigned int major_id; + unsigned int pack_id; + unsigned int pack_mask; +} soc_packages[] = { + { "S905", 0x1f, 0, 0x20 }, /* pack_id != 0x20 */ + { "S905H", 0x1f, 0x3, 0xf }, /* pack_id & 0xf == 0x3 */ + { "S905M", 0x1f, 0x20, 0xf0 }, /* pack_id == 0x20 */ + { "S905D", 0x21, 0, 0xf0 }, + { "S905X", 0x21, 0x80, 0xf0 }, + { "S905W", 0x21, 0xa0, 0xf0 }, + { "S905L", 0x21, 0xc0, 0xf0 }, + { "S905M2", 0x21, 0xe0, 0xf0 }, + { "S805X", 0x21, 0x30, 0xf0 }, + { "S805Y", 0x21, 0xb0, 0xf0 }, + { "S912", 0x22, 0, 0x0 }, /* Only S912 is known for GXM */ + { "962X", 0x24, 0x10, 0xf0 }, + { "962E", 0x24, 0x20, 0xf0 }, + { "A113X", 0x25, 0x37, 0xff }, + { "A113X", 0x25, 0x43, 0xff }, + { "A113D", 0x25, 0x22, 0xff }, + { "S905L", 0x26, 0, 0x0 }, + { "S905D2", 0x28, 0x10, 0xf0 }, + { "S905Y2", 0x28, 0x30, 0xf0 }, + { "S905X2", 0x28, 0x40, 0xf0 }, + { "A311D", 0x29, 0x10, 0xf0 }, + { "S922X", 0x29, 0x40, 0xf0 }, + { "S905D3", 0x2b, 0x4, 0xf5 }, + { "S905X3", 0x2b, 0x5, 0xf5 }, + { "S905X3", 0x2b, 0x10, 0x3f }, + { "S905D3", 0x2b, 0x30, 0x3f }, + { "A113L", 0x2c, 0x0, 0xf8 }, + { "S805X2", 0x37, 0x2, 0xf }, + { "S905Y4", 0x37, 0x3, 0xf }, + { "C308L", 0x3d, 0x1, 0xf }, + { "A311D2", 0x36, 0x1, 0xf }, + { "A113X2", 0x3c, 0x1, 0xf }, + { "A113L2", 0x40, 0x1, 0xf }, + { "S805X3", 0x46, 0x3, 0xf }, + { "S905X5M", 0x47, 0x1, 0xf }, + { "S905X5", 0x48, 0x1, 0xf }, +}; + +static inline unsigned int socinfo_to_major(u32 socinfo) +{ + return FIELD_GET(SOCINFO_MAJOR, socinfo); +} + +static inline unsigned int socinfo_to_minor(u32 socinfo) +{ + return FIELD_GET(SOCINFO_MINOR, socinfo); +} + +static inline unsigned int socinfo_to_pack(u32 socinfo) +{ + return FIELD_GET(SOCINFO_PACK, socinfo); +} + +static inline unsigned int socinfo_to_misc(u32 socinfo) +{ + return FIELD_GET(SOCINFO_MISC, socinfo); +} + +static const char *socinfo_to_package_id(u32 socinfo) +{ + unsigned int pack = socinfo_to_pack(socinfo); + unsigned int major = socinfo_to_major(socinfo); + int i; + + for (i = 0 ; i < ARRAY_SIZE(soc_packages) ; ++i) { + if (soc_packages[i].major_id == major && + soc_packages[i].pack_id == + (pack & soc_packages[i].pack_mask)) + return soc_packages[i].name; + } + + return "Unknown"; +} + +static const char *socinfo_to_soc_id(u32 socinfo) +{ + unsigned int id = socinfo_to_major(socinfo); + int i; + + for (i = 0 ; i < ARRAY_SIZE(soc_ids) ; ++i) { + if (soc_ids[i].id == id) + return soc_ids[i].name; + } + + return "Unknown"; +} + +static int __init meson_gx_socinfo_init(void) +{ + struct soc_device_attribute *soc_dev_attr; + struct soc_device *soc_dev; + struct device_node *np; + struct regmap *regmap; + unsigned int socinfo; + struct device *dev; + int ret; + + /* look up for chipid node */ + np = of_find_compatible_node(NULL, NULL, "amlogic,meson-gx-ao-secure"); + if (!np) + return -ENODEV; + + /* check if interface is enabled */ + if (!of_device_is_available(np)) { + of_node_put(np); + return -ENODEV; + } + + /* check if chip-id is available */ + if (!of_property_read_bool(np, "amlogic,has-chip-id")) { + of_node_put(np); + return -ENODEV; + } + + /* node should be a syscon */ + regmap = syscon_node_to_regmap(np); + of_node_put(np); + if (IS_ERR(regmap)) { + pr_err("%s: failed to get regmap\n", __func__); + return -ENODEV; + } + + ret = regmap_read(regmap, AO_SEC_SOCINFO_OFFSET, &socinfo); + if (ret < 0) + return ret; + + if (!socinfo) { + pr_err("%s: invalid chipid value\n", __func__); + return -EINVAL; + } + + soc_dev_attr = kzalloc_obj(*soc_dev_attr); + if (!soc_dev_attr) + return -ENODEV; + + soc_dev_attr->family = "Amlogic Meson"; + soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%x:%x - %x:%x", + socinfo_to_major(socinfo), + socinfo_to_minor(socinfo), + socinfo_to_pack(socinfo), + socinfo_to_misc(socinfo)); + soc_dev_attr->soc_id = kasprintf(GFP_KERNEL, "%s (%s)", + socinfo_to_soc_id(socinfo), + socinfo_to_package_id(socinfo)); + + soc_dev = soc_device_register(soc_dev_attr); + if (IS_ERR(soc_dev)) { + kfree(soc_dev_attr->revision); + kfree_const(soc_dev_attr->soc_id); + kfree(soc_dev_attr); + return PTR_ERR(soc_dev); + } + dev = soc_device_to_device(soc_dev); + + dev_info(dev, "Amlogic Meson %s Revision %x:%x (%x:%x) Detected\n", + soc_dev_attr->soc_id, + socinfo_to_major(socinfo), + socinfo_to_minor(socinfo), + socinfo_to_pack(socinfo), + socinfo_to_misc(socinfo)); + + return 0; +} +device_initcall(meson_gx_socinfo_init); diff --git a/drivers/soc/amlogic/meson-mx-socinfo.c b/drivers/soc/amlogic/meson-mx-socinfo.c new file mode 100644 index 000000000..e1a7795a2 --- /dev/null +++ b/drivers/soc/amlogic/meson-mx-socinfo.c @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2017 Martin Blumenstingl + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MESON_SOCINFO_MAJOR_VER_MESON6 0x16 +#define MESON_SOCINFO_MAJOR_VER_MESON8 0x19 +#define MESON_SOCINFO_MAJOR_VER_MESON8B 0x1b + +#define MESON_MX_ASSIST_HW_REV 0x14c + +#define MESON_MX_ANALOG_TOP_METAL_REVISION 0x0 + +#define MESON_MX_BOOTROM_MISC_VER 0x4 + +static const char *meson_mx_socinfo_revision(unsigned int major_ver, + unsigned int misc_ver, + unsigned int metal_rev) +{ + unsigned int minor_ver; + + switch (major_ver) { + case MESON_SOCINFO_MAJOR_VER_MESON6: + minor_ver = 0xa; + break; + + case MESON_SOCINFO_MAJOR_VER_MESON8: + if (metal_rev == 0x11111112) + major_ver = 0x1d; + + if (metal_rev == 0x11111111 || metal_rev == 0x11111112) + minor_ver = 0xa; + else if (metal_rev == 0x11111113) + minor_ver = 0xb; + else if (metal_rev == 0x11111133) + minor_ver = 0xc; + else + minor_ver = 0xd; + + break; + + case MESON_SOCINFO_MAJOR_VER_MESON8B: + if (metal_rev == 0x11111111) + minor_ver = 0xa; + else + minor_ver = 0xb; + + break; + + default: + minor_ver = 0x0; + break; + } + + return kasprintf(GFP_KERNEL, "Rev%X (%x - 0:%X)", minor_ver, major_ver, + misc_ver); +} + +static const char *meson_mx_socinfo_soc_id(unsigned int major_ver, + unsigned int metal_rev) +{ + const char *soc_id; + + switch (major_ver) { + case MESON_SOCINFO_MAJOR_VER_MESON6: + soc_id = "Meson6 (AML8726-MX)"; + break; + + case MESON_SOCINFO_MAJOR_VER_MESON8: + if (metal_rev == 0x11111112) + soc_id = "Meson8m2 (S812)"; + else + soc_id = "Meson8 (S802)"; + + break; + + case MESON_SOCINFO_MAJOR_VER_MESON8B: + soc_id = "Meson8b (S805)"; + break; + + default: + soc_id = "Unknown"; + break; + } + + return kstrdup_const(soc_id, GFP_KERNEL); +} + +static const struct of_device_id meson_mx_socinfo_analog_top_ids[] = { + { .compatible = "amlogic,meson8-analog-top", }, + { .compatible = "amlogic,meson8b-analog-top", }, + { /* sentinel */ } +}; + +static int __init meson_mx_socinfo_init(void) +{ + struct soc_device_attribute *soc_dev_attr; + struct soc_device *soc_dev; + struct device_node *np; + struct regmap *assist_regmap, *bootrom_regmap, *analog_top_regmap; + unsigned int major_ver, misc_ver, metal_rev = 0; + int ret; + + assist_regmap = + syscon_regmap_lookup_by_compatible("amlogic,meson-mx-assist"); + if (IS_ERR(assist_regmap)) + return PTR_ERR(assist_regmap); + + bootrom_regmap = + syscon_regmap_lookup_by_compatible("amlogic,meson-mx-bootrom"); + if (IS_ERR(bootrom_regmap)) + return PTR_ERR(bootrom_regmap); + + np = of_find_matching_node(NULL, meson_mx_socinfo_analog_top_ids); + if (np) { + analog_top_regmap = syscon_node_to_regmap(np); + of_node_put(np); + if (IS_ERR(analog_top_regmap)) + return PTR_ERR(analog_top_regmap); + + ret = regmap_read(analog_top_regmap, + MESON_MX_ANALOG_TOP_METAL_REVISION, + &metal_rev); + if (ret) + return ret; + } + + ret = regmap_read(assist_regmap, MESON_MX_ASSIST_HW_REV, &major_ver); + if (ret < 0) + return ret; + + ret = regmap_read(bootrom_regmap, MESON_MX_BOOTROM_MISC_VER, + &misc_ver); + if (ret < 0) + return ret; + + soc_dev_attr = kzalloc_obj(*soc_dev_attr); + if (!soc_dev_attr) + return -ENODEV; + + soc_dev_attr->family = "Amlogic Meson"; + + np = of_find_node_by_path("/"); + of_property_read_string(np, "model", &soc_dev_attr->machine); + of_node_put(np); + + soc_dev_attr->revision = meson_mx_socinfo_revision(major_ver, misc_ver, + metal_rev); + soc_dev_attr->soc_id = meson_mx_socinfo_soc_id(major_ver, metal_rev); + + soc_dev = soc_device_register(soc_dev_attr); + if (IS_ERR(soc_dev)) { + kfree_const(soc_dev_attr->revision); + kfree_const(soc_dev_attr->soc_id); + kfree(soc_dev_attr); + return PTR_ERR(soc_dev); + } + + dev_info(soc_device_to_device(soc_dev), "Amlogic %s %s detected\n", + soc_dev_attr->soc_id, soc_dev_attr->revision); + + return 0; +} +device_initcall(meson_mx_socinfo_init); -- cgit v1.3.1