xref: /openbmc/linux/drivers/gnss/sirf.c (revision 09bae3b6)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * SiRFstar GNSS receiver driver
4  *
5  * Copyright (C) 2018 Johan Hovold <johan@kernel.org>
6  */
7 
8 #include <linux/errno.h>
9 #include <linux/gnss.h>
10 #include <linux/gpio/consumer.h>
11 #include <linux/init.h>
12 #include <linux/interrupt.h>
13 #include <linux/kernel.h>
14 #include <linux/module.h>
15 #include <linux/of.h>
16 #include <linux/pm.h>
17 #include <linux/pm_runtime.h>
18 #include <linux/regulator/consumer.h>
19 #include <linux/serdev.h>
20 #include <linux/slab.h>
21 #include <linux/wait.h>
22 
23 #define SIRF_BOOT_DELAY			500
24 #define SIRF_ON_OFF_PULSE_TIME		100
25 #define SIRF_ACTIVATE_TIMEOUT		200
26 #define SIRF_HIBERNATE_TIMEOUT		200
27 
28 struct sirf_data {
29 	struct gnss_device *gdev;
30 	struct serdev_device *serdev;
31 	speed_t	speed;
32 	struct regulator *vcc;
33 	struct gpio_desc *on_off;
34 	struct gpio_desc *wakeup;
35 	int irq;
36 	bool active;
37 	wait_queue_head_t power_wait;
38 };
39 
40 static int sirf_open(struct gnss_device *gdev)
41 {
42 	struct sirf_data *data = gnss_get_drvdata(gdev);
43 	struct serdev_device *serdev = data->serdev;
44 	int ret;
45 
46 	ret = serdev_device_open(serdev);
47 	if (ret)
48 		return ret;
49 
50 	serdev_device_set_baudrate(serdev, data->speed);
51 	serdev_device_set_flow_control(serdev, false);
52 
53 	ret = pm_runtime_get_sync(&serdev->dev);
54 	if (ret < 0) {
55 		dev_err(&gdev->dev, "failed to runtime resume: %d\n", ret);
56 		pm_runtime_put_noidle(&serdev->dev);
57 		goto err_close;
58 	}
59 
60 	return 0;
61 
62 err_close:
63 	serdev_device_close(serdev);
64 
65 	return ret;
66 }
67 
68 static void sirf_close(struct gnss_device *gdev)
69 {
70 	struct sirf_data *data = gnss_get_drvdata(gdev);
71 	struct serdev_device *serdev = data->serdev;
72 
73 	serdev_device_close(serdev);
74 
75 	pm_runtime_put(&serdev->dev);
76 }
77 
78 static int sirf_write_raw(struct gnss_device *gdev, const unsigned char *buf,
79 				size_t count)
80 {
81 	struct sirf_data *data = gnss_get_drvdata(gdev);
82 	struct serdev_device *serdev = data->serdev;
83 	int ret;
84 
85 	/* write is only buffered synchronously */
86 	ret = serdev_device_write(serdev, buf, count, 0);
87 	if (ret < 0)
88 		return ret;
89 
90 	/* FIXME: determine if interrupted? */
91 	serdev_device_wait_until_sent(serdev, 0);
92 
93 	return count;
94 }
95 
96 static const struct gnss_operations sirf_gnss_ops = {
97 	.open		= sirf_open,
98 	.close		= sirf_close,
99 	.write_raw	= sirf_write_raw,
100 };
101 
102 static int sirf_receive_buf(struct serdev_device *serdev,
103 				const unsigned char *buf, size_t count)
104 {
105 	struct sirf_data *data = serdev_device_get_drvdata(serdev);
106 	struct gnss_device *gdev = data->gdev;
107 
108 	return gnss_insert_raw(gdev, buf, count);
109 }
110 
111 static const struct serdev_device_ops sirf_serdev_ops = {
112 	.receive_buf	= sirf_receive_buf,
113 	.write_wakeup	= serdev_device_write_wakeup,
114 };
115 
116 static irqreturn_t sirf_wakeup_handler(int irq, void *dev_id)
117 {
118 	struct sirf_data *data = dev_id;
119 	struct device *dev = &data->serdev->dev;
120 	int ret;
121 
122 	ret = gpiod_get_value_cansleep(data->wakeup);
123 	dev_dbg(dev, "%s - wakeup = %d\n", __func__, ret);
124 	if (ret < 0)
125 		goto out;
126 
127 	data->active = !!ret;
128 	wake_up_interruptible(&data->power_wait);
129 out:
130 	return IRQ_HANDLED;
131 }
132 
133 static int sirf_wait_for_power_state(struct sirf_data *data, bool active,
134 					unsigned long timeout)
135 {
136 	int ret;
137 
138 	ret = wait_event_interruptible_timeout(data->power_wait,
139 			data->active == active, msecs_to_jiffies(timeout));
140 	if (ret < 0)
141 		return ret;
142 
143 	if (ret == 0) {
144 		dev_warn(&data->serdev->dev, "timeout waiting for active state = %d\n",
145 				active);
146 		return -ETIMEDOUT;
147 	}
148 
149 	return 0;
150 }
151 
152 static void sirf_pulse_on_off(struct sirf_data *data)
153 {
154 	gpiod_set_value_cansleep(data->on_off, 1);
155 	msleep(SIRF_ON_OFF_PULSE_TIME);
156 	gpiod_set_value_cansleep(data->on_off, 0);
157 }
158 
159 static int sirf_set_active(struct sirf_data *data, bool active)
160 {
161 	unsigned long timeout;
162 	int retries = 3;
163 	int ret;
164 
165 	if (active)
166 		timeout = SIRF_ACTIVATE_TIMEOUT;
167 	else
168 		timeout = SIRF_HIBERNATE_TIMEOUT;
169 
170 	while (retries-- > 0) {
171 		sirf_pulse_on_off(data);
172 		ret = sirf_wait_for_power_state(data, active, timeout);
173 		if (ret < 0) {
174 			if (ret == -ETIMEDOUT)
175 				continue;
176 
177 			return ret;
178 		}
179 
180 		break;
181 	}
182 
183 	if (retries == 0)
184 		return -ETIMEDOUT;
185 
186 	return 0;
187 }
188 
189 static int sirf_runtime_suspend(struct device *dev)
190 {
191 	struct sirf_data *data = dev_get_drvdata(dev);
192 
193 	if (!data->on_off)
194 		return regulator_disable(data->vcc);
195 
196 	return sirf_set_active(data, false);
197 }
198 
199 static int sirf_runtime_resume(struct device *dev)
200 {
201 	struct sirf_data *data = dev_get_drvdata(dev);
202 
203 	if (!data->on_off)
204 		return regulator_enable(data->vcc);
205 
206 	return sirf_set_active(data, true);
207 }
208 
209 static int __maybe_unused sirf_suspend(struct device *dev)
210 {
211 	struct sirf_data *data = dev_get_drvdata(dev);
212 	int ret = 0;
213 
214 	if (!pm_runtime_suspended(dev))
215 		ret = sirf_runtime_suspend(dev);
216 
217 	if (data->wakeup)
218 		disable_irq(data->irq);
219 
220 	return ret;
221 }
222 
223 static int __maybe_unused sirf_resume(struct device *dev)
224 {
225 	struct sirf_data *data = dev_get_drvdata(dev);
226 	int ret = 0;
227 
228 	if (data->wakeup)
229 		enable_irq(data->irq);
230 
231 	if (!pm_runtime_suspended(dev))
232 		ret = sirf_runtime_resume(dev);
233 
234 	return ret;
235 }
236 
237 static const struct dev_pm_ops sirf_pm_ops = {
238 	SET_SYSTEM_SLEEP_PM_OPS(sirf_suspend, sirf_resume)
239 	SET_RUNTIME_PM_OPS(sirf_runtime_suspend, sirf_runtime_resume, NULL)
240 };
241 
242 static int sirf_parse_dt(struct serdev_device *serdev)
243 {
244 	struct sirf_data *data = serdev_device_get_drvdata(serdev);
245 	struct device_node *node = serdev->dev.of_node;
246 	u32 speed = 9600;
247 
248 	of_property_read_u32(node, "current-speed", &speed);
249 
250 	data->speed = speed;
251 
252 	return 0;
253 }
254 
255 static int sirf_probe(struct serdev_device *serdev)
256 {
257 	struct device *dev = &serdev->dev;
258 	struct gnss_device *gdev;
259 	struct sirf_data *data;
260 	int ret;
261 
262 	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
263 	if (!data)
264 		return -ENOMEM;
265 
266 	gdev = gnss_allocate_device(dev);
267 	if (!gdev)
268 		return -ENOMEM;
269 
270 	gdev->type = GNSS_TYPE_SIRF;
271 	gdev->ops = &sirf_gnss_ops;
272 	gnss_set_drvdata(gdev, data);
273 
274 	data->serdev = serdev;
275 	data->gdev = gdev;
276 
277 	init_waitqueue_head(&data->power_wait);
278 
279 	serdev_device_set_drvdata(serdev, data);
280 	serdev_device_set_client_ops(serdev, &sirf_serdev_ops);
281 
282 	ret = sirf_parse_dt(serdev);
283 	if (ret)
284 		goto err_put_device;
285 
286 	data->vcc = devm_regulator_get(dev, "vcc");
287 	if (IS_ERR(data->vcc)) {
288 		ret = PTR_ERR(data->vcc);
289 		goto err_put_device;
290 	}
291 
292 	data->on_off = devm_gpiod_get_optional(dev, "sirf,onoff",
293 			GPIOD_OUT_LOW);
294 	if (IS_ERR(data->on_off))
295 		goto err_put_device;
296 
297 	if (data->on_off) {
298 		data->wakeup = devm_gpiod_get_optional(dev, "sirf,wakeup",
299 				GPIOD_IN);
300 		if (IS_ERR(data->wakeup))
301 			goto err_put_device;
302 
303 		/*
304 		 * Configurations where WAKEUP has been left not connected,
305 		 * are currently not supported.
306 		 */
307 		if (!data->wakeup) {
308 			dev_err(dev, "no wakeup gpio specified\n");
309 			ret = -ENODEV;
310 			goto err_put_device;
311 		}
312 	}
313 
314 	if (data->wakeup) {
315 		ret = gpiod_to_irq(data->wakeup);
316 		if (ret < 0)
317 			goto err_put_device;
318 
319 		data->irq = ret;
320 
321 		ret = devm_request_threaded_irq(dev, data->irq, NULL,
322 				sirf_wakeup_handler,
323 				IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
324 				"wakeup", data);
325 		if (ret)
326 			goto err_put_device;
327 	}
328 
329 	if (data->on_off) {
330 		ret = regulator_enable(data->vcc);
331 		if (ret)
332 			goto err_put_device;
333 
334 		/* Wait for chip to boot into hibernate mode */
335 		msleep(SIRF_BOOT_DELAY);
336 	}
337 
338 	if (IS_ENABLED(CONFIG_PM)) {
339 		pm_runtime_set_suspended(dev);	/* clear runtime_error flag */
340 		pm_runtime_enable(dev);
341 	} else {
342 		ret = sirf_runtime_resume(dev);
343 		if (ret < 0)
344 			goto err_disable_vcc;
345 	}
346 
347 	ret = gnss_register_device(gdev);
348 	if (ret)
349 		goto err_disable_rpm;
350 
351 	return 0;
352 
353 err_disable_rpm:
354 	if (IS_ENABLED(CONFIG_PM))
355 		pm_runtime_disable(dev);
356 	else
357 		sirf_runtime_suspend(dev);
358 err_disable_vcc:
359 	if (data->on_off)
360 		regulator_disable(data->vcc);
361 err_put_device:
362 	gnss_put_device(data->gdev);
363 
364 	return ret;
365 }
366 
367 static void sirf_remove(struct serdev_device *serdev)
368 {
369 	struct sirf_data *data = serdev_device_get_drvdata(serdev);
370 
371 	gnss_deregister_device(data->gdev);
372 
373 	if (IS_ENABLED(CONFIG_PM))
374 		pm_runtime_disable(&serdev->dev);
375 	else
376 		sirf_runtime_suspend(&serdev->dev);
377 
378 	if (data->on_off)
379 		regulator_disable(data->vcc);
380 
381 	gnss_put_device(data->gdev);
382 };
383 
384 #ifdef CONFIG_OF
385 static const struct of_device_id sirf_of_match[] = {
386 	{ .compatible = "fastrax,uc430" },
387 	{ .compatible = "linx,r4" },
388 	{ .compatible = "wi2wi,w2sg0008i" },
389 	{ .compatible = "wi2wi,w2sg0084i" },
390 	{},
391 };
392 MODULE_DEVICE_TABLE(of, sirf_of_match);
393 #endif
394 
395 static struct serdev_device_driver sirf_driver = {
396 	.driver	= {
397 		.name		= "gnss-sirf",
398 		.of_match_table	= of_match_ptr(sirf_of_match),
399 		.pm		= &sirf_pm_ops,
400 	},
401 	.probe	= sirf_probe,
402 	.remove	= sirf_remove,
403 };
404 module_serdev_device_driver(sirf_driver);
405 
406 MODULE_AUTHOR("Johan Hovold <johan@kernel.org>");
407 MODULE_DESCRIPTION("SiRFstar GNSS receiver driver");
408 MODULE_LICENSE("GPL v2");
409