3 * GPS driver for SiRFstar based chip.
5 * Copyright (C) 2011 Samsung Electronics
6 * Minho Ban <mhban@samsung.com>
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.
13 #include <linux/module.h>
14 #include <linux/init.h>
15 #include <linux/platform_device.h>
16 #include <linux/regulator/consumer.h>
17 #include <linux/mutex.h>
18 #include <linux/err.h>
19 #include <linux/slab.h>
20 #include <linux/delay.h>
21 #include <linux/rfkill.h>
22 #include <asm/mach-types.h>
23 #include <mach/gpio.h>
24 #include <plat/gpio-cfg.h>
29 struct gsd4t_platform_data *pdata;
32 /* No need below if constraints is always_on */
33 struct regulator *vdd_18;
34 struct regulator *rtc_xi;
37 static int gsd4t_set_block(void *data, bool blocked)
39 struct gsd4t_data *bd = data;
40 struct gsd4t_platform_data *pdata = bd->pdata;
46 pr_info("gsd4t on\n");
48 regulator_enable(bd->vdd_18);
49 regulator_enable(bd->rtc_xi);
52 * CSR(SiRF) recommends,
54 * _|^^^|_100ms_|^^^^^^^^^^^^^^^ nrst
55 * _____________,___200ms___|^^^ onoff
59 gpio_set_value(pdata->nrst, 1);
60 gpio_set_value(pdata->onoff, 0);
62 * But real boot sequence should be handled by user layer
63 * (including download firmware) so we don't need control pins
67 gpio_set_value(pdata->nrst, 0);
69 gpio_set_value(pdata->nrst, 1);
71 gpio_set_value(pdata->onoff, 1);
79 pr_info("gsd4t off\n");
81 gpio_set_value(pdata->nrst, 0);
83 regulator_disable(bd->vdd_18);
84 regulator_disable(bd->rtc_xi);
91 static const struct rfkill_ops gsd4t_rfkill_ops = {
92 .set_block = gsd4t_set_block,
95 static int __devinit gsd4t_probe(struct platform_device *dev)
97 struct gsd4t_platform_data *pdata;
98 struct gsd4t_data *bd;
102 pdata = dev->dev.platform_data;
104 dev_err(&dev->dev, "No platform data.\n");
108 bd = kzalloc(sizeof(struct gsd4t_data), GFP_KERNEL);
114 if (gpio_is_valid(pdata->nrst)) {
116 /* GPS_nRST is high */
117 gpio_request(gpio, "GPS_nRST");
118 s3c_gpio_cfgpin(gpio, S3C_GPIO_OUTPUT);
119 gpio_direction_output(gpio, 0);
121 gpio_export(gpio, 1);
122 gpio_export_link(&dev->dev, "reset", gpio);
124 dev_err(&dev->dev, "Invalid nRST pin\n");
126 goto err_invalid_pin1;
130 if (gpio_is_valid(pdata->onoff)) {
133 gpio_request(gpio, "GPS_EN");
134 s3c_gpio_cfgpin(gpio, S3C_GPIO_OUTPUT);
135 gpio_direction_output(gpio, 0);
137 gpio_export(gpio, 1);
138 gpio_export_link(&dev->dev, "onoff", gpio);
140 dev_err(&dev->dev, "Invalid GPS_EN pin\n");
142 goto err_invalid_pin2;
145 /* Optional aiding pin */
146 if (gpio_is_valid(pdata->tsync)) {
148 /* AP_AGPS_TSYNC is low */
149 gpio_request(gpio, "AP_AGPS_TSYNC");
150 s3c_gpio_cfgpin(gpio, S3C_GPIO_OUTPUT);
151 gpio_direction_output(gpio, 0);
153 gpio_export(gpio, 1);
154 gpio_export_link(&dev->dev, "tsync", gpio);
157 /* input UART pin need to set pull-up to prevent floating */
158 if (gpio_is_valid(pdata->uart_rxd))
159 s3c_gpio_setpull(pdata->uart_rxd, S3C_GPIO_PULL_UP);
163 * If always_on power, can remove below.
165 bd->rtc_xi = regulator_get(&dev->dev, "gps_clk");
166 if (IS_ERR_OR_NULL(bd->rtc_xi)) {
167 dev_err(&dev->dev, "gps_clk regulator_get error\n");
169 goto err_regulator_1;
172 bd->vdd_18 = regulator_get(&dev->dev, "v_gps_1.8v");
173 if (IS_ERR_OR_NULL(bd->vdd_18)) {
174 dev_err(&dev->dev, "vdd_18 regulator_get error\n");
176 goto err_regulator_2;
180 * Actually, we don't need rfkill becasue most of power sequences to be
181 * done by user level. Just leave this to know user trggers onoff so we
182 * can set pins PDN mode at suspend/resume.
184 bd->rfk = rfkill_alloc("gsd4t", &dev->dev, RFKILL_TYPE_GPS,
185 &gsd4t_rfkill_ops, bd);
196 rfkill_init_sw_state(bd->rfk, true);
199 ret = rfkill_register(bd->rfk);
203 platform_set_drvdata(dev, bd);
205 dev_info(&dev->dev, "ready\n");
210 rfkill_destroy(bd->rfk);
212 regulator_put(bd->vdd_18);
214 regulator_put(bd->rtc_xi);
216 gpio_unexport(pdata->tsync);
217 gpio_unexport(pdata->onoff);
219 gpio_unexport(pdata->nrst);
225 static int __devexit gsd4t_remove(struct platform_device *dev)
227 struct gsd4t_data *bd = platform_get_drvdata(dev);
228 struct gsd4t_platform_data *pdata = bd->pdata;
231 rfkill_init_sw_state(bd->rfk, true);
233 rfkill_unregister(bd->rfk);
234 rfkill_destroy(bd->rfk);
235 gpio_unexport(pdata->onoff);
236 gpio_unexport(pdata->nrst);
237 gpio_unexport(pdata->tsync);
238 gpio_free(pdata->onoff);
239 gpio_free(pdata->nrst);
241 regulator_put(bd->vdd_18);
242 regulator_put(bd->rtc_xi);
245 platform_set_drvdata(dev, NULL);
251 static int gsd4t_suspend(struct platform_device *dev, pm_message_t stata)
253 struct gsd4t_data *bd = platform_get_drvdata(dev);
254 struct gsd4t_platform_data *pdata = bd->pdata;
257 s5p_gpio_set_pdn_config(pdata->nrst, S3C_GPIO_PDNCFG_OUTPUT1);
259 s5p_gpio_set_pdn_config(pdata->nrst, S3C_GPIO_PDNCFG_OUTPUT0);
264 static int gsd4t_resume(struct platform_device *dev)
269 #define gsd4t_suspend NULL
270 #define gsd4t_resume NULL
273 static struct platform_driver gsd4t_driver = {
274 .probe = gsd4t_probe,
275 .remove = __devexit_p(gsd4t_remove),
276 .suspend = gsd4t_suspend,
277 .resume = gsd4t_resume,
283 static int __init gsd4t_init(void)
285 return platform_driver_register(&gsd4t_driver);
288 static void __exit gsd4t_exit(void)
290 platform_driver_unregister(&gsd4t_driver);
293 module_init(gsd4t_init);
294 module_exit(gsd4t_exit);
296 MODULE_AUTHOR("Minho Ban <mhban@samsung.com>");
297 MODULE_DESCRIPTION("GSD4T GPS driver");
298 MODULE_LICENSE("GPL");