3 * Copyright (C) 2015, Fuzhou Rockchip Electronics Co., Ltd
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
17 #include <linux/kernel.h>
18 #include <linux/init.h>
19 #include <linux/module.h>
23 #include <linux/of_address.h>
24 #include <asm/compiler.h>
26 #define PSCI_OS_SUSPEND_CTRBITS (0xa600ffc0)
28 #define SEC_REG_RW_SHT (0x0)
29 #define SEC_REG_RD (0x0)
30 #define SEC_REG_WR (0x1)
32 #define SEC_REG_BITS_SHT (0x1)
33 #define SEC_REG_32 (0x0)
34 #define SEC_REG_64 (0x2)
36 #define SEC_REG_RD_32 (SEC_REG_RD | SEC_REG_32)
37 #define SEC_REG_RD_64 (SEC_REG_RD | SEC_REG_64)
38 #define SEC_REG_WR_32 (SEC_REG_WR | SEC_REG_32)
39 #define SEC_REG_WR_64 (SEC_REG_WR | SEC_REG_64)
42 * arg2: rd/wr control, bit[0] 0-rd 1-rt, bit[1] 0-32bit, 1-64bit
44 * arg0: read or write val
45 * function_id: return fail/succes
47 static noinline int __invoke_reg_pm_wr_fn_smc(u64 function_id, u64 arg0, u64 arg1,
56 : "+r" (function_id) ,"+r" (arg0)
57 : "r" (arg1), "r" (arg2));
61 static noinline int __invoke_reg_pm_rd_fn_smc(u64 function_id, u64 arg0, u64 arg1,
70 : "+r" (function_id) ,"+r" (arg0)
71 : "r" (arg1), "r" (arg2));
78 static int (*invoke_regs_pm_wr_fn)(u64, u64 , u64, u64) = __invoke_reg_pm_wr_fn_smc;
79 static int (*invoke_regs_pm_rd_fn)(u64, u64 , u64, u64, u64 *) = __invoke_reg_pm_rd_fn_smc;
81 static int pmu_ctlbits_rd_32(u32 *val)
85 ret = invoke_regs_pm_rd_fn(PSCI_OS_SUSPEND_CTRBITS, 0, 0, SEC_REG_RD, &val_64);
91 static int pmu_ctlbits_wr_32(u32 val)
94 return invoke_regs_pm_wr_fn(PSCI_OS_SUSPEND_CTRBITS, val_64, 0, SEC_REG_WR);
97 static int __init rk3688_suspend_init(void)
99 struct device_node *parent;
100 u32 pm_ctrbits, rd_ctrbits = 0;
102 parent = of_find_node_by_name(NULL, "rockchip_suspend");
104 if (IS_ERR_OR_NULL(parent)) {
105 printk(KERN_ERR "%s dev node err\n", __func__);
109 if(of_property_read_u32_array(parent,"rockchip,ctrbits",&pm_ctrbits,1)) {
110 printk(KERN_ERR "%s:get pm ctr error\n",__func__);
114 pmu_ctlbits_wr_32(pm_ctrbits);
115 pmu_ctlbits_rd_32(&rd_ctrbits);
117 if (rd_ctrbits != pm_ctrbits) {
118 printk(KERN_ERR "%s read val error\n", __func__);
122 printk(KERN_INFO "%s: pm_ctrbits =0x%x\n", __func__, pm_ctrbits);
127 late_initcall_sync(rk3688_suspend_init);