Commit 6ade6e90 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge tag 'gnss-5.1-rc1' of...

Merge tag 'gnss-5.1-rc1' of https://git.kernel.org/pub/scm/linux/kernel/git/johan/gnss into char-misc-next

Johan writes:

GNSS updates for 5.1-rc1

Here are the GNSS updates for 5.1-rc1, including:

 - a new driver for Mediatek-based receivers
 - support for SiRF receivers without a wakeup signal
 - support for a separate LNA supply for SiRF receivers

Included are also various clean ups and minor fixes.

All have been in linux-next with no reported issues.
Signed-off-by: default avatarJohan Hovold <johan@kernel.org>

* tag 'gnss-5.1-rc1' of https://git.kernel.org/pub/scm/linux/kernel/git/johan/gnss:
  gnss: add driver for mediatek receivers
  gnss: add mtk receiver type support
  dt-bindings: gnss: add mediatek binding
  dt-bindings: Add vendor prefix for "GlobalTop Technology, Inc."
  dt-bindings: gnss: add lna-supply property
  gnss: sirf: add a separate supply for a lna
  dt-bindings: gnss: add w2sg0004 compatible string
  gnss: sirf: add support for configurations without wakeup signal
  gnss: sirf: write data to gnss only when the gnss device is open
  gnss: sirf: drop redundant double negation
  gnss: sirf: force hibernate mode on probe
  gnss: sirf: fix premature wakeup interrupt enable
parents 7f2b8af2 d4584bbf
...@@ -17,6 +17,7 @@ Required properties: ...@@ -17,6 +17,7 @@ Required properties:
represents represents
Optional properties: Optional properties:
- lna-supply : Separate supply for an LNA
- enable-gpios : GPIO used to enable the device - enable-gpios : GPIO used to enable the device
- timepulse-gpios : Time pulse GPIO - timepulse-gpios : Time pulse GPIO
......
Mediatek-based GNSS Receiver DT binding
Mediatek chipsets are used in GNSS-receiver modules produced by several
vendors and can use a UART interface.
Please see Documentation/devicetree/bindings/gnss/gnss.txt for generic
properties.
Required properties:
- compatible : Must be
"globaltop,pa6h"
- vcc-supply : Main voltage regulator (pin name: VCC)
Optional properties:
- current-speed : Default UART baud rate
- gnss-fix-gpios : GPIO used to determine device position fix state
(pin name: FIX, 3D_FIX)
- reset-gpios : GPIO used to reset the device (pin name: RESET, NRESET)
- timepulse-gpios : Time pulse GPIO (pin name: PPS1, 1PPS)
- vbackup-supply : Backup voltage regulator (pin name: VBAT, VBACKUP)
Example:
serial@1234 {
compatible = "ns16550a";
gnss {
compatible = "globaltop,pa6h";
vcc-supply = <&vcc_3v3>;
};
};
...@@ -12,6 +12,7 @@ Required properties: ...@@ -12,6 +12,7 @@ Required properties:
"fastrax,uc430" "fastrax,uc430"
"linx,r4" "linx,r4"
"wi2wi,w2sg0004"
"wi2wi,w2sg0008i" "wi2wi,w2sg0008i"
"wi2wi,w2sg0084i" "wi2wi,w2sg0084i"
......
...@@ -150,6 +150,7 @@ geniatech Geniatech, Inc. ...@@ -150,6 +150,7 @@ geniatech Geniatech, Inc.
giantec Giantec Semiconductor, Inc. giantec Giantec Semiconductor, Inc.
giantplus Giantplus Technology Co., Ltd. giantplus Giantplus Technology Co., Ltd.
globalscale Globalscale Technologies, Inc. globalscale Globalscale Technologies, Inc.
globaltop GlobalTop Technology, Inc.
gmt Global Mixed-mode Technology, Inc. gmt Global Mixed-mode Technology, Inc.
goodix Shenzhen Huiding Technology Co., Ltd. goodix Shenzhen Huiding Technology Co., Ltd.
google Google, Inc. google Google, Inc.
......
...@@ -15,6 +15,19 @@ if GNSS ...@@ -15,6 +15,19 @@ if GNSS
config GNSS_SERIAL config GNSS_SERIAL
tristate tristate
config GNSS_MTK_SERIAL
tristate "Mediatek GNSS receiver support"
depends on SERIAL_DEV_BUS
select GNSS_SERIAL
help
Say Y here if you have a Mediatek-based GNSS receiver which uses a
serial interface.
To compile this driver as a module, choose M here: the module will
be called gnss-mtk.
If unsure, say N.
config GNSS_SIRF_SERIAL config GNSS_SIRF_SERIAL
tristate "SiRFstar GNSS receiver support" tristate "SiRFstar GNSS receiver support"
depends on SERIAL_DEV_BUS depends on SERIAL_DEV_BUS
......
...@@ -9,6 +9,9 @@ gnss-y := core.o ...@@ -9,6 +9,9 @@ gnss-y := core.o
obj-$(CONFIG_GNSS_SERIAL) += gnss-serial.o obj-$(CONFIG_GNSS_SERIAL) += gnss-serial.o
gnss-serial-y := serial.o gnss-serial-y := serial.o
obj-$(CONFIG_GNSS_MTK_SERIAL) += gnss-mtk.o
gnss-mtk-y := mtk.o
obj-$(CONFIG_GNSS_SIRF_SERIAL) += gnss-sirf.o obj-$(CONFIG_GNSS_SIRF_SERIAL) += gnss-sirf.o
gnss-sirf-y := sirf.o gnss-sirf-y := sirf.o
......
...@@ -334,6 +334,7 @@ static const char * const gnss_type_names[GNSS_TYPE_COUNT] = { ...@@ -334,6 +334,7 @@ static const char * const gnss_type_names[GNSS_TYPE_COUNT] = {
[GNSS_TYPE_NMEA] = "NMEA", [GNSS_TYPE_NMEA] = "NMEA",
[GNSS_TYPE_SIRF] = "SiRF", [GNSS_TYPE_SIRF] = "SiRF",
[GNSS_TYPE_UBX] = "UBX", [GNSS_TYPE_UBX] = "UBX",
[GNSS_TYPE_MTK] = "MTK",
}; };
static const char *gnss_type_name(struct gnss_device *gdev) static const char *gnss_type_name(struct gnss_device *gdev)
......
// SPDX-License-Identifier: GPL-2.0
/*
* Mediatek GNSS receiver driver
*
* Copyright (C) 2018 Johan Hovold <johan@kernel.org>
*/
#include <linux/errno.h>
#include <linux/gnss.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/regulator/consumer.h>
#include <linux/serdev.h>
#include "serial.h"
struct mtk_data {
struct regulator *vbackup;
struct regulator *vcc;
};
static int mtk_set_active(struct gnss_serial *gserial)
{
struct mtk_data *data = gnss_serial_get_drvdata(gserial);
int ret;
ret = regulator_enable(data->vcc);
if (ret)
return ret;
return 0;
}
static int mtk_set_standby(struct gnss_serial *gserial)
{
struct mtk_data *data = gnss_serial_get_drvdata(gserial);
int ret;
ret = regulator_disable(data->vcc);
if (ret)
return ret;
return 0;
}
static int mtk_set_power(struct gnss_serial *gserial,
enum gnss_serial_pm_state state)
{
switch (state) {
case GNSS_SERIAL_ACTIVE:
return mtk_set_active(gserial);
case GNSS_SERIAL_OFF:
case GNSS_SERIAL_STANDBY:
return mtk_set_standby(gserial);
}
return -EINVAL;
}
static const struct gnss_serial_ops mtk_gserial_ops = {
.set_power = mtk_set_power,
};
static int mtk_probe(struct serdev_device *serdev)
{
struct gnss_serial *gserial;
struct mtk_data *data;
int ret;
gserial = gnss_serial_allocate(serdev, sizeof(*data));
if (IS_ERR(gserial)) {
ret = PTR_ERR(gserial);
return ret;
}
gserial->ops = &mtk_gserial_ops;
gserial->gdev->type = GNSS_TYPE_MTK;
data = gnss_serial_get_drvdata(gserial);
data->vcc = devm_regulator_get(&serdev->dev, "vcc");
if (IS_ERR(data->vcc)) {
ret = PTR_ERR(data->vcc);
goto err_free_gserial;
}
data->vbackup = devm_regulator_get_optional(&serdev->dev, "vbackup");
if (IS_ERR(data->vbackup)) {
ret = PTR_ERR(data->vbackup);
if (ret == -ENODEV)
data->vbackup = NULL;
else
goto err_free_gserial;
}
if (data->vbackup) {
ret = regulator_enable(data->vbackup);
if (ret)
goto err_free_gserial;
}
ret = gnss_serial_register(gserial);
if (ret)
goto err_disable_vbackup;
return 0;
err_disable_vbackup:
if (data->vbackup)
regulator_disable(data->vbackup);
err_free_gserial:
gnss_serial_free(gserial);
return ret;
}
static void mtk_remove(struct serdev_device *serdev)
{
struct gnss_serial *gserial = serdev_device_get_drvdata(serdev);
struct mtk_data *data = gnss_serial_get_drvdata(gserial);
gnss_serial_deregister(gserial);
if (data->vbackup)
regulator_disable(data->vbackup);
gnss_serial_free(gserial);
};
#ifdef CONFIG_OF
static const struct of_device_id mtk_of_match[] = {
{ .compatible = "globaltop,pa6h" },
{},
};
MODULE_DEVICE_TABLE(of, mtk_of_match);
#endif
static struct serdev_device_driver mtk_driver = {
.driver = {
.name = "gnss-mtk",
.of_match_table = of_match_ptr(mtk_of_match),
.pm = &gnss_serial_pm_ops,
},
.probe = mtk_probe,
.remove = mtk_remove,
};
module_serdev_device_driver(mtk_driver);
MODULE_AUTHOR("Loys Ollivier <lollivier@baylibre.com>");
MODULE_DESCRIPTION("Mediatek GNSS receiver driver");
MODULE_LICENSE("GPL v2");
...@@ -25,31 +25,83 @@ ...@@ -25,31 +25,83 @@
#define SIRF_ON_OFF_PULSE_TIME 100 #define SIRF_ON_OFF_PULSE_TIME 100
#define SIRF_ACTIVATE_TIMEOUT 200 #define SIRF_ACTIVATE_TIMEOUT 200
#define SIRF_HIBERNATE_TIMEOUT 200 #define SIRF_HIBERNATE_TIMEOUT 200
/*
* If no data arrives for this time, we assume that the chip is off.
* REVISIT: The report cycle is configurable and can be several minutes long,
* so this will only work reliably if the report cycle is set to a reasonable
* low value. Also power saving settings (like send data only on movement)
* might things work even worse.
* Workaround might be to parse shutdown or bootup messages.
*/
#define SIRF_REPORT_CYCLE 2000
struct sirf_data { struct sirf_data {
struct gnss_device *gdev; struct gnss_device *gdev;
struct serdev_device *serdev; struct serdev_device *serdev;
speed_t speed; speed_t speed;
struct regulator *vcc; struct regulator *vcc;
struct regulator *lna;
struct gpio_desc *on_off; struct gpio_desc *on_off;
struct gpio_desc *wakeup; struct gpio_desc *wakeup;
int irq; int irq;
bool active; bool active;
struct mutex gdev_mutex;
bool open;
struct mutex serdev_mutex;
int serdev_count;
wait_queue_head_t power_wait; wait_queue_head_t power_wait;
}; };
static int sirf_serdev_open(struct sirf_data *data)
{
int ret = 0;
mutex_lock(&data->serdev_mutex);
if (++data->serdev_count == 1) {
ret = serdev_device_open(data->serdev);
if (ret) {
data->serdev_count--;
goto out_unlock;
}
serdev_device_set_baudrate(data->serdev, data->speed);
serdev_device_set_flow_control(data->serdev, false);
}
out_unlock:
mutex_unlock(&data->serdev_mutex);
return ret;
}
static void sirf_serdev_close(struct sirf_data *data)
{
mutex_lock(&data->serdev_mutex);
if (--data->serdev_count == 0)
serdev_device_close(data->serdev);
mutex_unlock(&data->serdev_mutex);
}
static int sirf_open(struct gnss_device *gdev) static int sirf_open(struct gnss_device *gdev)
{ {
struct sirf_data *data = gnss_get_drvdata(gdev); struct sirf_data *data = gnss_get_drvdata(gdev);
struct serdev_device *serdev = data->serdev; struct serdev_device *serdev = data->serdev;
int ret; int ret;
ret = serdev_device_open(serdev); mutex_lock(&data->gdev_mutex);
if (ret) data->open = true;
return ret; mutex_unlock(&data->gdev_mutex);
serdev_device_set_baudrate(serdev, data->speed); ret = sirf_serdev_open(data);
serdev_device_set_flow_control(serdev, false); if (ret) {
mutex_lock(&data->gdev_mutex);
data->open = false;
mutex_unlock(&data->gdev_mutex);
return ret;
}
ret = pm_runtime_get_sync(&serdev->dev); ret = pm_runtime_get_sync(&serdev->dev);
if (ret < 0) { if (ret < 0) {
...@@ -61,7 +113,11 @@ static int sirf_open(struct gnss_device *gdev) ...@@ -61,7 +113,11 @@ static int sirf_open(struct gnss_device *gdev)
return 0; return 0;
err_close: err_close:
serdev_device_close(serdev); sirf_serdev_close(data);
mutex_lock(&data->gdev_mutex);
data->open = false;
mutex_unlock(&data->gdev_mutex);
return ret; return ret;
} }
...@@ -71,9 +127,13 @@ static void sirf_close(struct gnss_device *gdev) ...@@ -71,9 +127,13 @@ static void sirf_close(struct gnss_device *gdev)
struct sirf_data *data = gnss_get_drvdata(gdev); struct sirf_data *data = gnss_get_drvdata(gdev);
struct serdev_device *serdev = data->serdev; struct serdev_device *serdev = data->serdev;
serdev_device_close(serdev); sirf_serdev_close(data);
pm_runtime_put(&serdev->dev); pm_runtime_put(&serdev->dev);
mutex_lock(&data->gdev_mutex);
data->open = false;
mutex_unlock(&data->gdev_mutex);
} }
static int sirf_write_raw(struct gnss_device *gdev, const unsigned char *buf, static int sirf_write_raw(struct gnss_device *gdev, const unsigned char *buf,
...@@ -105,8 +165,19 @@ static int sirf_receive_buf(struct serdev_device *serdev, ...@@ -105,8 +165,19 @@ static int sirf_receive_buf(struct serdev_device *serdev,
{ {
struct sirf_data *data = serdev_device_get_drvdata(serdev); struct sirf_data *data = serdev_device_get_drvdata(serdev);
struct gnss_device *gdev = data->gdev; struct gnss_device *gdev = data->gdev;
int ret = 0;
return gnss_insert_raw(gdev, buf, count); if (!data->wakeup && !data->active) {
data->active = true;
wake_up_interruptible(&data->power_wait);
}
mutex_lock(&data->gdev_mutex);
if (data->open)
ret = gnss_insert_raw(gdev, buf, count);
mutex_unlock(&data->gdev_mutex);
return ret;
} }
static const struct serdev_device_ops sirf_serdev_ops = { static const struct serdev_device_ops sirf_serdev_ops = {
...@@ -125,17 +196,45 @@ static irqreturn_t sirf_wakeup_handler(int irq, void *dev_id) ...@@ -125,17 +196,45 @@ static irqreturn_t sirf_wakeup_handler(int irq, void *dev_id)
if (ret < 0) if (ret < 0)
goto out; goto out;
data->active = !!ret; data->active = ret;
wake_up_interruptible(&data->power_wait); wake_up_interruptible(&data->power_wait);
out: out:
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static int sirf_wait_for_power_state_nowakeup(struct sirf_data *data,
bool active,
unsigned long timeout)
{
int ret;
/* Wait for state change (including any shutdown messages). */
msleep(timeout);
/* Wait for data reception or timeout. */
data->active = false;
ret = wait_event_interruptible_timeout(data->power_wait,
data->active, msecs_to_jiffies(SIRF_REPORT_CYCLE));
if (ret < 0)
return ret;
if (ret > 0 && !active)
return -ETIMEDOUT;
if (ret == 0 && active)
return -ETIMEDOUT;
return 0;
}
static int sirf_wait_for_power_state(struct sirf_data *data, bool active, static int sirf_wait_for_power_state(struct sirf_data *data, bool active,
unsigned long timeout) unsigned long timeout)
{ {
int ret; int ret;
if (!data->wakeup)
return sirf_wait_for_power_state_nowakeup(data, active, timeout);
ret = wait_event_interruptible_timeout(data->power_wait, ret = wait_event_interruptible_timeout(data->power_wait,
data->active == active, msecs_to_jiffies(timeout)); data->active == active, msecs_to_jiffies(timeout));
if (ret < 0) if (ret < 0)
...@@ -168,21 +267,22 @@ static int sirf_set_active(struct sirf_data *data, bool active) ...@@ -168,21 +267,22 @@ static int sirf_set_active(struct sirf_data *data, bool active)
else else
timeout = SIRF_HIBERNATE_TIMEOUT; timeout = SIRF_HIBERNATE_TIMEOUT;
if (!data->wakeup) {
ret = sirf_serdev_open(data);
if (ret)
return ret;
}
do { do {
sirf_pulse_on_off(data); sirf_pulse_on_off(data);
ret = sirf_wait_for_power_state(data, active, timeout); ret = sirf_wait_for_power_state(data, active, timeout);
if (ret < 0) { } while (ret == -ETIMEDOUT && retries--);
if (ret == -ETIMEDOUT)
continue;
return ret; if (!data->wakeup)
} sirf_serdev_close(data);
break; if (ret)
} while (retries--); return ret;
if (retries < 0)
return -ETIMEDOUT;
return 0; return 0;
} }
...@@ -190,21 +290,60 @@ static int sirf_set_active(struct sirf_data *data, bool active) ...@@ -190,21 +290,60 @@ static int sirf_set_active(struct sirf_data *data, bool active)
static int sirf_runtime_suspend(struct device *dev) static int sirf_runtime_suspend(struct device *dev)
{ {
struct sirf_data *data = dev_get_drvdata(dev); struct sirf_data *data = dev_get_drvdata(dev);
int ret2;
int ret;
if (!data->on_off) if (data->on_off)
return regulator_disable(data->vcc); ret = sirf_set_active(data, false);
else
ret = regulator_disable(data->vcc);
if (ret)
return ret;
ret = regulator_disable(data->lna);
if (ret)
goto err_reenable;
return sirf_set_active(data, false); return 0;
err_reenable:
if (data->on_off)
ret2 = sirf_set_active(data, true);
else
ret2 = regulator_enable(data->vcc);
if (ret2)
dev_err(dev,
"failed to reenable power on failed suspend: %d\n",
ret2);
return ret;
} }
static int sirf_runtime_resume(struct device *dev) static int sirf_runtime_resume(struct device *dev)
{ {
struct sirf_data *data = dev_get_drvdata(dev); struct sirf_data *data = dev_get_drvdata(dev);
int ret;
if (!data->on_off) ret = regulator_enable(data->lna);
return regulator_enable(data->vcc); if (ret)
return ret;
if (data->on_off)
ret = sirf_set_active(data, true);
else
ret = regulator_enable(data->vcc);
if (ret)
goto err_disable_lna;
return sirf_set_active(data, true); return 0;
err_disable_lna:
regulator_disable(data->lna);
return ret;
} }
static int __maybe_unused sirf_suspend(struct device *dev) static int __maybe_unused sirf_suspend(struct device *dev)
...@@ -275,6 +414,8 @@ static int sirf_probe(struct serdev_device *serdev) ...@@ -275,6 +414,8 @@ static int sirf_probe(struct serdev_device *serdev)
data->serdev = serdev; data->serdev = serdev;
data->gdev = gdev; data->gdev = gdev;
mutex_init(&data->gdev_mutex);
mutex_init(&data->serdev_mutex);
init_waitqueue_head(&data->power_wait); init_waitqueue_head(&data->power_wait);
serdev_device_set_drvdata(serdev, data); serdev_device_set_drvdata(serdev, data);
...@@ -290,6 +431,12 @@ static int sirf_probe(struct serdev_device *serdev) ...@@ -290,6 +431,12 @@ static int sirf_probe(struct serdev_device *serdev)
goto err_put_device; goto err_put_device;
} }
data->lna = devm_regulator_get(dev, "lna");
if (IS_ERR(data->lna)) {
ret = PTR_ERR(data->lna);
goto err_put_device;
}
data->on_off = devm_gpiod_get_optional(dev, "sirf,onoff", data->on_off = devm_gpiod_get_optional(dev, "sirf,onoff",
GPIOD_OUT_LOW); GPIOD_OUT_LOW);
if (IS_ERR(data->on_off)) if (IS_ERR(data->on_off))
...@@ -301,39 +448,53 @@ static int sirf_probe(struct serdev_device *serdev) ...@@ -301,39 +448,53 @@ static int sirf_probe(struct serdev_device *serdev)
if (IS_ERR(data->wakeup)) if (IS_ERR(data->wakeup))
goto err_put_device; goto err_put_device;
/* ret = regulator_enable(data->vcc);
* Configurations where WAKEUP has been left not connected, if (ret)
* are currently not supported.
*/
if (!data->wakeup) {
dev_err(dev, "no wakeup gpio specified\n");
ret = -ENODEV;
goto err_put_device; goto err_put_device;
}
/* Wait for chip to boot into hibernate mode. */
msleep(SIRF_BOOT_DELAY);
} }
if (data->wakeup) { if (data->wakeup) {
ret = gpiod_to_irq(data->wakeup); ret = gpiod_get_value_cansleep(data->wakeup);
if (ret < 0) if (ret < 0)
goto err_put_device; goto err_disable_vcc;
data->active = ret;
ret = gpiod_to_irq(data->wakeup);
if (ret < 0)
goto err_disable_vcc;
data->irq = ret; data->irq = ret;
ret = devm_request_threaded_irq(dev, data->irq, NULL, ret = request_threaded_irq(data->irq, NULL, sirf_wakeup_handler,
sirf_wakeup_handler,
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
"wakeup", data); "wakeup", data);
if (ret) if (ret)
goto err_put_device; goto err_disable_vcc;
} }
if (data->on_off) { if (data->on_off) {
ret = regulator_enable(data->vcc); if (!data->wakeup) {
data->active = false;
ret = sirf_serdev_open(data);
if (ret) if (ret)
goto err_put_device; goto err_disable_vcc;
/* Wait for chip to boot into hibernate mode */ msleep(SIRF_REPORT_CYCLE);
msleep(SIRF_BOOT_DELAY); sirf_serdev_close(data);
}
/* Force hibernate mode if already active. */
if (data->active) {
ret = sirf_set_active(data, false);
if (ret) {
dev_err(dev, "failed to set hibernate mode: %d\n",
ret);
goto err_free_irq;
}
}
} }
if (IS_ENABLED(CONFIG_PM)) { if (IS_ENABLED(CONFIG_PM)) {
...@@ -342,7 +503,7 @@ static int sirf_probe(struct serdev_device *serdev) ...@@ -342,7 +503,7 @@ static int sirf_probe(struct serdev_device *serdev)
} else { } else {
ret = sirf_runtime_resume(dev); ret = sirf_runtime_resume(dev);
if (ret < 0) if (ret < 0)
goto err_disable_vcc; goto err_free_irq;
} }
ret = gnss_register_device(gdev); ret = gnss_register_device(gdev);
...@@ -356,6 +517,9 @@ static int sirf_probe(struct serdev_device *serdev) ...@@ -356,6 +517,9 @@ static int sirf_probe(struct serdev_device *serdev)
pm_runtime_disable(dev); pm_runtime_disable(dev);
else else
sirf_runtime_suspend(dev); sirf_runtime_suspend(dev);
err_free_irq:
if (data->wakeup)
free_irq(data->irq, data);
err_disable_vcc: err_disable_vcc:
if (data->on_off) if (data->on_off)
regulator_disable(data->vcc); regulator_disable(data->vcc);
...@@ -376,6 +540,9 @@ static void sirf_remove(struct serdev_device *serdev) ...@@ -376,6 +540,9 @@ static void sirf_remove(struct serdev_device *serdev)
else else
sirf_runtime_suspend(&serdev->dev); sirf_runtime_suspend(&serdev->dev);
if (data->wakeup)
free_irq(data->irq, data);
if (data->on_off) if (data->on_off)
regulator_disable(data->vcc); regulator_disable(data->vcc);
...@@ -386,6 +553,7 @@ static void sirf_remove(struct serdev_device *serdev) ...@@ -386,6 +553,7 @@ static void sirf_remove(struct serdev_device *serdev)
static const struct of_device_id sirf_of_match[] = { static const struct of_device_id sirf_of_match[] = {
{ .compatible = "fastrax,uc430" }, { .compatible = "fastrax,uc430" },
{ .compatible = "linx,r4" }, { .compatible = "linx,r4" },
{ .compatible = "wi2wi,w2sg0004" },
{ .compatible = "wi2wi,w2sg0008i" }, { .compatible = "wi2wi,w2sg0008i" },
{ .compatible = "wi2wi,w2sg0084i" }, { .compatible = "wi2wi,w2sg0084i" },
{}, {},
......
...@@ -22,6 +22,7 @@ enum gnss_type { ...@@ -22,6 +22,7 @@ enum gnss_type {
GNSS_TYPE_NMEA = 0, GNSS_TYPE_NMEA = 0,
GNSS_TYPE_SIRF, GNSS_TYPE_SIRF,
GNSS_TYPE_UBX, GNSS_TYPE_UBX,
GNSS_TYPE_MTK,
GNSS_TYPE_COUNT GNSS_TYPE_COUNT
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment