kernel: bump to 4.14.172 / 4.19.108

This commit is contained in:
lean 2020-03-13 12:11:40 +08:00
parent cd59b49863
commit 3bef40a0cb
33 changed files with 1232 additions and 48 deletions

View File

@ -7,12 +7,12 @@ ifdef CONFIG_TESTING_KERNEL
endif
LINUX_VERSION-4.9 = .214
LINUX_VERSION-4.14 = .171
LINUX_VERSION-4.19 = .106
LINUX_VERSION-4.14 = .172
LINUX_VERSION-4.19 = .108
LINUX_KERNEL_HASH-4.9.214 = b47f093dac7034c7c4722e80042c05e4ef53c14a4f28aa992117a127d2b1e483
LINUX_KERNEL_HASH-4.14.171 = 4fe02489e4b4a187eccf0ef87df6100534c9d485e76d876b1fa247c7635332a0
LINUX_KERNEL_HASH-4.19.106 = 63c8bd76a9b282e18112f8ff9e3fd41e3d1df9f9b7248ea1a370b05a827e9cda
LINUX_KERNEL_HASH-4.14.172 = 2318a1ab937580a079351ed20557c336a3d95b664f667b14e3ba49e3271b217a
LINUX_KERNEL_HASH-4.19.108 = 09aeeca5b08efea2f54b977b2999afb60d42f93b9f65b2b0111969f183f750a3
remove_uri_prefix=$(subst git://,,$(subst http://,,$(subst https://,,$(1))))
sanitize_uri=$(call qstrip,$(subst @,_,$(subst :,_,$(subst .,_,$(subst -,_,$(subst /,_,$(1)))))))

View File

@ -44,7 +44,7 @@ Signed-off-by: Christian Lamparter <chunkeey@googlemail.com>
#include "xhci.h"
#include "xhci-trace.h"
@@ -266,6 +268,458 @@ static void xhci_pme_acpi_rtd3_enable(st
@@ -268,6 +270,458 @@ static void xhci_pme_acpi_rtd3_enable(st
static void xhci_pme_acpi_rtd3_enable(struct pci_dev *dev) { }
#endif /* CONFIG_ACPI */
@ -503,7 +503,7 @@ Signed-off-by: Christian Lamparter <chunkeey@googlemail.com>
/* called during probe() after chip reset completes */
static int xhci_pci_setup(struct usb_hcd *hcd)
{
@@ -301,6 +755,22 @@ static int xhci_pci_probe(struct pci_dev
@@ -306,6 +760,22 @@ static int xhci_pci_probe(struct pci_dev
struct hc_driver *driver;
struct usb_hcd *hcd;
@ -526,7 +526,7 @@ Signed-off-by: Christian Lamparter <chunkeey@googlemail.com>
driver = (struct hc_driver *)id->driver_data;
/* For some HW implementation, a XHCI reset is just not enough... */
@@ -365,6 +835,16 @@ static void xhci_pci_remove(struct pci_d
@@ -367,6 +837,16 @@ static void xhci_pci_remove(struct pci_d
{
struct xhci_hcd *xhci;

View File

@ -13,7 +13,7 @@ produce a noisy warning.
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -219,7 +219,7 @@ static void xhci_pci_quirks(struct devic
@@ -221,7 +221,7 @@ static void xhci_pci_quirks(struct devic
xhci->quirks |= XHCI_TRUST_TX_LENGTH;
if (pdev->vendor == PCI_VENDOR_ID_RENESAS &&
pdev->device == 0x0015)

View File

@ -44,7 +44,7 @@ Signed-off-by: Christian Lamparter <chunkeey@googlemail.com>
#include "xhci.h"
#include "xhci-trace.h"
@@ -262,6 +264,458 @@ static void xhci_pme_acpi_rtd3_enable(st
@@ -264,6 +266,458 @@ static void xhci_pme_acpi_rtd3_enable(st
static void xhci_pme_acpi_rtd3_enable(struct pci_dev *dev) { }
#endif /* CONFIG_ACPI */
@ -503,7 +503,7 @@ Signed-off-by: Christian Lamparter <chunkeey@googlemail.com>
/* called during probe() after chip reset completes */
static int xhci_pci_setup(struct usb_hcd *hcd)
{
@@ -300,6 +754,22 @@ static int xhci_pci_probe(struct pci_dev
@@ -305,6 +759,22 @@ static int xhci_pci_probe(struct pci_dev
struct hc_driver *driver;
struct usb_hcd *hcd;
@ -526,7 +526,7 @@ Signed-off-by: Christian Lamparter <chunkeey@googlemail.com>
driver = (struct hc_driver *)id->driver_data;
/* Prevent runtime suspending between USB-2 and USB-3 initialization */
@@ -361,6 +831,16 @@ static void xhci_pci_remove(struct pci_d
@@ -363,6 +833,16 @@ static void xhci_pci_remove(struct pci_d
{
struct xhci_hcd *xhci;

View File

@ -13,7 +13,7 @@ produce a noisy warning.
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -215,6 +215,7 @@ static void xhci_pci_quirks(struct devic
@@ -217,6 +217,7 @@ static void xhci_pci_quirks(struct devic
pdev->device == 0x0015) {
xhci->quirks |= XHCI_RESET_ON_RESUME;
xhci->quirks |= XHCI_ZERO_64B_REGS;
@ -43,7 +43,7 @@ produce a noisy warning.
hcd->msi_enabled = 1;
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1876,6 +1876,7 @@ struct xhci_hcd {
@@ -1883,6 +1883,7 @@ struct xhci_hcd {
/* support xHCI 0.96 spec USB2 software LPM */
unsigned sw_lpm_support:1;
/* support xHCI 1.0 spec USB2 hardware LPM */

View File

@ -917,7 +917,7 @@ Fixes https://github.com/raspberrypi/linux/issues/2408
}
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -5222,7 +5222,7 @@ static void port_event(struct usb_hub *h
@@ -5228,7 +5228,7 @@ static void port_event(struct usb_hub *h
u16 status = 0, unused;
port_dev->over_current_count++;

View File

@ -62,8 +62,8 @@ Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
+ const struct brcmstb_thermal_of_data *socdata;
};
static void avs_tmon_get_coeffs(struct thermal_zone_device *tz, int *slope,
@@ -164,17 +171,18 @@ static inline u32 avs_tmon_temp_to_code(
/* Convert a HW code to a temperature reading (millidegree celsius) */
@@ -151,17 +158,18 @@ static inline u32 avs_tmon_temp_to_code(
static int brcmstb_get_temp(void *data, int *temp)
{
struct brcmstb_thermal_priv *priv = data;
@ -84,7 +84,7 @@ Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
t = avs_tmon_code_to_temp(priv->thermal, val);
if (t < 0)
@@ -299,13 +307,34 @@ static int brcmstb_set_trips(void *data,
@@ -286,13 +294,34 @@ static int brcmstb_set_trips(void *data,
return 0;
}
@ -121,7 +121,7 @@ Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
{},
};
MODULE_DEVICE_TABLE(of, brcmstb_thermal_id_table);
@@ -326,10 +355,27 @@ static int brcmstb_thermal_probe(struct
@@ -313,10 +342,27 @@ static int brcmstb_thermal_probe(struct
if (IS_ERR(priv->tmon_base))
return PTR_ERR(priv->tmon_base);
@ -150,7 +150,7 @@ Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
if (IS_ERR(thermal)) {
ret = PTR_ERR(thermal);
dev_err(&pdev->dev, "could not register sensor: %d\n", ret);
@@ -369,6 +415,9 @@ static int brcmstb_thermal_exit(struct p
@@ -356,6 +402,9 @@ static int brcmstb_thermal_exit(struct p
if (thermal)
thermal_zone_of_sensor_unregister(&pdev->dev, priv->thermal);

View File

@ -10,7 +10,7 @@ Signed-off-by: Phil Elwell <phil@raspberrypi.org>
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -222,6 +222,10 @@ static void xhci_pci_quirks(struct devic
@@ -224,6 +224,10 @@ static void xhci_pci_quirks(struct devic
pdev->device == 0x3432)
xhci->quirks |= XHCI_BROKEN_STREAMS;

View File

@ -23,7 +23,7 @@ Signed-off-by: Jonathan Bell <jonathan@raspberrypi.org>
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -223,8 +223,10 @@ static void xhci_pci_quirks(struct devic
@@ -225,8 +225,10 @@ static void xhci_pci_quirks(struct devic
xhci->quirks |= XHCI_BROKEN_STREAMS;
if (pdev->vendor == PCI_VENDOR_ID_VIA &&
@ -80,7 +80,7 @@ Signed-off-by: Jonathan Bell <jonathan@raspberrypi.org>
/*
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1865,6 +1865,7 @@ struct xhci_hcd {
@@ -1872,6 +1872,7 @@ struct xhci_hcd {
#define XHCI_ZERO_64B_REGS BIT_ULL(32)
#define XHCI_RESET_PLL_ON_DISCONNECT BIT_ULL(34)
#define XHCI_SNPS_BROKEN_SUSPEND BIT_ULL(35)

View File

@ -22,7 +22,7 @@ Signed-off-by: Jonathan Bell <jonathan@raspberrypi.org>
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -2495,9 +2495,11 @@ int xhci_mem_init(struct xhci_hcd *xhci,
@@ -2516,9 +2516,11 @@ int xhci_mem_init(struct xhci_hcd *xhci,
* Event ring setup: Allocate a normal ring, but also setup
* the event ring segment table (ERST). Section 4.9.3.
*/
@ -36,7 +36,7 @@ Signed-off-by: Jonathan Bell <jonathan@raspberrypi.org>
if (!xhci->event_ring)
goto fail;
if (xhci_check_trb_in_td_math(xhci) < 0)
@@ -2510,7 +2512,7 @@ int xhci_mem_init(struct xhci_hcd *xhci,
@@ -2531,7 +2533,7 @@ int xhci_mem_init(struct xhci_hcd *xhci,
/* set ERST count with the number of entries in the segment table */
val = readl(&xhci->ir_set->erst_size);
val &= ERST_SIZE_MASK;

View File

@ -127,7 +127,7 @@ it on BCM4708 family.
/*
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1865,6 +1865,7 @@ struct xhci_hcd {
@@ -1872,6 +1872,7 @@ struct xhci_hcd {
#define XHCI_ZERO_64B_REGS BIT_ULL(32)
#define XHCI_RESET_PLL_ON_DISCONNECT BIT_ULL(34)
#define XHCI_SNPS_BROKEN_SUSPEND BIT_ULL(35)

View File

@ -0,0 +1,28 @@
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
Date: Mon, 9 Mar 2020 08:30:19 +0100
Subject: [PATCH] mtd: fix calculating partition end address
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This fixes check for partitions that don't start at beginning of their
parents. Missing partition's offset in formula could result in forcing
read-only incorrectly.
Fixes: 6750f61a13a0 ("mtd: improve calculating partition boundaries when checking for alignment")
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
---
drivers/mtd/mtdpart.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -538,7 +538,7 @@ static struct mtd_part *allocate_partiti
part->name);
}
- tmp = part_absolute_offset(parent) + slave->mtd.size;
+ tmp = part_absolute_offset(parent) + slave->offset + slave->mtd.size;
remainder = do_div(tmp, wr_alignment);
if ((slave->mtd.flags & MTD_WRITEABLE) && remainder) {
slave->mtd.flags &= ~MTD_WRITEABLE;

View File

@ -0,0 +1,27 @@
From 10050a02f7d508fa88f70fcfceefbacd13488ca7 Mon Sep 17 00:00:00 2001
From: Robert Marko <robimarko@gmail.com>
Date: Mon, 23 Dec 2019 17:05:49 +0200
Subject: [PATCH] mtd: spi-nor: Add 4B_OPCODES flag to w25q256
The w25q256 supports 4-byte opcodes so lets add the flag.
Tested on OpenWrt under 4.19.82 kernel on 8devices Habanero.
Signed-off-by: Robert Marko <robimarko@gmail.com>
Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
---
drivers/mtd/spi-nor/spi-nor.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -1244,7 +1244,9 @@ static const struct flash_info spi_nor_i
{ "w25q80", INFO(0xef5014, 0, 64 * 1024, 16, SECT_4K) },
{ "w25q80bl", INFO(0xef4014, 0, 64 * 1024, 16, SECT_4K) },
{ "w25q128", INFO(0xef4018, 0, 64 * 1024, 256, SECT_4K) },
- { "w25q256", INFO(0xef4019, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+ { "w25q256", INFO(0xef4019, 0, 64 * 1024, 512,
+ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+ SPI_NOR_4B_OPCODES) },
{ "w25m512jv", INFO(0xef7119, 0, 64 * 1024, 1024,
SECT_4K | SPI_NOR_QUAD_READ | SPI_NOR_DUAL_READ) },

View File

@ -0,0 +1,136 @@
From 17abc9ec68b73ddeb262a507a62421016b9c54d5 Mon Sep 17 00:00:00 2001
From: Tomasz Duszynski <tduszyns@gmail.com>
Date: Fri, 14 Dec 2018 19:28:01 +0100
Subject: [PATCH] iio: add IIO_MASSCONCENTRATION channel type
Measuring particulate matter in ug / m3 (micro-grams per cubic meter)
is de facto standard. Existing air quality sensors usually follow
this convention and are capable of returning measurements using
this unit.
IIO currently does not offer suitable channel type for this
type of measurements hence this patch adds this.
In addition, extra modifiers are introduced used for distinguishing
between fine pm1, pm2p5 and coarse pm4, pm10 particle measurements, i.e
IIO_MOD_PM1, IIO_MOD_PM25 and IIO_MOD_PM4, IIO_MOD_PM10.
pmX consists of particles with aerodynamic diameter less or equal to
X micrometers.
Signed-off-by: Tomasz Duszynski <tduszyns@gmail.com>
Acked-by: Matt Ranostay <matt.ranostay@konsulko.com>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
---
Documentation/ABI/testing/sysfs-bus-iio | 17 ++++++++++++++++-
drivers/iio/industrialio-core.c | 5 +++++
include/uapi/linux/iio/types.h | 5 +++++
tools/iio/iio_event_monitor.c | 10 ++++++++++
4 files changed, 36 insertions(+), 1 deletion(-)
--- a/Documentation/ABI/testing/sysfs-bus-iio
+++ b/Documentation/ABI/testing/sysfs-bus-iio
@@ -1684,4 +1684,19 @@ KernelVersion: 4.18
Contact: linux-iio@vger.kernel.org
Description:
Raw (unscaled) phase difference reading from channel Y
- that can be processed to radians.
\ No newline at end of file
+ that can be processed to radians.
+
+What: /sys/bus/iio/devices/iio:deviceX/in_massconcentration_pm1_input
+What: /sys/bus/iio/devices/iio:deviceX/in_massconcentrationY_pm1_input
+What: /sys/bus/iio/devices/iio:deviceX/in_massconcentration_pm2p5_input
+What: /sys/bus/iio/devices/iio:deviceX/in_massconcentrationY_pm2p5_input
+What: /sys/bus/iio/devices/iio:deviceX/in_massconcentration_pm4_input
+What: /sys/bus/iio/devices/iio:deviceX/in_massconcentrationY_pm4_input
+What: /sys/bus/iio/devices/iio:deviceX/in_massconcentration_pm10_input
+What: /sys/bus/iio/devices/iio:deviceX/in_massconcentrationY_pm10_input
+KernelVersion: 4.22
+Contact: linux-iio@vger.kernel.org
+Description:
+ Mass concentration reading of particulate matter in ug / m3.
+ pmX consists of particles with aerodynamic diameter less or
+ equal to X micrometers.
--- a/drivers/iio/industrialio-core.c
+++ b/drivers/iio/industrialio-core.c
@@ -87,6 +87,7 @@ static const char * const iio_chan_type_
[IIO_GRAVITY] = "gravity",
[IIO_POSITIONRELATIVE] = "positionrelative",
[IIO_PHASE] = "phase",
+ [IIO_MASSCONCENTRATION] = "massconcentration",
};
static const char * const iio_modifier_names[] = {
@@ -127,6 +128,10 @@ static const char * const iio_modifier_n
[IIO_MOD_Q] = "q",
[IIO_MOD_CO2] = "co2",
[IIO_MOD_VOC] = "voc",
+ [IIO_MOD_PM1] = "pm1",
+ [IIO_MOD_PM2P5] = "pm2p5",
+ [IIO_MOD_PM4] = "pm4",
+ [IIO_MOD_PM10] = "pm10",
};
/* relies on pairs of these shared then separate */
--- a/include/uapi/linux/iio/types.h
+++ b/include/uapi/linux/iio/types.h
@@ -46,6 +46,7 @@ enum iio_chan_type {
IIO_GRAVITY,
IIO_POSITIONRELATIVE,
IIO_PHASE,
+ IIO_MASSCONCENTRATION,
};
enum iio_modifier {
@@ -87,6 +88,10 @@ enum iio_modifier {
IIO_MOD_VOC,
IIO_MOD_LIGHT_UV,
IIO_MOD_LIGHT_DUV,
+ IIO_MOD_PM1,
+ IIO_MOD_PM2P5,
+ IIO_MOD_PM4,
+ IIO_MOD_PM10,
};
enum iio_event_type {
--- a/tools/iio/iio_event_monitor.c
+++ b/tools/iio/iio_event_monitor.c
@@ -60,6 +60,7 @@ static const char * const iio_chan_type_
[IIO_GRAVITY] = "gravity",
[IIO_POSITIONRELATIVE] = "positionrelative",
[IIO_PHASE] = "phase",
+ [IIO_MASSCONCENTRATION] = "massconcentration",
};
static const char * const iio_ev_type_text[] = {
@@ -115,6 +116,10 @@ static const char * const iio_modifier_n
[IIO_MOD_Q] = "q",
[IIO_MOD_CO2] = "co2",
[IIO_MOD_VOC] = "voc",
+ [IIO_MOD_PM1] = "pm1",
+ [IIO_MOD_PM2P5] = "pm2p5",
+ [IIO_MOD_PM4] = "pm4",
+ [IIO_MOD_PM10] = "pm10",
};
static bool event_is_known(struct iio_event_data *event)
@@ -156,6 +161,7 @@ static bool event_is_known(struct iio_ev
case IIO_GRAVITY:
case IIO_POSITIONRELATIVE:
case IIO_PHASE:
+ case IIO_MASSCONCENTRATION:
break;
default:
return false;
@@ -200,6 +206,10 @@ static bool event_is_known(struct iio_ev
case IIO_MOD_Q:
case IIO_MOD_CO2:
case IIO_MOD_VOC:
+ case IIO_MOD_PM1:
+ case IIO_MOD_PM2P5:
+ case IIO_MOD_PM4:
+ case IIO_MOD_PM10:
break;
default:
return false;

View File

@ -0,0 +1,454 @@
From 232e0f6ddeaee104d64675fe7d0cc142cf955f35 Mon Sep 17 00:00:00 2001
From: Tomasz Duszynski <tduszyns@gmail.com>
Date: Fri, 14 Dec 2018 19:28:02 +0100
Subject: [PATCH] iio: chemical: add support for Sensirion SPS30 sensor
Add support for Sensirion SPS30 particulate matter sensor.
Signed-off-by: Tomasz Duszynski <tduszyns@gmail.com>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
---
drivers/iio/chemical/Kconfig | 11 +
drivers/iio/chemical/Makefile | 1 +
drivers/iio/chemical/sps30.c | 407 ++++++++++++++++++++++++++++++++++
3 files changed, 419 insertions(+)
create mode 100644 drivers/iio/chemical/sps30.c
--- a/drivers/iio/chemical/Kconfig
+++ b/drivers/iio/chemical/Kconfig
@@ -61,6 +61,17 @@ config IAQCORE
iAQ-Core Continuous/Pulsed VOC (Volatile Organic Compounds)
sensors
+config SPS30
+ tristate "SPS30 particulate matter sensor"
+ depends on I2C
+ select CRC8
+ help
+ Say Y here to build support for the Sensirion SPS30 particulate
+ matter sensor.
+
+ To compile this driver as a module, choose M here: the module will
+ be called sps30.
+
config VZ89X
tristate "SGX Sensortech MiCS VZ89X VOC sensor"
depends on I2C
--- a/drivers/iio/chemical/Makefile
+++ b/drivers/iio/chemical/Makefile
@@ -9,4 +9,5 @@ obj-$(CONFIG_BME680_I2C) += bme680_i2c.o
obj-$(CONFIG_BME680_SPI) += bme680_spi.o
obj-$(CONFIG_CCS811) += ccs811.o
obj-$(CONFIG_IAQCORE) += ams-iaq-core.o
+obj-$(CONFIG_SPS30) += sps30.o
obj-$(CONFIG_VZ89X) += vz89x.o
--- /dev/null
+++ b/drivers/iio/chemical/sps30.c
@@ -0,0 +1,407 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Sensirion SPS30 particulate matter sensor driver
+ *
+ * Copyright (c) Tomasz Duszynski <tduszyns@gmail.com>
+ *
+ * I2C slave address: 0x69
+ *
+ * TODO:
+ * - support for turning on fan cleaning
+ * - support for reading/setting auto cleaning interval
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <asm/unaligned.h>
+#include <linux/crc8.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
+#include <linux/module.h>
+
+#define SPS30_CRC8_POLYNOMIAL 0x31
+/* max number of bytes needed to store PM measurements or serial string */
+#define SPS30_MAX_READ_SIZE 48
+/* sensor measures reliably up to 3000 ug / m3 */
+#define SPS30_MAX_PM 3000
+
+/* SPS30 commands */
+#define SPS30_START_MEAS 0x0010
+#define SPS30_STOP_MEAS 0x0104
+#define SPS30_RESET 0xd304
+#define SPS30_READ_DATA_READY_FLAG 0x0202
+#define SPS30_READ_DATA 0x0300
+#define SPS30_READ_SERIAL 0xd033
+
+enum {
+ PM1,
+ PM2P5,
+ PM4,
+ PM10,
+};
+
+struct sps30_state {
+ struct i2c_client *client;
+ /*
+ * Guards against concurrent access to sensor registers.
+ * Must be held whenever sequence of commands is to be executed.
+ */
+ struct mutex lock;
+};
+
+DECLARE_CRC8_TABLE(sps30_crc8_table);
+
+static int sps30_write_then_read(struct sps30_state *state, u8 *txbuf,
+ int txsize, u8 *rxbuf, int rxsize)
+{
+ int ret;
+
+ /*
+ * Sensor does not support repeated start so instead of
+ * sending two i2c messages in a row we just send one by one.
+ */
+ ret = i2c_master_send(state->client, txbuf, txsize);
+ if (ret != txsize)
+ return ret < 0 ? ret : -EIO;
+
+ if (!rxbuf)
+ return 0;
+
+ ret = i2c_master_recv(state->client, rxbuf, rxsize);
+ if (ret != rxsize)
+ return ret < 0 ? ret : -EIO;
+
+ return 0;
+}
+
+static int sps30_do_cmd(struct sps30_state *state, u16 cmd, u8 *data, int size)
+{
+ /*
+ * Internally sensor stores measurements in a following manner:
+ *
+ * PM1: upper two bytes, crc8, lower two bytes, crc8
+ * PM2P5: upper two bytes, crc8, lower two bytes, crc8
+ * PM4: upper two bytes, crc8, lower two bytes, crc8
+ * PM10: upper two bytes, crc8, lower two bytes, crc8
+ *
+ * What follows next are number concentration measurements and
+ * typical particle size measurement which we omit.
+ */
+ u8 buf[SPS30_MAX_READ_SIZE] = { cmd >> 8, cmd };
+ int i, ret = 0;
+
+ switch (cmd) {
+ case SPS30_START_MEAS:
+ buf[2] = 0x03;
+ buf[3] = 0x00;
+ buf[4] = crc8(sps30_crc8_table, &buf[2], 2, CRC8_INIT_VALUE);
+ ret = sps30_write_then_read(state, buf, 5, NULL, 0);
+ break;
+ case SPS30_STOP_MEAS:
+ case SPS30_RESET:
+ ret = sps30_write_then_read(state, buf, 2, NULL, 0);
+ break;
+ case SPS30_READ_DATA_READY_FLAG:
+ case SPS30_READ_DATA:
+ case SPS30_READ_SERIAL:
+ /* every two data bytes are checksummed */
+ size += size / 2;
+ ret = sps30_write_then_read(state, buf, 2, buf, size);
+ break;
+ }
+
+ if (ret)
+ return ret;
+
+ /* validate received data and strip off crc bytes */
+ for (i = 0; i < size; i += 3) {
+ u8 crc = crc8(sps30_crc8_table, &buf[i], 2, CRC8_INIT_VALUE);
+
+ if (crc != buf[i + 2]) {
+ dev_err(&state->client->dev,
+ "data integrity check failed\n");
+ return -EIO;
+ }
+
+ *data++ = buf[i];
+ *data++ = buf[i + 1];
+ }
+
+ return 0;
+}
+
+static s32 sps30_float_to_int_clamped(const u8 *fp)
+{
+ int val = get_unaligned_be32(fp);
+ int mantissa = val & GENMASK(22, 0);
+ /* this is fine since passed float is always non-negative */
+ int exp = val >> 23;
+ int fraction, shift;
+
+ /* special case 0 */
+ if (!exp && !mantissa)
+ return 0;
+
+ exp -= 127;
+ if (exp < 0) {
+ /* return values ranging from 1 to 99 */
+ return ((((1 << 23) + mantissa) * 100) >> 23) >> (-exp);
+ }
+
+ /* return values ranging from 100 to 300000 */
+ shift = 23 - exp;
+ val = (1 << exp) + (mantissa >> shift);
+ if (val >= SPS30_MAX_PM)
+ return SPS30_MAX_PM * 100;
+
+ fraction = mantissa & GENMASK(shift - 1, 0);
+
+ return val * 100 + ((fraction * 100) >> shift);
+}
+
+static int sps30_do_meas(struct sps30_state *state, s32 *data, int size)
+{
+ int i, ret, tries = 5;
+ u8 tmp[16];
+
+ while (tries--) {
+ ret = sps30_do_cmd(state, SPS30_READ_DATA_READY_FLAG, tmp, 2);
+ if (ret)
+ return -EIO;
+
+ /* new measurements ready to be read */
+ if (tmp[1] == 1)
+ break;
+
+ msleep_interruptible(300);
+ }
+
+ if (!tries)
+ return -ETIMEDOUT;
+
+ ret = sps30_do_cmd(state, SPS30_READ_DATA, tmp, sizeof(int) * size);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < size; i++)
+ data[i] = sps30_float_to_int_clamped(&tmp[4 * i]);
+
+ return 0;
+}
+
+static irqreturn_t sps30_trigger_handler(int irq, void *p)
+{
+ struct iio_poll_func *pf = p;
+ struct iio_dev *indio_dev = pf->indio_dev;
+ struct sps30_state *state = iio_priv(indio_dev);
+ int ret;
+ s32 data[4 + 2]; /* PM1, PM2P5, PM4, PM10, timestamp */
+
+ mutex_lock(&state->lock);
+ ret = sps30_do_meas(state, data, 4);
+ mutex_unlock(&state->lock);
+ if (ret)
+ goto err;
+
+ iio_push_to_buffers_with_timestamp(indio_dev, data,
+ iio_get_time_ns(indio_dev));
+err:
+ iio_trigger_notify_done(indio_dev->trig);
+
+ return IRQ_HANDLED;
+}
+
+static int sps30_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val, int *val2, long mask)
+{
+ struct sps30_state *state = iio_priv(indio_dev);
+ int data[4], ret = -EINVAL;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_PROCESSED:
+ switch (chan->type) {
+ case IIO_MASSCONCENTRATION:
+ mutex_lock(&state->lock);
+ /* read up to the number of bytes actually needed */
+ switch (chan->channel2) {
+ case IIO_MOD_PM1:
+ ret = sps30_do_meas(state, data, 1);
+ break;
+ case IIO_MOD_PM2P5:
+ ret = sps30_do_meas(state, data, 2);
+ break;
+ case IIO_MOD_PM4:
+ ret = sps30_do_meas(state, data, 3);
+ break;
+ case IIO_MOD_PM10:
+ ret = sps30_do_meas(state, data, 4);
+ break;
+ }
+ mutex_unlock(&state->lock);
+ if (ret)
+ return ret;
+
+ *val = data[chan->address] / 100;
+ *val2 = (data[chan->address] % 100) * 10000;
+
+ return IIO_VAL_INT_PLUS_MICRO;
+ default:
+ return -EINVAL;
+ }
+ case IIO_CHAN_INFO_SCALE:
+ switch (chan->type) {
+ case IIO_MASSCONCENTRATION:
+ switch (chan->channel2) {
+ case IIO_MOD_PM1:
+ case IIO_MOD_PM2P5:
+ case IIO_MOD_PM4:
+ case IIO_MOD_PM10:
+ *val = 0;
+ *val2 = 10000;
+
+ return IIO_VAL_INT_PLUS_MICRO;
+ }
+ default:
+ return -EINVAL;
+ }
+ }
+
+ return -EINVAL;
+}
+
+static const struct iio_info sps30_info = {
+ .read_raw = sps30_read_raw,
+};
+
+#define SPS30_CHAN(_index, _mod) { \
+ .type = IIO_MASSCONCENTRATION, \
+ .modified = 1, \
+ .channel2 = IIO_MOD_ ## _mod, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), \
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
+ .address = _mod, \
+ .scan_index = _index, \
+ .scan_type = { \
+ .sign = 'u', \
+ .realbits = 19, \
+ .storagebits = 32, \
+ .endianness = IIO_CPU, \
+ }, \
+}
+
+static const struct iio_chan_spec sps30_channels[] = {
+ SPS30_CHAN(0, PM1),
+ SPS30_CHAN(1, PM2P5),
+ SPS30_CHAN(2, PM4),
+ SPS30_CHAN(3, PM10),
+ IIO_CHAN_SOFT_TIMESTAMP(4),
+};
+
+static void sps30_stop_meas(void *data)
+{
+ struct sps30_state *state = data;
+
+ sps30_do_cmd(state, SPS30_STOP_MEAS, NULL, 0);
+}
+
+static const unsigned long sps30_scan_masks[] = { 0x0f, 0x00 };
+
+static int sps30_probe(struct i2c_client *client)
+{
+ struct iio_dev *indio_dev;
+ struct sps30_state *state;
+ u8 buf[32];
+ int ret;
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
+ return -EOPNOTSUPP;
+
+ indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*state));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ state = iio_priv(indio_dev);
+ i2c_set_clientdata(client, indio_dev);
+ state->client = client;
+ indio_dev->dev.parent = &client->dev;
+ indio_dev->info = &sps30_info;
+ indio_dev->name = client->name;
+ indio_dev->channels = sps30_channels;
+ indio_dev->num_channels = ARRAY_SIZE(sps30_channels);
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->available_scan_masks = sps30_scan_masks;
+
+ mutex_init(&state->lock);
+ crc8_populate_msb(sps30_crc8_table, SPS30_CRC8_POLYNOMIAL);
+
+ ret = sps30_do_cmd(state, SPS30_RESET, NULL, 0);
+ if (ret) {
+ dev_err(&client->dev, "failed to reset device\n");
+ return ret;
+ }
+ msleep(300);
+ /*
+ * Power-on-reset causes sensor to produce some glitch on i2c bus and
+ * some controllers end up in error state. Recover simply by placing
+ * some data on the bus, for example STOP_MEAS command, which
+ * is NOP in this case.
+ */
+ sps30_do_cmd(state, SPS30_STOP_MEAS, NULL, 0);
+
+ ret = sps30_do_cmd(state, SPS30_READ_SERIAL, buf, sizeof(buf));
+ if (ret) {
+ dev_err(&client->dev, "failed to read serial number\n");
+ return ret;
+ }
+ /* returned serial number is already NUL terminated */
+ dev_info(&client->dev, "serial number: %s\n", buf);
+
+ ret = sps30_do_cmd(state, SPS30_START_MEAS, NULL, 0);
+ if (ret) {
+ dev_err(&client->dev, "failed to start measurement\n");
+ return ret;
+ }
+
+ ret = devm_add_action_or_reset(&client->dev, sps30_stop_meas, state);
+ if (ret)
+ return ret;
+
+ ret = devm_iio_triggered_buffer_setup(&client->dev, indio_dev, NULL,
+ sps30_trigger_handler, NULL);
+ if (ret)
+ return ret;
+
+ return devm_iio_device_register(&client->dev, indio_dev);
+}
+
+static const struct i2c_device_id sps30_id[] = {
+ { "sps30" },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, sps30_id);
+
+static const struct of_device_id sps30_of_match[] = {
+ { .compatible = "sensirion,sps30" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, sps30_of_match);
+
+static struct i2c_driver sps30_driver = {
+ .driver = {
+ .name = "sps30",
+ .of_match_table = sps30_of_match,
+ },
+ .id_table = sps30_id,
+ .probe_new = sps30_probe,
+};
+module_i2c_driver(sps30_driver);
+
+MODULE_AUTHOR("Tomasz Duszynski <tduszyns@gmail.com>");
+MODULE_DESCRIPTION("Sensirion SPS30 particulate matter sensor driver");
+MODULE_LICENSE("GPL v2");

View File

@ -0,0 +1,100 @@
From c546d49656143855093c7b7fde60866e6e23a69d Mon Sep 17 00:00:00 2001
From: Tomasz Duszynski <tduszyns@gmail.com>
Date: Tue, 18 Dec 2018 21:28:09 +0100
Subject: [PATCH] iio: chemical: sps30: add support for self cleaning
Self cleaning is especially useful in cases where sensor undergoes
frequent power on/off cycles. In such scenarios it is recommended to
turn self cleaning at least once per week in order to maintain reliable
measurements.
Self cleaning is activated by writing 1 to a dedicated attribute.
Internal fan accelerates to its maximum speed and keeps spinning
for about 10 seconds blowing out accumulated dust.
Signed-off-by: Tomasz Duszynski <tduszyns@gmail.com>
Tested-by: Andreas Brauchli <andreas.brauchli@sensirion.com>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
---
Documentation/ABI/testing/sysfs-bus-iio-sps30 | 8 +++++
drivers/iio/chemical/sps30.c | 35 ++++++++++++++++++-
2 files changed, 42 insertions(+), 1 deletion(-)
create mode 100644 Documentation/ABI/testing/sysfs-bus-iio-sps30
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-bus-iio-sps30
@@ -0,0 +1,8 @@
+What: /sys/bus/iio/devices/iio:deviceX/start_cleaning
+Date: December 2018
+KernelVersion: 4.22
+Contact: linux-iio@vger.kernel.org
+Description:
+ Writing 1 starts sensor self cleaning. Internal fan accelerates
+ to its maximum speed and keeps spinning for about 10 seconds in
+ order to blow out accumulated dust.
--- a/drivers/iio/chemical/sps30.c
+++ b/drivers/iio/chemical/sps30.c
@@ -7,7 +7,6 @@
* I2C slave address: 0x69
*
* TODO:
- * - support for turning on fan cleaning
* - support for reading/setting auto cleaning interval
*/
@@ -37,6 +36,7 @@
#define SPS30_READ_DATA_READY_FLAG 0x0202
#define SPS30_READ_DATA 0x0300
#define SPS30_READ_SERIAL 0xd033
+#define SPS30_START_FAN_CLEANING 0x5607
enum {
PM1,
@@ -104,6 +104,7 @@ static int sps30_do_cmd(struct sps30_sta
break;
case SPS30_STOP_MEAS:
case SPS30_RESET:
+ case SPS30_START_FAN_CLEANING:
ret = sps30_write_then_read(state, buf, 2, NULL, 0);
break;
case SPS30_READ_DATA_READY_FLAG:
@@ -275,7 +276,39 @@ static int sps30_read_raw(struct iio_dev
return -EINVAL;
}
+static ssize_t start_cleaning_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t len)
+{
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ struct sps30_state *state = iio_priv(indio_dev);
+ int val, ret;
+
+ if (kstrtoint(buf, 0, &val) || val != 1)
+ return -EINVAL;
+
+ mutex_lock(&state->lock);
+ ret = sps30_do_cmd(state, SPS30_START_FAN_CLEANING, NULL, 0);
+ mutex_unlock(&state->lock);
+ if (ret)
+ return ret;
+
+ return len;
+}
+
+static IIO_DEVICE_ATTR_WO(start_cleaning, 0);
+
+static struct attribute *sps30_attrs[] = {
+ &iio_dev_attr_start_cleaning.dev_attr.attr,
+ NULL
+};
+
+static const struct attribute_group sps30_attr_group = {
+ .attrs = sps30_attrs,
+};
+
static const struct iio_info sps30_info = {
+ .attrs = &sps30_attr_group,
.read_raw = sps30_read_raw,
};

View File

@ -0,0 +1,293 @@
From 62129a0849d27cc94ced832bcf9dcde283dcbe08 Mon Sep 17 00:00:00 2001
From: Tomasz Duszynski <tduszyns@gmail.com>
Date: Tue, 15 Jan 2019 20:00:06 +0100
Subject: [PATCH] iio: chemical: sps30: allow changing self cleaning period
Sensor can periodically trigger self cleaning. Period can be changed by
writing a new value to a dedicated attribute. Upon attribute read
current period gets returned.
Signed-off-by: Tomasz Duszynski <tduszyns@gmail.com>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
---
Documentation/ABI/testing/sysfs-bus-iio-sps30 | 20 +++
drivers/iio/chemical/sps30.c | 143 +++++++++++++++---
2 files changed, 145 insertions(+), 18 deletions(-)
--- a/Documentation/ABI/testing/sysfs-bus-iio-sps30
+++ b/Documentation/ABI/testing/sysfs-bus-iio-sps30
@@ -6,3 +6,23 @@ Description:
Writing 1 starts sensor self cleaning. Internal fan accelerates
to its maximum speed and keeps spinning for about 10 seconds in
order to blow out accumulated dust.
+
+What: /sys/bus/iio/devices/iio:deviceX/cleaning_period
+Date: January 2019
+KernelVersion: 5.1
+Contact: linux-iio@vger.kernel.org
+Description:
+ Sensor is capable of triggering self cleaning periodically.
+ Period can be changed by writing a new value here. Upon reading
+ the current one is returned. Units are seconds.
+
+ Writing 0 disables periodical self cleaning entirely.
+
+What: /sys/bus/iio/devices/iio:deviceX/cleaning_period_available
+Date: January 2019
+KernelVersion: 5.1
+Contact: linux-iio@vger.kernel.org
+Description:
+ The range of available values in seconds represented as the
+ minimum value, the step and the maximum value, all enclosed in
+ square brackets.
--- a/drivers/iio/chemical/sps30.c
+++ b/drivers/iio/chemical/sps30.c
@@ -5,9 +5,6 @@
* Copyright (c) Tomasz Duszynski <tduszyns@gmail.com>
*
* I2C slave address: 0x69
- *
- * TODO:
- * - support for reading/setting auto cleaning interval
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@@ -21,6 +18,7 @@
#include <linux/iio/sysfs.h>
#include <linux/iio/trigger_consumer.h>
#include <linux/iio/triggered_buffer.h>
+#include <linux/kernel.h>
#include <linux/module.h>
#define SPS30_CRC8_POLYNOMIAL 0x31
@@ -28,6 +26,9 @@
#define SPS30_MAX_READ_SIZE 48
/* sensor measures reliably up to 3000 ug / m3 */
#define SPS30_MAX_PM 3000
+/* minimum and maximum self cleaning periods in seconds */
+#define SPS30_AUTO_CLEANING_PERIOD_MIN 0
+#define SPS30_AUTO_CLEANING_PERIOD_MAX 604800
/* SPS30 commands */
#define SPS30_START_MEAS 0x0010
@@ -37,6 +38,9 @@
#define SPS30_READ_DATA 0x0300
#define SPS30_READ_SERIAL 0xd033
#define SPS30_START_FAN_CLEANING 0x5607
+#define SPS30_AUTO_CLEANING_PERIOD 0x8004
+/* not a sensor command per se, used only to distinguish write from read */
+#define SPS30_READ_AUTO_CLEANING_PERIOD 0x8005
enum {
PM1,
@@ -45,6 +49,11 @@ enum {
PM10,
};
+enum {
+ RESET,
+ MEASURING,
+};
+
struct sps30_state {
struct i2c_client *client;
/*
@@ -52,6 +61,7 @@ struct sps30_state {
* Must be held whenever sequence of commands is to be executed.
*/
struct mutex lock;
+ int state;
};
DECLARE_CRC8_TABLE(sps30_crc8_table);
@@ -107,6 +117,9 @@ static int sps30_do_cmd(struct sps30_sta
case SPS30_START_FAN_CLEANING:
ret = sps30_write_then_read(state, buf, 2, NULL, 0);
break;
+ case SPS30_READ_AUTO_CLEANING_PERIOD:
+ buf[0] = SPS30_AUTO_CLEANING_PERIOD >> 8;
+ buf[1] = (u8)SPS30_AUTO_CLEANING_PERIOD;
case SPS30_READ_DATA_READY_FLAG:
case SPS30_READ_DATA:
case SPS30_READ_SERIAL:
@@ -114,6 +127,15 @@ static int sps30_do_cmd(struct sps30_sta
size += size / 2;
ret = sps30_write_then_read(state, buf, 2, buf, size);
break;
+ case SPS30_AUTO_CLEANING_PERIOD:
+ buf[2] = data[0];
+ buf[3] = data[1];
+ buf[4] = crc8(sps30_crc8_table, &buf[2], 2, CRC8_INIT_VALUE);
+ buf[5] = data[2];
+ buf[6] = data[3];
+ buf[7] = crc8(sps30_crc8_table, &buf[5], 2, CRC8_INIT_VALUE);
+ ret = sps30_write_then_read(state, buf, 8, NULL, 0);
+ break;
}
if (ret)
@@ -170,6 +192,14 @@ static int sps30_do_meas(struct sps30_st
int i, ret, tries = 5;
u8 tmp[16];
+ if (state->state == RESET) {
+ ret = sps30_do_cmd(state, SPS30_START_MEAS, NULL, 0);
+ if (ret)
+ return ret;
+
+ state->state = MEASURING;
+ }
+
while (tries--) {
ret = sps30_do_cmd(state, SPS30_READ_DATA_READY_FLAG, tmp, 2);
if (ret)
@@ -276,6 +306,24 @@ static int sps30_read_raw(struct iio_dev
return -EINVAL;
}
+static int sps30_do_cmd_reset(struct sps30_state *state)
+{
+ int ret;
+
+ ret = sps30_do_cmd(state, SPS30_RESET, NULL, 0);
+ msleep(300);
+ /*
+ * Power-on-reset causes sensor to produce some glitch on i2c bus and
+ * some controllers end up in error state. Recover simply by placing
+ * some data on the bus, for example STOP_MEAS command, which
+ * is NOP in this case.
+ */
+ sps30_do_cmd(state, SPS30_STOP_MEAS, NULL, 0);
+ state->state = RESET;
+
+ return ret;
+}
+
static ssize_t start_cleaning_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t len)
@@ -296,10 +344,82 @@ static ssize_t start_cleaning_store(stru
return len;
}
+static ssize_t cleaning_period_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ struct sps30_state *state = iio_priv(indio_dev);
+ u8 tmp[4];
+ int ret;
+
+ mutex_lock(&state->lock);
+ ret = sps30_do_cmd(state, SPS30_READ_AUTO_CLEANING_PERIOD, tmp, 4);
+ mutex_unlock(&state->lock);
+ if (ret)
+ return ret;
+
+ return sprintf(buf, "%d\n", get_unaligned_be32(tmp));
+}
+
+static ssize_t cleaning_period_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t len)
+{
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ struct sps30_state *state = iio_priv(indio_dev);
+ int val, ret;
+ u8 tmp[4];
+
+ if (kstrtoint(buf, 0, &val))
+ return -EINVAL;
+
+ if ((val < SPS30_AUTO_CLEANING_PERIOD_MIN) ||
+ (val > SPS30_AUTO_CLEANING_PERIOD_MAX))
+ return -EINVAL;
+
+ put_unaligned_be32(val, tmp);
+
+ mutex_lock(&state->lock);
+ ret = sps30_do_cmd(state, SPS30_AUTO_CLEANING_PERIOD, tmp, 0);
+ if (ret) {
+ mutex_unlock(&state->lock);
+ return ret;
+ }
+
+ msleep(20);
+
+ /*
+ * sensor requires reset in order to return up to date self cleaning
+ * period
+ */
+ ret = sps30_do_cmd_reset(state);
+ if (ret)
+ dev_warn(dev,
+ "period changed but reads will return the old value\n");
+
+ mutex_unlock(&state->lock);
+
+ return len;
+}
+
+static ssize_t cleaning_period_available_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "[%d %d %d]\n",
+ SPS30_AUTO_CLEANING_PERIOD_MIN, 1,
+ SPS30_AUTO_CLEANING_PERIOD_MAX);
+}
+
static IIO_DEVICE_ATTR_WO(start_cleaning, 0);
+static IIO_DEVICE_ATTR_RW(cleaning_period, 0);
+static IIO_DEVICE_ATTR_RO(cleaning_period_available, 0);
static struct attribute *sps30_attrs[] = {
&iio_dev_attr_start_cleaning.dev_attr.attr,
+ &iio_dev_attr_cleaning_period.dev_attr.attr,
+ &iio_dev_attr_cleaning_period_available.dev_attr.attr,
NULL
};
@@ -362,6 +482,7 @@ static int sps30_probe(struct i2c_client
state = iio_priv(indio_dev);
i2c_set_clientdata(client, indio_dev);
state->client = client;
+ state->state = RESET;
indio_dev->dev.parent = &client->dev;
indio_dev->info = &sps30_info;
indio_dev->name = client->name;
@@ -373,19 +494,11 @@ static int sps30_probe(struct i2c_client
mutex_init(&state->lock);
crc8_populate_msb(sps30_crc8_table, SPS30_CRC8_POLYNOMIAL);
- ret = sps30_do_cmd(state, SPS30_RESET, NULL, 0);
+ ret = sps30_do_cmd_reset(state);
if (ret) {
dev_err(&client->dev, "failed to reset device\n");
return ret;
}
- msleep(300);
- /*
- * Power-on-reset causes sensor to produce some glitch on i2c bus and
- * some controllers end up in error state. Recover simply by placing
- * some data on the bus, for example STOP_MEAS command, which
- * is NOP in this case.
- */
- sps30_do_cmd(state, SPS30_STOP_MEAS, NULL, 0);
ret = sps30_do_cmd(state, SPS30_READ_SERIAL, buf, sizeof(buf));
if (ret) {
@@ -395,12 +508,6 @@ static int sps30_probe(struct i2c_client
/* returned serial number is already NUL terminated */
dev_info(&client->dev, "serial number: %s\n", buf);
- ret = sps30_do_cmd(state, SPS30_START_MEAS, NULL, 0);
- if (ret) {
- dev_err(&client->dev, "failed to start measurement\n");
- return ret;
- }
-
ret = devm_add_action_or_reset(&client->dev, sps30_stop_meas, state);
if (ret)
return ret;

View File

@ -0,0 +1,25 @@
From 3fa30bf7004bb8069826ef85487f4753666a73da Mon Sep 17 00:00:00 2001
From: Tomasz Duszynski <tduszyns@gmail.com>
Date: Sat, 2 Feb 2019 10:00:03 +0100
Subject: [PATCH] iio: chemical: sps30: remove printk format specifier
pr_fmt is used by printk wrappers. There are not any in the driver
code so remove the format specifier.
Signed-off-by: Tomasz Duszynski <tduszyns@gmail.com>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
---
drivers/iio/chemical/sps30.c | 2 --
1 file changed, 2 deletions(-)
--- a/drivers/iio/chemical/sps30.c
+++ b/drivers/iio/chemical/sps30.c
@@ -7,8 +7,6 @@
* I2C slave address: 0x69
*/
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
#include <asm/unaligned.h>
#include <linux/crc8.h>
#include <linux/delay.h>

View File

@ -0,0 +1,26 @@
From 905889b4a34c753a538015f0b2cdaa0c9e3a4fd5 Mon Sep 17 00:00:00 2001
From: Dan Carpenter <dan.carpenter@oracle.com>
Date: Sat, 9 Feb 2019 12:03:52 +0300
Subject: [PATCH] iio: chemical: sps30: fix a loop timeout test
The "while (tries--) {" loop is a postop so it exits with "tries" set
to -1.
Fixes: 232e0f6ddeae ("iio: chemical: add support for Sensirion SPS30 sensor")
Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
---
drivers/iio/chemical/sps30.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/iio/chemical/sps30.c
+++ b/drivers/iio/chemical/sps30.c
@@ -210,7 +210,7 @@ static int sps30_do_meas(struct sps30_st
msleep_interruptible(300);
}
- if (!tries)
+ if (tries == -1)
return -ETIMEDOUT;
ret = sps30_do_cmd(state, SPS30_READ_DATA, tmp, sizeof(int) * size);

View File

@ -0,0 +1,34 @@
From 59b9bb0abca9efe47207301dbaf0d1beee2bd0f7 Mon Sep 17 00:00:00 2001
From: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Date: Sat, 9 Feb 2019 19:32:58 +0000
Subject: [PATCH] iio:chemical:sps30 Supress some switch fallthrough warnings.
Fixes warnings reported on linux-next but marking one path
and adding an explicit return in the other.
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Cc: Andreas Brauchli <a.brauchli@elementarea.net>
Acked-by: Tomasz Duszynski <tduszyns@gmail.com>
---
drivers/iio/chemical/sps30.c | 3 +++
1 file changed, 3 insertions(+)
--- a/drivers/iio/chemical/sps30.c
+++ b/drivers/iio/chemical/sps30.c
@@ -118,6 +118,7 @@ static int sps30_do_cmd(struct sps30_sta
case SPS30_READ_AUTO_CLEANING_PERIOD:
buf[0] = SPS30_AUTO_CLEANING_PERIOD >> 8;
buf[1] = (u8)SPS30_AUTO_CLEANING_PERIOD;
+ /* fall through */
case SPS30_READ_DATA_READY_FLAG:
case SPS30_READ_DATA:
case SPS30_READ_SERIAL:
@@ -295,6 +296,8 @@ static int sps30_read_raw(struct iio_dev
*val2 = 10000;
return IIO_VAL_INT_PLUS_MICRO;
+ default:
+ return -EINVAL;
}
default:
return -EINVAL;

View File

@ -0,0 +1,31 @@
From 78b75ab3f8c9dfac563b81105a1b838ec37a940e Mon Sep 17 00:00:00 2001
From: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Date: Sun, 13 Oct 2019 10:55:15 +0100
Subject: [PATCH] iio: chemical: sps30: Explicity truncate constant by masking
When breaking up a constant to write to two 8 bit registers
it isn't obvious to sparse that it was intentional.
CHECK drivers/iio/chemical/sps30.c
drivers/iio/chemical/sps30.c:120:30: warning: cast truncates bits from constant value (8004 becomes 4)
So in the interests of minimising noisy warnings, let us add
a mask.
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Acked-by: Tomasz Duszynski <tduszyns@gmail.com>
---
drivers/iio/chemical/sps30.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/iio/chemical/sps30.c
+++ b/drivers/iio/chemical/sps30.c
@@ -117,7 +117,7 @@ static int sps30_do_cmd(struct sps30_sta
break;
case SPS30_READ_AUTO_CLEANING_PERIOD:
buf[0] = SPS30_AUTO_CLEANING_PERIOD >> 8;
- buf[1] = (u8)SPS30_AUTO_CLEANING_PERIOD;
+ buf[1] = (u8)(SPS30_AUTO_CLEANING_PERIOD & 0xff);
/* fall through */
case SPS30_READ_DATA_READY_FLAG:
case SPS30_READ_DATA:

View File

@ -0,0 +1,30 @@
From 61338e27e2eef3bfcd3df5c39cec5b9dc10ba25c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Petr=20=C5=A0tetiar?= <ynezz@true.cz>
Date: Sun, 23 Feb 2020 22:08:25 +0100
Subject: [PATCH] iio: chemical: sps30: fix missing triggered buffer dependency
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
SPS30 uses triggered buffer, but the dependency is not specified in the
Kconfig file. Fix this by selecting IIO_BUFFER and IIO_TRIGGERED_BUFFER
config symbols.
Cc: stable@vger.kernel.org
Fixes: 232e0f6ddeae ("iio: chemical: add support for Sensirion SPS30 sensor")
Signed-off-by: Petr Štetiar <ynezz@true.cz>
---
drivers/iio/chemical/Kconfig | 2 ++
1 file changed, 2 insertions(+)
--- a/drivers/iio/chemical/Kconfig
+++ b/drivers/iio/chemical/Kconfig
@@ -65,6 +65,8 @@ config SPS30
tristate "SPS30 particulate matter sensor"
depends on I2C
select CRC8
+ select IIO_BUFFER
+ select IIO_TRIGGERED_BUFFER
help
Say Y here to build support for the Sensirion SPS30 particulate
matter sensor.

View File

@ -189,7 +189,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
}
--- a/kernel/irq/proc.c
+++ b/kernel/irq/proc.c
@@ -396,6 +396,9 @@ void register_irq_proc(unsigned int irq,
@@ -418,6 +418,9 @@ void register_irq_proc(unsigned int irq,
void __maybe_unused *irqp = (void *)(unsigned long) irq;
char name [MAX_NAMELEN];
@ -199,7 +199,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
if (!root_irq_dir || (desc->irq_data.chip == &no_irq_chip))
return;
@@ -449,6 +452,9 @@ void unregister_irq_proc(unsigned int ir
@@ -471,6 +474,9 @@ void unregister_irq_proc(unsigned int ir
{
char name [MAX_NAMELEN];
@ -209,7 +209,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
if (!root_irq_dir || !desc->dir)
return;
#ifdef CONFIG_SMP
@@ -487,6 +493,9 @@ void init_irq_proc(void)
@@ -509,6 +515,9 @@ void init_irq_proc(void)
unsigned int irq;
struct irq_desc *desc;

View File

@ -189,7 +189,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
}
--- a/kernel/irq/proc.c
+++ b/kernel/irq/proc.c
@@ -333,6 +333,9 @@ void register_irq_proc(unsigned int irq,
@@ -355,6 +355,9 @@ void register_irq_proc(unsigned int irq,
void __maybe_unused *irqp = (void *)(unsigned long) irq;
char name [MAX_NAMELEN];
@ -199,7 +199,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
if (!root_irq_dir || (desc->irq_data.chip == &no_irq_chip))
return;
@@ -386,6 +389,9 @@ void unregister_irq_proc(unsigned int ir
@@ -408,6 +411,9 @@ void unregister_irq_proc(unsigned int ir
{
char name [MAX_NAMELEN];
@ -209,7 +209,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
if (!root_irq_dir || !desc->dir)
return;
#ifdef CONFIG_SMP
@@ -424,6 +430,9 @@ void init_irq_proc(void)
@@ -446,6 +452,9 @@ void init_irq_proc(void)
unsigned int irq;
struct irq_desc *desc;

View File

@ -185,7 +185,7 @@ Signed-off-by: Jonas Gorski <jogo@openwrt.org>
cfg->fc_flags |= RTF_REJECT;
if (rtm->rtm_type == RTN_LOCAL)
@@ -5084,6 +5115,8 @@ static int ip6_route_dev_notify(struct n
@@ -5085,6 +5116,8 @@ static int ip6_route_dev_notify(struct n
#ifdef CONFIG_IPV6_MULTIPLE_TABLES
net->ipv6.ip6_prohibit_entry->dst.dev = dev;
net->ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(dev);
@ -194,7 +194,7 @@ Signed-off-by: Jonas Gorski <jogo@openwrt.org>
net->ipv6.ip6_blk_hole_entry->dst.dev = dev;
net->ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(dev);
#endif
@@ -5095,6 +5128,7 @@ static int ip6_route_dev_notify(struct n
@@ -5096,6 +5129,7 @@ static int ip6_route_dev_notify(struct n
in6_dev_put_clear(&net->ipv6.ip6_null_entry->rt6i_idev);
#ifdef CONFIG_IPV6_MULTIPLE_TABLES
in6_dev_put_clear(&net->ipv6.ip6_prohibit_entry->rt6i_idev);
@ -202,7 +202,7 @@ Signed-off-by: Jonas Gorski <jogo@openwrt.org>
in6_dev_put_clear(&net->ipv6.ip6_blk_hole_entry->rt6i_idev);
#endif
}
@@ -5289,6 +5323,15 @@ static int __net_init ip6_route_net_init
@@ -5290,6 +5324,15 @@ static int __net_init ip6_route_net_init
net->ipv6.ip6_blk_hole_entry->dst.ops = &net->ipv6.ip6_dst_ops;
dst_init_metrics(&net->ipv6.ip6_blk_hole_entry->dst,
ip6_template_metrics, true);
@ -218,7 +218,7 @@ Signed-off-by: Jonas Gorski <jogo@openwrt.org>
#endif
net->ipv6.sysctl.flush_delay = 0;
@@ -5307,6 +5350,8 @@ out:
@@ -5308,6 +5351,8 @@ out:
return ret;
#ifdef CONFIG_IPV6_MULTIPLE_TABLES
@ -227,7 +227,7 @@ Signed-off-by: Jonas Gorski <jogo@openwrt.org>
out_ip6_prohibit_entry:
kfree(net->ipv6.ip6_prohibit_entry);
out_ip6_null_entry:
@@ -5327,6 +5372,7 @@ static void __net_exit ip6_route_net_exi
@@ -5328,6 +5373,7 @@ static void __net_exit ip6_route_net_exi
#ifdef CONFIG_IPV6_MULTIPLE_TABLES
kfree(net->ipv6.ip6_prohibit_entry);
kfree(net->ipv6.ip6_blk_hole_entry);
@ -235,7 +235,7 @@ Signed-off-by: Jonas Gorski <jogo@openwrt.org>
#endif
dst_entries_destroy(&net->ipv6.ip6_dst_ops);
}
@@ -5403,6 +5449,9 @@ void __init ip6_route_init_special_entri
@@ -5404,6 +5450,9 @@ void __init ip6_route_init_special_entri
init_net.ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev);
init_net.ipv6.ip6_blk_hole_entry->dst.dev = init_net.loopback_dev;
init_net.ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev);

View File

@ -14,7 +14,7 @@ Signed-off-by: John Crispin <john@phrozen.org>
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -150,6 +150,7 @@ endif
@@ -152,6 +152,7 @@ endif
textofs-$(CONFIG_ARCH_MSM8X60) := 0x00208000
textofs-$(CONFIG_ARCH_MSM8960) := 0x00208000
textofs-$(CONFIG_ARCH_AXXIA) := 0x00308000

View File

@ -8,7 +8,7 @@
{ "mx25u25635f", INFO(0xc22539, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_4B_OPCODES) },
{ "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) },
{ "mx66l51235l", INFO(0xc2201a, 0, 64 * 1024, 1024, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
@@ -1284,11 +1285,12 @@ static const struct flash_info spi_nor_i
@@ -1286,11 +1287,12 @@ static const struct flash_info spi_nor_i
{ },
};
@ -23,7 +23,7 @@
tmp = nor->read_reg(nor, SPINOR_OP_RDID, id, SPI_NOR_MAX_ID_LEN);
if (tmp < 0) {
@@ -1299,10 +1301,16 @@ static const struct flash_info *spi_nor_
@@ -1301,10 +1303,16 @@ static const struct flash_info *spi_nor_
for (tmp = 0; tmp < ARRAY_SIZE(spi_nor_ids) - 1; tmp++) {
info = &spi_nor_ids[tmp];
if (info->id_len) {
@ -42,7 +42,7 @@
dev_err(nor->dev, "unrecognized JEDEC id bytes: %02x, %02x, %02x\n",
id[0], id[1], id[2]);
return ERR_PTR(-ENODEV);
@@ -2836,7 +2844,7 @@ int spi_nor_scan(struct spi_nor *nor, co
@@ -2838,7 +2846,7 @@ int spi_nor_scan(struct spi_nor *nor, co
info = spi_nor_match_id(name);
/* Try to auto-detect if chip name wasn't specified or not found */
if (!info)
@ -51,7 +51,7 @@
if (IS_ERR_OR_NULL(info))
return -ENOENT;
@@ -2847,7 +2855,7 @@ int spi_nor_scan(struct spi_nor *nor, co
@@ -2849,7 +2857,7 @@ int spi_nor_scan(struct spi_nor *nor, co
if (name && info->id_len) {
const struct flash_info *jinfo;

View File

@ -44,7 +44,7 @@ Signed-off-by: Mathieu Olivari <mathieu@codeaurora.org>
select GENERIC_CLOCKEVENTS
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -255,9 +255,11 @@ MACHINE := arch/arm/mach-$(word 1,$(mac
@@ -257,9 +257,11 @@ MACHINE := arch/arm/mach-$(word 1,$(mac
else
MACHINE :=
endif

View File

@ -22,7 +22,7 @@ Signed-off-by: Adrian Panella <ianchi74@outlook.com>
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1939,6 +1939,17 @@ config ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEN
@@ -1934,6 +1934,17 @@ config ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEN
The command-line arguments provided by the boot loader will be
appended to the the device tree bootargs property.

View File

@ -86,7 +86,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
if (!xhci->shared_hcd) {
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -277,6 +277,9 @@ static int xhci_pci_setup(struct usb_hcd
@@ -279,6 +279,9 @@ static int xhci_pci_setup(struct usb_hcd
if (!xhci->sbrn)
pci_read_config_byte(pdev, XHCI_SBRN_OFFSET, &xhci->sbrn);

View File

@ -19,7 +19,7 @@
},
[PORT_NPCM] = {
.name = "Nuvoton 16550",
@@ -2644,6 +2644,11 @@ serial8250_do_set_termios(struct uart_po
@@ -2648,6 +2648,11 @@ serial8250_do_set_termios(struct uart_po
unsigned long flags;
unsigned int baud, quot, frac = 0;

View File

@ -28,7 +28,7 @@ Signed-off-by: Michael Gray <michael.gray@lantisproject.com>
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1939,6 +1939,17 @@ config ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEN
@@ -1934,6 +1934,17 @@ config ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEN
The command-line arguments provided by the boot loader will be
appended to the the device tree bootargs property.

View File

@ -22,7 +22,7 @@ Signed-off-by: Adrian Panella <ianchi74@outlook.com>
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1939,6 +1939,17 @@ config ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEN
@@ -1934,6 +1934,17 @@ config ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEN
The command-line arguments provided by the boot loader will be
appended to the the device tree bootargs property.