timer.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * OMAP1 Dual-Mode Timers - platform device registration
  4. *
  5. * Contains first level initialization routines which internally
  6. * generates timer device information and registers with linux
  7. * device model. It also has a low level function to change the timer
  8. * input clock source.
  9. *
  10. * Copyright (C) 2011 Texas Instruments Incorporated - https://www.ti.com/
  11. * Tarun Kanti DebBarma <[email protected]>
  12. * Thara Gopinath <[email protected]>
  13. */
  14. #include <linux/clk.h>
  15. #include <linux/io.h>
  16. #include <linux/err.h>
  17. #include <linux/slab.h>
  18. #include <linux/platform_device.h>
  19. #include <linux/platform_data/dmtimer-omap.h>
  20. #include <linux/soc/ti/omap1-io.h>
  21. #include <clocksource/timer-ti-dm.h>
  22. #include "soc.h"
  23. #define OMAP1610_GPTIMER1_BASE 0xfffb1400
  24. #define OMAP1610_GPTIMER2_BASE 0xfffb1c00
  25. #define OMAP1610_GPTIMER3_BASE 0xfffb2400
  26. #define OMAP1610_GPTIMER4_BASE 0xfffb2c00
  27. #define OMAP1610_GPTIMER5_BASE 0xfffb3400
  28. #define OMAP1610_GPTIMER6_BASE 0xfffb3c00
  29. #define OMAP1610_GPTIMER7_BASE 0xfffb7400
  30. #define OMAP1610_GPTIMER8_BASE 0xfffbd400
  31. #define OMAP1_DM_TIMER_COUNT 8
  32. static int omap1_dm_timer_set_src(struct platform_device *pdev,
  33. int source)
  34. {
  35. int n = (pdev->id - 1) << 1;
  36. u32 l;
  37. l = omap_readl(MOD_CONF_CTRL_1) & ~(0x03 << n);
  38. l |= source << n;
  39. omap_writel(l, MOD_CONF_CTRL_1);
  40. return 0;
  41. }
  42. static int __init omap1_dm_timer_init(void)
  43. {
  44. int i;
  45. int ret;
  46. struct dmtimer_platform_data *pdata;
  47. struct platform_device *pdev;
  48. if (!cpu_is_omap16xx())
  49. return 0;
  50. for (i = 1; i <= OMAP1_DM_TIMER_COUNT; i++) {
  51. struct resource res[2];
  52. u32 base, irq;
  53. switch (i) {
  54. case 1:
  55. base = OMAP1610_GPTIMER1_BASE;
  56. irq = INT_1610_GPTIMER1;
  57. break;
  58. case 2:
  59. base = OMAP1610_GPTIMER2_BASE;
  60. irq = INT_1610_GPTIMER2;
  61. break;
  62. case 3:
  63. base = OMAP1610_GPTIMER3_BASE;
  64. irq = INT_1610_GPTIMER3;
  65. break;
  66. case 4:
  67. base = OMAP1610_GPTIMER4_BASE;
  68. irq = INT_1610_GPTIMER4;
  69. break;
  70. case 5:
  71. base = OMAP1610_GPTIMER5_BASE;
  72. irq = INT_1610_GPTIMER5;
  73. break;
  74. case 6:
  75. base = OMAP1610_GPTIMER6_BASE;
  76. irq = INT_1610_GPTIMER6;
  77. break;
  78. case 7:
  79. base = OMAP1610_GPTIMER7_BASE;
  80. irq = INT_1610_GPTIMER7;
  81. break;
  82. case 8:
  83. base = OMAP1610_GPTIMER8_BASE;
  84. irq = INT_1610_GPTIMER8;
  85. break;
  86. default:
  87. /*
  88. * not supposed to reach here.
  89. * this is to remove warning.
  90. */
  91. return -EINVAL;
  92. }
  93. pdev = platform_device_alloc("omap_timer", i);
  94. if (!pdev) {
  95. pr_err("%s: Failed to device alloc for dmtimer%d\n",
  96. __func__, i);
  97. return -ENOMEM;
  98. }
  99. memset(res, 0, 2 * sizeof(struct resource));
  100. res[0].start = base;
  101. res[0].end = base + 0x46;
  102. res[0].flags = IORESOURCE_MEM;
  103. res[1].start = irq;
  104. res[1].end = irq;
  105. res[1].flags = IORESOURCE_IRQ;
  106. ret = platform_device_add_resources(pdev, res,
  107. ARRAY_SIZE(res));
  108. if (ret) {
  109. dev_err(&pdev->dev, "%s: Failed to add resources.\n",
  110. __func__);
  111. goto err_free_pdev;
  112. }
  113. pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
  114. if (!pdata) {
  115. ret = -ENOMEM;
  116. goto err_free_pdata;
  117. }
  118. pdata->set_timer_src = omap1_dm_timer_set_src;
  119. pdata->timer_capability = OMAP_TIMER_ALWON |
  120. OMAP_TIMER_NEEDS_RESET | OMAP_TIMER_HAS_DSP_IRQ;
  121. ret = platform_device_add_data(pdev, pdata, sizeof(*pdata));
  122. if (ret) {
  123. dev_err(&pdev->dev, "%s: Failed to add platform data.\n",
  124. __func__);
  125. goto err_free_pdata;
  126. }
  127. ret = platform_device_add(pdev);
  128. if (ret) {
  129. dev_err(&pdev->dev, "%s: Failed to add platform device.\n",
  130. __func__);
  131. goto err_free_pdata;
  132. }
  133. dev_dbg(&pdev->dev, " Registered.\n");
  134. }
  135. return 0;
  136. err_free_pdata:
  137. kfree(pdata);
  138. err_free_pdev:
  139. platform_device_put(pdev);
  140. return ret;
  141. }
  142. arch_initcall(omap1_dm_timer_init);