xref: /openbmc/linux/drivers/soc/amlogic/meson-clk-measure.c (revision 03ab8e6297acd1bc0eedaa050e2a1635c576fd11)
12b45ebefSNeil Armstrong // SPDX-License-Identifier: GPL-2.0+
22b45ebefSNeil Armstrong /*
32b45ebefSNeil Armstrong  * Copyright (c) 2018 BayLibre, SAS
42b45ebefSNeil Armstrong  * Author: Neil Armstrong <narmstrong@baylibre.com>
52b45ebefSNeil Armstrong  */
62b45ebefSNeil Armstrong 
72b45ebefSNeil Armstrong #include <linux/of_address.h>
82b45ebefSNeil Armstrong #include <linux/platform_device.h>
92b45ebefSNeil Armstrong #include <linux/bitfield.h>
102b45ebefSNeil Armstrong #include <linux/seq_file.h>
112b45ebefSNeil Armstrong #include <linux/debugfs.h>
122b45ebefSNeil Armstrong #include <linux/regmap.h>
13d9da1785SKevin Hilman #include <linux/module.h>
142b45ebefSNeil Armstrong 
153a760d98SNeil Armstrong static DEFINE_MUTEX(measure_lock);
163a760d98SNeil Armstrong 
172b45ebefSNeil Armstrong #define MSR_CLK_DUTY		0x0
182b45ebefSNeil Armstrong #define MSR_CLK_REG0		0x4
192b45ebefSNeil Armstrong #define MSR_CLK_REG1		0x8
202b45ebefSNeil Armstrong #define MSR_CLK_REG2		0xc
212b45ebefSNeil Armstrong 
222b45ebefSNeil Armstrong #define MSR_DURATION		GENMASK(15, 0)
232b45ebefSNeil Armstrong #define MSR_ENABLE		BIT(16)
242b45ebefSNeil Armstrong #define MSR_CONT		BIT(17) /* continuous measurement */
252b45ebefSNeil Armstrong #define MSR_INTR		BIT(18) /* interrupts */
262b45ebefSNeil Armstrong #define MSR_RUN			BIT(19)
272b45ebefSNeil Armstrong #define MSR_CLK_SRC		GENMASK(26, 20)
282b45ebefSNeil Armstrong #define MSR_BUSY		BIT(31)
292b45ebefSNeil Armstrong 
302b45ebefSNeil Armstrong #define MSR_VAL_MASK		GENMASK(15, 0)
312b45ebefSNeil Armstrong 
322b45ebefSNeil Armstrong #define DIV_MIN			32
332b45ebefSNeil Armstrong #define DIV_STEP		32
342b45ebefSNeil Armstrong #define DIV_MAX			640
352b45ebefSNeil Armstrong 
362b45ebefSNeil Armstrong #define CLK_MSR_MAX		128
372b45ebefSNeil Armstrong 
382b45ebefSNeil Armstrong struct meson_msr_id {
392b45ebefSNeil Armstrong 	struct meson_msr *priv;
402b45ebefSNeil Armstrong 	unsigned int id;
412b45ebefSNeil Armstrong 	const char *name;
422b45ebefSNeil Armstrong };
432b45ebefSNeil Armstrong 
442b45ebefSNeil Armstrong struct meson_msr {
452b45ebefSNeil Armstrong 	struct regmap *regmap;
462b45ebefSNeil Armstrong 	struct meson_msr_id msr_table[CLK_MSR_MAX];
472b45ebefSNeil Armstrong };
482b45ebefSNeil Armstrong 
492b45ebefSNeil Armstrong #define CLK_MSR_ID(__id, __name) \
502b45ebefSNeil Armstrong 	[__id] = {.id = __id, .name = __name,}
512b45ebefSNeil Armstrong 
522b45ebefSNeil Armstrong static struct meson_msr_id clk_msr_m8[CLK_MSR_MAX] = {
532b45ebefSNeil Armstrong 	CLK_MSR_ID(0, "ring_osc_out_ee0"),
542b45ebefSNeil Armstrong 	CLK_MSR_ID(1, "ring_osc_out_ee1"),
552b45ebefSNeil Armstrong 	CLK_MSR_ID(2, "ring_osc_out_ee2"),
562b45ebefSNeil Armstrong 	CLK_MSR_ID(3, "a9_ring_osck"),
572b45ebefSNeil Armstrong 	CLK_MSR_ID(6, "vid_pll"),
582b45ebefSNeil Armstrong 	CLK_MSR_ID(7, "clk81"),
592b45ebefSNeil Armstrong 	CLK_MSR_ID(8, "encp"),
602b45ebefSNeil Armstrong 	CLK_MSR_ID(9, "encl"),
612b45ebefSNeil Armstrong 	CLK_MSR_ID(11, "eth_rmii"),
622b45ebefSNeil Armstrong 	CLK_MSR_ID(13, "amclk"),
632b45ebefSNeil Armstrong 	CLK_MSR_ID(14, "fec_clk_0"),
642b45ebefSNeil Armstrong 	CLK_MSR_ID(15, "fec_clk_1"),
652b45ebefSNeil Armstrong 	CLK_MSR_ID(16, "fec_clk_2"),
662b45ebefSNeil Armstrong 	CLK_MSR_ID(18, "a9_clk_div16"),
672b45ebefSNeil Armstrong 	CLK_MSR_ID(19, "hdmi_sys"),
682b45ebefSNeil Armstrong 	CLK_MSR_ID(20, "rtc_osc_clk_out"),
692b45ebefSNeil Armstrong 	CLK_MSR_ID(21, "i2s_clk_in_src0"),
702b45ebefSNeil Armstrong 	CLK_MSR_ID(22, "clk_rmii_from_pad"),
712b45ebefSNeil Armstrong 	CLK_MSR_ID(23, "hdmi_ch0_tmds"),
722b45ebefSNeil Armstrong 	CLK_MSR_ID(24, "lvds_fifo"),
732b45ebefSNeil Armstrong 	CLK_MSR_ID(26, "sc_clk_int"),
742b45ebefSNeil Armstrong 	CLK_MSR_ID(28, "sar_adc"),
752b45ebefSNeil Armstrong 	CLK_MSR_ID(30, "mpll_clk_test_out"),
762b45ebefSNeil Armstrong 	CLK_MSR_ID(31, "audac_clkpi"),
772b45ebefSNeil Armstrong 	CLK_MSR_ID(32, "vdac"),
782b45ebefSNeil Armstrong 	CLK_MSR_ID(33, "sdhc_rx"),
792b45ebefSNeil Armstrong 	CLK_MSR_ID(34, "sdhc_sd"),
802b45ebefSNeil Armstrong 	CLK_MSR_ID(35, "mali"),
812b45ebefSNeil Armstrong 	CLK_MSR_ID(36, "hdmi_tx_pixel"),
822b45ebefSNeil Armstrong 	CLK_MSR_ID(38, "vdin_meas"),
832b45ebefSNeil Armstrong 	CLK_MSR_ID(39, "pcm_sclk"),
842b45ebefSNeil Armstrong 	CLK_MSR_ID(40, "pcm_mclk"),
852b45ebefSNeil Armstrong 	CLK_MSR_ID(41, "eth_rx_tx"),
862b45ebefSNeil Armstrong 	CLK_MSR_ID(42, "pwm_d"),
872b45ebefSNeil Armstrong 	CLK_MSR_ID(43, "pwm_c"),
882b45ebefSNeil Armstrong 	CLK_MSR_ID(44, "pwm_b"),
892b45ebefSNeil Armstrong 	CLK_MSR_ID(45, "pwm_a"),
902b45ebefSNeil Armstrong 	CLK_MSR_ID(46, "pcm2_sclk"),
912b45ebefSNeil Armstrong 	CLK_MSR_ID(47, "ddr_dpll_pt"),
922b45ebefSNeil Armstrong 	CLK_MSR_ID(48, "pwm_f"),
932b45ebefSNeil Armstrong 	CLK_MSR_ID(49, "pwm_e"),
942b45ebefSNeil Armstrong 	CLK_MSR_ID(59, "hcodec"),
952b45ebefSNeil Armstrong 	CLK_MSR_ID(60, "usb_32k_alt"),
962b45ebefSNeil Armstrong 	CLK_MSR_ID(61, "gpio"),
972b45ebefSNeil Armstrong 	CLK_MSR_ID(62, "vid2_pll"),
982b45ebefSNeil Armstrong 	CLK_MSR_ID(63, "mipi_csi_cfg"),
992b45ebefSNeil Armstrong };
1002b45ebefSNeil Armstrong 
1012b45ebefSNeil Armstrong static struct meson_msr_id clk_msr_gx[CLK_MSR_MAX] = {
1022b45ebefSNeil Armstrong 	CLK_MSR_ID(0, "ring_osc_out_ee_0"),
1032b45ebefSNeil Armstrong 	CLK_MSR_ID(1, "ring_osc_out_ee_1"),
1042b45ebefSNeil Armstrong 	CLK_MSR_ID(2, "ring_osc_out_ee_2"),
1052b45ebefSNeil Armstrong 	CLK_MSR_ID(3, "a53_ring_osc"),
1062b45ebefSNeil Armstrong 	CLK_MSR_ID(4, "gp0_pll"),
1072b45ebefSNeil Armstrong 	CLK_MSR_ID(6, "enci"),
1082b45ebefSNeil Armstrong 	CLK_MSR_ID(7, "clk81"),
1092b45ebefSNeil Armstrong 	CLK_MSR_ID(8, "encp"),
1102b45ebefSNeil Armstrong 	CLK_MSR_ID(9, "encl"),
1112b45ebefSNeil Armstrong 	CLK_MSR_ID(10, "vdac"),
1122b45ebefSNeil Armstrong 	CLK_MSR_ID(11, "rgmii_tx"),
1132b45ebefSNeil Armstrong 	CLK_MSR_ID(12, "pdm"),
1142b45ebefSNeil Armstrong 	CLK_MSR_ID(13, "amclk"),
1152b45ebefSNeil Armstrong 	CLK_MSR_ID(14, "fec_0"),
1162b45ebefSNeil Armstrong 	CLK_MSR_ID(15, "fec_1"),
1172b45ebefSNeil Armstrong 	CLK_MSR_ID(16, "fec_2"),
1182b45ebefSNeil Armstrong 	CLK_MSR_ID(17, "sys_pll_div16"),
1192b45ebefSNeil Armstrong 	CLK_MSR_ID(18, "sys_cpu_div16"),
1202b45ebefSNeil Armstrong 	CLK_MSR_ID(19, "hdmitx_sys"),
1212b45ebefSNeil Armstrong 	CLK_MSR_ID(20, "rtc_osc_out"),
1222b45ebefSNeil Armstrong 	CLK_MSR_ID(21, "i2s_in_src0"),
1232b45ebefSNeil Armstrong 	CLK_MSR_ID(22, "eth_phy_ref"),
1242b45ebefSNeil Armstrong 	CLK_MSR_ID(23, "hdmi_todig"),
1252b45ebefSNeil Armstrong 	CLK_MSR_ID(26, "sc_int"),
1262b45ebefSNeil Armstrong 	CLK_MSR_ID(28, "sar_adc"),
1272b45ebefSNeil Armstrong 	CLK_MSR_ID(31, "mpll_test_out"),
1282b45ebefSNeil Armstrong 	CLK_MSR_ID(32, "vdec"),
1292b45ebefSNeil Armstrong 	CLK_MSR_ID(35, "mali"),
1302b45ebefSNeil Armstrong 	CLK_MSR_ID(36, "hdmi_tx_pixel"),
1312b45ebefSNeil Armstrong 	CLK_MSR_ID(37, "i958"),
1322b45ebefSNeil Armstrong 	CLK_MSR_ID(38, "vdin_meas"),
1332b45ebefSNeil Armstrong 	CLK_MSR_ID(39, "pcm_sclk"),
1342b45ebefSNeil Armstrong 	CLK_MSR_ID(40, "pcm_mclk"),
1352b45ebefSNeil Armstrong 	CLK_MSR_ID(41, "eth_rx_or_rmii"),
1362b45ebefSNeil Armstrong 	CLK_MSR_ID(42, "mp0_out"),
1372b45ebefSNeil Armstrong 	CLK_MSR_ID(43, "fclk_div5"),
1382b45ebefSNeil Armstrong 	CLK_MSR_ID(44, "pwm_b"),
1392b45ebefSNeil Armstrong 	CLK_MSR_ID(45, "pwm_a"),
1402b45ebefSNeil Armstrong 	CLK_MSR_ID(46, "vpu"),
1412b45ebefSNeil Armstrong 	CLK_MSR_ID(47, "ddr_dpll_pt"),
1422b45ebefSNeil Armstrong 	CLK_MSR_ID(48, "mp1_out"),
1432b45ebefSNeil Armstrong 	CLK_MSR_ID(49, "mp2_out"),
1442b45ebefSNeil Armstrong 	CLK_MSR_ID(50, "mp3_out"),
1452b45ebefSNeil Armstrong 	CLK_MSR_ID(51, "nand_core"),
1462b45ebefSNeil Armstrong 	CLK_MSR_ID(52, "sd_emmc_b"),
1472b45ebefSNeil Armstrong 	CLK_MSR_ID(53, "sd_emmc_a"),
1482b45ebefSNeil Armstrong 	CLK_MSR_ID(55, "vid_pll_div_out"),
1492b45ebefSNeil Armstrong 	CLK_MSR_ID(56, "cci"),
1502b45ebefSNeil Armstrong 	CLK_MSR_ID(57, "wave420l_c"),
1512b45ebefSNeil Armstrong 	CLK_MSR_ID(58, "wave420l_b"),
1522b45ebefSNeil Armstrong 	CLK_MSR_ID(59, "hcodec"),
1532b45ebefSNeil Armstrong 	CLK_MSR_ID(60, "alt_32k"),
1542b45ebefSNeil Armstrong 	CLK_MSR_ID(61, "gpio_msr"),
1552b45ebefSNeil Armstrong 	CLK_MSR_ID(62, "hevc"),
1562b45ebefSNeil Armstrong 	CLK_MSR_ID(66, "vid_lock"),
1572b45ebefSNeil Armstrong 	CLK_MSR_ID(70, "pwm_f"),
1582b45ebefSNeil Armstrong 	CLK_MSR_ID(71, "pwm_e"),
1592b45ebefSNeil Armstrong 	CLK_MSR_ID(72, "pwm_d"),
1602b45ebefSNeil Armstrong 	CLK_MSR_ID(73, "pwm_c"),
1612b45ebefSNeil Armstrong 	CLK_MSR_ID(75, "aoclkx2_int"),
1622b45ebefSNeil Armstrong 	CLK_MSR_ID(76, "aoclk_int"),
1632b45ebefSNeil Armstrong 	CLK_MSR_ID(77, "rng_ring_osc_0"),
1642b45ebefSNeil Armstrong 	CLK_MSR_ID(78, "rng_ring_osc_1"),
1652b45ebefSNeil Armstrong 	CLK_MSR_ID(79, "rng_ring_osc_2"),
1662b45ebefSNeil Armstrong 	CLK_MSR_ID(80, "rng_ring_osc_3"),
1672b45ebefSNeil Armstrong 	CLK_MSR_ID(81, "vapb"),
1682b45ebefSNeil Armstrong 	CLK_MSR_ID(82, "ge2d"),
1692b45ebefSNeil Armstrong };
1702b45ebefSNeil Armstrong 
17119e0bde7SJerome Brunet static struct meson_msr_id clk_msr_axg[CLK_MSR_MAX] = {
17219e0bde7SJerome Brunet 	CLK_MSR_ID(0, "ring_osc_out_ee_0"),
17319e0bde7SJerome Brunet 	CLK_MSR_ID(1, "ring_osc_out_ee_1"),
17419e0bde7SJerome Brunet 	CLK_MSR_ID(2, "ring_osc_out_ee_2"),
17519e0bde7SJerome Brunet 	CLK_MSR_ID(3, "a53_ring_osc"),
17619e0bde7SJerome Brunet 	CLK_MSR_ID(4, "gp0_pll"),
17719e0bde7SJerome Brunet 	CLK_MSR_ID(5, "gp1_pll"),
17819e0bde7SJerome Brunet 	CLK_MSR_ID(7, "clk81"),
17919e0bde7SJerome Brunet 	CLK_MSR_ID(9, "encl"),
18019e0bde7SJerome Brunet 	CLK_MSR_ID(17, "sys_pll_div16"),
18119e0bde7SJerome Brunet 	CLK_MSR_ID(18, "sys_cpu_div16"),
18219e0bde7SJerome Brunet 	CLK_MSR_ID(20, "rtc_osc_out"),
18319e0bde7SJerome Brunet 	CLK_MSR_ID(23, "mmc_clk"),
18419e0bde7SJerome Brunet 	CLK_MSR_ID(28, "sar_adc"),
18519e0bde7SJerome Brunet 	CLK_MSR_ID(31, "mpll_test_out"),
18619e0bde7SJerome Brunet 	CLK_MSR_ID(40, "mod_eth_tx_clk"),
18719e0bde7SJerome Brunet 	CLK_MSR_ID(41, "mod_eth_rx_clk_rmii"),
18819e0bde7SJerome Brunet 	CLK_MSR_ID(42, "mp0_out"),
18919e0bde7SJerome Brunet 	CLK_MSR_ID(43, "fclk_div5"),
19019e0bde7SJerome Brunet 	CLK_MSR_ID(44, "pwm_b"),
19119e0bde7SJerome Brunet 	CLK_MSR_ID(45, "pwm_a"),
19219e0bde7SJerome Brunet 	CLK_MSR_ID(46, "vpu"),
19319e0bde7SJerome Brunet 	CLK_MSR_ID(47, "ddr_dpll_pt"),
19419e0bde7SJerome Brunet 	CLK_MSR_ID(48, "mp1_out"),
19519e0bde7SJerome Brunet 	CLK_MSR_ID(49, "mp2_out"),
19619e0bde7SJerome Brunet 	CLK_MSR_ID(50, "mp3_out"),
19719e0bde7SJerome Brunet 	CLK_MSR_ID(51, "sd_emmm_c"),
19819e0bde7SJerome Brunet 	CLK_MSR_ID(52, "sd_emmc_b"),
19919e0bde7SJerome Brunet 	CLK_MSR_ID(61, "gpio_msr"),
20019e0bde7SJerome Brunet 	CLK_MSR_ID(66, "audio_slv_lrclk_c"),
20119e0bde7SJerome Brunet 	CLK_MSR_ID(67, "audio_slv_lrclk_b"),
20219e0bde7SJerome Brunet 	CLK_MSR_ID(68, "audio_slv_lrclk_a"),
20319e0bde7SJerome Brunet 	CLK_MSR_ID(69, "audio_slv_sclk_c"),
20419e0bde7SJerome Brunet 	CLK_MSR_ID(70, "audio_slv_sclk_b"),
20519e0bde7SJerome Brunet 	CLK_MSR_ID(71, "audio_slv_sclk_a"),
20619e0bde7SJerome Brunet 	CLK_MSR_ID(72, "pwm_d"),
20719e0bde7SJerome Brunet 	CLK_MSR_ID(73, "pwm_c"),
20819e0bde7SJerome Brunet 	CLK_MSR_ID(74, "wifi_beacon"),
20919e0bde7SJerome Brunet 	CLK_MSR_ID(75, "tdmin_lb_lrcl"),
21019e0bde7SJerome Brunet 	CLK_MSR_ID(76, "tdmin_lb_sclk"),
21119e0bde7SJerome Brunet 	CLK_MSR_ID(77, "rng_ring_osc_0"),
21219e0bde7SJerome Brunet 	CLK_MSR_ID(78, "rng_ring_osc_1"),
21319e0bde7SJerome Brunet 	CLK_MSR_ID(79, "rng_ring_osc_2"),
21419e0bde7SJerome Brunet 	CLK_MSR_ID(80, "rng_ring_osc_3"),
21519e0bde7SJerome Brunet 	CLK_MSR_ID(81, "vapb"),
21619e0bde7SJerome Brunet 	CLK_MSR_ID(82, "ge2d"),
21719e0bde7SJerome Brunet 	CLK_MSR_ID(84, "audio_resample"),
21819e0bde7SJerome Brunet 	CLK_MSR_ID(85, "audio_pdm_sys"),
21919e0bde7SJerome Brunet 	CLK_MSR_ID(86, "audio_spdifout"),
22019e0bde7SJerome Brunet 	CLK_MSR_ID(87, "audio_spdifin"),
22119e0bde7SJerome Brunet 	CLK_MSR_ID(88, "audio_lrclk_f"),
22219e0bde7SJerome Brunet 	CLK_MSR_ID(89, "audio_lrclk_e"),
22319e0bde7SJerome Brunet 	CLK_MSR_ID(90, "audio_lrclk_d"),
22419e0bde7SJerome Brunet 	CLK_MSR_ID(91, "audio_lrclk_c"),
22519e0bde7SJerome Brunet 	CLK_MSR_ID(92, "audio_lrclk_b"),
22619e0bde7SJerome Brunet 	CLK_MSR_ID(93, "audio_lrclk_a"),
22719e0bde7SJerome Brunet 	CLK_MSR_ID(94, "audio_sclk_f"),
22819e0bde7SJerome Brunet 	CLK_MSR_ID(95, "audio_sclk_e"),
22919e0bde7SJerome Brunet 	CLK_MSR_ID(96, "audio_sclk_d"),
23019e0bde7SJerome Brunet 	CLK_MSR_ID(97, "audio_sclk_c"),
23119e0bde7SJerome Brunet 	CLK_MSR_ID(98, "audio_sclk_b"),
23219e0bde7SJerome Brunet 	CLK_MSR_ID(99, "audio_sclk_a"),
23319e0bde7SJerome Brunet 	CLK_MSR_ID(100, "audio_mclk_f"),
23419e0bde7SJerome Brunet 	CLK_MSR_ID(101, "audio_mclk_e"),
23519e0bde7SJerome Brunet 	CLK_MSR_ID(102, "audio_mclk_d"),
23619e0bde7SJerome Brunet 	CLK_MSR_ID(103, "audio_mclk_c"),
23719e0bde7SJerome Brunet 	CLK_MSR_ID(104, "audio_mclk_b"),
23819e0bde7SJerome Brunet 	CLK_MSR_ID(105, "audio_mclk_a"),
23919e0bde7SJerome Brunet 	CLK_MSR_ID(106, "pcie_refclk_n"),
24019e0bde7SJerome Brunet 	CLK_MSR_ID(107, "pcie_refclk_p"),
24119e0bde7SJerome Brunet 	CLK_MSR_ID(108, "audio_locker_out"),
24219e0bde7SJerome Brunet 	CLK_MSR_ID(109, "audio_locker_in"),
24319e0bde7SJerome Brunet };
24419e0bde7SJerome Brunet 
24519e0bde7SJerome Brunet static struct meson_msr_id clk_msr_g12a[CLK_MSR_MAX] = {
24619e0bde7SJerome Brunet 	CLK_MSR_ID(0, "ring_osc_out_ee_0"),
24719e0bde7SJerome Brunet 	CLK_MSR_ID(1, "ring_osc_out_ee_1"),
24819e0bde7SJerome Brunet 	CLK_MSR_ID(2, "ring_osc_out_ee_2"),
24919e0bde7SJerome Brunet 	CLK_MSR_ID(3, "sys_cpu_ring_osc"),
25019e0bde7SJerome Brunet 	CLK_MSR_ID(4, "gp0_pll"),
25119e0bde7SJerome Brunet 	CLK_MSR_ID(6, "enci"),
25219e0bde7SJerome Brunet 	CLK_MSR_ID(7, "clk81"),
25319e0bde7SJerome Brunet 	CLK_MSR_ID(8, "encp"),
25419e0bde7SJerome Brunet 	CLK_MSR_ID(9, "encl"),
25519e0bde7SJerome Brunet 	CLK_MSR_ID(10, "vdac"),
25619e0bde7SJerome Brunet 	CLK_MSR_ID(11, "eth_tx"),
25719e0bde7SJerome Brunet 	CLK_MSR_ID(12, "hifi_pll"),
25819e0bde7SJerome Brunet 	CLK_MSR_ID(13, "mod_tcon"),
25919e0bde7SJerome Brunet 	CLK_MSR_ID(14, "fec_0"),
26019e0bde7SJerome Brunet 	CLK_MSR_ID(15, "fec_1"),
26119e0bde7SJerome Brunet 	CLK_MSR_ID(16, "fec_2"),
26219e0bde7SJerome Brunet 	CLK_MSR_ID(17, "sys_pll_div16"),
26319e0bde7SJerome Brunet 	CLK_MSR_ID(18, "sys_cpu_div16"),
26419e0bde7SJerome Brunet 	CLK_MSR_ID(19, "lcd_an_ph2"),
26519e0bde7SJerome Brunet 	CLK_MSR_ID(20, "rtc_osc_out"),
26619e0bde7SJerome Brunet 	CLK_MSR_ID(21, "lcd_an_ph3"),
26719e0bde7SJerome Brunet 	CLK_MSR_ID(22, "eth_phy_ref"),
26819e0bde7SJerome Brunet 	CLK_MSR_ID(23, "mpll_50m"),
26919e0bde7SJerome Brunet 	CLK_MSR_ID(24, "eth_125m"),
27019e0bde7SJerome Brunet 	CLK_MSR_ID(25, "eth_rmii"),
27119e0bde7SJerome Brunet 	CLK_MSR_ID(26, "sc_int"),
27219e0bde7SJerome Brunet 	CLK_MSR_ID(27, "in_mac"),
27319e0bde7SJerome Brunet 	CLK_MSR_ID(28, "sar_adc"),
27419e0bde7SJerome Brunet 	CLK_MSR_ID(29, "pcie_inp"),
27519e0bde7SJerome Brunet 	CLK_MSR_ID(30, "pcie_inn"),
27619e0bde7SJerome Brunet 	CLK_MSR_ID(31, "mpll_test_out"),
27719e0bde7SJerome Brunet 	CLK_MSR_ID(32, "vdec"),
27819e0bde7SJerome Brunet 	CLK_MSR_ID(33, "sys_cpu_ring_osc_1"),
27919e0bde7SJerome Brunet 	CLK_MSR_ID(34, "eth_mpll_50m"),
28019e0bde7SJerome Brunet 	CLK_MSR_ID(35, "mali"),
28119e0bde7SJerome Brunet 	CLK_MSR_ID(36, "hdmi_tx_pixel"),
28219e0bde7SJerome Brunet 	CLK_MSR_ID(37, "cdac"),
28319e0bde7SJerome Brunet 	CLK_MSR_ID(38, "vdin_meas"),
28419e0bde7SJerome Brunet 	CLK_MSR_ID(39, "bt656"),
28519e0bde7SJerome Brunet 	CLK_MSR_ID(41, "eth_rx_or_rmii"),
28619e0bde7SJerome Brunet 	CLK_MSR_ID(42, "mp0_out"),
28719e0bde7SJerome Brunet 	CLK_MSR_ID(43, "fclk_div5"),
28819e0bde7SJerome Brunet 	CLK_MSR_ID(44, "pwm_b"),
28919e0bde7SJerome Brunet 	CLK_MSR_ID(45, "pwm_a"),
29019e0bde7SJerome Brunet 	CLK_MSR_ID(46, "vpu"),
29119e0bde7SJerome Brunet 	CLK_MSR_ID(47, "ddr_dpll_pt"),
29219e0bde7SJerome Brunet 	CLK_MSR_ID(48, "mp1_out"),
29319e0bde7SJerome Brunet 	CLK_MSR_ID(49, "mp2_out"),
29419e0bde7SJerome Brunet 	CLK_MSR_ID(50, "mp3_out"),
29519e0bde7SJerome Brunet 	CLK_MSR_ID(51, "sd_emmc_c"),
29619e0bde7SJerome Brunet 	CLK_MSR_ID(52, "sd_emmc_b"),
29719e0bde7SJerome Brunet 	CLK_MSR_ID(53, "sd_emmc_a"),
29819e0bde7SJerome Brunet 	CLK_MSR_ID(54, "vpu_clkc"),
29919e0bde7SJerome Brunet 	CLK_MSR_ID(55, "vid_pll_div_out"),
30019e0bde7SJerome Brunet 	CLK_MSR_ID(56, "wave420l_a"),
30119e0bde7SJerome Brunet 	CLK_MSR_ID(57, "wave420l_c"),
30219e0bde7SJerome Brunet 	CLK_MSR_ID(58, "wave420l_b"),
30319e0bde7SJerome Brunet 	CLK_MSR_ID(59, "hcodec"),
30419e0bde7SJerome Brunet 	CLK_MSR_ID(61, "gpio_msr"),
30519e0bde7SJerome Brunet 	CLK_MSR_ID(62, "hevcb"),
30619e0bde7SJerome Brunet 	CLK_MSR_ID(63, "dsi_meas"),
30719e0bde7SJerome Brunet 	CLK_MSR_ID(64, "spicc_1"),
30819e0bde7SJerome Brunet 	CLK_MSR_ID(65, "spicc_0"),
30919e0bde7SJerome Brunet 	CLK_MSR_ID(66, "vid_lock"),
31019e0bde7SJerome Brunet 	CLK_MSR_ID(67, "dsi_phy"),
31119e0bde7SJerome Brunet 	CLK_MSR_ID(68, "hdcp22_esm"),
31219e0bde7SJerome Brunet 	CLK_MSR_ID(69, "hdcp22_skp"),
31319e0bde7SJerome Brunet 	CLK_MSR_ID(70, "pwm_f"),
31419e0bde7SJerome Brunet 	CLK_MSR_ID(71, "pwm_e"),
31519e0bde7SJerome Brunet 	CLK_MSR_ID(72, "pwm_d"),
31619e0bde7SJerome Brunet 	CLK_MSR_ID(73, "pwm_c"),
31719e0bde7SJerome Brunet 	CLK_MSR_ID(75, "hevcf"),
31819e0bde7SJerome Brunet 	CLK_MSR_ID(77, "rng_ring_osc_0"),
31919e0bde7SJerome Brunet 	CLK_MSR_ID(78, "rng_ring_osc_1"),
32019e0bde7SJerome Brunet 	CLK_MSR_ID(79, "rng_ring_osc_2"),
32119e0bde7SJerome Brunet 	CLK_MSR_ID(80, "rng_ring_osc_3"),
32219e0bde7SJerome Brunet 	CLK_MSR_ID(81, "vapb"),
32319e0bde7SJerome Brunet 	CLK_MSR_ID(82, "ge2d"),
32419e0bde7SJerome Brunet 	CLK_MSR_ID(83, "co_rx"),
32519e0bde7SJerome Brunet 	CLK_MSR_ID(84, "co_tx"),
32619e0bde7SJerome Brunet 	CLK_MSR_ID(89, "hdmi_todig"),
32719e0bde7SJerome Brunet 	CLK_MSR_ID(90, "hdmitx_sys"),
328c33b2777SNeil Armstrong 	CLK_MSR_ID(91, "sys_cpub_div16"),
329c33b2777SNeil Armstrong 	CLK_MSR_ID(92, "sys_pll_cpub_div16"),
33019e0bde7SJerome Brunet 	CLK_MSR_ID(94, "eth_phy_rx"),
33119e0bde7SJerome Brunet 	CLK_MSR_ID(95, "eth_phy_pll"),
33219e0bde7SJerome Brunet 	CLK_MSR_ID(96, "vpu_b"),
33319e0bde7SJerome Brunet 	CLK_MSR_ID(97, "cpu_b_tmp"),
33419e0bde7SJerome Brunet 	CLK_MSR_ID(98, "ts"),
33519e0bde7SJerome Brunet 	CLK_MSR_ID(99, "ring_osc_out_ee_3"),
33619e0bde7SJerome Brunet 	CLK_MSR_ID(100, "ring_osc_out_ee_4"),
33719e0bde7SJerome Brunet 	CLK_MSR_ID(101, "ring_osc_out_ee_5"),
33819e0bde7SJerome Brunet 	CLK_MSR_ID(102, "ring_osc_out_ee_6"),
33919e0bde7SJerome Brunet 	CLK_MSR_ID(103, "ring_osc_out_ee_7"),
34019e0bde7SJerome Brunet 	CLK_MSR_ID(104, "ring_osc_out_ee_8"),
34119e0bde7SJerome Brunet 	CLK_MSR_ID(105, "ring_osc_out_ee_9"),
34219e0bde7SJerome Brunet 	CLK_MSR_ID(106, "ephy_test"),
34319e0bde7SJerome Brunet 	CLK_MSR_ID(107, "au_dac_g128x"),
34419e0bde7SJerome Brunet 	CLK_MSR_ID(108, "audio_locker_out"),
34519e0bde7SJerome Brunet 	CLK_MSR_ID(109, "audio_locker_in"),
34619e0bde7SJerome Brunet 	CLK_MSR_ID(110, "audio_tdmout_c_sclk"),
34719e0bde7SJerome Brunet 	CLK_MSR_ID(111, "audio_tdmout_b_sclk"),
34819e0bde7SJerome Brunet 	CLK_MSR_ID(112, "audio_tdmout_a_sclk"),
34919e0bde7SJerome Brunet 	CLK_MSR_ID(113, "audio_tdmin_lb_sclk"),
35019e0bde7SJerome Brunet 	CLK_MSR_ID(114, "audio_tdmin_c_sclk"),
35119e0bde7SJerome Brunet 	CLK_MSR_ID(115, "audio_tdmin_b_sclk"),
35219e0bde7SJerome Brunet 	CLK_MSR_ID(116, "audio_tdmin_a_sclk"),
35319e0bde7SJerome Brunet 	CLK_MSR_ID(117, "audio_resample"),
35419e0bde7SJerome Brunet 	CLK_MSR_ID(118, "audio_pdm_sys"),
35519e0bde7SJerome Brunet 	CLK_MSR_ID(119, "audio_spdifout_b"),
35619e0bde7SJerome Brunet 	CLK_MSR_ID(120, "audio_spdifout"),
35719e0bde7SJerome Brunet 	CLK_MSR_ID(121, "audio_spdifin"),
35819e0bde7SJerome Brunet 	CLK_MSR_ID(122, "audio_pdm_dclk"),
35919e0bde7SJerome Brunet };
36019e0bde7SJerome Brunet 
36162369971SNeil Armstrong static struct meson_msr_id clk_msr_sm1[CLK_MSR_MAX] = {
36262369971SNeil Armstrong 	CLK_MSR_ID(0, "ring_osc_out_ee_0"),
36362369971SNeil Armstrong 	CLK_MSR_ID(1, "ring_osc_out_ee_1"),
36462369971SNeil Armstrong 	CLK_MSR_ID(2, "ring_osc_out_ee_2"),
36562369971SNeil Armstrong 	CLK_MSR_ID(3, "ring_osc_out_ee_3"),
36662369971SNeil Armstrong 	CLK_MSR_ID(4, "gp0_pll"),
36762369971SNeil Armstrong 	CLK_MSR_ID(5, "gp1_pll"),
36862369971SNeil Armstrong 	CLK_MSR_ID(6, "enci"),
36962369971SNeil Armstrong 	CLK_MSR_ID(7, "clk81"),
37062369971SNeil Armstrong 	CLK_MSR_ID(8, "encp"),
37162369971SNeil Armstrong 	CLK_MSR_ID(9, "encl"),
37262369971SNeil Armstrong 	CLK_MSR_ID(10, "vdac"),
37362369971SNeil Armstrong 	CLK_MSR_ID(11, "eth_tx"),
37462369971SNeil Armstrong 	CLK_MSR_ID(12, "hifi_pll"),
37562369971SNeil Armstrong 	CLK_MSR_ID(13, "mod_tcon"),
37662369971SNeil Armstrong 	CLK_MSR_ID(14, "fec_0"),
37762369971SNeil Armstrong 	CLK_MSR_ID(15, "fec_1"),
37862369971SNeil Armstrong 	CLK_MSR_ID(16, "fec_2"),
37962369971SNeil Armstrong 	CLK_MSR_ID(17, "sys_pll_div16"),
38062369971SNeil Armstrong 	CLK_MSR_ID(18, "sys_cpu_div16"),
38162369971SNeil Armstrong 	CLK_MSR_ID(19, "lcd_an_ph2"),
38262369971SNeil Armstrong 	CLK_MSR_ID(20, "rtc_osc_out"),
38362369971SNeil Armstrong 	CLK_MSR_ID(21, "lcd_an_ph3"),
38462369971SNeil Armstrong 	CLK_MSR_ID(22, "eth_phy_ref"),
38562369971SNeil Armstrong 	CLK_MSR_ID(23, "mpll_50m"),
38662369971SNeil Armstrong 	CLK_MSR_ID(24, "eth_125m"),
38762369971SNeil Armstrong 	CLK_MSR_ID(25, "eth_rmii"),
38862369971SNeil Armstrong 	CLK_MSR_ID(26, "sc_int"),
38962369971SNeil Armstrong 	CLK_MSR_ID(27, "in_mac"),
39062369971SNeil Armstrong 	CLK_MSR_ID(28, "sar_adc"),
39162369971SNeil Armstrong 	CLK_MSR_ID(29, "pcie_inp"),
39262369971SNeil Armstrong 	CLK_MSR_ID(30, "pcie_inn"),
39362369971SNeil Armstrong 	CLK_MSR_ID(31, "mpll_test_out"),
39462369971SNeil Armstrong 	CLK_MSR_ID(32, "vdec"),
39562369971SNeil Armstrong 	CLK_MSR_ID(34, "eth_mpll_50m"),
39662369971SNeil Armstrong 	CLK_MSR_ID(35, "mali"),
39762369971SNeil Armstrong 	CLK_MSR_ID(36, "hdmi_tx_pixel"),
39862369971SNeil Armstrong 	CLK_MSR_ID(37, "cdac"),
39962369971SNeil Armstrong 	CLK_MSR_ID(38, "vdin_meas"),
40062369971SNeil Armstrong 	CLK_MSR_ID(39, "bt656"),
40162369971SNeil Armstrong 	CLK_MSR_ID(40, "arm_ring_osc_out_4"),
40262369971SNeil Armstrong 	CLK_MSR_ID(41, "eth_rx_or_rmii"),
40362369971SNeil Armstrong 	CLK_MSR_ID(42, "mp0_out"),
40462369971SNeil Armstrong 	CLK_MSR_ID(43, "fclk_div5"),
40562369971SNeil Armstrong 	CLK_MSR_ID(44, "pwm_b"),
40662369971SNeil Armstrong 	CLK_MSR_ID(45, "pwm_a"),
40762369971SNeil Armstrong 	CLK_MSR_ID(46, "vpu"),
40862369971SNeil Armstrong 	CLK_MSR_ID(47, "ddr_dpll_pt"),
40962369971SNeil Armstrong 	CLK_MSR_ID(48, "mp1_out"),
41062369971SNeil Armstrong 	CLK_MSR_ID(49, "mp2_out"),
41162369971SNeil Armstrong 	CLK_MSR_ID(50, "mp3_out"),
41262369971SNeil Armstrong 	CLK_MSR_ID(51, "sd_emmc_c"),
41362369971SNeil Armstrong 	CLK_MSR_ID(52, "sd_emmc_b"),
41462369971SNeil Armstrong 	CLK_MSR_ID(53, "sd_emmc_a"),
41562369971SNeil Armstrong 	CLK_MSR_ID(54, "vpu_clkc"),
41662369971SNeil Armstrong 	CLK_MSR_ID(55, "vid_pll_div_out"),
41762369971SNeil Armstrong 	CLK_MSR_ID(56, "wave420l_a"),
41862369971SNeil Armstrong 	CLK_MSR_ID(57, "wave420l_c"),
41962369971SNeil Armstrong 	CLK_MSR_ID(58, "wave420l_b"),
42062369971SNeil Armstrong 	CLK_MSR_ID(59, "hcodec"),
42162369971SNeil Armstrong 	CLK_MSR_ID(60, "arm_ring_osc_out_5"),
42262369971SNeil Armstrong 	CLK_MSR_ID(61, "gpio_msr"),
42362369971SNeil Armstrong 	CLK_MSR_ID(62, "hevcb"),
42462369971SNeil Armstrong 	CLK_MSR_ID(63, "dsi_meas"),
42562369971SNeil Armstrong 	CLK_MSR_ID(64, "spicc_1"),
42662369971SNeil Armstrong 	CLK_MSR_ID(65, "spicc_0"),
42762369971SNeil Armstrong 	CLK_MSR_ID(66, "vid_lock"),
42862369971SNeil Armstrong 	CLK_MSR_ID(67, "dsi_phy"),
42962369971SNeil Armstrong 	CLK_MSR_ID(68, "hdcp22_esm"),
43062369971SNeil Armstrong 	CLK_MSR_ID(69, "hdcp22_skp"),
43162369971SNeil Armstrong 	CLK_MSR_ID(70, "pwm_f"),
43262369971SNeil Armstrong 	CLK_MSR_ID(71, "pwm_e"),
43362369971SNeil Armstrong 	CLK_MSR_ID(72, "pwm_d"),
43462369971SNeil Armstrong 	CLK_MSR_ID(73, "pwm_c"),
43562369971SNeil Armstrong 	CLK_MSR_ID(74, "arm_ring_osc_out_6"),
43662369971SNeil Armstrong 	CLK_MSR_ID(75, "hevcf"),
43762369971SNeil Armstrong 	CLK_MSR_ID(76, "arm_ring_osc_out_7"),
43862369971SNeil Armstrong 	CLK_MSR_ID(77, "rng_ring_osc_0"),
43962369971SNeil Armstrong 	CLK_MSR_ID(78, "rng_ring_osc_1"),
44062369971SNeil Armstrong 	CLK_MSR_ID(79, "rng_ring_osc_2"),
44162369971SNeil Armstrong 	CLK_MSR_ID(80, "rng_ring_osc_3"),
44262369971SNeil Armstrong 	CLK_MSR_ID(81, "vapb"),
44362369971SNeil Armstrong 	CLK_MSR_ID(82, "ge2d"),
44462369971SNeil Armstrong 	CLK_MSR_ID(83, "co_rx"),
44562369971SNeil Armstrong 	CLK_MSR_ID(84, "co_tx"),
44662369971SNeil Armstrong 	CLK_MSR_ID(85, "arm_ring_osc_out_8"),
44762369971SNeil Armstrong 	CLK_MSR_ID(86, "arm_ring_osc_out_9"),
44862369971SNeil Armstrong 	CLK_MSR_ID(87, "mipi_dsi_phy"),
44962369971SNeil Armstrong 	CLK_MSR_ID(88, "cis2_adapt"),
45062369971SNeil Armstrong 	CLK_MSR_ID(89, "hdmi_todig"),
45162369971SNeil Armstrong 	CLK_MSR_ID(90, "hdmitx_sys"),
45262369971SNeil Armstrong 	CLK_MSR_ID(91, "nna_core"),
45362369971SNeil Armstrong 	CLK_MSR_ID(92, "nna_axi"),
45462369971SNeil Armstrong 	CLK_MSR_ID(93, "vad"),
45562369971SNeil Armstrong 	CLK_MSR_ID(94, "eth_phy_rx"),
45662369971SNeil Armstrong 	CLK_MSR_ID(95, "eth_phy_pll"),
45762369971SNeil Armstrong 	CLK_MSR_ID(96, "vpu_b"),
45862369971SNeil Armstrong 	CLK_MSR_ID(97, "cpu_b_tmp"),
45962369971SNeil Armstrong 	CLK_MSR_ID(98, "ts"),
46062369971SNeil Armstrong 	CLK_MSR_ID(99, "arm_ring_osc_out_10"),
46162369971SNeil Armstrong 	CLK_MSR_ID(100, "arm_ring_osc_out_11"),
46262369971SNeil Armstrong 	CLK_MSR_ID(101, "arm_ring_osc_out_12"),
46362369971SNeil Armstrong 	CLK_MSR_ID(102, "arm_ring_osc_out_13"),
46462369971SNeil Armstrong 	CLK_MSR_ID(103, "arm_ring_osc_out_14"),
46562369971SNeil Armstrong 	CLK_MSR_ID(104, "arm_ring_osc_out_15"),
46662369971SNeil Armstrong 	CLK_MSR_ID(105, "arm_ring_osc_out_16"),
46762369971SNeil Armstrong 	CLK_MSR_ID(106, "ephy_test"),
46862369971SNeil Armstrong 	CLK_MSR_ID(107, "au_dac_g128x"),
46962369971SNeil Armstrong 	CLK_MSR_ID(108, "audio_locker_out"),
47062369971SNeil Armstrong 	CLK_MSR_ID(109, "audio_locker_in"),
47162369971SNeil Armstrong 	CLK_MSR_ID(110, "audio_tdmout_c_sclk"),
47262369971SNeil Armstrong 	CLK_MSR_ID(111, "audio_tdmout_b_sclk"),
47362369971SNeil Armstrong 	CLK_MSR_ID(112, "audio_tdmout_a_sclk"),
47462369971SNeil Armstrong 	CLK_MSR_ID(113, "audio_tdmin_lb_sclk"),
47562369971SNeil Armstrong 	CLK_MSR_ID(114, "audio_tdmin_c_sclk"),
47662369971SNeil Armstrong 	CLK_MSR_ID(115, "audio_tdmin_b_sclk"),
47762369971SNeil Armstrong 	CLK_MSR_ID(116, "audio_tdmin_a_sclk"),
47862369971SNeil Armstrong 	CLK_MSR_ID(117, "audio_resample"),
47962369971SNeil Armstrong 	CLK_MSR_ID(118, "audio_pdm_sys"),
48062369971SNeil Armstrong 	CLK_MSR_ID(119, "audio_spdifout_b"),
48162369971SNeil Armstrong 	CLK_MSR_ID(120, "audio_spdifout"),
48262369971SNeil Armstrong 	CLK_MSR_ID(121, "audio_spdifin"),
48362369971SNeil Armstrong 	CLK_MSR_ID(122, "audio_pdm_dclk"),
48462369971SNeil Armstrong 	CLK_MSR_ID(123, "audio_resampled"),
48562369971SNeil Armstrong 	CLK_MSR_ID(124, "earcrx_pll"),
48662369971SNeil Armstrong 	CLK_MSR_ID(125, "earcrx_pll_test"),
48762369971SNeil Armstrong 	CLK_MSR_ID(126, "csi_phy0"),
48862369971SNeil Armstrong 	CLK_MSR_ID(127, "csi2_data"),
48962369971SNeil Armstrong };
49062369971SNeil Armstrong 
meson_measure_id(struct meson_msr_id * clk_msr_id,unsigned int duration)4912b45ebefSNeil Armstrong static int meson_measure_id(struct meson_msr_id *clk_msr_id,
4922b45ebefSNeil Armstrong 			       unsigned int duration)
4932b45ebefSNeil Armstrong {
4942b45ebefSNeil Armstrong 	struct meson_msr *priv = clk_msr_id->priv;
4952b45ebefSNeil Armstrong 	unsigned int val;
4962b45ebefSNeil Armstrong 	int ret;
4972b45ebefSNeil Armstrong 
4983a760d98SNeil Armstrong 	ret = mutex_lock_interruptible(&measure_lock);
4993a760d98SNeil Armstrong 	if (ret)
5003a760d98SNeil Armstrong 		return ret;
5013a760d98SNeil Armstrong 
5022b45ebefSNeil Armstrong 	regmap_write(priv->regmap, MSR_CLK_REG0, 0);
5032b45ebefSNeil Armstrong 
5042b45ebefSNeil Armstrong 	/* Set measurement duration */
5052b45ebefSNeil Armstrong 	regmap_update_bits(priv->regmap, MSR_CLK_REG0, MSR_DURATION,
5062b45ebefSNeil Armstrong 			   FIELD_PREP(MSR_DURATION, duration - 1));
5072b45ebefSNeil Armstrong 
5082b45ebefSNeil Armstrong 	/* Set ID */
5092b45ebefSNeil Armstrong 	regmap_update_bits(priv->regmap, MSR_CLK_REG0, MSR_CLK_SRC,
5102b45ebefSNeil Armstrong 			   FIELD_PREP(MSR_CLK_SRC, clk_msr_id->id));
5112b45ebefSNeil Armstrong 
5122b45ebefSNeil Armstrong 	/* Enable & Start */
5132b45ebefSNeil Armstrong 	regmap_update_bits(priv->regmap, MSR_CLK_REG0,
5142b45ebefSNeil Armstrong 			   MSR_RUN | MSR_ENABLE,
5152b45ebefSNeil Armstrong 			   MSR_RUN | MSR_ENABLE);
5162b45ebefSNeil Armstrong 
5172b45ebefSNeil Armstrong 	ret = regmap_read_poll_timeout(priv->regmap, MSR_CLK_REG0,
5182b45ebefSNeil Armstrong 				       val, !(val & MSR_BUSY), 10, 10000);
5193a760d98SNeil Armstrong 	if (ret) {
5203a760d98SNeil Armstrong 		mutex_unlock(&measure_lock);
5212b45ebefSNeil Armstrong 		return ret;
5223a760d98SNeil Armstrong 	}
5232b45ebefSNeil Armstrong 
5242b45ebefSNeil Armstrong 	/* Disable */
5252b45ebefSNeil Armstrong 	regmap_update_bits(priv->regmap, MSR_CLK_REG0, MSR_ENABLE, 0);
5262b45ebefSNeil Armstrong 
5272b45ebefSNeil Armstrong 	/* Get the value in multiple of gate time counts */
5282b45ebefSNeil Armstrong 	regmap_read(priv->regmap, MSR_CLK_REG2, &val);
5292b45ebefSNeil Armstrong 
5303a760d98SNeil Armstrong 	mutex_unlock(&measure_lock);
5313a760d98SNeil Armstrong 
5322b45ebefSNeil Armstrong 	if (val >= MSR_VAL_MASK)
5332b45ebefSNeil Armstrong 		return -EINVAL;
5342b45ebefSNeil Armstrong 
5352b45ebefSNeil Armstrong 	return DIV_ROUND_CLOSEST_ULL((val & MSR_VAL_MASK) * 1000000ULL,
5362b45ebefSNeil Armstrong 				     duration);
5372b45ebefSNeil Armstrong }
5382b45ebefSNeil Armstrong 
meson_measure_best_id(struct meson_msr_id * clk_msr_id,unsigned int * precision)5392b45ebefSNeil Armstrong static int meson_measure_best_id(struct meson_msr_id *clk_msr_id,
5402b45ebefSNeil Armstrong 				    unsigned int *precision)
5412b45ebefSNeil Armstrong {
5422b45ebefSNeil Armstrong 	unsigned int duration = DIV_MAX;
5432b45ebefSNeil Armstrong 	int ret;
5442b45ebefSNeil Armstrong 
5452b45ebefSNeil Armstrong 	/* Start from max duration and down to min duration */
5462b45ebefSNeil Armstrong 	do {
5472b45ebefSNeil Armstrong 		ret = meson_measure_id(clk_msr_id, duration);
5482b45ebefSNeil Armstrong 		if (ret >= 0)
5492b45ebefSNeil Armstrong 			*precision = (2 * 1000000) / duration;
5502b45ebefSNeil Armstrong 		else
5512b45ebefSNeil Armstrong 			duration -= DIV_STEP;
5522b45ebefSNeil Armstrong 	} while (duration >= DIV_MIN && ret == -EINVAL);
5532b45ebefSNeil Armstrong 
5542b45ebefSNeil Armstrong 	return ret;
5552b45ebefSNeil Armstrong }
5562b45ebefSNeil Armstrong 
clk_msr_show(struct seq_file * s,void * data)5572b45ebefSNeil Armstrong static int clk_msr_show(struct seq_file *s, void *data)
5582b45ebefSNeil Armstrong {
5592b45ebefSNeil Armstrong 	struct meson_msr_id *clk_msr_id = s->private;
5602b45ebefSNeil Armstrong 	unsigned int precision = 0;
5612b45ebefSNeil Armstrong 	int val;
5622b45ebefSNeil Armstrong 
5632b45ebefSNeil Armstrong 	val = meson_measure_best_id(clk_msr_id, &precision);
5642b45ebefSNeil Armstrong 	if (val < 0)
5652b45ebefSNeil Armstrong 		return val;
5662b45ebefSNeil Armstrong 
5672b45ebefSNeil Armstrong 	seq_printf(s, "%d\t+/-%dHz\n", val, precision);
5682b45ebefSNeil Armstrong 
5692b45ebefSNeil Armstrong 	return 0;
5702b45ebefSNeil Armstrong }
5712b45ebefSNeil Armstrong DEFINE_SHOW_ATTRIBUTE(clk_msr);
5722b45ebefSNeil Armstrong 
clk_msr_summary_show(struct seq_file * s,void * data)5732b45ebefSNeil Armstrong static int clk_msr_summary_show(struct seq_file *s, void *data)
5742b45ebefSNeil Armstrong {
5752b45ebefSNeil Armstrong 	struct meson_msr_id *msr_table = s->private;
5762b45ebefSNeil Armstrong 	unsigned int precision = 0;
5772b45ebefSNeil Armstrong 	int val, i;
5782b45ebefSNeil Armstrong 
5792b45ebefSNeil Armstrong 	seq_puts(s, "  clock                     rate    precision\n");
5802b45ebefSNeil Armstrong 	seq_puts(s, "---------------------------------------------\n");
5812b45ebefSNeil Armstrong 
5822b45ebefSNeil Armstrong 	for (i = 0 ; i < CLK_MSR_MAX ; ++i) {
5832b45ebefSNeil Armstrong 		if (!msr_table[i].name)
5842b45ebefSNeil Armstrong 			continue;
5852b45ebefSNeil Armstrong 
5862b45ebefSNeil Armstrong 		val = meson_measure_best_id(&msr_table[i], &precision);
5872b45ebefSNeil Armstrong 		if (val < 0)
5882b45ebefSNeil Armstrong 			return val;
5892b45ebefSNeil Armstrong 
5902b45ebefSNeil Armstrong 		seq_printf(s, " %-20s %10d    +/-%dHz\n",
5912b45ebefSNeil Armstrong 			   msr_table[i].name, val, precision);
5922b45ebefSNeil Armstrong 	}
5932b45ebefSNeil Armstrong 
5942b45ebefSNeil Armstrong 	return 0;
5952b45ebefSNeil Armstrong }
5962b45ebefSNeil Armstrong DEFINE_SHOW_ATTRIBUTE(clk_msr_summary);
5972b45ebefSNeil Armstrong 
5982b45ebefSNeil Armstrong static const struct regmap_config meson_clk_msr_regmap_config = {
5992b45ebefSNeil Armstrong 	.reg_bits = 32,
6002b45ebefSNeil Armstrong 	.val_bits = 32,
6012b45ebefSNeil Armstrong 	.reg_stride = 4,
6022b45ebefSNeil Armstrong 	.max_register = MSR_CLK_REG2,
6032b45ebefSNeil Armstrong };
6042b45ebefSNeil Armstrong 
meson_msr_probe(struct platform_device * pdev)6052b45ebefSNeil Armstrong static int meson_msr_probe(struct platform_device *pdev)
6062b45ebefSNeil Armstrong {
6072b45ebefSNeil Armstrong 	const struct meson_msr_id *match_data;
6082b45ebefSNeil Armstrong 	struct meson_msr *priv;
6092b45ebefSNeil Armstrong 	struct dentry *root, *clks;
6102b45ebefSNeil Armstrong 	void __iomem *base;
6112b45ebefSNeil Armstrong 	int i;
6122b45ebefSNeil Armstrong 
6132b45ebefSNeil Armstrong 	priv = devm_kzalloc(&pdev->dev, sizeof(struct meson_msr),
6142b45ebefSNeil Armstrong 			    GFP_KERNEL);
6152b45ebefSNeil Armstrong 	if (!priv)
6162b45ebefSNeil Armstrong 		return -ENOMEM;
6172b45ebefSNeil Armstrong 
6182b45ebefSNeil Armstrong 	match_data = device_get_match_data(&pdev->dev);
6192b45ebefSNeil Armstrong 	if (!match_data) {
6202b45ebefSNeil Armstrong 		dev_err(&pdev->dev, "failed to get match data\n");
6212b45ebefSNeil Armstrong 		return -ENODEV;
6222b45ebefSNeil Armstrong 	}
6232b45ebefSNeil Armstrong 
6242b45ebefSNeil Armstrong 	memcpy(priv->msr_table, match_data, sizeof(priv->msr_table));
6252b45ebefSNeil Armstrong 
626*d54dbe9fSCai Huoqing 	base = devm_platform_ioremap_resource(pdev, 0);
627a06bc969SQiheng Lin 	if (IS_ERR(base))
6282b45ebefSNeil Armstrong 		return PTR_ERR(base);
6292b45ebefSNeil Armstrong 
6302b45ebefSNeil Armstrong 	priv->regmap = devm_regmap_init_mmio(&pdev->dev, base,
6312b45ebefSNeil Armstrong 					     &meson_clk_msr_regmap_config);
6322b45ebefSNeil Armstrong 	if (IS_ERR(priv->regmap))
6332b45ebefSNeil Armstrong 		return PTR_ERR(priv->regmap);
6342b45ebefSNeil Armstrong 
6352b45ebefSNeil Armstrong 	root = debugfs_create_dir("meson-clk-msr", NULL);
6362b45ebefSNeil Armstrong 	clks = debugfs_create_dir("clks", root);
6372b45ebefSNeil Armstrong 
6382b45ebefSNeil Armstrong 	debugfs_create_file("measure_summary", 0444, root,
6392b45ebefSNeil Armstrong 			    priv->msr_table, &clk_msr_summary_fops);
6402b45ebefSNeil Armstrong 
6412b45ebefSNeil Armstrong 	for (i = 0 ; i < CLK_MSR_MAX ; ++i) {
6422b45ebefSNeil Armstrong 		if (!priv->msr_table[i].name)
6432b45ebefSNeil Armstrong 			continue;
6442b45ebefSNeil Armstrong 
6452b45ebefSNeil Armstrong 		priv->msr_table[i].priv = priv;
6462b45ebefSNeil Armstrong 
6472b45ebefSNeil Armstrong 		debugfs_create_file(priv->msr_table[i].name, 0444, clks,
6482b45ebefSNeil Armstrong 				    &priv->msr_table[i], &clk_msr_fops);
6492b45ebefSNeil Armstrong 	}
6502b45ebefSNeil Armstrong 
6512b45ebefSNeil Armstrong 	return 0;
6522b45ebefSNeil Armstrong }
6532b45ebefSNeil Armstrong 
6542b45ebefSNeil Armstrong static const struct of_device_id meson_msr_match_table[] = {
6552b45ebefSNeil Armstrong 	{
6562b45ebefSNeil Armstrong 		.compatible = "amlogic,meson-gx-clk-measure",
6572b45ebefSNeil Armstrong 		.data = (void *)clk_msr_gx,
6582b45ebefSNeil Armstrong 	},
6592b45ebefSNeil Armstrong 	{
6602b45ebefSNeil Armstrong 		.compatible = "amlogic,meson8-clk-measure",
6612b45ebefSNeil Armstrong 		.data = (void *)clk_msr_m8,
6622b45ebefSNeil Armstrong 	},
6632b45ebefSNeil Armstrong 	{
6642b45ebefSNeil Armstrong 		.compatible = "amlogic,meson8b-clk-measure",
6652b45ebefSNeil Armstrong 		.data = (void *)clk_msr_m8,
6662b45ebefSNeil Armstrong 	},
66719e0bde7SJerome Brunet 	{
66819e0bde7SJerome Brunet 		.compatible = "amlogic,meson-axg-clk-measure",
66919e0bde7SJerome Brunet 		.data = (void *)clk_msr_axg,
67019e0bde7SJerome Brunet 	},
67119e0bde7SJerome Brunet 	{
67219e0bde7SJerome Brunet 		.compatible = "amlogic,meson-g12a-clk-measure",
67319e0bde7SJerome Brunet 		.data = (void *)clk_msr_g12a,
67419e0bde7SJerome Brunet 	},
67562369971SNeil Armstrong 	{
67662369971SNeil Armstrong 		.compatible = "amlogic,meson-sm1-clk-measure",
67762369971SNeil Armstrong 		.data = (void *)clk_msr_sm1,
67862369971SNeil Armstrong 	},
6792b45ebefSNeil Armstrong 	{ /* sentinel */ }
6802b45ebefSNeil Armstrong };
681d9da1785SKevin Hilman MODULE_DEVICE_TABLE(of, meson_msr_match_table);
6822b45ebefSNeil Armstrong 
6832b45ebefSNeil Armstrong static struct platform_driver meson_msr_driver = {
6842b45ebefSNeil Armstrong 	.probe	= meson_msr_probe,
6852b45ebefSNeil Armstrong 	.driver = {
6862b45ebefSNeil Armstrong 		.name		= "meson_msr",
6872b45ebefSNeil Armstrong 		.of_match_table	= meson_msr_match_table,
6882b45ebefSNeil Armstrong 	},
6892b45ebefSNeil Armstrong };
690d9da1785SKevin Hilman module_platform_driver(meson_msr_driver);
691d9da1785SKevin Hilman MODULE_LICENSE("GPL v2");
692