mtk_timer.c 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * MediaTek timer driver
  4. *
  5. * Copyright (C) 2018 MediaTek Inc.
  6. * Author: Ryder Lee <ryder.lee@mediatek.com>
  7. */
  8. #include <clk.h>
  9. #include <common.h>
  10. #include <dm.h>
  11. #include <timer.h>
  12. #include <asm/io.h>
  13. #include <linux/bitops.h>
  14. #define MTK_GPT4_OFFSET_V1 0x40
  15. #define MTK_GPT4_OFFSET_V2 0x80
  16. #define MTK_GPT_CON 0x0
  17. #define MTK_GPT_V1_CLK 0x4
  18. #define MTK_GPT_CNT 0x8
  19. #define GPT_ENABLE BIT(0)
  20. #define GPT_CLEAR BIT(1)
  21. #define GPT_V1_FREERUN GENMASK(5, 4)
  22. #define GPT_V2_FREERUN GENMASK(6, 5)
  23. enum mtk_gpt_ver {
  24. MTK_GPT_V1,
  25. MTK_GPT_V2
  26. };
  27. struct mtk_timer_priv {
  28. void __iomem *base;
  29. unsigned int gpt4_offset;
  30. };
  31. static u64 mtk_timer_get_count(struct udevice *dev)
  32. {
  33. struct mtk_timer_priv *priv = dev_get_priv(dev);
  34. u32 val = readl(priv->base + priv->gpt4_offset + MTK_GPT_CNT);
  35. return timer_conv_64(val);
  36. }
  37. static int mtk_timer_probe(struct udevice *dev)
  38. {
  39. struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev);
  40. struct mtk_timer_priv *priv = dev_get_priv(dev);
  41. struct clk clk, parent;
  42. int ret, gpt_ver;
  43. priv->base = dev_read_addr_ptr(dev);
  44. gpt_ver = dev_get_driver_data(dev);
  45. if (!priv->base)
  46. return -ENOENT;
  47. if (gpt_ver == MTK_GPT_V2) {
  48. priv->gpt4_offset = MTK_GPT4_OFFSET_V2;
  49. writel(GPT_V2_FREERUN | GPT_CLEAR | GPT_ENABLE,
  50. priv->base + priv->gpt4_offset + MTK_GPT_CON);
  51. } else {
  52. priv->gpt4_offset = MTK_GPT4_OFFSET_V1;
  53. writel(GPT_V1_FREERUN | GPT_CLEAR | GPT_ENABLE,
  54. priv->base + priv->gpt4_offset + MTK_GPT_CON);
  55. writel(0, priv->base + priv->gpt4_offset + MTK_GPT_V1_CLK);
  56. }
  57. ret = clk_get_by_index(dev, 0, &clk);
  58. if (ret)
  59. return ret;
  60. ret = clk_get_by_index(dev, 1, &parent);
  61. if (!ret) {
  62. ret = clk_set_parent(&clk, &parent);
  63. if (ret)
  64. return ret;
  65. }
  66. uc_priv->clock_rate = clk_get_rate(&clk);
  67. if (!uc_priv->clock_rate)
  68. return -EINVAL;
  69. return 0;
  70. }
  71. static const struct timer_ops mtk_timer_ops = {
  72. .get_count = mtk_timer_get_count,
  73. };
  74. static const struct udevice_id mtk_timer_ids[] = {
  75. { .compatible = "mediatek,timer", .data = MTK_GPT_V1 },
  76. { .compatible = "mediatek,mt6577-timer", .data = MTK_GPT_V1 },
  77. { .compatible = "mediatek,mt7981-timer", .data = MTK_GPT_V2 },
  78. { .compatible = "mediatek,mt7986-timer", .data = MTK_GPT_V2 },
  79. { }
  80. };
  81. U_BOOT_DRIVER(mtk_timer) = {
  82. .name = "mtk_timer",
  83. .id = UCLASS_TIMER,
  84. .of_match = mtk_timer_ids,
  85. .priv_auto = sizeof(struct mtk_timer_priv),
  86. .probe = mtk_timer_probe,
  87. .ops = &mtk_timer_ops,
  88. .flags = DM_FLAG_PRE_RELOC,
  89. };