pm.c 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Zynq power management
  4. *
  5. * Copyright (C) 2012 - 2014 Xilinx
  6. *
  7. * Sören Brinkmann <[email protected]>
  8. */
  9. #include <linux/io.h>
  10. #include <linux/of_address.h>
  11. #include <linux/of_device.h>
  12. #include "common.h"
  13. /* register offsets */
  14. #define DDRC_CTRL_REG1_OFFS 0x60
  15. #define DDRC_DRAM_PARAM_REG3_OFFS 0x20
  16. /* bitfields */
  17. #define DDRC_CLOCKSTOP_MASK BIT(23)
  18. #define DDRC_SELFREFRESH_MASK BIT(12)
  19. static void __iomem *ddrc_base;
  20. /**
  21. * zynq_pm_ioremap() - Create IO mappings
  22. * @comp: DT compatible string
  23. * Return: Pointer to the mapped memory or NULL.
  24. *
  25. * Remap the memory region for a compatible DT node.
  26. */
  27. static void __iomem *zynq_pm_ioremap(const char *comp)
  28. {
  29. struct device_node *np;
  30. void __iomem *base = NULL;
  31. np = of_find_compatible_node(NULL, NULL, comp);
  32. if (np) {
  33. base = of_iomap(np, 0);
  34. of_node_put(np);
  35. } else {
  36. pr_warn("%s: no compatible node found for '%s'\n", __func__,
  37. comp);
  38. }
  39. return base;
  40. }
  41. /**
  42. * zynq_pm_late_init() - Power management init
  43. *
  44. * Initialization of power management related features and infrastructure.
  45. */
  46. void __init zynq_pm_late_init(void)
  47. {
  48. u32 reg;
  49. ddrc_base = zynq_pm_ioremap("xlnx,zynq-ddrc-a05");
  50. if (!ddrc_base) {
  51. pr_warn("%s: Unable to map DDRC IO memory.\n", __func__);
  52. } else {
  53. /*
  54. * Enable DDRC clock stop feature. The HW takes care of
  55. * entering/exiting the correct mode depending
  56. * on activity state.
  57. */
  58. reg = readl(ddrc_base + DDRC_DRAM_PARAM_REG3_OFFS);
  59. reg |= DDRC_CLOCKSTOP_MASK;
  60. writel(reg, ddrc_base + DDRC_DRAM_PARAM_REG3_OFFS);
  61. }
  62. }