Devicetree
 help / color / mirror / Atom feed
* Re: [PATCH v4 5/6] pstore/ram: Introduce max_reason and convert dump_oops
From: Kees Cook @ 2020-05-15 19:53 UTC (permalink / raw)
  To: Pavel Tatashin
  Cc: Petr Mladek, Anton Vorontsov, Colin Cross, Tony Luck,
	Jonathan Corbet, Benson Leung, Rob Herring, Michael Ellerman,
	Benjamin Herrenschmidt, Paul Mackerras, Enric Balletbo i Serra,
	Sergey Senozhatsky, Steven Rostedt, Linux Doc Mailing List, LKML,
	devicetree, linuxppc-dev
In-Reply-To: <CA+CK2bCbAb1EN6xa9a-DRfan6Cv3YgZgPJ1buwUaej7jBRv=Kg@mail.gmail.com>

On Fri, May 15, 2020 at 03:40:14PM -0400, Pavel Tatashin wrote:
>  pdata.dump_oops = dump_oops;
> > +       /* If "max_reason" is set, its value has priority over "dump_oops". */
> > +       if (ramoops_max_reason != -1)
> > +               pdata.max_reason = ramoops_max_reason;
> 
>  (ramoops_max_reason >= 0) might make more sense here, we do not want
> negative max_reason even if it was provided by the user.

Yeah, that's a good point. I'll tweak that. Thanks!

-- 
Kees Cook

^ permalink raw reply

* Re: [PATCH v4 5/6] pstore/ram: Introduce max_reason and convert dump_oops
From: Kees Cook @ 2020-05-15 19:48 UTC (permalink / raw)
  To: Pavel Tatashin
  Cc: Petr Mladek, Anton Vorontsov, Colin Cross, Tony Luck,
	Jonathan Corbet, Benson Leung, Rob Herring, Michael Ellerman,
	Benjamin Herrenschmidt, Paul Mackerras, Enric Balletbo i Serra,
	Sergey Senozhatsky, Steven Rostedt, Linux Doc Mailing List, LKML,
	devicetree, linuxppc-dev
In-Reply-To: <CA+CK2bAvTo1=oLH32-Wdz07F3OP=T+gA6GgzkBH1Q9W8upHkNg@mail.gmail.com>

On Fri, May 15, 2020 at 03:30:27PM -0400, Pavel Tatashin wrote:
> >  #define parse_u32(name, field, default_value) {                                \
> >                 ret = ramoops_parse_dt_u32(pdev, name, default_value,   \
> 
> The series seems to be missing the patch where ramoops_parse_dt_size
> -> ramoops_parse_dt_u32 get renamed, and updated to handle default
> value.

Oops! Sorry, I cut the line in the wrong place for sending out the delta
on top of the pstore tree. :)

It's unchanged from:
https://lore.kernel.org/lkml/20200506211523.15077-4-keescook@chromium.org/

-- 
Kees Cook

^ permalink raw reply

* [PATCH 2/3] Add the bindings for the bq25150 and bq25155 500mA charging ICs from Texas Instruments.
From: Dan Murphy @ 2020-05-15 19:31 UTC (permalink / raw)
  To: sre; +Cc: sspatil, linux-pm, robh, linux-kernel, devicetree,
	Ricardo Rivera-Matos
In-Reply-To: <20200515193148.8502-1-dmurphy@ti.com>

From: Ricardo Rivera-Matos <r-rivera-matos@ti.com>

The BQ2515X family of devices are highly integrated battery management
ICs that integrate the most common functions for wearbale devices
namely a charger, an output voltage rail, ADC for battery and system
monitoring, and a push-button controller.

Datasheets:
http://www.ti.com/lit/ds/symlink/bq25150.pdf
http://www.ti.com/lit/ds/symlink/bq25155.pdf

Signed-off-by: Ricardo Rivera-Matos <r-rivera-matos@ti.com>
---
 .../bindings/power/supply/bq2515x.yaml        | 106 ++++++++++++++++++
 1 file changed, 106 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/power/supply/bq2515x.yaml

diff --git a/Documentation/devicetree/bindings/power/supply/bq2515x.yaml b/Documentation/devicetree/bindings/power/supply/bq2515x.yaml
new file mode 100644
index 000000000000..83487957fc8c
--- /dev/null
+++ b/Documentation/devicetree/bindings/power/supply/bq2515x.yaml
@@ -0,0 +1,106 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+# Copyright (C) 2020 Texas Instruments Incorporated
+%YAML 1.2
+---
+$id: "http://devicetree.org/schemas/power/supply/bq2515x.yaml#"
+$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+
+title: TI bq2515x 500-mA Linear charger family
+
+maintainers:
+  - Dan Murphy <dmurphy@ti.com>
+  - Ricardo Rivera-Matos <r-rivera-matos@ti.com>
+
+description: |
+  The BQ2515x family is a highly integrated battery charge management IC that
+  integrates the most common functions for wearable devices, namely a charger,
+  an output voltage rail, ADC for battery and system monitoring, and
+  push-button controller.
+
+  Specifications about the charger can be found at:
+    http://www.ti.com/lit/ds/symlink/bq25150.pdf
+    http://www.ti.com/lit/ds/symlink/bq25155.pdf
+
+properties:
+  compatible:
+    enum:
+      - ti,bq25150
+      - ti,bq25155
+
+  reg:
+    maxItems: 1
+    description: I2C address of the charger.
+
+  ac-detect-gpios:
+    description: |
+       GPIO used for connecting the bq2515x device PG (AC Detect)
+       pin.  This pin should be used if possible as this is the
+       recommended way to obtain the charger's input PG state.
+       If this pin is not specified a software-based approach for PG
+       detection is used.
+
+  reset-gpios:
+    description: |
+       GPIO used for hardware reset.
+
+  low-power-gpios:
+    description: |
+       GPIO used for low power mode of IC.
+
+  charge-enable-gpios:
+    description: |
+       GPIO used to turn on and off charging.
+
+  constant-charge-current-max-microamp:
+    description: |
+       Maximum charging current in micro Amps.
+    minimum: 50000
+    maximum: 600000
+
+  precharge-current-max-microamp:
+    description: |
+       Maximum precharging current in micro Amps.
+    minimum: 1250
+    maximum: 77500
+
+  input-current-limit-microamp:
+    description: |
+       Maximum input current in micro Amps.
+    minimum: 50000
+    maximum: 500000
+
+  constant-charge-voltage-max-microvolt:
+    description: |
+       Maximum charging voltage in micro volts.
+    minimum: 3600000
+    maximum: 4600000
+
+required:
+  - compatible
+  - reg
+
+examples:
+  - |
+    bat: battery {
+      compatible = "simple-battery";
+      constant-charge-current-max-microamp = <50000>;
+      precharge-current-microamp = <2500>;
+      constant-charge-voltage-max-microvolt = <4000000>;
+    };
+    #include <dt-bindings/gpio/gpio.h>
+    i2c0 {
+      #address-cells = <1>;
+      #size-cells = <0>;
+
+      bq25150: charger@6b {
+        compatible = "ti,bq25150";
+        reg = <0x6b>;
+        monitored-battery = <&bat>;
+        input-current-limit-microamp = <100000>;
+
+        ac-detect-gpios = <&gpio1 28 GPIO_ACTIVE_HIGH>;
+        reset-gpios = <&gpio0 14 GPIO_ACTIVE_HIGH>;
+        low-power-gpios = <&gpio0 15 GPIO_ACTIVE_HIGH>;
+        charge-enable-gpios = <&gpio0 13 GPIO_ACTIVE_LOW>;
+      };
+    };
-- 
2.26.2


^ permalink raw reply related

* [PATCH 3/3] power: supply: bq25150 introduce the bq25150
From: Dan Murphy @ 2020-05-15 19:31 UTC (permalink / raw)
  To: sre; +Cc: sspatil, linux-pm, robh, linux-kernel, devicetree,
	Ricardo Rivera-Matos
In-Reply-To: <20200515193148.8502-1-dmurphy@ti.com>

From: Ricardo Rivera-Matos <r-rivera-matos@ti.com>

Introduce the bq2515x family of chargers.

The BQ2515X family of devices are highly integrated battery management
ICs that integrate the most common functions for wearbale devices
namely a charger, an output voltage rail, ADC for battery and system
monitoring, and a push-button controller.

Datasheets:
	bq25150 - http://www.ti.com/lit/ds/symlink/bq25150.pdf
	bq25155 - http://www.ti.com/lit/ds/symlink/bq25155.pdf

Signed-off-by: Ricardo Rivera-Matos <r-rivera-matos@ti.com>
---
 drivers/power/supply/Kconfig           |   13 +
 drivers/power/supply/Makefile          |    1 +
 drivers/power/supply/bq2515x_charger.c | 1176 ++++++++++++++++++++++++
 3 files changed, 1190 insertions(+)
 create mode 100644 drivers/power/supply/bq2515x_charger.c

diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig
index f3424fdce341..266193301e2d 100644
--- a/drivers/power/supply/Kconfig
+++ b/drivers/power/supply/Kconfig
@@ -589,6 +589,19 @@ config CHARGER_BQ24735
 	help
 	  Say Y to enable support for the TI BQ24735 battery charger.
 
+config CHARGER_BQ2515X
+	tristate "TI BQ2515X battery charger family"
+	depends on I2C
+	depends on GPIOLIB || COMPILE_TEST
+	select REGMAP_I2C
+	help
+	  Say Y to enable support for the TI BQ2515X family of battery
+	  charging integrated circuits. The BQ2515X are highly integrated
+	  battery charge management ICs that integrate the most common
+	  functions for wearable devices, namely a charger, an output voltage
+	  rail, ADC for battery and system monitoring, and push-button
+	  controller.
+
 config CHARGER_BQ25890
 	tristate "TI BQ25890 battery charger driver"
 	depends on I2C
diff --git a/drivers/power/supply/Makefile b/drivers/power/supply/Makefile
index 6c7da920ea83..8fcc175a7e22 100644
--- a/drivers/power/supply/Makefile
+++ b/drivers/power/supply/Makefile
@@ -80,6 +80,7 @@ obj-$(CONFIG_CHARGER_BQ2415X)	+= bq2415x_charger.o
 obj-$(CONFIG_CHARGER_BQ24190)	+= bq24190_charger.o
 obj-$(CONFIG_CHARGER_BQ24257)	+= bq24257_charger.o
 obj-$(CONFIG_CHARGER_BQ24735)	+= bq24735-charger.o
+obj-$(CONFIG_CHARGER_BQ2515X)	+= bq2515x_charger.o
 obj-$(CONFIG_CHARGER_BQ25890)	+= bq25890_charger.o
 obj-$(CONFIG_CHARGER_SMB347)	+= smb347-charger.o
 obj-$(CONFIG_CHARGER_TPS65090)	+= tps65090-charger.o
diff --git a/drivers/power/supply/bq2515x_charger.c b/drivers/power/supply/bq2515x_charger.c
new file mode 100644
index 000000000000..78311168b171
--- /dev/null
+++ b/drivers/power/supply/bq2515x_charger.c
@@ -0,0 +1,1176 @@
+// SPDX-License-Identifier: GPL-2.0
+// BQ2515X Battery Charger Driver
+// Copyright (C) 2020 Texas Instruments Incorporated - http://www.ti.com/
+
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/gpio/consumer.h>
+#include <linux/power_supply.h>
+#include <linux/regmap.h>
+#include <linux/types.h>
+
+#define BQ2515X_MANUFACTURER "Texas Instruments"
+
+#define BQ2515X_STAT0		0x00
+#define BQ2515X_STAT1		0x01
+#define BQ2515X_STAT2		0x02
+#define BQ2515X_FLAG0		0x03
+#define BQ2515X_FLAG1		0x04
+#define BQ2515X_FLAG2		0x05
+#define BQ2515X_FLAG3		0x06
+#define BQ2515X_MASK0		0x07
+#define BQ2515X_MASK1		0x08
+#define BQ2515X_MASK2		0x09
+#define BQ2515X_MASK3		0x0a
+#define BQ2515X_VBAT_CTRL	0x12
+#define BQ2515X_ICHG_CTRL	0x13
+#define BQ2515X_PCHRGCTRL	0x14
+#define BQ2515X_TERMCTRL	0x15
+#define BQ2515X_BUVLO		0x16
+#define BQ2515X_CHARGERCTRL0	0x17
+#define BQ2515X_CHARGERCTRL1	0x18
+#define BQ2515X_ILIMCTRL	0x19
+#define BQ2515X_LDOCTRL		0x1d
+#define BQ2515X_MRCTRL		0x30
+#define BQ2515X_ICCTRL0		0x35
+#define BQ2515X_ICCTRL1		0x36
+#define BQ2515X_ICCTRL2		0x37
+#define BQ2515X_ADCCTRL0	0x40
+#define BQ2515X_ADCCTRL1	0x41
+#define BQ2515X_ADC_VBAT_M	0x42
+#define BQ2515X_ADC_VBAT_L	0x43
+#define BQ2515X_ADC_TS_M	0x44
+#define BQ2515X_ADC_TS_L	0x45
+#define BQ2515X_ADC_ICHG_M	0x46
+#define BQ2515X_ADC_ICHG_L	0x47
+#define BQ2515X_ADC_ADCIN_M	0x48
+#define BQ2515X_ADC_ADCIN_L	0x49
+#define BQ2515X_ADC_VIN_M	0x4a
+#define BQ2515X_ADC_VIN_L	0x4b
+#define BQ2515X_ADC_PMID_M	0x4c
+#define BQ2515X_ADC_PMID_L	0x4d
+#define BQ2515X_ADC_IIN_M	0x4e
+#define BQ2515X_ADC_IIN_L	0x4f
+#define BQ2515X_ADC_COMP1_M	0x52
+#define BQ2515X_ADC_COMP1_L	0X53
+#define BQ2515X_ADC_COMP2_M	0X54
+#define BQ2515X_ADC_COMP2_L	0x55
+#define BQ2515X_ADC_COMP3_M	0x56
+#define BQ2515X_ADC_COMP3_L	0x57
+#define BQ2515X_ADC_READ_EN	0x58
+#define BQ2515X_TS_FASTCHGCTRL	0x61
+#define BQ2515X_TS_COLD		0x62
+#define BQ2515X_TS_COOL		0x63
+#define BQ2515X_TS_WARM		0x64
+#define BQ2515X_TS_HOT		0x65
+#define BQ2515X_DEVICE_ID	0x6f
+
+#define BQ2515X_DEFAULT_ICHG_UA		10000
+#define BQ25150_DEFAULT_ILIM_UA		100000
+#define BQ25155_DEFAULT_ILIM_UA		500000
+#define BQ2515X_DEFAULT_VBAT_REG_UV	4200000
+#define BQ2515X_DEFAULT_IPRECHARGE_UA	2500
+
+#define BQ2515X_DIVISOR				65536
+#define BQ2515X_VBAT_BASE_VOLT			3600000
+#define BQ2515X_VBAT_REG_MAX			4600000
+#define BQ2515X_VBAT_REG_MIN			3600000
+#define BQ2515X_VBAT_STEP_UV			10000
+#define BQ2515X_UV_FACTOR			1000000
+#define BQ2515X_VBAT_MULTIPLIER			6
+#define BQ2515X_ICHG_DIVISOR			52429
+#define BQ2515X_ICHG_CURR_STEP_THRESH_UA	318750
+#define BQ2515X_ICHG_MIN_UA			0
+#define BQ2515X_ICHG_MAX_UA			500000
+#define BQ2515X_ICHG_RNG_1B0_UA			1250
+#define BQ2515X_ICHG_RNG_1B1_UA			2500
+#define BQ2515X_VLOWV_SEL_1B0_UV		3000000
+#define BQ2515X_VLOWV_SEL_1B1_UV		2800000
+#define BQ2515X_PRECHRG_ICHRG_RNGE_1875_UA	18750
+#define BQ2515X_PRECHRG_ICHRG_RNGE_3750_UA	37500
+#define BQ2515X_TWAKE2_MIN_US			1700000
+#define BQ2515X_TWAKE2_MAX_US			2300000
+
+#define BQ2515X_ILIM_150MA	0x2
+#define BQ2515X_ILIM_MASK	0x7
+#define BQ2515X_HEALTH_MASK	0xf
+#define BQ2515X_ICHGRNG_MASK	0x80
+#define BQ2515X_STAT0_MASK	0x0f
+#define BQ2515X_STAT1_MASK	0x1f
+#define BQ2515X_PRECHARGE_MASK	0x1f
+
+#define BQ2515X_TS_HOT_STAT		BIT(0)
+#define BQ2515X_TS_WARM_STAT		BIT(1)
+#define BQ2515X_TS_COOL_STAT		BIT(2)
+#define BQ2515X_TS_COLD_STAT		BIT(3)
+#define BQ2515X_SAFETY_TIMER_EXP	BIT(5)
+
+#define BQ2515X_EN_VBAT_READ		BIT(3)
+#define BQ2515X_EN_ICHG_READ		BIT(5)
+
+#define BQ2515X_VIN_GOOD		BIT(0)
+#define BQ2515X_CHRG_DONE		BIT(5)
+#define BQ2515X_CV_CHRG_MODE		BIT(6)
+
+#define BQ2515X_VIN_OVP_FAULT_STAT	BIT(7)
+
+#define BQ2515X_WATCHDOG_DISABLE	BIT(4)
+
+#define BQ2515X_ICHARGE_RANGE		BIT(7)
+
+#define BQ2515X_VLOWV_SEL		BIT(5)
+
+#define BQ2515X_CHARGER_DISABLE		BIT(0)
+
+#define BQ2515X_HWRESET_14S_WD		BIT(1)
+
+static const int bq2515x_ilim_lvl_values[] = {
+	50000, 100000, 150000, 200000, 300000, 400000, 500000, 600000
+};
+
+/**
+ * struct bq2515x_init_data -
+ * @ilim: input current limit
+ */
+struct bq2515x_init_data {
+	int ilim;
+};
+
+enum bq2515x_id {
+	BQ25150,
+	BQ25155,
+};
+
+/**
+ * struct bq2515x_device -
+ * @mains: mains properties
+ * @battery: battery properties
+ * @client: i2c client structure
+ * @regmap: register map structure
+ * @dev: device structure
+ * @id: enumeration of device ids
+ *
+ * @reset_gpio: manual reset (MR) pin
+ * @lp_gpio: low power mode pin
+ * @ac_detect_gpio: power good (PG) pin
+ * @ce_gpio: charge enable (CE) pin
+ *
+ * @model_name: string value describing device model
+ * @device_id: value of device_id
+ * @mains_online: boolean value indicating power supply online
+ *
+ * @bq2515x_init_data init_data: charger initialization data structure
+ */
+struct bq2515x_device {
+	struct power_supply *mains;
+	struct power_supply *battery;
+	struct i2c_client *client;
+	struct regmap *regmap;
+	struct device *dev;
+	enum bq2515x_id id;
+
+	struct gpio_desc *reset_gpio;
+	struct gpio_desc *lp_gpio;
+	struct gpio_desc *ac_detect_gpio;
+	struct gpio_desc *ce_gpio;
+
+	char model_name[I2C_NAME_SIZE];
+	int device_id;
+	bool mains_online;
+
+	struct bq2515x_init_data init_data;
+};
+
+static struct reg_default bq25150_reg_defs[] = {
+	{BQ2515X_FLAG0, 0x0},
+	{BQ2515X_FLAG1, 0x0},
+	{BQ2515X_FLAG2, 0x0},
+	{BQ2515X_FLAG3, 0x0},
+	{BQ2515X_MASK0, 0x0},
+	{BQ2515X_MASK1, 0x0},
+	{BQ2515X_MASK2, 0x71},
+	{BQ2515X_MASK3, 0x0},
+	{BQ2515X_VBAT_CTRL, 0x3C},
+	{BQ2515X_ICHG_CTRL, 0x8},
+	{BQ2515X_PCHRGCTRL, 0x2},
+	{BQ2515X_TERMCTRL, 0x14},
+	{BQ2515X_BUVLO, 0x0},
+	{BQ2515X_CHARGERCTRL0, 0x82},
+	{BQ2515X_CHARGERCTRL1, 0x42},
+	{BQ2515X_ILIMCTRL, 0x1},
+	{BQ2515X_LDOCTRL, 0xB0},
+	{BQ2515X_MRCTRL, 0x2A},
+	{BQ2515X_ICCTRL0, 0x10},
+	{BQ2515X_ICCTRL1, 0x0},
+	{BQ2515X_ICCTRL2, 0x0},
+	{BQ2515X_ADCCTRL0, 0x2},
+	{BQ2515X_ADCCTRL1, 0x40},
+	{BQ2515X_ADC_COMP1_M, 0x23},
+	{BQ2515X_ADC_COMP1_L, 0x20},
+	{BQ2515X_ADC_COMP2_M, 0x38},
+	{BQ2515X_ADC_COMP2_L, 0x90},
+	{BQ2515X_ADC_COMP3_M, 0x0},
+	{BQ2515X_ADC_COMP3_L, 0x0},
+	{BQ2515X_ADC_READ_EN, 0x0},
+	{BQ2515X_TS_FASTCHGCTRL, 0x34},
+	{BQ2515X_TS_COLD, 0x7C},
+	{BQ2515X_TS_COOL, 0x6D},
+	{BQ2515X_TS_WARM, 0x38},
+	{BQ2515X_TS_HOT, 0x27},
+	{BQ2515X_DEVICE_ID, 0x20},
+};
+
+static struct reg_default bq25155_reg_defs[] = {
+	{BQ2515X_FLAG0, 0x0},
+	{BQ2515X_FLAG1, 0x0},
+	{BQ2515X_FLAG2, 0x0},
+	{BQ2515X_FLAG3, 0x0},
+	{BQ2515X_MASK0, 0x0},
+	{BQ2515X_MASK1, 0x0},
+	{BQ2515X_MASK2, 0x71},
+	{BQ2515X_MASK3, 0x0},
+	{BQ2515X_VBAT_CTRL, 0x3C},
+	{BQ2515X_ICHG_CTRL, 0x8},
+	{BQ2515X_PCHRGCTRL, 0x2},
+	{BQ2515X_TERMCTRL, 0x14},
+	{BQ2515X_BUVLO, 0x0},
+	{BQ2515X_CHARGERCTRL0, 0x82},
+	{BQ2515X_CHARGERCTRL1, 0xC2},
+	{BQ2515X_ILIMCTRL, 0x6},
+	{BQ2515X_LDOCTRL, 0xB0},
+	{BQ2515X_MRCTRL, 0x2A},
+	{BQ2515X_ICCTRL0, 0x10},
+	{BQ2515X_ICCTRL1, 0x0},
+	{BQ2515X_ICCTRL2, 0x40},
+	{BQ2515X_ADCCTRL0, 0x2},
+	{BQ2515X_ADCCTRL1, 0x40},
+	{BQ2515X_ADC_COMP1_M, 0x23},
+	{BQ2515X_ADC_COMP1_L, 0x20},
+	{BQ2515X_ADC_COMP2_M, 0x38},
+	{BQ2515X_ADC_COMP2_L, 0x90},
+	{BQ2515X_ADC_COMP3_M, 0x0},
+	{BQ2515X_ADC_COMP3_L, 0x0},
+	{BQ2515X_ADC_READ_EN, 0x0},
+	{BQ2515X_TS_FASTCHGCTRL, 0x34},
+	{BQ2515X_TS_COLD, 0x7C},
+	{BQ2515X_TS_COOL, 0x6D},
+	{BQ2515X_TS_WARM, 0x38},
+	{BQ2515X_TS_HOT, 0x27},
+	{BQ2515X_DEVICE_ID, 0x35},
+};
+
+static bool bq2515x_is_ps_online(struct bq2515x_device *bq2515x)
+{
+	return bq2515x->mains_online;
+}
+
+static int bq2515x_wake_up(struct bq2515x_device *bq2515x)
+{
+	int ret;
+	int val;
+
+	/* Read the STAT register if we can read it then the device is out
+	 * of ship mode.  If the register cannot be read then attempt to wake
+	 * it up and enable the ADC.
+	 */
+	ret = regmap_read(bq2515x->regmap, BQ2515X_STAT0, &val);
+	if (ret)
+		return ret;
+
+	/* Need to toggle LP and bring device out of ship mode. The device
+	 * will exit the ship mode when the MR pin is held low for at least
+	 * t_WAKE2 as shown in section 8.3.7.1 of the datasheet.
+	 */
+	gpiod_set_value_cansleep(bq2515x->lp_gpio, 0);
+
+	gpiod_set_value_cansleep(bq2515x->reset_gpio, 0);
+	usleep_range(BQ2515X_TWAKE2_MIN_US, BQ2515X_TWAKE2_MAX_US);
+	gpiod_set_value_cansleep(bq2515x->reset_gpio, 1);
+
+	return regmap_write(bq2515x->regmap, BQ2515X_ADC_READ_EN,
+				(BQ2515X_EN_VBAT_READ | BQ2515X_EN_ICHG_READ));
+}
+
+static int bq2515x_update_ps_status(struct bq2515x_device *bq2515x)
+{
+	bool dc = false;
+	unsigned int val;
+	int ret;
+
+	if (bq2515x->ac_detect_gpio)
+		val = gpiod_get_value_cansleep(bq2515x->ac_detect_gpio);
+	else {
+		ret = regmap_read(bq2515x->regmap, BQ2515X_STAT0, &val);
+		if (ret)
+			return ret;
+	}
+
+	dc = val & BQ2515X_VIN_GOOD;
+
+	ret = bq2515x->mains_online != dc;
+
+	bq2515x->mains_online = dc;
+
+	return ret;
+}
+
+static int bq2515x_disable_watchdog_timers(struct bq2515x_device *bq2515x)
+{
+	int ret;
+
+	ret = regmap_update_bits(bq2515x->regmap, BQ2515X_CHARGERCTRL0,
+			BQ2515X_WATCHDOG_DISABLE, BQ2515X_WATCHDOG_DISABLE);
+	if (ret)
+		return ret;
+
+	return regmap_update_bits(bq2515x->regmap, BQ2515X_ICCTRL2,
+						BQ2515X_HWRESET_14S_WD, 0);
+}
+
+static int bq2515x_get_battery_voltage_now(struct bq2515x_device *bq2515x)
+{
+	int ret;
+	int vbat_msb;
+	int vbat_lsb;
+	uint32_t vbat_measurement;
+
+	if (!bq2515x_is_ps_online(bq2515x))
+		bq2515x_wake_up(bq2515x);
+
+	ret = regmap_read(bq2515x->regmap, BQ2515X_ADC_VBAT_M, &vbat_msb);
+	if (ret)
+		return ret;
+
+	ret = regmap_read(bq2515x->regmap, BQ2515X_ADC_VBAT_L, &vbat_lsb);
+	if (ret)
+		return ret;
+
+	vbat_measurement = (vbat_msb << 8) | vbat_lsb;
+
+	return vbat_measurement * (BQ2515X_UV_FACTOR / BQ2515X_DIVISOR) *
+						BQ2515X_VBAT_MULTIPLIER;
+}
+
+static int bq2515x_get_battery_current_now(struct bq2515x_device *bq2515x)
+{
+	int ret;
+	int ichg_msb;
+	int ichg_lsb;
+	uint32_t ichg_measurement;
+	u16 ichg_multiplier = BQ2515X_ICHG_RNG_1B0_UA;
+	unsigned int ichg_reg_code, reg_code;
+	unsigned int icharge_range = 0, pchrgctrl;
+	unsigned int buvlo, vlowv_sel, vlowv = BQ2515X_VLOWV_SEL_1B0_UV;
+
+	if (!bq2515x_is_ps_online(bq2515x))
+		return -ENODATA;
+
+	ret = regmap_read(bq2515x->regmap, BQ2515X_ADC_ICHG_M, &ichg_msb);
+	if (ret)
+		return ret;
+
+	ret = regmap_read(bq2515x->regmap, BQ2515X_ADC_ICHG_L, &ichg_lsb);
+	if (ret)
+		return ret;
+
+	ichg_measurement = (ichg_msb << 8) | ichg_lsb;
+
+	ret = regmap_read(bq2515x->regmap, BQ2515X_BUVLO, &buvlo);
+	if (ret)
+		return ret;
+
+	vlowv_sel = buvlo & BQ2515X_VLOWV_SEL;
+
+	if (vlowv_sel)
+		vlowv = BQ2515X_VLOWV_SEL_1B1_UV;
+
+	if (bq2515x_get_battery_voltage_now(bq2515x) < vlowv) {
+		ret = regmap_read(bq2515x->regmap, BQ2515X_PCHRGCTRL,
+								&pchrgctrl);
+		if (ret)
+			return ret;
+
+		reg_code = pchrgctrl & BQ2515X_PRECHARGE_MASK;
+	} else {
+		ret = regmap_read(bq2515x->regmap, BQ2515X_ICHG_CTRL,
+							&ichg_reg_code);
+		if (ret)
+			return ret;
+
+		reg_code = ichg_reg_code;
+	}
+
+	ret = regmap_read(bq2515x->regmap, BQ2515X_PCHRGCTRL, &pchrgctrl);
+	if (ret)
+		return ret;
+
+	icharge_range = pchrgctrl & BQ2515X_ICHARGE_RANGE;
+
+	if (icharge_range)
+		ichg_multiplier = BQ2515X_ICHG_RNG_1B1_UA;
+
+	return reg_code * (ichg_multiplier * ichg_measurement /
+							BQ2515X_ICHG_DIVISOR);
+}
+
+static bool bq2515x_get_charge_disable(struct bq2515x_device *bq2515x)
+{
+	int ret;
+	int ce_pin;
+	int icctrl2;
+	int charger_disable;
+
+	ce_pin = gpiod_get_value_cansleep(bq2515x->ce_gpio);
+
+	ret = regmap_read(bq2515x->regmap, BQ2515X_ICCTRL2, &icctrl2);
+	if (ret)
+		return ret;
+
+	charger_disable = icctrl2 & BQ2515X_CHARGER_DISABLE;
+
+	if (charger_disable || ce_pin)
+		return true;
+
+	return false;
+}
+
+static int bq2515x_set_charge_disable(struct bq2515x_device *bq2515x, int val)
+{
+	gpiod_set_value_cansleep(bq2515x->ce_gpio, val);
+
+	return regmap_update_bits(bq2515x->regmap, BQ2515X_ICCTRL2,
+					BQ2515X_CHARGER_DISABLE, val);
+}
+
+static int bq2515x_get_const_charge_current(struct bq2515x_device *bq2515x)
+{
+	int ret;
+	u16 ichg_multiplier = BQ2515X_ICHG_RNG_1B0_UA;
+	unsigned int ichg_reg_code;
+	unsigned int pchrgctrl;
+	unsigned int icharge_range;
+
+	ret = regmap_read(bq2515x->regmap, BQ2515X_ICHG_CTRL, &ichg_reg_code);
+	if (ret)
+		return ret;
+
+	ret = regmap_read(bq2515x->regmap, BQ2515X_PCHRGCTRL, &pchrgctrl);
+	if (ret)
+		return ret;
+
+	icharge_range = pchrgctrl & BQ2515X_ICHARGE_RANGE;
+
+	if (icharge_range)
+		ichg_multiplier = BQ2515X_ICHG_RNG_1B1_UA;
+
+	return ichg_reg_code * ichg_multiplier;
+}
+
+static int bq2515x_set_const_charge_current(struct bq2515x_device *bq2515x,
+								int val)
+{
+	int ret;
+	unsigned int ichg_reg_code;
+	u16 ichg_multiplier = BQ2515X_ICHG_RNG_1B0_UA;
+	unsigned int icharge_range = 0;
+
+	if (val > BQ2515X_ICHG_MAX_UA || val < BQ2515X_ICHG_MIN_UA)
+		return -EINVAL;
+
+	if (val > BQ2515X_ICHG_CURR_STEP_THRESH_UA) {
+		ichg_multiplier = BQ2515X_ICHG_RNG_1B1_UA;
+		icharge_range = BQ2515X_ICHARGE_RANGE;
+	}
+
+	bq2515x_set_charge_disable(bq2515x, 1);
+
+	ret = regmap_update_bits(bq2515x->regmap, BQ2515X_PCHRGCTRL,
+					BQ2515X_ICHARGE_RANGE, icharge_range);
+	if (ret)
+		return ret;
+
+	ichg_reg_code = val / ichg_multiplier;
+
+	ret = regmap_write(bq2515x->regmap, BQ2515X_ICHG_CTRL, ichg_reg_code);
+	if (ret)
+		return ret;
+
+	return bq2515x_set_charge_disable(bq2515x, 0);
+}
+
+static int bq2515x_get_precharge_current(struct bq2515x_device *bq2515x)
+{
+	int ret;
+	unsigned int pchrgctrl;
+	unsigned int icharge_range;
+	u16 precharge_multiplier = BQ2515X_ICHG_RNG_1B0_UA;
+	unsigned int precharge_reg_code;
+
+	ret = regmap_read(bq2515x->regmap, BQ2515X_PCHRGCTRL, &pchrgctrl);
+	if (ret)
+		return ret;
+
+	icharge_range = pchrgctrl & BQ2515X_ICHARGE_RANGE;
+
+	if (icharge_range)
+		precharge_multiplier = BQ2515X_ICHG_RNG_1B1_UA;
+
+	precharge_reg_code = pchrgctrl & BQ2515X_PRECHARGE_MASK;
+
+	return precharge_reg_code * precharge_multiplier;
+}
+
+static int bq2515x_set_precharge_current(struct bq2515x_device *bq2515x,
+					int val)
+{
+	int ret;
+	unsigned int pchrgctrl;
+	unsigned int icharge_range;
+	unsigned int precharge_reg_code;
+	u16 precharge_multiplier = BQ2515X_ICHG_RNG_1B0_UA;
+	u16 precharge_max_ua = BQ2515X_PRECHRG_ICHRG_RNGE_1875_UA;
+
+	ret = regmap_read(bq2515x->regmap, BQ2515X_PCHRGCTRL, &pchrgctrl);
+	if (ret)
+		return ret;
+
+	icharge_range = pchrgctrl & BQ2515X_ICHARGE_RANGE;
+
+	if (icharge_range) {
+		precharge_max_ua = BQ2515X_PRECHRG_ICHRG_RNGE_3750_UA;
+		precharge_multiplier = BQ2515X_ICHG_RNG_1B1_UA;
+	}
+	if (val > precharge_max_ua || val < BQ2515X_ICHG_MIN_UA)
+		return -EINVAL;
+
+	precharge_reg_code = val / precharge_multiplier;
+
+	ret = bq2515x_set_charge_disable(bq2515x, 1);
+	if (ret)
+		return ret;
+
+	ret = regmap_update_bits(bq2515x->regmap, BQ2515X_PCHRGCTRL,
+				BQ2515X_PRECHARGE_MASK, precharge_reg_code);
+	if (ret)
+		return ret;
+
+	return bq2515x_set_charge_disable(bq2515x, 0);
+}
+
+static int bq2515x_charging_status(struct bq2515x_device *bq2515x,
+				   union power_supply_propval *val)
+{
+	bool status0_no_fault;
+	bool status1_no_fault;
+	bool ce_status;
+	bool charge_done;
+	unsigned int status;
+	int ret;
+
+	if (!bq2515x_is_ps_online(bq2515x)) {
+		val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
+		return 0;
+	}
+
+	ret = regmap_read(bq2515x->regmap, BQ2515X_STAT0, &status);
+	if (ret)
+		return ret;
+
+	/*
+	 * The code block below is used to determine if any faults from the
+	 * STAT0 register are disbaling charging or if the charge has completed
+	 * according to the CHARGE_DONE_STAT bit.
+	 */
+	if (((status & BQ2515X_STAT0_MASK) == true) &
+			((status & BQ2515X_CHRG_DONE) == false)) {
+		status0_no_fault = true;
+		charge_done = false;
+	} else if (status & BQ2515X_CHRG_DONE) {
+		charge_done = true;
+		status0_no_fault = false;
+	} else {
+		status0_no_fault = false;
+		charge_done = false;
+	}
+
+	ret = regmap_read(bq2515x->regmap, BQ2515X_STAT1, &status);
+	if (ret)
+		return ret;
+	/*
+	 * The code block below is used to determine if any faults from the
+	 * STAT1 register are disbaling charging
+	 */
+	if ((status & BQ2515X_STAT1_MASK) == false)
+		status1_no_fault = true;
+	else
+		status1_no_fault = false;
+
+	ce_status = (!bq2515x_get_charge_disable(bq2515x));
+
+	/*
+	 * If there are no faults and charging is enabled, then status is
+	 * charging. Otherwise, if charging is complete, then status is full.
+	 * Otherwise, if a fault exists or charging is disabled, then status is
+	 * not charging
+	 */
+	if (status0_no_fault & status1_no_fault & ce_status)
+		val->intval = POWER_SUPPLY_STATUS_CHARGING;
+	else if (charge_done)
+		val->intval = POWER_SUPPLY_STATUS_FULL;
+	else if (!(status0_no_fault & status1_no_fault & ce_status))
+		val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
+
+	return 0;
+}
+
+static int bq2515x_get_batt_reg(struct bq2515x_device *bq2515x)
+{
+	int vbat_reg_code;
+	int ret;
+
+	ret = regmap_read(bq2515x->regmap, BQ2515X_VBAT_CTRL, &vbat_reg_code);
+	if (ret)
+		return ret;
+
+	return BQ2515X_VBAT_BASE_VOLT + vbat_reg_code * BQ2515X_VBAT_STEP_UV;
+}
+
+static int bq2515x_set_batt_reg(struct bq2515x_device *bq2515x, int val)
+{
+	int vbat_reg_code;
+
+	if (val > BQ2515X_VBAT_REG_MAX || val < BQ2515X_VBAT_REG_MIN)
+		return -EINVAL;
+
+	vbat_reg_code = (val - BQ2515X_VBAT_BASE_VOLT) / BQ2515X_VBAT_STEP_UV;
+
+	return regmap_write(bq2515x->regmap, BQ2515X_VBAT_CTRL, vbat_reg_code);
+}
+
+static int bq2515x_get_ilim_lvl(struct bq2515x_device *bq2515x)
+{
+	int ret;
+	int ilimctrl;
+
+	ret = regmap_read(bq2515x->regmap, BQ2515X_ILIMCTRL, &ilimctrl);
+	if (ret)
+		return ret;
+
+	return bq2515x_ilim_lvl_values[ilimctrl & BQ2515X_ILIM_MASK];
+}
+
+static int bq2515x_set_ilim_lvl(struct bq2515x_device *bq2515x, int val)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(bq2515x_ilim_lvl_values); i++) {
+		if (val == bq2515x_ilim_lvl_values[i])
+			break;
+
+		if (val > bq2515x_ilim_lvl_values[i - 1] &&
+		    val < bq2515x_ilim_lvl_values[i]) {
+			if (val - bq2515x_ilim_lvl_values[i - 1] <
+			    bq2515x_ilim_lvl_values[i] - val) {
+				i = i - 1;
+				break;
+			}
+		}
+	}
+
+	return regmap_write(bq2515x->regmap, BQ2515X_ILIMCTRL, i);
+}
+
+static int bq2515x_power_supply_property_is_writeable(struct power_supply *psy,
+					enum power_supply_property prop)
+{
+	switch (prop) {
+	case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
+	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
+	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
+	case POWER_SUPPLY_PROP_PRECHARGE_CURRENT:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static int bq2515x_charger_get_health(struct bq2515x_device *bq2515x,
+				      union power_supply_propval *val)
+{
+	int health = POWER_SUPPLY_HEALTH_GOOD;
+	int ret;
+	unsigned int stat1;
+	unsigned int flag3;
+
+	if (!bq2515x_is_ps_online(bq2515x))
+		bq2515x_wake_up(bq2515x);
+
+	ret = regmap_read(bq2515x->regmap, BQ2515X_FLAG3, &flag3);
+	if (ret)
+		return ret;
+
+	ret = regmap_read(bq2515x->regmap, BQ2515X_STAT1, &stat1);
+	if (ret)
+		return ret;
+
+	if (stat1 & BQ2515X_HEALTH_MASK) {
+		switch (stat1 & BQ2515X_HEALTH_MASK) {
+		case BQ2515X_TS_HOT_STAT:
+			health = POWER_SUPPLY_HEALTH_HOT;
+			break;
+		case BQ2515X_TS_WARM_STAT:
+			health = POWER_SUPPLY_HEALTH_WARM;
+			break;
+		case BQ2515X_TS_COOL_STAT:
+			health = POWER_SUPPLY_HEALTH_COOL;
+			break;
+		case BQ2515X_TS_COLD_STAT:
+			health = POWER_SUPPLY_HEALTH_COLD;
+			break;
+		default:
+			health = POWER_SUPPLY_HEALTH_UNKNOWN;
+			break;
+		}
+	}
+
+	if (stat1 & BQ2515X_VIN_OVP_FAULT_STAT)
+		health = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
+
+	if (flag3 & BQ2515X_SAFETY_TIMER_EXP)
+		health = POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE;
+
+	val->intval = health;
+	return 0;
+}
+
+static int bq2515x_mains_set_property(struct power_supply *psy,
+		enum power_supply_property prop,
+		const union power_supply_propval *val)
+{
+	struct bq2515x_device *bq2515x = power_supply_get_drvdata(psy);
+	int ret;
+
+	switch (prop) {
+	case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
+		ret = bq2515x_set_ilim_lvl(bq2515x, val->intval);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return ret;
+}
+
+static int bq2515x_battery_set_property(struct power_supply *psy,
+		enum power_supply_property prop,
+		const union power_supply_propval *val)
+{
+	struct bq2515x_device *bq2515x = power_supply_get_drvdata(psy);
+	int ret;
+
+	switch (prop) {
+	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
+		ret = bq2515x_set_batt_reg(bq2515x, val->intval);
+		break;
+	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
+		ret = bq2515x_set_const_charge_current(bq2515x, val->intval);
+		break;
+	case POWER_SUPPLY_PROP_PRECHARGE_CURRENT:
+		ret = bq2515x_set_precharge_current(bq2515x, val->intval);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return ret;
+}
+
+static int bq2515x_mains_get_property(struct power_supply *psy,
+				     enum power_supply_property prop,
+				     union power_supply_propval *val)
+{
+	struct bq2515x_device *bq2515x = power_supply_get_drvdata(psy);
+	int ret = 0;
+
+	switch (prop) {
+	case POWER_SUPPLY_PROP_ONLINE:
+		val->intval = bq2515x->mains_online;
+		break;
+	case POWER_SUPPLY_PROP_HEALTH:
+		ret = bq2515x_charger_get_health(bq2515x, val);
+		if (ret)
+			val->intval = POWER_SUPPLY_HEALTH_UNKNOWN;
+		break;
+	case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
+		ret = bq2515x_get_ilim_lvl(bq2515x);
+		if (ret)
+			return ret;
+
+		val->intval = ret;
+		break;
+	case POWER_SUPPLY_PROP_MODEL_NAME:
+		val->strval = bq2515x->model_name;
+		break;
+	case POWER_SUPPLY_PROP_MANUFACTURER:
+		val->strval = BQ2515X_MANUFACTURER;
+		break;
+	case POWER_SUPPLY_PROP_STATUS:
+		ret = bq2515x_charging_status(bq2515x, val);
+		if (ret)
+			return ret;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	return ret;
+}
+
+static int bq2515x_battery_get_property(struct power_supply *psy,
+				       enum power_supply_property prop,
+				       union power_supply_propval *val)
+{
+	struct bq2515x_device *bq2515x = power_supply_get_drvdata(psy);
+	int ret;
+
+	ret = bq2515x_update_ps_status(bq2515x);
+	if (ret)
+		return ret;
+
+	switch (prop) {
+
+	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+		ret = bq2515x_get_battery_voltage_now(bq2515x);
+		if (ret < 0)
+			return ret;
+
+		val->intval = ret;
+		break;
+	case POWER_SUPPLY_PROP_CURRENT_NOW:
+		ret = bq2515x_get_battery_current_now(bq2515x);
+		if (ret < 0)
+			return ret;
+
+		val->intval = ret;
+		break;
+	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
+		ret = bq2515x_get_const_charge_current(bq2515x);
+		if (ret < 0)
+			return ret;
+
+		val->intval = ret;
+		break;
+	case POWER_SUPPLY_PROP_PRECHARGE_CURRENT:
+		ret = bq2515x_get_precharge_current(bq2515x);
+		if (ret < 0)
+			return ret;
+
+		val->intval = ret;
+		break;
+	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
+		ret = bq2515x_get_batt_reg(bq2515x);
+		if (ret < 0)
+			return ret;
+
+		val->intval = ret;
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static enum power_supply_property bq2515x_battery_properties[] = {
+	POWER_SUPPLY_PROP_VOLTAGE_NOW,
+	POWER_SUPPLY_PROP_CURRENT_NOW,
+	POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT,
+	POWER_SUPPLY_PROP_PRECHARGE_CURRENT,
+	POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE,
+};
+
+static enum power_supply_property bq2515x_charger_properties[] = {
+	POWER_SUPPLY_PROP_ONLINE,
+	POWER_SUPPLY_PROP_STATUS,
+	POWER_SUPPLY_PROP_HEALTH,
+	POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
+	POWER_SUPPLY_PROP_MODEL_NAME,
+	POWER_SUPPLY_PROP_MANUFACTURER,
+};
+
+static struct power_supply_desc bq2515x_mains_desc = {
+	.name			= "bq2515x-mains",
+	.type			= POWER_SUPPLY_TYPE_MAINS,
+	.get_property		= bq2515x_mains_get_property,
+	.set_property		= bq2515x_mains_set_property,
+	.properties		= bq2515x_charger_properties,
+	.num_properties		= ARRAY_SIZE(bq2515x_charger_properties),
+	.property_is_writeable	= bq2515x_power_supply_property_is_writeable,
+};
+
+static struct power_supply_desc bq2515x_battery_desc = {
+	.name			= "bq2515x-battery",
+	.type			= POWER_SUPPLY_TYPE_BATTERY,
+	.get_property		= bq2515x_battery_get_property,
+	.set_property		= bq2515x_battery_set_property,
+	.properties		= bq2515x_battery_properties,
+	.num_properties		= ARRAY_SIZE(bq2515x_battery_properties),
+	.property_is_writeable	= bq2515x_power_supply_property_is_writeable,
+};
+
+static int bq2515x_power_supply_register(struct bq2515x_device *bq2515x,
+							struct device *dev)
+{
+	struct power_supply_config psy_cfg = { .drv_data = bq2515x,
+						.of_node = dev->of_node, };
+
+	bq2515x->mains = devm_power_supply_register(bq2515x->dev,
+						    &bq2515x_mains_desc,
+						    &psy_cfg);
+	if (IS_ERR(bq2515x->mains))
+		return -EINVAL;
+
+	bq2515x->battery = devm_power_supply_register(bq2515x->dev,
+						      &bq2515x_battery_desc,
+						      &psy_cfg);
+	if (IS_ERR(bq2515x->battery))
+		return -EINVAL;
+
+	return 0;
+}
+
+static int bq2515x_hw_init(struct bq2515x_device *bq2515x)
+{
+	int ret;
+	struct power_supply_battery_info bat_info = { };
+
+	ret = bq2515x_disable_watchdog_timers(bq2515x);
+	if (ret)
+		return ret;
+
+	if (bq2515x->init_data.ilim) {
+		ret = bq2515x_set_ilim_lvl(bq2515x, bq2515x->init_data.ilim);
+		if (ret)
+			return ret;
+	}
+
+	ret = power_supply_get_battery_info(bq2515x->mains, &bat_info);
+	if (ret) {
+		dev_warn(bq2515x->dev, "battery info missing, default values will be applied\n");
+
+		bat_info.constant_charge_current_max_ua =
+						BQ2515X_DEFAULT_ICHG_UA;
+
+		bat_info.constant_charge_voltage_max_uv =
+						BQ2515X_DEFAULT_VBAT_REG_UV;
+
+		bat_info.precharge_current_ua =
+						BQ2515X_DEFAULT_IPRECHARGE_UA;
+	}
+
+	ret = bq2515x_set_const_charge_current(bq2515x,
+			bat_info.constant_charge_current_max_ua);
+	if (ret)
+		return ret;
+
+	ret = bq2515x_set_batt_reg(bq2515x,
+			bat_info.constant_charge_voltage_max_uv);
+	if (ret)
+		return ret;
+
+	return bq2515x_set_precharge_current(bq2515x,
+			bat_info.precharge_current_ua);
+}
+
+static int bq2515x_read_properties(struct bq2515x_device *bq2515x)
+{
+	int ret;
+
+	ret = device_property_read_u32(bq2515x->dev,
+				      "input-current-limit-microamp",
+				      &bq2515x->init_data.ilim);
+	if (ret)
+		switch (bq2515x->device_id) {
+		case BQ25150:
+			bq2515x->init_data.ilim = BQ25150_DEFAULT_ILIM_UA;
+			break;
+		case BQ25155:
+			bq2515x->init_data.ilim = BQ25155_DEFAULT_ILIM_UA;
+			break;
+		}
+
+	bq2515x->ac_detect_gpio = devm_gpiod_get_optional(bq2515x->dev,
+						   "ac-detect", GPIOD_IN);
+	if (IS_ERR(bq2515x->ac_detect_gpio)) {
+		ret = PTR_ERR(bq2515x->ac_detect_gpio);
+		if (ret != -ENODEV) {
+			dev_err(bq2515x->dev, "Failed to get ac detect: %d\n",
+								ret);
+			return ret;
+		}
+		bq2515x->ac_detect_gpio = NULL;
+	}
+
+	bq2515x->reset_gpio = devm_gpiod_get_optional(bq2515x->dev,
+						   "reset", GPIOD_OUT_LOW);
+	if (IS_ERR(bq2515x->reset_gpio)) {
+		ret = PTR_ERR(bq2515x->reset_gpio);
+		if (ret != -ENODEV) {
+			dev_err(bq2515x->dev, "Failed to get reset: %d\n",
+								ret);
+			return ret;
+		}
+		bq2515x->reset_gpio = NULL;
+	}
+
+	bq2515x->lp_gpio = devm_gpiod_get_optional(bq2515x->dev, "low-power",
+						   GPIOD_OUT_LOW);
+	if (IS_ERR(bq2515x->lp_gpio)) {
+		ret = PTR_ERR(bq2515x->lp_gpio);
+		if (ret != -ENODEV) {
+			dev_err(bq2515x->dev, "Failed to get low power: %d\n",
+								ret);
+			return ret;
+		}
+		bq2515x->lp_gpio = NULL;
+	}
+
+	bq2515x->ce_gpio = devm_gpiod_get_optional(bq2515x->dev,
+						   "charge-enable",
+						   GPIOD_OUT_LOW);
+	if (IS_ERR(bq2515x->ce_gpio)) {
+		ret = PTR_ERR(bq2515x->ce_gpio);
+		if (ret != -ENODEV) {
+			dev_err(bq2515x->dev, "Failed to get ce %d\n", ret);
+			return ret;
+		}
+		bq2515x->ce_gpio = NULL;
+	}
+
+	return 0;
+}
+
+static bool bq2515x_volatile_register(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case BQ2515X_STAT0 ... BQ2515X_FLAG3:
+	case BQ2515X_ADC_VBAT_M ... BQ2515X_ADC_IIN_L:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static const struct regmap_config bq25150_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+
+	.max_register		= BQ2515X_DEVICE_ID,
+	.reg_defaults		= bq25150_reg_defs,
+	.num_reg_defaults	= ARRAY_SIZE(bq25150_reg_defs),
+	.cache_type		= REGCACHE_RBTREE,
+	.volatile_reg		= bq2515x_volatile_register,
+};
+
+static const struct regmap_config bq25155_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+
+	.max_register		= BQ2515X_DEVICE_ID,
+	.reg_defaults		= bq25155_reg_defs,
+	.num_reg_defaults	= ARRAY_SIZE(bq25155_reg_defs),
+	.cache_type		= REGCACHE_RBTREE,
+	.volatile_reg		= bq2515x_volatile_register,
+};
+
+static int bq2515x_probe(struct i2c_client *client,
+			 const struct i2c_device_id *id)
+{
+	struct device *dev = &client->dev;
+	struct bq2515x_device *bq;
+	int ret;
+
+	bq = devm_kzalloc(dev, sizeof(*bq), GFP_KERNEL);
+	if (!bq)
+		return -ENOMEM;
+
+	bq->client = client;
+	bq->dev = dev;
+
+	strncpy(bq->model_name, id->name, I2C_NAME_SIZE);
+
+	bq->device_id = (enum bq2515x_id)of_device_get_match_data(&client->dev);
+
+	switch (bq->device_id) {
+	case BQ25150:
+		bq->regmap = devm_regmap_init_i2c(client,
+						&bq25150_regmap_config);
+		break;
+	case BQ25155:
+		bq->regmap = devm_regmap_init_i2c(client,
+						&bq25155_regmap_config);
+		break;
+	}
+
+	if (IS_ERR(bq->regmap)) {
+		dev_err(dev, "failed to allocate register map\n");
+		return PTR_ERR(bq->regmap);
+	}
+
+	i2c_set_clientdata(client, bq);
+
+	ret = bq2515x_read_properties(bq);
+	if (ret) {
+		dev_err(dev, "Failed to read device tree properties %d\n",
+									ret);
+		return ret;
+	}
+
+	ret = bq2515x_power_supply_register(bq, dev);
+	if (ret) {
+		dev_err(dev, "failed to register power supply\n");
+		return ret;
+	}
+
+	ret = bq2515x_hw_init(bq);
+	if (ret) {
+		dev_err(dev, "Cannot initialize the chip\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static const struct i2c_device_id bq2515x_i2c_ids[] = {
+	{ "bq25150", BQ25150, },
+	{ "bq25155", BQ25155, },
+	{},
+};
+MODULE_DEVICE_TABLE(i2c, bq2515x_i2c_ids);
+
+static const struct of_device_id bq2515x_of_match[] = {
+	{ .compatible = "ti,bq25150", },
+	{ .compatible = "ti,bq25155", },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, bq2515x_of_match);
+
+static struct i2c_driver bq2515x_driver = {
+	.driver = {
+		.name = "bq2515x-charger",
+		.of_match_table = bq2515x_of_match,
+	},
+	.probe = bq2515x_probe,
+	.id_table = bq2515x_i2c_ids,
+};
+module_i2c_driver(bq2515x_driver);
+
+MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com>");
+MODULE_AUTHOR("Ricardo Rivera-Matos <r-rivera-matos@ti.com>");
+MODULE_DESCRIPTION("BQ2515X charger driver");
+MODULE_LICENSE("GPL v2");
-- 
2.26.2


^ permalink raw reply related

* [PATCH 1/3] power_supply: Add additional health properties to the header
From: Dan Murphy @ 2020-05-15 19:31 UTC (permalink / raw)
  To: sre
  Cc: sspatil, linux-pm, robh, linux-kernel, devicetree, Dan Murphy,
	Guru Das Srinagesh
In-Reply-To: <20200515193148.8502-1-dmurphy@ti.com>

Add HEALTH_WARM, HEALTH_COOL and HEALTH_HOT to the health enum.

HEALTH_WARM, HEALTH_COOL, and HEALTH_HOT properties are taken from the JEITA spec.

Signed-off-by: Dan Murphy <dmurphy@ti.com>

Tested-by: Guru Das Srinagesh <gurus@codeaurora.org>
---
 Documentation/ABI/testing/sysfs-class-power | 2 +-
 drivers/power/supply/power_supply_sysfs.c   | 2 +-
 include/linux/power_supply.h                | 3 +++
 3 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-class-power b/Documentation/ABI/testing/sysfs-class-power
index bf3b48f022dc..9f3fd01a9373 100644
--- a/Documentation/ABI/testing/sysfs-class-power
+++ b/Documentation/ABI/testing/sysfs-class-power
@@ -190,7 +190,7 @@ Description:
 		Valid values: "Unknown", "Good", "Overheat", "Dead",
 			      "Over voltage", "Unspecified failure", "Cold",
 			      "Watchdog timer expire", "Safety timer expire",
-			      "Over current"
+			      "Over current", "Warm", "Cool", "Hot"
 
 What:		/sys/class/power_supply/<supply_name>/precharge_current
 Date:		June 2017
diff --git a/drivers/power/supply/power_supply_sysfs.c b/drivers/power/supply/power_supply_sysfs.c
index f37ad4eae60b..d0d549611794 100644
--- a/drivers/power/supply/power_supply_sysfs.c
+++ b/drivers/power/supply/power_supply_sysfs.c
@@ -61,7 +61,7 @@ static const char * const power_supply_charge_type_text[] = {
 static const char * const power_supply_health_text[] = {
 	"Unknown", "Good", "Overheat", "Dead", "Over voltage",
 	"Unspecified failure", "Cold", "Watchdog timer expire",
-	"Safety timer expire", "Over current"
+	"Safety timer expire", "Over current", "Warm", "Cool", "Hot"
 };
 
 static const char * const power_supply_technology_text[] = {
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
index dcd5a71e6c67..8670e90c1d51 100644
--- a/include/linux/power_supply.h
+++ b/include/linux/power_supply.h
@@ -61,6 +61,9 @@ enum {
 	POWER_SUPPLY_HEALTH_WATCHDOG_TIMER_EXPIRE,
 	POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE,
 	POWER_SUPPLY_HEALTH_OVERCURRENT,
+	POWER_SUPPLY_HEALTH_WARM,
+	POWER_SUPPLY_HEALTH_COOL,
+	POWER_SUPPLY_HEALTH_HOT,
 };
 
 enum {
-- 
2.26.2


^ permalink raw reply related

* [PATCH 0/3] Add JEITA properties and introduce the bq2515x charger
From: Dan Murphy @ 2020-05-15 19:31 UTC (permalink / raw)
  To: sre; +Cc: sspatil, linux-pm, robh, linux-kernel, devicetree, Dan Murphy

Hello,

This patchset adds additional health properties to the power_supply header.
These additional properties are taken from the JEITA specification. This 
patchset also introduces the bq2515x family of charging ICs.

Dan Murphy (1):
  power_supply: Add additional health properties to the header

Ricardo Rivera-Matos (2):
  Add the bindings for the bq25150 and bq25155 500mA charging ICs from
    Texas Instruments.
  power: supply: bq25150 introduce the bq25150

 Documentation/ABI/testing/sysfs-class-power   |    2 +-
 .../bindings/power/supply/bq2515x.yaml        |  106 ++
 drivers/power/supply/Kconfig                  |   13 +
 drivers/power/supply/Makefile                 |    1 +
 drivers/power/supply/bq2515x_charger.c        | 1176 +++++++++++++++++
 drivers/power/supply/power_supply_sysfs.c     |    2 +-
 include/linux/power_supply.h                  |    3 +
 7 files changed, 1301 insertions(+), 2 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/power/supply/bq2515x.yaml
 create mode 100644 drivers/power/supply/bq2515x_charger.c

-- 
2.26.2


^ permalink raw reply

* Re: [PATCH v4 5/6] pstore/ram: Introduce max_reason and convert dump_oops
From: Pavel Tatashin @ 2020-05-15 19:40 UTC (permalink / raw)
  To: Kees Cook
  Cc: Petr Mladek, Anton Vorontsov, Colin Cross, Tony Luck,
	Jonathan Corbet, Benson Leung, Rob Herring, Michael Ellerman,
	Benjamin Herrenschmidt, Paul Mackerras, Enric Balletbo i Serra,
	Sergey Senozhatsky, Steven Rostedt, Linux Doc Mailing List, LKML,
	devicetree, linuxppc-dev
In-Reply-To: <20200515184434.8470-6-keescook@chromium.org>

 pdata.dump_oops = dump_oops;
> +       /* If "max_reason" is set, its value has priority over "dump_oops". */
> +       if (ramoops_max_reason != -1)
> +               pdata.max_reason = ramoops_max_reason;

 (ramoops_max_reason >= 0) might make more sense here, we do not want
negative max_reason even if it was provided by the user.

Otherwise the series looks good.

Thank you,
Pasha

^ permalink raw reply

* Re: [PATCH v4 5/6] pstore/ram: Introduce max_reason and convert dump_oops
From: Pavel Tatashin @ 2020-05-15 19:30 UTC (permalink / raw)
  To: Kees Cook
  Cc: Petr Mladek, Anton Vorontsov, Colin Cross, Tony Luck,
	Jonathan Corbet, Benson Leung, Rob Herring, Michael Ellerman,
	Benjamin Herrenschmidt, Paul Mackerras, Enric Balletbo i Serra,
	Sergey Senozhatsky, Steven Rostedt, Linux Doc Mailing List, LKML,
	devicetree, linuxppc-dev
In-Reply-To: <20200515184434.8470-6-keescook@chromium.org>

>  #define parse_u32(name, field, default_value) {                                \
>                 ret = ramoops_parse_dt_u32(pdev, name, default_value,   \

The series seems to be missing the patch where ramoops_parse_dt_size
-> ramoops_parse_dt_u32 get renamed, and updated to handle default
value.

^ permalink raw reply

* Re: [PATCH v1 5/9] dt-bindings: dmaengine: convert Actions Semi Owl SoCs bindings to yaml
From: Amit Tomer @ 2020-05-15 19:24 UTC (permalink / raw)
  To: André Przywara
  Cc: Andreas Färber, Manivannan Sadhasivam, Rob Herring,
	cristian.ciocaltea, linux-arm-kernel, linux-actions, devicetree
In-Reply-To: <CABHD4K_BpHMSypfdiQKeRfHOgdO8e7ekU0TKBmqisDe_+4hGPg@mail.gmail.com>

> But having it under reg: looks bit odd to me, no?
>
> reg:
>    - description: ...
>
> Or did you mean something else ?

Ah, I see you wanted to have description for individual items, for instance one
for reg, one for interrupts and clock etc..

Thanks
Amit

^ permalink raw reply

* Re: [PATCH v4 3/6] printk: Introduce kmsg_dump_reason_str()
From: Pavel Tatashin @ 2020-05-15 19:23 UTC (permalink / raw)
  To: Kees Cook
  Cc: Petr Mladek, Sergey Senozhatsky, Anton Vorontsov, Colin Cross,
	Tony Luck, Jonathan Corbet, Benson Leung, Rob Herring,
	Michael Ellerman, Benjamin Herrenschmidt, Paul Mackerras,
	Enric Balletbo i Serra, Steven Rostedt, Linux Doc Mailing List,
	LKML, devicetree, linuxppc-dev
In-Reply-To: <20200515184434.8470-4-keescook@chromium.org>

On Fri, May 15, 2020 at 2:44 PM Kees Cook <keescook@chromium.org> wrote:
>
> The pstore subsystem already had a private version of this function.
> With the coming addition of the pstore/zone driver, this needs to be
> shared. As it really should live with printk, move it there instead.
>
> Link: https://lore.kernel.org/lkml/20200510202436.63222-8-keescook@chromium.org/
> Acked-by: Petr Mladek <pmladek@suse.com>
> Acked-by: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
> Signed-off-by: Kees Cook <keescook@chromium.org>

Reviewed-by: Pavel Tatashin <pasha.tatashin@soleen.com>

^ permalink raw reply

* Re: [PATCH v4 1/6] printk: Collapse shutdown types into a single dump reason
From: Pavel Tatashin @ 2020-05-15 19:17 UTC (permalink / raw)
  To: Kees Cook
  Cc: Petr Mladek, Anton Vorontsov, Colin Cross, Tony Luck,
	Jonathan Corbet, Benson Leung, Rob Herring, Michael Ellerman,
	Benjamin Herrenschmidt, Paul Mackerras, Enric Balletbo i Serra,
	Sergey Senozhatsky, Steven Rostedt, Linux Doc Mailing List, LKML,
	devicetree, linuxppc-dev
In-Reply-To: <20200515184434.8470-2-keescook@chromium.org>

On Fri, May 15, 2020 at 2:44 PM Kees Cook <keescook@chromium.org> wrote:
>
> To turn the KMSG_DUMP_* reasons into a more ordered list, collapse
> the redundant KMSG_DUMP_(RESTART|HALT|POWEROFF) reasons into
> KMSG_DUMP_SHUTDOWN. The current users already don't meaningfully
> distinguish between them, so there's no need to, as discussed here:
> https://lore.kernel.org/lkml/CA+CK2bAPv5u1ih5y9t5FUnTyximtFCtDYXJCpuyjOyHNOkRdqw@mail.gmail.com/
>
> Signed-off-by: Kees Cook <keescook@chromium.org>

Maybe it makes sense to mention in the commit log that for all three
merged cases there is a pr_emerg() message logged right before the
kmsg_dump(), thus the reason is distinguishable from the dmesg log
itself.

Reviewed-by: Pavel Tatashin <pasha.tatashin@soleen.com>

^ permalink raw reply

* Re: [PATCH v4 0/6] allow ramoops to collect all kmesg_dump events
From: Pavel Tatashin @ 2020-05-15 19:13 UTC (permalink / raw)
  To: Kees Cook
  Cc: Petr Mladek, Anton Vorontsov, Colin Cross, Tony Luck,
	Jonathan Corbet, Benson Leung, Rob Herring, Michael Ellerman,
	Benjamin Herrenschmidt, Paul Mackerras, Enric Balletbo i Serra,
	Sergey Senozhatsky, Steven Rostedt, Linux Doc Mailing List, LKML,
	devicetree, linuxppc-dev
In-Reply-To: <20200515184434.8470-1-keescook@chromium.org>

On Fri, May 15, 2020 at 2:44 PM Kees Cook <keescook@chromium.org> wrote:
>
> Hello!
>
> I wanted to get the pstore tree nailed down, so here's the v4 of
> Pavel's series, tweaked for the feedback during v3 review.

Hi Kees,

Thank you, I was planning to send a new version of this series later
today. Let me quickly review it.

Pasha

>
> -Kees
>
> v4:
> - rebase on pstore tree
> - collapse shutdown types into a single dump reason
>   https://lore.kernel.org/lkml/CA+CK2bAPv5u1ih5y9t5FUnTyximtFCtDYXJCpuyjOyHNOkRdqw@mail.gmail.com/
> - fix dump_oops vs max_reason module params
>   https://lore.kernel.org/lkml/20200512233504.GA118720@sequoia/
> - typos
>   https://lore.kernel.org/lkml/4cdeaa2af2fe0d6cc2ca8ce3a37608340799df8a.camel@perches.com/
> - rename DT parsing routines ..._size -> ..._u32
>   https://lore.kernel.org/lkml/CA+CK2bCu8eFomiU+NeBjVn-o2dbuECxwRfssNjB3ys3caCbXeA@mail.gmail.com/
> v3: https://lore.kernel.org/lkml/20200506211523.15077-1-keescook@chromium.org/
> v2: https://lore.kernel.org/lkml/20200505154510.93506-1-pasha.tatashin@soleen.com
> v1: https://lore.kernel.org/lkml/20200502143555.543636-1-pasha.tatashin@soleen.com
>
> Kees Cook (3):
>   printk: Collapse shutdown types into a single dump reason
>   printk: Introduce kmsg_dump_reason_str()
>   pstore/ram: Introduce max_reason and convert dump_oops
>
> Pavel Tatashin (3):
>   printk: honor the max_reason field in kmsg_dumper
>   pstore/platform: Pass max_reason to kmesg dump
>   ramoops: Add max_reason optional field to ramoops DT node
>
>  Documentation/admin-guide/ramoops.rst         | 14 +++--
>  .../bindings/reserved-memory/ramoops.txt      | 13 ++++-
>  arch/powerpc/kernel/nvram_64.c                |  4 +-
>  drivers/platform/chrome/chromeos_pstore.c     |  2 +-
>  fs/pstore/platform.c                          | 26 ++-------
>  fs/pstore/ram.c                               | 58 +++++++++++++------
>  include/linux/kmsg_dump.h                     | 12 +++-
>  include/linux/pstore.h                        |  7 +++
>  include/linux/pstore_ram.h                    |  2 +-
>  kernel/printk/printk.c                        | 32 ++++++++--
>  kernel/reboot.c                               |  6 +-
>  11 files changed, 114 insertions(+), 62 deletions(-)
>
> --
> 2.20.1
>

^ permalink raw reply

* Re: [PATCH v1 5/9] dt-bindings: dmaengine: convert Actions Semi Owl SoCs bindings to yaml
From: Amit Tomer @ 2020-05-15 19:05 UTC (permalink / raw)
  To: André Przywara
  Cc: Andreas Färber, Manivannan Sadhasivam, Rob Herring,
	cristian.ciocaltea, linux-arm-kernel, linux-actions, devicetree
In-Reply-To: <afc0d7f3-d763-b936-988c-d802b86836bc@arm.com>

Hi,

> Could you replace those "maxItems: 1" here and below with:
>   - description: ...., copying in the explanation from the .txt binding?
> That should serve the same purpose as "maxItems: 1", but is more
> descriptive.

But having it under reg: looks bit odd to me, no?

reg:
   - description: ...

Or did you mean something else ?

Thanks
-Amit

^ permalink raw reply

* [PATCH v4 3/6] printk: Introduce kmsg_dump_reason_str()
From: Kees Cook @ 2020-05-15 18:44 UTC (permalink / raw)
  To: Pavel Tatashin
  Cc: Kees Cook, Petr Mladek, Sergey Senozhatsky, Anton Vorontsov,
	Colin Cross, Tony Luck, Jonathan Corbet, Benson Leung,
	Rob Herring, Michael Ellerman, Benjamin Herrenschmidt,
	Paul Mackerras, Enric Balletbo i Serra, Steven Rostedt, linux-doc,
	linux-kernel, devicetree, linuxppc-dev
In-Reply-To: <20200515184434.8470-1-keescook@chromium.org>

The pstore subsystem already had a private version of this function.
With the coming addition of the pstore/zone driver, this needs to be
shared. As it really should live with printk, move it there instead.

Link: https://lore.kernel.org/lkml/20200510202436.63222-8-keescook@chromium.org/
Acked-by: Petr Mladek <pmladek@suse.com>
Acked-by: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
Signed-off-by: Kees Cook <keescook@chromium.org>
---
 fs/pstore/platform.c      | 18 +-----------------
 include/linux/kmsg_dump.h |  7 +++++++
 kernel/printk/printk.c    | 17 +++++++++++++++++
 3 files changed, 25 insertions(+), 17 deletions(-)

diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c
index 90d74ebaa70a..5e6c6022deb9 100644
--- a/fs/pstore/platform.c
+++ b/fs/pstore/platform.c
@@ -135,22 +135,6 @@ enum pstore_type_id pstore_name_to_type(const char *name)
 }
 EXPORT_SYMBOL_GPL(pstore_name_to_type);
 
-static const char *get_reason_str(enum kmsg_dump_reason reason)
-{
-	switch (reason) {
-	case KMSG_DUMP_PANIC:
-		return "Panic";
-	case KMSG_DUMP_OOPS:
-		return "Oops";
-	case KMSG_DUMP_EMERG:
-		return "Emergency";
-	case KMSG_DUMP_SHUTDOWN:
-		return "Shutdown";
-	default:
-		return "Unknown";
-	}
-}
-
 static void pstore_timer_kick(void)
 {
 	if (pstore_update_ms < 0)
@@ -403,7 +387,7 @@ static void pstore_dump(struct kmsg_dumper *dumper,
 	unsigned int	part = 1;
 	int		ret;
 
-	why = get_reason_str(reason);
+	why = kmsg_dump_reason_str(reason);
 
 	if (down_trylock(&psinfo->buf_lock)) {
 		/* Failed to acquire lock: give up if we cannot wait. */
diff --git a/include/linux/kmsg_dump.h b/include/linux/kmsg_dump.h
index 9826014771ab..3378bcbe585e 100644
--- a/include/linux/kmsg_dump.h
+++ b/include/linux/kmsg_dump.h
@@ -70,6 +70,8 @@ void kmsg_dump_rewind(struct kmsg_dumper *dumper);
 int kmsg_dump_register(struct kmsg_dumper *dumper);
 
 int kmsg_dump_unregister(struct kmsg_dumper *dumper);
+
+const char *kmsg_dump_reason_str(enum kmsg_dump_reason reason);
 #else
 static inline void kmsg_dump(enum kmsg_dump_reason reason)
 {
@@ -111,6 +113,11 @@ static inline int kmsg_dump_unregister(struct kmsg_dumper *dumper)
 {
 	return -EINVAL;
 }
+
+static inline const char *kmsg_dump_reason_str(enum kmsg_dump_reason reason)
+{
+	return "Disabled";
+}
 #endif
 
 #endif /* _LINUX_KMSG_DUMP_H */
diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index a121c2255737..14ca4d05d902 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -3144,6 +3144,23 @@ EXPORT_SYMBOL_GPL(kmsg_dump_unregister);
 static bool always_kmsg_dump;
 module_param_named(always_kmsg_dump, always_kmsg_dump, bool, S_IRUGO | S_IWUSR);
 
+const char *kmsg_dump_reason_str(enum kmsg_dump_reason reason)
+{
+	switch (reason) {
+	case KMSG_DUMP_PANIC:
+		return "Panic";
+	case KMSG_DUMP_OOPS:
+		return "Oops";
+	case KMSG_DUMP_EMERG:
+		return "Emergency";
+	case KMSG_DUMP_SHUTDOWN:
+		return "Shutdown";
+	default:
+		return "Unknown";
+	}
+}
+EXPORT_SYMBOL_GPL(kmsg_dump_reason_str);
+
 /**
  * kmsg_dump - dump kernel log to kernel message dumpers.
  * @reason: the reason (oops, panic etc) for dumping
-- 
2.20.1


^ permalink raw reply related

* [PATCH v4 0/6] allow ramoops to collect all kmesg_dump events
From: Kees Cook @ 2020-05-15 18:44 UTC (permalink / raw)
  To: Pavel Tatashin
  Cc: Kees Cook, Petr Mladek, Anton Vorontsov, Colin Cross, Tony Luck,
	Jonathan Corbet, Benson Leung, Rob Herring, Michael Ellerman,
	Benjamin Herrenschmidt, Paul Mackerras, Enric Balletbo i Serra,
	Sergey Senozhatsky, Steven Rostedt, linux-doc, linux-kernel,
	devicetree, linuxppc-dev

Hello!

I wanted to get the pstore tree nailed down, so here's the v4 of
Pavel's series, tweaked for the feedback during v3 review.

-Kees

v4:
- rebase on pstore tree
- collapse shutdown types into a single dump reason
  https://lore.kernel.org/lkml/CA+CK2bAPv5u1ih5y9t5FUnTyximtFCtDYXJCpuyjOyHNOkRdqw@mail.gmail.com/
- fix dump_oops vs max_reason module params
  https://lore.kernel.org/lkml/20200512233504.GA118720@sequoia/
- typos
  https://lore.kernel.org/lkml/4cdeaa2af2fe0d6cc2ca8ce3a37608340799df8a.camel@perches.com/
- rename DT parsing routines ..._size -> ..._u32
  https://lore.kernel.org/lkml/CA+CK2bCu8eFomiU+NeBjVn-o2dbuECxwRfssNjB3ys3caCbXeA@mail.gmail.com/
v3: https://lore.kernel.org/lkml/20200506211523.15077-1-keescook@chromium.org/
v2: https://lore.kernel.org/lkml/20200505154510.93506-1-pasha.tatashin@soleen.com
v1: https://lore.kernel.org/lkml/20200502143555.543636-1-pasha.tatashin@soleen.com

Kees Cook (3):
  printk: Collapse shutdown types into a single dump reason
  printk: Introduce kmsg_dump_reason_str()
  pstore/ram: Introduce max_reason and convert dump_oops

Pavel Tatashin (3):
  printk: honor the max_reason field in kmsg_dumper
  pstore/platform: Pass max_reason to kmesg dump
  ramoops: Add max_reason optional field to ramoops DT node

 Documentation/admin-guide/ramoops.rst         | 14 +++--
 .../bindings/reserved-memory/ramoops.txt      | 13 ++++-
 arch/powerpc/kernel/nvram_64.c                |  4 +-
 drivers/platform/chrome/chromeos_pstore.c     |  2 +-
 fs/pstore/platform.c                          | 26 ++-------
 fs/pstore/ram.c                               | 58 +++++++++++++------
 include/linux/kmsg_dump.h                     | 12 +++-
 include/linux/pstore.h                        |  7 +++
 include/linux/pstore_ram.h                    |  2 +-
 kernel/printk/printk.c                        | 32 ++++++++--
 kernel/reboot.c                               |  6 +-
 11 files changed, 114 insertions(+), 62 deletions(-)

-- 
2.20.1


^ permalink raw reply

* [PATCH v4 5/6] pstore/ram: Introduce max_reason and convert dump_oops
From: Kees Cook @ 2020-05-15 18:44 UTC (permalink / raw)
  To: Pavel Tatashin
  Cc: Kees Cook, Petr Mladek, Anton Vorontsov, Colin Cross, Tony Luck,
	Jonathan Corbet, Benson Leung, Rob Herring, Michael Ellerman,
	Benjamin Herrenschmidt, Paul Mackerras, Enric Balletbo i Serra,
	Sergey Senozhatsky, Steven Rostedt, linux-doc, linux-kernel,
	devicetree, linuxppc-dev
In-Reply-To: <20200515184434.8470-1-keescook@chromium.org>

Now that pstore_register() can correctly pass max_reason to the kmesg
dump facility, introduce a new "max_reason" module parameter and
"max-reason" Device Tree field.

The "dump_oops" module parameter and "dump-oops" Device
Tree field are now considered deprecated, but are now automatically
converted to their corresponding max_reason values when present, though
the new max_reason setting has precedence.

For struct ramoops_platform_data, the "dump_oops" member is entirely
replaced by a new "max_reason" member, with the only existing user
updated in place.

Additionally remove the "reason" filter logic from ramoops_pstore_write(),
as that is not specifically needed anymore, though technically
this is a change in behavior for any ramoops users also setting the
printk.always_kmsg_dump boot param, which will cause ramoops to behave as
if max_reason was set to KMSG_DUMP_MAX.

Co-developed-by: Pavel Tatashin <pasha.tatashin@soleen.com>
Signed-off-by: Pavel Tatashin <pasha.tatashin@soleen.com>
Link: https://lore.kernel.org/lkml/20200506211523.15077-5-keescook@chromium.org/
Signed-off-by: Kees Cook <keescook@chromium.org>
---
 Documentation/admin-guide/ramoops.rst     | 14 ++++--
 drivers/platform/chrome/chromeos_pstore.c |  2 +-
 fs/pstore/ram.c                           | 58 +++++++++++++++--------
 include/linux/pstore_ram.h                |  2 +-
 4 files changed, 51 insertions(+), 25 deletions(-)

diff --git a/Documentation/admin-guide/ramoops.rst b/Documentation/admin-guide/ramoops.rst
index 6dbcc5481000..a60a96218ba9 100644
--- a/Documentation/admin-guide/ramoops.rst
+++ b/Documentation/admin-guide/ramoops.rst
@@ -32,11 +32,17 @@ memory to be mapped strongly ordered, and atomic operations on strongly ordered
 memory are implementation defined, and won't work on many ARMs such as omaps.
 
 The memory area is divided into ``record_size`` chunks (also rounded down to
-power of two) and each oops/panic writes a ``record_size`` chunk of
+power of two) and each kmesg dump writes a ``record_size`` chunk of
 information.
 
-Dumping both oopses and panics can be done by setting 1 in the ``dump_oops``
-variable while setting 0 in that variable dumps only the panics.
+Limiting which kinds of kmsg dumps are stored can be controlled via
+the ``max_reason`` value, as defined in include/linux/kmsg_dump.h's
+``enum kmsg_dump_reason``. For example, to store both Oopses and Panics,
+``max_reason`` should be set to 2 (KMSG_DUMP_OOPS), to store only Panics
+``max_reason`` should be set to 1 (KMSG_DUMP_PANIC). Setting this to 0
+(KMSG_DUMP_UNDEF), means the reason filtering will be controlled by the
+``printk.always_kmsg_dump`` boot param: if unset, it'll be KMSG_DUMP_OOPS,
+otherwise KMSG_DUMP_MAX.
 
 The module uses a counter to record multiple dumps but the counter gets reset
 on restart (i.e. new dumps after the restart will overwrite old ones).
@@ -90,7 +96,7 @@ Setting the ramoops parameters can be done in several different manners:
         .mem_address            = <...>,
         .mem_type               = <...>,
         .record_size            = <...>,
-        .dump_oops              = <...>,
+        .max_reason             = <...>,
         .ecc                    = <...>,
   };
 
diff --git a/drivers/platform/chrome/chromeos_pstore.c b/drivers/platform/chrome/chromeos_pstore.c
index d13770785fb5..fa51153688b4 100644
--- a/drivers/platform/chrome/chromeos_pstore.c
+++ b/drivers/platform/chrome/chromeos_pstore.c
@@ -57,7 +57,7 @@ static struct ramoops_platform_data chromeos_ramoops_data = {
 	.record_size	= 0x40000,
 	.console_size	= 0x20000,
 	.ftrace_size	= 0x20000,
-	.dump_oops	= 1,
+	.max_reason	= KMSG_DUMP_OOPS,
 };
 
 static struct platform_device chromeos_ramoops = {
diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c
index 31f277633beb..f6eace1dbf7e 100644
--- a/fs/pstore/ram.c
+++ b/fs/pstore/ram.c
@@ -58,10 +58,10 @@ module_param(mem_type, uint, 0400);
 MODULE_PARM_DESC(mem_type,
 		"set to 1 to try to use unbuffered memory (default 0)");
 
-static int dump_oops = 1;
-module_param(dump_oops, int, 0400);
-MODULE_PARM_DESC(dump_oops,
-		"set to 1 to dump oopses, 0 to only dump panics (default 1)");
+static int ramoops_max_reason = -1;
+module_param_named(max_reason, ramoops_max_reason, int, 0400);
+MODULE_PARM_DESC(max_reason,
+		 "maximum reason for kmsg dump (default 2: Oops and Panic) ");
 
 static int ramoops_ecc;
 module_param_named(ecc, ramoops_ecc, int, 0400);
@@ -70,6 +70,11 @@ MODULE_PARM_DESC(ramoops_ecc,
 		"ECC buffer size in bytes (1 is a special value, means 16 "
 		"bytes ECC)");
 
+static int ramoops_dump_oops = -1;
+module_param_named(dump_oops, ramoops_dump_oops, int, 0400);
+MODULE_PARM_DESC(dump_oops,
+		 "(deprecated: use max_reason instead) set to 1 to dump oopses & panics, 0 to only dump panics");
+
 struct ramoops_context {
 	struct persistent_ram_zone **dprzs;	/* Oops dump zones */
 	struct persistent_ram_zone *cprz;	/* Console zone */
@@ -82,7 +87,6 @@ struct ramoops_context {
 	size_t console_size;
 	size_t ftrace_size;
 	size_t pmsg_size;
-	int dump_oops;
 	u32 flags;
 	struct persistent_ram_ecc_info ecc_info;
 	unsigned int max_dump_cnt;
@@ -336,16 +340,14 @@ static int notrace ramoops_pstore_write(struct pstore_record *record)
 		return -EINVAL;
 
 	/*
-	 * Out of the various dmesg dump types, ramoops is currently designed
-	 * to only store crash logs, rather than storing general kernel logs.
+	 * We could filter on record->reason here if we wanted to (which
+	 * would duplicate what happened before the "max_reason" setting
+	 * was added), but that would defeat the purpose of a system
+	 * changing printk.always_kmsg_dump, so instead log everything that
+	 * the kmsg dumper sends us, since it should be doing the filtering
+	 * based on the combination of printk.always_kmsg_dump and our
+	 * requested "max_reason".
 	 */
-	if (record->reason != KMSG_DUMP_OOPS &&
-	    record->reason != KMSG_DUMP_PANIC)
-		return -EINVAL;
-
-	/* Skip Oopes when configured to do so. */
-	if (record->reason == KMSG_DUMP_OOPS && !cxt->dump_oops)
-		return -EINVAL;
 
 	/*
 	 * Explicitly only take the first part of any new crash.
@@ -647,7 +649,14 @@ static int ramoops_parse_dt(struct platform_device *pdev,
 	pdata->mem_size = resource_size(res);
 	pdata->mem_address = res->start;
 	pdata->mem_type = of_property_read_bool(of_node, "unbuffered");
-	pdata->dump_oops = !of_property_read_bool(of_node, "no-dump-oops");
+	/*
+	 * Setting "no-dump-oops" is deprecated and will be ignored if
+	 * "max_reason" is also specified.
+	 */
+	if (of_property_read_bool(of_node, "no-dump-oops"))
+		pdata->max_reason = KMSG_DUMP_PANIC;
+	else
+		pdata->max_reason = KMSG_DUMP_OOPS;
 
 #define parse_u32(name, field, default_value) {				\
 		ret = ramoops_parse_dt_u32(pdev, name, default_value,	\
@@ -663,6 +672,7 @@ static int ramoops_parse_dt(struct platform_device *pdev,
 	parse_u32("pmsg-size", pdata->pmsg_size, 0);
 	parse_u32("ecc-size", pdata->ecc_info.ecc_size, 0);
 	parse_u32("flags", pdata->flags, 0);
+	parse_u32("max-reason", pdata->max_reason, pdata->max_reason);
 
 #undef parse_size
 
@@ -746,7 +756,6 @@ static int ramoops_probe(struct platform_device *pdev)
 	cxt->console_size = pdata->console_size;
 	cxt->ftrace_size = pdata->ftrace_size;
 	cxt->pmsg_size = pdata->pmsg_size;
-	cxt->dump_oops = pdata->dump_oops;
 	cxt->flags = pdata->flags;
 	cxt->ecc_info = pdata->ecc_info;
 
@@ -789,8 +798,10 @@ static int ramoops_probe(struct platform_device *pdev)
 	 * the single region size is how to check.
 	 */
 	cxt->pstore.flags = 0;
-	if (cxt->max_dump_cnt)
+	if (cxt->max_dump_cnt) {
 		cxt->pstore.flags |= PSTORE_FLAGS_DMESG;
+		cxt->pstore.max_reason = pdata->max_reason;
+	}
 	if (cxt->console_size)
 		cxt->pstore.flags |= PSTORE_FLAGS_CONSOLE;
 	if (cxt->max_ftrace_cnt)
@@ -826,7 +837,7 @@ static int ramoops_probe(struct platform_device *pdev)
 	mem_size = pdata->mem_size;
 	mem_address = pdata->mem_address;
 	record_size = pdata->record_size;
-	dump_oops = pdata->dump_oops;
+	ramoops_max_reason = pdata->max_reason;
 	ramoops_console_size = pdata->console_size;
 	ramoops_pmsg_size = pdata->pmsg_size;
 	ramoops_ftrace_size = pdata->ftrace_size;
@@ -909,7 +920,16 @@ static void __init ramoops_register_dummy(void)
 	pdata.console_size = ramoops_console_size;
 	pdata.ftrace_size = ramoops_ftrace_size;
 	pdata.pmsg_size = ramoops_pmsg_size;
-	pdata.dump_oops = dump_oops;
+	/* If "max_reason" is set, its value has priority over "dump_oops". */
+	if (ramoops_max_reason != -1)
+		pdata.max_reason = ramoops_max_reason;
+	/* Otherwise, if "dump_oops" is set, parse it into "max_reason". */
+	else if (ramoops_dump_oops != -1)
+		pdata.max_reason = ramoops_dump_oops ? KMSG_DUMP_OOPS
+						     : KMSG_DUMP_PANIC;
+	/* And if neither are explicitly set, use the default. */
+	else
+		pdata.max_reason = KMSG_DUMP_OOPS;
 	pdata.flags = RAMOOPS_FLAG_FTRACE_PER_CPU;
 
 	/*
diff --git a/include/linux/pstore_ram.h b/include/linux/pstore_ram.h
index 9cb9b9067298..9f16afec7290 100644
--- a/include/linux/pstore_ram.h
+++ b/include/linux/pstore_ram.h
@@ -133,7 +133,7 @@ struct ramoops_platform_data {
 	unsigned long	console_size;
 	unsigned long	ftrace_size;
 	unsigned long	pmsg_size;
-	int		dump_oops;
+	int		max_reason;
 	u32		flags;
 	struct persistent_ram_ecc_info ecc_info;
 };
-- 
2.20.1


^ permalink raw reply related

* [PATCH v4 2/6] printk: honor the max_reason field in kmsg_dumper
From: Kees Cook @ 2020-05-15 18:44 UTC (permalink / raw)
  To: Pavel Tatashin
  Cc: Kees Cook, Petr Mladek, Anton Vorontsov, Colin Cross, Tony Luck,
	Jonathan Corbet, Benson Leung, Rob Herring, Michael Ellerman,
	Benjamin Herrenschmidt, Paul Mackerras, Enric Balletbo i Serra,
	Sergey Senozhatsky, Steven Rostedt, linux-doc, linux-kernel,
	devicetree, linuxppc-dev
In-Reply-To: <20200515184434.8470-1-keescook@chromium.org>

From: Pavel Tatashin <pasha.tatashin@soleen.com>

kmsg_dump() allows to dump kmesg buffer for various system events: oops,
panic, reboot, etc. It provides an interface to register a callback call
for clients, and in that callback interface there is a field "max_reason"
which gets ignored unless always_kmsg_dump is passed as kernel parameter.

Allow clients to decide max_reason, and keep the current behavior when
max_reason is not set.

Signed-off-by: Pavel Tatashin <pasha.tatashin@soleen.com>
Link: https://lore.kernel.org/lkml/20200506211523.15077-2-keescook@chromium.org/
Signed-off-by: Kees Cook <keescook@chromium.org>
---
 include/linux/kmsg_dump.h |  1 +
 kernel/printk/printk.c    | 15 +++++++++++----
 2 files changed, 12 insertions(+), 4 deletions(-)

diff --git a/include/linux/kmsg_dump.h b/include/linux/kmsg_dump.h
index 3f82b5cb2d82..9826014771ab 100644
--- a/include/linux/kmsg_dump.h
+++ b/include/linux/kmsg_dump.h
@@ -26,6 +26,7 @@ enum kmsg_dump_reason {
 	KMSG_DUMP_OOPS,
 	KMSG_DUMP_EMERG,
 	KMSG_DUMP_SHUTDOWN,
+	KMSG_DUMP_MAX
 };
 
 /**
diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index 9a9b6156270b..a121c2255737 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -3157,12 +3157,19 @@ void kmsg_dump(enum kmsg_dump_reason reason)
 	struct kmsg_dumper *dumper;
 	unsigned long flags;
 
-	if ((reason > KMSG_DUMP_OOPS) && !always_kmsg_dump)
-		return;
-
 	rcu_read_lock();
 	list_for_each_entry_rcu(dumper, &dump_list, list) {
-		if (dumper->max_reason && reason > dumper->max_reason)
+		enum kmsg_dump_reason max_reason = dumper->max_reason;
+
+		/*
+		 * If client has not provided a specific max_reason, default
+		 * to KMSG_DUMP_OOPS, unless always_kmsg_dump was set.
+		 */
+		if (max_reason == KMSG_DUMP_UNDEF) {
+			max_reason = always_kmsg_dump ? KMSG_DUMP_MAX :
+							KMSG_DUMP_OOPS;
+		}
+		if (reason > max_reason)
 			continue;
 
 		/* initialize iterator with data about the stored records */
-- 
2.20.1


^ permalink raw reply related

* [PATCH v4 6/6] ramoops: Add max_reason optional field to ramoops DT node
From: Kees Cook @ 2020-05-15 18:44 UTC (permalink / raw)
  To: Pavel Tatashin
  Cc: Kees Cook, Petr Mladek, Anton Vorontsov, Colin Cross, Tony Luck,
	Jonathan Corbet, Benson Leung, Rob Herring, Michael Ellerman,
	Benjamin Herrenschmidt, Paul Mackerras, Enric Balletbo i Serra,
	Sergey Senozhatsky, Steven Rostedt, linux-doc, linux-kernel,
	devicetree, linuxppc-dev
In-Reply-To: <20200515184434.8470-1-keescook@chromium.org>

From: Pavel Tatashin <pasha.tatashin@soleen.com>

Currently, it is possible to dump kmsges for panic, or oops.
With max_reason it is possible to dump messages for other
kmesg_dump events, for example reboot, halt, shutdown, kexec.

Signed-off-by: Pavel Tatashin <pasha.tatashin@soleen.com>
Link: https://lore.kernel.org/lkml/20200506211523.15077-6-keescook@chromium.org/
Signed-off-by: Kees Cook <keescook@chromium.org>
---
 .../devicetree/bindings/reserved-memory/ramoops.txt | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/reserved-memory/ramoops.txt b/Documentation/devicetree/bindings/reserved-memory/ramoops.txt
index 0eba562fe5c6..b7886fea368c 100644
--- a/Documentation/devicetree/bindings/reserved-memory/ramoops.txt
+++ b/Documentation/devicetree/bindings/reserved-memory/ramoops.txt
@@ -30,7 +30,7 @@ Optional properties:
 - ecc-size: enables ECC support and specifies ECC buffer size in bytes
   (defaults to 0: no ECC)
 
-- record-size: maximum size in bytes of each dump done on oops/panic
+- record-size: maximum size in bytes of each kmsg dump.
   (defaults to 0: disabled)
 
 - console-size: size in bytes of log buffer reserved for kernel messages
@@ -45,7 +45,16 @@ Optional properties:
 - unbuffered: if present, use unbuffered mappings to map the reserved region
   (defaults to buffered mappings)
 
-- no-dump-oops: if present, only dump panics (defaults to panics and oops)
+- max-reason: if present, sets maximum type of kmsg dump reasons to store
+  (defaults to 2: log Oopses and Panics). This can be set to INT_MAX to
+  store all kmsg dumps. See include/linux/kmsg_dump.h KMSG_DUMP_* for other
+  kmsg dump reason values. Setting this to 0 (KMSG_DUMP_UNDEF), means the
+  reason filtering will be controlled by the printk.always_kmsg_dump boot
+  param: if unset, it will be KMSG_DUMP_OOPS, otherwise KMSG_DUMP_MAX.
+
+- no-dump-oops: deprecated, use max_reason instead. If present, and
+  max_reason is not specified, it is equivalent to max_reason = 1
+  (KMSG_DUMP_PANIC).
 
 - flags: if present, pass ramoops behavioral flags (defaults to 0,
   see include/linux/pstore_ram.h RAMOOPS_FLAG_* for flag values).
-- 
2.20.1


^ permalink raw reply related

* [PATCH v4 4/6] pstore/platform: Pass max_reason to kmesg dump
From: Kees Cook @ 2020-05-15 18:44 UTC (permalink / raw)
  To: Pavel Tatashin
  Cc: Kees Cook, Petr Mladek, Anton Vorontsov, Colin Cross, Tony Luck,
	Jonathan Corbet, Benson Leung, Rob Herring, Michael Ellerman,
	Benjamin Herrenschmidt, Paul Mackerras, Enric Balletbo i Serra,
	Sergey Senozhatsky, Steven Rostedt, linux-doc, linux-kernel,
	devicetree, linuxppc-dev
In-Reply-To: <20200515184434.8470-1-keescook@chromium.org>

From: Pavel Tatashin <pasha.tatashin@soleen.com>

Add a new member to struct pstore_info for passing information about
kmesg dump maximum reason. This allows a finer control of what kmesg
dumps are sent to pstore storage backends.

Those backends that do not explicitly set this field (keeping it equal to
0), get the default behavior: store only Oopses and Panics, or everything
if the printk.always_kmsg_dump boot param is set.

Signed-off-by: Pavel Tatashin <pasha.tatashin@soleen.com>
Link: https://lore.kernel.org/lkml/20200506211523.15077-3-keescook@chromium.org/
Co-developed-by: Kees Cook <keescook@chromium.org>
Signed-off-by: Kees Cook <keescook@chromium.org>
---
 fs/pstore/platform.c   | 4 +++-
 include/linux/pstore.h | 7 +++++++
 2 files changed, 10 insertions(+), 1 deletion(-)

diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c
index 5e6c6022deb9..a9e297eefdff 100644
--- a/fs/pstore/platform.c
+++ b/fs/pstore/platform.c
@@ -595,8 +595,10 @@ int pstore_register(struct pstore_info *psi)
 
 	pstore_get_records(0);
 
-	if (psi->flags & PSTORE_FLAGS_DMESG)
+	if (psi->flags & PSTORE_FLAGS_DMESG) {
+		pstore_dumper.max_reason = psinfo->max_reason;
 		pstore_register_kmsg();
+	}
 	if (psi->flags & PSTORE_FLAGS_CONSOLE)
 		pstore_register_console();
 	if (psi->flags & PSTORE_FLAGS_FTRACE)
diff --git a/include/linux/pstore.h b/include/linux/pstore.h
index f6f22b13e04f..eb93a54cff31 100644
--- a/include/linux/pstore.h
+++ b/include/linux/pstore.h
@@ -96,6 +96,12 @@ struct pstore_record {
  *
  * @read_mutex:	serializes @open, @read, @close, and @erase callbacks
  * @flags:	bitfield of frontends the backend can accept writes for
+ * @max_reason:	Used when PSTORE_FLAGS_DMESG is set. Contains the
+ *		kmsg_dump_reason enum value. KMSG_DUMP_UNDEF means
+ *		"use existing kmsg_dump() filtering, based on the
+ *		printk.always_kmsg_dump boot param" (which is either
+ *		KMSG_DUMP_OOPS when false, or KMSG_DUMP_MAX when
+ *		true); see printk.always_kmsg_dump for more details.
  * @data:	backend-private pointer passed back during callbacks
  *
  * Callbacks:
@@ -179,6 +185,7 @@ struct pstore_info {
 	struct mutex	read_mutex;
 
 	int		flags;
+	int		max_reason;
 	void		*data;
 
 	int		(*open)(struct pstore_info *psi);
-- 
2.20.1


^ permalink raw reply related

* [PATCH v4 1/6] printk: Collapse shutdown types into a single dump reason
From: Kees Cook @ 2020-05-15 18:44 UTC (permalink / raw)
  To: Pavel Tatashin
  Cc: Kees Cook, Petr Mladek, Anton Vorontsov, Colin Cross, Tony Luck,
	Jonathan Corbet, Benson Leung, Rob Herring, Michael Ellerman,
	Benjamin Herrenschmidt, Paul Mackerras, Enric Balletbo i Serra,
	Sergey Senozhatsky, Steven Rostedt, linux-doc, linux-kernel,
	devicetree, linuxppc-dev
In-Reply-To: <20200515184434.8470-1-keescook@chromium.org>

To turn the KMSG_DUMP_* reasons into a more ordered list, collapse
the redundant KMSG_DUMP_(RESTART|HALT|POWEROFF) reasons into
KMSG_DUMP_SHUTDOWN. The current users already don't meaningfully
distinguish between them, so there's no need to, as discussed here:
https://lore.kernel.org/lkml/CA+CK2bAPv5u1ih5y9t5FUnTyximtFCtDYXJCpuyjOyHNOkRdqw@mail.gmail.com/

Signed-off-by: Kees Cook <keescook@chromium.org>
---
 arch/powerpc/kernel/nvram_64.c | 4 +---
 fs/pstore/platform.c           | 8 ++------
 include/linux/kmsg_dump.h      | 4 +---
 kernel/reboot.c                | 6 +++---
 4 files changed, 7 insertions(+), 15 deletions(-)

diff --git a/arch/powerpc/kernel/nvram_64.c b/arch/powerpc/kernel/nvram_64.c
index fb4f61096613..0cd1c88bfc8b 100644
--- a/arch/powerpc/kernel/nvram_64.c
+++ b/arch/powerpc/kernel/nvram_64.c
@@ -655,9 +655,7 @@ static void oops_to_nvram(struct kmsg_dumper *dumper,
 	int rc = -1;
 
 	switch (reason) {
-	case KMSG_DUMP_RESTART:
-	case KMSG_DUMP_HALT:
-	case KMSG_DUMP_POWEROFF:
+	case KMSG_DUMP_SHUTDOWN:
 		/* These are almost always orderly shutdowns. */
 		return;
 	case KMSG_DUMP_OOPS:
diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c
index 072440457c08..90d74ebaa70a 100644
--- a/fs/pstore/platform.c
+++ b/fs/pstore/platform.c
@@ -144,12 +144,8 @@ static const char *get_reason_str(enum kmsg_dump_reason reason)
 		return "Oops";
 	case KMSG_DUMP_EMERG:
 		return "Emergency";
-	case KMSG_DUMP_RESTART:
-		return "Restart";
-	case KMSG_DUMP_HALT:
-		return "Halt";
-	case KMSG_DUMP_POWEROFF:
-		return "Poweroff";
+	case KMSG_DUMP_SHUTDOWN:
+		return "Shutdown";
 	default:
 		return "Unknown";
 	}
diff --git a/include/linux/kmsg_dump.h b/include/linux/kmsg_dump.h
index 2e7a1e032c71..3f82b5cb2d82 100644
--- a/include/linux/kmsg_dump.h
+++ b/include/linux/kmsg_dump.h
@@ -25,9 +25,7 @@ enum kmsg_dump_reason {
 	KMSG_DUMP_PANIC,
 	KMSG_DUMP_OOPS,
 	KMSG_DUMP_EMERG,
-	KMSG_DUMP_RESTART,
-	KMSG_DUMP_HALT,
-	KMSG_DUMP_POWEROFF,
+	KMSG_DUMP_SHUTDOWN,
 };
 
 /**
diff --git a/kernel/reboot.c b/kernel/reboot.c
index c4d472b7f1b4..491f1347bf43 100644
--- a/kernel/reboot.c
+++ b/kernel/reboot.c
@@ -250,7 +250,7 @@ void kernel_restart(char *cmd)
 		pr_emerg("Restarting system\n");
 	else
 		pr_emerg("Restarting system with command '%s'\n", cmd);
-	kmsg_dump(KMSG_DUMP_RESTART);
+	kmsg_dump(KMSG_DUMP_SHUTDOWN);
 	machine_restart(cmd);
 }
 EXPORT_SYMBOL_GPL(kernel_restart);
@@ -274,7 +274,7 @@ void kernel_halt(void)
 	migrate_to_reboot_cpu();
 	syscore_shutdown();
 	pr_emerg("System halted\n");
-	kmsg_dump(KMSG_DUMP_HALT);
+	kmsg_dump(KMSG_DUMP_SHUTDOWN);
 	machine_halt();
 }
 EXPORT_SYMBOL_GPL(kernel_halt);
@@ -292,7 +292,7 @@ void kernel_power_off(void)
 	migrate_to_reboot_cpu();
 	syscore_shutdown();
 	pr_emerg("Power down\n");
-	kmsg_dump(KMSG_DUMP_POWEROFF);
+	kmsg_dump(KMSG_DUMP_SHUTDOWN);
 	machine_power_off();
 }
 EXPORT_SYMBOL_GPL(kernel_power_off);
-- 
2.20.1


^ permalink raw reply related

* Re: [PATCH v1 8/9] arm64: dts: actions: Add MMC controller support for S700
From: Amit Tomer @ 2020-05-15 18:41 UTC (permalink / raw)
  To: André Przywara
  Cc: Andreas Färber, Manivannan Sadhasivam, Rob Herring,
	cristian.ciocaltea, linux-arm-kernel, linux-actions, devicetree
In-Reply-To: <b2ad8a81-619f-5f35-9596-c2061ae15e4c@arm.com>

Hi,

> I was wondering if we should add a SoC specific compatible here, to be
> on the safe side. The BSP driver seems to differentiate between S900 and
> S700, although it looks like only to cover some misplaced platform setup.
>
> But if we later find a problem, the DTs stay the same, and the driver
> can easily be fixed.
>
> So, using "actions,s700-mmc", "actions,owl-mmc" here, adding this combo
> to the binding, but leaving the driver alone for now.

I think, it can be a good idea to have this extra compatible string that may
be needed when MMC driver evolves to support more features which requires
data to be differentiated based on SoC.

Thanks
Amit

^ permalink raw reply

* Re: [RFC 3/3] dt-bindings: usb: dwc3: Add entry for tx-fifo-resize
From: Wesley Cheng @ 2020-05-15 18:39 UTC (permalink / raw)
  To: Rob Herring
  Cc: agross, bjorn.andersson, balbi, gregkh, linux-arm-msm, devicetree,
	linux-kernel, linux-usb, jackp
In-Reply-To: <20200515031042.GA25107@bogus>



On 5/14/2020 8:10 PM, Rob Herring wrote:
> On Thu, May 07, 2020 at 02:59:28PM -0700, Wesley Cheng wrote:
>> Re-introduce the comment for the tx-fifo-resize setting for the DWC3
>> controller.
> 
> Why?
> 

Hi Rob,

Initially, the reasoning behind bringing back the DTSI parameter, was to
address situations where vendors don't require the resizing logic.  I
was assuming that each vendor has their own HW configuration for the TX
FIFO size, and some may already have sufficient space to account for
their endpoint requirements.  However, if Felipe doesn't believe we need
to have a DTSI parameter for this, then we don't need to re-add this
back in.

>>
>> Signed-off-by: Wesley Cheng <wcheng@codeaurora.org>
>> ---
>>  Documentation/devicetree/bindings/usb/dwc3.txt | 2 +-
>>  1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/Documentation/devicetree/bindings/usb/dwc3.txt b/Documentation/devicetree/bindings/usb/dwc3.txt
>> index 9946ff9..489f5da 100644
>> --- a/Documentation/devicetree/bindings/usb/dwc3.txt
>> +++ b/Documentation/devicetree/bindings/usb/dwc3.txt
>> @@ -105,7 +105,7 @@ Optional properties:
>>  			1-16 (DWC_usb31 programming guide section 1.2.3) to
>>  			enable periodic ESS TX threshold.
>>  
>> - - <DEPRECATED> tx-fifo-resize: determines if the FIFO *has* to be reallocated.
>> + - tx-fifo-resize: determines if the FIFO *has* to be reallocated.
>>   - snps,incr-burst-type-adjustment: Value for INCR burst type of GSBUSCFG0
>>  			register, undefined length INCR burst type enable and INCRx type.
>>  			When just one value, which means INCRX burst mode enabled. When
>> -- 
>> The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
>> a Linux Foundation Collaborative Project

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply

* Re: [PATCH v7 2/4] dt-bindings: phy: qcom,qmp-usb3-dp: Add dt bindings for USB3 DP PHY
From: Matthias Kaehlcke @ 2020-05-15 18:39 UTC (permalink / raw)
  To: Sandeep Maheswaram
  Cc: Andy Gross, Bjorn Andersson, Kishon Vijay Abraham I, Rob Herring,
	Mark Rutland, Stephen Boyd, Doug Anderson, linux-arm-msm,
	linux-kernel, devicetree, Manu Gautam
In-Reply-To: <1589510358-3865-3-git-send-email-sanm@codeaurora.org>

On Fri, May 15, 2020 at 08:09:16AM +0530, Sandeep Maheswaram wrote:

> Subject: dt-bindings: phy: qcom,qmp-usb3-dp: Add dt bindings for USB3 DP PHY

The subject is misleading, this patch doesn't add the binding for the USB3 DP
PHY, but factors it out.

^ permalink raw reply

* Re: [PATCH v2 00/19] spi: dw: Add generic DW DMA controller support
From: Mark Brown @ 2020-05-15 18:21 UTC (permalink / raw)
  To: Serge Semin
  Cc: Serge Semin, Georgy Vlasov, Ramil Zaripov, Alexey Malahov,
	Maxim Kaurkin, Pavel Parkhomenko, Ekaterina Skachko, Vadim Vlasov,
	Alexey Kolotnikov, Thomas Bogendoerfer, Paul Burton, Ralf Baechle,
	Arnd Bergmann, Allison Randal, Andy Shevchenko, Gareth Williams,
	Rob Herring, linux-mips, linux-spi, devicetree, linux-kernel
In-Reply-To: <20200515104758.6934-1-Sergey.Semin@baikalelectronics.ru>

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

On Fri, May 15, 2020 at 01:47:39PM +0300, Serge Semin wrote:

Appled:

>   dt-bindings: spi: dw: Add Tx/Rx DMA properties
>   spi: dw: Clear DMAC register when done or stopped
>   spi: dw: Fix native CS being unset
>   spi: dw: Initialize paddr in DW SPI MMIO private data

Thanks.  No issues from me with the other patches.

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply

* Re: [PATCH v8 2/6] ARM: tegra: Add device-tree for ASUS Google Nexus 7
From: Michał Mirosław @ 2020-05-15 18:18 UTC (permalink / raw)
  To: Dmitry Osipenko
  Cc: Rob Herring, Thierry Reding, Jonathan Hunter, David Heidelberg,
	Peter Geis, Stephen Warren, Nicolas Chauvet, Pedro Ângelo,
	Matt Merhar, Zack Pearsall, linux-tegra, devicetree, linux-kernel
In-Reply-To: <20200514213654.12834-3-digetx@gmail.com>

On Fri, May 15, 2020 at 12:36:50AM +0300, Dmitry Osipenko wrote:
> There are few hardware variants of NVIDIA Tegra30-based Nexus 7 device:
> 
> 1. WiFi-only (named Grouper)
> 2. GSM (named Tilapia)
> 3. Using Maxim PMIC (E1565 board ID)
> 4. Using Ti PMIC (PM269 board ID)

Hi,

I've briefly looked at the PM269 devicetree (PMIC part) and it looks very
similar, if not the same, to what I deduced from the TF300T kernel.
Those devices don't look to differ much from original Cardhu tablet
devkit, so maybe the trees can base off of that?

I would also guess that because of this 'ram-code', memory timings would
be duplicated between devices. I can see small differences between
ram-code=1 timings of Grouper and TF300T, though they look like arbiter
tuning differences. I'll have to test if my TF300T works with Grouper's
settings. In case they work, could you split the memory timings to another
dtsi file?

BTW, shouldn't EMC timing set match MC? I see more frequencies listed in
MC than EMC nodes.

Best Regards,
Michał Mirosław

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox