LKML Archive on lore.kernel.org
help / color / mirror / Atom feed
* [PATCH v7 0/6] gnss: special driver for Wi2Wi w2sg0004 GPS module on GTA04 board
@ 2018-05-03  9:35 H. Nikolaus Schaller
  2018-05-03  9:35 ` [PATCH v7 1/6] dt-bindings: define vendor prefix for Wi2Wi, Inc H. Nikolaus Schaller
                   ` (5 more replies)
  0 siblings, 6 replies; 11+ messages in thread
From: H. Nikolaus Schaller @ 2018-05-03  9:35 UTC (permalink / raw)
  To: Johan Hovold, afd, Rob Herring, Mark Rutland,
	Benoît Cousson, Tony Lindgren, Russell King, Arnd Bergmann,
	Greg Kroah-Hartman, H. Nikolaus Schaller, Kevin Hilman,
	Andreas Färber, Thierry Reding, Jonathan Cameron,
	Noralf Trønnes, David Lechner
  Cc: devicetree, linux-kernel, linux-omap, letux-kernel, kernel,
	linux-arm-kernel

Changes V7:
* propose a separate and dedicated driver because the w2sg0004 is quite special
* moved all code to drivers/gnss
* adapted to make use of the newly proposed gnss framework
* dropped support for w2sg0084(i) with WAKEUP feedback because that
  case is covered by the sirfstar driver
NOTE: must beapplied on top of GNSS framework

Changes V6: -- was not posted --
* worked in some feedbacks by Johan Hovold:
  risk of rfkill race, use gpiod, fix typos
* make consistent use of bool type
* factor out creation of user-space tty interface into a "gps-core"
  to make the chip driver code independent of such core features
  (originally suggested by Andrew F. Davis)

2017-12-01 08:49:41: Changes V5:
* clarified to keep it in drivers/misc and not create a new group drivers/gps
* fix formatting of new entry in omap3-gta04.dtsi (suggested by Tony Lindgren)
* removed MODULE_ALIAS (suggested by Andrew F. Davis)
* some more formatting, code&style fixes (suggested by Andrew F. Davis)
* apply __maybe_unused for PM (suggested by Andrew F. Davis)
* fixed copyright and author records (suggested by Andrew F. Davis)

2017-11-15 22:38:01: Changes V4:
* removed all pdata remains (suggested by Arnd Bergmann and Rob Herring)
* fixed minor issues and subject/commit messages (suggested by Rob Herring)
* added one missing Signed-off-By: (suggested by Andreas Färber)
* added SPDX header (suggested by Rob Herring)

2017-11-15 16:19:17: Changes V3:
* worked in suggestions by kbuild test robot
* added misc+serdev to the subject

2017-11-12 22:00:02: Changes V2:
* reduced to submit only w2sg00x4 GPS driver code
* add DT node for GTA04 device to make use of the driver
* split into base code and a debugging Kconfig option (brings device into false power state after boot)
* worked in comments by kbuild robot and Rob Herring

2017-05-21 12:44:07: RFC V1
* RFC concerning new serdev based drivers for Wi2Wi w2sg00x4 GPS module and w2cbw003 bluetooth

Years long history of getting this devices supported (original work by Neil Brown).

H. Nikolaus Schaller (6):
  dt-bindings: define vendor prefix for Wi2Wi, Inc.
  dt-bindings: gnss: add w2sg0004 bindings documentation
  DTS: gta04: add uart2 child node for w2sg0004 GPS receiver
  misc gnss serdev: Add w2sg0004 power control driver
  gnss: add w2sg0004 to Makefile
  gnss: add w2sg0004 to Kconfig

 .../devicetree/bindings/gnss/wi2wi,w2sg0004.txt    |  23 ++
 .../devicetree/bindings/vendor-prefixes.txt        |   1 +
 arch/arm/boot/dts/omap3-gta04.dtsi                 |   7 +
 drivers/gnss/Kconfig                               |  10 +
 drivers/gnss/Makefile                              |   3 +
 drivers/gnss/w2sg0004.c                            | 435 +++++++++++++++++++++
 6 files changed, 479 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/gnss/wi2wi,w2sg0004.txt
 create mode 100644 drivers/gnss/w2sg0004.c

-- 
2.12.2

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH v7 1/6] dt-bindings: define vendor prefix for Wi2Wi, Inc.
  2018-05-03  9:35 [PATCH v7 0/6] gnss: special driver for Wi2Wi w2sg0004 GPS module on GTA04 board H. Nikolaus Schaller
@ 2018-05-03  9:35 ` H. Nikolaus Schaller
  2018-05-07 20:54   ` Rob Herring
  2018-05-03  9:35 ` [PATCH v7 2/6] dt-bindings: gnss: add w2sg0004 bindings documentation H. Nikolaus Schaller
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 11+ messages in thread
From: H. Nikolaus Schaller @ 2018-05-03  9:35 UTC (permalink / raw)
  To: Johan Hovold, afd, Rob Herring, Mark Rutland,
	Benoît Cousson, Tony Lindgren, Russell King, Arnd Bergmann,
	Greg Kroah-Hartman, H. Nikolaus Schaller, Kevin Hilman,
	Andreas Färber, Thierry Reding, Jonathan Cameron,
	Noralf Trønnes, David Lechner
  Cc: devicetree, linux-kernel, linux-omap, letux-kernel, kernel,
	linux-arm-kernel

Introduce vendor prefix for Wi2Wi, Inc. for W2SG0004 GPS module
and W2CBW003 Bluetooth/WiFi combo (CSR/Marvell).

Signed-off-by: H. Nikolaus Schaller <hns@goldelico.com>
Acked-by: Rob Herring <robh@kernel.org>
---
 Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index ddd81c82082d..9b3af098b99d 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -396,6 +396,7 @@ wi2wi	Wi2Wi
 wd	Western Digital Corp.
 wetek	WeTek Electronics, limited.
 wexler	Wexler
+wi2wi	Wi2Wi, Inc.
 winbond Winbond Electronics corp.
 winstar	Winstar Display Corp.
 wlf	Wolfson Microelectronics
-- 
2.12.2

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH v7 2/6] dt-bindings: gnss: add w2sg0004 bindings documentation
  2018-05-03  9:35 [PATCH v7 0/6] gnss: special driver for Wi2Wi w2sg0004 GPS module on GTA04 board H. Nikolaus Schaller
  2018-05-03  9:35 ` [PATCH v7 1/6] dt-bindings: define vendor prefix for Wi2Wi, Inc H. Nikolaus Schaller
@ 2018-05-03  9:35 ` H. Nikolaus Schaller
  2018-05-03  9:35 ` [PATCH v7 3/6] DTS: gta04: add uart2 child node for w2sg0004 GPS receiver H. Nikolaus Schaller
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 11+ messages in thread
From: H. Nikolaus Schaller @ 2018-05-03  9:35 UTC (permalink / raw)
  To: Johan Hovold, afd, Rob Herring, Mark Rutland,
	Benoît Cousson, Tony Lindgren, Russell King, Arnd Bergmann,
	Greg Kroah-Hartman, H. Nikolaus Schaller, Kevin Hilman,
	Andreas Färber, Thierry Reding, Jonathan Cameron,
	Noralf Trønnes, David Lechner
  Cc: devicetree, linux-kernel, linux-omap, letux-kernel, kernel,
	linux-arm-kernel

Add bindings documentation for Wi2Wi W2SG0004 GPS module.

This is a quite old module which does not support a WAKEUP
line and hence can't use a generic SirfStar driver.

Signed-off-by: H. Nikolaus Schaller <hns@goldelico.com>
Acked-by: Rob Herring <robh@kernel.org>
---
 .../devicetree/bindings/gnss/wi2wi,w2sg0004.txt    | 23 ++++++++++++++++++++++
 1 file changed, 23 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/gnss/wi2wi,w2sg0004.txt

diff --git a/Documentation/devicetree/bindings/gnss/wi2wi,w2sg0004.txt b/Documentation/devicetree/bindings/gnss/wi2wi,w2sg0004.txt
new file mode 100644
index 000000000000..ac4ec479ea98
--- /dev/null
+++ b/Documentation/devicetree/bindings/gnss/wi2wi,w2sg0004.txt
@@ -0,0 +1,23 @@
+Wi2Wi W2SG0004 GPS module connected through UART
+
+Should be a subnode of the SoC UART it is connected to.
+
+Required properties:
+- compatible:	must be
+	"wi2wi,w2sg0004"
+- enable-gpio:	the GPIO that controls the module's power toggle
+	input. A positive impulse of sufficent length toggles the
+	power state.
+
+Optional properties:
+- lna-supply:	an (optional) LNA regulator that is enabled together with the GPS receiver
+
+Example:
+
+&uart2 {
+	w2sg0004: gps {
+		compatible = "wi2wi,w2sg0004";
+		lna-supply = <&vsim>;   /* LNA regulator */
+		enable-gpios = <&gpio5 17 GPIO_ACTIVE_HIGH>;    /* GPIO_145: trigger for turning on/off w2sg0004 */
+        };
+};
-- 
2.12.2

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH v7 3/6] DTS: gta04: add uart2 child node for w2sg0004 GPS receiver
  2018-05-03  9:35 [PATCH v7 0/6] gnss: special driver for Wi2Wi w2sg0004 GPS module on GTA04 board H. Nikolaus Schaller
  2018-05-03  9:35 ` [PATCH v7 1/6] dt-bindings: define vendor prefix for Wi2Wi, Inc H. Nikolaus Schaller
  2018-05-03  9:35 ` [PATCH v7 2/6] dt-bindings: gnss: add w2sg0004 bindings documentation H. Nikolaus Schaller
@ 2018-05-03  9:35 ` H. Nikolaus Schaller
  2018-06-14 19:44   ` Pavel Machek
  2018-05-03  9:35 ` [PATCH v7 4/6] misc gnss serdev: Add w2sg0004 power control driver H. Nikolaus Schaller
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 11+ messages in thread
From: H. Nikolaus Schaller @ 2018-05-03  9:35 UTC (permalink / raw)
  To: Johan Hovold, afd, Rob Herring, Mark Rutland,
	Benoît Cousson, Tony Lindgren, Russell King, Arnd Bergmann,
	Greg Kroah-Hartman, H. Nikolaus Schaller, Kevin Hilman,
	Andreas Färber, Thierry Reding, Jonathan Cameron,
	Noralf Trønnes, David Lechner
  Cc: devicetree, linux-kernel, linux-omap, letux-kernel, kernel,
	linux-arm-kernel

GTA04 has a W2SG0004 module connected to UART2 of the OMAP3
processor. A GPIO can pulse the on/off toggle switch.

Note that there is no WAKEUP output from the W2SG0004,
hence we can't use the generic SirfStar binding.

The VSIM regulator is used to power on/off the LNA of an
external active GPS antenna so that a driver can turn the
LNA off if GPS is not needed to save battery energy.

Signed-off-by: H. Nikolaus Schaller <hns@goldelico.com>
---
 arch/arm/boot/dts/omap3-gta04.dtsi | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/arch/arm/boot/dts/omap3-gta04.dtsi b/arch/arm/boot/dts/omap3-gta04.dtsi
index 4170be70460e..1c9e1ccf2346 100644
--- a/arch/arm/boot/dts/omap3-gta04.dtsi
+++ b/arch/arm/boot/dts/omap3-gta04.dtsi
@@ -478,6 +478,13 @@
 &uart2 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&uart2_pins>;
+
+	gps: gps {
+		compatible = "wi2wi,w2sg0004";
+		lna-supply = <&vsim>;   /* LNA regulator */
+		/* GPIO_145: trigger for on/off-impulse for w2sg0004 */
+		enable-gpios = <&gpio5 17 GPIO_ACTIVE_HIGH>;
+	};
 };
 
 &uart3 {
-- 
2.12.2

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH v7 4/6] misc gnss serdev: Add w2sg0004 power control driver
  2018-05-03  9:35 [PATCH v7 0/6] gnss: special driver for Wi2Wi w2sg0004 GPS module on GTA04 board H. Nikolaus Schaller
                   ` (2 preceding siblings ...)
  2018-05-03  9:35 ` [PATCH v7 3/6] DTS: gta04: add uart2 child node for w2sg0004 GPS receiver H. Nikolaus Schaller
@ 2018-05-03  9:35 ` H. Nikolaus Schaller
  2018-05-03  9:35 ` [PATCH v7 5/6] gnss: add w2sg0004 to Makefile H. Nikolaus Schaller
  2018-05-03  9:35 ` [PATCH v7 6/6] gnss: add w2sg0004 to Kconfig H. Nikolaus Schaller
  5 siblings, 0 replies; 11+ messages in thread
From: H. Nikolaus Schaller @ 2018-05-03  9:35 UTC (permalink / raw)
  To: Johan Hovold, afd, Rob Herring, Mark Rutland,
	Benoît Cousson, Tony Lindgren, Russell King, Arnd Bergmann,
	Greg Kroah-Hartman, H. Nikolaus Schaller, Kevin Hilman,
	Andreas Färber, Thierry Reding, Jonathan Cameron,
	Noralf Trønnes, David Lechner
  Cc: devicetree, linux-kernel, linux-omap, letux-kernel, kernel,
	linux-arm-kernel

Add driver for Wi2Wi W2SG0004 GPS module connected to some SoC UART.

This chip is an older version of modern SirfStar modules and is
lacking a WAKEUP output.

Hence we need a different strategy to determine the real power state.

This driver uses serdev API hooks to monitor the UART traffic before
forwarding to the gnss framework. Especially, it detects the situation
where the module is turned on (sends data) but should be off. This can
happen if it was already turned on during (re)boot or power-on-reset.

Additionally, "rfkill block/unblock gps" is supported to control power
of an external LNA.

The driver concept is based on code developed by Neil Brown <neilb@suse.de>
but strongly simplified and heavily adapted to use the new serdev API
introduced in v4.11 and the upcoming GNSS framework.

Signed-off-by: H. Nikolaus Schaller <hns@goldelico.com>
---
 drivers/gnss/w2sg0004.c | 435 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 435 insertions(+)
 create mode 100644 drivers/gnss/w2sg0004.c

diff --git a/drivers/gnss/w2sg0004.c b/drivers/gnss/w2sg0004.c
new file mode 100644
index 000000000000..7e844ab7b31a
--- /dev/null
+++ b/drivers/gnss/w2sg0004.c
@@ -0,0 +1,435 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Driver for power controlling the w2sg0004 GPS receiver.
+ *
+ * Copyright (C) 2013 Neil Brown <neilb@suse.de>
+ * Copyright (C) 2015-2018 H. Nikolaus Schaller <hns@goldelico.com>,
+ *						Golden Delicious Computers
+ *
+ * This receiver has an ON/OFF pin which must be toggled to
+ * turn the device 'on' or 'off'.  A high->low->high toggle
+ * will switch the device on if it is off, and off if it is on.
+ *
+ * Contrary to newer Sirf based modules is not possible to directly
+ * detect the power state of the w2sg0004.
+ *
+ * However, when it is on it will send characters on a UART line
+ * regularly.
+ *
+ * To detect that the power state is out of sync (e.g. if GPS
+ * was enabled before a reboot), we monitor the serdev data stream
+ * and compare with what the driver thinks about the state.
+ *
+ * In addition we register as a rfkill client so that we can
+ * control the LNA power.
+ *
+ */
+
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/gnss.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_gpio.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/rfkill.h>
+#include <linux/serdev.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/workqueue.h>
+
+/*
+ * There seems to be restrictions on how quickly we can toggle the
+ * on/off line.  data sheets says "two rtc ticks", whatever that means.
+ * If we do it too soon it doesn't work.
+ * So we have a state machine which uses the common work queue to ensure
+ * clean transitions.
+ * When a change is requested we record that request and only act on it
+ * once the previous change has completed.
+ * A change involves a 10ms low pulse, and a 990ms raised level, so only
+ * one change per second.
+ */
+
+enum w2sg_state {
+	W2SG_IDLE,	/* is not changing state */
+	W2SG_PULSE,	/* activate on/off impulse */
+	W2SG_NOPULSE	/* deactivate on/off impulse */
+};
+
+struct w2sg_data {
+	struct		gnss_device *gdev;
+	struct		regulator *lna_regulator;
+	struct		gpio_desc *on_off_gpio;	/* the on-off gpio */
+	struct		rfkill *rf_kill;
+	struct		serdev_device *uart;	/* uart connected to the chip */
+	bool		lna_blocked;	/* rfkill block gps is active */
+	bool		lna_is_off;	/* LNA is currently off */
+	bool		is_on;		/* current power state (0/1) */
+	unsigned long	last_toggle;
+	unsigned long	backoff;	/* time to wait since last_toggle */
+	enum		w2sg_state state;	/* state engine state */
+	bool		requested;	/* requested power state (0/1) */
+	bool		suspended;
+	struct		delayed_work work;
+	int		discard_count;
+};
+
+static int w2sg_set_lna_power(struct w2sg_data *data)
+{
+	int ret = 0;
+	bool off = data->suspended || !data->requested || data->lna_blocked;
+
+	if (off != data->lna_is_off) {
+		data->lna_is_off = off;
+		if (!IS_ERR_OR_NULL(data->lna_regulator)) {
+			if (off)
+				regulator_disable(data->lna_regulator);
+			else
+				ret = regulator_enable(data->lna_regulator);
+		}
+	}
+
+	return ret;
+}
+
+static void w2sg_set_power(struct w2sg_data *data, bool val)
+{
+	if (val && !data->requested) {
+		data->requested = true;
+	} else if (!val && data->requested) {
+		data->backoff = HZ;
+		data->requested = false;
+	} else
+		return;
+
+	if (!data->suspended)
+		schedule_delayed_work(&data->work, 0);
+}
+
+/* called each time data is received by the UART (i.e. sent by the w2sg0004) */
+static int w2sg_uart_receive_buf(struct serdev_device *serdev,
+				const unsigned char *rxdata,
+				size_t count)
+{
+	struct w2sg_data *data =
+		(struct w2sg_data *) serdev_device_get_drvdata(serdev);
+
+	if (!data->requested && !data->is_on) {
+		/*
+		 * we have received characters while the w2sg
+		 * should have been be turned off
+		 */
+		data->discard_count += count;
+		if ((data->state == W2SG_IDLE) &&
+		    time_after(jiffies,
+		    data->last_toggle + data->backoff)) {
+			/* Should be off by now, time to toggle again */
+			dev_dbg(&serdev->dev, "w2sg00x4 has sent %d characters data although it should be off!\n",
+				data->discard_count);
+
+			data->discard_count = 0;
+
+			data->is_on = true;
+			data->backoff *= 2;
+			if (!data->suspended)
+				schedule_delayed_work(&data->work, 0);
+		}
+		return count;
+	}
+
+	/*
+	 * pass to user-space
+	 */
+
+	if (data->requested)
+		return gnss_insert_raw(data->gdev, rxdata, count);
+
+	data->discard_count += count;
+
+	return count;
+}
+
+/* try to toggle the power state by sending a pulse to the on-off GPIO */
+static void toggle_work(struct work_struct *work)
+{
+	struct w2sg_data *data = container_of(work, struct w2sg_data,
+					      work.work);
+
+	w2sg_set_lna_power(data);	/* update LNA power state */
+
+	switch (data->state) {
+	case W2SG_IDLE:
+		if (data->requested == data->is_on)
+			return;
+
+		gpiod_set_value_cansleep(data->on_off_gpio, 1);
+		data->state = W2SG_PULSE;
+
+		schedule_delayed_work(&data->work,
+				      msecs_to_jiffies(10));
+		break;
+
+	case W2SG_PULSE:
+		gpiod_set_value_cansleep(data->on_off_gpio, 0);
+		data->last_toggle = jiffies;
+		data->state = W2SG_NOPULSE;
+		data->is_on = !data->is_on;
+
+		schedule_delayed_work(&data->work,
+				      msecs_to_jiffies(10));
+		break;
+
+	case W2SG_NOPULSE:
+		data->state = W2SG_IDLE;
+
+		break;
+
+	}
+}
+
+static int w2sg_rfkill_set_block(void *pdata, bool blocked)
+{
+	struct w2sg_data *data = pdata;
+
+	data->lna_blocked = blocked;
+
+	if (!data->suspended)
+		schedule_delayed_work(&data->work, 0);
+
+	return 0;
+}
+
+static struct rfkill_ops w2sg0004_rfkill_ops = {
+	.set_block = w2sg_rfkill_set_block,
+};
+
+static struct serdev_device_ops serdev_ops = {
+	.receive_buf = w2sg_uart_receive_buf,
+};
+
+static int w2sg_gps_open(struct gnss_device *gdev)
+{ /* user-space has opened our interface */
+	struct w2sg_data *data = gnss_get_drvdata(gdev);
+
+	w2sg_set_power(data, true);
+
+	return 0;
+}
+
+static void w2sg_gps_close(struct gnss_device *gdev)
+{ /* user-space has finally closed our interface */
+	struct w2sg_data *data = gnss_get_drvdata(gdev);
+
+	w2sg_set_power(data, false);
+}
+
+static int w2sg_gps_send(struct gnss_device *gdev,
+		const unsigned char *buffer, size_t count)
+{ /* raw data coming from user space */
+	struct w2sg_data *data = gnss_get_drvdata(gdev);
+
+	/* simply pass down to UART */
+	return serdev_device_write_buf(data->uart, buffer, count);
+}
+
+static const struct gnss_operations w2sg_gnss_ops = {
+	.open		= w2sg_gps_open,
+	.close		= w2sg_gps_close,
+	.write_raw	= w2sg_gps_send,
+};
+
+static int w2sg_probe(struct serdev_device *serdev)
+{
+	struct w2sg_data *data;
+	struct rfkill *rf_kill;
+	struct gnss_device *gdev;
+	int err;
+
+	data = devm_kzalloc(&serdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->on_off_gpio = devm_gpiod_get_index(&serdev->dev,
+						   "enable", 0,
+						   GPIOD_OUT_LOW);
+	if (IS_ERR(data->on_off_gpio)) {
+		/* defer until we have the gpio */
+		if (PTR_ERR(data->on_off_gpio) == -EPROBE_DEFER)
+			return -EPROBE_DEFER;
+		dev_err(&serdev->dev, "could not get the enable-gpio");
+		return PTR_ERR(data->on_off_gpio);
+	}
+
+	gpiod_direction_output(data->on_off_gpio, false);
+
+	data->lna_regulator = devm_regulator_get_optional(&serdev->dev,
+							"lna");
+	if (IS_ERR(data->lna_regulator)) {
+		/* defer until we can get the regulator */
+		if (PTR_ERR(data->lna_regulator) == -EPROBE_DEFER)
+			return -EPROBE_DEFER;
+
+		data->lna_regulator = NULL;	/* ignore other errors */
+	}
+
+	gdev = gnss_allocate_device(&serdev->dev);
+	if (!gdev)
+		return -ENOMEM;
+
+	gdev->ops = &w2sg_gnss_ops;
+	gnss_set_drvdata(gdev, data);
+
+	data->gdev = gdev;
+	data->uart = serdev;
+
+	data->lna_blocked = true;
+	data->lna_is_off = true;
+
+	data->is_on = false;
+	data->requested = false;
+	data->state = W2SG_IDLE;
+	data->last_toggle = jiffies;
+	data->backoff = HZ;
+
+	INIT_DELAYED_WORK(&data->work, toggle_work);
+
+	serdev_device_set_drvdata(serdev, data);
+	serdev_device_set_client_ops(data->uart, &serdev_ops);
+
+	err = serdev_device_open(data->uart);
+	if (err < 0)
+		goto err_put_gnss;
+
+	err = serdev_device_set_baudrate(data->uart, 9600);
+	if (err < 0)
+		goto err_close_serdev;
+
+	serdev_device_set_flow_control(data->uart, false);
+
+	err = gnss_register_device(gdev);
+	if (err < 0)
+		goto err_close_serdev;
+
+	rf_kill = rfkill_alloc("GPS", &serdev->dev, RFKILL_TYPE_GPS,
+				&w2sg0004_rfkill_ops, data);
+	if (!rf_kill) {
+		err = -ENOMEM;
+		goto err_deregister_gnss;
+	}
+
+	err = rfkill_register(rf_kill);
+	if (err) {
+		dev_err(&serdev->dev, "Cannot register rfkill device\n");
+		goto err_destroy_rfkill;
+	}
+
+	data->rf_kill = rf_kill;
+
+	/* keep off until user space requests the device */
+	w2sg_set_power(data, false);
+
+	return 0;
+
+err_destroy_rfkill:
+	rfkill_destroy(data->rf_kill);
+
+err_deregister_gnss:
+	gnss_deregister_device(data->gdev);
+
+err_close_serdev:
+	serdev_device_close(data->uart);
+
+err_put_gnss:
+	gnss_put_device(data->gdev);
+
+	return err;
+}
+
+static void w2sg_remove(struct serdev_device *serdev)
+{
+	struct w2sg_data *data = serdev_device_get_drvdata(serdev);
+
+	rfkill_destroy(data->rf_kill);
+
+	gnss_deregister_device(data->gdev);
+
+	cancel_delayed_work_sync(&data->work);
+
+	serdev_device_close(data->uart);
+
+	gnss_put_device(data->gdev);
+}
+
+static int __maybe_unused w2sg_suspend(struct device *dev)
+{
+	struct w2sg_data *data = dev_get_drvdata(dev);
+
+	data->suspended = true;
+
+	cancel_delayed_work_sync(&data->work);
+
+	w2sg_set_lna_power(data);	/* shuts down if needed */
+
+	if (data->state == W2SG_PULSE) {
+		msleep(10);
+		gpiod_set_value_cansleep(data->on_off_gpio, 0);
+		data->last_toggle = jiffies;
+		data->is_on = !data->is_on;
+		data->state = W2SG_NOPULSE;
+	}
+
+	if (data->state == W2SG_NOPULSE) {
+		msleep(10);
+		data->state = W2SG_IDLE;
+	}
+
+	if (data->is_on) {
+		gpiod_set_value_cansleep(data->on_off_gpio, 1);
+		msleep(10);
+		gpiod_set_value_cansleep(data->on_off_gpio, 0);
+		data->is_on = false;
+	}
+
+	return 0;
+}
+
+static int __maybe_unused w2sg_resume(struct device *dev)
+{
+	struct w2sg_data *data = dev_get_drvdata(dev);
+
+	data->suspended = false;
+
+	schedule_delayed_work(&data->work, 0);	/* enables LNA if needed */
+
+	return 0;
+}
+
+static const struct of_device_id w2sg0004_of_match[] = {
+	{ .compatible = "wi2wi,w2sg0004" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, w2sg0004_of_match);
+
+SIMPLE_DEV_PM_OPS(w2sg_pm_ops, w2sg_suspend, w2sg_resume);
+
+static struct serdev_device_driver w2sg_driver = {
+	.probe		= w2sg_probe,
+	.remove		= w2sg_remove,
+	.driver = {
+		.name	= "w2sg0004",
+		.owner	= THIS_MODULE,
+		.pm	= &w2sg_pm_ops,
+		.of_match_table = of_match_ptr(w2sg0004_of_match)
+	},
+};
+
+module_serdev_device_driver(w2sg_driver);
+
+MODULE_AUTHOR("NeilBrown <neilb@suse.de>");
+MODULE_AUTHOR("H. Nikolaus Schaller <hns@goldelico.com>");
+MODULE_DESCRIPTION("w2sg0004 GPS power management driver");
+MODULE_LICENSE("GPL v2");
-- 
2.12.2

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH v7 5/6] gnss: add w2sg0004 to Makefile
  2018-05-03  9:35 [PATCH v7 0/6] gnss: special driver for Wi2Wi w2sg0004 GPS module on GTA04 board H. Nikolaus Schaller
                   ` (3 preceding siblings ...)
  2018-05-03  9:35 ` [PATCH v7 4/6] misc gnss serdev: Add w2sg0004 power control driver H. Nikolaus Schaller
@ 2018-05-03  9:35 ` H. Nikolaus Schaller
  2018-05-03  9:35 ` [PATCH v7 6/6] gnss: add w2sg0004 to Kconfig H. Nikolaus Schaller
  5 siblings, 0 replies; 11+ messages in thread
From: H. Nikolaus Schaller @ 2018-05-03  9:35 UTC (permalink / raw)
  To: Johan Hovold, afd, Rob Herring, Mark Rutland,
	Benoît Cousson, Tony Lindgren, Russell King, Arnd Bergmann,
	Greg Kroah-Hartman, H. Nikolaus Schaller, Kevin Hilman,
	Andreas Färber, Thierry Reding, Jonathan Cameron,
	Noralf Trønnes, David Lechner
  Cc: devicetree, linux-kernel, linux-omap, letux-kernel, kernel,
	linux-arm-kernel

Add the w2sg0004 driver to the gnss framework.

Signed-off-by: H. Nikolaus Schaller <hns@goldelico.com>
---
 drivers/gnss/Makefile | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/gnss/Makefile b/drivers/gnss/Makefile
index 5cf0ebe0330a..c3c0b5548c94 100644
--- a/drivers/gnss/Makefile
+++ b/drivers/gnss/Makefile
@@ -14,3 +14,6 @@ gnss-sirf-y := sirf.o
 
 obj-$(CONFIG_GNSS_UBX_SERIAL)		+= gnss-ubx.o
 gnss-ubx-y := ubx.o
+
+obj-$(CONFIG_GNSS_W2SG0004)		+= gnss-w2sg0004.o
+gnss-w2sg0004-y := w2sg0004.o
-- 
2.12.2

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH v7 6/6] gnss: add w2sg0004 to Kconfig
  2018-05-03  9:35 [PATCH v7 0/6] gnss: special driver for Wi2Wi w2sg0004 GPS module on GTA04 board H. Nikolaus Schaller
                   ` (4 preceding siblings ...)
  2018-05-03  9:35 ` [PATCH v7 5/6] gnss: add w2sg0004 to Makefile H. Nikolaus Schaller
@ 2018-05-03  9:35 ` H. Nikolaus Schaller
  5 siblings, 0 replies; 11+ messages in thread
From: H. Nikolaus Schaller @ 2018-05-03  9:35 UTC (permalink / raw)
  To: Johan Hovold, afd, Rob Herring, Mark Rutland,
	Benoît Cousson, Tony Lindgren, Russell King, Arnd Bergmann,
	Greg Kroah-Hartman, H. Nikolaus Schaller, Kevin Hilman,
	Andreas Färber, Thierry Reding, Jonathan Cameron,
	Noralf Trønnes, David Lechner
  Cc: devicetree, linux-kernel, linux-omap, letux-kernel, kernel,
	linux-arm-kernel

Allow to configure for w2sg0004 driver.

Signed-off-by: H. Nikolaus Schaller <hns@goldelico.com>
---
 drivers/gnss/Kconfig | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/drivers/gnss/Kconfig b/drivers/gnss/Kconfig
index 6abc88514512..ccc128bd0a3f 100644
--- a/drivers/gnss/Kconfig
+++ b/drivers/gnss/Kconfig
@@ -40,4 +40,14 @@ config GNSS_UBX_SERIAL
 
 	  If unsure, say N.
 
+config GNSS_W2SG0004
+	tristate "W2SG00x4 power on/off driver"
+	depends on GPIOLIB && SERIAL_DEV_BUS
+	help
+	  Enable on/off control of W2SG00x4 GPS module connected
+	  to some SoC UART to allow powering up/down if the /dev/gnss
+	  is opened/closed.
+
+	  It also provides a "rfkill gps" name to control the LNA power.
+
 endif # GNSS
-- 
2.12.2

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v7 1/6] dt-bindings: define vendor prefix for Wi2Wi, Inc.
  2018-05-03  9:35 ` [PATCH v7 1/6] dt-bindings: define vendor prefix for Wi2Wi, Inc H. Nikolaus Schaller
@ 2018-05-07 20:54   ` Rob Herring
  2018-05-08  6:41     ` H. Nikolaus Schaller
  0 siblings, 1 reply; 11+ messages in thread
From: Rob Herring @ 2018-05-07 20:54 UTC (permalink / raw)
  To: H. Nikolaus Schaller
  Cc: Johan Hovold, afd, Mark Rutland, Benoît Cousson,
	Tony Lindgren, Russell King, Arnd Bergmann, Greg Kroah-Hartman,
	Kevin Hilman, Andreas Färber, Thierry Reding,
	Jonathan Cameron, Noralf Trønnes, David Lechner, devicetree,
	linux-kernel, linux-omap, letux-kernel, kernel, linux-arm-kernel

On Thu, May 03, 2018 at 11:35:46AM +0200, H. Nikolaus Schaller wrote:
> Introduce vendor prefix for Wi2Wi, Inc. for W2SG0004 GPS module
> and W2CBW003 Bluetooth/WiFi combo (CSR/Marvell).
> 
> Signed-off-by: H. Nikolaus Schaller <hns@goldelico.com>
> Acked-by: Rob Herring <robh@kernel.org>
> ---
>  Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +
>  1 file changed, 1 insertion(+)

Applied this one so you don't have to keep sending it.

Rob

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v7 1/6] dt-bindings: define vendor prefix for Wi2Wi, Inc.
  2018-05-07 20:54   ` Rob Herring
@ 2018-05-08  6:41     ` H. Nikolaus Schaller
  0 siblings, 0 replies; 11+ messages in thread
From: H. Nikolaus Schaller @ 2018-05-08  6:41 UTC (permalink / raw)
  To: Rob Herring
  Cc: Johan Hovold, afd, Mark Rutland, Benoît Cousson,
	Tony Lindgren, Russell King, Arnd Bergmann, Greg Kroah-Hartman,
	Kevin Hilman, Andreas Färber, Thierry Reding,
	Jonathan Cameron, Noralf Trønnes, David Lechner, devicetree,
	linux-kernel, linux-omap, letux-kernel, kernel, linux-arm-kernel

HI Rob,

> Am 07.05.2018 um 22:54 schrieb Rob Herring <robh@kernel.org>:
> 
> On Thu, May 03, 2018 at 11:35:46AM +0200, H. Nikolaus Schaller wrote:
>> Introduce vendor prefix for Wi2Wi, Inc. for W2SG0004 GPS module
>> and W2CBW003 Bluetooth/WiFi combo (CSR/Marvell).
>> 
>> Signed-off-by: H. Nikolaus Schaller <hns@goldelico.com>
>> Acked-by: Rob Herring <robh@kernel.org>
>> ---
>> Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +
>> 1 file changed, 1 insertion(+)
> 
> Applied this one so you don't have to keep sending it.

Thanks and BR,
Nikolaus

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v7 3/6] DTS: gta04: add uart2 child node for w2sg0004 GPS receiver
  2018-05-03  9:35 ` [PATCH v7 3/6] DTS: gta04: add uart2 child node for w2sg0004 GPS receiver H. Nikolaus Schaller
@ 2018-06-14 19:44   ` Pavel Machek
  2018-06-16 15:37     ` H. Nikolaus Schaller
  0 siblings, 1 reply; 11+ messages in thread
From: Pavel Machek @ 2018-06-14 19:44 UTC (permalink / raw)
  To: H. Nikolaus Schaller
  Cc: Johan Hovold, afd, Rob Herring, Mark Rutland,
	Benoît Cousson, Tony Lindgren, Russell King, Arnd Bergmann,
	Greg Kroah-Hartman, Kevin Hilman, Andreas Färber,
	Thierry Reding, Jonathan Cameron, Noralf Trønnes,
	David Lechner, devicetree, linux-kernel, linux-omap,
	letux-kernel, kernel, linux-arm-kernel

[-- Attachment #1: Type: text/plain, Size: 733 bytes --]

On Thu 2018-05-03 11:35:48, H. Nikolaus Schaller wrote:
> GTA04 has a W2SG0004 module connected to UART2 of the OMAP3
> processor. A GPIO can pulse the on/off toggle switch.
> 
> Note that there is no WAKEUP output from the W2SG0004,
> hence we can't use the generic SirfStar binding.
> 
> The VSIM regulator is used to power on/off the LNA of an
> external active GPS antenna so that a driver can turn the
> LNA off if GPS is not needed to save battery energy.

This reads as if you did low->high->low to turn GPS on, then
low->high->low to turn GPS off again. Is that correct?

-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 181 bytes --]

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v7 3/6] DTS: gta04: add uart2 child node for w2sg0004 GPS receiver
  2018-06-14 19:44   ` Pavel Machek
@ 2018-06-16 15:37     ` H. Nikolaus Schaller
  0 siblings, 0 replies; 11+ messages in thread
From: H. Nikolaus Schaller @ 2018-06-16 15:37 UTC (permalink / raw)
  To: Pavel Machek
  Cc: Johan Hovold, Andrew F. Davis, Rob Herring, Mark Rutland,
	Benoît Cousson, Tony Lindgren, Russell King, Arnd Bergmann,
	Greg Kroah-Hartman, Kevin Hilman, Andreas Färber,
	Thierry Reding, Jonathan Cameron, Noralf Trønnes,
	David Lechner, devicetree, linux-kernel, linux-omap,
	letux-kernel, kernel, linux-arm-kernel

Hi Pavel,

> Am 14.06.2018 um 21:44 schrieb Pavel Machek <pavel@ucw.cz>:
> 
> On Thu 2018-05-03 11:35:48, H. Nikolaus Schaller wrote:
>> GTA04 has a W2SG0004 module connected to UART2 of the OMAP3
>> processor. A GPIO can pulse the on/off toggle switch.
>> 
>> Note that there is no WAKEUP output from the W2SG0004,
>> hence we can't use the generic SirfStar binding.
>> 
>> The VSIM regulator is used to power on/off the LNA of an
>> external active GPS antenna so that a driver can turn the
>> LNA off if GPS is not needed to save battery energy.
> 
> This reads as if you did low->high->low to turn GPS on, then
> low->high->low to turn GPS off again. Is that correct?

Yes, it controls a toggle switch inside the gps module.

Data sheet (page 5, table 1):

	http://download.goldelico.com/gta04-hardware/Datasheets/W2SG0004_Datasheet_Rev1.81.pdf

Well, it says it wants a "Low going pulse (two RTC ticks), for power save".
So this indicates "high->low->high" and the chip responds on an unspecified edge.

If I speculate about the logic behind this, I think there was the concept of a
push-button at the navigator's console of a vessel (button is connected through
a single long wire and grounded at the console) to turn the receiver on or off.

Now the question is which edge turns it on or of. Pushing or releasing the button?
high->low or low->high? There is no hint in the data sheet.

If we assume it has not been changed in the w2sg0084i, we can look at page 9, figure 3

	https://www.mouser.com/ds/2/437/W2SG0084i_Datasheet_Rev1%2061-1114.pdf

to find that a rising edge changes the power state.

Experiments with manually controlling the w2sg0004 through /sys/class/gpio have
confirmed that that the rising edge is relevant.

Now on power-on there seems to be a special rule. If the on/off line is
permanently grounded (i.e. low), the module will turn on automatically at
power-on. So there is no need for any edge.

But since we don't want the module to be turned on at power-on (while U-Boot
is running) we have code there to initialize the gpio line to high.

Unfortunately you have not cited the code of the patch, so let me add it back:

> +		/* GPIO_145: trigger for on/off-impulse for w2sg0004 */
> +		enable-gpios = <&gpio5 17 GPIO_ACTIVE_HIGH>;

So there it is described as GPIO_ACTIVE_HIGH.

This might seem to contradict the data sheet which talks about a low going pulse,
but better reflects the active low->high edge.

I hope this answers your question completely.

BR and thanks,
Nikolaus



^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2018-06-16 15:38 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-05-03  9:35 [PATCH v7 0/6] gnss: special driver for Wi2Wi w2sg0004 GPS module on GTA04 board H. Nikolaus Schaller
2018-05-03  9:35 ` [PATCH v7 1/6] dt-bindings: define vendor prefix for Wi2Wi, Inc H. Nikolaus Schaller
2018-05-07 20:54   ` Rob Herring
2018-05-08  6:41     ` H. Nikolaus Schaller
2018-05-03  9:35 ` [PATCH v7 2/6] dt-bindings: gnss: add w2sg0004 bindings documentation H. Nikolaus Schaller
2018-05-03  9:35 ` [PATCH v7 3/6] DTS: gta04: add uart2 child node for w2sg0004 GPS receiver H. Nikolaus Schaller
2018-06-14 19:44   ` Pavel Machek
2018-06-16 15:37     ` H. Nikolaus Schaller
2018-05-03  9:35 ` [PATCH v7 4/6] misc gnss serdev: Add w2sg0004 power control driver H. Nikolaus Schaller
2018-05-03  9:35 ` [PATCH v7 5/6] gnss: add w2sg0004 to Makefile H. Nikolaus Schaller
2018-05-03  9:35 ` [PATCH v7 6/6] gnss: add w2sg0004 to Kconfig H. Nikolaus Schaller

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).