clkt_iclk.c 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * OMAP2/3 interface clock control
  4. *
  5. * Copyright (C) 2011 Nokia Corporation
  6. * Paul Walmsley
  7. */
  8. #undef DEBUG
  9. #include <linux/kernel.h>
  10. #include <linux/clk-provider.h>
  11. #include <linux/io.h>
  12. #include <linux/clk/ti.h>
  13. #include "clock.h"
  14. /* Register offsets */
  15. #define OMAP24XX_CM_FCLKEN2 0x04
  16. #define CM_AUTOIDLE 0x30
  17. #define CM_ICLKEN 0x10
  18. #define CM_IDLEST 0x20
  19. #define OMAP24XX_CM_IDLEST_VAL 0
  20. /* Private functions */
  21. /* XXX */
  22. void omap2_clkt_iclk_allow_idle(struct clk_hw_omap *clk)
  23. {
  24. u32 v;
  25. struct clk_omap_reg r;
  26. memcpy(&r, &clk->enable_reg, sizeof(r));
  27. r.offset ^= (CM_AUTOIDLE ^ CM_ICLKEN);
  28. v = ti_clk_ll_ops->clk_readl(&r);
  29. v |= (1 << clk->enable_bit);
  30. ti_clk_ll_ops->clk_writel(v, &r);
  31. }
  32. /* XXX */
  33. void omap2_clkt_iclk_deny_idle(struct clk_hw_omap *clk)
  34. {
  35. u32 v;
  36. struct clk_omap_reg r;
  37. memcpy(&r, &clk->enable_reg, sizeof(r));
  38. r.offset ^= (CM_AUTOIDLE ^ CM_ICLKEN);
  39. v = ti_clk_ll_ops->clk_readl(&r);
  40. v &= ~(1 << clk->enable_bit);
  41. ti_clk_ll_ops->clk_writel(v, &r);
  42. }
  43. /**
  44. * omap2430_clk_i2chs_find_idlest - return CM_IDLEST info for 2430 I2CHS
  45. * @clk: struct clk * being enabled
  46. * @idlest_reg: void __iomem ** to store CM_IDLEST reg address into
  47. * @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into
  48. * @idlest_val: pointer to a u8 to store the CM_IDLEST indicator
  49. *
  50. * OMAP2430 I2CHS CM_IDLEST bits are in CM_IDLEST1_CORE, but the
  51. * CM_*CLKEN bits are in CM_{I,F}CLKEN2_CORE. This custom function
  52. * passes back the correct CM_IDLEST register address for I2CHS
  53. * modules. No return value.
  54. */
  55. static void omap2430_clk_i2chs_find_idlest(struct clk_hw_omap *clk,
  56. struct clk_omap_reg *idlest_reg,
  57. u8 *idlest_bit,
  58. u8 *idlest_val)
  59. {
  60. memcpy(idlest_reg, &clk->enable_reg, sizeof(*idlest_reg));
  61. idlest_reg->offset ^= (OMAP24XX_CM_FCLKEN2 ^ CM_IDLEST);
  62. *idlest_bit = clk->enable_bit;
  63. *idlest_val = OMAP24XX_CM_IDLEST_VAL;
  64. }
  65. /* Public data */
  66. const struct clk_hw_omap_ops clkhwops_iclk = {
  67. .allow_idle = omap2_clkt_iclk_allow_idle,
  68. .deny_idle = omap2_clkt_iclk_deny_idle,
  69. };
  70. const struct clk_hw_omap_ops clkhwops_iclk_wait = {
  71. .allow_idle = omap2_clkt_iclk_allow_idle,
  72. .deny_idle = omap2_clkt_iclk_deny_idle,
  73. .find_idlest = omap2_clk_dflt_find_idlest,
  74. .find_companion = omap2_clk_dflt_find_companion,
  75. };
  76. /* 2430 I2CHS has non-standard IDLEST register */
  77. const struct clk_hw_omap_ops clkhwops_omap2430_i2chs_wait = {
  78. .find_idlest = omap2430_clk_i2chs_find_idlest,
  79. .find_companion = omap2_clk_dflt_find_companion,
  80. };