digital_sensor_test.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. /*
  2. * Copyright (C) 2017-2022 Alibaba Group Holding Limited
  3. *
  4. * SPDX-License-Identifier: GPL-2.0+
  5. */
  6. #include <common.h>
  7. #include <asm/io.h>
  8. #include <asm/types.h>
  9. #include <thead/clock_config.h>
  10. #include <linux/bitops.h>
  11. #include <asm/arch-thead/light-iopmp.h>
  12. #include <asm/arch-thead/light-plic.h>
  13. #include <thead/clock_config.h>
  14. #define TEE_LIGHT_APCLK_ADDRBASE ((void __iomem *)0xffff011000)
  15. #define REG_TEESYS_CLK_TEECFG ((void __iomem *)TEE_LIGHT_APCLK_ADDRBASE + 0x1cc)
  16. /* VIDEO PLL */
  17. #define TEESYS_I1_HCLK_DIV_EN BIT(12)
  18. #define TEESYS_I1_HCLK_DIV_NUM_SHIFT 8
  19. #define TEESYS_I1_HCLK_DIV_NUM_MASK 0xf
  20. #define LIGHT_CPUFREQ_THRE 1500000
  21. #define LIGHT_C910_BUS_CLK_SYNC BIT(11)
  22. #define LIGHT_C910_BUS_CLK_RATIO_MASK 0x700
  23. #define LIGHT_C910_BUS_CLK_DIV_RATIO_2 0x100
  24. #define LIGHT_C910_BUS_CLK_DIV_RATIO_3 0x200
  25. extern int ds_init(void);
  26. bool global_ds_init = false;
  27. static int ds_cpu_alarm_clk_set(cmd_tbl_t *cmdtp, int flag, int argc,
  28. char * const argv[])
  29. {
  30. unsigned long new_freq;
  31. int ret = 0;
  32. u32 val;
  33. const struct clk_info *parent;
  34. if (argc != 2) {
  35. printf("invalid input parameters\n");
  36. return -EINVAL;
  37. }
  38. if (strict_strtoul(argv[1], 10, &new_freq) < 0)
  39. return CMD_RET_USAGE;
  40. val = readl(TEE_LIGHT_APCLK_ADDRBASE + 0x100);
  41. val &= ~LIGHT_C910_BUS_CLK_RATIO_MASK;
  42. val |= LIGHT_C910_BUS_CLK_DIV_RATIO_3;
  43. writel(val, TEE_LIGHT_APCLK_ADDRBASE + 0x100);
  44. val &= ~LIGHT_C910_BUS_CLK_SYNC;
  45. writel(val, TEE_LIGHT_APCLK_ADDRBASE + 0x100);
  46. udelay(1);
  47. val |= LIGHT_C910_BUS_CLK_SYNC;
  48. writel(val, TEE_LIGHT_APCLK_ADDRBASE + 0x100);
  49. udelay(1);
  50. printf("wait for cpu frequency alarm, rate: %ld\n", new_freq);
  51. parent = clk_light_get_parent("c910_cclk");
  52. if (!strcmp(parent->clk_name, "cpu_pll1_foutpostdiv")) {
  53. ret = clk_light_set_rate("c910_cclk_i0", CLK_DEV_MUX, new_freq);
  54. if (ret) {
  55. printf("failed to set cpu frequency\n");
  56. ret = -EINVAL;
  57. goto out;
  58. }
  59. udelay(3);
  60. ret = clk_light_set_parent("c910_cclk", "c910_cclk_i0");
  61. if (ret) {
  62. printf("failed to set parent clock for cpu\n");
  63. ret = -EINVAL;
  64. goto out;
  65. }
  66. } else {
  67. ret = clk_light_set_rate("cpu_pll1_foutpostdiv", CLK_DEV_PLL, new_freq);
  68. if (ret) {
  69. printf("failed to set cpu frequency\n");
  70. ret = -EINVAL;
  71. goto out;
  72. }
  73. udelay(3);
  74. ret = clk_light_set_parent("c910_cclk", "cpu_pll1_foutpostdiv");
  75. if (ret) {
  76. printf("failed to set parent clock for cpu\n");
  77. ret = -EINVAL;
  78. goto out;
  79. }
  80. }
  81. printf("C910 CPU FREQ: %ldMHz\n", new_freq / 1000000);
  82. out:
  83. return ret;
  84. }
  85. static int ds_3to6_alarm_clk_set(cmd_tbl_t *cmdtp, int flag, int argc,
  86. char * const argv[])
  87. {
  88. unsigned long div;
  89. int ret = 0;
  90. u32 cfg;
  91. if (argc != 2) {
  92. printf("invalid input parameters\n");
  93. return -EINVAL;
  94. }
  95. if (strict_strtoul(argv[1], 10, &div) < 0)
  96. return CMD_RET_USAGE;
  97. if (div < 2 || div > 15) {
  98. printf("invalid teesys clock divider number(%ld)\n", div);
  99. return -EINVAL;
  100. }
  101. cfg = readl(REG_TEESYS_CLK_TEECFG);
  102. cfg &= ~TEESYS_I1_HCLK_DIV_EN;
  103. writel(cfg, REG_TEESYS_CLK_TEECFG);
  104. cfg &= ~(TEESYS_I1_HCLK_DIV_NUM_MASK << TEESYS_I1_HCLK_DIV_NUM_SHIFT);
  105. cfg |= (div & TEESYS_I1_HCLK_DIV_NUM_MASK) << TEESYS_I1_HCLK_DIV_NUM_SHIFT;
  106. cfg |= TEESYS_I1_HCLK_DIV_EN;
  107. writel(cfg, REG_TEESYS_CLK_TEECFG);
  108. return ret;
  109. }
  110. static int ds_7_alarm_clk_set(cmd_tbl_t *cmdtp, int flag, int argc,
  111. char * const argv[])
  112. {
  113. return ds_3to6_alarm_clk_set(cmdtp, flag, argc, argv);
  114. }
  115. static int ds_init_cfg(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
  116. {
  117. if (!global_ds_init) {
  118. global_ds_init = true;
  119. return ds_init();
  120. }
  121. return 0;
  122. }
  123. U_BOOT_CMD(ds_init, 1, 0, ds_init_cfg, "ds_init", "Initalize the digital sensor controller");
  124. U_BOOT_CMD(ds_cpu_alarm, 2, 0, ds_cpu_alarm_clk_set, "ds_cpu_alarm 1500000000", "digital sensor cpu0~cpu3 alarm test");
  125. U_BOOT_CMD(ds_3to6_alarm, 2, 0, ds_3to6_alarm_clk_set, "ds_3to6_alarm 3", "digital sensor for digital3~digital6 alarm test");
  126. U_BOOT_CMD(ds_7_alarm, 2, 0, ds_7_alarm_clk_set, "ds_7_alarm 3", "digital sensor for digital7 alarm test");