brintos

brintos / linux-shallow public Read only

0
0
Text · 12.0 KiB · 79375d1 Raw
582 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * SiRFstar GNSS receiver driver4 *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/sched.h>20#include <linux/serdev.h>21#include <linux/slab.h>22#include <linux/wait.h>23 24#define SIRF_BOOT_DELAY			50025#define SIRF_ON_OFF_PULSE_TIME		10026#define SIRF_ACTIVATE_TIMEOUT		20027#define SIRF_HIBERNATE_TIMEOUT		20028/*29 * If no data arrives for this time, we assume that the chip is off.30 * REVISIT: The report cycle is configurable and can be several minutes long,31 * so this will only work reliably if the report cycle is set to a reasonable32 * low value. Also power saving settings (like send data only on movement)33 * might things work even worse.34 * Workaround might be to parse shutdown or bootup messages.35 */36#define SIRF_REPORT_CYCLE	200037 38struct sirf_data {39	struct gnss_device *gdev;40	struct serdev_device *serdev;41	speed_t	speed;42	struct regulator *vcc;43	struct regulator *lna;44	struct gpio_desc *on_off;45	struct gpio_desc *wakeup;46	int irq;47	bool active;48 49	struct mutex gdev_mutex;50	bool open;51 52	struct mutex serdev_mutex;53	int serdev_count;54 55	wait_queue_head_t power_wait;56};57 58static int sirf_serdev_open(struct sirf_data *data)59{60	int ret = 0;61 62	mutex_lock(&data->serdev_mutex);63	if (++data->serdev_count == 1) {64		ret = serdev_device_open(data->serdev);65		if (ret) {66			data->serdev_count--;67			goto out_unlock;68		}69 70		serdev_device_set_baudrate(data->serdev, data->speed);71		serdev_device_set_flow_control(data->serdev, false);72	}73 74out_unlock:75	mutex_unlock(&data->serdev_mutex);76 77	return ret;78}79 80static void sirf_serdev_close(struct sirf_data *data)81{82	mutex_lock(&data->serdev_mutex);83	if (--data->serdev_count == 0)84		serdev_device_close(data->serdev);85	mutex_unlock(&data->serdev_mutex);86}87 88static int sirf_open(struct gnss_device *gdev)89{90	struct sirf_data *data = gnss_get_drvdata(gdev);91	struct serdev_device *serdev = data->serdev;92	int ret;93 94	mutex_lock(&data->gdev_mutex);95	data->open = true;96	mutex_unlock(&data->gdev_mutex);97 98	ret = sirf_serdev_open(data);99	if (ret) {100		mutex_lock(&data->gdev_mutex);101		data->open = false;102		mutex_unlock(&data->gdev_mutex);103		return ret;104	}105 106	ret = pm_runtime_get_sync(&serdev->dev);107	if (ret < 0) {108		dev_err(&gdev->dev, "failed to runtime resume: %d\n", ret);109		pm_runtime_put_noidle(&serdev->dev);110		goto err_close;111	}112 113	return 0;114 115err_close:116	sirf_serdev_close(data);117 118	mutex_lock(&data->gdev_mutex);119	data->open = false;120	mutex_unlock(&data->gdev_mutex);121 122	return ret;123}124 125static void sirf_close(struct gnss_device *gdev)126{127	struct sirf_data *data = gnss_get_drvdata(gdev);128	struct serdev_device *serdev = data->serdev;129 130	sirf_serdev_close(data);131 132	pm_runtime_put(&serdev->dev);133 134	mutex_lock(&data->gdev_mutex);135	data->open = false;136	mutex_unlock(&data->gdev_mutex);137}138 139static int sirf_write_raw(struct gnss_device *gdev, const unsigned char *buf,140				size_t count)141{142	struct sirf_data *data = gnss_get_drvdata(gdev);143	struct serdev_device *serdev = data->serdev;144	int ret;145 146	/* write is only buffered synchronously */147	ret = serdev_device_write(serdev, buf, count, MAX_SCHEDULE_TIMEOUT);148	if (ret < 0 || ret < count)149		return ret;150 151	/* FIXME: determine if interrupted? */152	serdev_device_wait_until_sent(serdev, 0);153 154	return count;155}156 157static const struct gnss_operations sirf_gnss_ops = {158	.open		= sirf_open,159	.close		= sirf_close,160	.write_raw	= sirf_write_raw,161};162 163static size_t sirf_receive_buf(struct serdev_device *serdev,164				const u8 *buf, size_t count)165{166	struct sirf_data *data = serdev_device_get_drvdata(serdev);167	struct gnss_device *gdev = data->gdev;168	int ret = 0;169 170	if (!data->wakeup && !data->active) {171		data->active = true;172		wake_up_interruptible(&data->power_wait);173	}174 175	mutex_lock(&data->gdev_mutex);176	if (data->open)177		ret = gnss_insert_raw(gdev, buf, count);178	mutex_unlock(&data->gdev_mutex);179 180	return ret;181}182 183static const struct serdev_device_ops sirf_serdev_ops = {184	.receive_buf	= sirf_receive_buf,185	.write_wakeup	= serdev_device_write_wakeup,186};187 188static irqreturn_t sirf_wakeup_handler(int irq, void *dev_id)189{190	struct sirf_data *data = dev_id;191	struct device *dev = &data->serdev->dev;192	int ret;193 194	ret = gpiod_get_value_cansleep(data->wakeup);195	dev_dbg(dev, "%s - wakeup = %d\n", __func__, ret);196	if (ret < 0)197		goto out;198 199	data->active = ret;200	wake_up_interruptible(&data->power_wait);201out:202	return IRQ_HANDLED;203}204 205static int sirf_wait_for_power_state_nowakeup(struct sirf_data *data,206						bool active,207						unsigned long timeout)208{209	int ret;210 211	/* Wait for state change (including any shutdown messages). */212	msleep(timeout);213 214	/* Wait for data reception or timeout. */215	data->active = false;216	ret = wait_event_interruptible_timeout(data->power_wait,217			data->active, msecs_to_jiffies(SIRF_REPORT_CYCLE));218	if (ret < 0)219		return ret;220 221	if (ret > 0 && !active)222		return -ETIMEDOUT;223 224	if (ret == 0 && active)225		return -ETIMEDOUT;226 227	return 0;228}229 230static int sirf_wait_for_power_state(struct sirf_data *data, bool active,231					unsigned long timeout)232{233	int ret;234 235	if (!data->wakeup)236		return sirf_wait_for_power_state_nowakeup(data, active, timeout);237 238	ret = wait_event_interruptible_timeout(data->power_wait,239			data->active == active, msecs_to_jiffies(timeout));240	if (ret < 0)241		return ret;242 243	if (ret == 0) {244		dev_warn(&data->serdev->dev, "timeout waiting for active state = %d\n",245				active);246		return -ETIMEDOUT;247	}248 249	return 0;250}251 252static void sirf_pulse_on_off(struct sirf_data *data)253{254	gpiod_set_value_cansleep(data->on_off, 1);255	msleep(SIRF_ON_OFF_PULSE_TIME);256	gpiod_set_value_cansleep(data->on_off, 0);257}258 259static int sirf_set_active(struct sirf_data *data, bool active)260{261	unsigned long timeout;262	int retries = 3;263	int ret;264 265	if (active)266		timeout = SIRF_ACTIVATE_TIMEOUT;267	else268		timeout = SIRF_HIBERNATE_TIMEOUT;269 270	if (!data->wakeup) {271		ret = sirf_serdev_open(data);272		if (ret)273			return ret;274	}275 276	do {277		sirf_pulse_on_off(data);278		ret = sirf_wait_for_power_state(data, active, timeout);279	} while (ret == -ETIMEDOUT && retries--);280 281	if (!data->wakeup)282		sirf_serdev_close(data);283 284	if (ret)285		return ret;286 287	return 0;288}289 290static int sirf_runtime_suspend(struct device *dev)291{292	struct sirf_data *data = dev_get_drvdata(dev);293	int ret2;294	int ret;295 296	if (data->on_off)297		ret = sirf_set_active(data, false);298	else299		ret = regulator_disable(data->vcc);300 301	if (ret)302		return ret;303 304	ret = regulator_disable(data->lna);305	if (ret)306		goto err_reenable;307 308	return 0;309 310err_reenable:311	if (data->on_off)312		ret2 = sirf_set_active(data, true);313	else314		ret2 = regulator_enable(data->vcc);315 316	if (ret2)317		dev_err(dev,318			"failed to reenable power on failed suspend: %d\n",319			ret2);320 321	return ret;322}323 324static int sirf_runtime_resume(struct device *dev)325{326	struct sirf_data *data = dev_get_drvdata(dev);327	int ret;328 329	ret = regulator_enable(data->lna);330	if (ret)331		return ret;332 333	if (data->on_off)334		ret = sirf_set_active(data, true);335	else336		ret = regulator_enable(data->vcc);337 338	if (ret)339		goto err_disable_lna;340 341	return 0;342 343err_disable_lna:344	regulator_disable(data->lna);345 346	return ret;347}348 349static int __maybe_unused sirf_suspend(struct device *dev)350{351	struct sirf_data *data = dev_get_drvdata(dev);352	int ret = 0;353 354	if (!pm_runtime_suspended(dev))355		ret = sirf_runtime_suspend(dev);356 357	if (data->wakeup)358		disable_irq(data->irq);359 360	return ret;361}362 363static int __maybe_unused sirf_resume(struct device *dev)364{365	struct sirf_data *data = dev_get_drvdata(dev);366	int ret = 0;367 368	if (data->wakeup)369		enable_irq(data->irq);370 371	if (!pm_runtime_suspended(dev))372		ret = sirf_runtime_resume(dev);373 374	return ret;375}376 377static const struct dev_pm_ops sirf_pm_ops = {378	SET_SYSTEM_SLEEP_PM_OPS(sirf_suspend, sirf_resume)379	SET_RUNTIME_PM_OPS(sirf_runtime_suspend, sirf_runtime_resume, NULL)380};381 382static int sirf_parse_dt(struct serdev_device *serdev)383{384	struct sirf_data *data = serdev_device_get_drvdata(serdev);385	struct device_node *node = serdev->dev.of_node;386	u32 speed = 9600;387 388	of_property_read_u32(node, "current-speed", &speed);389 390	data->speed = speed;391 392	return 0;393}394 395static int sirf_probe(struct serdev_device *serdev)396{397	struct device *dev = &serdev->dev;398	struct gnss_device *gdev;399	struct sirf_data *data;400	int ret;401 402	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);403	if (!data)404		return -ENOMEM;405 406	gdev = gnss_allocate_device(dev);407	if (!gdev)408		return -ENOMEM;409 410	gdev->type = GNSS_TYPE_SIRF;411	gdev->ops = &sirf_gnss_ops;412	gnss_set_drvdata(gdev, data);413 414	data->serdev = serdev;415	data->gdev = gdev;416 417	mutex_init(&data->gdev_mutex);418	mutex_init(&data->serdev_mutex);419	init_waitqueue_head(&data->power_wait);420 421	serdev_device_set_drvdata(serdev, data);422	serdev_device_set_client_ops(serdev, &sirf_serdev_ops);423 424	ret = sirf_parse_dt(serdev);425	if (ret)426		goto err_put_device;427 428	data->vcc = devm_regulator_get(dev, "vcc");429	if (IS_ERR(data->vcc)) {430		ret = PTR_ERR(data->vcc);431		goto err_put_device;432	}433 434	data->lna = devm_regulator_get(dev, "lna");435	if (IS_ERR(data->lna)) {436		ret = PTR_ERR(data->lna);437		goto err_put_device;438	}439 440	data->on_off = devm_gpiod_get_optional(dev, "sirf,onoff",441			GPIOD_OUT_LOW);442	if (IS_ERR(data->on_off)) {443		ret = PTR_ERR(data->on_off);444		goto err_put_device;445	}446 447	if (data->on_off) {448		data->wakeup = devm_gpiod_get_optional(dev, "sirf,wakeup",449				GPIOD_IN);450		if (IS_ERR(data->wakeup)) {451			ret = PTR_ERR(data->wakeup);452			goto err_put_device;453		}454 455		ret = regulator_enable(data->vcc);456		if (ret)457			goto err_put_device;458 459		/* Wait for chip to boot into hibernate mode. */460		msleep(SIRF_BOOT_DELAY);461	}462 463	if (data->wakeup) {464		ret = gpiod_get_value_cansleep(data->wakeup);465		if (ret < 0)466			goto err_disable_vcc;467		data->active = ret;468 469		ret = gpiod_to_irq(data->wakeup);470		if (ret < 0)471			goto err_disable_vcc;472		data->irq = ret;473 474		ret = request_threaded_irq(data->irq, NULL, sirf_wakeup_handler,475				IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT,476				"wakeup", data);477		if (ret)478			goto err_disable_vcc;479	}480 481	if (data->on_off) {482		if (!data->wakeup) {483			data->active = false;484 485			ret = sirf_serdev_open(data);486			if (ret)487				goto err_disable_vcc;488 489			msleep(SIRF_REPORT_CYCLE);490			sirf_serdev_close(data);491		}492 493		/* Force hibernate mode if already active. */494		if (data->active) {495			ret = sirf_set_active(data, false);496			if (ret) {497				dev_err(dev, "failed to set hibernate mode: %d\n",498						ret);499				goto err_free_irq;500			}501		}502	}503 504	if (IS_ENABLED(CONFIG_PM)) {505		pm_runtime_set_suspended(dev);	/* clear runtime_error flag */506		pm_runtime_enable(dev);507	} else {508		ret = sirf_runtime_resume(dev);509		if (ret < 0)510			goto err_free_irq;511	}512 513	ret = gnss_register_device(gdev);514	if (ret)515		goto err_disable_rpm;516 517	return 0;518 519err_disable_rpm:520	if (IS_ENABLED(CONFIG_PM))521		pm_runtime_disable(dev);522	else523		sirf_runtime_suspend(dev);524err_free_irq:525	if (data->wakeup)526		free_irq(data->irq, data);527err_disable_vcc:528	if (data->on_off)529		regulator_disable(data->vcc);530err_put_device:531	gnss_put_device(data->gdev);532 533	return ret;534}535 536static void sirf_remove(struct serdev_device *serdev)537{538	struct sirf_data *data = serdev_device_get_drvdata(serdev);539 540	gnss_deregister_device(data->gdev);541 542	if (IS_ENABLED(CONFIG_PM))543		pm_runtime_disable(&serdev->dev);544	else545		sirf_runtime_suspend(&serdev->dev);546 547	if (data->wakeup)548		free_irq(data->irq, data);549 550	if (data->on_off)551		regulator_disable(data->vcc);552 553	gnss_put_device(data->gdev);554}555 556#ifdef CONFIG_OF557static const struct of_device_id sirf_of_match[] = {558	{ .compatible = "fastrax,uc430" },559	{ .compatible = "linx,r4" },560	{ .compatible = "wi2wi,w2sg0004" },561	{ .compatible = "wi2wi,w2sg0008i" },562	{ .compatible = "wi2wi,w2sg0084i" },563	{},564};565MODULE_DEVICE_TABLE(of, sirf_of_match);566#endif567 568static struct serdev_device_driver sirf_driver = {569	.driver	= {570		.name		= "gnss-sirf",571		.of_match_table	= of_match_ptr(sirf_of_match),572		.pm		= &sirf_pm_ops,573	},574	.probe	= sirf_probe,575	.remove	= sirf_remove,576};577module_serdev_device_driver(sirf_driver);578 579MODULE_AUTHOR("Johan Hovold <johan@kernel.org>");580MODULE_DESCRIPTION("SiRFstar GNSS receiver driver");581MODULE_LICENSE("GPL v2");582