1 #include <linux/input.h>
\r
2 #include <linux/module.h>
\r
3 #include <linux/init.h>
\r
4 #include <linux/interrupt.h>
\r
5 #include <linux/kernel.h>
\r
6 #include <linux/fcntl.h>
\r
7 #include <linux/delay.h>
\r
8 #include <linux/device.h>
\r
9 #include <linux/miscdevice.h>
\r
10 #include <asm/types.h>
\r
11 #include <mach/gpio.h>
\r
12 #include <mach/iomux.h>
\r
13 #include <linux/platform_device.h>
\r
14 #include <asm/uaccess.h>
\r
15 #include <linux/wait.h>
\r
16 #include "rk29_gps.h"
\r
18 #define DBG(x...) printk(KERN_INFO x)
\r
26 static struct rk29_gps_data *pgps;
\r
28 static int rk29_gps_uart_to_gpio(int uart_id)
\r
31 rk29_mux_api_set(GPIO2B3_UART3SOUT_NAME, GPIO2L_GPIO2B3);
\r
32 rk29_mux_api_set(GPIO2B2_UART3SIN_NAME, GPIO2L_GPIO2B2);
\r
34 gpio_request(RK29_PIN2_PB3, NULL);
\r
35 gpio_request(RK29_PIN2_PB2, NULL);
\r
37 gpio_pull_updown(RK29_PIN2_PB3, PullDisable);
\r
38 gpio_pull_updown(RK29_PIN2_PB2, PullDisable);
\r
40 gpio_direction_output(RK29_PIN2_PB3, GPIO_LOW);
\r
41 gpio_direction_output(RK29_PIN2_PB2, GPIO_LOW);
\r
43 gpio_free(RK29_PIN2_PB3);
\r
44 gpio_free(RK29_PIN2_PB2);
\r
46 else if(uart_id == 2) {
\r
47 rk29_mux_api_set(GPIO2B1_UART2SOUT_NAME, GPIO2L_GPIO2B1);
\r
48 rk29_mux_api_set(GPIO2B0_UART2SIN_NAME, GPIO2L_GPIO2B0);
\r
50 gpio_request(RK29_PIN2_PB1, NULL);
\r
51 gpio_request(RK29_PIN2_PB0, NULL);
\r
53 gpio_direction_output(RK29_PIN2_PB1, GPIO_LOW);
\r
54 gpio_direction_output(RK29_PIN2_PB0, GPIO_LOW);
\r
56 else if(uart_id == 1) {
\r
57 rk29_mux_api_set(GPIO2A5_UART1SOUT_NAME, GPIO2L_GPIO2A5);
\r
58 rk29_mux_api_set(GPIO2A4_UART1SIN_NAME, GPIO2L_GPIO2A4);
\r
60 gpio_request(RK29_PIN2_PA5, NULL);
\r
61 gpio_request(RK29_PIN2_PA4, NULL);
\r
63 gpio_direction_output(RK29_PIN2_PA5, GPIO_LOW);
\r
64 gpio_direction_output(RK29_PIN2_PA4, GPIO_LOW);
\r
73 static int rk29_gps_gpio_to_uart(int uart_id)
\r
76 rk29_mux_api_set(GPIO2B3_UART3SOUT_NAME, GPIO2L_UART3_SOUT);
\r
77 rk29_mux_api_set(GPIO2B2_UART3SIN_NAME, GPIO2L_UART3_SIN);
\r
79 gpio_request(RK29_PIN2_PB3, NULL);
\r
80 gpio_request(RK29_PIN2_PB2, NULL);
\r
82 gpio_direction_output(RK29_PIN2_PB3, GPIO_HIGH);
\r
83 gpio_direction_output(RK29_PIN2_PB2, GPIO_HIGH);
\r
85 else if(uart_id == 2) {
\r
86 rk29_mux_api_set(GPIO2B1_UART2SOUT_NAME, GPIO2L_UART2_SOUT);
\r
87 rk29_mux_api_set(GPIO2B0_UART2SIN_NAME, GPIO2L_UART2_SIN);
\r
89 gpio_request(RK29_PIN2_PB1, NULL);
\r
90 gpio_request(RK29_PIN2_PB0, NULL);
\r
92 gpio_direction_output(RK29_PIN2_PB1, GPIO_HIGH);
\r
93 gpio_direction_output(RK29_PIN2_PB0, GPIO_HIGH);
\r
95 else if(uart_id == 1) {
\r
96 rk29_mux_api_set(GPIO2A5_UART1SOUT_NAME, GPIO2L_UART1_SOUT);
\r
97 rk29_mux_api_set(GPIO2A4_UART1SIN_NAME, GPIO2L_UART1_SIN);
\r
99 gpio_request(RK29_PIN2_PA5, NULL);
\r
100 gpio_request(RK29_PIN2_PA4, NULL);
\r
102 gpio_direction_output(RK29_PIN2_PA5, GPIO_HIGH);
\r
103 gpio_direction_output(RK29_PIN2_PA4, GPIO_HIGH);
\r
113 int rk29_gps_suspend(struct platform_device *pdev, pm_message_t state)
\r
115 struct rk29_gps_data *pdata = pdev->dev.platform_data;
\r
118 printk("%s: pdata = NULL ...... \n", __func__);
\r
122 if(pdata->power_flag == 1)
\r
124 rk29_gps_uart_to_gpio(pdata->uart_id);
\r
125 pdata->power_down();
\r
126 pdata->reset(GPIO_LOW);
\r
129 printk("%s\n",__FUNCTION__);
\r
133 int rk29_gps_resume(struct platform_device *pdev)
\r
135 struct rk29_gps_data *pdata = pdev->dev.platform_data;
\r
138 printk("%s: pdata = NULL ...... \n", __func__);
\r
142 if(pdata->power_flag == 1)
\r
144 queue_work(pdata->wq, &pdata->work);
\r
147 printk("%s\n",__FUNCTION__);
\r
151 static void rk29_gps_delay_power_downup(struct work_struct *work)
\r
153 struct rk29_gps_data *pdata = container_of(work, struct rk29_gps_data, work);
\r
154 if (pdata == NULL) {
\r
155 printk("%s: pdata = NULL\n", __func__);
\r
159 DBG("%s: suspend=%d\n", __func__, pdata->suspend);
\r
161 down(&pdata->power_sem);
\r
163 pdata->reset(GPIO_LOW);
\r
167 pdata->reset(GPIO_HIGH);
\r
168 rk29_gps_gpio_to_uart(pdata->uart_id);
\r
170 up(&pdata->power_sem);
\r
173 int rk29_gps_open(struct inode *inode, struct file *filp)
\r
175 DBG("rk29_gps_open\n");
\r
180 ssize_t rk29_gps_read(struct file *filp, char __user *ptr, size_t size, loff_t *pos)
\r
183 printk("%s: user space address is NULL\n", __func__);
\r
185 if (pgps == NULL) {
\r
186 printk("%s: pgps addr is NULL\n", __func__);
\r
190 put_user(pgps->uart_id, ptr);
\r
192 return sizeof(int);
\r
195 int rk29_gps_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
\r
198 struct rk29_gps_data *pdata = pgps;
\r
200 DBG("rk29_gps_ioctl: cmd = %d\n",cmd);
\r
202 ret = down_interruptible(&pdata->power_sem);
\r
204 printk("%s: down power_sem error ret = %d\n", __func__, ret);
\r
210 pdata->reset(GPIO_LOW);
\r
214 rk29_gps_gpio_to_uart(pdata->uart_id);
\r
216 pdata->reset(GPIO_HIGH);
\r
217 pdata->power_flag = 1;
\r
221 rk29_gps_uart_to_gpio(pdata->uart_id);
\r
222 pdata->power_down();
\r
223 pdata->reset(GPIO_LOW);
\r
224 pdata->power_flag = 0;
\r
228 printk("unknown ioctl cmd!\n");
\r
229 up(&pdata->power_sem);
\r
234 up(&pdata->power_sem);
\r
240 int rk29_gps_release(struct inode *inode, struct file *filp)
\r
242 DBG("rk29_gps_release\n");
\r
247 static struct file_operations rk29_gps_fops = {
\r
248 .owner = THIS_MODULE,
\r
249 .open = rk29_gps_open,
\r
250 .read = rk29_gps_read,
\r
251 .unlocked_ioctl = rk29_gps_ioctl,
\r
252 .release = rk29_gps_release,
\r
255 static struct miscdevice rk29_gps_dev =
\r
257 .minor = MISC_DYNAMIC_MINOR,
\r
258 .name = "rk29_gps",
\r
259 .fops = &rk29_gps_fops,
\r
262 static int rk29_gps_probe(struct platform_device *pdev)
\r
265 struct rk29_gps_data *pdata = pdev->dev.platform_data;
\r
269 ret = misc_register(&rk29_gps_dev);
\r
271 printk("rk29 gps register err!\n");
\r
275 sema_init(&pdata->power_sem,1);
\r
276 pdata->wq = create_freezable_workqueue("rk29_gps");
\r
277 INIT_WORK(&pdata->work, rk29_gps_delay_power_downup);
\r
278 pdata->power_flag = 0;
\r
281 rk29_gps_uart_to_gpio(pdata->uart_id);
\r
282 if (pdata->power_down)
\r
283 pdata->power_down();
\r
285 pdata->reset(GPIO_LOW);
\r
290 printk("%s:rk29 GPS initialized\n",__FUNCTION__);
\r
295 static int rk29_gps_remove(struct platform_device *pdev)
\r
297 struct rk29_gps_data *pdata = pdev->dev.platform_data;
\r
301 misc_deregister(&rk29_gps_dev);
\r
302 destroy_workqueue(pdata->wq);
\r
307 static struct platform_driver rk29_gps_driver = {
\r
308 .probe = rk29_gps_probe,
\r
309 .remove = rk29_gps_remove,
\r
310 .suspend = rk29_gps_suspend,
\r
311 .resume = rk29_gps_resume,
\r
313 .name = "rk29_gps",
\r
314 .owner = THIS_MODULE,
\r
318 static int __init rk29_gps_init(void)
\r
320 return platform_driver_register(&rk29_gps_driver);
\r
323 static void __exit rk29_gps_exit(void)
\r
325 platform_driver_unregister(&rk29_gps_driver);
\r
328 module_init(rk29_gps_init);
\r
329 module_exit(rk29_gps_exit);
\r
330 MODULE_DESCRIPTION ("rk29 gps driver");
\r
331 MODULE_LICENSE("GPL");
\r