clk_sunxi.c 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright (C) 2018 Amarula Solutions.
  4. * Author: Jagan Teki <jagan@amarulasolutions.com>
  5. */
  6. #include <common.h>
  7. #include <clk-uclass.h>
  8. #include <dm.h>
  9. #include <errno.h>
  10. #include <log.h>
  11. #include <reset.h>
  12. #include <asm/io.h>
  13. #include <asm/arch/ccu.h>
  14. #include <linux/bitops.h>
  15. #include <linux/log2.h>
  16. static const struct ccu_clk_gate *priv_to_gate(struct ccu_priv *priv,
  17. unsigned long id)
  18. {
  19. return &priv->desc->gates[id];
  20. }
  21. static int sunxi_set_gate(struct clk *clk, bool on)
  22. {
  23. struct ccu_priv *priv = dev_get_priv(clk->dev);
  24. const struct ccu_clk_gate *gate = priv_to_gate(priv, clk->id);
  25. u32 reg;
  26. if (!(gate->flags & CCU_CLK_F_IS_VALID)) {
  27. printf("%s: (CLK#%ld) unhandled\n", __func__, clk->id);
  28. return 0;
  29. }
  30. debug("%s: (CLK#%ld) off#0x%x, BIT(%d)\n", __func__,
  31. clk->id, gate->off, ilog2(gate->bit));
  32. reg = readl(priv->base + gate->off);
  33. if (on)
  34. reg |= gate->bit;
  35. else
  36. reg &= ~gate->bit;
  37. writel(reg, priv->base + gate->off);
  38. return 0;
  39. }
  40. static int sunxi_clk_enable(struct clk *clk)
  41. {
  42. return sunxi_set_gate(clk, true);
  43. }
  44. static int sunxi_clk_disable(struct clk *clk)
  45. {
  46. return sunxi_set_gate(clk, false);
  47. }
  48. struct clk_ops sunxi_clk_ops = {
  49. .enable = sunxi_clk_enable,
  50. .disable = sunxi_clk_disable,
  51. };
  52. int sunxi_clk_probe(struct udevice *dev)
  53. {
  54. struct ccu_priv *priv = dev_get_priv(dev);
  55. struct clk_bulk clk_bulk;
  56. struct reset_ctl_bulk rst_bulk;
  57. int ret;
  58. priv->base = dev_read_addr_ptr(dev);
  59. if (!priv->base)
  60. return -ENOMEM;
  61. priv->desc = (const struct ccu_desc *)dev_get_driver_data(dev);
  62. if (!priv->desc)
  63. return -EINVAL;
  64. ret = clk_get_bulk(dev, &clk_bulk);
  65. if (!ret)
  66. clk_enable_bulk(&clk_bulk);
  67. ret = reset_get_bulk(dev, &rst_bulk);
  68. if (!ret)
  69. reset_deassert_bulk(&rst_bulk);
  70. return 0;
  71. }