linux/drivers/gnss/sirf.c
<<
>>
Prefs
   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/sched.h>
  20#include <linux/serdev.h>
  21#include <linux/slab.h>
  22#include <linux/wait.h>
  23
  24#define SIRF_BOOT_DELAY                 500
  25#define SIRF_ON_OFF_PULSE_TIME          100
  26#define SIRF_ACTIVATE_TIMEOUT           200
  27#define SIRF_HIBERNATE_TIMEOUT          200
  28/*
  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 reasonable
  32 * 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       2000
  37
  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 int sirf_receive_buf(struct serdev_device *serdev,
 164                                const unsigned char *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        else
 268                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        else
 299                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        else
 314                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        else
 336                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        else
 523                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        else
 545                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_OF
 557static 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#endif
 567
 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