linux/drivers/soc/amlogic/meson-clk-measure.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (c) 2018 BayLibre, SAS
   4 * Author: Neil Armstrong <narmstrong@baylibre.com>
   5 */
   6
   7#include <linux/of_address.h>
   8#include <linux/platform_device.h>
   9#include <linux/bitfield.h>
  10#include <linux/seq_file.h>
  11#include <linux/debugfs.h>
  12#include <linux/regmap.h>
  13#include <linux/module.h>
  14
  15static DEFINE_MUTEX(measure_lock);
  16
  17#define MSR_CLK_DUTY            0x0
  18#define MSR_CLK_REG0            0x4
  19#define MSR_CLK_REG1            0x8
  20#define MSR_CLK_REG2            0xc
  21
  22#define MSR_DURATION            GENMASK(15, 0)
  23#define MSR_ENABLE              BIT(16)
  24#define MSR_CONT                BIT(17) /* continuous measurement */
  25#define MSR_INTR                BIT(18) /* interrupts */
  26#define MSR_RUN                 BIT(19)
  27#define MSR_CLK_SRC             GENMASK(26, 20)
  28#define MSR_BUSY                BIT(31)
  29
  30#define MSR_VAL_MASK            GENMASK(15, 0)
  31
  32#define DIV_MIN                 32
  33#define DIV_STEP                32
  34#define DIV_MAX                 640
  35
  36#define CLK_MSR_MAX             128
  37
  38struct meson_msr_id {
  39        struct meson_msr *priv;
  40        unsigned int id;
  41        const char *name;
  42};
  43
  44struct meson_msr {
  45        struct regmap *regmap;
  46        struct meson_msr_id msr_table[CLK_MSR_MAX];
  47};
  48
  49#define CLK_MSR_ID(__id, __name) \
  50        [__id] = {.id = __id, .name = __name,}
  51
  52static struct meson_msr_id clk_msr_m8[CLK_MSR_MAX] = {
  53        CLK_MSR_ID(0, "ring_osc_out_ee0"),
  54        CLK_MSR_ID(1, "ring_osc_out_ee1"),
  55        CLK_MSR_ID(2, "ring_osc_out_ee2"),
  56        CLK_MSR_ID(3, "a9_ring_osck"),
  57        CLK_MSR_ID(6, "vid_pll"),
  58        CLK_MSR_ID(7, "clk81"),
  59        CLK_MSR_ID(8, "encp"),
  60        CLK_MSR_ID(9, "encl"),
  61        CLK_MSR_ID(11, "eth_rmii"),
  62        CLK_MSR_ID(13, "amclk"),
  63        CLK_MSR_ID(14, "fec_clk_0"),
  64        CLK_MSR_ID(15, "fec_clk_1"),
  65        CLK_MSR_ID(16, "fec_clk_2"),
  66        CLK_MSR_ID(18, "a9_clk_div16"),
  67        CLK_MSR_ID(19, "hdmi_sys"),
  68        CLK_MSR_ID(20, "rtc_osc_clk_out"),
  69        CLK_MSR_ID(21, "i2s_clk_in_src0"),
  70        CLK_MSR_ID(22, "clk_rmii_from_pad"),
  71        CLK_MSR_ID(23, "hdmi_ch0_tmds"),
  72        CLK_MSR_ID(24, "lvds_fifo"),
  73        CLK_MSR_ID(26, "sc_clk_int"),
  74        CLK_MSR_ID(28, "sar_adc"),
  75        CLK_MSR_ID(30, "mpll_clk_test_out"),
  76        CLK_MSR_ID(31, "audac_clkpi"),
  77        CLK_MSR_ID(32, "vdac"),
  78        CLK_MSR_ID(33, "sdhc_rx"),
  79        CLK_MSR_ID(34, "sdhc_sd"),
  80        CLK_MSR_ID(35, "mali"),
  81        CLK_MSR_ID(36, "hdmi_tx_pixel"),
  82        CLK_MSR_ID(38, "vdin_meas"),
  83        CLK_MSR_ID(39, "pcm_sclk"),
  84        CLK_MSR_ID(40, "pcm_mclk"),
  85        CLK_MSR_ID(41, "eth_rx_tx"),
  86        CLK_MSR_ID(42, "pwm_d"),
  87        CLK_MSR_ID(43, "pwm_c"),
  88        CLK_MSR_ID(44, "pwm_b"),
  89        CLK_MSR_ID(45, "pwm_a"),
  90        CLK_MSR_ID(46, "pcm2_sclk"),
  91        CLK_MSR_ID(47, "ddr_dpll_pt"),
  92        CLK_MSR_ID(48, "pwm_f"),
  93        CLK_MSR_ID(49, "pwm_e"),
  94        CLK_MSR_ID(59, "hcodec"),
  95        CLK_MSR_ID(60, "usb_32k_alt"),
  96        CLK_MSR_ID(61, "gpio"),
  97        CLK_MSR_ID(62, "vid2_pll"),
  98        CLK_MSR_ID(63, "mipi_csi_cfg"),
  99};
 100
 101static struct meson_msr_id clk_msr_gx[CLK_MSR_MAX] = {
 102        CLK_MSR_ID(0, "ring_osc_out_ee_0"),
 103        CLK_MSR_ID(1, "ring_osc_out_ee_1"),
 104        CLK_MSR_ID(2, "ring_osc_out_ee_2"),
 105        CLK_MSR_ID(3, "a53_ring_osc"),
 106        CLK_MSR_ID(4, "gp0_pll"),
 107        CLK_MSR_ID(6, "enci"),
 108        CLK_MSR_ID(7, "clk81"),
 109        CLK_MSR_ID(8, "encp"),
 110        CLK_MSR_ID(9, "encl"),
 111        CLK_MSR_ID(10, "vdac"),
 112        CLK_MSR_ID(11, "rgmii_tx"),
 113        CLK_MSR_ID(12, "pdm"),
 114        CLK_MSR_ID(13, "amclk"),
 115        CLK_MSR_ID(14, "fec_0"),
 116        CLK_MSR_ID(15, "fec_1"),
 117        CLK_MSR_ID(16, "fec_2"),
 118        CLK_MSR_ID(17, "sys_pll_div16"),
 119        CLK_MSR_ID(18, "sys_cpu_div16"),
 120        CLK_MSR_ID(19, "hdmitx_sys"),
 121        CLK_MSR_ID(20, "rtc_osc_out"),
 122        CLK_MSR_ID(21, "i2s_in_src0"),
 123        CLK_MSR_ID(22, "eth_phy_ref"),
 124        CLK_MSR_ID(23, "hdmi_todig"),
 125        CLK_MSR_ID(26, "sc_int"),
 126        CLK_MSR_ID(28, "sar_adc"),
 127        CLK_MSR_ID(31, "mpll_test_out"),
 128        CLK_MSR_ID(32, "vdec"),
 129        CLK_MSR_ID(35, "mali"),
 130        CLK_MSR_ID(36, "hdmi_tx_pixel"),
 131        CLK_MSR_ID(37, "i958"),
 132        CLK_MSR_ID(38, "vdin_meas"),
 133        CLK_MSR_ID(39, "pcm_sclk"),
 134        CLK_MSR_ID(40, "pcm_mclk"),
 135        CLK_MSR_ID(41, "eth_rx_or_rmii"),
 136        CLK_MSR_ID(42, "mp0_out"),
 137        CLK_MSR_ID(43, "fclk_div5"),
 138        CLK_MSR_ID(44, "pwm_b"),
 139        CLK_MSR_ID(45, "pwm_a"),
 140        CLK_MSR_ID(46, "vpu"),
 141        CLK_MSR_ID(47, "ddr_dpll_pt"),
 142        CLK_MSR_ID(48, "mp1_out"),
 143        CLK_MSR_ID(49, "mp2_out"),
 144        CLK_MSR_ID(50, "mp3_out"),
 145        CLK_MSR_ID(51, "nand_core"),
 146        CLK_MSR_ID(52, "sd_emmc_b"),
 147        CLK_MSR_ID(53, "sd_emmc_a"),
 148        CLK_MSR_ID(55, "vid_pll_div_out"),
 149        CLK_MSR_ID(56, "cci"),
 150        CLK_MSR_ID(57, "wave420l_c"),
 151        CLK_MSR_ID(58, "wave420l_b"),
 152        CLK_MSR_ID(59, "hcodec"),
 153        CLK_MSR_ID(60, "alt_32k"),
 154        CLK_MSR_ID(61, "gpio_msr"),
 155        CLK_MSR_ID(62, "hevc"),
 156        CLK_MSR_ID(66, "vid_lock"),
 157        CLK_MSR_ID(70, "pwm_f"),
 158        CLK_MSR_ID(71, "pwm_e"),
 159        CLK_MSR_ID(72, "pwm_d"),
 160        CLK_MSR_ID(73, "pwm_c"),
 161        CLK_MSR_ID(75, "aoclkx2_int"),
 162        CLK_MSR_ID(76, "aoclk_int"),
 163        CLK_MSR_ID(77, "rng_ring_osc_0"),
 164        CLK_MSR_ID(78, "rng_ring_osc_1"),
 165        CLK_MSR_ID(79, "rng_ring_osc_2"),
 166        CLK_MSR_ID(80, "rng_ring_osc_3"),
 167        CLK_MSR_ID(81, "vapb"),
 168        CLK_MSR_ID(82, "ge2d"),
 169};
 170
 171static struct meson_msr_id clk_msr_axg[CLK_MSR_MAX] = {
 172        CLK_MSR_ID(0, "ring_osc_out_ee_0"),
 173        CLK_MSR_ID(1, "ring_osc_out_ee_1"),
 174        CLK_MSR_ID(2, "ring_osc_out_ee_2"),
 175        CLK_MSR_ID(3, "a53_ring_osc"),
 176        CLK_MSR_ID(4, "gp0_pll"),
 177        CLK_MSR_ID(5, "gp1_pll"),
 178        CLK_MSR_ID(7, "clk81"),
 179        CLK_MSR_ID(9, "encl"),
 180        CLK_MSR_ID(17, "sys_pll_div16"),
 181        CLK_MSR_ID(18, "sys_cpu_div16"),
 182        CLK_MSR_ID(20, "rtc_osc_out"),
 183        CLK_MSR_ID(23, "mmc_clk"),
 184        CLK_MSR_ID(28, "sar_adc"),
 185        CLK_MSR_ID(31, "mpll_test_out"),
 186        CLK_MSR_ID(40, "mod_eth_tx_clk"),
 187        CLK_MSR_ID(41, "mod_eth_rx_clk_rmii"),
 188        CLK_MSR_ID(42, "mp0_out"),
 189        CLK_MSR_ID(43, "fclk_div5"),
 190        CLK_MSR_ID(44, "pwm_b"),
 191        CLK_MSR_ID(45, "pwm_a"),
 192        CLK_MSR_ID(46, "vpu"),
 193        CLK_MSR_ID(47, "ddr_dpll_pt"),
 194        CLK_MSR_ID(48, "mp1_out"),
 195        CLK_MSR_ID(49, "mp2_out"),
 196        CLK_MSR_ID(50, "mp3_out"),
 197        CLK_MSR_ID(51, "sd_emmm_c"),
 198        CLK_MSR_ID(52, "sd_emmc_b"),
 199        CLK_MSR_ID(61, "gpio_msr"),
 200        CLK_MSR_ID(66, "audio_slv_lrclk_c"),
 201        CLK_MSR_ID(67, "audio_slv_lrclk_b"),
 202        CLK_MSR_ID(68, "audio_slv_lrclk_a"),
 203        CLK_MSR_ID(69, "audio_slv_sclk_c"),
 204        CLK_MSR_ID(70, "audio_slv_sclk_b"),
 205        CLK_MSR_ID(71, "audio_slv_sclk_a"),
 206        CLK_MSR_ID(72, "pwm_d"),
 207        CLK_MSR_ID(73, "pwm_c"),
 208        CLK_MSR_ID(74, "wifi_beacon"),
 209        CLK_MSR_ID(75, "tdmin_lb_lrcl"),
 210        CLK_MSR_ID(76, "tdmin_lb_sclk"),
 211        CLK_MSR_ID(77, "rng_ring_osc_0"),
 212        CLK_MSR_ID(78, "rng_ring_osc_1"),
 213        CLK_MSR_ID(79, "rng_ring_osc_2"),
 214        CLK_MSR_ID(80, "rng_ring_osc_3"),
 215        CLK_MSR_ID(81, "vapb"),
 216        CLK_MSR_ID(82, "ge2d"),
 217        CLK_MSR_ID(84, "audio_resample"),
 218        CLK_MSR_ID(85, "audio_pdm_sys"),
 219        CLK_MSR_ID(86, "audio_spdifout"),
 220        CLK_MSR_ID(87, "audio_spdifin"),
 221        CLK_MSR_ID(88, "audio_lrclk_f"),
 222        CLK_MSR_ID(89, "audio_lrclk_e"),
 223        CLK_MSR_ID(90, "audio_lrclk_d"),
 224        CLK_MSR_ID(91, "audio_lrclk_c"),
 225        CLK_MSR_ID(92, "audio_lrclk_b"),
 226        CLK_MSR_ID(93, "audio_lrclk_a"),
 227        CLK_MSR_ID(94, "audio_sclk_f"),
 228        CLK_MSR_ID(95, "audio_sclk_e"),
 229        CLK_MSR_ID(96, "audio_sclk_d"),
 230        CLK_MSR_ID(97, "audio_sclk_c"),
 231        CLK_MSR_ID(98, "audio_sclk_b"),
 232        CLK_MSR_ID(99, "audio_sclk_a"),
 233        CLK_MSR_ID(100, "audio_mclk_f"),
 234        CLK_MSR_ID(101, "audio_mclk_e"),
 235        CLK_MSR_ID(102, "audio_mclk_d"),
 236        CLK_MSR_ID(103, "audio_mclk_c"),
 237        CLK_MSR_ID(104, "audio_mclk_b"),
 238        CLK_MSR_ID(105, "audio_mclk_a"),
 239        CLK_MSR_ID(106, "pcie_refclk_n"),
 240        CLK_MSR_ID(107, "pcie_refclk_p"),
 241        CLK_MSR_ID(108, "audio_locker_out"),
 242        CLK_MSR_ID(109, "audio_locker_in"),
 243};
 244
 245static struct meson_msr_id clk_msr_g12a[CLK_MSR_MAX] = {
 246        CLK_MSR_ID(0, "ring_osc_out_ee_0"),
 247        CLK_MSR_ID(1, "ring_osc_out_ee_1"),
 248        CLK_MSR_ID(2, "ring_osc_out_ee_2"),
 249        CLK_MSR_ID(3, "sys_cpu_ring_osc"),
 250        CLK_MSR_ID(4, "gp0_pll"),
 251        CLK_MSR_ID(6, "enci"),
 252        CLK_MSR_ID(7, "clk81"),
 253        CLK_MSR_ID(8, "encp"),
 254        CLK_MSR_ID(9, "encl"),
 255        CLK_MSR_ID(10, "vdac"),
 256        CLK_MSR_ID(11, "eth_tx"),
 257        CLK_MSR_ID(12, "hifi_pll"),
 258        CLK_MSR_ID(13, "mod_tcon"),
 259        CLK_MSR_ID(14, "fec_0"),
 260        CLK_MSR_ID(15, "fec_1"),
 261        CLK_MSR_ID(16, "fec_2"),
 262        CLK_MSR_ID(17, "sys_pll_div16"),
 263        CLK_MSR_ID(18, "sys_cpu_div16"),
 264        CLK_MSR_ID(19, "lcd_an_ph2"),
 265        CLK_MSR_ID(20, "rtc_osc_out"),
 266        CLK_MSR_ID(21, "lcd_an_ph3"),
 267        CLK_MSR_ID(22, "eth_phy_ref"),
 268        CLK_MSR_ID(23, "mpll_50m"),
 269        CLK_MSR_ID(24, "eth_125m"),
 270        CLK_MSR_ID(25, "eth_rmii"),
 271        CLK_MSR_ID(26, "sc_int"),
 272        CLK_MSR_ID(27, "in_mac"),
 273        CLK_MSR_ID(28, "sar_adc"),
 274        CLK_MSR_ID(29, "pcie_inp"),
 275        CLK_MSR_ID(30, "pcie_inn"),
 276        CLK_MSR_ID(31, "mpll_test_out"),
 277        CLK_MSR_ID(32, "vdec"),
 278        CLK_MSR_ID(33, "sys_cpu_ring_osc_1"),
 279        CLK_MSR_ID(34, "eth_mpll_50m"),
 280        CLK_MSR_ID(35, "mali"),
 281        CLK_MSR_ID(36, "hdmi_tx_pixel"),
 282        CLK_MSR_ID(37, "cdac"),
 283        CLK_MSR_ID(38, "vdin_meas"),
 284        CLK_MSR_ID(39, "bt656"),
 285        CLK_MSR_ID(41, "eth_rx_or_rmii"),
 286        CLK_MSR_ID(42, "mp0_out"),
 287        CLK_MSR_ID(43, "fclk_div5"),
 288        CLK_MSR_ID(44, "pwm_b"),
 289        CLK_MSR_ID(45, "pwm_a"),
 290        CLK_MSR_ID(46, "vpu"),
 291        CLK_MSR_ID(47, "ddr_dpll_pt"),
 292        CLK_MSR_ID(48, "mp1_out"),
 293        CLK_MSR_ID(49, "mp2_out"),
 294        CLK_MSR_ID(50, "mp3_out"),
 295        CLK_MSR_ID(51, "sd_emmc_c"),
 296        CLK_MSR_ID(52, "sd_emmc_b"),
 297        CLK_MSR_ID(53, "sd_emmc_a"),
 298        CLK_MSR_ID(54, "vpu_clkc"),
 299        CLK_MSR_ID(55, "vid_pll_div_out"),
 300        CLK_MSR_ID(56, "wave420l_a"),
 301        CLK_MSR_ID(57, "wave420l_c"),
 302        CLK_MSR_ID(58, "wave420l_b"),
 303        CLK_MSR_ID(59, "hcodec"),
 304        CLK_MSR_ID(61, "gpio_msr"),
 305        CLK_MSR_ID(62, "hevcb"),
 306        CLK_MSR_ID(63, "dsi_meas"),
 307        CLK_MSR_ID(64, "spicc_1"),
 308        CLK_MSR_ID(65, "spicc_0"),
 309        CLK_MSR_ID(66, "vid_lock"),
 310        CLK_MSR_ID(67, "dsi_phy"),
 311        CLK_MSR_ID(68, "hdcp22_esm"),
 312        CLK_MSR_ID(69, "hdcp22_skp"),
 313        CLK_MSR_ID(70, "pwm_f"),
 314        CLK_MSR_ID(71, "pwm_e"),
 315        CLK_MSR_ID(72, "pwm_d"),
 316        CLK_MSR_ID(73, "pwm_c"),
 317        CLK_MSR_ID(75, "hevcf"),
 318        CLK_MSR_ID(77, "rng_ring_osc_0"),
 319        CLK_MSR_ID(78, "rng_ring_osc_1"),
 320        CLK_MSR_ID(79, "rng_ring_osc_2"),
 321        CLK_MSR_ID(80, "rng_ring_osc_3"),
 322        CLK_MSR_ID(81, "vapb"),
 323        CLK_MSR_ID(82, "ge2d"),
 324        CLK_MSR_ID(83, "co_rx"),
 325        CLK_MSR_ID(84, "co_tx"),
 326        CLK_MSR_ID(89, "hdmi_todig"),
 327        CLK_MSR_ID(90, "hdmitx_sys"),
 328        CLK_MSR_ID(91, "sys_cpub_div16"),
 329        CLK_MSR_ID(92, "sys_pll_cpub_div16"),
 330        CLK_MSR_ID(94, "eth_phy_rx"),
 331        CLK_MSR_ID(95, "eth_phy_pll"),
 332        CLK_MSR_ID(96, "vpu_b"),
 333        CLK_MSR_ID(97, "cpu_b_tmp"),
 334        CLK_MSR_ID(98, "ts"),
 335        CLK_MSR_ID(99, "ring_osc_out_ee_3"),
 336        CLK_MSR_ID(100, "ring_osc_out_ee_4"),
 337        CLK_MSR_ID(101, "ring_osc_out_ee_5"),
 338        CLK_MSR_ID(102, "ring_osc_out_ee_6"),
 339        CLK_MSR_ID(103, "ring_osc_out_ee_7"),
 340        CLK_MSR_ID(104, "ring_osc_out_ee_8"),
 341        CLK_MSR_ID(105, "ring_osc_out_ee_9"),
 342        CLK_MSR_ID(106, "ephy_test"),
 343        CLK_MSR_ID(107, "au_dac_g128x"),
 344        CLK_MSR_ID(108, "audio_locker_out"),
 345        CLK_MSR_ID(109, "audio_locker_in"),
 346        CLK_MSR_ID(110, "audio_tdmout_c_sclk"),
 347        CLK_MSR_ID(111, "audio_tdmout_b_sclk"),
 348        CLK_MSR_ID(112, "audio_tdmout_a_sclk"),
 349        CLK_MSR_ID(113, "audio_tdmin_lb_sclk"),
 350        CLK_MSR_ID(114, "audio_tdmin_c_sclk"),
 351        CLK_MSR_ID(115, "audio_tdmin_b_sclk"),
 352        CLK_MSR_ID(116, "audio_tdmin_a_sclk"),
 353        CLK_MSR_ID(117, "audio_resample"),
 354        CLK_MSR_ID(118, "audio_pdm_sys"),
 355        CLK_MSR_ID(119, "audio_spdifout_b"),
 356        CLK_MSR_ID(120, "audio_spdifout"),
 357        CLK_MSR_ID(121, "audio_spdifin"),
 358        CLK_MSR_ID(122, "audio_pdm_dclk"),
 359};
 360
 361static struct meson_msr_id clk_msr_sm1[CLK_MSR_MAX] = {
 362        CLK_MSR_ID(0, "ring_osc_out_ee_0"),
 363        CLK_MSR_ID(1, "ring_osc_out_ee_1"),
 364        CLK_MSR_ID(2, "ring_osc_out_ee_2"),
 365        CLK_MSR_ID(3, "ring_osc_out_ee_3"),
 366        CLK_MSR_ID(4, "gp0_pll"),
 367        CLK_MSR_ID(5, "gp1_pll"),
 368        CLK_MSR_ID(6, "enci"),
 369        CLK_MSR_ID(7, "clk81"),
 370        CLK_MSR_ID(8, "encp"),
 371        CLK_MSR_ID(9, "encl"),
 372        CLK_MSR_ID(10, "vdac"),
 373        CLK_MSR_ID(11, "eth_tx"),
 374        CLK_MSR_ID(12, "hifi_pll"),
 375        CLK_MSR_ID(13, "mod_tcon"),
 376        CLK_MSR_ID(14, "fec_0"),
 377        CLK_MSR_ID(15, "fec_1"),
 378        CLK_MSR_ID(16, "fec_2"),
 379        CLK_MSR_ID(17, "sys_pll_div16"),
 380        CLK_MSR_ID(18, "sys_cpu_div16"),
 381        CLK_MSR_ID(19, "lcd_an_ph2"),
 382        CLK_MSR_ID(20, "rtc_osc_out"),
 383        CLK_MSR_ID(21, "lcd_an_ph3"),
 384        CLK_MSR_ID(22, "eth_phy_ref"),
 385        CLK_MSR_ID(23, "mpll_50m"),
 386        CLK_MSR_ID(24, "eth_125m"),
 387        CLK_MSR_ID(25, "eth_rmii"),
 388        CLK_MSR_ID(26, "sc_int"),
 389        CLK_MSR_ID(27, "in_mac"),
 390        CLK_MSR_ID(28, "sar_adc"),
 391        CLK_MSR_ID(29, "pcie_inp"),
 392        CLK_MSR_ID(30, "pcie_inn"),
 393        CLK_MSR_ID(31, "mpll_test_out"),
 394        CLK_MSR_ID(32, "vdec"),
 395        CLK_MSR_ID(34, "eth_mpll_50m"),
 396        CLK_MSR_ID(35, "mali"),
 397        CLK_MSR_ID(36, "hdmi_tx_pixel"),
 398        CLK_MSR_ID(37, "cdac"),
 399        CLK_MSR_ID(38, "vdin_meas"),
 400        CLK_MSR_ID(39, "bt656"),
 401        CLK_MSR_ID(40, "arm_ring_osc_out_4"),
 402        CLK_MSR_ID(41, "eth_rx_or_rmii"),
 403        CLK_MSR_ID(42, "mp0_out"),
 404        CLK_MSR_ID(43, "fclk_div5"),
 405        CLK_MSR_ID(44, "pwm_b"),
 406        CLK_MSR_ID(45, "pwm_a"),
 407        CLK_MSR_ID(46, "vpu"),
 408        CLK_MSR_ID(47, "ddr_dpll_pt"),
 409        CLK_MSR_ID(48, "mp1_out"),
 410        CLK_MSR_ID(49, "mp2_out"),
 411        CLK_MSR_ID(50, "mp3_out"),
 412        CLK_MSR_ID(51, "sd_emmc_c"),
 413        CLK_MSR_ID(52, "sd_emmc_b"),
 414        CLK_MSR_ID(53, "sd_emmc_a"),
 415        CLK_MSR_ID(54, "vpu_clkc"),
 416        CLK_MSR_ID(55, "vid_pll_div_out"),
 417        CLK_MSR_ID(56, "wave420l_a"),
 418        CLK_MSR_ID(57, "wave420l_c"),
 419        CLK_MSR_ID(58, "wave420l_b"),
 420        CLK_MSR_ID(59, "hcodec"),
 421        CLK_MSR_ID(60, "arm_ring_osc_out_5"),
 422        CLK_MSR_ID(61, "gpio_msr"),
 423        CLK_MSR_ID(62, "hevcb"),
 424        CLK_MSR_ID(63, "dsi_meas"),
 425        CLK_MSR_ID(64, "spicc_1"),
 426        CLK_MSR_ID(65, "spicc_0"),
 427        CLK_MSR_ID(66, "vid_lock"),
 428        CLK_MSR_ID(67, "dsi_phy"),
 429        CLK_MSR_ID(68, "hdcp22_esm"),
 430        CLK_MSR_ID(69, "hdcp22_skp"),
 431        CLK_MSR_ID(70, "pwm_f"),
 432        CLK_MSR_ID(71, "pwm_e"),
 433        CLK_MSR_ID(72, "pwm_d"),
 434        CLK_MSR_ID(73, "pwm_c"),
 435        CLK_MSR_ID(74, "arm_ring_osc_out_6"),
 436        CLK_MSR_ID(75, "hevcf"),
 437        CLK_MSR_ID(76, "arm_ring_osc_out_7"),
 438        CLK_MSR_ID(77, "rng_ring_osc_0"),
 439        CLK_MSR_ID(78, "rng_ring_osc_1"),
 440        CLK_MSR_ID(79, "rng_ring_osc_2"),
 441        CLK_MSR_ID(80, "rng_ring_osc_3"),
 442        CLK_MSR_ID(81, "vapb"),
 443        CLK_MSR_ID(82, "ge2d"),
 444        CLK_MSR_ID(83, "co_rx"),
 445        CLK_MSR_ID(84, "co_tx"),
 446        CLK_MSR_ID(85, "arm_ring_osc_out_8"),
 447        CLK_MSR_ID(86, "arm_ring_osc_out_9"),
 448        CLK_MSR_ID(87, "mipi_dsi_phy"),
 449        CLK_MSR_ID(88, "cis2_adapt"),
 450        CLK_MSR_ID(89, "hdmi_todig"),
 451        CLK_MSR_ID(90, "hdmitx_sys"),
 452        CLK_MSR_ID(91, "nna_core"),
 453        CLK_MSR_ID(92, "nna_axi"),
 454        CLK_MSR_ID(93, "vad"),
 455        CLK_MSR_ID(94, "eth_phy_rx"),
 456        CLK_MSR_ID(95, "eth_phy_pll"),
 457        CLK_MSR_ID(96, "vpu_b"),
 458        CLK_MSR_ID(97, "cpu_b_tmp"),
 459        CLK_MSR_ID(98, "ts"),
 460        CLK_MSR_ID(99, "arm_ring_osc_out_10"),
 461        CLK_MSR_ID(100, "arm_ring_osc_out_11"),
 462        CLK_MSR_ID(101, "arm_ring_osc_out_12"),
 463        CLK_MSR_ID(102, "arm_ring_osc_out_13"),
 464        CLK_MSR_ID(103, "arm_ring_osc_out_14"),
 465        CLK_MSR_ID(104, "arm_ring_osc_out_15"),
 466        CLK_MSR_ID(105, "arm_ring_osc_out_16"),
 467        CLK_MSR_ID(106, "ephy_test"),
 468        CLK_MSR_ID(107, "au_dac_g128x"),
 469        CLK_MSR_ID(108, "audio_locker_out"),
 470        CLK_MSR_ID(109, "audio_locker_in"),
 471        CLK_MSR_ID(110, "audio_tdmout_c_sclk"),
 472        CLK_MSR_ID(111, "audio_tdmout_b_sclk"),
 473        CLK_MSR_ID(112, "audio_tdmout_a_sclk"),
 474        CLK_MSR_ID(113, "audio_tdmin_lb_sclk"),
 475        CLK_MSR_ID(114, "audio_tdmin_c_sclk"),
 476        CLK_MSR_ID(115, "audio_tdmin_b_sclk"),
 477        CLK_MSR_ID(116, "audio_tdmin_a_sclk"),
 478        CLK_MSR_ID(117, "audio_resample"),
 479        CLK_MSR_ID(118, "audio_pdm_sys"),
 480        CLK_MSR_ID(119, "audio_spdifout_b"),
 481        CLK_MSR_ID(120, "audio_spdifout"),
 482        CLK_MSR_ID(121, "audio_spdifin"),
 483        CLK_MSR_ID(122, "audio_pdm_dclk"),
 484        CLK_MSR_ID(123, "audio_resampled"),
 485        CLK_MSR_ID(124, "earcrx_pll"),
 486        CLK_MSR_ID(125, "earcrx_pll_test"),
 487        CLK_MSR_ID(126, "csi_phy0"),
 488        CLK_MSR_ID(127, "csi2_data"),
 489};
 490
 491static int meson_measure_id(struct meson_msr_id *clk_msr_id,
 492                               unsigned int duration)
 493{
 494        struct meson_msr *priv = clk_msr_id->priv;
 495        unsigned int val;
 496        int ret;
 497
 498        ret = mutex_lock_interruptible(&measure_lock);
 499        if (ret)
 500                return ret;
 501
 502        regmap_write(priv->regmap, MSR_CLK_REG0, 0);
 503
 504        /* Set measurement duration */
 505        regmap_update_bits(priv->regmap, MSR_CLK_REG0, MSR_DURATION,
 506                           FIELD_PREP(MSR_DURATION, duration - 1));
 507
 508        /* Set ID */
 509        regmap_update_bits(priv->regmap, MSR_CLK_REG0, MSR_CLK_SRC,
 510                           FIELD_PREP(MSR_CLK_SRC, clk_msr_id->id));
 511
 512        /* Enable & Start */
 513        regmap_update_bits(priv->regmap, MSR_CLK_REG0,
 514                           MSR_RUN | MSR_ENABLE,
 515                           MSR_RUN | MSR_ENABLE);
 516
 517        ret = regmap_read_poll_timeout(priv->regmap, MSR_CLK_REG0,
 518                                       val, !(val & MSR_BUSY), 10, 10000);
 519        if (ret) {
 520                mutex_unlock(&measure_lock);
 521                return ret;
 522        }
 523
 524        /* Disable */
 525        regmap_update_bits(priv->regmap, MSR_CLK_REG0, MSR_ENABLE, 0);
 526
 527        /* Get the value in multiple of gate time counts */
 528        regmap_read(priv->regmap, MSR_CLK_REG2, &val);
 529
 530        mutex_unlock(&measure_lock);
 531
 532        if (val >= MSR_VAL_MASK)
 533                return -EINVAL;
 534
 535        return DIV_ROUND_CLOSEST_ULL((val & MSR_VAL_MASK) * 1000000ULL,
 536                                     duration);
 537}
 538
 539static int meson_measure_best_id(struct meson_msr_id *clk_msr_id,
 540                                    unsigned int *precision)
 541{
 542        unsigned int duration = DIV_MAX;
 543        int ret;
 544
 545        /* Start from max duration and down to min duration */
 546        do {
 547                ret = meson_measure_id(clk_msr_id, duration);
 548                if (ret >= 0)
 549                        *precision = (2 * 1000000) / duration;
 550                else
 551                        duration -= DIV_STEP;
 552        } while (duration >= DIV_MIN && ret == -EINVAL);
 553
 554        return ret;
 555}
 556
 557static int clk_msr_show(struct seq_file *s, void *data)
 558{
 559        struct meson_msr_id *clk_msr_id = s->private;
 560        unsigned int precision = 0;
 561        int val;
 562
 563        val = meson_measure_best_id(clk_msr_id, &precision);
 564        if (val < 0)
 565                return val;
 566
 567        seq_printf(s, "%d\t+/-%dHz\n", val, precision);
 568
 569        return 0;
 570}
 571DEFINE_SHOW_ATTRIBUTE(clk_msr);
 572
 573static int clk_msr_summary_show(struct seq_file *s, void *data)
 574{
 575        struct meson_msr_id *msr_table = s->private;
 576        unsigned int precision = 0;
 577        int val, i;
 578
 579        seq_puts(s, "  clock                     rate    precision\n");
 580        seq_puts(s, "---------------------------------------------\n");
 581
 582        for (i = 0 ; i < CLK_MSR_MAX ; ++i) {
 583                if (!msr_table[i].name)
 584                        continue;
 585
 586                val = meson_measure_best_id(&msr_table[i], &precision);
 587                if (val < 0)
 588                        return val;
 589
 590                seq_printf(s, " %-20s %10d    +/-%dHz\n",
 591                           msr_table[i].name, val, precision);
 592        }
 593
 594        return 0;
 595}
 596DEFINE_SHOW_ATTRIBUTE(clk_msr_summary);
 597
 598static const struct regmap_config meson_clk_msr_regmap_config = {
 599        .reg_bits = 32,
 600        .val_bits = 32,
 601        .reg_stride = 4,
 602        .max_register = MSR_CLK_REG2,
 603};
 604
 605static int meson_msr_probe(struct platform_device *pdev)
 606{
 607        const struct meson_msr_id *match_data;
 608        struct meson_msr *priv;
 609        struct resource *res;
 610        struct dentry *root, *clks;
 611        void __iomem *base;
 612        int i;
 613
 614        priv = devm_kzalloc(&pdev->dev, sizeof(struct meson_msr),
 615                            GFP_KERNEL);
 616        if (!priv)
 617                return -ENOMEM;
 618
 619        match_data = device_get_match_data(&pdev->dev);
 620        if (!match_data) {
 621                dev_err(&pdev->dev, "failed to get match data\n");
 622                return -ENODEV;
 623        }
 624
 625        memcpy(priv->msr_table, match_data, sizeof(priv->msr_table));
 626
 627        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 628        base = devm_ioremap_resource(&pdev->dev, res);
 629        if (IS_ERR(base))
 630                return PTR_ERR(base);
 631
 632        priv->regmap = devm_regmap_init_mmio(&pdev->dev, base,
 633                                             &meson_clk_msr_regmap_config);
 634        if (IS_ERR(priv->regmap))
 635                return PTR_ERR(priv->regmap);
 636
 637        root = debugfs_create_dir("meson-clk-msr", NULL);
 638        clks = debugfs_create_dir("clks", root);
 639
 640        debugfs_create_file("measure_summary", 0444, root,
 641                            priv->msr_table, &clk_msr_summary_fops);
 642
 643        for (i = 0 ; i < CLK_MSR_MAX ; ++i) {
 644                if (!priv->msr_table[i].name)
 645                        continue;
 646
 647                priv->msr_table[i].priv = priv;
 648
 649                debugfs_create_file(priv->msr_table[i].name, 0444, clks,
 650                                    &priv->msr_table[i], &clk_msr_fops);
 651        }
 652
 653        return 0;
 654}
 655
 656static const struct of_device_id meson_msr_match_table[] = {
 657        {
 658                .compatible = "amlogic,meson-gx-clk-measure",
 659                .data = (void *)clk_msr_gx,
 660        },
 661        {
 662                .compatible = "amlogic,meson8-clk-measure",
 663                .data = (void *)clk_msr_m8,
 664        },
 665        {
 666                .compatible = "amlogic,meson8b-clk-measure",
 667                .data = (void *)clk_msr_m8,
 668        },
 669        {
 670                .compatible = "amlogic,meson-axg-clk-measure",
 671                .data = (void *)clk_msr_axg,
 672        },
 673        {
 674                .compatible = "amlogic,meson-g12a-clk-measure",
 675                .data = (void *)clk_msr_g12a,
 676        },
 677        {
 678                .compatible = "amlogic,meson-sm1-clk-measure",
 679                .data = (void *)clk_msr_sm1,
 680        },
 681        { /* sentinel */ }
 682};
 683MODULE_DEVICE_TABLE(of, meson_msr_match_table);
 684
 685static struct platform_driver meson_msr_driver = {
 686        .probe  = meson_msr_probe,
 687        .driver = {
 688                .name           = "meson_msr",
 689                .of_match_table = meson_msr_match_table,
 690        },
 691};
 692module_platform_driver(meson_msr_driver);
 693MODULE_LICENSE("GPL v2");
 694