~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/arm/mach-socfpga/pm.c

Version: ~ [ linux-5.6 ] ~ [ linux-5.5.13 ] ~ [ linux-5.4.28 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.113 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.174 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.217 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.217 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.82 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  *  arch/arm/mach-socfpga/pm.c
  3  *
  4  * Copyright (C) 2014-2015 Altera Corporation. All rights reserved.
  5  *
  6  * with code from pm-imx6.c
  7  * Copyright 2011-2014 Freescale Semiconductor, Inc.
  8  * Copyright 2011 Linaro Ltd.
  9  *
 10  * This program is free software; you can redistribute it and/or modify it
 11  * under the terms and conditions of the GNU General Public License,
 12  * version 2, as published by the Free Software Foundation.
 13  *
 14  * This program is distributed in the hope it will be useful, but WITHOUT
 15  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 16  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 17  * more details.
 18  *
 19  * You should have received a copy of the GNU General Public License along with
 20  * this program.  If not, see <http://www.gnu.org/licenses/>.
 21  */
 22 
 23 #include <linux/bitops.h>
 24 #include <linux/genalloc.h>
 25 #include <linux/init.h>
 26 #include <linux/io.h>
 27 #include <linux/of_platform.h>
 28 #include <linux/suspend.h>
 29 #include <asm/suspend.h>
 30 #include <asm/fncpy.h>
 31 #include "core.h"
 32 
 33 /* Pointer to function copied to ocram */
 34 static u32 (*socfpga_sdram_self_refresh_in_ocram)(u32 sdr_base);
 35 
 36 static int socfpga_setup_ocram_self_refresh(void)
 37 {
 38         struct platform_device *pdev;
 39         phys_addr_t ocram_pbase;
 40         struct device_node *np;
 41         struct gen_pool *ocram_pool;
 42         unsigned long ocram_base;
 43         void __iomem *suspend_ocram_base;
 44         int ret = 0;
 45 
 46         np = of_find_compatible_node(NULL, NULL, "mmio-sram");
 47         if (!np) {
 48                 pr_err("%s: Unable to find mmio-sram in dtb\n", __func__);
 49                 return -ENODEV;
 50         }
 51 
 52         pdev = of_find_device_by_node(np);
 53         if (!pdev) {
 54                 pr_warn("%s: failed to find ocram device!\n", __func__);
 55                 ret = -ENODEV;
 56                 goto put_node;
 57         }
 58 
 59         ocram_pool = gen_pool_get(&pdev->dev, NULL);
 60         if (!ocram_pool) {
 61                 pr_warn("%s: ocram pool unavailable!\n", __func__);
 62                 ret = -ENODEV;
 63                 goto put_node;
 64         }
 65 
 66         ocram_base = gen_pool_alloc(ocram_pool, socfpga_sdram_self_refresh_sz);
 67         if (!ocram_base) {
 68                 pr_warn("%s: unable to alloc ocram!\n", __func__);
 69                 ret = -ENOMEM;
 70                 goto put_node;
 71         }
 72 
 73         ocram_pbase = gen_pool_virt_to_phys(ocram_pool, ocram_base);
 74 
 75         suspend_ocram_base = __arm_ioremap_exec(ocram_pbase,
 76                                                 socfpga_sdram_self_refresh_sz,
 77                                                 false);
 78         if (!suspend_ocram_base) {
 79                 pr_warn("%s: __arm_ioremap_exec failed!\n", __func__);
 80                 ret = -ENOMEM;
 81                 goto put_node;
 82         }
 83 
 84         /* Copy the code that puts DDR in self refresh to ocram */
 85         socfpga_sdram_self_refresh_in_ocram =
 86                 (void *)fncpy(suspend_ocram_base,
 87                               &socfpga_sdram_self_refresh,
 88                               socfpga_sdram_self_refresh_sz);
 89 
 90         WARN(!socfpga_sdram_self_refresh_in_ocram,
 91              "could not copy function to ocram");
 92         if (!socfpga_sdram_self_refresh_in_ocram)
 93                 ret = -EFAULT;
 94 
 95 put_node:
 96         of_node_put(np);
 97 
 98         return ret;
 99 }
100 
101 static int socfpga_pm_suspend(unsigned long arg)
102 {
103         u32 ret;
104 
105         if (!sdr_ctl_base_addr)
106                 return -EFAULT;
107 
108         ret = socfpga_sdram_self_refresh_in_ocram((u32)sdr_ctl_base_addr);
109 
110         pr_debug("%s self-refresh loops request=%d exit=%d\n", __func__,
111                  ret & 0xffff, (ret >> 16) & 0xffff);
112 
113         return 0;
114 }
115 
116 static int socfpga_pm_enter(suspend_state_t state)
117 {
118         switch (state) {
119         case PM_SUSPEND_STANDBY:
120         case PM_SUSPEND_MEM:
121                 outer_disable();
122                 cpu_suspend(0, socfpga_pm_suspend);
123                 outer_resume();
124                 break;
125         default:
126                 return -EINVAL;
127         }
128         return 0;
129 }
130 
131 static const struct platform_suspend_ops socfpga_pm_ops = {
132         .valid  = suspend_valid_only_mem,
133         .enter  = socfpga_pm_enter,
134 };
135 
136 static int __init socfpga_pm_init(void)
137 {
138         int ret;
139 
140         ret = socfpga_setup_ocram_self_refresh();
141         if (ret)
142                 return ret;
143 
144         suspend_set_ops(&socfpga_pm_ops);
145         pr_info("SoCFPGA initialized for DDR self-refresh during suspend.\n");
146 
147         return 0;
148 }
149 arch_initcall(socfpga_pm_init);
150 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp