xref: /openbmc/linux/arch/arm/mach-zynq/pm.c (revision bb9cac24)
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