* [PATCH v3 4/4] DTS: Pandora: fix panel compatibility string
From: Tomi Valkeinen @ 2017-12-01 8:13 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171130220633.imkfyeiqtftnw4j4@earth>
On 01/12/17 00:06, Sebastian Reichel wrote:
>>>> How about let's call it a "typo fix" then? :)
>>>
>>> Well, it is not really a typo.
>>
>> Well what if the stable people pick it into earlier stable series
>> based on the word fix in the subject? That has happened before.
>>
>> I suggest you update the dts patches to use wording like
>> "update compatible to use new naming" or something similar.
>
> Patch 4/4 is a Fix and should be applied to stable trees. "omapdss,"
> prefix was never supposed to be in the DTS files, is not supposed to
> be in there now and will break some time in the future.
>
> Explanation: The early init of omapdss adds the prefix at runtime,
> so that the binding can use generic properties and the kernel can
> use omapdss specific drivers until the generic ones can be used
This is true, but the extra "omapdss" does not cause any issues at the
moment, and the time when it causes issues is still many kernel versions
in the future.
But, yes, thinking about this, I agree, it's better to pick this one
separately as a fix (after rebasing it on top of current maineline so
that it doesn't depend on the toppoly name change), and leaving the
toppoly->tpo change as a cleanup.
--
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki
^ permalink raw reply
* [PATCH] KVM: arm: Use PTR_ERR_OR_ZERO()
From: Christoffer Dall @ 2017-12-01 8:00 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1511909297-8585-1-git-send-email-gomonovych@gmail.com>
Hi Vasyl,
On Tue, Nov 28, 2017 at 11:48:17PM +0100, Vasyl Gomonovych wrote:
> Fix ptr_ret.cocci warnings:
> virt/kvm/arm/vgic/vgic-its.c:971:1-3: WARNING: PTR_ERR_OR_ZERO can be used
>
> Use PTR_ERR_OR_ZERO rather than if(IS_ERR(...)) + PTR_ERR
>
> Generated by: scripts/coccinelle/api/ptr_ret.cocci
For new code, sure it would make sense to use this.
But why is it worth changing existing code to use PTR_ERR_OR_ZERO?
Thanks,
-Christoffer
>
> Signed-off-by: Vasyl Gomonovych <gomonovych@gmail.com>
> ---
> virt/kvm/arm/vgic/vgic-its.c | 4 +---
> 1 file changed, 1 insertion(+), 3 deletions(-)
>
> diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
> index 1f761a9991e7..28d85754320b 100644
> --- a/virt/kvm/arm/vgic/vgic-its.c
> +++ b/virt/kvm/arm/vgic/vgic-its.c
> @@ -1032,10 +1032,8 @@ static int vgic_its_cmd_handle_mapd(struct kvm *kvm, struct vgic_its *its,
>
> device = vgic_its_alloc_device(its, device_id, itt_addr,
> num_eventid_bits);
> - if (IS_ERR(device))
> - return PTR_ERR(device);
>
> - return 0;
> + return PTR_ERR_OR_ZERO(device);
> }
>
> /*
> --
> 1.9.1
>
^ permalink raw reply
* [PATCH RFC 2/2] arm64: allwinner: a64: Add Brava Keller initial support
From: Maxime Ripard @ 2017-12-01 7:54 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1512067334-12761-2-git-send-email-jagan@amarulasolutions.com>
On Fri, Dec 01, 2017 at 12:12:14AM +0530, Jagan Teki wrote:
> Brava Keller is A64 based IoT device, which support
> - Allwinner A64 Cortex-A53
> - AXP803 PMIC
> - 1GB DDR3 RAM
> - 8GB eMMC
> - Mali-400MP2 GPU
> - AP6330 Wifi/BLE
> - Camera OV5640
> - USB Host and OTG
>
> Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
> ---
> Note: Need to test it on hardware
>
> arch/arm64/boot/dts/allwinner/Makefile | 1 +
> .../boot/dts/allwinner/sun50i-a64-brava-keller.dts | 244 +++++++++++++++++++++
> 2 files changed, 245 insertions(+)
> create mode 100644 arch/arm64/boot/dts/allwinner/sun50i-a64-brava-keller.dts
>
> diff --git a/arch/arm64/boot/dts/allwinner/Makefile b/arch/arm64/boot/dts/allwinner/Makefile
> index f505227..af80ca0 100644
> --- a/arch/arm64/boot/dts/allwinner/Makefile
> +++ b/arch/arm64/boot/dts/allwinner/Makefile
> @@ -1,5 +1,6 @@
> # SPDX-License-Identifier: GPL-2.0
> dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-bananapi-m64.dtb
> +dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-brava-keller.dtb
> dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-nanopi-a64.dtb
> dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-olinuxino.dtb
> dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-orangepi-win.dtb
> diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-brava-keller.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-brava-keller.dts
> new file mode 100644
> index 0000000..f5303a3
> --- /dev/null
> +++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-brava-keller.dts
> @@ -0,0 +1,244 @@
> +/*
> + * Copyright (C) 2017 Jagan Teki <jagan@amarulasolutions.com>
> + *
> + * This file is dual-licensed: you can use it either under the terms
> + * of the GPL or the X11 license, at your option. Note that this dual
> + * licensing only applies to this file, and not this project as a
> + * whole.
> + *
> + * a) This library is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of the
> + * License, or (at your option) any later version.
> + *
> + * This library is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * Or, alternatively,
> + *
> + * b) Permission is hereby granted, free of charge, to any person
> + * obtaining a copy of this software and associated documentation
> + * files (the "Software"), to deal in the Software without
> + * restriction, including without limitation the rights to use,
> + * copy, modify, merge, publish, distribute, sublicense, and/or
> + * sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following
> + * conditions:
> + *
> + * The above copyright notice and this permission notice shall be
> + * included in all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
> + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
> + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
> + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
> + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
> + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
> + * OTHER DEALINGS IN THE SOFTWARE.
> + */
> +
> +/dts-v1/;
> +
> +#include "sun50i-a64.dtsi"
> +
> +#include <dt-bindings/gpio/gpio.h>
> +
> +/ {
> + model = "Brava Keller";
> + compatible = "brava,brava-keller", "allwinner,sun50i-a64";
> +
> + aliases {
> + serial2 = &uart2;
> + };
> +
> + chosen {
> + stdout-path = "serial0:115200n8";
> + };
Same comment than on U-Boot.
> + wifi_pwrseq: wifi_pwrseq {
> + compatible = "mmc-pwrseq-simple";
> + pinctrl-names = "default";
> + reset-gpios = <&pio 0 2 GPIO_ACTIVE_LOW>; /* WL-PMU-EN: PL2 */
> + post-power-on-delay-ms = <200>;
> + };
> +};
> +
> +&ehci0 {
> + status = "okay";
> +};
> +
> +&ehci1 {
> + status = "okay";
> +};
> +
> +&mmc1 {
> + pinctrl-names = "default";
> + pinctrl-0 = <&mmc1_pins>;
> + vmmc-supply = <®_dcdc1>;
> + vqmmc-supply = <®_dldo4>;
> + mmc-pwrseq = <&wifi_pwrseq>;
> + bus-width = <4>;
> + non-removable;
> + status = "okay";
> +
> + brcmf: wifi at 1 {
> + reg = <1>;
> + compatible = "brcm,bcm4329-fmac";
> + interrupt-parent = <&r_pio>;
> + interrupts = <0 7 IRQ_TYPE_LEVEL_LOW>; /* WL-WAKE-AP: PL3 */
> + interrupt-names = "host-wake";
> + };
> +};
> +
> +&mmc2 {
> + pinctrl-names = "default";
> + pinctrl-0 = <&mmc2_pins>;
> + vmmc-supply = <®_dcdc1>;
You probably have a vqmmc tosetup too.
> + bus-width = <8>;
> + non-removable;
> + cap-mmc-hw-reset;
> + status = "okay";
> +};
> +
> +&ohci0 {
> + status = "okay";
> +};
> +
> +&ohci1 {
> + status = "okay";
> +};
> +
> +&r_rsb {
> + status = "okay";
> +
> + axp803: pmic at 3a3 {
> + compatible = "x-powers,axp803";
> + reg = <0x3a3>;
> + interrupt-parent = <&r_intc>;
> + interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
> + };
> +};
> +
> +#include "axp803.dtsi"
> +
> +®_aldo1 {
> + regulator-always-on;
> + regulator-min-microvolt = <1800000>;
> + regulator-max-microvolt = <3300000>;
> + regulator-name = "avdd-csi";
> +};
> +
> +®_aldo2 {
> + regulator-always-on;
> + regulator-min-microvolt = <1800000>;
> + regulator-max-microvolt = <1800000>;
> + regulator-name = "vcc-pl";
> +};
> +
> +®_aldo3 {
> + regulator-always-on;
> + regulator-min-microvolt = <3000000>;
> + regulator-max-microvolt = <3000000>;
> + regulator-name = "vcc-pll-avcc";
> +};
> +
> +®_dcdc1 {
> + regulator-always-on;
> + regulator-min-microvolt = <3300000>;
> + regulator-max-microvolt = <3300000>;
> + regulator-name = "vcc-3v3";
> +};
> +
> +®_dcdc2 {
> + regulator-always-on;
> + regulator-min-microvolt = <1040000>;
> + regulator-max-microvolt = <1300000>;
> + regulator-name = "vdd-cpux";
> +};
> +
> +/* DCDC3 is polyphased with DCDC2 */
> +
> +®_dcdc5 {
> + regulator-always-on;
> + regulator-min-microvolt = <1500000>;
> + regulator-max-microvolt = <1500000>;
> + regulator-name = "vcc-dram";
> +};
> +
> +®_dcdc6 {
> + regulator-always-on;
> + regulator-min-microvolt = <1100000>;
> + regulator-max-microvolt = <1100000>;
> + regulator-name = "vdd-sys";
> +};
> +
> +®_dldo1 {
> + regulator-min-microvolt = <3300000>;
> + regulator-max-microvolt = <3300000>;
> + regulator-name = "vcc-hdmi-dsi-sensor";
> +};
> +
> +®_dldo2 {
> + regulator-min-microvolt = <3300000>;
> + regulator-max-microvolt = <3300000>;
> + regulator-name = "vcc-mipi";
> +};
> +
> +®_dldo3 {
> + regulator-min-microvolt = <2800000>;
> + regulator-max-microvolt = <2800000>;
> + regulator-name = "vcc-gen";
> +};
> +
> +®_dldo4 {
> + regulator-min-microvolt = <3300000>;
> + regulator-max-microvolt = <3300000>;
> + regulator-name = "vcc-wifi-io";
> +};
> +
> +®_eldo1 {
> + regulator-min-microvolt = <1800000>;
> + regulator-max-microvolt = <1800000>;
> + regulator-name = "cpvdd";
> +};
> +
> +®_fldo1 {
> + regulator-min-microvolt = <1200000>;
> + regulator-max-microvolt = <1200000>;
> + regulator-name = "vcc-1v2-hsic";
> +};
> +
> +/*
> + * The A64 chip cannot work without this regulator off, although
> + * it seems to be only driving the AR100 core.
> + * Maybe we don't still know well about CPUs domain.
> + */
> +®_fldo2 {
> + regulator-always-on;
> + regulator-min-microvolt = <1100000>;
> + regulator-max-microvolt = <1100000>;
> + regulator-name = "vdd-cpus";
> +};
> +
> +®_rtc_ldo {
> + regulator-name = "vcc-rtc";
> +};
> +
> +&uart1 {
> + pinctrl-names = "default";
> + pinctrl-0 = <&uart1_pins>, <&uart1_rts_cts_pins>;
> + status = "okay";
> +};
I guess this is a BT device, please use the serdev binding here.
> +&uart2 {
> + pinctrl-names = "default";
> + pinctrl-0 = <&uart2_pins>;
> + status = "okay";
> +};
> +
> +&usbphy {
> + status = "okay";
And please tie in the regulators here.
> +};
> --
> 2.7.4
>
--
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20171201/8a9f7031/attachment-0001.sig>
^ permalink raw reply
* [PATCH v5 5/5] misc serdev: w2sg0004: add debugging code and Kconfig
From: H. Nikolaus Schaller @ 2017-12-01 7:49 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1512114576.git.hns@goldelico.com>
This allows to set CONFIG_W2SG0004_DEBUG which will
make the driver report more activities and it will turn on the
GPS module during boot while the driver assumes that it
is off. This can be used to debug the correct functioning of
the hardware. Therefore we add it as an option to the driver
because we think it is of general use (and a little tricky to
add by system testers).
Normally it should be off.
Signed-off-by: H. Nikolaus Schaller <hns@goldelico.com>
---
drivers/misc/Kconfig | 8 ++++++++
drivers/misc/w2sg0004.c | 37 +++++++++++++++++++++++++++++++++++++
2 files changed, 45 insertions(+)
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index a3b11016ed2b..ad6e60f0cc8c 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -518,4 +518,12 @@ config W2SG0004
is opened/closed.
It also provides a rfkill gps name to control the LNA power.
+config W2SG0004_DEBUG
+ bool "W2SG0004 on/off debugging"
+ depends on W2SG0004
+ help
+ Enable driver debugging mode of W2SG0004 GPS. If you say y here
+ this will turn on the module and you can check if it is turned
+ off by the driver.
+
endmenu
diff --git a/drivers/misc/w2sg0004.c b/drivers/misc/w2sg0004.c
index 6bfd12eb8e02..82c708fce510 100644
--- a/drivers/misc/w2sg0004.c
+++ b/drivers/misc/w2sg0004.c
@@ -26,6 +26,10 @@
*
*/
+#ifdef CONFIG_W2SG0004_DEBUG
+#define DEBUG 1
+#endif
+
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/interrupt.h>
@@ -256,6 +260,7 @@ static int w2sg_tty_install(struct tty_driver *driver, struct tty_struct *tty)
pr_debug("%s() tty = %p\n", __func__, tty);
data = w2sg_get_by_minor(tty->index);
+ pr_debug("%s() data = %p\n", __func__, data);
if (!data)
return -ENODEV;
@@ -342,6 +347,8 @@ static int w2sg_probe(struct serdev_device *serdev)
if (data == NULL)
return -ENOMEM;
+ pr_debug("w2sg serdev_device_set_drvdata\n");
+
serdev_device_set_drvdata(serdev, data);
data->on_off_gpio = of_get_named_gpio_flags(serdev->dev.of_node,
@@ -375,6 +382,8 @@ static int w2sg_probe(struct serdev_device *serdev)
INIT_DELAYED_WORK(&data->work, toggle_work);
+ pr_debug("w2sg devm_gpio_request\n");
+
err = devm_gpio_request(&serdev->dev, data->on_off_gpio,
"w2sg0004-on-off");
if (err < 0)
@@ -388,6 +397,8 @@ static int w2sg_probe(struct serdev_device *serdev)
serdev_device_set_baudrate(data->uart, 9600);
serdev_device_set_flow_control(data->uart, false);
+ pr_debug("w2sg rfkill_alloc\n");
+
rf_kill = rfkill_alloc("GPS", &serdev->dev, RFKILL_TYPE_GPS,
&w2sg0004_rfkill_ops, data);
if (rf_kill == NULL) {
@@ -395,6 +406,8 @@ static int w2sg_probe(struct serdev_device *serdev)
goto err_rfkill;
}
+ pr_debug("w2sg register rfkill\n");
+
err = rfkill_register(rf_kill);
if (err) {
dev_err(&serdev->dev, "Cannot register rfkill device\n");
@@ -403,6 +416,8 @@ static int w2sg_probe(struct serdev_device *serdev)
data->rf_kill = rf_kill;
+ pr_debug("w2sg alloc_tty_driver\n");
+
/* allocate the tty driver */
data->tty_drv = alloc_tty_driver(1);
if (!data->tty_drv)
@@ -428,6 +443,8 @@ static int w2sg_probe(struct serdev_device *serdev)
*/
tty_set_operations(data->tty_drv, &w2sg_serial_ops);
+ pr_debug("w2sg tty_register_driver\n");
+
/* register the tty driver */
err = tty_register_driver(data->tty_drv);
if (err) {
@@ -443,9 +460,27 @@ static int w2sg_probe(struct serdev_device *serdev)
tty_port_init(&data->port);
data->port.ops = &w2sg_port_ops;
+ pr_debug("w2sg call tty_port_register_device\n");
+
data->dev = tty_port_register_device(&data->port,
data->tty_drv, minor, &serdev->dev);
+ pr_debug("w2sg tty_port_register_device -> %p\n", data->dev);
+ pr_debug("w2sg port.tty = %p\n", data->port.tty);
+
+ pr_debug("w2sg probed\n");
+
+#ifdef CONFIG_W2SG0004_DEBUG
+ pr_debug("w2sg DEBUGGING MODE enabled\n");
+ /* turn on for debugging rx notifications */
+ pr_debug("w2sg power gpio ON\n");
+ gpio_set_value_cansleep(data->on_off_gpio, 1);
+ mdelay(100);
+ pr_debug("w2sg power gpio OFF\n");
+ gpio_set_value_cansleep(data->on_off_gpio, 0);
+ mdelay(300);
+#endif
+
/* keep off until user space requests the device */
w2sg_set_power(data, false);
@@ -455,6 +490,8 @@ static int w2sg_probe(struct serdev_device *serdev)
rfkill_destroy(rf_kill);
serdev_device_close(data->uart);
out:
+ pr_debug("w2sg error %d\n", err);
+
return err;
}
--
2.12.2
^ permalink raw reply related
* [PATCH v5 4/5] DTS: gta04: add uart2 child node for w2sg00x4
From: H. Nikolaus Schaller @ 2017-12-01 7:49 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1512114576.git.hns@goldelico.com>
GTA04 has a W2SG0004/84 connected to UART2 of the OMAP3
processor. A GPIO can pulse the on/off toggle switch.
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 4504908c23fe..1ad744a25c36 100644
--- a/arch/arm/boot/dts/omap3-gta04.dtsi
+++ b/arch/arm/boot/dts/omap3-gta04.dtsi
@@ -477,6 +477,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 related
* [PATCH v5 3/5] misc serdev: Add w2sg0004 (gps receiver) power control driver
From: H. Nikolaus Schaller @ 2017-12-01 7:49 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1512114576.git.hns@goldelico.com>
Add driver for Wi2Wi W2SG0004/84 GPS module connected to some SoC UART.
It uses serdev API hooks to monitor and forward the UART traffic to /dev/ttyGPSn
and turn on/off the module. It also detects if the module is turned on (sends data)
but should be off, e.g. if it was already turned on during boot or power-on-reset.
Additionally, rfkill block/unblock can be used to control an external LNA
(and power down the module if not needed).
The driver concept is based on code developed by Neil Brown <neilb@suse.de>
but simplified and adapted to use the new serdev API introduced in v4.11.
Signed-off-by: H. Nikolaus Schaller <hns@goldelico.com>
---
drivers/misc/Kconfig | 10 +
drivers/misc/Makefile | 1 +
drivers/misc/w2sg0004.c | 553 ++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 564 insertions(+)
create mode 100644 drivers/misc/w2sg0004.c
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index f1a5c2357b14..a3b11016ed2b 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -508,4 +508,14 @@ source "drivers/misc/mic/Kconfig"
source "drivers/misc/genwqe/Kconfig"
source "drivers/misc/echo/Kconfig"
source "drivers/misc/cxl/Kconfig"
+
+config W2SG0004
+ tristate "W2SG00x4 on/off control"
+ depends on GPIOLIB && SERIAL_DEV_BUS
+ help
+ Enable on/off control of W2SG00x4 GPS moduled connected
+ to some SoC UART to allow powering up/down if the /dev/ttyGPSn
+ is opened/closed.
+ It also provides a rfkill gps name to control the LNA power.
+
endmenu
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 5ca5f64df478..d9d824b3d20a 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -50,6 +50,7 @@ obj-$(CONFIG_SRAM_EXEC) += sram-exec.o
obj-y += mic/
obj-$(CONFIG_GENWQE) += genwqe/
obj-$(CONFIG_ECHO) += echo/
+obj-$(CONFIG_W2SG0004) += w2sg0004.o
obj-$(CONFIG_VEXPRESS_SYSCFG) += vexpress-syscfg.o
obj-$(CONFIG_CXL_BASE) += cxl/
obj-$(CONFIG_ASPEED_LPC_CTRL) += aspeed-lpc-ctrl.o
diff --git a/drivers/misc/w2sg0004.c b/drivers/misc/w2sg0004.c
new file mode 100644
index 000000000000..6bfd12eb8e02
--- /dev/null
+++ b/drivers/misc/w2sg0004.c
@@ -0,0 +1,553 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Driver for power controlling the w2sg0004/w2sg0084 GPS receiver.
+ *
+ * Copyright (C) 2013 Neil Brown <neilb@suse.de>
+ * Copyright (C) 2015-2017 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' of 'off'. A high->low->high toggle
+ * will switch the device on if it is off, and off if it is on.
+ *
+ * To enable receiving on/off requests we register with the
+ * UART power management notifications.
+ *
+ * It is not possible to directly detect the state of the device.
+ * 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 register for UART data received
+ * notifications.
+ *
+ * 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/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/tty.h>
+#include <linux/tty_flip.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 rfkill *rf_kill;
+ struct regulator *lna_regulator;
+ int lna_blocked; /* rfkill block gps active */
+ int lna_is_off; /* LNA is currently off */
+ int is_on; /* current state (0/1) */
+ unsigned long last_toggle;
+ unsigned long backoff; /* time to wait since last_toggle */
+ int on_off_gpio; /* the on-off gpio number */
+ struct serdev_device *uart; /* uart connected to the chip */
+ struct tty_driver *tty_drv; /* this is the user space tty */
+ struct device *dev; /* from tty_port_register_device() */
+ struct tty_port port;
+ int open_count; /* how often we were opened */
+ enum w2sg_state state;
+ int requested; /* requested state (0/1) */
+ int suspended;
+ struct delayed_work work;
+ int discard_count;
+};
+
+/* should become w2sg_by_minor[n] if we want to support multiple devices */
+static struct w2sg_data *w2sg_by_minor;
+
+static int w2sg_set_lna_power(struct w2sg_data *data)
+{
+ int ret = 0;
+ int off = data->suspended || !data->requested || data->lna_blocked;
+
+ pr_debug("%s: %s\n", __func__, off ? "off" : "on");
+
+ 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(void *pdata, int val)
+{
+ struct w2sg_data *data = (struct w2sg_data *) pdata;
+
+ pr_debug("%s to state=%d (requested=%d)\n", __func__, val,
+ data->requested);
+
+ 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 */
+ pr_debug("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);
+ }
+ } else if (data->open_count > 0) {
+ int n;
+
+ pr_debug("w2sg00x4: push %lu chars to tty port\n",
+ (unsigned long) count);
+
+ /* pass to user-space */
+ n = tty_insert_flip_string(&data->port, rxdata, count);
+ if (n != count)
+ pr_err("w2sg00x4: did loose %lu characters\n",
+ (unsigned long) (count - n));
+ tty_flip_buffer_push(&data->port);
+ return n;
+ }
+
+ /* assume we have processed everything */
+ 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);
+
+ switch (data->state) {
+ case W2SG_IDLE:
+ if (data->requested == data->is_on)
+ return;
+
+ w2sg_set_lna_power(data); /* update LNA power state */
+ gpio_set_value_cansleep(data->on_off_gpio, 0);
+ data->state = W2SG_PULSE;
+
+ pr_debug("w2sg: power gpio ON\n");
+
+ schedule_delayed_work(&data->work,
+ msecs_to_jiffies(10));
+ break;
+
+ case W2SG_PULSE:
+ gpio_set_value_cansleep(data->on_off_gpio, 1);
+ data->last_toggle = jiffies;
+ data->state = W2SG_NOPULSE;
+ data->is_on = !data->is_on;
+
+ pr_debug("w2sg: power gpio OFF\n");
+
+ schedule_delayed_work(&data->work,
+ msecs_to_jiffies(10));
+ break;
+
+ case W2SG_NOPULSE:
+ data->state = W2SG_IDLE;
+
+ pr_debug("w2sg: idle\n");
+
+ break;
+
+ }
+}
+
+static int w2sg_rfkill_set_block(void *pdata, bool blocked)
+{
+ struct w2sg_data *data = pdata;
+
+ pr_debug("%s: blocked: %d\n", __func__, blocked);
+
+ data->lna_blocked = blocked;
+
+ return w2sg_set_lna_power(data);
+}
+
+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,
+};
+
+/*
+ * we are a man-in the middle between the user-space visible tty port
+ * and the serdev tty where the chip is connected.
+ * This allows us to recognise when the device should be powered on
+ * or off and handle the "false" state that data arrives while no
+ * users-space tty client exists.
+ */
+
+static struct w2sg_data *w2sg_get_by_minor(unsigned int minor)
+{
+ BUG_ON(minor >= 1);
+ return w2sg_by_minor;
+}
+
+static int w2sg_tty_install(struct tty_driver *driver, struct tty_struct *tty)
+{
+ struct w2sg_data *data;
+ int retval;
+
+ pr_debug("%s() tty = %p\n", __func__, tty);
+
+ data = w2sg_get_by_minor(tty->index);
+
+ if (!data)
+ return -ENODEV;
+
+ retval = tty_standard_install(driver, tty);
+ if (retval)
+ goto error_init_termios;
+
+ tty->driver_data = data;
+
+ return 0;
+
+error_init_termios:
+ tty_port_put(&data->port);
+ return retval;
+}
+
+static int w2sg_tty_open(struct tty_struct *tty, struct file *file)
+{
+ struct w2sg_data *data = tty->driver_data;
+
+ pr_debug("%s() data = %p open_count = ++%d\n", __func__,
+ data, data->open_count);
+
+ w2sg_set_power(data, ++data->open_count > 0);
+
+ return tty_port_open(&data->port, tty, file);
+}
+
+static void w2sg_tty_close(struct tty_struct *tty, struct file *file)
+{
+ struct w2sg_data *data = tty->driver_data;
+
+ pr_debug("%s()\n", __func__);
+
+ w2sg_set_power(data, --data->open_count > 0);
+
+ tty_port_close(&data->port, tty, file);
+}
+
+static int w2sg_tty_write(struct tty_struct *tty,
+ const unsigned char *buffer, int count)
+{
+ struct w2sg_data *data = tty->driver_data;
+
+ /* simply pass down to UART */
+ return serdev_device_write_buf(data->uart, buffer, count);
+}
+
+static const struct tty_operations w2sg_serial_ops = {
+ .install = w2sg_tty_install,
+ .open = w2sg_tty_open,
+ .close = w2sg_tty_close,
+ .write = w2sg_tty_write,
+};
+
+static const struct tty_port_operations w2sg_port_ops = {
+ /* none defined, but we need the struct */
+};
+
+static int w2sg_probe(struct serdev_device *serdev)
+{
+ struct w2sg_data *data;
+ struct rfkill *rf_kill;
+ int err;
+ int minor;
+ enum of_gpio_flags flags;
+
+ pr_debug("%s()\n", __func__);
+
+ /*
+ * For future consideration:
+ * for multiple such GPS receivers in one system
+ * we need a mechanism to define distinct minor values
+ * and search for an unused one.
+ */
+ minor = 0;
+ if (w2sg_get_by_minor(minor)) {
+ pr_err("w2sg minor is already in use!\n");
+ return -ENODEV;
+ }
+
+ data = devm_kzalloc(&serdev->dev, sizeof(*data), GFP_KERNEL);
+ if (data == NULL)
+ return -ENOMEM;
+
+ serdev_device_set_drvdata(serdev, data);
+
+ data->on_off_gpio = of_get_named_gpio_flags(serdev->dev.of_node,
+ "enable-gpios", 0,
+ &flags);
+ /* defer until we have all gpios */
+ if (data->on_off_gpio == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+
+ 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;
+ }
+ pr_debug("%s() lna_regulator = %p\n", __func__, data->lna_regulator);
+
+ 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;
+
+ data->uart = serdev;
+
+ INIT_DELAYED_WORK(&data->work, toggle_work);
+
+ err = devm_gpio_request(&serdev->dev, data->on_off_gpio,
+ "w2sg0004-on-off");
+ if (err < 0)
+ goto out;
+
+ gpio_direction_output(data->on_off_gpio, false);
+
+ serdev_device_set_client_ops(data->uart, &serdev_ops);
+ serdev_device_open(data->uart);
+
+ serdev_device_set_baudrate(data->uart, 9600);
+ serdev_device_set_flow_control(data->uart, false);
+
+ rf_kill = rfkill_alloc("GPS", &serdev->dev, RFKILL_TYPE_GPS,
+ &w2sg0004_rfkill_ops, data);
+ if (rf_kill == NULL) {
+ err = -ENOMEM;
+ goto err_rfkill;
+ }
+
+ err = rfkill_register(rf_kill);
+ if (err) {
+ dev_err(&serdev->dev, "Cannot register rfkill device\n");
+ goto err_rfkill;
+ }
+
+ data->rf_kill = rf_kill;
+
+ /* allocate the tty driver */
+ data->tty_drv = alloc_tty_driver(1);
+ if (!data->tty_drv)
+ return -ENOMEM;
+
+ /* initialize the tty driver */
+ data->tty_drv->owner = THIS_MODULE;
+ data->tty_drv->driver_name = "w2sg0004";
+ data->tty_drv->name = "ttyGPS";
+ data->tty_drv->major = 0;
+ data->tty_drv->minor_start = 0;
+ data->tty_drv->type = TTY_DRIVER_TYPE_SERIAL;
+ data->tty_drv->subtype = SERIAL_TYPE_NORMAL;
+ data->tty_drv->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
+ data->tty_drv->init_termios = tty_std_termios;
+ data->tty_drv->init_termios.c_cflag = B9600 | CS8 | CREAD |
+ HUPCL | CLOCAL;
+ /*
+ * optional:
+ * tty_termios_encode_baud_rate(&data->tty_drv->init_termios,
+ 115200, 115200);
+ * w2sg_tty_termios(&data->tty_drv->init_termios);
+ */
+ tty_set_operations(data->tty_drv, &w2sg_serial_ops);
+
+ /* register the tty driver */
+ err = tty_register_driver(data->tty_drv);
+ if (err) {
+ pr_err("%s - tty_register_driver failed(%d)\n",
+ __func__, err);
+ put_tty_driver(data->tty_drv);
+ goto err_rfkill;
+ }
+
+ /* minor (0) is now in use */
+ w2sg_by_minor = data;
+
+ tty_port_init(&data->port);
+ data->port.ops = &w2sg_port_ops;
+
+ data->dev = tty_port_register_device(&data->port,
+ data->tty_drv, minor, &serdev->dev);
+
+ /* keep off until user space requests the device */
+ w2sg_set_power(data, false);
+
+ return 0;
+
+err_rfkill:
+ rfkill_destroy(rf_kill);
+ serdev_device_close(data->uart);
+out:
+ return err;
+}
+
+static void w2sg_remove(struct serdev_device *serdev)
+{
+ struct w2sg_data *data = serdev_device_get_drvdata(serdev);
+ int minor;
+
+ cancel_delayed_work_sync(&data->work);
+
+ /* what is the right sequence to avoid problems? */
+ serdev_device_close(data->uart);
+
+ /* we should lookup in w2sg_by_minor */
+ minor = 0;
+ tty_unregister_device(data->tty_drv, minor);
+
+ tty_unregister_driver(data->tty_drv);
+}
+
+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);
+ gpio_set_value_cansleep(data->on_off_gpio, 1);
+ 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) {
+ pr_info("GPS off for suspend %d %d %d\n", data->requested,
+ data->is_on, data->lna_is_off);
+
+ gpio_set_value_cansleep(data->on_off_gpio, 0);
+ msleep(10);
+ gpio_set_value_cansleep(data->on_off_gpio, 1);
+ data->is_on = 0;
+ }
+
+ return 0;
+}
+
+static int __maybe_unused w2sg_resume(struct device *dev)
+{
+ struct w2sg_data *data = dev_get_drvdata(dev);
+
+ data->suspended = false;
+
+ pr_info("GPS resuming %d %d %d\n", data->requested,
+ data->is_on, data->lna_is_off);
+
+ schedule_delayed_work(&data->work, 0); /* enables LNA if needed */
+
+ return 0;
+}
+
+static const struct of_device_id w2sg0004_of_match[] = {
+ { .compatible = "wi2wi,w2sg0004" },
+ { .compatible = "wi2wi,w2sg0084" },
+ {},
+};
+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 related
* [PATCH v5 2/5] dt-bindings: gps: add w2sg00x4 bindings documentation (GPS module with UART))
From: H. Nikolaus Schaller @ 2017-12-01 7:49 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1512114576.git.hns@goldelico.com>
add bindings documentation for Wi2Wi W2SG00x4 GPS module.
Signed-off-by: H. Nikolaus Schaller <hns@goldelico.com>
Acked-by: Rob Herring <robh@kernel.org>
---
.../devicetree/bindings/gps/wi2wi,w2sg0004.txt | 24 ++++++++++++++++++++++
1 file changed, 24 insertions(+)
create mode 100644 Documentation/devicetree/bindings/gps/wi2wi,w2sg0004.txt
diff --git a/Documentation/devicetree/bindings/gps/wi2wi,w2sg0004.txt b/Documentation/devicetree/bindings/gps/wi2wi,w2sg0004.txt
new file mode 100644
index 000000000000..bcf307382afb
--- /dev/null
+++ b/Documentation/devicetree/bindings/gps/wi2wi,w2sg0004.txt
@@ -0,0 +1,24 @@
+Wi2Wi GPS module connected through UART
+
+Should be a subnode of the SoC UART it is connected to.
+
+Required properties:
+- compatible: should be one of (depending on precise model)
+ "wi2wi,w2sg0004"
+ "wi2wi,w2sg0084"
+- 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 related
* [PATCH v5 1/5] dt-bindings: define vendor prefix for Wi2Wi, Inc.
From: H. Nikolaus Schaller @ 2017-12-01 7:49 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1512114576.git.hns@goldelico.com>
Introduce vendor prefix for Wi2Wi, Inc. for W2SG00x4 GPS modules
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 0994bdd82cd3..879f1d9291cd 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -382,6 +382,7 @@ voipac Voipac Technologies s.r.o.
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 related
* [PATCH v5 0/5] misc serdev: new serdev based driver for Wi2Wi w2sg00x4 GPS module
From: H. Nikolaus Schaller @ 2017-12-01 7:49 UTC (permalink / raw)
To: linux-arm-kernel
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 (5):
dt-bindings: define vendor prefix for Wi2Wi, Inc.
dt-bindings: gps: add w2sg00x4 bindings documentation (GPS module with
UART))
misc serdev: Add w2sg0004 (gps receiver) power control driver
DTS: gta04: add uart2 child node for w2sg00x4
misc serdev: w2sg0004: add debugging code and Kconfig
.../devicetree/bindings/gps/wi2wi,w2sg0004.txt | 24 +
.../devicetree/bindings/vendor-prefixes.txt | 1 +
arch/arm/boot/dts/omap3-gta04.dtsi | 7 +
drivers/misc/Kconfig | 18 +
drivers/misc/Makefile | 1 +
drivers/misc/w2sg0004.c | 590 +++++++++++++++++++++
6 files changed, 641 insertions(+)
create mode 100644 Documentation/devicetree/bindings/gps/wi2wi,w2sg0004.txt
create mode 100644 drivers/misc/w2sg0004.c
--
2.12.2
^ permalink raw reply
* [PATCH v4 3/5] misc serdev: Add w2sg0004 (gps receiver) power control driver
From: H. Nikolaus Schaller @ 2017-12-01 7:49 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <7379a64d-f3f8-977a-308e-99f21654ba1d@ti.com>
Hi,
> Am 29.11.2017 um 15:47 schrieb Andrew F. Davis <afd@ti.com>:
>
> On 11/28/2017 03:42 PM, H. Nikolaus Schaller wrote:
>> Hi Andrew,
>> now as 4.15-rc1 is out I find time to continue this work and prepare [PATCH v5].
>>
>>> Am 23.11.2017 um 17:06 schrieb Andrew F. Davis <afd@ti.com>:
>>>
>>> On 11/15/2017 03:37 PM, H. Nikolaus Schaller wrote:
>>>> Add driver for Wi2Wi W2SG0004/84 GPS module connected through uart.
>>>>
>>>> Use serdev API hooks to monitor and forward the UART traffic to /dev/ttyGPSn
>>>> and turn on/off the module. It also detects if the module is turned on (sends data)
>>>> but should be off, e.g. if it was already turned on during boot or power-on-reset.
>>>>
>>>> Additionally, rfkill block/unblock can be used to control an external LNA
>>>> (and power down the module if not needed).
>>>>
>>>> The driver concept is based on code developed by NeilBrown <neilb@suse.de>
>>>> but simplified and adapted to use the new serdev API introduced in 4.11.
>>>>
>>>> Signed-off-by: H. Nikolaus Schaller <hns@goldelico.com>
>>>> ---
>>>> drivers/misc/Kconfig | 10 +
>>>> drivers/misc/Makefile | 1 +
>>>> drivers/misc/w2sg0004.c | 545 ++++++++++++++++++++++++++++++++++++++++++++++++
>>
>> I wonder if this shouldn't better go to
>>
>> drivers/gps
>>
>> But this directory does not yet exist and has no overall maintainer.
>> So it could be left in drivers/misc and moved as soon as drivers/gps
>> is created elsewhere.
>>
>
> Making that directory would imply the existence of a GPS driver
> framework, until one comes about (or if you would like to create one), I
> think misc is the most appropriate spot for now.
Understood and fine with it.
I just wanted to have asked and clarified.
>
>>>> 3 files changed, 556 insertions(+)
>>>> create mode 100644 drivers/misc/w2sg0004.c
>>>>
>>>> diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
>>>> index 8136dc7e863d..09d171d68408 100644
>>>> --- a/drivers/misc/Kconfig
>>>> +++ b/drivers/misc/Kconfig
>>>> @@ -518,4 +518,14 @@ source "drivers/misc/mic/Kconfig"
>>>> source "drivers/misc/genwqe/Kconfig"
>>>> source "drivers/misc/echo/Kconfig"
>>>> source "drivers/misc/cxl/Kconfig"
>>>> +
>>>> +config W2SG0004
>>>> + tristate "W2SG00x4 on/off control"
>>>> + depends on GPIOLIB && SERIAL_DEV_BUS
>>>> + help
>>>> + Enable on/off control of W2SG00x4 GPS moduled connected
>>>> + to some SoC UART to allow powering up/down if the /dev/ttyGPSn
>>>> + is opened/closed.
>>>> + It also provides a rfkill gps name to control the LNA power.
>>>> +
>>>> endmenu
>>>> diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
>>>> index ad0e64fdba34..abcb667e0ff0 100644
>>>> --- a/drivers/misc/Makefile
>>>> +++ b/drivers/misc/Makefile
>>>> @@ -51,6 +51,7 @@ obj-$(CONFIG_SRAM_EXEC) += sram-exec.o
>>>> obj-y += mic/
>>>> obj-$(CONFIG_GENWQE) += genwqe/
>>>> obj-$(CONFIG_ECHO) += echo/
>>>> +obj-$(CONFIG_W2SG0004) += w2sg0004.o
>>>> obj-$(CONFIG_VEXPRESS_SYSCFG) += vexpress-syscfg.o
>>>> obj-$(CONFIG_CXL_BASE) += cxl/
>>>> obj-$(CONFIG_ASPEED_LPC_CTRL) += aspeed-lpc-ctrl.o
>>>> diff --git a/drivers/misc/w2sg0004.c b/drivers/misc/w2sg0004.c
>>>> new file mode 100644
>>>> index 000000000000..12e14b5e0a99
>>>> --- /dev/null
>>>> +++ b/drivers/misc/w2sg0004.c
>>>> @@ -0,0 +1,545 @@
>>>> +// SPDX-License-Identifier: GPL-2.0
>>>
>>> Damn this looks ugly, oh well :/
>>
>> I could remove it for [PATCH v5] ... :\
>>
>
> Nah, you should leave it, this comment was just me venting, Greg KH has
> spoken, so this is the correct way now.
Yes, sigh...
>
>>>
>>>> +/*
>>>> + * Driver for power controlling the w2sg0004/w2sg0084 GPS receiver.
>>>> + *
>>>
>>>
>>> Think you still need copyright tag here somewhere.
>>
>> At the bottom there is:
>>
>>>> +MODULE_AUTHOR("NeilBrown <neilb@suse.de>");
>>>> +MODULE_DESCRIPTION("w2sg0004 GPS power management driver");
>>>> +MODULE_LICENSE("GPL v2");
>>
>> Isn't that enough any more?
>>
>
> Not sure.. someone needs to hold the copyright to this file and it
> really should be close to the top.
Ok, I'll add some (C) line(s) matching the author(s).
>
>>>
>>>> + * This receiver has an ON/OFF pin which must be toggled to
>>>> + * turn the device 'on' of 'off'. A high->low->high toggle
>>>> + * will switch the device on if it is off, and off if it is on.
>>>> + *
>>>> + * To enable receiving on/off requests we register with the
>>>> + * UART power management notifications.
>>>> + *
>>>> + * It is not possible to directly detect the state of the device.
>>>> + * 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 register for UART data received
>>>> + * notifications.
>>>> + *
>>>> + * 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/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/tty.h>
>>>> +#include <linux/tty_flip.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 rfkill *rf_kill;
>>>> + struct regulator *lna_regulator;
>>>> + int lna_blocked; /* rfkill block gps active */
>>>> + int lna_is_off; /* LNA is currently off */
>>>> + int is_on; /* current state (0/1) */
>>>> + unsigned long last_toggle;
>>>> + unsigned long backoff; /* time to wait since last_toggle */
>>>> + int on_off_gpio; /* the on-off gpio number */
>>>> + struct serdev_device *uart; /* uart connected to the chip */
>>>> + struct tty_driver *tty_drv; /* this is the user space tty */
>>>> + struct device *dev; /* from tty_port_register_device() */
>>>> + struct tty_port port;
>>>> + int open_count; /* how often we were opened */
>>>> + enum w2sg_state state;
>>>> + int requested; /* requested state (0/1) */
>>>> + int suspended;
>>>> + struct delayed_work work;
>>>> + int discard_count;
>>>> +};
>>>> +
>>>
>>> Kernel doc style.
>>
>> Is this really needed here?
>>
>> For pure driver internal structs (they are not kernel infrastructure API) I usually
>> consult the source code of a driver and never well formatted kernel doc. Hence I think
>> readability by programmers looking into the source file is more important than serving
>> kernel doc tools.
>>
>> Yes, there are examples like:
>>
>> https://elixir.free-electrons.com/linux/v4.15-rc1/source/drivers/iio/accel/mma8452.c#L113
>>
>> But I find them more confusing than helpful because I have to jump between code lines
>> to match the comment with the data type.
>>
>
> I have no strong preference here as long as you think this is the most
> readable way.
Ok, then let's leave it as it is.
>
>>>
>>>> +static struct w2sg_data *w2sg_by_minor[1];
>>>> +
>>>
>>> If you can only have one right now then just drop the array.
>>
>> w2sg_get_by_minor() is prepared to access more than one record.
>> And there are plans to have more than one (but I don't know exactly
>> how to provide it).
>>
>
> Just add it back when you get that functionality.
I have added a BUG_ON if anyone tries to access an index different from 0.
Why BUG_ON? Because there is no way to cure this situation safely.
>
>> Making it a non-array seems to be an unnecessary hurdle for such
>> improvements. And regarding memory footprint, a single-element
>> array is equivalent to a non-array.
>>
>
> This comment was not about memory footprint, it's about sane code practices.
Well, I would consider using a 1-element array when the plan is to use an n-element
array as more future-proof...
But I have changed it for v5.
>
>>>
>>>> +static int w2sg_set_lna_power(struct w2sg_data *data)
>>>> +{
>>>> + int ret = 0;
>>>> + int off = data->suspended || !data->requested || data->lna_blocked;
>>>> +
>>>> + pr_debug("%s: %s\n", __func__, off ? "off" : "on");
>>>> +
>>>> + 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(void *pdata, int val)
>>>> +{
>>>> + struct w2sg_data *data = (struct w2sg_data *) pdata;
>>>> +
>>>> + pr_debug("%s to state=%d (requested=%d)\n", __func__, val, data->requested);
>>>> +
>>>> + if (val && !data->requested) {
>>>> + data->requested = true;
>>>> + } else if (!val && data->requested) {
>>>> + data->backoff = HZ;
>>>> + data->requested = false;
>>>> + } else
>>>> + return;
>>>> +
>>>> + pr_debug("w2sg00x4 scheduled for %d\n", data->requested);
>>>> +
>>>> + 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 */
>>>> + pr_debug("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);
>>>> + }
>>>> + } else if (data->open_count > 0) {
>>>> + int n;
>>>> +
>>>> + pr_debug("w2sg00x4: push %lu chars to tty port\n",
>>>> + (unsigned long) count);
>>>> +
>>>> + /* pass to user-space */
>>>> + n = tty_insert_flip_string(&data->port, rxdata, count);
>>>> + if (n != count)
>>>> + pr_err("w2sg00x4: did loose %lu characters\n",
>>>> + (unsigned long) (count - n));
>>>> + tty_flip_buffer_push(&data->port);
>>>> + return n;
>>>> + }
>>>> +
>>>> + /* assume we have processed everything */
>>>> + return count;
>>>> +}
>>>> +
>>>> +/* try to toggle the power state by sending a pulse to the on-off GPIO */
>>>> +
>>>
>>> drop extra line, same everywhere
>>
>> Ok! Was just this and one more location.
>>
>>>
>>>> +static void toggle_work(struct work_struct *work)
>>>> +{
>>>> + struct w2sg_data *data = container_of(work, struct w2sg_data,
>>>> + work.work);
>>>> +
>>>> + switch (data->state) {
>>>> + case W2SG_IDLE:
>>>> + if (data->requested == data->is_on)
>>>> + return;
>>>> +
>>>> + w2sg_set_lna_power(data); /* update LNA power state */
>>>> + gpio_set_value_cansleep(data->on_off_gpio, 0);
>>>> + data->state = W2SG_PULSE;
>>>> +
>>>> + pr_debug("w2sg: power gpio ON\n");
>>>> +
>>>> + schedule_delayed_work(&data->work,
>>>> + msecs_to_jiffies(10));
>>>> + break;
>>>> +
>>>> + case W2SG_PULSE:
>>>> + gpio_set_value_cansleep(data->on_off_gpio, 1);
>>>> + data->last_toggle = jiffies;
>>>> + data->state = W2SG_NOPULSE;
>>>> + data->is_on = !data->is_on;
>>>> +
>>>> + pr_debug("w2sg: power gpio OFF\n");
>>>> +
>>>> + schedule_delayed_work(&data->work,
>>>> + msecs_to_jiffies(10));
>>>> + break;
>>>> +
>>>> + case W2SG_NOPULSE:
>>>> + data->state = W2SG_IDLE;
>>>> +
>>>> + pr_debug("w2sg: idle\n");
>>>> +
>>>> + break;
>>>> +
>>>> + }
>>>> +}
>>>> +
>>>> +static int w2sg_rfkill_set_block(void *pdata, bool blocked)
>>>> +{
>>>> + struct w2sg_data *data = pdata;
>>>> +
>>>> + pr_debug("%s: blocked: %d\n", __func__, blocked);
>>>> +
>>>> + data->lna_blocked = blocked;
>>>> +
>>>> + return w2sg_set_lna_power(data);
>>>> +}
>>>> +
>>>> +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,
>>>> +};
>>>> +
>>>> +/*
>>>> + * we are a man-in the middle between the user-space visible tty port
>>>> + * and the serdev tty where the chip is connected.
>>>> + * This allows us to recognise when the device should be powered on
>>>> + * or off and handle the "false" state that data arrives while no
>>>> + * users-space tty client exists.
>>>> + */
>>>> +
>>>> +static struct w2sg_data *w2sg_get_by_minor(unsigned int minor)
>>>> +{
>>>> + return w2sg_by_minor[minor];
>>>> +}
>>>> +
>>>> +static int w2sg_tty_install(struct tty_driver *driver, struct tty_struct *tty)
>>>> +{
>>>> + struct w2sg_data *data;
>>>> + int retval;
>>>> +
>>>> + pr_debug("%s() tty = %p\n", __func__, tty);
>>>> +
>>>> + data = w2sg_get_by_minor(tty->index);
>>>> +
>>>> + if (!data)
>>>> + return -ENODEV;
>>>> +
>>>> + retval = tty_standard_install(driver, tty);
>>>> + if (retval)
>>>> + goto error_init_termios;
>>>> +
>>>> + tty->driver_data = data;
>>>> +
>>>> + return 0;
>>>> +
>>>> +error_init_termios:
>>>> + tty_port_put(&data->port);
>>>> + return retval;
>>>> +}
>>>> +
>>>> +static int w2sg_tty_open(struct tty_struct *tty, struct file *file)
>>>> +{
>>>> + struct w2sg_data *data = tty->driver_data;
>>>> +
>>>> + pr_debug("%s() data = %p open_count = ++%d\n", __func__, data, data->open_count);
>>>> +
>>>> + w2sg_set_power(data, ++data->open_count > 0);
>>>> +
>>>> + return tty_port_open(&data->port, tty, file);
>>>> +}
>>>> +
>>>> +static void w2sg_tty_close(struct tty_struct *tty, struct file *file)
>>>> +{
>>>> + struct w2sg_data *data = tty->driver_data;
>>>> +
>>>> + pr_debug("%s()\n", __func__);
>>>> +
>>>> + w2sg_set_power(data, --data->open_count > 0);
>>>> +
>>>> + tty_port_close(&data->port, tty, file);
>>>> +}
>>>> +
>>>> +static int w2sg_tty_write(struct tty_struct *tty,
>>>> + const unsigned char *buffer, int count)
>>>> +{
>>>> + struct w2sg_data *data = tty->driver_data;
>>>> +
>>>> + /* simply pass down to UART */
>>>> + return serdev_device_write_buf(data->uart, buffer, count);
>>>> +}
>>>> +
>>>> +static const struct tty_operations w2sg_serial_ops = {
>>>> + .install = w2sg_tty_install,
>>>> + .open = w2sg_tty_open,
>>>> + .close = w2sg_tty_close,
>>>> + .write = w2sg_tty_write,
>>>> +};
>>>> +
>>>> +static const struct tty_port_operations w2sg_port_ops = {
>>>> +};
>>>
>>> drop the brackets? or use NULL below, not sure if this needs memory.
>>
>> This allocates a struct tty_port_operations initialized with NULL for
>> all function pointers.
>>
>
> Then just drop the brackets, or allocate it with kzalloc.
>
>> I am not sure if this is the same as providing no w2sg_port_ops at all.
>>
>> Rather I think the serial core is only port == NULL safe but not
>> port->ops == NULL e.g.:
>>
>> http://elixir.free-electrons.com/linux/v4.15-rc1/source/drivers/tty/tty_port.c#L422
>>
>> A test confirms (see comment below):
>>
>>>
>>>> +
>>>> +static int w2sg_probe(struct serdev_device *serdev)
>>>> +{
>>>> + struct w2sg_data *data;
>>>> + struct rfkill *rf_kill;
>>>> + int err;
>>>> + int minor;
>>>> + enum of_gpio_flags flags;
>>>> +
>>>> + pr_debug("%s()\n", __func__);
>>>> +
>>>> + minor = 0;
>>>> + if (w2sg_by_minor[minor]) {
>>>> + pr_err("w2sg minor is already in use!\n");
>>>> + return -ENODEV;
>>>> + }
>>>> +
>>>> + data = devm_kzalloc(&serdev->dev, sizeof(*data), GFP_KERNEL);
>>>> + if (data == NULL)
>>>> + return -ENOMEM;
>>>> +
>>>> + w2sg_by_minor[minor] = data;
>>
>> While looking through this, I found a potential issue if allocating the
>> gpio fails with -EPROBE_DEFER.
>>
>> Then, we have set w2sg_by_minor[minor] != NULL and the above test will already
>> find it allocated on next deferred probe attempt.
>>
>> So I'll move that to a position further down.
>>
>>>> +
>>>> + serdev_device_set_drvdata(serdev, data);
>>>> +
>>>> + data->on_off_gpio = of_get_named_gpio_flags(serdev->dev.of_node,
>>>> + "enable-gpios", 0,
>>>> + &flags);
>>>> + /* defer until we have all gpios */
>>>> + if (data->on_off_gpio == -EPROBE_DEFER)
>>>> + return -EPROBE_DEFER;
>>>> +
>>>> + 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;
>>>> + }
>>>> + pr_debug("%s() lna_regulator = %p\n", __func__, data->lna_regulator);
>>>> +
>>>> + 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;
>>>> +
>>>> + data->uart = serdev;
>>>> +
>>>> + INIT_DELAYED_WORK(&data->work, toggle_work);
>>>> +
>>>> + err = devm_gpio_request(&serdev->dev, data->on_off_gpio,
>>>> + "w2sg0004-on-off");
>>>> + if (err < 0)
>>>> + goto out;
>>>> +
>>>> + gpio_direction_output(data->on_off_gpio, false);
>>>> +
>>>> + serdev_device_set_client_ops(data->uart, &serdev_ops);
>>>> + serdev_device_open(data->uart);
>>>> +
>>>> + serdev_device_set_baudrate(data->uart, 9600);
>>>> + serdev_device_set_flow_control(data->uart, false);
>>>> +
>>>> + rf_kill = rfkill_alloc("GPS", &serdev->dev, RFKILL_TYPE_GPS,
>>>> + &w2sg0004_rfkill_ops, data);
>>>> + if (rf_kill == NULL) {
>>>> + err = -ENOMEM;
>>>> + goto err_rfkill;
>>>> + }
>>>> +
>>>> + err = rfkill_register(rf_kill);
>>>> + if (err) {
>>>> + dev_err(&serdev->dev, "Cannot register rfkill device\n");
>>>> + goto err_rfkill;
>>>> + }
>>>> +
>>>> + data->rf_kill = rf_kill;
>>>> +
>>>> + /* allocate the tty driver */
>>>> + data->tty_drv = alloc_tty_driver(1);
>>>> + if (!data->tty_drv)
>>>> + return -ENOMEM;
>>>> +
>>>> + /* initialize the tty driver */
>>>> + data->tty_drv->owner = THIS_MODULE;
>>>> + data->tty_drv->driver_name = "w2sg0004";
>>>> + data->tty_drv->name = "ttyGPS";
>>>> + data->tty_drv->major = 0;
>>>> + data->tty_drv->minor_start = 0;
>>>> + data->tty_drv->type = TTY_DRIVER_TYPE_SERIAL;
>>>> + data->tty_drv->subtype = SERIAL_TYPE_NORMAL;
>>>> + data->tty_drv->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
>>>> + data->tty_drv->init_termios = tty_std_termios;
>>>> + data->tty_drv->init_termios.c_cflag = B9600 | CS8 | CREAD |
>>>> + HUPCL | CLOCAL;
>>>> + /*
>>>> + * optional:
>>>> + * tty_termios_encode_baud_rate(&data->tty_drv->init_termios,
>>>> + 115200, 115200);
>>>> + * w2sg_tty_termios(&data->tty_drv->init_termios);
>>>> + */
>>>> + tty_set_operations(data->tty_drv, &w2sg_serial_ops);
>>>> +
>>>> + /* register the tty driver */
>>>> + err = tty_register_driver(data->tty_drv);
>>>> + if (err) {
>>>> + pr_err("%s - tty_register_driver failed(%d)\n",
>>>> + __func__, err);
>>>> + put_tty_driver(data->tty_drv);
>>>> + goto err_rfkill;
>>>> + }
>>>> +
>>>> + tty_port_init(&data->port);
>>>> + data->port.ops = &w2sg_port_ops;
>>
>> A test setting this to NULL leads to a kernel oops in:
>>
>> [ 3048.821258] [<c046c598>] (tty_port_open) from [<c0466328>] (tty_open+0x1e8/0x2d8)
>>
>> So we must define this completely empty struct w2sg_port_ops
>> and pass a reference.
>>
>>>> +
>>>> + pr_debug("w2sg call tty_port_register_device\n");
>>>> +
>>>> + data->dev = tty_port_register_device(&data->port,
>>>> + data->tty_drv, minor, &serdev->dev);
>>>> +
>>>> + pr_debug("w2sg probed\n");
>>>> +
>>>> + /* keep off until user space requests the device */
>>>> + w2sg_set_power(data, false);
>>>> +
>>>> + return 0;
>>>> +
>>>> +err_rfkill:
>>>> + rfkill_destroy(rf_kill);
>>>> + serdev_device_close(data->uart);
>>>> +out:
>>>> + return err;
>>>> +}
>>>> +
>>>> +static void w2sg_remove(struct serdev_device *serdev)
>>>> +{
>>>> + struct w2sg_data *data = serdev_device_get_drvdata(serdev);
>>>> + int minor;
>>>> +
>>>> + cancel_delayed_work_sync(&data->work);
>>>> +
>>>> + /* what is the right sequence to avoid problems? */
>>>> + serdev_device_close(data->uart);
>>>> +
>>>> + minor = 0;
>>>> + tty_unregister_device(data->tty_drv, minor);
>>>> +
>>>> + tty_unregister_driver(data->tty_drv);
>>>> +}
>>>> +
>>>> +static int w2sg_suspend(struct device *dev)
>>>
>>> __maybe_unused, or if PM is disabled you will get a warning.
>>
>> Ok.
>>
>>>
>>>> +{
>>>> + 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);
>>>> + gpio_set_value_cansleep(data->on_off_gpio, 1);
>>>> + 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) {
>>>> + pr_info("GPS off for suspend %d %d %d\n", data->requested,
>>>> + data->is_on, data->lna_is_off);
>>>> +
>>>> + gpio_set_value_cansleep(data->on_off_gpio, 0);
>>>> + msleep(10);
>>>> + gpio_set_value_cansleep(data->on_off_gpio, 1);
>>>> + data->is_on = 0;
>>>> + }
>>>> +
>>>> + return 0;
>>>> +}
>>>> +
>>>> +static int w2sg_resume(struct device *dev)
>>>> +{
>>>> + struct w2sg_data *data = dev_get_drvdata(dev);
>>>> +
>>>> + data->suspended = false;
>>>> +
>>>> + pr_info("GPS resuming %d %d %d\n", data->requested,
>>>> + data->is_on, data->lna_is_off);
>>>> +
>>>> + schedule_delayed_work(&data->work, 0); /* enables LNA if needed */
>>>> +
>>>> + return 0;
>>>> +}
>>>> +
>>>> +static const struct of_device_id w2sg0004_of_match[] = {
>>>> + { .compatible = "wi2wi,w2sg0004" },
>>>> + { .compatible = "wi2wi,w2sg0084" },
>>>> + {},
>>>> +};
>>>> +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_ALIAS("w2sg0004");
>>>
>>> Is this needed?
>>
>> Seems to be redundant.
>> After removal the driver is still loaded automatically after boot:
>>
>> root at letux:~# modprobe -c | fgrep w2sg
>> alias of:N*T*Cwi2wi,w2sg0004 w2sg0004
>> alias of:N*T*Cwi2wi,w2sg0004C* w2sg0004
>> alias of:N*T*Cwi2wi,w2sg0084 w2sg0004
>> alias of:N*T*Cwi2wi,w2sg0084C* w2sg0004
>> root at letux:~# lsmod | fgrep w2sg
>> w2sg0004 16384 2
>> root at letux:~#
>>
>>>
>>>> +
>>>> +MODULE_AUTHOR("NeilBrown <neilb@suse.de>");
>>>
>>> Who really wrote this?
>>
>> Good question.
>>
>> The problem is that with cleaning up the code and rewriting history over such
>> a long time, it is no more visible.
>>
>> But I have searched through our older branches:
>>
>> Neil Brown had developed the first version for v3.7 in 2013:
>> http://git.goldelico.com/?p=gta04-kernel.git;a=commit;h=5b6fad7c7f15db8bb8e2c98ae9a50da52bda8b69
>>
>> This is where the MODULE_AUTHOR line comes from.
>>
>> Later, Marek Belisko worked on the UART driver, pinmux and interrupts.
>>
>> And I have
>> * added lna-regulator and rfkill ca. v3.12
>> * added device tree support ca. v3.15
>> * moved to drivers/misc
>> * ported the code to serdev API ca. v4.11
>> * submitted to LKML and worked in comments by reviewers ca. 4.15
>>
>> So this is the first version that is close to be acceptable.
>>
>> Neil had also submitted different versions to LKML but I am not
>> sure if he still is active anywhere.
>>
>> I have also checked a diff between the v3.7 version and the
>> current one and there are ca. 30-40% of lines original code by
>> Neil.
>>
>> So I'd say:
>>
>> * Neil is the original author and a significant amount of untouched code lines and comments are still there
>> * he designed the overall driver architecture
>> * Hence he is the copyright holder, did license under GPL v2 and we have just made a derivative work out of it
>> * Neil did submit his version of serdev ca. 2015 (quite different from this) but resigned after review feedback
>> * I did add some important features but not the core code and driver architecture
>> * I feel my role as maintainer and massaging everything for DT, serdev and get it upstream, but not "the author"
>>
>> How should we best reflect this in the AUTHOR macro?
>>
>
> Easy:
>
> MODULE_AUTHOR("NeilBrown <neilb@suse.de>");
> MODULE_AUTHOR("H. Nikolaus Schaller <hns@goldelico.com>");
>
> you can have more than one :)
Ah, that is much easier to solve than I had thought...
>
>>>
>>>> +MODULE_DESCRIPTION("w2sg0004 GPS power management driver");
>>>> +MODULE_LICENSE("GPL v2");
>>>>
[PATCH v5] now coming.
BR and thanks,
Nikolaus
^ permalink raw reply
* [PATCH 1/1] timecounter: Make cyclecounter struct part of timecounter struct
From: Sagar Arun Kamble @ 2017-12-01 7:47 UTC (permalink / raw)
To: linux-arm-kernel
There is no real need for the users of timecounters to define cyclecounter
and timecounter variables separately. Since timecounter will always be
based on cyclecounter, have cyclecounter struct as member of timecounter
struct.
Suggested-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Sagar Arun Kamble <sagar.a.kamble@intel.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Cc: John Stultz <john.stultz@linaro.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Stephen Boyd <sboyd@codeaurora.org>
Cc: linux-kernel at vger.kernel.org
Cc: linux-arm-kernel at lists.infradead.org
Cc: netdev at vger.kernel.org
Cc: intel-wired-lan at lists.osuosl.org
Cc: linux-rdma at vger.kernel.org
Cc: alsa-devel at alsa-project.org
Cc: kvmarm at lists.cs.columbia.edu
---
arch/microblaze/kernel/timer.c | 20 ++++++------
drivers/clocksource/arm_arch_timer.c | 19 ++++++------
drivers/net/ethernet/amd/xgbe/xgbe-dev.c | 3 +-
drivers/net/ethernet/amd/xgbe/xgbe-ptp.c | 9 +++---
drivers/net/ethernet/amd/xgbe/xgbe.h | 1 -
drivers/net/ethernet/broadcom/bnx2x/bnx2x.h | 1 -
drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | 20 ++++++------
drivers/net/ethernet/freescale/fec.h | 1 -
drivers/net/ethernet/freescale/fec_ptp.c | 30 +++++++++---------
drivers/net/ethernet/intel/e1000e/e1000.h | 1 -
drivers/net/ethernet/intel/e1000e/netdev.c | 27 ++++++++--------
drivers/net/ethernet/intel/e1000e/ptp.c | 2 +-
drivers/net/ethernet/intel/igb/igb.h | 1 -
drivers/net/ethernet/intel/igb/igb_ptp.c | 25 ++++++++-------
drivers/net/ethernet/intel/ixgbe/ixgbe.h | 1 -
drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c | 17 +++++-----
drivers/net/ethernet/mellanox/mlx4/en_clock.c | 28 ++++++++---------
drivers/net/ethernet/mellanox/mlx4/mlx4_en.h | 1 -
.../net/ethernet/mellanox/mlx5/core/lib/clock.c | 34 ++++++++++----------
drivers/net/ethernet/qlogic/qede/qede_ptp.c | 20 ++++++------
drivers/net/ethernet/ti/cpts.c | 36 ++++++++++++----------
drivers/net/ethernet/ti/cpts.h | 1 -
include/linux/mlx5/driver.h | 1 -
include/linux/timecounter.h | 4 +--
include/sound/hdaudio.h | 1 -
kernel/time/timecounter.c | 28 ++++++++---------
sound/hda/hdac_stream.c | 7 +++--
virt/kvm/arm/arch_timer.c | 6 ++--
28 files changed, 163 insertions(+), 182 deletions(-)
diff --git a/arch/microblaze/kernel/timer.c b/arch/microblaze/kernel/timer.c
index 7de941c..b7f89e9 100644
--- a/arch/microblaze/kernel/timer.c
+++ b/arch/microblaze/kernel/timer.c
@@ -199,27 +199,25 @@ static u64 xilinx_read(struct clocksource *cs)
return (u64)xilinx_clock_read();
}
-static struct timecounter xilinx_tc = {
- .cc = NULL,
-};
-
static u64 xilinx_cc_read(const struct cyclecounter *cc)
{
return xilinx_read(NULL);
}
-static struct cyclecounter xilinx_cc = {
- .read = xilinx_cc_read,
- .mask = CLOCKSOURCE_MASK(32),
- .shift = 8,
+static struct timecounter xilinx_tc = {
+ .cc.read = xilinx_cc_read,
+ .cc.mask = CLOCKSOURCE_MASK(32),
+ .cc.mult = 0,
+ .cc.shift = 8,
};
static int __init init_xilinx_timecounter(void)
{
- xilinx_cc.mult = div_sc(timer_clock_freq, NSEC_PER_SEC,
- xilinx_cc.shift);
+ struct cyclecounter *cc = &xilinx_tc.cc;
+
+ cc->mult = div_sc(timer_clock_freq, NSEC_PER_SEC, cc->shift);
- timecounter_init(&xilinx_tc, &xilinx_cc, sched_clock());
+ timecounter_init(&xilinx_tc, sched_clock());
return 0;
}
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index 57cb2f0..31543e5 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -179,11 +179,6 @@ static u64 arch_counter_read_cc(const struct cyclecounter *cc)
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
};
-static struct cyclecounter cyclecounter __ro_after_init = {
- .read = arch_counter_read_cc,
- .mask = CLOCKSOURCE_MASK(56),
-};
-
struct ate_acpi_oem_info {
char oem_id[ACPI_OEM_ID_SIZE + 1];
char oem_table_id[ACPI_OEM_TABLE_ID_SIZE + 1];
@@ -915,7 +910,10 @@ static u64 arch_counter_get_cntvct_mem(void)
return ((u64) vct_hi << 32) | vct_lo;
}
-static struct arch_timer_kvm_info arch_timer_kvm_info;
+static struct arch_timer_kvm_info arch_timer_kvm_info = {
+ .timecounter.cc.read = arch_counter_read_cc,
+ .timecounter.cc.mask = CLOCKSOURCE_MASK(56),
+};
struct arch_timer_kvm_info *arch_timer_get_kvm_info(void)
{
@@ -925,6 +923,7 @@ struct arch_timer_kvm_info *arch_timer_get_kvm_info(void)
static void __init arch_counter_register(unsigned type)
{
u64 start_count;
+ struct cyclecounter *cc = &arch_timer_kvm_info.timecounter.cc;
/* Register the CP15 based counter if we have one */
if (type & ARCH_TIMER_TYPE_CP15) {
@@ -943,10 +942,10 @@ static void __init arch_counter_register(unsigned type)
clocksource_counter.flags |= CLOCK_SOURCE_SUSPEND_NONSTOP;
start_count = arch_timer_read_counter();
clocksource_register_hz(&clocksource_counter, arch_timer_rate);
- cyclecounter.mult = clocksource_counter.mult;
- cyclecounter.shift = clocksource_counter.shift;
- timecounter_init(&arch_timer_kvm_info.timecounter,
- &cyclecounter, start_count);
+
+ cc->mult = clocksource_counter.mult;
+ cc->shift = clocksource_counter.shift;
+ timecounter_init(&arch_timer_kvm_info.timecounter, start_count);
/* 56 bits minimum, so we assume worst case rollover */
sched_clock_register(arch_timer_read_counter, 56, arch_timer_rate);
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
index e107e18..5005c87 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
@@ -1622,8 +1622,7 @@ static int xgbe_config_tstamp(struct xgbe_prv_data *pdata,
xgbe_set_tstamp_time(pdata, 0, 0);
/* Initialize the timecounter */
- timecounter_init(&pdata->tstamp_tc, &pdata->tstamp_cc,
- ktime_to_ns(ktime_get_real()));
+ timecounter_init(&pdata->tstamp_tc, ktime_to_ns(ktime_get_real()));
return 0;
}
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-ptp.c b/drivers/net/ethernet/amd/xgbe/xgbe-ptp.c
index d06d260..5ea4edf 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-ptp.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-ptp.c
@@ -126,7 +126,7 @@ static u64 xgbe_cc_read(const struct cyclecounter *cc)
{
struct xgbe_prv_data *pdata = container_of(cc,
struct xgbe_prv_data,
- tstamp_cc);
+ tstamp_tc.cc);
u64 nsec;
nsec = pdata->hw_if.get_tstamp_time(pdata);
@@ -211,7 +211,7 @@ static int xgbe_settime(struct ptp_clock_info *info,
spin_lock_irqsave(&pdata->tstamp_lock, flags);
- timecounter_init(&pdata->tstamp_tc, &pdata->tstamp_cc, nsec);
+ timecounter_init(&pdata->tstamp_tc, nsec);
spin_unlock_irqrestore(&pdata->tstamp_lock, flags);
@@ -228,7 +228,7 @@ void xgbe_ptp_register(struct xgbe_prv_data *pdata)
{
struct ptp_clock_info *info = &pdata->ptp_clock_info;
struct ptp_clock *clock;
- struct cyclecounter *cc = &pdata->tstamp_cc;
+ struct cyclecounter *cc = &pdata->tstamp_tc.cc;
u64 dividend;
snprintf(info->name, sizeof(info->name), "%s",
@@ -263,8 +263,7 @@ void xgbe_ptp_register(struct xgbe_prv_data *pdata)
cc->mult = 1;
cc->shift = 0;
- timecounter_init(&pdata->tstamp_tc, &pdata->tstamp_cc,
- ktime_to_ns(ktime_get_real()));
+ timecounter_init(&pdata->tstamp_tc, ktime_to_ns(ktime_get_real()));
/* Disable all timestamping to start */
XGMAC_IOWRITE(pdata, MAC_TSCR, 0);
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe.h b/drivers/net/ethernet/amd/xgbe/xgbe.h
index ad102c8..2445103 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe.h
+++ b/drivers/net/ethernet/amd/xgbe/xgbe.h
@@ -1168,7 +1168,6 @@ struct xgbe_prv_data {
struct ptp_clock_info ptp_clock_info;
struct ptp_clock *ptp_clock;
struct hwtstamp_config tstamp_config;
- struct cyclecounter tstamp_cc;
struct timecounter tstamp_tc;
unsigned int tstamp_addend;
struct work_struct tx_tstamp_work;
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
index 352beff..f164fe0 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
@@ -1827,7 +1827,6 @@ struct bnx2x {
struct ptp_clock *ptp_clock;
struct ptp_clock_info ptp_clock_info;
struct work_struct ptp_task;
- struct cyclecounter cyclecounter;
struct timecounter timecounter;
bool timecounter_init_done;
struct sk_buff *ptp_tx_skb;
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
index 91e2a75..83624ad 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
@@ -13850,7 +13850,7 @@ static int bnx2x_ptp_settime(struct ptp_clock_info *ptp,
DP(BNX2X_MSG_PTP, "PTP settime called, ns = %llu\n", ns);
/* Re-init the timecounter */
- timecounter_init(&bp->timecounter, &bp->cyclecounter, ns);
+ timecounter_init(&bp->timecounter, ns);
return 0;
}
@@ -15254,7 +15254,7 @@ void bnx2x_set_rx_ts(struct bnx2x *bp, struct sk_buff *skb)
/* Read the PHC */
static u64 bnx2x_cyclecounter_read(const struct cyclecounter *cc)
{
- struct bnx2x *bp = container_of(cc, struct bnx2x, cyclecounter);
+ struct bnx2x *bp = container_of(cc, struct bnx2x, timecounter.cc);
int port = BP_PORT(bp);
u32 wb_data[2];
u64 phc_cycles;
@@ -15269,13 +15269,13 @@ static u64 bnx2x_cyclecounter_read(const struct cyclecounter *cc)
return phc_cycles;
}
-static void bnx2x_init_cyclecounter(struct bnx2x *bp)
+static void bnx2x_init_cyclecounter(struct cyclecounter *cc)
{
- memset(&bp->cyclecounter, 0, sizeof(bp->cyclecounter));
- bp->cyclecounter.read = bnx2x_cyclecounter_read;
- bp->cyclecounter.mask = CYCLECOUNTER_MASK(64);
- bp->cyclecounter.shift = 0;
- bp->cyclecounter.mult = 1;
+ memset(cc, 0, sizeof(*cc));
+ cc->read = bnx2x_cyclecounter_read;
+ cc->mask = CYCLECOUNTER_MASK(64);
+ cc->shift = 0;
+ cc->mult = 1;
}
static int bnx2x_send_reset_timesync_ramrod(struct bnx2x *bp)
@@ -15511,8 +15511,8 @@ void bnx2x_init_ptp(struct bnx2x *bp)
* unload / load (e.g. MTU change) while it is running.
*/
if (!bp->timecounter_init_done) {
- bnx2x_init_cyclecounter(bp);
- timecounter_init(&bp->timecounter, &bp->cyclecounter,
+ bnx2x_init_cyclecounter(&bp->timecounter.cc);
+ timecounter_init(&bp->timecounter,
ktime_to_ns(ktime_get_real()));
bp->timecounter_init_done = 1;
}
diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h
index 5385074..d54b501 100644
--- a/drivers/net/ethernet/freescale/fec.h
+++ b/drivers/net/ethernet/freescale/fec.h
@@ -549,7 +549,6 @@ struct fec_enet_private {
struct ptp_clock_info ptp_caps;
unsigned long last_overflow_check;
spinlock_t tmreg_lock;
- struct cyclecounter cc;
struct timecounter tc;
int rx_hwtstamp_filter;
u32 base_incval;
diff --git a/drivers/net/ethernet/freescale/fec_ptp.c b/drivers/net/ethernet/freescale/fec_ptp.c
index f814397..b1261d1 100644
--- a/drivers/net/ethernet/freescale/fec_ptp.c
+++ b/drivers/net/ethernet/freescale/fec_ptp.c
@@ -186,13 +186,14 @@ static int fec_ptp_enable_pps(struct fec_enet_private *fep, uint enable)
* ptp counter, which maybe cause 32-bit wrap. Since the
* (NSEC_PER_SEC - (u32)ts.tv_nsec) is less than 2 second.
* We can ensure the wrap will not cause issue. If the offset
- * is bigger than fep->cc.mask would be a error.
+ * is bigger than fep->tc.cc.mask would be a error.
*/
- val &= fep->cc.mask;
+ val &= fep->tc.cc.mask;
writel(val, fep->hwp + FEC_TCCR(fep->pps_channel));
/* Calculate the second the compare event timestamp */
- fep->next_counter = (val + fep->reload_period) & fep->cc.mask;
+ fep->next_counter = (val + fep->reload_period) &
+ fep->tc.cc.mask;
/* * Enable compare event when overflow */
val = readl(fep->hwp + FEC_ATIME_CTRL);
@@ -211,7 +212,8 @@ static int fec_ptp_enable_pps(struct fec_enet_private *fep, uint enable)
* the third timestamp. Refer the TCCR register detail in the spec.
*/
writel(fep->next_counter, fep->hwp + FEC_TCCR(fep->pps_channel));
- fep->next_counter = (fep->next_counter + fep->reload_period) & fep->cc.mask;
+ fep->next_counter = (fep->next_counter + fep->reload_period) &
+ fep->tc.cc.mask;
} else {
writel(0, fep->hwp + FEC_TCSR(fep->pps_channel));
}
@@ -233,7 +235,7 @@ static int fec_ptp_enable_pps(struct fec_enet_private *fep, uint enable)
static u64 fec_ptp_read(const struct cyclecounter *cc)
{
struct fec_enet_private *fep =
- container_of(cc, struct fec_enet_private, cc);
+ container_of(cc, struct fec_enet_private, tc.cc);
const struct platform_device_id *id_entry =
platform_get_device_id(fep->pdev);
u32 tempval;
@@ -276,14 +278,14 @@ void fec_ptp_start_cyclecounter(struct net_device *ndev)
writel(FEC_T_CTRL_ENABLE | FEC_T_CTRL_PERIOD_RST,
fep->hwp + FEC_ATIME_CTRL);
- memset(&fep->cc, 0, sizeof(fep->cc));
- fep->cc.read = fec_ptp_read;
- fep->cc.mask = CLOCKSOURCE_MASK(31);
- fep->cc.shift = 31;
- fep->cc.mult = FEC_CC_MULT;
+ memset(&fep->tc.cc, 0, sizeof(fep->tc.cc));
+ fep->tc.cc.read = fec_ptp_read;
+ fep->tc.cc.mask = CLOCKSOURCE_MASK(31);
+ fep->tc.cc.shift = 31;
+ fep->tc.cc.mult = FEC_CC_MULT;
/* reset the ns time counter */
- timecounter_init(&fep->tc, &fep->cc, ktime_to_ns(ktime_get_real()));
+ timecounter_init(&fep->tc, ktime_to_ns(ktime_get_real()));
spin_unlock_irqrestore(&fep->tmreg_lock, flags);
}
@@ -434,11 +436,11 @@ static int fec_ptp_settime(struct ptp_clock_info *ptp,
/* Get the timer value based on timestamp.
* Update the counter with the masked value.
*/
- counter = ns & fep->cc.mask;
+ counter = ns & fep->tc.cc.mask;
spin_lock_irqsave(&fep->tmreg_lock, flags);
writel(counter, fep->hwp + FEC_ATIME);
- timecounter_init(&fep->tc, &fep->cc, ns);
+ timecounter_init(&fep->tc, ns);
spin_unlock_irqrestore(&fep->tmreg_lock, flags);
mutex_unlock(&fep->ptp_clk_mutex);
return 0;
@@ -570,7 +572,7 @@ static irqreturn_t fec_pps_interrupt(int irq, void *dev_id)
/* Update the counter; */
fep->next_counter = (fep->next_counter + fep->reload_period) &
- fep->cc.mask;
+ fep->tc.cc.mask;
event.type = PTP_CLOCK_PPS;
ptp_clock_event(fep->ptp_clock, &event);
diff --git a/drivers/net/ethernet/intel/e1000e/e1000.h b/drivers/net/ethernet/intel/e1000e/e1000.h
index 2311b31..b59f82a 100644
--- a/drivers/net/ethernet/intel/e1000e/e1000.h
+++ b/drivers/net/ethernet/intel/e1000e/e1000.h
@@ -340,7 +340,6 @@ struct e1000_adapter {
unsigned long tx_hwtstamp_start;
struct work_struct tx_hwtstamp_work;
spinlock_t systim_lock; /* protects SYSTIML/H regsters */
- struct cyclecounter cc;
struct timecounter tc;
struct ptp_clock *ptp_clock;
struct ptp_clock_info ptp_clock_info;
diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c
index 9f18d39..c9f7ba3 100644
--- a/drivers/net/ethernet/intel/e1000e/netdev.c
+++ b/drivers/net/ethernet/intel/e1000e/netdev.c
@@ -3536,7 +3536,7 @@ s32 e1000e_get_base_timinca(struct e1000_adapter *adapter, u32 *timinca)
incperiod = INCPERIOD_96MHZ;
incvalue = INCVALUE_96MHZ;
shift = INCVALUE_SHIFT_96MHZ;
- adapter->cc.shift = shift + INCPERIOD_SHIFT_96MHZ;
+ adapter->tc.cc.shift = shift + INCPERIOD_SHIFT_96MHZ;
break;
case e1000_pch_lpt:
if (er32(TSYNCRXCTL) & E1000_TSYNCRXCTL_SYSCFI) {
@@ -3544,13 +3544,13 @@ s32 e1000e_get_base_timinca(struct e1000_adapter *adapter, u32 *timinca)
incperiod = INCPERIOD_96MHZ;
incvalue = INCVALUE_96MHZ;
shift = INCVALUE_SHIFT_96MHZ;
- adapter->cc.shift = shift + INCPERIOD_SHIFT_96MHZ;
+ adapter->tc.cc.shift = shift + INCPERIOD_SHIFT_96MHZ;
} else {
/* Stable 25MHz frequency */
incperiod = INCPERIOD_25MHZ;
incvalue = INCVALUE_25MHZ;
shift = INCVALUE_SHIFT_25MHZ;
- adapter->cc.shift = shift;
+ adapter->tc.cc.shift = shift;
}
break;
case e1000_pch_spt:
@@ -3559,7 +3559,7 @@ s32 e1000e_get_base_timinca(struct e1000_adapter *adapter, u32 *timinca)
incperiod = INCPERIOD_24MHZ;
incvalue = INCVALUE_24MHZ;
shift = INCVALUE_SHIFT_24MHZ;
- adapter->cc.shift = shift;
+ adapter->tc.cc.shift = shift;
break;
}
return -EINVAL;
@@ -3569,13 +3569,13 @@ s32 e1000e_get_base_timinca(struct e1000_adapter *adapter, u32 *timinca)
incperiod = INCPERIOD_24MHZ;
incvalue = INCVALUE_24MHZ;
shift = INCVALUE_SHIFT_24MHZ;
- adapter->cc.shift = shift;
+ adapter->tc.cc.shift = shift;
} else {
/* Stable 38400KHz frequency */
incperiod = INCPERIOD_38400KHZ;
incvalue = INCVALUE_38400KHZ;
shift = INCVALUE_SHIFT_38400KHZ;
- adapter->cc.shift = shift;
+ adapter->tc.cc.shift = shift;
}
break;
case e1000_82574:
@@ -3584,7 +3584,7 @@ s32 e1000e_get_base_timinca(struct e1000_adapter *adapter, u32 *timinca)
incperiod = INCPERIOD_25MHZ;
incvalue = INCVALUE_25MHZ;
shift = INCVALUE_SHIFT_25MHZ;
- adapter->cc.shift = shift;
+ adapter->tc.cc.shift = shift;
break;
default:
return -EINVAL;
@@ -3955,8 +3955,7 @@ static void e1000e_systim_reset(struct e1000_adapter *adapter)
/* reset the systim ns time counter */
spin_lock_irqsave(&adapter->systim_lock, flags);
- timecounter_init(&adapter->tc, &adapter->cc,
- ktime_to_ns(ktime_get_real()));
+ timecounter_init(&adapter->tc, ktime_to_ns(ktime_get_real()));
spin_unlock_irqrestore(&adapter->systim_lock, flags);
/* restore the previous hwtstamp configuration settings */
@@ -4389,7 +4388,7 @@ static u64 e1000e_sanitize_systim(struct e1000_hw *hw, u64 systim)
static u64 e1000e_cyclecounter_read(const struct cyclecounter *cc)
{
struct e1000_adapter *adapter = container_of(cc, struct e1000_adapter,
- cc);
+ tc.cc);
struct e1000_hw *hw = &adapter->hw;
u32 systimel, systimeh;
u64 systim;
@@ -4449,10 +4448,10 @@ static int e1000_sw_init(struct e1000_adapter *adapter)
/* Setup hardware time stamping cyclecounter */
if (adapter->flags & FLAG_HAS_HW_TIMESTAMP) {
- adapter->cc.read = e1000e_cyclecounter_read;
- adapter->cc.mask = CYCLECOUNTER_MASK(64);
- adapter->cc.mult = 1;
- /* cc.shift set in e1000e_get_base_tininca() */
+ adapter->tc.cc.read = e1000e_cyclecounter_read;
+ adapter->tc.cc.mask = CYCLECOUNTER_MASK(64);
+ adapter->tc.cc.mult = 1;
+ /* tc.cc.shift set in e1000e_get_base_tininca() */
spin_lock_init(&adapter->systim_lock);
INIT_WORK(&adapter->tx_hwtstamp_work, e1000e_tx_hwtstamp_work);
diff --git a/drivers/net/ethernet/intel/e1000e/ptp.c b/drivers/net/ethernet/intel/e1000e/ptp.c
index b366885..03d5f2a 100644
--- a/drivers/net/ethernet/intel/e1000e/ptp.c
+++ b/drivers/net/ethernet/intel/e1000e/ptp.c
@@ -222,7 +222,7 @@ static int e1000e_phc_settime(struct ptp_clock_info *ptp,
/* reset the timecounter */
spin_lock_irqsave(&adapter->systim_lock, flags);
- timecounter_init(&adapter->tc, &adapter->cc, ns);
+ timecounter_init(&adapter->tc, ns);
spin_unlock_irqrestore(&adapter->systim_lock, flags);
return 0;
diff --git a/drivers/net/ethernet/intel/igb/igb.h b/drivers/net/ethernet/intel/igb/igb.h
index 9284569..4eac4f2 100644
--- a/drivers/net/ethernet/intel/igb/igb.h
+++ b/drivers/net/ethernet/intel/igb/igb.h
@@ -565,7 +565,6 @@ struct igb_adapter {
unsigned long last_rx_timestamp;
unsigned int ptp_flags;
spinlock_t tmreg_lock;
- struct cyclecounter cc;
struct timecounter tc;
u32 tx_hwtstamp_timeouts;
u32 tx_hwtstamp_skipped;
diff --git a/drivers/net/ethernet/intel/igb/igb_ptp.c b/drivers/net/ethernet/intel/igb/igb_ptp.c
index 841c2a0..0745eff 100644
--- a/drivers/net/ethernet/intel/igb/igb_ptp.c
+++ b/drivers/net/ethernet/intel/igb/igb_ptp.c
@@ -79,7 +79,7 @@
/* SYSTIM read access for the 82576 */
static u64 igb_ptp_read_82576(const struct cyclecounter *cc)
{
- struct igb_adapter *igb = container_of(cc, struct igb_adapter, cc);
+ struct igb_adapter *igb = container_of(cc, struct igb_adapter, tc.cc);
struct e1000_hw *hw = &igb->hw;
u64 val;
u32 lo, hi;
@@ -96,7 +96,7 @@ static u64 igb_ptp_read_82576(const struct cyclecounter *cc)
/* SYSTIM read access for the 82580 */
static u64 igb_ptp_read_82580(const struct cyclecounter *cc)
{
- struct igb_adapter *igb = container_of(cc, struct igb_adapter, cc);
+ struct igb_adapter *igb = container_of(cc, struct igb_adapter, tc.cc);
struct e1000_hw *hw = &igb->hw;
u32 lo, hi;
u64 val;
@@ -330,7 +330,7 @@ static int igb_ptp_settime_82576(struct ptp_clock_info *ptp,
spin_lock_irqsave(&igb->tmreg_lock, flags);
- timecounter_init(&igb->tc, &igb->cc, ns);
+ timecounter_init(&igb->tc, ns);
spin_unlock_irqrestore(&igb->tmreg_lock, flags);
@@ -1126,10 +1126,10 @@ void igb_ptp_init(struct igb_adapter *adapter)
adapter->ptp_caps.gettime64 = igb_ptp_gettime_82576;
adapter->ptp_caps.settime64 = igb_ptp_settime_82576;
adapter->ptp_caps.enable = igb_ptp_feature_enable;
- adapter->cc.read = igb_ptp_read_82576;
- adapter->cc.mask = CYCLECOUNTER_MASK(64);
- adapter->cc.mult = 1;
- adapter->cc.shift = IGB_82576_TSYNC_SHIFT;
+ adapter->tc.cc.read = igb_ptp_read_82576;
+ adapter->tc.cc.mask = CYCLECOUNTER_MASK(64);
+ adapter->tc.cc.mult = 1;
+ adapter->tc.cc.shift = IGB_82576_TSYNC_SHIFT;
adapter->ptp_flags |= IGB_PTP_OVERFLOW_CHECK;
break;
case e1000_82580:
@@ -1145,10 +1145,10 @@ void igb_ptp_init(struct igb_adapter *adapter)
adapter->ptp_caps.gettime64 = igb_ptp_gettime_82576;
adapter->ptp_caps.settime64 = igb_ptp_settime_82576;
adapter->ptp_caps.enable = igb_ptp_feature_enable;
- adapter->cc.read = igb_ptp_read_82580;
- adapter->cc.mask = CYCLECOUNTER_MASK(IGB_NBITS_82580);
- adapter->cc.mult = 1;
- adapter->cc.shift = 0;
+ adapter->tc.cc.read = igb_ptp_read_82580;
+ adapter->tc.cc.mask = CYCLECOUNTER_MASK(IGB_NBITS_82580);
+ adapter->tc.cc.mult = 1;
+ adapter->tc.cc.shift = 0;
adapter->ptp_flags |= IGB_PTP_OVERFLOW_CHECK;
break;
case e1000_i210:
@@ -1289,8 +1289,7 @@ void igb_ptp_reset(struct igb_adapter *adapter)
igb_ptp_write_i210(adapter, &ts);
} else {
- timecounter_init(&adapter->tc, &adapter->cc,
- ktime_to_ns(ktime_get_real()));
+ timecounter_init(&adapter->tc, ktime_to_ns(ktime_get_real()));
}
out:
spin_unlock_irqrestore(&adapter->tmreg_lock, flags);
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
index 468c355..5c391a0 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
@@ -738,7 +738,6 @@ struct ixgbe_adapter {
unsigned long last_rx_ptp_check;
unsigned long last_rx_timestamp;
spinlock_t tmreg_lock;
- struct cyclecounter hw_cc;
struct timecounter hw_tc;
u32 base_incval;
u32 tx_hwtstamp_timeouts;
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c
index ae312c4..6e9f2c0 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c
@@ -179,7 +179,7 @@
static void ixgbe_ptp_setup_sdp_x540(struct ixgbe_adapter *adapter)
{
struct ixgbe_hw *hw = &adapter->hw;
- int shift = adapter->hw_cc.shift;
+ int shift = adapter->hw_tc.cc.shift;
u32 esdp, tsauxc, clktiml, clktimh, trgttiml, trgttimh, rem;
u64 ns = 0, clock_edge = 0;
@@ -237,7 +237,7 @@ static void ixgbe_ptp_setup_sdp_x540(struct ixgbe_adapter *adapter)
/**
* ixgbe_ptp_read_X550 - read cycle counter value
- * @hw_cc: cyclecounter structure
+ * @cc: cyclecounter structure
*
* This function reads SYSTIME registers. It is called by the cyclecounter
* structure to convert from internal representation into nanoseconds. We need
@@ -245,10 +245,10 @@ static void ixgbe_ptp_setup_sdp_x540(struct ixgbe_adapter *adapter)
* result of SYSTIME is 32bits of "billions of cycles" and 32 bits of
* "cycles", rather than seconds and nanoseconds.
*/
-static u64 ixgbe_ptp_read_X550(const struct cyclecounter *hw_cc)
+static u64 ixgbe_ptp_read_X550(const struct cyclecounter *cc)
{
struct ixgbe_adapter *adapter =
- container_of(hw_cc, struct ixgbe_adapter, hw_cc);
+ container_of(cc, struct ixgbe_adapter, hw_tc.cc);
struct ixgbe_hw *hw = &adapter->hw;
struct timespec64 ts;
@@ -285,7 +285,7 @@ static u64 ixgbe_ptp_read_X550(const struct cyclecounter *hw_cc)
static u64 ixgbe_ptp_read_82599(const struct cyclecounter *cc)
{
struct ixgbe_adapter *adapter =
- container_of(cc, struct ixgbe_adapter, hw_cc);
+ container_of(cc, struct ixgbe_adapter, hw_tc.cc);
struct ixgbe_hw *hw = &adapter->hw;
u64 stamp = 0;
@@ -508,7 +508,7 @@ static int ixgbe_ptp_settime(struct ptp_clock_info *ptp,
/* reset the timecounter */
spin_lock_irqsave(&adapter->tmreg_lock, flags);
- timecounter_init(&adapter->hw_tc, &adapter->hw_cc, ns);
+ timecounter_init(&adapter->hw_tc, ns);
spin_unlock_irqrestore(&adapter->tmreg_lock, flags);
if (adapter->ptp_setup_sdp)
@@ -1164,7 +1164,7 @@ void ixgbe_ptp_start_cyclecounter(struct ixgbe_adapter *adapter)
/* need lock to prevent incorrect read while modifying cyclecounter */
spin_lock_irqsave(&adapter->tmreg_lock, flags);
- memcpy(&adapter->hw_cc, &cc, sizeof(adapter->hw_cc));
+ memcpy(&adapter->hw_tc.cc, &cc, sizeof(adapter->hw_tc.cc));
spin_unlock_irqrestore(&adapter->tmreg_lock, flags);
}
@@ -1195,8 +1195,7 @@ void ixgbe_ptp_reset(struct ixgbe_adapter *adapter)
ixgbe_ptp_start_cyclecounter(adapter);
spin_lock_irqsave(&adapter->tmreg_lock, flags);
- timecounter_init(&adapter->hw_tc, &adapter->hw_cc,
- ktime_to_ns(ktime_get_real()));
+ timecounter_init(&adapter->hw_tc, ktime_to_ns(ktime_get_real()));
spin_unlock_irqrestore(&adapter->tmreg_lock, flags);
adapter->last_overflow_check = jiffies;
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_clock.c b/drivers/net/ethernet/mellanox/mlx4/en_clock.c
index 0247885..35987b5 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_clock.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_clock.c
@@ -38,13 +38,13 @@
/* mlx4_en_read_clock - read raw cycle counter (to be used by time counter)
*/
-static u64 mlx4_en_read_clock(const struct cyclecounter *tc)
+static u64 mlx4_en_read_clock(const struct cyclecounter *cc)
{
struct mlx4_en_dev *mdev =
- container_of(tc, struct mlx4_en_dev, cycles);
+ container_of(cc, struct mlx4_en_dev, clock.cc);
struct mlx4_dev *dev = mdev->dev;
- return mlx4_read_clock(dev) & tc->mask;
+ return mlx4_read_clock(dev) & cc->mask;
}
u64 mlx4_en_get_cqe_ts(struct mlx4_cqe *cqe)
@@ -138,7 +138,7 @@ static int mlx4_en_phc_adjfreq(struct ptp_clock_info *ptp, s32 delta)
write_seqlock_irqsave(&mdev->clock_lock, flags);
timecounter_read(&mdev->clock);
- mdev->cycles.mult = neg_adj ? mult - diff : mult + diff;
+ mdev->clock.cc.mult = neg_adj ? mult - diff : mult + diff;
write_sequnlock_irqrestore(&mdev->clock_lock, flags);
return 0;
@@ -207,7 +207,7 @@ static int mlx4_en_phc_settime(struct ptp_clock_info *ptp,
/* reset the timecounter */
write_seqlock_irqsave(&mdev->clock_lock, flags);
- timecounter_init(&mdev->clock, &mdev->cycles, ns);
+ timecounter_init(&mdev->clock, ns);
write_sequnlock_irqrestore(&mdev->clock_lock, flags);
return 0;
@@ -274,17 +274,17 @@ void mlx4_en_init_timestamp(struct mlx4_en_dev *mdev)
seqlock_init(&mdev->clock_lock);
- memset(&mdev->cycles, 0, sizeof(mdev->cycles));
- mdev->cycles.read = mlx4_en_read_clock;
- mdev->cycles.mask = CLOCKSOURCE_MASK(48);
- mdev->cycles.shift = freq_to_shift(dev->caps.hca_core_clock);
- mdev->cycles.mult =
- clocksource_khz2mult(1000 * dev->caps.hca_core_clock, mdev->cycles.shift);
- mdev->nominal_c_mult = mdev->cycles.mult;
+ memset(&mdev->clock.cc, 0, sizeof(mdev->clock.cc));
+ mdev->clock.cc.read = mlx4_en_read_clock;
+ mdev->clock.cc.mask = CLOCKSOURCE_MASK(48);
+ mdev->clock.cc.shift = freq_to_shift(dev->caps.hca_core_clock);
+ mdev->clock.cc.mult =
+ clocksource_khz2mult(1000 * dev->caps.hca_core_clock,
+ mdev->clock.cc.shift);
+ mdev->nominal_c_mult = mdev->clock.cc.mult;
write_seqlock_irqsave(&mdev->clock_lock, flags);
- timecounter_init(&mdev->clock, &mdev->cycles,
- ktime_to_ns(ktime_get_real()));
+ timecounter_init(&mdev->clock, ktime_to_ns(ktime_get_real()));
write_sequnlock_irqrestore(&mdev->clock_lock, flags);
/* Configure the PHC */
diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
index 1856e27..e301dcf 100644
--- a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
+++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
@@ -422,7 +422,6 @@ struct mlx4_en_dev {
spinlock_t uar_lock;
u8 mac_removed[MLX4_MAX_PORTS + 1];
u32 nominal_c_mult;
- struct cyclecounter cycles;
seqlock_t clock_lock;
struct timecounter clock;
unsigned long last_overflow_check;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c
index fa8aed6..8cb6838 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c
@@ -64,7 +64,7 @@ enum {
static u64 read_internal_timer(const struct cyclecounter *cc)
{
- struct mlx5_clock *clock = container_of(cc, struct mlx5_clock, cycles);
+ struct mlx5_clock *clock = container_of(cc, struct mlx5_clock, tc.cc);
struct mlx5_core_dev *mdev = container_of(clock, struct mlx5_core_dev,
clock);
@@ -122,7 +122,7 @@ static int mlx5_ptp_settime(struct ptp_clock_info *ptp,
unsigned long flags;
write_lock_irqsave(&clock->lock, flags);
- timecounter_init(&clock->tc, &clock->cycles, ns);
+ timecounter_init(&clock->tc, ns);
write_unlock_irqrestore(&clock->lock, flags);
return 0;
@@ -177,8 +177,8 @@ static int mlx5_ptp_adjfreq(struct ptp_clock_info *ptp, s32 delta)
write_lock_irqsave(&clock->lock, flags);
timecounter_read(&clock->tc);
- clock->cycles.mult = neg_adj ? clock->nominal_c_mult - diff :
- clock->nominal_c_mult + diff;
+ clock->tc.cc.mult = neg_adj ? clock->nominal_c_mult - diff :
+ clock->nominal_c_mult + diff;
write_unlock_irqrestore(&clock->lock, flags);
return 0;
@@ -281,8 +281,8 @@ static int mlx5_perout_configure(struct ptp_clock_info *ptp,
write_lock_irqsave(&clock->lock, flags);
nsec_now = timecounter_cyc2time(&clock->tc, cycles_now);
nsec_delta = ns - nsec_now;
- cycles_delta = div64_u64(nsec_delta << clock->cycles.shift,
- clock->cycles.mult);
+ cycles_delta = div64_u64(nsec_delta << clock->tc.cc.shift,
+ clock->tc.cc.mult);
write_unlock_irqrestore(&clock->lock, flags);
time_stamp = cycles_now + cycles_delta;
field_select = MLX5_MTPPS_FS_PIN_MODE |
@@ -440,8 +440,8 @@ void mlx5_pps_event(struct mlx5_core_dev *mdev,
write_lock_irqsave(&clock->lock, flags);
nsec_now = timecounter_cyc2time(&clock->tc, cycles_now);
nsec_delta = ns - nsec_now;
- cycles_delta = div64_u64(nsec_delta << clock->cycles.shift,
- clock->cycles.mult);
+ cycles_delta = div64_u64(nsec_delta << clock->tc.cc.shift,
+ clock->tc.cc.mult);
clock->pps_info.start[pin] = cycles_now + cycles_delta;
schedule_work(&clock->pps_info.out_work);
write_unlock_irqrestore(&clock->lock, flags);
@@ -454,6 +454,7 @@ void mlx5_pps_event(struct mlx5_core_dev *mdev,
void mlx5_init_clock(struct mlx5_core_dev *mdev)
{
struct mlx5_clock *clock = &mdev->clock;
+ struct cyclecounter *cc = &clock->tc.cc;
u64 ns;
u64 frac = 0;
u32 dev_freq;
@@ -464,21 +465,18 @@ void mlx5_init_clock(struct mlx5_core_dev *mdev)
return;
}
rwlock_init(&clock->lock);
- clock->cycles.read = read_internal_timer;
- clock->cycles.shift = MLX5_CYCLES_SHIFT;
- clock->cycles.mult = clocksource_khz2mult(dev_freq,
- clock->cycles.shift);
- clock->nominal_c_mult = clock->cycles.mult;
- clock->cycles.mask = CLOCKSOURCE_MASK(41);
+ cc->read = read_internal_timer;
+ cc->shift = MLX5_CYCLES_SHIFT;
+ cc->mult = clocksource_khz2mult(dev_freq, cc->shift);
+ clock->nominal_c_mult = cc->mult;
+ cc->mask = CLOCKSOURCE_MASK(41);
- timecounter_init(&clock->tc, &clock->cycles,
- ktime_to_ns(ktime_get_real()));
+ timecounter_init(&clock->tc, ktime_to_ns(ktime_get_real()));
/* Calculate period in seconds to call the overflow watchdog - to make
* sure counter is checked at least once every wrap around.
*/
- ns = cyclecounter_cyc2ns(&clock->cycles, clock->cycles.mask,
- frac, &frac);
+ ns = cyclecounter_cyc2ns(cc, cc->mask, frac, &frac);
do_div(ns, NSEC_PER_SEC / 2 / HZ);
clock->overflow_period = ns;
diff --git a/drivers/net/ethernet/qlogic/qede/qede_ptp.c b/drivers/net/ethernet/qlogic/qede/qede_ptp.c
index 9b2280b..95bb8a8 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_ptp.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_ptp.c
@@ -34,7 +34,6 @@
struct qede_ptp {
const struct qed_eth_ptp_ops *ops;
struct ptp_clock_info clock_info;
- struct cyclecounter cc;
struct timecounter tc;
struct ptp_clock *clock;
struct work_struct work;
@@ -132,7 +131,7 @@ static int qede_ptp_settime(struct ptp_clock_info *info,
/* Re-init the timecounter */
spin_lock_bh(&ptp->lock);
- timecounter_init(&ptp->tc, &ptp->cc, ns);
+ timecounter_init(&ptp->tc, ns);
spin_unlock_bh(&ptp->lock);
return 0;
@@ -196,7 +195,7 @@ static u64 qede_ptp_read_cc(const struct cyclecounter *cc)
u64 phc_cycles;
int rc;
- ptp = container_of(cc, struct qede_ptp, cc);
+ ptp = container_of(cc, struct qede_ptp, tc.cc);
edev = ptp->edev;
rc = ptp->ops->read_cc(edev->cdev, &phc_cycles);
if (rc)
@@ -428,14 +427,13 @@ static int qede_ptp_init(struct qede_dev *edev, bool init_tc)
* unload / load (e.g. MTU change) while it is running.
*/
if (init_tc) {
- memset(&ptp->cc, 0, sizeof(ptp->cc));
- ptp->cc.read = qede_ptp_read_cc;
- ptp->cc.mask = CYCLECOUNTER_MASK(64);
- ptp->cc.shift = 0;
- ptp->cc.mult = 1;
-
- timecounter_init(&ptp->tc, &ptp->cc,
- ktime_to_ns(ktime_get_real()));
+ memset(&ptp->tc.cc, 0, sizeof(ptp->tc.cc));
+ ptp->tc.cc.read = qede_ptp_read_cc;
+ ptp->tc.cc.mask = CYCLECOUNTER_MASK(64);
+ ptp->tc.cc.shift = 0;
+ ptp->tc.cc.mult = 1;
+
+ timecounter_init(&ptp->tc, ktime_to_ns(ktime_get_real()));
}
return rc;
diff --git a/drivers/net/ethernet/ti/cpts.c b/drivers/net/ethernet/ti/cpts.c
index e7b76f6..b8fe843 100644
--- a/drivers/net/ethernet/ti/cpts.c
+++ b/drivers/net/ethernet/ti/cpts.c
@@ -182,7 +182,7 @@ static u64 cpts_systim_read(const struct cyclecounter *cc)
u64 val = 0;
struct cpts_event *event;
struct list_head *this, *next;
- struct cpts *cpts = container_of(cc, struct cpts, cc);
+ struct cpts *cpts = container_of(cc, struct cpts, tc.cc);
cpts_write32(cpts, TS_PUSH, ts_push);
if (cpts_fifo_read(cpts, CPTS_EV_PUSH))
@@ -224,7 +224,7 @@ static int cpts_ptp_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
timecounter_read(&cpts->tc);
- cpts->cc.mult = neg_adj ? mult - diff : mult + diff;
+ cpts->tc.cc.mult = neg_adj ? mult - diff : mult + diff;
spin_unlock_irqrestore(&cpts->lock, flags);
@@ -268,7 +268,7 @@ static int cpts_ptp_settime(struct ptp_clock_info *ptp,
ns = timespec64_to_ns(ts);
spin_lock_irqsave(&cpts->lock, flags);
- timecounter_init(&cpts->tc, &cpts->cc, ns);
+ timecounter_init(&cpts->tc, ns);
spin_unlock_irqrestore(&cpts->lock, flags);
return 0;
@@ -447,7 +447,7 @@ int cpts_register(struct cpts *cpts)
cpts_write32(cpts, CPTS_EN, control);
cpts_write32(cpts, TS_PEND_EN, int_enable);
- timecounter_init(&cpts->tc, &cpts->cc, ktime_to_ns(ktime_get_real()));
+ timecounter_init(&cpts->tc, ktime_to_ns(ktime_get_real()));
cpts->clock = ptp_clock_register(&cpts->info, cpts->dev);
if (IS_ERR(cpts->clock)) {
@@ -486,6 +486,7 @@ void cpts_unregister(struct cpts *cpts)
static void cpts_calc_mult_shift(struct cpts *cpts)
{
+ struct cyclecounter *cc = &cpts->tc.cc;
u64 frac, maxsec, ns;
u32 freq;
@@ -494,7 +495,7 @@ static void cpts_calc_mult_shift(struct cpts *cpts)
/* Calc the maximum number of seconds which we can run before
* wrapping around.
*/
- maxsec = cpts->cc.mask;
+ maxsec = cc->mask;
do_div(maxsec, freq);
/* limit conversation rate to 10 sec as higher values will produce
* too small mult factors and so reduce the conversion accuracy
@@ -507,18 +508,19 @@ static void cpts_calc_mult_shift(struct cpts *cpts)
dev_info(cpts->dev, "cpts: overflow check period %lu (jiffies)\n",
cpts->ov_check_period);
- if (cpts->cc.mult || cpts->cc.shift)
+ if (cc->mult || cc->shift)
return;
- clocks_calc_mult_shift(&cpts->cc.mult, &cpts->cc.shift,
+ clocks_calc_mult_shift(&cc->mult, &cc->shift,
freq, NSEC_PER_SEC, maxsec);
frac = 0;
- ns = cyclecounter_cyc2ns(&cpts->cc, freq, cpts->cc.mask, &frac);
+ ns = cyclecounter_cyc2ns(cc, freq, cc->mask, &frac);
dev_info(cpts->dev,
"CPTS: ref_clk_freq:%u calc_mult:%u calc_shift:%u error:%lld nsec/sec\n",
- freq, cpts->cc.mult, cpts->cc.shift, (ns - NSEC_PER_SEC));
+ freq, cc->mult, cc->shift,
+ (ns - NSEC_PER_SEC));
}
static int cpts_of_parse(struct cpts *cpts, struct device_node *node)
@@ -527,13 +529,13 @@ static int cpts_of_parse(struct cpts *cpts, struct device_node *node)
u32 prop;
if (!of_property_read_u32(node, "cpts_clock_mult", &prop))
- cpts->cc.mult = prop;
+ cpts->tc.cc.mult = prop;
if (!of_property_read_u32(node, "cpts_clock_shift", &prop))
- cpts->cc.shift = prop;
+ cpts->tc.cc.shift = prop;
- if ((cpts->cc.mult && !cpts->cc.shift) ||
- (!cpts->cc.mult && cpts->cc.shift))
+ if ((cpts->tc.cc.mult && !cpts->tc.cc.shift) ||
+ (!cpts->tc.cc.mult && cpts->tc.cc.shift))
goto of_error;
return 0;
@@ -569,15 +571,15 @@ struct cpts *cpts_create(struct device *dev, void __iomem *regs,
clk_prepare(cpts->refclk);
- cpts->cc.read = cpts_systim_read;
- cpts->cc.mask = CLOCKSOURCE_MASK(32);
+ cpts->tc.cc.read = cpts_systim_read;
+ cpts->tc.cc.mask = CLOCKSOURCE_MASK(32);
cpts->info = cpts_info;
cpts_calc_mult_shift(cpts);
- /* save cc.mult original value as it can be modified
+ /* save tc.cc.mult original value as it can be modified
* by cpts_ptp_adjfreq().
*/
- cpts->cc_mult = cpts->cc.mult;
+ cpts->cc_mult = cpts->tc.cc.mult;
return cpts;
}
diff --git a/drivers/net/ethernet/ti/cpts.h b/drivers/net/ethernet/ti/cpts.h
index 73d73fa..a7174eb 100644
--- a/drivers/net/ethernet/ti/cpts.h
+++ b/drivers/net/ethernet/ti/cpts.h
@@ -117,7 +117,6 @@ struct cpts {
struct ptp_clock *clock;
spinlock_t lock; /* protects time registers */
u32 cc_mult; /* for the nominal frequency */
- struct cyclecounter cc;
struct timecounter tc;
int phc_index;
struct clk *refclk;
diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h
index a886b51..c81c615 100644
--- a/include/linux/mlx5/driver.h
+++ b/include/linux/mlx5/driver.h
@@ -780,7 +780,6 @@ struct mlx5_pps {
struct mlx5_clock {
rwlock_t lock;
- struct cyclecounter cycles;
struct timecounter tc;
struct hwtstamp_config hwtstamp_config;
u32 nominal_c_mult;
diff --git a/include/linux/timecounter.h b/include/linux/timecounter.h
index 2496ad4..6daca06 100644
--- a/include/linux/timecounter.h
+++ b/include/linux/timecounter.h
@@ -62,7 +62,7 @@ struct cyclecounter {
* @frac: accumulated fractional nanoseconds
*/
struct timecounter {
- const struct cyclecounter *cc;
+ struct cyclecounter cc;
u64 cycle_last;
u64 nsec;
u64 mask;
@@ -98,7 +98,6 @@ static inline void timecounter_adjtime(struct timecounter *tc, s64 delta)
/**
* timecounter_init - initialize a time counter
* @tc: Pointer to time counter which is to be initialized/reset
- * @cc: A cycle counter, ready to be used.
* @start_tstamp: Arbitrary initial time stamp.
*
* After this call the current cycle register (roughly) corresponds to
@@ -106,7 +105,6 @@ static inline void timecounter_adjtime(struct timecounter *tc, s64 delta)
* the time stamp counter by the number of elapsed nanoseconds.
*/
extern void timecounter_init(struct timecounter *tc,
- const struct cyclecounter *cc,
u64 start_tstamp);
/**
diff --git a/include/sound/hdaudio.h b/include/sound/hdaudio.h
index 68169e3..3061f44 100644
--- a/include/sound/hdaudio.h
+++ b/include/sound/hdaudio.h
@@ -445,7 +445,6 @@ struct hdac_stream {
unsigned long start_wallclk; /* start + minimum wallclk */
unsigned long period_wallclk; /* wallclk for period */
struct timecounter tc;
- struct cyclecounter cc;
int delay_negative_threshold;
struct list_head list;
diff --git a/kernel/time/timecounter.c b/kernel/time/timecounter.c
index 8afd789..7919acb 100644
--- a/kernel/time/timecounter.c
+++ b/kernel/time/timecounter.c
@@ -18,11 +18,10 @@
#include <linux/export.h>
#include <linux/timecounter.h>
-void timecounter_init(struct timecounter *tc,
- const struct cyclecounter *cc,
- u64 start_tstamp)
+void timecounter_init(struct timecounter *tc, u64 start_tstamp)
{
- tc->cc = cc;
+ struct cyclecounter *cc = &tc->cc;
+
tc->cycle_last = cc->read(cc);
tc->nsec = start_tstamp;
tc->mask = (1ULL << cc->shift) - 1;
@@ -43,17 +42,18 @@ void timecounter_init(struct timecounter *tc,
*/
static u64 timecounter_read_delta(struct timecounter *tc)
{
+ struct cyclecounter *cc = &tc->cc;
u64 cycle_now, cycle_delta;
u64 ns_offset;
/* read cycle counter: */
- cycle_now = tc->cc->read(tc->cc);
+ cycle_now = cc->read(cc);
/* calculate the delta since the last timecounter_read_delta(): */
- cycle_delta = (cycle_now - tc->cycle_last) & tc->cc->mask;
+ cycle_delta = (cycle_now - tc->cycle_last) & cc->mask;
/* convert to nanoseconds: */
- ns_offset = cyclecounter_cyc2ns(tc->cc, cycle_delta,
+ ns_offset = cyclecounter_cyc2ns(cc, cycle_delta,
tc->mask, &tc->frac);
/* update time stamp of timecounter_read_delta() call: */
@@ -89,10 +89,10 @@ static u64 cc_cyc2ns_backwards(const struct cyclecounter *cc,
return ns;
}
-u64 timecounter_cyc2time(struct timecounter *tc,
- u64 cycle_tstamp)
+u64 timecounter_cyc2time(struct timecounter *tc, u64 cycle_tstamp)
{
- u64 delta = (cycle_tstamp - tc->cycle_last) & tc->cc->mask;
+ struct cyclecounter *cc = &tc->cc;
+ u64 delta = (cycle_tstamp - tc->cycle_last) & cc->mask;
u64 nsec = tc->nsec, frac = tc->frac;
/*
@@ -100,11 +100,11 @@ u64 timecounter_cyc2time(struct timecounter *tc,
* than tc->cycle_last, detect when it is too far in the
* future and treat it as old time stamp instead.
*/
- if (delta > tc->cc->mask / 2) {
- delta = (tc->cycle_last - cycle_tstamp) & tc->cc->mask;
- nsec -= cc_cyc2ns_backwards(tc->cc, delta, tc->mask, frac);
+ if (delta > cc->mask / 2) {
+ delta = (tc->cycle_last - cycle_tstamp) & cc->mask;
+ nsec -= cc_cyc2ns_backwards(cc, delta, tc->mask, frac);
} else {
- nsec += cyclecounter_cyc2ns(tc->cc, delta, tc->mask, &frac);
+ nsec += cyclecounter_cyc2ns(cc, delta, tc->mask, &frac);
}
return nsec;
diff --git a/sound/hda/hdac_stream.c b/sound/hda/hdac_stream.c
index e1472c7..9426c1a 100644
--- a/sound/hda/hdac_stream.c
+++ b/sound/hda/hdac_stream.c
@@ -467,7 +467,8 @@ int snd_hdac_stream_set_params(struct hdac_stream *azx_dev,
static u64 azx_cc_read(const struct cyclecounter *cc)
{
- struct hdac_stream *azx_dev = container_of(cc, struct hdac_stream, cc);
+ struct hdac_stream *azx_dev = container_of(cc, struct hdac_stream,
+ tc.cc);
return snd_hdac_chip_readl(azx_dev->bus, WALLCLK);
}
@@ -476,7 +477,7 @@ static void azx_timecounter_init(struct hdac_stream *azx_dev,
bool force, u64 last)
{
struct timecounter *tc = &azx_dev->tc;
- struct cyclecounter *cc = &azx_dev->cc;
+ struct cyclecounter *cc = &azx_dev->tc.cc;
u64 nsec;
cc->read = azx_cc_read;
@@ -496,7 +497,7 @@ static void azx_timecounter_init(struct hdac_stream *azx_dev,
cc->shift = 0;
nsec = 0; /* audio time is elapsed time since trigger */
- timecounter_init(tc, cc, nsec);
+ timecounter_init(tc, nsec);
if (force) {
/*
* force timecounter to use predefined value,
diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
index 4151250..f3505bd 100644
--- a/virt/kvm/arm/arch_timer.c
+++ b/virt/kvm/arm/arch_timer.c
@@ -53,7 +53,7 @@ static void kvm_timer_update_irq(struct kvm_vcpu *vcpu, bool new_level,
u64 kvm_phys_timer_read(void)
{
- return timecounter->cc->read(timecounter->cc);
+ return timecounter->cc.read(&timecounter->cc);
}
static void soft_timer_start(struct hrtimer *hrt, u64 ns)
@@ -138,7 +138,7 @@ static u64 kvm_timer_compute_delta(struct arch_timer_context *timer_ctx)
if (now < cval) {
u64 ns;
- ns = cyclecounter_cyc2ns(timecounter->cc,
+ ns = cyclecounter_cyc2ns(&timecounter->cc,
cval - now,
timecounter->mask,
&timecounter->frac);
@@ -734,7 +734,7 @@ int kvm_timer_hyp_init(void)
info = arch_timer_get_kvm_info();
timecounter = &info->timecounter;
- if (!timecounter->cc) {
+ if (!timecounter->cc.mask) {
kvm_err("kvm_arch_timer: uninitialized timecounter\n");
return -ENODEV;
}
--
1.9.1
^ permalink raw reply related
* [PATCH v3 1/4] omapdrm: panel: fix compatible vendor string for td028ttec1
From: H. Nikolaus Schaller @ 2017-12-01 7:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171201015730.nvw6sblxn566dhhb@rob-hp-laptop>
> Am 01.12.2017 um 02:57 schrieb Rob Herring <robh@kernel.org>:
>
> On Tue, Nov 28, 2017 at 04:48:54PM +0100, H. Nikolaus Schaller wrote:
>> The vendor name was "toppoly" but other panels and the vendor list
>> have defined it as "tpo". So let's fix it in driver and bindings.
>>
>> We keep the old definition in parallel to stay compatible with
>> potential older DTB setup.
>>
>> Signed-off-by: H. Nikolaus Schaller <hns@goldelico.com>
>> ---
>> .../display/panel/{toppoly,td028ttec1.txt => tpo,td028ttec1.txt} | 4 ++--
>> drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c | 3 +++
>> drivers/video/fbdev/omap2/omapfb/displays/panel-tpo-td028ttec1.c | 3 +++
>> 3 files changed, 8 insertions(+), 2 deletions(-)
>> rename Documentation/devicetree/bindings/display/panel/{toppoly,td028ttec1.txt => tpo,td028ttec1.txt} (84%)
>>
>> diff --git a/Documentation/devicetree/bindings/display/panel/toppoly,td028ttec1.txt b/Documentation/devicetree/bindings/display/panel/tpo,td028ttec1.txt
>> similarity index 84%
>> rename from Documentation/devicetree/bindings/display/panel/toppoly,td028ttec1.txt
>> rename to Documentation/devicetree/bindings/display/panel/tpo,td028ttec1.txt
>> index 7175dc3740ac..ed34253d9fb1 100644
>> --- a/Documentation/devicetree/bindings/display/panel/toppoly,td028ttec1.txt
>> +++ b/Documentation/devicetree/bindings/display/panel/tpo,td028ttec1.txt
>> @@ -2,7 +2,7 @@ Toppoly TD028TTEC1 Panel
>> ========================
>>
>> Required properties:
>> -- compatible: "toppoly,td028ttec1"
>> +- compatible: "tpo,td028ttec1"
>>
>> Optional properties:
>> - label: a symbolic name for the panel
>> @@ -14,7 +14,7 @@ Example
>> -------
>>
>> lcd-panel: td028ttec1 at 0 {
>> - compatible = "toppoly,td028ttec1";
>> + compatible = "tpo,td028ttec1";
>> reg = <0>;
>> spi-max-frequency = <100000>;
>> spi-cpol;
>> diff --git a/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c b/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c
>> index 0a38a0e8c925..a0dfa14f4fab 100644
>> --- a/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c
>> +++ b/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c
>> @@ -452,6 +452,8 @@ static int td028ttec1_panel_remove(struct spi_device *spi)
>> }
>>
>> static const struct of_device_id td028ttec1_of_match[] = {
>> + { .compatible = "omapdss,tpo,td028ttec1", },
>
> Why the omapdss part?
I think because they are (currently and still) omapdrm
(omapdss) specific since SoC specific drivers for the
same panel may exist in parallel.
All panel drivers in drivers/gpu/drm/omapdrm/displays
have and need this prefix.
As far as I understand, the omapdss driver takes the
DTS compatible string, adds "omapdss," and then looks for
a panel driver to probe.
See also: Sebastian Reichel's comment to "[PATCH v3 4/4] DTS: Pandora: fix panel compatibility string"
BR,
Nikolaus Schaller
^ permalink raw reply
* [PATCH v4 2/2] DTS: Pandora: fix panel compatibility string
From: H. Nikolaus Schaller @ 2017-12-01 7:41 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1512114082.git.hns@goldelico.com>
We can remove the unnecessary "omapdss," prefix because
the omapdrm driver takes care of it when matching with
the driver table.
Signed-off-by: H. Nikolaus Schaller <hns@goldelico.com>
---
arch/arm/boot/dts/omap3-pandora-common.dtsi | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm/boot/dts/omap3-pandora-common.dtsi b/arch/arm/boot/dts/omap3-pandora-common.dtsi
index 53e007abdc71..64d967ec8c58 100644
--- a/arch/arm/boot/dts/omap3-pandora-common.dtsi
+++ b/arch/arm/boot/dts/omap3-pandora-common.dtsi
@@ -626,7 +626,7 @@
lcd: lcd at 1 {
reg = <1>; /* CS1 */
- compatible = "omapdss,tpo,td043mtea1";
+ compatible = "tpo,td043mtea1";
spi-max-frequency = <100000>;
spi-cpol;
spi-cpha;
--
2.12.2
^ permalink raw reply related
* [PATCH v4 1/2] DTS: GTA04: improve panel compatibility string
From: H. Nikolaus Schaller @ 2017-12-01 7:41 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1512114082.git.hns@goldelico.com>
Official vendor string is now "tpo" and not "toppoly".
Requires patch "omapdrm: panel: fix compatible vendor string for td028ttec1"
so that the driver understands both.
Signed-off-by: H. Nikolaus Schaller <hns@goldelico.com>
---
arch/arm/boot/dts/omap3-gta04.dtsi | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm/boot/dts/omap3-gta04.dtsi b/arch/arm/boot/dts/omap3-gta04.dtsi
index 4504908c23fe..ec27ed67a22a 100644
--- a/arch/arm/boot/dts/omap3-gta04.dtsi
+++ b/arch/arm/boot/dts/omap3-gta04.dtsi
@@ -86,7 +86,7 @@
/* lcd panel */
lcd: td028ttec1 at 0 {
- compatible = "toppoly,td028ttec1";
+ compatible = "tpo,td028ttec1";
reg = <0>;
spi-max-frequency = <100000>;
spi-cpol;
--
2.12.2
^ permalink raw reply related
* [PATCH v4 0/2] Fixes for omapdrm on OpenPandora and GTA04
From: H. Nikolaus Schaller @ 2017-12-01 7:41 UTC (permalink / raw)
To: linux-arm-kernel
Changes V4:
* removed already accepted panel driver patches
* reworded commit subject to clarify
2017-11-28 16:49:00: Changes V3:
* stay compatible with old DTB files which still use "toppoly" (suggested by Tomi Valkeinen)
* replaced MODULE_ALIAS entries by MODULE_DEVICE_TABLE (suggested by Andrew F. Davis)
* removed DSI VDDS patch as it has already been accepted
2017-11-16 09:50:22: Changes V2:
* replaced patch to fix DSI VDDS for OMAP3 by equivalent patch from Laurent Pinchart
* keep previous compatibility option in panel driver to handle older device tree binaries
2017-11-08 22:09:36:
This patch set fixes vendor names of the panels
and fixes a problem on omapdrm with enabling
VDD_DSI for OMAP3 which is needed for displaying
the Red and Green channel on OMAP3530 (Pandora).
H. Nikolaus Schaller (2):
DTS: GTA04: improve panel compatibility string
DTS: Pandora: fix panel compatibility string
arch/arm/boot/dts/omap3-gta04.dtsi | 2 +-
arch/arm/boot/dts/omap3-pandora-common.dtsi | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
--
2.12.2
^ permalink raw reply
* [PATCH v3 4/4] DTS: Pandora: fix panel compatibility string
From: H. Nikolaus Schaller @ 2017-12-01 7:41 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171130152430.GM28152@atomide.com>
> Am 30.11.2017 um 16:24 schrieb Tony Lindgren <tony@atomide.com>:
>
> * H. Nikolaus Schaller <hns@goldelico.com> [171128 18:35]:
>> Hi,
>>
>>> Am 28.11.2017 um 17:18 schrieb Tony Lindgren <tony@atomide.com>:
>>>
>>> * H. Nikolaus Schaller <hns@goldelico.com> [171128 16:17]:
>>>> Hi Tony,
>>>>
>>>>> Am 28.11.2017 um 17:04 schrieb Tony Lindgren <tony@atomide.com>:
>>>>>
>>>>> * H. Nikolaus Schaller <hns@goldelico.com> [171128 15:52]:
>>>>>> We can remove the unnecessary "omapdss," prefix because
>>>>>> the omapdrm driver takes care of it when matching with
>>>>>> the driver table.
>>>>>
>>>>> So is this needed as a fix or is this another clean-up?
>>>>>
>>>>> So is this is really needed as a fix?
>>>>
>>>> Hm. How do you differentiate between "fix" and "cleanup"?
>>>> Maybe it is more a wording than a content issue...
>>>>
>>>> For me it is a "fix" because it is semantically wrong to have
>>>> a prefix where it is not needed. And "fixing" it changes the
>>>> compiler output by 8 bytes.
>>>
>>> How about let's call it a "typo fix" then? :)
>>
>> Well, it is not really a typo.
>
> Well what if the stable people pick it into earlier stable series
> based on the word fix in the subject? That has happened before.
Well, that may happen but IMHO *every* such backport must be checked
for reasonability and compatibility and sometimes even modified to apply.
And I think the author of the original patch receives a notification
from the stable maintainers and can then veto.
For Example I received "[PATCH 4.7 118/186] w1:omap_hdq: fix regression"
"4.7-stable review patch. If anyone has any objections, please let me know."
If that process still fails, we simply have to revert it... Has also
happened before. So it will not be end of mankind :)
>
> I suggest you update the dts patches to use wording like
> "update compatible to use new naming" or something similar.
I have applied s/fix/improve/ for patch 3/4 and left 4/4 as
suggested by Sebastian since it is really a strongly suggested
correction.
Since Tomi has already accepted the underlaying driver patch,
[PATCH v4] will only have the remaining DTS patches.
BR and thanks,
Nikolaus
^ permalink raw reply
* SCPI regressions in v4.15-rc1 on Amlogic SoCs.
From: Heiner Kallweit @ 2017-12-01 7:08 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAOi56cXCBAJO6iOONTENqGdm9kE+t4fGYgTENupzkRgHjJfykw@mail.gmail.com>
Am 01.12.2017 um 01:21 schrieb Kevin Hilman:
> Hi Sudeep,
>
> There's been a pretty major regression in v4.15-rc1 compared to v4.15
> in SCPI causing warning splats on amlogic SoCs when cpufreq starts up
> and tries to set the OPP for the first time[1].
>
Thanks for the report. Strange enough, it works perfectly fine on my
Odroid-C2, see below log part from latest next kernel.
Your log seems to indicate that due to deferred probing something is
not done in the right order.
Can you bisect the issue? I'd assume that it's commit 931cf0c53e69
("firmware: arm_scpi: pre-populate dvfs info in scpi_probe").
Rgds, Heiner
[ 0.034293] soc soc0: Amlogic Meson GXBB (S905) Revision 1f:0 (c:1) Detected
[ 0.036666] c81004c0.serial: ttyAML0 at MMIO 0xc81004c0 (irq = 13, base_baud = 1500000) is a meson_uart
[ 0.606914] console [ttyAML0] enabled
[ 0.615031] loop: module loaded
[ 0.616117] meson-gx-mmc d0074000.mmc: allocated mmc-pwrseq
[ 0.643406] ledtrig-cpu: registered to indicate activity on CPUs
[ 0.644047] meson-sm: secure-monitor enabled
[ 0.648156] hidraw: raw HID events driver (C) Jiri Kosina
[ 0.653572] platform-mhu c883c404.mailbox: Platform MHU Mailbox registered
[ 0.660439] NET: Registered protocol family 17
[ 0.665031] registered taskstats version 1
[ 0.668689] Loading compiled-in X.509 certificates
[ 0.678049] meson-gx-mmc d0072000.mmc: Got CD GPIO
[ 0.712946] scpi_protocol scpi: SCP Protocol 0.0 Firmware 0.0.0 version
[ 0.715600] cpu cpu0: bL_cpufreq_init: CPU 0 initialized
[ 0.719245] arm_big_little: bL_cpufreq_register: Registered platform driver: scpi
[ 0.727344] mmc0: new HS400 MMC card at address 0001
[ 0.729179] hctosys: unable to open rtc device (rtc0)
[ 0.729355] USB_OTG_PWR: disabling
[ 0.729358] TFLASH_VDD: disabling
[ 0.729361] TF_IO: disabling
[ 0.747230] mmcblk0: mmc0:0001 DJNB4R 116 GiB
[ 0.752588] mmcblk0boot0: mmc0:0001 DJNB4R partition 1 4.00 MiB
[ 0.757220] mmcblk0boot1: mmc0:0001 DJNB4R partition 2 4.00 MiB
[ 0.762274] mmcblk0rpmb: mmc0:0001 DJNB4R partition 3 4.00 MiB, chardev (249:0)
[ 0.770243] mmcblk0: p1
[ 0.781732] EXT4-fs (mmcblk0p1): mounted filesystem with ordered data mode. Opts: (null)
> I ran out of time to narrow it down further since there have been
> quite a few changes since v4.14, but simply reverting
> drivers/firmware/arm_scpi.c to its v4.14 state gets things working
> again.
>
> This has been happening for awhile, and we should've caught it sooner
> in kernelCI.org, however this warning splat still allows the kernel to
> finish booting, so it still resulted in a PASS for the boot test.
> That combined with the fact that we've been tracking some other
> regressions, we didn't notice it until now.
>
> Also, is this the expected result for the pre-1.0 firmware:
>
> scpi_protocol scpi: SCP Protocol 0.0 Firmware 0.0.0 version
>
> Kevin
>
> [1] Here are a few boot logs from v4.15-rc1 with the splat:
>
> https://storage.kernelci.org/mainline/master/v4.15-rc1/arm64/defconfig/lab-baylibre-seattle/boot-meson-gxl-s905x-khadas-vim.html
>
> https://storage.kernelci.org/mainline/master/v4.15-rc1/arm64/defconfig/lab-baylibre-seattle/boot-meson-gxbb-p200.html
>
> https://storage.kernelci.org/mainline/master/v4.15-rc1/arm64/defconfig/lab-baylibre-seattle/boot-meson-gxl-s905d-p230.html
>
^ permalink raw reply
* [PATCH] bus: simple-pm-bus: convert bool SIMPLE_PM_BUS to tristate
From: Simon Horman @ 2017-12-01 7:02 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1512043020-23452-1-git-send-email-geert+renesas@glider.be>
On Thu, Nov 30, 2017 at 12:57:00PM +0100, Geert Uytterhoeven wrote:
> From: Paul Gortmaker <paul.gortmaker@windriver.com>
>
> The Kconfig currently controlling compilation of this code is:
>
> config SIMPLE_PM_BUS
> bool "Simple Power-Managed Bus Driver"
>
> ...meaning that it currently is not being built as a module by anyone.
>
> In removing the orphaned modular support in a previous patch set,
> Geert indicated he'd rather see this code converted to tristate.
>
> I normally don't do that because it extends functionality that I
> can't easily run time test or even know if the use case makes sense,
> but since in this case the author has nominated it as such, we do
> the conversion here.
>
> Note that doesn't change the lack of run time testing ; this change
> is only tested for sucessful compile and modpost.
>
> [geert: Ethernet is probed successfully on sh73a0/kzm9g after
> insmodding simple-pm-bus.ko]
>
> Cc: Kevin Hilman <khilman@linaro.org>
> Cc: Simon Horman <horms+renesas@verge.net.au>
> Cc: linux-arm-kernel at lists.infradead.org
> Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
> Tested-by: Geert Uytterhoeven <geert+renesas@glider.be>
> Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Acked-by: Simon Horman <horms+renesas@verge.net.au>
> ---
> drivers/bus/Kconfig | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig
> index dc7b3c7b7d42fd09..57e011d36a79fce3 100644
> --- a/drivers/bus/Kconfig
> +++ b/drivers/bus/Kconfig
> @@ -120,7 +120,7 @@ config QCOM_EBI2
> SRAM, ethernet adapters, FPGAs and LCD displays.
>
> config SIMPLE_PM_BUS
> - bool "Simple Power-Managed Bus Driver"
> + tristate "Simple Power-Managed Bus Driver"
> depends on OF && PM
> help
> Driver for transparent busses that don't need a real driver, but
> --
> 2.7.4
>
^ permalink raw reply
* [PATCH 4/4] arm: dts: imx28: Device tree cleanup
From: venkataravi.e at techveda.org @ 2017-12-01 6:38 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1512110311-15788-1-git-send-email-venkataravi.e@techveda.org>
From: Ravi Eluri <venkataravi.e@techveda.org>
Cleaned up device tree.
Signed-off-by: Ravi Eluri <venkataravi.e@techveda.org>
Signed-off-by: Suniel Mahesh <sunil.m@techveda.org>
---
Note:
- This is the fourth patch of the four patch series.
- Patch was compile tested and built(ARCH=arm, imx28) on linux-next
(latest).
- No build issues reported.
- Please discard this changeset, if this is not making any better.
---
arch/arm/boot/dts/imx28-evk.dts | 448 ++++++++++++++++++++--------------------
1 file changed, 224 insertions(+), 224 deletions(-)
diff --git a/arch/arm/boot/dts/imx28-evk.dts b/arch/arm/boot/dts/imx28-evk.dts
index 9d74486..eb683264 100644
--- a/arch/arm/boot/dts/imx28-evk.dts
+++ b/arch/arm/boot/dts/imx28-evk.dts
@@ -121,249 +121,249 @@
};
};
- &gpmi {
- pinctrl-names = "default";
- pinctrl-0 = <&gpmi_pins_a &gpmi_status_cfg
- &gpmi_pins_evk>;
- status = "okay";
- };
+&gpmi {
+ pinctrl-names = "default";
+ pinctrl-0 = <&gpmi_pins_a &gpmi_status_cfg
+ &gpmi_pins_evk>;
+ status = "okay";
+};
- &ssp0 {
- compatible = "fsl,imx28-mmc";
- pinctrl-names = "default";
- pinctrl-0 = <&mmc0_8bit_pins_a
- &mmc0_cd_cfg &mmc0_sck_cfg>;
- bus-width = <8>;
- wp-gpios = <&gpio2 12 0>;
- vmmc-supply = <®_vddio_sd0>;
- status = "okay";
- };
+&ssp0 {
+ compatible = "fsl,imx28-mmc";
+ pinctrl-names = "default";
+ pinctrl-0 = <&mmc0_8bit_pins_a
+ &mmc0_cd_cfg &mmc0_sck_cfg>;
+ bus-width = <8>;
+ wp-gpios = <&gpio2 12 0>;
+ vmmc-supply = <®_vddio_sd0>;
+ status = "okay";
+};
- &ssp1 {
- compatible = "fsl,imx28-mmc";
- bus-width = <8>;
- wp-gpios = <&gpio0 28 0>;
- };
+&ssp1 {
+ compatible = "fsl,imx28-mmc";
+ bus-width = <8>;
+ wp-gpios = <&gpio0 28 0>;
+};
- &ssp2 {
- #address-cells = <1>;
- #size-cells = <0>;
- compatible = "fsl,imx28-spi";
- pinctrl-names = "default";
- pinctrl-0 = <&spi2_pins_a>;
- status = "okay";
-
- flash: m25p80 at 0 {
- #address-cells = <1>;
- #size-cells = <1>;
- compatible = "sst,sst25vf016b", "jedec,spi-nor";
- spi-max-frequency = <40000000>;
- reg = <0>;
- };
- };
+&ssp2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx28-spi";
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi2_pins_a>;
+ status = "okay";
- &pinctrl {
- pinctrl-names = "default";
- pinctrl-0 = <&hog_pins_a>;
-
- hog_pins_a: hog at 0 {
- reg = <0>;
- fsl,pinmux-ids = <
- MX28_PAD_SSP1_CMD__GPIO_2_13
- MX28_PAD_SSP1_DATA3__GPIO_2_15
- MX28_PAD_ENET0_RX_CLK__GPIO_4_13
- MX28_PAD_SSP1_SCK__GPIO_2_12
- MX28_PAD_PWM3__GPIO_3_28
- MX28_PAD_LCD_RESET__GPIO_3_30
- MX28_PAD_AUART2_RX__GPIO_3_8
- MX28_PAD_AUART2_TX__GPIO_3_9
- >;
- fsl,drive-strength = <MXS_DRIVE_4mA>;
- fsl,voltage = <MXS_VOLTAGE_HIGH>;
- fsl,pull-up = <MXS_PULL_DISABLE>;
- };
-
- led_pin_gpio3_5: led_gpio3_5 at 0 {
- reg = <0>;
- fsl,pinmux-ids = <
- MX28_PAD_AUART1_TX__GPIO_3_5
- >;
- fsl,drive-strength = <MXS_DRIVE_4mA>;
- fsl,voltage = <MXS_VOLTAGE_HIGH>;
- fsl,pull-up = <MXS_PULL_DISABLE>;
- };
-
- gpmi_pins_evk: gpmi-nand-evk at 0 {
- reg = <0>;
- fsl,pinmux-ids = <
- MX28_PAD_GPMI_CE1N__GPMI_CE1N
- MX28_PAD_GPMI_RDY1__GPMI_READY1
- >;
- fsl,drive-strength = <MXS_DRIVE_4mA>;
- fsl,voltage = <MXS_VOLTAGE_HIGH>;
- fsl,pull-up = <MXS_PULL_DISABLE>;
- };
-
- lcdif_pins_evk: lcdif-evk at 0 {
- reg = <0>;
- fsl,pinmux-ids = <
- MX28_PAD_LCD_RD_E__LCD_VSYNC
- MX28_PAD_LCD_WR_RWN__LCD_HSYNC
- MX28_PAD_LCD_RS__LCD_DOTCLK
- MX28_PAD_LCD_CS__LCD_ENABLE
- >;
- fsl,drive-strength = <MXS_DRIVE_4mA>;
- fsl,voltage = <MXS_VOLTAGE_HIGH>;
- fsl,pull-up = <MXS_PULL_DISABLE>;
- };
- };
+ flash: m25p80 at 0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "sst,sst25vf016b", "jedec,spi-nor";
+ spi-max-frequency = <40000000>;
+ reg = <0>;
+ };
+};
- &lcdif {
- pinctrl-names = "default";
- pinctrl-0 = <&lcdif_24bit_pins_a
- &lcdif_pins_evk>;
- lcd-supply = <®_lcd_3v3>;
- display = <&display0>;
- status = "okay";
-
- display0: display0 {
- bits-per-pixel = <32>;
- bus-width = <24>;
-
- display-timings {
- native-mode = <&timing0>;
- timing0: timing0 {
- clock-frequency = <33500000>;
- hactive = <800>;
- vactive = <480>;
- hback-porch = <89>;
- hfront-porch = <164>;
- vback-porch = <23>;
- vfront-porch = <10>;
- hsync-len = <10>;
- vsync-len = <10>;
- hsync-active = <0>;
- vsync-active = <0>;
- de-active = <1>;
- pixelclk-active = <0>;
- };
- };
- };
- };
+&pinctrl {
+ pinctrl-names = "default";
+ pinctrl-0 = <&hog_pins_a>;
+
+ hog_pins_a: hog at 0 {
+ reg = <0>;
+ fsl,pinmux-ids = <
+ MX28_PAD_SSP1_CMD__GPIO_2_13
+ MX28_PAD_SSP1_DATA3__GPIO_2_15
+ MX28_PAD_ENET0_RX_CLK__GPIO_4_13
+ MX28_PAD_SSP1_SCK__GPIO_2_12
+ MX28_PAD_PWM3__GPIO_3_28
+ MX28_PAD_LCD_RESET__GPIO_3_30
+ MX28_PAD_AUART2_RX__GPIO_3_8
+ MX28_PAD_AUART2_TX__GPIO_3_9
+ >;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
+ };
- &can0 {
- pinctrl-names = "default";
- pinctrl-0 = <&can0_pins_a>;
- xceiver-supply = <®_can_3v3>;
- status = "okay";
- };
+ led_pin_gpio3_5: led_gpio3_5 at 0 {
+ reg = <0>;
+ fsl,pinmux-ids = <
+ MX28_PAD_AUART1_TX__GPIO_3_5
+ >;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
+ };
- &can1 {
- pinctrl-names = "default";
- pinctrl-0 = <&can1_pins_a>;
- xceiver-supply = <®_can_3v3>;
- status = "okay";
- };
+ gpmi_pins_evk: gpmi-nand-evk at 0 {
+ reg = <0>;
+ fsl,pinmux-ids = <
+ MX28_PAD_GPMI_CE1N__GPMI_CE1N
+ MX28_PAD_GPMI_RDY1__GPMI_READY1
+ >;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
+ };
- &saif0 {
- pinctrl-names = "default";
- pinctrl-0 = <&saif0_pins_a>;
- status = "okay";
- };
+ lcdif_pins_evk: lcdif-evk at 0 {
+ reg = <0>;
+ fsl,pinmux-ids = <
+ MX28_PAD_LCD_RD_E__LCD_VSYNC
+ MX28_PAD_LCD_WR_RWN__LCD_HSYNC
+ MX28_PAD_LCD_RS__LCD_DOTCLK
+ MX28_PAD_LCD_CS__LCD_ENABLE
+ >;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
+ };
+};
- &saif1 {
- pinctrl-names = "default";
- pinctrl-0 = <&saif1_pins_a>;
- fsl,saif-master = <&saif0>;
- status = "okay";
+&lcdif {
+ pinctrl-names = "default";
+ pinctrl-0 = <&lcdif_24bit_pins_a
+ &lcdif_pins_evk>;
+ lcd-supply = <®_lcd_3v3>;
+ display = <&display0>;
+ status = "okay";
+
+ display0: display0 {
+ bits-per-pixel = <32>;
+ bus-width = <24>;
+
+ display-timings {
+ native-mode = <&timing0>;
+ timing0: timing0 {
+ clock-frequency = <33500000>;
+ hactive = <800>;
+ vactive = <480>;
+ hback-porch = <89>;
+ hfront-porch = <164>;
+ vback-porch = <23>;
+ vfront-porch = <10>;
+ hsync-len = <10>;
+ vsync-len = <10>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ de-active = <1>;
+ pixelclk-active = <0>;
};
+ };
+ };
+};
- &lradc {
- status = "okay";
- fsl,lradc-touchscreen-wires = <4>;
- fsl,ave-ctrl = <4>;
- fsl,ave-delay = <2>;
- fsl,settling = <10>;
- };
+&can0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&can0_pins_a>;
+ xceiver-supply = <®_can_3v3>;
+ status = "okay";
+};
- &i2c0 {
- pinctrl-names = "default";
- pinctrl-0 = <&i2c0_pins_a>;
- status = "okay";
-
- sgtl5000: codec at a {
- compatible = "fsl,sgtl5000";
- reg = <0x0a>;
- VDDA-supply = <®_3p3v>;
- VDDIO-supply = <®_3p3v>;
- clocks = <&saif0>;
- };
-
- at24 at 51 {
- compatible = "atmel,24c32";
- pagesize = <32>;
- reg = <0x51>;
- };
- };
+&can1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&can1_pins_a>;
+ xceiver-supply = <®_can_3v3>;
+ status = "okay";
+};
- &pwm {
- pinctrl-names = "default";
- pinctrl-0 = <&pwm2_pins_a>;
- status = "okay";
- };
+&saif0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&saif0_pins_a>;
+ status = "okay";
+};
- &duart {
- pinctrl-names = "default";
- pinctrl-0 = <&duart_pins_a>;
- status = "okay";
- };
+&saif1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&saif1_pins_a>;
+ fsl,saif-master = <&saif0>;
+ status = "okay";
+};
- &auart0 {
- pinctrl-names = "default";
- pinctrl-0 = <&auart0_pins_a>;
- uart-has-rtscts;
- status = "okay";
- };
+&lradc {
+ status = "okay";
+ fsl,lradc-touchscreen-wires = <4>;
+ fsl,ave-ctrl = <4>;
+ fsl,ave-delay = <2>;
+ fsl,settling = <10>;
+};
- &auart3 {
- pinctrl-names = "default";
- pinctrl-0 = <&auart3_pins_a>;
- status = "okay";
- };
+&i2c0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c0_pins_a>;
+ status = "okay";
+
+ sgtl5000: codec at a {
+ compatible = "fsl,sgtl5000";
+ reg = <0x0a>;
+ VDDA-supply = <®_3p3v>;
+ VDDIO-supply = <®_3p3v>;
+ clocks = <&saif0>;
+ };
- &usbphy0 {
- status = "okay";
- };
+ at24 at 51 {
+ compatible = "atmel,24c32";
+ pagesize = <32>;
+ reg = <0x51>;
+ };
+};
- &usbphy1 {
- status = "okay";
- };
+&pwm {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pwm2_pins_a>;
+ status = "okay";
+};
- &usb0 {
- pinctrl-names = "default";
- pinctrl-0 = <&usb0_id_pins_a>;
- vbus-supply = <®_usb0_vbus>;
- status = "okay";
- };
+&duart {
+ pinctrl-names = "default";
+ pinctrl-0 = <&duart_pins_a>;
+ status = "okay";
+};
- &usb1 {
- vbus-supply = <®_usb1_vbus>;
- status = "okay";
- };
+&auart0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&auart0_pins_a>;
+ uart-has-rtscts;
+ status = "okay";
+};
- &mac0 {
- phy-mode = "rmii";
- pinctrl-names = "default";
- pinctrl-0 = <&mac0_pins_a>;
- phy-supply = <®_fec_3v3>;
- phy-reset-gpios = <&gpio4 13 GPIO_ACTIVE_LOW>;
- phy-reset-duration = <100>;
- status = "okay";
- };
+&auart3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&auart3_pins_a>;
+ status = "okay";
+};
- &mac1 {
- phy-mode = "rmii";
- pinctrl-names = "default";
- pinctrl-0 = <&mac1_pins_a>;
- status = "okay";
- };
+&usbphy0 {
+ status = "okay";
+};
+
+&usbphy1 {
+ status = "okay";
+};
+
+&usb0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&usb0_id_pins_a>;
+ vbus-supply = <®_usb0_vbus>;
+ status = "okay";
+};
+
+&usb1 {
+ vbus-supply = <®_usb1_vbus>;
+ status = "okay";
+};
+
+&mac0 {
+ phy-mode = "rmii";
+ pinctrl-names = "default";
+ pinctrl-0 = <&mac0_pins_a>;
+ phy-supply = <®_fec_3v3>;
+ phy-reset-gpios = <&gpio4 13 GPIO_ACTIVE_LOW>;
+ phy-reset-duration = <100>;
+ status = "okay";
+};
+
+&mac1 {
+ phy-mode = "rmii";
+ pinctrl-names = "default";
+ pinctrl-0 = <&mac1_pins_a>;
+ status = "okay";
+};
--
1.9.1
^ permalink raw reply related
* [PATCH 3/4] arm: dts: imx28: Rearrange nodes for better readability
From: venkataravi.e at techveda.org @ 2017-12-01 6:38 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1512110311-15788-1-git-send-email-venkataravi.e@techveda.org>
From: Ravi Eluri <venkataravi.e@techveda.org>
Moved regulator, sound, leds, backlight nodes to the top of the
device tree, cleaned up for better readability.
Signed-off-by: Ravi Eluri <venkataravi.e@techveda.org>
Signed-off-by: Suniel Mahesh <sunil.m@techveda.org>
---
Note:
- This is the third patch of the four patch series.
- Patch was compile tested and built(ARCH=arm, imx28) on linux-next
(latest).
- No build issues reported.
- Please discard this changeset, if this is not making any better.
---
arch/arm/boot/dts/imx28-evk.dts | 203 ++++++++++++++++++++--------------------
1 file changed, 101 insertions(+), 102 deletions(-)
diff --git a/arch/arm/boot/dts/imx28-evk.dts b/arch/arm/boot/dts/imx28-evk.dts
index 28564864..9d74486 100644
--- a/arch/arm/boot/dts/imx28-evk.dts
+++ b/arch/arm/boot/dts/imx28-evk.dts
@@ -20,6 +20,107 @@
reg = <0x40000000 0x08000000>;
};
+ regulators {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg_3p3v: regulator at 0 {
+ compatible = "regulator-fixed";
+ reg = <0>;
+ regulator-name = "3P3V";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ reg_vddio_sd0: regulator at 1 {
+ compatible = "regulator-fixed";
+ reg = <1>;
+ regulator-name = "vddio-sd0";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&gpio3 28 0>;
+ };
+
+ reg_fec_3v3: regulator at 2 {
+ compatible = "regulator-fixed";
+ reg = <2>;
+ regulator-name = "fec-3v3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&gpio2 15 0>;
+ };
+
+ reg_usb0_vbus: regulator at 3 {
+ compatible = "regulator-fixed";
+ reg = <3>;
+ regulator-name = "usb0_vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&gpio3 9 0>;
+ enable-active-high;
+ };
+
+ reg_usb1_vbus: regulator at 4 {
+ compatible = "regulator-fixed";
+ reg = <4>;
+ regulator-name = "usb1_vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&gpio3 8 0>;
+ enable-active-high;
+ };
+
+ reg_lcd_3v3: regulator at 5 {
+ compatible = "regulator-fixed";
+ reg = <5>;
+ regulator-name = "lcd-3v3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&gpio3 30 0>;
+ enable-active-high;
+ };
+
+ reg_can_3v3: regulator at 6 {
+ compatible = "regulator-fixed";
+ reg = <6>;
+ regulator-name = "can-3v3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&gpio2 13 0>;
+ enable-active-high;
+ };
+ };
+
+ sound {
+ compatible = "fsl,imx28-evk-sgtl5000",
+ "fsl,mxs-audio-sgtl5000";
+ model = "imx28-evk-sgtl5000";
+ saif-controllers = <&saif0 &saif1>;
+ audio-codec = <&sgtl5000>;
+ };
+
+ leds {
+ compatible = "gpio-leds";
+ pinctrl-names = "default";
+ pinctrl-0 = <&led_pin_gpio3_5>;
+
+ user {
+ label = "Heartbeat";
+ gpios = <&gpio3 5 0>;
+ linux,default-trigger = "heartbeat";
+ };
+ };
+
+ backlight {
+ compatible = "pwm-backlight";
+ pwms = <&pwm 2 5000000>;
+ brightness-levels = <0 4 8 16 32 64 128 255>;
+ default-brightness-level = <6>;
+ };
+};
+
&gpmi {
pinctrl-names = "default";
pinctrl-0 = <&gpmi_pins_a &gpmi_status_cfg
@@ -266,105 +367,3 @@
pinctrl-0 = <&mac1_pins_a>;
status = "okay";
};
-
- regulators {
- compatible = "simple-bus";
- #address-cells = <1>;
- #size-cells = <0>;
-
- reg_3p3v: regulator at 0 {
- compatible = "regulator-fixed";
- reg = <0>;
- regulator-name = "3P3V";
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
- regulator-always-on;
- };
-
- reg_vddio_sd0: regulator at 1 {
- compatible = "regulator-fixed";
- reg = <1>;
- regulator-name = "vddio-sd0";
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
- gpio = <&gpio3 28 0>;
- };
-
- reg_fec_3v3: regulator at 2 {
- compatible = "regulator-fixed";
- reg = <2>;
- regulator-name = "fec-3v3";
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
- gpio = <&gpio2 15 0>;
- };
-
- reg_usb0_vbus: regulator at 3 {
- compatible = "regulator-fixed";
- reg = <3>;
- regulator-name = "usb0_vbus";
- regulator-min-microvolt = <5000000>;
- regulator-max-microvolt = <5000000>;
- gpio = <&gpio3 9 0>;
- enable-active-high;
- };
-
- reg_usb1_vbus: regulator at 4 {
- compatible = "regulator-fixed";
- reg = <4>;
- regulator-name = "usb1_vbus";
- regulator-min-microvolt = <5000000>;
- regulator-max-microvolt = <5000000>;
- gpio = <&gpio3 8 0>;
- enable-active-high;
- };
-
- reg_lcd_3v3: regulator at 5 {
- compatible = "regulator-fixed";
- reg = <5>;
- regulator-name = "lcd-3v3";
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
- gpio = <&gpio3 30 0>;
- enable-active-high;
- };
-
- reg_can_3v3: regulator at 6 {
- compatible = "regulator-fixed";
- reg = <6>;
- regulator-name = "can-3v3";
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
- gpio = <&gpio2 13 0>;
- enable-active-high;
- };
-
- };
-
- sound {
- compatible = "fsl,imx28-evk-sgtl5000",
- "fsl,mxs-audio-sgtl5000";
- model = "imx28-evk-sgtl5000";
- saif-controllers = <&saif0 &saif1>;
- audio-codec = <&sgtl5000>;
- };
-
- leds {
- compatible = "gpio-leds";
- pinctrl-names = "default";
- pinctrl-0 = <&led_pin_gpio3_5>;
-
- user {
- label = "Heartbeat";
- gpios = <&gpio3 5 0>;
- linux,default-trigger = "heartbeat";
- };
- };
-
- backlight {
- compatible = "pwm-backlight";
- pwms = <&pwm 2 5000000>;
- brightness-levels = <0 4 8 16 32 64 128 255>;
- default-brightness-level = <6>;
- };
-};
--
1.9.1
^ permalink raw reply related
* [PATCH 2/4] arm: dts: imx28: Remove system bus unit addresses
From: venkataravi.e at techveda.org @ 2017-12-01 6:38 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1512110311-15788-1-git-send-email-venkataravi.e@techveda.org>
From: Ravi Eluri <venkataravi.e@techveda.org>
Unit addresses for the system buses of imx28 are defined in
the corresponding dtsi file. Any peripheral node on APBH, APBX
and AHB busses can be accessed via phandle. Removed duplicate
system bus unit address entries, this makes the DT more robust
and readable.
Signed-off-by: Ravi Eluri <venkataravi.e@techveda.org>
Signed-off-by: Suniel Mahesh <sunil.m@techveda.org>
---
Note:
- This is the second patch of the four patch series.
- Patch was compile tested and built(ARCH=arm, imx28) on linux-next
(latest).
- No build issues reported.
- Please discard this changeset, if this is not making any better.
---
arch/arm/boot/dts/imx28-evk.dts | 8 --------
1 file changed, 8 deletions(-)
diff --git a/arch/arm/boot/dts/imx28-evk.dts b/arch/arm/boot/dts/imx28-evk.dts
index 21ac4fa..28564864 100644
--- a/arch/arm/boot/dts/imx28-evk.dts
+++ b/arch/arm/boot/dts/imx28-evk.dts
@@ -20,8 +20,6 @@
reg = <0x40000000 0x08000000>;
};
- apb at 80000000 {
- apbh at 80000000 {
&gpmi {
pinctrl-names = "default";
pinctrl-0 = <&gpmi_pins_a &gpmi_status_cfg
@@ -165,9 +163,7 @@
xceiver-supply = <®_can_3v3>;
status = "okay";
};
- };
- apbx at 80040000 {
&saif0 {
pinctrl-names = "default";
pinctrl-0 = <&saif0_pins_a>;
@@ -241,10 +237,7 @@
&usbphy1 {
status = "okay";
};
- };
- };
- ahb at 80080000 {
&usb0 {
pinctrl-names = "default";
pinctrl-0 = <&usb0_id_pins_a>;
@@ -273,7 +266,6 @@
pinctrl-0 = <&mac1_pins_a>;
status = "okay";
};
- };
regulators {
compatible = "simple-bus";
--
1.9.1
^ permalink raw reply related
* [PATCH 1/4] arm: dts: imx28: Use phandles instead of unit addresses
From: venkataravi.e at techveda.org @ 2017-12-01 6:38 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1512110311-15788-1-git-send-email-venkataravi.e@techveda.org>
From: Ravi Eluri <venkataravi.e@techveda.org>
Unit addresses for all peripherals of imx28 are defined in
the corresponding dtsi file, use phandles instead of unit addresses
to reference peripheral nodes in dts files. This makes the DT more
robust and readable.
Signed-off-by: Ravi Eluri <venkataravi.e@techveda.org>
Signed-off-by: Suniel Mahesh <sunil.m@techveda.org>
---
Note:
- This is the first patch of the four patch series.
- Patch was compile tested and built(ARCH=arm, imx28) on linux-next
(latest).
- No build issues reported.
- Please discard this changeset, if this is not making any better.
---
arch/arm/boot/dts/imx28-evk.dts | 44 ++++++++++++++++++++---------------------
1 file changed, 22 insertions(+), 22 deletions(-)
diff --git a/arch/arm/boot/dts/imx28-evk.dts b/arch/arm/boot/dts/imx28-evk.dts
index 7f5b804..21ac4fa 100644
--- a/arch/arm/boot/dts/imx28-evk.dts
+++ b/arch/arm/boot/dts/imx28-evk.dts
@@ -22,14 +22,14 @@
apb at 80000000 {
apbh at 80000000 {
- gpmi-nand at 8000c000 {
+ &gpmi {
pinctrl-names = "default";
pinctrl-0 = <&gpmi_pins_a &gpmi_status_cfg
&gpmi_pins_evk>;
status = "okay";
};
- ssp0: ssp at 80010000 {
+ &ssp0 {
compatible = "fsl,imx28-mmc";
pinctrl-names = "default";
pinctrl-0 = <&mmc0_8bit_pins_a
@@ -40,13 +40,13 @@
status = "okay";
};
- ssp1: ssp@80012000 {
+ &ssp1 {
compatible = "fsl,imx28-mmc";
bus-width = <8>;
wp-gpios = <&gpio0 28 0>;
};
- ssp2: ssp at 80014000 {
+ &ssp2 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "fsl,imx28-spi";
@@ -63,7 +63,7 @@
};
};
- pinctrl at 80018000 {
+ &pinctrl {
pinctrl-names = "default";
pinctrl-0 = <&hog_pins_a>;
@@ -119,7 +119,7 @@
};
};
- lcdif at 80030000 {
+ &lcdif {
pinctrl-names = "default";
pinctrl-0 = <&lcdif_24bit_pins_a
&lcdif_pins_evk>;
@@ -152,14 +152,14 @@
};
};
- can0: can at 80032000 {
+ &can0 {
pinctrl-names = "default";
pinctrl-0 = <&can0_pins_a>;
xceiver-supply = <®_can_3v3>;
status = "okay";
};
- can1: can at 80034000 {
+ &can1 {
pinctrl-names = "default";
pinctrl-0 = <&can1_pins_a>;
xceiver-supply = <®_can_3v3>;
@@ -168,20 +168,20 @@
};
apbx at 80040000 {
- saif0: saif at 80042000 {
+ &saif0 {
pinctrl-names = "default";
pinctrl-0 = <&saif0_pins_a>;
status = "okay";
};
- saif1: saif at 80046000 {
+ &saif1 {
pinctrl-names = "default";
pinctrl-0 = <&saif1_pins_a>;
fsl,saif-master = <&saif0>;
status = "okay";
};
- lradc at 80050000 {
+ &lradc {
status = "okay";
fsl,lradc-touchscreen-wires = <4>;
fsl,ave-ctrl = <4>;
@@ -189,7 +189,7 @@
fsl,settling = <10>;
};
- i2c0: i2c at 80058000 {
+ &i2c0 {
pinctrl-names = "default";
pinctrl-0 = <&i2c0_pins_a>;
status = "okay";
@@ -209,55 +209,55 @@
};
};
- pwm: pwm at 80064000 {
+ &pwm {
pinctrl-names = "default";
pinctrl-0 = <&pwm2_pins_a>;
status = "okay";
};
- duart: serial at 80074000 {
+ &duart {
pinctrl-names = "default";
pinctrl-0 = <&duart_pins_a>;
status = "okay";
};
- auart0: serial at 8006a000 {
+ &auart0 {
pinctrl-names = "default";
pinctrl-0 = <&auart0_pins_a>;
uart-has-rtscts;
status = "okay";
};
- auart3: serial at 80070000 {
+ &auart3 {
pinctrl-names = "default";
pinctrl-0 = <&auart3_pins_a>;
status = "okay";
};
- usbphy0: usbphy at 8007c000 {
+ &usbphy0 {
status = "okay";
};
- usbphy1: usbphy at 8007e000 {
+ &usbphy1 {
status = "okay";
};
};
};
ahb at 80080000 {
- usb0: usb at 80080000 {
+ &usb0 {
pinctrl-names = "default";
pinctrl-0 = <&usb0_id_pins_a>;
vbus-supply = <®_usb0_vbus>;
status = "okay";
};
- usb1: usb at 80090000 {
+ &usb1 {
vbus-supply = <®_usb1_vbus>;
status = "okay";
};
- mac0: ethernet at 800f0000 {
+ &mac0 {
phy-mode = "rmii";
pinctrl-names = "default";
pinctrl-0 = <&mac0_pins_a>;
@@ -267,7 +267,7 @@
status = "okay";
};
- mac1: ethernet at 800f4000 {
+ &mac1 {
phy-mode = "rmii";
pinctrl-names = "default";
pinctrl-0 = <&mac1_pins_a>;
--
1.9.1
^ permalink raw reply related
* [PATCH 0/4] arm: dts: imx28: imx28-evk device tree cleanup
From: venkataravi.e at techveda.org @ 2017-12-01 6:38 UTC (permalink / raw)
To: linux-arm-kernel
From: Ravi Eluri <venkataravi.e@techveda.org>
Removed lot of redundant device tree syntax from imx28-evk device tree
to make it more robust and readable.
Total four changesets and are described as follows:
Changeset 1 removes unit addresses for all peripherals of imx28 in
imx28-evk DT as they are already defined in the corresponding dtsi file.
Make use of phandles reference peripheral nodes in dts files.
Changeset 2 removes unit addresses for the system buses of imx28 as they
are already defined in the corresponding dtsi file.
Changeset 3 rearranges nodes for better readability.
Changeset 4 does DT cleanup (whitespaces, tabs ...)
Note:
- Changesets were compile tested and built(ARCH=arm, imx28) on linux-next
(latest).
- No build issues reported.
- Please discard this changesets, if this is not making any better."
Ravi Eluri (4):
arm: dts: imx28: Use phandles instead of unit addresses
arm: dts: imx28: Remove system bus unit addresses
arm: dts: imx28: Rearrange nodes for better readability
arm: dts: imx28: Device tree cleanup
arch/arm/boot/dts/imx28-evk.dts | 503 ++++++++++++++++++++--------------------
1 file changed, 247 insertions(+), 256 deletions(-)
--
1.9.1
^ permalink raw reply
* [PATCH 0/4] pci-dra7xx: Fix legacy IRQ handling and errata handling
From: Vignesh R @ 2017-12-01 6:15 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171201061311.16691-1-vigneshr@ti.com>
On Friday 01 December 2017 11:43 AM, Vignesh R wrote:
> This series contains two fixes:
> 1. Make workaround for errata i870 applicable in Host mode as
> well(previously it was enabled only for EP mode) as per errata
> documentation: http://www.ti.com/lit/er/sprz429k/sprz429k.pdf
> 2. Fix problem with handling of legacy INTD interrupts.
>
> Tested on 66AK2G EVM and ICE boards
>
Oops, sorry, I meant tested on DRA74 EVM and AM572 GP EVM here.
>
> Vignesh R (4):
> pci: dwc: pci-dra7xx: Enable errata i870 for both EP and RC mode
> dt-bindings: PCI: dra7xx: Add bindings for unaligned access in host
> mode
> ARM: dts: dra7: Add DT property to allow unaligned mem access to PCIe
> RC
> PCI: dwc: pci-dra7xx: Fix legacy IRQ handling
>
> Documentation/devicetree/bindings/pci/ti-pci.txt | 5 +++++
> arch/arm/boot/dts/dra7.dtsi | 2 ++
> drivers/pci/dwc/pci-dra7xx.c | 23 ++++++++++++++---------
> 3 files changed, 21 insertions(+), 9 deletions(-)
>
--
Regards
Vignesh
^ permalink raw reply
* [PATCH 4/4] PCI: dwc: pci-dra7xx: Fix legacy IRQ handling
From: Vignesh R @ 2017-12-01 6:13 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171201061311.16691-1-vigneshr@ti.com>
Legacy INTD IRQ handling is broken on dra7xx due to fact that driver
uses hwirq in range of 1-4 for INTA, INTD whereas IRQ domain is of size
4 which is numbered 0-3. Therefore when INTD IRQ line is used with
pci-dra7xx driver following warning is seen:
WARNING: CPU: 0 PID: 1 at kernel/irq/irqdomain.c:342 irq_domain_associate+0x12c/0x1c4
error: hwirq 0x4 is too large for dummy
Fix this by using pci_irqd_intx_xlate() helper to translate the INTx 1-4
range into the 0-3 as done in other PCIe drivers.
Also, iterate over all the INTx bits and call their respective IRQ
handlers before clearing the status register.
Suggested-by: Bjorn Helgaas <bhelgaas@google.com>
Reported-by: Chris Welch <Chris.Welch@viavisolutions.com>
Signed-off-by: Vignesh R <vigneshr@ti.com>
---
drivers/pci/dwc/pci-dra7xx.c | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/drivers/pci/dwc/pci-dra7xx.c b/drivers/pci/dwc/pci-dra7xx.c
index 53f721d1cc40..59e8de34cec6 100644
--- a/drivers/pci/dwc/pci-dra7xx.c
+++ b/drivers/pci/dwc/pci-dra7xx.c
@@ -226,6 +226,7 @@ static int dra7xx_pcie_intx_map(struct irq_domain *domain, unsigned int irq,
static const struct irq_domain_ops intx_domain_ops = {
.map = dra7xx_pcie_intx_map,
+ .xlate = pci_irqd_intx_xlate,
};
static int dra7xx_pcie_init_irq_domain(struct pcie_port *pp)
@@ -256,7 +257,8 @@ static irqreturn_t dra7xx_pcie_msi_irq_handler(int irq, void *arg)
struct dra7xx_pcie *dra7xx = arg;
struct dw_pcie *pci = dra7xx->pci;
struct pcie_port *pp = &pci->pp;
- u32 reg;
+ unsigned long reg;
+ u32 virq, bit;
reg = dra7xx_pcie_readl(dra7xx, PCIECTRL_DRA7XX_CONF_IRQSTATUS_MSI);
@@ -268,8 +270,11 @@ static irqreturn_t dra7xx_pcie_msi_irq_handler(int irq, void *arg)
case INTB:
case INTC:
case INTD:
- generic_handle_irq(irq_find_mapping(dra7xx->irq_domain,
- ffs(reg)));
+ for_each_set_bit(bit, ®, PCI_NUM_INTX) {
+ virq = irq_find_mapping(dra7xx->irq_domain, bit);
+ if (virq)
+ generic_handle_irq(virq);
+ }
break;
}
--
2.15.0
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox