* Maxim MAX77705:

* Added core MFD driver.
     * Added charger driver.
     * Added devicetree bindings for the charger and MFD core.
     * Added Haptic controller support via the input subsystem.
     * Added LED support.
     * Added support to simple-mfd-i2c for fuel gauge and hwmon.
   * Samsung S2MPU05 (Exynos7870 PMIC):
     * Added core MFD support.
     * Added Regulator support for 21 LDOs and 5 BUCKs.
     * Added devicetree bindings for regulators and the PMIC core.
   * TI TPS65215 & TPS65214:
     * Added support to the existing TPS65219 driver.
     * Added devicetree bindings.
   * STMicroelectronics STM32MP25:
     * Added support to the stm32-timers MFD driver.
     * Added devicetree bindings.
   * Congatec Board Controller (CGBC):
     * Added HWMON support for internal sensors.
     * Added support for the conga-SA8 module.
   * Microchip LAN969X:
     * Enabled the at91-usart MFD driver for this architecture.
   * MediaTek MT6359:
     * Added mfd_cell for mt6359-accdet to allow its driver to probe.
 
   * AXP20X (AXP717): Added AXP717_TS_PIN_CFG register to writeable
     regs for temperature sensor configuration.
   * SM501: Switched to using BIT() macro to mitigate potential
     integer overflows in GPIO functions.
   * ENE KB3930: Added a NULL pointer check for off_gpios during
     probe to prevent potential dereference.
   * SYSCON: Added a check for invalid resource size to prevent
     issues from DT misconfiguration.
   * CGBC: Corrected signedness issues in cgbc_session_request.
 
   * intel_soc_pmic_chtdc_ti / intel_soc_pmic_crc: Removed unneeded
     explicit assignment to REGCACHE_NONE.
   * ipaq-micro / tps65010: Switched to using str_enable_disable()
     helpers for clarity and potential size reduction.
   * upboard-fpga: Removed unnecessary ACPI_PTR() annotation.
   * max8997: Removed unused max8997_irq_exit() function, using
     devm_* helpers instead.
   * lp3943: Dropped unused #include <linux/pwm.h> from the header
     file.
   * db8500-prcmu: Removed needless return statements in void APIs.
   * qnap-mcu: Replaced commas with semicolons between expressions
     for correctness.
 
   * STA2X11: Removed the core MFD driver as the underlying
     platform support was removed.
   * EZX-PCAP: Removed the unused pcap_adc_sync function.
   * PCF50633 (OpenMoko PMIC): Removed the entire driver (core, adc,
     gpio, irq) as the underlying s3c24xx platform support was removed.
 
   * Converted fsl,mcu-mpc8349emitx binding to YAML.
   * Added qcom,msm8937-tcsr compatible.
   * Added microchip,sama7d65-flexcom compatible.
   * Added rockchip,rk3528-qos syscon compatible.
   * Added airoha,en7581-pbus-csr syscon compatible.
   * Added microchip,sama7d65-ddr3phy syscon compatible.
   * Added microchip,sama7d65-sfrbu syscon compatible.
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEdrbJNaO+IJqU8IdIUa+KL4f8d2EFAmfmqKQACgkQUa+KL4f8
 d2G+rA//UU3UixCD8FsNN+o4DS7FbxdiSUCrATOBKia9MGfor4xCl6Qk9ZyO4sE1
 Rr9zUrTb1xlCmMZupZlkV8TDHHcaiUbgmnKB161d4HMxCbju10MKlm7faz2vRMz3
 a73ehTmUeNDiWG3t1/2zAyRt7PHPC2zakUlnXlLhLir12uR2jsDSeGOZh4xR7Hdi
 5nkOA2xWbbeW4b+ybwZ32afbLtZFkLo80QvqDx/D9lMUnQO0FqKak0Zope7IzeqC
 ilg+tIJOQRGEbjEVQ+pVXsPI6zfmO8eAja70F7sm+Q6TVDw2JhHU/YElHw+quiP+
 aLYeE+DuSun1EYlK4ATQ0vzUdgsaOEWblF0eythctXFTfM9ZKhzWYdXEOvco7N4u
 R9BYRtM/zGkxiScbr6igyjWZx7NPOsKEKIi5tOv+C2BAKb53om7vsNuMgvMDL/8W
 gztmG0SMKwJSx2Dg7h1LLUfa3tG9QRFd0I+Yfaso3MtYmxnZVcJtM5IQbvzf6i/B
 3fSiGP6PDNeJqbn9k3/7SB8Tb4XmJUN2LFdDtDuWVhgZpSDULkjpYxAXDIrbp+il
 QNdLPiU1x7OzPkFZQxtXLt7yRmlEc2lu9jJHkGVM1M18TMexQiFxoSY9NxkbUj3o
 T4s/PKGmRKHP9XxCmRSfu6Veql0MPUwtvkErlUf4GTLWK4oshag=
 =ntF1
 -----END PGP SIGNATURE-----

Merge tag 'mfd-next-6.15' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd

Pull MFD updates from Lee Jones:
 "Maxim MAX77705:
   - Added core MFD driver.
   - Added charger driver.
   - Added devicetree bindings for the charger and MFD core.
   - Added Haptic controller support via the input subsystem.
   - Added LED support.
   - Added support to simple-mfd-i2c for fuel gauge and hwmon.

  Samsung S2MPU05 (Exynos7870 PMIC):
   - Added core MFD support.
   - Added Regulator support for 21 LDOs and 5 BUCKs.
   - Added devicetree bindings for regulators and the PMIC core.

  TI TPS65215 & TPS65214:
   - Added support to the existing TPS65219 driver.
   - Added devicetree bindings.

  STMicroelectronics STM32MP25:
   - Added support to the stm32-timers MFD driver.
   - Added devicetree bindings.

  Congatec Board Controller (CGBC):
   - Added HWMON support for internal sensors.
   - Added support for the conga-SA8 module.

  Microchip LAN969X:
   - Enabled the at91-usart MFD driver for this architecture.

  MediaTek MT6359:
   - Added mfd_cell for mt6359-accdet to allow its driver to probe.

  Other misc driver updates:
   - AXP20X (AXP717): Added AXP717_TS_PIN_CFG register to writeable regs
     for temperature sensor configuration.
   - SM501: Switched to using BIT() macro to mitigate potential integer
     overflows in GPIO functions.
   - ENE KB3930: Added a NULL pointer check for off_gpios during probe
     to prevent potential dereference.
   - SYSCON: Added a check for invalid resource size to prevent issues
     from DT misconfiguration.
   - CGBC: Corrected signedness issues in cgbc_session_request
   - intel_soc_pmic_chtdc_ti / intel_soc_pmic_crc: Removed unneeded
     explicit assignment to REGCACHE_NONE.
   - ipaq-micro / tps65010: Switched to using str_enable_disable()
     helpers for clarity and potential size reduction.
   - upboard-fpga: Removed unnecessary ACPI_PTR() annotation.
   - max8997: Removed unused max8997_irq_exit() function, using devm_*
     helpers instead.
   - lp3943: Dropped unused #include <linux/pwm.h> from the header file.
   - db8500-prcmu: Removed needless return statements in void APIs.
   - qnap-mcu: Replaced commas with semicolons between expressions for
     correctness.
   - STA2X11: Removed the core MFD driver as the underlying platform
     support was removed.
   - EZX-PCAP: Removed the unused pcap_adc_sync function.
   - PCF50633 (OpenMoko PMIC): Removed the entire driver (core, adc,
     gpio, irq) as the underlying s3c24xx platform support was removed.

  Devicetree updates:
   - Converted fsl,mcu-mpc8349emitx binding to YAML
   - Added qcom,msm8937-tcsr compatible
   - Added microchip,sama7d65-flexcom compatible
   - Added rockchip,rk3528-qos syscon compatible
   - Added airoha,en7581-pbus-csr syscon compatible
   - Added microchip,sama7d65-ddr3phy syscon compatible
   - Added microchip,sama7d65-sfrbu syscon compatible"

* tag 'mfd-next-6.15' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd: (49 commits)
  mfd: cgbc-core: Add support for conga-SA8
  dt-bindings: mfd: syscon: Add microchip,sama7d65-sfrbu
  dt-bindings: mfd: syscon: Add microchip,sama7d65-ddr3phy
  mfd: cgbc: Add support for HWMON
  dt-bindings: mfd: syscon: Add the pbus-csr node for Airoha EN7581 SoC
  mfd: cgbc-core: Cleanup signedness in cgbc_session_request()
  mfd: pcf50633: Remove remaining PCF50633 support
  mfd: pcf50633: Remove unused platform IRQ code
  mfd: pcF50633-gpio: Remove unused driver
  mfd: pcf50633-adc: Remove unused driver
  mfd: qnap-mcu: Convert commas to semicolons in qnap_mcu_exec()
  mfd: mt6397-core: Add mfd_cell for mt6359-accdet
  dt-bindings: mfd: syscon: Add rk3528 QoS register compatible
  dt-bindings: mfd: atmel,sama5d2-flexcom: Add microchip,sama7d65-flexcom
  mfd: ezx-pcap: Remove unused pcap_adc_sync
  mfd: db8500-prcmu: Remove needless return in three void APIs
  mfd: Remove STA2x11 core driver
  mfd: max77620: Allow building as a module
  mfd: ene-kb3930: Fix a potential NULL pointer dereference
  dt-bindings: mfd: qcom,tcsr: Add compatible for MSM8937
  ...
This commit is contained in:
Linus Torvalds 2025-03-29 14:33:13 -07:00
commit dcab75a3c8
69 changed files with 2722 additions and 2599 deletions

View File

@ -19,12 +19,11 @@ properties:
oneOf:
- const: atmel,sama5d2-flexcom
- items:
- const: microchip,sam9x7-flexcom
- enum:
- microchip,sam9x7-flexcom
- microchip,sama7d65-flexcom
- microchip,sama7g5-flexcom
- const: atmel,sama5d2-flexcom
- items:
- const: microchip,sama7g5-flexcom
- const: atmel,sama5d2-flexcom
reg:
maxItems: 1

View File

@ -0,0 +1,53 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/mfd/fsl,mcu-mpc8349emitx.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Freescale MPC8349E-mITX-compatible Power Management Micro Controller Unit (MCU)
maintainers:
- J. Neuschäfer <j.ne@posteo.net>
properties:
compatible:
oneOf:
- items:
- enum:
- fsl,mc9s08qg8-mpc8315erdb
- fsl,mc9s08qg8-mpc8349emitx
- fsl,mc9s08qg8-mpc8377erdb
- fsl,mc9s08qg8-mpc8378erdb
- fsl,mc9s08qg8-mpc8379erdb
- const: fsl,mcu-mpc8349emitx
reg:
maxItems: 1
"#gpio-cells":
const: 2
gpio-controller: true
required:
- compatible
- reg
- "#gpio-cells"
- gpio-controller
additionalProperties: false
examples:
- |
i2c {
#address-cells = <1>;
#size-cells = <0>;
mcu@a {
#gpio-cells = <2>;
compatible = "fsl,mc9s08qg8-mpc8349emitx",
"fsl,mcu-mpc8349emitx";
reg = <0x0a>;
gpio-controller;
};
};

View File

@ -0,0 +1,158 @@
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/mfd/maxim,max77705.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Maxim MAX77705 Companion Power Management and USB Type-C interface
maintainers:
- Dzmitry Sankouski <dsankouski@gmail.com>
description: |
This is a part of device tree bindings for Maxim MAX77705.
Maxim MAX77705 is a Companion Power Management and Type-C
interface IC which includes charger, fuelgauge, LED, haptic motor driver and
Type-C management.
properties:
compatible:
const: maxim,max77705
reg:
maxItems: 1
interrupts:
maxItems: 1
haptic:
type: object
additionalProperties: false
properties:
compatible:
const: maxim,max77705-haptic
haptic-supply: true
pwms:
maxItems: 1
required:
- compatible
- haptic-supply
- pwms
leds:
type: object
additionalProperties: false
description:
Up to 4 LED channels supported.
properties:
compatible:
const: maxim,max77705-rgb
"#address-cells":
const: 1
"#size-cells":
const: 0
multi-led:
type: object
$ref: /schemas/leds/leds-class-multicolor.yaml#
unevaluatedProperties: false
properties:
"#address-cells":
const: 1
"#size-cells":
const: 0
patternProperties:
"^led@[0-3]$":
type: object
$ref: /schemas/leds/common.yaml#
unevaluatedProperties: false
properties:
reg:
maxItems: 1
required:
- reg
patternProperties:
"^led@[0-3]$":
type: object
$ref: /schemas/leds/common.yaml#
unevaluatedProperties: false
properties:
reg:
maxItems: 1
required:
- reg
required:
- compatible
required:
- compatible
additionalProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/leds/common.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
pmic@66 {
compatible = "maxim,max77705";
reg = <0x66>;
interrupt-parent = <&pm8998_gpios>;
interrupts = <11 IRQ_TYPE_LEVEL_LOW>;
pinctrl-0 = <&chg_int_default>;
pinctrl-names = "default";
leds {
compatible = "maxim,max77705-rgb";
multi-led {
color = <LED_COLOR_ID_RGB>;
function = LED_FUNCTION_STATUS;
#address-cells = <1>;
#size-cells = <0>;
led@1 {
reg = <1>;
color = <LED_COLOR_ID_RED>;
};
led@2 {
reg = <2>;
color = <LED_COLOR_ID_GREEN>;
};
led@3 {
reg = <3>;
color = <LED_COLOR_ID_BLUE>;
};
};
};
haptic {
compatible = "maxim,max77705-haptic";
haptic-supply = <&vib_regulator>;
pwms = <&vib_pwm 0 50000>;
};
};
};

View File

@ -52,6 +52,7 @@ properties:
- qcom,tcsr-msm8660
- qcom,tcsr-msm8916
- qcom,tcsr-msm8917
- qcom,tcsr-msm8937
- qcom,tcsr-msm8953
- qcom,tcsr-msm8960
- qcom,tcsr-msm8974

View File

@ -25,6 +25,7 @@ properties:
- samsung,s2mps14-pmic
- samsung,s2mps15-pmic
- samsung,s2mpu02-pmic
- samsung,s2mpu05-pmic
clocks:
$ref: /schemas/clock/samsung,s2mps11.yaml
@ -125,6 +126,18 @@ allOf:
samsung,s2mps11-acokb-ground: false
samsung,s2mps11-wrstbi-ground: false
- if:
properties:
compatible:
contains:
const: samsung,s2mpu05-pmic
then:
properties:
regulators:
$ref: /schemas/regulator/samsung,s2mpu05.yaml
samsung,s2mps11-acokb-ground: false
samsung,s2mps11-wrstbi-ground: false
examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>

View File

@ -21,7 +21,9 @@ maintainers:
properties:
compatible:
const: st,stm32-timers
enum:
- st,stm32-timers
- st,stm32mp25-timers
reg:
maxItems: 1
@ -36,6 +38,9 @@ properties:
resets:
maxItems: 1
power-domains:
maxItems: 1
dmas:
minItems: 1
maxItems: 7
@ -77,7 +82,9 @@ properties:
properties:
compatible:
const: st,stm32-pwm
enum:
- st,stm32-pwm
- st,stm32mp25-pwm
"#pwm-cells":
const: 3
@ -113,7 +120,9 @@ properties:
properties:
compatible:
const: st,stm32-timer-counter
enum:
- st,stm32-timer-counter
- st,stm32mp25-timer-counter
required:
- compatible
@ -128,12 +137,13 @@ patternProperties:
enum:
- st,stm32-timer-trigger
- st,stm32h7-timer-trigger
- st,stm32mp25-timer-trigger
reg:
description: Identify trigger hardware block.
items:
minimum: 0
maximum: 16
maximum: 19
required:
- compatible

View File

@ -27,6 +27,7 @@ select:
compatible:
contains:
enum:
- airoha,en7581-pbus-csr
- al,alpine-sysfabric-service
- allwinner,sun8i-a83t-system-controller
- allwinner,sun8i-h3-system-controller
@ -90,6 +91,8 @@ select:
- microchip,lan966x-cpu-syscon
- microchip,mpfs-sysreg-scb
- microchip,sam9x60-sfr
- microchip,sama7d65-ddr3phy
- microchip,sama7d65-sfrbu
- microchip,sama7g5-ddr3phy
- mscc,ocelot-cpu-syscon
- mstar,msc313-pmsleep
@ -127,6 +130,7 @@ properties:
compatible:
items:
- enum:
- airoha,en7581-pbus-csr
- al,alpine-sysfabric-service
- allwinner,sun8i-a83t-system-controller
- allwinner,sun8i-h3-system-controller
@ -190,6 +194,8 @@ properties:
- microchip,lan966x-cpu-syscon
- microchip,mpfs-sysreg-scb
- microchip,sam9x60-sfr
- microchip,sama7d65-ddr3phy
- microchip,sama7d65-sfrbu
- microchip,sama7g5-ddr3phy
- mscc,ocelot-cpu-syscon
- mstar,msc313-pmsleep

View File

@ -0,0 +1,50 @@
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/power/supply/maxim,max77705.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Maxim MAX777705 charger
maintainers:
- Dzmitry Sankouski <dsankouski@gmail.com>
description: |
This is a device tree bindings for charger found in Maxim MAX77705 chip.
allOf:
- $ref: power-supply.yaml#
properties:
compatible:
const: maxim,max77705-charger
interrupts:
maxItems: 1
reg:
maxItems: 1
required:
- compatible
- reg
- monitored-battery
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
charger@69 {
compatible = "maxim,max77705-charger";
reg = <0x69>;
monitored-battery = <&battery>;
interrupt-parent = <&pm8998_gpios>;
interrupts = <11 IRQ_TYPE_LEVEL_LOW>;
};
};

View File

@ -1,17 +0,0 @@
Freescale MPC8349E-mITX-compatible Power Management Micro Controller Unit (MCU)
Required properties:
- compatible : "fsl,<mcu-chip>-<board>", "fsl,mcu-mpc8349emitx".
- reg : should specify I2C address (0x0a).
- #gpio-cells : should be 2.
- gpio-controller : should be present.
Example:
mcu@a {
#gpio-cells = <2>;
compatible = "fsl,mc9s08qg8-mpc8349emitx",
"fsl,mcu-mpc8349emitx";
reg = <0x0a>;
gpio-controller;
};

View File

@ -0,0 +1,47 @@
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/regulator/samsung,s2mpu05.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Samsung S2MPU05 Power Management IC regulators
maintainers:
- Kaustabh Chakraborty <kauschluss@disroot.org>
description: |
This is a part of device tree bindings for S2M and S5M family of Power
Management IC (PMIC).
The S2MPU05 provides buck and LDO regulators.
See also Documentation/devicetree/bindings/mfd/samsung,s2mps11.yaml for
additional information and example.
patternProperties:
# 21 LDOs
"^ldo([1-9]|10|2[5-9]|3[0-5])$":
type: object
$ref: regulator.yaml#
unevaluatedProperties: false
description:
Properties for single LDO regulator.
LDOs 11-24 are used for CP, and they're left unimplemented due to lack
of documentation on these regulators.
required:
- regulator-name
# 5 bucks
"^buck[1-5]$":
type: object
$ref: regulator.yaml#
unevaluatedProperties: false
description:
Properties for single buck regulator.
required:
- regulator-name
additionalProperties: false

View File

@ -4,7 +4,7 @@
$id: http://devicetree.org/schemas/regulator/ti,tps65219.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: TI tps65219 Power Management Integrated Circuit regulators
title: TI TPS65214/TPS65215/TPS65219 Power Management Integrated Circuit
maintainers:
- Jerome Neanne <jerome.neanne@baylibre.com>
@ -12,9 +12,20 @@ maintainers:
description: |
Regulator nodes should be named to buck<number> and ldo<number>.
TI TPS65219 is a Power Management IC with 3 Buck regulators, 4 Low
Drop-out Regulators (LDOs), 1 GPIO, 2 GPOs, and power-button.
TI TPS65215 is a derivative of TPS65219 with 3 Buck regulators, 2 Low
Drop-out Regulators (LDOs), 1 GPIO, 1 GPO, and power-button.
TI TPS65214 is a derivative of TPS65219 with 3 Buck regulators, 2 Low
Drop-out Regulators (LDOs), 1 GPIO, 1 GPO, and power-button.
properties:
compatible:
enum:
- ti,tps65214
- ti,tps65215
- ti,tps65219
reg:
@ -90,6 +101,20 @@ required:
additionalProperties: false
allOf:
- if:
properties:
compatible:
contains:
enum:
- ti,tps65214
- ti,tps65215
then:
properties:
regulators:
patternProperties:
"^ldo[3-4]$": false
examples:
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>

View File

@ -14524,12 +14524,15 @@ B: mailto:linux-samsung-soc@vger.kernel.org
F: Documentation/devicetree/bindings/*/maxim,max14577.yaml
F: Documentation/devicetree/bindings/*/maxim,max77686.yaml
F: Documentation/devicetree/bindings/*/maxim,max77693.yaml
F: Documentation/devicetree/bindings/*/maxim,max77705*.yaml
F: Documentation/devicetree/bindings/*/maxim,max77843.yaml
F: Documentation/devicetree/bindings/clock/maxim,max77686.txt
F: drivers/leds/leds-max77705.c
F: drivers/*/*max77843.c
F: drivers/*/max14577*.c
F: drivers/*/max77686*.c
F: drivers/*/max77693*.c
F: drivers/*/max77705*.c
F: drivers/clk/clk-max77686.c
F: drivers/extcon/extcon-max14577.c
F: drivers/extcon/extcon-max77693.c
@ -14537,6 +14540,7 @@ F: drivers/rtc/rtc-max77686.c
F: include/linux/mfd/max14577*.h
F: include/linux/mfd/max77686*.h
F: include/linux/mfd/max77693*.h
F: include/linux/mfd/max77705*.h
MAXIRADIO FM RADIO RECEIVER DRIVER
M: Hans Verkuil <hverkuil@xs4all.nl>

View File

@ -254,9 +254,6 @@ CONFIG_I2C_TAOS_EVM=m
CONFIG_I2C_STUB=m
# CONFIG_HWMON is not set
CONFIG_THERMAL=y
CONFIG_MFD_PCF50633=m
CONFIG_PCF50633_ADC=m
CONFIG_PCF50633_GPIO=m
# CONFIG_VGA_ARB is not set
CONFIG_LEDS_LP3944=m
CONFIG_LEDS_PCA955X=m

View File

@ -240,12 +240,12 @@ config INPUT_MAX77650_ONKEY
will be called max77650-onkey.
config INPUT_MAX77693_HAPTIC
tristate "MAXIM MAX77693/MAX77843 haptic controller support"
depends on (MFD_MAX77693 || MFD_MAX77843) && PWM
tristate "MAXIM MAX77693/MAX77705/MAX77843 haptic controller support"
depends on (MFD_MAX77693 || MFD_MAX77705 || MFD_MAX77843) && PWM
select INPUT_FF_MEMLESS
help
This option enables support for the haptic controller on
MAXIM MAX77693 and MAX77843 chips.
MAXIM MAX77693, MAX77705 and MAX77843 chips.
To compile this driver as module, choose M here: the
module will be called max77693-haptic.

View File

@ -24,6 +24,7 @@
#include <linux/mfd/max77693.h>
#include <linux/mfd/max77693-common.h>
#include <linux/mfd/max77693-private.h>
#include <linux/mfd/max77705-private.h>
#include <linux/mfd/max77843-private.h>
#define MAX_MAGNITUDE_SHIFT 16
@ -116,6 +117,13 @@ static int max77693_haptic_configure(struct max77693_haptic *haptic,
MAX77693_HAPTIC_PWM_DIVISOR_128);
config_reg = MAX77693_HAPTIC_REG_CONFIG2;
break;
case TYPE_MAX77705:
value = ((haptic->type << MAX77693_CONFIG2_MODE) |
(enable << MAX77693_CONFIG2_MEN) |
(haptic->mode << MAX77693_CONFIG2_HTYP) |
MAX77693_HAPTIC_PWM_DIVISOR_128);
config_reg = MAX77705_PMIC_REG_MCONFIG;
break;
case TYPE_MAX77843:
value = (haptic->type << MCONFIG_MODE_SHIFT) |
(enable << MCONFIG_MEN_SHIFT) |
@ -313,6 +321,7 @@ static int max77693_haptic_probe(struct platform_device *pdev)
case TYPE_MAX77693:
haptic->regmap_haptic = max77693->regmap_haptic;
break;
case TYPE_MAX77705:
case TYPE_MAX77843:
haptic->regmap_haptic = max77693->regmap;
break;
@ -408,6 +417,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(max77693_haptic_pm_ops,
static const struct platform_device_id max77693_haptic_id[] = {
{ "max77693-haptic", },
{ "max77705-haptic", },
{ "max77843-haptic", },
{},
};
@ -415,6 +425,7 @@ MODULE_DEVICE_TABLE(platform, max77693_haptic_id);
static const struct of_device_id of_max77693_haptic_dt_match[] = {
{ .compatible = "maxim,max77693-haptic", },
{ .compatible = "maxim,max77705-haptic", },
{ .compatible = "maxim,max77843-haptic", },
{ /* sentinel */ },
};
@ -433,5 +444,5 @@ module_platform_driver(max77693_haptic_driver);
MODULE_AUTHOR("Jaewon Kim <jaewon02.kim@samsung.com>");
MODULE_AUTHOR("Krzysztof Kozlowski <krzk@kernel.org>");
MODULE_DESCRIPTION("MAXIM 77693/77843 Haptic driver");
MODULE_DESCRIPTION("MAXIM 77693/77705/77843 Haptic driver");
MODULE_LICENSE("GPL");

View File

@ -778,6 +778,14 @@ config LEDS_MAX77650
help
LEDs driver for MAX77650 family of PMICs from Maxim Integrated.
config LEDS_MAX77705
tristate "LED support for Maxim MAX77705 PMIC"
depends on MFD_MAX77705
depends on LEDS_CLASS
depends on LEDS_CLASS_MULTICOLOR
help
LED driver for MAX77705 PMIC from Maxim Integrated.
config LEDS_MAX8997
tristate "LED support for MAX8997 PMIC"
depends on LEDS_CLASS && MFD_MAX8997

View File

@ -61,6 +61,7 @@ obj-$(CONFIG_LEDS_LP8864) += leds-lp8864.o
obj-$(CONFIG_LEDS_LT3593) += leds-lt3593.o
obj-$(CONFIG_LEDS_MAX5970) += leds-max5970.o
obj-$(CONFIG_LEDS_MAX77650) += leds-max77650.o
obj-$(CONFIG_LEDS_MAX77705) += leds-max77705.o
obj-$(CONFIG_LEDS_MAX8997) += leds-max8997.o
obj-$(CONFIG_LEDS_MC13783) += leds-mc13783.o
obj-$(CONFIG_LEDS_MENF21BMC) += leds-menf21bmc.o

View File

@ -0,0 +1,275 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Based on leds-max77650 driver
*
* LED driver for MAXIM 77705 PMIC.
* Copyright (C) 2025 Dzmitry Sankouski <dsankouski@gmail.org>
*/
#include <linux/i2c.h>
#include <linux/led-class-multicolor.h>
#include <linux/leds.h>
#include <linux/mfd/max77705-private.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#define MAX77705_LED_NUM_LEDS 4
#define MAX77705_LED_EN_MASK GENMASK(1, 0)
#define MAX77705_LED_MAX_BRIGHTNESS 0xff
#define MAX77705_LED_EN_SHIFT(reg) (reg * MAX77705_RGBLED_EN_WIDTH)
#define MAX77705_LED_REG_BRIGHTNESS(reg) (reg + MAX77705_RGBLED_REG_LED0BRT)
struct max77705_led {
struct led_classdev cdev;
struct led_classdev_mc mcdev;
struct regmap *regmap;
struct mc_subled *subled_info;
};
static const struct regmap_config max77705_leds_regmap_config = {
.reg_base = MAX77705_RGBLED_REG_BASE,
.reg_bits = 8,
.val_bits = 8,
.max_register = MAX77705_LED_REG_END,
};
static int max77705_rgb_blink(struct led_classdev *cdev,
unsigned long *delay_on,
unsigned long *delay_off)
{
struct max77705_led *led = container_of(cdev, struct max77705_led, cdev);
int value, on_value, off_value;
if (*delay_on < MAX77705_RGB_DELAY_100_STEP)
on_value = 0;
else if (*delay_on < MAX77705_RGB_DELAY_100_STEP_LIM)
on_value = *delay_on / MAX77705_RGB_DELAY_100_STEP - 1;
else if (*delay_on < MAX77705_RGB_DELAY_250_STEP_LIM)
on_value = (*delay_on - MAX77705_RGB_DELAY_100_STEP_LIM) /
MAX77705_RGB_DELAY_250_STEP +
MAX77705_RGB_DELAY_100_STEP_COUNT;
else
on_value = 15;
on_value <<= 4;
if (*delay_off < 1)
off_value = 0;
else if (*delay_off < MAX77705_RGB_DELAY_500_STEP)
off_value = 1;
else if (*delay_off < MAX77705_RGB_DELAY_500_STEP_LIM)
off_value = *delay_off / MAX77705_RGB_DELAY_500_STEP;
else if (*delay_off < MAX77705_RGB_DELAY_1000_STEP_LIM)
off_value = (*delay_off - MAX77705_RGB_DELAY_1000_STEP_LIM) /
MAX77705_RGB_DELAY_1000_STEP +
MAX77705_RGB_DELAY_500_STEP_COUNT;
else if (*delay_off < MAX77705_RGB_DELAY_2000_STEP_LIM)
off_value = (*delay_off - MAX77705_RGB_DELAY_2000_STEP_LIM) /
MAX77705_RGB_DELAY_2000_STEP +
MAX77705_RGB_DELAY_1000_STEP_COUNT;
else
off_value = 15;
value = on_value | off_value;
return regmap_write(led->regmap, MAX77705_RGBLED_REG_LEDBLNK, value);
}
static int max77705_led_brightness_set(struct regmap *regmap, struct mc_subled *subled,
int num_colors)
{
int ret;
for (int i = 0; i < num_colors; i++) {
unsigned int channel, brightness;
channel = subled[i].channel;
brightness = subled[i].brightness;
if (brightness == LED_OFF) {
/* Flash OFF */
ret = regmap_update_bits(regmap,
MAX77705_RGBLED_REG_LEDEN,
MAX77705_LED_EN_MASK << MAX77705_LED_EN_SHIFT(channel), 0);
} else {
/* Set current */
ret = regmap_write(regmap, MAX77705_LED_REG_BRIGHTNESS(channel),
brightness);
if (ret < 0)
return ret;
ret = regmap_update_bits(regmap,
MAX77705_RGBLED_REG_LEDEN,
LED_ON << MAX77705_LED_EN_SHIFT(channel),
MAX77705_LED_EN_MASK << MAX77705_LED_EN_SHIFT(channel));
}
}
return ret;
}
static int max77705_led_brightness_set_single(struct led_classdev *cdev,
enum led_brightness brightness)
{
struct max77705_led *led = container_of(cdev, struct max77705_led, cdev);
led->subled_info->brightness = brightness;
return max77705_led_brightness_set(led->regmap, led->subled_info, 1);
}
static int max77705_led_brightness_set_multi(struct led_classdev *cdev,
enum led_brightness brightness)
{
struct led_classdev_mc *mcdev = lcdev_to_mccdev(cdev);
struct max77705_led *led = container_of(mcdev, struct max77705_led, mcdev);
led_mc_calc_color_components(mcdev, brightness);
return max77705_led_brightness_set(led->regmap, led->mcdev.subled_info, mcdev->num_colors);
}
static int max77705_parse_subled(struct device *dev, struct fwnode_handle *np,
struct mc_subled *info)
{
u32 color = LED_COLOR_ID_GREEN;
u32 reg;
int ret;
ret = fwnode_property_read_u32(np, "reg", &reg);
if (ret || !reg || reg >= MAX77705_LED_NUM_LEDS)
return dev_err_probe(dev, -EINVAL, "invalid \"reg\" of %pOFn\n", np);
info->channel = reg;
ret = fwnode_property_read_u32(np, "color", &color);
if (ret < 0 && ret != -EINVAL)
return dev_err_probe(dev, ret,
"failed to parse \"color\" of %pOF\n", np);
info->color_index = color;
return 0;
}
static int max77705_add_led(struct device *dev, struct regmap *regmap, struct fwnode_handle *np)
{
int ret, i = 0;
unsigned int color, reg;
struct max77705_led *led;
struct led_classdev *cdev;
struct mc_subled *info;
struct fwnode_handle *child;
struct led_init_data init_data = {};
led = devm_kzalloc(dev, sizeof(*led), GFP_KERNEL);
if (!led)
return -ENOMEM;
ret = fwnode_property_read_u32(np, "color", &color);
if (ret < 0 && ret != -EINVAL)
return dev_err_probe(dev, ret,
"failed to parse \"color\" of %pOF\n", np);
led->regmap = regmap;
init_data.fwnode = np;
if (color == LED_COLOR_ID_RGB) {
int num_channels = of_get_available_child_count(to_of_node(np));
ret = fwnode_property_read_u32(np, "reg", &reg);
if (ret || reg >= MAX77705_LED_NUM_LEDS)
ret = -EINVAL;
info = devm_kcalloc(dev, num_channels, sizeof(*info), GFP_KERNEL);
if (!info)
return -ENOMEM;
cdev = &led->mcdev.led_cdev;
cdev->max_brightness = MAX77705_LED_MAX_BRIGHTNESS;
cdev->brightness_set_blocking = max77705_led_brightness_set_multi;
cdev->blink_set = max77705_rgb_blink;
fwnode_for_each_available_child_node(np, child) {
ret = max77705_parse_subled(dev, child, &info[i]);
if (ret < 0)
return ret;
info[i].intensity = 0;
i++;
}
led->mcdev.subled_info = info;
led->mcdev.num_colors = num_channels;
led->cdev = *cdev;
ret = devm_led_classdev_multicolor_register_ext(dev, &led->mcdev, &init_data);
if (ret)
return ret;
ret = max77705_led_brightness_set_multi(&led->cdev, LED_OFF);
if (ret)
return ret;
} else {
info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
if (!info)
return -ENOMEM;
max77705_parse_subled(dev, np, info);
led->subled_info = info;
led->cdev.brightness_set_blocking = max77705_led_brightness_set_single;
led->cdev.blink_set = max77705_rgb_blink;
led->cdev.max_brightness = MAX77705_LED_MAX_BRIGHTNESS;
ret = devm_led_classdev_register_ext(dev, &led->cdev, &init_data);
if (ret)
return ret;
ret = max77705_led_brightness_set_single(&led->cdev, LED_OFF);
if (ret)
return ret;
}
return 0;
}
static int max77705_led_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct i2c_client *i2c = to_i2c_client(pdev->dev.parent);
struct regmap *regmap;
int ret;
regmap = devm_regmap_init_i2c(i2c, &max77705_leds_regmap_config);
if (IS_ERR(regmap))
return dev_err_probe(dev, PTR_ERR(regmap), "Failed to register LEDs regmap\n");
device_for_each_child_node_scoped(dev, child) {
ret = max77705_add_led(dev, regmap, child);
if (ret)
return ret;
}
return 0;
}
static const struct of_device_id max77705_led_of_match[] = {
{ .compatible = "maxim,max77705-rgb" },
{ }
};
MODULE_DEVICE_TABLE(of, max77705_led_of_match);
static struct platform_driver max77705_led_driver = {
.driver = {
.name = "max77705-led",
.of_match_table = max77705_led_of_match,
},
.probe = max77705_led_probe,
};
module_platform_driver(max77705_led_driver);
MODULE_DESCRIPTION("Maxim MAX77705 LED driver");
MODULE_AUTHOR("Dzmitry Sankouski <dsankouski@gmail.com>");
MODULE_LICENSE("GPL");

View File

@ -138,7 +138,7 @@ config MFD_AAT2870_CORE
config MFD_AT91_USART
tristate "AT91 USART Driver"
select MFD_CORE
depends on ARCH_AT91 || COMPILE_TEST
depends on ARCH_AT91 || ARCH_LAN969X || COMPILE_TEST
help
Select this to get support for AT91 USART IP. This is a wrapper
over at91-usart-serial driver and usart-spi-driver. Only one function
@ -858,7 +858,7 @@ config MFD_MAX77541
There are regulators and adc.
config MFD_MAX77620
bool "Maxim Semiconductor MAX77620 and MAX20024 PMIC Support"
tristate "Maxim Semiconductor MAX77620 and MAX20024 PMIC Support"
depends on I2C=y
depends on OF
select MFD_CORE
@ -916,6 +916,19 @@ config MFD_MAX77693
additional drivers must be enabled in order to use the functionality
of the device.
config MFD_MAX77705
tristate "Maxim MAX77705 PMIC Support"
depends on I2C
select MFD_CORE
select MFD_SIMPLE_MFD_I2C
help
Say yes here to add support for Maxim Integrated MAX77705 PMIC.
This is a Power Management IC with Charger, safe LDOs, Flash, Haptic
and MUIC controls on chip.
This driver provides common support for accessing the device;
additional drivers must be enabled in order to use the functionality
of the device.
config MFD_MAX77714
tristate "Maxim Semiconductor MAX77714 PMIC Support"
depends on I2C
@ -1119,30 +1132,6 @@ config MFD_RETU
Retu and Tahvo are a multi-function devices found on Nokia
Internet Tablets (770, N800 and N810).
config MFD_PCF50633
tristate "NXP PCF50633"
depends on I2C
select REGMAP_I2C
help
Say yes here if you have NXP PCF50633 chip on your board.
This core driver provides register access and IRQ handling
facilities, and registers devices for the various functions
so that function-specific drivers can bind to them.
config PCF50633_ADC
tristate "NXP PCF50633 ADC"
depends on MFD_PCF50633
help
Say yes here if you want to include support for ADC in the
NXP PCF50633 chip.
config PCF50633_GPIO
tristate "NXP PCF50633 GPIO"
depends on MFD_PCF50633
help
Say yes here if you want to include support GPIO for pins on
the PCF50633 chip.
config MFD_PM8XXX
tristate "Qualcomm PM8xxx PMIC chips driver"
depends on ARM || HEXAGON || COMPILE_TEST
@ -1495,12 +1484,6 @@ config STMPE_SPI
This is used to enable SPI interface of STMPE
endmenu
config MFD_STA2X11
bool "STMicroelectronics STA2X11"
depends on STA2X11
select MFD_CORE
select REGMAP_MMIO
config MFD_SUN6I_PRCM
bool "Allwinner A31/A23/A33 PRCM controller"
depends on ARCH_SUNXI || COMPILE_TEST

View File

@ -26,7 +26,6 @@ obj-$(CONFIG_MFD_TI_LP873X) += lp873x.o
obj-$(CONFIG_MFD_TI_LP87565) += lp87565.o
obj-$(CONFIG_MFD_TI_AM335X_TSCADC) += ti_am335x_tscadc.o
obj-$(CONFIG_MFD_STA2X11) += sta2x11-mfd.o
obj-$(CONFIG_MFD_STMPE) += stmpe.o
obj-$(CONFIG_STMPE_I2C) += stmpe-i2c.o
obj-$(CONFIG_STMPE_SPI) += stmpe-spi.o
@ -168,6 +167,7 @@ obj-$(CONFIG_MFD_MAX77620) += max77620.o
obj-$(CONFIG_MFD_MAX77650) += max77650.o
obj-$(CONFIG_MFD_MAX77686) += max77686.o
obj-$(CONFIG_MFD_MAX77693) += max77693.o
obj-$(CONFIG_MFD_MAX77705) += max77705.o
obj-$(CONFIG_MFD_MAX77714) += max77714.o
obj-$(CONFIG_MFD_MAX77843) += max77843.o
obj-$(CONFIG_MFD_MAX8907) += max8907.o
@ -183,10 +183,6 @@ obj-$(CONFIG_MFD_MT6370) += mt6370.o
mt6397-objs := mt6397-core.o mt6397-irq.o mt6358-irq.o
obj-$(CONFIG_MFD_MT6397) += mt6397.o
pcf50633-objs := pcf50633-core.o pcf50633-irq.o
obj-$(CONFIG_MFD_PCF50633) += pcf50633.o
obj-$(CONFIG_PCF50633_ADC) += pcf50633-adc.o
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

View File

@ -224,6 +224,7 @@ static const struct regmap_range axp717_writeable_ranges[] = {
regmap_reg_range(AXP717_VSYS_V_POWEROFF, AXP717_VSYS_V_POWEROFF),
regmap_reg_range(AXP717_IRQ0_EN, AXP717_IRQ4_EN),
regmap_reg_range(AXP717_IRQ0_STATE, AXP717_IRQ4_STATE),
regmap_reg_range(AXP717_TS_PIN_CFG, AXP717_TS_PIN_CFG),
regmap_reg_range(AXP717_ICC_CHG_SET, AXP717_CV_CHG_SET),
regmap_reg_range(AXP717_DCDC_OUTPUT_CONTROL, AXP717_CPUSLDO_CONTROL),
regmap_reg_range(AXP717_ADC_CH_EN_CONTROL, AXP717_ADC_CH_EN_CONTROL),

View File

@ -96,7 +96,7 @@ static int cgbc_session_command(struct cgbc_device_data *cgbc, u8 cmd)
static int cgbc_session_request(struct cgbc_device_data *cgbc)
{
unsigned int ret;
int ret;
ret = cgbc_wait_device(cgbc);
@ -236,6 +236,7 @@ static struct mfd_cell cgbc_devs[] = {
{ .name = "cgbc-gpio" },
{ .name = "cgbc-i2c", .id = 1 },
{ .name = "cgbc-i2c", .id = 2 },
{ .name = "cgbc-hwmon" },
};
static int cgbc_map(struct cgbc_device_data *cgbc)
@ -384,6 +385,13 @@ static const struct dmi_system_id cgbc_dmi_table[] __initconst = {
DMI_MATCH(DMI_BOARD_NAME, "conga-SA7"),
},
},
{
.ident = "SA8",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "congatec"),
DMI_MATCH(DMI_BOARD_NAME, "conga-SA8"),
},
},
{}
};
MODULE_DEVICE_TABLE(dmi, cgbc_dmi_table);

View File

@ -162,7 +162,7 @@ static int kb3930_probe(struct i2c_client *client)
devm_gpiod_get_array_optional(dev, "off", GPIOD_IN);
if (IS_ERR(ddata->off_gpios))
return PTR_ERR(ddata->off_gpios);
if (ddata->off_gpios->ndescs < 2) {
if (ddata->off_gpios && ddata->off_gpios->ndescs < 2) {
dev_err(dev, "invalid off-gpios property\n");
return -EINVAL;
}

View File

@ -25,11 +25,6 @@ struct pcap_adc_request {
void *data;
};
struct pcap_adc_sync_request {
u16 res[2];
struct completion completion;
};
struct pcap_chip {
struct spi_device *spi;
@ -335,34 +330,6 @@ int pcap_adc_async(struct pcap_chip *pcap, u8 bank, u32 flags, u8 ch[],
}
EXPORT_SYMBOL_GPL(pcap_adc_async);
static void pcap_adc_sync_cb(void *param, u16 res[])
{
struct pcap_adc_sync_request *req = param;
req->res[0] = res[0];
req->res[1] = res[1];
complete(&req->completion);
}
int pcap_adc_sync(struct pcap_chip *pcap, u8 bank, u32 flags, u8 ch[],
u16 res[])
{
struct pcap_adc_sync_request sync_data;
int ret;
init_completion(&sync_data.completion);
ret = pcap_adc_async(pcap, bank, flags, ch, pcap_adc_sync_cb,
&sync_data);
if (ret)
return ret;
wait_for_completion(&sync_data.completion);
res[0] = sync_data.res[0];
res[1] = sync_data.res[1];
return 0;
}
EXPORT_SYMBOL_GPL(pcap_adc_sync);
/* subdevs */
static int pcap_remove_subdev(struct device *dev, void *unused)
{

View File

@ -82,7 +82,6 @@ static const struct regmap_config chtdc_ti_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = 0xff,
.cache_type = REGCACHE_NONE,
};
static const struct regmap_irq chtdc_ti_irqs[] = {

View File

@ -113,7 +113,6 @@ static const struct regmap_config crystal_cove_regmap_config = {
.val_bits = 8,
.max_register = CRYSTAL_COVE_MAX_REGISTER,
.cache_type = REGCACHE_NONE,
};
static const struct regmap_irq crystal_cove_irqs[] = {

View File

@ -22,6 +22,7 @@
#include <linux/mfd/core.h>
#include <linux/mfd/ipaq-micro.h>
#include <linux/string.h>
#include <linux/string_choices.h>
#include <linux/random.h>
#include <linux/slab.h>
#include <linux/list.h>
@ -267,7 +268,7 @@ static void __init ipaq_micro_eeprom_dump(struct ipaq_micro *micro)
dev_info(micro->dev, "page mode: %u\n", ipaq_micro_to_u16(dump+84));
dev_info(micro->dev, "country ID: %u\n", ipaq_micro_to_u16(dump+86));
dev_info(micro->dev, "color display: %s\n",
ipaq_micro_to_u16(dump+88) ? "yes" : "no");
str_yes_no(ipaq_micro_to_u16(dump + 88)));
dev_info(micro->dev, "ROM size: %u MiB\n", ipaq_micro_to_u16(dump+90));
dev_info(micro->dev, "RAM size: %u KiB\n", ipaq_micro_to_u16(dump+92));
dev_info(micro->dev, "screen: %u x %u\n",

View File

@ -29,6 +29,7 @@
#include <linux/mfd/core.h>
#include <linux/mfd/max77620.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/regmap.h>
#include <linux/slab.h>
@ -700,3 +701,7 @@ static struct i2c_driver max77620_driver = {
.id_table = max77620_id,
};
builtin_i2c_driver(max77620_driver);
MODULE_DESCRIPTION("Maxim Semiconductor MAX77620 and MAX20024 PMIC Support");
MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
MODULE_LICENSE("GPL");

182
drivers/mfd/max77705.c Normal file
View File

@ -0,0 +1,182 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Maxim MAX77705 PMIC core driver
*
* Copyright (C) 2025 Dzmitry Sankouski <dsankouski@gmail.com>
**/
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/mfd/core.h>
#include <linux/mfd/max77705-private.h>
#include <linux/mfd/max77693-common.h>
#include <linux/pm.h>
#include <linux/power/max17042_battery.h>
#include <linux/module.h>
#include <linux/regmap.h>
#include <linux/of.h>
static struct mfd_cell max77705_devs[] = {
MFD_CELL_OF("max77705-rgb", NULL, NULL, 0, 0, "maxim,max77705-rgb"),
MFD_CELL_OF("max77705-charger", NULL, NULL, 0, 0, "maxim,max77705-charger"),
MFD_CELL_OF("max77705-haptic", NULL, NULL, 0, 0, "maxim,max77705-haptic"),
};
static const struct regmap_range max77705_readable_ranges[] = {
regmap_reg_range(MAX77705_PMIC_REG_PMICID1, MAX77705_PMIC_REG_BSTOUT_MASK),
regmap_reg_range(MAX77705_PMIC_REG_INTSRC, MAX77705_PMIC_REG_RESERVED_29),
regmap_reg_range(MAX77705_PMIC_REG_BOOSTCONTROL1, MAX77705_PMIC_REG_BOOSTCONTROL1),
regmap_reg_range(MAX77705_PMIC_REG_MCONFIG, MAX77705_PMIC_REG_MCONFIG2),
regmap_reg_range(MAX77705_PMIC_REG_FORCE_EN_MASK, MAX77705_PMIC_REG_FORCE_EN_MASK),
regmap_reg_range(MAX77705_PMIC_REG_BOOSTCONTROL1, MAX77705_PMIC_REG_BOOSTCONTROL1),
regmap_reg_range(MAX77705_PMIC_REG_BOOSTCONTROL2, MAX77705_PMIC_REG_BOOSTCONTROL2),
regmap_reg_range(MAX77705_PMIC_REG_SW_RESET, MAX77705_PMIC_REG_USBC_RESET),
};
static const struct regmap_range max77705_writable_ranges[] = {
regmap_reg_range(MAX77705_PMIC_REG_MAINCTRL1, MAX77705_PMIC_REG_BSTOUT_MASK),
regmap_reg_range(MAX77705_PMIC_REG_INTSRC, MAX77705_PMIC_REG_RESERVED_29),
regmap_reg_range(MAX77705_PMIC_REG_BOOSTCONTROL1, MAX77705_PMIC_REG_BOOSTCONTROL1),
regmap_reg_range(MAX77705_PMIC_REG_MCONFIG, MAX77705_PMIC_REG_MCONFIG2),
regmap_reg_range(MAX77705_PMIC_REG_FORCE_EN_MASK, MAX77705_PMIC_REG_FORCE_EN_MASK),
regmap_reg_range(MAX77705_PMIC_REG_BOOSTCONTROL1, MAX77705_PMIC_REG_BOOSTCONTROL1),
regmap_reg_range(MAX77705_PMIC_REG_BOOSTCONTROL2, MAX77705_PMIC_REG_BOOSTCONTROL2),
regmap_reg_range(MAX77705_PMIC_REG_SW_RESET, MAX77705_PMIC_REG_USBC_RESET),
};
static const struct regmap_access_table max77705_readable_table = {
.yes_ranges = max77705_readable_ranges,
.n_yes_ranges = ARRAY_SIZE(max77705_readable_ranges),
};
static const struct regmap_access_table max77705_writable_table = {
.yes_ranges = max77705_writable_ranges,
.n_yes_ranges = ARRAY_SIZE(max77705_writable_ranges),
};
static const struct regmap_config max77705_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.rd_table = &max77705_readable_table,
.wr_table = &max77705_writable_table,
.max_register = MAX77705_PMIC_REG_USBC_RESET,
};
static const struct regmap_irq max77705_topsys_irqs[] = {
{ .mask = MAX77705_SYSTEM_IRQ_BSTEN_INT, },
{ .mask = MAX77705_SYSTEM_IRQ_SYSUVLO_INT, },
{ .mask = MAX77705_SYSTEM_IRQ_SYSOVLO_INT, },
{ .mask = MAX77705_SYSTEM_IRQ_TSHDN_INT, },
{ .mask = MAX77705_SYSTEM_IRQ_TM_INT, },
};
static const struct regmap_irq_chip max77705_topsys_irq_chip = {
.name = "max77705-topsys",
.status_base = MAX77705_PMIC_REG_SYSTEM_INT,
.mask_base = MAX77705_PMIC_REG_SYSTEM_INT_MASK,
.num_regs = 1,
.irqs = max77705_topsys_irqs,
.num_irqs = ARRAY_SIZE(max77705_topsys_irqs),
};
static int max77705_i2c_probe(struct i2c_client *i2c)
{
struct device *dev = &i2c->dev;
struct max77693_dev *max77705;
struct regmap_irq_chip_data *irq_data;
struct irq_domain *domain;
enum max77705_hw_rev pmic_rev;
unsigned int pmic_rev_value;
int ret;
max77705 = devm_kzalloc(dev, sizeof(*max77705), GFP_KERNEL);
if (!max77705)
return -ENOMEM;
max77705->i2c = i2c;
max77705->type = TYPE_MAX77705;
i2c_set_clientdata(i2c, max77705);
max77705->regmap = devm_regmap_init_i2c(i2c, &max77705_regmap_config);
if (IS_ERR(max77705->regmap))
return PTR_ERR(max77705->regmap);
ret = regmap_read(max77705->regmap, MAX77705_PMIC_REG_PMICREV, &pmic_rev_value);
if (ret < 0)
return -ENODEV;
pmic_rev = pmic_rev_value & MAX77705_REVISION_MASK;
if (pmic_rev != MAX77705_PASS3)
return dev_err_probe(dev, -ENODEV, "Rev.0x%x is not tested\n", pmic_rev);
ret = devm_regmap_add_irq_chip(dev, max77705->regmap,
i2c->irq,
IRQF_ONESHOT | IRQF_SHARED, 0,
&max77705_topsys_irq_chip,
&irq_data);
if (ret)
return dev_err_probe(dev, ret, "Failed to add IRQ chip\n");
/* Unmask interrupts from all blocks in interrupt source register */
ret = regmap_update_bits(max77705->regmap,
MAX77705_PMIC_REG_INTSRC_MASK,
MAX77705_SRC_IRQ_ALL, (unsigned int)~MAX77705_SRC_IRQ_ALL);
if (ret < 0)
return dev_err_probe(dev, ret, "Could not unmask interrupts in INTSRC\n");
domain = regmap_irq_get_domain(irq_data);
ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE,
max77705_devs, ARRAY_SIZE(max77705_devs),
NULL, 0, domain);
if (ret)
return dev_err_probe(dev, ret, "Failed to register child devices\n");
device_init_wakeup(dev, true);
return 0;
}
static int max77705_suspend(struct device *dev)
{
struct i2c_client *i2c = to_i2c_client(dev);
disable_irq(i2c->irq);
if (device_may_wakeup(dev))
enable_irq_wake(i2c->irq);
return 0;
}
static int max77705_resume(struct device *dev)
{
struct i2c_client *i2c = to_i2c_client(dev);
if (device_may_wakeup(dev))
disable_irq_wake(i2c->irq);
enable_irq(i2c->irq);
return 0;
}
DEFINE_SIMPLE_DEV_PM_OPS(max77705_pm_ops, max77705_suspend, max77705_resume);
static const struct of_device_id max77705_i2c_of_match[] = {
{ .compatible = "maxim,max77705" },
{ }
};
MODULE_DEVICE_TABLE(of, max77705_i2c_of_match);
static struct i2c_driver max77705_i2c_driver = {
.driver = {
.name = "max77705",
.of_match_table = max77705_i2c_of_match,
.pm = pm_sleep_ptr(&max77705_pm_ops),
},
.probe = max77705_i2c_probe
};
module_i2c_driver(max77705_i2c_driver);
MODULE_DESCRIPTION("Maxim MAX77705 PMIC core driver");
MODULE_AUTHOR("Dzmitry Sankouski <dsankouski@gmail.com>");
MODULE_LICENSE("GPL");

View File

@ -335,7 +335,8 @@ int max8997_irq_init(struct max8997_dev *max8997)
}
max8997->irq_domain = domain;
ret = request_threaded_irq(max8997->irq, NULL, max8997_irq_thread,
ret = devm_request_threaded_irq(max8997->dev, max8997->irq, NULL,
max8997_irq_thread,
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
"max8997-irq", max8997);
@ -348,7 +349,8 @@ int max8997_irq_init(struct max8997_dev *max8997)
if (!max8997->ono)
return 0;
ret = request_threaded_irq(max8997->ono, NULL, max8997_irq_thread,
ret = devm_request_threaded_irq(max8997->dev, max8997->ono, NULL,
max8997_irq_thread,
IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING |
IRQF_ONESHOT, "max8997-ono", max8997);
@ -358,12 +360,3 @@ int max8997_irq_init(struct max8997_dev *max8997)
return 0;
}
void max8997_irq_exit(struct max8997_dev *max8997)
{
if (max8997->ono)
free_irq(max8997->ono, max8997);
if (max8997->irq)
free_irq(max8997->irq, max8997);
}

View File

@ -84,6 +84,12 @@ static const struct resource mt6359_keys_resources[] = {
DEFINE_RES_IRQ_NAMED(MT6359_IRQ_HOMEKEY_R, "homekey_r"),
};
static const struct resource mt6359_accdet_resources[] = {
DEFINE_RES_IRQ_NAMED(MT6359_IRQ_ACCDET, "accdet_irq"),
DEFINE_RES_IRQ_NAMED(MT6359_IRQ_ACCDET_EINT0, "accdet_eint0"),
DEFINE_RES_IRQ_NAMED(MT6359_IRQ_ACCDET_EINT1, "accdet_eint1"),
};
static const struct resource mt6323_keys_resources[] = {
DEFINE_RES_IRQ_NAMED(MT6323_IRQ_STATUS_PWRKEY, "powerkey"),
DEFINE_RES_IRQ_NAMED(MT6323_IRQ_STATUS_FCHRKEY, "homekey"),
@ -239,6 +245,12 @@ static const struct mfd_cell mt6359_devs[] = {
.resources = mt6359_keys_resources,
.of_compatible = "mediatek,mt6359-keys"
},
{
.name = "mt6359-accdet",
.of_compatible = "mediatek,mt6359-accdet",
.num_resources = ARRAY_SIZE(mt6359_accdet_resources),
.resources = mt6359_accdet_resources,
},
};
static const struct mfd_cell mt6397_devs[] = {

View File

@ -1,255 +0,0 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/* NXP PCF50633 ADC Driver
*
* (C) 2006-2008 by Openmoko, Inc.
* Author: Balaji Rao <balajirrao@openmoko.org>
* All rights reserved.
*
* Broken down from monstrous PCF50633 driver mainly by
* Harald Welte, Andy Green and Werner Almesberger
*
* NOTE: This driver does not yet support subtractive ADC mode, which means
* you can do only one measurement per read request.
*/
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/completion.h>
#include <linux/mfd/pcf50633/core.h>
#include <linux/mfd/pcf50633/adc.h>
struct pcf50633_adc_request {
int mux;
int avg;
void (*callback)(struct pcf50633 *, void *, int);
void *callback_param;
};
struct pcf50633_adc_sync_request {
int result;
struct completion completion;
};
#define PCF50633_MAX_ADC_FIFO_DEPTH 8
struct pcf50633_adc {
struct pcf50633 *pcf;
/* Private stuff */
struct pcf50633_adc_request *queue[PCF50633_MAX_ADC_FIFO_DEPTH];
int queue_head;
int queue_tail;
struct mutex queue_mutex;
};
static inline struct pcf50633_adc *__to_adc(struct pcf50633 *pcf)
{
return platform_get_drvdata(pcf->adc_pdev);
}
static void adc_setup(struct pcf50633 *pcf, int channel, int avg)
{
channel &= PCF50633_ADCC1_ADCMUX_MASK;
/* kill ratiometric, but enable ACCSW biasing */
pcf50633_reg_write(pcf, PCF50633_REG_ADCC2, 0x00);
pcf50633_reg_write(pcf, PCF50633_REG_ADCC3, 0x01);
/* start ADC conversion on selected channel */
pcf50633_reg_write(pcf, PCF50633_REG_ADCC1, channel | avg |
PCF50633_ADCC1_ADCSTART | PCF50633_ADCC1_RES_10BIT);
}
static void trigger_next_adc_job_if_any(struct pcf50633 *pcf)
{
struct pcf50633_adc *adc = __to_adc(pcf);
int head;
head = adc->queue_head;
if (!adc->queue[head])
return;
adc_setup(pcf, adc->queue[head]->mux, adc->queue[head]->avg);
}
static int
adc_enqueue_request(struct pcf50633 *pcf, struct pcf50633_adc_request *req)
{
struct pcf50633_adc *adc = __to_adc(pcf);
int head, tail;
mutex_lock(&adc->queue_mutex);
head = adc->queue_head;
tail = adc->queue_tail;
if (adc->queue[tail]) {
mutex_unlock(&adc->queue_mutex);
dev_err(pcf->dev, "ADC queue is full, dropping request\n");
return -EBUSY;
}
adc->queue[tail] = req;
if (head == tail)
trigger_next_adc_job_if_any(pcf);
adc->queue_tail = (tail + 1) & (PCF50633_MAX_ADC_FIFO_DEPTH - 1);
mutex_unlock(&adc->queue_mutex);
return 0;
}
static void pcf50633_adc_sync_read_callback(struct pcf50633 *pcf, void *param,
int result)
{
struct pcf50633_adc_sync_request *req = param;
req->result = result;
complete(&req->completion);
}
int pcf50633_adc_sync_read(struct pcf50633 *pcf, int mux, int avg)
{
struct pcf50633_adc_sync_request req;
int ret;
init_completion(&req.completion);
ret = pcf50633_adc_async_read(pcf, mux, avg,
pcf50633_adc_sync_read_callback, &req);
if (ret)
return ret;
wait_for_completion(&req.completion);
return req.result;
}
EXPORT_SYMBOL_GPL(pcf50633_adc_sync_read);
int pcf50633_adc_async_read(struct pcf50633 *pcf, int mux, int avg,
void (*callback)(struct pcf50633 *, void *, int),
void *callback_param)
{
struct pcf50633_adc_request *req;
int ret;
/* req is freed when the result is ready, in interrupt handler */
req = kmalloc(sizeof(*req), GFP_KERNEL);
if (!req)
return -ENOMEM;
req->mux = mux;
req->avg = avg;
req->callback = callback;
req->callback_param = callback_param;
ret = adc_enqueue_request(pcf, req);
if (ret)
kfree(req);
return ret;
}
EXPORT_SYMBOL_GPL(pcf50633_adc_async_read);
static int adc_result(struct pcf50633 *pcf)
{
u8 adcs1, adcs3;
u16 result;
adcs1 = pcf50633_reg_read(pcf, PCF50633_REG_ADCS1);
adcs3 = pcf50633_reg_read(pcf, PCF50633_REG_ADCS3);
result = (adcs1 << 2) | (adcs3 & PCF50633_ADCS3_ADCDAT1L_MASK);
dev_dbg(pcf->dev, "adc result = %d\n", result);
return result;
}
static void pcf50633_adc_irq(int irq, void *data)
{
struct pcf50633_adc *adc = data;
struct pcf50633 *pcf = adc->pcf;
struct pcf50633_adc_request *req;
int head, res;
mutex_lock(&adc->queue_mutex);
head = adc->queue_head;
req = adc->queue[head];
if (WARN_ON(!req)) {
dev_err(pcf->dev, "pcf50633-adc irq: ADC queue empty!\n");
mutex_unlock(&adc->queue_mutex);
return;
}
adc->queue[head] = NULL;
adc->queue_head = (head + 1) &
(PCF50633_MAX_ADC_FIFO_DEPTH - 1);
res = adc_result(pcf);
trigger_next_adc_job_if_any(pcf);
mutex_unlock(&adc->queue_mutex);
req->callback(pcf, req->callback_param, res);
kfree(req);
}
static int pcf50633_adc_probe(struct platform_device *pdev)
{
struct pcf50633_adc *adc;
adc = devm_kzalloc(&pdev->dev, sizeof(*adc), GFP_KERNEL);
if (!adc)
return -ENOMEM;
adc->pcf = dev_to_pcf50633(pdev->dev.parent);
platform_set_drvdata(pdev, adc);
pcf50633_register_irq(adc->pcf, PCF50633_IRQ_ADCRDY,
pcf50633_adc_irq, adc);
mutex_init(&adc->queue_mutex);
return 0;
}
static void pcf50633_adc_remove(struct platform_device *pdev)
{
struct pcf50633_adc *adc = platform_get_drvdata(pdev);
int i, head;
pcf50633_free_irq(adc->pcf, PCF50633_IRQ_ADCRDY);
mutex_lock(&adc->queue_mutex);
head = adc->queue_head;
if (WARN_ON(adc->queue[head]))
dev_err(adc->pcf->dev,
"adc driver removed with request pending\n");
for (i = 0; i < PCF50633_MAX_ADC_FIFO_DEPTH; i++)
kfree(adc->queue[i]);
mutex_unlock(&adc->queue_mutex);
}
static struct platform_driver pcf50633_adc_driver = {
.driver = {
.name = "pcf50633-adc",
},
.probe = pcf50633_adc_probe,
.remove = pcf50633_adc_remove,
};
module_platform_driver(pcf50633_adc_driver);
MODULE_AUTHOR("Balaji Rao <balajirrao@openmoko.org>");
MODULE_DESCRIPTION("PCF50633 adc driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:pcf50633-adc");

View File

@ -1,304 +0,0 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/* NXP PCF50633 Power Management Unit (PMU) driver
*
* (C) 2006-2008 by Openmoko, Inc.
* Author: Harald Welte <laforge@openmoko.org>
* Balaji Rao <balajirrao@openmoko.org>
* All rights reserved.
*/
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/sysfs.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/interrupt.h>
#include <linux/workqueue.h>
#include <linux/platform_device.h>
#include <linux/i2c.h>
#include <linux/pm.h>
#include <linux/slab.h>
#include <linux/regmap.h>
#include <linux/err.h>
#include <linux/mfd/pcf50633/core.h>
/* Read a block of up to 32 regs */
int pcf50633_read_block(struct pcf50633 *pcf, u8 reg,
int nr_regs, u8 *data)
{
int ret;
ret = regmap_raw_read(pcf->regmap, reg, data, nr_regs);
if (ret != 0)
return ret;
return nr_regs;
}
EXPORT_SYMBOL_GPL(pcf50633_read_block);
/* Write a block of up to 32 regs */
int pcf50633_write_block(struct pcf50633 *pcf , u8 reg,
int nr_regs, u8 *data)
{
return regmap_raw_write(pcf->regmap, reg, data, nr_regs);
}
EXPORT_SYMBOL_GPL(pcf50633_write_block);
u8 pcf50633_reg_read(struct pcf50633 *pcf, u8 reg)
{
unsigned int val;
int ret;
ret = regmap_read(pcf->regmap, reg, &val);
if (ret < 0)
return -1;
return val;
}
EXPORT_SYMBOL_GPL(pcf50633_reg_read);
int pcf50633_reg_write(struct pcf50633 *pcf, u8 reg, u8 val)
{
return regmap_write(pcf->regmap, reg, val);
}
EXPORT_SYMBOL_GPL(pcf50633_reg_write);
int pcf50633_reg_set_bit_mask(struct pcf50633 *pcf, u8 reg, u8 mask, u8 val)
{
return regmap_update_bits(pcf->regmap, reg, mask, val);
}
EXPORT_SYMBOL_GPL(pcf50633_reg_set_bit_mask);
int pcf50633_reg_clear_bits(struct pcf50633 *pcf, u8 reg, u8 val)
{
return regmap_update_bits(pcf->regmap, reg, val, 0);
}
EXPORT_SYMBOL_GPL(pcf50633_reg_clear_bits);
/* sysfs attributes */
static ssize_t dump_regs_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct pcf50633 *pcf = dev_get_drvdata(dev);
u8 dump[16];
int n, n1, idx = 0;
char *buf1 = buf;
static u8 address_no_read[] = { /* must be ascending */
PCF50633_REG_INT1,
PCF50633_REG_INT2,
PCF50633_REG_INT3,
PCF50633_REG_INT4,
PCF50633_REG_INT5,
0 /* terminator */
};
for (n = 0; n < 256; n += sizeof(dump)) {
for (n1 = 0; n1 < sizeof(dump); n1++)
if (n == address_no_read[idx]) {
idx++;
dump[n1] = 0x00;
} else
dump[n1] = pcf50633_reg_read(pcf, n + n1);
buf1 += sprintf(buf1, "%*ph\n", (int)sizeof(dump), dump);
}
return buf1 - buf;
}
static DEVICE_ATTR_ADMIN_RO(dump_regs);
static ssize_t resume_reason_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct pcf50633 *pcf = dev_get_drvdata(dev);
int n;
n = sprintf(buf, "%02x%02x%02x%02x%02x\n",
pcf->resume_reason[0],
pcf->resume_reason[1],
pcf->resume_reason[2],
pcf->resume_reason[3],
pcf->resume_reason[4]);
return n;
}
static DEVICE_ATTR_ADMIN_RO(resume_reason);
static struct attribute *pcf_sysfs_entries[] = {
&dev_attr_dump_regs.attr,
&dev_attr_resume_reason.attr,
NULL,
};
static struct attribute_group pcf_attr_group = {
.name = NULL, /* put in device directory */
.attrs = pcf_sysfs_entries,
};
static void
pcf50633_client_dev_register(struct pcf50633 *pcf, const char *name,
struct platform_device **pdev)
{
int ret;
*pdev = platform_device_alloc(name, -1);
if (!*pdev) {
dev_err(pcf->dev, "Failed to allocate %s\n", name);
return;
}
(*pdev)->dev.parent = pcf->dev;
ret = platform_device_add(*pdev);
if (ret) {
dev_err(pcf->dev, "Failed to register %s: %d\n", name, ret);
platform_device_put(*pdev);
*pdev = NULL;
}
}
static const struct regmap_config pcf50633_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
};
static int pcf50633_probe(struct i2c_client *client)
{
struct pcf50633 *pcf;
struct platform_device *pdev;
struct pcf50633_platform_data *pdata = dev_get_platdata(&client->dev);
int i, j, ret;
int version, variant;
if (!client->irq) {
dev_err(&client->dev, "Missing IRQ\n");
return -ENOENT;
}
pcf = devm_kzalloc(&client->dev, sizeof(*pcf), GFP_KERNEL);
if (!pcf)
return -ENOMEM;
i2c_set_clientdata(client, pcf);
pcf->dev = &client->dev;
pcf->pdata = pdata;
mutex_init(&pcf->lock);
pcf->regmap = devm_regmap_init_i2c(client, &pcf50633_regmap_config);
if (IS_ERR(pcf->regmap)) {
ret = PTR_ERR(pcf->regmap);
dev_err(pcf->dev, "Failed to allocate register map: %d\n", ret);
return ret;
}
version = pcf50633_reg_read(pcf, 0);
variant = pcf50633_reg_read(pcf, 1);
if (version < 0 || variant < 0) {
dev_err(pcf->dev, "Unable to probe pcf50633\n");
ret = -ENODEV;
return ret;
}
dev_info(pcf->dev, "Probed device version %d variant %d\n",
version, variant);
pcf50633_irq_init(pcf, client->irq);
/* Create sub devices */
pcf50633_client_dev_register(pcf, "pcf50633-input", &pcf->input_pdev);
pcf50633_client_dev_register(pcf, "pcf50633-rtc", &pcf->rtc_pdev);
pcf50633_client_dev_register(pcf, "pcf50633-mbc", &pcf->mbc_pdev);
pcf50633_client_dev_register(pcf, "pcf50633-adc", &pcf->adc_pdev);
pcf50633_client_dev_register(pcf, "pcf50633-backlight", &pcf->bl_pdev);
for (i = 0; i < PCF50633_NUM_REGULATORS; i++) {
pdev = platform_device_alloc("pcf50633-regulator", i);
if (!pdev) {
ret = -ENOMEM;
goto err2;
}
pdev->dev.parent = pcf->dev;
ret = platform_device_add_data(pdev, &pdata->reg_init_data[i],
sizeof(pdata->reg_init_data[i]));
if (ret)
goto err;
ret = platform_device_add(pdev);
if (ret)
goto err;
pcf->regulator_pdev[i] = pdev;
}
ret = sysfs_create_group(&client->dev.kobj, &pcf_attr_group);
if (ret)
dev_warn(pcf->dev, "error creating sysfs entries\n");
if (pdata->probe_done)
pdata->probe_done(pcf);
return 0;
err:
platform_device_put(pdev);
err2:
for (j = 0; j < i; j++)
platform_device_put(pcf->regulator_pdev[j]);
return ret;
}
static void pcf50633_remove(struct i2c_client *client)
{
struct pcf50633 *pcf = i2c_get_clientdata(client);
int i;
sysfs_remove_group(&client->dev.kobj, &pcf_attr_group);
pcf50633_irq_free(pcf);
platform_device_unregister(pcf->input_pdev);
platform_device_unregister(pcf->rtc_pdev);
platform_device_unregister(pcf->mbc_pdev);
platform_device_unregister(pcf->adc_pdev);
platform_device_unregister(pcf->bl_pdev);
for (i = 0; i < PCF50633_NUM_REGULATORS; i++)
platform_device_unregister(pcf->regulator_pdev[i]);
}
static const struct i2c_device_id pcf50633_id_table[] = {
{"pcf50633", 0x73},
{/* end of list */}
};
MODULE_DEVICE_TABLE(i2c, pcf50633_id_table);
static struct i2c_driver pcf50633_driver = {
.driver = {
.name = "pcf50633",
.pm = pm_sleep_ptr(&pcf50633_pm),
},
.id_table = pcf50633_id_table,
.probe = pcf50633_probe,
.remove = pcf50633_remove,
};
static int __init pcf50633_init(void)
{
return i2c_add_driver(&pcf50633_driver);
}
static void __exit pcf50633_exit(void)
{
i2c_del_driver(&pcf50633_driver);
}
MODULE_DESCRIPTION("I2C chip driver for NXP PCF50633 PMU");
MODULE_AUTHOR("Harald Welte <laforge@openmoko.org>");
MODULE_LICENSE("GPL");
subsys_initcall(pcf50633_init);
module_exit(pcf50633_exit);

View File

@ -1,92 +0,0 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/* NXP PCF50633 GPIO Driver
*
* (C) 2006-2008 by Openmoko, Inc.
* Author: Balaji Rao <balajirrao@openmoko.org>
* All rights reserved.
*
* Broken down from monstrous PCF50633 driver mainly by
* Harald Welte, Andy Green and Werner Almesberger
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mfd/pcf50633/core.h>
#include <linux/mfd/pcf50633/gpio.h>
#include <linux/mfd/pcf50633/pmic.h>
static const u8 pcf50633_regulator_registers[PCF50633_NUM_REGULATORS] = {
[PCF50633_REGULATOR_AUTO] = PCF50633_REG_AUTOOUT,
[PCF50633_REGULATOR_DOWN1] = PCF50633_REG_DOWN1OUT,
[PCF50633_REGULATOR_DOWN2] = PCF50633_REG_DOWN2OUT,
[PCF50633_REGULATOR_MEMLDO] = PCF50633_REG_MEMLDOOUT,
[PCF50633_REGULATOR_LDO1] = PCF50633_REG_LDO1OUT,
[PCF50633_REGULATOR_LDO2] = PCF50633_REG_LDO2OUT,
[PCF50633_REGULATOR_LDO3] = PCF50633_REG_LDO3OUT,
[PCF50633_REGULATOR_LDO4] = PCF50633_REG_LDO4OUT,
[PCF50633_REGULATOR_LDO5] = PCF50633_REG_LDO5OUT,
[PCF50633_REGULATOR_LDO6] = PCF50633_REG_LDO6OUT,
[PCF50633_REGULATOR_HCLDO] = PCF50633_REG_HCLDOOUT,
};
int pcf50633_gpio_set(struct pcf50633 *pcf, int gpio, u8 val)
{
u8 reg;
reg = gpio - PCF50633_GPIO1 + PCF50633_REG_GPIO1CFG;
return pcf50633_reg_set_bit_mask(pcf, reg, 0x07, val);
}
EXPORT_SYMBOL_GPL(pcf50633_gpio_set);
u8 pcf50633_gpio_get(struct pcf50633 *pcf, int gpio)
{
u8 reg, val;
reg = gpio - PCF50633_GPIO1 + PCF50633_REG_GPIO1CFG;
val = pcf50633_reg_read(pcf, reg) & 0x07;
return val;
}
EXPORT_SYMBOL_GPL(pcf50633_gpio_get);
int pcf50633_gpio_invert_set(struct pcf50633 *pcf, int gpio, int invert)
{
u8 val, reg;
reg = gpio - PCF50633_GPIO1 + PCF50633_REG_GPIO1CFG;
val = !!invert << 3;
return pcf50633_reg_set_bit_mask(pcf, reg, 1 << 3, val);
}
EXPORT_SYMBOL_GPL(pcf50633_gpio_invert_set);
int pcf50633_gpio_invert_get(struct pcf50633 *pcf, int gpio)
{
u8 reg, val;
reg = gpio - PCF50633_GPIO1 + PCF50633_REG_GPIO1CFG;
val = pcf50633_reg_read(pcf, reg);
return val & (1 << 3);
}
EXPORT_SYMBOL_GPL(pcf50633_gpio_invert_get);
int pcf50633_gpio_power_supply_set(struct pcf50633 *pcf,
int gpio, int regulator, int on)
{
u8 reg, val, mask;
/* the *ENA register is always one after the *OUT register */
reg = pcf50633_regulator_registers[regulator] + 1;
val = !!on << (gpio - PCF50633_GPIO1);
mask = 1 << (gpio - PCF50633_GPIO1);
return pcf50633_reg_set_bit_mask(pcf, reg, mask, val);
}
EXPORT_SYMBOL_GPL(pcf50633_gpio_power_supply_set);
MODULE_DESCRIPTION("NXP PCF50633 GPIO Driver");
MODULE_LICENSE("GPL");

View File

@ -1,312 +0,0 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/* NXP PCF50633 Power Management Unit (PMU) driver
*
* (C) 2006-2008 by Openmoko, Inc.
* Author: Harald Welte <laforge@openmoko.org>
* Balaji Rao <balajirrao@openmoko.org>
* All rights reserved.
*/
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/mutex.h>
#include <linux/export.h>
#include <linux/slab.h>
#include <linux/mfd/pcf50633/core.h>
#include <linux/mfd/pcf50633/mbc.h>
int pcf50633_register_irq(struct pcf50633 *pcf, int irq,
void (*handler) (int, void *), void *data)
{
if (irq < 0 || irq >= PCF50633_NUM_IRQ || !handler)
return -EINVAL;
if (WARN_ON(pcf->irq_handler[irq].handler))
return -EBUSY;
mutex_lock(&pcf->lock);
pcf->irq_handler[irq].handler = handler;
pcf->irq_handler[irq].data = data;
mutex_unlock(&pcf->lock);
return 0;
}
EXPORT_SYMBOL_GPL(pcf50633_register_irq);
int pcf50633_free_irq(struct pcf50633 *pcf, int irq)
{
if (irq < 0 || irq >= PCF50633_NUM_IRQ)
return -EINVAL;
mutex_lock(&pcf->lock);
pcf->irq_handler[irq].handler = NULL;
mutex_unlock(&pcf->lock);
return 0;
}
EXPORT_SYMBOL_GPL(pcf50633_free_irq);
static int __pcf50633_irq_mask_set(struct pcf50633 *pcf, int irq, u8 mask)
{
u8 reg, bit;
int idx;
idx = irq >> 3;
reg = PCF50633_REG_INT1M + idx;
bit = 1 << (irq & 0x07);
pcf50633_reg_set_bit_mask(pcf, reg, bit, mask ? bit : 0);
mutex_lock(&pcf->lock);
if (mask)
pcf->mask_regs[idx] |= bit;
else
pcf->mask_regs[idx] &= ~bit;
mutex_unlock(&pcf->lock);
return 0;
}
int pcf50633_irq_mask(struct pcf50633 *pcf, int irq)
{
dev_dbg(pcf->dev, "Masking IRQ %d\n", irq);
return __pcf50633_irq_mask_set(pcf, irq, 1);
}
EXPORT_SYMBOL_GPL(pcf50633_irq_mask);
int pcf50633_irq_unmask(struct pcf50633 *pcf, int irq)
{
dev_dbg(pcf->dev, "Unmasking IRQ %d\n", irq);
return __pcf50633_irq_mask_set(pcf, irq, 0);
}
EXPORT_SYMBOL_GPL(pcf50633_irq_unmask);
int pcf50633_irq_mask_get(struct pcf50633 *pcf, int irq)
{
u8 reg, bits;
reg = irq >> 3;
bits = 1 << (irq & 0x07);
return pcf->mask_regs[reg] & bits;
}
EXPORT_SYMBOL_GPL(pcf50633_irq_mask_get);
static void pcf50633_irq_call_handler(struct pcf50633 *pcf, int irq)
{
if (pcf->irq_handler[irq].handler)
pcf->irq_handler[irq].handler(irq, pcf->irq_handler[irq].data);
}
/* Maximum amount of time ONKEY is held before emergency action is taken */
#define PCF50633_ONKEY1S_TIMEOUT 8
static irqreturn_t pcf50633_irq(int irq, void *data)
{
struct pcf50633 *pcf = data;
int ret, i, j;
u8 pcf_int[5], chgstat;
/* Read the 5 INT regs in one transaction */
ret = pcf50633_read_block(pcf, PCF50633_REG_INT1,
ARRAY_SIZE(pcf_int), pcf_int);
if (ret != ARRAY_SIZE(pcf_int)) {
dev_err(pcf->dev, "Error reading INT registers\n");
/*
* If this doesn't ACK the interrupt to the chip, we'll be
* called once again as we're level triggered.
*/
goto out;
}
/* defeat 8s death from lowsys on A5 */
pcf50633_reg_write(pcf, PCF50633_REG_OOCSHDWN, 0x04);
/* We immediately read the usb and adapter status. We thus make sure
* only of USBINS/USBREM IRQ handlers are called */
if (pcf_int[0] & (PCF50633_INT1_USBINS | PCF50633_INT1_USBREM)) {
chgstat = pcf50633_reg_read(pcf, PCF50633_REG_MBCS2);
if (chgstat & (0x3 << 4))
pcf_int[0] &= ~PCF50633_INT1_USBREM;
else
pcf_int[0] &= ~PCF50633_INT1_USBINS;
}
/* Make sure only one of ADPINS or ADPREM is set */
if (pcf_int[0] & (PCF50633_INT1_ADPINS | PCF50633_INT1_ADPREM)) {
chgstat = pcf50633_reg_read(pcf, PCF50633_REG_MBCS2);
if (chgstat & (0x3 << 4))
pcf_int[0] &= ~PCF50633_INT1_ADPREM;
else
pcf_int[0] &= ~PCF50633_INT1_ADPINS;
}
dev_dbg(pcf->dev, "INT1=0x%02x INT2=0x%02x INT3=0x%02x "
"INT4=0x%02x INT5=0x%02x\n", pcf_int[0],
pcf_int[1], pcf_int[2], pcf_int[3], pcf_int[4]);
/* Some revisions of the chip don't have a 8s standby mode on
* ONKEY1S press. We try to manually do it in such cases. */
if ((pcf_int[0] & PCF50633_INT1_SECOND) && pcf->onkey1s_held) {
dev_info(pcf->dev, "ONKEY1S held for %d secs\n",
pcf->onkey1s_held);
if (pcf->onkey1s_held++ == PCF50633_ONKEY1S_TIMEOUT)
if (pcf->pdata->force_shutdown)
pcf->pdata->force_shutdown(pcf);
}
if (pcf_int[2] & PCF50633_INT3_ONKEY1S) {
dev_info(pcf->dev, "ONKEY1S held\n");
pcf->onkey1s_held = 1 ;
/* Unmask IRQ_SECOND */
pcf50633_reg_clear_bits(pcf, PCF50633_REG_INT1M,
PCF50633_INT1_SECOND);
/* Unmask IRQ_ONKEYR */
pcf50633_reg_clear_bits(pcf, PCF50633_REG_INT2M,
PCF50633_INT2_ONKEYR);
}
if ((pcf_int[1] & PCF50633_INT2_ONKEYR) && pcf->onkey1s_held) {
pcf->onkey1s_held = 0;
/* Mask SECOND and ONKEYR interrupts */
if (pcf->mask_regs[0] & PCF50633_INT1_SECOND)
pcf50633_reg_set_bit_mask(pcf,
PCF50633_REG_INT1M,
PCF50633_INT1_SECOND,
PCF50633_INT1_SECOND);
if (pcf->mask_regs[1] & PCF50633_INT2_ONKEYR)
pcf50633_reg_set_bit_mask(pcf,
PCF50633_REG_INT2M,
PCF50633_INT2_ONKEYR,
PCF50633_INT2_ONKEYR);
}
/* Have we just resumed ? */
if (pcf->is_suspended) {
pcf->is_suspended = 0;
/* Set the resume reason filtering out non resumers */
for (i = 0; i < ARRAY_SIZE(pcf_int); i++)
pcf->resume_reason[i] = pcf_int[i] &
pcf->pdata->resumers[i];
/* Make sure we don't pass on any ONKEY events to
* userspace now */
pcf_int[1] &= ~(PCF50633_INT2_ONKEYR | PCF50633_INT2_ONKEYF);
}
for (i = 0; i < ARRAY_SIZE(pcf_int); i++) {
/* Unset masked interrupts */
pcf_int[i] &= ~pcf->mask_regs[i];
for (j = 0; j < 8 ; j++)
if (pcf_int[i] & (1 << j))
pcf50633_irq_call_handler(pcf, (i * 8) + j);
}
out:
return IRQ_HANDLED;
}
static int pcf50633_suspend(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct pcf50633 *pcf = i2c_get_clientdata(client);
int ret;
int i;
u8 res[5];
/* Make sure our interrupt handlers are not called
* henceforth */
disable_irq(pcf->irq);
/* Save the masks */
ret = pcf50633_read_block(pcf, PCF50633_REG_INT1M,
ARRAY_SIZE(pcf->suspend_irq_masks),
pcf->suspend_irq_masks);
if (ret < 0) {
dev_err(pcf->dev, "error saving irq masks\n");
goto out;
}
/* Write wakeup irq masks */
for (i = 0; i < ARRAY_SIZE(res); i++)
res[i] = ~pcf->pdata->resumers[i];
ret = pcf50633_write_block(pcf, PCF50633_REG_INT1M,
ARRAY_SIZE(res), &res[0]);
if (ret < 0) {
dev_err(pcf->dev, "error writing wakeup irq masks\n");
goto out;
}
pcf->is_suspended = 1;
out:
return ret;
}
static int pcf50633_resume(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct pcf50633 *pcf = i2c_get_clientdata(client);
int ret;
/* Write the saved mask registers */
ret = pcf50633_write_block(pcf, PCF50633_REG_INT1M,
ARRAY_SIZE(pcf->suspend_irq_masks),
pcf->suspend_irq_masks);
if (ret < 0)
dev_err(pcf->dev, "Error restoring saved suspend masks\n");
enable_irq(pcf->irq);
return ret;
}
EXPORT_GPL_SIMPLE_DEV_PM_OPS(pcf50633_pm, pcf50633_suspend, pcf50633_resume);
int pcf50633_irq_init(struct pcf50633 *pcf, int irq)
{
int ret;
pcf->irq = irq;
/* Enable all interrupts except RTC SECOND */
pcf->mask_regs[0] = 0x80;
pcf50633_reg_write(pcf, PCF50633_REG_INT1M, pcf->mask_regs[0]);
pcf50633_reg_write(pcf, PCF50633_REG_INT2M, 0x00);
pcf50633_reg_write(pcf, PCF50633_REG_INT3M, 0x00);
pcf50633_reg_write(pcf, PCF50633_REG_INT4M, 0x00);
pcf50633_reg_write(pcf, PCF50633_REG_INT5M, 0x00);
ret = request_threaded_irq(irq, NULL, pcf50633_irq,
IRQF_TRIGGER_LOW | IRQF_ONESHOT,
"pcf50633", pcf);
if (ret)
dev_err(pcf->dev, "Failed to request IRQ %d\n", ret);
if (enable_irq_wake(irq) < 0)
dev_err(pcf->dev, "IRQ %u cannot be enabled as wake-up source"
"in this hardware revision", irq);
return ret;
}
void pcf50633_irq_free(struct pcf50633 *pcf)
{
free_irq(pcf->irq, pcf);
}

View File

@ -158,9 +158,9 @@ int qnap_mcu_exec(struct qnap_mcu *mcu,
mutex_lock(&mcu->bus_lock);
reply->data = rx,
reply->length = length,
reply->received = 0,
reply->data = rx;
reply->length = length;
reply->received = 0;
reinit_completion(&reply->done);
qnap_mcu_write(mcu, cmd_data, cmd_data_size);

View File

@ -83,6 +83,11 @@ static const struct mfd_cell s2mpu02_devs[] = {
{ .name = "s2mpu02-regulator", },
};
static const struct mfd_cell s2mpu05_devs[] = {
{ .name = "s2mpu05-regulator", },
{ .name = "s2mps15-rtc", },
};
static const struct of_device_id sec_dt_match[] = {
{
.compatible = "samsung,s5m8767-pmic",
@ -108,6 +113,9 @@ static const struct of_device_id sec_dt_match[] = {
}, {
.compatible = "samsung,s2mpu02-pmic",
.data = (void *)S2MPU02,
}, {
.compatible = "samsung,s2mpu05-pmic",
.data = (void *)S2MPU05,
}, {
/* Sentinel */
},
@ -374,6 +382,10 @@ static int sec_pmic_probe(struct i2c_client *i2c)
sec_devs = s2mpu02_devs;
num_sec_devs = ARRAY_SIZE(s2mpu02_devs);
break;
case S2MPU05:
sec_devs = s2mpu05_devs;
num_sec_devs = ARRAY_SIZE(s2mpu05_devs);
break;
default:
dev_err(&i2c->dev, "Unsupported device type (%lu)\n",
sec_pmic->device_type);

View File

@ -14,6 +14,7 @@
#include <linux/mfd/samsung/s2mps11.h>
#include <linux/mfd/samsung/s2mps14.h>
#include <linux/mfd/samsung/s2mpu02.h>
#include <linux/mfd/samsung/s2mpu05.h>
#include <linux/mfd/samsung/s5m8767.h>
static const struct regmap_irq s2mps11_irqs[] = {
@ -225,6 +226,26 @@ static const struct regmap_irq s2mpu02_irqs[] = {
},
};
static const struct regmap_irq s2mpu05_irqs[] = {
REGMAP_IRQ_REG(S2MPU05_IRQ_PWRONF, 0, S2MPU05_IRQ_PWRONF_MASK),
REGMAP_IRQ_REG(S2MPU05_IRQ_PWRONR, 0, S2MPU05_IRQ_PWRONR_MASK),
REGMAP_IRQ_REG(S2MPU05_IRQ_JIGONBF, 0, S2MPU05_IRQ_JIGONBF_MASK),
REGMAP_IRQ_REG(S2MPU05_IRQ_JIGONBR, 0, S2MPU05_IRQ_JIGONBR_MASK),
REGMAP_IRQ_REG(S2MPU05_IRQ_ACOKF, 0, S2MPU05_IRQ_ACOKF_MASK),
REGMAP_IRQ_REG(S2MPU05_IRQ_ACOKR, 0, S2MPU05_IRQ_ACOKR_MASK),
REGMAP_IRQ_REG(S2MPU05_IRQ_PWRON1S, 0, S2MPU05_IRQ_PWRON1S_MASK),
REGMAP_IRQ_REG(S2MPU05_IRQ_MRB, 0, S2MPU05_IRQ_MRB_MASK),
REGMAP_IRQ_REG(S2MPU05_IRQ_RTC60S, 1, S2MPU05_IRQ_RTC60S_MASK),
REGMAP_IRQ_REG(S2MPU05_IRQ_RTCA1, 1, S2MPU05_IRQ_RTCA1_MASK),
REGMAP_IRQ_REG(S2MPU05_IRQ_RTCA0, 1, S2MPU05_IRQ_RTCA0_MASK),
REGMAP_IRQ_REG(S2MPU05_IRQ_SMPL, 1, S2MPU05_IRQ_SMPL_MASK),
REGMAP_IRQ_REG(S2MPU05_IRQ_RTC1S, 1, S2MPU05_IRQ_RTC1S_MASK),
REGMAP_IRQ_REG(S2MPU05_IRQ_WTSR, 1, S2MPU05_IRQ_WTSR_MASK),
REGMAP_IRQ_REG(S2MPU05_IRQ_INT120C, 2, S2MPU05_IRQ_INT120C_MASK),
REGMAP_IRQ_REG(S2MPU05_IRQ_INT140C, 2, S2MPU05_IRQ_INT140C_MASK),
REGMAP_IRQ_REG(S2MPU05_IRQ_TSD, 2, S2MPU05_IRQ_TSD_MASK),
};
static const struct regmap_irq s5m8767_irqs[] = {
[S5M8767_IRQ_PWRR] = {
.reg_offset = 0,
@ -339,6 +360,16 @@ static const struct regmap_irq_chip s2mpu02_irq_chip = {
.ack_base = S2MPU02_REG_INT1,
};
static const struct regmap_irq_chip s2mpu05_irq_chip = {
.name = "s2mpu05",
.irqs = s2mpu05_irqs,
.num_irqs = ARRAY_SIZE(s2mpu05_irqs),
.num_regs = 3,
.status_base = S2MPU05_REG_INT1,
.mask_base = S2MPU05_REG_INT1M,
.ack_base = S2MPU05_REG_INT1,
};
static const struct regmap_irq_chip s5m8767_irq_chip = {
.name = "s5m8767",
.irqs = s5m8767_irqs,
@ -383,6 +414,9 @@ int sec_irq_init(struct sec_pmic_dev *sec_pmic)
case S2MPU02:
sec_irq_chip = &s2mpu02_irq_chip;
break;
case S2MPU05:
sec_irq_chip = &s2mpu05_irq_chip;
break;
default:
dev_err(sec_pmic->dev, "Unknown device type %lu\n",
sec_pmic->device_type);

View File

@ -83,11 +83,22 @@ static const struct simple_mfd_data maxim_max5970 = {
.mfd_cell_size = ARRAY_SIZE(max5970_cells),
};
static const struct mfd_cell max77705_sensor_cells[] = {
{ .name = "max77705-battery" },
{ .name = "max77705-hwmon", },
};
static const struct simple_mfd_data maxim_mon_max77705 = {
.mfd_cell = max77705_sensor_cells,
.mfd_cell_size = ARRAY_SIZE(max77705_sensor_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_max5970},
{ .compatible = "maxim,max5978", .data = &maxim_max5970},
{ .compatible = "maxim,max77705-battery", .data = &maxim_mon_max77705},
{}
};
MODULE_DEVICE_TABLE(of, simple_mfd_i2c_of_match);

View File

@ -920,7 +920,7 @@ static void sm501_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
{
struct sm501_gpio_chip *smchip = gpiochip_get_data(chip);
struct sm501_gpio *smgpio = smchip->ourgpio;
unsigned long bit = 1 << offset;
unsigned long bit = BIT(offset);
void __iomem *regs = smchip->regbase;
unsigned long save;
unsigned long val;
@ -946,7 +946,7 @@ static int sm501_gpio_input(struct gpio_chip *chip, unsigned offset)
struct sm501_gpio_chip *smchip = gpiochip_get_data(chip);
struct sm501_gpio *smgpio = smchip->ourgpio;
void __iomem *regs = smchip->regbase;
unsigned long bit = 1 << offset;
unsigned long bit = BIT(offset);
unsigned long save;
unsigned long ddr;
@ -971,7 +971,7 @@ static int sm501_gpio_output(struct gpio_chip *chip,
{
struct sm501_gpio_chip *smchip = gpiochip_get_data(chip);
struct sm501_gpio *smgpio = smchip->ourgpio;
unsigned long bit = 1 << offset;
unsigned long bit = BIT(offset);
void __iomem *regs = smchip->regbase;
unsigned long save;
unsigned long val;

View File

@ -1,645 +0,0 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* STA2x11 mfd for GPIO, SCTL and APBREG
*
* Copyright (c) 2009-2011 Wind River Systems, Inc.
* Copyright (c) 2011 ST Microelectronics (Alessandro Rubini, Davide Ciminaghi)
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/export.h>
#include <linux/spinlock.h>
#include <linux/errno.h>
#include <linux/device.h>
#include <linux/slab.h>
#include <linux/list.h>
#include <linux/io.h>
#include <linux/ioport.h>
#include <linux/pci.h>
#include <linux/seq_file.h>
#include <linux/platform_device.h>
#include <linux/mfd/core.h>
#include <linux/mfd/sta2x11-mfd.h>
#include <linux/regmap.h>
#include <asm/sta2x11.h>
static inline int __reg_within_range(unsigned int r,
unsigned int start,
unsigned int end)
{
return ((r >= start) && (r <= end));
}
/* This describes STA2X11 MFD chip for us, we may have several */
struct sta2x11_mfd {
struct sta2x11_instance *instance;
struct regmap *regmap[sta2x11_n_mfd_plat_devs];
spinlock_t lock[sta2x11_n_mfd_plat_devs];
struct list_head list;
void __iomem *regs[sta2x11_n_mfd_plat_devs];
};
static LIST_HEAD(sta2x11_mfd_list);
/* Three functions to act on the list */
static struct sta2x11_mfd *sta2x11_mfd_find(struct pci_dev *pdev)
{
struct sta2x11_instance *instance;
struct sta2x11_mfd *mfd;
if (!pdev && !list_empty(&sta2x11_mfd_list)) {
pr_warn("%s: Unspecified device, using first instance\n",
__func__);
return list_entry(sta2x11_mfd_list.next,
struct sta2x11_mfd, list);
}
instance = sta2x11_get_instance(pdev);
if (!instance)
return NULL;
list_for_each_entry(mfd, &sta2x11_mfd_list, list) {
if (mfd->instance == instance)
return mfd;
}
return NULL;
}
static int sta2x11_mfd_add(struct pci_dev *pdev, gfp_t flags)
{
int i;
struct sta2x11_mfd *mfd = sta2x11_mfd_find(pdev);
struct sta2x11_instance *instance;
if (mfd)
return -EBUSY;
instance = sta2x11_get_instance(pdev);
if (!instance)
return -EINVAL;
mfd = kzalloc(sizeof(*mfd), flags);
if (!mfd)
return -ENOMEM;
INIT_LIST_HEAD(&mfd->list);
for (i = 0; i < ARRAY_SIZE(mfd->lock); i++)
spin_lock_init(&mfd->lock[i]);
mfd->instance = instance;
list_add(&mfd->list, &sta2x11_mfd_list);
return 0;
}
/* This function is exported and is not expected to fail */
u32 __sta2x11_mfd_mask(struct pci_dev *pdev, u32 reg, u32 mask, u32 val,
enum sta2x11_mfd_plat_dev index)
{
struct sta2x11_mfd *mfd = sta2x11_mfd_find(pdev);
u32 r;
unsigned long flags;
void __iomem *regs;
if (!mfd) {
dev_warn(&pdev->dev, ": can't access sctl regs\n");
return 0;
}
regs = mfd->regs[index];
if (!regs) {
dev_warn(&pdev->dev, ": system ctl not initialized\n");
return 0;
}
spin_lock_irqsave(&mfd->lock[index], flags);
r = readl(regs + reg);
r &= ~mask;
r |= val;
if (mask)
writel(r, regs + reg);
spin_unlock_irqrestore(&mfd->lock[index], flags);
return r;
}
EXPORT_SYMBOL(__sta2x11_mfd_mask);
int sta2x11_mfd_get_regs_data(struct platform_device *dev,
enum sta2x11_mfd_plat_dev index,
void __iomem **regs,
spinlock_t **lock)
{
struct pci_dev *pdev = *(struct pci_dev **)dev_get_platdata(&dev->dev);
struct sta2x11_mfd *mfd;
if (!pdev)
return -ENODEV;
mfd = sta2x11_mfd_find(pdev);
if (!mfd)
return -ENODEV;
if (index >= sta2x11_n_mfd_plat_devs)
return -ENODEV;
*regs = mfd->regs[index];
*lock = &mfd->lock[index];
pr_debug("%s %d *regs = %p\n", __func__, __LINE__, *regs);
return *regs ? 0 : -ENODEV;
}
EXPORT_SYMBOL(sta2x11_mfd_get_regs_data);
/*
* Special sta2x11-mfd regmap lock/unlock functions
*/
static void sta2x11_regmap_lock(void *__lock)
{
spinlock_t *lock = __lock;
spin_lock(lock);
}
static void sta2x11_regmap_unlock(void *__lock)
{
spinlock_t *lock = __lock;
spin_unlock(lock);
}
/* OTP (one time programmable registers do not require locking */
static void sta2x11_regmap_nolock(void *__lock)
{
}
static const char *sta2x11_mfd_names[sta2x11_n_mfd_plat_devs] = {
[sta2x11_sctl] = STA2X11_MFD_SCTL_NAME,
[sta2x11_apbreg] = STA2X11_MFD_APBREG_NAME,
[sta2x11_apb_soc_regs] = STA2X11_MFD_APB_SOC_REGS_NAME,
[sta2x11_scr] = STA2X11_MFD_SCR_NAME,
};
static bool sta2x11_sctl_writeable_reg(struct device *dev, unsigned int reg)
{
return !__reg_within_range(reg, SCTL_SCPCIECSBRST, SCTL_SCRSTSTA);
}
static struct regmap_config sta2x11_sctl_regmap_config = {
.reg_bits = 32,
.reg_stride = 4,
.val_bits = 32,
.lock = sta2x11_regmap_lock,
.unlock = sta2x11_regmap_unlock,
.max_register = SCTL_SCRSTSTA,
.writeable_reg = sta2x11_sctl_writeable_reg,
};
static bool sta2x11_scr_readable_reg(struct device *dev, unsigned int reg)
{
return (reg == STA2X11_SECR_CR) ||
__reg_within_range(reg, STA2X11_SECR_FVR0, STA2X11_SECR_FVR1);
}
static bool sta2x11_scr_writeable_reg(struct device *dev, unsigned int reg)
{
return false;
}
static struct regmap_config sta2x11_scr_regmap_config = {
.reg_bits = 32,
.reg_stride = 4,
.val_bits = 32,
.lock = sta2x11_regmap_nolock,
.unlock = sta2x11_regmap_nolock,
.max_register = STA2X11_SECR_FVR1,
.readable_reg = sta2x11_scr_readable_reg,
.writeable_reg = sta2x11_scr_writeable_reg,
};
static bool sta2x11_apbreg_readable_reg(struct device *dev, unsigned int reg)
{
/* Two blocks (CAN and MLB, SARAC) 0x100 bytes apart */
if (reg >= APBREG_BSR_SARAC)
reg -= APBREG_BSR_SARAC;
switch (reg) {
case APBREG_BSR:
case APBREG_PAER:
case APBREG_PWAC:
case APBREG_PRAC:
case APBREG_PCG:
case APBREG_PUR:
case APBREG_EMU_PCG:
return true;
default:
return false;
}
}
static bool sta2x11_apbreg_writeable_reg(struct device *dev, unsigned int reg)
{
if (reg >= APBREG_BSR_SARAC)
reg -= APBREG_BSR_SARAC;
if (!sta2x11_apbreg_readable_reg(dev, reg))
return false;
return reg != APBREG_PAER;
}
static struct regmap_config sta2x11_apbreg_regmap_config = {
.reg_bits = 32,
.reg_stride = 4,
.val_bits = 32,
.lock = sta2x11_regmap_lock,
.unlock = sta2x11_regmap_unlock,
.max_register = APBREG_EMU_PCG_SARAC,
.readable_reg = sta2x11_apbreg_readable_reg,
.writeable_reg = sta2x11_apbreg_writeable_reg,
};
static bool sta2x11_apb_soc_regs_readable_reg(struct device *dev,
unsigned int reg)
{
return reg <= PCIE_SoC_INT_ROUTER_STATUS3_REG ||
__reg_within_range(reg, DMA_IP_CTRL_REG, SPARE3_RESERVED) ||
__reg_within_range(reg, MASTER_LOCK_REG,
SYSTEM_CONFIG_STATUS_REG) ||
reg == MSP_CLK_CTRL_REG ||
__reg_within_range(reg, COMPENSATION_REG1, TEST_CTL_REG);
}
static bool sta2x11_apb_soc_regs_writeable_reg(struct device *dev,
unsigned int reg)
{
if (!sta2x11_apb_soc_regs_readable_reg(dev, reg))
return false;
switch (reg) {
case PCIE_COMMON_CLOCK_CONFIG_0_4_0:
case SYSTEM_CONFIG_STATUS_REG:
case COMPENSATION_REG1:
case PCIE_SoC_INT_ROUTER_STATUS0_REG...PCIE_SoC_INT_ROUTER_STATUS3_REG:
case PCIE_PM_STATUS_0_PORT_0_4...PCIE_PM_STATUS_7_0_EP4:
return false;
default:
return true;
}
}
static struct regmap_config sta2x11_apb_soc_regs_regmap_config = {
.reg_bits = 32,
.reg_stride = 4,
.val_bits = 32,
.lock = sta2x11_regmap_lock,
.unlock = sta2x11_regmap_unlock,
.max_register = TEST_CTL_REG,
.readable_reg = sta2x11_apb_soc_regs_readable_reg,
.writeable_reg = sta2x11_apb_soc_regs_writeable_reg,
};
static struct regmap_config *
sta2x11_mfd_regmap_configs[sta2x11_n_mfd_plat_devs] = {
[sta2x11_sctl] = &sta2x11_sctl_regmap_config,
[sta2x11_apbreg] = &sta2x11_apbreg_regmap_config,
[sta2x11_apb_soc_regs] = &sta2x11_apb_soc_regs_regmap_config,
[sta2x11_scr] = &sta2x11_scr_regmap_config,
};
/* Probe for the four platform devices */
static int sta2x11_mfd_platform_probe(struct platform_device *dev,
enum sta2x11_mfd_plat_dev index)
{
struct pci_dev **pdev;
struct sta2x11_mfd *mfd;
struct resource *res;
const char *name = sta2x11_mfd_names[index];
struct regmap_config *regmap_config = sta2x11_mfd_regmap_configs[index];
pdev = dev_get_platdata(&dev->dev);
mfd = sta2x11_mfd_find(*pdev);
if (!mfd)
return -ENODEV;
if (!regmap_config)
return -ENODEV;
res = platform_get_resource(dev, IORESOURCE_MEM, 0);
if (!res)
return -ENOMEM;
if (!request_mem_region(res->start, resource_size(res), name))
return -EBUSY;
mfd->regs[index] = ioremap(res->start, resource_size(res));
if (!mfd->regs[index]) {
release_mem_region(res->start, resource_size(res));
return -ENOMEM;
}
regmap_config->lock_arg = &mfd->lock;
/*
No caching, registers could be reached both via regmap and via
void __iomem *
*/
regmap_config->cache_type = REGCACHE_NONE;
mfd->regmap[index] = devm_regmap_init_mmio(&dev->dev, mfd->regs[index],
regmap_config);
WARN_ON(IS_ERR(mfd->regmap[index]));
return 0;
}
static int sta2x11_sctl_probe(struct platform_device *dev)
{
return sta2x11_mfd_platform_probe(dev, sta2x11_sctl);
}
static int sta2x11_apbreg_probe(struct platform_device *dev)
{
return sta2x11_mfd_platform_probe(dev, sta2x11_apbreg);
}
static int sta2x11_apb_soc_regs_probe(struct platform_device *dev)
{
return sta2x11_mfd_platform_probe(dev, sta2x11_apb_soc_regs);
}
static int sta2x11_scr_probe(struct platform_device *dev)
{
return sta2x11_mfd_platform_probe(dev, sta2x11_scr);
}
/* The three platform drivers */
static struct platform_driver sta2x11_sctl_platform_driver = {
.driver = {
.name = STA2X11_MFD_SCTL_NAME,
},
.probe = sta2x11_sctl_probe,
};
static struct platform_driver sta2x11_platform_driver = {
.driver = {
.name = STA2X11_MFD_APBREG_NAME,
},
.probe = sta2x11_apbreg_probe,
};
static struct platform_driver sta2x11_apb_soc_regs_platform_driver = {
.driver = {
.name = STA2X11_MFD_APB_SOC_REGS_NAME,
},
.probe = sta2x11_apb_soc_regs_probe,
};
static struct platform_driver sta2x11_scr_platform_driver = {
.driver = {
.name = STA2X11_MFD_SCR_NAME,
},
.probe = sta2x11_scr_probe,
};
static struct platform_driver * const drivers[] = {
&sta2x11_platform_driver,
&sta2x11_sctl_platform_driver,
&sta2x11_apb_soc_regs_platform_driver,
&sta2x11_scr_platform_driver,
};
static int __init sta2x11_drivers_init(void)
{
return platform_register_drivers(drivers, ARRAY_SIZE(drivers));
}
/*
* What follows are the PCI devices that host the above pdevs.
* Each logic block is 4kB and they are all consecutive: we use this info.
*/
/* Mfd 0 device */
/* Mfd 0, Bar 0 */
enum mfd0_bar0_cells {
STA2X11_GPIO_0 = 0,
STA2X11_GPIO_1,
STA2X11_GPIO_2,
STA2X11_GPIO_3,
STA2X11_SCTL,
STA2X11_SCR,
STA2X11_TIME,
};
/* Mfd 0 , Bar 1 */
enum mfd0_bar1_cells {
STA2X11_APBREG = 0,
};
#define CELL_4K(_name, _cell) { \
.name = _name, \
.start = _cell * 4096, .end = _cell * 4096 + 4095, \
.flags = IORESOURCE_MEM, \
}
static const struct resource gpio_resources[] = {
{
/* 4 consecutive cells, 1 driver */
.name = STA2X11_MFD_GPIO_NAME,
.start = 0,
.end = (4 * 4096) - 1,
.flags = IORESOURCE_MEM,
}
};
static const struct resource sctl_resources[] = {
CELL_4K(STA2X11_MFD_SCTL_NAME, STA2X11_SCTL),
};
static const struct resource scr_resources[] = {
CELL_4K(STA2X11_MFD_SCR_NAME, STA2X11_SCR),
};
static const struct resource time_resources[] = {
CELL_4K(STA2X11_MFD_TIME_NAME, STA2X11_TIME),
};
static const struct resource apbreg_resources[] = {
CELL_4K(STA2X11_MFD_APBREG_NAME, STA2X11_APBREG),
};
#define DEV(_name, _r) \
{ .name = _name, .num_resources = ARRAY_SIZE(_r), .resources = _r, }
static struct mfd_cell sta2x11_mfd0_bar0[] = {
/* offset 0: we add pdata later */
DEV(STA2X11_MFD_GPIO_NAME, gpio_resources),
DEV(STA2X11_MFD_SCTL_NAME, sctl_resources),
DEV(STA2X11_MFD_SCR_NAME, scr_resources),
DEV(STA2X11_MFD_TIME_NAME, time_resources),
};
static struct mfd_cell sta2x11_mfd0_bar1[] = {
DEV(STA2X11_MFD_APBREG_NAME, apbreg_resources),
};
/* Mfd 1 devices */
/* Mfd 1, Bar 0 */
enum mfd1_bar0_cells {
STA2X11_VIC = 0,
};
/* Mfd 1, Bar 1 */
enum mfd1_bar1_cells {
STA2X11_APB_SOC_REGS = 0,
};
static const struct resource vic_resources[] = {
CELL_4K(STA2X11_MFD_VIC_NAME, STA2X11_VIC),
};
static const struct resource apb_soc_regs_resources[] = {
CELL_4K(STA2X11_MFD_APB_SOC_REGS_NAME, STA2X11_APB_SOC_REGS),
};
static struct mfd_cell sta2x11_mfd1_bar0[] = {
DEV(STA2X11_MFD_VIC_NAME, vic_resources),
};
static struct mfd_cell sta2x11_mfd1_bar1[] = {
DEV(STA2X11_MFD_APB_SOC_REGS_NAME, apb_soc_regs_resources),
};
static int sta2x11_mfd_suspend(struct pci_dev *pdev, pm_message_t state)
{
pci_save_state(pdev);
pci_disable_device(pdev);
pci_set_power_state(pdev, pci_choose_state(pdev, state));
return 0;
}
static int sta2x11_mfd_resume(struct pci_dev *pdev)
{
int err;
pci_set_power_state(pdev, PCI_D0);
err = pci_enable_device(pdev);
if (err)
return err;
pci_restore_state(pdev);
return 0;
}
struct sta2x11_mfd_bar_setup_data {
struct mfd_cell *cells;
int ncells;
};
struct sta2x11_mfd_setup_data {
struct sta2x11_mfd_bar_setup_data bars[2];
};
#define STA2X11_MFD0 0
#define STA2X11_MFD1 1
static struct sta2x11_mfd_setup_data mfd_setup_data[] = {
/* Mfd 0: gpio, sctl, scr, timers / apbregs */
[STA2X11_MFD0] = {
.bars = {
[0] = {
.cells = sta2x11_mfd0_bar0,
.ncells = ARRAY_SIZE(sta2x11_mfd0_bar0),
},
[1] = {
.cells = sta2x11_mfd0_bar1,
.ncells = ARRAY_SIZE(sta2x11_mfd0_bar1),
},
},
},
/* Mfd 1: vic / apb-soc-regs */
[STA2X11_MFD1] = {
.bars = {
[0] = {
.cells = sta2x11_mfd1_bar0,
.ncells = ARRAY_SIZE(sta2x11_mfd1_bar0),
},
[1] = {
.cells = sta2x11_mfd1_bar1,
.ncells = ARRAY_SIZE(sta2x11_mfd1_bar1),
},
},
},
};
static void sta2x11_mfd_setup(struct pci_dev *pdev,
struct sta2x11_mfd_setup_data *sd)
{
int i, j;
for (i = 0; i < ARRAY_SIZE(sd->bars); i++)
for (j = 0; j < sd->bars[i].ncells; j++) {
sd->bars[i].cells[j].pdata_size = sizeof(pdev);
sd->bars[i].cells[j].platform_data = &pdev;
}
}
static int sta2x11_mfd_probe(struct pci_dev *pdev,
const struct pci_device_id *pci_id)
{
int err, i;
struct sta2x11_mfd_setup_data *setup_data;
dev_info(&pdev->dev, "%s\n", __func__);
err = pci_enable_device(pdev);
if (err) {
dev_err(&pdev->dev, "Can't enable device.\n");
return err;
}
err = pci_enable_msi(pdev);
if (err)
dev_info(&pdev->dev, "Enable msi failed\n");
setup_data = pci_id->device == PCI_DEVICE_ID_STMICRO_GPIO ?
&mfd_setup_data[STA2X11_MFD0] :
&mfd_setup_data[STA2X11_MFD1];
/* platform data is the pci device for all of them */
sta2x11_mfd_setup(pdev, setup_data);
/* Record this pdev before mfd_add_devices: their probe looks for it */
if (!sta2x11_mfd_find(pdev))
sta2x11_mfd_add(pdev, GFP_KERNEL);
/* Just 2 bars for all mfd's at present */
for (i = 0; i < 2; i++) {
err = mfd_add_devices(&pdev->dev, -1,
setup_data->bars[i].cells,
setup_data->bars[i].ncells,
&pdev->resource[i],
0, NULL);
if (err) {
dev_err(&pdev->dev,
"mfd_add_devices[%d] failed: %d\n", i, err);
goto err_disable;
}
}
return 0;
err_disable:
mfd_remove_devices(&pdev->dev);
pci_disable_device(pdev);
pci_disable_msi(pdev);
return err;
}
static const struct pci_device_id sta2x11_mfd_tbl[] = {
{PCI_DEVICE(PCI_VENDOR_ID_STMICRO, PCI_DEVICE_ID_STMICRO_GPIO)},
{PCI_DEVICE(PCI_VENDOR_ID_STMICRO, PCI_DEVICE_ID_STMICRO_VIC)},
{0,},
};
static struct pci_driver sta2x11_mfd_driver = {
.name = "sta2x11-mfd",
.id_table = sta2x11_mfd_tbl,
.probe = sta2x11_mfd_probe,
.suspend = sta2x11_mfd_suspend,
.resume = sta2x11_mfd_resume,
};
static int __init sta2x11_mfd_init(void)
{
pr_info("%s\n", __func__);
return pci_register_driver(&sta2x11_mfd_driver);
}
/*
* All of this must be ready before "normal" devices like MMCI appear.
* But MFD (the pci device) can't be too early. The following choice
* prepares platform drivers very early and probe the PCI device later,
* but before other PCI devices.
*/
subsys_initcall(sta2x11_drivers_init);
rootfs_initcall(sta2x11_mfd_init);

View File

@ -9,6 +9,7 @@
#include <linux/module.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/property.h>
#include <linux/reset.h>
#define STM32_TIMERS_MAX_REGISTERS 0x3fc
@ -173,6 +174,31 @@ static void stm32_timers_get_arr_size(struct stm32_timers *ddata)
regmap_write(ddata->regmap, TIM_ARR, arr);
}
static int stm32_timers_probe_hwcfgr(struct device *dev, struct stm32_timers *ddata)
{
u32 val;
ddata->ipidr = (uintptr_t)device_get_match_data(dev);
if (!ddata->ipidr) {
/* Fallback to legacy method for probing counter width */
stm32_timers_get_arr_size(ddata);
return 0;
}
regmap_read(ddata->regmap, TIM_IPIDR, &val);
if (val != ddata->ipidr) {
dev_err(dev, "Unsupported device detected: %u\n", val);
return -EINVAL;
}
regmap_read(ddata->regmap, TIM_HWCFGR2, &val);
/* Counter width in bits, max reload value is BIT(width) - 1 */
ddata->max_arr = BIT(FIELD_GET(TIM_HWCFGR2_CNT_WIDTH, val)) - 1;
return 0;
}
static int stm32_timers_dma_probe(struct device *dev,
struct stm32_timers *ddata)
{
@ -285,7 +311,9 @@ static int stm32_timers_probe(struct platform_device *pdev)
if (IS_ERR(ddata->clk))
return PTR_ERR(ddata->clk);
stm32_timers_get_arr_size(ddata);
ret = stm32_timers_probe_hwcfgr(dev, ddata);
if (ret)
return ret;
ret = stm32_timers_irq_probe(pdev, ddata);
if (ret)
@ -320,6 +348,7 @@ static void stm32_timers_remove(struct platform_device *pdev)
static const struct of_device_id stm32_timers_of_match[] = {
{ .compatible = "st,stm32-timers", },
{ .compatible = "st,stm32mp25-timers", .data = (void *)STM32MP25_TIM_IPIDR },
{ /* end node */ },
};
MODULE_DEVICE_TABLE(of, stm32_timers_of_match);

View File

@ -47,6 +47,7 @@ static struct syscon *of_syscon_register(struct device_node *np, bool check_res)
struct regmap_config syscon_config = syscon_regmap_config;
struct resource res;
struct reset_control *reset;
resource_size_t res_size;
WARN_ON(!mutex_is_locked(&syscon_list_lock));
@ -96,6 +97,12 @@ static struct syscon *of_syscon_register(struct device_node *np, bool check_res)
}
}
res_size = resource_size(&res);
if (res_size < reg_io_width) {
ret = -EFAULT;
goto err_regmap;
}
syscon_config.name = kasprintf(GFP_KERNEL, "%pOFn@%pa", np, &res.start);
if (!syscon_config.name) {
ret = -ENOMEM;
@ -103,7 +110,7 @@ static struct syscon *of_syscon_register(struct device_node *np, bool check_res)
}
syscon_config.reg_stride = reg_io_width;
syscon_config.val_bits = reg_io_width * 8;
syscon_config.max_register = resource_size(&res) - reg_io_width;
syscon_config.max_register = res_size - reg_io_width;
if (!syscon_config.max_register)
syscon_config.max_register_is_0 = true;

View File

@ -16,6 +16,7 @@
#include <linux/workqueue.h>
#include <linux/debugfs.h>
#include <linux/seq_file.h>
#include <linux/string_choices.h>
#include <linux/mutex.h>
#include <linux/platform_device.h>
@ -250,7 +251,7 @@ static int dbg_show(struct seq_file *s, void *_)
v2 = i2c_smbus_read_byte_data(tps->client, TPS_LED1_PER);
seq_printf(s, "led1 %s, on=%02x, per=%02x, %d/%d msec\n",
(value & 0x80)
? ((v2 & 0x80) ? "on" : "off")
? str_on_off(v2 & 0x80)
: ((v2 & 0x80) ? "blink" : "(nPG)"),
value, v2,
(value & 0x7f) * 10, (v2 & 0x7f) * 100);
@ -259,7 +260,7 @@ static int dbg_show(struct seq_file *s, void *_)
v2 = i2c_smbus_read_byte_data(tps->client, TPS_LED2_PER);
seq_printf(s, "led2 %s, on=%02x, per=%02x, %d/%d msec\n",
(value & 0x80)
? ((v2 & 0x80) ? "on" : "off")
? str_on_off(v2 & 0x80)
: ((v2 & 0x80) ? "blink" : "off"),
value, v2,
(value & 0x7f) * 10, (v2 & 0x7f) * 100);
@ -738,7 +739,7 @@ int tps65010_set_gpio_out_value(unsigned gpio, unsigned value)
TPS_DEFGPIO, defgpio);
pr_debug("%s: gpio%dout = %s, defgpio 0x%02x\n", DRIVER_NAME,
gpio, value ? "high" : "low",
gpio, str_high_low(value),
i2c_smbus_read_byte_data(the_tps->client, TPS_DEFGPIO));
mutex_unlock(&the_tps->lock);
@ -850,7 +851,7 @@ int tps65010_set_vib(unsigned value)
status = i2c_smbus_write_byte_data(the_tps->client,
TPS_VDCDC2, vdcdc2);
pr_debug("%s: vibrator %s\n", DRIVER_NAME, value ? "on" : "off");
pr_debug("%s: vibrator %s\n", DRIVER_NAME, str_on_off(value));
mutex_unlock(&the_tps->lock);
return status;
@ -872,7 +873,7 @@ int tps65010_set_low_pwr(unsigned mode)
mutex_lock(&the_tps->lock);
pr_debug("%s: %s low_pwr, vdcdc1 0x%02x\n", DRIVER_NAME,
mode ? "enable" : "disable",
str_enable_disable(mode),
i2c_smbus_read_byte_data(the_tps->client, TPS_VDCDC1));
vdcdc1 = i2c_smbus_read_byte_data(the_tps->client, TPS_VDCDC1);
@ -984,7 +985,7 @@ int tps65013_set_low_pwr(unsigned mode)
pr_debug("%s: %s low_pwr, chgconfig 0x%02x vdcdc1 0x%02x\n",
DRIVER_NAME,
mode ? "enable" : "disable",
str_enable_disable(mode),
i2c_smbus_read_byte_data(the_tps->client, TPS_CHGCONFIG),
i2c_smbus_read_byte_data(the_tps->client, TPS_VDCDC1));

View File

@ -1,8 +1,9 @@
// SPDX-License-Identifier: GPL-2.0
//
// Driver for TPS65219 Integrated Power Management Integrated Chips (PMIC)
// Driver for TPS65214/TPS65215/TPS65219 Power Management Integrated Chips
//
// Copyright (C) 2022 BayLibre Incorporated - https://www.baylibre.com/
// Copyright (C) 2024 Texas Instruments Incorporated - https://www.ti.com/
#include <linux/i2c.h>
#include <linux/reboot.h>
@ -59,6 +60,84 @@ static const struct resource tps65219_pwrbutton_resources[] = {
DEFINE_RES_IRQ_NAMED(TPS65219_INT_PB_RISING_EDGE_DETECT, "rising"),
};
static const struct resource tps65214_regulator_resources[] = {
DEFINE_RES_IRQ_NAMED(TPS65219_INT_LDO1_SCG, "LDO1_SCG"),
DEFINE_RES_IRQ_NAMED(TPS65219_INT_LDO1_OC, "LDO1_OC"),
DEFINE_RES_IRQ_NAMED(TPS65219_INT_LDO1_UV, "LDO1_UV"),
DEFINE_RES_IRQ_NAMED(TPS65219_INT_LDO2_SCG, "LDO2_SCG"),
DEFINE_RES_IRQ_NAMED(TPS65219_INT_LDO2_OC, "LDO2_OC"),
DEFINE_RES_IRQ_NAMED(TPS65219_INT_LDO2_UV, "LDO2_UV"),
DEFINE_RES_IRQ_NAMED(TPS65219_INT_BUCK3_SCG, "BUCK3_SCG"),
DEFINE_RES_IRQ_NAMED(TPS65219_INT_BUCK3_OC, "BUCK3_OC"),
DEFINE_RES_IRQ_NAMED(TPS65219_INT_BUCK3_NEG_OC, "BUCK3_NEG_OC"),
DEFINE_RES_IRQ_NAMED(TPS65219_INT_BUCK3_UV, "BUCK3_UV"),
DEFINE_RES_IRQ_NAMED(TPS65219_INT_BUCK1_SCG, "BUCK1_SCG"),
DEFINE_RES_IRQ_NAMED(TPS65219_INT_BUCK1_OC, "BUCK1_OC"),
DEFINE_RES_IRQ_NAMED(TPS65219_INT_BUCK1_NEG_OC, "BUCK1_NEG_OC"),
DEFINE_RES_IRQ_NAMED(TPS65219_INT_BUCK1_UV, "BUCK1_UV"),
DEFINE_RES_IRQ_NAMED(TPS65219_INT_BUCK2_SCG, "BUCK2_SCG"),
DEFINE_RES_IRQ_NAMED(TPS65219_INT_BUCK2_OC, "BUCK2_OC"),
DEFINE_RES_IRQ_NAMED(TPS65219_INT_BUCK2_NEG_OC, "BUCK2_NEG_OC"),
DEFINE_RES_IRQ_NAMED(TPS65219_INT_BUCK2_UV, "BUCK2_UV"),
DEFINE_RES_IRQ_NAMED(TPS65219_INT_BUCK1_RV, "BUCK1_RV"),
DEFINE_RES_IRQ_NAMED(TPS65219_INT_BUCK2_RV, "BUCK2_RV"),
DEFINE_RES_IRQ_NAMED(TPS65219_INT_BUCK3_RV, "BUCK3_RV"),
DEFINE_RES_IRQ_NAMED(TPS65219_INT_LDO1_RV, "LDO1_RV"),
DEFINE_RES_IRQ_NAMED(TPS65214_INT_LDO2_RV, "LDO2_RV"),
DEFINE_RES_IRQ_NAMED(TPS65219_INT_BUCK1_RV_SD, "BUCK1_RV_SD"),
DEFINE_RES_IRQ_NAMED(TPS65219_INT_BUCK2_RV_SD, "BUCK2_RV_SD"),
DEFINE_RES_IRQ_NAMED(TPS65219_INT_BUCK3_RV_SD, "BUCK3_RV_SD"),
DEFINE_RES_IRQ_NAMED(TPS65214_INT_LDO1_RV_SD, "LDO1_RV_SD"),
DEFINE_RES_IRQ_NAMED(TPS65219_INT_LDO2_RV_SD, "LDO2_RV_SD"),
DEFINE_RES_IRQ_NAMED(TPS65219_INT_TIMEOUT, "TIMEOUT"),
DEFINE_RES_IRQ_NAMED(TPS65219_INT_SENSOR_2_WARM, "SENSOR_2_WARM"),
DEFINE_RES_IRQ_NAMED(TPS65219_INT_SENSOR_1_WARM, "SENSOR_1_WARM"),
DEFINE_RES_IRQ_NAMED(TPS65219_INT_SENSOR_0_WARM, "SENSOR_0_WARM"),
DEFINE_RES_IRQ_NAMED(TPS65219_INT_SENSOR_2_HOT, "SENSOR_2_HOT"),
DEFINE_RES_IRQ_NAMED(TPS65219_INT_SENSOR_1_HOT, "SENSOR_1_HOT"),
DEFINE_RES_IRQ_NAMED(TPS65219_INT_SENSOR_0_HOT, "SENSOR_0_HOT"),
};
static const struct resource tps65215_regulator_resources[] = {
DEFINE_RES_IRQ_NAMED(TPS65215_INT_LDO1_SCG, "LDO1_SCG"),
DEFINE_RES_IRQ_NAMED(TPS65215_INT_LDO1_OC, "LDO1_OC"),
DEFINE_RES_IRQ_NAMED(TPS65215_INT_LDO1_UV, "LDO1_UV"),
DEFINE_RES_IRQ_NAMED(TPS65215_INT_LDO2_SCG, "LDO2_SCG"),
DEFINE_RES_IRQ_NAMED(TPS65215_INT_LDO2_OC, "LDO2_OC"),
DEFINE_RES_IRQ_NAMED(TPS65215_INT_LDO2_UV, "LDO2_UV"),
DEFINE_RES_IRQ_NAMED(TPS65219_INT_BUCK3_SCG, "BUCK3_SCG"),
DEFINE_RES_IRQ_NAMED(TPS65219_INT_BUCK3_OC, "BUCK3_OC"),
DEFINE_RES_IRQ_NAMED(TPS65219_INT_BUCK3_NEG_OC, "BUCK3_NEG_OC"),
DEFINE_RES_IRQ_NAMED(TPS65219_INT_BUCK3_UV, "BUCK3_UV"),
DEFINE_RES_IRQ_NAMED(TPS65219_INT_BUCK1_SCG, "BUCK1_SCG"),
DEFINE_RES_IRQ_NAMED(TPS65219_INT_BUCK1_OC, "BUCK1_OC"),
DEFINE_RES_IRQ_NAMED(TPS65219_INT_BUCK1_NEG_OC, "BUCK1_NEG_OC"),
DEFINE_RES_IRQ_NAMED(TPS65219_INT_BUCK1_UV, "BUCK1_UV"),
DEFINE_RES_IRQ_NAMED(TPS65219_INT_BUCK2_SCG, "BUCK2_SCG"),
DEFINE_RES_IRQ_NAMED(TPS65219_INT_BUCK2_OC, "BUCK2_OC"),
DEFINE_RES_IRQ_NAMED(TPS65219_INT_BUCK2_NEG_OC, "BUCK2_NEG_OC"),
DEFINE_RES_IRQ_NAMED(TPS65219_INT_BUCK2_UV, "BUCK2_UV"),
DEFINE_RES_IRQ_NAMED(TPS65219_INT_BUCK1_RV, "BUCK1_RV"),
DEFINE_RES_IRQ_NAMED(TPS65219_INT_BUCK2_RV, "BUCK2_RV"),
DEFINE_RES_IRQ_NAMED(TPS65219_INT_BUCK3_RV, "BUCK3_RV"),
DEFINE_RES_IRQ_NAMED(TPS65219_INT_LDO1_RV, "LDO1_RV"),
DEFINE_RES_IRQ_NAMED(TPS65215_INT_LDO2_RV, "LDO2_RV"),
DEFINE_RES_IRQ_NAMED(TPS65219_INT_BUCK1_RV_SD, "BUCK1_RV_SD"),
DEFINE_RES_IRQ_NAMED(TPS65219_INT_BUCK2_RV_SD, "BUCK2_RV_SD"),
DEFINE_RES_IRQ_NAMED(TPS65219_INT_BUCK3_RV_SD, "BUCK3_RV_SD"),
DEFINE_RES_IRQ_NAMED(TPS65219_INT_LDO1_RV_SD, "LDO1_RV_SD"),
DEFINE_RES_IRQ_NAMED(TPS65215_INT_LDO2_RV_SD, "LDO2_RV_SD"),
DEFINE_RES_IRQ_NAMED(TPS65219_INT_TIMEOUT, "TIMEOUT"),
DEFINE_RES_IRQ_NAMED(TPS65219_INT_SENSOR_3_WARM, "SENSOR_3_WARM"),
DEFINE_RES_IRQ_NAMED(TPS65219_INT_SENSOR_2_WARM, "SENSOR_2_WARM"),
DEFINE_RES_IRQ_NAMED(TPS65219_INT_SENSOR_1_WARM, "SENSOR_1_WARM"),
DEFINE_RES_IRQ_NAMED(TPS65219_INT_SENSOR_0_WARM, "SENSOR_0_WARM"),
DEFINE_RES_IRQ_NAMED(TPS65219_INT_SENSOR_3_HOT, "SENSOR_3_HOT"),
DEFINE_RES_IRQ_NAMED(TPS65219_INT_SENSOR_2_HOT, "SENSOR_2_HOT"),
DEFINE_RES_IRQ_NAMED(TPS65219_INT_SENSOR_1_HOT, "SENSOR_1_HOT"),
DEFINE_RES_IRQ_NAMED(TPS65219_INT_SENSOR_0_HOT, "SENSOR_0_HOT"),
};
static const struct resource tps65219_regulator_resources[] = {
DEFINE_RES_IRQ_NAMED(TPS65219_INT_LDO3_SCG, "LDO3_SCG"),
DEFINE_RES_IRQ_NAMED(TPS65219_INT_LDO3_OC, "LDO3_OC"),
@ -109,6 +188,16 @@ static const struct resource tps65219_regulator_resources[] = {
DEFINE_RES_IRQ_NAMED(TPS65219_INT_SENSOR_0_HOT, "SENSOR_0_HOT"),
};
static const struct mfd_cell tps65214_cells[] = {
MFD_CELL_RES("tps65214-regulator", tps65214_regulator_resources),
MFD_CELL_NAME("tps65215-gpio"),
};
static const struct mfd_cell tps65215_cells[] = {
MFD_CELL_RES("tps65215-regulator", tps65215_regulator_resources),
MFD_CELL_NAME("tps65215-gpio"),
};
static const struct mfd_cell tps65219_cells[] = {
MFD_CELL_RES("tps65219-regulator", tps65219_regulator_resources),
MFD_CELL_NAME("tps65219-gpio"),
@ -136,8 +225,19 @@ static unsigned int bit3_offsets[] = { TPS65219_REG_INT_BUCK_1_2_POS }; /* Buck
static unsigned int bit4_offsets[] = { TPS65219_REG_INT_BUCK_3_POS }; /* Buck 3 */
static unsigned int bit5_offsets[] = { TPS65219_REG_INT_LDO_1_2_POS }; /* LDO 1-2 */
static unsigned int bit6_offsets[] = { TPS65219_REG_INT_LDO_3_4_POS }; /* LDO 3-4 */
static unsigned int tps65215_bit5_offsets[] = { TPS65215_REG_INT_LDO_1_POS };
static unsigned int tps65215_bit6_offsets[] = { TPS65215_REG_INT_LDO_2_POS };
static unsigned int bit7_offsets[] = { TPS65219_REG_INT_PB_POS }; /* Power Button */
/* TPS65214 INT_SOURCE bit 6 is 'RESERVED'*/
static unsigned int tps65214_bit0_offsets[] = { TPS65214_REG_INT_TO_RV_POS };
static unsigned int tps65214_bit1_offsets[] = { TPS65214_REG_INT_RV_POS };
static unsigned int tps65214_bit2_offsets[] = { TPS65214_REG_INT_SYS_POS };
static unsigned int tps65214_bit3_offsets[] = { TPS65214_REG_INT_BUCK_1_2_POS };
static unsigned int tps65214_bit4_offsets[] = { TPS65214_REG_INT_BUCK_3_POS };
static unsigned int tps65214_bit5_offsets[] = { TPS65214_REG_INT_LDO_1_2_POS };
static unsigned int tps65214_bit7_offsets[] = { TPS65214_REG_INT_PB_POS };
static struct regmap_irq_sub_irq_map tps65219_sub_irq_offsets[] = {
REGMAP_IRQ_MAIN_REG_OFFSET(bit0_offsets),
REGMAP_IRQ_MAIN_REG_OFFSET(bit1_offsets),
@ -149,9 +249,112 @@ static struct regmap_irq_sub_irq_map tps65219_sub_irq_offsets[] = {
REGMAP_IRQ_MAIN_REG_OFFSET(bit7_offsets),
};
static struct regmap_irq_sub_irq_map tps65215_sub_irq_offsets[] = {
REGMAP_IRQ_MAIN_REG_OFFSET(bit0_offsets),
REGMAP_IRQ_MAIN_REG_OFFSET(bit1_offsets),
REGMAP_IRQ_MAIN_REG_OFFSET(bit2_offsets),
REGMAP_IRQ_MAIN_REG_OFFSET(bit3_offsets),
REGMAP_IRQ_MAIN_REG_OFFSET(bit4_offsets),
REGMAP_IRQ_MAIN_REG_OFFSET(tps65215_bit5_offsets),
REGMAP_IRQ_MAIN_REG_OFFSET(tps65215_bit6_offsets),
REGMAP_IRQ_MAIN_REG_OFFSET(bit7_offsets),
};
static struct regmap_irq_sub_irq_map tps65214_sub_irq_offsets[] = {
REGMAP_IRQ_MAIN_REG_OFFSET(tps65214_bit0_offsets),
REGMAP_IRQ_MAIN_REG_OFFSET(tps65214_bit1_offsets),
REGMAP_IRQ_MAIN_REG_OFFSET(tps65214_bit2_offsets),
REGMAP_IRQ_MAIN_REG_OFFSET(tps65214_bit3_offsets),
REGMAP_IRQ_MAIN_REG_OFFSET(tps65214_bit4_offsets),
REGMAP_IRQ_MAIN_REG_OFFSET(tps65214_bit5_offsets),
REGMAP_IRQ_MAIN_REG_OFFSET(tps65214_bit7_offsets),
};
#define TPS65219_REGMAP_IRQ_REG(int_name, register_position) \
REGMAP_IRQ_REG(int_name, register_position, int_name##_MASK)
static const struct regmap_irq tps65214_irqs[] = {
TPS65219_REGMAP_IRQ_REG(TPS65219_INT_LDO1_SCG, TPS65214_REG_INT_LDO_1_2_POS),
TPS65219_REGMAP_IRQ_REG(TPS65219_INT_LDO1_OC, TPS65214_REG_INT_LDO_1_2_POS),
TPS65219_REGMAP_IRQ_REG(TPS65219_INT_LDO1_UV, TPS65214_REG_INT_LDO_1_2_POS),
TPS65219_REGMAP_IRQ_REG(TPS65219_INT_LDO2_SCG, TPS65214_REG_INT_LDO_1_2_POS),
TPS65219_REGMAP_IRQ_REG(TPS65219_INT_LDO2_OC, TPS65214_REG_INT_LDO_1_2_POS),
TPS65219_REGMAP_IRQ_REG(TPS65219_INT_LDO2_UV, TPS65214_REG_INT_LDO_1_2_POS),
TPS65219_REGMAP_IRQ_REG(TPS65219_INT_BUCK3_SCG, TPS65214_REG_INT_BUCK_3_POS),
TPS65219_REGMAP_IRQ_REG(TPS65219_INT_BUCK3_OC, TPS65214_REG_INT_BUCK_3_POS),
TPS65219_REGMAP_IRQ_REG(TPS65219_INT_BUCK3_NEG_OC, TPS65214_REG_INT_BUCK_3_POS),
TPS65219_REGMAP_IRQ_REG(TPS65219_INT_BUCK3_UV, TPS65214_REG_INT_BUCK_3_POS),
TPS65219_REGMAP_IRQ_REG(TPS65219_INT_BUCK2_SCG, TPS65214_REG_INT_BUCK_1_2_POS),
TPS65219_REGMAP_IRQ_REG(TPS65219_INT_BUCK2_OC, TPS65214_REG_INT_BUCK_1_2_POS),
TPS65219_REGMAP_IRQ_REG(TPS65219_INT_BUCK2_NEG_OC, TPS65214_REG_INT_BUCK_1_2_POS),
TPS65219_REGMAP_IRQ_REG(TPS65219_INT_BUCK2_UV, TPS65214_REG_INT_BUCK_1_2_POS),
TPS65219_REGMAP_IRQ_REG(TPS65219_INT_BUCK1_SCG, TPS65214_REG_INT_BUCK_1_2_POS),
TPS65219_REGMAP_IRQ_REG(TPS65219_INT_BUCK1_OC, TPS65214_REG_INT_BUCK_1_2_POS),
TPS65219_REGMAP_IRQ_REG(TPS65219_INT_BUCK1_NEG_OC, TPS65214_REG_INT_BUCK_1_2_POS),
TPS65219_REGMAP_IRQ_REG(TPS65219_INT_BUCK1_UV, TPS65214_REG_INT_BUCK_1_2_POS),
TPS65219_REGMAP_IRQ_REG(TPS65219_INT_SENSOR_2_WARM, TPS65214_REG_INT_SYS_POS),
TPS65219_REGMAP_IRQ_REG(TPS65219_INT_SENSOR_1_WARM, TPS65214_REG_INT_SYS_POS),
TPS65219_REGMAP_IRQ_REG(TPS65219_INT_SENSOR_0_WARM, TPS65214_REG_INT_SYS_POS),
TPS65219_REGMAP_IRQ_REG(TPS65219_INT_SENSOR_2_HOT, TPS65214_REG_INT_SYS_POS),
TPS65219_REGMAP_IRQ_REG(TPS65219_INT_SENSOR_1_HOT, TPS65214_REG_INT_SYS_POS),
TPS65219_REGMAP_IRQ_REG(TPS65219_INT_SENSOR_0_HOT, TPS65214_REG_INT_SYS_POS),
TPS65219_REGMAP_IRQ_REG(TPS65219_INT_BUCK1_RV, TPS65214_REG_INT_RV_POS),
TPS65219_REGMAP_IRQ_REG(TPS65219_INT_BUCK2_RV, TPS65214_REG_INT_RV_POS),
TPS65219_REGMAP_IRQ_REG(TPS65219_INT_BUCK3_RV, TPS65214_REG_INT_RV_POS),
TPS65219_REGMAP_IRQ_REG(TPS65219_INT_LDO1_RV, TPS65214_REG_INT_RV_POS),
TPS65219_REGMAP_IRQ_REG(TPS65214_INT_LDO2_RV, TPS65214_REG_INT_RV_POS),
TPS65219_REGMAP_IRQ_REG(TPS65219_INT_BUCK1_RV_SD, TPS65214_REG_INT_TO_RV_POS),
TPS65219_REGMAP_IRQ_REG(TPS65219_INT_BUCK2_RV_SD, TPS65214_REG_INT_TO_RV_POS),
TPS65219_REGMAP_IRQ_REG(TPS65219_INT_BUCK3_RV_SD, TPS65214_REG_INT_TO_RV_POS),
TPS65219_REGMAP_IRQ_REG(TPS65214_INT_LDO1_RV_SD, TPS65214_REG_INT_TO_RV_POS),
TPS65219_REGMAP_IRQ_REG(TPS65219_INT_LDO2_RV_SD, TPS65214_REG_INT_TO_RV_POS),
TPS65219_REGMAP_IRQ_REG(TPS65219_INT_TIMEOUT, TPS65214_REG_INT_TO_RV_POS),
TPS65219_REGMAP_IRQ_REG(TPS65219_INT_PB_FALLING_EDGE_DETECT, TPS65214_REG_INT_PB_POS),
TPS65219_REGMAP_IRQ_REG(TPS65219_INT_PB_RISING_EDGE_DETECT, TPS65214_REG_INT_PB_POS),
};
static const struct regmap_irq tps65215_irqs[] = {
TPS65219_REGMAP_IRQ_REG(TPS65215_INT_LDO1_SCG, TPS65215_REG_INT_LDO_1_POS),
TPS65219_REGMAP_IRQ_REG(TPS65215_INT_LDO1_OC, TPS65215_REG_INT_LDO_1_POS),
TPS65219_REGMAP_IRQ_REG(TPS65215_INT_LDO1_UV, TPS65215_REG_INT_LDO_1_POS),
TPS65219_REGMAP_IRQ_REG(TPS65215_INT_LDO2_SCG, TPS65215_REG_INT_LDO_2_POS),
TPS65219_REGMAP_IRQ_REG(TPS65215_INT_LDO2_OC, TPS65215_REG_INT_LDO_2_POS),
TPS65219_REGMAP_IRQ_REG(TPS65215_INT_LDO2_UV, TPS65215_REG_INT_LDO_2_POS),
TPS65219_REGMAP_IRQ_REG(TPS65219_INT_BUCK3_SCG, TPS65219_REG_INT_BUCK_3_POS),
TPS65219_REGMAP_IRQ_REG(TPS65219_INT_BUCK3_OC, TPS65219_REG_INT_BUCK_3_POS),
TPS65219_REGMAP_IRQ_REG(TPS65219_INT_BUCK3_NEG_OC, TPS65219_REG_INT_BUCK_3_POS),
TPS65219_REGMAP_IRQ_REG(TPS65219_INT_BUCK3_UV, TPS65219_REG_INT_BUCK_3_POS),
TPS65219_REGMAP_IRQ_REG(TPS65219_INT_BUCK2_SCG, TPS65219_REG_INT_BUCK_1_2_POS),
TPS65219_REGMAP_IRQ_REG(TPS65219_INT_BUCK2_OC, TPS65219_REG_INT_BUCK_1_2_POS),
TPS65219_REGMAP_IRQ_REG(TPS65219_INT_BUCK2_NEG_OC, TPS65219_REG_INT_BUCK_1_2_POS),
TPS65219_REGMAP_IRQ_REG(TPS65219_INT_BUCK2_UV, TPS65219_REG_INT_BUCK_1_2_POS),
TPS65219_REGMAP_IRQ_REG(TPS65219_INT_BUCK1_SCG, TPS65219_REG_INT_BUCK_1_2_POS),
TPS65219_REGMAP_IRQ_REG(TPS65219_INT_BUCK1_OC, TPS65219_REG_INT_BUCK_1_2_POS),
TPS65219_REGMAP_IRQ_REG(TPS65219_INT_BUCK1_NEG_OC, TPS65219_REG_INT_BUCK_1_2_POS),
TPS65219_REGMAP_IRQ_REG(TPS65219_INT_BUCK1_UV, TPS65219_REG_INT_BUCK_1_2_POS),
TPS65219_REGMAP_IRQ_REG(TPS65219_INT_SENSOR_3_WARM, TPS65219_REG_INT_SYS_POS),
TPS65219_REGMAP_IRQ_REG(TPS65219_INT_SENSOR_2_WARM, TPS65219_REG_INT_SYS_POS),
TPS65219_REGMAP_IRQ_REG(TPS65219_INT_SENSOR_1_WARM, TPS65219_REG_INT_SYS_POS),
TPS65219_REGMAP_IRQ_REG(TPS65219_INT_SENSOR_0_WARM, TPS65219_REG_INT_SYS_POS),
TPS65219_REGMAP_IRQ_REG(TPS65219_INT_SENSOR_3_HOT, TPS65219_REG_INT_SYS_POS),
TPS65219_REGMAP_IRQ_REG(TPS65219_INT_SENSOR_2_HOT, TPS65219_REG_INT_SYS_POS),
TPS65219_REGMAP_IRQ_REG(TPS65219_INT_SENSOR_1_HOT, TPS65219_REG_INT_SYS_POS),
TPS65219_REGMAP_IRQ_REG(TPS65219_INT_SENSOR_0_HOT, TPS65219_REG_INT_SYS_POS),
TPS65219_REGMAP_IRQ_REG(TPS65219_INT_BUCK1_RV, TPS65219_REG_INT_RV_POS),
TPS65219_REGMAP_IRQ_REG(TPS65219_INT_BUCK2_RV, TPS65219_REG_INT_RV_POS),
TPS65219_REGMAP_IRQ_REG(TPS65219_INT_BUCK3_RV, TPS65219_REG_INT_RV_POS),
TPS65219_REGMAP_IRQ_REG(TPS65219_INT_LDO1_RV, TPS65219_REG_INT_RV_POS),
TPS65219_REGMAP_IRQ_REG(TPS65215_INT_LDO2_RV, TPS65219_REG_INT_RV_POS),
TPS65219_REGMAP_IRQ_REG(TPS65219_INT_BUCK1_RV_SD, TPS65219_REG_INT_TO_RV_POS),
TPS65219_REGMAP_IRQ_REG(TPS65219_INT_BUCK2_RV_SD, TPS65219_REG_INT_TO_RV_POS),
TPS65219_REGMAP_IRQ_REG(TPS65219_INT_BUCK3_RV_SD, TPS65219_REG_INT_TO_RV_POS),
TPS65219_REGMAP_IRQ_REG(TPS65219_INT_LDO1_RV_SD, TPS65219_REG_INT_TO_RV_POS),
TPS65219_REGMAP_IRQ_REG(TPS65215_INT_LDO2_RV_SD, TPS65219_REG_INT_TO_RV_POS),
TPS65219_REGMAP_IRQ_REG(TPS65219_INT_TIMEOUT, TPS65219_REG_INT_TO_RV_POS),
TPS65219_REGMAP_IRQ_REG(TPS65219_INT_PB_FALLING_EDGE_DETECT, TPS65219_REG_INT_PB_POS),
TPS65219_REGMAP_IRQ_REG(TPS65219_INT_PB_RISING_EDGE_DETECT, TPS65219_REG_INT_PB_POS),
};
static const struct regmap_irq tps65219_irqs[] = {
TPS65219_REGMAP_IRQ_REG(TPS65219_INT_LDO3_SCG, TPS65219_REG_INT_LDO_3_4_POS),
TPS65219_REGMAP_IRQ_REG(TPS65219_INT_LDO3_OC, TPS65219_REG_INT_LDO_3_4_POS),
@ -204,6 +407,34 @@ static const struct regmap_irq tps65219_irqs[] = {
TPS65219_REGMAP_IRQ_REG(TPS65219_INT_PB_RISING_EDGE_DETECT, TPS65219_REG_INT_PB_POS),
};
static const struct regmap_irq_chip tps65214_irq_chip = {
.name = "tps65214_irq",
.main_status = TPS65219_REG_INT_SOURCE,
.num_main_regs = 1,
.num_main_status_bits = 8,
.irqs = tps65214_irqs,
.num_irqs = ARRAY_SIZE(tps65214_irqs),
.status_base = TPS65214_REG_INT_LDO_1_2,
.ack_base = TPS65214_REG_INT_LDO_1_2,
.clear_ack = 1,
.num_regs = 8,
.sub_reg_offsets = tps65214_sub_irq_offsets,
};
static const struct regmap_irq_chip tps65215_irq_chip = {
.name = "tps65215_irq",
.main_status = TPS65219_REG_INT_SOURCE,
.num_main_regs = 1,
.num_main_status_bits = 8,
.irqs = tps65215_irqs,
.num_irqs = ARRAY_SIZE(tps65215_irqs),
.status_base = TPS65215_REG_INT_LDO_2,
.ack_base = TPS65215_REG_INT_LDO_2,
.clear_ack = 1,
.num_regs = 8,
.sub_reg_offsets = tps65215_sub_irq_offsets,
};
static const struct regmap_irq_chip tps65219_irq_chip = {
.name = "tps65219_irq",
.main_status = TPS65219_REG_INT_SOURCE,
@ -218,10 +449,34 @@ static const struct regmap_irq_chip tps65219_irq_chip = {
.sub_reg_offsets = tps65219_sub_irq_offsets,
};
struct tps65219_chip_data {
const struct regmap_irq_chip *irq_chip;
const struct mfd_cell *cells;
int n_cells;
};
static struct tps65219_chip_data chip_info_table[] = {
[TPS65214] = {
.irq_chip = &tps65214_irq_chip,
.cells = tps65214_cells,
.n_cells = ARRAY_SIZE(tps65214_cells),
},
[TPS65215] = {
.irq_chip = &tps65215_irq_chip,
.cells = tps65215_cells,
.n_cells = ARRAY_SIZE(tps65215_cells),
},
[TPS65219] = {
.irq_chip = &tps65219_irq_chip,
.cells = tps65219_cells,
.n_cells = ARRAY_SIZE(tps65219_cells),
},
};
static int tps65219_probe(struct i2c_client *client)
{
struct tps65219 *tps;
unsigned int chipid;
struct tps65219_chip_data *pmic;
bool pwr_button;
int ret;
@ -232,6 +487,8 @@ static int tps65219_probe(struct i2c_client *client)
i2c_set_clientdata(client, tps);
tps->dev = &client->dev;
tps->chip_id = (uintptr_t)i2c_get_match_data(client);
pmic = &chip_info_table[tps->chip_id];
tps->regmap = devm_regmap_init_i2c(client, &tps65219_regmap_config);
if (IS_ERR(tps->regmap)) {
@ -240,20 +497,14 @@ static int tps65219_probe(struct i2c_client *client)
return ret;
}
ret = devm_regmap_add_irq_chip(&client->dev, tps->regmap, client->irq,
IRQF_ONESHOT, 0, &tps65219_irq_chip,
ret = devm_regmap_add_irq_chip(tps->dev, tps->regmap, client->irq,
IRQF_ONESHOT, 0, pmic->irq_chip,
&tps->irq_data);
if (ret)
return ret;
ret = regmap_read(tps->regmap, TPS65219_REG_TI_DEV_ID, &chipid);
if (ret) {
dev_err(tps->dev, "Failed to read device ID: %d\n", ret);
return ret;
}
ret = devm_mfd_add_devices(tps->dev, PLATFORM_DEVID_AUTO,
tps65219_cells, ARRAY_SIZE(tps65219_cells),
pmic->cells, pmic->n_cells,
NULL, 0, regmap_irq_get_domain(tps->irq_data));
if (ret) {
dev_err(tps->dev, "Failed to add child devices: %d\n", ret);
@ -291,7 +542,9 @@ static int tps65219_probe(struct i2c_client *client)
}
static const struct of_device_id of_tps65219_match_table[] = {
{ .compatible = "ti,tps65219", },
{ .compatible = "ti,tps65214", .data = (void *)TPS65214, },
{ .compatible = "ti,tps65215", .data = (void *)TPS65215, },
{ .compatible = "ti,tps65219", .data = (void *)TPS65219, },
{}
};
MODULE_DEVICE_TABLE(of, of_tps65219_match_table);
@ -306,5 +559,5 @@ static struct i2c_driver tps65219_driver = {
module_i2c_driver(tps65219_driver);
MODULE_AUTHOR("Jerome Neanne <jneanne@baylibre.com>");
MODULE_DESCRIPTION("TPS65219 power management IC driver");
MODULE_DESCRIPTION("TPS65214/TPS65215/TPS65219 PMIC driver");
MODULE_LICENSE("GPL");

View File

@ -11,7 +11,6 @@
* Author: Thomas Richard <thomas.richard@bootlin.com>
*/
#include <linux/acpi.h>
#include <linux/bitfield.h>
#include <linux/device.h>
#include <linux/err.h>
@ -311,7 +310,7 @@ MODULE_DEVICE_TABLE(acpi, upboard_fpga_acpi_match);
static struct platform_driver upboard_fpga_driver = {
.driver = {
.name = "upboard-fpga",
.acpi_match_table = ACPI_PTR(upboard_fpga_acpi_match),
.acpi_match_table = upboard_fpga_acpi_match,
.dev_groups = upboard_fpga_groups,
},
.probe = upboard_fpga_probe,

View File

@ -583,6 +583,12 @@ config CHARGER_MAX77693
help
Say Y to enable support for the Maxim MAX77693 battery charger.
config CHARGER_MAX77705
tristate "Maxim MAX77705 battery charger driver"
depends on MFD_MAX77705
help
Say Y to enable support for the Maxim MAX77705 battery charger.
config CHARGER_MAX77976
tristate "Maxim MAX77976 battery charger driver"
depends on I2C

View File

@ -80,6 +80,7 @@ obj-$(CONFIG_CHARGER_MAX14577) += max14577_charger.o
obj-$(CONFIG_CHARGER_DETECTOR_MAX14656) += max14656_charger_detector.o
obj-$(CONFIG_CHARGER_MAX77650) += max77650-charger.o
obj-$(CONFIG_CHARGER_MAX77693) += max77693_charger.o
obj-$(CONFIG_CHARGER_MAX77705) += max77705_charger.o
obj-$(CONFIG_CHARGER_MAX77976) += max77976_charger.o
obj-$(CONFIG_CHARGER_MAX8997) += max8997_charger.o
obj-$(CONFIG_CHARGER_MAX8998) += max8998_charger.o

View File

@ -0,0 +1,581 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Based on max77650-charger.c
*
* Copyright (C) 2025 Dzmitry Sankouski <dsankouski@gmail.org>
*
* Battery charger driver for MAXIM 77705 charger/power-supply.
*/
#include <linux/devm-helpers.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/mfd/max77693-common.h>
#include <linux/mfd/max77705-private.h>
#include <linux/power/max77705_charger.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/power_supply.h>
#include <linux/regmap.h>
static const char *max77705_charger_model = "max77705";
static const char *max77705_charger_manufacturer = "Maxim Integrated";
static const struct regmap_config max77705_chg_regmap_config = {
.reg_base = MAX77705_CHG_REG_BASE,
.reg_bits = 8,
.val_bits = 8,
.max_register = MAX77705_CHG_REG_SAFEOUT_CTRL,
};
static enum power_supply_property max77705_charger_props[] = {
POWER_SUPPLY_PROP_ONLINE,
POWER_SUPPLY_PROP_PRESENT,
POWER_SUPPLY_PROP_STATUS,
POWER_SUPPLY_PROP_CHARGE_TYPE,
POWER_SUPPLY_PROP_HEALTH,
POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE,
POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT,
POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
};
static int max77705_chgin_irq(void *irq_drv_data)
{
struct max77705_charger_data *charger = irq_drv_data;
queue_work(charger->wqueue, &charger->chgin_work);
return 0;
}
static const struct regmap_irq max77705_charger_irqs[] = {
{ .mask = MAX77705_BYP_IM, },
{ .mask = MAX77705_INP_LIMIT_IM, },
{ .mask = MAX77705_BATP_IM, },
{ .mask = MAX77705_BAT_IM, },
{ .mask = MAX77705_CHG_IM, },
{ .mask = MAX77705_WCIN_IM, },
{ .mask = MAX77705_CHGIN_IM, },
{ .mask = MAX77705_AICL_IM, },
};
static struct regmap_irq_chip max77705_charger_irq_chip = {
.name = "max77705-charger",
.status_base = MAX77705_CHG_REG_INT,
.mask_base = MAX77705_CHG_REG_INT_MASK,
.handle_post_irq = max77705_chgin_irq,
.num_regs = 1,
.irqs = max77705_charger_irqs,
.num_irqs = ARRAY_SIZE(max77705_charger_irqs),
};
static int max77705_charger_enable(struct max77705_charger_data *chg)
{
int rv;
rv = regmap_update_bits(chg->regmap, MAX77705_CHG_REG_CNFG_09,
MAX77705_CHG_EN_MASK, MAX77705_CHG_EN_MASK);
if (rv)
dev_err(chg->dev, "unable to enable the charger: %d\n", rv);
return rv;
}
static void max77705_charger_disable(void *data)
{
struct max77705_charger_data *chg = data;
int rv;
rv = regmap_update_bits(chg->regmap,
MAX77705_CHG_REG_CNFG_09,
MAX77705_CHG_EN_MASK,
MAX77705_CHG_DISABLE);
if (rv)
dev_err(chg->dev, "unable to disable the charger: %d\n", rv);
}
static int max77705_get_online(struct regmap *regmap, int *val)
{
unsigned int data;
int ret;
ret = regmap_read(regmap, MAX77705_CHG_REG_INT_OK, &data);
if (ret < 0)
return ret;
*val = !!(data & MAX77705_CHGIN_OK);
return 0;
}
static int max77705_check_battery(struct max77705_charger_data *charger, int *val)
{
unsigned int reg_data;
unsigned int reg_data2;
struct regmap *regmap = charger->regmap;
regmap_read(regmap, MAX77705_CHG_REG_INT_OK, &reg_data);
dev_dbg(charger->dev, "CHG_INT_OK(0x%x)\n", reg_data);
regmap_read(regmap, MAX77705_CHG_REG_DETAILS_00, &reg_data2);
dev_dbg(charger->dev, "CHG_DETAILS00(0x%x)\n", reg_data2);
if ((reg_data & MAX77705_BATP_OK) || !(reg_data2 & MAX77705_BATP_DTLS))
*val = true;
else
*val = false;
return 0;
}
static int max77705_get_charge_type(struct max77705_charger_data *charger, int *val)
{
struct regmap *regmap = charger->regmap;
unsigned int reg_data;
regmap_read(regmap, MAX77705_CHG_REG_CNFG_09, &reg_data);
if (!MAX77705_CHARGER_CHG_CHARGING(reg_data)) {
*val = POWER_SUPPLY_CHARGE_TYPE_NONE;
return 0;
}
regmap_read(regmap, MAX77705_CHG_REG_DETAILS_01, &reg_data);
reg_data &= MAX77705_CHG_DTLS;
switch (reg_data) {
case 0x0:
case MAX77705_CHARGER_CONSTANT_CURRENT:
case MAX77705_CHARGER_CONSTANT_VOLTAGE:
*val = POWER_SUPPLY_CHARGE_TYPE_FAST;
return 0;
default:
*val = POWER_SUPPLY_CHARGE_TYPE_NONE;
return 0;
}
return 0;
}
static int max77705_get_status(struct max77705_charger_data *charger, int *val)
{
struct regmap *regmap = charger->regmap;
unsigned int reg_data;
regmap_read(regmap, MAX77705_CHG_REG_CNFG_09, &reg_data);
if (!MAX77705_CHARGER_CHG_CHARGING(reg_data)) {
*val = POWER_SUPPLY_CHARGE_TYPE_NONE;
return 0;
}
regmap_read(regmap, MAX77705_CHG_REG_DETAILS_01, &reg_data);
reg_data &= MAX77705_CHG_DTLS;
switch (reg_data) {
case 0x0:
case MAX77705_CHARGER_CONSTANT_CURRENT:
case MAX77705_CHARGER_CONSTANT_VOLTAGE:
*val = POWER_SUPPLY_STATUS_CHARGING;
return 0;
case MAX77705_CHARGER_END_OF_CHARGE:
case MAX77705_CHARGER_DONE:
*val = POWER_SUPPLY_STATUS_FULL;
return 0;
/* those values hard coded as in vendor kernel, because of */
/* failure to determine it's actual meaning. */
case 0x05:
case 0x06:
case 0x07:
*val = POWER_SUPPLY_STATUS_NOT_CHARGING;
return 0;
case 0x08:
case 0xA:
case 0xB:
*val = POWER_SUPPLY_STATUS_DISCHARGING;
return 0;
default:
*val = POWER_SUPPLY_STATUS_UNKNOWN;
return 0;
}
return 0;
}
static int max77705_get_vbus_state(struct regmap *regmap, int *value)
{
int ret;
unsigned int charge_dtls;
ret = regmap_read(regmap, MAX77705_CHG_REG_DETAILS_00, &charge_dtls);
if (ret)
return ret;
charge_dtls = ((charge_dtls & MAX77705_CHGIN_DTLS) >>
MAX77705_CHGIN_DTLS_SHIFT);
switch (charge_dtls) {
case 0x00:
*value = POWER_SUPPLY_HEALTH_UNDERVOLTAGE;
break;
case 0x01:
*value = POWER_SUPPLY_HEALTH_UNDERVOLTAGE;
break;
case 0x02:
*value = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
break;
case 0x03:
*value = POWER_SUPPLY_HEALTH_GOOD;
break;
default:
return 0;
}
return 0;
}
static int max77705_get_battery_health(struct max77705_charger_data *charger,
int *value)
{
struct regmap *regmap = charger->regmap;
unsigned int bat_dtls;
regmap_read(regmap, MAX77705_CHG_REG_DETAILS_01, &bat_dtls);
bat_dtls = ((bat_dtls & MAX77705_BAT_DTLS) >> MAX77705_BAT_DTLS_SHIFT);
switch (bat_dtls) {
case MAX77705_BATTERY_NOBAT:
dev_dbg(charger->dev, "%s: No battery and the charger is suspended\n",
__func__);
*value = POWER_SUPPLY_HEALTH_NO_BATTERY;
break;
case MAX77705_BATTERY_PREQUALIFICATION:
dev_dbg(charger->dev, "%s: battery is okay but its voltage is low(~VPQLB)\n",
__func__);
break;
case MAX77705_BATTERY_DEAD:
dev_dbg(charger->dev, "%s: battery dead\n", __func__);
*value = POWER_SUPPLY_HEALTH_DEAD;
break;
case MAX77705_BATTERY_GOOD:
case MAX77705_BATTERY_LOWVOLTAGE:
*value = POWER_SUPPLY_HEALTH_GOOD;
break;
case MAX77705_BATTERY_OVERVOLTAGE:
dev_dbg(charger->dev, "%s: battery ovp\n", __func__);
*value = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
break;
default:
dev_dbg(charger->dev, "%s: battery unknown\n", __func__);
*value = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
break;
}
return 0;
}
static int max77705_get_health(struct max77705_charger_data *charger, int *val)
{
struct regmap *regmap = charger->regmap;
int ret, is_online = 0;
ret = max77705_get_online(regmap, &is_online);
if (ret)
return ret;
if (is_online) {
ret = max77705_get_vbus_state(regmap, val);
if (ret || (*val != POWER_SUPPLY_HEALTH_GOOD))
return ret;
}
return max77705_get_battery_health(charger, val);
}
static int max77705_get_input_current(struct max77705_charger_data *charger,
int *val)
{
unsigned int reg_data;
int get_current = 0;
struct regmap *regmap = charger->regmap;
regmap_read(regmap, MAX77705_CHG_REG_CNFG_09, &reg_data);
reg_data &= MAX77705_CHG_CHGIN_LIM_MASK;
if (reg_data <= 3)
get_current = MAX77705_CURRENT_CHGIN_MIN;
else if (reg_data >= MAX77705_CHG_CHGIN_LIM_MASK)
get_current = MAX77705_CURRENT_CHGIN_MAX;
else
get_current = (reg_data + 1) * MAX77705_CURRENT_CHGIN_STEP;
*val = get_current;
return 0;
}
static int max77705_get_charge_current(struct max77705_charger_data *charger,
int *val)
{
unsigned int reg_data;
struct regmap *regmap = charger->regmap;
regmap_read(regmap, MAX77705_CHG_REG_CNFG_02, &reg_data);
reg_data &= MAX77705_CHG_CC;
*val = reg_data <= 0x2 ? MAX77705_CURRENT_CHGIN_MIN : reg_data * MAX77705_CURRENT_CHG_STEP;
return 0;
}
static int max77705_set_float_voltage(struct max77705_charger_data *charger,
int float_voltage)
{
int float_voltage_mv;
unsigned int reg_data = 0;
struct regmap *regmap = charger->regmap;
float_voltage_mv = float_voltage / 1000;
reg_data = float_voltage_mv <= 4000 ? 0x0 :
float_voltage_mv >= 4500 ? 0x23 :
(float_voltage_mv <= 4200) ? (float_voltage_mv - 4000) / 50 :
(((float_voltage_mv - 4200) / 10) + 0x04);
return regmap_update_bits(regmap, MAX77705_CHG_REG_CNFG_04,
MAX77705_CHG_CV_PRM_MASK,
(reg_data << MAX77705_CHG_CV_PRM_SHIFT));
}
static int max77705_get_float_voltage(struct max77705_charger_data *charger,
int *val)
{
unsigned int reg_data = 0;
int voltage_mv;
struct regmap *regmap = charger->regmap;
regmap_read(regmap, MAX77705_CHG_REG_CNFG_04, &reg_data);
reg_data &= MAX77705_CHG_PRM_MASK;
voltage_mv = reg_data <= 0x04 ? reg_data * 50 + 4000 :
(reg_data - 4) * 10 + 4200;
*val = voltage_mv * 1000;
return 0;
}
static int max77705_chg_get_property(struct power_supply *psy,
enum power_supply_property psp,
union power_supply_propval *val)
{
struct max77705_charger_data *charger = power_supply_get_drvdata(psy);
struct regmap *regmap = charger->regmap;
switch (psp) {
case POWER_SUPPLY_PROP_ONLINE:
return max77705_get_online(regmap, &val->intval);
case POWER_SUPPLY_PROP_PRESENT:
return max77705_check_battery(charger, &val->intval);
case POWER_SUPPLY_PROP_STATUS:
return max77705_get_status(charger, &val->intval);
case POWER_SUPPLY_PROP_CHARGE_TYPE:
return max77705_get_charge_type(charger, &val->intval);
case POWER_SUPPLY_PROP_HEALTH:
return max77705_get_health(charger, &val->intval);
case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
return max77705_get_input_current(charger, &val->intval);
case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
return max77705_get_charge_current(charger, &val->intval);
case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
return max77705_get_float_voltage(charger, &val->intval);
case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
val->intval = charger->bat_info->voltage_max_design_uv;
break;
case POWER_SUPPLY_PROP_MODEL_NAME:
val->strval = max77705_charger_model;
break;
case POWER_SUPPLY_PROP_MANUFACTURER:
val->strval = max77705_charger_manufacturer;
break;
default:
return -EINVAL;
}
return 0;
}
static const struct power_supply_desc max77705_charger_psy_desc = {
.name = "max77705-charger",
.type = POWER_SUPPLY_TYPE_USB,
.properties = max77705_charger_props,
.num_properties = ARRAY_SIZE(max77705_charger_props),
.get_property = max77705_chg_get_property,
};
static void max77705_chgin_isr_work(struct work_struct *work)
{
struct max77705_charger_data *charger =
container_of(work, struct max77705_charger_data, chgin_work);
power_supply_changed(charger->psy_chg);
}
static void max77705_charger_initialize(struct max77705_charger_data *chg)
{
u8 reg_data;
struct power_supply_battery_info *info;
struct regmap *regmap = chg->regmap;
if (power_supply_get_battery_info(chg->psy_chg, &info) < 0)
return;
chg->bat_info = info;
/* unlock charger setting protect */
/* slowest LX slope */
reg_data = MAX77705_CHGPROT_MASK | MAX77705_SLOWEST_LX_SLOPE;
regmap_update_bits(regmap, MAX77705_CHG_REG_CNFG_06, reg_data,
reg_data);
/* fast charge timer disable */
/* restart threshold disable */
/* pre-qual charge disable */
reg_data = (MAX77705_FCHGTIME_DISABLE << MAX77705_FCHGTIME_SHIFT) |
(MAX77705_CHG_RSTRT_DISABLE << MAX77705_CHG_RSTRT_SHIFT) |
(MAX77705_CHG_PQEN_DISABLE << MAX77705_PQEN_SHIFT);
regmap_update_bits(regmap, MAX77705_CHG_REG_CNFG_01,
(MAX77705_FCHGTIME_MASK |
MAX77705_CHG_RSTRT_MASK |
MAX77705_PQEN_MASK),
reg_data);
/* OTG off(UNO on), boost off */
regmap_update_bits(regmap, MAX77705_CHG_REG_CNFG_00,
MAX77705_OTG_CTRL, 0);
/* charge current 450mA(default) */
/* otg current limit 900mA */
regmap_update_bits(regmap, MAX77705_CHG_REG_CNFG_02,
MAX77705_OTG_ILIM_MASK,
MAX77705_OTG_ILIM_900 << MAX77705_OTG_ILIM_SHIFT);
/* BAT to SYS OCP 4.80A */
regmap_update_bits(regmap, MAX77705_CHG_REG_CNFG_05,
MAX77705_REG_B2SOVRC_MASK,
MAX77705_B2SOVRC_4_8A << MAX77705_REG_B2SOVRC_SHIFT);
/* top off current 150mA */
/* top off timer 30min */
reg_data = (MAX77705_TO_ITH_150MA << MAX77705_TO_ITH_SHIFT) |
(MAX77705_TO_TIME_30M << MAX77705_TO_TIME_SHIFT) |
(MAX77705_SYS_TRACK_DISABLE << MAX77705_SYS_TRACK_DIS_SHIFT);
regmap_update_bits(regmap, MAX77705_CHG_REG_CNFG_03,
(MAX77705_TO_ITH_MASK |
MAX77705_TO_TIME_MASK |
MAX77705_SYS_TRACK_DIS_MASK), reg_data);
/* cv voltage 4.2V or 4.35V */
/* MINVSYS 3.6V(default) */
if (info->voltage_max_design_uv < 0) {
dev_warn(chg->dev, "missing battery:voltage-max-design-microvolt\n");
max77705_set_float_voltage(chg, 4200000);
} else {
max77705_set_float_voltage(chg, info->voltage_max_design_uv);
}
regmap_update_bits(regmap, MAX77705_CHG_REG_CNFG_12,
MAX77705_VCHGIN_REG_MASK, MAX77705_VCHGIN_4_5);
regmap_update_bits(regmap, MAX77705_CHG_REG_CNFG_12,
MAX77705_WCIN_REG_MASK, MAX77705_WCIN_4_5);
/* Watchdog timer */
regmap_update_bits(regmap, MAX77705_CHG_REG_CNFG_00,
MAX77705_WDTEN_MASK, 0);
/* Active Discharge Enable */
regmap_update_bits(regmap, MAX77705_PMIC_REG_MAINCTRL1, 1, 1);
/* VBYPSET=5.0V */
regmap_update_bits(regmap, MAX77705_CHG_REG_CNFG_11, MAX77705_VBYPSET_MASK, 0);
/* Switching Frequency : 1.5MHz */
regmap_update_bits(regmap, MAX77705_CHG_REG_CNFG_08, MAX77705_REG_FSW_MASK,
(MAX77705_CHG_FSW_1_5MHz << MAX77705_REG_FSW_SHIFT));
/* Auto skip mode */
regmap_update_bits(regmap, MAX77705_CHG_REG_CNFG_12, MAX77705_REG_DISKIP_MASK,
(MAX77705_AUTO_SKIP << MAX77705_REG_DISKIP_SHIFT));
}
static int max77705_charger_probe(struct i2c_client *i2c)
{
struct power_supply_config pscfg = {};
struct max77705_charger_data *chg;
struct device *dev;
struct regmap_irq_chip_data *irq_data;
int ret;
dev = &i2c->dev;
chg = devm_kzalloc(dev, sizeof(*chg), GFP_KERNEL);
if (!chg)
return -ENOMEM;
chg->dev = dev;
i2c_set_clientdata(i2c, chg);
chg->regmap = devm_regmap_init_i2c(i2c, &max77705_chg_regmap_config);
if (IS_ERR(chg->regmap))
return PTR_ERR(chg->regmap);
ret = regmap_update_bits(chg->regmap,
MAX77705_CHG_REG_INT_MASK,
MAX77705_CHGIN_IM, 0);
if (ret)
return ret;
pscfg.fwnode = dev_fwnode(dev);
pscfg.drv_data = chg;
chg->psy_chg = devm_power_supply_register(dev, &max77705_charger_psy_desc, &pscfg);
if (IS_ERR(chg->psy_chg))
return PTR_ERR(chg->psy_chg);
max77705_charger_irq_chip.irq_drv_data = chg;
ret = devm_regmap_add_irq_chip(chg->dev, chg->regmap, i2c->irq,
IRQF_ONESHOT | IRQF_SHARED, 0,
&max77705_charger_irq_chip,
&irq_data);
if (ret)
return dev_err_probe(dev, ret, "failed to add irq chip\n");
chg->wqueue = create_singlethread_workqueue(dev_name(dev));
if (IS_ERR(chg->wqueue))
return dev_err_probe(dev, PTR_ERR(chg->wqueue), "failed to create workqueue\n");
ret = devm_work_autocancel(dev, &chg->chgin_work, max77705_chgin_isr_work);
if (ret)
return dev_err_probe(dev, ret, "failed to initialize interrupt work\n");
max77705_charger_initialize(chg);
ret = max77705_charger_enable(chg);
if (ret)
return dev_err_probe(dev, ret, "failed to enable charge\n");
return devm_add_action_or_reset(dev, max77705_charger_disable, chg);
}
static const struct of_device_id max77705_charger_of_match[] = {
{ .compatible = "maxim,max77705-charger" },
{ }
};
MODULE_DEVICE_TABLE(of, max77705_charger_of_match);
static struct i2c_driver max77705_charger_driver = {
.driver = {
.name = "max77705-charger",
.of_match_table = max77705_charger_of_match,
},
.probe = max77705_charger_probe,
};
module_i2c_driver(max77705_charger_driver);
MODULE_AUTHOR("Dzmitry Sankouski <dsankouski@gmail.com>");
MODULE_DESCRIPTION("Maxim MAX77705 charger driver");
MODULE_LICENSE("GPL");

View File

@ -1330,10 +1330,10 @@ config REGULATOR_S2MPA01
via I2C bus. S2MPA01 has 10 Bucks and 26 LDO outputs.
config REGULATOR_S2MPS11
tristate "Samsung S2MPS11/13/14/15/S2MPU02 voltage regulator"
tristate "Samsung S2MPS11/13/14/15/S2MPU02/05 voltage regulator"
depends on MFD_SEC_CORE || COMPILE_TEST
help
This driver supports a Samsung S2MPS11/13/14/15/S2MPU02 voltage
This driver supports a Samsung S2MPS11/13/14/15/S2MPU02/05 voltage
output regulator via I2C bus. The chip is comprised of high efficient
Buck converters including Dual-Phase Buck converter, Buck-Boost
converter, various LDOs.

View File

@ -21,6 +21,7 @@
#include <linux/mfd/samsung/s2mps14.h>
#include <linux/mfd/samsung/s2mps15.h>
#include <linux/mfd/samsung/s2mpu02.h>
#include <linux/mfd/samsung/s2mpu05.h>
/* The highest number of possible regulators for supported devices. */
#define S2MPS_REGULATOR_MAX S2MPS13_REGULATOR_MAX
@ -254,6 +255,9 @@ static int s2mps11_regulator_enable(struct regulator_dev *rdev)
else
val = rdev->desc->enable_mask;
break;
case S2MPU05:
val = rdev->desc->enable_mask;
break;
default:
return -EINVAL;
}
@ -1118,6 +1122,86 @@ static const struct regulator_desc s2mpu02_regulators[] = {
regulator_desc_s2mpu02_buck7(7),
};
#define regulator_desc_s2mpu05_ldo_reg(num, min, step, reg) { \
.name = "ldo"#num, \
.id = S2MPU05_LDO##num, \
.ops = &s2mpu02_ldo_ops, \
.type = REGULATOR_VOLTAGE, \
.owner = THIS_MODULE, \
.min_uV = min, \
.uV_step = step, \
.n_voltages = S2MPU05_LDO_N_VOLTAGES, \
.vsel_reg = reg, \
.vsel_mask = S2MPU05_LDO_VSEL_MASK, \
.enable_reg = reg, \
.enable_mask = S2MPU05_ENABLE_MASK, \
.enable_time = S2MPU05_ENABLE_TIME_LDO \
}
#define regulator_desc_s2mpu05_ldo(num, reg, min, step) \
regulator_desc_s2mpu05_ldo_reg(num, min, step, S2MPU05_REG_L##num##reg)
#define regulator_desc_s2mpu05_ldo1(num, reg) \
regulator_desc_s2mpu05_ldo(num, reg, S2MPU05_LDO_MIN1, S2MPU05_LDO_STEP1)
#define regulator_desc_s2mpu05_ldo2(num, reg) \
regulator_desc_s2mpu05_ldo(num, reg, S2MPU05_LDO_MIN1, S2MPU05_LDO_STEP2)
#define regulator_desc_s2mpu05_ldo3(num, reg) \
regulator_desc_s2mpu05_ldo(num, reg, S2MPU05_LDO_MIN2, S2MPU05_LDO_STEP2)
#define regulator_desc_s2mpu05_ldo4(num, reg) \
regulator_desc_s2mpu05_ldo(num, reg, S2MPU05_LDO_MIN3, S2MPU05_LDO_STEP2)
#define regulator_desc_s2mpu05_buck(num, which) { \
.name = "buck"#num, \
.id = S2MPU05_BUCK##num, \
.ops = &s2mpu02_buck_ops, \
.type = REGULATOR_VOLTAGE, \
.owner = THIS_MODULE, \
.min_uV = S2MPU05_BUCK_MIN##which, \
.uV_step = S2MPU05_BUCK_STEP##which, \
.n_voltages = S2MPU05_BUCK_N_VOLTAGES, \
.vsel_reg = S2MPU05_REG_B##num##CTRL2, \
.vsel_mask = S2MPU05_BUCK_VSEL_MASK, \
.enable_reg = S2MPU05_REG_B##num##CTRL1, \
.enable_mask = S2MPU05_ENABLE_MASK, \
.enable_time = S2MPU05_ENABLE_TIME_BUCK##num \
}
#define regulator_desc_s2mpu05_buck123(num) regulator_desc_s2mpu05_buck(num, 1)
#define regulator_desc_s2mpu05_buck45(num) regulator_desc_s2mpu05_buck(num, 2)
static const struct regulator_desc s2mpu05_regulators[] = {
regulator_desc_s2mpu05_ldo4(1, CTRL),
regulator_desc_s2mpu05_ldo3(2, CTRL),
regulator_desc_s2mpu05_ldo2(3, CTRL),
regulator_desc_s2mpu05_ldo1(4, CTRL),
regulator_desc_s2mpu05_ldo1(5, CTRL),
regulator_desc_s2mpu05_ldo1(6, CTRL),
regulator_desc_s2mpu05_ldo2(7, CTRL),
regulator_desc_s2mpu05_ldo3(8, CTRL),
regulator_desc_s2mpu05_ldo4(9, CTRL1),
regulator_desc_s2mpu05_ldo4(10, CTRL),
/* LDOs 11-24 are used for CP. They aren't documented. */
regulator_desc_s2mpu05_ldo2(25, CTRL),
regulator_desc_s2mpu05_ldo3(26, CTRL),
regulator_desc_s2mpu05_ldo2(27, CTRL),
regulator_desc_s2mpu05_ldo3(28, CTRL),
regulator_desc_s2mpu05_ldo3(29, CTRL),
regulator_desc_s2mpu05_ldo2(30, CTRL),
regulator_desc_s2mpu05_ldo3(31, CTRL),
regulator_desc_s2mpu05_ldo3(32, CTRL),
regulator_desc_s2mpu05_ldo3(33, CTRL),
regulator_desc_s2mpu05_ldo3(34, CTRL),
regulator_desc_s2mpu05_ldo3(35, CTRL),
regulator_desc_s2mpu05_buck123(1),
regulator_desc_s2mpu05_buck123(2),
regulator_desc_s2mpu05_buck123(3),
regulator_desc_s2mpu05_buck45(4),
regulator_desc_s2mpu05_buck45(5),
};
static int s2mps11_pmic_probe(struct platform_device *pdev)
{
struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent);
@ -1159,6 +1243,11 @@ static int s2mps11_pmic_probe(struct platform_device *pdev)
regulators = s2mpu02_regulators;
BUILD_BUG_ON(S2MPS_REGULATOR_MAX < ARRAY_SIZE(s2mpu02_regulators));
break;
case S2MPU05:
rdev_num = ARRAY_SIZE(s2mpu05_regulators);
regulators = s2mpu05_regulators;
BUILD_BUG_ON(S2MPS_REGULATOR_MAX < ARRAY_SIZE(s2mpu05_regulators));
break;
default:
dev_err(&pdev->dev, "Invalid device type: %u\n",
s2mps11->dev_type);
@ -1228,6 +1317,7 @@ static const struct platform_device_id s2mps11_pmic_id[] = {
{ "s2mps14-regulator", S2MPS14X},
{ "s2mps15-regulator", S2MPS15X},
{ "s2mpu02-regulator", S2MPU02},
{ "s2mpu05-regulator", S2MPU05},
{ },
};
MODULE_DEVICE_TABLE(platform, s2mps11_pmic_id);
@ -1245,5 +1335,5 @@ module_platform_driver(s2mps11_pmic_driver);
/* Module information */
MODULE_AUTHOR("Sangbeom Kim <sbkim73@samsung.com>");
MODULE_DESCRIPTION("Samsung S2MPS11/S2MPS14/S2MPS15/S2MPU02 Regulator Driver");
MODULE_DESCRIPTION("Samsung S2MPS11/14/15/S2MPU02/05 Regulator Driver");
MODULE_LICENSE("GPL");

View File

@ -137,6 +137,7 @@ enum axp20x_variants {
#define AXP717_IRQ2_STATE 0x4a
#define AXP717_IRQ3_STATE 0x4b
#define AXP717_IRQ4_STATE 0x4c
#define AXP717_TS_PIN_CFG 0x50
#define AXP717_ICC_CHG_SET 0x62
#define AXP717_ITERM_CHG_SET 0x63
#define AXP717_CV_CHG_SET 0x64

View File

@ -215,7 +215,7 @@ struct prcmu_fw_version {
static inline void prcmu_early_init(void)
{
return db8500_prcmu_early_init();
db8500_prcmu_early_init();
}
static inline int prcmu_set_power_state(u8 state, bool keep_ulp_clk,
@ -302,7 +302,7 @@ static inline int prcmu_request_ape_opp_100_voltage(bool enable)
static inline void prcmu_system_reset(u16 reset_code)
{
return db8500_prcmu_system_reset(reset_code);
db8500_prcmu_system_reset(reset_code);
}
static inline u16 prcmu_get_reset_code(void)
@ -314,7 +314,7 @@ int prcmu_ac_wake_req(void);
void prcmu_ac_sleep_req(void);
static inline void prcmu_modem_reset(void)
{
return db8500_prcmu_modem_reset();
db8500_prcmu_modem_reset();
}
static inline bool prcmu_is_ac_wake_requested(void)

View File

@ -31,7 +31,6 @@ int ezx_pcap_set_bits(struct pcap_chip *, u8, u32, u32);
int pcap_to_irq(struct pcap_chip *, int);
int irq_to_pcap(struct pcap_chip *, int);
int pcap_adc_async(struct pcap_chip *, u8, u32, u8[], void *, void *);
int pcap_adc_sync(struct pcap_chip *, u8, u32, u8[], u16[]);
void pcap_set_ts_bits(struct pcap_chip *, u32);
#define PCAP_SECOND_PORT 1

View File

@ -11,7 +11,6 @@
#define __MFD_LP3943_H__
#include <linux/gpio.h>
#include <linux/pwm.h>
#include <linux/regmap.h>
/* Registers */

View File

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Common data shared between Maxim 77693 and 77843 drivers
* Common data shared between Maxim 77693, 77705 and 77843 drivers
*
* Copyright (C) 2015 Samsung Electronics
*/
@ -11,6 +11,7 @@
enum max77693_types {
TYPE_MAX77693_UNKNOWN,
TYPE_MAX77693,
TYPE_MAX77705,
TYPE_MAX77843,
TYPE_MAX77693_NUM,
@ -32,6 +33,7 @@ struct max77693_dev {
struct regmap *regmap_muic;
struct regmap *regmap_haptic; /* Only MAX77693 */
struct regmap *regmap_chg; /* Only MAX77843 */
struct regmap *regmap_leds; /* Only MAX77705 */
struct regmap_irq_chip_data *irq_data_led;
struct regmap_irq_chip_data *irq_data_topsys;

View File

@ -0,0 +1,195 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Maxim MAX77705 definitions.
*
* Copyright (C) 2015 Samsung Electronics, Inc.
* Copyright (C) 2025 Dzmitry Sankouski <dsankouski@gmail.com>
*/
#ifndef __LINUX_MFD_MAX77705_PRIV_H
#define __LINUX_MFD_MAX77705_PRIV_H
#define MAX77705_SRC_IRQ_CHG BIT(0)
#define MAX77705_SRC_IRQ_TOP BIT(1)
#define MAX77705_SRC_IRQ_FG BIT(2)
#define MAX77705_SRC_IRQ_USBC BIT(3)
#define MAX77705_SRC_IRQ_ALL (MAX77705_SRC_IRQ_CHG | MAX77705_SRC_IRQ_TOP | \
MAX77705_SRC_IRQ_FG | MAX77705_SRC_IRQ_USBC)
/* MAX77705_PMIC_REG_PMICREV register */
#define MAX77705_VERSION_SHIFT 3
#define MAX77705_REVISION_MASK GENMASK(2, 0)
#define MAX77705_VERSION_MASK GENMASK(7, MAX77705_VERSION_SHIFT)
/* MAX77705_PMIC_REG_MAINCTRL1 register */
#define MAX77705_MAINCTRL1_BIASEN_SHIFT 7
#define MAX77705_MAINCTRL1_BIASEN_MASK BIT(MAX77705_MAINCTRL1_BIASEN_SHIFT)
/* MAX77705_PMIC_REG_MCONFIG2 (haptics) register */
#define MAX77705_CONFIG2_MEN_SHIFT 6
#define MAX77705_CONFIG2_MODE_SHIFT 7
#define MAX77705_CONFIG2_HTYP_SHIFT 5
/* MAX77705_PMIC_REG_SYSTEM_INT_MASK register */
#define MAX77705_SYSTEM_IRQ_BSTEN_INT BIT(3)
#define MAX77705_SYSTEM_IRQ_SYSUVLO_INT BIT(4)
#define MAX77705_SYSTEM_IRQ_SYSOVLO_INT BIT(5)
#define MAX77705_SYSTEM_IRQ_TSHDN_INT BIT(6)
#define MAX77705_SYSTEM_IRQ_TM_INT BIT(7)
/* MAX77705_RGBLED_REG_LEDEN register */
#define MAX77705_RGBLED_EN_WIDTH 2
/* MAX77705_RGBLED_REG_LEDBLNK register */
#define MAX77705_RGB_DELAY_100_STEP_LIM 500
#define MAX77705_RGB_DELAY_100_STEP_COUNT 4
#define MAX77705_RGB_DELAY_100_STEP 100
#define MAX77705_RGB_DELAY_250_STEP_LIM 3250
#define MAX77705_RGB_DELAY_250_STEP 250
#define MAX77705_RGB_DELAY_500_STEP 500
#define MAX77705_RGB_DELAY_500_STEP_COUNT 10
#define MAX77705_RGB_DELAY_500_STEP_LIM 5000
#define MAX77705_RGB_DELAY_1000_STEP_LIM 8000
#define MAX77705_RGB_DELAY_1000_STEP_COUNT 13
#define MAX77705_RGB_DELAY_1000_STEP 1000
#define MAX77705_RGB_DELAY_2000_STEP 2000
#define MAX77705_RGB_DELAY_2000_STEP_COUNT 13
#define MAX77705_RGB_DELAY_2000_STEP_LIM 12000
enum max77705_hw_rev {
MAX77705_PASS1 = 1,
MAX77705_PASS2,
MAX77705_PASS3
};
enum max77705_reg {
MAX77705_PMIC_REG_PMICID1 = 0x00,
MAX77705_PMIC_REG_PMICREV = 0x01,
MAX77705_PMIC_REG_MAINCTRL1 = 0x02,
MAX77705_PMIC_REG_BSTOUT_MASK = 0x03,
MAX77705_PMIC_REG_FORCE_EN_MASK = 0x08,
MAX77705_PMIC_REG_MCONFIG = 0x10,
MAX77705_PMIC_REG_MCONFIG2 = 0x11,
MAX77705_PMIC_REG_INTSRC = 0x22,
MAX77705_PMIC_REG_INTSRC_MASK = 0x23,
MAX77705_PMIC_REG_SYSTEM_INT = 0x24,
MAX77705_PMIC_REG_RESERVED_25 = 0x25,
MAX77705_PMIC_REG_SYSTEM_INT_MASK = 0x26,
MAX77705_PMIC_REG_RESERVED_27 = 0x27,
MAX77705_PMIC_REG_RESERVED_28 = 0x28,
MAX77705_PMIC_REG_RESERVED_29 = 0x29,
MAX77705_PMIC_REG_BOOSTCONTROL1 = 0x4C,
MAX77705_PMIC_REG_BOOSTCONTROL2 = 0x4F,
MAX77705_PMIC_REG_SW_RESET = 0x50,
MAX77705_PMIC_REG_USBC_RESET = 0x51,
MAX77705_PMIC_REG_END
};
enum max77705_chg_reg {
MAX77705_CHG_REG_BASE = 0xB0,
MAX77705_CHG_REG_INT = 0,
MAX77705_CHG_REG_INT_MASK,
MAX77705_CHG_REG_INT_OK,
MAX77705_CHG_REG_DETAILS_00,
MAX77705_CHG_REG_DETAILS_01,
MAX77705_CHG_REG_DETAILS_02,
MAX77705_CHG_REG_DTLS_03,
MAX77705_CHG_REG_CNFG_00,
MAX77705_CHG_REG_CNFG_01,
MAX77705_CHG_REG_CNFG_02,
MAX77705_CHG_REG_CNFG_03,
MAX77705_CHG_REG_CNFG_04,
MAX77705_CHG_REG_CNFG_05,
MAX77705_CHG_REG_CNFG_06,
MAX77705_CHG_REG_CNFG_07,
MAX77705_CHG_REG_CNFG_08,
MAX77705_CHG_REG_CNFG_09,
MAX77705_CHG_REG_CNFG_10,
MAX77705_CHG_REG_CNFG_11,
MAX77705_CHG_REG_CNFG_12,
MAX77705_CHG_REG_CNFG_13,
MAX77705_CHG_REG_CNFG_14,
MAX77705_CHG_REG_SAFEOUT_CTRL
};
enum max77705_fuelgauge_reg {
STATUS_REG = 0x00,
VALRT_THRESHOLD_REG = 0x01,
TALRT_THRESHOLD_REG = 0x02,
SALRT_THRESHOLD_REG = 0x03,
REMCAP_REP_REG = 0x05,
SOCREP_REG = 0x06,
TEMPERATURE_REG = 0x08,
VCELL_REG = 0x09,
TIME_TO_EMPTY_REG = 0x11,
FULLSOCTHR_REG = 0x13,
CURRENT_REG = 0x0A,
AVG_CURRENT_REG = 0x0B,
SOCMIX_REG = 0x0D,
SOCAV_REG = 0x0E,
REMCAP_MIX_REG = 0x0F,
FULLCAP_REG = 0x10,
RFAST_REG = 0x15,
AVR_TEMPERATURE_REG = 0x16,
CYCLES_REG = 0x17,
DESIGNCAP_REG = 0x18,
AVR_VCELL_REG = 0x19,
TIME_TO_FULL_REG = 0x20,
CONFIG_REG = 0x1D,
ICHGTERM_REG = 0x1E,
REMCAP_AV_REG = 0x1F,
FULLCAP_NOM_REG = 0x23,
LEARN_CFG_REG = 0x28,
FILTER_CFG_REG = 0x29,
MISCCFG_REG = 0x2B,
QRTABLE20_REG = 0x32,
FULLCAP_REP_REG = 0x35,
RCOMP_REG = 0x38,
VEMPTY_REG = 0x3A,
FSTAT_REG = 0x3D,
DISCHARGE_THRESHOLD_REG = 0x40,
QRTABLE30_REG = 0x42,
ISYS_REG = 0x43,
DQACC_REG = 0x45,
DPACC_REG = 0x46,
AVGISYS_REG = 0x4B,
QH_REG = 0x4D,
VSYS_REG = 0xB1,
TALRTTH2_REG = 0xB2,
VBYP_REG = 0xB3,
CONFIG2_REG = 0xBB,
IIN_REG = 0xD0,
OCV_REG = 0xEE,
VFOCV_REG = 0xFB,
VFSOC_REG = 0xFF,
MAX77705_FG_END
};
enum max77705_led_reg {
MAX77705_RGBLED_REG_BASE = 0x30,
MAX77705_RGBLED_REG_LEDEN = 0,
MAX77705_RGBLED_REG_LED0BRT,
MAX77705_RGBLED_REG_LED1BRT,
MAX77705_RGBLED_REG_LED2BRT,
MAX77705_RGBLED_REG_LED3BRT,
MAX77705_RGBLED_REG_LEDRMP,
MAX77705_RGBLED_REG_LEDBLNK,
MAX77705_LED_REG_END
};
enum max77705_charger_battery_state {
MAX77705_BATTERY_NOBAT,
MAX77705_BATTERY_PREQUALIFICATION,
MAX77705_BATTERY_DEAD,
MAX77705_BATTERY_GOOD,
MAX77705_BATTERY_LOWVOLTAGE,
MAX77705_BATTERY_OVERVOLTAGE,
MAX77705_BATTERY_RESERVED
};
enum max77705_charger_charge_type {
MAX77705_CHARGER_CONSTANT_CURRENT = 1,
MAX77705_CHARGER_CONSTANT_VOLTAGE,
MAX77705_CHARGER_END_OF_CHARGE,
MAX77705_CHARGER_DONE
};
#endif /* __LINUX_MFD_MAX77705_PRIV_H */

View File

@ -397,7 +397,6 @@ enum max8997_types {
};
extern int max8997_irq_init(struct max8997_dev *max8997);
extern void max8997_irq_exit(struct max8997_dev *max8997);
extern int max8997_irq_resume(struct max8997_dev *max8997);
extern int max8997_read_reg(struct i2c_client *i2c, u8 reg, u8 *dest);

View File

@ -1,69 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* adc.h -- Driver for NXP PCF50633 ADC
*
* (C) 2006-2008 by Openmoko, Inc.
* All rights reserved.
*/
#ifndef __LINUX_MFD_PCF50633_ADC_H
#define __LINUX_MFD_PCF50633_ADC_H
#include <linux/mfd/pcf50633/core.h>
#include <linux/platform_device.h>
/* ADC Registers */
#define PCF50633_REG_ADCC3 0x52
#define PCF50633_REG_ADCC2 0x53
#define PCF50633_REG_ADCC1 0x54
#define PCF50633_REG_ADCS1 0x55
#define PCF50633_REG_ADCS2 0x56
#define PCF50633_REG_ADCS3 0x57
#define PCF50633_ADCC1_ADCSTART 0x01
#define PCF50633_ADCC1_RES_8BIT 0x02
#define PCF50633_ADCC1_RES_10BIT 0x00
#define PCF50633_ADCC1_AVERAGE_NO 0x00
#define PCF50633_ADCC1_AVERAGE_4 0x04
#define PCF50633_ADCC1_AVERAGE_8 0x08
#define PCF50633_ADCC1_AVERAGE_16 0x0c
#define PCF50633_ADCC1_MUX_BATSNS_RES 0x00
#define PCF50633_ADCC1_MUX_BATSNS_SUBTR 0x10
#define PCF50633_ADCC1_MUX_ADCIN2_RES 0x20
#define PCF50633_ADCC1_MUX_ADCIN2_SUBTR 0x30
#define PCF50633_ADCC1_MUX_BATTEMP 0x60
#define PCF50633_ADCC1_MUX_ADCIN1 0x70
#define PCF50633_ADCC1_AVERAGE_MASK 0x0c
#define PCF50633_ADCC1_ADCMUX_MASK 0xf0
#define PCF50633_ADCC2_RATIO_NONE 0x00
#define PCF50633_ADCC2_RATIO_BATTEMP 0x01
#define PCF50633_ADCC2_RATIO_ADCIN1 0x02
#define PCF50633_ADCC2_RATIO_BOTH 0x03
#define PCF50633_ADCC2_RATIOSETTL_100US 0x04
#define PCF50633_ADCC3_ACCSW_EN 0x01
#define PCF50633_ADCC3_NTCSW_EN 0x04
#define PCF50633_ADCC3_RES_DIV_TWO 0x10
#define PCF50633_ADCC3_RES_DIV_THREE 0x00
#define PCF50633_ADCS3_REF_NTCSW 0x00
#define PCF50633_ADCS3_REF_ACCSW 0x10
#define PCF50633_ADCS3_REF_2V0 0x20
#define PCF50633_ADCS3_REF_VISA 0x30
#define PCF50633_ADCS3_REF_2V0_2 0x70
#define PCF50633_ADCS3_ADCRDY 0x80
#define PCF50633_ADCS3_ADCDAT1L_MASK 0x03
#define PCF50633_ADCS3_ADCDAT2L_MASK 0x0c
#define PCF50633_ADCS3_ADCDAT2L_SHIFT 2
#define PCF50633_ASCS3_REF_MASK 0x70
extern int
pcf50633_adc_async_read(struct pcf50633 *pcf, int mux, int avg,
void (*callback)(struct pcf50633 *, void *, int),
void *callback_param);
extern int
pcf50633_adc_sync_read(struct pcf50633 *pcf, int mux, int avg);
#endif /* __LINUX_PCF50633_ADC_H */

View File

@ -1,48 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* gpio.h -- GPIO driver for NXP PCF50633
*
* (C) 2006-2008 by Openmoko, Inc.
* All rights reserved.
*/
#ifndef __LINUX_MFD_PCF50633_GPIO_H
#define __LINUX_MFD_PCF50633_GPIO_H
#include <linux/mfd/pcf50633/core.h>
#define PCF50633_GPIO1 1
#define PCF50633_GPIO2 2
#define PCF50633_GPIO3 3
#define PCF50633_GPO 4
#define PCF50633_REG_GPIO1CFG 0x14
#define PCF50633_REG_GPIO2CFG 0x15
#define PCF50633_REG_GPIO3CFG 0x16
#define PCF50633_REG_GPOCFG 0x17
#define PCF50633_GPOCFG_GPOSEL_MASK 0x07
enum pcf50633_reg_gpocfg {
PCF50633_GPOCFG_GPOSEL_0 = 0x00,
PCF50633_GPOCFG_GPOSEL_LED_NFET = 0x01,
PCF50633_GPOCFG_GPOSEL_SYSxOK = 0x02,
PCF50633_GPOCFG_GPOSEL_CLK32K = 0x03,
PCF50633_GPOCFG_GPOSEL_ADAPUSB = 0x04,
PCF50633_GPOCFG_GPOSEL_USBxOK = 0x05,
PCF50633_GPOCFG_GPOSEL_ACTPH4 = 0x06,
PCF50633_GPOCFG_GPOSEL_1 = 0x07,
PCF50633_GPOCFG_GPOSEL_INVERSE = 0x08,
};
int pcf50633_gpio_set(struct pcf50633 *pcf, int gpio, u8 val);
u8 pcf50633_gpio_get(struct pcf50633 *pcf, int gpio);
int pcf50633_gpio_invert_set(struct pcf50633 *, int gpio, int invert);
int pcf50633_gpio_invert_get(struct pcf50633 *pcf, int gpio);
int pcf50633_gpio_power_supply_set(struct pcf50633 *,
int gpio, int regulator, int on);
#endif /* __LINUX_MFD_PCF50633_GPIO_H */

View File

@ -1,130 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* mbc.h -- Driver for NXP PCF50633 Main Battery Charger
*
* (C) 2006-2008 by Openmoko, Inc.
* All rights reserved.
*/
#ifndef __LINUX_MFD_PCF50633_MBC_H
#define __LINUX_MFD_PCF50633_MBC_H
#include <linux/mfd/pcf50633/core.h>
#include <linux/platform_device.h>
#define PCF50633_REG_MBCC1 0x43
#define PCF50633_REG_MBCC2 0x44
#define PCF50633_REG_MBCC3 0x45
#define PCF50633_REG_MBCC4 0x46
#define PCF50633_REG_MBCC5 0x47
#define PCF50633_REG_MBCC6 0x48
#define PCF50633_REG_MBCC7 0x49
#define PCF50633_REG_MBCC8 0x4a
#define PCF50633_REG_MBCS1 0x4b
#define PCF50633_REG_MBCS2 0x4c
#define PCF50633_REG_MBCS3 0x4d
enum pcf50633_reg_mbcc1 {
PCF50633_MBCC1_CHGENA = 0x01, /* Charger enable */
PCF50633_MBCC1_AUTOSTOP = 0x02,
PCF50633_MBCC1_AUTORES = 0x04, /* automatic resume */
PCF50633_MBCC1_RESUME = 0x08, /* explicit resume cmd */
PCF50633_MBCC1_RESTART = 0x10, /* restart charging */
PCF50633_MBCC1_PREWDTIME_60M = 0x20, /* max. precharging time */
PCF50633_MBCC1_WDTIME_1H = 0x00,
PCF50633_MBCC1_WDTIME_2H = 0x40,
PCF50633_MBCC1_WDTIME_4H = 0x80,
PCF50633_MBCC1_WDTIME_6H = 0xc0,
};
#define PCF50633_MBCC1_WDTIME_MASK 0xc0
enum pcf50633_reg_mbcc2 {
PCF50633_MBCC2_VBATCOND_2V7 = 0x00,
PCF50633_MBCC2_VBATCOND_2V85 = 0x01,
PCF50633_MBCC2_VBATCOND_3V0 = 0x02,
PCF50633_MBCC2_VBATCOND_3V15 = 0x03,
PCF50633_MBCC2_VMAX_4V = 0x00,
PCF50633_MBCC2_VMAX_4V20 = 0x28,
PCF50633_MBCC2_VRESDEBTIME_64S = 0x80, /* debounce time (32/64sec) */
};
enum pcf50633_reg_mbcc7 {
PCF50633_MBCC7_USB_100mA = 0x00,
PCF50633_MBCC7_USB_500mA = 0x01,
PCF50633_MBCC7_USB_1000mA = 0x02,
PCF50633_MBCC7_USB_SUSPEND = 0x03,
PCF50633_MBCC7_BATTEMP_EN = 0x04,
PCF50633_MBCC7_BATSYSIMAX_1A6 = 0x00,
PCF50633_MBCC7_BATSYSIMAX_1A8 = 0x40,
PCF50633_MBCC7_BATSYSIMAX_2A0 = 0x80,
PCF50633_MBCC7_BATSYSIMAX_2A2 = 0xc0,
};
#define PCF50633_MBCC7_USB_MASK 0x03
enum pcf50633_reg_mbcc8 {
PCF50633_MBCC8_USBENASUS = 0x10,
};
enum pcf50633_reg_mbcs1 {
PCF50633_MBCS1_USBPRES = 0x01,
PCF50633_MBCS1_USBOK = 0x02,
PCF50633_MBCS1_ADAPTPRES = 0x04,
PCF50633_MBCS1_ADAPTOK = 0x08,
PCF50633_MBCS1_TBAT_OK = 0x00,
PCF50633_MBCS1_TBAT_ABOVE = 0x10,
PCF50633_MBCS1_TBAT_BELOW = 0x20,
PCF50633_MBCS1_TBAT_UNDEF = 0x30,
PCF50633_MBCS1_PREWDTEXP = 0x40,
PCF50633_MBCS1_WDTEXP = 0x80,
};
enum pcf50633_reg_mbcs2_mbcmod {
PCF50633_MBCS2_MBC_PLAY = 0x00,
PCF50633_MBCS2_MBC_USB_PRE = 0x01,
PCF50633_MBCS2_MBC_USB_PRE_WAIT = 0x02,
PCF50633_MBCS2_MBC_USB_FAST = 0x03,
PCF50633_MBCS2_MBC_USB_FAST_WAIT = 0x04,
PCF50633_MBCS2_MBC_USB_SUSPEND = 0x05,
PCF50633_MBCS2_MBC_ADP_PRE = 0x06,
PCF50633_MBCS2_MBC_ADP_PRE_WAIT = 0x07,
PCF50633_MBCS2_MBC_ADP_FAST = 0x08,
PCF50633_MBCS2_MBC_ADP_FAST_WAIT = 0x09,
PCF50633_MBCS2_MBC_BAT_FULL = 0x0a,
PCF50633_MBCS2_MBC_HALT = 0x0b,
};
#define PCF50633_MBCS2_MBC_MASK 0x0f
enum pcf50633_reg_mbcs2_chgstat {
PCF50633_MBCS2_CHGS_NONE = 0x00,
PCF50633_MBCS2_CHGS_ADAPTER = 0x10,
PCF50633_MBCS2_CHGS_USB = 0x20,
PCF50633_MBCS2_CHGS_BOTH = 0x30,
};
#define PCF50633_MBCS2_RESSTAT_AUTO 0x40
enum pcf50633_reg_mbcs3 {
PCF50633_MBCS3_USBLIM_PLAY = 0x01,
PCF50633_MBCS3_USBLIM_CGH = 0x02,
PCF50633_MBCS3_TLIM_PLAY = 0x04,
PCF50633_MBCS3_TLIM_CHG = 0x08,
PCF50633_MBCS3_ILIM = 0x10, /* 1: Ibat > Icutoff */
PCF50633_MBCS3_VLIM = 0x20, /* 1: Vbat == Vmax */
PCF50633_MBCS3_VBATSTAT = 0x40, /* 1: Vbat > Vbatcond */
PCF50633_MBCS3_VRES = 0x80, /* 1: Vbat > Vth(RES) */
};
#define PCF50633_MBCC2_VBATCOND_MASK 0x03
#define PCF50633_MBCC2_VMAX_MASK 0x3c
/* Charger status */
#define PCF50633_MBC_USB_ONLINE 0x01
#define PCF50633_MBC_USB_ACTIVE 0x02
#define PCF50633_MBC_ADAPTER_ONLINE 0x04
#define PCF50633_MBC_ADAPTER_ACTIVE 0x08
int pcf50633_mbc_usb_curlim_set(struct pcf50633 *pcf, int ma);
int pcf50633_mbc_get_status(struct pcf50633 *);
int pcf50633_mbc_get_usb_online_status(struct pcf50633 *);
#endif

View File

@ -1,68 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __LINUX_MFD_PCF50633_PMIC_H
#define __LINUX_MFD_PCF50633_PMIC_H
#include <linux/mfd/pcf50633/core.h>
#include <linux/platform_device.h>
#define PCF50633_REG_AUTOOUT 0x1a
#define PCF50633_REG_AUTOENA 0x1b
#define PCF50633_REG_AUTOCTL 0x1c
#define PCF50633_REG_AUTOMXC 0x1d
#define PCF50633_REG_DOWN1OUT 0x1e
#define PCF50633_REG_DOWN1ENA 0x1f
#define PCF50633_REG_DOWN1CTL 0x20
#define PCF50633_REG_DOWN1MXC 0x21
#define PCF50633_REG_DOWN2OUT 0x22
#define PCF50633_REG_DOWN2ENA 0x23
#define PCF50633_REG_DOWN2CTL 0x24
#define PCF50633_REG_DOWN2MXC 0x25
#define PCF50633_REG_MEMLDOOUT 0x26
#define PCF50633_REG_MEMLDOENA 0x27
#define PCF50633_REG_LDO1OUT 0x2d
#define PCF50633_REG_LDO1ENA 0x2e
#define PCF50633_REG_LDO2OUT 0x2f
#define PCF50633_REG_LDO2ENA 0x30
#define PCF50633_REG_LDO3OUT 0x31
#define PCF50633_REG_LDO3ENA 0x32
#define PCF50633_REG_LDO4OUT 0x33
#define PCF50633_REG_LDO4ENA 0x34
#define PCF50633_REG_LDO5OUT 0x35
#define PCF50633_REG_LDO5ENA 0x36
#define PCF50633_REG_LDO6OUT 0x37
#define PCF50633_REG_LDO6ENA 0x38
#define PCF50633_REG_HCLDOOUT 0x39
#define PCF50633_REG_HCLDOENA 0x3a
#define PCF50633_REG_HCLDOOVL 0x40
enum pcf50633_regulator_enable {
PCF50633_REGULATOR_ON = 0x01,
PCF50633_REGULATOR_ON_GPIO1 = 0x02,
PCF50633_REGULATOR_ON_GPIO2 = 0x04,
PCF50633_REGULATOR_ON_GPIO3 = 0x08,
};
#define PCF50633_REGULATOR_ON_MASK 0x0f
enum pcf50633_regulator_phase {
PCF50633_REGULATOR_ACTPH1 = 0x00,
PCF50633_REGULATOR_ACTPH2 = 0x10,
PCF50633_REGULATOR_ACTPH3 = 0x20,
PCF50633_REGULATOR_ACTPH4 = 0x30,
};
#define PCF50633_REGULATOR_ACTPH_MASK 0x30
enum pcf50633_regulator_id {
PCF50633_REGULATOR_AUTO,
PCF50633_REGULATOR_DOWN1,
PCF50633_REGULATOR_DOWN2,
PCF50633_REGULATOR_LDO1,
PCF50633_REGULATOR_LDO2,
PCF50633_REGULATOR_LDO3,
PCF50633_REGULATOR_LDO4,
PCF50633_REGULATOR_LDO5,
PCF50633_REGULATOR_LDO6,
PCF50633_REGULATOR_HCLDO,
PCF50633_REGULATOR_MEMLDO,
};
#endif

View File

@ -44,6 +44,7 @@ enum sec_device_type {
S2MPS14X,
S2MPS15X,
S2MPU02,
S2MPU05,
};
/**

View File

@ -150,6 +150,50 @@ enum s2mpu02_irq {
/* Masks for interrupts are the same as in s2mps11 */
#define S2MPS14_IRQ_TSD_MASK (1 << 2)
enum s2mpu05_irq {
S2MPU05_IRQ_PWRONF,
S2MPU05_IRQ_PWRONR,
S2MPU05_IRQ_JIGONBF,
S2MPU05_IRQ_JIGONBR,
S2MPU05_IRQ_ACOKF,
S2MPU05_IRQ_ACOKR,
S2MPU05_IRQ_PWRON1S,
S2MPU05_IRQ_MRB,
S2MPU05_IRQ_RTC60S,
S2MPU05_IRQ_RTCA1,
S2MPU05_IRQ_RTCA0,
S2MPU05_IRQ_SMPL,
S2MPU05_IRQ_RTC1S,
S2MPU05_IRQ_WTSR,
S2MPU05_IRQ_INT120C,
S2MPU05_IRQ_INT140C,
S2MPU05_IRQ_TSD,
S2MPU05_IRQ_NR,
};
#define S2MPU05_IRQ_PWRONF_MASK BIT(0)
#define S2MPU05_IRQ_PWRONR_MASK BIT(1)
#define S2MPU05_IRQ_JIGONBF_MASK BIT(2)
#define S2MPU05_IRQ_JIGONBR_MASK BIT(3)
#define S2MPU05_IRQ_ACOKF_MASK BIT(4)
#define S2MPU05_IRQ_ACOKR_MASK BIT(5)
#define S2MPU05_IRQ_PWRON1S_MASK BIT(6)
#define S2MPU05_IRQ_MRB_MASK BIT(7)
#define S2MPU05_IRQ_RTC60S_MASK BIT(0)
#define S2MPU05_IRQ_RTCA1_MASK BIT(1)
#define S2MPU05_IRQ_RTCA0_MASK BIT(2)
#define S2MPU05_IRQ_SMPL_MASK BIT(3)
#define S2MPU05_IRQ_RTC1S_MASK BIT(4)
#define S2MPU05_IRQ_WTSR_MASK BIT(5)
#define S2MPU05_IRQ_INT120C_MASK BIT(0)
#define S2MPU05_IRQ_INT140C_MASK BIT(1)
#define S2MPU05_IRQ_TSD_MASK BIT(2)
enum s5m8767_irq {
S5M8767_IRQ_PWRR,
S5M8767_IRQ_PWRF,

View File

@ -0,0 +1,183 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Copyright (c) 2015 Samsung Electronics Co., Ltd
* Copyright (c) 2025 Kaustabh Chakraborty <kauschluss@disroot.org>
*/
#ifndef __LINUX_MFD_S2MPU05_H
#define __LINUX_MFD_S2MPU05_H
/* S2MPU05 registers */
enum S2MPU05_reg {
S2MPU05_REG_ID,
S2MPU05_REG_INT1,
S2MPU05_REG_INT2,
S2MPU05_REG_INT3,
S2MPU05_REG_INT1M,
S2MPU05_REG_INT2M,
S2MPU05_REG_INT3M,
S2MPU05_REG_ST1,
S2MPU05_REG_ST2,
S2MPU05_REG_PWRONSRC,
S2MPU05_REG_OFFSRC,
S2MPU05_REG_BU_CHG,
S2MPU05_REG_RTC_BUF,
S2MPU05_REG_CTRL1,
S2MPU05_REG_CTRL2,
S2MPU05_REG_ETC_TEST,
S2MPU05_REG_OTP_ADRL,
S2MPU05_REG_OTP_ADRH,
S2MPU05_REG_OTP_DATA,
S2MPU05_REG_MON1SEL,
S2MPU05_REG_MON2SEL,
S2MPU05_REG_CTRL3,
S2MPU05_REG_ETC_OTP,
S2MPU05_REG_UVLO,
S2MPU05_REG_TIME_CTRL1,
S2MPU05_REG_TIME_CTRL2,
S2MPU05_REG_B1CTRL1,
S2MPU05_REG_B1CTRL2,
S2MPU05_REG_B2CTRL1,
S2MPU05_REG_B2CTRL2,
S2MPU05_REG_B2CTRL3,
S2MPU05_REG_B2CTRL4,
S2MPU05_REG_B3CTRL1,
S2MPU05_REG_B3CTRL2,
S2MPU05_REG_B3CTRL3,
S2MPU05_REG_B4CTRL1,
S2MPU05_REG_B4CTRL2,
S2MPU05_REG_B5CTRL1,
S2MPU05_REG_B5CTRL2,
S2MPU05_REG_BUCK_RAMP,
S2MPU05_REG_LDO_DVS1,
S2MPU05_REG_LDO_DVS9,
S2MPU05_REG_LDO_DVS10,
S2MPU05_REG_L1CTRL,
S2MPU05_REG_L2CTRL,
S2MPU05_REG_L3CTRL,
S2MPU05_REG_L4CTRL,
S2MPU05_REG_L5CTRL,
S2MPU05_REG_L6CTRL,
S2MPU05_REG_L7CTRL,
S2MPU05_REG_L8CTRL,
S2MPU05_REG_L9CTRL1,
S2MPU05_REG_L9CTRL2,
S2MPU05_REG_L10CTRL,
S2MPU05_REG_L11CTRL1,
S2MPU05_REG_L11CTRL2,
S2MPU05_REG_L12CTRL,
S2MPU05_REG_L13CTRL,
S2MPU05_REG_L14CTRL,
S2MPU05_REG_L15CTRL,
S2MPU05_REG_L16CTRL,
S2MPU05_REG_L17CTRL1,
S2MPU05_REG_L17CTRL2,
S2MPU05_REG_L18CTRL1,
S2MPU05_REG_L18CTRL2,
S2MPU05_REG_L19CTRL,
S2MPU05_REG_L20CTRL,
S2MPU05_REG_L21CTRL,
S2MPU05_REG_L22CTRL,
S2MPU05_REG_L23CTRL,
S2MPU05_REG_L24CTRL,
S2MPU05_REG_L25CTRL,
S2MPU05_REG_L26CTRL,
S2MPU05_REG_L27CTRL,
S2MPU05_REG_L28CTRL,
S2MPU05_REG_L29CTRL,
S2MPU05_REG_L30CTRL,
S2MPU05_REG_L31CTRL,
S2MPU05_REG_L32CTRL,
S2MPU05_REG_L33CTRL,
S2MPU05_REG_L34CTRL,
S2MPU05_REG_L35CTRL,
S2MPU05_REG_LDO_DSCH1,
S2MPU05_REG_LDO_DSCH2,
S2MPU05_REG_LDO_DSCH3,
S2MPU05_REG_LDO_DSCH4,
S2MPU05_REG_LDO_DSCH5,
S2MPU05_REG_LDO_CTRL1,
S2MPU05_REG_LDO_CTRL2,
S2MPU05_REG_TCXO_CTRL,
S2MPU05_REG_SELMIF,
};
/* S2MPU05 regulator ids */
enum S2MPU05_regulators {
S2MPU05_LDO1,
S2MPU05_LDO2,
S2MPU05_LDO3,
S2MPU05_LDO4,
S2MPU05_LDO5,
S2MPU05_LDO6,
S2MPU05_LDO7,
S2MPU05_LDO8,
S2MPU05_LDO9,
S2MPU05_LDO10,
S2MPU05_LDO11,
S2MPU05_LDO12,
S2MPU05_LDO13,
S2MPU05_LDO14,
S2MPU05_LDO15,
S2MPU05_LDO16,
S2MPU05_LDO17,
S2MPU05_LDO18,
S2MPU05_LDO19,
S2MPU05_LDO20,
S2MPU05_LDO21,
S2MPU05_LDO22,
S2MPU05_LDO23,
S2MPU05_LDO24,
S2MPU05_LDO25,
S2MPU05_LDO26,
S2MPU05_LDO27,
S2MPU05_LDO28,
S2MPU05_LDO29,
S2MPU05_LDO30,
S2MPU05_LDO31,
S2MPU05_LDO32,
S2MPU05_LDO33,
S2MPU05_LDO34,
S2MPU05_LDO35,
S2MPU05_BUCK1,
S2MPU05_BUCK2,
S2MPU05_BUCK3,
S2MPU05_BUCK4,
S2MPU05_BUCK5,
S2MPU05_REGULATOR_MAX,
};
#define S2MPU05_SW_ENABLE_MASK 0x03
#define S2MPU05_ENABLE_TIME_LDO 128
#define S2MPU05_ENABLE_TIME_BUCK1 110
#define S2MPU05_ENABLE_TIME_BUCK2 110
#define S2MPU05_ENABLE_TIME_BUCK3 110
#define S2MPU05_ENABLE_TIME_BUCK4 150
#define S2MPU05_ENABLE_TIME_BUCK5 150
#define S2MPU05_LDO_MIN1 800000
#define S2MPU05_LDO_MIN2 1800000
#define S2MPU05_LDO_MIN3 400000
#define S2MPU05_LDO_STEP1 12500
#define S2MPU05_LDO_STEP2 25000
#define S2MPU05_BUCK_MIN1 400000
#define S2MPU05_BUCK_MIN2 600000
#define S2MPU05_BUCK_STEP1 6250
#define S2MPU05_BUCK_STEP2 12500
#define S2MPU05_RAMP_DELAY 12000 /* uV/uS */
#define S2MPU05_ENABLE_SHIFT 6
#define S2MPU05_ENABLE_MASK (0x03 << S2MPU05_ENABLE_SHIFT)
#define S2MPU05_LDO_VSEL_MASK 0x3F
#define S2MPU05_BUCK_VSEL_MASK 0xFF
#define S2MPU05_LDO_N_VOLTAGES (S2MPU05_LDO_VSEL_MASK + 1)
#define S2MPU05_BUCK_N_VOLTAGES (S2MPU05_BUCK_VSEL_MASK + 1)
#define S2MPU05_PMIC_EN_SHIFT 6
#endif /* __LINUX_MFD_S2MPU05_H */

View File

@ -1,506 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2009-2011 Wind River Systems, Inc.
* Copyright (c) 2011 ST Microelectronics (Alessandro Rubini)
*
* The STMicroelectronics ConneXt (STA2X11) chip has several unrelated
* functions in one PCI endpoint functions. This driver simply
* registers the platform devices in this iomemregion and exports a few
* functions to access common registers
*/
#ifndef __STA2X11_MFD_H
#define __STA2X11_MFD_H
#include <linux/types.h>
#include <linux/pci.h>
enum sta2x11_mfd_plat_dev {
sta2x11_sctl = 0,
sta2x11_gpio,
sta2x11_scr,
sta2x11_time,
sta2x11_apbreg,
sta2x11_apb_soc_regs,
sta2x11_vic,
sta2x11_n_mfd_plat_devs,
};
#define STA2X11_MFD_SCTL_NAME "sta2x11-sctl"
#define STA2X11_MFD_GPIO_NAME "sta2x11-gpio"
#define STA2X11_MFD_SCR_NAME "sta2x11-scr"
#define STA2X11_MFD_TIME_NAME "sta2x11-time"
#define STA2X11_MFD_APBREG_NAME "sta2x11-apbreg"
#define STA2X11_MFD_APB_SOC_REGS_NAME "sta2x11-apb-soc-regs"
#define STA2X11_MFD_VIC_NAME "sta2x11-vic"
extern u32
__sta2x11_mfd_mask(struct pci_dev *, u32, u32, u32, enum sta2x11_mfd_plat_dev);
/*
* The MFD PCI block includes the GPIO peripherals and other register blocks.
* For GPIO, we have 32*4 bits (I use "gsta" for "gpio sta2x11".)
*/
#define GSTA_GPIO_PER_BLOCK 32
#define GSTA_NR_BLOCKS 4
#define GSTA_NR_GPIO (GSTA_GPIO_PER_BLOCK * GSTA_NR_BLOCKS)
/* Pinconfig is set by the board definition: altfunc, pull-up, pull-down */
struct sta2x11_gpio_pdata {
unsigned pinconfig[GSTA_NR_GPIO];
};
/* Macros below lifted from sh_pfc.h, with minor differences */
#define PINMUX_TYPE_NONE 0
#define PINMUX_TYPE_FUNCTION 1
#define PINMUX_TYPE_OUTPUT_LOW 2
#define PINMUX_TYPE_OUTPUT_HIGH 3
#define PINMUX_TYPE_INPUT 4
#define PINMUX_TYPE_INPUT_PULLUP 5
#define PINMUX_TYPE_INPUT_PULLDOWN 6
/* Give names to GPIO pins, like PXA does, taken from the manual */
#define STA2X11_GPIO0 0
#define STA2X11_GPIO1 1
#define STA2X11_GPIO2 2
#define STA2X11_GPIO3 3
#define STA2X11_GPIO4 4
#define STA2X11_GPIO5 5
#define STA2X11_GPIO6 6
#define STA2X11_GPIO7 7
#define STA2X11_GPIO8_RGBOUT_RED7 8
#define STA2X11_GPIO9_RGBOUT_RED6 9
#define STA2X11_GPIO10_RGBOUT_RED5 10
#define STA2X11_GPIO11_RGBOUT_RED4 11
#define STA2X11_GPIO12_RGBOUT_RED3 12
#define STA2X11_GPIO13_RGBOUT_RED2 13
#define STA2X11_GPIO14_RGBOUT_RED1 14
#define STA2X11_GPIO15_RGBOUT_RED0 15
#define STA2X11_GPIO16_RGBOUT_GREEN7 16
#define STA2X11_GPIO17_RGBOUT_GREEN6 17
#define STA2X11_GPIO18_RGBOUT_GREEN5 18
#define STA2X11_GPIO19_RGBOUT_GREEN4 19
#define STA2X11_GPIO20_RGBOUT_GREEN3 20
#define STA2X11_GPIO21_RGBOUT_GREEN2 21
#define STA2X11_GPIO22_RGBOUT_GREEN1 22
#define STA2X11_GPIO23_RGBOUT_GREEN0 23
#define STA2X11_GPIO24_RGBOUT_BLUE7 24
#define STA2X11_GPIO25_RGBOUT_BLUE6 25
#define STA2X11_GPIO26_RGBOUT_BLUE5 26
#define STA2X11_GPIO27_RGBOUT_BLUE4 27
#define STA2X11_GPIO28_RGBOUT_BLUE3 28
#define STA2X11_GPIO29_RGBOUT_BLUE2 29
#define STA2X11_GPIO30_RGBOUT_BLUE1 30
#define STA2X11_GPIO31_RGBOUT_BLUE0 31
#define STA2X11_GPIO32_RGBOUT_VSYNCH 32
#define STA2X11_GPIO33_RGBOUT_HSYNCH 33
#define STA2X11_GPIO34_RGBOUT_DEN 34
#define STA2X11_GPIO35_ETH_CRS_DV 35
#define STA2X11_GPIO36_ETH_TXD1 36
#define STA2X11_GPIO37_ETH_TXD0 37
#define STA2X11_GPIO38_ETH_TX_EN 38
#define STA2X11_GPIO39_MDIO 39
#define STA2X11_GPIO40_ETH_REF_CLK 40
#define STA2X11_GPIO41_ETH_RXD1 41
#define STA2X11_GPIO42_ETH_RXD0 42
#define STA2X11_GPIO43_MDC 43
#define STA2X11_GPIO44_CAN_TX 44
#define STA2X11_GPIO45_CAN_RX 45
#define STA2X11_GPIO46_MLB_DAT 46
#define STA2X11_GPIO47_MLB_SIG 47
#define STA2X11_GPIO48_SPI0_CLK 48
#define STA2X11_GPIO49_SPI0_TXD 49
#define STA2X11_GPIO50_SPI0_RXD 50
#define STA2X11_GPIO51_SPI0_FRM 51
#define STA2X11_GPIO52_SPI1_CLK 52
#define STA2X11_GPIO53_SPI1_TXD 53
#define STA2X11_GPIO54_SPI1_RXD 54
#define STA2X11_GPIO55_SPI1_FRM 55
#define STA2X11_GPIO56_SPI2_CLK 56
#define STA2X11_GPIO57_SPI2_TXD 57
#define STA2X11_GPIO58_SPI2_RXD 58
#define STA2X11_GPIO59_SPI2_FRM 59
#define STA2X11_GPIO60_I2C0_SCL 60
#define STA2X11_GPIO61_I2C0_SDA 61
#define STA2X11_GPIO62_I2C1_SCL 62
#define STA2X11_GPIO63_I2C1_SDA 63
#define STA2X11_GPIO64_I2C2_SCL 64
#define STA2X11_GPIO65_I2C2_SDA 65
#define STA2X11_GPIO66_I2C3_SCL 66
#define STA2X11_GPIO67_I2C3_SDA 67
#define STA2X11_GPIO68_MSP0_RCK 68
#define STA2X11_GPIO69_MSP0_RXD 69
#define STA2X11_GPIO70_MSP0_RFS 70
#define STA2X11_GPIO71_MSP0_TCK 71
#define STA2X11_GPIO72_MSP0_TXD 72
#define STA2X11_GPIO73_MSP0_TFS 73
#define STA2X11_GPIO74_MSP0_SCK 74
#define STA2X11_GPIO75_MSP1_CK 75
#define STA2X11_GPIO76_MSP1_RXD 76
#define STA2X11_GPIO77_MSP1_FS 77
#define STA2X11_GPIO78_MSP1_TXD 78
#define STA2X11_GPIO79_MSP2_CK 79
#define STA2X11_GPIO80_MSP2_RXD 80
#define STA2X11_GPIO81_MSP2_FS 81
#define STA2X11_GPIO82_MSP2_TXD 82
#define STA2X11_GPIO83_MSP3_CK 83
#define STA2X11_GPIO84_MSP3_RXD 84
#define STA2X11_GPIO85_MSP3_FS 85
#define STA2X11_GPIO86_MSP3_TXD 86
#define STA2X11_GPIO87_MSP4_CK 87
#define STA2X11_GPIO88_MSP4_RXD 88
#define STA2X11_GPIO89_MSP4_FS 89
#define STA2X11_GPIO90_MSP4_TXD 90
#define STA2X11_GPIO91_MSP5_CK 91
#define STA2X11_GPIO92_MSP5_RXD 92
#define STA2X11_GPIO93_MSP5_FS 93
#define STA2X11_GPIO94_MSP5_TXD 94
#define STA2X11_GPIO95_SDIO3_DAT3 95
#define STA2X11_GPIO96_SDIO3_DAT2 96
#define STA2X11_GPIO97_SDIO3_DAT1 97
#define STA2X11_GPIO98_SDIO3_DAT0 98
#define STA2X11_GPIO99_SDIO3_CLK 99
#define STA2X11_GPIO100_SDIO3_CMD 100
#define STA2X11_GPIO101 101
#define STA2X11_GPIO102 102
#define STA2X11_GPIO103 103
#define STA2X11_GPIO104 104
#define STA2X11_GPIO105_SDIO2_DAT3 105
#define STA2X11_GPIO106_SDIO2_DAT2 106
#define STA2X11_GPIO107_SDIO2_DAT1 107
#define STA2X11_GPIO108_SDIO2_DAT0 108
#define STA2X11_GPIO109_SDIO2_CLK 109
#define STA2X11_GPIO110_SDIO2_CMD 110
#define STA2X11_GPIO111 111
#define STA2X11_GPIO112 112
#define STA2X11_GPIO113 113
#define STA2X11_GPIO114 114
#define STA2X11_GPIO115_SDIO1_DAT3 115
#define STA2X11_GPIO116_SDIO1_DAT2 116
#define STA2X11_GPIO117_SDIO1_DAT1 117
#define STA2X11_GPIO118_SDIO1_DAT0 118
#define STA2X11_GPIO119_SDIO1_CLK 119
#define STA2X11_GPIO120_SDIO1_CMD 120
#define STA2X11_GPIO121 121
#define STA2X11_GPIO122 122
#define STA2X11_GPIO123 123
#define STA2X11_GPIO124 124
#define STA2X11_GPIO125_UART2_TXD 125
#define STA2X11_GPIO126_UART2_RXD 126
#define STA2X11_GPIO127_UART3_TXD 127
/*
* The APB bridge has its own registers, needed by our users as well.
* They are accessed with the following read/mask/write function.
*/
static inline u32
sta2x11_apbreg_mask(struct pci_dev *pdev, u32 reg, u32 mask, u32 val)
{
return __sta2x11_mfd_mask(pdev, reg, mask, val, sta2x11_apbreg);
}
/* CAN and MLB */
#define APBREG_BSR 0x00 /* Bridge Status Reg */
#define APBREG_PAER 0x08 /* Peripherals Address Error Reg */
#define APBREG_PWAC 0x20 /* Peripheral Write Access Control reg */
#define APBREG_PRAC 0x40 /* Peripheral Read Access Control reg */
#define APBREG_PCG 0x60 /* Peripheral Clock Gating Reg */
#define APBREG_PUR 0x80 /* Peripheral Under Reset Reg */
#define APBREG_EMU_PCG 0xA0 /* Emulator Peripheral Clock Gating Reg */
#define APBREG_CAN (1 << 1)
#define APBREG_MLB (1 << 3)
/* SARAC */
#define APBREG_BSR_SARAC 0x100 /* Bridge Status Reg */
#define APBREG_PAER_SARAC 0x108 /* Peripherals Address Error Reg */
#define APBREG_PWAC_SARAC 0x120 /* Peripheral Write Access Control reg */
#define APBREG_PRAC_SARAC 0x140 /* Peripheral Read Access Control reg */
#define APBREG_PCG_SARAC 0x160 /* Peripheral Clock Gating Reg */
#define APBREG_PUR_SARAC 0x180 /* Peripheral Under Reset Reg */
#define APBREG_EMU_PCG_SARAC 0x1A0 /* Emulator Peripheral Clock Gating Reg */
#define APBREG_SARAC (1 << 2)
/*
* The system controller has its own registers. Some of these are accessed
* by out users as well, using the following read/mask/write/function
*/
static inline
u32 sta2x11_sctl_mask(struct pci_dev *pdev, u32 reg, u32 mask, u32 val)
{
return __sta2x11_mfd_mask(pdev, reg, mask, val, sta2x11_sctl);
}
#define SCTL_SCCTL 0x00 /* System controller control register */
#define SCTL_ARMCFG 0x04 /* ARM configuration register */
#define SCTL_SCPLLCTL 0x08 /* PLL control status register */
#define SCTL_SCPLLCTL_AUDIO_PLL_PD BIT(1)
#define SCTL_SCPLLCTL_FRAC_CONTROL BIT(3)
#define SCTL_SCPLLCTL_STRB_BYPASS BIT(6)
#define SCTL_SCPLLCTL_STRB_INPUT BIT(8)
#define SCTL_SCPLLFCTRL 0x0c /* PLL frequency control register */
#define SCTL_SCPLLFCTRL_AUDIO_PLL_NDIV_MASK 0xff
#define SCTL_SCPLLFCTRL_AUDIO_PLL_NDIV_SHIFT 10
#define SCTL_SCPLLFCTRL_AUDIO_PLL_IDF_MASK 7
#define SCTL_SCPLLFCTRL_AUDIO_PLL_IDF_SHIFT 21
#define SCTL_SCPLLFCTRL_AUDIO_PLL_ODF_MASK 7
#define SCTL_SCPLLFCTRL_AUDIO_PLL_ODF_SHIFT 18
#define SCTL_SCPLLFCTRL_DITHER_DISABLE_MASK 0x03
#define SCTL_SCPLLFCTRL_DITHER_DISABLE_SHIFT 4
#define SCTL_SCRESFRACT 0x10 /* PLL fractional input register */
#define SCTL_SCRESFRACT_MASK 0x0000ffff
#define SCTL_SCRESCTRL1 0x14 /* Peripheral reset control 1 */
#define SCTL_SCRESXTRL2 0x18 /* Peripheral reset control 2 */
#define SCTL_SCPEREN0 0x1c /* Peripheral clock enable register 0 */
#define SCTL_SCPEREN1 0x20 /* Peripheral clock enable register 1 */
#define SCTL_SCPEREN2 0x24 /* Peripheral clock enable register 2 */
#define SCTL_SCGRST 0x28 /* Peripheral global reset */
#define SCTL_SCPCIECSBRST 0x2c /* PCIe PAB CSB reset status register */
#define SCTL_SCPCIPMCR1 0x30 /* PCI power management control 1 */
#define SCTL_SCPCIPMCR2 0x34 /* PCI power management control 2 */
#define SCTL_SCPCIPMSR1 0x38 /* PCI power management status 1 */
#define SCTL_SCPCIPMSR2 0x3c /* PCI power management status 2 */
#define SCTL_SCPCIPMSR3 0x40 /* PCI power management status 3 */
#define SCTL_SCINTREN 0x44 /* Interrupt enable */
#define SCTL_SCRISR 0x48 /* RAW interrupt status */
#define SCTL_SCCLKSTAT0 0x4c /* Peripheral clocks status 0 */
#define SCTL_SCCLKSTAT1 0x50 /* Peripheral clocks status 1 */
#define SCTL_SCCLKSTAT2 0x54 /* Peripheral clocks status 2 */
#define SCTL_SCRSTSTA 0x58 /* Reset status register */
#define SCTL_SCRESCTRL1_USB_PHY_POR (1 << 0)
#define SCTL_SCRESCTRL1_USB_OTG (1 << 1)
#define SCTL_SCRESCTRL1_USB_HRST (1 << 2)
#define SCTL_SCRESCTRL1_USB_PHY_HOST (1 << 3)
#define SCTL_SCRESCTRL1_SATAII (1 << 4)
#define SCTL_SCRESCTRL1_VIP (1 << 5)
#define SCTL_SCRESCTRL1_PER_MMC0 (1 << 6)
#define SCTL_SCRESCTRL1_PER_MMC1 (1 << 7)
#define SCTL_SCRESCTRL1_PER_GPIO0 (1 << 8)
#define SCTL_SCRESCTRL1_PER_GPIO1 (1 << 9)
#define SCTL_SCRESCTRL1_PER_GPIO2 (1 << 10)
#define SCTL_SCRESCTRL1_PER_GPIO3 (1 << 11)
#define SCTL_SCRESCTRL1_PER_MTU0 (1 << 12)
#define SCTL_SCRESCTRL1_KER_SPI0 (1 << 13)
#define SCTL_SCRESCTRL1_KER_SPI1 (1 << 14)
#define SCTL_SCRESCTRL1_KER_SPI2 (1 << 15)
#define SCTL_SCRESCTRL1_KER_MCI0 (1 << 16)
#define SCTL_SCRESCTRL1_KER_MCI1 (1 << 17)
#define SCTL_SCRESCTRL1_PRE_HSI2C0 (1 << 18)
#define SCTL_SCRESCTRL1_PER_HSI2C1 (1 << 19)
#define SCTL_SCRESCTRL1_PER_HSI2C2 (1 << 20)
#define SCTL_SCRESCTRL1_PER_HSI2C3 (1 << 21)
#define SCTL_SCRESCTRL1_PER_MSP0 (1 << 22)
#define SCTL_SCRESCTRL1_PER_MSP1 (1 << 23)
#define SCTL_SCRESCTRL1_PER_MSP2 (1 << 24)
#define SCTL_SCRESCTRL1_PER_MSP3 (1 << 25)
#define SCTL_SCRESCTRL1_PER_MSP4 (1 << 26)
#define SCTL_SCRESCTRL1_PER_MSP5 (1 << 27)
#define SCTL_SCRESCTRL1_PER_MMC (1 << 28)
#define SCTL_SCRESCTRL1_KER_MSP0 (1 << 29)
#define SCTL_SCRESCTRL1_KER_MSP1 (1 << 30)
#define SCTL_SCRESCTRL1_KER_MSP2 (1 << 31)
#define SCTL_SCPEREN0_UART0 (1 << 0)
#define SCTL_SCPEREN0_UART1 (1 << 1)
#define SCTL_SCPEREN0_UART2 (1 << 2)
#define SCTL_SCPEREN0_UART3 (1 << 3)
#define SCTL_SCPEREN0_MSP0 (1 << 4)
#define SCTL_SCPEREN0_MSP1 (1 << 5)
#define SCTL_SCPEREN0_MSP2 (1 << 6)
#define SCTL_SCPEREN0_MSP3 (1 << 7)
#define SCTL_SCPEREN0_MSP4 (1 << 8)
#define SCTL_SCPEREN0_MSP5 (1 << 9)
#define SCTL_SCPEREN0_SPI0 (1 << 10)
#define SCTL_SCPEREN0_SPI1 (1 << 11)
#define SCTL_SCPEREN0_SPI2 (1 << 12)
#define SCTL_SCPEREN0_I2C0 (1 << 13)
#define SCTL_SCPEREN0_I2C1 (1 << 14)
#define SCTL_SCPEREN0_I2C2 (1 << 15)
#define SCTL_SCPEREN0_I2C3 (1 << 16)
#define SCTL_SCPEREN0_SVDO_LVDS (1 << 17)
#define SCTL_SCPEREN0_USB_HOST (1 << 18)
#define SCTL_SCPEREN0_USB_OTG (1 << 19)
#define SCTL_SCPEREN0_MCI0 (1 << 20)
#define SCTL_SCPEREN0_MCI1 (1 << 21)
#define SCTL_SCPEREN0_MCI2 (1 << 22)
#define SCTL_SCPEREN0_MCI3 (1 << 23)
#define SCTL_SCPEREN0_SATA (1 << 24)
#define SCTL_SCPEREN0_ETHERNET (1 << 25)
#define SCTL_SCPEREN0_VIC (1 << 26)
#define SCTL_SCPEREN0_DMA_AUDIO (1 << 27)
#define SCTL_SCPEREN0_DMA_SOC (1 << 28)
#define SCTL_SCPEREN0_RAM (1 << 29)
#define SCTL_SCPEREN0_VIP (1 << 30)
#define SCTL_SCPEREN0_ARM (1 << 31)
#define SCTL_SCPEREN1_UART0 (1 << 0)
#define SCTL_SCPEREN1_UART1 (1 << 1)
#define SCTL_SCPEREN1_UART2 (1 << 2)
#define SCTL_SCPEREN1_UART3 (1 << 3)
#define SCTL_SCPEREN1_MSP0 (1 << 4)
#define SCTL_SCPEREN1_MSP1 (1 << 5)
#define SCTL_SCPEREN1_MSP2 (1 << 6)
#define SCTL_SCPEREN1_MSP3 (1 << 7)
#define SCTL_SCPEREN1_MSP4 (1 << 8)
#define SCTL_SCPEREN1_MSP5 (1 << 9)
#define SCTL_SCPEREN1_SPI0 (1 << 10)
#define SCTL_SCPEREN1_SPI1 (1 << 11)
#define SCTL_SCPEREN1_SPI2 (1 << 12)
#define SCTL_SCPEREN1_I2C0 (1 << 13)
#define SCTL_SCPEREN1_I2C1 (1 << 14)
#define SCTL_SCPEREN1_I2C2 (1 << 15)
#define SCTL_SCPEREN1_I2C3 (1 << 16)
#define SCTL_SCPEREN1_USB_PHY (1 << 17)
/*
* APB-SOC registers
*/
static inline
u32 sta2x11_apb_soc_regs_mask(struct pci_dev *pdev, u32 reg, u32 mask, u32 val)
{
return __sta2x11_mfd_mask(pdev, reg, mask, val, sta2x11_apb_soc_regs);
}
#define PCIE_EP1_FUNC3_0_INTR_REG 0x000
#define PCIE_EP1_FUNC7_4_INTR_REG 0x004
#define PCIE_EP2_FUNC3_0_INTR_REG 0x008
#define PCIE_EP2_FUNC7_4_INTR_REG 0x00c
#define PCIE_EP3_FUNC3_0_INTR_REG 0x010
#define PCIE_EP3_FUNC7_4_INTR_REG 0x014
#define PCIE_EP4_FUNC3_0_INTR_REG 0x018
#define PCIE_EP4_FUNC7_4_INTR_REG 0x01c
#define PCIE_INTR_ENABLE0_REG 0x020
#define PCIE_INTR_ENABLE1_REG 0x024
#define PCIE_EP1_FUNC_TC_REG 0x028
#define PCIE_EP2_FUNC_TC_REG 0x02c
#define PCIE_EP3_FUNC_TC_REG 0x030
#define PCIE_EP4_FUNC_TC_REG 0x034
#define PCIE_EP1_FUNC_F_REG 0x038
#define PCIE_EP2_FUNC_F_REG 0x03c
#define PCIE_EP3_FUNC_F_REG 0x040
#define PCIE_EP4_FUNC_F_REG 0x044
#define PCIE_PAB_AMBA_SW_RST_REG 0x048
#define PCIE_PM_STATUS_0_PORT_0_4 0x04c
#define PCIE_PM_STATUS_7_0_EP1 0x050
#define PCIE_PM_STATUS_7_0_EP2 0x054
#define PCIE_PM_STATUS_7_0_EP3 0x058
#define PCIE_PM_STATUS_7_0_EP4 0x05c
#define PCIE_DEV_ID_0_EP1_REG 0x060
#define PCIE_CC_REV_ID_0_EP1_REG 0x064
#define PCIE_DEV_ID_1_EP1_REG 0x068
#define PCIE_CC_REV_ID_1_EP1_REG 0x06c
#define PCIE_DEV_ID_2_EP1_REG 0x070
#define PCIE_CC_REV_ID_2_EP1_REG 0x074
#define PCIE_DEV_ID_3_EP1_REG 0x078
#define PCIE_CC_REV_ID_3_EP1_REG 0x07c
#define PCIE_DEV_ID_4_EP1_REG 0x080
#define PCIE_CC_REV_ID_4_EP1_REG 0x084
#define PCIE_DEV_ID_5_EP1_REG 0x088
#define PCIE_CC_REV_ID_5_EP1_REG 0x08c
#define PCIE_DEV_ID_6_EP1_REG 0x090
#define PCIE_CC_REV_ID_6_EP1_REG 0x094
#define PCIE_DEV_ID_7_EP1_REG 0x098
#define PCIE_CC_REV_ID_7_EP1_REG 0x09c
#define PCIE_DEV_ID_0_EP2_REG 0x0a0
#define PCIE_CC_REV_ID_0_EP2_REG 0x0a4
#define PCIE_DEV_ID_1_EP2_REG 0x0a8
#define PCIE_CC_REV_ID_1_EP2_REG 0x0ac
#define PCIE_DEV_ID_2_EP2_REG 0x0b0
#define PCIE_CC_REV_ID_2_EP2_REG 0x0b4
#define PCIE_DEV_ID_3_EP2_REG 0x0b8
#define PCIE_CC_REV_ID_3_EP2_REG 0x0bc
#define PCIE_DEV_ID_4_EP2_REG 0x0c0
#define PCIE_CC_REV_ID_4_EP2_REG 0x0c4
#define PCIE_DEV_ID_5_EP2_REG 0x0c8
#define PCIE_CC_REV_ID_5_EP2_REG 0x0cc
#define PCIE_DEV_ID_6_EP2_REG 0x0d0
#define PCIE_CC_REV_ID_6_EP2_REG 0x0d4
#define PCIE_DEV_ID_7_EP2_REG 0x0d8
#define PCIE_CC_REV_ID_7_EP2_REG 0x0dC
#define PCIE_DEV_ID_0_EP3_REG 0x0e0
#define PCIE_CC_REV_ID_0_EP3_REG 0x0e4
#define PCIE_DEV_ID_1_EP3_REG 0x0e8
#define PCIE_CC_REV_ID_1_EP3_REG 0x0ec
#define PCIE_DEV_ID_2_EP3_REG 0x0f0
#define PCIE_CC_REV_ID_2_EP3_REG 0x0f4
#define PCIE_DEV_ID_3_EP3_REG 0x0f8
#define PCIE_CC_REV_ID_3_EP3_REG 0x0fc
#define PCIE_DEV_ID_4_EP3_REG 0x100
#define PCIE_CC_REV_ID_4_EP3_REG 0x104
#define PCIE_DEV_ID_5_EP3_REG 0x108
#define PCIE_CC_REV_ID_5_EP3_REG 0x10c
#define PCIE_DEV_ID_6_EP3_REG 0x110
#define PCIE_CC_REV_ID_6_EP3_REG 0x114
#define PCIE_DEV_ID_7_EP3_REG 0x118
#define PCIE_CC_REV_ID_7_EP3_REG 0x11c
#define PCIE_DEV_ID_0_EP4_REG 0x120
#define PCIE_CC_REV_ID_0_EP4_REG 0x124
#define PCIE_DEV_ID_1_EP4_REG 0x128
#define PCIE_CC_REV_ID_1_EP4_REG 0x12c
#define PCIE_DEV_ID_2_EP4_REG 0x130
#define PCIE_CC_REV_ID_2_EP4_REG 0x134
#define PCIE_DEV_ID_3_EP4_REG 0x138
#define PCIE_CC_REV_ID_3_EP4_REG 0x13c
#define PCIE_DEV_ID_4_EP4_REG 0x140
#define PCIE_CC_REV_ID_4_EP4_REG 0x144
#define PCIE_DEV_ID_5_EP4_REG 0x148
#define PCIE_CC_REV_ID_5_EP4_REG 0x14c
#define PCIE_DEV_ID_6_EP4_REG 0x150
#define PCIE_CC_REV_ID_6_EP4_REG 0x154
#define PCIE_DEV_ID_7_EP4_REG 0x158
#define PCIE_CC_REV_ID_7_EP4_REG 0x15c
#define PCIE_SUBSYS_VEN_ID_REG 0x160
#define PCIE_COMMON_CLOCK_CONFIG_0_4_0 0x164
#define PCIE_MIPHYP_SSC_EN_REG 0x168
#define PCIE_MIPHYP_ADDR_REG 0x16c
#define PCIE_L1_ASPM_READY_REG 0x170
#define PCIE_EXT_CFG_RDY_REG 0x174
#define PCIE_SoC_INT_ROUTER_STATUS0_REG 0x178
#define PCIE_SoC_INT_ROUTER_STATUS1_REG 0x17c
#define PCIE_SoC_INT_ROUTER_STATUS2_REG 0x180
#define PCIE_SoC_INT_ROUTER_STATUS3_REG 0x184
#define DMA_IP_CTRL_REG 0x324
#define DISP_BRIDGE_PU_PD_CTRL_REG 0x328
#define VIP_PU_PD_CTRL_REG 0x32c
#define USB_MLB_PU_PD_CTRL_REG 0x330
#define SDIO_PU_PD_MISCFUNC_CTRL_REG1 0x334
#define SDIO_PU_PD_MISCFUNC_CTRL_REG2 0x338
#define UART_PU_PD_CTRL_REG 0x33c
#define ARM_Lock 0x340
#define SYS_IO_CHAR_REG1 0x344
#define SYS_IO_CHAR_REG2 0x348
#define SATA_CORE_ID_REG 0x34c
#define SATA_CTRL_REG 0x350
#define I2C_HSFIX_MISC_REG 0x354
#define SPARE2_RESERVED 0x358
#define SPARE3_RESERVED 0x35c
#define MASTER_LOCK_REG 0x368
#define SYSTEM_CONFIG_STATUS_REG 0x36c
#define MSP_CLK_CTRL_REG 0x39c
#define COMPENSATION_REG1 0x3c4
#define COMPENSATION_REG2 0x3c8
#define COMPENSATION_REG3 0x3cc
#define TEST_CTL_REG 0x3d0
/*
* SECR (OTP) registers
*/
#define STA2X11_SECR_CR 0x00
#define STA2X11_SECR_FVR0 0x10
#define STA2X11_SECR_FVR1 0x14
extern int sta2x11_mfd_get_regs_data(struct platform_device *pdev,
enum sta2x11_mfd_plat_dev index,
void __iomem **regs,
spinlock_t **lock);
#endif /* __STA2X11_MFD_H */

View File

@ -33,6 +33,9 @@
#define TIM_DCR 0x48 /* DMA control register */
#define TIM_DMAR 0x4C /* DMA register for transfer */
#define TIM_TISEL 0x68 /* Input Selection */
#define TIM_HWCFGR2 0x3EC /* hardware configuration 2 Reg (MP25) */
#define TIM_HWCFGR1 0x3F0 /* hardware configuration 1 Reg (MP25) */
#define TIM_IPIDR 0x3F8 /* IP identification Reg (MP25) */
#define TIM_CR1_CEN BIT(0) /* Counter Enable */
#define TIM_CR1_DIR BIT(4) /* Counter Direction */
@ -100,6 +103,9 @@
#define TIM_BDTR_BKF(x) (0xf << (16 + (x) * 4))
#define TIM_DCR_DBA GENMASK(4, 0) /* DMA base addr */
#define TIM_DCR_DBL GENMASK(12, 8) /* DMA burst len */
#define TIM_HWCFGR1_NB_OF_CC GENMASK(3, 0) /* Capture/compare channels */
#define TIM_HWCFGR1_NB_OF_DT GENMASK(7, 4) /* Complementary outputs & dead-time generators */
#define TIM_HWCFGR2_CNT_WIDTH GENMASK(15, 8) /* Counter width */
#define MAX_TIM_PSC 0xFFFF
#define MAX_TIM_ICPSC 0x3
@ -113,6 +119,8 @@
#define TIM_BDTR_BKF_MASK 0xF
#define TIM_BDTR_BKF_SHIFT(x) (16 + (x) * 4)
#define STM32MP25_TIM_IPIDR 0x00120002
enum stm32_timers_dmas {
STM32_TIMERS_DMA_CH1,
STM32_TIMERS_DMA_CH2,
@ -151,6 +159,7 @@ struct stm32_timers_dma {
struct stm32_timers {
struct clk *clk;
u32 ipidr;
struct regmap *regmap;
u32 max_arr;
struct stm32_timers_dma dma; /* Only to be used by the parent */

View File

@ -1,8 +1,9 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Functions to access TPS65219 Power Management IC.
* Functions to access TPS65215/TPS65219 Power Management Integrated Chips
*
* Copyright (C) 2022 BayLibre Incorporated - https://www.baylibre.com/
* Copyright (C) 2024 Texas Instruments Incorporated - https://www.ti.com/
*/
#ifndef MFD_TPS65219_H
@ -13,8 +14,12 @@
#include <linux/regmap.h>
#include <linux/regulator/driver.h>
/* TPS chip id list */
#define TPS65219 0xF0
/* Chip id list*/
enum pmic_id {
TPS65214,
TPS65215,
TPS65219,
};
/* I2C ID for TPS65219 part */
#define TPS65219_I2C_ID 0x24
@ -24,15 +29,23 @@
#define TPS65219_REG_NVM_ID 0x01
#define TPS65219_REG_ENABLE_CTRL 0x02
#define TPS65219_REG_BUCKS_CONFIG 0x03
#define TPS65214_REG_LOCK 0x03
#define TPS65219_REG_LDO4_VOUT 0x04
#define TPS65214_REG_LDO1_VOUT_STBY 0x04
#define TPS65219_REG_LDO3_VOUT 0x05
#define TPS65215_REG_LDO2_VOUT 0x05
#define TPS65214_REG_LDO1_VOUT 0x05
#define TPS65219_REG_LDO2_VOUT 0x06
#define TPS65214_REG_LDO2_VOUT 0x06
#define TPS65219_REG_LDO1_VOUT 0x07
#define TPS65214_REG_LDO2_VOUT_STBY 0x07
#define TPS65219_REG_BUCK3_VOUT 0x8
#define TPS65219_REG_BUCK2_VOUT 0x9
#define TPS65219_REG_BUCK1_VOUT 0xA
#define TPS65219_REG_LDO4_SEQUENCE_SLOT 0xB
#define TPS65219_REG_LDO3_SEQUENCE_SLOT 0xC
#define TPS65215_REG_LDO2_SEQUENCE_SLOT 0xC
#define TPS65214_REG_LDO1_SEQUENCE_SLOT 0xC
#define TPS65219_REG_LDO2_SEQUENCE_SLOT 0xD
#define TPS65219_REG_LDO1_SEQUENCE_SLOT 0xE
#define TPS65219_REG_BUCK3_SEQUENCE_SLOT 0xF
@ -41,15 +54,21 @@
#define TPS65219_REG_nRST_SEQUENCE_SLOT 0x12
#define TPS65219_REG_GPIO_SEQUENCE_SLOT 0x13
#define TPS65219_REG_GPO2_SEQUENCE_SLOT 0x14
#define TPS65214_REG_GPIO_GPI_SEQUENCE_SLOT 0x14
#define TPS65219_REG_GPO1_SEQUENCE_SLOT 0x15
#define TPS65214_REG_GPO_SEQUENCE_SLOT 0x15
#define TPS65219_REG_POWER_UP_SLOT_DURATION_1 0x16
#define TPS65219_REG_POWER_UP_SLOT_DURATION_2 0x17
/* _SLOT_DURATION_3 doesn't apply to TPS65215*/
#define TPS65219_REG_POWER_UP_SLOT_DURATION_3 0x18
#define TPS65219_REG_POWER_UP_SLOT_DURATION_4 0x19
#define TPS65214_REG_BUCK3_VOUT_STBY 0x19
#define TPS65219_REG_POWER_DOWN_SLOT_DURATION_1 0x1A
#define TPS65219_REG_POWER_DOWN_SLOT_DURATION_2 0x1B
#define TPS65219_REG_POWER_DOWN_SLOT_DURATION_3 0x1C
#define TPS65214_REG_BUCK2_VOUT_STBY 0x1C
#define TPS65219_REG_POWER_DOWN_SLOT_DURATION_4 0x1D
#define TPS65214_REG_BUCK1_VOUT_STBY 0x1D
#define TPS65219_REG_GENERAL_CONFIG 0x1E
#define TPS65219_REG_MFP_1_CONFIG 0x1F
#define TPS65219_REG_MFP_2_CONFIG 0x20
@ -67,9 +86,19 @@
#define TPS65219_REG_DISCHARGE_CONFIG 0x2A
/* main irq registers */
#define TPS65219_REG_INT_SOURCE 0x2B
/* 'sub irq' registers */
/* TPS65219 'sub irq' registers */
#define TPS65219_REG_INT_LDO_3_4 0x2C
#define TPS65219_REG_INT_LDO_1_2 0x2D
/* TPS65215 specific 'sub irq' registers */
#define TPS65215_REG_INT_LDO_2 0x2C
#define TPS65215_REG_INT_LDO_1 0x2D
/* TPS65214 specific 'sub irq' register */
#define TPS65214_REG_INT_LDO_1_2 0x2D
/* Common TPS65215 & TPS65219 'sub irq' registers */
#define TPS65219_REG_INT_BUCK_3 0x2E
#define TPS65219_REG_INT_BUCK_1_2 0x2F
#define TPS65219_REG_INT_SYSTEM 0x30
@ -86,6 +115,17 @@
#define TPS65219_REG_INT_TO_RV_POS 6
#define TPS65219_REG_INT_PB_POS 7
#define TPS65215_REG_INT_LDO_2_POS 0
#define TPS65215_REG_INT_LDO_1_POS 1
#define TPS65214_REG_INT_LDO_1_2_POS 0
#define TPS65214_REG_INT_BUCK_3_POS 1
#define TPS65214_REG_INT_BUCK_1_2_POS 2
#define TPS65214_REG_INT_SYS_POS 3
#define TPS65214_REG_INT_RV_POS 4
#define TPS65214_REG_INT_TO_RV_POS 5
#define TPS65214_REG_INT_PB_POS 6
#define TPS65219_REG_USER_NVM_CMD 0x34
#define TPS65219_REG_POWER_UP_STATUS 0x35
#define TPS65219_REG_SPARE_2 0x36
@ -107,6 +147,8 @@
#define TPS65219_ENABLE_LDO1_EN_MASK BIT(3)
#define TPS65219_ENABLE_LDO2_EN_MASK BIT(4)
#define TPS65219_ENABLE_LDO3_EN_MASK BIT(5)
#define TPS65215_ENABLE_LDO2_EN_MASK BIT(5)
#define TPS65214_ENABLE_LDO1_EN_MASK BIT(5)
#define TPS65219_ENABLE_LDO4_EN_MASK BIT(6)
/* power ON-OFF sequence slot */
#define TPS65219_BUCKS_LDOS_SEQUENCE_OFF_SLOT_MASK GENMASK(3, 0)
@ -158,20 +200,27 @@
#define TPS65219_REG_MASK_EFFECT_MASK GENMASK(2, 1)
#define TPS65219_REG_MASK_INT_FOR_PB_MASK BIT(7)
/* UnderVoltage - Short to GND - OverCurrent*/
/* LDO3-4 */
/* LDO3-4: only for TPS65219*/
#define TPS65219_INT_LDO3_SCG_MASK BIT(0)
#define TPS65219_INT_LDO3_OC_MASK BIT(1)
#define TPS65219_INT_LDO3_UV_MASK BIT(2)
#define TPS65219_INT_LDO4_SCG_MASK BIT(3)
#define TPS65219_INT_LDO4_OC_MASK BIT(4)
#define TPS65219_INT_LDO4_UV_MASK BIT(5)
/* LDO1-2 */
/* LDO1-2: TPS65214 & TPS65219 */
#define TPS65219_INT_LDO1_SCG_MASK BIT(0)
#define TPS65219_INT_LDO1_OC_MASK BIT(1)
#define TPS65219_INT_LDO1_UV_MASK BIT(2)
#define TPS65219_INT_LDO2_SCG_MASK BIT(3)
#define TPS65219_INT_LDO2_OC_MASK BIT(4)
#define TPS65219_INT_LDO2_UV_MASK BIT(5)
/* TPS65215 LDO1-2*/
#define TPS65215_INT_LDO1_SCG_MASK BIT(0)
#define TPS65215_INT_LDO1_OC_MASK BIT(1)
#define TPS65215_INT_LDO1_UV_MASK BIT(2)
#define TPS65215_INT_LDO2_SCG_MASK BIT(0)
#define TPS65215_INT_LDO2_OC_MASK BIT(1)
#define TPS65215_INT_LDO2_UV_MASK BIT(2)
/* BUCK3 */
#define TPS65219_INT_BUCK3_SCG_MASK BIT(0)
#define TPS65219_INT_BUCK3_OC_MASK BIT(1)
@ -186,12 +235,13 @@
#define TPS65219_INT_BUCK2_OC_MASK BIT(5)
#define TPS65219_INT_BUCK2_NEG_OC_MASK BIT(6)
#define TPS65219_INT_BUCK2_UV_MASK BIT(7)
/* Thermal Sensor */
/* Thermal Sensor: TPS65219/TPS65215 */
#define TPS65219_INT_SENSOR_3_WARM_MASK BIT(0)
#define TPS65219_INT_SENSOR_3_HOT_MASK BIT(4)
/* Thermal Sensor: TPS65219/TPS65215/TPS65214 */
#define TPS65219_INT_SENSOR_2_WARM_MASK BIT(1)
#define TPS65219_INT_SENSOR_1_WARM_MASK BIT(2)
#define TPS65219_INT_SENSOR_0_WARM_MASK BIT(3)
#define TPS65219_INT_SENSOR_3_HOT_MASK BIT(4)
#define TPS65219_INT_SENSOR_2_HOT_MASK BIT(5)
#define TPS65219_INT_SENSOR_1_HOT_MASK BIT(6)
#define TPS65219_INT_SENSOR_0_HOT_MASK BIT(7)
@ -202,6 +252,8 @@
#define TPS65219_INT_LDO1_RV_MASK BIT(3)
#define TPS65219_INT_LDO2_RV_MASK BIT(4)
#define TPS65219_INT_LDO3_RV_MASK BIT(5)
#define TPS65215_INT_LDO2_RV_MASK BIT(5)
#define TPS65214_INT_LDO2_RV_MASK BIT(5)
#define TPS65219_INT_LDO4_RV_MASK BIT(6)
/* Residual Voltage ShutDown */
#define TPS65219_INT_BUCK1_RV_SD_MASK BIT(0)
@ -210,6 +262,8 @@
#define TPS65219_INT_LDO1_RV_SD_MASK BIT(3)
#define TPS65219_INT_LDO2_RV_SD_MASK BIT(4)
#define TPS65219_INT_LDO3_RV_SD_MASK BIT(5)
#define TPS65215_INT_LDO2_RV_SD_MASK BIT(5)
#define TPS65214_INT_LDO1_RV_SD_MASK BIT(5)
#define TPS65219_INT_LDO4_RV_SD_MASK BIT(6)
#define TPS65219_INT_TIMEOUT_MASK BIT(7)
/* Power Button */
@ -235,7 +289,15 @@ enum {
TPS65219_INT_LDO4_SCG,
TPS65219_INT_LDO4_OC,
TPS65219_INT_LDO4_UV,
/* LDO1-2 */
/* TPS65215 LDO1*/
TPS65215_INT_LDO1_SCG,
TPS65215_INT_LDO1_OC,
TPS65215_INT_LDO1_UV,
/* TPS65215 LDO2*/
TPS65215_INT_LDO2_SCG,
TPS65215_INT_LDO2_OC,
TPS65215_INT_LDO2_UV,
/* LDO1-2: TPS65219/TPS65214 */
TPS65219_INT_LDO1_SCG,
TPS65219_INT_LDO1_OC,
TPS65219_INT_LDO1_UV,
@ -271,6 +333,8 @@ enum {
TPS65219_INT_BUCK3_RV,
TPS65219_INT_LDO1_RV,
TPS65219_INT_LDO2_RV,
TPS65215_INT_LDO2_RV,
TPS65214_INT_LDO2_RV,
TPS65219_INT_LDO3_RV,
TPS65219_INT_LDO4_RV,
/* Residual Voltage ShutDown */
@ -278,6 +342,8 @@ enum {
TPS65219_INT_BUCK2_RV_SD,
TPS65219_INT_BUCK3_RV_SD,
TPS65219_INT_LDO1_RV_SD,
TPS65214_INT_LDO1_RV_SD,
TPS65215_INT_LDO2_RV_SD,
TPS65219_INT_LDO2_RV_SD,
TPS65219_INT_LDO3_RV_SD,
TPS65219_INT_LDO4_RV_SD,
@ -287,6 +353,23 @@ enum {
TPS65219_INT_PB_RISING_EDGE_DETECT,
};
enum tps65214_regulator_id {
/*
* DCDC's same as TPS65219
* LDO1 maps to TPS65219's LDO3
* LDO2 is the same as TPS65219
*
*/
TPS65214_LDO_1 = 3,
TPS65214_LDO_2 = 4,
};
enum tps65215_regulator_id {
/* DCDC's same as TPS65219 */
/* LDO1 is the same as TPS65219 */
TPS65215_LDO_2 = 4,
};
enum tps65219_regulator_id {
/* DCDC's */
TPS65219_BUCK_1,
@ -300,11 +383,40 @@ enum tps65219_regulator_id {
};
/* Number of step-down converters available */
#define TPS65219_NUM_DCDC 3
#define TPS6521X_NUM_BUCKS 3
/* Number of LDO voltage regulators available */
#define TPS65219_NUM_LDO 4
#define TPS65215_NUM_LDO 2
#define TPS65214_NUM_LDO 2
/* Number of total regulators available */
#define TPS65219_NUM_REGULATOR (TPS65219_NUM_DCDC + TPS65219_NUM_LDO)
#define TPS65219_NUM_REGULATOR (TPS6521X_NUM_BUCKS + TPS65219_NUM_LDO)
#define TPS65215_NUM_REGULATOR (TPS6521X_NUM_BUCKS + TPS65215_NUM_LDO)
#define TPS65214_NUM_REGULATOR (TPS6521X_NUM_BUCKS + TPS65214_NUM_LDO)
/* Define the TPS65214 IRQ numbers */
enum tps65214_irqs {
/* INT source registers */
TPS65214_TO_RV_SD_SET_IRQ,
TPS65214_RV_SET_IRQ,
TPS65214_SYS_SET_IRQ,
TPS65214_BUCK_1_2_SET_IRQ,
TPS65214_BUCK_3_SET_IRQ,
TPS65214_LDO_1_2_SET_IRQ,
TPS65214_PB_SET_IRQ = 7,
};
/* Define the TPS65215 IRQ numbers */
enum tps65215_irqs {
/* INT source registers */
TPS65215_TO_RV_SD_SET_IRQ,
TPS65215_RV_SET_IRQ,
TPS65215_SYS_SET_IRQ,
TPS65215_BUCK_1_2_SET_IRQ,
TPS65215_BUCK_3_SET_IRQ,
TPS65215_LDO_1_SET_IRQ,
TPS65215_LDO_2_SET_IRQ,
TPS65215_PB_SET_IRQ,
};
/* Define the TPS65219 IRQ numbers */
enum tps65219_irqs {
@ -326,6 +438,7 @@ enum tps65219_irqs {
*
* @dev: MFD device
* @regmap: Regmap for accessing the device registers
* @chip_id: Chip ID
* @irq_data: Regmap irq data used for the irq chip
* @nb: notifier block for the restart handler
*/
@ -333,6 +446,7 @@ struct tps65219 {
struct device *dev;
struct regmap *regmap;
unsigned int chip_id;
struct regmap_irq_chip_data *irq_data;
struct notifier_block nb;
};

View File

@ -0,0 +1,195 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Maxim MAX77705 definitions.
*
* Copyright (C) 2015 Samsung Electronics, Inc.
* Copyright (C) 2025 Dzmitry Sankouski <dsankouski@gmail.com>
*/
#ifndef __MAX77705_CHARGER_H
#define __MAX77705_CHARGER_H __FILE__
/* MAX77705_CHG_REG_CHG_INT */
#define MAX77705_BYP_I BIT(0)
#define MAX77705_INP_LIMIT_I BIT(1)
#define MAX77705_BATP_I BIT(2)
#define MAX77705_BAT_I BIT(3)
#define MAX77705_CHG_I BIT(4)
#define MAX77705_WCIN_I BIT(5)
#define MAX77705_CHGIN_I BIT(6)
#define MAX77705_AICL_I BIT(7)
/* MAX77705_CHG_REG_CHG_INT_MASK */
#define MAX77705_BYP_IM BIT(0)
#define MAX77705_INP_LIMIT_IM BIT(1)
#define MAX77705_BATP_IM BIT(2)
#define MAX77705_BAT_IM BIT(3)
#define MAX77705_CHG_IM BIT(4)
#define MAX77705_WCIN_IM BIT(5)
#define MAX77705_CHGIN_IM BIT(6)
#define MAX77705_AICL_IM BIT(7)
/* MAX77705_CHG_REG_CHG_INT_OK */
#define MAX77705_BYP_OK BIT(0)
#define MAX77705_DISQBAT_OK BIT(1)
#define MAX77705_BATP_OK BIT(2)
#define MAX77705_BAT_OK BIT(3)
#define MAX77705_CHG_OK BIT(4)
#define MAX77705_WCIN_OK BIT(5)
#define MAX77705_CHGIN_OK BIT(6)
#define MAX77705_AICL_OK BIT(7)
/* MAX77705_CHG_REG_DETAILS_00 */
#define MAX77705_BATP_DTLS BIT(0)
#define MAX77705_WCIN_DTLS GENMASK(4, 3)
#define MAX77705_WCIN_DTLS_SHIFT 3
#define MAX77705_CHGIN_DTLS GENMASK(6, 5)
#define MAX77705_CHGIN_DTLS_SHIFT 5
/* MAX77705_CHG_REG_DETAILS_01 */
#define MAX77705_CHG_DTLS GENMASK(3, 0)
#define MAX77705_CHG_DTLS_SHIFT 0
#define MAX77705_BAT_DTLS GENMASK(6, 4)
#define MAX77705_BAT_DTLS_SHIFT 4
/* MAX77705_CHG_REG_DETAILS_02 */
#define MAX77705_BYP_DTLS GENMASK(3, 0)
#define MAX77705_BYP_DTLS_SHIFT 0
/* MAX77705_CHG_REG_CNFG_00 */
#define MAX77705_CHG_SHIFT 0
#define MAX77705_UNO_SHIFT 1
#define MAX77705_OTG_SHIFT 1
#define MAX77705_BUCK_SHIFT 2
#define MAX77705_BOOST_SHIFT 3
#define MAX77705_WDTEN_SHIFT 4
#define MAX77705_MODE_MASK GENMASK(3, 0)
#define MAX77705_CHG_MASK BIT(MAX77705_CHG_SHIFT)
#define MAX77705_UNO_MASK BIT(MAX77705_UNO_SHIFT)
#define MAX77705_OTG_MASK BIT(MAX77705_OTG_SHIFT)
#define MAX77705_BUCK_MASK BIT(MAX77705_BUCK_SHIFT)
#define MAX77705_BOOST_MASK BIT(MAX77705_BOOST_SHIFT)
#define MAX77705_WDTEN_MASK BIT(MAX77705_WDTEN_SHIFT)
#define MAX77705_UNO_CTRL (MAX77705_UNO_MASK | MAX77705_BOOST_MASK)
#define MAX77705_OTG_CTRL (MAX77705_OTG_MASK | MAX77705_BOOST_MASK)
/* MAX77705_CHG_REG_CNFG_01 */
#define MAX77705_FCHGTIME_SHIFT 0
#define MAX77705_FCHGTIME_MASK GENMASK(2, 0)
#define MAX77705_CHG_RSTRT_SHIFT 4
#define MAX77705_CHG_RSTRT_MASK GENMASK(5, 4)
#define MAX77705_FCHGTIME_DISABLE 0
#define MAX77705_CHG_RSTRT_DISABLE 0x3
#define MAX77705_PQEN_SHIFT 7
#define MAX77705_PQEN_MASK BIT(7)
#define MAX77705_CHG_PQEN_DISABLE 0
#define MAX77705_CHG_PQEN_ENABLE 1
/* MAX77705_CHG_REG_CNFG_02 */
#define MAX77705_OTG_ILIM_SHIFT 6
#define MAX77705_OTG_ILIM_MASK GENMASK(7, 6)
#define MAX77705_OTG_ILIM_500 0
#define MAX77705_OTG_ILIM_900 1
#define MAX77705_OTG_ILIM_1200 2
#define MAX77705_OTG_ILIM_1500 3
#define MAX77705_CHG_CC GENMASK(5, 0)
/* MAX77705_CHG_REG_CNFG_03 */
#define MAX77705_TO_ITH_SHIFT 0
#define MAX77705_TO_ITH_MASK GENMASK(2, 0)
#define MAX77705_TO_TIME_SHIFT 3
#define MAX77705_TO_TIME_MASK GENMASK(5, 3)
#define MAX77705_SYS_TRACK_DIS_SHIFT 7
#define MAX77705_SYS_TRACK_DIS_MASK BIT(7)
#define MAX77705_TO_ITH_150MA 0
#define MAX77705_TO_TIME_30M 3
#define MAX77705_SYS_TRACK_ENABLE 0
#define MAX77705_SYS_TRACK_DISABLE 1
/* MAX77705_CHG_REG_CNFG_04 */
#define MAX77705_CHG_MINVSYS_SHIFT 6
#define MAX77705_CHG_MINVSYS_MASK GENMASK(7, 6)
#define MAX77705_CHG_PRM_SHIFT 0
#define MAX77705_CHG_PRM_MASK GENMASK(5, 0)
#define MAX77705_CHG_CV_PRM_SHIFT 0
#define MAX77705_CHG_CV_PRM_MASK GENMASK(5, 0)
/* MAX77705_CHG_REG_CNFG_05 */
#define MAX77705_REG_B2SOVRC_SHIFT 0
#define MAX77705_REG_B2SOVRC_MASK GENMASK(3, 0)
#define MAX77705_B2SOVRC_DISABLE 0
#define MAX77705_B2SOVRC_4_5A 6
#define MAX77705_B2SOVRC_4_8A 8
#define MAX77705_B2SOVRC_5_0A 9
/* MAX77705_CHG_CNFG_06 */
#define MAX77705_WDTCLR_SHIFT 0
#define MAX77705_WDTCLR_MASK GENMASK(1, 0)
#define MAX77705_WDTCLR 1
#define MAX77705_CHGPROT_MASK GENMASK(3, 2)
#define MAX77705_CHGPROT_UNLOCKED GENMASK(3, 2)
#define MAX77705_SLOWEST_LX_SLOPE GENMASK(6, 5)
/* MAX77705_CHG_REG_CNFG_07 */
#define MAX77705_CHG_FMBST 4
#define MAX77705_REG_FMBST_SHIFT 2
#define MAX77705_REG_FMBST_MASK BIT(MAX77705_REG_FMBST_SHIFT)
#define MAX77705_REG_FGSRC_SHIFT 1
#define MAX77705_REG_FGSRC_MASK BIT(MAX77705_REG_FGSRC_SHIFT)
/* MAX77705_CHG_REG_CNFG_08 */
#define MAX77705_REG_FSW_SHIFT 0
#define MAX77705_REG_FSW_MASK GENMASK(1, 0)
#define MAX77705_CHG_FSW_3MHz 0
#define MAX77705_CHG_FSW_2MHz 1
#define MAX77705_CHG_FSW_1_5MHz 2
/* MAX77705_CHG_REG_CNFG_09 */
#define MAX77705_CHG_CHGIN_LIM_MASK GENMASK(6, 0)
#define MAX77705_CHG_EN_MASK BIT(7)
#define MAX77705_CHG_DISABLE 0
#define MAX77705_CHARGER_CHG_CHARGING(_reg) \
(((_reg) & MAX77705_CHG_EN_MASK) > 1)
/* MAX77705_CHG_REG_CNFG_10 */
#define MAX77705_CHG_WCIN_LIM GENMASK(5, 0)
/* MAX77705_CHG_REG_CNFG_11 */
#define MAX77705_VBYPSET_SHIFT 0
#define MAX77705_VBYPSET_MASK GENMASK(6, 0)
/* MAX77705_CHG_REG_CNFG_12 */
#define MAX77705_CHGINSEL_SHIFT 5
#define MAX77705_CHGINSEL_MASK BIT(MAX77705_CHGINSEL_SHIFT)
#define MAX77705_WCINSEL_SHIFT 6
#define MAX77705_WCINSEL_MASK BIT(MAX77705_WCINSEL_SHIFT)
#define MAX77705_VCHGIN_REG_MASK GENMASK(4, 3)
#define MAX77705_WCIN_REG_MASK GENMASK(2, 1)
#define MAX77705_REG_DISKIP_SHIFT 0
#define MAX77705_REG_DISKIP_MASK BIT(MAX77705_REG_DISKIP_SHIFT)
/* REG=4.5V, UVLO=4.7V */
#define MAX77705_VCHGIN_4_5 0
/* REG=4.5V, UVLO=4.7V */
#define MAX77705_WCIN_4_5 0
#define MAX77705_DISABLE_SKIP 1
#define MAX77705_AUTO_SKIP 0
/* uA */
#define MAX77705_CURRENT_CHGIN_STEP 25000
#define MAX77705_CURRENT_CHG_STEP 50000
#define MAX77705_CURRENT_CHGIN_MIN 100000
#define MAX77705_CURRENT_CHGIN_MAX 3200000
struct max77705_charger_data {
struct device *dev;
struct regmap *regmap;
struct power_supply_battery_info *bat_info;
struct workqueue_struct *wqueue;
struct work_struct chgin_work;
struct power_supply *psy_chg;
};
#endif /* __MAX77705_CHARGER_H */