blob: 21621b1ba6ee1401e1f36d75b484ec483ecbef4b [file] [log] [blame]
wanwei.jiangd8cfbc12021-12-08 16:32:55 +08001// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
2/*
3 * Copyright (c) 2019 Amlogic, Inc. All rights reserved.
4 */
5
6#include <linux/errno.h>
7#include <linux/err.h>
8#include <linux/of.h>
9#include <linux/module.h>
10#include <linux/of_fdt.h>
11#include <linux/libfdt_env.h>
12#include <linux/of_reserved_mem.h>
13#include <linux/io.h>
14#include <linux/platform_device.h>
15//#include <linux/dma-map-ops.h>
16#include <linux/dma-mapping.h>
17//#include <linux/cma.h>
18#include <linux/arm-smccc.h>
19#undef pr_fmt
20#define pr_fmt(fmt) "secmon: " fmt
21
22static void __iomem *sharemem_in_base;
23static void __iomem *sharemem_out_base;
24static long phy_in_base;
25static long phy_out_base;
26static unsigned long secmon_start_virt;
27static unsigned int secmon_size;
28
29#ifdef CONFIG_ARM64
30#define IN_SIZE 0x6000
31#else
32 #define IN_SIZE 0x6000
33#endif
34 #define OUT_SIZE 0x1000
35static DEFINE_MUTEX(sharemem_mutex);
36#define DEV_REGISTERED 1
37#define DEV_UNREGISTED 0
38
39unsigned int sharemem_in_size = IN_SIZE;
40unsigned int sharemem_out_size = OUT_SIZE;
41
42static int secmon_dev_registered = DEV_UNREGISTED;
43static long get_sharemem_info(unsigned int function_id)
44{
45 struct arm_smccc_res res;
46
47 arm_smccc_smc(function_id, 0, 0, 0, 0, 0, 0, 0, &res);
48
49 return res.a0;
50}
51
52static void get_sharemem_size(unsigned int function_id)
53{
54 struct arm_smccc_res res;
55
56 arm_smccc_smc(function_id, 1, 0, 0, 0, 0, 0, 0, &res);
57 if (res.a0 != -1)
58 sharemem_in_size = res.a0;
59
60 arm_smccc_smc(function_id, 2, 0, 0, 0, 0, 0, 0, &res);
61 if (res.a0 != -1)
62 sharemem_out_size = res.a0;
63}
64
65#define RESERVE_MEM_SIZE 0x300000
66
67int within_secmon_region(unsigned long addr)
68{
69 if (!secmon_start_virt)
70 return 0;
71
72 if (addr >= secmon_start_virt &&
73 addr <= (secmon_start_virt + secmon_size))
74 return 1;
75
76 return 0;
77}
78
79static int secmon_probe(struct platform_device *pdev)
80{
81 struct device_node *np = pdev->dev.of_node;
82 unsigned int id;
83 int ret;
84 // struct page *page;
85 dma_addr_t addr;
86
87 if (!of_property_read_u32(np, "in_base_func", &id))
88 phy_in_base = get_sharemem_info(id);
89
90 if (!of_property_read_u32(np, "out_base_func", &id))
91 phy_out_base = get_sharemem_info(id);
92
93 if (!of_property_read_u32(np, "inout_size_func", &id))
94 get_sharemem_size(id);
95
96 if (of_property_read_u32(np, "reserve_mem_size", &secmon_size)) {
97 pr_err("can't get reserve_mem_size, use default value\n");
98 secmon_size = RESERVE_MEM_SIZE;
99 } else {
100 pr_info("reserve_mem_size:0x%x\n", secmon_size);
101 }
102
103 ret = of_reserved_mem_device_init(&pdev->dev);
104 if (ret) {
105 pr_info("reserve memory init fail:%d\n", ret);
106 return ret;
107 }
108
109 /* page = dma_alloc_from_contiguous(&pdev->dev, secmon_size >> PAGE_SHIFT, 0, 0);
110 if (!page) {
111 pr_err("alloc page failed, ret:%p\n", page);
112 return -ENOMEM;
113 }
114 pr_info("get page:%p, %lx\n", page, page_to_pfn(page));
115 secmon_start_virt = (unsigned long)page_to_virt(page); */
116 secmon_start_virt=(unsigned long)dma_alloc_coherent(&pdev->dev, secmon_size, &addr, GFP_KERNEL);
117
118 if (pfn_valid(__phys_to_pfn(phy_in_base)))
119 sharemem_in_base = (void __iomem *)__phys_to_virt(phy_in_base);
120 else
121 sharemem_in_base = ioremap_cache(phy_in_base, sharemem_in_size);
122
123 if (!sharemem_in_base) {
124 pr_info("secmon share mem in buffer remap fail!\n");
125 return -ENOMEM;
126 }
127
128 if (pfn_valid(__phys_to_pfn(phy_out_base)))
129 sharemem_out_base = (void __iomem *)
130 __phys_to_virt(phy_out_base);
131 else
132 sharemem_out_base = ioremap_cache(phy_out_base,
133 sharemem_out_size);
134
135 if (!sharemem_out_base) {
136 pr_info("secmon share mem out buffer remap fail!\n");
137 return -ENOMEM;
138 }
139 secmon_dev_registered = DEV_REGISTERED;
140 pr_info("share in base: 0x%lx, share out base: 0x%lx\n",
141 (long)sharemem_in_base, (long)sharemem_out_base);
142 pr_info("phy_in_base: 0x%lx, phy_out_base: 0x%lx\n",
143 phy_in_base, phy_out_base);
144
145 return ret;
146}
147
148/* void __init secmon_clear_cma_mmu(void)
149{
150 struct device_node *np;
151 unsigned int clear[2] = {};
152
153 np = of_find_node_by_name(NULL, "secmon");
154 if (!np)
155 return;
156
157 if (of_property_read_u32_array(np, "clear_range", clear, 2))
158 pr_info("can't fine clear_range\n");
159 else
160 pr_info("clear_range:%x %x\n", clear[0], clear[1]);
161
162 if (clear[0]) {
163 struct page *page = phys_to_page(clear[0]);
164 int cnt = clear[1] / PAGE_SIZE;
165
166 cma_mmu_op(page, cnt, 0);
167 }
168} */
169
170static const struct of_device_id secmon_dt_match[] = {
171 { .compatible = "amlogic, secmon" },
172 { /* sentinel */ },
173};
174
175static struct platform_driver secmon_platform_driver = {
176 .probe = secmon_probe,
177 .driver = {
178 .owner = THIS_MODULE,
179 .name = "secmon",
180 .of_match_table = secmon_dt_match,
181 },
182};
183
184int __init meson_secmon_init(void)
185{
186 int ret;
187
188 ret = platform_driver_register(&secmon_platform_driver);
189 WARN((secmon_dev_registered != DEV_REGISTERED),
190 "ERROR: secmon device must be enable!!!\n");
191 return ret;
192}
193
194#ifdef MODULE
195module_init(meson_secmon_init);
196MODULE_LICENSE("GPL v2");
197#else
198subsys_initcall(meson_secmon_init);
199#endif
200
201void meson_sm_mutex_lock(void)
202{
203 mutex_lock(&sharemem_mutex);
204}
205EXPORT_SYMBOL(meson_sm_mutex_lock);
206
207void meson_sm_mutex_unlock(void)
208{
209 mutex_unlock(&sharemem_mutex);
210}
211EXPORT_SYMBOL(meson_sm_mutex_unlock);
212
213void __iomem *get_meson_sm_input_base(void)
214{
215 return sharemem_in_base;
216}
217EXPORT_SYMBOL(get_meson_sm_input_base);
218void __iomem *get_meson_sm_output_base(void)
219{
220 return sharemem_out_base;
221}
222EXPORT_SYMBOL(get_meson_sm_output_base);
223
224long get_secmon_phy_input_base(void)
225{
226 return phy_in_base;
227}
228EXPORT_SYMBOL(get_secmon_phy_input_base);
229
230long get_secmon_phy_output_base(void)
231{
232 return phy_out_base;
233}
234
235unsigned int get_secmon_sharemem_in_size(void)
236{
237 return sharemem_in_size;
238}
239EXPORT_SYMBOL(get_secmon_sharemem_in_size);
240unsigned int get_secmon_sharemem_out_size(void)
241{
242 return sharemem_out_size;
243}
244EXPORT_SYMBOL(get_secmon_sharemem_out_size);
245