summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2023-05-02 10:41:31 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2023-05-02 10:41:31 -0700
commit3af49062b0115b55a54615109172b44f618daf97 (patch)
tree54bc04f20c95dc27362978c04e7d00e2399f9904
parentc5eb8bf76718cf2e2f36aac216a99014f00927de (diff)
parent9e9ff39243ea8795a4833708613f884b39dc91f9 (diff)
downloadlinux-stable-3af49062b0115b55a54615109172b44f618daf97.tar.gz
linux-stable-3af49062b0115b55a54615109172b44f618daf97.tar.bz2
linux-stable-3af49062b0115b55a54615109172b44f618daf97.zip
Merge tag 'mfd-next-6.4' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd
Pull MFD updates from Lee Jones: "New Drivers: - Add support for Renesas RZ/G2L MTU3 New Device Support: - Add support for Lenovo Yoga Book X90F to Intel CHT WC - Add support for MAX5970 and MAX5978 to Simple MFD (I2C) - Add support for Meteor Lake PCH-S LPSS PCI to Intel LPSS PCI - Add support for AXP15060 PMIC to X-Powers PMIC collection Remove Device Support: - Remove support for Samsung 5M8751 and S5M8763 PMIC devices New Functionality: - Convert deprecated QCOM IRQ Chip to config registers - Add support for 32-bit address spaces to Renesas SMUs Fix-ups: - Make use of APIs / MACROs designed to simplify and demystify - Add / improve Device Tree bindings - Memory saving struct layout optimisations - Remove old / deprecated functionality - Factor out unassigned register addresses from ranges - Trivial: Spelling fixes, renames and coding style fixes - Rid 'defined but not used' warnings - Remove ineffective casts and pointer stubs Bug Fixes: - Fix incorrectly non-inverted mask/unmask IRQs on QCOM platforms - Remove MODULE_*() helpers from non-tristate drivers - Do not attempt to use out-of-range memory addresses associated with io_base - Provide missing export helpers - Fix remap bulk read optimisation fallout - Fix memory leak issues in error paths" * tag 'mfd-next-6.4' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd: (88 commits) dt-bindings: mfd: ti,j721e-system-controller: Add SoC chip ID leds: bd2606mvv: Driver for the Rohm 6 Channel i2c LED driver dt-bindings: mfd: qcom,spmi-pmic: Document flash LED controller dt-bindings: mfd: x-powers,axp152: Document the AXP15060 variant mfd: axp20x: Add support for AXP15060 PMIC dt-bindings: mfd: x-powers,axp152: Document the AXP313a variant counter: rz-mtu3-cnt: Unlock on error in rz_mtu3_count_ceiling_write() dt-bindings: mfd: dlg,da9063: Document voltage monitoring dt-bindings: mfd: stm32: Remove unnecessary blank lines dt-bindings: mfd: qcom,spmi-pmic: Use generic ADC node name in examples dt-bindings: mfd: syscon: Add nuvoton,ma35d1-sys compatible MAINTAINERS: Add entries for Renesas RZ/G2L MTU3a counter driver counter: Add Renesas RZ/G2L MTU3a counter driver Documentation: ABI: sysfs-bus-counter: add cascade_counts_enable and external_input_phase_clock_select mfd: Add Renesas RZ/G2L MTU3a core driver dt-bindings: timer: Document RZ/G2L MTU3a bindings mfd: rsmu_i2c: Convert to i2c's .probe_new() again mfd: intel-lpss: Add Intel Meteor Lake PCH-S LPSS PCI IDs mfd: dln2: Fix memory leak in dln2_probe() mfd: axp20x: Fix axp288 writable-ranges ...
-rw-r--r--Documentation/ABI/testing/sysfs-bus-counter32
-rw-r--r--Documentation/devicetree/bindings/mfd/canaan,k210-sysctl.yaml6
-rw-r--r--Documentation/devicetree/bindings/mfd/google,cros-ec.yaml22
-rw-r--r--Documentation/devicetree/bindings/mfd/hisilicon,hi6421-spmi-pmic.yaml2
-rw-r--r--Documentation/devicetree/bindings/mfd/maxim,max5970.yaml151
-rw-r--r--Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml15
-rw-r--r--Documentation/devicetree/bindings/mfd/qcom,tcsr.yaml4
-rw-r--r--Documentation/devicetree/bindings/mfd/qcom-pm8xxx.yaml2
-rw-r--r--Documentation/devicetree/bindings/mfd/rohm,bd71815-pmic.yaml2
-rw-r--r--Documentation/devicetree/bindings/mfd/rohm,bd71828-pmic.yaml2
-rw-r--r--Documentation/devicetree/bindings/mfd/syscon.yaml2
-rw-r--r--Documentation/devicetree/bindings/mfd/ti,j721e-system-controller.yaml11
-rw-r--r--Documentation/devicetree/bindings/mfd/ti,nspire-misc.yaml51
-rw-r--r--Documentation/devicetree/bindings/mfd/wlf,arizona.yaml2
-rw-r--r--Documentation/devicetree/bindings/mfd/x-powers,ac100.yaml4
-rw-r--r--Documentation/devicetree/bindings/mfd/x-powers,axp152.yaml32
-rw-r--r--Documentation/devicetree/bindings/mfd/xylon,logicvc.yaml4
-rw-r--r--Documentation/devicetree/bindings/timer/renesas,rz-mtu3.yaml302
-rw-r--r--MAINTAINERS8
-rw-r--r--drivers/counter/Kconfig11
-rw-r--r--drivers/counter/Makefile1
-rw-r--r--drivers/counter/rz-mtu3-cnt.c906
-rw-r--r--drivers/gpio/Kconfig12
-rw-r--r--drivers/gpio/Makefile1
-rw-r--r--drivers/gpio/gpio-ljca.c454
-rw-r--r--drivers/mfd/88pm860x-core.c4
-rw-r--r--drivers/mfd/Kconfig23
-rw-r--r--drivers/mfd/Makefile1
-rw-r--r--drivers/mfd/arizona-i2c.c1
-rw-r--r--drivers/mfd/arizona-spi.c1
-rw-r--r--drivers/mfd/atc260x-i2c.c2
-rw-r--r--drivers/mfd/atmel-flexcom.c4
-rw-r--r--drivers/mfd/atmel-smc.c2
-rw-r--r--drivers/mfd/axp20x-i2c.c2
-rw-r--r--drivers/mfd/axp20x.c108
-rw-r--r--drivers/mfd/bcm2835-pm.c3
-rw-r--r--drivers/mfd/da903x.c1
-rw-r--r--drivers/mfd/da9052-core.c1
-rw-r--r--drivers/mfd/da9052-i2c.c1
-rw-r--r--drivers/mfd/da9052-spi.c1
-rw-r--r--drivers/mfd/da9055-core.c1
-rw-r--r--drivers/mfd/da9055-i2c.c1
-rw-r--r--drivers/mfd/da9062-core.c176
-rw-r--r--drivers/mfd/dln2.c1
-rw-r--r--drivers/mfd/ezx-pcap.c1
-rw-r--r--drivers/mfd/hi6421-pmic-core.c4
-rw-r--r--drivers/mfd/intel-lpss-pci.c15
-rw-r--r--drivers/mfd/intel_soc_pmic_chtwc.c14
-rw-r--r--drivers/mfd/intel_soc_pmic_crc.c1
-rw-r--r--drivers/mfd/ipaq-micro.c4
-rw-r--r--drivers/mfd/khadas-mcu.c2
-rw-r--r--drivers/mfd/lp8788.c1
-rw-r--r--drivers/mfd/mfd-core.c26
-rw-r--r--drivers/mfd/ocelot-spi.c1
-rw-r--r--drivers/mfd/omap-usb-host.c1
-rw-r--r--drivers/mfd/omap-usb-tll.c6
-rw-r--r--drivers/mfd/qcom-pm8008.c132
-rw-r--r--drivers/mfd/qcom_rpm.c4
-rw-r--r--drivers/mfd/rsmu.h2
-rw-r--r--drivers/mfd/rsmu_i2c.c165
-rw-r--r--drivers/mfd/rsmu_spi.c48
-rw-r--r--drivers/mfd/rz-mtu3.c391
-rw-r--r--drivers/mfd/rz-mtu3.h147
-rw-r--r--drivers/mfd/sec-core.c46
-rw-r--r--drivers/mfd/sec-irq.c89
-rw-r--r--drivers/mfd/si476x-cmd.c14
-rw-r--r--drivers/mfd/simple-mfd-i2c.c13
-rw-r--r--drivers/mfd/ssbi.c4
-rw-r--r--drivers/mfd/stmpe-i2c.c1
-rw-r--r--drivers/mfd/stmpe-spi.c1
-rw-r--r--drivers/mfd/stmpe.c2
-rw-r--r--drivers/mfd/sun4i-gpadc.c4
-rw-r--r--drivers/mfd/tc3589x.c1
-rw-r--r--drivers/mfd/tps6586x.c1
-rw-r--r--drivers/mfd/tqmx86.c52
-rw-r--r--drivers/mfd/twl-core.c65
-rw-r--r--drivers/mfd/twl4030-audio.c1
-rw-r--r--drivers/mfd/twl6040.c1
-rw-r--r--drivers/mfd/wm8994-core.c19
-rw-r--r--drivers/rtc/rtc-s5m.c82
-rw-r--r--include/dt-bindings/mfd/stm32f4-rcc.h1
-rw-r--r--include/linux/mfd/axp20x.h85
-rw-r--r--include/linux/mfd/core.h20
-rw-r--r--include/linux/mfd/max597x.h96
-rw-r--r--include/linux/mfd/rsmu.h5
-rw-r--r--include/linux/mfd/rt5033-private.h17
-rw-r--r--include/linux/mfd/rt5033.h7
-rw-r--r--include/linux/mfd/rz-mtu3.h257
-rw-r--r--include/linux/mfd/samsung/core.h2
-rw-r--r--include/linux/mfd/samsung/irq.h50
-rw-r--r--include/linux/mfd/samsung/s5m8763.h90
91 files changed, 3519 insertions, 845 deletions
diff --git a/Documentation/ABI/testing/sysfs-bus-counter b/Documentation/ABI/testing/sysfs-bus-counter
index ff83320b4255..1417c4272c6c 100644
--- a/Documentation/ABI/testing/sysfs-bus-counter
+++ b/Documentation/ABI/testing/sysfs-bus-counter
@@ -1,3 +1,33 @@
+What: /sys/bus/counter/devices/counterX/cascade_counts_enable
+KernelVersion: 6.4
+Contact: linux-iio@vger.kernel.org
+Description:
+ Indicates the cascading of Counts on Counter X.
+
+ Valid attribute values are boolean.
+
+What: /sys/bus/counter/devices/counterX/external_input_phase_clock_select
+KernelVersion: 6.4
+Contact: linux-iio@vger.kernel.org
+Description:
+ Selects the external clock pin for phase counting mode of
+ Counter X.
+
+ MTCLKA-MTCLKB:
+ MTCLKA and MTCLKB pins are selected for the external
+ phase clock.
+
+ MTCLKC-MTCLKD:
+ MTCLKC and MTCLKD pins are selected for the external
+ phase clock.
+
+What: /sys/bus/counter/devices/counterX/external_input_phase_clock_select_available
+KernelVersion: 6.4
+Contact: linux-iio@vger.kernel.org
+Description:
+ Discrete set of available values for the respective device
+ configuration are listed in this file.
+
What: /sys/bus/counter/devices/counterX/countY/count
KernelVersion: 5.2
Contact: linux-iio@vger.kernel.org
@@ -215,6 +245,8 @@ Contact: linux-iio@vger.kernel.org
Description:
This attribute indicates the number of overflows of count Y.
+What: /sys/bus/counter/devices/counterX/cascade_counts_enable_component_id
+What: /sys/bus/counter/devices/counterX/external_input_phase_clock_select_component_id
What: /sys/bus/counter/devices/counterX/countY/capture_component_id
What: /sys/bus/counter/devices/counterX/countY/ceiling_component_id
What: /sys/bus/counter/devices/counterX/countY/floor_component_id
diff --git a/Documentation/devicetree/bindings/mfd/canaan,k210-sysctl.yaml b/Documentation/devicetree/bindings/mfd/canaan,k210-sysctl.yaml
index e2046f07a40e..8459d3642205 100644
--- a/Documentation/devicetree/bindings/mfd/canaan,k210-sysctl.yaml
+++ b/Documentation/devicetree/bindings/mfd/canaan,k210-sysctl.yaml
@@ -36,7 +36,7 @@ properties:
clock-controller:
# Child node
type: object
- $ref: "../clock/canaan,k210-clk.yaml"
+ $ref: ../clock/canaan,k210-clk.yaml
description:
Clock controller for the SoC clocks. This child node definition
should follow the bindings specified in
@@ -45,7 +45,7 @@ properties:
reset-controller:
# Child node
type: object
- $ref: "../reset/canaan,k210-rst.yaml"
+ $ref: ../reset/canaan,k210-rst.yaml
description:
Reset controller for the SoC. This child node definition
should follow the bindings specified in
@@ -54,7 +54,7 @@ properties:
syscon-reboot:
# Child node
type: object
- $ref: "../power/reset/syscon-reboot.yaml"
+ $ref: ../power/reset/syscon-reboot.yaml
description:
Reboot method for the SoC. This child node definition
should follow the bindings specified in
diff --git a/Documentation/devicetree/bindings/mfd/google,cros-ec.yaml b/Documentation/devicetree/bindings/mfd/google,cros-ec.yaml
index 8caa48f4570e..e1ca4f297c6d 100644
--- a/Documentation/devicetree/bindings/mfd/google,cros-ec.yaml
+++ b/Documentation/devicetree/bindings/mfd/google,cros-ec.yaml
@@ -65,7 +65,7 @@ properties:
ARM Cortex M4 Co-processor. Contains the name of the rpmsg
device. Used to match the subnode to the rpmsg device announced by
the SCP.
- $ref: "/schemas/types.yaml#/definitions/string"
+ $ref: /schemas/types.yaml#/definitions/string
spi-max-frequency: true
@@ -94,23 +94,23 @@ properties:
const: 0
typec:
- $ref: "/schemas/chrome/google,cros-ec-typec.yaml#"
+ $ref: /schemas/chrome/google,cros-ec-typec.yaml#
ec-pwm:
- $ref: "/schemas/pwm/google,cros-ec-pwm.yaml#"
+ $ref: /schemas/pwm/google,cros-ec-pwm.yaml#
deprecated: true
pwm:
- $ref: "/schemas/pwm/google,cros-ec-pwm.yaml#"
+ $ref: /schemas/pwm/google,cros-ec-pwm.yaml#
kbd-led-backlight:
- $ref: "/schemas/chrome/google,cros-kbd-led-backlight.yaml#"
+ $ref: /schemas/chrome/google,cros-kbd-led-backlight.yaml#
keyboard-controller:
- $ref: "/schemas/input/google,cros-ec-keyb.yaml#"
+ $ref: /schemas/input/google,cros-ec-keyb.yaml#
proximity:
- $ref: "/schemas/iio/proximity/google,cros-ec-mkbp-proximity.yaml#"
+ $ref: /schemas/iio/proximity/google,cros-ec-mkbp-proximity.yaml#
codecs:
type: object
@@ -126,7 +126,7 @@ properties:
patternProperties:
"^ec-codec@[a-f0-9]+$":
type: object
- $ref: "/schemas/sound/google,cros-ec-codec.yaml#"
+ $ref: /schemas/sound/google,cros-ec-codec.yaml#
required:
- "#address-cells"
@@ -151,15 +151,15 @@ properties:
patternProperties:
"^i2c-tunnel[0-9]*$":
type: object
- $ref: "/schemas/i2c/google,cros-ec-i2c-tunnel.yaml#"
+ $ref: /schemas/i2c/google,cros-ec-i2c-tunnel.yaml#
"^regulator@[0-9]+$":
type: object
- $ref: "/schemas/regulator/google,cros-ec-regulator.yaml#"
+ $ref: /schemas/regulator/google,cros-ec-regulator.yaml#
"^extcon[0-9]*$":
type: object
- $ref: "/schemas/extcon/extcon-usbc-cros-ec.yaml#"
+ $ref: /schemas/extcon/extcon-usbc-cros-ec.yaml#
required:
- compatible
diff --git a/Documentation/devicetree/bindings/mfd/hisilicon,hi6421-spmi-pmic.yaml b/Documentation/devicetree/bindings/mfd/hisilicon,hi6421-spmi-pmic.yaml
index 22edcb4b212f..bdff5b653453 100644
--- a/Documentation/devicetree/bindings/mfd/hisilicon,hi6421-spmi-pmic.yaml
+++ b/Documentation/devicetree/bindings/mfd/hisilicon,hi6421-spmi-pmic.yaml
@@ -53,7 +53,7 @@ properties:
'^ldo[0-9]+$':
type: object
- $ref: "/schemas/regulator/regulator.yaml#"
+ $ref: /schemas/regulator/regulator.yaml#
unevaluatedProperties: false
diff --git a/Documentation/devicetree/bindings/mfd/maxim,max5970.yaml b/Documentation/devicetree/bindings/mfd/maxim,max5970.yaml
new file mode 100644
index 000000000000..da67742c5aa9
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/maxim,max5970.yaml
@@ -0,0 +1,151 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mfd/maxim,max5970.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Regulator for MAX5970 Smart Switch from Maxim Integrated
+
+maintainers:
+ - Patrick Rudolph <patrick.rudolph@9elements.com>
+
+description: |
+ The smart switch provides no output regulation, but independent fault protection
+ and voltage and current sensing.
+ Programming is done through I2C bus.
+
+ Datasheets:
+ https://datasheets.maximintegrated.com/en/ds/MAX5970.pdf
+ https://datasheets.maximintegrated.com/en/ds/MAX5978.pdf
+
+properties:
+ compatible:
+ enum:
+ - maxim,max5970
+ - maxim,max5978
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ leds:
+ type: object
+ description:
+ Properties for four LEDS.
+
+ properties:
+ "#address-cells":
+ const: 1
+
+ "#size-cells":
+ const: 0
+
+ patternProperties:
+ "^led@[0-3]$":
+ $ref: /schemas/leds/common.yaml#
+ type: object
+
+ additionalProperties: false
+
+ vss1-supply:
+ description: Supply of the first channel.
+
+ vss2-supply:
+ description: Supply of the second channel.
+
+ regulators:
+ type: object
+ description:
+ Properties for both hot swap control/switch.
+
+ patternProperties:
+ "^sw[0-1]$":
+ $ref: /schemas/regulator/regulator.yaml#
+ type: object
+ properties:
+ shunt-resistor-micro-ohms:
+ description: |
+ The value of current sense resistor in microohms.
+
+ required:
+ - shunt-resistor-micro-ohms
+
+ unevaluatedProperties: false
+
+ additionalProperties: false
+
+required:
+ - compatible
+ - reg
+ - regulators
+ - vss1-supply
+
+allOf:
+ - if:
+ properties:
+ compatible:
+ enum:
+ - maxim,max5970
+ then:
+ required:
+ - vss2-supply
+
+additionalProperties: false
+
+examples:
+ - |
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ regulator@3a {
+ compatible = "maxim,max5978";
+ reg = <0x3a>;
+ vss1-supply = <&p3v3>;
+
+ regulators {
+ sw0_ref_0: sw0 {
+ shunt-resistor-micro-ohms = <12000>;
+ };
+ };
+
+ leds {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ led@0 {
+ reg = <0>;
+ label = "led0";
+ default-state = "on";
+ };
+ led@1 {
+ reg = <1>;
+ label = "led1";
+ default-state = "on";
+ };
+ };
+ };
+ };
+
+ - |
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ regulator@3a {
+ compatible = "maxim,max5970";
+ reg = <0x3a>;
+ vss1-supply = <&p3v3>;
+ vss2-supply = <&p5v>;
+
+ regulators {
+ sw0_ref_1: sw0 {
+ shunt-resistor-micro-ohms = <12000>;
+ };
+ sw1_ref_1: sw1 {
+ shunt-resistor-micro-ohms = <10000>;
+ };
+ };
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml b/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml
index adf88245c409..36de335a33aa 100644
--- a/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml
+++ b/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml
@@ -33,6 +33,7 @@ properties:
compatible:
items:
- enum:
+ - qcom,pm2250
- qcom,pm6125
- qcom,pm6150
- qcom,pm6150l
@@ -78,6 +79,7 @@ properties:
- qcom,pmk8350
- qcom,pmk8550
- qcom,pmm8155au
+ - qcom,pmm8654au
- qcom,pmp8074
- qcom,pmr735a
- qcom,pmr735b
@@ -115,6 +117,7 @@ patternProperties:
type: object
oneOf:
- $ref: /schemas/iio/adc/qcom,spmi-iadc.yaml#
+ - $ref: /schemas/iio/adc/qcom,spmi-rradc.yaml#
- $ref: /schemas/iio/adc/qcom,spmi-vadc.yaml#
"^adc-tm@[0-9a-f]+$":
@@ -135,6 +138,14 @@ patternProperties:
type: object
$ref: /schemas/pinctrl/qcom,pmic-gpio.yaml#
+ "^led-controller@[0-9a-f]+$":
+ type: object
+ $ref: /schemas/leds/qcom,spmi-flash-led.yaml#
+
+ "^nvram@[0-9a-f]+$":
+ type: object
+ $ref: /schemas/nvmem/qcom,spmi-sdam.yaml#
+
"pon@[0-9a-f]+$":
type: object
$ref: /schemas/power/reset/qcom,pon.yaml#
@@ -276,12 +287,12 @@ examples:
#size-cells = <0>;
#io-channel-cells = <1>;
- adc-chan@6 {
+ channel@6 {
reg = <ADC5_DIE_TEMP>;
label = "die_temp";
};
- adc-chan@4f {
+ channel@4f {
reg = <ADC5_AMUX_THM3_100K_PU>;
qcom,ratiometric;
qcom,hw-settle-time = <200>;
diff --git a/Documentation/devicetree/bindings/mfd/qcom,tcsr.yaml b/Documentation/devicetree/bindings/mfd/qcom,tcsr.yaml
index 2eeebe920e6e..fe790af7b4fb 100644
--- a/Documentation/devicetree/bindings/mfd/qcom,tcsr.yaml
+++ b/Documentation/devicetree/bindings/mfd/qcom,tcsr.yaml
@@ -25,12 +25,16 @@ properties:
- qcom,sc8280xp-tcsr
- qcom,sdm630-tcsr
- qcom,sdm845-tcsr
+ - qcom,sdx55-tcsr
+ - qcom,sdx65-tcsr
- qcom,sm8150-tcsr
+ - qcom,sm8450-tcsr
- qcom,tcsr-apq8064
- qcom,tcsr-apq8084
- qcom,tcsr-ipq5332
- qcom,tcsr-ipq6018
- qcom,tcsr-ipq8064
+ - qcom,tcsr-ipq9574
- qcom,tcsr-mdm9615
- qcom,tcsr-msm8226
- qcom,tcsr-msm8660
diff --git a/Documentation/devicetree/bindings/mfd/qcom-pm8xxx.yaml b/Documentation/devicetree/bindings/mfd/qcom-pm8xxx.yaml
index 9acad9d326eb..9c51c1b19067 100644
--- a/Documentation/devicetree/bindings/mfd/qcom-pm8xxx.yaml
+++ b/Documentation/devicetree/bindings/mfd/qcom-pm8xxx.yaml
@@ -49,7 +49,7 @@ patternProperties:
"rtc@[0-9a-f]+$":
type: object
- $ref: "../rtc/qcom-pm8xxx-rtc.yaml"
+ $ref: ../rtc/qcom-pm8xxx-rtc.yaml
required:
- compatible
diff --git a/Documentation/devicetree/bindings/mfd/rohm,bd71815-pmic.yaml b/Documentation/devicetree/bindings/mfd/rohm,bd71815-pmic.yaml
index d6d120a78094..05747e012516 100644
--- a/Documentation/devicetree/bindings/mfd/rohm,bd71815-pmic.yaml
+++ b/Documentation/devicetree/bindings/mfd/rohm,bd71815-pmic.yaml
@@ -46,7 +46,7 @@ properties:
rohm,clkout-open-drain:
description: clk32kout mode. Set to 1 for "open-drain" or 0 for "cmos".
- $ref: "/schemas/types.yaml#/definitions/uint32"
+ $ref: /schemas/types.yaml#/definitions/uint32
minimum: 0
maximum: 1
diff --git a/Documentation/devicetree/bindings/mfd/rohm,bd71828-pmic.yaml b/Documentation/devicetree/bindings/mfd/rohm,bd71828-pmic.yaml
index ec3adcd3483d..11089aa89ec6 100644
--- a/Documentation/devicetree/bindings/mfd/rohm,bd71828-pmic.yaml
+++ b/Documentation/devicetree/bindings/mfd/rohm,bd71828-pmic.yaml
@@ -46,7 +46,7 @@ properties:
rohm,clkout-open-drain:
description: clk32kout mode. Set to 1 for "open-drain" or 0 for "cmos".
- $ref: "/schemas/types.yaml#/definitions/uint32"
+ $ref: /schemas/types.yaml#/definitions/uint32
minimum: 0
maximum: 1
diff --git a/Documentation/devicetree/bindings/mfd/syscon.yaml b/Documentation/devicetree/bindings/mfd/syscon.yaml
index c828c4f5e4a7..8103154bbb52 100644
--- a/Documentation/devicetree/bindings/mfd/syscon.yaml
+++ b/Documentation/devicetree/bindings/mfd/syscon.yaml
@@ -56,6 +56,7 @@ properties:
- microchip,lan966x-cpu-syscon
- microchip,sparx5-cpu-syscon
- mstar,msc313-pmsleep
+ - nuvoton,ma35d1-sys
- nuvoton,wpcm450-shm
- rockchip,px30-qos
- rockchip,rk3036-qos
@@ -67,6 +68,7 @@ properties:
- rockchip,rk3568-qos
- rockchip,rk3588-qos
- rockchip,rv1126-qos
+ - starfive,jh7100-sysmain
- const: syscon
diff --git a/Documentation/devicetree/bindings/mfd/ti,j721e-system-controller.yaml b/Documentation/devicetree/bindings/mfd/ti,j721e-system-controller.yaml
index 76ef4352e13c..0c98d913747b 100644
--- a/Documentation/devicetree/bindings/mfd/ti,j721e-system-controller.yaml
+++ b/Documentation/devicetree/bindings/mfd/ti,j721e-system-controller.yaml
@@ -62,6 +62,12 @@ patternProperties:
description:
The phy node corresponding to the ethernet MAC.
+ "^chipid@[0-9a-f]+$":
+ type: object
+ $ref: /schemas/hwinfo/ti,k3-socinfo.yaml#
+ description:
+ The node corresponding to SoC chip identification.
+
required:
- compatible
- reg
@@ -99,5 +105,10 @@ examples:
reg = <0x4140 0x18>;
#clock-cells = <1>;
};
+
+ chipid@14 {
+ compatible = "ti,am654-chipid";
+ reg = <0x14 0x4>;
+ };
};
...
diff --git a/Documentation/devicetree/bindings/mfd/ti,nspire-misc.yaml b/Documentation/devicetree/bindings/mfd/ti,nspire-misc.yaml
new file mode 100644
index 000000000000..28cd5164d46f
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/ti,nspire-misc.yaml
@@ -0,0 +1,51 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+# Copyright (C) 2022-2023 Texas Instruments Incorporated - https://www.ti.com/
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mfd/ti,nspire-misc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: TI Nspire MISC hardware block
+
+maintainers:
+ - Andrew Davis <afd@ti.com>
+
+description:
+ System controller node represents a register region containing a set
+ of miscellaneous registers. The registers are not cohesive enough to
+ represent as any specific type of device. Currently there is a reset
+ controller.
+
+properties:
+ compatible:
+ items:
+ - enum:
+ - ti,nspire-misc
+ - const: syscon
+ - const: simple-mfd
+
+ reg:
+ maxItems: 1
+
+ reboot:
+ $ref: /schemas/power/reset/syscon-reboot.yaml#
+
+required:
+ - compatible
+ - reg
+ - reboot
+
+additionalProperties: false
+
+examples:
+ - |
+ misc: misc@900a0000 {
+ compatible = "ti,nspire-misc", "syscon", "simple-mfd";
+ reg = <0x900a0000 0x1000>;
+
+ reboot {
+ compatible = "syscon-reboot";
+ offset = <0x08>;
+ value = <0x02>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/mfd/wlf,arizona.yaml b/Documentation/devicetree/bindings/mfd/wlf,arizona.yaml
index ea3337dafaf5..7902f3c5d289 100644
--- a/Documentation/devicetree/bindings/mfd/wlf,arizona.yaml
+++ b/Documentation/devicetree/bindings/mfd/wlf,arizona.yaml
@@ -156,7 +156,7 @@ properties:
entry has a value that is out of range for a 16 bit register then the
chip default will be used. If present exactly five values must be
specified.
- $ref: "/schemas/types.yaml#/definitions/uint32-array"
+ $ref: /schemas/types.yaml#/definitions/uint32-array
minItems: 1
maxItems: 5
diff --git a/Documentation/devicetree/bindings/mfd/x-powers,ac100.yaml b/Documentation/devicetree/bindings/mfd/x-powers,ac100.yaml
index 309606d2d806..f3d8394b27e7 100644
--- a/Documentation/devicetree/bindings/mfd/x-powers,ac100.yaml
+++ b/Documentation/devicetree/bindings/mfd/x-powers,ac100.yaml
@@ -1,8 +1,8 @@
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
-$id: "http://devicetree.org/schemas/mfd/x-powers,ac100.yaml#"
-$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+$id: http://devicetree.org/schemas/mfd/x-powers,ac100.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
title: X-Powers AC100
diff --git a/Documentation/devicetree/bindings/mfd/x-powers,axp152.yaml b/Documentation/devicetree/bindings/mfd/x-powers,axp152.yaml
index 24d03996b93a..f7f0f2c0421a 100644
--- a/Documentation/devicetree/bindings/mfd/x-powers,axp152.yaml
+++ b/Documentation/devicetree/bindings/mfd/x-powers,axp152.yaml
@@ -47,9 +47,8 @@ allOf:
- x-powers,axp209
then:
- not:
- required:
- - x-powers,drive-vbus-en
+ properties:
+ x-powers,drive-vbus-en: false
- if:
not:
@@ -59,14 +58,9 @@ allOf:
const: x-powers,axp806
then:
- allOf:
- - not:
- required:
- - x-powers,self-working-mode
-
- - not:
- required:
- - x-powers,master-mode
+ properties:
+ x-powers,self-working-mode: false
+ x-powers,master-mode: false
- if:
not:
@@ -79,6 +73,18 @@ allOf:
required:
- interrupts
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - x-powers,axp313a
+ - x-powers,axp15060
+
+ then:
+ properties:
+ x-powers,dcdc-freq: false
+
properties:
compatible:
oneOf:
@@ -88,10 +94,12 @@ properties:
- x-powers,axp209
- x-powers,axp221
- x-powers,axp223
+ - x-powers,axp313a
- x-powers,axp803
- x-powers,axp806
- x-powers,axp809
- x-powers,axp813
+ - x-powers,axp15060
- items:
- const: x-powers,axp228
- const: x-powers,axp221
@@ -260,7 +268,7 @@ properties:
Defines the work frequency of DC-DC in kHz.
patternProperties:
- "^(([a-f])?ldo[0-9]|dcdc[0-7a-e]|ldo(_|-)io(0|1)|(dc1)?sw|rtc(_|-)ldo|drivevbus|dc5ldo)$":
+ "^(([a-f])?ldo[0-9]|dcdc[0-7a-e]|ldo(_|-)io(0|1)|(dc1)?sw|rtc(_|-)ldo|cpusldo|drivevbus|dc5ldo)$":
$ref: /schemas/regulator/regulator.yaml#
type: object
unevaluatedProperties: false
diff --git a/Documentation/devicetree/bindings/mfd/xylon,logicvc.yaml b/Documentation/devicetree/bindings/mfd/xylon,logicvc.yaml
index 9efd49c39bd2..6e880a46d7ee 100644
--- a/Documentation/devicetree/bindings/mfd/xylon,logicvc.yaml
+++ b/Documentation/devicetree/bindings/mfd/xylon,logicvc.yaml
@@ -2,8 +2,8 @@
# Copyright 2019 Bootlin
%YAML 1.2
---
-$id: "http://devicetree.org/schemas/mfd/xylon,logicvc.yaml#"
-$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+$id: http://devicetree.org/schemas/mfd/xylon,logicvc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Xylon LogiCVC multi-function device
diff --git a/Documentation/devicetree/bindings/timer/renesas,rz-mtu3.yaml b/Documentation/devicetree/bindings/timer/renesas,rz-mtu3.yaml
new file mode 100644
index 000000000000..bffdab0b0185
--- /dev/null
+++ b/Documentation/devicetree/bindings/timer/renesas,rz-mtu3.yaml
@@ -0,0 +1,302 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/timer/renesas,rz-mtu3.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Renesas RZ/G2L Multi-Function Timer Pulse Unit 3 (MTU3a)
+
+maintainers:
+ - Biju Das <biju.das.jz@bp.renesas.com>
+
+description: |
+ This hardware block consists of eight 16-bit timer channels and one
+ 32- bit timer channel. It supports the following specifications:
+ - Pulse input/output: 28 lines max.
+ - Pulse input 3 lines
+ - Count clock 11 clocks for each channel (14 clocks for MTU0, 12 clocks
+ for MTU2, and 10 clocks for MTU5, four clocks for MTU1-MTU2 combination
+ (when LWA = 1))
+ - Operating frequency Up to 100 MHz
+ - Available operations [MTU0 to MTU4, MTU6, MTU7, and MTU8]
+ - Waveform output on compare match
+ - Input capture function (noise filter setting available)
+ - Counter-clearing operation
+ - Simultaneous writing to multiple timer counters (TCNT)
+ (excluding MTU8).
+ - Simultaneous clearing on compare match or input capture
+ (excluding MTU8).
+ - Simultaneous input and output to registers in synchronization with
+ counter operations (excluding MTU8).
+ - Up to 12-phase PWM output in combination with synchronous operation
+ (excluding MTU8)
+ - [MTU0 MTU3, MTU4, MTU6, MTU7, and MTU8]
+ - Buffer operation specifiable
+ - [MTU1, MTU2]
+ - Phase counting mode can be specified independently
+ - 32-bit phase counting mode can be specified for interlocked operation
+ of MTU1 and MTU2 (when TMDR3.LWA = 1)
+ - Cascade connection operation available
+ - [MTU3, MTU4, MTU6, and MTU7]
+ - Through interlocked operation of MTU3/4 and MTU6/7, the positive and
+ negative signals in six phases (12 phases in total) can be output in
+ complementary PWM and reset-synchronized PWM operation.
+ - In complementary PWM mode, values can be transferred from buffer
+ registers to temporary registers at crests and troughs of the timer-
+ counter values or when the buffer registers (TGRD registers in MTU4
+ and MTU7) are written to.
+ - Double-buffering selectable in complementary PWM mode.
+ - [MTU3 and MTU4]
+ - Through interlocking with MTU0, a mode for driving AC synchronous
+ motors (brushless DC motors) by using complementary PWM output and
+ reset-synchronized PWM output is settable and allows the selection
+ of two types of waveform output (chopping or level).
+ - [MTU5]
+ - Capable of operation as a dead-time compensation counter.
+ - [MTU0/MTU5, MTU1, MTU2, and MTU8]
+ - 32-bit phase counting mode specifiable by combining MTU1 and MTU2 and
+ through interlocked operation with MTU0/MTU5 and MTU8.
+ - Interrupt-skipping function
+ - In complementary PWM mode, interrupts on crests and troughs of counter
+ values and triggers to start conversion by the A/D converter can be
+ skipped.
+ - Interrupt sources: 43 sources.
+ - Buffer operation:
+ - Automatic transfer of register data (transfer from the buffer
+ register to the timer register).
+ - Trigger generation
+ - A/D converter start triggers can be generated
+ - A/D converter start request delaying function enables A/D converter
+ to be started with any desired timing and to be synchronized with
+ PWM output.
+ - Low power consumption function
+ - The MTU3a can be placed in the module-stop state.
+
+ There are two phase counting modes. 16-bit phase counting mode in which
+ MTU1 and MTU2 operate independently, and cascade connection 32-bit phase
+ counting mode in which MTU1 and MTU2 are cascaded.
+
+ In phase counting mode, the phase difference between two external input
+ clocks is detected and the corresponding TCNT is incremented or
+ decremented.
+ The below counters are supported
+ count0 - MTU1 16-bit phase counting
+ count1 - MTU2 16-bit phase counting
+ count2 - MTU1+ MTU2 32-bit phase counting
+
+ The module supports PWM mode{1,2}, Reset-synchronized PWM mode and
+ complementary PWM mode{1,2,3}.
+
+ In complementary PWM mode, six positive-phase and six negative-phase PWM
+ waveforms (12 phases in total) with dead time can be output by
+ combining MTU{3,4} and MTU{6,7}.
+
+ The below pwm channels are supported in pwm mode 1.
+ pwm0 - MTU0.MTIOC0A PWM mode 1
+ pwm1 - MTU0.MTIOC0C PWM mode 1
+ pwm2 - MTU1.MTIOC1A PWM mode 1
+ pwm3 - MTU2.MTIOC2A PWM mode 1
+ pwm4 - MTU3.MTIOC3A PWM mode 1
+ pwm5 - MTU3.MTIOC3C PWM mode 1
+ pwm6 - MTU4.MTIOC4A PWM mode 1
+ pwm7 - MTU4.MTIOC4C PWM mode 1
+ pwm8 - MTU6.MTIOC6A PWM mode 1
+ pwm9 - MTU6.MTIOC6C PWM mode 1
+ pwm10 - MTU7.MTIOC7A PWM mode 1
+ pwm11 - MTU7.MTIOC7C PWM mode 1
+
+properties:
+ compatible:
+ items:
+ - enum:
+ - renesas,r9a07g044-mtu3 # RZ/G2{L,LC}
+ - renesas,r9a07g054-mtu3 # RZ/V2L
+ - const: renesas,rz-mtu3
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ items:
+ - description: MTU0.TGRA input capture/compare match
+ - description: MTU0.TGRB input capture/compare match
+ - description: MTU0.TGRC input capture/compare match
+ - description: MTU0.TGRD input capture/compare match
+ - description: MTU0.TCNT overflow
+ - description: MTU0.TGRE compare match
+ - description: MTU0.TGRF compare match
+ - description: MTU1.TGRA input capture/compare match
+ - description: MTU1.TGRB input capture/compare match
+ - description: MTU1.TCNT overflow
+ - description: MTU1.TCNT underflow
+ - description: MTU2.TGRA input capture/compare match
+ - description: MTU2.TGRB input capture/compare match
+ - description: MTU2.TCNT overflow
+ - description: MTU2.TCNT underflow
+ - description: MTU3.TGRA input capture/compare match
+ - description: MTU3.TGRB input capture/compare match
+ - description: MTU3.TGRC input capture/compare match
+ - description: MTU3.TGRD input capture/compare match
+ - description: MTU3.TCNT overflow
+ - description: MTU4.TGRA input capture/compare match
+ - description: MTU4.TGRB input capture/compare match
+ - description: MTU4.TGRC input capture/compare match
+ - description: MTU4.TGRD input capture/compare match
+ - description: MTU4.TCNT overflow/underflow
+ - description: MTU5.TGRU input capture/compare match
+ - description: MTU5.TGRV input capture/compare match
+ - description: MTU5.TGRW input capture/compare match
+ - description: MTU6.TGRA input capture/compare match
+ - description: MTU6.TGRB input capture/compare match
+ - description: MTU6.TGRC input capture/compare match
+ - description: MTU6.TGRD input capture/compare match
+ - description: MTU6.TCNT overflow
+ - description: MTU7.TGRA input capture/compare match
+ - description: MTU7.TGRB input capture/compare match
+ - description: MTU7.TGRC input capture/compare match
+ - description: MTU7.TGRD input capture/compare match
+ - description: MTU7.TCNT overflow/underflow
+ - description: MTU8.TGRA input capture/compare match
+ - description: MTU8.TGRB input capture/compare match
+ - description: MTU8.TGRC input capture/compare match
+ - description: MTU8.TGRD input capture/compare match
+ - description: MTU8.TCNT overflow
+ - description: MTU8.TCNT underflow
+
+ interrupt-names:
+ items:
+ - const: tgia0
+ - const: tgib0
+ - const: tgic0
+ - const: tgid0
+ - const: tgiv0
+ - const: tgie0
+ - const: tgif0
+ - const: tgia1
+ - const: tgib1
+ - const: tgiv1
+ - const: tgiu1
+ - const: tgia2
+ - const: tgib2
+ - const: tgiv2
+ - const: tgiu2
+ - const: tgia3
+ - const: tgib3
+ - const: tgic3
+ - const: tgid3
+ - const: tgiv3
+ - const: tgia4
+ - const: tgib4
+ - const: tgic4
+ - const: tgid4
+ - const: tgiv4
+ - const: tgiu5
+ - const: tgiv5
+ - const: tgiw5
+ - const: tgia6
+ - const: tgib6
+ - const: tgic6
+ - const: tgid6
+ - const: tgiv6
+ - const: tgia7
+ - const: tgib7
+ - const: tgic7
+ - const: tgid7
+ - const: tgiv7
+ - const: tgia8
+ - const: tgib8
+ - const: tgic8
+ - const: tgid8
+ - const: tgiv8
+ - const: tgiu8
+
+ clocks:
+ maxItems: 1
+
+ power-domains:
+ maxItems: 1
+
+ resets:
+ maxItems: 1
+
+ "#pwm-cells":
+ const: 2
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - interrupt-names
+ - clocks
+ - power-domains
+ - resets
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/r9a07g044-cpg.h>
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+ mtu3: timer@10001200 {
+ compatible = "renesas,r9a07g044-mtu3", "renesas,rz-mtu3";
+ reg = <0x10001200 0xb00>;
+ interrupts = <GIC_SPI 170 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 171 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 172 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 173 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 174 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 175 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 176 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 177 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 178 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 179 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 180 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 181 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 182 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 183 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 184 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 185 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 186 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 187 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 188 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 189 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 190 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 191 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 192 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 193 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 194 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 195 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 196 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 197 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 198 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 199 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 200 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 201 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 202 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 203 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 204 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 205 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 206 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 207 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 208 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 209 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 210 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 211 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 212 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 213 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "tgia0", "tgib0", "tgic0", "tgid0", "tgiv0", "tgie0",
+ "tgif0",
+ "tgia1", "tgib1", "tgiv1", "tgiu1",
+ "tgia2", "tgib2", "tgiv2", "tgiu2",
+ "tgia3", "tgib3", "tgic3", "tgid3", "tgiv3",
+ "tgia4", "tgib4", "tgic4", "tgid4", "tgiv4",
+ "tgiu5", "tgiv5", "tgiw5",
+ "tgia6", "tgib6", "tgic6", "tgid6", "tgiv6",
+ "tgia7", "tgib7", "tgic7", "tgid7", "tgiv7",
+ "tgia8", "tgib8", "tgic8", "tgid8", "tgiv8", "tgiu8";
+ clocks = <&cpg CPG_MOD R9A07G044_MTU_X_MCK_MTU3>;
+ power-domains = <&cpg>;
+ resets = <&cpg R9A07G044_MTU_X_PRESET_MTU3>;
+ #pwm-cells = <2>;
+ };
diff --git a/MAINTAINERS b/MAINTAINERS
index e307d977c100..773b5650ad23 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -17972,6 +17972,14 @@ S: Supported
F: Documentation/devicetree/bindings/iio/adc/renesas,rzg2l-adc.yaml
F: drivers/iio/adc/rzg2l_adc.c
+RENESAS RZ/G2L MTU3a COUNTER DRIVER
+M: Biju Das <biju.das.jz@bp.renesas.com>
+L: linux-iio@vger.kernel.org
+L: linux-renesas-soc@vger.kernel.org
+S: Supported
+F: Documentation/devicetree/bindings/timer/renesas,rz-mtu3.yaml
+F: drivers/counter/rz-mtu3-cnt.c
+
RENESAS RZ/N1 A5PSW SWITCH DRIVER
M: Clément Léger <clement.leger@bootlin.com>
L: linux-renesas-soc@vger.kernel.org
diff --git a/drivers/counter/Kconfig b/drivers/counter/Kconfig
index b5ba8fb02cf7..4228be917038 100644
--- a/drivers/counter/Kconfig
+++ b/drivers/counter/Kconfig
@@ -73,6 +73,17 @@ config MICROCHIP_TCB_CAPTURE
To compile this driver as a module, choose M here: the
module will be called microchip-tcb-capture.
+config RZ_MTU3_CNT
+ tristate "Renesas RZ/G2L MTU3a counter driver"
+ depends on RZ_MTU3 || COMPILE_TEST
+ help
+ Enable support for MTU3a counter driver found on Renesas RZ/G2L alike
+ SoCs. This IP supports both 16-bit and 32-bit phase counting mode
+ support.
+
+ To compile this driver as a module, choose M here: the
+ module will be called rz-mtu3-cnt.
+
config STM32_LPTIMER_CNT
tristate "STM32 LP Timer encoder counter driver"
depends on MFD_STM32_LPTIMER || COMPILE_TEST
diff --git a/drivers/counter/Makefile b/drivers/counter/Makefile
index b9a369e0d4fc..933fdd50b3e4 100644
--- a/drivers/counter/Makefile
+++ b/drivers/counter/Makefile
@@ -8,6 +8,7 @@ counter-y := counter-core.o counter-sysfs.o counter-chrdev.o
obj-$(CONFIG_104_QUAD_8) += 104-quad-8.o
obj-$(CONFIG_INTERRUPT_CNT) += interrupt-cnt.o
+obj-$(CONFIG_RZ_MTU3_CNT) += rz-mtu3-cnt.o
obj-$(CONFIG_STM32_TIMER_CNT) += stm32-timer-cnt.o
obj-$(CONFIG_STM32_LPTIMER_CNT) += stm32-lptimer-cnt.o
obj-$(CONFIG_TI_EQEP) += ti-eqep.o
diff --git a/drivers/counter/rz-mtu3-cnt.c b/drivers/counter/rz-mtu3-cnt.c
new file mode 100644
index 000000000000..48c83933aa2f
--- /dev/null
+++ b/drivers/counter/rz-mtu3-cnt.c
@@ -0,0 +1,906 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Renesas RZ/G2L MTU3a Counter driver
+ *
+ * Copyright (C) 2022 Renesas Electronics Corporation
+ */
+
+#include <linux/clk.h>
+#include <linux/counter.h>
+#include <linux/mfd/rz-mtu3.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/types.h>
+
+/*
+ * Register descriptions
+ * TSR: Timer Status Register
+ * TMDR1: Timer Mode Register 1
+ * TMDR3: Timer Mode Register 3
+ * TIOR: Timer I/O Control Register
+ * TCR: Timer Control Register
+ * TCNT: Timer Counter
+ * TGRA: Timer general register A
+ * TCNTLW: Timer Longword Counter
+ * TGRALW: Timer longword general register A
+ */
+
+#define RZ_MTU3_TSR_TCFD BIT(7) /* Count Direction Flag */
+
+#define RZ_MTU3_TMDR1_PH_CNT_MODE_1 (4) /* Phase counting mode 1 */
+#define RZ_MTU3_TMDR1_PH_CNT_MODE_2 (5) /* Phase counting mode 2 */
+#define RZ_MTU3_TMDR1_PH_CNT_MODE_3 (6) /* Phase counting mode 3 */
+#define RZ_MTU3_TMDR1_PH_CNT_MODE_4 (7) /* Phase counting mode 4 */
+#define RZ_MTU3_TMDR1_PH_CNT_MODE_5 (9) /* Phase counting mode 5 */
+#define RZ_MTU3_TMDR1_PH_CNT_MODE_MASK (0xf)
+
+/*
+ * LWA: MTU1/MTU2 Combination Longword Access Control
+ * 0: 16-bit, 1: 32-bit
+ */
+#define RZ_MTU3_TMDR3_LWA (0)
+
+/*
+ * PHCKSEL: External Input Phase Clock Select
+ * 0: MTCLKA and MTCLKB, 1: MTCLKC and MTCLKD
+ */
+#define RZ_MTU3_TMDR3_PHCKSEL (1)
+
+#define RZ_MTU3_16_BIT_MTU1_CH (0)
+#define RZ_MTU3_16_BIT_MTU2_CH (1)
+#define RZ_MTU3_32_BIT_CH (2)
+
+#define RZ_MTU3_TIOR_NO_OUTPUT (0) /* Output prohibited */
+#define RZ_MTU3_TIOR_IC_BOTH (10) /* Input capture at both edges */
+
+#define SIGNAL_A_ID (0)
+#define SIGNAL_B_ID (1)
+#define SIGNAL_C_ID (2)
+#define SIGNAL_D_ID (3)
+
+#define RZ_MTU3_MAX_HW_CNTR_CHANNELS (2)
+#define RZ_MTU3_MAX_LOGICAL_CNTR_CHANNELS (3)
+
+/**
+ * struct rz_mtu3_cnt - MTU3 counter private data
+ *
+ * @clk: MTU3 module clock
+ * @lock: Lock to prevent concurrent access for ceiling and count
+ * @ch: HW channels for the counters
+ * @count_is_enabled: Enabled state of Counter value channel
+ * @mtu_16bit_max: Cache for 16-bit counters
+ * @mtu_32bit_max: Cache for 32-bit counters
+ */
+struct rz_mtu3_cnt {
+ struct clk *clk;
+ struct mutex lock;
+ struct rz_mtu3_channel *ch;
+ bool count_is_enabled[RZ_MTU3_MAX_LOGICAL_CNTR_CHANNELS];
+ union {
+ u16 mtu_16bit_max[RZ_MTU3_MAX_HW_CNTR_CHANNELS];
+ u32 mtu_32bit_max;
+ };
+};
+
+static const enum counter_function rz_mtu3_count_functions[] = {
+ COUNTER_FUNCTION_QUADRATURE_X4,
+ COUNTER_FUNCTION_PULSE_DIRECTION,
+ COUNTER_FUNCTION_QUADRATURE_X2_B,
+};
+
+static inline size_t rz_mtu3_get_hw_ch(const size_t id)
+{
+ return (id == RZ_MTU3_32_BIT_CH) ? 0 : id;
+}
+
+static inline struct rz_mtu3_channel *rz_mtu3_get_ch(struct counter_device *counter, int id)
+{
+ struct rz_mtu3_cnt *const priv = counter_priv(counter);
+ const size_t ch_id = rz_mtu3_get_hw_ch(id);
+
+ return &priv->ch[ch_id];
+}
+
+static bool rz_mtu3_is_counter_invalid(struct counter_device *counter, int id)
+{
+ struct rz_mtu3_cnt *const priv = counter_priv(counter);
+ unsigned long tmdr;
+
+ pm_runtime_get_sync(priv->ch->dev);
+ tmdr = rz_mtu3_shared_reg_read(priv->ch, RZ_MTU3_TMDR3);
+ pm_runtime_put(priv->ch->dev);
+
+ if (id == RZ_MTU3_32_BIT_CH && test_bit(RZ_MTU3_TMDR3_LWA, &tmdr))
+ return false;
+
+ if (id != RZ_MTU3_32_BIT_CH && !test_bit(RZ_MTU3_TMDR3_LWA, &tmdr))
+ return false;
+
+ return true;
+}
+
+static int rz_mtu3_lock_if_counter_is_valid(struct counter_device *counter,
+ struct rz_mtu3_channel *const ch,
+ struct rz_mtu3_cnt *const priv,
+ int id)
+{
+ mutex_lock(&priv->lock);
+
+ if (ch->is_busy && !priv->count_is_enabled[id]) {
+ mutex_unlock(&priv->lock);
+ return -EINVAL;
+ }
+
+ if (rz_mtu3_is_counter_invalid(counter, id)) {
+ mutex_unlock(&priv->lock);
+ return -EBUSY;
+ }
+
+ return 0;
+}
+
+static int rz_mtu3_lock_if_count_is_enabled(struct rz_mtu3_channel *const ch,
+ struct rz_mtu3_cnt *const priv,
+ int id)
+{
+ mutex_lock(&priv->lock);
+
+ if (ch->is_busy && !priv->count_is_enabled[id]) {
+ mutex_unlock(&priv->lock);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int rz_mtu3_count_read(struct counter_device *counter,
+ struct counter_count *count, u64 *val)
+{
+ struct rz_mtu3_channel *const ch = rz_mtu3_get_ch(counter, count->id);
+ struct rz_mtu3_cnt *const priv = counter_priv(counter);
+ int ret;
+
+ ret = rz_mtu3_lock_if_counter_is_valid(counter, ch, priv, count->id);
+ if (ret)
+ return ret;
+
+ pm_runtime_get_sync(ch->dev);
+ if (count->id == RZ_MTU3_32_BIT_CH)
+ *val = rz_mtu3_32bit_ch_read(ch, RZ_MTU3_TCNTLW);
+ else
+ *val = rz_mtu3_16bit_ch_read(ch, RZ_MTU3_TCNT);
+ pm_runtime_put(ch->dev);
+ mutex_unlock(&priv->lock);
+
+ return 0;
+}
+
+static int rz_mtu3_count_write(struct counter_device *counter,
+ struct counter_count *count, const u64 val)
+{
+ struct rz_mtu3_channel *const ch = rz_mtu3_get_ch(counter, count->id);
+ struct rz_mtu3_cnt *const priv = counter_priv(counter);
+ int ret;
+
+ ret = rz_mtu3_lock_if_counter_is_valid(counter, ch, priv, count->id);
+ if (ret)
+ return ret;
+
+ pm_runtime_get_sync(ch->dev);
+ if (count->id == RZ_MTU3_32_BIT_CH)
+ rz_mtu3_32bit_ch_write(ch, RZ_MTU3_TCNTLW, val);
+ else
+ rz_mtu3_16bit_ch_write(ch, RZ_MTU3_TCNT, val);
+ pm_runtime_put(ch->dev);
+ mutex_unlock(&priv->lock);
+
+ return 0;
+}
+
+static int rz_mtu3_count_function_read_helper(struct rz_mtu3_channel *const ch,
+ struct rz_mtu3_cnt *const priv,
+ enum counter_function *function)
+{
+ u8 timer_mode;
+
+ pm_runtime_get_sync(ch->dev);
+ timer_mode = rz_mtu3_8bit_ch_read(ch, RZ_MTU3_TMDR1);
+ pm_runtime_put(ch->dev);
+
+ switch (timer_mode & RZ_MTU3_TMDR1_PH_CNT_MODE_MASK) {
+ case RZ_MTU3_TMDR1_PH_CNT_MODE_1:
+ *function = COUNTER_FUNCTION_QUADRATURE_X4;
+ return 0;
+ case RZ_MTU3_TMDR1_PH_CNT_MODE_2:
+ *function = COUNTER_FUNCTION_PULSE_DIRECTION;
+ return 0;
+ case RZ_MTU3_TMDR1_PH_CNT_MODE_4:
+ *function = COUNTER_FUNCTION_QUADRATURE_X2_B;
+ return 0;
+ default:
+ /*
+ * TODO:
+ * - need to add RZ_MTU3_TMDR1_PH_CNT_MODE_3
+ * - need to add RZ_MTU3_TMDR1_PH_CNT_MODE_5
+ */
+ return -EINVAL;
+ }
+}
+
+static int rz_mtu3_count_function_read(struct counter_device *counter,
+ struct counter_count *count,
+ enum counter_function *function)
+{
+ struct rz_mtu3_channel *const ch = rz_mtu3_get_ch(counter, count->id);
+ struct rz_mtu3_cnt *const priv = counter_priv(counter);
+ int ret;
+
+ ret = rz_mtu3_lock_if_count_is_enabled(ch, priv, count->id);
+ if (ret)
+ return ret;
+
+ ret = rz_mtu3_count_function_read_helper(ch, priv, function);
+ mutex_unlock(&priv->lock);
+
+ return ret;
+}
+
+static int rz_mtu3_count_function_write(struct counter_device *counter,
+ struct counter_count *count,
+ enum counter_function function)
+{
+ struct rz_mtu3_channel *const ch = rz_mtu3_get_ch(counter, count->id);
+ struct rz_mtu3_cnt *const priv = counter_priv(counter);
+ u8 timer_mode;
+ int ret;
+
+ ret = rz_mtu3_lock_if_count_is_enabled(ch, priv, count->id);
+ if (ret)
+ return ret;
+
+ switch (function) {
+ case COUNTER_FUNCTION_QUADRATURE_X4:
+ timer_mode = RZ_MTU3_TMDR1_PH_CNT_MODE_1;
+ break;
+ case COUNTER_FUNCTION_PULSE_DIRECTION:
+ timer_mode = RZ_MTU3_TMDR1_PH_CNT_MODE_2;
+ break;
+ case COUNTER_FUNCTION_QUADRATURE_X2_B:
+ timer_mode = RZ_MTU3_TMDR1_PH_CNT_MODE_4;
+ break;
+ default:
+ /*
+ * TODO:
+ * - need to add RZ_MTU3_TMDR1_PH_CNT_MODE_3
+ * - need to add RZ_MTU3_TMDR1_PH_CNT_MODE_5
+ */
+ mutex_unlock(&priv->lock);
+ return -EINVAL;
+ }
+
+ pm_runtime_get_sync(ch->dev);
+ rz_mtu3_8bit_ch_write(ch, RZ_MTU3_TMDR1, timer_mode);
+ pm_runtime_put(ch->dev);
+ mutex_unlock(&priv->lock);
+
+ return 0;
+}
+
+static int rz_mtu3_count_direction_read(struct counter_device *counter,
+ struct counter_count *count,
+ enum counter_count_direction *direction)
+{
+ struct rz_mtu3_channel *const ch = rz_mtu3_get_ch(counter, count->id);
+ struct rz_mtu3_cnt *const priv = counter_priv(counter);
+ int ret;
+ u8 tsr;
+
+ ret = rz_mtu3_lock_if_count_is_enabled(ch, priv, count->id);
+ if (ret)
+ return ret;
+
+ pm_runtime_get_sync(ch->dev);
+ tsr = rz_mtu3_8bit_ch_read(ch, RZ_MTU3_TSR);
+ pm_runtime_put(ch->dev);
+
+ *direction = (tsr & RZ_MTU3_TSR_TCFD) ?
+ COUNTER_COUNT_DIRECTION_FORWARD : COUNTER_COUNT_DIRECTION_BACKWARD;
+ mutex_unlock(&priv->lock);
+
+ return 0;
+}
+
+static int rz_mtu3_count_ceiling_read(struct counter_device *counter,
+ struct counter_count *count,
+ u64 *ceiling)
+{
+ struct rz_mtu3_channel *const ch = rz_mtu3_get_ch(counter, count->id);
+ struct rz_mtu3_cnt *const priv = counter_priv(counter);
+ const size_t ch_id = rz_mtu3_get_hw_ch(count->id);
+ int ret;
+
+ ret = rz_mtu3_lock_if_counter_is_valid(counter, ch, priv, count->id);
+ if (ret)
+ return ret;
+
+ switch (count->id) {
+ case RZ_MTU3_16_BIT_MTU1_CH:
+ case RZ_MTU3_16_BIT_MTU2_CH:
+ *ceiling = priv->mtu_16bit_max[ch_id];
+ break;
+ case RZ_MTU3_32_BIT_CH:
+ *ceiling = priv->mtu_32bit_max;
+ break;
+ default:
+ /* should never reach this path */
+ mutex_unlock(&priv->lock);
+ return -EINVAL;
+ }
+
+ mutex_unlock(&priv->lock);
+ return 0;
+}
+
+static int rz_mtu3_count_ceiling_write(struct counter_device *counter,
+ struct counter_count *count,
+ u64 ceiling)
+{
+ struct rz_mtu3_channel *const ch = rz_mtu3_get_ch(counter, count->id);
+ struct rz_mtu3_cnt *const priv = counter_priv(counter);
+ const size_t ch_id = rz_mtu3_get_hw_ch(count->id);
+ int ret;
+
+ ret = rz_mtu3_lock_if_counter_is_valid(counter, ch, priv, count->id);
+ if (ret)
+ return ret;
+
+ switch (count->id) {
+ case RZ_MTU3_16_BIT_MTU1_CH:
+ case RZ_MTU3_16_BIT_MTU2_CH:
+ if (ceiling > U16_MAX) {
+ mutex_unlock(&priv->lock);
+ return -ERANGE;
+ }
+ priv->mtu_16bit_max[ch_id] = ceiling;
+ break;
+ case RZ_MTU3_32_BIT_CH:
+ if (ceiling > U32_MAX) {
+ mutex_unlock(&priv->lock);
+ return -ERANGE;
+ }
+ priv->mtu_32bit_max = ceiling;
+ break;
+ default:
+ /* should never reach this path */
+ mutex_unlock(&priv->lock);
+ return -EINVAL;
+ }
+
+ pm_runtime_get_sync(ch->dev);
+ if (count->id == RZ_MTU3_32_BIT_CH)
+ rz_mtu3_32bit_ch_write(ch, RZ_MTU3_TGRALW, ceiling);
+ else
+ rz_mtu3_16bit_ch_write(ch, RZ_MTU3_TGRA, ceiling);
+
+ rz_mtu3_8bit_ch_write(ch, RZ_MTU3_TCR, RZ_MTU3_TCR_CCLR_TGRA);
+ pm_runtime_put(ch->dev);
+ mutex_unlock(&priv->lock);
+
+ return 0;
+}
+
+static void rz_mtu3_32bit_cnt_setting(struct counter_device *counter)
+{
+ struct rz_mtu3_channel *const ch1 = rz_mtu3_get_ch(counter, 0);
+ struct rz_mtu3_channel *const ch2 = rz_mtu3_get_ch(counter, 1);
+
+ /* Phase counting mode 1 is used as default in initialization. */
+ rz_mtu3_8bit_ch_write(ch1, RZ_MTU3_TMDR1, RZ_MTU3_TMDR1_PH_CNT_MODE_1);
+
+ rz_mtu3_8bit_ch_write(ch1, RZ_MTU3_TCR, RZ_MTU3_TCR_CCLR_TGRA);
+ rz_mtu3_8bit_ch_write(ch1, RZ_MTU3_TIOR, RZ_MTU3_TIOR_IC_BOTH);
+
+ rz_mtu3_enable(ch1);
+ rz_mtu3_enable(ch2);
+}
+
+static void rz_mtu3_16bit_cnt_setting(struct counter_device *counter, int id)
+{
+ struct rz_mtu3_channel *const ch = rz_mtu3_get_ch(counter, id);
+
+ /* Phase counting mode 1 is used as default in initialization. */
+ rz_mtu3_8bit_ch_write(ch, RZ_MTU3_TMDR1, RZ_MTU3_TMDR1_PH_CNT_MODE_1);
+
+ rz_mtu3_8bit_ch_write(ch, RZ_MTU3_TCR, RZ_MTU3_TCR_CCLR_TGRA);
+ rz_mtu3_8bit_ch_write(ch, RZ_MTU3_TIOR, RZ_MTU3_TIOR_NO_OUTPUT);
+ rz_mtu3_enable(ch);
+}
+
+static int rz_mtu3_initialize_counter(struct counter_device *counter, int id)
+{
+ struct rz_mtu3_channel *const ch = rz_mtu3_get_ch(counter, id);
+ struct rz_mtu3_channel *const ch1 = rz_mtu3_get_ch(counter, 0);
+ struct rz_mtu3_channel *const ch2 = rz_mtu3_get_ch(counter, 1);
+
+ switch (id) {
+ case RZ_MTU3_16_BIT_MTU1_CH:
+ case RZ_MTU3_16_BIT_MTU2_CH:
+ if (!rz_mtu3_request_channel(ch))
+ return -EBUSY;
+
+ rz_mtu3_16bit_cnt_setting(counter, id);
+ return 0;
+ case RZ_MTU3_32_BIT_CH:
+ /*
+ * 32-bit phase counting need MTU1 and MTU2 to create 32-bit
+ * cascade counter.
+ */
+ if (!rz_mtu3_request_channel(ch1))
+ return -EBUSY;
+
+ if (!rz_mtu3_request_channel(ch2)) {
+ rz_mtu3_release_channel(ch1);
+ return -EBUSY;
+ }
+
+ rz_mtu3_32bit_cnt_setting(counter);
+ return 0;
+ default:
+ /* should never reach this path */
+ return -EINVAL;
+ }
+}
+
+static void rz_mtu3_terminate_counter(struct counter_device *counter, int id)
+{
+ struct rz_mtu3_channel *const ch = rz_mtu3_get_ch(counter, id);
+ struct rz_mtu3_channel *const ch1 = rz_mtu3_get_ch(counter, 0);
+ struct rz_mtu3_channel *const ch2 = rz_mtu3_get_ch(counter, 1);
+
+ if (id == RZ_MTU3_32_BIT_CH) {
+ rz_mtu3_release_channel(ch2);
+ rz_mtu3_release_channel(ch1);
+ rz_mtu3_disable(ch2);
+ rz_mtu3_disable(ch1);
+ } else {
+ rz_mtu3_release_channel(ch);
+ rz_mtu3_disable(ch);
+ }
+}
+
+static int rz_mtu3_count_enable_read(struct counter_device *counter,
+ struct counter_count *count, u8 *enable)
+{
+ struct rz_mtu3_channel *const ch = rz_mtu3_get_ch(counter, count->id);
+ struct rz_mtu3_channel *const ch1 = rz_mtu3_get_ch(counter, 0);
+ struct rz_mtu3_channel *const ch2 = rz_mtu3_get_ch(counter, 1);
+ struct rz_mtu3_cnt *const priv = counter_priv(counter);
+ int ret;
+
+ ret = rz_mtu3_lock_if_count_is_enabled(ch, priv, count->id);
+ if (ret)
+ return ret;
+
+ if (count->id == RZ_MTU3_32_BIT_CH)
+ *enable = rz_mtu3_is_enabled(ch1) && rz_mtu3_is_enabled(ch2);
+ else
+ *enable = rz_mtu3_is_enabled(ch);
+
+ mutex_unlock(&priv->lock);
+
+ return 0;
+}
+
+static int rz_mtu3_count_enable_write(struct counter_device *counter,
+ struct counter_count *count, u8 enable)
+{
+ struct rz_mtu3_channel *const ch = rz_mtu3_get_ch(counter, count->id);
+ struct rz_mtu3_cnt *const priv = counter_priv(counter);
+ int ret = 0;
+
+ if (enable) {
+ pm_runtime_get_sync(ch->dev);
+ mutex_lock(&priv->lock);
+ ret = rz_mtu3_initialize_counter(counter, count->id);
+ if (ret == 0)
+ priv->count_is_enabled[count->id] = true;
+ mutex_unlock(&priv->lock);
+ } else {
+ mutex_lock(&priv->lock);
+ rz_mtu3_terminate_counter(counter, count->id);
+ priv->count_is_enabled[count->id] = false;
+ mutex_unlock(&priv->lock);
+ pm_runtime_put(ch->dev);
+ }
+
+ return ret;
+}
+
+static int rz_mtu3_lock_if_ch0_is_enabled(struct rz_mtu3_cnt *const priv)
+{
+ mutex_lock(&priv->lock);
+ if (priv->ch->is_busy && !(priv->count_is_enabled[RZ_MTU3_16_BIT_MTU1_CH] ||
+ priv->count_is_enabled[RZ_MTU3_32_BIT_CH])) {
+ mutex_unlock(&priv->lock);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int rz_mtu3_cascade_counts_enable_get(struct counter_device *counter,
+ u8 *cascade_enable)
+{
+ struct rz_mtu3_cnt *const priv = counter_priv(counter);
+ unsigned long tmdr;
+ int ret;
+
+ ret = rz_mtu3_lock_if_ch0_is_enabled(priv);
+ if (ret)
+ return ret;
+
+ pm_runtime_get_sync(priv->ch->dev);
+ tmdr = rz_mtu3_shared_reg_read(priv->ch, RZ_MTU3_TMDR3);
+ pm_runtime_put(priv->ch->dev);
+ *cascade_enable = test_bit(RZ_MTU3_TMDR3_LWA, &tmdr);
+ mutex_unlock(&priv->lock);
+
+ return 0;
+}
+
+static int rz_mtu3_cascade_counts_enable_set(struct counter_device *counter,
+ u8 cascade_enable)
+{
+ struct rz_mtu3_cnt *const priv = counter_priv(counter);
+ int ret;
+
+ ret = rz_mtu3_lock_if_ch0_is_enabled(priv);
+ if (ret)
+ return ret;
+
+ pm_runtime_get_sync(priv->ch->dev);
+ rz_mtu3_shared_reg_update_bit(priv->ch, RZ_MTU3_TMDR3,
+ RZ_MTU3_TMDR3_LWA, cascade_enable);
+ pm_runtime_put(priv->ch->dev);
+ mutex_unlock(&priv->lock);
+
+ return 0;
+}
+
+static int rz_mtu3_ext_input_phase_clock_select_get(struct counter_device *counter,
+ u32 *ext_input_phase_clock_select)
+{
+ struct rz_mtu3_cnt *const priv = counter_priv(counter);
+ unsigned long tmdr;
+ int ret;
+
+ ret = rz_mtu3_lock_if_ch0_is_enabled(priv);
+ if (ret)
+ return ret;
+
+ pm_runtime_get_sync(priv->ch->dev);
+ tmdr = rz_mtu3_shared_reg_read(priv->ch, RZ_MTU3_TMDR3);
+ pm_runtime_put(priv->ch->dev);
+ *ext_input_phase_clock_select = test_bit(RZ_MTU3_TMDR3_PHCKSEL, &tmdr);
+ mutex_unlock(&priv->lock);
+
+ return 0;
+}
+
+static int rz_mtu3_ext_input_phase_clock_select_set(struct counter_device *counter,
+ u32 ext_input_phase_clock_select)
+{
+ struct rz_mtu3_cnt *const priv = counter_priv(counter);
+ int ret;
+
+ ret = rz_mtu3_lock_if_ch0_is_enabled(priv);
+ if (ret)
+ return ret;
+
+ pm_runtime_get_sync(priv->ch->dev);
+ rz_mtu3_shared_reg_update_bit(priv->ch, RZ_MTU3_TMDR3,
+ RZ_MTU3_TMDR3_PHCKSEL,
+ ext_input_phase_clock_select);
+ pm_runtime_put(priv->ch->dev);
+ mutex_unlock(&priv->lock);
+
+ return 0;
+}
+
+static struct counter_comp rz_mtu3_count_ext[] = {
+ COUNTER_COMP_DIRECTION(rz_mtu3_count_direction_read),
+ COUNTER_COMP_ENABLE(rz_mtu3_count_enable_read,
+ rz_mtu3_count_enable_write),
+ COUNTER_COMP_CEILING(rz_mtu3_count_ceiling_read,
+ rz_mtu3_count_ceiling_write),
+};
+
+static const enum counter_synapse_action rz_mtu3_synapse_actions[] = {
+ COUNTER_SYNAPSE_ACTION_BOTH_EDGES,
+ COUNTER_SYNAPSE_ACTION_RISING_EDGE,
+ COUNTER_SYNAPSE_ACTION_NONE,
+};
+
+static int rz_mtu3_action_read(struct counter_device *counter,
+ struct counter_count *count,
+ struct counter_synapse *synapse,
+ enum counter_synapse_action *action)
+{
+ const bool is_signal_ab = (synapse->signal->id == SIGNAL_A_ID) ||
+ (synapse->signal->id == SIGNAL_B_ID);
+ struct rz_mtu3_channel *const ch = rz_mtu3_get_ch(counter, count->id);
+ struct rz_mtu3_cnt *const priv = counter_priv(counter);
+ enum counter_function function;
+ bool mtclkc_mtclkd;
+ unsigned long tmdr;
+ int ret;
+
+ ret = rz_mtu3_lock_if_count_is_enabled(ch, priv, count->id);
+ if (ret)
+ return ret;
+
+ ret = rz_mtu3_count_function_read_helper(ch, priv, &function);
+ if (ret) {
+ mutex_unlock(&priv->lock);
+ return ret;
+ }
+
+ /* Default action mode */
+ *action = COUNTER_SYNAPSE_ACTION_NONE;
+
+ if (count->id != RZ_MTU3_16_BIT_MTU1_CH) {
+ tmdr = rz_mtu3_shared_reg_read(priv->ch, RZ_MTU3_TMDR3);
+ mtclkc_mtclkd = test_bit(RZ_MTU3_TMDR3_PHCKSEL, &tmdr);
+ if ((mtclkc_mtclkd && is_signal_ab) ||
+ (!mtclkc_mtclkd && !is_signal_ab)) {
+ mutex_unlock(&priv->lock);
+ return 0;
+ }
+ }
+
+ switch (function) {
+ case COUNTER_FUNCTION_PULSE_DIRECTION:
+ /*
+ * Rising edges on signal A (signal C) updates the respective
+ * count. The input level of signal B (signal D) determines
+ * direction.
+ */
+ if (synapse->signal->id == SIGNAL_A_ID ||
+ synapse->signal->id == SIGNAL_C_ID)
+ *action = COUNTER_SYNAPSE_ACTION_RISING_EDGE;
+ break;
+ case COUNTER_FUNCTION_QUADRATURE_X2_B:
+ /*
+ * Any state transition on quadrature pair signal B (signal D)
+ * updates the respective count.
+ */
+ if (synapse->signal->id == SIGNAL_B_ID ||
+ synapse->signal->id == SIGNAL_D_ID)
+ *action = COUNTER_SYNAPSE_ACTION_BOTH_EDGES;
+ break;
+ case COUNTER_FUNCTION_QUADRATURE_X4:
+ /* counts up/down on both edges of A (C) and B (D) signal */
+ *action = COUNTER_SYNAPSE_ACTION_BOTH_EDGES;
+ break;
+ default:
+ /* should never reach this path */
+ mutex_unlock(&priv->lock);
+ return -EINVAL;
+ }
+
+ mutex_unlock(&priv->lock);
+
+ return 0;
+}
+
+static const struct counter_ops rz_mtu3_cnt_ops = {
+ .count_read = rz_mtu3_count_read,
+ .count_write = rz_mtu3_count_write,
+ .function_read = rz_mtu3_count_function_read,
+ .function_write = rz_mtu3_count_function_write,
+ .action_read = rz_mtu3_action_read,
+};
+
+#define RZ_MTU3_PHASE_SIGNAL(_id, _name) { \
+ .id = (_id), \
+ .name = (_name), \
+}
+
+static struct counter_signal rz_mtu3_signals[] = {
+ RZ_MTU3_PHASE_SIGNAL(SIGNAL_A_ID, "MTU1 MTCLKA"),
+ RZ_MTU3_PHASE_SIGNAL(SIGNAL_B_ID, "MTU1 MTCLKB"),
+ RZ_MTU3_PHASE_SIGNAL(SIGNAL_C_ID, "MTU2 MTCLKC"),
+ RZ_MTU3_PHASE_SIGNAL(SIGNAL_D_ID, "MTU2 MTCLKD"),
+};
+
+static struct counter_synapse rz_mtu3_mtu1_count_synapses[] = {
+ {
+ .actions_list = rz_mtu3_synapse_actions,
+ .num_actions = ARRAY_SIZE(rz_mtu3_synapse_actions),
+ .signal = rz_mtu3_signals,
+ },
+ {
+ .actions_list = rz_mtu3_synapse_actions,
+ .num_actions = ARRAY_SIZE(rz_mtu3_synapse_actions),
+ .signal = rz_mtu3_signals + 1,
+ }
+};
+
+static struct counter_synapse rz_mtu3_mtu2_count_synapses[] = {
+ {
+ .actions_list = rz_mtu3_synapse_actions,
+ .num_actions = ARRAY_SIZE(rz_mtu3_synapse_actions),
+ .signal = rz_mtu3_signals,
+ },
+ {
+ .actions_list = rz_mtu3_synapse_actions,
+ .num_actions = ARRAY_SIZE(rz_mtu3_synapse_actions),
+ .signal = rz_mtu3_signals + 1,
+ },
+ {
+ .actions_list = rz_mtu3_synapse_actions,
+ .num_actions = ARRAY_SIZE(rz_mtu3_synapse_actions),
+ .signal = rz_mtu3_signals + 2,
+ },
+ {
+ .actions_list = rz_mtu3_synapse_actions,
+ .num_actions = ARRAY_SIZE(rz_mtu3_synapse_actions),
+ .signal = rz_mtu3_signals + 3,
+ }
+};
+
+static struct counter_count rz_mtu3_counts[] = {
+ {
+ .id = RZ_MTU3_16_BIT_MTU1_CH,
+ .name = "Channel 1 Count",
+ .functions_list = rz_mtu3_count_functions,
+ .num_functions = ARRAY_SIZE(rz_mtu3_count_functions),
+ .synapses = rz_mtu3_mtu1_count_synapses,
+ .num_synapses = ARRAY_SIZE(rz_mtu3_mtu1_count_synapses),
+ .ext = rz_mtu3_count_ext,
+ .num_ext = ARRAY_SIZE(rz_mtu3_count_ext),
+ },
+ {
+ .id = RZ_MTU3_16_BIT_MTU2_CH,
+ .name = "Channel 2 Count",
+ .functions_list = rz_mtu3_count_functions,
+ .num_functions = ARRAY_SIZE(rz_mtu3_count_functions),
+ .synapses = rz_mtu3_mtu2_count_synapses,
+ .num_synapses = ARRAY_SIZE(rz_mtu3_mtu2_count_synapses),
+ .ext = rz_mtu3_count_ext,
+ .num_ext = ARRAY_SIZE(rz_mtu3_count_ext),
+ },
+ {
+ .id = RZ_MTU3_32_BIT_CH,
+ .name = "Channel 1 and 2 (cascaded) Count",
+ .functions_list = rz_mtu3_count_functions,
+ .num_functions = ARRAY_SIZE(rz_mtu3_count_functions),
+ .synapses = rz_mtu3_mtu2_count_synapses,
+ .num_synapses = ARRAY_SIZE(rz_mtu3_mtu2_count_synapses),
+ .ext = rz_mtu3_count_ext,
+ .num_ext = ARRAY_SIZE(rz_mtu3_count_ext),
+ }
+};
+
+static const char *const rz_mtu3_ext_input_phase_clock_select[] = {
+ "MTCLKA-MTCLKB",
+ "MTCLKC-MTCLKD",
+};
+
+static DEFINE_COUNTER_ENUM(rz_mtu3_ext_input_phase_clock_select_enum,
+ rz_mtu3_ext_input_phase_clock_select);
+
+static struct counter_comp rz_mtu3_device_ext[] = {
+ COUNTER_COMP_DEVICE_BOOL("cascade_counts_enable",
+ rz_mtu3_cascade_counts_enable_get,
+ rz_mtu3_cascade_counts_enable_set),
+ COUNTER_COMP_DEVICE_ENUM("external_input_phase_clock_select",
+ rz_mtu3_ext_input_phase_clock_select_get,
+ rz_mtu3_ext_input_phase_clock_select_set,
+ rz_mtu3_ext_input_phase_clock_select_enum),
+};
+
+static int rz_mtu3_cnt_pm_runtime_suspend(struct device *dev)
+{
+ struct clk *const clk = dev_get_drvdata(dev);
+
+ clk_disable_unprepare(clk);
+
+ return 0;
+}
+
+static int rz_mtu3_cnt_pm_runtime_resume(struct device *dev)
+{
+ struct clk *const clk = dev_get_drvdata(dev);
+
+ clk_prepare_enable(clk);
+
+ return 0;
+}
+
+static DEFINE_RUNTIME_DEV_PM_OPS(rz_mtu3_cnt_pm_ops,
+ rz_mtu3_cnt_pm_runtime_suspend,
+ rz_mtu3_cnt_pm_runtime_resume, NULL);
+
+static void rz_mtu3_cnt_pm_disable(void *data)
+{
+ struct device *dev = data;
+
+ pm_runtime_disable(dev);
+ pm_runtime_set_suspended(dev);
+}
+
+static int rz_mtu3_cnt_probe(struct platform_device *pdev)
+{
+ struct rz_mtu3 *ddata = dev_get_drvdata(pdev->dev.parent);
+ struct device *dev = &pdev->dev;
+ struct counter_device *counter;
+ struct rz_mtu3_channel *ch;
+ struct rz_mtu3_cnt *priv;
+ unsigned int i;
+ int ret;
+
+ counter = devm_counter_alloc(dev, sizeof(*priv));
+ if (!counter)
+ return -ENOMEM;
+
+ priv = counter_priv(counter);
+ priv->clk = ddata->clk;
+ priv->mtu_32bit_max = U32_MAX;
+ priv->ch = &ddata->channels[RZ_MTU3_CHAN_1];
+ ch = &priv->ch[0];
+ for (i = 0; i < RZ_MTU3_MAX_HW_CNTR_CHANNELS; i++) {
+ ch->dev = dev;
+ priv->mtu_16bit_max[i] = U16_MAX;
+ ch++;
+ }
+
+ mutex_init(&priv->lock);
+ platform_set_drvdata(pdev, priv->clk);
+ clk_prepare_enable(priv->clk);
+ pm_runtime_set_active(&pdev->dev);
+ pm_runtime_enable(&pdev->dev);
+ ret = devm_add_action_or_reset(&pdev->dev, rz_mtu3_cnt_pm_disable, dev);
+ if (ret < 0)
+ goto disable_clock;
+
+ counter->name = dev_name(dev);
+ counter->parent = dev;
+ counter->ops = &rz_mtu3_cnt_ops;
+ counter->counts = rz_mtu3_counts;
+ counter->num_counts = ARRAY_SIZE(rz_mtu3_counts);
+ counter->signals = rz_mtu3_signals;
+ counter->num_signals = ARRAY_SIZE(rz_mtu3_signals);
+ counter->ext = rz_mtu3_device_ext;
+ counter->num_ext = ARRAY_SIZE(rz_mtu3_device_ext);
+
+ /* Register Counter device */
+ ret = devm_counter_add(dev, counter);
+ if (ret < 0) {
+ dev_err_probe(dev, ret, "Failed to add counter\n");
+ goto disable_clock;
+ }
+
+ return 0;
+
+disable_clock:
+ clk_disable_unprepare(priv->clk);
+
+ return ret;
+}
+
+static struct platform_driver rz_mtu3_cnt_driver = {
+ .probe = rz_mtu3_cnt_probe,
+ .driver = {
+ .name = "rz-mtu3-counter",
+ .pm = pm_ptr(&rz_mtu3_cnt_pm_ops),
+ },
+};
+module_platform_driver(rz_mtu3_cnt_driver);
+
+MODULE_AUTHOR("Biju Das <biju.das.jz@bp.renesas.com>");
+MODULE_ALIAS("platform:rz-mtu3-counter");
+MODULE_DESCRIPTION("Renesas RZ/G2L MTU3a counter driver");
+MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS(COUNTER);
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index b81393072715..5521f060d58e 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -1292,6 +1292,18 @@ config GPIO_KEMPLD
This driver can also be built as a module. If so, the module will be
called gpio-kempld.
+config GPIO_LJCA
+ tristate "INTEL La Jolla Cove Adapter GPIO support"
+ depends on MFD_LJCA
+ select GPIOLIB_IRQCHIP
+ default MFD_LJCA
+ help
+ Select this option to enable GPIO driver for the INTEL
+ La Jolla Cove Adapter (LJCA) board.
+
+ This driver can also be built as a module. If so, the module
+ will be called gpio-ljca.
+
config GPIO_LP3943
tristate "TI/National Semiconductor LP3943 GPIO expander"
depends on MFD_LP3943
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 8309b4ff128b..20036af3acb1 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -79,6 +79,7 @@ obj-$(CONFIG_GPIO_IXP4XX) += gpio-ixp4xx.o
obj-$(CONFIG_GPIO_JANZ_TTL) += gpio-janz-ttl.o
obj-$(CONFIG_GPIO_KEMPLD) += gpio-kempld.o
obj-$(CONFIG_GPIO_LATCH) += gpio-latch.o
+obj-$(CONFIG_GPIO_LJCA) += gpio-ljca.o
obj-$(CONFIG_GPIO_LOGICVC) += gpio-logicvc.o
obj-$(CONFIG_GPIO_LOONGSON1) += gpio-loongson1.o
obj-$(CONFIG_GPIO_LOONGSON) += gpio-loongson.o
diff --git a/drivers/gpio/gpio-ljca.c b/drivers/gpio/gpio-ljca.c
new file mode 100644
index 000000000000..87863f0230f5
--- /dev/null
+++ b/drivers/gpio/gpio-ljca.c
@@ -0,0 +1,454 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Intel La Jolla Cove Adapter USB-GPIO driver
+ *
+ * Copyright (c) 2023, Intel Corporation.
+ */
+
+#include <linux/acpi.h>
+#include <linux/bitfield.h>
+#include <linux/bitops.h>
+#include <linux/dev_printk.h>
+#include <linux/gpio/driver.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/kref.h>
+#include <linux/mfd/ljca.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+/* GPIO commands */
+#define LJCA_GPIO_CONFIG 1
+#define LJCA_GPIO_READ 2
+#define LJCA_GPIO_WRITE 3
+#define LJCA_GPIO_INT_EVENT 4
+#define LJCA_GPIO_INT_MASK 5
+#define LJCA_GPIO_INT_UNMASK 6
+
+#define LJCA_GPIO_CONF_DISABLE BIT(0)
+#define LJCA_GPIO_CONF_INPUT BIT(1)
+#define LJCA_GPIO_CONF_OUTPUT BIT(2)
+#define LJCA_GPIO_CONF_PULLUP BIT(3)
+#define LJCA_GPIO_CONF_PULLDOWN BIT(4)
+#define LJCA_GPIO_CONF_DEFAULT BIT(5)
+#define LJCA_GPIO_CONF_INTERRUPT BIT(6)
+#define LJCA_GPIO_INT_TYPE BIT(7)
+
+#define LJCA_GPIO_CONF_EDGE FIELD_PREP(LJCA_GPIO_INT_TYPE, 1)
+#define LJCA_GPIO_CONF_LEVEL FIELD_PREP(LJCA_GPIO_INT_TYPE, 0)
+
+/* Intentional overlap with PULLUP / PULLDOWN */
+#define LJCA_GPIO_CONF_SET BIT(3)
+#define LJCA_GPIO_CONF_CLR BIT(4)
+
+struct gpio_op {
+ u8 index;
+ u8 value;
+} __packed;
+
+struct gpio_packet {
+ u8 num;
+ struct gpio_op item[];
+} __packed;
+
+#define LJCA_GPIO_BUF_SIZE 60
+struct ljca_gpio_dev {
+ struct platform_device *pdev;
+ struct gpio_chip gc;
+ struct ljca_gpio_info *gpio_info;
+ DECLARE_BITMAP(unmasked_irqs, LJCA_MAX_GPIO_NUM);
+ DECLARE_BITMAP(enabled_irqs, LJCA_MAX_GPIO_NUM);
+ DECLARE_BITMAP(reenable_irqs, LJCA_MAX_GPIO_NUM);
+ u8 *connect_mode;
+ /* mutex to protect irq bus */
+ struct mutex irq_lock;
+ struct work_struct work;
+ /* lock to protect package transfer to Hardware */
+ struct mutex trans_lock;
+
+ u8 obuf[LJCA_GPIO_BUF_SIZE];
+ u8 ibuf[LJCA_GPIO_BUF_SIZE];
+};
+
+static int gpio_config(struct ljca_gpio_dev *ljca_gpio, u8 gpio_id, u8 config)
+{
+ struct gpio_packet *packet = (struct gpio_packet *)ljca_gpio->obuf;
+ int ret;
+
+ mutex_lock(&ljca_gpio->trans_lock);
+ packet->item[0].index = gpio_id;
+ packet->item[0].value = config | ljca_gpio->connect_mode[gpio_id];
+ packet->num = 1;
+
+ ret = ljca_transfer(ljca_gpio->gpio_info->ljca, LJCA_GPIO_CONFIG, packet,
+ struct_size(packet, item, packet->num), NULL, NULL);
+ mutex_unlock(&ljca_gpio->trans_lock);
+ return ret;
+}
+
+static int ljca_gpio_read(struct ljca_gpio_dev *ljca_gpio, u8 gpio_id)
+{
+ struct gpio_packet *packet = (struct gpio_packet *)ljca_gpio->obuf;
+ struct gpio_packet *ack_packet = (struct gpio_packet *)ljca_gpio->ibuf;
+ unsigned int ibuf_len = LJCA_GPIO_BUF_SIZE;
+ int ret;
+
+ mutex_lock(&ljca_gpio->trans_lock);
+ packet->num = 1;
+ packet->item[0].index = gpio_id;
+ ret = ljca_transfer(ljca_gpio->gpio_info->ljca, LJCA_GPIO_READ, packet,
+ struct_size(packet, item, packet->num), ljca_gpio->ibuf, &ibuf_len);
+ if (ret)
+ goto out_unlock;
+
+ if (!ibuf_len || ack_packet->num != packet->num) {
+ dev_err(&ljca_gpio->pdev->dev, "failed gpio_id:%u %u", gpio_id, ack_packet->num);
+ ret = -EIO;
+ }
+
+out_unlock:
+ mutex_unlock(&ljca_gpio->trans_lock);
+ if (ret)
+ return ret;
+ return ack_packet->item[0].value > 0;
+}
+
+static int ljca_gpio_write(struct ljca_gpio_dev *ljca_gpio, u8 gpio_id,
+ int value)
+{
+ struct gpio_packet *packet = (struct gpio_packet *)ljca_gpio->obuf;
+ int ret;
+
+ mutex_lock(&ljca_gpio->trans_lock);
+ packet->num = 1;
+ packet->item[0].index = gpio_id;
+ packet->item[0].value = value & 1;
+
+ ret = ljca_transfer(ljca_gpio->gpio_info->ljca, LJCA_GPIO_WRITE, packet,
+ struct_size(packet, item, packet->num), NULL, NULL);
+ mutex_unlock(&ljca_gpio->trans_lock);
+ return ret;
+}
+
+static int ljca_gpio_get_value(struct gpio_chip *chip, unsigned int offset)
+{
+ struct ljca_gpio_dev *ljca_gpio = gpiochip_get_data(chip);
+
+ return ljca_gpio_read(ljca_gpio, offset);
+}
+
+static void ljca_gpio_set_value(struct gpio_chip *chip, unsigned int offset,
+ int val)
+{
+ struct ljca_gpio_dev *ljca_gpio = gpiochip_get_data(chip);
+ int ret;
+
+ ret = ljca_gpio_write(ljca_gpio, offset, val);
+ if (ret)
+ dev_err(chip->parent, "offset:%u val:%d set value failed %d\n", offset, val, ret);
+}
+
+static int ljca_gpio_direction_input(struct gpio_chip *chip,
+ unsigned int offset)
+{
+ struct ljca_gpio_dev *ljca_gpio = gpiochip_get_data(chip);
+ u8 config = LJCA_GPIO_CONF_INPUT | LJCA_GPIO_CONF_CLR;
+
+ return gpio_config(ljca_gpio, offset, config);
+}
+
+static int ljca_gpio_direction_output(struct gpio_chip *chip,
+ unsigned int offset, int val)
+{
+ struct ljca_gpio_dev *ljca_gpio = gpiochip_get_data(chip);
+ u8 config = LJCA_GPIO_CONF_OUTPUT | LJCA_GPIO_CONF_CLR;
+ int ret;
+
+ ret = gpio_config(ljca_gpio, offset, config);
+ if (ret)
+ return ret;
+
+ ljca_gpio_set_value(chip, offset, val);
+ return 0;
+}
+
+static int ljca_gpio_set_config(struct gpio_chip *chip, unsigned int offset,
+ unsigned long config)
+{
+ struct ljca_gpio_dev *ljca_gpio = gpiochip_get_data(chip);
+
+ ljca_gpio->connect_mode[offset] = 0;
+ switch (pinconf_to_config_param(config)) {
+ case PIN_CONFIG_BIAS_PULL_UP:
+ ljca_gpio->connect_mode[offset] |= LJCA_GPIO_CONF_PULLUP;
+ break;
+ case PIN_CONFIG_BIAS_PULL_DOWN:
+ ljca_gpio->connect_mode[offset] |= LJCA_GPIO_CONF_PULLDOWN;
+ break;
+ case PIN_CONFIG_DRIVE_PUSH_PULL:
+ case PIN_CONFIG_PERSIST_STATE:
+ break;
+ default:
+ return -ENOTSUPP;
+ }
+
+ return 0;
+}
+
+static int ljca_gpio_init_valid_mask(struct gpio_chip *chip, unsigned long *valid_mask,
+ unsigned int ngpios)
+{
+ struct ljca_gpio_dev *ljca_gpio = gpiochip_get_data(chip);
+
+ WARN_ON_ONCE(ngpios != ljca_gpio->gpio_info->num);
+ bitmap_copy(valid_mask, ljca_gpio->gpio_info->valid_pin_map, ngpios);
+
+ return 0;
+}
+
+static void ljca_gpio_irq_init_valid_mask(struct gpio_chip *chip, unsigned long *valid_mask,
+ unsigned int ngpios)
+{
+ ljca_gpio_init_valid_mask(chip, valid_mask, ngpios);
+}
+
+static int ljca_enable_irq(struct ljca_gpio_dev *ljca_gpio, int gpio_id, bool enable)
+{
+ struct gpio_packet *packet = (struct gpio_packet *)ljca_gpio->obuf;
+ int ret;
+
+ mutex_lock(&ljca_gpio->trans_lock);
+ packet->num = 1;
+ packet->item[0].index = gpio_id;
+ packet->item[0].value = 0;
+
+ ret = ljca_transfer(ljca_gpio->gpio_info->ljca,
+ enable ? LJCA_GPIO_INT_UNMASK : LJCA_GPIO_INT_MASK, packet,
+ struct_size(packet, item, packet->num), NULL, NULL);
+ mutex_unlock(&ljca_gpio->trans_lock);
+ return ret;
+}
+
+static void ljca_gpio_async(struct work_struct *work)
+{
+ struct ljca_gpio_dev *ljca_gpio = container_of(work, struct ljca_gpio_dev, work);
+ int gpio_id;
+ int unmasked;
+
+ for_each_set_bit(gpio_id, ljca_gpio->reenable_irqs, ljca_gpio->gc.ngpio) {
+ clear_bit(gpio_id, ljca_gpio->reenable_irqs);
+ unmasked = test_bit(gpio_id, ljca_gpio->unmasked_irqs);
+ if (unmasked)
+ ljca_enable_irq(ljca_gpio, gpio_id, true);
+ }
+}
+
+static void ljca_gpio_event_cb(void *context, u8 cmd, const void *evt_data, int len)
+{
+ const struct gpio_packet *packet = evt_data;
+ struct ljca_gpio_dev *ljca_gpio = context;
+ int i;
+ int irq;
+
+ if (cmd != LJCA_GPIO_INT_EVENT)
+ return;
+
+ for (i = 0; i < packet->num; i++) {
+ irq = irq_find_mapping(ljca_gpio->gc.irq.domain, packet->item[i].index);
+ if (!irq) {
+ dev_err(ljca_gpio->gc.parent, "gpio_id %u does not mapped to IRQ yet\n",
+ packet->item[i].index);
+ return;
+ }
+
+ generic_handle_domain_irq(ljca_gpio->gc.irq.domain, irq);
+ set_bit(packet->item[i].index, ljca_gpio->reenable_irqs);
+ }
+
+ schedule_work(&ljca_gpio->work);
+}
+
+static void ljca_irq_unmask(struct irq_data *irqd)
+{
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd);
+ struct ljca_gpio_dev *ljca_gpio = gpiochip_get_data(gc);
+ int gpio_id = irqd_to_hwirq(irqd);
+
+ gpiochip_enable_irq(gc, gpio_id);
+ set_bit(gpio_id, ljca_gpio->unmasked_irqs);
+}
+
+static void ljca_irq_mask(struct irq_data *irqd)
+{
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd);
+ struct ljca_gpio_dev *ljca_gpio = gpiochip_get_data(gc);
+ int gpio_id = irqd_to_hwirq(irqd);
+
+ clear_bit(gpio_id, ljca_gpio->unmasked_irqs);
+ gpiochip_disable_irq(gc, gpio_id);
+}
+
+static int ljca_irq_set_type(struct irq_data *irqd, unsigned int type)
+{
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd);
+ struct ljca_gpio_dev *ljca_gpio = gpiochip_get_data(gc);
+ int gpio_id = irqd_to_hwirq(irqd);
+
+ ljca_gpio->connect_mode[gpio_id] = LJCA_GPIO_CONF_INTERRUPT;
+ switch (type) {
+ case IRQ_TYPE_LEVEL_HIGH:
+ ljca_gpio->connect_mode[gpio_id] |= (LJCA_GPIO_CONF_LEVEL | LJCA_GPIO_CONF_PULLUP);
+ break;
+ case IRQ_TYPE_LEVEL_LOW:
+ ljca_gpio->connect_mode[gpio_id] |= (LJCA_GPIO_CONF_LEVEL | LJCA_GPIO_CONF_PULLDOWN);
+ break;
+ case IRQ_TYPE_EDGE_BOTH:
+ break;
+ case IRQ_TYPE_EDGE_RISING:
+ ljca_gpio->connect_mode[gpio_id] |= (LJCA_GPIO_CONF_EDGE | LJCA_GPIO_CONF_PULLUP);
+ break;
+ case IRQ_TYPE_EDGE_FALLING:
+ ljca_gpio->connect_mode[gpio_id] |= (LJCA_GPIO_CONF_EDGE | LJCA_GPIO_CONF_PULLDOWN);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static void ljca_irq_bus_lock(struct irq_data *irqd)
+{
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd);
+ struct ljca_gpio_dev *ljca_gpio = gpiochip_get_data(gc);
+
+ mutex_lock(&ljca_gpio->irq_lock);
+}
+
+static void ljca_irq_bus_unlock(struct irq_data *irqd)
+{
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd);
+ struct ljca_gpio_dev *ljca_gpio = gpiochip_get_data(gc);
+ int gpio_id = irqd_to_hwirq(irqd);
+ int enabled;
+ int unmasked;
+
+ enabled = test_bit(gpio_id, ljca_gpio->enabled_irqs);
+ unmasked = test_bit(gpio_id, ljca_gpio->unmasked_irqs);
+
+ if (enabled != unmasked) {
+ if (unmasked) {
+ gpio_config(ljca_gpio, gpio_id, 0);
+ ljca_enable_irq(ljca_gpio, gpio_id, true);
+ set_bit(gpio_id, ljca_gpio->enabled_irqs);
+ } else {
+ ljca_enable_irq(ljca_gpio, gpio_id, false);
+ clear_bit(gpio_id, ljca_gpio->enabled_irqs);
+ }
+ }
+
+ mutex_unlock(&ljca_gpio->irq_lock);
+}
+
+static const struct irq_chip ljca_gpio_irqchip = {
+ .name = "ljca-irq",
+ .irq_mask = ljca_irq_mask,
+ .irq_unmask = ljca_irq_unmask,
+ .irq_set_type = ljca_irq_set_type,
+ .irq_bus_lock = ljca_irq_bus_lock,
+ .irq_bus_sync_unlock = ljca_irq_bus_unlock,
+ .flags = IRQCHIP_IMMUTABLE,
+ GPIOCHIP_IRQ_RESOURCE_HELPERS,
+};
+
+static int ljca_gpio_probe(struct platform_device *pdev)
+{
+ struct ljca_gpio_dev *ljca_gpio;
+ struct gpio_irq_chip *girq;
+ int ret;
+
+ ljca_gpio = devm_kzalloc(&pdev->dev, sizeof(*ljca_gpio), GFP_KERNEL);
+ if (!ljca_gpio)
+ return -ENOMEM;
+
+ ljca_gpio->gpio_info = dev_get_platdata(&pdev->dev);
+ ljca_gpio->connect_mode = devm_kcalloc(&pdev->dev, ljca_gpio->gpio_info->num,
+ sizeof(*ljca_gpio->connect_mode), GFP_KERNEL);
+ if (!ljca_gpio->connect_mode)
+ return -ENOMEM;
+
+ mutex_init(&ljca_gpio->irq_lock);
+ mutex_init(&ljca_gpio->trans_lock);
+ ljca_gpio->pdev = pdev;
+ ljca_gpio->gc.direction_input = ljca_gpio_direction_input;
+ ljca_gpio->gc.direction_output = ljca_gpio_direction_output;
+ ljca_gpio->gc.get = ljca_gpio_get_value;
+ ljca_gpio->gc.set = ljca_gpio_set_value;
+ ljca_gpio->gc.set_config = ljca_gpio_set_config;
+ ljca_gpio->gc.init_valid_mask = ljca_gpio_init_valid_mask;
+ ljca_gpio->gc.can_sleep = true;
+ ljca_gpio->gc.parent = &pdev->dev;
+
+ ljca_gpio->gc.base = -1;
+ ljca_gpio->gc.ngpio = ljca_gpio->gpio_info->num;
+ ljca_gpio->gc.label = ACPI_COMPANION(&pdev->dev) ?
+ acpi_dev_name(ACPI_COMPANION(&pdev->dev)) :
+ dev_name(&pdev->dev);
+ ljca_gpio->gc.owner = THIS_MODULE;
+
+ platform_set_drvdata(pdev, ljca_gpio);
+ ljca_register_event_cb(ljca_gpio->gpio_info->ljca, ljca_gpio_event_cb, ljca_gpio);
+
+ girq = &ljca_gpio->gc.irq;
+ gpio_irq_chip_set_chip(girq, &ljca_gpio_irqchip);
+ girq->parent_handler = NULL;
+ girq->num_parents = 0;
+ girq->parents = NULL;
+ girq->default_type = IRQ_TYPE_NONE;
+ girq->handler = handle_simple_irq;
+ girq->init_valid_mask = ljca_gpio_irq_init_valid_mask;
+
+ INIT_WORK(&ljca_gpio->work, ljca_gpio_async);
+ ret = gpiochip_add_data(&ljca_gpio->gc, ljca_gpio);
+ if (ret) {
+ ljca_unregister_event_cb(ljca_gpio->gpio_info->ljca);
+ mutex_destroy(&ljca_gpio->irq_lock);
+ mutex_destroy(&ljca_gpio->trans_lock);
+ }
+
+ return ret;
+}
+
+static int ljca_gpio_remove(struct platform_device *pdev)
+{
+ struct ljca_gpio_dev *ljca_gpio = platform_get_drvdata(pdev);
+
+ gpiochip_remove(&ljca_gpio->gc);
+ ljca_unregister_event_cb(ljca_gpio->gpio_info->ljca);
+ mutex_destroy(&ljca_gpio->irq_lock);
+ mutex_destroy(&ljca_gpio->trans_lock);
+ return 0;
+}
+
+#define LJCA_GPIO_DRV_NAME "ljca-gpio"
+static const struct platform_device_id ljca_gpio_id[] = {
+ { LJCA_GPIO_DRV_NAME, 0 },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(platform, ljca_gpio_id);
+
+static struct platform_driver ljca_gpio_driver = {
+ .driver.name = LJCA_GPIO_DRV_NAME,
+ .probe = ljca_gpio_probe,
+ .remove = ljca_gpio_remove,
+};
+module_platform_driver(ljca_gpio_driver);
+
+MODULE_AUTHOR("Ye Xiang <xiang.ye@intel.com>");
+MODULE_AUTHOR("Wang Zhifeng <zhifeng.wang@intel.com>");
+MODULE_AUTHOR("Zhang Lixu <lixu.zhang@intel.com>");
+MODULE_DESCRIPTION("Intel La Jolla Cove Adapter USB-GPIO driver");
+MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS(LJCA);
diff --git a/drivers/mfd/88pm860x-core.c b/drivers/mfd/88pm860x-core.c
index 6ba7169cb953..aabac37c3502 100644
--- a/drivers/mfd/88pm860x-core.c
+++ b/drivers/mfd/88pm860x-core.c
@@ -1117,8 +1117,7 @@ static int pm860x_dt_init(struct device_node *np,
{
int ret;
- if (of_get_property(np, "marvell,88pm860x-irq-read-clr", NULL))
- pdata->irq_mode = 1;
+ pdata->irq_mode = of_property_read_bool(np, "marvell,88pm860x-irq-read-clr");
ret = of_property_read_u32(np, "marvell,88pm860x-slave-addr",
&pdata->companion_addr);
if (ret) {
@@ -1276,4 +1275,3 @@ module_exit(pm860x_i2c_exit);
MODULE_DESCRIPTION("PMIC Driver for Marvell 88PM860x");
MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index fcc141e067b9..e90463c4441c 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -266,6 +266,16 @@ config MFD_MADERA_SPI
Support for the Cirrus Logic Madera platform audio SoC
core functionality controlled via SPI.
+config MFD_MAX597X
+ tristate "Maxim 597x power switch and monitor"
+ depends on (I2C && OF)
+ select MFD_SIMPLE_MFD_I2C
+ help
+ This driver controls a Maxim 5970/5978 switch via I2C bus.
+ The MAX5970/5978 is a smart switch with no output regulation, but
+ fault protection and voltage and current monitoring capabilities.
+ Also it supports upto 4 indication leds.
+
config MFD_CS47L15
bool "Cirrus Logic CS47L15"
select PINCTRL_CS47L15
@@ -353,9 +363,6 @@ config MFD_DA9055
Additional drivers must be enabled in order to use the functionality
of the device.
- This driver can be built as a module. If built as a module it will be
- called "da9055"
-
config MFD_DA9062
tristate "Dialog Semiconductor DA9062/61 PMIC Support"
select MFD_CORE
@@ -1308,6 +1315,16 @@ config MFD_SC27XX_PMIC
This driver provides common support for accessing the SC27xx PMICs,
and it also adds the irq_chip parts for handling the PMIC chip events.
+config RZ_MTU3
+ bool "Renesas RZ/G2L MTU3a core driver"
+ depends on (ARCH_RZG2L && OF) || COMPILE_TEST
+ help
+ Select this option to enable Renesas RZ/G2L MTU3a core driver for
+ the Multi-Function Timer Pulse Unit 3 (MTU3a) hardware available
+ on SoCs from Renesas. The core driver shares the clk and channel
+ register access for the other child devices like Counter, PWM,
+ Clock Source, and Clock event.
+
config ABX500_CORE
bool "ST-Ericsson ABX500 Mixed Signal Circuit register functions"
depends on ARCH_U8500 || COMPILE_TEST
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 2f6c89d1e277..1d2392f06f78 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -174,6 +174,7 @@ pcf50633-objs := pcf50633-core.o pcf50633-irq.o
obj-$(CONFIG_MFD_PCF50633) += pcf50633.o
obj-$(CONFIG_PCF50633_ADC) += pcf50633-adc.o
obj-$(CONFIG_PCF50633_GPIO) += pcf50633-gpio.o
+obj-$(CONFIG_RZ_MTU3) += rz-mtu3.o
obj-$(CONFIG_ABX500_CORE) += abx500-core.o
obj-$(CONFIG_MFD_DB8500_PRCMU) += db8500-prcmu.o
# ab8500-core need to come after db8500-prcmu (which provides the channel)
diff --git a/drivers/mfd/arizona-i2c.c b/drivers/mfd/arizona-i2c.c
index b2301586adbc..43e393c8608d 100644
--- a/drivers/mfd/arizona-i2c.c
+++ b/drivers/mfd/arizona-i2c.c
@@ -112,6 +112,7 @@ static const struct of_device_id arizona_i2c_of_match[] = {
{ .compatible = "wlf,wm1814", .data = (void *)WM1814 },
{},
};
+MODULE_DEVICE_TABLE(of, arizona_i2c_of_match);
#endif
static struct i2c_driver arizona_i2c_driver = {
diff --git a/drivers/mfd/arizona-spi.c b/drivers/mfd/arizona-spi.c
index da05b966d48c..02cf4f3e91d7 100644
--- a/drivers/mfd/arizona-spi.c
+++ b/drivers/mfd/arizona-spi.c
@@ -277,6 +277,7 @@ static const struct of_device_id arizona_spi_of_match[] = {
{ .compatible = "cirrus,cs47l24", .data = (void *)CS47L24 },
{},
};
+MODULE_DEVICE_TABLE(of, arizona_spi_of_match);
#endif
static struct spi_driver arizona_spi_driver = {
diff --git a/drivers/mfd/atc260x-i2c.c b/drivers/mfd/atc260x-i2c.c
index 19e248ed7966..8e1491167160 100644
--- a/drivers/mfd/atc260x-i2c.c
+++ b/drivers/mfd/atc260x-i2c.c
@@ -51,7 +51,7 @@ MODULE_DEVICE_TABLE(of, atc260x_i2c_of_match);
static struct i2c_driver atc260x_i2c_driver = {
.driver = {
.name = "atc260x",
- .of_match_table = of_match_ptr(atc260x_i2c_of_match),
+ .of_match_table = atc260x_i2c_of_match,
},
.probe_new = atc260x_i2c_probe,
};
diff --git a/drivers/mfd/atmel-flexcom.c b/drivers/mfd/atmel-flexcom.c
index 33caa4fba6af..b52f7ffdad35 100644
--- a/drivers/mfd/atmel-flexcom.c
+++ b/drivers/mfd/atmel-flexcom.c
@@ -37,7 +37,6 @@ struct atmel_flexcom {
static int atmel_flexcom_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
- struct resource *res;
struct atmel_flexcom *ddata;
int err;
@@ -55,8 +54,7 @@ static int atmel_flexcom_probe(struct platform_device *pdev)
ddata->opmode > ATMEL_FLEXCOM_MODE_TWI)
return -EINVAL;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- ddata->base = devm_ioremap_resource(&pdev->dev, res);
+ ddata->base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
if (IS_ERR(ddata->base))
return PTR_ERR(ddata->base);
diff --git a/drivers/mfd/atmel-smc.c b/drivers/mfd/atmel-smc.c
index f3bad2b52f17..e560066e5885 100644
--- a/drivers/mfd/atmel-smc.c
+++ b/drivers/mfd/atmel-smc.c
@@ -323,7 +323,7 @@ static const struct atmel_hsmc_reg_layout sama5d2_reg_layout = {
.timing_regs_offset = 0x700,
};
-static const struct of_device_id atmel_smc_ids[] = {
+static const struct of_device_id atmel_smc_ids[] __maybe_unused = {
{ .compatible = "atmel,at91sam9260-smc", .data = NULL },
{ .compatible = "atmel,sama5d3-smc", .data = &sama5d3_reg_layout },
{ .compatible = "atmel,sama5d2-smc", .data = &sama5d2_reg_layout },
diff --git a/drivers/mfd/axp20x-i2c.c b/drivers/mfd/axp20x-i2c.c
index f49fbd307958..b4f5cb457117 100644
--- a/drivers/mfd/axp20x-i2c.c
+++ b/drivers/mfd/axp20x-i2c.c
@@ -65,6 +65,7 @@ static const struct of_device_id axp20x_i2c_of_match[] = {
{ .compatible = "x-powers,axp223", .data = (void *)AXP223_ID },
{ .compatible = "x-powers,axp803", .data = (void *)AXP803_ID },
{ .compatible = "x-powers,axp806", .data = (void *)AXP806_ID },
+ { .compatible = "x-powers,axp15060", .data = (void *)AXP15060_ID },
{ },
};
MODULE_DEVICE_TABLE(of, axp20x_i2c_of_match);
@@ -78,6 +79,7 @@ static const struct i2c_device_id axp20x_i2c_id[] = {
{ "axp223", 0 },
{ "axp803", 0 },
{ "axp806", 0 },
+ { "axp15060", 0 },
{ },
};
MODULE_DEVICE_TABLE(i2c, axp20x_i2c_id);
diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c
index 01a6bbb6d266..72b87aae60cc 100644
--- a/drivers/mfd/axp20x.c
+++ b/drivers/mfd/axp20x.c
@@ -43,6 +43,7 @@ static const char * const axp20x_model_names[] = {
"AXP806",
"AXP809",
"AXP813",
+ "AXP15060",
};
static const struct regmap_range axp152_writeable_ranges[] = {
@@ -119,6 +120,7 @@ static const struct regmap_access_table axp22x_volatile_table = {
/* AXP288 ranges are shared with the AXP803, as they cover the same range */
static const struct regmap_range axp288_writeable_ranges[] = {
+ regmap_reg_range(AXP288_POWER_REASON, AXP288_POWER_REASON),
regmap_reg_range(AXP20X_DATACACHE(0), AXP20X_IRQ6_STATE),
regmap_reg_range(AXP20X_DCDC_MODE, AXP288_FG_TUNE5),
};
@@ -168,6 +170,31 @@ static const struct regmap_access_table axp806_volatile_table = {
.n_yes_ranges = ARRAY_SIZE(axp806_volatile_ranges),
};
+static const struct regmap_range axp15060_writeable_ranges[] = {
+ regmap_reg_range(AXP15060_PWR_OUT_CTRL1, AXP15060_DCDC_MODE_CTRL2),
+ regmap_reg_range(AXP15060_OUTPUT_MONITOR_DISCHARGE, AXP15060_CPUSLDO_V_CTRL),
+ regmap_reg_range(AXP15060_PWR_WAKEUP_CTRL, AXP15060_PWR_DISABLE_DOWN_SEQ),
+ regmap_reg_range(AXP15060_PEK_KEY, AXP15060_PEK_KEY),
+ regmap_reg_range(AXP15060_IRQ1_EN, AXP15060_IRQ2_EN),
+ regmap_reg_range(AXP15060_IRQ1_STATE, AXP15060_IRQ2_STATE),
+};
+
+static const struct regmap_range axp15060_volatile_ranges[] = {
+ regmap_reg_range(AXP15060_STARTUP_SRC, AXP15060_STARTUP_SRC),
+ regmap_reg_range(AXP15060_PWR_WAKEUP_CTRL, AXP15060_PWR_DISABLE_DOWN_SEQ),
+ regmap_reg_range(AXP15060_IRQ1_STATE, AXP15060_IRQ2_STATE),
+};
+
+static const struct regmap_access_table axp15060_writeable_table = {
+ .yes_ranges = axp15060_writeable_ranges,
+ .n_yes_ranges = ARRAY_SIZE(axp15060_writeable_ranges),
+};
+
+static const struct regmap_access_table axp15060_volatile_table = {
+ .yes_ranges = axp15060_volatile_ranges,
+ .n_yes_ranges = ARRAY_SIZE(axp15060_volatile_ranges),
+};
+
static const struct resource axp152_pek_resources[] = {
DEFINE_RES_IRQ_NAMED(AXP152_IRQ_PEK_RIS_EDGE, "PEK_DBR"),
DEFINE_RES_IRQ_NAMED(AXP152_IRQ_PEK_FAL_EDGE, "PEK_DBF"),
@@ -236,6 +263,11 @@ static const struct resource axp809_pek_resources[] = {
DEFINE_RES_IRQ_NAMED(AXP809_IRQ_PEK_FAL_EDGE, "PEK_DBF"),
};
+static const struct resource axp15060_pek_resources[] = {
+ DEFINE_RES_IRQ_NAMED(AXP15060_IRQ_PEK_RIS_EDGE, "PEK_DBR"),
+ DEFINE_RES_IRQ_NAMED(AXP15060_IRQ_PEK_FAL_EDGE, "PEK_DBF"),
+};
+
static const struct regmap_config axp152_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
@@ -281,6 +313,15 @@ static const struct regmap_config axp806_regmap_config = {
.cache_type = REGCACHE_RBTREE,
};
+static const struct regmap_config axp15060_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .wr_table = &axp15060_writeable_table,
+ .volatile_table = &axp15060_volatile_table,
+ .max_register = AXP15060_IRQ2_STATE,
+ .cache_type = REGCACHE_RBTREE,
+};
+
#define INIT_REGMAP_IRQ(_variant, _irq, _off, _mask) \
[_variant##_IRQ_##_irq] = { .reg_offset = (_off), .mask = BIT(_mask) }
@@ -502,6 +543,23 @@ static const struct regmap_irq axp809_regmap_irqs[] = {
INIT_REGMAP_IRQ(AXP809, GPIO0_INPUT, 4, 0),
};
+static const struct regmap_irq axp15060_regmap_irqs[] = {
+ INIT_REGMAP_IRQ(AXP15060, DIE_TEMP_HIGH_LV1, 0, 0),
+ INIT_REGMAP_IRQ(AXP15060, DIE_TEMP_HIGH_LV2, 0, 1),
+ INIT_REGMAP_IRQ(AXP15060, DCDC1_V_LOW, 0, 2),
+ INIT_REGMAP_IRQ(AXP15060, DCDC2_V_LOW, 0, 3),
+ INIT_REGMAP_IRQ(AXP15060, DCDC3_V_LOW, 0, 4),
+ INIT_REGMAP_IRQ(AXP15060, DCDC4_V_LOW, 0, 5),
+ INIT_REGMAP_IRQ(AXP15060, DCDC5_V_LOW, 0, 6),
+ INIT_REGMAP_IRQ(AXP15060, DCDC6_V_LOW, 0, 7),
+ INIT_REGMAP_IRQ(AXP15060, PEK_LONG, 1, 0),
+ INIT_REGMAP_IRQ(AXP15060, PEK_SHORT, 1, 1),
+ INIT_REGMAP_IRQ(AXP15060, GPIO1_INPUT, 1, 2),
+ INIT_REGMAP_IRQ(AXP15060, PEK_FAL_EDGE, 1, 3),
+ INIT_REGMAP_IRQ(AXP15060, PEK_RIS_EDGE, 1, 4),
+ INIT_REGMAP_IRQ(AXP15060, GPIO2_INPUT, 1, 5),
+};
+
static const struct regmap_irq_chip axp152_regmap_irq_chip = {
.name = "axp152_irq_chip",
.status_base = AXP152_IRQ1_STATE,
@@ -581,6 +639,17 @@ static const struct regmap_irq_chip axp809_regmap_irq_chip = {
.num_regs = 5,
};
+static const struct regmap_irq_chip axp15060_regmap_irq_chip = {
+ .name = "axp15060",
+ .status_base = AXP15060_IRQ1_STATE,
+ .ack_base = AXP15060_IRQ1_STATE,
+ .unmask_base = AXP15060_IRQ1_EN,
+ .init_ack_masked = true,
+ .irqs = axp15060_regmap_irqs,
+ .num_irqs = ARRAY_SIZE(axp15060_regmap_irqs),
+ .num_regs = 2,
+};
+
static const struct mfd_cell axp20x_cells[] = {
{
.name = "axp20x-gpio",
@@ -825,6 +894,23 @@ static const struct mfd_cell axp813_cells[] = {
},
};
+static const struct mfd_cell axp15060_cells[] = {
+ {
+ .name = "axp221-pek",
+ .num_resources = ARRAY_SIZE(axp15060_pek_resources),
+ .resources = axp15060_pek_resources,
+ }, {
+ .name = "axp20x-regulator",
+ },
+};
+
+/* For boards that don't have IRQ line connected to SOC. */
+static const struct mfd_cell axp_regulator_only_cells[] = {
+ {
+ .name = "axp20x-regulator",
+ },
+};
+
static int axp20x_power_off(struct sys_off_data *data)
{
struct axp20x_dev *axp20x = data->cb_data;
@@ -934,6 +1020,28 @@ int axp20x_match_device(struct axp20x_dev *axp20x)
*/
axp20x->regmap_irq_chip = &axp803_regmap_irq_chip;
break;
+ case AXP15060_ID:
+ /*
+ * Don't register the power key part if there is no interrupt
+ * line.
+ *
+ * Since most use cases of AXP PMICs are Allwinner SOCs, board
+ * designers follow Allwinner's reference design and connects
+ * IRQ line to SOC, there's no need for those variants to deal
+ * with cases that IRQ isn't connected. However, AXP15660 is
+ * used by some other vendors' SOCs that didn't connect IRQ
+ * line, we need to deal with this case.
+ */
+ if (axp20x->irq > 0) {
+ axp20x->nr_cells = ARRAY_SIZE(axp15060_cells);
+ axp20x->cells = axp15060_cells;
+ } else {
+ axp20x->nr_cells = ARRAY_SIZE(axp_regulator_only_cells);
+ axp20x->cells = axp_regulator_only_cells;
+ }
+ axp20x->regmap_cfg = &axp15060_regmap_config;
+ axp20x->regmap_irq_chip = &axp15060_regmap_irq_chip;
+ break;
default:
dev_err(dev, "unsupported AXP20X ID %lu\n", axp20x->variant);
return -EINVAL;
diff --git a/drivers/mfd/bcm2835-pm.c b/drivers/mfd/bcm2835-pm.c
index 49cd1f03884a..3cb2b9423121 100644
--- a/drivers/mfd/bcm2835-pm.c
+++ b/drivers/mfd/bcm2835-pm.c
@@ -28,7 +28,7 @@ static const struct mfd_cell bcm2835_power_devs[] = {
static int bcm2835_pm_get_pdata(struct platform_device *pdev,
struct bcm2835_pm *pm)
{
- if (of_find_property(pm->dev->of_node, "reg-names", NULL)) {
+ if (of_property_present(pm->dev->of_node, "reg-names")) {
struct resource *res;
pm->base = devm_platform_ioremap_resource_byname(pdev, "pm");
@@ -123,4 +123,3 @@ module_platform_driver(bcm2835_pm_driver);
MODULE_AUTHOR("Eric Anholt <eric@anholt.net>");
MODULE_DESCRIPTION("Driver for Broadcom BCM2835 PM MFD");
-MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/da903x.c b/drivers/mfd/da903x.c
index 44a25d642ce9..6570b33a5a77 100644
--- a/drivers/mfd/da903x.c
+++ b/drivers/mfd/da903x.c
@@ -563,4 +563,3 @@ module_exit(da903x_exit);
MODULE_DESCRIPTION("PMIC Driver for Dialog Semiconductor DA9034");
MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>");
MODULE_AUTHOR("Mike Rapoport <mike@compulab.co.il>");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/mfd/da9052-core.c b/drivers/mfd/da9052-core.c
index 8b42d2f7024f..150448cd2eb0 100644
--- a/drivers/mfd/da9052-core.c
+++ b/drivers/mfd/da9052-core.c
@@ -653,4 +653,3 @@ void da9052_device_exit(struct da9052 *da9052)
MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>");
MODULE_DESCRIPTION("DA9052 MFD Core");
-MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/da9052-i2c.c b/drivers/mfd/da9052-i2c.c
index ecb8077cdaaf..03db7a2ccf7a 100644
--- a/drivers/mfd/da9052-i2c.c
+++ b/drivers/mfd/da9052-i2c.c
@@ -209,4 +209,3 @@ module_exit(da9052_i2c_exit);
MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>");
MODULE_DESCRIPTION("I2C driver for Dialog DA9052 PMIC");
-MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/da9052-spi.c b/drivers/mfd/da9052-spi.c
index b79a57b45c1e..be5f2b34e18a 100644
--- a/drivers/mfd/da9052-spi.c
+++ b/drivers/mfd/da9052-spi.c
@@ -102,4 +102,3 @@ module_exit(da9052_spi_exit);
MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>");
MODULE_DESCRIPTION("SPI driver for Dialog DA9052 PMIC");
-MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/da9055-core.c b/drivers/mfd/da9055-core.c
index c3bcbd8905c6..768302e05baa 100644
--- a/drivers/mfd/da9055-core.c
+++ b/drivers/mfd/da9055-core.c
@@ -398,5 +398,4 @@ void da9055_device_exit(struct da9055 *da9055)
}
MODULE_DESCRIPTION("Core support for the DA9055 PMIC");
-MODULE_LICENSE("GPL");
MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>");
diff --git a/drivers/mfd/da9055-i2c.c b/drivers/mfd/da9055-i2c.c
index 702abff506a1..537fd5de3e6d 100644
--- a/drivers/mfd/da9055-i2c.c
+++ b/drivers/mfd/da9055-i2c.c
@@ -97,4 +97,3 @@ module_exit(da9055_i2c_exit);
MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>");
MODULE_DESCRIPTION("I2C driver for Dialog DA9055 PMIC");
-MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/da9062-core.c b/drivers/mfd/da9062-core.c
index 40cde51e5719..d073d5f106ec 100644
--- a/drivers/mfd/da9062-core.c
+++ b/drivers/mfd/da9062-core.c
@@ -181,35 +181,25 @@ static const struct resource da9061_onkey_resources[] = {
DEFINE_RES_IRQ_NAMED(DA9061_IRQ_ONKEY, "ONKEY"),
};
-static const struct mfd_cell da9061_devs[] = {
- {
- .name = "da9061-core",
- .num_resources = ARRAY_SIZE(da9061_core_resources),
- .resources = da9061_core_resources,
- },
- {
- .name = "da9062-regulators",
- .num_resources = ARRAY_SIZE(da9061_regulators_resources),
- .resources = da9061_regulators_resources,
- },
- {
- .name = "da9061-watchdog",
- .num_resources = ARRAY_SIZE(da9061_wdt_resources),
- .resources = da9061_wdt_resources,
- .of_compatible = "dlg,da9061-watchdog",
- },
- {
- .name = "da9061-thermal",
- .num_resources = ARRAY_SIZE(da9061_thermal_resources),
- .resources = da9061_thermal_resources,
- .of_compatible = "dlg,da9061-thermal",
- },
- {
- .name = "da9061-onkey",
- .num_resources = ARRAY_SIZE(da9061_onkey_resources),
- .resources = da9061_onkey_resources,
- .of_compatible = "dlg,da9061-onkey",
- },
+static const struct mfd_cell da9061_devs_irq[] = {
+ MFD_CELL_OF("da9061-core", da9061_core_resources, NULL, 0, 0,
+ NULL),
+ MFD_CELL_OF("da9062-regulators", da9061_regulators_resources, NULL, 0, 0,
+ NULL),
+ MFD_CELL_OF("da9061-watchdog", da9061_wdt_resources, NULL, 0, 0,
+ "dlg,da9061-watchdog"),
+ MFD_CELL_OF("da9061-thermal", da9061_thermal_resources, NULL, 0, 0,
+ "dlg,da9061-thermal"),
+ MFD_CELL_OF("da9061-onkey", da9061_onkey_resources, NULL, 0, 0,
+ "dlg,da9061-onkey"),
+};
+
+static const struct mfd_cell da9061_devs_noirq[] = {
+ MFD_CELL_OF("da9061-core", NULL, NULL, 0, 0, NULL),
+ MFD_CELL_OF("da9062-regulators", NULL, NULL, 0, 0, NULL),
+ MFD_CELL_OF("da9061-watchdog", NULL, NULL, 0, 0, "dlg,da9061-watchdog"),
+ MFD_CELL_OF("da9061-thermal", NULL, NULL, 0, 0, "dlg,da9061-thermal"),
+ MFD_CELL_OF("da9061-onkey", NULL, NULL, 0, 0, "dlg,da9061-onkey"),
};
static const struct resource da9062_core_resources[] = {
@@ -245,47 +235,31 @@ static const struct resource da9062_gpio_resources[] = {
DEFINE_RES_NAMED(DA9062_IRQ_GPI4, 1, "GPI4", IORESOURCE_IRQ),
};
-static const struct mfd_cell da9062_devs[] = {
- {
- .name = "da9062-core",
- .num_resources = ARRAY_SIZE(da9062_core_resources),
- .resources = da9062_core_resources,
- },
- {
- .name = "da9062-regulators",
- .num_resources = ARRAY_SIZE(da9062_regulators_resources),
- .resources = da9062_regulators_resources,
- },
- {
- .name = "da9062-watchdog",
- .num_resources = ARRAY_SIZE(da9062_wdt_resources),
- .resources = da9062_wdt_resources,
- .of_compatible = "dlg,da9062-watchdog",
- },
- {
- .name = "da9062-thermal",
- .num_resources = ARRAY_SIZE(da9062_thermal_resources),
- .resources = da9062_thermal_resources,
- .of_compatible = "dlg,da9062-thermal",
- },
- {
- .name = "da9062-rtc",
- .num_resources = ARRAY_SIZE(da9062_rtc_resources),
- .resources = da9062_rtc_resources,
- .of_compatible = "dlg,da9062-rtc",
- },
- {
- .name = "da9062-onkey",
- .num_resources = ARRAY_SIZE(da9062_onkey_resources),
- .resources = da9062_onkey_resources,
- .of_compatible = "dlg,da9062-onkey",
- },
- {
- .name = "da9062-gpio",
- .num_resources = ARRAY_SIZE(da9062_gpio_resources),
- .resources = da9062_gpio_resources,
- .of_compatible = "dlg,da9062-gpio",
- },
+static const struct mfd_cell da9062_devs_irq[] = {
+ MFD_CELL_OF("da9062-core", da9062_core_resources, NULL, 0, 0,
+ NULL),
+ MFD_CELL_OF("da9062-regulators", da9062_regulators_resources, NULL, 0, 0,
+ NULL),
+ MFD_CELL_OF("da9062-watchdog", da9062_wdt_resources, NULL, 0, 0,
+ "dlg,da9062-watchdog"),
+ MFD_CELL_OF("da9062-thermal", da9062_thermal_resources, NULL, 0, 0,
+ "dlg,da9062-thermal"),
+ MFD_CELL_OF("da9062-rtc", da9062_rtc_resources, NULL, 0, 0,
+ "dlg,da9062-rtc"),
+ MFD_CELL_OF("da9062-onkey", da9062_onkey_resources, NULL, 0, 0,
+ "dlg,da9062-onkey"),
+ MFD_CELL_OF("da9062-gpio", da9062_gpio_resources, NULL, 0, 0,
+ "dlg,da9062-gpio"),
+};
+
+static const struct mfd_cell da9062_devs_noirq[] = {
+ MFD_CELL_OF("da9062-core", NULL, NULL, 0, 0, NULL),
+ MFD_CELL_OF("da9062-regulators", NULL, NULL, 0, 0, NULL),
+ MFD_CELL_OF("da9062-watchdog", NULL, NULL, 0, 0, "dlg,da9062-watchdog"),
+ MFD_CELL_OF("da9062-thermal", NULL, NULL, 0, 0, "dlg,da9062-thermal"),
+ MFD_CELL_OF("da9062-rtc", NULL, NULL, 0, 0, "dlg,da9062-rtc"),
+ MFD_CELL_OF("da9062-onkey", NULL, NULL, 0, 0, "dlg,da9062-onkey"),
+ MFD_CELL_OF("da9062-gpio", NULL, NULL, 0, 0, "dlg,da9062-gpio"),
};
static int da9062_clear_fault_log(struct da9062 *chip)
@@ -625,7 +599,7 @@ static int da9062_i2c_probe(struct i2c_client *i2c)
{
const struct i2c_device_id *id = i2c_client_get_device_id(i2c);
struct da9062 *chip;
- unsigned int irq_base;
+ unsigned int irq_base = 0;
const struct mfd_cell *cell;
const struct regmap_irq_chip *irq_chip;
const struct regmap_config *config;
@@ -645,22 +619,16 @@ static int da9062_i2c_probe(struct i2c_client *i2c)
i2c_set_clientdata(i2c, chip);
chip->dev = &i2c->dev;
- if (!i2c->irq) {
- dev_err(chip->dev, "No IRQ configured\n");
- return -EINVAL;
- }
-
+ /* Start with a base configuration without IRQ */
switch (chip->chip_type) {
case COMPAT_TYPE_DA9061:
- cell = da9061_devs;
- cell_num = ARRAY_SIZE(da9061_devs);
- irq_chip = &da9061_irq_chip;
+ cell = da9061_devs_noirq;
+ cell_num = ARRAY_SIZE(da9061_devs_noirq);
config = &da9061_regmap_config;
break;
case COMPAT_TYPE_DA9062:
- cell = da9062_devs;
- cell_num = ARRAY_SIZE(da9062_devs);
- irq_chip = &da9062_irq_chip;
+ cell = da9062_devs_noirq;
+ cell_num = ARRAY_SIZE(da9062_devs_noirq);
config = &da9062_regmap_config;
break;
default:
@@ -695,29 +663,43 @@ static int da9062_i2c_probe(struct i2c_client *i2c)
if (ret)
return ret;
- ret = da9062_configure_irq_type(chip, i2c->irq, &trigger_type);
- if (ret < 0) {
- dev_err(chip->dev, "Failed to configure IRQ type\n");
- return ret;
- }
+ /* If IRQ is available, reconfigure it accordingly */
+ if (i2c->irq) {
+ if (chip->chip_type == COMPAT_TYPE_DA9061) {
+ cell = da9061_devs_irq;
+ cell_num = ARRAY_SIZE(da9061_devs_irq);
+ irq_chip = &da9061_irq_chip;
+ } else {
+ cell = da9062_devs_irq;
+ cell_num = ARRAY_SIZE(da9062_devs_irq);
+ irq_chip = &da9062_irq_chip;
+ }
- ret = regmap_add_irq_chip(chip->regmap, i2c->irq,
- trigger_type | IRQF_SHARED | IRQF_ONESHOT,
- -1, irq_chip, &chip->regmap_irq);
- if (ret) {
- dev_err(chip->dev, "Failed to request IRQ %d: %d\n",
- i2c->irq, ret);
- return ret;
- }
+ ret = da9062_configure_irq_type(chip, i2c->irq, &trigger_type);
+ if (ret < 0) {
+ dev_err(chip->dev, "Failed to configure IRQ type\n");
+ return ret;
+ }
- irq_base = regmap_irq_chip_get_base(chip->regmap_irq);
+ ret = regmap_add_irq_chip(chip->regmap, i2c->irq,
+ trigger_type | IRQF_SHARED | IRQF_ONESHOT,
+ -1, irq_chip, &chip->regmap_irq);
+ if (ret) {
+ dev_err(chip->dev, "Failed to request IRQ %d: %d\n",
+ i2c->irq, ret);
+ return ret;
+ }
+
+ irq_base = regmap_irq_chip_get_base(chip->regmap_irq);
+ }
ret = mfd_add_devices(chip->dev, PLATFORM_DEVID_NONE, cell,
cell_num, NULL, irq_base,
NULL);
if (ret) {
dev_err(chip->dev, "Cannot register child devices\n");
- regmap_del_irq_chip(i2c->irq, chip->regmap_irq);
+ if (i2c->irq)
+ regmap_del_irq_chip(i2c->irq, chip->regmap_irq);
return ret;
}
diff --git a/drivers/mfd/dln2.c b/drivers/mfd/dln2.c
index 6cd0b0c752d6..c3149729cec2 100644
--- a/drivers/mfd/dln2.c
+++ b/drivers/mfd/dln2.c
@@ -827,6 +827,7 @@ out_stop_rx:
dln2_stop_rx_urbs(dln2);
out_free:
+ usb_put_dev(dln2->usb_dev);
dln2_free(dln2);
return ret;
diff --git a/drivers/mfd/ezx-pcap.c b/drivers/mfd/ezx-pcap.c
index 3d5ce18aa9ae..8d006f6be48c 100644
--- a/drivers/mfd/ezx-pcap.c
+++ b/drivers/mfd/ezx-pcap.c
@@ -528,7 +528,6 @@ static void __exit ezx_pcap_exit(void)
subsys_initcall(ezx_pcap_init);
module_exit(ezx_pcap_exit);
-MODULE_LICENSE("GPL");
MODULE_AUTHOR("Daniel Ribeiro / Harald Welte");
MODULE_DESCRIPTION("Motorola PCAP2 ASIC Driver");
MODULE_ALIAS("spi:ezx-pcap");
diff --git a/drivers/mfd/hi6421-pmic-core.c b/drivers/mfd/hi6421-pmic-core.c
index eba88b80d969..cb5cf4a81c06 100644
--- a/drivers/mfd/hi6421-pmic-core.c
+++ b/drivers/mfd/hi6421-pmic-core.c
@@ -50,7 +50,6 @@ MODULE_DEVICE_TABLE(of, of_hi6421_pmic_match);
static int hi6421_pmic_probe(struct platform_device *pdev)
{
struct hi6421_pmic *pmic;
- struct resource *res;
const struct of_device_id *id;
const struct mfd_cell *subdevs;
enum hi6421_type type;
@@ -66,8 +65,7 @@ static int hi6421_pmic_probe(struct platform_device *pdev)
if (!pmic)
return -ENOMEM;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- base = devm_ioremap_resource(&pdev->dev, res);
+ base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
if (IS_ERR(base))
return PTR_ERR(base);
diff --git a/drivers/mfd/intel-lpss-pci.c b/drivers/mfd/intel-lpss-pci.c
index dde31c50a632..699f44ffff0e 100644
--- a/drivers/mfd/intel-lpss-pci.c
+++ b/drivers/mfd/intel-lpss-pci.c
@@ -447,6 +447,21 @@ static const struct pci_device_id intel_lpss_pci_ids[] = {
{ PCI_VDEVICE(INTEL, 0x7e79), (kernel_ulong_t)&bxt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x7e7a), (kernel_ulong_t)&bxt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x7e7b), (kernel_ulong_t)&bxt_i2c_info },
+ /* MTP-S */
+ { PCI_VDEVICE(INTEL, 0x7f28), (kernel_ulong_t)&bxt_uart_info },
+ { PCI_VDEVICE(INTEL, 0x7f29), (kernel_ulong_t)&bxt_uart_info },
+ { PCI_VDEVICE(INTEL, 0x7f2a), (kernel_ulong_t)&tgl_info },
+ { PCI_VDEVICE(INTEL, 0x7f2b), (kernel_ulong_t)&tgl_info },
+ { PCI_VDEVICE(INTEL, 0x7f4c), (kernel_ulong_t)&bxt_i2c_info },
+ { PCI_VDEVICE(INTEL, 0x7f4d), (kernel_ulong_t)&bxt_i2c_info },
+ { PCI_VDEVICE(INTEL, 0x7f4e), (kernel_ulong_t)&bxt_i2c_info },
+ { PCI_VDEVICE(INTEL, 0x7f4f), (kernel_ulong_t)&bxt_i2c_info },
+ { PCI_VDEVICE(INTEL, 0x7f5c), (kernel_ulong_t)&bxt_uart_info },
+ { PCI_VDEVICE(INTEL, 0x7f5d), (kernel_ulong_t)&bxt_uart_info },
+ { PCI_VDEVICE(INTEL, 0x7f5e), (kernel_ulong_t)&tgl_info },
+ { PCI_VDEVICE(INTEL, 0x7f5f), (kernel_ulong_t)&tgl_info },
+ { PCI_VDEVICE(INTEL, 0x7f7a), (kernel_ulong_t)&bxt_i2c_info },
+ { PCI_VDEVICE(INTEL, 0x7f7b), (kernel_ulong_t)&bxt_i2c_info },
/* LKF */
{ PCI_VDEVICE(INTEL, 0x98a8), (kernel_ulong_t)&bxt_uart_info },
{ PCI_VDEVICE(INTEL, 0x98a9), (kernel_ulong_t)&bxt_uart_info },
diff --git a/drivers/mfd/intel_soc_pmic_chtwc.c b/drivers/mfd/intel_soc_pmic_chtwc.c
index d53dae255490..871776d511e3 100644
--- a/drivers/mfd/intel_soc_pmic_chtwc.c
+++ b/drivers/mfd/intel_soc_pmic_chtwc.c
@@ -159,11 +159,19 @@ static const struct dmi_system_id cht_wc_model_dmi_ids[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "Mipad2"),
},
}, {
- /* Lenovo Yoga Book X90F / X91F / X91L */
+ /* Lenovo Yoga Book X90F / X90L */
.driver_data = (void *)(long)INTEL_CHT_WC_LENOVO_YOGABOOK1,
.matches = {
- /* Non exact match to match all versions */
- DMI_MATCH(DMI_PRODUCT_NAME, "Lenovo YB1-X9"),
+ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "CHERRYVIEW D1 PLATFORM"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "YETI-11"),
+ },
+ }, {
+ /* Lenovo Yoga Book X91F / X91L */
+ .driver_data = (void *)(long)INTEL_CHT_WC_LENOVO_YOGABOOK1,
+ .matches = {
+ /* Non exact match to match F + L versions */
+ DMI_MATCH(DMI_PRODUCT_NAME, "Lenovo YB1-X91"),
},
}, {
/* Lenovo Yoga Tab 3 Pro YT3-X90F */
diff --git a/drivers/mfd/intel_soc_pmic_crc.c b/drivers/mfd/intel_soc_pmic_crc.c
index b1548a933dc3..b745ace46e5b 100644
--- a/drivers/mfd/intel_soc_pmic_crc.c
+++ b/drivers/mfd/intel_soc_pmic_crc.c
@@ -271,6 +271,5 @@ static struct i2c_driver crystal_cove_i2c_driver = {
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/ipaq-micro.c b/drivers/mfd/ipaq-micro.c
index 4cd5ecc72211..6d3968458e81 100644
--- a/drivers/mfd/ipaq-micro.c
+++ b/drivers/mfd/ipaq-micro.c
@@ -381,7 +381,6 @@ static int __maybe_unused micro_resume(struct device *dev)
static int __init micro_probe(struct platform_device *pdev)
{
struct ipaq_micro *micro;
- struct resource *res;
int ret;
int irq;
@@ -391,8 +390,7 @@ static int __init micro_probe(struct platform_device *pdev)
micro->dev = &pdev->dev;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- micro->base = devm_ioremap_resource(&pdev->dev, res);
+ micro->base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
if (IS_ERR(micro->base))
return PTR_ERR(micro->base);
diff --git a/drivers/mfd/khadas-mcu.c b/drivers/mfd/khadas-mcu.c
index 7338cc16f327..1c807c0e6d25 100644
--- a/drivers/mfd/khadas-mcu.c
+++ b/drivers/mfd/khadas-mcu.c
@@ -112,7 +112,7 @@ static int khadas_mcu_probe(struct i2c_client *client)
if (ret)
return ret;
- if (of_find_property(dev->of_node, "#cooling-cells", NULL))
+ if (of_property_present(dev->of_node, "#cooling-cells"))
return devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE,
khadas_mcu_fan_cells,
ARRAY_SIZE(khadas_mcu_fan_cells),
diff --git a/drivers/mfd/lp8788.c b/drivers/mfd/lp8788.c
index fe809b64147e..18583addaae2 100644
--- a/drivers/mfd/lp8788.c
+++ b/drivers/mfd/lp8788.c
@@ -244,4 +244,3 @@ module_exit(lp8788_exit);
MODULE_DESCRIPTION("TI LP8788 MFD Driver");
MODULE_AUTHOR("Milo Kim");
-MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c
index 16d1861e9682..695d50b3bac6 100644
--- a/drivers/mfd/mfd-core.c
+++ b/drivers/mfd/mfd-core.c
@@ -33,32 +33,6 @@ static struct device_type mfd_dev_type = {
.name = "mfd_device",
};
-int mfd_cell_enable(struct platform_device *pdev)
-{
- const struct mfd_cell *cell = mfd_get_cell(pdev);
-
- if (!cell->enable) {
- dev_dbg(&pdev->dev, "No .enable() call-back registered\n");
- return 0;
- }
-
- return cell->enable(pdev);
-}
-EXPORT_SYMBOL(mfd_cell_enable);
-
-int mfd_cell_disable(struct platform_device *pdev)
-{
- const struct mfd_cell *cell = mfd_get_cell(pdev);
-
- if (!cell->disable) {
- dev_dbg(&pdev->dev, "No .disable() call-back registered\n");
- return 0;
- }
-
- return cell->disable(pdev);
-}
-EXPORT_SYMBOL(mfd_cell_disable);
-
#if IS_ENABLED(CONFIG_ACPI)
struct match_ids_walk_data {
struct acpi_device_id *ids;
diff --git a/drivers/mfd/ocelot-spi.c b/drivers/mfd/ocelot-spi.c
index 2d1349a10ca9..94f82677675b 100644
--- a/drivers/mfd/ocelot-spi.c
+++ b/drivers/mfd/ocelot-spi.c
@@ -130,6 +130,7 @@ static const struct regmap_config ocelot_spi_regmap_config = {
.write_flag_mask = 0x80,
+ .use_single_read = true,
.use_single_write = true,
.can_multi_write = false,
diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c
index 787d2ae86375..7f5775109593 100644
--- a/drivers/mfd/omap-usb-host.c
+++ b/drivers/mfd/omap-usb-host.c
@@ -853,7 +853,6 @@ static struct platform_driver usbhs_omap_driver = {
MODULE_AUTHOR("Keshava Munegowda <keshava_mgowda@ti.com>");
MODULE_AUTHOR("Roger Quadros <rogerq@ti.com>");
MODULE_ALIAS("platform:" USBHS_DRIVER_NAME);
-MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("usb host common core driver for omap EHCI and OHCI");
static int omap_usbhs_drvinit(void)
diff --git a/drivers/mfd/omap-usb-tll.c b/drivers/mfd/omap-usb-tll.c
index 080d7970a377..69cbc2097911 100644
--- a/drivers/mfd/omap-usb-tll.c
+++ b/drivers/mfd/omap-usb-tll.c
@@ -125,11 +125,6 @@ static inline void usbtll_writeb(void __iomem *base, u32 reg, u8 val)
writeb_relaxed(val, base + reg);
}
-static inline u8 usbtll_readb(void __iomem *base, u32 reg)
-{
- return readb_relaxed(base + reg);
-}
-
/*-------------------------------------------------------------------------*/
static bool is_ohci_port(enum usbhs_omap_port_mode pmode)
@@ -450,7 +445,6 @@ EXPORT_SYMBOL_GPL(omap_tll_disable);
MODULE_AUTHOR("Keshava Munegowda <keshava_mgowda@ti.com>");
MODULE_AUTHOR("Roger Quadros <rogerq@ti.com>");
-MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("usb tll driver for TI OMAP EHCI and OHCI controllers");
static int __init omap_usbtll_drvinit(void)
diff --git a/drivers/mfd/qcom-pm8008.c b/drivers/mfd/qcom-pm8008.c
index 9f3c4a01b4c1..837246aab4ac 100644
--- a/drivers/mfd/qcom-pm8008.c
+++ b/drivers/mfd/qcom-pm8008.c
@@ -44,37 +44,16 @@ enum {
#define PM8008_GPIO1_ADDR PM8008_PERIPH_2_BASE
#define PM8008_GPIO2_ADDR PM8008_PERIPH_3_BASE
-#define PM8008_STATUS_BASE (PM8008_PERIPH_0_BASE | INT_LATCHED_STS_OFFSET)
-#define PM8008_MASK_BASE (PM8008_PERIPH_0_BASE | INT_EN_SET_OFFSET)
-#define PM8008_UNMASK_BASE (PM8008_PERIPH_0_BASE | INT_EN_CLR_OFFSET)
-#define PM8008_TYPE_BASE (PM8008_PERIPH_0_BASE | INT_SET_TYPE_OFFSET)
-#define PM8008_ACK_BASE (PM8008_PERIPH_0_BASE | INT_LATCHED_CLR_OFFSET)
-#define PM8008_POLARITY_HI_BASE (PM8008_PERIPH_0_BASE | INT_POL_HIGH_OFFSET)
-#define PM8008_POLARITY_LO_BASE (PM8008_PERIPH_0_BASE | INT_POL_LOW_OFFSET)
-
-#define PM8008_PERIPH_OFFSET(paddr) (paddr - PM8008_PERIPH_0_BASE)
-
-static unsigned int p0_offs[] = {PM8008_PERIPH_OFFSET(PM8008_PERIPH_0_BASE)};
-static unsigned int p1_offs[] = {PM8008_PERIPH_OFFSET(PM8008_PERIPH_1_BASE)};
-static unsigned int p2_offs[] = {PM8008_PERIPH_OFFSET(PM8008_PERIPH_2_BASE)};
-static unsigned int p3_offs[] = {PM8008_PERIPH_OFFSET(PM8008_PERIPH_3_BASE)};
-
-static struct regmap_irq_sub_irq_map pm8008_sub_reg_offsets[] = {
- REGMAP_IRQ_MAIN_REG_OFFSET(p0_offs),
- REGMAP_IRQ_MAIN_REG_OFFSET(p1_offs),
- REGMAP_IRQ_MAIN_REG_OFFSET(p2_offs),
- REGMAP_IRQ_MAIN_REG_OFFSET(p3_offs),
-};
-
-static unsigned int pm8008_virt_regs[] = {
- PM8008_POLARITY_HI_BASE,
- PM8008_POLARITY_LO_BASE,
-};
-
enum {
+ SET_TYPE_INDEX,
POLARITY_HI_INDEX,
POLARITY_LO_INDEX,
- PM8008_NUM_VIRT_REGS,
+};
+
+static unsigned int pm8008_config_regs[] = {
+ INT_SET_TYPE_OFFSET,
+ INT_POL_HIGH_OFFSET,
+ INT_POL_LOW_OFFSET,
};
static struct regmap_irq pm8008_irqs[] = {
@@ -88,32 +67,54 @@ static struct regmap_irq pm8008_irqs[] = {
REGMAP_IRQ_REG(PM8008_IRQ_GPIO2, PM8008_GPIO2, BIT(0)),
};
-static int pm8008_set_type_virt(unsigned int **virt_buf,
- unsigned int type, unsigned long hwirq,
- int reg)
+static const unsigned int pm8008_periph_base[] = {
+ PM8008_PERIPH_0_BASE,
+ PM8008_PERIPH_1_BASE,
+ PM8008_PERIPH_2_BASE,
+ PM8008_PERIPH_3_BASE,
+};
+
+static unsigned int pm8008_get_irq_reg(struct regmap_irq_chip_data *data,
+ unsigned int base, int index)
+{
+ /* Simple linear addressing for the main status register */
+ if (base == I2C_INTR_STATUS_BASE)
+ return base + index;
+
+ return pm8008_periph_base[index] + base;
+}
+
+static int pm8008_set_type_config(unsigned int **buf, unsigned int type,
+ const struct regmap_irq *irq_data, int idx,
+ void *irq_drv_data)
{
switch (type) {
case IRQ_TYPE_EDGE_FALLING:
case IRQ_TYPE_LEVEL_LOW:
- virt_buf[POLARITY_HI_INDEX][reg] &= ~pm8008_irqs[hwirq].mask;
- virt_buf[POLARITY_LO_INDEX][reg] |= pm8008_irqs[hwirq].mask;
+ buf[POLARITY_HI_INDEX][idx] &= ~irq_data->mask;
+ buf[POLARITY_LO_INDEX][idx] |= irq_data->mask;
break;
case IRQ_TYPE_EDGE_RISING:
case IRQ_TYPE_LEVEL_HIGH:
- virt_buf[POLARITY_HI_INDEX][reg] |= pm8008_irqs[hwirq].mask;
- virt_buf[POLARITY_LO_INDEX][reg] &= ~pm8008_irqs[hwirq].mask;
+ buf[POLARITY_HI_INDEX][idx] |= irq_data->mask;
+ buf[POLARITY_LO_INDEX][idx] &= ~irq_data->mask;
break;
case IRQ_TYPE_EDGE_BOTH:
- virt_buf[POLARITY_HI_INDEX][reg] |= pm8008_irqs[hwirq].mask;
- virt_buf[POLARITY_LO_INDEX][reg] |= pm8008_irqs[hwirq].mask;
+ buf[POLARITY_HI_INDEX][idx] |= irq_data->mask;
+ buf[POLARITY_LO_INDEX][idx] |= irq_data->mask;
break;
default:
return -EINVAL;
}
+ if (type & IRQ_TYPE_EDGE_BOTH)
+ buf[SET_TYPE_INDEX][idx] |= irq_data->mask;
+ else
+ buf[SET_TYPE_INDEX][idx] &= ~irq_data->mask;
+
return 0;
}
@@ -121,20 +122,19 @@ static struct regmap_irq_chip pm8008_irq_chip = {
.name = "pm8008_irq",
.main_status = I2C_INTR_STATUS_BASE,
.num_main_regs = 1,
- .num_virt_regs = PM8008_NUM_VIRT_REGS,
.irqs = pm8008_irqs,
.num_irqs = ARRAY_SIZE(pm8008_irqs),
.num_regs = PM8008_NUM_PERIPHS,
- .not_fixed_stride = true,
- .sub_reg_offsets = pm8008_sub_reg_offsets,
- .set_type_virt = pm8008_set_type_virt,
- .status_base = PM8008_STATUS_BASE,
- .mask_base = PM8008_MASK_BASE,
- .unmask_base = PM8008_UNMASK_BASE,
- .type_base = PM8008_TYPE_BASE,
- .ack_base = PM8008_ACK_BASE,
- .virt_reg_base = pm8008_virt_regs,
- .num_type_reg = PM8008_NUM_PERIPHS,
+ .status_base = INT_LATCHED_STS_OFFSET,
+ .mask_base = INT_EN_CLR_OFFSET,
+ .unmask_base = INT_EN_SET_OFFSET,
+ .mask_unmask_non_inverted = true,
+ .ack_base = INT_LATCHED_CLR_OFFSET,
+ .config_base = pm8008_config_regs,
+ .num_config_bases = ARRAY_SIZE(pm8008_config_regs),
+ .num_config_regs = PM8008_NUM_PERIPHS,
+ .set_type_config = pm8008_set_type_config,
+ .get_irq_reg = pm8008_get_irq_reg,
};
static struct regmap_config qcom_mfd_regmap_cfg = {
@@ -143,30 +143,6 @@ static struct regmap_config qcom_mfd_regmap_cfg = {
.max_register = 0xFFFF,
};
-static int pm8008_init(struct regmap *regmap)
-{
- int rc;
-
- /*
- * Set TEMP_ALARM peripheral's TYPE so that the regmap-irq framework
- * reads this as the default value instead of zero, the HW default.
- * This is required to enable the writing of TYPE registers in
- * regmap_irq_sync_unlock().
- */
- rc = regmap_write(regmap, (PM8008_TEMP_ALARM_ADDR | INT_SET_TYPE_OFFSET), BIT(0));
- if (rc)
- return rc;
-
- /* Do the same for GPIO1 and GPIO2 peripherals */
- rc = regmap_write(regmap, (PM8008_GPIO1_ADDR | INT_SET_TYPE_OFFSET), BIT(0));
- if (rc)
- return rc;
-
- rc = regmap_write(regmap, (PM8008_GPIO2_ADDR | INT_SET_TYPE_OFFSET), BIT(0));
-
- return rc;
-}
-
static int pm8008_probe_irq_peripherals(struct device *dev,
struct regmap *regmap,
int client_irq)
@@ -175,20 +151,10 @@ static int pm8008_probe_irq_peripherals(struct device *dev,
struct regmap_irq_type *type;
struct regmap_irq_chip_data *irq_data;
- rc = pm8008_init(regmap);
- if (rc) {
- dev_err(dev, "Init failed: %d\n", rc);
- return rc;
- }
-
for (i = 0; i < ARRAY_SIZE(pm8008_irqs); i++) {
type = &pm8008_irqs[i].type;
- type->type_reg_offset = pm8008_irqs[i].reg_offset;
- type->type_rising_val = pm8008_irqs[i].mask;
- type->type_falling_val = pm8008_irqs[i].mask;
- type->type_level_high_val = 0;
- type->type_level_low_val = 0;
+ type->type_reg_offset = pm8008_irqs[i].reg_offset;
if (type->type_reg_offset == PM8008_MISC)
type->types_supported = IRQ_TYPE_EDGE_RISING;
diff --git a/drivers/mfd/qcom_rpm.c b/drivers/mfd/qcom_rpm.c
index 8fea0e511550..086611322874 100644
--- a/drivers/mfd/qcom_rpm.c
+++ b/drivers/mfd/qcom_rpm.c
@@ -530,7 +530,6 @@ static int qcom_rpm_probe(struct platform_device *pdev)
{
const struct of_device_id *match;
struct device_node *syscon_np;
- struct resource *res;
struct qcom_rpm *rpm;
u32 fw_version[3];
int irq_wakeup;
@@ -576,8 +575,7 @@ static int qcom_rpm_probe(struct platform_device *pdev)
return -ENODEV;
rpm->data = match->data;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- rpm->status_regs = devm_ioremap_resource(&pdev->dev, res);
+ rpm->status_regs = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
if (IS_ERR(rpm->status_regs))
return PTR_ERR(rpm->status_regs);
rpm->ctrl_regs = rpm->status_regs + 0x400;
diff --git a/drivers/mfd/rsmu.h b/drivers/mfd/rsmu.h
index bb88597d189f..1bb04cafa45d 100644
--- a/drivers/mfd/rsmu.h
+++ b/drivers/mfd/rsmu.h
@@ -10,6 +10,8 @@
#include <linux/mfd/rsmu.h>
+#define RSMU_CM_SCSR_BASE 0x20100000
+
int rsmu_core_init(struct rsmu_ddata *rsmu);
void rsmu_core_exit(struct rsmu_ddata *rsmu);
diff --git a/drivers/mfd/rsmu_i2c.c b/drivers/mfd/rsmu_i2c.c
index 15d25b081434..807c32101460 100644
--- a/drivers/mfd/rsmu_i2c.c
+++ b/drivers/mfd/rsmu_i2c.c
@@ -18,11 +18,12 @@
#include "rsmu.h"
/*
- * 16-bit register address: the lower 8 bits of the register address come
- * from the offset addr byte and the upper 8 bits come from the page register.
+ * 32-bit register address: the lower 8 bits of the register address come
+ * from the offset addr byte and the upper 24 bits come from the page register.
*/
-#define RSMU_CM_PAGE_ADDR 0xFD
-#define RSMU_CM_PAGE_WINDOW 256
+#define RSMU_CM_PAGE_ADDR 0xFC
+#define RSMU_CM_PAGE_MASK 0xFFFFFF00
+#define RSMU_CM_ADDRESS_MASK 0x000000FF
/*
* 15-bit register address: the lower 7 bits of the register address come
@@ -31,18 +32,6 @@
#define RSMU_SABRE_PAGE_ADDR 0x7F
#define RSMU_SABRE_PAGE_WINDOW 128
-static const struct regmap_range_cfg rsmu_cm_range_cfg[] = {
- {
- .range_min = 0,
- .range_max = 0xD000,
- .selector_reg = RSMU_CM_PAGE_ADDR,
- .selector_mask = 0xFF,
- .selector_shift = 0,
- .window_start = 0,
- .window_len = RSMU_CM_PAGE_WINDOW,
- }
-};
-
static const struct regmap_range_cfg rsmu_sabre_range_cfg[] = {
{
.range_min = 0,
@@ -55,35 +44,141 @@ static const struct regmap_range_cfg rsmu_sabre_range_cfg[] = {
}
};
-static bool rsmu_cm_volatile_reg(struct device *dev, unsigned int reg)
+static bool rsmu_sabre_volatile_reg(struct device *dev, unsigned int reg)
{
switch (reg) {
- case RSMU_CM_PAGE_ADDR:
+ case RSMU_SABRE_PAGE_ADDR:
return false;
default:
return true;
}
}
-static bool rsmu_sabre_volatile_reg(struct device *dev, unsigned int reg)
+static int rsmu_read_device(struct rsmu_ddata *rsmu, u8 reg, u8 *buf, u16 bytes)
{
- switch (reg) {
- case RSMU_SABRE_PAGE_ADDR:
- return false;
- default:
- return true;
+ struct i2c_client *client = to_i2c_client(rsmu->dev);
+ struct i2c_msg msg[2];
+ int cnt;
+
+ msg[0].addr = client->addr;
+ msg[0].flags = 0;
+ msg[0].len = 1;
+ msg[0].buf = &reg;
+
+ msg[1].addr = client->addr;
+ msg[1].flags = I2C_M_RD;
+ msg[1].len = bytes;
+ msg[1].buf = buf;
+
+ cnt = i2c_transfer(client->adapter, msg, 2);
+
+ if (cnt < 0) {
+ dev_err(rsmu->dev, "i2c_transfer failed at addr: %04x!", reg);
+ return cnt;
+ } else if (cnt != 2) {
+ dev_err(rsmu->dev,
+ "i2c_transfer sent only %d of 2 messages", cnt);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int rsmu_write_device(struct rsmu_ddata *rsmu, u8 reg, u8 *buf, u16 bytes)
+{
+ struct i2c_client *client = to_i2c_client(rsmu->dev);
+ u8 msg[RSMU_MAX_WRITE_COUNT + 1]; /* 1 Byte added for the device register */
+ int cnt;
+
+ if (bytes > RSMU_MAX_WRITE_COUNT)
+ return -EINVAL;
+
+ msg[0] = reg;
+ memcpy(&msg[1], buf, bytes);
+
+ cnt = i2c_master_send(client, msg, bytes + 1);
+
+ if (cnt < 0) {
+ dev_err(&client->dev,
+ "i2c_master_send failed at addr: %04x!", reg);
+ return cnt;
}
+
+ return 0;
+}
+
+static int rsmu_write_page_register(struct rsmu_ddata *rsmu, u32 reg)
+{
+ u32 page = reg & RSMU_CM_PAGE_MASK;
+ u8 buf[4];
+ int err;
+
+ /* Do not modify offset register for none-scsr registers */
+ if (reg < RSMU_CM_SCSR_BASE)
+ return 0;
+
+ /* Simply return if we are on the same page */
+ if (rsmu->page == page)
+ return 0;
+
+ buf[0] = 0x0;
+ buf[1] = (u8)((page >> 8) & 0xFF);
+ buf[2] = (u8)((page >> 16) & 0xFF);
+ buf[3] = (u8)((page >> 24) & 0xFF);
+
+ err = rsmu_write_device(rsmu, RSMU_CM_PAGE_ADDR, buf, sizeof(buf));
+ if (err)
+ dev_err(rsmu->dev, "Failed to set page offset 0x%x\n", page);
+ else
+ /* Remember the last page */
+ rsmu->page = page;
+
+ return err;
+}
+
+static int rsmu_reg_read(void *context, unsigned int reg, unsigned int *val)
+{
+ struct rsmu_ddata *rsmu = i2c_get_clientdata((struct i2c_client *)context);
+ u8 addr = (u8)(reg & RSMU_CM_ADDRESS_MASK);
+ int err;
+
+ err = rsmu_write_page_register(rsmu, reg);
+ if (err)
+ return err;
+
+ err = rsmu_read_device(rsmu, addr, (u8 *)val, 1);
+ if (err)
+ dev_err(rsmu->dev, "Failed to read offset address 0x%x\n", addr);
+
+ return err;
+}
+
+static int rsmu_reg_write(void *context, unsigned int reg, unsigned int val)
+{
+ struct rsmu_ddata *rsmu = i2c_get_clientdata((struct i2c_client *)context);
+ u8 addr = (u8)(reg & RSMU_CM_ADDRESS_MASK);
+ u8 data = (u8)val;
+ int err;
+
+ err = rsmu_write_page_register(rsmu, reg);
+ if (err)
+ return err;
+
+ err = rsmu_write_device(rsmu, addr, &data, 1);
+ if (err)
+ dev_err(rsmu->dev,
+ "Failed to write offset address 0x%x\n", addr);
+
+ return err;
}
static const struct regmap_config rsmu_cm_regmap_config = {
- .reg_bits = 8,
+ .reg_bits = 32,
.val_bits = 8,
- .max_register = 0xD000,
- .ranges = rsmu_cm_range_cfg,
- .num_ranges = ARRAY_SIZE(rsmu_cm_range_cfg),
- .volatile_reg = rsmu_cm_volatile_reg,
- .cache_type = REGCACHE_RBTREE,
- .can_multi_write = true,
+ .max_register = 0x20120000,
+ .reg_read = rsmu_reg_read,
+ .reg_write = rsmu_reg_write,
+ .cache_type = REGCACHE_NONE,
};
static const struct regmap_config rsmu_sabre_regmap_config = {
@@ -101,7 +196,7 @@ static const struct regmap_config rsmu_sl_regmap_config = {
.reg_bits = 16,
.val_bits = 8,
.reg_format_endian = REGMAP_ENDIAN_BIG,
- .max_register = 0x339,
+ .max_register = 0x340,
.cache_type = REGCACHE_NONE,
.can_multi_write = true,
};
@@ -136,7 +231,11 @@ static int rsmu_i2c_probe(struct i2c_client *client)
dev_err(rsmu->dev, "Unsupported RSMU device type: %d\n", rsmu->type);
return -ENODEV;
}
- rsmu->regmap = devm_regmap_init_i2c(client, cfg);
+
+ if (rsmu->type == RSMU_CM)
+ rsmu->regmap = devm_regmap_init(&client->dev, NULL, client, cfg);
+ else
+ rsmu->regmap = devm_regmap_init_i2c(client, cfg);
if (IS_ERR(rsmu->regmap)) {
ret = PTR_ERR(rsmu->regmap);
dev_err(rsmu->dev, "Failed to allocate register map: %d\n", ret);
diff --git a/drivers/mfd/rsmu_spi.c b/drivers/mfd/rsmu_spi.c
index d2f3d8f1e05a..a4a595bb8d0d 100644
--- a/drivers/mfd/rsmu_spi.c
+++ b/drivers/mfd/rsmu_spi.c
@@ -19,19 +19,21 @@
#define RSMU_CM_PAGE_ADDR 0x7C
#define RSMU_SABRE_PAGE_ADDR 0x7F
-#define RSMU_HIGHER_ADDR_MASK 0xFF80
-#define RSMU_HIGHER_ADDR_SHIFT 7
-#define RSMU_LOWER_ADDR_MASK 0x7F
+#define RSMU_PAGE_MASK 0xFFFFFF80
+#define RSMU_ADDR_MASK 0x7F
static int rsmu_read_device(struct rsmu_ddata *rsmu, u8 reg, u8 *buf, u16 bytes)
{
struct spi_device *client = to_spi_device(rsmu->dev);
struct spi_transfer xfer = {0};
struct spi_message msg;
- u8 cmd[256] = {0};
- u8 rsp[256] = {0};
+ u8 cmd[RSMU_MAX_READ_COUNT + 1] = {0};
+ u8 rsp[RSMU_MAX_READ_COUNT + 1] = {0};
int ret;
+ if (bytes > RSMU_MAX_READ_COUNT)
+ return -EINVAL;
+
cmd[0] = reg | 0x80;
xfer.rx_buf = rsp;
xfer.len = bytes + 1;
@@ -66,7 +68,10 @@ static int rsmu_write_device(struct rsmu_ddata *rsmu, u8 reg, u8 *buf, u16 bytes
struct spi_device *client = to_spi_device(rsmu->dev);
struct spi_transfer xfer = {0};
struct spi_message msg;
- u8 cmd[256] = {0};
+ u8 cmd[RSMU_MAX_WRITE_COUNT + 1] = {0};
+
+ if (bytes > RSMU_MAX_WRITE_COUNT)
+ return -EINVAL;
cmd[0] = reg;
memcpy(&cmd[1], buf, bytes);
@@ -86,26 +91,35 @@ static int rsmu_write_device(struct rsmu_ddata *rsmu, u8 reg, u8 *buf, u16 bytes
* 16-bit register address: the lower 7 bits of the register address come
* from the offset addr byte and the upper 9 bits come from the page register.
*/
-static int rsmu_write_page_register(struct rsmu_ddata *rsmu, u16 reg)
+static int rsmu_write_page_register(struct rsmu_ddata *rsmu, u32 reg)
{
u8 page_reg;
- u8 buf[2];
+ u8 buf[4];
u16 bytes;
- u16 page;
+ u32 page;
int err;
switch (rsmu->type) {
case RSMU_CM:
+ /* Do not modify page register for none-scsr registers */
+ if (reg < RSMU_CM_SCSR_BASE)
+ return 0;
page_reg = RSMU_CM_PAGE_ADDR;
- page = reg & RSMU_HIGHER_ADDR_MASK;
+ page = reg & RSMU_PAGE_MASK;
buf[0] = (u8)(page & 0xff);
buf[1] = (u8)((page >> 8) & 0xff);
- bytes = 2;
+ buf[2] = (u8)((page >> 16) & 0xff);
+ buf[3] = (u8)((page >> 24) & 0xff);
+ bytes = 4;
break;
case RSMU_SABRE:
+ /* Do not modify page register if reg is page register itself */
+ if ((reg & RSMU_ADDR_MASK) == RSMU_ADDR_MASK)
+ return 0;
page_reg = RSMU_SABRE_PAGE_ADDR;
- page = reg >> RSMU_HIGHER_ADDR_SHIFT;
- buf[0] = (u8)(page & 0xff);
+ page = reg & RSMU_PAGE_MASK;
+ /* The three page bits are located in the single Page Register */
+ buf[0] = (u8)((page >> 7) & 0x7);
bytes = 1;
break;
default:
@@ -130,7 +144,7 @@ static int rsmu_write_page_register(struct rsmu_ddata *rsmu, u16 reg)
static int rsmu_reg_read(void *context, unsigned int reg, unsigned int *val)
{
struct rsmu_ddata *rsmu = spi_get_drvdata((struct spi_device *)context);
- u8 addr = (u8)(reg & RSMU_LOWER_ADDR_MASK);
+ u8 addr = (u8)(reg & RSMU_ADDR_MASK);
int err;
err = rsmu_write_page_register(rsmu, reg);
@@ -147,7 +161,7 @@ static int rsmu_reg_read(void *context, unsigned int reg, unsigned int *val)
static int rsmu_reg_write(void *context, unsigned int reg, unsigned int val)
{
struct rsmu_ddata *rsmu = spi_get_drvdata((struct spi_device *)context);
- u8 addr = (u8)(reg & RSMU_LOWER_ADDR_MASK);
+ u8 addr = (u8)(reg & RSMU_ADDR_MASK);
u8 data = (u8)val;
int err;
@@ -164,9 +178,9 @@ static int rsmu_reg_write(void *context, unsigned int reg, unsigned int val)
}
static const struct regmap_config rsmu_cm_regmap_config = {
- .reg_bits = 16,
+ .reg_bits = 32,
.val_bits = 8,
- .max_register = 0xD000,
+ .max_register = 0x20120000,
.reg_read = rsmu_reg_read,
.reg_write = rsmu_reg_write,
.cache_type = REGCACHE_NONE,
diff --git a/drivers/mfd/rz-mtu3.c b/drivers/mfd/rz-mtu3.c
new file mode 100644
index 000000000000..04006f4aa702
--- /dev/null
+++ b/drivers/mfd/rz-mtu3.c
@@ -0,0 +1,391 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Renesas RZ/G2L Multi-Function Timer Pulse Unit 3(MTU3a) Core driver
+ *
+ * Copyright (C) 2023 Renesas Electronics Corporation
+ */
+
+#include <linux/bitfield.h>
+#include <linux/clk.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/rz-mtu3.h>
+#include <linux/of_platform.h>
+#include <linux/reset.h>
+#include <linux/spinlock.h>
+
+#include "rz-mtu3.h"
+
+struct rz_mtu3_priv {
+ void __iomem *mmio;
+ struct reset_control *rstc;
+ raw_spinlock_t lock;
+};
+
+/******* MTU3 registers (original offset is +0x1200) *******/
+static const unsigned long rz_mtu3_8bit_ch_reg_offs[][13] = {
+ [RZ_MTU3_CHAN_0] = MTU_8BIT_CH_0(0x104, 0x090, 0x100, 0x128, 0x101, 0x102, 0x103, 0x126),
+ [RZ_MTU3_CHAN_1] = MTU_8BIT_CH_1_2(0x184, 0x091, 0x185, 0x180, 0x194, 0x181, 0x182),
+ [RZ_MTU3_CHAN_2] = MTU_8BIT_CH_1_2(0x204, 0x092, 0x205, 0x200, 0x20c, 0x201, 0x202),
+ [RZ_MTU3_CHAN_3] = MTU_8BIT_CH_3_4_6_7(0x008, 0x093, 0x02c, 0x000, 0x04c, 0x002, 0x004, 0x005, 0x038),
+ [RZ_MTU3_CHAN_4] = MTU_8BIT_CH_3_4_6_7(0x009, 0x094, 0x02d, 0x001, 0x04d, 0x003, 0x006, 0x007, 0x039),
+ [RZ_MTU3_CHAN_5] = MTU_8BIT_CH_5(0xab2, 0x1eb, 0xab4, 0xab6, 0xa84, 0xa85, 0xa86, 0xa94, 0xa95, 0xa96, 0xaa4, 0xaa5, 0xaa6),
+ [RZ_MTU3_CHAN_6] = MTU_8BIT_CH_3_4_6_7(0x808, 0x893, 0x82c, 0x800, 0x84c, 0x802, 0x804, 0x805, 0x838),
+ [RZ_MTU3_CHAN_7] = MTU_8BIT_CH_3_4_6_7(0x809, 0x894, 0x82d, 0x801, 0x84d, 0x803, 0x806, 0x807, 0x839),
+ [RZ_MTU3_CHAN_8] = MTU_8BIT_CH_8(0x404, 0x098, 0x400, 0x406, 0x401, 0x402, 0x403)
+};
+
+static const unsigned long rz_mtu3_16bit_ch_reg_offs[][12] = {
+ [RZ_MTU3_CHAN_0] = MTU_16BIT_CH_0(0x106, 0x108, 0x10a, 0x10c, 0x10e, 0x120, 0x122),
+ [RZ_MTU3_CHAN_1] = MTU_16BIT_CH_1_2(0x186, 0x188, 0x18a),
+ [RZ_MTU3_CHAN_2] = MTU_16BIT_CH_1_2(0x206, 0x208, 0x20a),
+ [RZ_MTU3_CHAN_3] = MTU_16BIT_CH_3_6(0x010, 0x018, 0x01a, 0x024, 0x026, 0x072),
+ [RZ_MTU3_CHAN_4] = MTU_16BIT_CH_4_7(0x012, 0x01c, 0x01e, 0x028, 0x2a, 0x074, 0x076, 0x040, 0x044, 0x046, 0x048, 0x04a),
+ [RZ_MTU3_CHAN_5] = MTU_16BIT_CH_5(0xa80, 0xa82, 0xa90, 0xa92, 0xaa0, 0xaa2),
+ [RZ_MTU3_CHAN_6] = MTU_16BIT_CH_3_6(0x810, 0x818, 0x81a, 0x824, 0x826, 0x872),
+ [RZ_MTU3_CHAN_7] = MTU_16BIT_CH_4_7(0x812, 0x81c, 0x81e, 0x828, 0x82a, 0x874, 0x876, 0x840, 0x844, 0x846, 0x848, 0x84a)
+};
+
+static const unsigned long rz_mtu3_32bit_ch_reg_offs[][5] = {
+ [RZ_MTU3_CHAN_1] = MTU_32BIT_CH_1(0x1a0, 0x1a4, 0x1a8),
+ [RZ_MTU3_CHAN_8] = MTU_32BIT_CH_8(0x408, 0x40c, 0x410, 0x414, 0x418)
+};
+
+static bool rz_mtu3_is_16bit_shared_reg(u16 offset)
+{
+ return (offset == RZ_MTU3_TDDRA || offset == RZ_MTU3_TDDRB ||
+ offset == RZ_MTU3_TCDRA || offset == RZ_MTU3_TCDRB ||
+ offset == RZ_MTU3_TCBRA || offset == RZ_MTU3_TCBRB ||
+ offset == RZ_MTU3_TCNTSA || offset == RZ_MTU3_TCNTSB);
+}
+
+u16 rz_mtu3_shared_reg_read(struct rz_mtu3_channel *ch, u16 offset)
+{
+ struct rz_mtu3 *mtu = dev_get_drvdata(ch->dev->parent);
+ struct rz_mtu3_priv *priv = mtu->priv_data;
+
+ if (rz_mtu3_is_16bit_shared_reg(offset))
+ return readw(priv->mmio + offset);
+ else
+ return readb(priv->mmio + offset);
+}
+EXPORT_SYMBOL_GPL(rz_mtu3_shared_reg_read);
+
+u8 rz_mtu3_8bit_ch_read(struct rz_mtu3_channel *ch, u16 offset)
+{
+ struct rz_mtu3 *mtu = dev_get_drvdata(ch->dev->parent);
+ struct rz_mtu3_priv *priv = mtu->priv_data;
+ u16 ch_offs;
+
+ ch_offs = rz_mtu3_8bit_ch_reg_offs[ch->channel_number][offset];
+
+ return readb(priv->mmio + ch_offs);
+}
+EXPORT_SYMBOL_GPL(rz_mtu3_8bit_ch_read);
+
+u16 rz_mtu3_16bit_ch_read(struct rz_mtu3_channel *ch, u16 offset)
+{
+ struct rz_mtu3 *mtu = dev_get_drvdata(ch->dev->parent);
+ struct rz_mtu3_priv *priv = mtu->priv_data;
+ u16 ch_offs;
+
+ /* MTU8 doesn't have 16-bit registers */
+ if (ch->channel_number == RZ_MTU3_CHAN_8)
+ return 0;
+
+ ch_offs = rz_mtu3_16bit_ch_reg_offs[ch->channel_number][offset];
+
+ return readw(priv->mmio + ch_offs);
+}
+EXPORT_SYMBOL_GPL(rz_mtu3_16bit_ch_read);
+
+u32 rz_mtu3_32bit_ch_read(struct rz_mtu3_channel *ch, u16 offset)
+{
+ struct rz_mtu3 *mtu = dev_get_drvdata(ch->dev->parent);
+ struct rz_mtu3_priv *priv = mtu->priv_data;
+ u16 ch_offs;
+
+ if (ch->channel_number != RZ_MTU3_CHAN_1 && ch->channel_number != RZ_MTU3_CHAN_8)
+ return 0;
+
+ ch_offs = rz_mtu3_32bit_ch_reg_offs[ch->channel_number][offset];
+
+ return readl(priv->mmio + ch_offs);
+}
+EXPORT_SYMBOL_GPL(rz_mtu3_32bit_ch_read);
+
+void rz_mtu3_8bit_ch_write(struct rz_mtu3_channel *ch, u16 offset, u8 val)
+{
+ struct rz_mtu3 *mtu = dev_get_drvdata(ch->dev->parent);
+ struct rz_mtu3_priv *priv = mtu->priv_data;
+ u16 ch_offs;
+
+ ch_offs = rz_mtu3_8bit_ch_reg_offs[ch->channel_number][offset];
+ writeb(val, priv->mmio + ch_offs);
+}
+EXPORT_SYMBOL_GPL(rz_mtu3_8bit_ch_write);
+
+void rz_mtu3_16bit_ch_write(struct rz_mtu3_channel *ch, u16 offset, u16 val)
+{
+ struct rz_mtu3 *mtu = dev_get_drvdata(ch->dev->parent);
+ struct rz_mtu3_priv *priv = mtu->priv_data;
+ u16 ch_offs;
+
+ /* MTU8 doesn't have 16-bit registers */
+ if (ch->channel_number == RZ_MTU3_CHAN_8)
+ return;
+
+ ch_offs = rz_mtu3_16bit_ch_reg_offs[ch->channel_number][offset];
+ writew(val, priv->mmio + ch_offs);
+}
+EXPORT_SYMBOL_GPL(rz_mtu3_16bit_ch_write);
+
+void rz_mtu3_32bit_ch_write(struct rz_mtu3_channel *ch, u16 offset, u32 val)
+{
+ struct rz_mtu3 *mtu = dev_get_drvdata(ch->dev->parent);
+ struct rz_mtu3_priv *priv = mtu->priv_data;
+ u16 ch_offs;
+
+ if (ch->channel_number != RZ_MTU3_CHAN_1 && ch->channel_number != RZ_MTU3_CHAN_8)
+ return;
+
+ ch_offs = rz_mtu3_32bit_ch_reg_offs[ch->channel_number][offset];
+ writel(val, priv->mmio + ch_offs);
+}
+EXPORT_SYMBOL_GPL(rz_mtu3_32bit_ch_write);
+
+void rz_mtu3_shared_reg_write(struct rz_mtu3_channel *ch, u16 offset, u16 value)
+{
+ struct rz_mtu3 *mtu = dev_get_drvdata(ch->dev->parent);
+ struct rz_mtu3_priv *priv = mtu->priv_data;
+
+ if (rz_mtu3_is_16bit_shared_reg(offset))
+ writew(value, priv->mmio + offset);
+ else
+ writeb((u8)value, priv->mmio + offset);
+}
+EXPORT_SYMBOL_GPL(rz_mtu3_shared_reg_write);
+
+void rz_mtu3_shared_reg_update_bit(struct rz_mtu3_channel *ch, u16 offset,
+ u16 pos, u8 val)
+{
+ struct rz_mtu3 *mtu = dev_get_drvdata(ch->dev->parent);
+ struct rz_mtu3_priv *priv = mtu->priv_data;
+ unsigned long tmdr, flags;
+
+ raw_spin_lock_irqsave(&priv->lock, flags);
+ tmdr = rz_mtu3_shared_reg_read(ch, offset);
+ __assign_bit(pos, &tmdr, !!val);
+ rz_mtu3_shared_reg_write(ch, offset, tmdr);
+ raw_spin_unlock_irqrestore(&priv->lock, flags);
+}
+EXPORT_SYMBOL_GPL(rz_mtu3_shared_reg_update_bit);
+
+static u16 rz_mtu3_get_tstr_offset(struct rz_mtu3_channel *ch)
+{
+ u16 offset;
+
+ switch (ch->channel_number) {
+ case RZ_MTU3_CHAN_0:
+ case RZ_MTU3_CHAN_1:
+ case RZ_MTU3_CHAN_2:
+ case RZ_MTU3_CHAN_3:
+ case RZ_MTU3_CHAN_4:
+ case RZ_MTU3_CHAN_8:
+ offset = RZ_MTU3_TSTRA;
+ break;
+ case RZ_MTU3_CHAN_5:
+ offset = RZ_MTU3_TSTR;
+ break;
+ case RZ_MTU3_CHAN_6:
+ case RZ_MTU3_CHAN_7:
+ offset = RZ_MTU3_TSTRB;
+ break;
+ default:
+ offset = 0;
+ break;
+ }
+
+ return offset;
+}
+
+static u8 rz_mtu3_get_tstr_bit_pos(struct rz_mtu3_channel *ch)
+{
+ u8 bitpos;
+
+ switch (ch->channel_number) {
+ case RZ_MTU3_CHAN_0:
+ case RZ_MTU3_CHAN_1:
+ case RZ_MTU3_CHAN_2:
+ case RZ_MTU3_CHAN_6:
+ case RZ_MTU3_CHAN_7:
+ bitpos = ch->channel_number;
+ break;
+ case RZ_MTU3_CHAN_3:
+ bitpos = 6;
+ break;
+ case RZ_MTU3_CHAN_4:
+ bitpos = 7;
+ break;
+ case RZ_MTU3_CHAN_5:
+ bitpos = 2;
+ break;
+ case RZ_MTU3_CHAN_8:
+ bitpos = 3;
+ break;
+ default:
+ bitpos = 0;
+ break;
+ }
+
+ return bitpos;
+}
+
+static void rz_mtu3_start_stop_ch(struct rz_mtu3_channel *ch, bool start)
+{
+ struct rz_mtu3 *mtu = dev_get_drvdata(ch->dev->parent);
+ struct rz_mtu3_priv *priv = mtu->priv_data;
+ unsigned long flags, tstr;
+ u16 offset;
+ u8 bitpos;
+
+ /* start stop register shared by multiple timer channels */
+ raw_spin_lock_irqsave(&priv->lock, flags);
+
+ offset = rz_mtu3_get_tstr_offset(ch);
+ bitpos = rz_mtu3_get_tstr_bit_pos(ch);
+ tstr = rz_mtu3_shared_reg_read(ch, offset);
+ __assign_bit(bitpos, &tstr, start);
+ rz_mtu3_shared_reg_write(ch, offset, tstr);
+
+ raw_spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+bool rz_mtu3_is_enabled(struct rz_mtu3_channel *ch)
+{
+ struct rz_mtu3 *mtu = dev_get_drvdata(ch->dev->parent);
+ struct rz_mtu3_priv *priv = mtu->priv_data;
+ unsigned long flags, tstr;
+ bool ret = false;
+ u16 offset;
+ u8 bitpos;
+
+ /* start stop register shared by multiple timer channels */
+ raw_spin_lock_irqsave(&priv->lock, flags);
+
+ offset = rz_mtu3_get_tstr_offset(ch);
+ bitpos = rz_mtu3_get_tstr_bit_pos(ch);
+ tstr = rz_mtu3_shared_reg_read(ch, offset);
+ ret = tstr & BIT(bitpos);
+
+ raw_spin_unlock_irqrestore(&priv->lock, flags);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(rz_mtu3_is_enabled);
+
+int rz_mtu3_enable(struct rz_mtu3_channel *ch)
+{
+ /* enable channel */
+ rz_mtu3_start_stop_ch(ch, true);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(rz_mtu3_enable);
+
+void rz_mtu3_disable(struct rz_mtu3_channel *ch)
+{
+ /* disable channel */
+ rz_mtu3_start_stop_ch(ch, false);
+}
+EXPORT_SYMBOL_GPL(rz_mtu3_disable);
+
+static void rz_mtu3_reset_assert(void *data)
+{
+ struct rz_mtu3 *mtu = dev_get_drvdata(data);
+ struct rz_mtu3_priv *priv = mtu->priv_data;
+
+ mfd_remove_devices(data);
+ reset_control_assert(priv->rstc);
+}
+
+static const struct mfd_cell rz_mtu3_devs[] = {
+ {
+ .name = "rz-mtu3-counter",
+ },
+ {
+ .name = "pwm-rz-mtu3",
+ },
+};
+
+static int rz_mtu3_probe(struct platform_device *pdev)
+{
+ struct rz_mtu3_priv *priv;
+ struct rz_mtu3 *ddata;
+ unsigned int i;
+ int ret;
+
+ ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
+ if (!ddata)
+ return -ENOMEM;
+
+ ddata->priv_data = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+ if (!ddata->priv_data)
+ return -ENOMEM;
+
+ priv = ddata->priv_data;
+
+ priv->mmio = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(priv->mmio))
+ return PTR_ERR(priv->mmio);
+
+ priv->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL);
+ if (IS_ERR(priv->rstc))
+ return PTR_ERR(priv->rstc);
+
+ ddata->clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(ddata->clk))
+ return PTR_ERR(ddata->clk);
+
+ reset_control_deassert(priv->rstc);
+ raw_spin_lock_init(&priv->lock);
+ platform_set_drvdata(pdev, ddata);
+
+ for (i = 0; i < RZ_MTU_NUM_CHANNELS; i++) {
+ ddata->channels[i].channel_number = i;
+ ddata->channels[i].is_busy = false;
+ mutex_init(&ddata->channels[i].lock);
+ }
+
+ ret = mfd_add_devices(&pdev->dev, 0, rz_mtu3_devs,
+ ARRAY_SIZE(rz_mtu3_devs), NULL, 0, NULL);
+ if (ret < 0)
+ goto err_assert;
+
+ return devm_add_action_or_reset(&pdev->dev, rz_mtu3_reset_assert,
+ &pdev->dev);
+
+err_assert:
+ reset_control_assert(priv->rstc);
+ return ret;
+}
+
+static const struct of_device_id rz_mtu3_of_match[] = {
+ { .compatible = "renesas,rz-mtu3", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, rz_mtu3_of_match);
+
+static struct platform_driver rz_mtu3_driver = {
+ .probe = rz_mtu3_probe,
+ .driver = {
+ .name = "rz-mtu3",
+ .of_match_table = rz_mtu3_of_match,
+ },
+};
+module_platform_driver(rz_mtu3_driver);
+
+MODULE_AUTHOR("Biju Das <biju.das.jz@bp.renesas.com>");
+MODULE_DESCRIPTION("Renesas RZ/G2L MTU3a Core Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/rz-mtu3.h b/drivers/mfd/rz-mtu3.h
new file mode 100644
index 000000000000..51a1298b0613
--- /dev/null
+++ b/drivers/mfd/rz-mtu3.h
@@ -0,0 +1,147 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * MFD internals for Renesas RZ/G2L MTU3 Core driver
+ *
+ * Copyright (C) 2023 Renesas Electronics Corporation
+ */
+
+#ifndef RZ_MTU3_MFD_H
+#define RZ_MTU3_MFD_H
+
+#define MTU_8BIT_CH_0(_tier, _nfcr, _tcr, _tcr2, _tmdr1, _tiorh, _tiorl, _tbtm) \
+ { \
+ [RZ_MTU3_TIER] = _tier, \
+ [RZ_MTU3_NFCR] = _nfcr, \
+ [RZ_MTU3_TCR] = _tcr, \
+ [RZ_MTU3_TCR2] = _tcr2, \
+ [RZ_MTU3_TMDR1] = _tmdr1, \
+ [RZ_MTU3_TIORH] = _tiorh, \
+ [RZ_MTU3_TIORL] = _tiorl, \
+ [RZ_MTU3_TBTM] = _tbtm \
+ }
+
+#define MTU_8BIT_CH_1_2(_tier, _nfcr, _tsr, _tcr, _tcr2, _tmdr1, _tior) \
+ { \
+ [RZ_MTU3_TIER] = _tier, \
+ [RZ_MTU3_NFCR] = _nfcr, \
+ [RZ_MTU3_TSR] = _tsr, \
+ [RZ_MTU3_TCR] = _tcr, \
+ [RZ_MTU3_TCR2] = _tcr2, \
+ [RZ_MTU3_TMDR1] = _tmdr1, \
+ [RZ_MTU3_TIOR] = _tior \
+ } \
+
+#define MTU_8BIT_CH_3_4_6_7(_tier, _nfcr, _tsr, _tcr, _tcr2, _tmdr1, _tiorh, _tiorl, _tbtm) \
+ { \
+ [RZ_MTU3_TIER] = _tier, \
+ [RZ_MTU3_NFCR] = _nfcr, \
+ [RZ_MTU3_TSR] = _tsr, \
+ [RZ_MTU3_TCR] = _tcr, \
+ [RZ_MTU3_TCR2] = _tcr2, \
+ [RZ_MTU3_TMDR1] = _tmdr1, \
+ [RZ_MTU3_TIORH] = _tiorh, \
+ [RZ_MTU3_TIORL] = _tiorl, \
+ [RZ_MTU3_TBTM] = _tbtm \
+ } \
+
+#define MTU_8BIT_CH_5(_tier, _nfcr, _tstr, _tcntcmpclr, _tcru, _tcr2u, _tioru, \
+ _tcrv, _tcr2v, _tiorv, _tcrw, _tcr2w, _tiorw) \
+ { \
+ [RZ_MTU3_TIER] = _tier, \
+ [RZ_MTU3_NFCR] = _nfcr, \
+ [RZ_MTU3_TSTR] = _tstr, \
+ [RZ_MTU3_TCNTCMPCLR] = _tcntcmpclr, \
+ [RZ_MTU3_TCRU] = _tcru, \
+ [RZ_MTU3_TCR2U] = _tcr2u, \
+ [RZ_MTU3_TIORU] = _tioru, \
+ [RZ_MTU3_TCRV] = _tcrv, \
+ [RZ_MTU3_TCR2V] = _tcr2v, \
+ [RZ_MTU3_TIORV] = _tiorv, \
+ [RZ_MTU3_TCRW] = _tcrw, \
+ [RZ_MTU3_TCR2W] = _tcr2w, \
+ [RZ_MTU3_TIORW] = _tiorw \
+ } \
+
+#define MTU_8BIT_CH_8(_tier, _nfcr, _tcr, _tcr2, _tmdr1, _tiorh, _tiorl) \
+ { \
+ [RZ_MTU3_TIER] = _tier, \
+ [RZ_MTU3_NFCR] = _nfcr, \
+ [RZ_MTU3_TCR] = _tcr, \
+ [RZ_MTU3_TCR2] = _tcr2, \
+ [RZ_MTU3_TMDR1] = _tmdr1, \
+ [RZ_MTU3_TIORH] = _tiorh, \
+ [RZ_MTU3_TIORL] = _tiorl \
+ } \
+
+#define MTU_16BIT_CH_0(_tcnt, _tgra, _tgrb, _tgrc, _tgrd, _tgre, _tgrf) \
+ { \
+ [RZ_MTU3_TCNT] = _tcnt, \
+ [RZ_MTU3_TGRA] = _tgra, \
+ [RZ_MTU3_TGRB] = _tgrb, \
+ [RZ_MTU3_TGRC] = _tgrc, \
+ [RZ_MTU3_TGRD] = _tgrd, \
+ [RZ_MTU3_TGRE] = _tgre, \
+ [RZ_MTU3_TGRF] = _tgrf \
+ }
+
+#define MTU_16BIT_CH_1_2(_tcnt, _tgra, _tgrb) \
+ { \
+ [RZ_MTU3_TCNT] = _tcnt, \
+ [RZ_MTU3_TGRA] = _tgra, \
+ [RZ_MTU3_TGRB] = _tgrb \
+ }
+
+#define MTU_16BIT_CH_3_6(_tcnt, _tgra, _tgrb, _tgrc, _tgrd, _tgre) \
+ { \
+ [RZ_MTU3_TCNT] = _tcnt, \
+ [RZ_MTU3_TGRA] = _tgra, \
+ [RZ_MTU3_TGRB] = _tgrb, \
+ [RZ_MTU3_TGRC] = _tgrc, \
+ [RZ_MTU3_TGRD] = _tgrd, \
+ [RZ_MTU3_TGRE] = _tgre \
+ }
+
+#define MTU_16BIT_CH_4_7(_tcnt, _tgra, _tgrb, _tgrc, _tgrd, _tgre, _tgrf, \
+ _tadcr, _tadcora, _tadcorb, _tadcobra, _tadcobrb) \
+ { \
+ [RZ_MTU3_TCNT] = _tcnt, \
+ [RZ_MTU3_TGRA] = _tgra, \
+ [RZ_MTU3_TGRB] = _tgrb, \
+ [RZ_MTU3_TGRC] = _tgrc, \
+ [RZ_MTU3_TGRD] = _tgrd, \
+ [RZ_MTU3_TGRE] = _tgre, \
+ [RZ_MTU3_TGRF] = _tgrf, \
+ [RZ_MTU3_TADCR] = _tadcr, \
+ [RZ_MTU3_TADCORA] = _tadcora, \
+ [RZ_MTU3_TADCORB] = _tadcorb, \
+ [RZ_MTU3_TADCOBRA] = _tadcobra, \
+ [RZ_MTU3_TADCOBRB] = _tadcobrb \
+ }
+
+#define MTU_16BIT_CH_5(_tcntu, _tgru, _tcntv, _tgrv, _tcntw, _tgrw) \
+ { \
+ [RZ_MTU3_TCNTU] = _tcntu, \
+ [RZ_MTU3_TGRU] = _tgru, \
+ [RZ_MTU3_TCNTV] = _tcntv, \
+ [RZ_MTU3_TGRV] = _tgrv, \
+ [RZ_MTU3_TCNTW] = _tcntw, \
+ [RZ_MTU3_TGRW] = _tgrw \
+ }
+
+#define MTU_32BIT_CH_1(_tcntlw, _tgralw, _tgrblw) \
+ { \
+ [RZ_MTU3_TCNTLW] = _tcntlw, \
+ [RZ_MTU3_TGRALW] = _tgralw, \
+ [RZ_MTU3_TGRBLW] = _tgrblw \
+ }
+
+#define MTU_32BIT_CH_8(_tcnt, _tgra, _tgrb, _tgrc, _tgrd) \
+ { \
+ [RZ_MTU3_TCNT] = _tcnt, \
+ [RZ_MTU3_TGRA] = _tgra, \
+ [RZ_MTU3_TGRB] = _tgrb, \
+ [RZ_MTU3_TGRC] = _tgrc, \
+ [RZ_MTU3_TGRD] = _tgrd \
+ }
+
+#endif
diff --git a/drivers/mfd/sec-core.c b/drivers/mfd/sec-core.c
index b03edda56009..c2d0ed496959 100644
--- a/drivers/mfd/sec-core.c
+++ b/drivers/mfd/sec-core.c
@@ -24,22 +24,9 @@
#include <linux/mfd/samsung/s2mps14.h>
#include <linux/mfd/samsung/s2mps15.h>
#include <linux/mfd/samsung/s2mpu02.h>
-#include <linux/mfd/samsung/s5m8763.h>
#include <linux/mfd/samsung/s5m8767.h>
#include <linux/regmap.h>
-static const struct mfd_cell s5m8751_devs[] = {
- { .name = "s5m8751-pmic", },
- { .name = "s5m-charger", },
- { .name = "s5m8751-codec", },
-};
-
-static const struct mfd_cell s5m8763_devs[] = {
- { .name = "s5m8763-pmic", },
- { .name = "s5m-rtc", },
- { .name = "s5m-charger", },
-};
-
static const struct mfd_cell s5m8767_devs[] = {
{ .name = "s5m8767-pmic", },
{ .name = "s5m-rtc", },
@@ -158,19 +145,6 @@ static bool s2mpu02_volatile(struct device *dev, unsigned int reg)
}
}
-static bool s5m8763_volatile(struct device *dev, unsigned int reg)
-{
- switch (reg) {
- case S5M8763_REG_IRQM1:
- case S5M8763_REG_IRQM2:
- case S5M8763_REG_IRQM3:
- case S5M8763_REG_IRQM4:
- return false;
- default:
- return true;
- }
-}
-
static const struct regmap_config sec_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
@@ -230,15 +204,6 @@ static const struct regmap_config s2mpu02_regmap_config = {
.cache_type = REGCACHE_FLAT,
};
-static const struct regmap_config s5m8763_regmap_config = {
- .reg_bits = 8,
- .val_bits = 8,
-
- .max_register = S5M8763_REG_LBCNFG2,
- .volatile_reg = s5m8763_volatile,
- .cache_type = REGCACHE_FLAT,
-};
-
static const struct regmap_config s5m8767_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
@@ -348,9 +313,6 @@ static int sec_pmic_probe(struct i2c_client *i2c)
case S2MPS15X:
regmap = &s2mps15_regmap_config;
break;
- case S5M8763X:
- regmap = &s5m8763_regmap_config;
- break;
case S5M8767X:
regmap = &s5m8767_regmap_config;
break;
@@ -375,14 +337,6 @@ static int sec_pmic_probe(struct i2c_client *i2c)
pm_runtime_set_active(sec_pmic->dev);
switch (sec_pmic->device_type) {
- case S5M8751X:
- sec_devs = s5m8751_devs;
- num_sec_devs = ARRAY_SIZE(s5m8751_devs);
- break;
- case S5M8763X:
- sec_devs = s5m8763_devs;
- num_sec_devs = ARRAY_SIZE(s5m8763_devs);
- break;
case S5M8767X:
sec_devs = s5m8767_devs;
num_sec_devs = ARRAY_SIZE(s5m8767_devs);
diff --git a/drivers/mfd/sec-irq.c b/drivers/mfd/sec-irq.c
index f5f59fdc72fe..e191aeb0c07c 100644
--- a/drivers/mfd/sec-irq.c
+++ b/drivers/mfd/sec-irq.c
@@ -14,7 +14,6 @@
#include <linux/mfd/samsung/s2mps11.h>
#include <linux/mfd/samsung/s2mps14.h>
#include <linux/mfd/samsung/s2mpu02.h>
-#include <linux/mfd/samsung/s5m8763.h>
#include <linux/mfd/samsung/s5m8767.h>
static const struct regmap_irq s2mps11_irqs[] = {
@@ -297,81 +296,6 @@ static const struct regmap_irq s5m8767_irqs[] = {
},
};
-static const struct regmap_irq s5m8763_irqs[] = {
- [S5M8763_IRQ_DCINF] = {
- .reg_offset = 0,
- .mask = S5M8763_IRQ_DCINF_MASK,
- },
- [S5M8763_IRQ_DCINR] = {
- .reg_offset = 0,
- .mask = S5M8763_IRQ_DCINR_MASK,
- },
- [S5M8763_IRQ_JIGF] = {
- .reg_offset = 0,
- .mask = S5M8763_IRQ_JIGF_MASK,
- },
- [S5M8763_IRQ_JIGR] = {
- .reg_offset = 0,
- .mask = S5M8763_IRQ_JIGR_MASK,
- },
- [S5M8763_IRQ_PWRONF] = {
- .reg_offset = 0,
- .mask = S5M8763_IRQ_PWRONF_MASK,
- },
- [S5M8763_IRQ_PWRONR] = {
- .reg_offset = 0,
- .mask = S5M8763_IRQ_PWRONR_MASK,
- },
- [S5M8763_IRQ_WTSREVNT] = {
- .reg_offset = 1,
- .mask = S5M8763_IRQ_WTSREVNT_MASK,
- },
- [S5M8763_IRQ_SMPLEVNT] = {
- .reg_offset = 1,
- .mask = S5M8763_IRQ_SMPLEVNT_MASK,
- },
- [S5M8763_IRQ_ALARM1] = {
- .reg_offset = 1,
- .mask = S5M8763_IRQ_ALARM1_MASK,
- },
- [S5M8763_IRQ_ALARM0] = {
- .reg_offset = 1,
- .mask = S5M8763_IRQ_ALARM0_MASK,
- },
- [S5M8763_IRQ_ONKEY1S] = {
- .reg_offset = 2,
- .mask = S5M8763_IRQ_ONKEY1S_MASK,
- },
- [S5M8763_IRQ_TOPOFFR] = {
- .reg_offset = 2,
- .mask = S5M8763_IRQ_TOPOFFR_MASK,
- },
- [S5M8763_IRQ_DCINOVPR] = {
- .reg_offset = 2,
- .mask = S5M8763_IRQ_DCINOVPR_MASK,
- },
- [S5M8763_IRQ_CHGRSTF] = {
- .reg_offset = 2,
- .mask = S5M8763_IRQ_CHGRSTF_MASK,
- },
- [S5M8763_IRQ_DONER] = {
- .reg_offset = 2,
- .mask = S5M8763_IRQ_DONER_MASK,
- },
- [S5M8763_IRQ_CHGFAULT] = {
- .reg_offset = 2,
- .mask = S5M8763_IRQ_CHGFAULT_MASK,
- },
- [S5M8763_IRQ_LOBAT1] = {
- .reg_offset = 3,
- .mask = S5M8763_IRQ_LOBAT1_MASK,
- },
- [S5M8763_IRQ_LOBAT2] = {
- .reg_offset = 3,
- .mask = S5M8763_IRQ_LOBAT2_MASK,
- },
-};
-
static const struct regmap_irq_chip s2mps11_irq_chip = {
.name = "s2mps11",
.irqs = s2mps11_irqs,
@@ -425,16 +349,6 @@ static const struct regmap_irq_chip s5m8767_irq_chip = {
.ack_base = S5M8767_REG_INT1,
};
-static const struct regmap_irq_chip s5m8763_irq_chip = {
- .name = "s5m8763",
- .irqs = s5m8763_irqs,
- .num_irqs = ARRAY_SIZE(s5m8763_irqs),
- .num_regs = 4,
- .status_base = S5M8763_REG_IRQ1,
- .mask_base = S5M8763_REG_IRQM1,
- .ack_base = S5M8763_REG_IRQ1,
-};
-
int sec_irq_init(struct sec_pmic_dev *sec_pmic)
{
int ret = 0;
@@ -448,9 +362,6 @@ int sec_irq_init(struct sec_pmic_dev *sec_pmic)
}
switch (type) {
- case S5M8763X:
- sec_irq_chip = &s5m8763_irq_chip;
- break;
case S5M8767X:
sec_irq_chip = &s5m8767_irq_chip;
break;
diff --git a/drivers/mfd/si476x-cmd.c b/drivers/mfd/si476x-cmd.c
index f32f1fb93e37..c9a0ec084aa8 100644
--- a/drivers/mfd/si476x-cmd.c
+++ b/drivers/mfd/si476x-cmd.c
@@ -251,7 +251,7 @@ static int si476x_core_parse_and_nag_about_error(struct si476x_core *core)
* @usecs: amount of time to wait before reading the response (in
* usecs)
*
- * Function returns 0 on succsess and negative error code on
+ * Function returns 0 on success and negative error code on
* failure
*/
static int si476x_core_send_command(struct si476x_core *core,
@@ -398,7 +398,7 @@ static int si476x_cmd_tune_seek_freq(struct si476x_core *core,
* The command requests the firmware and patch version for currently
* loaded firmware (dependent on the function of the device FM/AM/WB)
*
- * Function returns 0 on succsess and negative error code on
+ * Function returns 0 on success and negative error code on
* failure
*/
int si476x_core_cmd_func_info(struct si476x_core *core,
@@ -429,7 +429,7 @@ EXPORT_SYMBOL_GPL(si476x_core_cmd_func_info);
* @property: property address
* @value: property value
*
- * Function returns 0 on succsess and negative error code on
+ * Function returns 0 on success and negative error code on
* failure
*/
int si476x_core_cmd_set_property(struct si476x_core *core,
@@ -545,13 +545,13 @@ EXPORT_SYMBOL_GPL(si476x_core_cmd_dig_audio_pin_cfg);
* SI476X_IQCLK_NOOP - do not modify the behaviour
* SI476X_IQCLK_TRISTATE - put the pin in tristate condition,
* enable 1MOhm pulldown
- * SI476X_IQCLK_IQ - set pin to be a part of I/Q interace
+ * SI476X_IQCLK_IQ - set pin to be a part of I/Q interface
* in master mode
* @iqfs: - IQFS pin function configuration:
* SI476X_IQFS_NOOP - do not modify the behaviour
* SI476X_IQFS_TRISTATE - put the pin in tristate condition,
* enable 1MOhm pulldown
- * SI476X_IQFS_IQ - set pin to be a part of I/Q interace
+ * SI476X_IQFS_IQ - set pin to be a part of I/Q interface
* in master mode
* @iout: - IOUT pin function configuration:
* SI476X_IOUT_NOOP - do not modify the behaviour
@@ -589,7 +589,7 @@ EXPORT_SYMBOL_GPL(si476x_core_cmd_zif_pin_cfg);
/**
* si476x_core_cmd_ic_link_gpo_ctl_pin_cfg - send
- * 'IC_LINK_GPIO_CTL_PIN_CFG' comand to the device
+ * 'IC_LINK_GPIO_CTL_PIN_CFG' command to the device
* @core: - device to send the command to
* @icin: - ICIN pin function configuration:
* SI476X_ICIN_NOOP - do not modify the behaviour
@@ -1014,7 +1014,7 @@ EXPORT_SYMBOL_GPL(si476x_core_cmd_fm_phase_diversity);
* NOTE caller must hold core lock
*
* Function returns the value of the status bit in case of success and
- * negative error code in case of failre.
+ * negative error code in case of failure.
*/
int si476x_core_cmd_fm_phase_div_status(struct si476x_core *core)
{
diff --git a/drivers/mfd/simple-mfd-i2c.c b/drivers/mfd/simple-mfd-i2c.c
index e31f13fd6a79..20782b4dd172 100644
--- a/drivers/mfd/simple-mfd-i2c.c
+++ b/drivers/mfd/simple-mfd-i2c.c
@@ -72,9 +72,22 @@ static const struct simple_mfd_data silergy_sy7636a = {
.mfd_cell_size = ARRAY_SIZE(sy7636a_cells),
};
+static const struct mfd_cell max597x_cells[] = {
+ { .name = "max597x-regulator", },
+ { .name = "max597x-iio", },
+ { .name = "max597x-led", },
+};
+
+static const struct simple_mfd_data maxim_max597x = {
+ .mfd_cell = max597x_cells,
+ .mfd_cell_size = ARRAY_SIZE(max597x_cells),
+};
+
static const struct of_device_id simple_mfd_i2c_of_match[] = {
{ .compatible = "kontron,sl28cpld" },
{ .compatible = "silergy,sy7636a", .data = &silergy_sy7636a},
+ { .compatible = "maxim,max5970", .data = &maxim_max597x},
+ { .compatible = "maxim,max5978", .data = &maxim_max597x},
{}
};
MODULE_DEVICE_TABLE(of, simple_mfd_i2c_of_match);
diff --git a/drivers/mfd/ssbi.c b/drivers/mfd/ssbi.c
index 94f60df0decd..dee89db3471d 100644
--- a/drivers/mfd/ssbi.c
+++ b/drivers/mfd/ssbi.c
@@ -262,7 +262,6 @@ EXPORT_SYMBOL_GPL(ssbi_write);
static int ssbi_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
- struct resource *mem_res;
struct ssbi *ssbi;
const char *type;
@@ -270,8 +269,7 @@ static int ssbi_probe(struct platform_device *pdev)
if (!ssbi)
return -ENOMEM;
- mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- ssbi->base = devm_ioremap_resource(&pdev->dev, mem_res);
+ ssbi->base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
if (IS_ERR(ssbi->base))
return PTR_ERR(ssbi->base);
diff --git a/drivers/mfd/stmpe-i2c.c b/drivers/mfd/stmpe-i2c.c
index d4944fc1feb1..7998e0db1e15 100644
--- a/drivers/mfd/stmpe-i2c.c
+++ b/drivers/mfd/stmpe-i2c.c
@@ -135,6 +135,5 @@ static void __exit stmpe_exit(void)
}
module_exit(stmpe_exit);
-MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("STMPE MFD I2C Interface Driver");
MODULE_AUTHOR("Rabin Vincent <rabin.vincent@stericsson.com>");
diff --git a/drivers/mfd/stmpe-spi.c b/drivers/mfd/stmpe-spi.c
index e9cbf33502b3..792236f56399 100644
--- a/drivers/mfd/stmpe-spi.c
+++ b/drivers/mfd/stmpe-spi.c
@@ -154,6 +154,5 @@ static void __exit stmpe_exit(void)
}
module_exit(stmpe_exit);
-MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("STMPE MFD SPI Interface Driver");
MODULE_AUTHOR("Viresh Kumar <vireshk@kernel.org>");
diff --git a/drivers/mfd/stmpe.c b/drivers/mfd/stmpe.c
index c304d20bb988..a92301dfc712 100644
--- a/drivers/mfd/stmpe.c
+++ b/drivers/mfd/stmpe.c
@@ -1378,7 +1378,7 @@ int stmpe_probe(struct stmpe_client_info *ci, enum stmpe_partnum partnum)
stmpe_of_probe(pdata, np);
- if (of_find_property(np, "interrupts", NULL) == NULL)
+ if (!of_property_present(np, "interrupts"))
ci->irq = -1;
stmpe = devm_kzalloc(ci->dev, sizeof(struct stmpe), GFP_KERNEL);
diff --git a/drivers/mfd/sun4i-gpadc.c b/drivers/mfd/sun4i-gpadc.c
index edc180d83a4b..d1cbea27b136 100644
--- a/drivers/mfd/sun4i-gpadc.c
+++ b/drivers/mfd/sun4i-gpadc.c
@@ -93,7 +93,6 @@ MODULE_DEVICE_TABLE(of, sun4i_gpadc_of_match);
static int sun4i_gpadc_probe(struct platform_device *pdev)
{
struct sun4i_gpadc_dev *dev;
- struct resource *mem;
const struct of_device_id *of_id;
const struct mfd_cell *cells;
unsigned int irq, size;
@@ -124,8 +123,7 @@ static int sun4i_gpadc_probe(struct platform_device *pdev)
if (!dev)
return -ENOMEM;
- mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- dev->base = devm_ioremap_resource(&pdev->dev, mem);
+ dev->base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
if (IS_ERR(dev->base))
return PTR_ERR(dev->base);
diff --git a/drivers/mfd/tc3589x.c b/drivers/mfd/tc3589x.c
index 1f6e0d682cd9..cbfe19d1b145 100644
--- a/drivers/mfd/tc3589x.c
+++ b/drivers/mfd/tc3589x.c
@@ -502,6 +502,5 @@ static void __exit tc3589x_exit(void)
}
module_exit(tc3589x_exit);
-MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("TC3589x MFD core driver");
MODULE_AUTHOR("Hanumath Prasad, Rabin Vincent");
diff --git a/drivers/mfd/tps6586x.c b/drivers/mfd/tps6586x.c
index 2d947f3f606a..90e23232b6b0 100644
--- a/drivers/mfd/tps6586x.c
+++ b/drivers/mfd/tps6586x.c
@@ -638,4 +638,3 @@ module_exit(tps6586x_exit);
MODULE_DESCRIPTION("TPS6586X core driver");
MODULE_AUTHOR("Mike Rapoport <mike@compulab.co.il>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/tqmx86.c b/drivers/mfd/tqmx86.c
index 7ae906ff8e35..fac02875fe7d 100644
--- a/drivers/mfd/tqmx86.c
+++ b/drivers/mfd/tqmx86.c
@@ -16,8 +16,8 @@
#include <linux/platform_data/i2c-ocores.h>
#include <linux/platform_device.h>
-#define TQMX86_IOBASE 0x160
-#define TQMX86_IOSIZE 0x3f
+#define TQMX86_IOBASE 0x180
+#define TQMX86_IOSIZE 0x20
#define TQMX86_IOBASE_I2C 0x1a0
#define TQMX86_IOSIZE_I2C 0xa
#define TQMX86_IOBASE_WATCHDOG 0x18b
@@ -25,14 +25,14 @@
#define TQMX86_IOBASE_GPIO 0x18d
#define TQMX86_IOSIZE_GPIO 0x4
-#define TQMX86_REG_BOARD_ID 0x20
+#define TQMX86_REG_BOARD_ID 0x00
#define TQMX86_REG_BOARD_ID_E38M 1
#define TQMX86_REG_BOARD_ID_50UC 2
#define TQMX86_REG_BOARD_ID_E38C 3
#define TQMX86_REG_BOARD_ID_60EB 4
-#define TQMX86_REG_BOARD_ID_E39M 5
-#define TQMX86_REG_BOARD_ID_E39C 6
-#define TQMX86_REG_BOARD_ID_E39x 7
+#define TQMX86_REG_BOARD_ID_E39MS 5
+#define TQMX86_REG_BOARD_ID_E39C1 6
+#define TQMX86_REG_BOARD_ID_E39C2 7
#define TQMX86_REG_BOARD_ID_70EB 8
#define TQMX86_REG_BOARD_ID_80UC 9
#define TQMX86_REG_BOARD_ID_110EB 11
@@ -40,18 +40,18 @@
#define TQMX86_REG_BOARD_ID_E40S 13
#define TQMX86_REG_BOARD_ID_E40C1 14
#define TQMX86_REG_BOARD_ID_E40C2 15
-#define TQMX86_REG_BOARD_REV 0x21
-#define TQMX86_REG_IO_EXT_INT 0x26
+#define TQMX86_REG_BOARD_REV 0x01
+#define TQMX86_REG_IO_EXT_INT 0x06
#define TQMX86_REG_IO_EXT_INT_NONE 0
#define TQMX86_REG_IO_EXT_INT_7 1
#define TQMX86_REG_IO_EXT_INT_9 2
#define TQMX86_REG_IO_EXT_INT_12 3
#define TQMX86_REG_IO_EXT_INT_MASK 0x3
#define TQMX86_REG_IO_EXT_INT_GPIO_SHIFT 4
+#define TQMX86_REG_SAUC 0x17
-#define TQMX86_REG_I2C_DETECT 0x47
+#define TQMX86_REG_I2C_DETECT 0x1a7
#define TQMX86_REG_I2C_DETECT_SOFT 0xa5
-#define TQMX86_REG_I2C_INT_EN 0x49
static uint gpio_irq;
module_param(gpio_irq, uint, 0);
@@ -111,7 +111,7 @@ static const struct mfd_cell tqmx86_devs[] = {
},
};
-static const char *tqmx86_board_id_to_name(u8 board_id)
+static const char *tqmx86_board_id_to_name(u8 board_id, u8 sauc)
{
switch (board_id) {
case TQMX86_REG_BOARD_ID_E38M:
@@ -122,12 +122,12 @@ static const char *tqmx86_board_id_to_name(u8 board_id)
return "TQMxE38C";
case TQMX86_REG_BOARD_ID_60EB:
return "TQMx60EB";
- case TQMX86_REG_BOARD_ID_E39M:
- return "TQMxE39M";
- case TQMX86_REG_BOARD_ID_E39C:
- return "TQMxE39C";
- case TQMX86_REG_BOARD_ID_E39x:
- return "TQMxE39x";
+ case TQMX86_REG_BOARD_ID_E39MS:
+ return (sauc == 0xff) ? "TQMxE39M" : "TQMxE39S";
+ case TQMX86_REG_BOARD_ID_E39C1:
+ return "TQMxE39C1";
+ case TQMX86_REG_BOARD_ID_E39C2:
+ return "TQMxE39C2";
case TQMX86_REG_BOARD_ID_70EB:
return "TQMx70EB";
case TQMX86_REG_BOARD_ID_80UC:
@@ -160,9 +160,9 @@ static int tqmx86_board_id_to_clk_rate(struct device *dev, u8 board_id)
case TQMX86_REG_BOARD_ID_E40C1:
case TQMX86_REG_BOARD_ID_E40C2:
return 24000;
- case TQMX86_REG_BOARD_ID_E39M:
- case TQMX86_REG_BOARD_ID_E39C:
- case TQMX86_REG_BOARD_ID_E39x:
+ case TQMX86_REG_BOARD_ID_E39MS:
+ case TQMX86_REG_BOARD_ID_E39C1:
+ case TQMX86_REG_BOARD_ID_E39C2:
return 25000;
case TQMX86_REG_BOARD_ID_E38M:
case TQMX86_REG_BOARD_ID_E38C:
@@ -176,7 +176,7 @@ static int tqmx86_board_id_to_clk_rate(struct device *dev, u8 board_id)
static int tqmx86_probe(struct platform_device *pdev)
{
- u8 board_id, rev, i2c_det, io_ext_int_val;
+ u8 board_id, sauc, rev, i2c_det, io_ext_int_val;
struct device *dev = &pdev->dev;
u8 gpio_irq_cfg, readback;
const char *board_name;
@@ -206,14 +206,20 @@ static int tqmx86_probe(struct platform_device *pdev)
return -ENOMEM;
board_id = ioread8(io_base + TQMX86_REG_BOARD_ID);
- board_name = tqmx86_board_id_to_name(board_id);
+ sauc = ioread8(io_base + TQMX86_REG_SAUC);
+ board_name = tqmx86_board_id_to_name(board_id, sauc);
rev = ioread8(io_base + TQMX86_REG_BOARD_REV);
dev_info(dev,
"Found %s - Board ID %d, PCB Revision %d, PLD Revision %d\n",
board_name, board_id, rev >> 4, rev & 0xf);
- i2c_det = ioread8(io_base + TQMX86_REG_I2C_DETECT);
+ /*
+ * The I2C_DETECT register is in the range assigned to the I2C driver
+ * later, so we don't extend TQMX86_IOSIZE. Use inb() for this one-off
+ * access instead of ioport_map + unmap.
+ */
+ i2c_det = inb(TQMX86_REG_I2C_DETECT);
if (gpio_irq_cfg) {
io_ext_int_val =
diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
index e2d9a93be43b..e801b7ce010f 100644
--- a/drivers/mfd/twl-core.c
+++ b/drivers/mfd/twl-core.c
@@ -594,71 +594,6 @@ int twl_get_hfclk_rate(void)
}
EXPORT_SYMBOL_GPL(twl_get_hfclk_rate);
-static struct device *
-add_numbered_child(unsigned mod_no, const char *name, int num,
- void *pdata, unsigned pdata_len,
- bool can_wakeup, int irq0, int irq1)
-{
- struct platform_device *pdev;
- struct twl_client *twl;
- int status, sid;
-
- if (unlikely(mod_no >= twl_get_last_module())) {
- pr_err("%s: invalid module number %d\n", DRIVER_NAME, mod_no);
- return ERR_PTR(-EPERM);
- }
- sid = twl_priv->twl_map[mod_no].sid;
- twl = &twl_priv->twl_modules[sid];
-
- pdev = platform_device_alloc(name, num);
- if (!pdev)
- return ERR_PTR(-ENOMEM);
-
- pdev->dev.parent = &twl->client->dev;
-
- if (pdata) {
- status = platform_device_add_data(pdev, pdata, pdata_len);
- if (status < 0) {
- dev_dbg(&pdev->dev, "can't add platform_data\n");
- goto put_device;
- }
- }
-
- if (irq0) {
- struct resource r[2] = {
- { .start = irq0, .flags = IORESOURCE_IRQ, },
- { .start = irq1, .flags = IORESOURCE_IRQ, },
- };
-
- status = platform_device_add_resources(pdev, r, irq1 ? 2 : 1);
- if (status < 0) {
- dev_dbg(&pdev->dev, "can't add irqs\n");
- goto put_device;
- }
- }
-
- status = platform_device_add(pdev);
- if (status)
- goto put_device;
-
- device_init_wakeup(&pdev->dev, can_wakeup);
-
- return &pdev->dev;
-
-put_device:
- platform_device_put(pdev);
- dev_err(&twl->client->dev, "failed to add device %s\n", name);
- return ERR_PTR(status);
-}
-
-static inline struct device *add_child(unsigned mod_no, const char *name,
- void *pdata, unsigned pdata_len,
- bool can_wakeup, int irq0, int irq1)
-{
- return add_numbered_child(mod_no, name, -1, pdata, pdata_len,
- can_wakeup, irq0, irq1);
-}
-
/*----------------------------------------------------------------------*/
/*
diff --git a/drivers/mfd/twl4030-audio.c b/drivers/mfd/twl4030-audio.c
index 4536d829b43e..88002f8941e5 100644
--- a/drivers/mfd/twl4030-audio.c
+++ b/drivers/mfd/twl4030-audio.c
@@ -285,5 +285,4 @@ module_platform_driver(twl4030_audio_driver);
MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@ti.com>");
MODULE_DESCRIPTION("TWL4030 audio block MFD driver");
-MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:twl4030-audio");
diff --git a/drivers/mfd/twl6040.c b/drivers/mfd/twl6040.c
index fc97fa5a2d0c..e982119bbefa 100644
--- a/drivers/mfd/twl6040.c
+++ b/drivers/mfd/twl6040.c
@@ -839,4 +839,3 @@ module_i2c_driver(twl6040_driver);
MODULE_DESCRIPTION("TWL6040 MFD");
MODULE_AUTHOR("Misael Lopez Cruz <misael.lopez@ti.com>");
MODULE_AUTHOR("Jorge Eduardo Candelaria <jorge.candelaria@ti.com>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/wm8994-core.c b/drivers/mfd/wm8994-core.c
index a89221bffde5..c419ab0c0eae 100644
--- a/drivers/mfd/wm8994-core.c
+++ b/drivers/mfd/wm8994-core.c
@@ -279,20 +279,11 @@ static int wm8994_set_pdata_from_of(struct wm8994 *wm8994)
of_property_read_u32_array(np, "wlf,micbias-cfg", pdata->micbias,
ARRAY_SIZE(pdata->micbias));
- pdata->lineout1_diff = true;
- pdata->lineout2_diff = true;
- if (of_find_property(np, "wlf,lineout1-se", NULL))
- pdata->lineout1_diff = false;
- if (of_find_property(np, "wlf,lineout2-se", NULL))
- pdata->lineout2_diff = false;
-
- if (of_find_property(np, "wlf,lineout1-feedback", NULL))
- pdata->lineout1fb = true;
- if (of_find_property(np, "wlf,lineout2-feedback", NULL))
- pdata->lineout2fb = true;
-
- if (of_find_property(np, "wlf,ldoena-always-driven", NULL))
- pdata->lineout2fb = true;
+ pdata->lineout1_diff = !of_property_read_bool(np, "wlf,lineout1-se");
+ pdata->lineout2_diff = !of_property_read_bool(np, "wlf,lineout2-se");
+ pdata->lineout1fb = of_property_read_bool(np, "wlf,lineout1-feedback");
+ pdata->lineout2fb = of_property_read_bool(np, "wlf,lineout2-feedback") ||
+ of_property_read_bool(np, "wlf,ldoena-always-driven");
pdata->spkmode_pu = of_property_read_bool(np, "wlf,spkmode-pu");
diff --git a/drivers/rtc/rtc-s5m.c b/drivers/rtc/rtc-s5m.c
index 4243fe6d3842..dad294a0ce2a 100644
--- a/drivers/rtc/rtc-s5m.c
+++ b/drivers/rtc/rtc-s5m.c
@@ -85,7 +85,7 @@ struct s5m_rtc_reg_config {
unsigned int write_alarm_udr_mask;
};
-/* Register map for S5M8763 and S5M8767 */
+/* Register map for S5M8767 */
static const struct s5m_rtc_reg_config s5m_rtc_regs = {
.regs_count = 8,
.time = S5M_RTC_SEC,
@@ -236,7 +236,6 @@ static int s5m_check_peding_alarm_interrupt(struct s5m_rtc_info *info,
switch (info->device_type) {
case S5M8767X:
- case S5M8763X:
ret = regmap_read(info->regmap, S5M_RTC_STATUS, &val);
val &= S5M_ALARM0_STATUS;
break;
@@ -299,7 +298,6 @@ static int s5m8767_rtc_set_alarm_reg(struct s5m_rtc_info *info)
data |= info->regs->write_alarm_udr_mask;
switch (info->device_type) {
- case S5M8763X:
case S5M8767X:
data &= ~S5M_RTC_TIME_EN_MASK;
break;
@@ -329,38 +327,6 @@ static int s5m8767_rtc_set_alarm_reg(struct s5m_rtc_info *info)
return ret;
}
-static void s5m8763_data_to_tm(u8 *data, struct rtc_time *tm)
-{
- tm->tm_sec = bcd2bin(data[RTC_SEC]);
- tm->tm_min = bcd2bin(data[RTC_MIN]);
-
- if (data[RTC_HOUR] & HOUR_12) {
- tm->tm_hour = bcd2bin(data[RTC_HOUR] & 0x1f);
- if (data[RTC_HOUR] & HOUR_PM)
- tm->tm_hour += 12;
- } else {
- tm->tm_hour = bcd2bin(data[RTC_HOUR] & 0x3f);
- }
-
- tm->tm_wday = data[RTC_WEEKDAY] & 0x07;
- tm->tm_mday = bcd2bin(data[RTC_DATE]);
- tm->tm_mon = bcd2bin(data[RTC_MONTH]);
- tm->tm_year = bcd2bin(data[RTC_YEAR1]) + bcd2bin(data[RTC_YEAR2]) * 100;
- tm->tm_year -= 1900;
-}
-
-static void s5m8763_tm_to_data(struct rtc_time *tm, u8 *data)
-{
- data[RTC_SEC] = bin2bcd(tm->tm_sec);
- data[RTC_MIN] = bin2bcd(tm->tm_min);
- data[RTC_HOUR] = bin2bcd(tm->tm_hour);
- data[RTC_WEEKDAY] = tm->tm_wday;
- data[RTC_DATE] = bin2bcd(tm->tm_mday);
- data[RTC_MONTH] = bin2bcd(tm->tm_mon);
- data[RTC_YEAR1] = bin2bcd(tm->tm_year % 100);
- data[RTC_YEAR2] = bin2bcd((tm->tm_year + 1900) / 100);
-}
-
static int s5m_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
struct s5m_rtc_info *info = dev_get_drvdata(dev);
@@ -385,10 +351,6 @@ static int s5m_rtc_read_time(struct device *dev, struct rtc_time *tm)
return ret;
switch (info->device_type) {
- case S5M8763X:
- s5m8763_data_to_tm(data, tm);
- break;
-
case S5M8767X:
case S2MPS15X:
case S2MPS14X:
@@ -412,9 +374,6 @@ static int s5m_rtc_set_time(struct device *dev, struct rtc_time *tm)
int ret = 0;
switch (info->device_type) {
- case S5M8763X:
- s5m8763_tm_to_data(tm, data);
- break;
case S5M8767X:
case S2MPS15X:
case S2MPS14X:
@@ -444,7 +403,6 @@ static int s5m_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
struct s5m_rtc_info *info = dev_get_drvdata(dev);
u8 data[RTC_MAX_NUM_TIME_REGS];
- unsigned int val;
int ret, i;
ret = regmap_bulk_read(info->regmap, info->regs->alarm0, data,
@@ -453,15 +411,6 @@ static int s5m_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
return ret;
switch (info->device_type) {
- case S5M8763X:
- s5m8763_data_to_tm(data, &alrm->time);
- ret = regmap_read(info->regmap, S5M_ALARM0_CONF, &val);
- if (ret < 0)
- return ret;
-
- alrm->enabled = !!val;
- break;
-
case S5M8767X:
case S2MPS15X:
case S2MPS14X:
@@ -500,10 +449,6 @@ static int s5m_rtc_stop_alarm(struct s5m_rtc_info *info)
dev_dbg(info->dev, "%s: %ptR(%d)\n", __func__, &tm, tm.tm_wday);
switch (info->device_type) {
- case S5M8763X:
- ret = regmap_write(info->regmap, S5M_ALARM0_CONF, 0);
- break;
-
case S5M8767X:
case S2MPS15X:
case S2MPS14X:
@@ -531,7 +476,6 @@ static int s5m_rtc_start_alarm(struct s5m_rtc_info *info)
{
int ret;
u8 data[RTC_MAX_NUM_TIME_REGS];
- u8 alarm0_conf;
struct rtc_time tm;
ret = regmap_bulk_read(info->regmap, info->regs->alarm0, data,
@@ -543,11 +487,6 @@ static int s5m_rtc_start_alarm(struct s5m_rtc_info *info)
dev_dbg(info->dev, "%s: %ptR(%d)\n", __func__, &tm, tm.tm_wday);
switch (info->device_type) {
- case S5M8763X:
- alarm0_conf = 0x77;
- ret = regmap_write(info->regmap, S5M_ALARM0_CONF, alarm0_conf);
- break;
-
case S5M8767X:
case S2MPS15X:
case S2MPS14X:
@@ -585,10 +524,6 @@ static int s5m_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
int ret;
switch (info->device_type) {
- case S5M8763X:
- s5m8763_tm_to_data(&alrm->time, data);
- break;
-
case S5M8767X:
case S2MPS15X:
case S2MPS14X:
@@ -655,7 +590,6 @@ static int s5m8767_rtc_init_reg(struct s5m_rtc_info *info)
int ret;
switch (info->device_type) {
- case S5M8763X:
case S5M8767X:
/* UDR update time. Default of 7.32 ms is too long. */
ret = regmap_update_bits(info->regmap, S5M_RTC_UDR_CON,
@@ -729,11 +663,6 @@ static int s5m_rtc_probe(struct platform_device *pdev)
info->regs = &s2mps13_rtc_regs;
alarm_irq = S2MPS14_IRQ_RTCA0;
break;
- case S5M8763X:
- regmap_cfg = &s5m_rtc_regmap_config;
- info->regs = &s5m_rtc_regs;
- alarm_irq = S5M8763_IRQ_ALARM0;
- break;
case S5M8767X:
regmap_cfg = &s5m_rtc_regmap_config;
info->regs = &s5m_rtc_regs;
@@ -786,13 +715,8 @@ static int s5m_rtc_probe(struct platform_device *pdev)
info->rtc_dev->ops = &s5m_rtc_ops;
- if (info->device_type == S5M8763X) {
- info->rtc_dev->range_min = RTC_TIMESTAMP_BEGIN_0000;
- info->rtc_dev->range_max = RTC_TIMESTAMP_END_9999;
- } else {
- info->rtc_dev->range_min = RTC_TIMESTAMP_BEGIN_2000;
- info->rtc_dev->range_max = RTC_TIMESTAMP_END_2099;
- }
+ info->rtc_dev->range_min = RTC_TIMESTAMP_BEGIN_2000;
+ info->rtc_dev->range_max = RTC_TIMESTAMP_END_2099;
if (!info->irq) {
clear_bit(RTC_FEATURE_ALARM, info->rtc_dev->features);
diff --git a/include/dt-bindings/mfd/stm32f4-rcc.h b/include/dt-bindings/mfd/stm32f4-rcc.h
index 309e8c79f27b..36448a5619a1 100644
--- a/include/dt-bindings/mfd/stm32f4-rcc.h
+++ b/include/dt-bindings/mfd/stm32f4-rcc.h
@@ -34,7 +34,6 @@
#define STM32F4_AHB1_RESET(bit) (STM32F4_RCC_AHB1_##bit + (0x10 * 8))
#define STM32F4_AHB1_CLOCK(bit) (STM32F4_RCC_AHB1_##bit)
-
/* AHB2 */
#define STM32F4_RCC_AHB2_DCMI 0
#define STM32F4_RCC_AHB2_CRYP 4
diff --git a/include/linux/mfd/axp20x.h b/include/linux/mfd/axp20x.h
index 2058194807bd..beb3f44f85c5 100644
--- a/include/linux/mfd/axp20x.h
+++ b/include/linux/mfd/axp20x.h
@@ -21,6 +21,7 @@ enum axp20x_variants {
AXP806_ID,
AXP809_ID,
AXP813_ID,
+ AXP15060_ID,
NR_AXP20X_VARIANTS,
};
@@ -131,6 +132,39 @@ enum axp20x_variants {
/* Other DCDC regulator control registers are the same as AXP803 */
#define AXP813_DCDC7_V_OUT 0x26
+#define AXP15060_STARTUP_SRC 0x00
+#define AXP15060_PWR_OUT_CTRL1 0x10
+#define AXP15060_PWR_OUT_CTRL2 0x11
+#define AXP15060_PWR_OUT_CTRL3 0x12
+#define AXP15060_DCDC1_V_CTRL 0x13
+#define AXP15060_DCDC2_V_CTRL 0x14
+#define AXP15060_DCDC3_V_CTRL 0x15
+#define AXP15060_DCDC4_V_CTRL 0x16
+#define AXP15060_DCDC5_V_CTRL 0x17
+#define AXP15060_DCDC6_V_CTRL 0x18
+#define AXP15060_ALDO1_V_CTRL 0x19
+#define AXP15060_DCDC_MODE_CTRL1 0x1a
+#define AXP15060_DCDC_MODE_CTRL2 0x1b
+#define AXP15060_OUTPUT_MONITOR_DISCHARGE 0x1e
+#define AXP15060_IRQ_PWROK_VOFF 0x1f
+#define AXP15060_ALDO2_V_CTRL 0x20
+#define AXP15060_ALDO3_V_CTRL 0x21
+#define AXP15060_ALDO4_V_CTRL 0x22
+#define AXP15060_ALDO5_V_CTRL 0x23
+#define AXP15060_BLDO1_V_CTRL 0x24
+#define AXP15060_BLDO2_V_CTRL 0x25
+#define AXP15060_BLDO3_V_CTRL 0x26
+#define AXP15060_BLDO4_V_CTRL 0x27
+#define AXP15060_BLDO5_V_CTRL 0x28
+#define AXP15060_CLDO1_V_CTRL 0x29
+#define AXP15060_CLDO2_V_CTRL 0x2a
+#define AXP15060_CLDO3_V_CTRL 0x2b
+#define AXP15060_CLDO4_V_CTRL 0x2d
+#define AXP15060_CPUSLDO_V_CTRL 0x2e
+#define AXP15060_PWR_WAKEUP_CTRL 0x31
+#define AXP15060_PWR_DISABLE_DOWN_SEQ 0x32
+#define AXP15060_PEK_KEY 0x36
+
/* Interrupt */
#define AXP152_IRQ1_EN 0x40
#define AXP152_IRQ2_EN 0x41
@@ -152,6 +186,11 @@ enum axp20x_variants {
#define AXP20X_IRQ5_STATE 0x4c
#define AXP20X_IRQ6_STATE 0x4d
+#define AXP15060_IRQ1_EN 0x40
+#define AXP15060_IRQ2_EN 0x41
+#define AXP15060_IRQ1_STATE 0x48
+#define AXP15060_IRQ2_STATE 0x49
+
/* ADC */
#define AXP20X_ACIN_V_ADC_H 0x56
#define AXP20X_ACIN_V_ADC_L 0x57
@@ -222,6 +261,8 @@ enum axp20x_variants {
#define AXP22X_GPIO_STATE 0x94
#define AXP22X_GPIO_PULL_DOWN 0x95
+#define AXP15060_CLDO4_GPIO2_MODESET 0x2c
+
/* Battery */
#define AXP20X_CHRG_CC_31_24 0xb0
#define AXP20X_CHRG_CC_23_16 0xb1
@@ -419,6 +460,33 @@ enum {
AXP813_REG_ID_MAX,
};
+enum {
+ AXP15060_DCDC1 = 0,
+ AXP15060_DCDC2,
+ AXP15060_DCDC3,
+ AXP15060_DCDC4,
+ AXP15060_DCDC5,
+ AXP15060_DCDC6,
+ AXP15060_ALDO1,
+ AXP15060_ALDO2,
+ AXP15060_ALDO3,
+ AXP15060_ALDO4,
+ AXP15060_ALDO5,
+ AXP15060_BLDO1,
+ AXP15060_BLDO2,
+ AXP15060_BLDO3,
+ AXP15060_BLDO4,
+ AXP15060_BLDO5,
+ AXP15060_CLDO1,
+ AXP15060_CLDO2,
+ AXP15060_CLDO3,
+ AXP15060_CLDO4,
+ AXP15060_CPUSLDO,
+ AXP15060_SW,
+ AXP15060_RTC_LDO,
+ AXP15060_REG_ID_MAX,
+};
+
/* IRQs */
enum {
AXP152_IRQ_LDO0IN_CONNECT = 1,
@@ -637,6 +705,23 @@ enum axp809_irqs {
AXP809_IRQ_GPIO0_INPUT,
};
+enum axp15060_irqs {
+ AXP15060_IRQ_DIE_TEMP_HIGH_LV1 = 1,
+ AXP15060_IRQ_DIE_TEMP_HIGH_LV2,
+ AXP15060_IRQ_DCDC1_V_LOW,
+ AXP15060_IRQ_DCDC2_V_LOW,
+ AXP15060_IRQ_DCDC3_V_LOW,
+ AXP15060_IRQ_DCDC4_V_LOW,
+ AXP15060_IRQ_DCDC5_V_LOW,
+ AXP15060_IRQ_DCDC6_V_LOW,
+ AXP15060_IRQ_PEK_LONG,
+ AXP15060_IRQ_PEK_SHORT,
+ AXP15060_IRQ_GPIO1_INPUT,
+ AXP15060_IRQ_PEK_FAL_EDGE,
+ AXP15060_IRQ_PEK_RIS_EDGE,
+ AXP15060_IRQ_GPIO2_INPUT,
+};
+
struct axp20x_dev {
struct device *dev;
int irq;
diff --git a/include/linux/mfd/core.h b/include/linux/mfd/core.h
index 14ca7b471576..47e7a3a61ce6 100644
--- a/include/linux/mfd/core.h
+++ b/include/linux/mfd/core.h
@@ -68,9 +68,6 @@ struct mfd_cell {
int id;
int level;
- int (*enable)(struct platform_device *dev);
- int (*disable)(struct platform_device *dev);
-
int (*suspend)(struct platform_device *dev);
int (*resume)(struct platform_device *dev);
@@ -78,6 +75,9 @@ struct mfd_cell {
void *platform_data;
size_t pdata_size;
+ /* Matches ACPI */
+ const struct mfd_cell_acpi_match *acpi_match;
+
/* Software node for the device. */
const struct software_node *swnode;
@@ -97,9 +97,6 @@ struct mfd_cell {
/* Set to 'true' to use 'of_reg' (above) - allows for of_reg=0 */
bool use_of_reg;
- /* Matches ACPI */
- const struct mfd_cell_acpi_match *acpi_match;
-
/*
* These resources can be specified relative to the parent device.
* For accessing hardware you should use resources from the platform dev
@@ -119,20 +116,11 @@ struct mfd_cell {
/* A list of regulator supplies that should be mapped to the MFD
* device rather than the child device when requested
*/
- const char * const *parent_supplies;
int num_parent_supplies;
+ const char * const *parent_supplies;
};
/*
- * Convenience functions for clients using shared cells. Refcounting
- * happens automatically, with the cell's enable/disable callbacks
- * being called only when a device is first being enabled or no other
- * clients are making use of it.
- */
-extern int mfd_cell_enable(struct platform_device *pdev);
-extern int mfd_cell_disable(struct platform_device *pdev);
-
-/*
* Given a platform device that's been created by mfd_add_devices(), fetch
* the mfd_cell that created it.
*/
diff --git a/include/linux/mfd/max597x.h b/include/linux/mfd/max597x.h
new file mode 100644
index 000000000000..a850b2e02e6a
--- /dev/null
+++ b/include/linux/mfd/max597x.h
@@ -0,0 +1,96 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Device driver for regulators in MAX5970 and MAX5978 IC
+ *
+ * Copyright (c) 2022 9elements GmbH
+ *
+ * Author: Patrick Rudolph <patrick.rudolph@9elements.com>
+ */
+
+#ifndef _MFD_MAX597X_H
+#define _MFD_MAX597X_H
+
+#include <linux/regmap.h>
+
+#define MAX5970_NUM_SWITCHES 2
+#define MAX5978_NUM_SWITCHES 1
+#define MAX597X_NUM_LEDS 4
+
+struct max597x_data {
+ int num_switches;
+ u32 irng[MAX5970_NUM_SWITCHES];
+ u32 mon_rng[MAX5970_NUM_SWITCHES];
+ u32 shunt_micro_ohms[MAX5970_NUM_SWITCHES];
+};
+
+enum max597x_chip_type {
+ MAX597x_TYPE_MAX5978 = 1,
+ MAX597x_TYPE_MAX5970,
+};
+
+#define MAX5970_REG_CURRENT_L(ch) (0x01 + (ch) * 4)
+#define MAX5970_REG_CURRENT_H(ch) (0x00 + (ch) * 4)
+#define MAX5970_REG_VOLTAGE_L(ch) (0x03 + (ch) * 4)
+#define MAX5970_REG_VOLTAGE_H(ch) (0x02 + (ch) * 4)
+#define MAX5970_REG_MON_RANGE 0x18
+#define MAX5970_MON_MASK 0x3
+#define MAX5970_MON(reg, ch) (((reg) >> ((ch) * 2)) & MAX5970_MON_MASK)
+#define MAX5970_MON_MAX_RANGE_UV 16000000
+
+#define MAX5970_REG_CH_UV_WARN_H(ch) (0x1A + (ch) * 10)
+#define MAX5970_REG_CH_UV_WARN_L(ch) (0x1B + (ch) * 10)
+#define MAX5970_REG_CH_UV_CRIT_H(ch) (0x1C + (ch) * 10)
+#define MAX5970_REG_CH_UV_CRIT_L(ch) (0x1D + (ch) * 10)
+#define MAX5970_REG_CH_OV_WARN_H(ch) (0x1E + (ch) * 10)
+#define MAX5970_REG_CH_OV_WARN_L(ch) (0x1F + (ch) * 10)
+#define MAX5970_REG_CH_OV_CRIT_H(ch) (0x20 + (ch) * 10)
+#define MAX5970_REG_CH_OV_CRIT_L(ch) (0x21 + (ch) * 10)
+
+#define MAX5970_VAL2REG_H(x) (((x) >> 2) & 0xFF)
+#define MAX5970_VAL2REG_L(x) ((x) & 0x3)
+
+#define MAX5970_REG_DAC_FAST(ch) (0x2E + (ch))
+
+#define MAX5970_FAST2SLOW_RATIO 200
+
+#define MAX5970_REG_STATUS0 0x31
+#define MAX5970_CB_IFAULTF(ch) (1 << (ch))
+#define MAX5970_CB_IFAULTS(ch) (1 << ((ch) + 4))
+
+#define MAX5970_REG_STATUS1 0x32
+#define STATUS1_PROT_MASK 0x3
+#define STATUS1_PROT(reg) \
+ (((reg) >> 6) & STATUS1_PROT_MASK)
+#define STATUS1_PROT_SHUTDOWN 0
+#define STATUS1_PROT_CLEAR_PG 1
+#define STATUS1_PROT_ALERT_ONLY 2
+
+#define MAX5970_REG_STATUS2 0x33
+#define MAX5970_IRNG_MASK 0x3
+#define MAX5970_IRNG(reg, ch) \
+ (((reg) >> ((ch) * 2)) & MAX5970_IRNG_MASK)
+
+#define MAX5970_REG_STATUS3 0x34
+#define MAX5970_STATUS3_ALERT BIT(4)
+#define MAX5970_STATUS3_PG(ch) BIT(ch)
+
+#define MAX5970_REG_FAULT0 0x35
+#define UV_STATUS_WARN(ch) (1 << (ch))
+#define UV_STATUS_CRIT(ch) (1 << ((ch) + 4))
+
+#define MAX5970_REG_FAULT1 0x36
+#define OV_STATUS_WARN(ch) (1 << (ch))
+#define OV_STATUS_CRIT(ch) (1 << ((ch) + 4))
+
+#define MAX5970_REG_FAULT2 0x37
+#define OC_STATUS_WARN(ch) (1 << (ch))
+
+#define MAX5970_REG_CHXEN 0x3b
+#define CHXEN(ch) (3 << ((ch) * 2))
+
+#define MAX5970_REG_LED_FLASH 0x43
+
+#define MAX_REGISTERS 0x49
+#define ADC_MASK 0x3FF
+
+#endif /* _MFD_MAX597X_H */
diff --git a/include/linux/mfd/rsmu.h b/include/linux/mfd/rsmu.h
index 6870de608233..0379aa207428 100644
--- a/include/linux/mfd/rsmu.h
+++ b/include/linux/mfd/rsmu.h
@@ -8,6 +8,9 @@
#ifndef __LINUX_MFD_RSMU_H
#define __LINUX_MFD_RSMU_H
+#define RSMU_MAX_WRITE_COUNT (255)
+#define RSMU_MAX_READ_COUNT (255)
+
/* The supported devices are ClockMatrix, Sabre and SnowLotus */
enum rsmu_type {
RSMU_CM = 0x34000,
@@ -31,6 +34,6 @@ struct rsmu_ddata {
struct regmap *regmap;
struct mutex lock;
enum rsmu_type type;
- u16 page;
+ u32 page;
};
#endif /* __LINUX_MFD_RSMU_H */
diff --git a/include/linux/mfd/rt5033-private.h b/include/linux/mfd/rt5033-private.h
index 2d1895c3efbf..6bb432f6a96c 100644
--- a/include/linux/mfd/rt5033-private.h
+++ b/include/linux/mfd/rt5033-private.h
@@ -107,14 +107,13 @@ enum rt5033_reg {
#define RT5033_LDO_CTRL_MASK 0x1f
/* RT5033 charger property - model, manufacturer */
-
#define RT5033_CHARGER_MODEL "RT5033WSC Charger"
#define RT5033_MANUFACTURER "Richtek Technology Corporation"
/*
- * RT5033 charger fast-charge current lmits (as in CHGCTRL1 register),
- * AICR mode limits the input current for example,
- * the AIRC 100 mode limits the input current to 100 mA.
+ * While RT5033 charger can limit the fast-charge current (as in CHGCTRL1
+ * register), AICR mode limits the input current. For example, the AIRC 100
+ * mode limits the input current to 100 mA.
*/
#define RT5033_AICR_100_MODE 0x20
#define RT5033_AICR_500_MODE 0x40
@@ -139,10 +138,9 @@ enum rt5033_reg {
#define RT5033_TE_ENABLE_MASK 0x08
/*
- * RT5033 charger opa mode. RT50300 have two opa mode charger mode
- * and boost mode for OTG
+ * RT5033 charger opa mode. RT5033 has two opa modes for OTG: charger mode
+ * and boost mode.
*/
-
#define RT5033_CHARGER_MODE 0x00
#define RT5033_BOOST_MODE 0x01
@@ -181,18 +179,17 @@ enum rt5033_reg {
* RT5033 charger pre-charge threshold volt limits
* (as in CHGCTRL5 register), uV
*/
-
#define RT5033_CHARGER_PRE_THRESHOLD_LIMIT_MIN 2300000U
#define RT5033_CHARGER_PRE_THRESHOLD_STEP_NUM 100000U
#define RT5033_CHARGER_PRE_THRESHOLD_LIMIT_MAX 3800000U
/*
- * RT5033 charger enable UUG, If UUG enable MOS auto control by H/W charger
+ * RT5033 charger UUG. It enables MOS auto control by H/W charger
* circuit.
*/
#define RT5033_CHARGER_UUG_ENABLE 0x02
-/* RT5033 charger High impedance mode */
+/* RT5033 charger high impedance mode */
#define RT5033_CHARGER_HZ_DISABLE 0x00
#define RT5033_CHARGER_HZ_ENABLE 0x01
diff --git a/include/linux/mfd/rt5033.h b/include/linux/mfd/rt5033.h
index 3c23b6220c04..8f306ac15a27 100644
--- a/include/linux/mfd/rt5033.h
+++ b/include/linux/mfd/rt5033.h
@@ -49,10 +49,9 @@ struct rt5033_charger_data {
};
struct rt5033_charger {
- struct device *dev;
- struct rt5033_dev *rt5033;
- struct power_supply psy;
-
+ struct device *dev;
+ struct rt5033_dev *rt5033;
+ struct power_supply psy;
struct rt5033_charger_data *chg;
};
diff --git a/include/linux/mfd/rz-mtu3.h b/include/linux/mfd/rz-mtu3.h
new file mode 100644
index 000000000000..c5173bc06270
--- /dev/null
+++ b/include/linux/mfd/rz-mtu3.h
@@ -0,0 +1,257 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2022 Renesas Electronics Corporation
+ */
+#ifndef __MFD_RZ_MTU3_H__
+#define __MFD_RZ_MTU3_H__
+
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/mutex.h>
+
+/* 8-bit shared register offsets macros */
+#define RZ_MTU3_TSTRA 0x080 /* Timer start register A */
+#define RZ_MTU3_TSTRB 0x880 /* Timer start register B */
+
+/* 16-bit shared register offset macros */
+#define RZ_MTU3_TDDRA 0x016 /* Timer dead time data register A */
+#define RZ_MTU3_TDDRB 0x816 /* Timer dead time data register B */
+#define RZ_MTU3_TCDRA 0x014 /* Timer cycle data register A */
+#define RZ_MTU3_TCDRB 0x814 /* Timer cycle data register B */
+#define RZ_MTU3_TCBRA 0x022 /* Timer cycle buffer register A */
+#define RZ_MTU3_TCBRB 0x822 /* Timer cycle buffer register B */
+#define RZ_MTU3_TCNTSA 0x020 /* Timer subcounter A */
+#define RZ_MTU3_TCNTSB 0x820 /* Timer subcounter B */
+
+/*
+ * MTU5 contains 3 timer counter registers and is totaly different
+ * from other channels, so we must separate its offset
+ */
+
+/* 8-bit register offset macros of MTU3 channels except MTU5 */
+#define RZ_MTU3_TIER 0 /* Timer interrupt register */
+#define RZ_MTU3_NFCR 1 /* Noise filter control register */
+#define RZ_MTU3_TSR 2 /* Timer status register */
+#define RZ_MTU3_TCR 3 /* Timer control register */
+#define RZ_MTU3_TCR2 4 /* Timer control register 2 */
+
+/* Timer mode register 1 */
+#define RZ_MTU3_TMDR1 5
+#define RZ_MTU3_TMDR1_MD GENMASK(3, 0)
+#define RZ_MTU3_TMDR1_MD_NORMAL FIELD_PREP(RZ_MTU3_TMDR1_MD, 0)
+#define RZ_MTU3_TMDR1_MD_PWMMODE1 FIELD_PREP(RZ_MTU3_TMDR1_MD, 2)
+
+#define RZ_MTU3_TIOR 6 /* Timer I/O control register */
+#define RZ_MTU3_TIORH 6 /* Timer I/O control register H */
+#define RZ_MTU3_TIORL 7 /* Timer I/O control register L */
+/* Only MTU3/4/6/7 have TBTM registers */
+#define RZ_MTU3_TBTM 8 /* Timer buffer operation transfer mode register */
+
+/* 8-bit MTU5 register offset macros */
+#define RZ_MTU3_TSTR 2 /* MTU5 Timer start register */
+#define RZ_MTU3_TCNTCMPCLR 3 /* MTU5 Timer compare match clear register */
+#define RZ_MTU3_TCRU 4 /* Timer control register U */
+#define RZ_MTU3_TCR2U 5 /* Timer control register 2U */
+#define RZ_MTU3_TIORU 6 /* Timer I/O control register U */
+#define RZ_MTU3_TCRV 7 /* Timer control register V */
+#define RZ_MTU3_TCR2V 8 /* Timer control register 2V */
+#define RZ_MTU3_TIORV 9 /* Timer I/O control register V */
+#define RZ_MTU3_TCRW 10 /* Timer control register W */
+#define RZ_MTU3_TCR2W 11 /* Timer control register 2W */
+#define RZ_MTU3_TIORW 12 /* Timer I/O control register W */
+
+/* 16-bit register offset macros of MTU3 channels except MTU5 */
+#define RZ_MTU3_TCNT 0 /* Timer counter */
+#define RZ_MTU3_TGRA 1 /* Timer general register A */
+#define RZ_MTU3_TGRB 2 /* Timer general register B */
+#define RZ_MTU3_TGRC 3 /* Timer general register C */
+#define RZ_MTU3_TGRD 4 /* Timer general register D */
+#define RZ_MTU3_TGRE 5 /* Timer general register E */
+#define RZ_MTU3_TGRF 6 /* Timer general register F */
+/* Timer A/D converter start request registers */
+#define RZ_MTU3_TADCR 7 /* control register */
+#define RZ_MTU3_TADCORA 8 /* cycle set register A */
+#define RZ_MTU3_TADCORB 9 /* cycle set register B */
+#define RZ_MTU3_TADCOBRA 10 /* cycle set buffer register A */
+#define RZ_MTU3_TADCOBRB 11 /* cycle set buffer register B */
+
+/* 16-bit MTU5 register offset macros */
+#define RZ_MTU3_TCNTU 0 /* MTU5 Timer counter U */
+#define RZ_MTU3_TGRU 1 /* MTU5 Timer general register U */
+#define RZ_MTU3_TCNTV 2 /* MTU5 Timer counter V */
+#define RZ_MTU3_TGRV 3 /* MTU5 Timer general register V */
+#define RZ_MTU3_TCNTW 4 /* MTU5 Timer counter W */
+#define RZ_MTU3_TGRW 5 /* MTU5 Timer general register W */
+
+/* 32-bit register offset */
+#define RZ_MTU3_TCNTLW 0 /* Timer longword counter */
+#define RZ_MTU3_TGRALW 1 /* Timer longword general register A */
+#define RZ_MTU3_TGRBLW 2 /* Timer longowrd general register B */
+
+#define RZ_MTU3_TMDR3 0x191 /* MTU1 Timer Mode Register 3 */
+
+/* Macros for setting registers */
+#define RZ_MTU3_TCR_CCLR GENMASK(7, 5)
+#define RZ_MTU3_TCR_CKEG GENMASK(4, 3)
+#define RZ_MTU3_TCR_TPCS GENMASK(2, 0)
+#define RZ_MTU3_TCR_CCLR_TGRA BIT(5)
+#define RZ_MTU3_TCR_CCLR_TGRC FIELD_PREP(RZ_MTU3_TCR_CCLR, 5)
+#define RZ_MTU3_TCR_CKEG_RISING FIELD_PREP(RZ_MTU3_TCR_CKEG, 0)
+
+#define RZ_MTU3_TIOR_IOB GENMASK(7, 4)
+#define RZ_MTU3_TIOR_IOA GENMASK(3, 0)
+#define RZ_MTU3_TIOR_OC_RETAIN 0
+#define RZ_MTU3_TIOR_OC_INIT_OUT_LO_HI_OUT 2
+#define RZ_MTU3_TIOR_OC_INIT_OUT_HI_TOGGLE_OUT 7
+
+#define RZ_MTU3_TIOR_OC_IOA_H_COMP_MATCH \
+ FIELD_PREP(RZ_MTU3_TIOR_IOA, RZ_MTU3_TIOR_OC_INIT_OUT_LO_HI_OUT)
+#define RZ_MTU3_TIOR_OC_IOB_TOGGLE \
+ FIELD_PREP(RZ_MTU3_TIOR_IOB, RZ_MTU3_TIOR_OC_INIT_OUT_HI_TOGGLE_OUT)
+
+enum rz_mtu3_channels {
+ RZ_MTU3_CHAN_0,
+ RZ_MTU3_CHAN_1,
+ RZ_MTU3_CHAN_2,
+ RZ_MTU3_CHAN_3,
+ RZ_MTU3_CHAN_4,
+ RZ_MTU3_CHAN_5,
+ RZ_MTU3_CHAN_6,
+ RZ_MTU3_CHAN_7,
+ RZ_MTU3_CHAN_8,
+ RZ_MTU_NUM_CHANNELS
+};
+
+/**
+ * struct rz_mtu3_channel - MTU3 channel private data
+ *
+ * @dev: device handle
+ * @channel_number: channel number
+ * @lock: Lock to protect channel state
+ * @is_busy: channel state
+ */
+struct rz_mtu3_channel {
+ struct device *dev;
+ unsigned int channel_number;
+ struct mutex lock;
+ bool is_busy;
+};
+
+/**
+ * struct rz_mtu3 - MTU3 core private data
+ *
+ * @clk: MTU3 module clock
+ * @rz_mtu3_channel: HW channels
+ * @priv_data: MTU3 core driver private data
+ */
+struct rz_mtu3 {
+ struct clk *clk;
+ struct rz_mtu3_channel channels[RZ_MTU_NUM_CHANNELS];
+
+ void *priv_data;
+};
+
+#if IS_ENABLED(CONFIG_RZ_MTU3)
+static inline bool rz_mtu3_request_channel(struct rz_mtu3_channel *ch)
+{
+ mutex_lock(&ch->lock);
+ if (ch->is_busy) {
+ mutex_unlock(&ch->lock);
+ return false;
+ }
+
+ ch->is_busy = true;
+ mutex_unlock(&ch->lock);
+
+ return true;
+}
+
+static inline void rz_mtu3_release_channel(struct rz_mtu3_channel *ch)
+{
+ mutex_lock(&ch->lock);
+ ch->is_busy = false;
+ mutex_unlock(&ch->lock);
+}
+
+bool rz_mtu3_is_enabled(struct rz_mtu3_channel *ch);
+void rz_mtu3_disable(struct rz_mtu3_channel *ch);
+int rz_mtu3_enable(struct rz_mtu3_channel *ch);
+
+u8 rz_mtu3_8bit_ch_read(struct rz_mtu3_channel *ch, u16 off);
+u16 rz_mtu3_16bit_ch_read(struct rz_mtu3_channel *ch, u16 off);
+u32 rz_mtu3_32bit_ch_read(struct rz_mtu3_channel *ch, u16 off);
+u16 rz_mtu3_shared_reg_read(struct rz_mtu3_channel *ch, u16 off);
+
+void rz_mtu3_8bit_ch_write(struct rz_mtu3_channel *ch, u16 off, u8 val);
+void rz_mtu3_16bit_ch_write(struct rz_mtu3_channel *ch, u16 off, u16 val);
+void rz_mtu3_32bit_ch_write(struct rz_mtu3_channel *ch, u16 off, u32 val);
+void rz_mtu3_shared_reg_write(struct rz_mtu3_channel *ch, u16 off, u16 val);
+void rz_mtu3_shared_reg_update_bit(struct rz_mtu3_channel *ch, u16 off,
+ u16 pos, u8 val);
+#else
+static inline bool rz_mtu3_request_channel(struct rz_mtu3_channel *ch)
+{
+ return false;
+}
+
+static inline void rz_mtu3_release_channel(struct rz_mtu3_channel *ch)
+{
+}
+
+static inline bool rz_mtu3_is_enabled(struct rz_mtu3_channel *ch)
+{
+ return false;
+}
+
+static inline void rz_mtu3_disable(struct rz_mtu3_channel *ch)
+{
+}
+
+static inline int rz_mtu3_enable(struct rz_mtu3_channel *ch)
+{
+ return 0;
+}
+
+static inline u8 rz_mtu3_8bit_ch_read(struct rz_mtu3_channel *ch, u16 off)
+{
+ return 0;
+}
+
+static inline u16 rz_mtu3_16bit_ch_read(struct rz_mtu3_channel *ch, u16 off)
+{
+ return 0;
+}
+
+static inline u32 rz_mtu3_32bit_ch_read(struct rz_mtu3_channel *ch, u16 off)
+{
+ return 0;
+}
+
+static inline u16 rz_mtu3_shared_reg_read(struct rz_mtu3_channel *ch, u16 off)
+{
+ return 0;
+}
+
+static inline void rz_mtu3_8bit_ch_write(struct rz_mtu3_channel *ch, u16 off, u8 val)
+{
+}
+
+static inline void rz_mtu3_16bit_ch_write(struct rz_mtu3_channel *ch, u16 off, u16 val)
+{
+}
+
+static inline void rz_mtu3_32bit_ch_write(struct rz_mtu3_channel *ch, u16 off, u32 val)
+{
+}
+
+static inline void rz_mtu3_shared_reg_write(struct rz_mtu3_channel *ch, u16 off, u16 val)
+{
+}
+
+static inline void rz_mtu3_shared_reg_update_bit(struct rz_mtu3_channel *ch,
+ u16 off, u16 pos, u8 val)
+{
+}
+#endif
+
+#endif /* __MFD_RZ_MTU3_H__ */
diff --git a/include/linux/mfd/samsung/core.h b/include/linux/mfd/samsung/core.h
index f92fe090473d..a212b9f72bc9 100644
--- a/include/linux/mfd/samsung/core.h
+++ b/include/linux/mfd/samsung/core.h
@@ -36,8 +36,6 @@
struct gpio_desc;
enum sec_device_type {
- S5M8751X,
- S5M8763X,
S5M8767X,
S2MPA01,
S2MPS11X,
diff --git a/include/linux/mfd/samsung/irq.h b/include/linux/mfd/samsung/irq.h
index 6cfe4201a106..3fd2775eb9bb 100644
--- a/include/linux/mfd/samsung/irq.h
+++ b/include/linux/mfd/samsung/irq.h
@@ -194,54 +194,4 @@ enum s5m8767_irq {
#define S5M8767_IRQ_RTC1S_MASK (1 << 4)
#define S5M8767_IRQ_WTSR_MASK (1 << 5)
-enum s5m8763_irq {
- S5M8763_IRQ_DCINF,
- S5M8763_IRQ_DCINR,
- S5M8763_IRQ_JIGF,
- S5M8763_IRQ_JIGR,
- S5M8763_IRQ_PWRONF,
- S5M8763_IRQ_PWRONR,
-
- S5M8763_IRQ_WTSREVNT,
- S5M8763_IRQ_SMPLEVNT,
- S5M8763_IRQ_ALARM1,
- S5M8763_IRQ_ALARM0,
-
- S5M8763_IRQ_ONKEY1S,
- S5M8763_IRQ_TOPOFFR,
- S5M8763_IRQ_DCINOVPR,
- S5M8763_IRQ_CHGRSTF,
- S5M8763_IRQ_DONER,
- S5M8763_IRQ_CHGFAULT,
-
- S5M8763_IRQ_LOBAT1,
- S5M8763_IRQ_LOBAT2,
-
- S5M8763_IRQ_NR,
-};
-
-#define S5M8763_IRQ_DCINF_MASK (1 << 2)
-#define S5M8763_IRQ_DCINR_MASK (1 << 3)
-#define S5M8763_IRQ_JIGF_MASK (1 << 4)
-#define S5M8763_IRQ_JIGR_MASK (1 << 5)
-#define S5M8763_IRQ_PWRONF_MASK (1 << 6)
-#define S5M8763_IRQ_PWRONR_MASK (1 << 7)
-
-#define S5M8763_IRQ_WTSREVNT_MASK (1 << 0)
-#define S5M8763_IRQ_SMPLEVNT_MASK (1 << 1)
-#define S5M8763_IRQ_ALARM1_MASK (1 << 2)
-#define S5M8763_IRQ_ALARM0_MASK (1 << 3)
-
-#define S5M8763_IRQ_ONKEY1S_MASK (1 << 0)
-#define S5M8763_IRQ_TOPOFFR_MASK (1 << 2)
-#define S5M8763_IRQ_DCINOVPR_MASK (1 << 3)
-#define S5M8763_IRQ_CHGRSTF_MASK (1 << 4)
-#define S5M8763_IRQ_DONER_MASK (1 << 5)
-#define S5M8763_IRQ_CHGFAULT_MASK (1 << 7)
-
-#define S5M8763_IRQ_LOBAT1_MASK (1 << 0)
-#define S5M8763_IRQ_LOBAT2_MASK (1 << 1)
-
-#define S5M8763_ENRAMP (1 << 4)
-
#endif /* __LINUX_MFD_SEC_IRQ_H */
diff --git a/include/linux/mfd/samsung/s5m8763.h b/include/linux/mfd/samsung/s5m8763.h
deleted file mode 100644
index c534f086ca16..000000000000
--- a/include/linux/mfd/samsung/s5m8763.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Copyright (c) 2011 Samsung Electronics Co., Ltd
- * http://www.samsung.com
- */
-
-#ifndef __LINUX_MFD_S5M8763_H
-#define __LINUX_MFD_S5M8763_H
-
-/* S5M8763 registers */
-enum s5m8763_reg {
- S5M8763_REG_IRQ1,
- S5M8763_REG_IRQ2,
- S5M8763_REG_IRQ3,
- S5M8763_REG_IRQ4,
- S5M8763_REG_IRQM1,
- S5M8763_REG_IRQM2,
- S5M8763_REG_IRQM3,
- S5M8763_REG_IRQM4,
- S5M8763_REG_STATUS1,
- S5M8763_REG_STATUS2,
- S5M8763_REG_STATUSM1,
- S5M8763_REG_STATUSM2,
- S5M8763_REG_CHGR1,
- S5M8763_REG_CHGR2,
- S5M8763_REG_LDO_ACTIVE_DISCHARGE1,
- S5M8763_REG_LDO_ACTIVE_DISCHARGE2,
- S5M8763_REG_BUCK_ACTIVE_DISCHARGE3,
- S5M8763_REG_ONOFF1,
- S5M8763_REG_ONOFF2,
- S5M8763_REG_ONOFF3,
- S5M8763_REG_ONOFF4,
- S5M8763_REG_BUCK1_VOLTAGE1,
- S5M8763_REG_BUCK1_VOLTAGE2,
- S5M8763_REG_BUCK1_VOLTAGE3,
- S5M8763_REG_BUCK1_VOLTAGE4,
- S5M8763_REG_BUCK2_VOLTAGE1,
- S5M8763_REG_BUCK2_VOLTAGE2,
- S5M8763_REG_BUCK3,
- S5M8763_REG_BUCK4,
- S5M8763_REG_LDO1_LDO2,
- S5M8763_REG_LDO3,
- S5M8763_REG_LDO4,
- S5M8763_REG_LDO5,
- S5M8763_REG_LDO6,
- S5M8763_REG_LDO7,
- S5M8763_REG_LDO7_LDO8,
- S5M8763_REG_LDO9_LDO10,
- S5M8763_REG_LDO11,
- S5M8763_REG_LDO12,
- S5M8763_REG_LDO13,
- S5M8763_REG_LDO14,
- S5M8763_REG_LDO15,
- S5M8763_REG_LDO16,
- S5M8763_REG_BKCHR,
- S5M8763_REG_LBCNFG1,
- S5M8763_REG_LBCNFG2,
-};
-
-/* S5M8763 regulator ids */
-enum s5m8763_regulators {
- S5M8763_LDO1,
- S5M8763_LDO2,
- S5M8763_LDO3,
- S5M8763_LDO4,
- S5M8763_LDO5,
- S5M8763_LDO6,
- S5M8763_LDO7,
- S5M8763_LDO8,
- S5M8763_LDO9,
- S5M8763_LDO10,
- S5M8763_LDO11,
- S5M8763_LDO12,
- S5M8763_LDO13,
- S5M8763_LDO14,
- S5M8763_LDO15,
- S5M8763_LDO16,
- S5M8763_BUCK1,
- S5M8763_BUCK2,
- S5M8763_BUCK3,
- S5M8763_BUCK4,
- S5M8763_AP_EN32KHZ,
- S5M8763_CP_EN32KHZ,
- S5M8763_ENCHGVI,
- S5M8763_ESAFEUSB1,
- S5M8763_ESAFEUSB2,
-};
-
-#define S5M8763_ENRAMP (1 << 4)
-#endif /* __LINUX_MFD_S5M8763_H */