blob: a0c14ec159b4a3f2942fe9b6c57dcdd8a7000936 [file] [log] [blame]
rjw1f884582022-01-06 17:20:42 +08001/*
2 * Implementation of the GPS EMI driver.
3 *
4 * Copyright (C) 2014 Mediatek
5 * Authors:
6 * Heiping <Heiping.Lei@mediatek.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13/******************************************************************************
14 * Dependency
15 ******************************************************************************/
16#ifdef CONFIG_MTK_GPS_EMI
17#include <linux/kernel.h>
18#include <linux/module.h>
19#include <linux/init.h>
20#include <linux/types.h>
21#include <linux/slab.h>
22#include <linux/fs.h>
23#include <linux/device.h>
24#include <linux/platform_device.h>
25#include <linux/cdev.h>
26#include <linux/errno.h>
27#include <linux/io.h>
28#include <linux/uaccess.h>
29#include <linux/printk.h>
30#include <linux/version.h>
31#include <asm/memblock.h>
32#include <mach/emi_mpu.h>
33#include "gps.h"
34
35#ifdef pr_fmt
36#undef pr_fmt
37#endif
38#define pr_fmt(fmt) "["KBUILD_MODNAME"]" fmt
39
40/******************************************************************************
41 * Definition
42 ******************************************************************************/
43/* device name and major number */
44#define GPSEMI_DEVNAME "gps_emi"
45#define IOCTL_MNL_IMAGE_FILE_TO_MEM 1
46#define IOCTL_MNL_NVRAM_FILE_TO_MEM 2
47#define IOCTL_MNL_NVRAM_MEM_TO_FILE 3
48
49/******************************************************************************
50 * Debug configuration
51 ******************************************************************************/
52#define GPS_DBG_NONE(fmt, arg...) do {} while (0)
53#define GPS_DBG pr_err
54#define GPS_TRC GPS_DBG_NONE
55#define GPS_VER pr_err
56#define GPS_ERR pr_err
57/******************************************************************************
58 * structure & enumeration
59 ******************************************************************************/
60/*---------------------------------------------------------------------------*/
61struct gps_emi_dev {
62 struct class *cls;
63 struct device *dev;
64 dev_t devno;
65 struct cdev chdev;
66};
67/*typedef unsigned char UINT8, *PUINT8, **PPUINT8;*/
68
69/******************************************************************************
70 * local variables
71 ******************************************************************************/
72phys_addr_t gGpsEmiPhyBase;
73UINT8 __iomem *pGpsEmibaseaddr;
74struct gps_emi_dev *devobj;
75#define EMI_MPU_PROTECTION_IS_READY 1
76
77void mtk_wcn_consys_gps_memory_reserve(void)
78{
79#if 0
80#ifdef MTK_WCN_ARM64
81 gGpsEmiPhyBase = arm64_memblock_steal(SZ_1M, SZ_1M);
82#else
83 gGpsEmiPhyBase = arm_memblock_steal(SZ_1M, SZ_1M);
84#endif
85#else
86 gGpsEmiPhyBase = gConEmiPhyBase + SZ_1M;
87
88#endif
89 if (gGpsEmiPhyBase)
90 GPS_DBG("memblock done: 0x%zx\n", (size_t)gGpsEmiPhyBase);
91 else
92 GPS_DBG("memblock fail\n");
93}
94INT32 mtk_wcn_consys_gps_emi_init(void)
95{
96 INT32 iRet = -1;
97
98 mtk_wcn_consys_gps_memory_reserve();
99 if (gGpsEmiPhyBase) {
100 #if CONSYS_EMI_MPU_SETTING
101 /*set MPU for EMI share Memory*/
102 GPS_DBG("setting MPU for EMI share memory\n");
103 #if EMI_MPU_PROTECTION_IS_READY
104 emi_mpu_set_region_protection(gGpsEmiPhyBase,
105 gGpsEmiPhyBase + SZ_1M - 1,
106 20,
107 SET_ACCESS_PERMISSON(FORBIDDEN, FORBIDDEN,
108 FORBIDDEN, FORBIDDEN, FORBIDDEN, NO_PROTECTION,
109 FORBIDDEN, NO_PROTECTION));
110 #endif
111
112 #endif
113 GPS_DBG("get consys start phy address(0x%zx)\n",
114 (size_t)gGpsEmiPhyBase);
115 #if 0
116 /*consys to ap emi remapping register:10001310,
117 *cal remapping address
118 */
119 addrPhy = (gGpsEmiPhyBase & 0xFFF00000) >> 20;
120
121 /*enable consys to ap emi remapping bit12*/
122 addrPhy -= 0x400;/*Gavin ??*/
123 addrPhy = addrPhy | 0x1000;
124
125 CONSYS_REG_WRITE(conn_reg.topckgen_base +
126 CONSYS_EMI_MAPPING_OFFSET, CONSYS_REG_READ
127 (conn_reg.topckgen_base + CONSYS_EMI_MAPPING_OFFSET)
128 | addrPhy);
129
130 GPS_DBG("GPS_EMI_MAPPING dump(0x%08x)\n",
131 CONSYS_REG_READ(conn_reg.topckgen_base
132 + CONSYS_EMI_MAPPING_OFFSET));
133 #endif
134
135 pGpsEmibaseaddr = ioremap_nocache(gGpsEmiPhyBase, SZ_1M);
136 if (pGpsEmibaseaddr != NULL) {
137 UINT8 *pFullPatchName = "/system/etc/firmware/MNL.bin";
138 firmware *pPatch = NULL;
139
140 GPS_DBG("EMI mapping OK(0x%p)\n", pGpsEmibaseaddr);
141 memset_io(pGpsEmibaseaddr, 0, SZ_1M);
142 if ((pFullPatchName != NULL)
143 && (wmt_dev_patch_get(pFullPatchName, &pPatch,
144 0/*BCNT_PATCH_BUF_HEADROOM*/) == 0)) {
145 if (pPatch != NULL) {
146 /*get full name patch success*/
147 GPS_DBG("get full patch name(%s) ",
148 pFullPatchName);
149 GPS_DBG("buf(0x%p) ", (pPatch)->data);
150 GPS_DBG("size(%ld)\n", (pPatch)->size);
151 GPS_DBG("AF get patch, pPatch(0x%p)\n",
152 pPatch);
153 }
154 }
155 if (pPatch != NULL) {
156 if ((pPatch)->size <= SZ_1M) {
157 memcpy(pGpsEmibaseaddr,
158 (pPatch)->data, (pPatch)->size);
159 iRet = 1;
160 }
161 }
162 } else {
163 GPS_DBG("EMI mapping fail\n");
164 }
165 } else {
166 GPS_DBG("gps emi memory address gGpsEmiPhyBase invalid\n");
167 }
168 return iRet;
169}
170
171/*---------------------------------------------------------------------------*/
172long gps_emi_unlocked_ioctl(struct file *file,
173 unsigned int cmd, unsigned long arg)
174{
175 int retval = 0;
176
177 GPS_DBG("cmd (%d),arg(%ld)\n", cmd, arg);
178
179 switch (cmd) {
180 case IOCTL_MNL_IMAGE_FILE_TO_MEM:
181 retval = mtk_wcn_consys_gps_emi_init();
182 GPS_DBG("IOCTL_MNL_IMAGE_FILE_TO_MEM\n");
183 break;
184
185 case IOCTL_MNL_NVRAM_FILE_TO_MEM:
186 GPS_DBG("IOCTL_MNL_NVRAM_FILE_TO_MEM\n");
187 break;
188
189 case IOCTL_MNL_NVRAM_MEM_TO_FILE:
190 GPS_DBG("IOCTL_MNL_NVRAM_MEM_TO_FILE\n");
191 break;
192
193 default:
194 GPS_DBG("unknown cmd (%d)\n", cmd);
195 retval = 0;
196 break;
197 }
198 return retval;
199
200}
201
202/******************************************************************************/
203/*****************************************************************************/
204static int gps_emi_open(struct inode *inode, struct file *file)
205{
206 GPS_TRC();
207 return nonseekable_open(inode, file);
208}
209
210/*****************************************************************************/
211
212
213/*****************************************************************************/
214static int gps_emi_release(struct inode *inode, struct file *file)
215{
216 GPS_TRC();
217
218 return 0;
219}
220
221/******************************************************************************/
222static ssize_t gps_emi_read(struct file *file,
223 char __user *buf, size_t count, loff_t *ppos)
224{
225 ssize_t ret = 0;
226
227 GPS_TRC();
228
229 return ret;
230}
231/******************************************************************************/
232static ssize_t gps_emi_write(struct file *file,
233 const char __user *buf, size_t count,
234 loff_t *ppos)
235{
236 ssize_t ret = 0;
237
238 GPS_TRC();
239
240 return ret;
241}
242
243
244/*****************************************************************************/
245/* Kernel interface */
246static const struct file_operations gps_emi_fops = {
247 .owner = THIS_MODULE,
248 .unlocked_ioctl = gps_emi_unlocked_ioctl,
249 .open = gps_emi_open,
250 .read = gps_emi_read,
251 .write = gps_emi_write,
252 .release = gps_emi_release,
253};
254
255/*****************************************************************************/
256static int gps_emi_probe(struct platform_device *dev)
257{
258 int ret = 0, err = 0;
259
260 devobj = kzalloc(sizeof(*devobj), GFP_KERNEL);
261 if (devobj == NULL) {
262 err = -ENOMEM;
263 ret = -ENOMEM;
264 goto err_out;
265 }
266
267 GPS_DBG("Registering chardev\n");
268 ret = alloc_chrdev_region(&devobj->devno, 0, 1, GPSEMI_DEVNAME);
269 if (ret) {
270 GPS_ERR("alloc_chrdev_region fail: %d\n", ret);
271 kfree(devobj);
272 err = -ENOMEM;
273 goto err_out;
274 } else {
275 GPS_DBG("major: %d, minor: %d\n",
276 MAJOR(devobj->devno), MINOR(devobj->devno));
277 }
278 cdev_init(&devobj->chdev, &gps_emi_fops);
279 devobj->chdev.owner = THIS_MODULE;
280 err = cdev_add(&devobj->chdev, devobj->devno, 1);
281 if (err) {
282 GPS_ERR("cdev_add fail: %d\n", err);
283 kfree(devobj);
284 goto err_out;
285 }
286 devobj->cls = class_create(THIS_MODULE, "gpsemi");
287 if (IS_ERR(devobj->cls)) {
288 GPS_ERR("Unable to create class, err = %d\n",
289 (int)PTR_ERR(devobj->cls));
290 kfree(devobj);
291 goto err_out;
292 }
293 devobj->dev = device_create(devobj->cls, NULL,
294 devobj->devno, devobj, "gps_emi");
295
296 GPS_DBG("Done\n");
297 return 0;
298
299err_out:
300 if (err == 0)
301 cdev_del(&devobj->chdev);
302 if (ret == 0)
303 unregister_chrdev_region(devobj->devno, 1);
304 return -1;
305}
306
307/*****************************************************************************/
308static int gps_emi_remove(struct platform_device *dev)
309{
310 if (!devobj) {
311 GPS_ERR("null pointer: %p\n", devobj);
312 return -1;
313 }
314
315 GPS_DBG("Unregistering chardev\n");
316 cdev_del(&devobj->chdev);
317 unregister_chrdev_region(devobj->devno, 1);
318 device_destroy(devobj->cls, devobj->devno);
319 class_destroy(devobj->cls);
320 kfree(devobj);
321 GPS_DBG("Done\n");
322 return 0;
323}
324
325/*****************************************************************************/
326#ifdef CONFIG_PM
327/*****************************************************************************/
328static int gps_emi_suspend(struct platform_device *dev, pm_message_t state)
329{
330 GPS_DBG("dev = %p, event = %u,", dev, state.event);
331 if (state.event == PM_EVENT_SUSPEND)
332 GPS_DBG("Receive PM_EVENT_SUSPEND!!\n");
333 return 0;
334}
335
336/*****************************************************************************/
337static int gps_emi_resume(struct platform_device *dev)
338{
339 GPS_DBG("");
340 return 0;
341}
342
343/*****************************************************************************/
344#endif /* CONFIG_PM */
345/*****************************************************************************/
346#ifdef CONFIG_OF
347static const struct of_device_id apgps_of_ids[] = {
348 { .compatible = "mediatek,gps_emi-v1", },
349 {}
350};
351#endif
352static struct platform_driver gps_emi_driver = {
353 .probe = gps_emi_probe,
354 .remove = gps_emi_remove,
355#if defined(CONFIG_PM)
356 .suspend = gps_emi_suspend,
357 .resume = gps_emi_resume,
358#endif
359 .driver = {
360 .name = GPSEMI_DEVNAME,
361 .bus = &platform_bus_type,
362#ifdef CONFIG_OF
363 .of_match_table = apgps_of_ids,
364#endif
365 },
366};
367
368/*****************************************************************************/
369static int __init gps_emi_mod_init(void)
370{
371 int ret = 0;
372
373 GPS_TRC();
374
375 ret = platform_driver_register(&gps_emi_driver);
376
377 return ret;
378}
379
380/*****************************************************************************/
381static void __exit gps_emi_mod_exit(void)
382{
383 GPS_TRC();
384 platform_driver_unregister(&gps_emi_driver);
385}
386
387/*****************************************************************************/
388module_init(gps_emi_mod_init);
389module_exit(gps_emi_mod_exit);
390/*****************************************************************************/
391MODULE_AUTHOR("Heiping Lei <Heiping.Lei@mediatek.com>");
392MODULE_DESCRIPTION("GPS EMI Driver");
393MODULE_LICENSE("GPL");
394#endif