10beb2bd3SSoren Brinkmann /* 20beb2bd3SSoren Brinkmann * Zynq power management 30beb2bd3SSoren Brinkmann * 40beb2bd3SSoren Brinkmann * Copyright (C) 2012 - 2014 Xilinx 50beb2bd3SSoren Brinkmann * 60beb2bd3SSoren Brinkmann * Sören Brinkmann <soren.brinkmann@xilinx.com> 70beb2bd3SSoren Brinkmann * 80beb2bd3SSoren Brinkmann * This program is free software: you can redistribute it and/or modify 90beb2bd3SSoren Brinkmann * it under the terms of the GNU General Public License as published by 100beb2bd3SSoren Brinkmann * the Free Software Foundation, either version 2 of the License, or 110beb2bd3SSoren Brinkmann * (at your option) any later version. 120beb2bd3SSoren Brinkmann * 130beb2bd3SSoren Brinkmann * This program is distributed in the hope that it will be useful, 140beb2bd3SSoren Brinkmann * but WITHOUT ANY WARRANTY; without even the implied warranty of 150beb2bd3SSoren Brinkmann * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 160beb2bd3SSoren Brinkmann * GNU General Public License for more details. 170beb2bd3SSoren Brinkmann * 180beb2bd3SSoren Brinkmann * You should have received a copy of the GNU General Public License 190beb2bd3SSoren Brinkmann * along with this program. If not, see <http://www.gnu.org/licenses/>. 200beb2bd3SSoren Brinkmann */ 210beb2bd3SSoren Brinkmann 220beb2bd3SSoren Brinkmann #include <linux/io.h> 230beb2bd3SSoren Brinkmann #include <linux/of_address.h> 240beb2bd3SSoren Brinkmann #include <linux/of_device.h> 250beb2bd3SSoren Brinkmann #include "common.h" 260beb2bd3SSoren Brinkmann 270beb2bd3SSoren Brinkmann /* register offsets */ 280beb2bd3SSoren Brinkmann #define DDRC_CTRL_REG1_OFFS 0x60 290beb2bd3SSoren Brinkmann #define DDRC_DRAM_PARAM_REG3_OFFS 0x20 300beb2bd3SSoren Brinkmann 310beb2bd3SSoren Brinkmann /* bitfields */ 320beb2bd3SSoren Brinkmann #define DDRC_CLOCKSTOP_MASK BIT(23) 330beb2bd3SSoren Brinkmann #define DDRC_SELFREFRESH_MASK BIT(12) 340beb2bd3SSoren Brinkmann 350beb2bd3SSoren Brinkmann static void __iomem *ddrc_base; 360beb2bd3SSoren Brinkmann 370beb2bd3SSoren Brinkmann /** 380beb2bd3SSoren Brinkmann * zynq_pm_ioremap() - Create IO mappings 390beb2bd3SSoren Brinkmann * @comp: DT compatible string 400beb2bd3SSoren Brinkmann * Return: Pointer to the mapped memory or NULL. 410beb2bd3SSoren Brinkmann * 420beb2bd3SSoren Brinkmann * Remap the memory region for a compatible DT node. 430beb2bd3SSoren Brinkmann */ 440beb2bd3SSoren Brinkmann static void __iomem *zynq_pm_ioremap(const char *comp) 450beb2bd3SSoren Brinkmann { 460beb2bd3SSoren Brinkmann struct device_node *np; 470beb2bd3SSoren Brinkmann void __iomem *base = NULL; 480beb2bd3SSoren Brinkmann 490beb2bd3SSoren Brinkmann np = of_find_compatible_node(NULL, NULL, comp); 500beb2bd3SSoren Brinkmann if (np) { 510beb2bd3SSoren Brinkmann base = of_iomap(np, 0); 520beb2bd3SSoren Brinkmann of_node_put(np); 530beb2bd3SSoren Brinkmann } else { 540beb2bd3SSoren Brinkmann pr_warn("%s: no compatible node found for '%s'\n", __func__, 550beb2bd3SSoren Brinkmann comp); 560beb2bd3SSoren Brinkmann } 570beb2bd3SSoren Brinkmann 580beb2bd3SSoren Brinkmann return base; 590beb2bd3SSoren Brinkmann } 600beb2bd3SSoren Brinkmann 610beb2bd3SSoren Brinkmann /** 620beb2bd3SSoren Brinkmann * zynq_pm_late_init() - Power management init 630beb2bd3SSoren Brinkmann * 64bb9cac24SMoritz Fischer * Initialization of power management related features and infrastructure. 650beb2bd3SSoren Brinkmann */ 660beb2bd3SSoren Brinkmann void __init zynq_pm_late_init(void) 670beb2bd3SSoren Brinkmann { 680beb2bd3SSoren Brinkmann u32 reg; 690beb2bd3SSoren Brinkmann 700beb2bd3SSoren Brinkmann ddrc_base = zynq_pm_ioremap("xlnx,zynq-ddrc-a05"); 710beb2bd3SSoren Brinkmann if (!ddrc_base) { 720beb2bd3SSoren Brinkmann pr_warn("%s: Unable to map DDRC IO memory.\n", __func__); 730beb2bd3SSoren Brinkmann } else { 740beb2bd3SSoren Brinkmann /* 750beb2bd3SSoren Brinkmann * Enable DDRC clock stop feature. The HW takes care of 760beb2bd3SSoren Brinkmann * entering/exiting the correct mode depending 770beb2bd3SSoren Brinkmann * on activity state. 780beb2bd3SSoren Brinkmann */ 790beb2bd3SSoren Brinkmann reg = readl(ddrc_base + DDRC_DRAM_PARAM_REG3_OFFS); 800beb2bd3SSoren Brinkmann reg |= DDRC_CLOCKSTOP_MASK; 810beb2bd3SSoren Brinkmann writel(reg, ddrc_base + DDRC_DRAM_PARAM_REG3_OFFS); 820beb2bd3SSoren Brinkmann } 830beb2bd3SSoren Brinkmann } 84