pm.c (1609B)
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 <soren.brinkmann@xilinx.com> 8 */ 9 10#include <linux/io.h> 11#include <linux/of_address.h> 12#include <linux/of_device.h> 13#include "common.h" 14 15/* register offsets */ 16#define DDRC_CTRL_REG1_OFFS 0x60 17#define DDRC_DRAM_PARAM_REG3_OFFS 0x20 18 19/* bitfields */ 20#define DDRC_CLOCKSTOP_MASK BIT(23) 21#define DDRC_SELFREFRESH_MASK BIT(12) 22 23static void __iomem *ddrc_base; 24 25/** 26 * zynq_pm_ioremap() - Create IO mappings 27 * @comp: DT compatible string 28 * Return: Pointer to the mapped memory or NULL. 29 * 30 * Remap the memory region for a compatible DT node. 31 */ 32static void __iomem *zynq_pm_ioremap(const char *comp) 33{ 34 struct device_node *np; 35 void __iomem *base = NULL; 36 37 np = of_find_compatible_node(NULL, NULL, comp); 38 if (np) { 39 base = of_iomap(np, 0); 40 of_node_put(np); 41 } else { 42 pr_warn("%s: no compatible node found for '%s'\n", __func__, 43 comp); 44 } 45 46 return base; 47} 48 49/** 50 * zynq_pm_late_init() - Power management init 51 * 52 * Initialization of power management related features and infrastructure. 53 */ 54void __init zynq_pm_late_init(void) 55{ 56 u32 reg; 57 58 ddrc_base = zynq_pm_ioremap("xlnx,zynq-ddrc-a05"); 59 if (!ddrc_base) { 60 pr_warn("%s: Unable to map DDRC IO memory.\n", __func__); 61 } else { 62 /* 63 * Enable DDRC clock stop feature. The HW takes care of 64 * entering/exiting the correct mode depending 65 * on activity state. 66 */ 67 reg = readl(ddrc_base + DDRC_DRAM_PARAM_REG3_OFFS); 68 reg |= DDRC_CLOCKSTOP_MASK; 69 writel(reg, ddrc_base + DDRC_DRAM_PARAM_REG3_OFFS); 70 } 71}