• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * vendor/amlogic/iomap/iomap.c
3  *
4  * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
5  *
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.
10  *
11  * This program is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
14  * more details.
15  *
16  */
17 
18 #include <asm/compiler.h>
19 #include <linux/module.h>
20 #include <linux/kernel.h>
21 #include <linux/init.h>
22 #include <linux/printk.h>
23 #include <linux/string.h>
24 #include <linux/of_address.h>
25 #include <linux/io.h>
26 #include <linux/regmap.h>
27 #include <linux/device.h>
28 #include <linux/of_platform.h>
29 #include <linux/platform_device.h>
30 #include <linux/amlogic/iomap.h>
31 #undef pr_fmt
32 #define pr_fmt(fmt) "aml_iomap: " fmt
33 
34 static const struct of_device_id iomap_dt_match[] = {
35     {.compatible = "amlogic, iomap"},
36     {},
37 };
38 
39 static void __iomem *meson_reg_map[IO_BUS_MAX] = {NULL};
40 static uint meson_reg_max[IO_BUS_MAX] = {0};
41 void __iomem *vpp_base;
42 EXPORT_SYMBOL(vpp_base);
43 unsigned int vpp_max;
44 
aml_reg_read(u32 bus_type,unsigned int reg,unsigned int * val)45 inline int aml_reg_read(u32 bus_type, unsigned int reg, unsigned int *val)
46 {
47     if (bus_type < IO_BUS_MAX && (meson_reg_map[bus_type]) && (meson_reg_max[bus_type] >= reg)) {
48         *val = readl((meson_reg_map[bus_type] + reg));
49         return 0;
50     } else {
51         return -1;
52     }
53 }
54 EXPORT_SYMBOL(aml_reg_read);
55 
aml_reg_write(u32 bus_type,unsigned int reg,unsigned int val)56 inline int aml_reg_write(u32 bus_type, unsigned int reg, unsigned int val)
57 {
58     if (bus_type < IO_BUS_MAX && (meson_reg_map[bus_type]) && (meson_reg_max[bus_type] >= reg)) {
59         writel(val, (meson_reg_map[bus_type] + reg));
60         return 0;
61     } else {
62         return -1;
63     }
64 }
65 EXPORT_SYMBOL(aml_reg_write);
66 
aml_regmap_update_bits(u32 bus_type,unsigned int reg,unsigned int mask,unsigned int val)67 int aml_regmap_update_bits(u32 bus_type, unsigned int reg, unsigned int mask, unsigned int val)
68 {
69     int ret = 0;
70     unsigned int tmp, orig;
71 
72     ret = aml_reg_read(bus_type, reg, &orig);
73     if (ret) {
74         pr_err("read bus reg %x error %d\n", reg, ret);
75         return ret;
76     }
77     tmp = orig & ~mask;
78     tmp |= val & mask;
79     ret = aml_reg_write(bus_type, reg, tmp);
80     if (ret) {
81         pr_err("write bus reg %x error %d\n", reg, ret);
82     }
83     return ret;
84 }
85 EXPORT_SYMBOL(aml_regmap_update_bits);
86 
87 /*
88  * CBUS REG Read Write and Update some bits
89  */
aml_read_cbus(unsigned int reg)90 int aml_read_cbus(unsigned int reg)
91 {
92     int ret, val;
93 
94     ret = aml_reg_read(IO_CBUS_BASE, reg << 2L, &val);
95     if (ret) {
96         pr_err("read cbus reg %x error %d\n", reg, ret);
97         return -1;
98     } else {
99         return val;
100     }
101 }
102 EXPORT_SYMBOL(aml_read_cbus);
103 
aml_write_cbus(unsigned int reg,unsigned int val)104 void aml_write_cbus(unsigned int reg, unsigned int val)
105 {
106     int ret;
107 
108     ret = aml_reg_write(IO_CBUS_BASE, reg << 2L, val);
109     if (ret) {
110         pr_err("write cbus reg %x error %d\n", reg, ret);
111     }
112 }
113 EXPORT_SYMBOL(aml_write_cbus);
114 
aml_cbus_update_bits(unsigned int reg,unsigned int mask,unsigned int val)115 void aml_cbus_update_bits(unsigned int reg, unsigned int mask, unsigned int val)
116 {
117     int ret;
118 
119     ret = aml_regmap_update_bits(IO_CBUS_BASE, reg << 2L, mask, val);
120     if (ret) {
121         pr_err("write cbus reg %x error %d\n", reg, ret);
122     }
123 }
124 EXPORT_SYMBOL(aml_cbus_update_bits);
125 
126 /*
127  * AO REG Read Write and Update some bits
128  */
aml_read_aobus(unsigned int reg)129 int aml_read_aobus(unsigned int reg)
130 {
131     int ret, val;
132 
133     ret = aml_reg_read(IO_AOBUS_BASE, reg, &val);
134     if (ret) {
135         pr_err("read ao bus reg %x error %d\n", reg, ret);
136         return -1;
137     } else {
138         return val;
139     }
140 }
141 EXPORT_SYMBOL(aml_read_aobus);
142 
aml_write_aobus(unsigned int reg,unsigned int val)143 void aml_write_aobus(unsigned int reg, unsigned int val)
144 {
145     int ret;
146 
147     ret = aml_reg_write(IO_AOBUS_BASE, reg, val);
148     if (ret) {
149         pr_err("write ao bus reg %x error %d\n", reg, ret);
150     }
151 }
152 EXPORT_SYMBOL(aml_write_aobus);
153 
aml_aobus_update_bits(unsigned int reg,unsigned int mask,unsigned int val)154 void aml_aobus_update_bits(unsigned int reg, unsigned int mask, unsigned int val)
155 {
156     int ret;
157 
158     ret = aml_regmap_update_bits(IO_AOBUS_BASE, reg, mask, val);
159     if (ret) {
160         pr_err("write aobus reg %x error %d\n", reg, ret);
161     }
162 }
163 EXPORT_SYMBOL(aml_aobus_update_bits);
164 
165 /*
166  ** VCBUS Bus REG Read Write and Update some bits
167  */
aml_read_vcbus(unsigned int reg)168 int aml_read_vcbus(unsigned int reg)
169 {
170     int ret, val;
171     ret = aml_reg_read(IO_VAPB_BUS_BASE, reg << 2L, &val);
172     if (ret) {
173         pr_err("read vcbus reg %x error %d\n", reg, ret);
174         return -1;
175     } else {
176         return val;
177     }
178 }
179 EXPORT_SYMBOL(aml_read_vcbus);
180 
aml_write_vcbus(unsigned int reg,unsigned int val)181 void aml_write_vcbus(unsigned int reg, unsigned int val)
182 {
183     int ret;
184 
185     ret = aml_reg_write(IO_VAPB_BUS_BASE, reg << 2L, val);
186     if (ret) {
187         pr_err("write vcbus reg %x error %d\n", reg, ret);
188     }
189 }
190 EXPORT_SYMBOL(aml_write_vcbus);
191 
aml_vcbus_update_bits(unsigned int reg,unsigned int mask,unsigned int val)192 void aml_vcbus_update_bits(unsigned int reg, unsigned int mask, unsigned int val)
193 {
194     int ret;
195 
196     ret = aml_regmap_update_bits(IO_VAPB_BUS_BASE, reg << 2L, mask, val);
197     if (ret) {
198         pr_err("write vcbus reg %x error %d\n", reg, ret);
199     }
200 }
201 EXPORT_SYMBOL(aml_vcbus_update_bits);
202 
203 /*
204  ** DOS BUS Bus REG Read Write and Update some bits
205  */
aml_read_dosbus(unsigned int reg)206 int aml_read_dosbus(unsigned int reg)
207 {
208     int ret, val;
209 
210     ret = aml_reg_read(IO_APB_BUS_BASE, reg << 2L, &val);
211     if (ret) {
212         pr_err("read vcbus reg %x error %d\n", reg, ret);
213         return -1;
214     } else {
215         return val;
216     }
217 }
218 EXPORT_SYMBOL(aml_read_dosbus);
219 
aml_write_dosbus(unsigned int reg,unsigned int val)220 void aml_write_dosbus(unsigned int reg, unsigned int val)
221 {
222     int ret;
223 
224     ret = aml_reg_write(IO_APB_BUS_BASE, reg << 2L, val);
225     if (ret) {
226         pr_err("write vcbus reg %x error %d\n", reg, ret);
227     }
228 }
229 EXPORT_SYMBOL(aml_write_dosbus);
230 
aml_dosbus_update_bits(unsigned int reg,unsigned int mask,unsigned int val)231 void aml_dosbus_update_bits(unsigned int reg, unsigned int mask, unsigned int val)
232 {
233     int ret;
234 
235     ret = aml_regmap_update_bits(IO_APB_BUS_BASE, reg << 2L, mask, val);
236     if (ret) {
237         pr_err("write vcbus reg %x error %d\n", reg, ret);
238     }
239 }
240 EXPORT_SYMBOL(aml_dosbus_update_bits);
241 
242 /*
243  * HIUBUS REG Read Write and Update some bits
244  */
aml_read_hiubus(unsigned int reg)245 int aml_read_hiubus(unsigned int reg)
246 {
247     int ret, val;
248 
249     ret = aml_reg_read(IO_HIUBUS_BASE, reg << 2L, &val);
250     if (ret) {
251         pr_err("read cbus reg %x error %d\n", reg, ret);
252         return -1;
253     } else {
254         return val;
255     }
256 }
257 EXPORT_SYMBOL(aml_read_hiubus);
258 
aml_write_hiubus(unsigned int reg,unsigned int val)259 void aml_write_hiubus(unsigned int reg, unsigned int val)
260 {
261     int ret;
262 
263     ret = aml_reg_write(IO_HIUBUS_BASE, reg << 2L, val);
264     if (ret) {
265         pr_err("write cbus reg %x error %d\n", reg, ret);
266     }
267 }
268 EXPORT_SYMBOL(aml_write_hiubus);
269 
aml_hiubus_update_bits(unsigned int reg,unsigned int mask,unsigned int val)270 void aml_hiubus_update_bits(unsigned int reg, unsigned int mask, unsigned int val)
271 {
272     int ret;
273 
274     ret = aml_regmap_update_bits(IO_HIUBUS_BASE, reg << 2L, mask, val);
275     if (ret) {
276         pr_err("write cbus reg %x error %d\n", reg, ret);
277     }
278 }
279 EXPORT_SYMBOL(aml_hiubus_update_bits);
280 
iomap_probe(struct platform_device * pdev)281 static int iomap_probe(struct platform_device *pdev)
282 {
283     int i = 0;
284     struct resource res;
285     struct device_node *np, *child;
286 
287     np = pdev->dev.of_node;
288 
289     for_each_child_of_node(np, child)
290     {
291         if (of_address_to_resource(child, 0, &res)) {
292             return -1;
293         }
294         meson_reg_map[i] = ioremap(res.start, resource_size(&res));
295         meson_reg_max[i] = res.end - res.start;
296         i++;
297     }
298     if (i > IO_VAPB_BUS_BASE) {
299         vpp_base = meson_reg_map[IO_VAPB_BUS_BASE];
300         vpp_max = meson_reg_max[IO_VAPB_BUS_BASE];
301     }
302     pr_info("amlogic iomap probe done\n");
303     return 0;
304 }
305 
306 static struct platform_driver iomap_platform_driver = {
307     .probe = iomap_probe,
308     .driver =
309         {
310             .owner = THIS_MODULE,
311             .name = "iomap_version",
312             .of_match_table = iomap_dt_match,
313         },
314 };
315 
meson_iomap_version_init(void)316 int __init meson_iomap_version_init(void)
317 {
318     int ret;
319 
320     ret = platform_driver_register(&iomap_platform_driver);
321 
322     return ret;
323 }
324 core_initcall(meson_iomap_version_init);
325