aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/mfd/allwinner,sun6i-a31-prcm.yaml40
-rw-r--r--Documentation/devicetree/bindings/mfd/allwinner,sun8i-a23-prcm.yaml10
-rw-r--r--Documentation/devicetree/bindings/mfd/aspeed,ast2x00-scu.yaml110
-rw-r--r--Documentation/devicetree/bindings/mfd/aspeed-scu.txt48
-rw-r--r--Documentation/devicetree/bindings/mfd/cirrus,lochnagar.yaml5
-rw-r--r--Documentation/devicetree/bindings/mfd/dlg,da9063.yaml7
-rw-r--r--Documentation/devicetree/bindings/mfd/gateworks-gsc.yaml5
-rw-r--r--Documentation/devicetree/bindings/mfd/maxim,max14577.yaml1
-rw-r--r--Documentation/devicetree/bindings/mfd/maxim,max77843.yaml1
-rw-r--r--Documentation/devicetree/bindings/mfd/mediatek,mt6370.yaml280
-rw-r--r--Documentation/devicetree/bindings/mfd/mediatek,mt8195-scpsys.yaml68
-rw-r--r--Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml114
-rw-r--r--Documentation/devicetree/bindings/mfd/qcom,tcsr.yaml46
-rw-r--r--Documentation/devicetree/bindings/mfd/richtek,rt5120.yaml178
-rw-r--r--Documentation/devicetree/bindings/mfd/rockchip,rk817.yaml52
-rw-r--r--Documentation/devicetree/bindings/mfd/silergy,sy7636a.yaml1
-rw-r--r--Documentation/devicetree/bindings/mfd/sprd,ums512-glbreg.yaml71
-rw-r--r--Documentation/devicetree/bindings/mfd/st,stm32-lptimer.yaml4
-rw-r--r--Documentation/devicetree/bindings/mfd/st,stm32-timers.yaml3
-rw-r--r--Documentation/devicetree/bindings/mfd/st,stmfx.yaml1
-rw-r--r--Documentation/devicetree/bindings/mfd/stericsson,ab8500.yaml22
-rw-r--r--Documentation/devicetree/bindings/mfd/syscon.yaml17
-rw-r--r--Documentation/devicetree/bindings/mfd/ti,tps65086.yaml1
-rw-r--r--Documentation/devicetree/bindings/mfd/x-powers,axp152.yaml4
-rw-r--r--Documentation/devicetree/bindings/power/mediatek,power-controller.yaml2
-rw-r--r--MAINTAINERS1
-rw-r--r--arch/arm/boot/dts/tegra30-apalis-v1.1.dtsi2
-rw-r--r--arch/arm/boot/dts/tegra30-apalis.dtsi2
-rw-r--r--arch/arm/boot/dts/tegra30-colibri.dtsi2
-rw-r--r--arch/arm/mach-omap1/board-htcherald.c9
-rw-r--r--drivers/hwmon/Kconfig1
-rw-r--r--drivers/mfd/Kconfig44
-rw-r--r--drivers/mfd/Makefile12
-rw-r--r--drivers/mfd/da9062-core.c1
-rw-r--r--drivers/mfd/fsl-imx25-tsadc.c34
-rw-r--r--drivers/mfd/htc-i2cpld.c60
-rw-r--r--drivers/mfd/intel-lpss-pci.c141
-rw-r--r--drivers/mfd/intel-m10-bmc.c1
-rw-r--r--drivers/mfd/intel_soc_pmic_chtdc_ti.c8
-rw-r--r--drivers/mfd/intel_soc_pmic_core.c158
-rw-r--r--drivers/mfd/intel_soc_pmic_core.h25
-rw-r--r--drivers/mfd/intel_soc_pmic_crc.c139
-rw-r--r--drivers/mfd/lp8788-irq.c3
-rw-r--r--drivers/mfd/lp8788.c12
-rw-r--r--drivers/mfd/lpc_ich.c2
-rw-r--r--drivers/mfd/mfd-core.c9
-rw-r--r--drivers/mfd/mt6370.c312
-rw-r--r--drivers/mfd/mt6370.h99
-rw-r--r--drivers/mfd/ocelot-spi.c1
-rw-r--r--drivers/mfd/qcom-spmi-pmic.c1
-rw-r--r--drivers/mfd/rk808.c16
-rw-r--r--drivers/mfd/rt5120.c124
-rw-r--r--drivers/mfd/sm501.c7
-rw-r--r--drivers/mfd/stmpe.c49
-rw-r--r--drivers/mfd/syscon.c8
-rw-r--r--drivers/mfd/twl-core.c2
-rw-r--r--drivers/mfd/twl4030-irq.c1
-rw-r--r--drivers/power/supply/Kconfig6
-rw-r--r--drivers/power/supply/Makefile1
-rw-r--r--drivers/power/supply/rk817_charger.c1211
-rw-r--r--drivers/regulator/Kconfig1
-rw-r--r--include/dt-bindings/iio/adc/mediatek,mt6370_adc.h18
-rw-r--r--include/linux/htcpld.h2
-rw-r--r--include/linux/mfd/rk808.h91
64 files changed, 3274 insertions, 433 deletions
diff --git a/Documentation/devicetree/bindings/mfd/allwinner,sun6i-a31-prcm.yaml b/Documentation/devicetree/bindings/mfd/allwinner,sun6i-a31-prcm.yaml
index d131759ccaf3..021d33cb3dd6 100644
--- a/Documentation/devicetree/bindings/mfd/allwinner,sun6i-a31-prcm.yaml
+++ b/Documentation/devicetree/bindings/mfd/allwinner,sun6i-a31-prcm.yaml
@@ -22,6 +22,7 @@ properties:
patternProperties:
"^.*_(clk|rst)$":
type: object
+ unevaluatedProperties: false
properties:
compatible:
@@ -38,6 +39,45 @@ patternProperties:
properties:
compatible:
contains:
+ const: fixed-factor-clock
+
+ then:
+ $ref: /schemas/clock/fixed-factor-clock.yaml#
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: allwinner,sun4i-a10-mod0-clk
+
+ then:
+ properties:
+ "#clock-cells":
+ const: 0
+
+ # Already checked in the main schema
+ compatible: true
+
+ clocks:
+ maxItems: 2
+
+ clock-output-names:
+ maxItems: 1
+
+ phandle: true
+
+ required:
+ - "#clock-cells"
+ - compatible
+ - clocks
+ - clock-output-names
+
+ additionalProperties: false
+
+ - if:
+ properties:
+ compatible:
+ contains:
const: allwinner,sun6i-a31-apb0-clk
then:
diff --git a/Documentation/devicetree/bindings/mfd/allwinner,sun8i-a23-prcm.yaml b/Documentation/devicetree/bindings/mfd/allwinner,sun8i-a23-prcm.yaml
index aa5e683b236c..01f4f5210574 100644
--- a/Documentation/devicetree/bindings/mfd/allwinner,sun8i-a23-prcm.yaml
+++ b/Documentation/devicetree/bindings/mfd/allwinner,sun8i-a23-prcm.yaml
@@ -22,6 +22,7 @@ properties:
patternProperties:
"^.*(clk|rst|codec).*$":
type: object
+ unevaluatedProperties: false
properties:
compatible:
@@ -40,6 +41,15 @@ patternProperties:
properties:
compatible:
contains:
+ const: fixed-factor-clock
+
+ then:
+ $ref: /schemas/clock/fixed-factor-clock.yaml#
+
+ - if:
+ properties:
+ compatible:
+ contains:
const: allwinner,sun8i-a23-apb0-clk
then:
diff --git a/Documentation/devicetree/bindings/mfd/aspeed,ast2x00-scu.yaml b/Documentation/devicetree/bindings/mfd/aspeed,ast2x00-scu.yaml
new file mode 100644
index 000000000000..1689b986f441
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/aspeed,ast2x00-scu.yaml
@@ -0,0 +1,110 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mfd/aspeed,ast2x00-scu.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Aspeed System Control Unit
+
+description:
+ The Aspeed System Control Unit manages the global behaviour of the SoC,
+ configuring elements such as clocks, pinmux, and reset.
+
+maintainers:
+ - Joel Stanley <joel@jms.id.au>
+ - Andrew Jeffery <andrew@aj.id.au>
+
+properties:
+ compatible:
+ items:
+ - enum:
+ - aspeed,ast2400-scu
+ - aspeed,ast2500-scu
+ - aspeed,ast2600-scu
+ - const: syscon
+ - const: simple-mfd
+
+ reg:
+ maxItems: 1
+
+ ranges: true
+
+ '#address-cells':
+ const: 1
+
+ '#size-cells':
+ const: 1
+
+ '#clock-cells':
+ const: 1
+
+ '#reset-cells':
+ const: 1
+
+patternProperties:
+ '^p2a-control@[0-9a-f]+$':
+ description: See Documentation/devicetree/bindings/misc/aspeed-p2a-ctrl.txt
+ type: object
+
+ '^pinctrl(@[0-9a-f]+)?$':
+ oneOf:
+ - $ref: /schemas/pinctrl/aspeed,ast2400-pinctrl.yaml
+ - $ref: /schemas/pinctrl/aspeed,ast2500-pinctrl.yaml
+ - $ref: /schemas/pinctrl/aspeed,ast2600-pinctrl.yaml
+
+ '^interrupt-controller@[0-9a-f]+$':
+ description: See Documentation/devicetree/bindings/interrupt-controller/aspeed,ast2xxx-scu-ic.txt
+ type: object
+
+ '^silicon-id@[0-9a-f]+$':
+ description: Unique hardware silicon identifiers within the SoC
+ type: object
+ additionalProperties: false
+
+ properties:
+ compatible:
+ items:
+ - enum:
+ - aspeed,ast2400-silicon-id
+ - aspeed,ast2500-silicon-id
+ - aspeed,ast2600-silicon-id
+ - const: aspeed,silicon-id
+
+ reg:
+ description:
+ The reg should be the unique silicon id register, and not backwards
+ compatible one in eg. the 2600.
+ minItems: 1
+ items:
+ - description: silicon id information registers
+ - description: unique chip id registers
+
+required:
+ - compatible
+ - reg
+ - ranges
+ - '#address-cells'
+ - '#size-cells'
+ - '#clock-cells'
+ - '#reset-cells'
+
+additionalProperties: false
+
+examples:
+ - |
+ syscon@1e6e2000 {
+ compatible = "aspeed,ast2400-scu", "syscon", "simple-mfd";
+ reg = <0x1e6e2000 0x1a8>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0x0 0x1e6e2000 0x1000>;
+
+ silicon-id@7c {
+ compatible = "aspeed,ast2500-silicon-id", "aspeed,silicon-id";
+ reg = <0x7c 0x4>, <0x150 0x8>;
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/mfd/aspeed-scu.txt b/Documentation/devicetree/bindings/mfd/aspeed-scu.txt
deleted file mode 100644
index 857ee33f7329..000000000000
--- a/Documentation/devicetree/bindings/mfd/aspeed-scu.txt
+++ /dev/null
@@ -1,48 +0,0 @@
-The Aspeed System Control Unit manages the global behaviour of the SoC,
-configuring elements such as clocks, pinmux, and reset.
-
-Required properties:
-- compatible: One of:
- "aspeed,ast2400-scu", "syscon", "simple-mfd"
- "aspeed,ast2500-scu", "syscon", "simple-mfd"
-
-- reg: contains the offset and length of the SCU memory region
-- #clock-cells: should be set to <1> - the system controller is also a
- clock provider
-- #reset-cells: should be set to <1> - the system controller is also a
- reset line provider
-
-Example:
-
-syscon: syscon@1e6e2000 {
- compatible = "aspeed,ast2400-scu", "syscon", "simple-mfd";
- reg = <0x1e6e2000 0x1a8>;
- #clock-cells = <1>;
- #reset-cells = <1>;
-};
-
-Silicon ID
------------------
-
-Families have unique hardware silicon identifiers within the SoC.
-
-Required properties:
-
- - compatible: "aspeed,silicon-id" or:
- "aspeed,ast2400-silicon-id" or
- "aspeed,ast2500-silicon-id" or
- "aspeed,ast2600-silicon-id"
-
- - reg: offset and length of the silicon id information
- optionally, a second offset and length describes the unique chip id
-
- The reg should be the unique silicon id register, and
- not backwards compatible one in eg. the 2600.
-
-Example:
-
-
-silicon-id@7c {
- compatible = "aspeed,ast2500-silicon-id", "aspeed,silicon-id";
- reg = <0x7c 0x4 0x150 0x8>;
-};
diff --git a/Documentation/devicetree/bindings/mfd/cirrus,lochnagar.yaml b/Documentation/devicetree/bindings/mfd/cirrus,lochnagar.yaml
index ad285cb480c9..86f7341eb7e1 100644
--- a/Documentation/devicetree/bindings/mfd/cirrus,lochnagar.yaml
+++ b/Documentation/devicetree/bindings/mfd/cirrus,lochnagar.yaml
@@ -144,6 +144,7 @@ properties:
CODECs digital core if not being provided by an internal regulator.
type: object
$ref: /schemas/regulator/regulator.yaml#
+ unevaluatedProperties: false
properties:
compatible:
enum:
@@ -161,6 +162,7 @@ properties:
CODECs MICVDD.
type: object
$ref: /schemas/regulator/regulator.yaml#
+ unevaluatedProperties: false
properties:
compatible:
enum:
@@ -177,6 +179,7 @@ properties:
Initialisation data for the MIC1VDD supplies.
type: object
$ref: /schemas/regulator/regulator.yaml#
+ unevaluatedProperties: false
properties:
compatible:
enum:
@@ -202,6 +205,7 @@ properties:
Initialisation data for the MIC2VDD supplies.
type: object
$ref: /schemas/regulator/regulator.yaml#
+ unevaluatedProperties: false
properties:
compatible:
enum:
@@ -228,6 +232,7 @@ properties:
the CODECs analog and 1.8V digital supplies.
type: object
$ref: /schemas/regulator/regulator.yaml#
+ unevaluatedProperties: false
properties:
compatible:
enum:
diff --git a/Documentation/devicetree/bindings/mfd/dlg,da9063.yaml b/Documentation/devicetree/bindings/mfd/dlg,da9063.yaml
index d71933460e90..e8e74e91070c 100644
--- a/Documentation/devicetree/bindings/mfd/dlg,da9063.yaml
+++ b/Documentation/devicetree/bindings/mfd/dlg,da9063.yaml
@@ -71,8 +71,9 @@ properties:
regulators:
type: object
+ additionalProperties: false
patternProperties:
- "^(ldo[1-11]|bcore[1-2]|bpro|bmem|bio|bperi)$":
+ "^(ldo([1-9]|1[01])|bcore([1-2]|s-merged)|b(pro|mem|io|peri)|bmem-bio-merged)$":
$ref: /schemas/regulator/regulator.yaml
unevaluatedProperties: false
@@ -112,7 +113,7 @@ examples:
};
regulators {
- regulator-bcore1 {
+ bcore1 {
regulator-name = "BCORE1";
regulator-min-microvolt = <300000>;
regulator-max-microvolt = <1570000>;
@@ -120,7 +121,7 @@ examples:
regulator-max-microamp = <2000000>;
regulator-boot-on;
};
- regulator-ldo11 {
+ ldo11 {
regulator-name = "LDO_11";
regulator-min-microvolt = <900000>;
regulator-max-microvolt = <3600000>;
diff --git a/Documentation/devicetree/bindings/mfd/gateworks-gsc.yaml b/Documentation/devicetree/bindings/mfd/gateworks-gsc.yaml
index 5e0fe3ebe1d2..acb9c54942d9 100644
--- a/Documentation/devicetree/bindings/mfd/gateworks-gsc.yaml
+++ b/Documentation/devicetree/bindings/mfd/gateworks-gsc.yaml
@@ -46,6 +46,7 @@ properties:
adc:
type: object
+ additionalProperties: false
description: Optional hardware monitoring module
properties:
@@ -59,8 +60,9 @@ properties:
const: 0
patternProperties:
- "^channel@[0-9]+$":
+ "^channel@[0-9a-f]+$":
type: object
+ additionalProperties: false
description: |
Properties for a single ADC which can report cooked values
(i.e. temperature sensor based on thermister), raw values
@@ -113,6 +115,7 @@ properties:
patternProperties:
"^fan-controller@[0-9a-f]+$":
type: object
+ additionalProperties: false
description: Optional fan controller
properties:
diff --git a/Documentation/devicetree/bindings/mfd/maxim,max14577.yaml b/Documentation/devicetree/bindings/mfd/maxim,max14577.yaml
index 52edd1bf549f..995e96ee7445 100644
--- a/Documentation/devicetree/bindings/mfd/maxim,max14577.yaml
+++ b/Documentation/devicetree/bindings/mfd/maxim,max14577.yaml
@@ -39,6 +39,7 @@ properties:
extcon:
type: object
+ additionalProperties: false
properties:
compatible:
enum:
diff --git a/Documentation/devicetree/bindings/mfd/maxim,max77843.yaml b/Documentation/devicetree/bindings/mfd/maxim,max77843.yaml
index f30f96bbff43..2e2a2a86b57d 100644
--- a/Documentation/devicetree/bindings/mfd/maxim,max77843.yaml
+++ b/Documentation/devicetree/bindings/mfd/maxim,max77843.yaml
@@ -32,6 +32,7 @@ properties:
motor-driver:
type: object
+ additionalProperties: false
properties:
compatible:
const: maxim,max77843-haptic
diff --git a/Documentation/devicetree/bindings/mfd/mediatek,mt6370.yaml b/Documentation/devicetree/bindings/mfd/mediatek,mt6370.yaml
new file mode 100644
index 000000000000..250484d59ecd
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/mediatek,mt6370.yaml
@@ -0,0 +1,280 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mfd/mediatek,mt6370.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: MediaTek MT6370 SubPMIC
+
+maintainers:
+ - ChiYuan Huang <cy_huang@richtek.com>
+
+description: |
+ MT6370 is a highly-integrated smart power management IC, which includes a
+ single cell Li-Ion/Li-Polymer switching battery charger, a USB Type-C &
+ Power Delivery (PD) controller, dual flash LED current sources, a RGB LED
+ driver, a backlight WLED driver, a display bias driver and a general LDO for
+ portable devices.
+
+properties:
+ compatible:
+ const: mediatek,mt6370
+
+ reg:
+ maxItems: 1
+
+ wakeup-source: true
+
+ interrupts:
+ maxItems: 1
+
+ interrupt-controller: true
+
+ "#interrupt-cells":
+ const: 1
+
+ adc:
+ type: object
+ description: |
+ Provides 9 channels for system monitoring, including VBUSDIV5 (lower
+ accuracy, higher measure range), VBUSDIV2 (higher accuracy, lower
+ measure range), VBAT, VSYS, CHG_VDDP, TS_BAT, IBUS, IBAT, and TEMP_JC.
+
+ properties:
+ compatible:
+ const: mediatek,mt6370-adc
+
+ "#io-channel-cells":
+ const: 1
+
+ required:
+ - compatible
+ - "#io-channel-cells"
+
+ backlight:
+ type: object
+ $ref: /schemas/leds/backlight/mediatek,mt6370-backlight.yaml#
+
+ charger:
+ type: object
+ $ref: /schemas/power/supply/mediatek,mt6370-charger.yaml#
+
+ tcpc:
+ type: object
+ $ref: /schemas/usb/mediatek,mt6370-tcpc.yaml#
+
+ indicator:
+ type: object
+ $ref: /schemas/leds/mediatek,mt6370-indicator.yaml#
+
+ flashlight:
+ type: object
+ $ref: /schemas/leds/mediatek,mt6370-flashlight.yaml#
+
+ regulators:
+ type: object
+ description: |
+ List all supported regulators, which support the control for DisplayBias
+ voltages and one general purpose LDO which commonly used to drive the
+ vibrator.
+
+ patternProperties:
+ "^(dsvbst|vibldo)$":
+ $ref: /schemas/regulator/regulator.yaml#
+ type: object
+ unevaluatedProperties: false
+
+ "^(dsvpos|dsvneg)$":
+ $ref: /schemas/regulator/regulator.yaml#
+ type: object
+ unevaluatedProperties: false
+
+ properties:
+ enable-gpios:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - interrupt-controller
+ - "#interrupt-cells"
+ - regulators
+ - adc
+ - backlight
+ - indicator
+ - tcpc
+ - charger
+ - flashlight
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+ #include <dt-bindings/leds/common.h>
+ #include <dt-bindings/iio/adc/mediatek,mt6370_adc.h>
+ #include <dt-bindings/usb/pd.h>
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ pmic@34 {
+ compatible = "mediatek,mt6370";
+ reg = <0x34>;
+ wakeup-source;
+ interrupts-extended = <&gpio26 3 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+
+ mt6370_adc: adc {
+ compatible = "mediatek,mt6370-adc";
+ #io-channel-cells = <1>;
+ };
+
+ backlight {
+ compatible = "mediatek,mt6370-backlight";
+ mediatek,bled-channel-use = /bits/ 8 <15>;
+ };
+
+ charger {
+ compatible = "mediatek,mt6370-charger";
+ interrupts = <48>, <68>, <6>;
+ interrupt-names = "attach_i", "uvp_d_evt", "mivr";
+ io-channels = <&mt6370_adc MT6370_CHAN_IBUS>;
+
+ mt6370_otg_vbus: usb-otg-vbus-regulator {
+ regulator-name = "mt6370-usb-otg-vbus";
+ regulator-min-microvolt = <4350000>;
+ regulator-max-microvolt = <5800000>;
+ regulator-min-microamp = <500000>;
+ regulator-max-microamp = <3000000>;
+ };
+ };
+
+ indicator {
+ compatible = "mediatek,mt6370-indicator";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ multi-led@0 {
+ reg = <0>;
+ function = LED_FUNCTION_INDICATOR;
+ color = <LED_COLOR_ID_RGB>;
+ led-max-microamp = <24000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ led@0 {
+ reg = <0>;
+ color = <LED_COLOR_ID_RED>;
+ };
+ led@1 {
+ reg = <1>;
+ color = <LED_COLOR_ID_GREEN>;
+ };
+ led@2 {
+ reg = <2>;
+ color = <LED_COLOR_ID_BLUE>;
+ };
+ };
+ led@3 {
+ reg = <3>;
+ function = LED_FUNCTION_INDICATOR;
+ color = <LED_COLOR_ID_WHITE>;
+ led-max-microamp = <6000>;
+ };
+ };
+
+ flashlight {
+ compatible = "mediatek,mt6370-flashlight";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ led@0 {
+ reg = <0>;
+ led-sources = <0>;
+ function = LED_FUNCTION_FLASH;
+ color = <LED_COLOR_ID_WHITE>;
+ function-enumerator = <1>;
+ led-max-microamp = <200000>;
+ flash-max-microamp = <500000>;
+ flash-max-timeout-us = <1248000>;
+ };
+ led@1 {
+ reg = <1>;
+ led-sources = <1>;
+ function = LED_FUNCTION_FLASH;
+ color = <LED_COLOR_ID_WHITE>;
+ function-enumerator = <2>;
+ led-max-microamp = <200000>;
+ flash-max-microamp = <500000>;
+ flash-max-timeout-us = <1248000>;
+ };
+ };
+
+ tcpc {
+ compatible = "mediatek,mt6370-tcpc";
+ interrupts-extended = <&gpio26 4 IRQ_TYPE_LEVEL_LOW>;
+
+ connector {
+ compatible = "usb-c-connector";
+ label = "USB-C";
+ vbus-supply = <&mt6370_otg_vbus>;
+ data-role = "dual";
+ power-role = "dual";
+ try-power-role = "sink";
+ source-pdos = <PDO_FIXED(5000, 1000, PDO_FIXED_DUAL_ROLE | PDO_FIXED_DATA_SWAP)>;
+ sink-pdos = <PDO_FIXED(5000, 2000, PDO_FIXED_DUAL_ROLE | PDO_FIXED_DATA_SWAP)>;
+ op-sink-microwatt = <10000000>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ endpoint {
+ remote-endpoint = <&usb_hs>;
+ };
+ };
+ port@1 {
+ reg = <1>;
+ endpoint {
+ remote-endpoint = <&usb_ss>;
+ };
+ };
+ port@2 {
+ reg = <2>;
+ endpoint {
+ remote-endpoint = <&dp_aux>;
+ };
+ };
+ };
+ };
+ };
+
+ regulators {
+ dsvbst {
+ regulator-name = "mt6370-dsv-vbst";
+ regulator-min-microvolt = <4000000>;
+ regulator-max-microvolt = <6200000>;
+ };
+ dsvpos {
+ regulator-name = "mt6370-dsv-vpos";
+ regulator-min-microvolt = <4000000>;
+ regulator-max-microvolt = <6000000>;
+ regulator-boot-on;
+ };
+ dsvneg {
+ regulator-name = "mt6370-dsv-vneg";
+ regulator-min-microvolt = <4000000>;
+ regulator-max-microvolt = <6000000>;
+ regulator-boot-on;
+ };
+ vibldo {
+ regulator-name = "mt6370-vib-ldo";
+ regulator-min-microvolt = <1600000>;
+ regulator-max-microvolt = <4000000>;
+ };
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/mfd/mediatek,mt8195-scpsys.yaml b/Documentation/devicetree/bindings/mfd/mediatek,mt8195-scpsys.yaml
new file mode 100644
index 000000000000..c8c4812fffe2
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/mediatek,mt8195-scpsys.yaml
@@ -0,0 +1,68 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mfd/mediatek,mt8195-scpsys.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: MediaTek System Control Processor System
+
+maintainers:
+ - MandyJH Liu <mandyjh.liu@mediatek.com>
+
+description:
+ MediaTek System Control Processor System (SCPSYS) has several
+ power management tasks. The tasks include MTCMOS power
+ domain control, thermal measurement, DVFS, etc.
+
+properties:
+ compatible:
+ items:
+ - enum:
+ - mediatek,mt8167-scpsys
+ - mediatek,mt8173-scpsys
+ - mediatek,mt8183-scpsys
+ - mediatek,mt8186-scpsys
+ - mediatek,mt8192-scpsys
+ - mediatek,mt8195-scpsys
+ - const: syscon
+ - const: simple-mfd
+
+ reg:
+ maxItems: 1
+
+ power-controller:
+ $ref: /schemas/power/mediatek,power-controller.yaml#
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/mt8195-clk.h>
+ #include <dt-bindings/power/mt8195-power.h>
+
+ syscon@10006000 {
+ compatible = "mediatek,mt8195-scpsys", "syscon", "simple-mfd";
+ reg = <0x10006000 0x100>;
+
+ spm: power-controller {
+ compatible = "mediatek,mt8195-power-controller";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #power-domain-cells = <1>;
+
+ /* sample of power domain nodes */
+ power-domain@MT8195_POWER_DOMAIN_PCIE_PHY {
+ reg = <MT8195_POWER_DOMAIN_PCIE_PHY>;
+ #power-domain-cells = <0>;
+ };
+
+ power-domain@MT8195_POWER_DOMAIN_SSUSB_PCIE_PHY {
+ reg = <MT8195_POWER_DOMAIN_SSUSB_PCIE_PHY>;
+ #power-domain-cells = <0>;
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml b/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml
index 65cbc6dee545..6a3e3ede1ede 100644
--- a/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml
+++ b/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml
@@ -33,19 +33,22 @@ properties:
compatible:
items:
- enum:
- - qcom,pm660
- - qcom,pm660l
- qcom,pm6150
- qcom,pm6150l
- qcom,pm6350
+ - qcom,pm660
+ - qcom,pm660l
+ - qcom,pm7250b
- qcom,pm7325
- qcom,pm8004
- qcom,pm8005
- qcom,pm8009
- qcom,pm8019
+ - qcom,pm8028
- qcom,pm8110
- qcom,pm8150
- qcom,pm8150b
+ - qcom,pm8150c
- qcom,pm8150l
- qcom,pm8226
- qcom,pm8350
@@ -56,6 +59,7 @@ properties:
- qcom,pm8916
- qcom,pm8941
- qcom,pm8950
+ - qcom,pm8953
- qcom,pm8994
- qcom,pm8998
- qcom,pma8084
@@ -64,8 +68,10 @@ properties:
- qcom,pmi8962
- qcom,pmi8994
- qcom,pmi8998
+ - qcom,pmk8002
- qcom,pmk8350
- qcom,pmm8155au
+ - qcom,pmp8074
- qcom,pmr735a
- qcom,pmr735b
- qcom,pms405
@@ -90,7 +96,7 @@ properties:
regulators:
type: object
- $ref: /schemas/regulator/regulator.yaml#
+ $ref: /schemas/regulator/qcom,spmi-regulator.yaml#
patternProperties:
"^adc@[0-9a-f]+$":
@@ -99,7 +105,7 @@ patternProperties:
"^adc-tm@[0-9a-f]+$":
type: object
- $ref: /schemas/thermal/qcom-spmi-adc-tm5.yaml#
+ # ref depends on compatible, see allOf below
"^audio-codec@[0-9a-f]+$":
type: object
@@ -146,6 +152,22 @@ required:
- compatible
- reg
+allOf:
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - qcom,pm8998
+ then:
+ patternProperties:
+ "^adc-tm@[0-9a-f]+$":
+ $ref: /schemas/thermal/qcom-spmi-adc-tm-hc.yaml#
+ else:
+ patternProperties:
+ "^adc-tm@[0-9a-f]+$":
+ $ref: /schemas/thermal/qcom-spmi-adc-tm5.yaml#
+
additionalProperties: false
examples:
@@ -188,3 +210,87 @@ examples:
};
};
};
+
+ - |
+ #include <dt-bindings/input/input.h>
+ #include <dt-bindings/interrupt-controller/irq.h>
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/iio/qcom,spmi-vadc.h>
+ #include <dt-bindings/spmi/spmi.h>
+
+ pmic@0 {
+ compatible = "qcom,pm6150", "qcom,spmi-pmic";
+ reg = <0x0 SPMI_USID>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ pon@800 {
+ compatible = "qcom,pm8998-pon";
+ reg = <0x800>;
+ mode-bootloader = <0x2>;
+ mode-recovery = <0x1>;
+
+ pwrkey {
+ compatible = "qcom,pm8941-pwrkey";
+ interrupts = <0x0 0x8 0 IRQ_TYPE_EDGE_BOTH>;
+ debounce = <15625>;
+ bias-pull-up;
+ linux,code = <KEY_POWER>;
+ };
+ };
+
+ temp-alarm@2400 {
+ compatible = "qcom,spmi-temp-alarm";
+ reg = <0x2400>;
+ interrupts = <0x0 0x24 0x0 IRQ_TYPE_EDGE_RISING>;
+ io-channels = <&pm6150_adc ADC5_DIE_TEMP>;
+ io-channel-names = "thermal";
+ #thermal-sensor-cells = <0>;
+ };
+
+ pm6150_adc: adc@3100 {
+ compatible = "qcom,spmi-adc5";
+ reg = <0x3100>;
+ interrupts = <0x0 0x31 0x0 IRQ_TYPE_EDGE_RISING>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #io-channel-cells = <1>;
+
+ adc-chan@6 {
+ reg = <ADC5_DIE_TEMP>;
+ label = "die_temp";
+ };
+
+ adc-chan@4f {
+ reg = <ADC5_AMUX_THM3_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time = <200>;
+ };
+ };
+
+ adc-tm@3500 {
+ compatible = "qcom,spmi-adc-tm5";
+ reg = <0x3500>;
+ interrupts = <0x0 0x35 0x0 IRQ_TYPE_EDGE_RISING>;
+ #thermal-sensor-cells = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ charger-thermistor@0 {
+ reg = <0>;
+ io-channels = <&pm6150_adc ADC5_AMUX_THM3_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time-us = <200>;
+ };
+ };
+
+ pm6150_gpio: gpios@c000 {
+ compatible = "qcom,pm6150-gpio", "qcom,spmi-gpio";
+ reg = <0xc000>;
+ gpio-controller;
+ gpio-ranges = <&pm6150_gpio 0 0 10>;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/mfd/qcom,tcsr.yaml b/Documentation/devicetree/bindings/mfd/qcom,tcsr.yaml
index d3c25daa995e..b12809b5cc22 100644
--- a/Documentation/devicetree/bindings/mfd/qcom,tcsr.yaml
+++ b/Documentation/devicetree/bindings/mfd/qcom,tcsr.yaml
@@ -15,31 +15,27 @@ description:
properties:
compatible:
- oneOf:
- - items:
- - enum:
- - qcom,msm8998-tcsr
- - qcom,qcs404-tcsr
- - qcom,sc7180-tcsr
- - qcom,sc7280-tcsr
- - qcom,sdm630-tcsr
- - qcom,sdm845-tcsr
- - qcom,sm8150-tcsr
- - qcom,tcsr-apq8064
- - qcom,tcsr-apq8084
- - qcom,tcsr-ipq8064
- - qcom,tcsr-mdm9615
- - qcom,tcsr-msm8660
- - qcom,tcsr-msm8916
- - qcom,tcsr-msm8953
- - qcom,tcsr-msm8960
- - qcom,tcsr-msm8974
- - qcom,tcsr-msm8996
- - const: syscon
- - items:
- - const: qcom,tcsr-ipq6018
- - const: syscon
- - const: simple-mfd
+ items:
+ - enum:
+ - qcom,msm8998-tcsr
+ - qcom,qcs404-tcsr
+ - qcom,sc7180-tcsr
+ - qcom,sc7280-tcsr
+ - qcom,sdm630-tcsr
+ - qcom,sdm845-tcsr
+ - qcom,sm8150-tcsr
+ - qcom,tcsr-apq8064
+ - qcom,tcsr-apq8084
+ - qcom,tcsr-ipq6018
+ - qcom,tcsr-ipq8064
+ - qcom,tcsr-mdm9615
+ - qcom,tcsr-msm8660
+ - qcom,tcsr-msm8916
+ - qcom,tcsr-msm8953
+ - qcom,tcsr-msm8960
+ - qcom,tcsr-msm8974
+ - qcom,tcsr-msm8996
+ - const: syscon
reg:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/mfd/richtek,rt5120.yaml b/Documentation/devicetree/bindings/mfd/richtek,rt5120.yaml
new file mode 100644
index 000000000000..f73b8b25d7d5
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/richtek,rt5120.yaml
@@ -0,0 +1,178 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mfd/richtek,rt5120.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Richtek RT5120 PMIC
+
+maintainers:
+ - ChiYuan Huang <cy_huang@richtek.com>
+
+description: |
+ The RT5120 provides four high-efficiency buck converters and one LDO voltage
+ regulator. The device is targeted at providingthe processor voltage, memory,
+ I/O, and peripheral rails in home entertainment devices. The I2C interface is
+ used for dynamic voltage scaling of the processor voltage, power rails on/off
+ sequence control, operation mode selection.
+
+properties:
+ compatible:
+ enum:
+ - richtek,rt5120
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ interrupt-controller: true
+
+ "#interrupt-cells":
+ const: 1
+
+ wakeup-source: true
+
+ richtek,enable-undervolt-hiccup:
+ type: boolean
+ description: |
+ If used, under voltage protection trigger hiccup behavior, else latchup as
+ default
+
+ richtek,enable-overvolt-hiccup:
+ type: boolean
+ description:
+ Like as 'enable-uv-hiccup', it configures over voltage protection to
+ hiccup, else latchup as default
+
+ vin1-supply:
+ description: phandle for buck1 input power source
+
+ vin2-supply:
+ description: phandle for buck2 input power source
+
+ vin3-supply:
+ description: phandle for buck3 input power source
+
+ vin4-supply:
+ description: phandle for buck4 input power source
+
+ vinldo-supply:
+ description: phandle for ldo input power source
+
+ regulators:
+ type: object
+
+ patternProperties:
+ "^buck[1-4]$":
+ type: object
+ $ref: /schemas/regulator/regulator.yaml#
+ unevaluatedProperties: false
+
+ properties:
+ regulator-allowed-modes:
+ description: |
+ Used to specify the allowed buck converter operating mode
+ mode mapping:
+ 0: auto mode
+ 1: force pwm mode
+ items:
+ enum: [0, 1]
+
+ "^(ldo|exten)$":
+ type: object
+ $ref: /schemas/regulator/regulator.yaml#
+ unevaluatedProperties: false
+
+ additionalProperties: false
+
+ powerkey:
+ type: object
+ description:
+ PON key that connected to RT5120 PMIC.
+
+ properties:
+ compatible:
+ enum:
+ - richtek,rt5120-pwrkey
+
+ required:
+ - compatible
+
+ additionalProperties: false
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - '#interrupt-cells'
+ - interrupt-controller
+ - regulators
+ - powerkey
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ pmic@62 {
+ compatible = "richtek,rt5120";
+ reg = <0x62>;
+ interrupts-extended = <&gpio_intc 32 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ wakeup-source;
+
+ regulators {
+ buck1 {
+ regulator-name = "rt5120-buck1";
+ regulator-min-microvolt = <600000>;
+ regulator-max-microvolt = <1393750>;
+ regulator-allowed-modes = <0 1>;
+ regulator-boot-on;
+ };
+ buck2 {
+ regulator-name = "rt5120-buck2";
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1100000>;
+ regulator-allowed-modes = <0 1>;
+ regulator-always-on;
+ };
+ buck3 {
+ regulator-name = "rt5120-buck3";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-allowed-modes = <0 1>;
+ regulator-always-on;
+ };
+ buck4 {
+ regulator-name = "rt5120-buck4";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-allowed-modes = <0 1>;
+ regulator-always-on;
+ };
+ ldo {
+ regulator-name = "rt5120-ldo";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ };
+ exten {
+ regulator-name = "rt5120-exten";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ regulator-always-on;
+ };
+ };
+ powerkey {
+ compatible = "richtek,rt5120-pwrkey";
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/mfd/rockchip,rk817.yaml b/Documentation/devicetree/bindings/mfd/rockchip,rk817.yaml
index bfc1720adc43..935e17099213 100644
--- a/Documentation/devicetree/bindings/mfd/rockchip,rk817.yaml
+++ b/Documentation/devicetree/bindings/mfd/rockchip,rk817.yaml
@@ -87,6 +87,7 @@ properties:
patternProperties:
"^(LDO_REG[1-9]|DCDC_REG[1-4]|BOOST|OTG_SWITCH)$":
type: object
+ unevaluatedProperties: false
$ref: ../regulator/regulator.yaml#
unevaluatedProperties: false
@@ -111,12 +112,56 @@ properties:
additional properties are required for the codec, this node can be
omitted.
type: object
+ additionalProperties: false
properties:
rockchip,mic-in-differential:
type: boolean
description:
Describes if the microphone uses differential mode.
+ charger:
+ description: |
+ The child node for the charger to hold additional properties. If a
+ battery is not in use, this node can be omitted.
+ type: object
+ properties:
+ monitored-battery:
+ description: |
+ A phandle to a monitored battery node that contains a valid
+ value for:
+ charge-full-design-microamp-hours,
+ charge-term-current-microamp,
+ constant-charge-current-max-microamp,
+ constant-charge-voltage-max-microvolt,
+ voltage-max-design-microvolt,
+ voltage-min-design-microvolt,
+ and a valid ocv-capacity table.
+
+ rockchip,resistor-sense-micro-ohms:
+ description: |
+ Value in microohms of the battery sense resistor. This value is
+ used by the driver to set the correct divisor value to translate
+ ADC readings into the proper units of measure.
+ enum: [10000, 20000]
+
+ rockchip,sleep-enter-current-microamp:
+ description: |
+ Value in microamps of the sleep enter current for the charger.
+ Value is used by the driver to calibrate the relax threshold.
+
+ rockchip,sleep-filter-current-microamp:
+ description:
+ Value in microamps of the sleep filter current for the charger.
+ Value is used by the driver to derive the sleep sample current.
+
+ required:
+ - monitored-battery
+ - rockchip,resistor-sense-micro-ohms
+ - rockchip,sleep-enter-current-microamp
+ - rockchip,sleep-filter-current-microamp
+
+ additionalProperties: false
+
allOf:
- if:
properties:
@@ -323,6 +368,13 @@ examples:
};
};
+ rk817_charger: charger {
+ monitored-battery = <&battery>;
+ rockchip,resistor-sense-micro-ohms = <10000>;
+ rockchip,sleep-enter-current-microamp = <300000>;
+ rockchip,sleep-filter-current-microamp = <100000>;
+ };
+
rk817_codec: codec {
rockchip,mic-in-differential;
};
diff --git a/Documentation/devicetree/bindings/mfd/silergy,sy7636a.yaml b/Documentation/devicetree/bindings/mfd/silergy,sy7636a.yaml
index 6de74c701635..ee0be32ac020 100644
--- a/Documentation/devicetree/bindings/mfd/silergy,sy7636a.yaml
+++ b/Documentation/devicetree/bindings/mfd/silergy,sy7636a.yaml
@@ -42,6 +42,7 @@ properties:
vcom:
type: object
$ref: /schemas/regulator/regulator.yaml#
+ unevaluatedProperties: false
description:
The regulator for the compenstation voltage. Enabling/disabling this
enables/disables the entire device.
diff --git a/Documentation/devicetree/bindings/mfd/sprd,ums512-glbreg.yaml b/Documentation/devicetree/bindings/mfd/sprd,ums512-glbreg.yaml
new file mode 100644
index 000000000000..996bd4a17ca3
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/sprd,ums512-glbreg.yaml
@@ -0,0 +1,71 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+# Copyright 2022 Unisoc Inc.
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mfd/sprd,ums512-glbreg.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Unisoc System Global Register
+
+maintainers:
+ - Orson Zhai <orsonzhai@gmail.com>
+ - Baolin Wang <baolin.wang7@gmail.com>
+ - Chunyan Zhang <zhang.lyra@gmail.com>
+
+description:
+ Unisoc system global registers provide register map
+ for clocks and some multimedia modules of the SoC.
+
+properties:
+ compatible:
+ items:
+ - const: sprd,ums512-glbregs
+ - const: syscon
+ - const: simple-mfd
+
+ "#address-cells":
+ const: 1
+
+ "#size-cells":
+ const: 1
+
+ ranges:
+ maxItems: 1
+
+ reg:
+ maxItems: 1
+
+patternProperties:
+ "^clock-controller@[0-9a-f]+$":
+ type: object
+ $ref: /schemas/clock/sprd,ums512-clk.yaml#
+ description:
+ Clock controller for the SoC clocks.
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ ap_apb_regs: syscon@71000000 {
+ compatible = "sprd,ums512-glbregs", "syscon", "simple-mfd";
+ reg = <0x71000000 0x3000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0 0x71000000 0x3000>;
+
+ clock-controller@0 {
+ compatible = "sprd,ums512-apahb-gate";
+ reg = <0x0 0x2000>;
+ #clock-cells = <1>;
+ };
+ };
+
+ - |
+ ap_intc5_regs: syscon@32360000 {
+ compatible = "sprd,ums512-glbregs", "syscon", "simple-mfd";
+ reg = <0x32360000 0x1000>;
+ };
diff --git a/Documentation/devicetree/bindings/mfd/st,stm32-lptimer.yaml b/Documentation/devicetree/bindings/mfd/st,stm32-lptimer.yaml
index a58f08aa430d..d950dd5d48bd 100644
--- a/Documentation/devicetree/bindings/mfd/st,stm32-lptimer.yaml
+++ b/Documentation/devicetree/bindings/mfd/st,stm32-lptimer.yaml
@@ -46,6 +46,7 @@ properties:
pwm:
type: object
+ additionalProperties: false
properties:
compatible:
@@ -60,6 +61,7 @@ properties:
counter:
type: object
+ additionalProperties: false
properties:
compatible:
@@ -70,6 +72,7 @@ properties:
timer:
type: object
+ additionalProperties: false
properties:
compatible:
@@ -81,6 +84,7 @@ properties:
patternProperties:
"^trigger@[0-9]+$":
type: object
+ additionalProperties: false
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/mfd/st,stm32-timers.yaml b/Documentation/devicetree/bindings/mfd/st,stm32-timers.yaml
index 5db00af8e116..e2c3c3b44abb 100644
--- a/Documentation/devicetree/bindings/mfd/st,stm32-timers.yaml
+++ b/Documentation/devicetree/bindings/mfd/st,stm32-timers.yaml
@@ -69,6 +69,7 @@ properties:
pwm:
type: object
+ additionalProperties: false
properties:
compatible:
@@ -104,6 +105,7 @@ properties:
counter:
type: object
+ additionalProperties: false
properties:
compatible:
@@ -115,6 +117,7 @@ properties:
patternProperties:
"^timer@[0-9]+$":
type: object
+ additionalProperties: false
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/mfd/st,stmfx.yaml b/Documentation/devicetree/bindings/mfd/st,stmfx.yaml
index b2a4e4aa7ff6..b4d54302582f 100644
--- a/Documentation/devicetree/bindings/mfd/st,stmfx.yaml
+++ b/Documentation/devicetree/bindings/mfd/st,stmfx.yaml
@@ -57,6 +57,7 @@ properties:
patternProperties:
"^[a-zA-Z]*-pins$":
type: object
+ additionalProperties: false
allOf:
- $ref: ../pinctrl/pinmux-node.yaml
diff --git a/Documentation/devicetree/bindings/mfd/stericsson,ab8500.yaml b/Documentation/devicetree/bindings/mfd/stericsson,ab8500.yaml
index 623a4b5cd27a..6c8d42f27fe8 100644
--- a/Documentation/devicetree/bindings/mfd/stericsson,ab8500.yaml
+++ b/Documentation/devicetree/bindings/mfd/stericsson,ab8500.yaml
@@ -51,6 +51,7 @@ properties:
provides the reference clock for the entire U8500 system and
the DB8500 counterpart.
type: object
+ additionalProperties: false
properties:
compatible:
@@ -63,6 +64,7 @@ properties:
description: Node describing the AB8500 GPIO controller. A few
GPIO pins available for misc usage.
type: object
+ additionalProperties: false
properties:
compatible:
@@ -78,6 +80,7 @@ properties:
rtc:
description: Node describing the AB8500 battery-backed RTC.
type: object
+ additionalProperties: false
properties:
compatible:
@@ -337,34 +340,40 @@ properties:
description: The voltage for the auxilary LDO regulator 1
type: object
$ref: ../regulator/regulator.yaml#
+ unevaluatedProperties: false
ab8500_ldo_aux2:
description: The voltage for the auxilary LDO regulator 2
type: object
$ref: ../regulator/regulator.yaml#
+ unevaluatedProperties: false
ab8500_ldo_aux3:
description: The voltage for the auxilary LDO regulator 3
type: object
$ref: ../regulator/regulator.yaml#
+ unevaluatedProperties: false
ab8500_ldo_aux4:
description: The voltage for the auxilary LDO regulator 4
only present on AB8505
type: object
$ref: ../regulator/regulator.yaml#
+ unevaluatedProperties: false
ab8500_ldo_aux5:
description: The voltage for the auxilary LDO regulator 5
only present on AB8505
type: object
$ref: ../regulator/regulator.yaml#
+ unevaluatedProperties: false
ab8500_ldo_aux6:
description: The voltage for the auxilary LDO regulator 6
only present on AB8505
type: object
$ref: ../regulator/regulator.yaml#
+ unevaluatedProperties: false
# There is never any AUX7 regulator which is confusing
@@ -373,18 +382,21 @@ properties:
only present on AB8505
type: object
$ref: ../regulator/regulator.yaml#
+ unevaluatedProperties: false
ab8500_ldo_intcore:
description: The LDO regulator for the internal core voltage
of the AB8500
type: object
$ref: ../regulator/regulator.yaml#
+ unevaluatedProperties: false
ab8500_ldo_adc:
description: Analog power regulator for the analog to digital converter
ADC, only present on AB8505
type: object
$ref: ../regulator/regulator.yaml#
+ unevaluatedProperties: false
ab8500_ldo_tvout:
description: The voltage for the TV output regulator, incidentally
@@ -393,33 +405,39 @@ properties:
Only present on AB8500.
type: object
$ref: ../regulator/regulator.yaml#
+ unevaluatedProperties: false
ab8500_ldo_audio:
description: The LDO regulator for the audio codec output
type: object
$ref: ../regulator/regulator.yaml#
+ unevaluatedProperties: false
ab8500_ldo_anamic1:
description: The LDO regulator for the analog microphone 1
type: object
$ref: ../regulator/regulator.yaml#
+ unevaluatedProperties: false
ab8500_ldo_anamic2:
description: The LDO regulator for the analog microphone 2
type: object
$ref: ../regulator/regulator.yaml#
+ unevaluatedProperties: false
ab8500_ldo_dmic:
description: The LDO regulator for the digital microphone
only present on AB8500
type: object
$ref: ../regulator/regulator.yaml#
+ unevaluatedProperties: false
ab8500_ldo_ana:
description: Analog power regulator for CSI and DSI interfaces,
Camera Serial Interface CSI and Display Serial Interface DSI.
type: object
$ref: ../regulator/regulator.yaml#
+ unevaluatedProperties: false
required:
- compatible
@@ -442,16 +460,19 @@ properties:
description: The voltage for the VSMPS1 external regulator
type: object
$ref: ../regulator/regulator.yaml#
+ unevaluatedProperties: false
ab8500_ext2:
description: The voltage for the VSMPS2 external regulator
type: object
$ref: ../regulator/regulator.yaml#
+ unevaluatedProperties: false
ab8500_ext3:
description: The voltage for the VSMPS3 external regulator
type: object
$ref: ../regulator/regulator.yaml#
+ unevaluatedProperties: false
required:
- compatible
@@ -462,6 +483,7 @@ patternProperties:
"^pwm@[1-9]+?$":
type: object
$ref: ../pwm/pwm.yaml#
+ unevaluatedProperties: false
description: Represents each of the PWM blocks in the AB8500
properties:
diff --git a/Documentation/devicetree/bindings/mfd/syscon.yaml b/Documentation/devicetree/bindings/mfd/syscon.yaml
index 5cbf2c5978b3..4fc483b1aee7 100644
--- a/Documentation/devicetree/bindings/mfd/syscon.yaml
+++ b/Documentation/devicetree/bindings/mfd/syscon.yaml
@@ -61,6 +61,8 @@ properties:
- rockchip,rk3368-qos
- rockchip,rk3399-qos
- rockchip,rk3568-qos
+ - rockchip,rk3588-qos
+ - rockchip,rv1126-qos
- samsung,exynos3-sysreg
- samsung,exynos4-sysreg
- samsung,exynos5-sysreg
@@ -73,7 +75,7 @@ properties:
- contains:
const: syscon
minItems: 2
- maxItems: 4 # Should be enough
+ maxItems: 5 # Should be enough
reg:
maxItems: 1
@@ -82,7 +84,6 @@ properties:
description: |
The size (in bytes) of the IO accesses that should be performed
on the device.
- $ref: /schemas/types.yaml#/definitions/uint32
enum: [1, 2, 4, 8]
hwlocks:
@@ -94,6 +95,18 @@ required:
- compatible
- reg
+allOf:
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: simple-mfd
+ then:
+ properties:
+ compatible:
+ minItems: 3
+ maxItems: 5
+
additionalProperties: true
examples:
diff --git a/Documentation/devicetree/bindings/mfd/ti,tps65086.yaml b/Documentation/devicetree/bindings/mfd/ti,tps65086.yaml
index 6aeedda3be15..3fdd9cb5b347 100644
--- a/Documentation/devicetree/bindings/mfd/ti,tps65086.yaml
+++ b/Documentation/devicetree/bindings/mfd/ti,tps65086.yaml
@@ -38,6 +38,7 @@ properties:
regulators:
type: object
+ additionalProperties: false
description: |
List of child nodes that specify the regulator initialization data.
Child nodes must be named after their hardware counterparts:
diff --git a/Documentation/devicetree/bindings/mfd/x-powers,axp152.yaml b/Documentation/devicetree/bindings/mfd/x-powers,axp152.yaml
index 3a53bae611bc..1c7601d05807 100644
--- a/Documentation/devicetree/bindings/mfd/x-powers,axp152.yaml
+++ b/Documentation/devicetree/bindings/mfd/x-powers,axp152.yaml
@@ -93,6 +93,9 @@ properties:
- x-powers,axp809
- x-powers,axp813
- items:
+ - const: x-powers,axp228
+ - const: x-powers,axp221
+ - items:
- const: x-powers,axp805
- const: x-powers,axp806
- items:
@@ -260,6 +263,7 @@ properties:
"^(([a-f])?ldo[0-9]|dcdc[0-7a-e]|ldo(_|-)io(0|1)|(dc1)?sw|rtc(_|-)ldo|drivevbus|dc5ldo)$":
$ref: /schemas/regulator/regulator.yaml#
type: object
+ unevaluatedProperties: false
properties:
regulator-ramp-delay:
diff --git a/Documentation/devicetree/bindings/power/mediatek,power-controller.yaml b/Documentation/devicetree/bindings/power/mediatek,power-controller.yaml
index 03b7f6aa591d..605ec7ab5f63 100644
--- a/Documentation/devicetree/bindings/power/mediatek,power-controller.yaml
+++ b/Documentation/devicetree/bindings/power/mediatek,power-controller.yaml
@@ -135,7 +135,7 @@ examples:
#size-cells = <2>;
scpsys: syscon@10006000 {
- compatible = "syscon", "simple-mfd";
+ compatible = "mediatek,mt8173-scpsys", "syscon", "simple-mfd";
reg = <0 0x10006000 0 0x1000>;
spm: power-controller {
diff --git a/MAINTAINERS b/MAINTAINERS
index 43ba66d26a30..a79d3f97a914 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8475,7 +8475,6 @@ F: tools/testing/selftests/futex/
GATEWORKS SYSTEM CONTROLLER (GSC) DRIVER
M: Tim Harvey <tharvey@gateworks.com>
-M: Robert Jones <rjones@gateworks.com>
S: Maintained
F: Documentation/devicetree/bindings/mfd/gateworks-gsc.yaml
F: drivers/mfd/gateworks-gsc.c
diff --git a/arch/arm/boot/dts/tegra30-apalis-v1.1.dtsi b/arch/arm/boot/dts/tegra30-apalis-v1.1.dtsi
index 380f22a35821..a1bcd67fa505 100644
--- a/arch/arm/boot/dts/tegra30-apalis-v1.1.dtsi
+++ b/arch/arm/boot/dts/tegra30-apalis-v1.1.dtsi
@@ -993,7 +993,7 @@
touchscreen@41 {
compatible = "st,stmpe811";
reg = <0x41>;
- irq-gpio = <&gpio TEGRA_GPIO(V, 0) IRQ_TYPE_LEVEL_LOW>;
+ irq-gpio = <&gpio TEGRA_GPIO(V, 0) GPIO_ACTIVE_LOW>;
interrupt-controller;
id = <0>;
blocks = <0x5>;
diff --git a/arch/arm/boot/dts/tegra30-apalis.dtsi b/arch/arm/boot/dts/tegra30-apalis.dtsi
index 9bdc4cb71449..99d7dad72d29 100644
--- a/arch/arm/boot/dts/tegra30-apalis.dtsi
+++ b/arch/arm/boot/dts/tegra30-apalis.dtsi
@@ -976,7 +976,7 @@
touchscreen@41 {
compatible = "st,stmpe811";
reg = <0x41>;
- irq-gpio = <&gpio TEGRA_GPIO(V, 0) IRQ_TYPE_LEVEL_LOW>;
+ irq-gpio = <&gpio TEGRA_GPIO(V, 0) GPIO_ACTIVE_LOW>;
interrupt-controller;
id = <0>;
blocks = <0x5>;
diff --git a/arch/arm/boot/dts/tegra30-colibri.dtsi b/arch/arm/boot/dts/tegra30-colibri.dtsi
index 310dff05910d..2867a138e011 100644
--- a/arch/arm/boot/dts/tegra30-colibri.dtsi
+++ b/arch/arm/boot/dts/tegra30-colibri.dtsi
@@ -849,7 +849,7 @@
touchscreen@41 {
compatible = "st,stmpe811";
reg = <0x41>;
- irq-gpio = <&gpio TEGRA_GPIO(V, 0) IRQ_TYPE_LEVEL_LOW>;
+ irq-gpio = <&gpio TEGRA_GPIO(V, 0) GPIO_ACTIVE_LOW>;
interrupt-controller;
id = <0>;
blocks = <0x5>;
diff --git a/arch/arm/mach-omap1/board-htcherald.c b/arch/arm/mach-omap1/board-htcherald.c
index ec049cee49c6..291d294b5824 100644
--- a/arch/arm/mach-omap1/board-htcherald.c
+++ b/arch/arm/mach-omap1/board-htcherald.c
@@ -141,13 +141,6 @@
#define HTCPLD_GPIO_DOWN_DPAD HTCPLD_BASE(7, 4)
#define HTCPLD_GPIO_ENTER_DPAD HTCPLD_BASE(7, 3)
-/*
- * The htcpld chip requires a gpio write to a specific line
- * to re-enable interrupts after one has occurred.
- */
-#define HTCPLD_GPIO_INT_RESET_HI HTCPLD_BASE(2, 7)
-#define HTCPLD_GPIO_INT_RESET_LO HTCPLD_BASE(2, 0)
-
/* Chip 5 */
#define HTCPLD_IRQ_RIGHT_KBD HTCPLD_IRQ(0, 7)
#define HTCPLD_IRQ_UP_KBD HTCPLD_IRQ(0, 6)
@@ -348,8 +341,6 @@ static struct htcpld_chip_platform_data htcpld_chips[] = {
};
static struct htcpld_core_platform_data htcpld_pfdata = {
- .int_reset_gpio_hi = HTCPLD_GPIO_INT_RESET_HI,
- .int_reset_gpio_lo = HTCPLD_GPIO_INT_RESET_LO,
.i2c_adapter_id = 1,
.chip = htcpld_chips,
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 5695b266abcf..7ac3daaf59ce 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -1758,6 +1758,7 @@ config SENSORS_SIS5595
config SENSORS_SY7636A
tristate "Silergy SY7636A"
+ depends on MFD_SY7636A
help
If you say yes here you get support for the thermistor readout of
the Silergy SY7636A PMIC.
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index c3dd1fe8d8c9..8b93856de432 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -589,8 +589,8 @@ config LPC_SCH
config INTEL_SOC_PMIC
bool "Support for Crystal Cove PMIC"
- depends on ACPI && HAS_IOMEM && I2C=y && GPIOLIB && COMMON_CLK
- depends on X86 || COMPILE_TEST
+ depends on HAS_IOMEM && I2C=y && GPIOLIB && COMMON_CLK
+ depends on (X86 && ACPI) || COMPILE_TEST
depends on I2C_DESIGNWARE_PLATFORM=y
select MFD_CORE
select REGMAP_I2C
@@ -938,6 +938,22 @@ config MFD_MT6360
PMIC part includes 2-channel BUCKs and 2-channel LDOs
LDO part includes 4-channel LDOs
+config MFD_MT6370
+ tristate "MediaTek MT6370 SubPMIC"
+ select MFD_CORE
+ select REGMAP_I2C
+ select REGMAP_IRQ
+ depends on I2C
+ help
+ Say Y here to enable MT6370 SubPMIC functional support.
+ It consists of a single cell battery charger with ADC monitoring, RGB
+ LEDs, dual channel flashlight, WLED backlight driver, display bias
+ voltage supply, one general purpose LDO, and the USB Type-C & PD
+ controller complies with the latest USB Type-C and PD standards.
+
+ This driver can also be built as a module. If so, the module
+ will be called "mt6370".
+
config MFD_MT6397
tristate "MediaTek MT6397 PMIC Support"
select MFD_CORE
@@ -1117,6 +1133,16 @@ config MFD_SPMI_PMIC
Say M here if you want to include support for the SPMI PMIC
series as a module. The module will be called "qcom-spmi-pmic".
+config MFD_SY7636A
+ tristate "Silergy SY7636A voltage regulator"
+ depends on I2C
+ select MFD_SIMPLE_MFD_I2C
+ help
+ Enable support for Silergy SY7636A voltage regulator.
+
+ To enable support for building sub-devices as modules,
+ choose M here.
+
config MFD_RDC321X
tristate "RDC R-321x southbridge"
select MFD_CORE
@@ -1149,6 +1175,18 @@ config MFD_RT5033
sub-devices like charger, fuel gauge, flash LED, current source,
LDO and Buck.
+config MFD_RT5120
+ tristate "Richtek RT5120 Power Management IC"
+ depends on I2C
+ select MFD_CORE
+ select REGMAP_I2C
+ select REGMAP_IRQ
+ help
+ The enables support for Richtek RT5120 PMIC. It includes four high
+ efficiency buck converters and one LDO voltage regulator. The device
+ is targeted at providing the CPU voltage, memory, I/O and peripheral
+ power rails in home entertainment devices.
+
config MFD_RC5T583
bool "Ricoh RC5T583 Power Management system device"
depends on I2C=y
@@ -1224,7 +1262,7 @@ config MFD_SI476X_CORE
module will be called si476x-core.
config MFD_SIMPLE_MFD_I2C
- tristate "Simple Multi-Functional Device support (I2C)"
+ tristate
depends on I2C
select MFD_CORE
select REGMAP_I2C
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 0004b7e86220..7ed3ef4a698c 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -175,6 +175,11 @@ obj-$(CONFIG_MFD_MAX8998) += max8998.o max8998-irq.o
obj-$(CONFIG_MFD_MP2629) += mp2629.o
+obj-$(CONFIG_MFD_MT6360) += mt6360-core.o
+obj-$(CONFIG_MFD_MT6370) += mt6370.o
+mt6397-objs := mt6397-core.o mt6397-irq.o mt6358-irq.o
+obj-$(CONFIG_MFD_MT6397) += mt6397.o
+
pcf50633-objs := pcf50633-core.o pcf50633-irq.o
obj-$(CONFIG_MFD_PCF50633) += pcf50633.o
obj-$(CONFIG_PCF50633_ADC) += pcf50633-adc.o
@@ -237,16 +242,13 @@ obj-$(CONFIG_MFD_HI655X_PMIC) += hi655x-pmic.o
obj-$(CONFIG_MFD_DLN2) += dln2.o
obj-$(CONFIG_MFD_RT4831) += rt4831.o
obj-$(CONFIG_MFD_RT5033) += rt5033.o
+obj-$(CONFIG_MFD_RT5120) += rt5120.o
obj-$(CONFIG_MFD_SKY81452) += sky81452.o
-intel-soc-pmic-objs := intel_soc_pmic_core.o intel_soc_pmic_crc.o
-obj-$(CONFIG_INTEL_SOC_PMIC) += intel-soc-pmic.o
+obj-$(CONFIG_INTEL_SOC_PMIC) += intel_soc_pmic_crc.o
obj-$(CONFIG_INTEL_SOC_PMIC_BXTWC) += intel_soc_pmic_bxtwc.o
obj-$(CONFIG_INTEL_SOC_PMIC_CHTWC) += intel_soc_pmic_chtwc.o
obj-$(CONFIG_INTEL_SOC_PMIC_CHTDC_TI) += intel_soc_pmic_chtdc_ti.o
-obj-$(CONFIG_MFD_MT6360) += mt6360-core.o
-mt6397-objs := mt6397-core.o mt6397-irq.o mt6358-irq.o
-obj-$(CONFIG_MFD_MT6397) += mt6397.o
obj-$(CONFIG_INTEL_SOC_PMIC_MRFLD) += intel_soc_pmic_mrfld.o
obj-$(CONFIG_MFD_ALTERA_A10SR) += altera-a10sr.o
diff --git a/drivers/mfd/da9062-core.c b/drivers/mfd/da9062-core.c
index 0a80d82c6858..a26e473507c7 100644
--- a/drivers/mfd/da9062-core.c
+++ b/drivers/mfd/da9062-core.c
@@ -453,6 +453,7 @@ static const struct regmap_range da9061_aa_writeable_ranges[] = {
regmap_reg_range(DA9062AA_VBUCK1_B, DA9062AA_VBUCK4_B),
regmap_reg_range(DA9062AA_VBUCK3_B, DA9062AA_VBUCK3_B),
regmap_reg_range(DA9062AA_VLDO1_B, DA9062AA_VLDO4_B),
+ regmap_reg_range(DA9062AA_CONFIG_J, DA9062AA_CONFIG_J),
regmap_reg_range(DA9062AA_GP_ID_0, DA9062AA_GP_ID_19),
};
diff --git a/drivers/mfd/fsl-imx25-tsadc.c b/drivers/mfd/fsl-imx25-tsadc.c
index 37e5e02a1d05..823595bcc9b7 100644
--- a/drivers/mfd/fsl-imx25-tsadc.c
+++ b/drivers/mfd/fsl-imx25-tsadc.c
@@ -69,7 +69,7 @@ static int mx25_tsadc_setup_irq(struct platform_device *pdev,
int irq;
irq = platform_get_irq(pdev, 0);
- if (irq <= 0)
+ if (irq < 0)
return irq;
tsadc->domain = irq_domain_add_simple(np, 2, 0, &mx25_tsadc_domain_ops,
@@ -84,6 +84,19 @@ static int mx25_tsadc_setup_irq(struct platform_device *pdev,
return 0;
}
+static int mx25_tsadc_unset_irq(struct platform_device *pdev)
+{
+ struct mx25_tsadc *tsadc = platform_get_drvdata(pdev);
+ int irq = platform_get_irq(pdev, 0);
+
+ if (irq >= 0) {
+ irq_set_chained_handler_and_data(irq, NULL, NULL);
+ irq_domain_remove(tsadc->domain);
+ }
+
+ return 0;
+}
+
static void mx25_tsadc_setup_clk(struct platform_device *pdev,
struct mx25_tsadc *tsadc)
{
@@ -171,18 +184,21 @@ static int mx25_tsadc_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, tsadc);
- return devm_of_platform_populate(dev);
+ ret = devm_of_platform_populate(dev);
+ if (ret)
+ goto err_irq;
+
+ return 0;
+
+err_irq:
+ mx25_tsadc_unset_irq(pdev);
+
+ return ret;
}
static int mx25_tsadc_remove(struct platform_device *pdev)
{
- struct mx25_tsadc *tsadc = platform_get_drvdata(pdev);
- int irq = platform_get_irq(pdev, 0);
-
- if (irq) {
- irq_set_chained_handler_and_data(irq, NULL, NULL);
- irq_domain_remove(tsadc->domain);
- }
+ mx25_tsadc_unset_irq(pdev);
return 0;
}
diff --git a/drivers/mfd/htc-i2cpld.c b/drivers/mfd/htc-i2cpld.c
index 417b0355d904..b45b1346ab54 100644
--- a/drivers/mfd/htc-i2cpld.c
+++ b/drivers/mfd/htc-i2cpld.c
@@ -20,7 +20,9 @@
#include <linux/irq.h>
#include <linux/spinlock.h>
#include <linux/htcpld.h>
-#include <linux/gpio.h>
+#include <linux/gpio/driver.h>
+#include <linux/gpio/machine.h>
+#include <linux/gpio/consumer.h>
#include <linux/slab.h>
struct htcpld_chip {
@@ -58,8 +60,8 @@ struct htcpld_data {
uint irq_start;
int nirqs;
uint chained_irq;
- unsigned int int_reset_gpio_hi;
- unsigned int int_reset_gpio_lo;
+ struct gpio_desc *int_reset_gpio_hi;
+ struct gpio_desc *int_reset_gpio_lo;
/* htcpld info */
struct htcpld_chip *chip;
@@ -196,9 +198,9 @@ static irqreturn_t htcpld_handler(int irq, void *dev)
* be asserted.
*/
if (htcpld->int_reset_gpio_hi)
- gpio_set_value(htcpld->int_reset_gpio_hi, 1);
+ gpiod_set_value(htcpld->int_reset_gpio_hi, 1);
if (htcpld->int_reset_gpio_lo)
- gpio_set_value(htcpld->int_reset_gpio_lo, 0);
+ gpiod_set_value(htcpld->int_reset_gpio_lo, 0);
return IRQ_HANDLED;
}
@@ -352,7 +354,7 @@ static int htcpld_register_chip_i2c(
memset(&info, 0, sizeof(struct i2c_board_info));
info.addr = plat_chip_data->addr;
- strlcpy(info.type, "htcpld-chip", I2C_NAME_SIZE);
+ strscpy(info.type, "htcpld-chip", I2C_NAME_SIZE);
info.platform_data = chip;
/* Add the I2C device. This calls the probe() function. */
@@ -562,34 +564,28 @@ static int htcpld_core_probe(struct platform_device *pdev)
return ret;
/* Request the GPIO(s) for the int reset and set them up */
- if (pdata->int_reset_gpio_hi) {
- ret = gpio_request(pdata->int_reset_gpio_hi, "htcpld-core");
- if (ret) {
- /*
- * If it failed, that sucks, but we can probably
- * continue on without it.
- */
- dev_warn(dev, "Unable to request int_reset_gpio_hi -- interrupts may not work\n");
- htcpld->int_reset_gpio_hi = 0;
- } else {
- htcpld->int_reset_gpio_hi = pdata->int_reset_gpio_hi;
- gpio_set_value(htcpld->int_reset_gpio_hi, 1);
- }
+ htcpld->int_reset_gpio_hi = gpiochip_request_own_desc(&htcpld->chip[2].chip_out,
+ 7, "htcpld-core", GPIO_ACTIVE_HIGH,
+ GPIOD_OUT_HIGH);
+ if (IS_ERR(htcpld->int_reset_gpio_hi)) {
+ /*
+ * If it failed, that sucks, but we can probably
+ * continue on without it.
+ */
+ htcpld->int_reset_gpio_hi = NULL;
+ dev_warn(dev, "Unable to request int_reset_gpio_hi -- interrupts may not work\n");
}
- if (pdata->int_reset_gpio_lo) {
- ret = gpio_request(pdata->int_reset_gpio_lo, "htcpld-core");
- if (ret) {
- /*
- * If it failed, that sucks, but we can probably
- * continue on without it.
- */
- dev_warn(dev, "Unable to request int_reset_gpio_lo -- interrupts may not work\n");
- htcpld->int_reset_gpio_lo = 0;
- } else {
- htcpld->int_reset_gpio_lo = pdata->int_reset_gpio_lo;
- gpio_set_value(htcpld->int_reset_gpio_lo, 0);
- }
+ htcpld->int_reset_gpio_lo = gpiochip_request_own_desc(&htcpld->chip[2].chip_out,
+ 0, "htcpld-core", GPIO_ACTIVE_HIGH,
+ GPIOD_OUT_LOW);
+ if (IS_ERR(htcpld->int_reset_gpio_lo)) {
+ /*
+ * If it failed, that sucks, but we can probably
+ * continue on without it.
+ */
+ htcpld->int_reset_gpio_lo = NULL;
+ dev_warn(dev, "Unable to request int_reset_gpio_lo -- interrupts may not work\n");
}
dev_info(dev, "Initialized successfully\n");
diff --git a/drivers/mfd/intel-lpss-pci.c b/drivers/mfd/intel-lpss-pci.c
index bb08b7a73fe1..dde31c50a632 100644
--- a/drivers/mfd/intel-lpss-pci.c
+++ b/drivers/mfd/intel-lpss-pci.c
@@ -14,6 +14,7 @@
#include <linux/pci.h>
#include <linux/pm_runtime.h>
#include <linux/property.h>
+#include <linux/pxa2xx_ssp.h>
#include "intel-lpss.h"
@@ -73,8 +74,18 @@ static void intel_lpss_pci_remove(struct pci_dev *pdev)
static INTEL_LPSS_PM_OPS(intel_lpss_pci_pm_ops);
+static const struct property_entry spt_spi_properties[] = {
+ PROPERTY_ENTRY_U32("intel,spi-pxa2xx-type", LPSS_SPT_SSP),
+ { }
+};
+
+static const struct software_node spt_spi_node = {
+ .properties = spt_spi_properties,
+};
+
static const struct intel_lpss_platform_info spt_info = {
.clk_rate = 120000000,
+ .swnode = &spt_spi_node,
};
static const struct property_entry spt_i2c_properties[] = {
@@ -108,8 +119,18 @@ static const struct intel_lpss_platform_info spt_uart_info = {
.swnode = &uart_node,
};
+static const struct property_entry bxt_spi_properties[] = {
+ PROPERTY_ENTRY_U32("intel,spi-pxa2xx-type", LPSS_BXT_SSP),
+ { }
+};
+
+static const struct software_node bxt_spi_node = {
+ .properties = bxt_spi_properties,
+};
+
static const struct intel_lpss_platform_info bxt_info = {
.clk_rate = 100000000,
+ .swnode = &bxt_spi_node,
};
static const struct intel_lpss_platform_info bxt_uart_info = {
@@ -166,6 +187,20 @@ static const struct intel_lpss_platform_info glk_i2c_info = {
.swnode = &glk_i2c_node,
};
+static const struct property_entry cnl_spi_properties[] = {
+ PROPERTY_ENTRY_U32("intel,spi-pxa2xx-type", LPSS_CNL_SSP),
+ { }
+};
+
+static const struct software_node cnl_spi_node = {
+ .properties = cnl_spi_properties,
+};
+
+static const struct intel_lpss_platform_info cnl_info = {
+ .clk_rate = 120000000,
+ .swnode = &cnl_spi_node,
+};
+
static const struct intel_lpss_platform_info cnl_i2c_info = {
.clk_rate = 216000000,
.swnode = &spt_i2c_node,
@@ -176,12 +211,26 @@ static const struct intel_lpss_platform_info ehl_i2c_info = {
.swnode = &bxt_i2c_node,
};
+static const struct property_entry tgl_spi_properties[] = {
+ PROPERTY_ENTRY_U32("intel,spi-pxa2xx-type", LPSS_CNL_SSP),
+ { }
+};
+
+static const struct software_node tgl_spi_node = {
+ .properties = tgl_spi_properties,
+};
+
+static const struct intel_lpss_platform_info tgl_info = {
+ .clk_rate = 100000000,
+ .swnode = &tgl_spi_node,
+};
+
static const struct pci_device_id intel_lpss_pci_ids[] = {
/* CML-LP */
{ PCI_VDEVICE(INTEL, 0x02a8), (kernel_ulong_t)&spt_uart_info },
{ PCI_VDEVICE(INTEL, 0x02a9), (kernel_ulong_t)&spt_uart_info },
- { PCI_VDEVICE(INTEL, 0x02aa), (kernel_ulong_t)&spt_info },
- { PCI_VDEVICE(INTEL, 0x02ab), (kernel_ulong_t)&spt_info },
+ { PCI_VDEVICE(INTEL, 0x02aa), (kernel_ulong_t)&cnl_info },
+ { PCI_VDEVICE(INTEL, 0x02ab), (kernel_ulong_t)&cnl_info },
{ PCI_VDEVICE(INTEL, 0x02c5), (kernel_ulong_t)&cnl_i2c_info },
{ PCI_VDEVICE(INTEL, 0x02c6), (kernel_ulong_t)&cnl_i2c_info },
{ PCI_VDEVICE(INTEL, 0x02c7), (kernel_ulong_t)&spt_uart_info },
@@ -189,18 +238,18 @@ static const struct pci_device_id intel_lpss_pci_ids[] = {
{ PCI_VDEVICE(INTEL, 0x02e9), (kernel_ulong_t)&cnl_i2c_info },
{ PCI_VDEVICE(INTEL, 0x02ea), (kernel_ulong_t)&cnl_i2c_info },
{ PCI_VDEVICE(INTEL, 0x02eb), (kernel_ulong_t)&cnl_i2c_info },
- { PCI_VDEVICE(INTEL, 0x02fb), (kernel_ulong_t)&spt_info },
+ { PCI_VDEVICE(INTEL, 0x02fb), (kernel_ulong_t)&cnl_info },
/* CML-H */
{ PCI_VDEVICE(INTEL, 0x06a8), (kernel_ulong_t)&spt_uart_info },
{ PCI_VDEVICE(INTEL, 0x06a9), (kernel_ulong_t)&spt_uart_info },
- { PCI_VDEVICE(INTEL, 0x06aa), (kernel_ulong_t)&spt_info },
- { PCI_VDEVICE(INTEL, 0x06ab), (kernel_ulong_t)&spt_info },
+ { PCI_VDEVICE(INTEL, 0x06aa), (kernel_ulong_t)&cnl_info },
+ { PCI_VDEVICE(INTEL, 0x06ab), (kernel_ulong_t)&cnl_info },
{ PCI_VDEVICE(INTEL, 0x06c7), (kernel_ulong_t)&spt_uart_info },
{ PCI_VDEVICE(INTEL, 0x06e8), (kernel_ulong_t)&cnl_i2c_info },
{ PCI_VDEVICE(INTEL, 0x06e9), (kernel_ulong_t)&cnl_i2c_info },
{ PCI_VDEVICE(INTEL, 0x06ea), (kernel_ulong_t)&cnl_i2c_info },
{ PCI_VDEVICE(INTEL, 0x06eb), (kernel_ulong_t)&cnl_i2c_info },
- { PCI_VDEVICE(INTEL, 0x06fb), (kernel_ulong_t)&spt_info },
+ { PCI_VDEVICE(INTEL, 0x06fb), (kernel_ulong_t)&cnl_info },
/* BXT A-Step */
{ PCI_VDEVICE(INTEL, 0x0aac), (kernel_ulong_t)&bxt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x0aae), (kernel_ulong_t)&bxt_i2c_info },
@@ -255,8 +304,8 @@ static const struct pci_device_id intel_lpss_pci_ids[] = {
/* ICL-LP */
{ PCI_VDEVICE(INTEL, 0x34a8), (kernel_ulong_t)&spt_uart_info },
{ PCI_VDEVICE(INTEL, 0x34a9), (kernel_ulong_t)&spt_uart_info },
- { PCI_VDEVICE(INTEL, 0x34aa), (kernel_ulong_t)&spt_info },
- { PCI_VDEVICE(INTEL, 0x34ab), (kernel_ulong_t)&spt_info },
+ { PCI_VDEVICE(INTEL, 0x34aa), (kernel_ulong_t)&cnl_info },
+ { PCI_VDEVICE(INTEL, 0x34ab), (kernel_ulong_t)&cnl_info },
{ PCI_VDEVICE(INTEL, 0x34c5), (kernel_ulong_t)&bxt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x34c6), (kernel_ulong_t)&bxt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x34c7), (kernel_ulong_t)&spt_uart_info },
@@ -264,15 +313,15 @@ static const struct pci_device_id intel_lpss_pci_ids[] = {
{ PCI_VDEVICE(INTEL, 0x34e9), (kernel_ulong_t)&bxt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x34ea), (kernel_ulong_t)&bxt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x34eb), (kernel_ulong_t)&bxt_i2c_info },
- { PCI_VDEVICE(INTEL, 0x34fb), (kernel_ulong_t)&spt_info },
+ { PCI_VDEVICE(INTEL, 0x34fb), (kernel_ulong_t)&cnl_info },
/* ICL-N */
{ PCI_VDEVICE(INTEL, 0x38a8), (kernel_ulong_t)&spt_uart_info },
/* TGL-H */
{ PCI_VDEVICE(INTEL, 0x43a7), (kernel_ulong_t)&bxt_uart_info },
{ PCI_VDEVICE(INTEL, 0x43a8), (kernel_ulong_t)&bxt_uart_info },
{ PCI_VDEVICE(INTEL, 0x43a9), (kernel_ulong_t)&bxt_uart_info },
- { PCI_VDEVICE(INTEL, 0x43aa), (kernel_ulong_t)&bxt_info },
- { PCI_VDEVICE(INTEL, 0x43ab), (kernel_ulong_t)&bxt_info },
+ { PCI_VDEVICE(INTEL, 0x43aa), (kernel_ulong_t)&tgl_info },
+ { PCI_VDEVICE(INTEL, 0x43ab), (kernel_ulong_t)&tgl_info },
{ PCI_VDEVICE(INTEL, 0x43ad), (kernel_ulong_t)&bxt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x43ae), (kernel_ulong_t)&bxt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x43d8), (kernel_ulong_t)&bxt_i2c_info },
@@ -281,8 +330,8 @@ static const struct pci_device_id intel_lpss_pci_ids[] = {
{ PCI_VDEVICE(INTEL, 0x43e9), (kernel_ulong_t)&bxt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x43ea), (kernel_ulong_t)&bxt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x43eb), (kernel_ulong_t)&bxt_i2c_info },
- { PCI_VDEVICE(INTEL, 0x43fb), (kernel_ulong_t)&bxt_info },
- { PCI_VDEVICE(INTEL, 0x43fd), (kernel_ulong_t)&bxt_info },
+ { PCI_VDEVICE(INTEL, 0x43fb), (kernel_ulong_t)&tgl_info },
+ { PCI_VDEVICE(INTEL, 0x43fd), (kernel_ulong_t)&tgl_info },
/* EHL */
{ PCI_VDEVICE(INTEL, 0x4b28), (kernel_ulong_t)&bxt_uart_info },
{ PCI_VDEVICE(INTEL, 0x4b29), (kernel_ulong_t)&bxt_uart_info },
@@ -301,8 +350,8 @@ static const struct pci_device_id intel_lpss_pci_ids[] = {
/* JSL */
{ PCI_VDEVICE(INTEL, 0x4da8), (kernel_ulong_t)&spt_uart_info },
{ PCI_VDEVICE(INTEL, 0x4da9), (kernel_ulong_t)&spt_uart_info },
- { PCI_VDEVICE(INTEL, 0x4daa), (kernel_ulong_t)&spt_info },
- { PCI_VDEVICE(INTEL, 0x4dab), (kernel_ulong_t)&spt_info },
+ { PCI_VDEVICE(INTEL, 0x4daa), (kernel_ulong_t)&cnl_info },
+ { PCI_VDEVICE(INTEL, 0x4dab), (kernel_ulong_t)&cnl_info },
{ PCI_VDEVICE(INTEL, 0x4dc5), (kernel_ulong_t)&bxt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x4dc6), (kernel_ulong_t)&bxt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x4dc7), (kernel_ulong_t)&spt_uart_info },
@@ -310,12 +359,12 @@ static const struct pci_device_id intel_lpss_pci_ids[] = {
{ PCI_VDEVICE(INTEL, 0x4de9), (kernel_ulong_t)&bxt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x4dea), (kernel_ulong_t)&bxt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x4deb), (kernel_ulong_t)&bxt_i2c_info },
- { PCI_VDEVICE(INTEL, 0x4dfb), (kernel_ulong_t)&spt_info },
+ { PCI_VDEVICE(INTEL, 0x4dfb), (kernel_ulong_t)&cnl_info },
/* ADL-P */
{ PCI_VDEVICE(INTEL, 0x51a8), (kernel_ulong_t)&bxt_uart_info },
{ PCI_VDEVICE(INTEL, 0x51a9), (kernel_ulong_t)&bxt_uart_info },
- { PCI_VDEVICE(INTEL, 0x51aa), (kernel_ulong_t)&bxt_info },
- { PCI_VDEVICE(INTEL, 0x51ab), (kernel_ulong_t)&bxt_info },
+ { PCI_VDEVICE(INTEL, 0x51aa), (kernel_ulong_t)&tgl_info },
+ { PCI_VDEVICE(INTEL, 0x51ab), (kernel_ulong_t)&tgl_info },
{ PCI_VDEVICE(INTEL, 0x51c5), (kernel_ulong_t)&bxt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x51c6), (kernel_ulong_t)&bxt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x51c7), (kernel_ulong_t)&bxt_uart_info },
@@ -325,12 +374,12 @@ static const struct pci_device_id intel_lpss_pci_ids[] = {
{ PCI_VDEVICE(INTEL, 0x51e9), (kernel_ulong_t)&bxt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x51ea), (kernel_ulong_t)&bxt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x51eb), (kernel_ulong_t)&bxt_i2c_info },
- { PCI_VDEVICE(INTEL, 0x51fb), (kernel_ulong_t)&bxt_info },
+ { PCI_VDEVICE(INTEL, 0x51fb), (kernel_ulong_t)&tgl_info },
/* ADL-M */
{ PCI_VDEVICE(INTEL, 0x54a8), (kernel_ulong_t)&bxt_uart_info },
{ PCI_VDEVICE(INTEL, 0x54a9), (kernel_ulong_t)&bxt_uart_info },
- { PCI_VDEVICE(INTEL, 0x54aa), (kernel_ulong_t)&bxt_info },
- { PCI_VDEVICE(INTEL, 0x54ab), (kernel_ulong_t)&bxt_info },
+ { PCI_VDEVICE(INTEL, 0x54aa), (kernel_ulong_t)&tgl_info },
+ { PCI_VDEVICE(INTEL, 0x54ab), (kernel_ulong_t)&tgl_info },
{ PCI_VDEVICE(INTEL, 0x54c5), (kernel_ulong_t)&bxt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x54c6), (kernel_ulong_t)&bxt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x54c7), (kernel_ulong_t)&bxt_uart_info },
@@ -338,7 +387,7 @@ static const struct pci_device_id intel_lpss_pci_ids[] = {
{ PCI_VDEVICE(INTEL, 0x54e9), (kernel_ulong_t)&bxt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x54ea), (kernel_ulong_t)&bxt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x54eb), (kernel_ulong_t)&bxt_i2c_info },
- { PCI_VDEVICE(INTEL, 0x54fb), (kernel_ulong_t)&bxt_info },
+ { PCI_VDEVICE(INTEL, 0x54fb), (kernel_ulong_t)&tgl_info },
/* APL */
{ PCI_VDEVICE(INTEL, 0x5aac), (kernel_ulong_t)&apl_i2c_info },
{ PCI_VDEVICE(INTEL, 0x5aae), (kernel_ulong_t)&apl_i2c_info },
@@ -358,39 +407,39 @@ static const struct pci_device_id intel_lpss_pci_ids[] = {
/* RPL-S */
{ PCI_VDEVICE(INTEL, 0x7a28), (kernel_ulong_t)&bxt_uart_info },
{ PCI_VDEVICE(INTEL, 0x7a29), (kernel_ulong_t)&bxt_uart_info },
- { PCI_VDEVICE(INTEL, 0x7a2a), (kernel_ulong_t)&bxt_info },
- { PCI_VDEVICE(INTEL, 0x7a2b), (kernel_ulong_t)&bxt_info },
+ { PCI_VDEVICE(INTEL, 0x7a2a), (kernel_ulong_t)&tgl_info },
+ { PCI_VDEVICE(INTEL, 0x7a2b), (kernel_ulong_t)&tgl_info },
{ PCI_VDEVICE(INTEL, 0x7a4c), (kernel_ulong_t)&bxt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x7a4d), (kernel_ulong_t)&bxt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x7a4e), (kernel_ulong_t)&bxt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x7a4f), (kernel_ulong_t)&bxt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x7a5c), (kernel_ulong_t)&bxt_uart_info },
- { PCI_VDEVICE(INTEL, 0x7a79), (kernel_ulong_t)&bxt_info },
- { PCI_VDEVICE(INTEL, 0x7a7b), (kernel_ulong_t)&bxt_info },
+ { PCI_VDEVICE(INTEL, 0x7a79), (kernel_ulong_t)&tgl_info },
+ { PCI_VDEVICE(INTEL, 0x7a7b), (kernel_ulong_t)&tgl_info },
{ PCI_VDEVICE(INTEL, 0x7a7c), (kernel_ulong_t)&bxt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x7a7d), (kernel_ulong_t)&bxt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x7a7e), (kernel_ulong_t)&bxt_uart_info },
/* ADL-S */
{ PCI_VDEVICE(INTEL, 0x7aa8), (kernel_ulong_t)&bxt_uart_info },
{ PCI_VDEVICE(INTEL, 0x7aa9), (kernel_ulong_t)&bxt_uart_info },
- { PCI_VDEVICE(INTEL, 0x7aaa), (kernel_ulong_t)&bxt_info },
- { PCI_VDEVICE(INTEL, 0x7aab), (kernel_ulong_t)&bxt_info },
+ { PCI_VDEVICE(INTEL, 0x7aaa), (kernel_ulong_t)&tgl_info },
+ { PCI_VDEVICE(INTEL, 0x7aab), (kernel_ulong_t)&tgl_info },
{ PCI_VDEVICE(INTEL, 0x7acc), (kernel_ulong_t)&bxt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x7acd), (kernel_ulong_t)&bxt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x7ace), (kernel_ulong_t)&bxt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x7acf), (kernel_ulong_t)&bxt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x7adc), (kernel_ulong_t)&bxt_uart_info },
- { PCI_VDEVICE(INTEL, 0x7af9), (kernel_ulong_t)&bxt_info },
- { PCI_VDEVICE(INTEL, 0x7afb), (kernel_ulong_t)&bxt_info },
+ { PCI_VDEVICE(INTEL, 0x7af9), (kernel_ulong_t)&tgl_info },
+ { PCI_VDEVICE(INTEL, 0x7afb), (kernel_ulong_t)&tgl_info },
{ PCI_VDEVICE(INTEL, 0x7afc), (kernel_ulong_t)&bxt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x7afd), (kernel_ulong_t)&bxt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x7afe), (kernel_ulong_t)&bxt_uart_info },
/* MTL-P */
{ PCI_VDEVICE(INTEL, 0x7e25), (kernel_ulong_t)&bxt_uart_info },
{ PCI_VDEVICE(INTEL, 0x7e26), (kernel_ulong_t)&bxt_uart_info },
- { PCI_VDEVICE(INTEL, 0x7e27), (kernel_ulong_t)&bxt_info },
- { PCI_VDEVICE(INTEL, 0x7e30), (kernel_ulong_t)&bxt_info },
- { PCI_VDEVICE(INTEL, 0x7e46), (kernel_ulong_t)&bxt_info },
+ { PCI_VDEVICE(INTEL, 0x7e27), (kernel_ulong_t)&tgl_info },
+ { PCI_VDEVICE(INTEL, 0x7e30), (kernel_ulong_t)&tgl_info },
+ { PCI_VDEVICE(INTEL, 0x7e46), (kernel_ulong_t)&tgl_info },
{ PCI_VDEVICE(INTEL, 0x7e50), (kernel_ulong_t)&bxt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x7e51), (kernel_ulong_t)&bxt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x7e52), (kernel_ulong_t)&bxt_uart_info },
@@ -424,8 +473,8 @@ static const struct pci_device_id intel_lpss_pci_ids[] = {
/* CNL-LP */
{ PCI_VDEVICE(INTEL, 0x9da8), (kernel_ulong_t)&spt_uart_info },
{ PCI_VDEVICE(INTEL, 0x9da9), (kernel_ulong_t)&spt_uart_info },
- { PCI_VDEVICE(INTEL, 0x9daa), (kernel_ulong_t)&spt_info },
- { PCI_VDEVICE(INTEL, 0x9dab), (kernel_ulong_t)&spt_info },
+ { PCI_VDEVICE(INTEL, 0x9daa), (kernel_ulong_t)&cnl_info },
+ { PCI_VDEVICE(INTEL, 0x9dab), (kernel_ulong_t)&cnl_info },
{ PCI_VDEVICE(INTEL, 0x9dc5), (kernel_ulong_t)&cnl_i2c_info },
{ PCI_VDEVICE(INTEL, 0x9dc6), (kernel_ulong_t)&cnl_i2c_info },
{ PCI_VDEVICE(INTEL, 0x9dc7), (kernel_ulong_t)&spt_uart_info },
@@ -433,12 +482,12 @@ static const struct pci_device_id intel_lpss_pci_ids[] = {
{ PCI_VDEVICE(INTEL, 0x9de9), (kernel_ulong_t)&cnl_i2c_info },
{ PCI_VDEVICE(INTEL, 0x9dea), (kernel_ulong_t)&cnl_i2c_info },
{ PCI_VDEVICE(INTEL, 0x9deb), (kernel_ulong_t)&cnl_i2c_info },
- { PCI_VDEVICE(INTEL, 0x9dfb), (kernel_ulong_t)&spt_info },
+ { PCI_VDEVICE(INTEL, 0x9dfb), (kernel_ulong_t)&cnl_info },
/* TGL-LP */
{ PCI_VDEVICE(INTEL, 0xa0a8), (kernel_ulong_t)&bxt_uart_info },
{ PCI_VDEVICE(INTEL, 0xa0a9), (kernel_ulong_t)&bxt_uart_info },
- { PCI_VDEVICE(INTEL, 0xa0aa), (kernel_ulong_t)&spt_info },
- { PCI_VDEVICE(INTEL, 0xa0ab), (kernel_ulong_t)&spt_info },
+ { PCI_VDEVICE(INTEL, 0xa0aa), (kernel_ulong_t)&cnl_info },
+ { PCI_VDEVICE(INTEL, 0xa0ab), (kernel_ulong_t)&cnl_info },
{ PCI_VDEVICE(INTEL, 0xa0c5), (kernel_ulong_t)&spt_i2c_info },
{ PCI_VDEVICE(INTEL, 0xa0c6), (kernel_ulong_t)&spt_i2c_info },
{ PCI_VDEVICE(INTEL, 0xa0c7), (kernel_ulong_t)&bxt_uart_info },
@@ -448,15 +497,15 @@ static const struct pci_device_id intel_lpss_pci_ids[] = {
{ PCI_VDEVICE(INTEL, 0xa0db), (kernel_ulong_t)&bxt_uart_info },
{ PCI_VDEVICE(INTEL, 0xa0dc), (kernel_ulong_t)&bxt_uart_info },
{ PCI_VDEVICE(INTEL, 0xa0dd), (kernel_ulong_t)&bxt_uart_info },
- { PCI_VDEVICE(INTEL, 0xa0de), (kernel_ulong_t)&spt_info },
- { PCI_VDEVICE(INTEL, 0xa0df), (kernel_ulong_t)&spt_info },
+ { PCI_VDEVICE(INTEL, 0xa0de), (kernel_ulong_t)&cnl_info },
+ { PCI_VDEVICE(INTEL, 0xa0df), (kernel_ulong_t)&cnl_info },
{ PCI_VDEVICE(INTEL, 0xa0e8), (kernel_ulong_t)&spt_i2c_info },
{ PCI_VDEVICE(INTEL, 0xa0e9), (kernel_ulong_t)&spt_i2c_info },
{ PCI_VDEVICE(INTEL, 0xa0ea), (kernel_ulong_t)&spt_i2c_info },
{ PCI_VDEVICE(INTEL, 0xa0eb), (kernel_ulong_t)&spt_i2c_info },
- { PCI_VDEVICE(INTEL, 0xa0fb), (kernel_ulong_t)&spt_info },
- { PCI_VDEVICE(INTEL, 0xa0fd), (kernel_ulong_t)&spt_info },
- { PCI_VDEVICE(INTEL, 0xa0fe), (kernel_ulong_t)&spt_info },
+ { PCI_VDEVICE(INTEL, 0xa0fb), (kernel_ulong_t)&cnl_info },
+ { PCI_VDEVICE(INTEL, 0xa0fd), (kernel_ulong_t)&cnl_info },
+ { PCI_VDEVICE(INTEL, 0xa0fe), (kernel_ulong_t)&cnl_info },
/* SPT-H */
{ PCI_VDEVICE(INTEL, 0xa127), (kernel_ulong_t)&spt_uart_info },
{ PCI_VDEVICE(INTEL, 0xa128), (kernel_ulong_t)&spt_uart_info },
@@ -479,14 +528,14 @@ static const struct pci_device_id intel_lpss_pci_ids[] = {
/* CNL-H */
{ PCI_VDEVICE(INTEL, 0xa328), (kernel_ulong_t)&spt_uart_info },
{ PCI_VDEVICE(INTEL, 0xa329), (kernel_ulong_t)&spt_uart_info },
- { PCI_VDEVICE(INTEL, 0xa32a), (kernel_ulong_t)&spt_info },
- { PCI_VDEVICE(INTEL, 0xa32b), (kernel_ulong_t)&spt_info },
+ { PCI_VDEVICE(INTEL, 0xa32a), (kernel_ulong_t)&cnl_info },
+ { PCI_VDEVICE(INTEL, 0xa32b), (kernel_ulong_t)&cnl_info },
{ PCI_VDEVICE(INTEL, 0xa347), (kernel_ulong_t)&spt_uart_info },
{ PCI_VDEVICE(INTEL, 0xa368), (kernel_ulong_t)&cnl_i2c_info },
{ PCI_VDEVICE(INTEL, 0xa369), (kernel_ulong_t)&cnl_i2c_info },
{ PCI_VDEVICE(INTEL, 0xa36a), (kernel_ulong_t)&cnl_i2c_info },
{ PCI_VDEVICE(INTEL, 0xa36b), (kernel_ulong_t)&cnl_i2c_info },
- { PCI_VDEVICE(INTEL, 0xa37b), (kernel_ulong_t)&spt_info },
+ { PCI_VDEVICE(INTEL, 0xa37b), (kernel_ulong_t)&cnl_info },
/* CML-V */
{ PCI_VDEVICE(INTEL, 0xa3a7), (kernel_ulong_t)&spt_uart_info },
{ PCI_VDEVICE(INTEL, 0xa3a8), (kernel_ulong_t)&spt_uart_info },
diff --git a/drivers/mfd/intel-m10-bmc.c b/drivers/mfd/intel-m10-bmc.c
index f4d0d72573c8..7e3319e5b22f 100644
--- a/drivers/mfd/intel-m10-bmc.c
+++ b/drivers/mfd/intel-m10-bmc.c
@@ -21,6 +21,7 @@ enum m10bmc_type {
static struct mfd_cell m10bmc_d5005_subdevs[] = {
{ .name = "d5005bmc-hwmon" },
+ { .name = "d5005bmc-sec-update" }
};
static struct mfd_cell m10bmc_pacn3000_subdevs[] = {
diff --git a/drivers/mfd/intel_soc_pmic_chtdc_ti.c b/drivers/mfd/intel_soc_pmic_chtdc_ti.c
index 1c7577b881ff..282b8fd08009 100644
--- a/drivers/mfd/intel_soc_pmic_chtdc_ti.c
+++ b/drivers/mfd/intel_soc_pmic_chtdc_ti.c
@@ -140,7 +140,7 @@ static void chtdc_ti_shutdown(struct i2c_client *i2c)
disable_irq(pmic->irq);
}
-static int __maybe_unused chtdc_ti_suspend(struct device *dev)
+static int chtdc_ti_suspend(struct device *dev)
{
struct intel_soc_pmic *pmic = dev_get_drvdata(dev);
@@ -149,7 +149,7 @@ static int __maybe_unused chtdc_ti_suspend(struct device *dev)
return 0;
}
-static int __maybe_unused chtdc_ti_resume(struct device *dev)
+static int chtdc_ti_resume(struct device *dev)
{
struct intel_soc_pmic *pmic = dev_get_drvdata(dev);
@@ -158,7 +158,7 @@ static int __maybe_unused chtdc_ti_resume(struct device *dev)
return 0;
}
-static SIMPLE_DEV_PM_OPS(chtdc_ti_pm_ops, chtdc_ti_suspend, chtdc_ti_resume);
+static DEFINE_SIMPLE_DEV_PM_OPS(chtdc_ti_pm_ops, chtdc_ti_suspend, chtdc_ti_resume);
static const struct acpi_device_id chtdc_ti_acpi_ids[] = {
{ "INT33F5" },
@@ -169,7 +169,7 @@ MODULE_DEVICE_TABLE(acpi, chtdc_ti_acpi_ids);
static struct i2c_driver chtdc_ti_i2c_driver = {
.driver = {
.name = "intel_soc_pmic_chtdc_ti",
- .pm = &chtdc_ti_pm_ops,
+ .pm = pm_sleep_ptr(&chtdc_ti_pm_ops),
.acpi_match_table = chtdc_ti_acpi_ids,
},
.probe_new = chtdc_ti_probe,
diff --git a/drivers/mfd/intel_soc_pmic_core.c b/drivers/mfd/intel_soc_pmic_core.c
deleted file mode 100644
index b824e15f4d22..000000000000
--- a/drivers/mfd/intel_soc_pmic_core.c
+++ /dev/null
@@ -1,158 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Intel SoC PMIC MFD Driver
- *
- * Copyright (C) 2013, 2014 Intel Corporation. All rights reserved.
- *
- * Author: Yang, Bin <bin.yang@intel.com>
- * Author: Zhu, Lejun <lejun.zhu@linux.intel.com>
- */
-
-#include <linux/acpi.h>
-#include <linux/i2c.h>
-#include <linux/interrupt.h>
-#include <linux/module.h>
-#include <linux/mfd/core.h>
-#include <linux/mfd/intel_soc_pmic.h>
-#include <linux/platform_data/x86/soc.h>
-#include <linux/pwm.h>
-#include <linux/regmap.h>
-
-#include "intel_soc_pmic_core.h"
-
-/* PWM consumed by the Intel GFX */
-static struct pwm_lookup crc_pwm_lookup[] = {
- PWM_LOOKUP("crystal_cove_pwm", 0, "0000:00:02.0", "pwm_pmic_backlight", 0, PWM_POLARITY_NORMAL),
-};
-
-static int intel_soc_pmic_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *i2c_id)
-{
- struct device *dev = &i2c->dev;
- struct intel_soc_pmic_config *config;
- struct intel_soc_pmic *pmic;
- int ret;
-
- if (soc_intel_is_byt())
- config = &intel_soc_pmic_config_byt_crc;
- else
- config = &intel_soc_pmic_config_cht_crc;
-
- pmic = devm_kzalloc(dev, sizeof(*pmic), GFP_KERNEL);
- if (!pmic)
- return -ENOMEM;
-
- dev_set_drvdata(dev, pmic);
-
- pmic->regmap = devm_regmap_init_i2c(i2c, config->regmap_config);
- if (IS_ERR(pmic->regmap))
- return PTR_ERR(pmic->regmap);
-
- pmic->irq = i2c->irq;
-
- ret = regmap_add_irq_chip(pmic->regmap, pmic->irq,
- config->irq_flags | IRQF_ONESHOT,
- 0, config->irq_chip,
- &pmic->irq_chip_data);
- if (ret)
- return ret;
-
- ret = enable_irq_wake(pmic->irq);
- if (ret)
- dev_warn(dev, "Can't enable IRQ as wake source: %d\n", ret);
-
- /* Add lookup table for crc-pwm */
- pwm_add_table(crc_pwm_lookup, ARRAY_SIZE(crc_pwm_lookup));
-
- /* To distuingish this domain from the GPIO/charger's irqchip domains */
- irq_domain_update_bus_token(regmap_irq_get_domain(pmic->irq_chip_data),
- DOMAIN_BUS_NEXUS);
-
- ret = mfd_add_devices(dev, -1, config->cell_dev,
- config->n_cell_devs, NULL, 0,
- regmap_irq_get_domain(pmic->irq_chip_data));
- if (ret)
- goto err_del_irq_chip;
-
- return 0;
-
-err_del_irq_chip:
- regmap_del_irq_chip(pmic->irq, pmic->irq_chip_data);
- return ret;
-}
-
-static void intel_soc_pmic_i2c_remove(struct i2c_client *i2c)
-{
- struct intel_soc_pmic *pmic = dev_get_drvdata(&i2c->dev);
-
- regmap_del_irq_chip(pmic->irq, pmic->irq_chip_data);
-
- /* remove crc-pwm lookup table */
- pwm_remove_table(crc_pwm_lookup, ARRAY_SIZE(crc_pwm_lookup));
-
- mfd_remove_devices(&i2c->dev);
-}
-
-static void intel_soc_pmic_shutdown(struct i2c_client *i2c)
-{
- struct intel_soc_pmic *pmic = dev_get_drvdata(&i2c->dev);
-
- disable_irq(pmic->irq);
-
- return;
-}
-
-#if defined(CONFIG_PM_SLEEP)
-static int intel_soc_pmic_suspend(struct device *dev)
-{
- struct intel_soc_pmic *pmic = dev_get_drvdata(dev);
-
- disable_irq(pmic->irq);
-
- return 0;
-}
-
-static int intel_soc_pmic_resume(struct device *dev)
-{
- struct intel_soc_pmic *pmic = dev_get_drvdata(dev);
-
- enable_irq(pmic->irq);
-
- return 0;
-}
-#endif
-
-static SIMPLE_DEV_PM_OPS(intel_soc_pmic_pm_ops, intel_soc_pmic_suspend,
- intel_soc_pmic_resume);
-
-static const struct i2c_device_id intel_soc_pmic_i2c_id[] = {
- { }
-};
-MODULE_DEVICE_TABLE(i2c, intel_soc_pmic_i2c_id);
-
-#if defined(CONFIG_ACPI)
-static const struct acpi_device_id intel_soc_pmic_acpi_match[] = {
- { "INT33FD" },
- { },
-};
-MODULE_DEVICE_TABLE(acpi, intel_soc_pmic_acpi_match);
-#endif
-
-static struct i2c_driver intel_soc_pmic_i2c_driver = {
- .driver = {
- .name = "intel_soc_pmic_i2c",
- .pm = &intel_soc_pmic_pm_ops,
- .acpi_match_table = ACPI_PTR(intel_soc_pmic_acpi_match),
- },
- .probe = intel_soc_pmic_i2c_probe,
- .remove = intel_soc_pmic_i2c_remove,
- .id_table = intel_soc_pmic_i2c_id,
- .shutdown = intel_soc_pmic_shutdown,
-};
-
-module_i2c_driver(intel_soc_pmic_i2c_driver);
-
-MODULE_DESCRIPTION("I2C driver for Intel SoC PMIC");
-MODULE_LICENSE("GPL v2");
-MODULE_AUTHOR("Yang, Bin <bin.yang@intel.com>");
-MODULE_AUTHOR("Zhu, Lejun <lejun.zhu@linux.intel.com>");
diff --git a/drivers/mfd/intel_soc_pmic_core.h b/drivers/mfd/intel_soc_pmic_core.h
deleted file mode 100644
index d490685845eb..000000000000
--- a/drivers/mfd/intel_soc_pmic_core.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Intel SoC PMIC MFD Driver
- *
- * Copyright (C) 2012-2014 Intel Corporation. All rights reserved.
- *
- * Author: Yang, Bin <bin.yang@intel.com>
- * Author: Zhu, Lejun <lejun.zhu@linux.intel.com>
- */
-
-#ifndef __INTEL_SOC_PMIC_CORE_H__
-#define __INTEL_SOC_PMIC_CORE_H__
-
-struct intel_soc_pmic_config {
- unsigned long irq_flags;
- struct mfd_cell *cell_dev;
- int n_cell_devs;
- const struct regmap_config *regmap_config;
- const struct regmap_irq_chip *irq_chip;
-};
-
-extern struct intel_soc_pmic_config intel_soc_pmic_config_byt_crc;
-extern struct intel_soc_pmic_config intel_soc_pmic_config_cht_crc;
-
-#endif /* __INTEL_SOC_PMIC_CORE_H__ */
diff --git a/drivers/mfd/intel_soc_pmic_crc.c b/drivers/mfd/intel_soc_pmic_crc.c
index 5bb0367bd974..b1548a933dc3 100644
--- a/drivers/mfd/intel_soc_pmic_crc.c
+++ b/drivers/mfd/intel_soc_pmic_crc.c
@@ -2,18 +2,21 @@
/*
* Device access for Crystal Cove PMIC
*
- * Copyright (C) 2013, 2014 Intel Corporation. All rights reserved.
+ * Copyright (C) 2012-2014, 2022 Intel Corporation. All rights reserved.
*
* Author: Yang, Bin <bin.yang@intel.com>
* Author: Zhu, Lejun <lejun.zhu@linux.intel.com>
*/
+#include <linux/i2c.h>
#include <linux/interrupt.h>
-#include <linux/regmap.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
#include <linux/mfd/core.h>
#include <linux/mfd/intel_soc_pmic.h>
-
-#include "intel_soc_pmic_core.h"
+#include <linux/platform_data/x86/soc.h>
+#include <linux/pwm.h>
+#include <linux/regmap.h>
#define CRYSTAL_COVE_MAX_REGISTER 0xC6
@@ -132,7 +135,20 @@ static const struct regmap_irq_chip crystal_cove_irq_chip = {
.mask_base = CRYSTAL_COVE_REG_MIRQLVL1,
};
-struct intel_soc_pmic_config intel_soc_pmic_config_byt_crc = {
+/* PWM consumed by the Intel GFX */
+static struct pwm_lookup crc_pwm_lookup[] = {
+ PWM_LOOKUP("crystal_cove_pwm", 0, "0000:00:02.0", "pwm_pmic_backlight", 0, PWM_POLARITY_NORMAL),
+};
+
+struct crystal_cove_config {
+ unsigned long irq_flags;
+ struct mfd_cell *cell_dev;
+ int n_cell_devs;
+ const struct regmap_config *regmap_config;
+ const struct regmap_irq_chip *irq_chip;
+};
+
+static const struct crystal_cove_config crystal_cove_config_byt_crc = {
.irq_flags = IRQF_TRIGGER_RISING,
.cell_dev = crystal_cove_byt_dev,
.n_cell_devs = ARRAY_SIZE(crystal_cove_byt_dev),
@@ -140,10 +156,121 @@ struct intel_soc_pmic_config intel_soc_pmic_config_byt_crc = {
.irq_chip = &crystal_cove_irq_chip,
};
-struct intel_soc_pmic_config intel_soc_pmic_config_cht_crc = {
+static const struct crystal_cove_config crystal_cove_config_cht_crc = {
.irq_flags = IRQF_TRIGGER_RISING,
.cell_dev = crystal_cove_cht_dev,
.n_cell_devs = ARRAY_SIZE(crystal_cove_cht_dev),
.regmap_config = &crystal_cove_regmap_config,
.irq_chip = &crystal_cove_irq_chip,
};
+
+static int crystal_cove_i2c_probe(struct i2c_client *i2c)
+{
+ const struct crystal_cove_config *config;
+ struct device *dev = &i2c->dev;
+ struct intel_soc_pmic *pmic;
+ int ret;
+
+ if (soc_intel_is_byt())
+ config = &crystal_cove_config_byt_crc;
+ else
+ config = &crystal_cove_config_cht_crc;
+
+ pmic = devm_kzalloc(dev, sizeof(*pmic), GFP_KERNEL);
+ if (!pmic)
+ return -ENOMEM;
+
+ i2c_set_clientdata(i2c, pmic);
+
+ pmic->regmap = devm_regmap_init_i2c(i2c, config->regmap_config);
+ if (IS_ERR(pmic->regmap))
+ return PTR_ERR(pmic->regmap);
+
+ pmic->irq = i2c->irq;
+
+ ret = devm_regmap_add_irq_chip(dev, pmic->regmap, pmic->irq,
+ config->irq_flags | IRQF_ONESHOT,
+ 0, config->irq_chip, &pmic->irq_chip_data);
+ if (ret)
+ return ret;
+
+ ret = enable_irq_wake(pmic->irq);
+ if (ret)
+ dev_warn(dev, "Can't enable IRQ as wake source: %d\n", ret);
+
+ /* Add lookup table for crc-pwm */
+ pwm_add_table(crc_pwm_lookup, ARRAY_SIZE(crc_pwm_lookup));
+
+ /* To distuingish this domain from the GPIO/charger's irqchip domains */
+ irq_domain_update_bus_token(regmap_irq_get_domain(pmic->irq_chip_data),
+ DOMAIN_BUS_NEXUS);
+
+ ret = mfd_add_devices(dev, PLATFORM_DEVID_NONE, config->cell_dev,
+ config->n_cell_devs, NULL, 0,
+ regmap_irq_get_domain(pmic->irq_chip_data));
+ if (ret)
+ pwm_remove_table(crc_pwm_lookup, ARRAY_SIZE(crc_pwm_lookup));
+
+ return ret;
+}
+
+static void crystal_cove_i2c_remove(struct i2c_client *i2c)
+{
+ /* remove crc-pwm lookup table */
+ pwm_remove_table(crc_pwm_lookup, ARRAY_SIZE(crc_pwm_lookup));
+
+ mfd_remove_devices(&i2c->dev);
+}
+
+static void crystal_cove_shutdown(struct i2c_client *i2c)
+{
+ struct intel_soc_pmic *pmic = i2c_get_clientdata(i2c);
+
+ disable_irq(pmic->irq);
+
+ return;
+}
+
+static int crystal_cove_suspend(struct device *dev)
+{
+ struct intel_soc_pmic *pmic = dev_get_drvdata(dev);
+
+ disable_irq(pmic->irq);
+
+ return 0;
+}
+
+static int crystal_cove_resume(struct device *dev)
+{
+ struct intel_soc_pmic *pmic = dev_get_drvdata(dev);
+
+ enable_irq(pmic->irq);
+
+ return 0;
+}
+
+static DEFINE_SIMPLE_DEV_PM_OPS(crystal_cove_pm_ops, crystal_cove_suspend, crystal_cove_resume);
+
+static const struct acpi_device_id crystal_cove_acpi_match[] = {
+ { "INT33FD" },
+ { },
+};
+MODULE_DEVICE_TABLE(acpi, crystal_cove_acpi_match);
+
+static struct i2c_driver crystal_cove_i2c_driver = {
+ .driver = {
+ .name = "crystal_cove_i2c",
+ .pm = pm_sleep_ptr(&crystal_cove_pm_ops),
+ .acpi_match_table = crystal_cove_acpi_match,
+ },
+ .probe_new = crystal_cove_i2c_probe,
+ .remove = crystal_cove_i2c_remove,
+ .shutdown = crystal_cove_shutdown,
+};
+
+module_i2c_driver(crystal_cove_i2c_driver);
+
+MODULE_DESCRIPTION("I2C driver for Intel SoC PMIC");
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Yang, Bin <bin.yang@intel.com>");
+MODULE_AUTHOR("Zhu, Lejun <lejun.zhu@linux.intel.com>");
diff --git a/drivers/mfd/lp8788-irq.c b/drivers/mfd/lp8788-irq.c
index 348439a3fbbd..39006297f3d2 100644
--- a/drivers/mfd/lp8788-irq.c
+++ b/drivers/mfd/lp8788-irq.c
@@ -175,6 +175,7 @@ int lp8788_irq_init(struct lp8788 *lp, int irq)
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
"lp8788-irq", irqd);
if (ret) {
+ irq_domain_remove(lp->irqdm);
dev_err(lp->dev, "failed to create a thread for IRQ_N\n");
return ret;
}
@@ -188,4 +189,6 @@ void lp8788_irq_exit(struct lp8788 *lp)
{
if (lp->irq)
free_irq(lp->irq, lp->irqdm);
+ if (lp->irqdm)
+ irq_domain_remove(lp->irqdm);
}
diff --git a/drivers/mfd/lp8788.c b/drivers/mfd/lp8788.c
index e7c601bca9ef..724a5712b36b 100644
--- a/drivers/mfd/lp8788.c
+++ b/drivers/mfd/lp8788.c
@@ -195,8 +195,16 @@ static int lp8788_probe(struct i2c_client *cl, const struct i2c_device_id *id)
if (ret)
return ret;
- return mfd_add_devices(lp->dev, -1, lp8788_devs,
- ARRAY_SIZE(lp8788_devs), NULL, 0, NULL);
+ ret = mfd_add_devices(lp->dev, -1, lp8788_devs,
+ ARRAY_SIZE(lp8788_devs), NULL, 0, NULL);
+ if (ret)
+ goto err_exit_irq;
+
+ return 0;
+
+err_exit_irq:
+ lp8788_irq_exit(lp);
+ return ret;
}
static void lp8788_remove(struct i2c_client *cl)
diff --git a/drivers/mfd/lpc_ich.c b/drivers/mfd/lpc_ich.c
index 650951f89f1c..7b1c597b6879 100644
--- a/drivers/mfd/lpc_ich.c
+++ b/drivers/mfd/lpc_ich.c
@@ -959,7 +959,7 @@ static int lpc_ich_finalize_wdt_cell(struct pci_dev *dev)
info = &lpc_chipset_info[priv->chipset];
pdata->version = info->iTCO_version;
- strlcpy(pdata->name, info->name, sizeof(pdata->name));
+ strscpy(pdata->name, info->name, sizeof(pdata->name));
cell->platform_data = pdata;
cell->pdata_size = sizeof(*pdata);
diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c
index 8b058200d5ad..16d1861e9682 100644
--- a/drivers/mfd/mfd-core.c
+++ b/drivers/mfd/mfd-core.c
@@ -105,7 +105,7 @@ static void mfd_acpi_add_device(const struct mfd_cell *cell,
.ids = ids,
};
- strlcpy(ids[0].id, match->pnpid, sizeof(ids[0].id));
+ strscpy(ids[0].id, match->pnpid, sizeof(ids[0].id));
acpi_dev_for_each_child(parent, match_device_ids, &wd);
adev = wd.adev;
} else {
@@ -368,6 +368,7 @@ static int mfd_remove_devices_fn(struct device *dev, void *data)
{
struct platform_device *pdev;
const struct mfd_cell *cell;
+ struct mfd_of_node_entry *of_entry, *tmp;
int *level = data;
if (dev->type != &mfd_dev_type)
@@ -382,6 +383,12 @@ static int mfd_remove_devices_fn(struct device *dev, void *data)
if (cell->swnode)
device_remove_software_node(&pdev->dev);
+ list_for_each_entry_safe(of_entry, tmp, &mfd_of_node_list, list)
+ if (of_entry->dev == &pdev->dev) {
+ list_del(&of_entry->list);
+ kfree(of_entry);
+ }
+
regulator_bulk_unregister_supply_alias(dev, cell->parent_supplies,
cell->num_parent_supplies);
diff --git a/drivers/mfd/mt6370.c b/drivers/mfd/mt6370.c
new file mode 100644
index 000000000000..cf19cce2fdc0
--- /dev/null
+++ b/drivers/mfd/mt6370.c
@@ -0,0 +1,312 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2022 Richtek Technology Corp.
+ *
+ * Author: ChiYuan Huang <cy_huang@richtek.com>
+ */
+
+#include <linux/bits.h>
+#include <linux/bitfield.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/mfd/core.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+
+#include "mt6370.h"
+
+#define MT6370_REG_DEV_INFO 0x100
+#define MT6370_REG_CHG_IRQ1 0x1C0
+#define MT6370_REG_CHG_MASK1 0x1E0
+#define MT6370_REG_MAXADDR 0x1FF
+
+#define MT6370_VENID_MASK GENMASK(7, 4)
+
+#define MT6370_NUM_IRQREGS 16
+#define MT6370_USBC_I2CADDR 0x4E
+#define MT6370_MAX_ADDRLEN 2
+
+#define MT6370_VENID_RT5081 0x8
+#define MT6370_VENID_RT5081A 0xA
+#define MT6370_VENID_MT6370 0xE
+#define MT6370_VENID_MT6371 0xF
+#define MT6370_VENID_MT6372P 0x9
+#define MT6370_VENID_MT6372CP 0xB
+
+static const struct regmap_irq mt6370_irqs[] = {
+ REGMAP_IRQ_REG_LINE(MT6370_IRQ_DIRCHGON, 8),
+ REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_TREG, 8),
+ REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_AICR, 8),
+ REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_MIVR, 8),
+ REGMAP_IRQ_REG_LINE(MT6370_IRQ_PWR_RDY, 8),
+ REGMAP_IRQ_REG_LINE(MT6370_IRQ_FL_CHG_VINOVP, 8),
+ REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_VSYSUV, 8),
+ REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_VSYSOV, 8),
+ REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_VBATOV, 8),
+ REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_VINOVPCHG, 8),
+ REGMAP_IRQ_REG_LINE(MT6370_IRQ_TS_BAT_COLD, 8),
+ REGMAP_IRQ_REG_LINE(MT6370_IRQ_TS_BAT_COOL, 8),
+ REGMAP_IRQ_REG_LINE(MT6370_IRQ_TS_BAT_WARM, 8),
+ REGMAP_IRQ_REG_LINE(MT6370_IRQ_TS_BAT_HOT, 8),
+ REGMAP_IRQ_REG_LINE(MT6370_IRQ_TS_STATC, 8),
+ REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_FAULT, 8),
+ REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_STATC, 8),
+ REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_TMR, 8),
+ REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_BATABS, 8),
+ REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_ADPBAD, 8),
+ REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_RVP, 8),
+ REGMAP_IRQ_REG_LINE(MT6370_IRQ_TSHUTDOWN, 8),
+ REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_IINMEAS, 8),
+ REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_ICCMEAS, 8),
+ REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHGDET_DONE, 8),
+ REGMAP_IRQ_REG_LINE(MT6370_IRQ_WDTMR, 8),
+ REGMAP_IRQ_REG_LINE(MT6370_IRQ_SSFINISH, 8),
+ REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_RECHG, 8),
+ REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_TERM, 8),
+ REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_IEOC, 8),
+ REGMAP_IRQ_REG_LINE(MT6370_IRQ_ADC_DONE, 8),
+ REGMAP_IRQ_REG_LINE(MT6370_IRQ_PUMPX_DONE, 8),
+ REGMAP_IRQ_REG_LINE(MT6370_IRQ_BST_BATUV, 8),
+ REGMAP_IRQ_REG_LINE(MT6370_IRQ_BST_MIDOV, 8),
+ REGMAP_IRQ_REG_LINE(MT6370_IRQ_BST_OLP, 8),
+ REGMAP_IRQ_REG_LINE(MT6370_IRQ_ATTACH, 8),
+ REGMAP_IRQ_REG_LINE(MT6370_IRQ_DETACH, 8),
+ REGMAP_IRQ_REG_LINE(MT6370_IRQ_HVDCP_STPDONE, 8),
+ REGMAP_IRQ_REG_LINE(MT6370_IRQ_HVDCP_VBUSDET_DONE, 8),
+ REGMAP_IRQ_REG_LINE(MT6370_IRQ_HVDCP_DET, 8),
+ REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHGDET, 8),
+ REGMAP_IRQ_REG_LINE(MT6370_IRQ_DCDT, 8),
+ REGMAP_IRQ_REG_LINE(MT6370_IRQ_DIRCHG_VGOK, 8),
+ REGMAP_IRQ_REG_LINE(MT6370_IRQ_DIRCHG_WDTMR, 8),
+ REGMAP_IRQ_REG_LINE(MT6370_IRQ_DIRCHG_UC, 8),
+ REGMAP_IRQ_REG_LINE(MT6370_IRQ_DIRCHG_OC, 8),
+ REGMAP_IRQ_REG_LINE(MT6370_IRQ_DIRCHG_OV, 8),
+ REGMAP_IRQ_REG_LINE(MT6370_IRQ_OVPCTRL_SWON, 8),
+ REGMAP_IRQ_REG_LINE(MT6370_IRQ_OVPCTRL_UVP_D, 8),
+ REGMAP_IRQ_REG_LINE(MT6370_IRQ_OVPCTRL_UVP, 8),
+ REGMAP_IRQ_REG_LINE(MT6370_IRQ_OVPCTRL_OVP_D, 8),
+ REGMAP_IRQ_REG_LINE(MT6370_IRQ_OVPCTRL_OVP, 8),
+ REGMAP_IRQ_REG_LINE(MT6370_IRQ_FLED_STRBPIN, 8),
+ REGMAP_IRQ_REG_LINE(MT6370_IRQ_FLED_TORPIN, 8),
+ REGMAP_IRQ_REG_LINE(MT6370_IRQ_FLED_TX, 8),
+ REGMAP_IRQ_REG_LINE(MT6370_IRQ_FLED_LVF, 8),
+ REGMAP_IRQ_REG_LINE(MT6370_IRQ_FLED2_SHORT, 8),
+ REGMAP_IRQ_REG_LINE(MT6370_IRQ_FLED1_SHORT, 8),
+ REGMAP_IRQ_REG_LINE(MT6370_IRQ_FLED2_STRB, 8),
+ REGMAP_IRQ_REG_LINE(MT6370_IRQ_FLED1_STRB, 8),
+ REGMAP_IRQ_REG_LINE(mT6370_IRQ_FLED2_STRB_TO, 8),
+ REGMAP_IRQ_REG_LINE(MT6370_IRQ_FLED1_STRB_TO, 8),
+ REGMAP_IRQ_REG_LINE(MT6370_IRQ_FLED2_TOR, 8),
+ REGMAP_IRQ_REG_LINE(MT6370_IRQ_FLED1_TOR, 8),
+ REGMAP_IRQ_REG_LINE(MT6370_IRQ_OTP, 8),
+ REGMAP_IRQ_REG_LINE(MT6370_IRQ_VDDA_OVP, 8),
+ REGMAP_IRQ_REG_LINE(MT6370_IRQ_VDDA_UV, 8),
+ REGMAP_IRQ_REG_LINE(MT6370_IRQ_LDO_OC, 8),
+ REGMAP_IRQ_REG_LINE(MT6370_IRQ_BLED_OCP, 8),
+ REGMAP_IRQ_REG_LINE(MT6370_IRQ_BLED_OVP, 8),
+ REGMAP_IRQ_REG_LINE(MT6370_IRQ_DSV_VNEG_OCP, 8),
+ REGMAP_IRQ_REG_LINE(MT6370_IRQ_DSV_VPOS_OCP, 8),
+ REGMAP_IRQ_REG_LINE(MT6370_IRQ_DSV_BST_OCP, 8),
+ REGMAP_IRQ_REG_LINE(MT6370_IRQ_DSV_VNEG_SCP, 8),
+ REGMAP_IRQ_REG_LINE(MT6370_IRQ_DSV_VPOS_SCP, 8),
+};
+
+static const struct regmap_irq_chip mt6370_irq_chip = {
+ .name = "mt6370-irqs",
+ .status_base = MT6370_REG_CHG_IRQ1,
+ .mask_base = MT6370_REG_CHG_MASK1,
+ .num_regs = MT6370_NUM_IRQREGS,
+ .irqs = mt6370_irqs,
+ .num_irqs = ARRAY_SIZE(mt6370_irqs),
+};
+
+static const struct resource mt6370_regulator_irqs[] = {
+ DEFINE_RES_IRQ_NAMED(MT6370_IRQ_DSV_VPOS_SCP, "db_vpos_scp"),
+ DEFINE_RES_IRQ_NAMED(MT6370_IRQ_DSV_VNEG_SCP, "db_vneg_scp"),
+ DEFINE_RES_IRQ_NAMED(MT6370_IRQ_DSV_BST_OCP, "db_vbst_ocp"),
+ DEFINE_RES_IRQ_NAMED(MT6370_IRQ_DSV_VPOS_OCP, "db_vpos_ocp"),
+ DEFINE_RES_IRQ_NAMED(MT6370_IRQ_DSV_VNEG_OCP, "db_vneg_ocp"),
+ DEFINE_RES_IRQ_NAMED(MT6370_IRQ_LDO_OC, "ldo_oc"),
+};
+
+static const struct mfd_cell mt6370_devices[] = {
+ MFD_CELL_OF("mt6370-adc",
+ NULL, NULL, 0, 0, "mediatek,mt6370-adc"),
+ MFD_CELL_OF("mt6370-charger",
+ NULL, NULL, 0, 0, "mediatek,mt6370-charger"),
+ MFD_CELL_OF("mt6370-flashlight",
+ NULL, NULL, 0, 0, "mediatek,mt6370-flashlight"),
+ MFD_CELL_OF("mt6370-indicator",
+ NULL, NULL, 0, 0, "mediatek,mt6370-indicator"),
+ MFD_CELL_OF("mt6370-tcpc",
+ NULL, NULL, 0, 0, "mediatek,mt6370-tcpc"),
+ MFD_CELL_RES("mt6370-regulator", mt6370_regulator_irqs),
+};
+
+static const struct mfd_cell mt6370_exclusive_devices[] = {
+ MFD_CELL_OF("mt6370-backlight",
+ NULL, NULL, 0, 0, "mediatek,mt6370-backlight"),
+};
+
+static const struct mfd_cell mt6372_exclusive_devices[] = {
+ MFD_CELL_OF("mt6370-backlight",
+ NULL, NULL, 0, 0, "mediatek,mt6372-backlight"),
+};
+
+static int mt6370_check_vendor_info(struct device *dev, struct regmap *rmap,
+ int *vid)
+{
+ unsigned int devinfo;
+ int ret;
+
+ ret = regmap_read(rmap, MT6370_REG_DEV_INFO, &devinfo);
+ if (ret)
+ return ret;
+
+ *vid = FIELD_GET(MT6370_VENID_MASK, devinfo);
+ switch (*vid) {
+ case MT6370_VENID_RT5081:
+ case MT6370_VENID_RT5081A:
+ case MT6370_VENID_MT6370:
+ case MT6370_VENID_MT6371:
+ case MT6370_VENID_MT6372P:
+ case MT6370_VENID_MT6372CP:
+ return 0;
+ default:
+ dev_err(dev, "Unknown Vendor ID 0x%02x\n", devinfo);
+ return -ENODEV;
+ }
+}
+
+static int mt6370_regmap_read(void *context, const void *reg_buf,
+ size_t reg_size, void *val_buf, size_t val_size)
+{
+ struct mt6370_info *info = context;
+ const u8 *u8_buf = reg_buf;
+ u8 bank_idx, bank_addr;
+ int ret;
+
+ bank_idx = u8_buf[0];
+ bank_addr = u8_buf[1];
+
+ ret = i2c_smbus_read_i2c_block_data(info->i2c[bank_idx], bank_addr,
+ val_size, val_buf);
+ if (ret < 0)
+ return ret;
+
+ if (ret != val_size)
+ return -EIO;
+
+ return 0;
+}
+
+static int mt6370_regmap_write(void *context, const void *data, size_t count)
+{
+ struct mt6370_info *info = context;
+ const u8 *u8_buf = data;
+ u8 bank_idx, bank_addr;
+ int len = count - MT6370_MAX_ADDRLEN;
+
+ bank_idx = u8_buf[0];
+ bank_addr = u8_buf[1];
+
+ return i2c_smbus_write_i2c_block_data(info->i2c[bank_idx], bank_addr,
+ len, data + MT6370_MAX_ADDRLEN);
+}
+
+static const struct regmap_bus mt6370_regmap_bus = {
+ .read = mt6370_regmap_read,
+ .write = mt6370_regmap_write,
+};
+
+static const struct regmap_config mt6370_regmap_config = {
+ .reg_bits = 16,
+ .val_bits = 8,
+ .reg_format_endian = REGMAP_ENDIAN_BIG,
+ .max_register = MT6370_REG_MAXADDR,
+};
+
+static int mt6370_probe(struct i2c_client *i2c)
+{
+ struct mt6370_info *info;
+ struct i2c_client *usbc_i2c;
+ struct regmap *regmap;
+ struct device *dev = &i2c->dev;
+ int ret, vid;
+
+ info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+
+ usbc_i2c = devm_i2c_new_dummy_device(dev, i2c->adapter,
+ MT6370_USBC_I2CADDR);
+ if (IS_ERR(usbc_i2c))
+ return dev_err_probe(dev, PTR_ERR(usbc_i2c),
+ "Failed to register USBC I2C client\n");
+
+ /* Assign I2C client for PMU and TypeC */
+ info->i2c[MT6370_PMU_I2C] = i2c;
+ info->i2c[MT6370_USBC_I2C] = usbc_i2c;
+
+ regmap = devm_regmap_init(dev, &mt6370_regmap_bus,
+ info, &mt6370_regmap_config);
+ if (IS_ERR(regmap))
+ return dev_err_probe(dev, PTR_ERR(regmap),
+ "Failed to init regmap\n");
+
+ ret = mt6370_check_vendor_info(dev, regmap, &vid);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to check vendor info\n");
+
+ ret = devm_regmap_add_irq_chip(dev, regmap, i2c->irq,
+ IRQF_ONESHOT, -1, &mt6370_irq_chip,
+ &info->irq_data);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to add irq chip\n");
+
+ switch (vid) {
+ case MT6370_VENID_MT6372P:
+ case MT6370_VENID_MT6372CP:
+ ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO,
+ mt6372_exclusive_devices,
+ ARRAY_SIZE(mt6372_exclusive_devices),
+ NULL, 0,
+ regmap_irq_get_domain(info->irq_data));
+ break;
+ default:
+ ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO,
+ mt6370_exclusive_devices,
+ ARRAY_SIZE(mt6370_exclusive_devices),
+ NULL, 0,
+ regmap_irq_get_domain(info->irq_data));
+ break;
+ }
+
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to add the exclusive devices\n");
+
+ return devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO,
+ mt6370_devices, ARRAY_SIZE(mt6370_devices),
+ NULL, 0,
+ regmap_irq_get_domain(info->irq_data));
+}
+
+static const struct of_device_id mt6370_match_table[] = {
+ { .compatible = "mediatek,mt6370" },
+ {}
+};
+MODULE_DEVICE_TABLE(of, mt6370_match_table);
+
+static struct i2c_driver mt6370_driver = {
+ .driver = {
+ .name = "mt6370",
+ .of_match_table = mt6370_match_table,
+ },
+ .probe_new = mt6370_probe,
+};
+module_i2c_driver(mt6370_driver);
+
+MODULE_AUTHOR("ChiYuan Huang <cy_huang@richtek.com>");
+MODULE_DESCRIPTION("MediaTek MT6370 SubPMIC Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/mfd/mt6370.h b/drivers/mfd/mt6370.h
new file mode 100644
index 000000000000..094e59e4af4e
--- /dev/null
+++ b/drivers/mfd/mt6370.h
@@ -0,0 +1,99 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2022 Richtek Technology Corp.
+ *
+ * Author: ChiYuan Huang <cy_huang@richtek.com>
+ */
+
+#ifndef __MFD_MT6370_H__
+#define __MFD_MT6370_H__
+
+/* IRQ definitions */
+#define MT6370_IRQ_DIRCHGON 0
+#define MT6370_IRQ_CHG_TREG 4
+#define MT6370_IRQ_CHG_AICR 5
+#define MT6370_IRQ_CHG_MIVR 6
+#define MT6370_IRQ_PWR_RDY 7
+#define MT6370_IRQ_FL_CHG_VINOVP 11
+#define MT6370_IRQ_CHG_VSYSUV 12
+#define MT6370_IRQ_CHG_VSYSOV 13
+#define MT6370_IRQ_CHG_VBATOV 14
+#define MT6370_IRQ_CHG_VINOVPCHG 15
+#define MT6370_IRQ_TS_BAT_COLD 20
+#define MT6370_IRQ_TS_BAT_COOL 21
+#define MT6370_IRQ_TS_BAT_WARM 22
+#define MT6370_IRQ_TS_BAT_HOT 23
+#define MT6370_IRQ_TS_STATC 24
+#define MT6370_IRQ_CHG_FAULT 25
+#define MT6370_IRQ_CHG_STATC 26
+#define MT6370_IRQ_CHG_TMR 27
+#define MT6370_IRQ_CHG_BATABS 28
+#define MT6370_IRQ_CHG_ADPBAD 29
+#define MT6370_IRQ_CHG_RVP 30
+#define MT6370_IRQ_TSHUTDOWN 31
+#define MT6370_IRQ_CHG_IINMEAS 32
+#define MT6370_IRQ_CHG_ICCMEAS 33
+#define MT6370_IRQ_CHGDET_DONE 34
+#define MT6370_IRQ_WDTMR 35
+#define MT6370_IRQ_SSFINISH 36
+#define MT6370_IRQ_CHG_RECHG 37
+#define MT6370_IRQ_CHG_TERM 38
+#define MT6370_IRQ_CHG_IEOC 39
+#define MT6370_IRQ_ADC_DONE 40
+#define MT6370_IRQ_PUMPX_DONE 41
+#define MT6370_IRQ_BST_BATUV 45
+#define MT6370_IRQ_BST_MIDOV 46
+#define MT6370_IRQ_BST_OLP 47
+#define MT6370_IRQ_ATTACH 48
+#define MT6370_IRQ_DETACH 49
+#define MT6370_IRQ_HVDCP_STPDONE 51
+#define MT6370_IRQ_HVDCP_VBUSDET_DONE 52
+#define MT6370_IRQ_HVDCP_DET 53
+#define MT6370_IRQ_CHGDET 54
+#define MT6370_IRQ_DCDT 55
+#define MT6370_IRQ_DIRCHG_VGOK 59
+#define MT6370_IRQ_DIRCHG_WDTMR 60
+#define MT6370_IRQ_DIRCHG_UC 61
+#define MT6370_IRQ_DIRCHG_OC 62
+#define MT6370_IRQ_DIRCHG_OV 63
+#define MT6370_IRQ_OVPCTRL_SWON 67
+#define MT6370_IRQ_OVPCTRL_UVP_D 68
+#define MT6370_IRQ_OVPCTRL_UVP 69
+#define MT6370_IRQ_OVPCTRL_OVP_D 70
+#define MT6370_IRQ_OVPCTRL_OVP 71
+#define MT6370_IRQ_FLED_STRBPIN 72
+#define MT6370_IRQ_FLED_TORPIN 73
+#define MT6370_IRQ_FLED_TX 74
+#define MT6370_IRQ_FLED_LVF 75
+#define MT6370_IRQ_FLED2_SHORT 78
+#define MT6370_IRQ_FLED1_SHORT 79
+#define MT6370_IRQ_FLED2_STRB 80
+#define MT6370_IRQ_FLED1_STRB 81
+#define mT6370_IRQ_FLED2_STRB_TO 82
+#define MT6370_IRQ_FLED1_STRB_TO 83
+#define MT6370_IRQ_FLED2_TOR 84
+#define MT6370_IRQ_FLED1_TOR 85
+#define MT6370_IRQ_OTP 93
+#define MT6370_IRQ_VDDA_OVP 94
+#define MT6370_IRQ_VDDA_UV 95
+#define MT6370_IRQ_LDO_OC 103
+#define MT6370_IRQ_BLED_OCP 118
+#define MT6370_IRQ_BLED_OVP 119
+#define MT6370_IRQ_DSV_VNEG_OCP 123
+#define MT6370_IRQ_DSV_VPOS_OCP 124
+#define MT6370_IRQ_DSV_BST_OCP 125
+#define MT6370_IRQ_DSV_VNEG_SCP 126
+#define MT6370_IRQ_DSV_VPOS_SCP 127
+
+enum {
+ MT6370_USBC_I2C = 0,
+ MT6370_PMU_I2C,
+ MT6370_MAX_I2C
+};
+
+struct mt6370_info {
+ struct i2c_client *i2c[MT6370_MAX_I2C];
+ struct regmap_irq_chip_data *irq_data;
+};
+
+#endif /* __MFD_MT6375_H__ */
diff --git a/drivers/mfd/ocelot-spi.c b/drivers/mfd/ocelot-spi.c
index 0f097f4829d1..2ecd271de2fb 100644
--- a/drivers/mfd/ocelot-spi.c
+++ b/drivers/mfd/ocelot-spi.c
@@ -276,6 +276,7 @@ static const struct spi_device_id ocelot_spi_ids[] = {
{ "vsc7512", 0 },
{ }
};
+MODULE_DEVICE_TABLE(spi, ocelot_spi_ids);
static const struct of_device_id ocelot_spi_of_match[] = {
{ .compatible = "mscc,vsc7512" },
diff --git a/drivers/mfd/qcom-spmi-pmic.c b/drivers/mfd/qcom-spmi-pmic.c
index 00003a868d28..7e2cd79d17eb 100644
--- a/drivers/mfd/qcom-spmi-pmic.c
+++ b/drivers/mfd/qcom-spmi-pmic.c
@@ -60,6 +60,7 @@ static const struct of_device_id pmic_spmi_id_table[] = {
{ .compatible = "qcom,pmi8994", .data = N_USIDS(2) },
{ .compatible = "qcom,pmi8998", .data = N_USIDS(2) },
{ .compatible = "qcom,pmk8002", .data = N_USIDS(2) },
+ { .compatible = "qcom,pmp8074", .data = N_USIDS(2) },
{ .compatible = "qcom,smb2351", .data = N_USIDS(2) },
{ .compatible = "qcom,spmi-pmic", .data = N_USIDS(1) },
{ }
diff --git a/drivers/mfd/rk808.c b/drivers/mfd/rk808.c
index d5d641efa077..e00da7c7e3b1 100644
--- a/drivers/mfd/rk808.c
+++ b/drivers/mfd/rk808.c
@@ -67,6 +67,10 @@ static bool rk817_is_volatile_reg(struct device *dev, unsigned int reg)
case RK817_SECONDS_REG ... RK817_WEEKS_REG:
case RK817_RTC_STATUS_REG:
case RK817_CODEC_DTOP_LPT_SRST:
+ case RK817_GAS_GAUGE_ADC_CONFIG0 ... RK817_GAS_GAUGE_CUR_ADC_K0:
+ case RK817_PMIC_CHRG_STS:
+ case RK817_PMIC_CHRG_OUT:
+ case RK817_PMIC_CHRG_IN:
case RK817_INT_STS_REG0:
case RK817_INT_STS_REG1:
case RK817_INT_STS_REG2:
@@ -74,7 +78,7 @@ static bool rk817_is_volatile_reg(struct device *dev, unsigned int reg)
return true;
}
- return true;
+ return false;
}
static const struct regmap_config rk818_regmap_config = {
@@ -127,6 +131,11 @@ static const struct resource rk817_pwrkey_resources[] = {
DEFINE_RES_IRQ(RK817_IRQ_PWRON_FALL),
};
+static const struct resource rk817_charger_resources[] = {
+ DEFINE_RES_IRQ(RK817_IRQ_PLUG_IN),
+ DEFINE_RES_IRQ(RK817_IRQ_PLUG_OUT),
+};
+
static const struct mfd_cell rk805s[] = {
{ .name = "rk808-clkout", },
{ .name = "rk808-regulator", },
@@ -166,6 +175,11 @@ static const struct mfd_cell rk817s[] = {
.resources = &rk817_rtc_resources[0],
},
{ .name = "rk817-codec",},
+ {
+ .name = "rk817-charger",
+ .num_resources = ARRAY_SIZE(rk817_charger_resources),
+ .resources = &rk817_charger_resources[0],
+ },
};
static const struct mfd_cell rk818s[] = {
diff --git a/drivers/mfd/rt5120.c b/drivers/mfd/rt5120.c
new file mode 100644
index 000000000000..8046e383bc92
--- /dev/null
+++ b/drivers/mfd/rt5120.c
@@ -0,0 +1,124 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2022 Richtek Technology Corp.
+ * Author: ChiYuan Huang <cy_huang@richtek.com>
+ */
+
+#include <linux/i2c.h>
+#include <linux/kernel.h>
+#include <linux/mfd/core.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/regmap.h>
+
+#define RT5120_REG_INTENABLE 0x1D
+#define RT5120_REG_INTSTAT 0x1E
+#define RT5120_REG_FZCMODE 0x44
+
+#define RT5120_INT_HOTDIE 0
+#define RT5120_INT_PWRKEY_REL 5
+#define RT5120_INT_PWRKEY_PRESS 6
+
+static const struct regmap_range rt5120_rd_yes_ranges[] = {
+ regmap_reg_range(0x03, 0x13),
+ regmap_reg_range(0x1c, 0x20),
+ regmap_reg_range(0x44, 0x44),
+};
+
+static const struct regmap_range rt5120_wr_yes_ranges[] = {
+ regmap_reg_range(0x06, 0x13),
+ regmap_reg_range(0x1c, 0x20),
+ regmap_reg_range(0x44, 0x44),
+};
+
+static const struct regmap_access_table rt5120_rd_table = {
+ .yes_ranges = rt5120_rd_yes_ranges,
+ .n_yes_ranges = ARRAY_SIZE(rt5120_rd_yes_ranges),
+};
+
+static const struct regmap_access_table rt5120_wr_table = {
+ .yes_ranges = rt5120_wr_yes_ranges,
+ .n_yes_ranges = ARRAY_SIZE(rt5120_wr_yes_ranges),
+};
+
+static const struct regmap_config rt5120_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = RT5120_REG_FZCMODE,
+
+ .wr_table = &rt5120_wr_table,
+ .rd_table = &rt5120_rd_table,
+};
+
+static const struct regmap_irq rt5120_irqs[] = {
+ REGMAP_IRQ_REG_LINE(RT5120_INT_HOTDIE, 8),
+ REGMAP_IRQ_REG_LINE(RT5120_INT_PWRKEY_REL, 8),
+ REGMAP_IRQ_REG_LINE(RT5120_INT_PWRKEY_PRESS, 8),
+};
+
+static const struct regmap_irq_chip rt5120_irq_chip = {
+ .name = "rt5120-pmic",
+ .status_base = RT5120_REG_INTSTAT,
+ .mask_base = RT5120_REG_INTENABLE,
+ .ack_base = RT5120_REG_INTSTAT,
+ .mask_invert = true,
+ .use_ack = true,
+ .num_regs = 1,
+ .irqs = rt5120_irqs,
+ .num_irqs = ARRAY_SIZE(rt5120_irqs),
+};
+
+static const struct resource rt5120_regulator_resources[] = {
+ DEFINE_RES_IRQ(RT5120_INT_HOTDIE),
+};
+
+static const struct resource rt5120_pwrkey_resources[] = {
+ DEFINE_RES_IRQ_NAMED(RT5120_INT_PWRKEY_PRESS, "pwrkey-press"),
+ DEFINE_RES_IRQ_NAMED(RT5120_INT_PWRKEY_REL, "pwrkey-release"),
+};
+
+static const struct mfd_cell rt5120_devs[] = {
+ MFD_CELL_RES("rt5120-regulator", rt5120_regulator_resources),
+ MFD_CELL_OF("rt5120-pwrkey", rt5120_pwrkey_resources, NULL, 0, 0, "richtek,rt5120-pwrkey"),
+};
+
+static int rt5120_probe(struct i2c_client *i2c)
+{
+ struct device *dev = &i2c->dev;
+ struct regmap *regmap;
+ struct regmap_irq_chip_data *irq_data;
+ int ret;
+
+ regmap = devm_regmap_init_i2c(i2c, &rt5120_regmap_config);
+ if (IS_ERR(regmap))
+ return dev_err_probe(dev, PTR_ERR(regmap),
+ "Failed to init regmap\n");
+
+ ret = devm_regmap_add_irq_chip(dev, regmap, i2c->irq, IRQF_ONESHOT, 0,
+ &rt5120_irq_chip, &irq_data);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to add IRQ chip\n");
+
+ return devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO, rt5120_devs,
+ ARRAY_SIZE(rt5120_devs), NULL, 0,
+ regmap_irq_get_domain(irq_data));
+}
+
+static const struct of_device_id rt5120_device_match_table[] = {
+ { .compatible = "richtek,rt5120" },
+ {}
+};
+MODULE_DEVICE_TABLE(of, rt5120_device_match_table);
+
+static struct i2c_driver rt5120_driver = {
+ .driver = {
+ .name = "rt5120",
+ .of_match_table = rt5120_device_match_table,
+ },
+ .probe_new = rt5120_probe,
+};
+module_i2c_driver(rt5120_driver);
+
+MODULE_AUTHOR("ChiYuan Huang <cy_huang@richtek.com>");
+MODULE_DESCRIPTION("Richtek RT5120 I2C driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/mfd/sm501.c b/drivers/mfd/sm501.c
index bc0a2c38653e..3ac4508a6742 100644
--- a/drivers/mfd/sm501.c
+++ b/drivers/mfd/sm501.c
@@ -1720,7 +1720,12 @@ static struct platform_driver sm501_plat_driver = {
static int __init sm501_base_init(void)
{
- platform_driver_register(&sm501_plat_driver);
+ int ret;
+
+ ret = platform_driver_register(&sm501_plat_driver);
+ if (ret < 0)
+ return ret;
+
return pci_register_driver(&sm501_pci_driver);
}
diff --git a/drivers/mfd/stmpe.c b/drivers/mfd/stmpe.c
index aeb9ea55f97d..0c4f74197d3e 100644
--- a/drivers/mfd/stmpe.c
+++ b/drivers/mfd/stmpe.c
@@ -8,14 +8,13 @@
*/
#include <linux/err.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
#include <linux/export.h>
#include <linux/kernel.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/irqdomain.h>
#include <linux/of.h>
-#include <linux/of_gpio.h>
#include <linux/pm.h>
#include <linux/slab.h>
#include <linux/mfd/core.h>
@@ -30,17 +29,12 @@
* @irq_trigger: IRQ trigger to use for the interrupt to the host
* @autosleep: bool to enable/disable stmpe autosleep
* @autosleep_timeout: inactivity timeout in milliseconds for autosleep
- * @irq_over_gpio: true if gpio is used to get irq
- * @irq_gpio: gpio number over which irq will be requested (significant only if
- * irq_over_gpio is true)
*/
struct stmpe_platform_data {
int id;
unsigned int blocks;
unsigned int irq_trigger;
bool autosleep;
- bool irq_over_gpio;
- int irq_gpio;
int autosleep_timeout;
};
@@ -1349,32 +1343,22 @@ static void stmpe_of_probe(struct stmpe_platform_data *pdata,
if (pdata->id < 0)
pdata->id = -1;
- pdata->irq_gpio = of_get_named_gpio_flags(np, "irq-gpio", 0,
- &pdata->irq_trigger);
- if (gpio_is_valid(pdata->irq_gpio))
- pdata->irq_over_gpio = 1;
- else
- pdata->irq_trigger = IRQF_TRIGGER_NONE;
-
of_property_read_u32(np, "st,autosleep-timeout",
&pdata->autosleep_timeout);
pdata->autosleep = (pdata->autosleep_timeout) ? true : false;
for_each_available_child_of_node(np, child) {
- if (of_node_name_eq(child, "stmpe_gpio")) {
+ if (of_device_is_compatible(child, stmpe_gpio_cell.of_compatible))
pdata->blocks |= STMPE_BLOCK_GPIO;
- } else if (of_node_name_eq(child, "stmpe_keypad")) {
+ else if (of_device_is_compatible(child, stmpe_keypad_cell.of_compatible))
pdata->blocks |= STMPE_BLOCK_KEYPAD;
- } else if (of_node_name_eq(child, "stmpe_touchscreen")) {
+ else if (of_device_is_compatible(child, stmpe_ts_cell.of_compatible))
pdata->blocks |= STMPE_BLOCK_TOUCHSCREEN;
- } else if (of_node_name_eq(child, "stmpe_adc")) {
+ else if (of_device_is_compatible(child, stmpe_adc_cell.of_compatible))
pdata->blocks |= STMPE_BLOCK_ADC;
- } else if (of_node_name_eq(child, "stmpe_pwm")) {
+ else if (of_device_is_compatible(child, stmpe_pwm_cell.of_compatible))
pdata->blocks |= STMPE_BLOCK_PWM;
- } else if (of_node_name_eq(child, "stmpe_rotator")) {
- pdata->blocks |= STMPE_BLOCK_ROTATOR;
- }
}
}
@@ -1384,6 +1368,7 @@ int stmpe_probe(struct stmpe_client_info *ci, enum stmpe_partnum partnum)
struct stmpe_platform_data *pdata;
struct device_node *np = ci->dev->of_node;
struct stmpe *stmpe;
+ struct gpio_desc *irq_gpio;
int ret;
u32 val;
@@ -1437,18 +1422,20 @@ int stmpe_probe(struct stmpe_client_info *ci, enum stmpe_partnum partnum)
if (ci->init)
ci->init(stmpe);
- if (pdata->irq_over_gpio) {
- ret = devm_gpio_request_one(ci->dev, pdata->irq_gpio,
- GPIOF_DIR_IN, "stmpe");
- if (ret) {
- dev_err(stmpe->dev, "failed to request IRQ GPIO: %d\n",
- ret);
- return ret;
- }
+ irq_gpio = devm_gpiod_get_optional(ci->dev, "irq", GPIOD_ASIS);
+ ret = PTR_ERR_OR_ZERO(irq_gpio);
+ if (ret) {
+ dev_err(stmpe->dev, "failed to request IRQ GPIO: %d\n", ret);
+ return ret;
+ }
- stmpe->irq = gpio_to_irq(pdata->irq_gpio);
+ if (irq_gpio) {
+ stmpe->irq = gpiod_to_irq(irq_gpio);
+ pdata->irq_trigger = gpiod_is_active_low(irq_gpio) ?
+ IRQF_TRIGGER_LOW : IRQF_TRIGGER_HIGH;
} else {
stmpe->irq = ci->irq;
+ pdata->irq_trigger = IRQF_TRIGGER_NONE;
}
if (stmpe->irq < 0) {
diff --git a/drivers/mfd/syscon.c b/drivers/mfd/syscon.c
index bdb2ce7ff03b..9489e80e905a 100644
--- a/drivers/mfd/syscon.c
+++ b/drivers/mfd/syscon.c
@@ -66,14 +66,6 @@ static struct syscon *of_syscon_register(struct device_node *np, bool check_clk)
goto err_map;
}
- /* Parse the device's DT node for an endianness specification */
- if (of_property_read_bool(np, "big-endian"))
- syscon_config.val_format_endian = REGMAP_ENDIAN_BIG;
- else if (of_property_read_bool(np, "little-endian"))
- syscon_config.val_format_endian = REGMAP_ENDIAN_LITTLE;
- else if (of_property_read_bool(np, "native-endian"))
- syscon_config.val_format_endian = REGMAP_ENDIAN_NATIVE;
-
/*
* search for reg-io-width property in DT. If it is not provided,
* default to 4 bytes. regmap_init_mmio will return an error if values
diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
index 2679c41232e6..f6b4b9d94bbd 100644
--- a/drivers/mfd/twl-core.c
+++ b/drivers/mfd/twl-core.c
@@ -882,7 +882,7 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
* SR_I2C_SCL_CTRL_PU(bit 4)=0 and SR_I2C_SDA_CTRL_PU(bit 6)=0.
*
* Also, always enable SmartReflex bit as that's needed for omaps to
- * to do anything over I2C4 for voltage scaling even if SmartReflex
+ * do anything over I2C4 for voltage scaling even if SmartReflex
* is disabled. Without the SmartReflex bit omap sys_clkreq idle
* signal will never trigger for retention idle.
*/
diff --git a/drivers/mfd/twl4030-irq.c b/drivers/mfd/twl4030-irq.c
index 4f576f0160a9..87496c1cb8bc 100644
--- a/drivers/mfd/twl4030-irq.c
+++ b/drivers/mfd/twl4030-irq.c
@@ -14,6 +14,7 @@
* by syed khasim <x0khasim@ti.com>
*/
+#include <linux/device.h>
#include <linux/export.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig
index 1aa8323ad9f6..56e70a68679a 100644
--- a/drivers/power/supply/Kconfig
+++ b/drivers/power/supply/Kconfig
@@ -708,6 +708,12 @@ config CHARGER_BQ256XX
charge management and system power path management devices for single
cell Li-ion and Li-polymer batteries.
+config CHARGER_RK817
+ tristate "Rockchip RK817 PMIC Battery Charger"
+ depends on MFD_RK808
+ help
+ Say Y to include support for Rockchip RK817 Battery Charger.
+
config CHARGER_SMB347
tristate "Summit Microelectronics SMB3XX Battery Charger"
depends on I2C
diff --git a/drivers/power/supply/Makefile b/drivers/power/supply/Makefile
index 7f02f36aea55..3040a1de81b8 100644
--- a/drivers/power/supply/Makefile
+++ b/drivers/power/supply/Makefile
@@ -91,6 +91,7 @@ obj-$(CONFIG_CHARGER_BQ2515X) += bq2515x_charger.o
obj-$(CONFIG_CHARGER_BQ25890) += bq25890_charger.o
obj-$(CONFIG_CHARGER_BQ25980) += bq25980_charger.o
obj-$(CONFIG_CHARGER_BQ256XX) += bq256xx_charger.o
+obj-$(CONFIG_CHARGER_RK817) += rk817_charger.o
obj-$(CONFIG_CHARGER_SMB347) += smb347-charger.o
obj-$(CONFIG_CHARGER_TPS65090) += tps65090-charger.o
obj-$(CONFIG_CHARGER_TPS65217) += tps65217_charger.o
diff --git a/drivers/power/supply/rk817_charger.c b/drivers/power/supply/rk817_charger.c
new file mode 100644
index 000000000000..635f051b0821
--- /dev/null
+++ b/drivers/power/supply/rk817_charger.c
@@ -0,0 +1,1211 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Charger Driver for Rockchip rk817
+ *
+ * Copyright (c) 2021 Maya Matuszczyk <maccraft123mc@gmail.com>
+ *
+ * Authors: Maya Matuszczyk <maccraft123mc@gmail.com>
+ * Chris Morgan <macromorgan@hotmail.com>
+ */
+
+#include <asm/unaligned.h>
+#include <linux/devm-helpers.h>
+#include <linux/mfd/rk808.h>
+#include <linux/irq.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/power_supply.h>
+#include <linux/regmap.h>
+
+/* Charging statuses reported by hardware register */
+enum rk817_charge_status {
+ CHRG_OFF,
+ DEAD_CHRG,
+ TRICKLE_CHRG,
+ CC_OR_CV_CHRG,
+ CHARGE_FINISH,
+ USB_OVER_VOL,
+ BAT_TMP_ERR,
+ BAT_TIM_ERR,
+};
+
+/*
+ * Max charging current read to/written from hardware register.
+ * Note how highest value corresponding to 0x7 is the lowest
+ * current, this is per the datasheet.
+ */
+enum rk817_chg_cur {
+ CHG_1A,
+ CHG_1_5A,
+ CHG_2A,
+ CHG_2_5A,
+ CHG_2_75A,
+ CHG_3A,
+ CHG_3_5A,
+ CHG_0_5A,
+};
+
+struct rk817_charger {
+ struct device *dev;
+ struct rk808 *rk808;
+
+ struct power_supply *bat_ps;
+ struct power_supply *chg_ps;
+ bool plugged_in;
+ bool battery_present;
+
+ /*
+ * voltage_k and voltage_b values are used to calibrate the ADC
+ * voltage readings. While they are documented in the BSP kernel and
+ * datasheet as voltage_k and voltage_b, there is no further
+ * information explaining them in more detail.
+ */
+
+ uint32_t voltage_k;
+ uint32_t voltage_b;
+
+ /*
+ * soc - state of charge - like the BSP this is stored as a percentage,
+ * to the thousandth. BSP has a display state of charge (dsoc) and a
+ * remaining state of charge (rsoc). This value will be used for both
+ * purposes here so we don't do any fancy math to try and "smooth" the
+ * charge and just report it as it is. Note for example an soc of 100
+ * is stored as 100000, an soc of 50 is stored as 50000, etc.
+ */
+ int soc;
+
+ /*
+ * Capacity of battery when fully charged, equal or less than design
+ * capacity depending upon wear. BSP kernel saves to nvram in mAh,
+ * so this value is in mAh not the standard uAh.
+ */
+ int fcc_mah;
+
+ /*
+ * Calibrate the SOC on a fully charged battery, this way we can use
+ * the calibrated SOC value to correct for columb counter drift.
+ */
+ bool soc_cal;
+
+ /* Implementation specific immutable properties from device tree */
+ int res_div;
+ int sleep_enter_current_ua;
+ int sleep_filter_current_ua;
+ int bat_charge_full_design_uah;
+ int bat_voltage_min_design_uv;
+ int bat_voltage_max_design_uv;
+
+ /* Values updated periodically by driver for display. */
+ int charge_now_uah;
+ int volt_avg_uv;
+ int cur_avg_ua;
+ int max_chg_cur_ua;
+ int max_chg_volt_uv;
+ int charge_status;
+ int charger_input_volt_avg_uv;
+
+ /* Work queue to periodically update values. */
+ struct delayed_work work;
+};
+
+/* ADC coefficients extracted from BSP kernel */
+#define ADC_TO_CURRENT(adc_value, res_div) \
+ (adc_value * 172 / res_div)
+
+#define CURRENT_TO_ADC(current, samp_res) \
+ (current * samp_res / 172)
+
+#define CHARGE_TO_ADC(capacity, res_div) \
+ (capacity * res_div * 3600 / 172 * 1000)
+
+#define ADC_TO_CHARGE_UAH(adc_value, res_div) \
+ (adc_value / 3600 * 172 / res_div)
+
+static u8 rk817_chg_cur_to_reg(u32 chg_cur_ma)
+{
+ if (chg_cur_ma >= 3500)
+ return CHG_3_5A;
+ else if (chg_cur_ma >= 3000)
+ return CHG_3A;
+ else if (chg_cur_ma >= 2750)
+ return CHG_2_75A;
+ else if (chg_cur_ma >= 2500)
+ return CHG_2_5A;
+ else if (chg_cur_ma >= 2000)
+ return CHG_2A;
+ else if (chg_cur_ma >= 1500)
+ return CHG_1_5A;
+ else if (chg_cur_ma >= 1000)
+ return CHG_1A;
+ else if (chg_cur_ma >= 500)
+ return CHG_0_5A;
+ else
+ return -EINVAL;
+}
+
+static int rk817_chg_cur_from_reg(u8 reg)
+{
+ switch (reg) {
+ case CHG_0_5A:
+ return 500000;
+ case CHG_1A:
+ return 1000000;
+ case CHG_1_5A:
+ return 1500000;
+ case CHG_2A:
+ return 2000000;
+ case CHG_2_5A:
+ return 2500000;
+ case CHG_2_75A:
+ return 2750000;
+ case CHG_3A:
+ return 3000000;
+ case CHG_3_5A:
+ return 3500000;
+ default:
+ return -EINVAL;
+ }
+}
+
+static void rk817_bat_calib_vol(struct rk817_charger *charger)
+{
+ uint32_t vcalib0 = 0;
+ uint32_t vcalib1 = 0;
+ u8 bulk_reg[2];
+
+ /* calibrate voltage */
+ regmap_bulk_read(charger->rk808->regmap, RK817_GAS_GAUGE_VCALIB0_H,
+ bulk_reg, 2);
+ vcalib0 = get_unaligned_be16(bulk_reg);
+
+ regmap_bulk_read(charger->rk808->regmap, RK817_GAS_GAUGE_VCALIB1_H,
+ bulk_reg, 2);
+ vcalib1 = get_unaligned_be16(bulk_reg);
+
+ /* values were taken from BSP kernel */
+ charger->voltage_k = (4025 - 2300) * 1000 /
+ ((vcalib1 - vcalib0) ? (vcalib1 - vcalib0) : 1);
+ charger->voltage_b = 4025 - (charger->voltage_k * vcalib1) / 1000;
+}
+
+static void rk817_bat_calib_cur(struct rk817_charger *charger)
+{
+ u8 bulk_reg[2];
+
+ /* calibrate current */
+ regmap_bulk_read(charger->rk808->regmap, RK817_GAS_GAUGE_IOFFSET_H,
+ bulk_reg, 2);
+ regmap_bulk_write(charger->rk808->regmap, RK817_GAS_GAUGE_CAL_OFFSET_H,
+ bulk_reg, 2);
+}
+
+/*
+ * note that only the fcc_mah is really used by this driver, the other values
+ * are to ensure we can remain backwards compatible with the BSP kernel.
+ */
+static int rk817_record_battery_nvram_values(struct rk817_charger *charger)
+{
+ u8 bulk_reg[3];
+ int ret, rsoc;
+
+ /*
+ * write the soc value to the nvram location used by the BSP kernel
+ * for the dsoc value.
+ */
+ put_unaligned_le24(charger->soc, bulk_reg);
+ ret = regmap_bulk_write(charger->rk808->regmap, RK817_GAS_GAUGE_BAT_R1,
+ bulk_reg, 3);
+ if (ret < 0)
+ return ret;
+ /*
+ * write the remaining capacity in mah to the nvram location used by
+ * the BSP kernel for the rsoc value.
+ */
+ rsoc = (charger->soc * charger->fcc_mah) / 100000;
+ put_unaligned_le24(rsoc, bulk_reg);
+ ret = regmap_bulk_write(charger->rk808->regmap, RK817_GAS_GAUGE_DATA0,
+ bulk_reg, 3);
+ if (ret < 0)
+ return ret;
+ /* write the fcc_mah in mAh, just as the BSP kernel does. */
+ put_unaligned_le24(charger->fcc_mah, bulk_reg);
+ ret = regmap_bulk_write(charger->rk808->regmap, RK817_GAS_GAUGE_DATA3,
+ bulk_reg, 3);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static int rk817_bat_calib_cap(struct rk817_charger *charger)
+{
+ struct rk808 *rk808 = charger->rk808;
+ int tmp, charge_now, charge_now_adc, volt_avg;
+ u8 bulk_reg[4];
+
+ /* Calibrate the soc and fcc on a fully charged battery */
+
+ if (charger->charge_status == CHARGE_FINISH && (!charger->soc_cal)) {
+ /*
+ * soc should be 100000 and columb counter should show the full
+ * charge capacity. Note that if the device is unplugged for a
+ * period of several days the columb counter will have a large
+ * margin of error, so setting it back to the full charge on
+ * a completed charge cycle should correct this (my device was
+ * showing 33% battery after 3 days unplugged when it should
+ * have been closer to 95% based on voltage and charge
+ * current).
+ */
+
+ charger->soc = 100000;
+ charge_now_adc = CHARGE_TO_ADC(charger->fcc_mah,
+ charger->res_div);
+ put_unaligned_be32(charge_now_adc, bulk_reg);
+ regmap_bulk_write(rk808->regmap, RK817_GAS_GAUGE_Q_INIT_H3,
+ bulk_reg, 4);
+
+ charger->soc_cal = 1;
+ dev_dbg(charger->dev,
+ "Fully charged. SOC is %d, full capacity is %d\n",
+ charger->soc, charger->fcc_mah * 1000);
+ }
+
+ /*
+ * The columb counter can drift up slightly, so we should correct for
+ * it. But don't correct it until we're at 100% soc.
+ */
+ if (charger->charge_status == CHARGE_FINISH && charger->soc_cal) {
+ regmap_bulk_read(rk808->regmap, RK817_GAS_GAUGE_Q_PRES_H3,
+ bulk_reg, 4);
+ charge_now_adc = get_unaligned_be32(bulk_reg);
+ if (charge_now_adc < 0)
+ return charge_now_adc;
+ charge_now = ADC_TO_CHARGE_UAH(charge_now_adc,
+ charger->res_div);
+
+ /*
+ * Re-init columb counter with updated values to correct drift.
+ */
+ if (charge_now / 1000 > charger->fcc_mah) {
+ dev_dbg(charger->dev,
+ "Recalibrating columb counter to %d uah\n",
+ charge_now);
+ /*
+ * Order of operations matters here to ensure we keep
+ * enough precision until the last step to keep from
+ * making needless updates to columb counter.
+ */
+ charge_now_adc = CHARGE_TO_ADC(charger->fcc_mah,
+ charger->res_div);
+ put_unaligned_be32(charge_now_adc, bulk_reg);
+ regmap_bulk_write(rk808->regmap,
+ RK817_GAS_GAUGE_Q_INIT_H3,
+ bulk_reg, 4);
+ }
+ }
+
+ /*
+ * Calibrate the fully charged capacity when we previously had a full
+ * battery (soc_cal = 1) and are now empty (at or below minimum design
+ * voltage). If our columb counter is still positive, subtract that
+ * from our fcc value to get a calibrated fcc, and if our columb
+ * counter is negative add that to our fcc (but not to exceed our
+ * design capacity).
+ */
+ regmap_bulk_read(charger->rk808->regmap, RK817_GAS_GAUGE_BAT_VOL_H,
+ bulk_reg, 2);
+ tmp = get_unaligned_be16(bulk_reg);
+ volt_avg = (charger->voltage_k * tmp) + 1000 * charger->voltage_b;
+ if (volt_avg <= charger->bat_voltage_min_design_uv &&
+ charger->soc_cal) {
+ regmap_bulk_read(rk808->regmap, RK817_GAS_GAUGE_Q_PRES_H3,
+ bulk_reg, 4);
+ charge_now_adc = get_unaligned_be32(bulk_reg);
+ charge_now = ADC_TO_CHARGE_UAH(charge_now_adc,
+ charger->res_div);
+ /*
+ * Note, if charge_now is negative this will add it (what we
+ * want) and if it's positive this will subtract (also what
+ * we want).
+ */
+ charger->fcc_mah = charger->fcc_mah - (charge_now / 1000);
+
+ dev_dbg(charger->dev,
+ "Recalibrating full charge capacity to %d uah\n",
+ charger->fcc_mah * 1000);
+ }
+
+ rk817_record_battery_nvram_values(charger);
+
+ return 0;
+}
+
+static void rk817_read_props(struct rk817_charger *charger)
+{
+ int tmp, reg;
+ u8 bulk_reg[4];
+
+ /*
+ * Recalibrate voltage and current readings if we need to BSP does both
+ * on CUR_CALIB_UPD, ignoring VOL_CALIB_UPD. Curiously enough, both
+ * documentation and the BSP show that you perform an update if bit 7
+ * is 1, but you clear the status by writing a 1 to bit 7.
+ */
+ regmap_read(charger->rk808->regmap, RK817_GAS_GAUGE_ADC_CONFIG1, &reg);
+ if (reg & RK817_VOL_CUR_CALIB_UPD) {
+ rk817_bat_calib_cur(charger);
+ rk817_bat_calib_vol(charger);
+ regmap_write_bits(charger->rk808->regmap,
+ RK817_GAS_GAUGE_ADC_CONFIG1,
+ RK817_VOL_CUR_CALIB_UPD,
+ RK817_VOL_CUR_CALIB_UPD);
+ }
+
+ /* Update reported charge. */
+ regmap_bulk_read(charger->rk808->regmap, RK817_GAS_GAUGE_Q_PRES_H3,
+ bulk_reg, 4);
+ tmp = get_unaligned_be32(bulk_reg);
+ charger->charge_now_uah = ADC_TO_CHARGE_UAH(tmp, charger->res_div);
+ if (charger->charge_now_uah < 0)
+ charger->charge_now_uah = 0;
+ if (charger->charge_now_uah > charger->fcc_mah * 1000)
+ charger->charge_now_uah = charger->fcc_mah * 1000;
+
+ /* Update soc based on reported charge. */
+ charger->soc = charger->charge_now_uah * 100 / charger->fcc_mah;
+
+ /* Update reported voltage. */
+ regmap_bulk_read(charger->rk808->regmap, RK817_GAS_GAUGE_BAT_VOL_H,
+ bulk_reg, 2);
+ tmp = get_unaligned_be16(bulk_reg);
+ charger->volt_avg_uv = (charger->voltage_k * tmp) + 1000 *
+ charger->voltage_b;
+
+ /*
+ * Update reported current. Note value from registers is a signed 16
+ * bit int.
+ */
+ regmap_bulk_read(charger->rk808->regmap, RK817_GAS_GAUGE_BAT_CUR_H,
+ bulk_reg, 2);
+ tmp = (short int)get_unaligned_be16(bulk_reg);
+ charger->cur_avg_ua = ADC_TO_CURRENT(tmp, charger->res_div);
+
+ /*
+ * Update the max charge current. This value shouldn't change, but we
+ * can read it to report what the PMIC says it is instead of simply
+ * returning the default value.
+ */
+ regmap_read(charger->rk808->regmap, RK817_PMIC_CHRG_OUT, &reg);
+ charger->max_chg_cur_ua =
+ rk817_chg_cur_from_reg(reg & RK817_CHRG_CUR_SEL);
+
+ /*
+ * Update max charge voltage. Like the max charge current this value
+ * shouldn't change, but we can report what the PMIC says.
+ */
+ regmap_read(charger->rk808->regmap, RK817_PMIC_CHRG_OUT, &reg);
+ charger->max_chg_volt_uv = ((((reg & RK817_CHRG_VOL_SEL) >> 4) *
+ 50000) + 4100000);
+
+ /* Check if battery still present. */
+ regmap_read(charger->rk808->regmap, RK817_PMIC_CHRG_STS, &reg);
+ charger->battery_present = (reg & RK817_BAT_EXS);
+
+ /* Get which type of charge we are using (if any). */
+ regmap_read(charger->rk808->regmap, RK817_PMIC_CHRG_STS, &reg);
+ charger->charge_status = (reg >> 4) & 0x07;
+
+ /*
+ * Get charger input voltage. Note that on my example hardware (an
+ * Odroid Go Advance) the voltage of the power connector is measured
+ * on the register labelled USB in the datasheet; I don't know if this
+ * is how it is designed or just a quirk of the implementation. I
+ * believe this will also measure the voltage of the USB output when in
+ * OTG mode, if that is the case we may need to change this in the
+ * future to return 0 if the power supply status is offline (I can't
+ * test this with my current implementation. Also, when the voltage
+ * should be zero sometimes the ADC still shows a single bit (which
+ * would register as 20000uv). When this happens set it to 0.
+ */
+ regmap_bulk_read(charger->rk808->regmap, RK817_GAS_GAUGE_USB_VOL_H,
+ bulk_reg, 2);
+ reg = get_unaligned_be16(bulk_reg);
+ if (reg > 1) {
+ tmp = ((charger->voltage_k * reg / 1000 + charger->voltage_b) *
+ 60 / 46);
+ charger->charger_input_volt_avg_uv = tmp * 1000;
+ } else {
+ charger->charger_input_volt_avg_uv = 0;
+ }
+
+ /* Calibrate battery capacity and soc. */
+ rk817_bat_calib_cap(charger);
+}
+
+static int rk817_bat_get_prop(struct power_supply *ps,
+ enum power_supply_property prop,
+ union power_supply_propval *val)
+{
+ struct rk817_charger *charger = power_supply_get_drvdata(ps);
+
+ switch (prop) {
+ case POWER_SUPPLY_PROP_PRESENT:
+ val->intval = charger->battery_present;
+ break;
+ case POWER_SUPPLY_PROP_STATUS:
+ if (charger->cur_avg_ua < 0) {
+ val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
+ break;
+ }
+ switch (charger->charge_status) {
+ case CHRG_OFF:
+ val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
+ break;
+ /*
+ * Dead charge is documented, but not explained. I never
+ * observed it but assume it's a pre-charge for a dead
+ * battery.
+ */
+ case DEAD_CHRG:
+ case TRICKLE_CHRG:
+ case CC_OR_CV_CHRG:
+ val->intval = POWER_SUPPLY_STATUS_CHARGING;
+ break;
+ case CHARGE_FINISH:
+ val->intval = POWER_SUPPLY_STATUS_FULL;
+ break;
+ default:
+ val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
+ return -EINVAL;
+
+ }
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_TYPE:
+ switch (charger->charge_status) {
+ case CHRG_OFF:
+ case CHARGE_FINISH:
+ val->intval = POWER_SUPPLY_CHARGE_TYPE_NONE;
+ break;
+ case TRICKLE_CHRG:
+ val->intval = POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
+ break;
+ case DEAD_CHRG:
+ case CC_OR_CV_CHRG:
+ val->intval = POWER_SUPPLY_CHARGE_TYPE_STANDARD;
+ break;
+ default:
+ val->intval = POWER_SUPPLY_CHARGE_TYPE_UNKNOWN;
+ break;
+ }
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_FULL:
+ val->intval = charger->fcc_mah * 1000;
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
+ val->intval = charger->bat_charge_full_design_uah;
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_EMPTY_DESIGN:
+ val->intval = 0;
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_NOW:
+ val->intval = charger->charge_now_uah;
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
+ val->intval = charger->bat_voltage_min_design_uv;
+ break;
+ case POWER_SUPPLY_PROP_CAPACITY:
+ /* Add 500 so that values like 99999 are 100% not 99%. */
+ val->intval = (charger->soc + 500) / 1000;
+ if (val->intval > 100)
+ val->intval = 100;
+ if (val->intval < 0)
+ val->intval = 0;
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_AVG:
+ val->intval = charger->volt_avg_uv;
+ break;
+ case POWER_SUPPLY_PROP_CURRENT_AVG:
+ val->intval = charger->cur_avg_ua;
+ break;
+ case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
+ val->intval = charger->max_chg_cur_ua;
+ break;
+ case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX:
+ val->intval = charger->max_chg_volt_uv;
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
+ val->intval = charger->bat_voltage_max_design_uv;
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int rk817_chg_get_prop(struct power_supply *ps,
+ enum power_supply_property prop,
+ union power_supply_propval *val)
+{
+ struct rk817_charger *charger = power_supply_get_drvdata(ps);
+
+ switch (prop) {
+ case POWER_SUPPLY_PROP_ONLINE:
+ val->intval = charger->plugged_in;
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
+ /* max voltage from datasheet at 5.5v (default 5.0v) */
+ val->intval = 5500000;
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
+ /* min voltage from datasheet at 3.8v (default 5.0v) */
+ val->intval = 3800000;
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_AVG:
+ val->intval = charger->charger_input_volt_avg_uv;
+ break;
+ /*
+ * While it's possible that other implementations could use different
+ * USB types, the current implementation for this PMIC (the Odroid Go
+ * Advance) only uses a dedicated charging port with no rx/tx lines.
+ */
+ case POWER_SUPPLY_PROP_USB_TYPE:
+ val->intval = POWER_SUPPLY_USB_TYPE_DCP;
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+
+}
+
+static irqreturn_t rk817_plug_in_isr(int irq, void *cg)
+{
+ struct rk817_charger *charger;
+
+ charger = (struct rk817_charger *)cg;
+ charger->plugged_in = 1;
+ power_supply_changed(charger->chg_ps);
+ power_supply_changed(charger->bat_ps);
+ /* try to recalibrate capacity if we hit full charge. */
+ charger->soc_cal = 0;
+
+ rk817_read_props(charger);
+
+ dev_dbg(charger->dev, "Power Cord Inserted\n");
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t rk817_plug_out_isr(int irq, void *cg)
+{
+ struct rk817_charger *charger;
+ struct rk808 *rk808;
+
+ charger = (struct rk817_charger *)cg;
+ rk808 = charger->rk808;
+ charger->plugged_in = 0;
+ power_supply_changed(charger->bat_ps);
+ power_supply_changed(charger->chg_ps);
+
+ /*
+ * For some reason the bits of RK817_PMIC_CHRG_IN reset whenever the
+ * power cord is unplugged. This was not documented in the BSP kernel
+ * or the datasheet and only discovered by trial and error. Set minimum
+ * USB input voltage to 4.5v and enable USB voltage input limit.
+ */
+ regmap_write_bits(rk808->regmap, RK817_PMIC_CHRG_IN,
+ RK817_USB_VLIM_SEL, (0x05 << 4));
+ regmap_write_bits(rk808->regmap, RK817_PMIC_CHRG_IN, RK817_USB_VLIM_EN,
+ (0x01 << 7));
+
+ /*
+ * Set average USB input current limit to 1.5A and enable USB current
+ * input limit.
+ */
+ regmap_write_bits(rk808->regmap, RK817_PMIC_CHRG_IN,
+ RK817_USB_ILIM_SEL, 0x03);
+ regmap_write_bits(rk808->regmap, RK817_PMIC_CHRG_IN, RK817_USB_ILIM_EN,
+ (0x01 << 3));
+
+ rk817_read_props(charger);
+
+ dev_dbg(charger->dev, "Power Cord Removed\n");
+
+ return IRQ_HANDLED;
+}
+
+static enum power_supply_property rk817_bat_props[] = {
+ POWER_SUPPLY_PROP_PRESENT,
+ POWER_SUPPLY_PROP_STATUS,
+ POWER_SUPPLY_PROP_CHARGE_TYPE,
+ POWER_SUPPLY_PROP_CHARGE_FULL,
+ POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
+ POWER_SUPPLY_PROP_CHARGE_EMPTY_DESIGN,
+ POWER_SUPPLY_PROP_CHARGE_NOW,
+ POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX,
+ POWER_SUPPLY_PROP_VOLTAGE_AVG,
+ POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
+ POWER_SUPPLY_PROP_CURRENT_AVG,
+ POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
+ POWER_SUPPLY_PROP_CAPACITY,
+ POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
+};
+
+static enum power_supply_property rk817_chg_props[] = {
+ POWER_SUPPLY_PROP_ONLINE,
+ POWER_SUPPLY_PROP_USB_TYPE,
+ POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
+ POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
+ POWER_SUPPLY_PROP_VOLTAGE_AVG,
+};
+
+static enum power_supply_usb_type rk817_usb_type[] = {
+ POWER_SUPPLY_USB_TYPE_DCP,
+ POWER_SUPPLY_USB_TYPE_UNKNOWN,
+};
+
+static const struct power_supply_desc rk817_bat_desc = {
+ .name = "rk817-battery",
+ .type = POWER_SUPPLY_TYPE_BATTERY,
+ .properties = rk817_bat_props,
+ .num_properties = ARRAY_SIZE(rk817_bat_props),
+ .get_property = rk817_bat_get_prop,
+};
+
+static const struct power_supply_desc rk817_chg_desc = {
+ .name = "rk817-charger",
+ .type = POWER_SUPPLY_TYPE_USB,
+ .usb_types = rk817_usb_type,
+ .num_usb_types = ARRAY_SIZE(rk817_usb_type),
+ .properties = rk817_chg_props,
+ .num_properties = ARRAY_SIZE(rk817_chg_props),
+ .get_property = rk817_chg_get_prop,
+};
+
+static int rk817_read_battery_nvram_values(struct rk817_charger *charger)
+{
+ u8 bulk_reg[3];
+ int ret;
+
+ /* Read the nvram data for full charge capacity. */
+ ret = regmap_bulk_read(charger->rk808->regmap,
+ RK817_GAS_GAUGE_DATA3, bulk_reg, 3);
+ if (ret < 0)
+ return ret;
+ charger->fcc_mah = get_unaligned_le24(bulk_reg);
+
+ /*
+ * Sanity checking for values equal to zero or less than would be
+ * practical for this device (BSP Kernel assumes 500mAH or less) for
+ * practicality purposes. Also check if the value is too large and
+ * correct it.
+ */
+ if ((charger->fcc_mah < 500) ||
+ ((charger->fcc_mah * 1000) > charger->bat_charge_full_design_uah)) {
+ dev_info(charger->dev,
+ "Invalid NVRAM max charge, setting to %u uAH\n",
+ charger->bat_charge_full_design_uah);
+ charger->fcc_mah = charger->bat_charge_full_design_uah / 1000;
+ }
+
+ /*
+ * Read the nvram for state of charge. Sanity check for values greater
+ * than 100 (10000). If the value is off it should get corrected
+ * automatically when the voltage drops to the min (soc is 0) or when
+ * the battery is full (soc is 100).
+ */
+ ret = regmap_bulk_read(charger->rk808->regmap,
+ RK817_GAS_GAUGE_BAT_R1, bulk_reg, 3);
+ if (ret < 0)
+ return ret;
+ charger->soc = get_unaligned_le24(bulk_reg);
+ if (charger->soc > 10000)
+ charger->soc = 10000;
+
+ return 0;
+}
+
+static int
+rk817_read_or_set_full_charge_on_boot(struct rk817_charger *charger,
+ struct power_supply_battery_info *bat_info)
+{
+ struct rk808 *rk808 = charger->rk808;
+ u8 bulk_reg[4];
+ u32 boot_voltage, boot_charge_mah, tmp;
+ int ret, reg, off_time;
+ bool first_boot;
+
+ /*
+ * Check if the battery is uninitalized. If it is, the columb counter
+ * needs to be set up.
+ */
+ ret = regmap_read(rk808->regmap, RK817_GAS_GAUGE_GG_STS, &reg);
+ if (ret < 0)
+ return ret;
+ first_boot = reg & RK817_BAT_CON;
+ /*
+ * If the battery is uninitialized, use the poweron voltage and an ocv
+ * lookup to guess our charge. The number won't be very accurate until
+ * we hit either our minimum voltage (0%) or full charge (100%).
+ */
+ if (first_boot) {
+ regmap_bulk_read(rk808->regmap, RK817_GAS_GAUGE_PWRON_VOL_H,
+ bulk_reg, 2);
+ tmp = get_unaligned_be16(bulk_reg);
+ boot_voltage = (charger->voltage_k * tmp) +
+ 1000 * charger->voltage_b;
+ /*
+ * Since only implementation has no working thermistor, assume
+ * 20C for OCV lookup. If lookup fails, report error with OCV
+ * table.
+ */
+ charger->soc = power_supply_batinfo_ocv2cap(bat_info,
+ boot_voltage,
+ 20) * 1000;
+ if (charger->soc < 0)
+ charger->soc = 0;
+
+ /* Guess that full charge capacity is the design capacity */
+ charger->fcc_mah = charger->bat_charge_full_design_uah / 1000;
+ /*
+ * Set battery as "set up". BSP driver uses this value even
+ * though datasheet claims it's a read-only value.
+ */
+ regmap_write_bits(rk808->regmap, RK817_GAS_GAUGE_GG_STS,
+ RK817_BAT_CON, 0);
+ /* Save nvram values */
+ ret = rk817_record_battery_nvram_values(charger);
+ if (ret < 0)
+ return ret;
+ } else {
+ ret = rk817_read_battery_nvram_values(charger);
+ if (ret < 0)
+ return ret;
+
+ regmap_bulk_read(rk808->regmap, RK817_GAS_GAUGE_Q_PRES_H3,
+ bulk_reg, 4);
+ tmp = get_unaligned_be32(bulk_reg);
+ if (tmp < 0)
+ tmp = 0;
+ boot_charge_mah = ADC_TO_CHARGE_UAH(tmp,
+ charger->res_div) / 1000;
+ /*
+ * Check if the columb counter has been off for more than 300
+ * minutes as it tends to drift downward. If so, re-init soc
+ * with the boot voltage instead. Note the unit values for the
+ * OFF_CNT register appear to be in decaminutes and stops
+ * counting at 2550 (0xFF) minutes. BSP kernel used OCV, but
+ * for me occasionally that would show invalid values. Boot
+ * voltage is only accurate for me on first poweron (not
+ * reboots), but we shouldn't ever encounter an OFF_CNT more
+ * than 0 on a reboot anyway.
+ */
+ regmap_read(rk808->regmap, RK817_GAS_GAUGE_OFF_CNT, &off_time);
+ if (off_time >= 30) {
+ regmap_bulk_read(rk808->regmap,
+ RK817_GAS_GAUGE_PWRON_VOL_H,
+ bulk_reg, 2);
+ tmp = get_unaligned_be16(bulk_reg);
+ boot_voltage = (charger->voltage_k * tmp) +
+ 1000 * charger->voltage_b;
+ charger->soc =
+ power_supply_batinfo_ocv2cap(bat_info,
+ boot_voltage,
+ 20) * 1000;
+ } else {
+ charger->soc = (boot_charge_mah * 1000 * 100 /
+ charger->fcc_mah);
+ }
+ }
+
+ regmap_bulk_read(rk808->regmap, RK817_GAS_GAUGE_PWRON_VOL_H,
+ bulk_reg, 2);
+ tmp = get_unaligned_be16(bulk_reg);
+ boot_voltage = (charger->voltage_k * tmp) + 1000 * charger->voltage_b;
+ regmap_bulk_read(rk808->regmap, RK817_GAS_GAUGE_Q_PRES_H3,
+ bulk_reg, 4);
+ tmp = get_unaligned_be32(bulk_reg);
+ if (tmp < 0)
+ tmp = 0;
+ boot_charge_mah = ADC_TO_CHARGE_UAH(tmp, charger->res_div) / 1000;
+ regmap_bulk_read(rk808->regmap, RK817_GAS_GAUGE_OCV_VOL_H,
+ bulk_reg, 2);
+ tmp = get_unaligned_be16(bulk_reg);
+ boot_voltage = (charger->voltage_k * tmp) + 1000 * charger->voltage_b;
+
+ /*
+ * Now we have our full charge capacity and soc, init the columb
+ * counter.
+ */
+ boot_charge_mah = charger->soc * charger->fcc_mah / 100 / 1000;
+ if (boot_charge_mah > charger->fcc_mah)
+ boot_charge_mah = charger->fcc_mah;
+ tmp = CHARGE_TO_ADC(boot_charge_mah, charger->res_div);
+ put_unaligned_be32(tmp, bulk_reg);
+ ret = regmap_bulk_write(rk808->regmap, RK817_GAS_GAUGE_Q_INIT_H3,
+ bulk_reg, 4);
+ if (ret < 0)
+ return ret;
+
+ /* Set QMAX value to max design capacity. */
+ tmp = CHARGE_TO_ADC((charger->bat_charge_full_design_uah / 1000),
+ charger->res_div);
+ put_unaligned_be32(tmp, bulk_reg);
+ ret = regmap_bulk_write(rk808->regmap, RK817_GAS_GAUGE_Q_MAX_H3,
+ bulk_reg, 4);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static int rk817_battery_init(struct rk817_charger *charger,
+ struct power_supply_battery_info *bat_info)
+{
+ struct rk808 *rk808 = charger->rk808;
+ u32 tmp, max_chg_vol_mv, max_chg_cur_ma;
+ u8 max_chg_vol_reg, chg_term_i_reg, max_chg_cur_reg;
+ int ret, chg_term_ma;
+ u8 bulk_reg[2];
+
+ /* Get initial plug state */
+ regmap_read(rk808->regmap, RK817_SYS_STS, &tmp);
+ charger->plugged_in = (tmp & RK817_PLUG_IN_STS);
+
+ /*
+ * Turn on all ADC functions to measure battery, USB, and sys voltage,
+ * as well as batt temp. Note only tested implementation so far does
+ * not use a battery with a thermistor.
+ */
+ regmap_write(rk808->regmap, RK817_GAS_GAUGE_ADC_CONFIG0, 0xfc);
+
+ /*
+ * Set relax mode voltage sampling interval and ADC offset calibration
+ * interval to 8 minutes to mirror BSP kernel. Set voltage and current
+ * modes to average to mirror BSP kernel.
+ */
+ regmap_write(rk808->regmap, RK817_GAS_GAUGE_GG_CON, 0x04);
+
+ /* Calibrate voltage like the BSP does here. */
+ rk817_bat_calib_vol(charger);
+
+ /* Write relax threshold, derived from sleep enter current. */
+ tmp = CURRENT_TO_ADC(charger->sleep_enter_current_ua,
+ charger->res_div);
+ put_unaligned_be16(tmp, bulk_reg);
+ regmap_bulk_write(rk808->regmap, RK817_GAS_GAUGE_RELAX_THRE_H,
+ bulk_reg, 2);
+
+ /* Write sleep sample current, derived from sleep filter current. */
+ tmp = CURRENT_TO_ADC(charger->sleep_filter_current_ua,
+ charger->res_div);
+ put_unaligned_be16(tmp, bulk_reg);
+ regmap_bulk_write(rk808->regmap, RK817_GAS_GAUGE_SLEEP_CON_SAMP_CUR_H,
+ bulk_reg, 2);
+
+ /* Restart battery relax voltage */
+ regmap_write_bits(rk808->regmap, RK817_GAS_GAUGE_GG_STS,
+ RK817_RELAX_VOL_UPD, (0x0 << 2));
+
+ /*
+ * Set OCV Threshold Voltage to 127.5mV. This was hard coded like this
+ * in the BSP.
+ */
+ regmap_write(rk808->regmap, RK817_GAS_GAUGE_OCV_THRE_VOL, 0xff);
+
+ /*
+ * Set maximum charging voltage to battery max voltage. Trying to be
+ * incredibly safe with these value, as setting them wrong could
+ * overcharge the battery, which would be very bad.
+ */
+ max_chg_vol_mv = bat_info->constant_charge_voltage_max_uv / 1000;
+ max_chg_cur_ma = bat_info->constant_charge_current_max_ua / 1000;
+
+ if (max_chg_vol_mv < 4100) {
+ return dev_err_probe(charger->dev, -EINVAL,
+ "invalid max charger voltage, value %u unsupported\n",
+ max_chg_vol_mv * 1000);
+ }
+ if (max_chg_vol_mv > 4450) {
+ dev_info(charger->dev,
+ "Setting max charge voltage to 4450000uv\n");
+ max_chg_vol_mv = 4450;
+ }
+
+ if (max_chg_cur_ma < 500) {
+ return dev_err_probe(charger->dev, -EINVAL,
+ "invalid max charger current, value %u unsupported\n",
+ max_chg_cur_ma * 1000);
+ }
+ if (max_chg_cur_ma > 3500)
+ dev_info(charger->dev,
+ "Setting max charge current to 3500000ua\n");
+
+ /*
+ * Now that the values are sanity checked, if we subtract 4100 from the
+ * max voltage and divide by 50, we conviently get the exact value for
+ * the registers, which are 4.1v, 4.15v, 4.2v, 4.25v, 4.3v, 4.35v,
+ * 4.4v, and 4.45v; these correspond to values 0x00 through 0x07.
+ */
+ max_chg_vol_reg = (max_chg_vol_mv - 4100) / 50;
+
+ max_chg_cur_reg = rk817_chg_cur_to_reg(max_chg_cur_ma);
+
+ if (max_chg_vol_reg < 0 || max_chg_vol_reg > 7) {
+ return dev_err_probe(charger->dev, -EINVAL,
+ "invalid max charger voltage, value %u unsupported\n",
+ max_chg_vol_mv * 1000);
+ }
+ if (max_chg_cur_reg < 0 || max_chg_cur_reg > 7) {
+ return dev_err_probe(charger->dev, -EINVAL,
+ "invalid max charger current, value %u unsupported\n",
+ max_chg_cur_ma * 1000);
+ }
+
+ /*
+ * Write the values to the registers, and deliver an emergency warning
+ * in the event they are not written correctly.
+ */
+ ret = regmap_write_bits(rk808->regmap, RK817_PMIC_CHRG_OUT,
+ RK817_CHRG_VOL_SEL, (max_chg_vol_reg << 4));
+ if (ret) {
+ dev_emerg(charger->dev,
+ "Danger, unable to set max charger voltage: %u\n",
+ ret);
+ }
+
+ ret = regmap_write_bits(rk808->regmap, RK817_PMIC_CHRG_OUT,
+ RK817_CHRG_CUR_SEL, max_chg_cur_reg);
+ if (ret) {
+ dev_emerg(charger->dev,
+ "Danger, unable to set max charger current: %u\n",
+ ret);
+ }
+
+ /* Set charge finishing mode to analog */
+ regmap_write_bits(rk808->regmap, RK817_PMIC_CHRG_TERM,
+ RK817_CHRG_TERM_ANA_DIG, (0x0 << 2));
+
+ /*
+ * Set charge finish current, warn if value not in range and keep
+ * default.
+ */
+ chg_term_ma = bat_info->charge_term_current_ua / 1000;
+ if (chg_term_ma < 150 || chg_term_ma > 400) {
+ dev_warn(charger->dev,
+ "Invalid charge termination %u, keeping default\n",
+ chg_term_ma * 1000);
+ chg_term_ma = 200;
+ }
+
+ /*
+ * Values of 150ma, 200ma, 300ma, and 400ma correspond to 00, 01, 10,
+ * and 11.
+ */
+ chg_term_i_reg = (chg_term_ma - 100) / 100;
+ regmap_write_bits(rk808->regmap, RK817_PMIC_CHRG_TERM,
+ RK817_CHRG_TERM_ANA_SEL, chg_term_i_reg);
+
+ ret = rk817_read_or_set_full_charge_on_boot(charger, bat_info);
+ if (ret < 0)
+ return ret;
+
+ /*
+ * Set minimum USB input voltage to 4.5v and enable USB voltage input
+ * limit.
+ */
+ regmap_write_bits(rk808->regmap, RK817_PMIC_CHRG_IN,
+ RK817_USB_VLIM_SEL, (0x05 << 4));
+ regmap_write_bits(rk808->regmap, RK817_PMIC_CHRG_IN, RK817_USB_VLIM_EN,
+ (0x01 << 7));
+
+ /*
+ * Set average USB input current limit to 1.5A and enable USB current
+ * input limit.
+ */
+ regmap_write_bits(rk808->regmap, RK817_PMIC_CHRG_IN,
+ RK817_USB_ILIM_SEL, 0x03);
+ regmap_write_bits(rk808->regmap, RK817_PMIC_CHRG_IN, RK817_USB_ILIM_EN,
+ (0x01 << 3));
+
+ return 0;
+}
+
+static void rk817_charging_monitor(struct work_struct *work)
+{
+ struct rk817_charger *charger;
+
+ charger = container_of(work, struct rk817_charger, work.work);
+
+ rk817_read_props(charger);
+
+ /* Run every 8 seconds like the BSP driver did. */
+ queue_delayed_work(system_wq, &charger->work, msecs_to_jiffies(8000));
+}
+
+static int rk817_charger_probe(struct platform_device *pdev)
+{
+ struct rk808 *rk808 = dev_get_drvdata(pdev->dev.parent);
+ struct rk817_charger *charger;
+ struct device_node *node;
+ struct power_supply_battery_info *bat_info;
+ struct device *dev = &pdev->dev;
+ struct power_supply_config pscfg = {};
+ int plugin_irq, plugout_irq;
+ int of_value;
+ int ret;
+
+ node = of_get_child_by_name(dev->parent->of_node, "charger");
+ if (!node)
+ return -ENODEV;
+
+ charger = devm_kzalloc(&pdev->dev, sizeof(*charger), GFP_KERNEL);
+ if (!charger)
+ return -ENOMEM;
+
+ charger->rk808 = rk808;
+
+ charger->dev = &pdev->dev;
+ platform_set_drvdata(pdev, charger);
+
+ rk817_bat_calib_vol(charger);
+
+ pscfg.drv_data = charger;
+ pscfg.of_node = node;
+
+ /*
+ * Get sample resistor value. Note only values of 10000 or 20000
+ * microohms are allowed. Schematic for my test implementation (an
+ * Odroid Go Advance) shows a 10 milliohm resistor for reference.
+ */
+ ret = of_property_read_u32(node, "rockchip,resistor-sense-micro-ohms",
+ &of_value);
+ if (ret < 0) {
+ return dev_err_probe(dev, ret,
+ "Error reading sample resistor value\n");
+ }
+ /*
+ * Store as a 1 or a 2, since all we really use the value for is as a
+ * divisor in some calculations.
+ */
+ charger->res_div = (of_value == 20000) ? 2 : 1;
+
+ /*
+ * Get sleep enter current value. Not sure what this value is for
+ * other than to help calibrate the relax threshold.
+ */
+ ret = of_property_read_u32(node,
+ "rockchip,sleep-enter-current-microamp",
+ &of_value);
+ if (ret < 0) {
+ return dev_err_probe(dev, ret,
+ "Error reading sleep enter cur value\n");
+ }
+ charger->sleep_enter_current_ua = of_value;
+
+ /* Get sleep filter current value */
+ ret = of_property_read_u32(node,
+ "rockchip,sleep-filter-current-microamp",
+ &of_value);
+ if (ret < 0) {
+ return dev_err_probe(dev, ret,
+ "Error reading sleep filter cur value\n");
+ }
+
+ charger->sleep_filter_current_ua = of_value;
+
+ charger->bat_ps = devm_power_supply_register(&pdev->dev,
+ &rk817_bat_desc, &pscfg);
+
+ charger->chg_ps = devm_power_supply_register(&pdev->dev,
+ &rk817_chg_desc, &pscfg);
+
+ if (IS_ERR(charger->chg_ps))
+ return dev_err_probe(dev, -EINVAL,
+ "Battery failed to probe\n");
+
+ if (IS_ERR(charger->chg_ps))
+ return dev_err_probe(dev, -EINVAL,
+ "Charger failed to probe\n");
+
+ ret = power_supply_get_battery_info(charger->bat_ps,
+ &bat_info);
+ if (ret) {
+ return dev_err_probe(dev, ret,
+ "Unable to get battery info: %d\n", ret);
+ }
+
+ if ((bat_info->charge_full_design_uah <= 0) ||
+ (bat_info->voltage_min_design_uv <= 0) ||
+ (bat_info->voltage_max_design_uv <= 0) ||
+ (bat_info->constant_charge_voltage_max_uv <= 0) ||
+ (bat_info->constant_charge_current_max_ua <= 0) ||
+ (bat_info->charge_term_current_ua <= 0)) {
+ return dev_err_probe(dev, -EINVAL,
+ "Required bat info missing or invalid\n");
+ }
+
+ charger->bat_charge_full_design_uah = bat_info->charge_full_design_uah;
+ charger->bat_voltage_min_design_uv = bat_info->voltage_min_design_uv;
+ charger->bat_voltage_max_design_uv = bat_info->voltage_max_design_uv;
+
+ /*
+ * Has to run after power_supply_get_battery_info as it depends on some
+ * values discovered from that routine.
+ */
+ ret = rk817_battery_init(charger, bat_info);
+ if (ret)
+ return ret;
+
+ power_supply_put_battery_info(charger->bat_ps, bat_info);
+
+ plugin_irq = platform_get_irq(pdev, 0);
+ if (plugin_irq < 0)
+ return plugin_irq;
+
+ plugout_irq = platform_get_irq(pdev, 1);
+ if (plugout_irq < 0)
+ return plugout_irq;
+
+ ret = devm_request_threaded_irq(charger->dev, plugin_irq, NULL,
+ rk817_plug_in_isr,
+ IRQF_TRIGGER_RISING | IRQF_ONESHOT,
+ "rk817_plug_in", charger);
+ if (ret) {
+ return dev_err_probe(&pdev->dev, ret,
+ "plug_in_irq request failed!\n");
+ }
+
+ ret = devm_request_threaded_irq(charger->dev, plugout_irq, NULL,
+ rk817_plug_out_isr,
+ IRQF_TRIGGER_RISING | IRQF_ONESHOT,
+ "rk817_plug_out", charger);
+ if (ret) {
+ return dev_err_probe(&pdev->dev, ret,
+ "plug_out_irq request failed!\n");
+ }
+
+ ret = devm_delayed_work_autocancel(&pdev->dev, &charger->work,
+ rk817_charging_monitor);
+ if (ret)
+ return ret;
+
+ /* Force the first update immediately. */
+ mod_delayed_work(system_wq, &charger->work, 0);
+
+ return 0;
+}
+
+
+static struct platform_driver rk817_charger_driver = {
+ .probe = rk817_charger_probe,
+ .driver = {
+ .name = "rk817-charger",
+ },
+};
+module_platform_driver(rk817_charger_driver);
+
+MODULE_DESCRIPTION("Battery power supply driver for RK817 PMIC");
+MODULE_AUTHOR("Maya Matuszczyk <maccraft123mc@gmail.com>");
+MODULE_AUTHOR("Chris Morgan <macromorgan@hotmail.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index d663ab9670fe..070e4403c6c2 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -1282,6 +1282,7 @@ config REGULATOR_STW481X_VMMC
config REGULATOR_SY7636A
tristate "Silergy SY7636A voltage regulator"
+ depends on MFD_SY7636A
help
This driver supports Silergy SY3686A voltage regulator.
diff --git a/include/dt-bindings/iio/adc/mediatek,mt6370_adc.h b/include/dt-bindings/iio/adc/mediatek,mt6370_adc.h
new file mode 100644
index 000000000000..6ee725547763
--- /dev/null
+++ b/include/dt-bindings/iio/adc/mediatek,mt6370_adc.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause */
+
+#ifndef __DT_BINDINGS_MEDIATEK_MT6370_ADC_H__
+#define __DT_BINDINGS_MEDIATEK_MT6370_ADC_H__
+
+/* ADC Channel Index */
+#define MT6370_CHAN_VBUSDIV5 0
+#define MT6370_CHAN_VBUSDIV2 1
+#define MT6370_CHAN_VSYS 2
+#define MT6370_CHAN_VBAT 3
+#define MT6370_CHAN_TS_BAT 4
+#define MT6370_CHAN_IBUS 5
+#define MT6370_CHAN_IBAT 6
+#define MT6370_CHAN_CHG_VDDP 7
+#define MT6370_CHAN_TEMP_JC 8
+#define MT6370_CHAN_MAX 9
+
+#endif
diff --git a/include/linux/htcpld.h b/include/linux/htcpld.h
index 842fce69ac06..5f8ac9b1d724 100644
--- a/include/linux/htcpld.h
+++ b/include/linux/htcpld.h
@@ -13,8 +13,6 @@ struct htcpld_chip_platform_data {
};
struct htcpld_core_platform_data {
- unsigned int int_reset_gpio_hi;
- unsigned int int_reset_gpio_lo;
unsigned int i2c_adapter_id;
struct htcpld_chip_platform_data *chip;
diff --git a/include/linux/mfd/rk808.h b/include/linux/mfd/rk808.h
index 58602032e642..9af1f3105f80 100644
--- a/include/linux/mfd/rk808.h
+++ b/include/linux/mfd/rk808.h
@@ -519,6 +519,77 @@ enum rk809_reg_id {
#define MIC_DIFF_DIS (0x0 << 7)
#define MIC_DIFF_EN (0x1 << 7)
+/* RK817 Battery Registers */
+#define RK817_GAS_GAUGE_ADC_CONFIG0 0x50
+#define RK817_GG_EN (0x1 << 7)
+#define RK817_SYS_VOL_ADC_EN (0x1 << 6)
+#define RK817_TS_ADC_EN (0x1 << 5)
+#define RK817_USB_VOL_ADC_EN (0x1 << 4)
+#define RK817_BAT_VOL_ADC_EN (0x1 << 3)
+#define RK817_BAT_CUR_ADC_EN (0x1 << 2)
+
+#define RK817_GAS_GAUGE_ADC_CONFIG1 0x55
+
+#define RK817_VOL_CUR_CALIB_UPD BIT(7)
+
+#define RK817_GAS_GAUGE_GG_CON 0x56
+#define RK817_GAS_GAUGE_GG_STS 0x57
+
+#define RK817_BAT_CON (0x1 << 4)
+#define RK817_RELAX_VOL_UPD (0x3 << 2)
+#define RK817_RELAX_STS (0x1 << 1)
+
+#define RK817_GAS_GAUGE_RELAX_THRE_H 0x58
+#define RK817_GAS_GAUGE_RELAX_THRE_L 0x59
+#define RK817_GAS_GAUGE_OCV_THRE_VOL 0x62
+#define RK817_GAS_GAUGE_OCV_VOL_H 0x63
+#define RK817_GAS_GAUGE_OCV_VOL_L 0x64
+#define RK817_GAS_GAUGE_PWRON_VOL_H 0x6b
+#define RK817_GAS_GAUGE_PWRON_VOL_L 0x6c
+#define RK817_GAS_GAUGE_PWRON_CUR_H 0x6d
+#define RK817_GAS_GAUGE_PWRON_CUR_L 0x6e
+#define RK817_GAS_GAUGE_OFF_CNT 0x6f
+#define RK817_GAS_GAUGE_Q_INIT_H3 0x70
+#define RK817_GAS_GAUGE_Q_INIT_H2 0x71
+#define RK817_GAS_GAUGE_Q_INIT_L1 0x72
+#define RK817_GAS_GAUGE_Q_INIT_L0 0x73
+#define RK817_GAS_GAUGE_Q_PRES_H3 0x74
+#define RK817_GAS_GAUGE_Q_PRES_H2 0x75
+#define RK817_GAS_GAUGE_Q_PRES_L1 0x76
+#define RK817_GAS_GAUGE_Q_PRES_L0 0x77
+#define RK817_GAS_GAUGE_BAT_VOL_H 0x78
+#define RK817_GAS_GAUGE_BAT_VOL_L 0x79
+#define RK817_GAS_GAUGE_BAT_CUR_H 0x7a
+#define RK817_GAS_GAUGE_BAT_CUR_L 0x7b
+#define RK817_GAS_GAUGE_USB_VOL_H 0x7e
+#define RK817_GAS_GAUGE_USB_VOL_L 0x7f
+#define RK817_GAS_GAUGE_SYS_VOL_H 0x80
+#define RK817_GAS_GAUGE_SYS_VOL_L 0x81
+#define RK817_GAS_GAUGE_Q_MAX_H3 0x82
+#define RK817_GAS_GAUGE_Q_MAX_H2 0x83
+#define RK817_GAS_GAUGE_Q_MAX_L1 0x84
+#define RK817_GAS_GAUGE_Q_MAX_L0 0x85
+#define RK817_GAS_GAUGE_SLEEP_CON_SAMP_CUR_H 0x8f
+#define RK817_GAS_GAUGE_SLEEP_CON_SAMP_CUR_L 0x90
+#define RK817_GAS_GAUGE_CAL_OFFSET_H 0x91
+#define RK817_GAS_GAUGE_CAL_OFFSET_L 0x92
+#define RK817_GAS_GAUGE_VCALIB0_H 0x93
+#define RK817_GAS_GAUGE_VCALIB0_L 0x94
+#define RK817_GAS_GAUGE_VCALIB1_H 0x95
+#define RK817_GAS_GAUGE_VCALIB1_L 0x96
+#define RK817_GAS_GAUGE_IOFFSET_H 0x97
+#define RK817_GAS_GAUGE_IOFFSET_L 0x98
+#define RK817_GAS_GAUGE_BAT_R1 0x9a
+#define RK817_GAS_GAUGE_BAT_R2 0x9b
+#define RK817_GAS_GAUGE_BAT_R3 0x9c
+#define RK817_GAS_GAUGE_DATA0 0x9d
+#define RK817_GAS_GAUGE_DATA1 0x9e
+#define RK817_GAS_GAUGE_DATA2 0x9f
+#define RK817_GAS_GAUGE_DATA3 0xa0
+#define RK817_GAS_GAUGE_DATA4 0xa1
+#define RK817_GAS_GAUGE_DATA5 0xa2
+#define RK817_GAS_GAUGE_CUR_ADC_K0 0xb0
+
#define RK817_POWER_EN_REG(i) (0xb1 + (i))
#define RK817_POWER_SLP_EN_REG(i) (0xb5 + (i))
@@ -544,10 +615,30 @@ enum rk809_reg_id {
#define RK817_LDO_ON_VSEL_REG(idx) (0xcc + (idx) * 2)
#define RK817_BOOST_OTG_CFG (0xde)
+#define RK817_PMIC_CHRG_OUT 0xe4
+#define RK817_CHRG_VOL_SEL (0x07 << 4)
+#define RK817_CHRG_CUR_SEL (0x07 << 0)
+
+#define RK817_PMIC_CHRG_IN 0xe5
+#define RK817_USB_VLIM_EN (0x01 << 7)
+#define RK817_USB_VLIM_SEL (0x07 << 4)
+#define RK817_USB_ILIM_EN (0x01 << 3)
+#define RK817_USB_ILIM_SEL (0x07 << 0)
+#define RK817_PMIC_CHRG_TERM 0xe6
+#define RK817_CHRG_TERM_ANA_DIG (0x01 << 2)
+#define RK817_CHRG_TERM_ANA_SEL (0x03 << 0)
+#define RK817_CHRG_EN (0x01 << 6)
+
+#define RK817_PMIC_CHRG_STS 0xeb
+#define RK817_BAT_EXS BIT(7)
+#define RK817_CHG_STS (0x07 << 4)
+
#define RK817_ID_MSB 0xed
#define RK817_ID_LSB 0xee
#define RK817_SYS_STS 0xf0
+#define RK817_PLUG_IN_STS (0x1 << 6)
+
#define RK817_SYS_CFG(i) (0xf1 + (i))
#define RK817_ON_SOURCE_REG 0xf5