1
0
mirror of https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git synced 2026-01-12 01:20:14 +00:00

MFD for v6.16

* Samsung Exynos ACPM:
     * Populate child platform devices from device tree data
     * Introduce a new API, `devm_acpm_get_by_node()`, for child devices to get the ACPM handle
   * ROHM PMICs:
     * Add support for the ROHM BD96802 scalable companion PMIC to the BD96801 core driver
     * Add support for controlling the BD96802 using the BD96801 regulator driver
     * Add support to the BD96805, which is almost identical to the BD96801
     * Add support to the BD96806, which is similar to the BD96802
   * Maxim MAX77759:
     * Add a core driver for the MAX77759 companion PMIC
     * Add a GPIO driver for the expander functions on the MAX77759
     * Add an NVMEM driver to expose the non-volatile memory on the MAX77759
   * STMicroelectronics STM32MP25:
     * Add support for the STM32MP25 SoC to the stm32-lptimer
     * Add support for the STM32MP25 to the clocksource driver, handling new register access requirements
     * Add support for the STM32MP25 to the PWM driver, enabling up to two PWM outputs
   * Broadcom BCM590xx:
     * Add support for the BCM59054 PMU
     * Parse the PMU ID and revision to support behavioral differences between chip revisions
     * Add regulator support for the BCM59054
   * Samsung S2MPG10:
     * Add support for the S2MPG10 PMIC, which communicates via the Samsung ACPM firmware instead of I2C
 
   * Exynos ACPM:
     * Improve timeout detection reliability by using ktime APIs instead of a loop counter assumption
     * Allow PMIC access during late system shutdown by switching to `udelay()` instead of a sleeping function
     * Fix an issue where reading command results longer than 8 bytes would fail
     * Silence non-error `-EPROBE_DEFER` messages during boot to clean up logs
   * Exynos LPASS:
     * Fix an error handling path by switching to `devm_regmap_init_mmio()` to prevent resource leaks
     * Fix a bug where `exynos_lpass_disable()` was called twice in the remove function
     * Fix another resource leak in the probe's error path by using `devm_add_action_or_reset()`
   * Samsung SEC:
     * Handle the s2dos05, which does not have IRQ support, explicitly to prevent warnings
     * Fix the core driver to correctly handle errors from `sec_irq_init()` instead of ignoring them
   * STMPE-SPI:
     * Correct an undeclared identifier in the `MODULE_DEVICE_TABLE` macro
   * MAINTAINERS:
     * Adjust a file path for the Siemens IPC LED drivers entry to fix a broken reference
   * Maxim Drivers:
     * Correct the spelling of "Electronics" in Samsung copyright headers across multiple files
   * General:
     * Fix wakeup source memory leaks on device unbind for 88pm886, as3722, max14577, max77541, max77705,
       max8925, rt5033, and sprd-sc27xx drivers
 
   * Samsung SEC Drivers:
     * Split the driver into a transport-agnostic core (`sec-core`) and transport-specific (`sec-i2c`,
       `sec-acpm`) modules to support non-I2C devices
     * Merge the `sec-core` and `sec-irq` modules to reduce memory consumption
     * Move internal APIs to a private header to clean up the public API
     * Improve code style by sorting includes, cleaning up headers, sorting device tables, and using helper
       macros like `dev_err_probe()`, `MFD_CELL`, and `REGMAP_IRQ_REG`
     * Make regmap configuration for s2dos05/s2mpu05 explicit to improve clarity
     * Rework platform data and regmap instantiation to use OF match data instead of a large switch statement
   * ROHM BD96801/2:
     * Prepare the driver for new models by separating chip-specific data into its own structure
     * Drop IC name prefix from IRQ resource names in both the MFD and regulator drivers for simplification
   * Broadcom BCM590xx:
     * Refactor the regulator driver to store descriptions in a table to ease support for new chips
     * Rename BCM59056-specific data to prepare for the addition of other regulators
     * Use `dev_err_probe()` for cleaner error handling
   * Exynos ACPM:
     * Correct kerneldoc warnings and use the conventional 'np' argument name
   * General MFD:
     * Convert `aat2870` and `tps65010` to use the per-client debugfs directory provided by the I2C core
     * Convert `sm501`, `tps65010` and `ucb1x00` to use the new GPIO line value setter callbacks
     * Constify `regmap_irq_chip` and other structures in `88pm886` to move data to read-only sections
 
   * BCM590xx:
     * Drop the unused "id" member from the `bcm590xx` struct in preparation for a replacement
   * Samsung SEC Core:
     * Remove forward declarations for functions that no longer exist
   * SM501:
     * Remove the unused `sm501_find_clock()` function
 
   * New Compatibles:
     * Google: Add a PMIC child node to the `google,gs101-acpm-ipc` binding
     * ROHM: Add new bindings for `rohm,bd96802-regulator` and `rohm,bd96802-pmic`, and add compatibles
       for BD96805 and BD96806
     * Maxim: Add new bindings for `maxim,max77759-gpio`, `maxim,max77759-nvmem`, and the top-level
       `maxim,max77759`
     * STM: Add `stm32mp25` compatible to the `stm32-lptimer` binding
     * Broadcom: Add `bcm59054` compatible
     * Atmel/Microchip: Add `microchip,sama7d65-gpbr` and `microchip,sama7d65-secumod` compatibles
     * Samsung: Add `s2mpg10` compatible to the `samsung,s2mps11` MFD binding
     * MediaTek: Add compatibles for `mt6893` (scpsys), `mt7988-topmisc`, and `mt8365-infracfg-nao`
     * Qualcomm: Add `qcom,apq8064-mmss-sfpb` and `qcom,apq8064-sps-sic` syscon compatibles
   * Refactoring & Cleanup:
     * Convert Broadcom BCM59056 devicetree bindings to YAML and split them into MFD and regulator parts
     * Convert the Microchip AT91 secumod binding to YAML
     * Drop unrelated consumer nodes from binding examples to reduce bloat
     * Correct indentation and style in various DTS examples
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEdrbJNaO+IJqU8IdIUa+KL4f8d2EFAmg+xmQACgkQUa+KL4f8
 d2FJAxAApmk3kxAlb9r6E268SY1qQSeQKhhzQZeQz1Dt9ZfMurgnou+EdY5juxCH
 owu4AjyQdaC/eIJJRaBcBjcskmNRsVd7mGwQfhMyg7IvhM9k1PxTuad/PSRauGqy
 p7XnYFYeDa9fwwAZ8qD01gpCenQ3oLm4ef05FGC5SDlqcZzxOzc4iGYgHYjE7ACp
 Iuv5tN0JkxCzTGtpZ6kXn5tp895KcndzPWgS0eQxf6Plw2syF0KKxlVCWUfLjAaZ
 Db1VFOkc2vgjhxuFPpybGzRhgtVKRdYRJqL4EQEhnB/u23cuxxqBSJ3BPGIjfqrA
 h6zaxbYJyBF3cHz9kOqi99inN4T3cZssOSdqIVuWTYSuH+FDdsVi5BF2WlrSgWqn
 hgyVZYjMEB4UbEU+0VdZMqTWjY0+kmAEl7xWQ++sp2cuTtYdcufrldLVl0d/HOCm
 zLXia1A2KHgFoBFN/sP0ffZD9ceM/ng1h1tfz+48MWWO7obpwbdFNtWllblfpm9d
 cYPlg0uddFljjzP/gm3jgJAZkMer2m5eSVfvf2L5VrSROFSfbxwHcvVgRTxmPR0K
 1rQqLm1w2Tp8HCocuO95bRv5g0Z4jWDu+CssM1XZrEXaNCZ5E0qm374JArpAFctb
 cAVFcLYSUT73S6lgBOjF05F2zGPCmqW26S+R2cMPcM2SA1N89Go=
 =hiAm
 -----END PGP SIGNATURE-----

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

Pull MFD updates from Lee Jones:
 "Samsung Exynos ACPM:
   - Populate child platform devices from device tree data
   - Introduce a new API, 'devm_acpm_get_by_node()', for child devices
     to get the ACPM handle

  ROHM PMICs:
   - Add support for the ROHM BD96802 scalable companion PMIC to the
     BD96801 core driver
   - Add support for controlling the BD96802 using the BD96801 regulator
     driver
   - Add support to the BD96805, which is almost identical to the
     BD96801
   - Add support to the BD96806, which is similar to the BD96802

  Maxim MAX77759:
   - Add a core driver for the MAX77759 companion PMIC
   - Add a GPIO driver for the expander functions on the MAX77759
   - Add an NVMEM driver to expose the non-volatile memory on the
     MAX77759

  STMicroelectronics STM32MP25:
   - Add support for the STM32MP25 SoC to the stm32-lptimer
   - Add support for the STM32MP25 to the clocksource driver, handling
     new register access requirements
   - Add support for the STM32MP25 to the PWM driver, enabling up to two
     PWM outputs

  Broadcom BCM590xx:
   - Add support for the BCM59054 PMU
   - Parse the PMU ID and revision to support behavioral differences
     between chip revisions
   - Add regulator support for the BCM59054

  Samsung S2MPG10:
   - Add support for the S2MPG10 PMIC, which communicates via the
     Samsung ACPM firmware instead of I2C

  Exynos ACPM:
   - Improve timeout detection reliability by using ktime APIs instead
     of a loop counter assumption
   - Allow PMIC access during late system shutdown by switching to
     'udelay()' instead of a sleeping function
   - Fix an issue where reading command results longer than 8 bytes
     would fail
   - Silence non-error '-EPROBE_DEFER' messages during boot to clean up
     logs

  Exynos LPASS:
   - Fix an error handling path by switching to
     'devm_regmap_init_mmio()' to prevent resource leaks
   - Fix a bug where 'exynos_lpass_disable()' was called twice in the
     remove function
   - Fix another resource leak in the probe's error path by using
     'devm_add_action_or_reset()'

  Samsung SEC:
   - Handle the s2dos05, which does not have IRQ support, explicitly to
     prevent warnings
   - Fix the core driver to correctly handle errors from
     'sec_irq_init()' instead of ignoring them

  STMPE-SPI:
   - Correct an undeclared identifier in the 'MODULE_DEVICE_TABLE' macro

  MAINTAINERS:
   - Adjust a file path for the Siemens IPC LED drivers entry to fix a
     broken reference

  Maxim Drivers:
   - Correct the spelling of "Electronics" in Samsung copyright headers
     across multiple files

  General:
   - Fix wakeup source memory leaks on device unbind for 88pm886,
     as3722, max14577, max77541, max77705, max8925, rt5033, and
     sprd-sc27xx drivers

  Samsung SEC Drivers:
   - Split the driver into a transport-agnostic core ('sec-core') and
     transport-specific ('sec-i2c', 'sec-acpm') modules to support
     non-I2C devices
   - Merge the 'sec-core' and 'sec-irq' modules to reduce memory
     consumption
   - Move internal APIs to a private header to clean up the public API
   - Improve code style by sorting includes, cleaning up headers,
     sorting device tables, and using helper macros like
     'dev_err_probe()', 'MFD_CELL', and 'REGMAP_IRQ_REG'
   - Make regmap configuration for s2dos05/s2mpu05 explicit to improve
     clarity
   - Rework platform data and regmap instantiation to use OF match data
     instead of a large switch statement

  ROHM BD96801/2:
   - Prepare the driver for new models by separating chip-specific data
     into its own structure
   - Drop IC name prefix from IRQ resource names in both the MFD and
     regulator drivers for simplification

  Broadcom BCM590xx:
   - Refactor the regulator driver to store descriptions in a table to
     ease support for new chips
   - Rename BCM59056-specific data to prepare for the addition of other
     regulators
   - Use 'dev_err_probe()' for cleaner error handling

  Exynos ACPM:
   - Correct kerneldoc warnings and use the conventional 'np' argument
     name

  General MFD:
   - Convert 'aat2870' and 'tps65010' to use the per-client debugfs
     directory provided by the I2C core
   - Convert 'sm501', 'tps65010' and 'ucb1x00' to use the new GPIO line
     value setter callbacks
   - Constify 'regmap_irq_chip' and other structures in '88pm886' to
     move data to read-only sections

  BCM590xx:
   - Drop the unused "id" member from the 'bcm590xx' struct in
     preparation for a replacement

  Samsung SEC Core:
   - Remove forward declarations for functions that no longer exist

  SM501:
   - Remove the unused 'sm501_find_clock()' function

  New Compatibles:
   - Google: Add a PMIC child node to the 'google,gs101-acpm-ipc'
     binding
   - ROHM: Add new bindings for 'rohm,bd96802-regulator' and
     'rohm,bd96802-pmic', and add compatibles for BD96805 and BD96806
   - Maxim: Add new bindings for 'maxim,max77759-gpio',
     'maxim,max77759-nvmem', and the top-level 'maxim,max77759'
   - STM: Add 'stm32mp25' compatible to the 'stm32-lptimer' binding
   - Broadcom: Add 'bcm59054' compatible
   - Atmel/Microchip: Add 'microchip,sama7d65-gpbr' and
     'microchip,sama7d65-secumod' compatibles
   - Samsung: Add 's2mpg10' compatible to the 'samsung,s2mps11' MFD
     binding
   - MediaTek: Add compatibles for 'mt6893' (scpsys), 'mt7988-topmisc',
     and 'mt8365-infracfg-nao'
   - Qualcomm: Add 'qcom,apq8064-mmss-sfpb' and 'qcom,apq8064-sps-sic'
     syscon compatibles

  Refactoring & Cleanup:
   - Convert Broadcom BCM59056 devicetree bindings to YAML and split
     them into MFD and regulator parts
   - Convert the Microchip AT91 secumod binding to YAML
   - Drop unrelated consumer nodes from binding examples to reduce bloat
   - Correct indentation and style in various DTS examples"

* tag 'mfd-next-6.16' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd: (81 commits)
  mfd: maxim: Correct Samsung "Electronics" spelling in copyright headers
  mfd: maxim: Correct Samsung "Electronics" spelling in headers
  mfd: sm501: Remove unused sm501_find_clock
  mfd: 88pm886: Constify struct regmap_irq_chip and some other structures
  dt-bindings: mfd: syscon: Add mediatek,mt8365-infracfg-nao
  mfd: sprd-sc27xx: Fix wakeup source leaks on device unbind
  mfd: rt5033: Fix wakeup source leaks on device unbind
  mfd: max8925: Fix wakeup source leaks on device unbind
  mfd: max77705: Fix wakeup source leaks on device unbind
  mfd: max77541: Fix wakeup source leaks on device unbind
  mfd: max14577: Fix wakeup source leaks on device unbind
  mfd: as3722: Fix wakeup source leaks on device unbind
  mfd: 88pm886: Fix wakeup source leaks on device unbind
  dt-bindings: mfd: Correct indentation and style in DTS example
  dt-bindings: mfd: Drop unrelated nodes from DTS example
  dt-bindings: mfd: syscon: Add qcom,apq8064-sps-sic
  dt-bindings: mfd: syscon: Add qcom,apq8064-mmss-sfpb
  mfd: stmpe-spi: Correct the name used in MODULE_DEVICE_TABLE
  dt-bindings: mfd: syscon: Add mt7988-topmisc
  mfd: exynos-lpass: Fix another error handling path in exynos_lpass_probe()
  ...
This commit is contained in:
Linus Torvalds 2025-06-03 11:53:55 -07:00
commit 69352bd52b
74 changed files with 4908 additions and 1645 deletions

View File

@ -0,0 +1,49 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/arm/atmel,sama5d2-secumod.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Microchip AT91 Security Module (SECUMOD)
maintainers:
- Nicolas Ferre <nicolas.ferre@microchip.com>
description:
The Security Module also offers the PIOBU pins which can be used as GPIO pins.
Note that they maintain their voltage during Backup/Self-refresh.
properties:
compatible:
oneOf:
- items:
- const: atmel,sama5d2-secumod
- const: syscon
- items:
- enum:
- microchip,sama7d65-secumod
- microchip,sama7g5-secumod
- const: atmel,sama5d2-secumod
- const: syscon
reg:
maxItems: 1
gpio-controller: true
"#gpio-cells":
const: 2
required:
- compatible
- reg
unevaluatedProperties: false
examples:
- |
security-module@fc040000 {
compatible = "atmel,sama5d2-secumod", "syscon";
reg = <0xfc040000 0x100>;
gpio-controller;
#gpio-cells = <2>;
};

View File

@ -46,28 +46,3 @@ Examples:
reg = <0xffffe800 0x200>;
};
Security Module (SECUMOD)
The Security Module macrocell provides all necessary secure functions to avoid
voltage, temperature, frequency and mechanical attacks on the chip. It also
embeds secure memories that can be scrambled.
The Security Module also offers the PIOBU pins which can be used as GPIO pins.
Note that they maintain their voltage during Backup/Self-refresh.
required properties:
- compatible: Should be "atmel,<chip>-secumod", "syscon".
<chip> can be "sama5d2".
- reg: Should contain registers location and length
- gpio-controller: Marks the port as GPIO controller.
- #gpio-cells: There are 2. The pin number is the
first, the second represents additional
parameters such as GPIO_ACTIVE_HIGH/LOW.
secumod@fc040000 {
compatible = "atmel,sama5d2-secumod", "syscon";
reg = <0xfc040000 0x100>;
gpio-controller;
#gpio-cells = <2>;
};

View File

@ -19,6 +19,7 @@ properties:
- items:
- enum:
- atmel,at91sam9260-gpbr
- microchip,sama7d65-gpbr
- const: syscon
- items:
- enum:

View File

@ -1,39 +0,0 @@
-------------------------------
BCM590xx Power Management Units
-------------------------------
Required properties:
- compatible: "brcm,bcm59056"
- reg: I2C slave address
- interrupts: interrupt for the PMU. Generic interrupt client node bindings
are described in interrupt-controller/interrupts.txt
------------------
Voltage Regulators
------------------
Optional child nodes:
- regulators: container node for regulators following the generic
regulator binding in regulator/regulator.txt
The valid regulator node names for BCM59056 are:
rfldo, camldo1, camldo2, simldo1, simldo2, sdldo, sdxldo,
mmcldo1, mmcldo2, audldo, micldo, usbldo, vibldo,
csr, iosr1, iosr2, msr, sdsr1, sdsr2, vsr,
gpldo1, gpldo2, gpldo3, gpldo4, gpldo5, gpldo6,
vbus
Example:
pmu: bcm59056@8 {
compatible = "brcm,bcm59056";
reg = <0x08>;
interrupts = <GIC_SPI 215 IRQ_TYPE_LEVEL_HIGH>;
regulators {
rfldo_reg: rfldo {
regulator-min-microvolt = <1200000>;
regulator-max-microvolt = <3300000>;
};
...
};
};

View File

@ -0,0 +1,76 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/mfd/brcm,bcm59056.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Broadcom BCM590xx Power Management Units
maintainers:
- Artur Weber <aweber.kernel@gmail.com>
properties:
compatible:
enum:
- brcm,bcm59054
- brcm,bcm59056
reg:
maxItems: 1
interrupts:
maxItems: 1
regulators:
type: object
required:
- compatible
- reg
- interrupts
additionalProperties: false
allOf:
- if:
properties:
compatible:
contains:
const: brcm,bcm59054
then:
properties:
regulators:
$ref: /schemas/regulator/brcm,bcm59054.yaml#
- if:
properties:
compatible:
contains:
const: brcm,bcm59056
then:
properties:
regulators:
$ref: /schemas/regulator/brcm,bcm59056.yaml#
examples:
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/interrupt-controller/irq.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
pmic@8 {
compatible = "brcm,bcm59056";
reg = <0x08>;
interrupts = <GIC_SPI 215 IRQ_TYPE_LEVEL_HIGH>;
regulators {
rfldo {
regulator-min-microvolt = <1200000>;
regulator-max-microvolt = <3300000>;
};
};
};
};

View File

@ -60,43 +60,34 @@ examples:
#include <dt-bindings/interrupt-controller/irq.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
#address-cells = <1>;
#size-cells = <0>;
iqs620a@44 {
compatible = "azoteq,iqs620a";
reg = <0x44>;
interrupt-parent = <&gpio>;
interrupts = <17 IRQ_TYPE_LEVEL_LOW>;
iqs620a@44 {
compatible = "azoteq,iqs620a";
reg = <0x44>;
interrupt-parent = <&gpio>;
interrupts = <17 IRQ_TYPE_LEVEL_LOW>;
keys {
compatible = "azoteq,iqs620a-keys";
keys {
compatible = "azoteq,iqs620a-keys";
linux,keycodes = <KEY_SELECT>,
<KEY_MENU>,
<KEY_OK>,
<KEY_MENU>;
linux,keycodes = <KEY_SELECT>,
<KEY_MENU>,
<KEY_OK>,
<KEY_MENU>;
hall-switch-south {
linux,code = <SW_LID>;
azoteq,use-prox;
};
};
iqs620a_pwm: pwm {
compatible = "azoteq,iqs620a-pwm";
#pwm-cells = <2>;
};
hall-switch-south {
linux,code = <SW_LID>;
azoteq,use-prox;
};
};
};
pwmleds {
compatible = "pwm-leds";
led-1 {
pwms = <&iqs620a_pwm 0 1000000>;
max-brightness = <255>;
iqs620a_pwm: pwm {
compatible = "azoteq,iqs620a-pwm";
#pwm-cells = <2>;
};
};
};
- |
@ -105,37 +96,37 @@ examples:
#include <dt-bindings/interrupt-controller/irq.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
#address-cells = <1>;
#size-cells = <0>;
iqs620a@44 {
compatible = "azoteq,iqs620a";
reg = <0x44>;
interrupt-parent = <&gpio>;
interrupts = <17 IRQ_TYPE_LEVEL_LOW>;
iqs620a@44 {
compatible = "azoteq,iqs620a";
reg = <0x44>;
interrupt-parent = <&gpio>;
interrupts = <17 IRQ_TYPE_LEVEL_LOW>;
firmware-name = "iqs620a_coil.bin";
firmware-name = "iqs620a_coil.bin";
keys {
compatible = "azoteq,iqs620a-keys";
keys {
compatible = "azoteq,iqs620a-keys";
linux,keycodes = <0>,
<0>,
<0>,
<0>,
<0>,
<0>,
<KEY_MUTE>;
linux,keycodes = <0>,
<0>,
<0>,
<0>,
<0>,
<0>,
<KEY_MUTE>;
hall-switch-north {
linux,code = <SW_DOCK>;
};
hall-switch-north {
linux,code = <SW_DOCK>;
};
hall-switch-south {
linux,code = <SW_TABLET_MODE>;
};
};
hall-switch-south {
linux,code = <SW_TABLET_MODE>;
};
};
};
};
- |
@ -144,36 +135,36 @@ examples:
#include <dt-bindings/interrupt-controller/irq.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
#address-cells = <1>;
#size-cells = <0>;
iqs624@44 {
compatible = "azoteq,iqs624";
reg = <0x44>;
interrupt-parent = <&gpio>;
interrupts = <17 IRQ_TYPE_LEVEL_LOW>;
iqs624@44 {
compatible = "azoteq,iqs624";
reg = <0x44>;
interrupt-parent = <&gpio>;
interrupts = <17 IRQ_TYPE_LEVEL_LOW>;
keys {
compatible = "azoteq,iqs624-keys";
keys {
compatible = "azoteq,iqs624-keys";
linux,keycodes = <BTN_0>,
<0>,
<BTN_1>,
<0>,
<0>,
<0>,
<0>,
<0>,
<0>,
<0>,
<0>,
<0>,
<0>,
<0>,
<KEY_VOLUMEUP>,
<KEY_VOLUMEDOWN>;
};
linux,keycodes = <BTN_0>,
<0>,
<BTN_1>,
<0>,
<0>,
<0>,
<0>,
<0>,
<0>,
<0>,
<0>,
<0>,
<0>,
<0>,
<KEY_VOLUMEUP>,
<KEY_VOLUMEDOWN>;
};
};
};
...

View File

@ -18,6 +18,7 @@ properties:
compatible:
items:
- enum:
- mediatek,mt6893-scpsys
- mediatek,mt8167-scpsys
- mediatek,mt8173-scpsys
- mediatek,mt8183-scpsys

View File

@ -76,12 +76,6 @@ additionalProperties: false
examples:
- |
ocelot_clock: ocelot-clock {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <125000000>;
};
spi {
#address-cells = <1>;
#size-cells = <0>;

View File

@ -48,29 +48,18 @@ examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
#address-cells = <1>;
#size-cells = <0>;
ec: embedded-controller@43 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_ntxec>;
ec: embedded-controller@43 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_ntxec>;
compatible = "netronix,ntxec";
reg = <0x43>;
system-power-controller;
interrupt-parent = <&gpio4>;
interrupts = <11 IRQ_TYPE_EDGE_FALLING>;
#pwm-cells = <2>;
};
};
backlight {
compatible = "pwm-backlight";
pwms = <&ec 0 50000>;
power-supply = <&backlight_regulator>;
};
backlight_regulator: regulator-dummy {
compatible = "regulator-fixed";
regulator-name = "backlight";
compatible = "netronix,ntxec";
reg = <0x43>;
system-power-controller;
interrupt-parent = <&gpio4>;
interrupts = <11 IRQ_TYPE_EDGE_FALLING>;
#pwm-cells = <2>;
};
};

View File

@ -99,29 +99,29 @@ examples:
#include <dt-bindings/interrupt-controller/irq.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
#address-cells = <1>;
#size-cells = <0>;
pmic: pmic@30 {
compatible = "rohm,bd9571mwv";
reg = <0x30>;
interrupt-parent = <&gpio2>;
interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
interrupt-controller;
#interrupt-cells = <2>;
gpio-controller;
#gpio-cells = <2>;
rohm,ddr-backup-power = <0xf>;
rohm,rstbmode-pulse;
pmic: pmic@30 {
compatible = "rohm,bd9571mwv";
reg = <0x30>;
interrupt-parent = <&gpio2>;
interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
interrupt-controller;
#interrupt-cells = <2>;
gpio-controller;
#gpio-cells = <2>;
rohm,ddr-backup-power = <0xf>;
rohm,rstbmode-pulse;
regulators {
dvfs: dvfs {
regulator-name = "dvfs";
regulator-min-microvolt = <750000>;
regulator-max-microvolt = <1030000>;
regulator-boot-on;
regulator-always-on;
};
};
};
regulators {
dvfs: dvfs {
regulator-name = "dvfs";
regulator-min-microvolt = <750000>;
regulator-max-microvolt = <1030000>;
regulator-boot-on;
regulator-always-on;
};
};
};
};

View File

@ -4,19 +4,21 @@
$id: http://devicetree.org/schemas/mfd/rohm,bd96801-pmic.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: ROHM BD96801 Scalable Power Management Integrated Circuit
title: ROHM BD96801/BD96805 Scalable Power Management Integrated Circuit
maintainers:
- Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>
description:
BD96801 is an automotive grade single-chip power management IC.
It integrates 4 buck converters and 3 LDOs with safety features like
BD96801 and BD96805 are automotive grade, single-chip power management ICs.
They both integrate 4 buck converters and 3 LDOs with safety features like
over-/under voltage and over current detection and a watchdog.
properties:
compatible:
const: rohm,bd96801
enum:
- rohm,bd96801
- rohm,bd96805
reg:
maxItems: 1

View File

@ -0,0 +1,101 @@
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/mfd/rohm,bd96802-pmic.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: ROHM BD96802 / BD96806 Scalable Power Management Integrated Circuit
maintainers:
- Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>
description: |
BD96802Qxx-C and BD96806 are automotive grade configurable Power Management
Integrated Circuits supporting Functional Safety features for application
processors, SoCs and FPGAs
properties:
compatible:
enum:
- rohm,bd96802
- rohm,bd96806
reg:
maxItems: 1
interrupts:
description:
The PMIC provides intb and errb IRQ lines. The errb IRQ line is used
for fatal IRQs which will cause the PMIC to shut down power outputs.
In many systems this will shut down the SoC contolling the PMIC and
connecting/handling the errb can be omitted. However, there are cases
where the SoC is not powered by the PMIC or has a short time backup
energy to handle shutdown of critical hardware. In that case it may be
useful to connect the errb and handle errb events.
minItems: 1
maxItems: 2
interrupt-names:
minItems: 1
items:
- enum: [intb, errb]
- const: errb
regulators:
$ref: ../regulator/rohm,bd96802-regulator.yaml
description:
List of child nodes that specify the regulators.
required:
- compatible
- reg
- interrupts
- interrupt-names
- regulators
additionalProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/leds/common.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
pmic: pmic@62 {
reg = <0x62>;
compatible = "rohm,bd96802";
interrupt-parent = <&gpio1>;
interrupts = <29 IRQ_TYPE_LEVEL_LOW>, <6 IRQ_TYPE_LEVEL_LOW>;
interrupt-names = "intb", "errb";
regulators {
buck1 {
regulator-name = "buck1";
regulator-ramp-delay = <1250>;
/* 0.5V min INITIAL - 150 mV tune */
regulator-min-microvolt = <350000>;
/* 3.3V + 150mV tune */
regulator-max-microvolt = <3450000>;
/* These can be set only when PMIC is in STBY */
rohm,initial-voltage-microvolt = <500000>;
regulator-ov-error-microvolt = <230000>;
regulator-uv-error-microvolt = <230000>;
regulator-temp-protection-kelvin = <1>;
regulator-temp-warn-kelvin = <0>;
};
buck2 {
regulator-name = "buck2";
regulator-min-microvolt = <350000>;
regulator-max-microvolt = <3450000>;
rohm,initial-voltage-microvolt = <3000000>;
regulator-ov-error-microvolt = <18000>;
regulator-uv-error-microvolt = <18000>;
regulator-temp-protection-kelvin = <1>;
regulator-temp-warn-kelvin = <1>;
};
};
};
};

View File

@ -20,6 +20,7 @@ description: |
properties:
compatible:
enum:
- samsung,s2mpg10-pmic
- samsung,s2mps11-pmic
- samsung,s2mps13-pmic
- samsung,s2mps14-pmic
@ -58,16 +59,39 @@ properties:
reset (setting buck voltages to default values).
type: boolean
system-power-controller: true
wakeup-source: true
required:
- compatible
- reg
- regulators
additionalProperties: false
allOf:
- if:
properties:
compatible:
contains:
const: samsung,s2mpg10-pmic
then:
properties:
reg: false
samsung,s2mps11-acokb-ground: false
samsung,s2mps11-wrstbi-ground: false
oneOf:
- required: [interrupts]
- required: [interrupts-extended]
else:
properties:
system-power-controller: false
required:
- reg
- if:
properties:
compatible:

View File

@ -21,7 +21,12 @@ maintainers:
properties:
compatible:
const: st,stm32-lptimer
oneOf:
- items:
- const: st,stm32mp25-lptimer
- const: st,stm32-lptimer
- items:
- const: st,stm32-lptimer
reg:
maxItems: 1
@ -48,13 +53,21 @@ properties:
minItems: 1
maxItems: 2
power-domains:
maxItems: 1
pwm:
type: object
additionalProperties: false
properties:
compatible:
const: st,stm32-pwm-lp
oneOf:
- items:
- const: st,stm32mp25-pwm-lp
- const: st,stm32-pwm-lp
- items:
- const: st,stm32-pwm-lp
"#pwm-cells":
const: 3
@ -69,7 +82,12 @@ properties:
properties:
compatible:
const: st,stm32-lptimer-counter
oneOf:
- items:
- const: st,stm32mp25-lptimer-counter
- const: st,stm32-lptimer-counter
- items:
- const: st,stm32-lptimer-counter
required:
- compatible
@ -80,7 +98,12 @@ properties:
properties:
compatible:
const: st,stm32-lptimer-timer
oneOf:
- items:
- const: st,stm32mp25-lptimer-timer
- const: st,stm32-lptimer-timer
- items:
- const: st,stm32-lptimer-timer
required:
- compatible
@ -92,13 +115,18 @@ patternProperties:
properties:
compatible:
const: st,stm32-lptimer-trigger
oneOf:
- items:
- const: st,stm32mp25-lptimer-trigger
- const: st,stm32-lptimer-trigger
- items:
- const: st,stm32-lptimer-trigger
reg:
description: Identify trigger hardware block.
items:
minimum: 0
maximum: 2
maximum: 4
required:
- compatible

View File

@ -84,6 +84,7 @@ select:
- mediatek,mt2701-pctl-a-syscfg
- mediatek,mt2712-pctl-a-syscfg
- mediatek,mt6397-pctl-pmic-syscfg
- mediatek,mt7988-topmisc
- mediatek,mt8135-pctl-a-syscfg
- mediatek,mt8135-pctl-b-syscfg
- mediatek,mt8173-pctl-a-syscfg
@ -98,6 +99,8 @@ select:
- mstar,msc313-pmsleep
- nuvoton,ma35d1-sys
- nuvoton,wpcm450-shm
- qcom,apq8064-mmss-sfpb
- qcom,apq8064-sps-sic
- rockchip,px30-qos
- rockchip,rk3036-qos
- rockchip,rk3066-qos
@ -187,9 +190,11 @@ properties:
- mediatek,mt2701-pctl-a-syscfg
- mediatek,mt2712-pctl-a-syscfg
- mediatek,mt6397-pctl-pmic-syscfg
- mediatek,mt7988-topmisc
- mediatek,mt8135-pctl-a-syscfg
- mediatek,mt8135-pctl-b-syscfg
- mediatek,mt8173-pctl-a-syscfg
- mediatek,mt8365-infracfg-nao
- mediatek,mt8365-syscfg
- microchip,lan966x-cpu-syscon
- microchip,mpfs-sysreg-scb
@ -201,6 +206,8 @@ properties:
- mstar,msc313-pmsleep
- nuvoton,ma35d1-sys
- nuvoton,wpcm450-shm
- qcom,apq8064-mmss-sfpb
- qcom,apq8064-sps-sic
- rockchip,px30-qos
- rockchip,rk3036-qos
- rockchip,rk3066-qos

View File

@ -316,106 +316,106 @@ additionalProperties: false
examples:
- |
i2c {
#address-cells = <1>;
#size-cells = <0>;
i2c {
#address-cells = <1>;
#size-cells = <0>;
pmic@30 {
compatible = "x-powers,axp152";
reg = <0x30>;
interrupts = <0>;
interrupt-controller;
#interrupt-cells = <1>;
};
};
pmic@30 {
compatible = "x-powers,axp152";
reg = <0x30>;
interrupts = <0>;
interrupt-controller;
#interrupt-cells = <1>;
};
};
- |
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/interrupt-controller/irq.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
i2c {
#address-cells = <1>;
#size-cells = <0>;
pmic@34 {
compatible = "x-powers,axp209";
reg = <0x34>;
interrupt-parent = <&nmi_intc>;
interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
interrupt-controller;
#interrupt-cells = <1>;
pmic@34 {
compatible = "x-powers,axp209";
reg = <0x34>;
interrupt-parent = <&nmi_intc>;
interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
interrupt-controller;
#interrupt-cells = <1>;
ac_power_supply: ac-power {
compatible = "x-powers,axp202-ac-power-supply";
};
ac_power_supply: ac-power {
compatible = "x-powers,axp202-ac-power-supply";
};
axp_adc: adc {
compatible = "x-powers,axp209-adc";
#io-channel-cells = <1>;
};
axp_adc: adc {
compatible = "x-powers,axp209-adc";
#io-channel-cells = <1>;
};
axp_gpio: gpio {
compatible = "x-powers,axp209-gpio";
gpio-controller;
#gpio-cells = <2>;
axp_gpio: gpio {
compatible = "x-powers,axp209-gpio";
gpio-controller;
#gpio-cells = <2>;
gpio0-adc-pin {
pins = "GPIO0";
function = "adc";
};
};
gpio0-adc-pin {
pins = "GPIO0";
function = "adc";
};
};
battery_power_supply: battery-power {
compatible = "x-powers,axp209-battery-power-supply";
};
battery_power_supply: battery-power {
compatible = "x-powers,axp209-battery-power-supply";
};
regulators {
/* Default work frequency for buck regulators */
x-powers,dcdc-freq = <1500>;
regulators {
/* Default work frequency for buck regulators */
x-powers,dcdc-freq = <1500>;
reg_dcdc2: dcdc2 {
regulator-always-on;
regulator-min-microvolt = <1000000>;
regulator-max-microvolt = <1450000>;
regulator-name = "vdd-cpu";
};
reg_dcdc2: dcdc2 {
regulator-always-on;
regulator-min-microvolt = <1000000>;
regulator-max-microvolt = <1450000>;
regulator-name = "vdd-cpu";
};
reg_dcdc3: dcdc3 {
regulator-always-on;
regulator-min-microvolt = <1000000>;
regulator-max-microvolt = <1400000>;
regulator-name = "vdd-int-dll";
};
reg_dcdc3: dcdc3 {
regulator-always-on;
regulator-min-microvolt = <1000000>;
regulator-max-microvolt = <1400000>;
regulator-name = "vdd-int-dll";
};
reg_ldo1: ldo1 {
/* LDO1 is a fixed output regulator */
regulator-always-on;
regulator-min-microvolt = <1300000>;
regulator-max-microvolt = <1300000>;
regulator-name = "vdd-rtc";
};
reg_ldo1: ldo1 {
/* LDO1 is a fixed output regulator */
regulator-always-on;
regulator-min-microvolt = <1300000>;
regulator-max-microvolt = <1300000>;
regulator-name = "vdd-rtc";
};
reg_ldo2: ldo2 {
regulator-always-on;
regulator-min-microvolt = <3000000>;
regulator-max-microvolt = <3000000>;
regulator-name = "avcc";
};
reg_ldo2: ldo2 {
regulator-always-on;
regulator-min-microvolt = <3000000>;
regulator-max-microvolt = <3000000>;
regulator-name = "avcc";
};
reg_ldo3: ldo3 {
regulator-name = "ldo3";
};
reg_ldo3: ldo3 {
regulator-name = "ldo3";
};
reg_ldo4: ldo4 {
regulator-name = "ldo4";
};
reg_ldo4: ldo4 {
regulator-name = "ldo4";
};
reg_ldo5: ldo5 {
regulator-name = "ldo5";
};
};
reg_ldo5: ldo5 {
regulator-name = "ldo5";
};
};
usb_power_supply: usb-power {
compatible = "x-powers,axp202-usb-power-supply";
};
};
};
usb_power_supply: usb-power {
compatible = "x-powers,axp202-usb-power-supply";
};
};
};

View File

@ -0,0 +1,56 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/regulator/brcm,bcm59054.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Broadcom BCM59054 Power Management Unit regulators
description: |
This is a part of device tree bindings for the BCM59054 power
management unit.
See Documentation/devicetree/bindings/mfd/brcm,bcm59056.yaml for
additional information and example.
maintainers:
- Artur Weber <aweber.kernel@gmail.com>
patternProperties:
"^(cam|sim|mmc)ldo[1-2]$":
type: object
$ref: /schemas/regulator/regulator.yaml#
unevaluatedProperties: false
"^(rf|sd|sdx|aud|mic|usb|vib|tcx)ldo$":
type: object
$ref: /schemas/regulator/regulator.yaml#
unevaluatedProperties: false
"^(c|mm|v)sr$":
type: object
$ref: /schemas/regulator/regulator.yaml#
unevaluatedProperties: false
"^(io|sd)sr[1-2]$":
type: object
$ref: /schemas/regulator/regulator.yaml#
unevaluatedProperties: false
"^gpldo[1-3]$":
type: object
$ref: /schemas/regulator/regulator.yaml#
unevaluatedProperties: false
"^lvldo[1-2]$":
type: object
$ref: /schemas/regulator/regulator.yaml#
unevaluatedProperties: false
properties:
vbus:
type: object
$ref: /schemas/regulator/regulator.yaml#
unevaluatedProperties: false
additionalProperties: false

View File

@ -0,0 +1,51 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/regulator/brcm,bcm59056.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Broadcom BCM59056 Power Management Unit regulators
description: |
This is a part of device tree bindings for the BCM59056 power
management unit.
See Documentation/devicetree/bindings/mfd/brcm,bcm59056.yaml for
additional information and example.
maintainers:
- Artur Weber <aweber.kernel@gmail.com>
patternProperties:
"^(cam|sim|mmc)ldo[1-2]$":
type: object
$ref: /schemas/regulator/regulator.yaml#
unevaluatedProperties: false
"^(rf|sd|sdx|aud|mic|usb|vib)ldo$":
type: object
$ref: /schemas/regulator/regulator.yaml#
unevaluatedProperties: false
"^(c|m|v)sr$":
type: object
$ref: /schemas/regulator/regulator.yaml#
unevaluatedProperties: false
"^(io|sd)sr[1-2]$":
type: object
$ref: /schemas/regulator/regulator.yaml#
unevaluatedProperties: false
"^gpldo[1-6]$":
type: object
$ref: /schemas/regulator/regulator.yaml#
unevaluatedProperties: false
properties:
vbus:
type: object
$ref: /schemas/regulator/regulator.yaml#
unevaluatedProperties: false
additionalProperties: false

View File

@ -0,0 +1,44 @@
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/regulator/rohm,bd96802-regulator.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: ROHM BD96802 Power Management Integrated Circuit regulators
maintainers:
- Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>
description:
This module is part of the ROHM BD96802 MFD device. For more details
see Documentation/devicetree/bindings/mfd/rohm,bd96802-pmic.yaml.
The regulator controller is represented as a sub-node of the PMIC node
on the device tree.
Regulator nodes should be named to buck1 and buck2.
patternProperties:
"^buck[1-2]$":
type: object
description:
Properties for single BUCK regulator.
$ref: regulator.yaml#
properties:
rohm,initial-voltage-microvolt:
description:
Initial voltage for regulator. Voltage can be tuned +/-150 mV from
this value. NOTE, This can be modified via I2C only when PMIC is in
STBY state.
minimum: 500000
maximum: 3300000
rohm,keep-on-stby:
description:
Keep the regulator powered when PMIC transitions to STBY state.
type: boolean
unevaluatedProperties: false
additionalProperties: false

View File

@ -21475,6 +21475,7 @@ F: include/linux/mfd/rohm-bd71828.h
F: include/linux/mfd/rohm-bd718x7.h
F: include/linux/mfd/rohm-bd957x.h
F: include/linux/mfd/rohm-bd96801.h
F: include/linux/mfd/rohm-bd96802.h
F: include/linux/mfd/rohm-generic.h
F: include/linux/mfd/rohm-shared.h
@ -21912,6 +21913,7 @@ F: drivers/platform/x86/samsung-laptop.c
SAMSUNG MULTIFUNCTION PMIC DEVICE DRIVERS
M: Krzysztof Kozlowski <krzk@kernel.org>
R: André Draszik <andre.draszik@linaro.org>
L: linux-kernel@vger.kernel.org
L: linux-samsung-soc@vger.kernel.org
S: Maintained
@ -21922,7 +21924,7 @@ F: Documentation/devicetree/bindings/mfd/samsung,s5m*.yaml
F: Documentation/devicetree/bindings/regulator/samsung,s2m*.yaml
F: Documentation/devicetree/bindings/regulator/samsung,s5m*.yaml
F: drivers/clk/clk-s2mps11.c
F: drivers/mfd/sec*.c
F: drivers/mfd/sec*.[ch]
F: drivers/regulator/s2m*.c
F: drivers/regulator/s5m*.c
F: drivers/rtc/rtc-s5m.c
@ -22575,7 +22577,7 @@ M: Benedikt Niedermayr <benedikt.niedermayr@siemens.com>
M: Tobias Schaffner <tobias.schaffner@siemens.com>
L: linux-leds@vger.kernel.org
S: Maintained
F: drivers/leds/simple/
F: drivers/leds/simatic/
SIEMENS IPC PLATFORM DRIVERS
M: Bao Cheng Su <baocheng.su@siemens.com>

View File

@ -167,7 +167,7 @@ CONFIG_MFD_MAX77686=y
CONFIG_MFD_MAX77693=y
CONFIG_MFD_MAX8997=y
CONFIG_MFD_MAX8998=y
CONFIG_MFD_SEC_CORE=y
CONFIG_MFD_SEC_I2C=y
CONFIG_MFD_STMPE=y
CONFIG_STMPE_I2C=y
CONFIG_MFD_TPS65090=y

View File

@ -612,7 +612,7 @@ CONFIG_MFD_QCOM_RPM=y
CONFIG_MFD_SPMI_PMIC=y
CONFIG_MFD_RK8XX_I2C=y
CONFIG_MFD_RN5T618=y
CONFIG_MFD_SEC_CORE=y
CONFIG_MFD_SEC_I2C=y
CONFIG_MFD_STMPE=y
CONFIG_MFD_PALMAS=y
CONFIG_MFD_TPS65090=y

View File

@ -335,7 +335,7 @@ CONFIG_MFD_MAX77693=y
CONFIG_MFD_MAX8907=m
CONFIG_EZX_PCAP=y
CONFIG_UCB1400_CORE=m
CONFIG_MFD_SEC_CORE=y
CONFIG_MFD_SEC_I2C=y
CONFIG_MFD_PALMAS=y
CONFIG_MFD_TPS65090=y
CONFIG_MFD_TPS6586X=y

View File

@ -774,7 +774,7 @@ CONFIG_MFD_MT6397=y
CONFIG_MFD_SPMI_PMIC=y
CONFIG_MFD_RK8XX_I2C=y
CONFIG_MFD_RK8XX_SPI=y
CONFIG_MFD_SEC_CORE=y
CONFIG_MFD_SEC_I2C=y
CONFIG_MFD_SL28CPLD=y
CONFIG_RZ_MTU3=y
CONFIG_MFD_TI_AM335X_TSCADC=m

View File

@ -5,6 +5,7 @@
* Pascal Paillet <p.paillet@st.com> for STMicroelectronics.
*/
#include <linux/bitfield.h>
#include <linux/clk.h>
#include <linux/clockchips.h>
#include <linux/interrupt.h>
@ -27,6 +28,7 @@ struct stm32_lp_private {
u32 psc;
struct device *dev;
struct clk *clk;
u32 version;
};
static struct stm32_lp_private*
@ -47,12 +49,46 @@ static int stm32_clkevent_lp_shutdown(struct clock_event_device *clkevt)
return 0;
}
static int stm32_clkevent_lp_set_timer(unsigned long evt,
struct clock_event_device *clkevt,
int is_periodic)
static int stm32mp25_clkevent_lp_set_evt(struct stm32_lp_private *priv, unsigned long evt)
{
struct stm32_lp_private *priv = to_priv(clkevt);
int ret;
u32 val;
regmap_read(priv->reg, STM32_LPTIM_CR, &val);
if (!FIELD_GET(STM32_LPTIM_ENABLE, val)) {
/* Enable LPTIMER to be able to write into IER and ARR registers */
regmap_write(priv->reg, STM32_LPTIM_CR, STM32_LPTIM_ENABLE);
/*
* After setting the ENABLE bit, a delay of two counter clock cycles is needed
* before the LPTIM is actually enabled. For 32KHz rate, this makes approximately
* 62.5 micro-seconds, round it up.
*/
udelay(63);
}
/* set next event counter */
regmap_write(priv->reg, STM32_LPTIM_ARR, evt);
/* enable ARR interrupt */
regmap_write(priv->reg, STM32_LPTIM_IER, STM32_LPTIM_ARRMIE);
/* Poll DIEROK and ARROK to ensure register access has completed */
ret = regmap_read_poll_timeout_atomic(priv->reg, STM32_LPTIM_ISR, val,
(val & STM32_LPTIM_DIEROK_ARROK) ==
STM32_LPTIM_DIEROK_ARROK,
10, 500);
if (ret) {
dev_err(priv->dev, "access to LPTIM timed out\n");
/* Disable LPTIMER */
regmap_write(priv->reg, STM32_LPTIM_CR, 0);
return ret;
}
/* Clear DIEROK and ARROK flags */
regmap_write(priv->reg, STM32_LPTIM_ICR, STM32_LPTIM_DIEROKCF_ARROKCF);
return 0;
}
static void stm32_clkevent_lp_set_evt(struct stm32_lp_private *priv, unsigned long evt)
{
/* disable LPTIMER to be able to write into IER register*/
regmap_write(priv->reg, STM32_LPTIM_CR, 0);
/* enable ARR interrupt */
@ -61,6 +97,22 @@ static int stm32_clkevent_lp_set_timer(unsigned long evt,
regmap_write(priv->reg, STM32_LPTIM_CR, STM32_LPTIM_ENABLE);
/* set next event counter */
regmap_write(priv->reg, STM32_LPTIM_ARR, evt);
}
static int stm32_clkevent_lp_set_timer(unsigned long evt,
struct clock_event_device *clkevt,
int is_periodic)
{
struct stm32_lp_private *priv = to_priv(clkevt);
int ret;
if (priv->version == STM32_LPTIM_VERR_23) {
ret = stm32mp25_clkevent_lp_set_evt(priv, evt);
if (ret)
return ret;
} else {
stm32_clkevent_lp_set_evt(priv, evt);
}
/* start counter */
if (is_periodic)
@ -176,6 +228,7 @@ static int stm32_clkevent_lp_probe(struct platform_device *pdev)
return -ENOMEM;
priv->reg = ddata->regmap;
priv->version = ddata->version;
priv->clk = ddata->clk;
ret = clk_prepare_enable(priv->clk);
if (ret)

View File

@ -16,11 +16,11 @@ static const struct regmap_config pm886_regmap_config = {
.max_register = PM886_REG_RTC_SPARE6,
};
static struct regmap_irq pm886_regmap_irqs[] = {
static const struct regmap_irq pm886_regmap_irqs[] = {
REGMAP_IRQ_REG(PM886_IRQ_ONKEY, 0, PM886_INT_ENA1_ONKEY),
};
static struct regmap_irq_chip pm886_regmap_irq_chip = {
static const struct regmap_irq_chip pm886_regmap_irq_chip = {
.name = "88pm886",
.irqs = pm886_regmap_irqs,
.num_irqs = ARRAY_SIZE(pm886_regmap_irqs),
@ -30,11 +30,11 @@ static struct regmap_irq_chip pm886_regmap_irq_chip = {
.unmask_base = PM886_REG_INT_ENA_1,
};
static struct resource pm886_onkey_resources[] = {
static const struct resource pm886_onkey_resources[] = {
DEFINE_RES_IRQ_NAMED(PM886_IRQ_ONKEY, "88pm886-onkey"),
};
static struct mfd_cell pm886_devs[] = {
static const struct mfd_cell pm886_devs[] = {
MFD_CELL_RES("88pm886-onkey", pm886_onkey_resources),
MFD_CELL_NAME("88pm886-regulator"),
MFD_CELL_NAME("88pm886-rtc"),
@ -124,7 +124,11 @@ static int pm886_probe(struct i2c_client *client)
if (err)
return dev_err_probe(dev, err, "Failed to register power off handler\n");
device_init_wakeup(dev, device_property_read_bool(dev, "wakeup-source"));
if (device_property_read_bool(dev, "wakeup-source")) {
err = devm_device_init_wakeup(dev);
if (err)
return dev_err_probe(dev, err, "Failed to init wakeup\n");
}
return 0;
}

View File

@ -1312,21 +1312,42 @@ config MFD_RN5T618
functionality of the device.
config MFD_SEC_CORE
tristate "Samsung Electronics PMIC Series Support"
tristate
select MFD_CORE
select REGMAP_IRQ
config MFD_SEC_ACPM
tristate "Samsung Electronics S2MPG1x PMICs"
depends on EXYNOS_ACPM_PROTOCOL
depends on OF
select MFD_SEC_CORE
help
Support for the Samsung Electronics PMICs with ACPM interface.
This is a Power Management IC for mobile applications with buck
converters, various LDOs, power meters, RTC, clock outputs, and
additional GPIOs interfaces.
This driver provides common support for accessing the device;
additional drivers must be enabled in order to use the functionality
of the device.
To compile this driver as a module, choose M here: the module will be
called sec-acpm.
config MFD_SEC_I2C
tristate "Samsung Electronics S2MPA/S2MPS1X/S2MPU/S5M series PMICs"
depends on I2C=y
depends on OF
select MFD_CORE
select MFD_SEC_CORE
select REGMAP_I2C
select REGMAP_IRQ
help
Support for the Samsung Electronics PMIC devices coming
usually along with Samsung Exynos SoC chipset.
Support for the Samsung Electronics PMIC devices with I2C interface
coming usually along with Samsung Exynos SoC chipset.
This driver provides common support for accessing the device,
additional drivers must be enabled in order to use the functionality
of the device
of the device.
To compile this driver as a module, choose M here: the
module will be called sec-core.
module will be called sec-i2c.
Have in mind that important core drivers (like regulators) depend
on this driver so building this as a module might require proper
initial ramdisk or might not boot up as well in certain scenarios.

View File

@ -229,7 +229,10 @@ obj-$(CONFIG_MFD_RK8XX) += rk8xx-core.o
obj-$(CONFIG_MFD_RK8XX_I2C) += rk8xx-i2c.o
obj-$(CONFIG_MFD_RK8XX_SPI) += rk8xx-spi.o
obj-$(CONFIG_MFD_RN5T618) += rn5t618.o
obj-$(CONFIG_MFD_SEC_CORE) += sec-core.o sec-irq.o
sec-core-objs := sec-common.o sec-irq.o
obj-$(CONFIG_MFD_SEC_CORE) += sec-core.o
obj-$(CONFIG_MFD_SEC_ACPM) += sec-acpm.o
obj-$(CONFIG_MFD_SEC_I2C) += sec-i2c.o
obj-$(CONFIG_MFD_SYSCON) += syscon.o
obj-$(CONFIG_MFD_LM3533) += lm3533-core.o lm3533-ctrlbank.o
obj-$(CONFIG_MFD_VEXPRESS_SYSREG) += vexpress-sysreg.o

View File

@ -320,9 +320,7 @@ static const struct file_operations aat2870_reg_fops = {
static void aat2870_init_debugfs(struct aat2870_data *aat2870)
{
aat2870->dentry_root = debugfs_create_dir("aat2870", NULL);
debugfs_create_file("regs", 0644, aat2870->dentry_root, aat2870,
debugfs_create_file("regs", 0644, aat2870->client->debugfs, aat2870,
&aat2870_reg_fops);
}

View File

@ -394,7 +394,9 @@ static int as3722_i2c_probe(struct i2c_client *i2c)
return ret;
}
device_init_wakeup(as3722->dev, true);
ret = devm_device_init_wakeup(as3722->dev);
if (ret)
return dev_err_probe(as3722->dev, ret, "Failed to init wakeup\n");
dev_dbg(as3722->dev, "AS3722 core driver initialized successfully\n");
return 0;

View File

@ -17,6 +17,15 @@
#include <linux/regmap.h>
#include <linux/slab.h>
/* Under primary I2C address: */
#define BCM590XX_REG_PMUID 0x1e
#define BCM590XX_REG_PMUREV 0x1f
#define BCM590XX_PMUREV_DIG_MASK 0xF
#define BCM590XX_PMUREV_DIG_SHIFT 0
#define BCM590XX_PMUREV_ANA_MASK 0xF0
#define BCM590XX_PMUREV_ANA_SHIFT 4
static const struct mfd_cell bcm590xx_devs[] = {
{
.name = "bcm590xx-vregs",
@ -37,6 +46,47 @@ static const struct regmap_config bcm590xx_regmap_config_sec = {
.cache_type = REGCACHE_MAPLE,
};
/* Map PMU ID value to model name string */
static const char * const bcm590xx_names[] = {
[BCM590XX_PMUID_BCM59054] = "BCM59054",
[BCM590XX_PMUID_BCM59056] = "BCM59056",
};
static int bcm590xx_parse_version(struct bcm590xx *bcm590xx)
{
unsigned int id, rev;
int ret;
/* Get PMU ID and verify that it matches compatible */
ret = regmap_read(bcm590xx->regmap_pri, BCM590XX_REG_PMUID, &id);
if (ret) {
dev_err(bcm590xx->dev, "failed to read PMU ID: %d\n", ret);
return ret;
}
if (id != bcm590xx->pmu_id) {
dev_err(bcm590xx->dev, "Incorrect ID for %s: expected %x, got %x.\n",
bcm590xx_names[bcm590xx->pmu_id], bcm590xx->pmu_id, id);
return -ENODEV;
}
/* Get PMU revision and store it in the info struct */
ret = regmap_read(bcm590xx->regmap_pri, BCM590XX_REG_PMUREV, &rev);
if (ret) {
dev_err(bcm590xx->dev, "failed to read PMU revision: %d\n", ret);
return ret;
}
bcm590xx->rev_digital = (rev & BCM590XX_PMUREV_DIG_MASK) >> BCM590XX_PMUREV_DIG_SHIFT;
bcm590xx->rev_analog = (rev & BCM590XX_PMUREV_ANA_MASK) >> BCM590XX_PMUREV_ANA_SHIFT;
dev_dbg(bcm590xx->dev, "PMU ID 0x%x (%s), revision: digital %d, analog %d",
id, bcm590xx_names[id], bcm590xx->rev_digital, bcm590xx->rev_analog);
return 0;
}
static int bcm590xx_i2c_probe(struct i2c_client *i2c_pri)
{
struct bcm590xx *bcm590xx;
@ -50,6 +100,8 @@ static int bcm590xx_i2c_probe(struct i2c_client *i2c_pri)
bcm590xx->dev = &i2c_pri->dev;
bcm590xx->i2c_pri = i2c_pri;
bcm590xx->pmu_id = (uintptr_t) of_device_get_match_data(bcm590xx->dev);
bcm590xx->regmap_pri = devm_regmap_init_i2c(i2c_pri,
&bcm590xx_regmap_config_pri);
if (IS_ERR(bcm590xx->regmap_pri)) {
@ -76,6 +128,10 @@ static int bcm590xx_i2c_probe(struct i2c_client *i2c_pri)
goto err;
}
ret = bcm590xx_parse_version(bcm590xx);
if (ret)
goto err;
ret = devm_mfd_add_devices(&i2c_pri->dev, -1, bcm590xx_devs,
ARRAY_SIZE(bcm590xx_devs), NULL, 0, NULL);
if (ret < 0) {
@ -91,12 +147,20 @@ err:
}
static const struct of_device_id bcm590xx_of_match[] = {
{ .compatible = "brcm,bcm59056" },
{
.compatible = "brcm,bcm59054",
.data = (void *)BCM590XX_PMUID_BCM59054,
},
{
.compatible = "brcm,bcm59056",
.data = (void *)BCM590XX_PMUID_BCM59056,
},
{ }
};
MODULE_DEVICE_TABLE(of, bcm590xx_of_match);
static const struct i2c_device_id bcm590xx_i2c_id[] = {
{ "bcm59054" },
{ "bcm59056" },
{ }
};

View File

@ -104,11 +104,22 @@ static const struct regmap_config exynos_lpass_reg_conf = {
.fast_io = true,
};
static void exynos_lpass_disable_lpass(void *data)
{
struct platform_device *pdev = data;
struct exynos_lpass *lpass = platform_get_drvdata(pdev);
pm_runtime_disable(&pdev->dev);
if (!pm_runtime_status_suspended(&pdev->dev))
exynos_lpass_disable(lpass);
}
static int exynos_lpass_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct exynos_lpass *lpass;
void __iomem *base_top;
int ret;
lpass = devm_kzalloc(dev, sizeof(*lpass), GFP_KERNEL);
if (!lpass)
@ -122,8 +133,8 @@ static int exynos_lpass_probe(struct platform_device *pdev)
if (IS_ERR(lpass->sfr0_clk))
return PTR_ERR(lpass->sfr0_clk);
lpass->top = regmap_init_mmio(dev, base_top,
&exynos_lpass_reg_conf);
lpass->top = devm_regmap_init_mmio(dev, base_top,
&exynos_lpass_reg_conf);
if (IS_ERR(lpass->top)) {
dev_err(dev, "LPASS top regmap initialization failed\n");
return PTR_ERR(lpass->top);
@ -134,20 +145,13 @@ static int exynos_lpass_probe(struct platform_device *pdev)
pm_runtime_enable(dev);
exynos_lpass_enable(lpass);
ret = devm_add_action_or_reset(dev, exynos_lpass_disable_lpass, pdev);
if (ret)
return ret;
return devm_of_platform_populate(dev);
}
static void exynos_lpass_remove(struct platform_device *pdev)
{
struct exynos_lpass *lpass = platform_get_drvdata(pdev);
exynos_lpass_disable(lpass);
pm_runtime_disable(&pdev->dev);
if (!pm_runtime_status_suspended(&pdev->dev))
exynos_lpass_disable(lpass);
regmap_exit(lpass->top);
}
static int __maybe_unused exynos_lpass_suspend(struct device *dev)
{
struct exynos_lpass *lpass = dev_get_drvdata(dev);
@ -185,7 +189,6 @@ static struct platform_driver exynos_lpass_driver = {
.of_match_table = exynos_lpass_of_match,
},
.probe = exynos_lpass_probe,
.remove = exynos_lpass_remove,
};
module_platform_driver(exynos_lpass_driver);

View File

@ -456,6 +456,7 @@ static void max14577_i2c_remove(struct i2c_client *i2c)
{
struct max14577 *max14577 = i2c_get_clientdata(i2c);
device_init_wakeup(max14577->dev, false);
mfd_remove_devices(max14577->dev);
regmap_del_irq_chip(max14577->irq, max14577->irq_data);
if (max14577->dev_type == MAXIM_DEVICE_TYPE_MAX77836)

View File

@ -152,7 +152,7 @@ static int max77541_pmic_setup(struct device *dev)
if (ret)
return dev_err_probe(dev, ret, "Failed to initialize IRQ\n");
ret = device_init_wakeup(dev, true);
ret = devm_device_init_wakeup(dev);
if (ret)
return dev_err_probe(dev, ret, "Unable to init wakeup\n");

View File

@ -131,7 +131,9 @@ static int max77705_i2c_probe(struct i2c_client *i2c)
if (ret)
return dev_err_probe(dev, ret, "Failed to register child devices\n");
device_init_wakeup(dev, true);
ret = devm_device_init_wakeup(dev);
if (ret)
return dev_err_probe(dev, ret, "Failed to init wakeup\n");
return 0;
}

View File

@ -201,6 +201,7 @@ static void max8925_remove(struct i2c_client *client)
struct max8925_chip *chip = i2c_get_clientdata(client);
max8925_device_exit(chip);
device_init_wakeup(&client->dev, false);
i2c_unregister_device(chip->adc);
i2c_unregister_device(chip->rtc);
}

View File

@ -38,108 +38,172 @@
#include <linux/types.h>
#include <linux/mfd/rohm-bd96801.h>
#include <linux/mfd/rohm-bd96802.h>
#include <linux/mfd/rohm-generic.h>
static const struct resource regulator_errb_irqs[] = {
DEFINE_RES_IRQ_NAMED(BD96801_OTP_ERR_STAT, "bd96801-otp-err"),
DEFINE_RES_IRQ_NAMED(BD96801_DBIST_ERR_STAT, "bd96801-dbist-err"),
DEFINE_RES_IRQ_NAMED(BD96801_EEP_ERR_STAT, "bd96801-eep-err"),
DEFINE_RES_IRQ_NAMED(BD96801_ABIST_ERR_STAT, "bd96801-abist-err"),
DEFINE_RES_IRQ_NAMED(BD96801_PRSTB_ERR_STAT, "bd96801-prstb-err"),
DEFINE_RES_IRQ_NAMED(BD96801_DRMOS1_ERR_STAT, "bd96801-drmoserr1"),
DEFINE_RES_IRQ_NAMED(BD96801_DRMOS2_ERR_STAT, "bd96801-drmoserr2"),
DEFINE_RES_IRQ_NAMED(BD96801_SLAVE_ERR_STAT, "bd96801-slave-err"),
DEFINE_RES_IRQ_NAMED(BD96801_VREF_ERR_STAT, "bd96801-vref-err"),
DEFINE_RES_IRQ_NAMED(BD96801_TSD_ERR_STAT, "bd96801-tsd"),
DEFINE_RES_IRQ_NAMED(BD96801_UVLO_ERR_STAT, "bd96801-uvlo-err"),
DEFINE_RES_IRQ_NAMED(BD96801_OVLO_ERR_STAT, "bd96801-ovlo-err"),
DEFINE_RES_IRQ_NAMED(BD96801_OSC_ERR_STAT, "bd96801-osc-err"),
DEFINE_RES_IRQ_NAMED(BD96801_PON_ERR_STAT, "bd96801-pon-err"),
DEFINE_RES_IRQ_NAMED(BD96801_POFF_ERR_STAT, "bd96801-poff-err"),
DEFINE_RES_IRQ_NAMED(BD96801_CMD_SHDN_ERR_STAT, "bd96801-cmd-shdn-err"),
struct bd968xx {
const struct resource *errb_irqs;
const struct resource *intb_irqs;
int num_errb_irqs;
int num_intb_irqs;
const struct regmap_irq_chip *errb_irq_chip;
const struct regmap_irq_chip *intb_irq_chip;
const struct regmap_config *regmap_config;
struct mfd_cell *cells;
int num_cells;
int unlock_reg;
int unlock_val;
};
static const struct resource bd96801_reg_errb_irqs[] = {
DEFINE_RES_IRQ_NAMED(BD96801_OTP_ERR_STAT, "otp-err"),
DEFINE_RES_IRQ_NAMED(BD96801_DBIST_ERR_STAT, "dbist-err"),
DEFINE_RES_IRQ_NAMED(BD96801_EEP_ERR_STAT, "eep-err"),
DEFINE_RES_IRQ_NAMED(BD96801_ABIST_ERR_STAT, "abist-err"),
DEFINE_RES_IRQ_NAMED(BD96801_PRSTB_ERR_STAT, "prstb-err"),
DEFINE_RES_IRQ_NAMED(BD96801_DRMOS1_ERR_STAT, "drmoserr1"),
DEFINE_RES_IRQ_NAMED(BD96801_DRMOS2_ERR_STAT, "drmoserr2"),
DEFINE_RES_IRQ_NAMED(BD96801_SLAVE_ERR_STAT, "slave-err"),
DEFINE_RES_IRQ_NAMED(BD96801_VREF_ERR_STAT, "vref-err"),
DEFINE_RES_IRQ_NAMED(BD96801_TSD_ERR_STAT, "tsd"),
DEFINE_RES_IRQ_NAMED(BD96801_UVLO_ERR_STAT, "uvlo-err"),
DEFINE_RES_IRQ_NAMED(BD96801_OVLO_ERR_STAT, "ovlo-err"),
DEFINE_RES_IRQ_NAMED(BD96801_OSC_ERR_STAT, "osc-err"),
DEFINE_RES_IRQ_NAMED(BD96801_PON_ERR_STAT, "pon-err"),
DEFINE_RES_IRQ_NAMED(BD96801_POFF_ERR_STAT, "poff-err"),
DEFINE_RES_IRQ_NAMED(BD96801_CMD_SHDN_ERR_STAT, "cmd-shdn-err"),
DEFINE_RES_IRQ_NAMED(BD96801_INT_PRSTB_WDT_ERR, "bd96801-prstb-wdt-err"),
DEFINE_RES_IRQ_NAMED(BD96801_INT_CHIP_IF_ERR, "bd96801-chip-if-err"),
DEFINE_RES_IRQ_NAMED(BD96801_INT_SHDN_ERR_STAT, "bd96801-int-shdn-err"),
DEFINE_RES_IRQ_NAMED(BD96801_BUCK1_PVIN_ERR_STAT, "bd96801-buck1-pvin-err"),
DEFINE_RES_IRQ_NAMED(BD96801_BUCK1_OVP_ERR_STAT, "bd96801-buck1-ovp-err"),
DEFINE_RES_IRQ_NAMED(BD96801_BUCK1_UVP_ERR_STAT, "bd96801-buck1-uvp-err"),
DEFINE_RES_IRQ_NAMED(BD96801_BUCK1_SHDN_ERR_STAT, "bd96801-buck1-shdn-err"),
DEFINE_RES_IRQ_NAMED(BD96801_INT_SHDN_ERR_STAT, "int-shdn-err"),
DEFINE_RES_IRQ_NAMED(BD96801_BUCK2_PVIN_ERR_STAT, "bd96801-buck2-pvin-err"),
DEFINE_RES_IRQ_NAMED(BD96801_BUCK2_OVP_ERR_STAT, "bd96801-buck2-ovp-err"),
DEFINE_RES_IRQ_NAMED(BD96801_BUCK2_UVP_ERR_STAT, "bd96801-buck2-uvp-err"),
DEFINE_RES_IRQ_NAMED(BD96801_BUCK2_SHDN_ERR_STAT, "bd96801-buck2-shdn-err"),
DEFINE_RES_IRQ_NAMED(BD96801_BUCK1_PVIN_ERR_STAT, "buck1-pvin-err"),
DEFINE_RES_IRQ_NAMED(BD96801_BUCK1_OVP_ERR_STAT, "buck1-ovp-err"),
DEFINE_RES_IRQ_NAMED(BD96801_BUCK1_UVP_ERR_STAT, "buck1-uvp-err"),
DEFINE_RES_IRQ_NAMED(BD96801_BUCK1_SHDN_ERR_STAT, "buck1-shdn-err"),
DEFINE_RES_IRQ_NAMED(BD96801_BUCK3_PVIN_ERR_STAT, "bd96801-buck3-pvin-err"),
DEFINE_RES_IRQ_NAMED(BD96801_BUCK3_OVP_ERR_STAT, "bd96801-buck3-ovp-err"),
DEFINE_RES_IRQ_NAMED(BD96801_BUCK3_UVP_ERR_STAT, "bd96801-buck3-uvp-err"),
DEFINE_RES_IRQ_NAMED(BD96801_BUCK3_SHDN_ERR_STAT, "bd96801-buck3-shdn-err"),
DEFINE_RES_IRQ_NAMED(BD96801_BUCK2_PVIN_ERR_STAT, "buck2-pvin-err"),
DEFINE_RES_IRQ_NAMED(BD96801_BUCK2_OVP_ERR_STAT, "buck2-ovp-err"),
DEFINE_RES_IRQ_NAMED(BD96801_BUCK2_UVP_ERR_STAT, "buck2-uvp-err"),
DEFINE_RES_IRQ_NAMED(BD96801_BUCK2_SHDN_ERR_STAT, "buck2-shdn-err"),
DEFINE_RES_IRQ_NAMED(BD96801_BUCK4_PVIN_ERR_STAT, "bd96801-buck4-pvin-err"),
DEFINE_RES_IRQ_NAMED(BD96801_BUCK4_OVP_ERR_STAT, "bd96801-buck4-ovp-err"),
DEFINE_RES_IRQ_NAMED(BD96801_BUCK4_UVP_ERR_STAT, "bd96801-buck4-uvp-err"),
DEFINE_RES_IRQ_NAMED(BD96801_BUCK4_SHDN_ERR_STAT, "bd96801-buck4-shdn-err"),
DEFINE_RES_IRQ_NAMED(BD96801_BUCK3_PVIN_ERR_STAT, "buck3-pvin-err"),
DEFINE_RES_IRQ_NAMED(BD96801_BUCK3_OVP_ERR_STAT, "buck3-ovp-err"),
DEFINE_RES_IRQ_NAMED(BD96801_BUCK3_UVP_ERR_STAT, "buck3-uvp-err"),
DEFINE_RES_IRQ_NAMED(BD96801_BUCK3_SHDN_ERR_STAT, "buck3-shdn-err"),
DEFINE_RES_IRQ_NAMED(BD96801_LDO5_PVIN_ERR_STAT, "bd96801-ldo5-pvin-err"),
DEFINE_RES_IRQ_NAMED(BD96801_LDO5_OVP_ERR_STAT, "bd96801-ldo5-ovp-err"),
DEFINE_RES_IRQ_NAMED(BD96801_LDO5_UVP_ERR_STAT, "bd96801-ldo5-uvp-err"),
DEFINE_RES_IRQ_NAMED(BD96801_LDO5_SHDN_ERR_STAT, "bd96801-ldo5-shdn-err"),
DEFINE_RES_IRQ_NAMED(BD96801_BUCK4_PVIN_ERR_STAT, "buck4-pvin-err"),
DEFINE_RES_IRQ_NAMED(BD96801_BUCK4_OVP_ERR_STAT, "buck4-ovp-err"),
DEFINE_RES_IRQ_NAMED(BD96801_BUCK4_UVP_ERR_STAT, "buck4-uvp-err"),
DEFINE_RES_IRQ_NAMED(BD96801_BUCK4_SHDN_ERR_STAT, "buck4-shdn-err"),
DEFINE_RES_IRQ_NAMED(BD96801_LDO6_PVIN_ERR_STAT, "bd96801-ldo6-pvin-err"),
DEFINE_RES_IRQ_NAMED(BD96801_LDO6_OVP_ERR_STAT, "bd96801-ldo6-ovp-err"),
DEFINE_RES_IRQ_NAMED(BD96801_LDO6_UVP_ERR_STAT, "bd96801-ldo6-uvp-err"),
DEFINE_RES_IRQ_NAMED(BD96801_LDO6_SHDN_ERR_STAT, "bd96801-ldo6-shdn-err"),
DEFINE_RES_IRQ_NAMED(BD96801_LDO5_PVIN_ERR_STAT, "ldo5-pvin-err"),
DEFINE_RES_IRQ_NAMED(BD96801_LDO5_OVP_ERR_STAT, "ldo5-ovp-err"),
DEFINE_RES_IRQ_NAMED(BD96801_LDO5_UVP_ERR_STAT, "ldo5-uvp-err"),
DEFINE_RES_IRQ_NAMED(BD96801_LDO5_SHDN_ERR_STAT, "ldo5-shdn-err"),
DEFINE_RES_IRQ_NAMED(BD96801_LDO7_PVIN_ERR_STAT, "bd96801-ldo7-pvin-err"),
DEFINE_RES_IRQ_NAMED(BD96801_LDO7_OVP_ERR_STAT, "bd96801-ldo7-ovp-err"),
DEFINE_RES_IRQ_NAMED(BD96801_LDO7_UVP_ERR_STAT, "bd96801-ldo7-uvp-err"),
DEFINE_RES_IRQ_NAMED(BD96801_LDO7_SHDN_ERR_STAT, "bd96801-ldo7-shdn-err"),
DEFINE_RES_IRQ_NAMED(BD96801_LDO6_PVIN_ERR_STAT, "ldo6-pvin-err"),
DEFINE_RES_IRQ_NAMED(BD96801_LDO6_OVP_ERR_STAT, "ldo6-ovp-err"),
DEFINE_RES_IRQ_NAMED(BD96801_LDO6_UVP_ERR_STAT, "ldo6-uvp-err"),
DEFINE_RES_IRQ_NAMED(BD96801_LDO6_SHDN_ERR_STAT, "ldo6-shdn-err"),
DEFINE_RES_IRQ_NAMED(BD96801_LDO7_PVIN_ERR_STAT, "ldo7-pvin-err"),
DEFINE_RES_IRQ_NAMED(BD96801_LDO7_OVP_ERR_STAT, "ldo7-ovp-err"),
DEFINE_RES_IRQ_NAMED(BD96801_LDO7_UVP_ERR_STAT, "ldo7-uvp-err"),
DEFINE_RES_IRQ_NAMED(BD96801_LDO7_SHDN_ERR_STAT, "ldo7-shdn-err"),
};
static const struct resource regulator_intb_irqs[] = {
DEFINE_RES_IRQ_NAMED(BD96801_TW_STAT, "bd96801-core-thermal"),
static const struct resource bd96802_reg_errb_irqs[] = {
DEFINE_RES_IRQ_NAMED(BD96802_OTP_ERR_STAT, "otp-err"),
DEFINE_RES_IRQ_NAMED(BD96802_DBIST_ERR_STAT, "dbist-err"),
DEFINE_RES_IRQ_NAMED(BD96802_EEP_ERR_STAT, "eep-err"),
DEFINE_RES_IRQ_NAMED(BD96802_ABIST_ERR_STAT, "abist-err"),
DEFINE_RES_IRQ_NAMED(BD96802_PRSTB_ERR_STAT, "prstb-err"),
DEFINE_RES_IRQ_NAMED(BD96802_DRMOS1_ERR_STAT, "drmoserr1"),
DEFINE_RES_IRQ_NAMED(BD96802_DRMOS1_ERR_STAT, "drmoserr2"),
DEFINE_RES_IRQ_NAMED(BD96802_SLAVE_ERR_STAT, "slave-err"),
DEFINE_RES_IRQ_NAMED(BD96802_VREF_ERR_STAT, "vref-err"),
DEFINE_RES_IRQ_NAMED(BD96802_TSD_ERR_STAT, "tsd"),
DEFINE_RES_IRQ_NAMED(BD96802_UVLO_ERR_STAT, "uvlo-err"),
DEFINE_RES_IRQ_NAMED(BD96802_OVLO_ERR_STAT, "ovlo-err"),
DEFINE_RES_IRQ_NAMED(BD96802_OSC_ERR_STAT, "osc-err"),
DEFINE_RES_IRQ_NAMED(BD96802_PON_ERR_STAT, "pon-err"),
DEFINE_RES_IRQ_NAMED(BD96802_POFF_ERR_STAT, "poff-err"),
DEFINE_RES_IRQ_NAMED(BD96802_CMD_SHDN_ERR_STAT, "cmd-shdn-err"),
DEFINE_RES_IRQ_NAMED(BD96802_INT_SHDN_ERR_STAT, "int-shdn-err"),
DEFINE_RES_IRQ_NAMED(BD96801_BUCK1_OCPH_STAT, "bd96801-buck1-overcurr-h"),
DEFINE_RES_IRQ_NAMED(BD96801_BUCK1_OCPL_STAT, "bd96801-buck1-overcurr-l"),
DEFINE_RES_IRQ_NAMED(BD96801_BUCK1_OCPN_STAT, "bd96801-buck1-overcurr-n"),
DEFINE_RES_IRQ_NAMED(BD96801_BUCK1_OVD_STAT, "bd96801-buck1-overvolt"),
DEFINE_RES_IRQ_NAMED(BD96801_BUCK1_UVD_STAT, "bd96801-buck1-undervolt"),
DEFINE_RES_IRQ_NAMED(BD96801_BUCK1_TW_CH_STAT, "bd96801-buck1-thermal"),
DEFINE_RES_IRQ_NAMED(BD96802_BUCK1_PVIN_ERR_STAT, "buck1-pvin-err"),
DEFINE_RES_IRQ_NAMED(BD96802_BUCK1_OVP_ERR_STAT, "buck1-ovp-err"),
DEFINE_RES_IRQ_NAMED(BD96802_BUCK1_UVP_ERR_STAT, "buck1-uvp-err"),
DEFINE_RES_IRQ_NAMED(BD96802_BUCK1_SHDN_ERR_STAT, "buck1-shdn-err"),
DEFINE_RES_IRQ_NAMED(BD96801_BUCK2_OCPH_STAT, "bd96801-buck2-overcurr-h"),
DEFINE_RES_IRQ_NAMED(BD96801_BUCK2_OCPL_STAT, "bd96801-buck2-overcurr-l"),
DEFINE_RES_IRQ_NAMED(BD96801_BUCK2_OCPN_STAT, "bd96801-buck2-overcurr-n"),
DEFINE_RES_IRQ_NAMED(BD96801_BUCK2_OVD_STAT, "bd96801-buck2-overvolt"),
DEFINE_RES_IRQ_NAMED(BD96801_BUCK2_UVD_STAT, "bd96801-buck2-undervolt"),
DEFINE_RES_IRQ_NAMED(BD96801_BUCK2_TW_CH_STAT, "bd96801-buck2-thermal"),
DEFINE_RES_IRQ_NAMED(BD96802_BUCK2_PVIN_ERR_STAT, "buck2-pvin-err"),
DEFINE_RES_IRQ_NAMED(BD96802_BUCK2_OVP_ERR_STAT, "buck2-ovp-err"),
DEFINE_RES_IRQ_NAMED(BD96802_BUCK2_UVP_ERR_STAT, "buck2-uvp-err"),
DEFINE_RES_IRQ_NAMED(BD96802_BUCK2_SHDN_ERR_STAT, "buck2-shdn-err"),
};
DEFINE_RES_IRQ_NAMED(BD96801_BUCK3_OCPH_STAT, "bd96801-buck3-overcurr-h"),
DEFINE_RES_IRQ_NAMED(BD96801_BUCK3_OCPL_STAT, "bd96801-buck3-overcurr-l"),
DEFINE_RES_IRQ_NAMED(BD96801_BUCK3_OCPN_STAT, "bd96801-buck3-overcurr-n"),
DEFINE_RES_IRQ_NAMED(BD96801_BUCK3_OVD_STAT, "bd96801-buck3-overvolt"),
DEFINE_RES_IRQ_NAMED(BD96801_BUCK3_UVD_STAT, "bd96801-buck3-undervolt"),
DEFINE_RES_IRQ_NAMED(BD96801_BUCK3_TW_CH_STAT, "bd96801-buck3-thermal"),
static const struct resource bd96801_reg_intb_irqs[] = {
DEFINE_RES_IRQ_NAMED(BD96801_TW_STAT, "core-thermal"),
DEFINE_RES_IRQ_NAMED(BD96801_BUCK4_OCPH_STAT, "bd96801-buck4-overcurr-h"),
DEFINE_RES_IRQ_NAMED(BD96801_BUCK4_OCPL_STAT, "bd96801-buck4-overcurr-l"),
DEFINE_RES_IRQ_NAMED(BD96801_BUCK4_OCPN_STAT, "bd96801-buck4-overcurr-n"),
DEFINE_RES_IRQ_NAMED(BD96801_BUCK4_OVD_STAT, "bd96801-buck4-overvolt"),
DEFINE_RES_IRQ_NAMED(BD96801_BUCK4_UVD_STAT, "bd96801-buck4-undervolt"),
DEFINE_RES_IRQ_NAMED(BD96801_BUCK4_TW_CH_STAT, "bd96801-buck4-thermal"),
DEFINE_RES_IRQ_NAMED(BD96801_BUCK1_OCPH_STAT, "buck1-overcurr-h"),
DEFINE_RES_IRQ_NAMED(BD96801_BUCK1_OCPL_STAT, "buck1-overcurr-l"),
DEFINE_RES_IRQ_NAMED(BD96801_BUCK1_OCPN_STAT, "buck1-overcurr-n"),
DEFINE_RES_IRQ_NAMED(BD96801_BUCK1_OVD_STAT, "buck1-overvolt"),
DEFINE_RES_IRQ_NAMED(BD96801_BUCK1_UVD_STAT, "buck1-undervolt"),
DEFINE_RES_IRQ_NAMED(BD96801_BUCK1_TW_CH_STAT, "buck1-thermal"),
DEFINE_RES_IRQ_NAMED(BD96801_LDO5_OCPH_STAT, "bd96801-ldo5-overcurr"),
DEFINE_RES_IRQ_NAMED(BD96801_LDO5_OVD_STAT, "bd96801-ldo5-overvolt"),
DEFINE_RES_IRQ_NAMED(BD96801_LDO5_UVD_STAT, "bd96801-ldo5-undervolt"),
DEFINE_RES_IRQ_NAMED(BD96801_BUCK2_OCPH_STAT, "buck2-overcurr-h"),
DEFINE_RES_IRQ_NAMED(BD96801_BUCK2_OCPL_STAT, "buck2-overcurr-l"),
DEFINE_RES_IRQ_NAMED(BD96801_BUCK2_OCPN_STAT, "buck2-overcurr-n"),
DEFINE_RES_IRQ_NAMED(BD96801_BUCK2_OVD_STAT, "buck2-overvolt"),
DEFINE_RES_IRQ_NAMED(BD96801_BUCK2_UVD_STAT, "buck2-undervolt"),
DEFINE_RES_IRQ_NAMED(BD96801_BUCK2_TW_CH_STAT, "buck2-thermal"),
DEFINE_RES_IRQ_NAMED(BD96801_LDO6_OCPH_STAT, "bd96801-ldo6-overcurr"),
DEFINE_RES_IRQ_NAMED(BD96801_LDO6_OVD_STAT, "bd96801-ldo6-overvolt"),
DEFINE_RES_IRQ_NAMED(BD96801_LDO6_UVD_STAT, "bd96801-ldo6-undervolt"),
DEFINE_RES_IRQ_NAMED(BD96801_BUCK3_OCPH_STAT, "buck3-overcurr-h"),
DEFINE_RES_IRQ_NAMED(BD96801_BUCK3_OCPL_STAT, "buck3-overcurr-l"),
DEFINE_RES_IRQ_NAMED(BD96801_BUCK3_OCPN_STAT, "buck3-overcurr-n"),
DEFINE_RES_IRQ_NAMED(BD96801_BUCK3_OVD_STAT, "buck3-overvolt"),
DEFINE_RES_IRQ_NAMED(BD96801_BUCK3_UVD_STAT, "buck3-undervolt"),
DEFINE_RES_IRQ_NAMED(BD96801_BUCK3_TW_CH_STAT, "buck3-thermal"),
DEFINE_RES_IRQ_NAMED(BD96801_LDO7_OCPH_STAT, "bd96801-ldo7-overcurr"),
DEFINE_RES_IRQ_NAMED(BD96801_LDO7_OVD_STAT, "bd96801-ldo7-overvolt"),
DEFINE_RES_IRQ_NAMED(BD96801_LDO7_UVD_STAT, "bd96801-ldo7-undervolt"),
DEFINE_RES_IRQ_NAMED(BD96801_BUCK4_OCPH_STAT, "buck4-overcurr-h"),
DEFINE_RES_IRQ_NAMED(BD96801_BUCK4_OCPL_STAT, "buck4-overcurr-l"),
DEFINE_RES_IRQ_NAMED(BD96801_BUCK4_OCPN_STAT, "buck4-overcurr-n"),
DEFINE_RES_IRQ_NAMED(BD96801_BUCK4_OVD_STAT, "buck4-overvolt"),
DEFINE_RES_IRQ_NAMED(BD96801_BUCK4_UVD_STAT, "buck4-undervolt"),
DEFINE_RES_IRQ_NAMED(BD96801_BUCK4_TW_CH_STAT, "buck4-thermal"),
DEFINE_RES_IRQ_NAMED(BD96801_LDO5_OCPH_STAT, "ldo5-overcurr"),
DEFINE_RES_IRQ_NAMED(BD96801_LDO5_OVD_STAT, "ldo5-overvolt"),
DEFINE_RES_IRQ_NAMED(BD96801_LDO5_UVD_STAT, "ldo5-undervolt"),
DEFINE_RES_IRQ_NAMED(BD96801_LDO6_OCPH_STAT, "ldo6-overcurr"),
DEFINE_RES_IRQ_NAMED(BD96801_LDO6_OVD_STAT, "ldo6-overvolt"),
DEFINE_RES_IRQ_NAMED(BD96801_LDO6_UVD_STAT, "ldo6-undervolt"),
DEFINE_RES_IRQ_NAMED(BD96801_LDO7_OCPH_STAT, "ldo7-overcurr"),
DEFINE_RES_IRQ_NAMED(BD96801_LDO7_OVD_STAT, "ldo7-overvolt"),
DEFINE_RES_IRQ_NAMED(BD96801_LDO7_UVD_STAT, "ldo7-undervolt"),
};
static const struct resource bd96802_reg_intb_irqs[] = {
DEFINE_RES_IRQ_NAMED(BD96802_TW_STAT, "core-thermal"),
DEFINE_RES_IRQ_NAMED(BD96802_BUCK1_OCPH_STAT, "buck1-overcurr-h"),
DEFINE_RES_IRQ_NAMED(BD96802_BUCK1_OCPL_STAT, "buck1-overcurr-l"),
DEFINE_RES_IRQ_NAMED(BD96802_BUCK1_OCPN_STAT, "buck1-overcurr-n"),
DEFINE_RES_IRQ_NAMED(BD96802_BUCK1_OVD_STAT, "buck1-overvolt"),
DEFINE_RES_IRQ_NAMED(BD96802_BUCK1_UVD_STAT, "buck1-undervolt"),
DEFINE_RES_IRQ_NAMED(BD96802_BUCK1_TW_CH_STAT, "buck1-thermal"),
DEFINE_RES_IRQ_NAMED(BD96802_BUCK2_OCPH_STAT, "buck2-overcurr-h"),
DEFINE_RES_IRQ_NAMED(BD96802_BUCK2_OCPL_STAT, "buck2-overcurr-l"),
DEFINE_RES_IRQ_NAMED(BD96802_BUCK2_OCPN_STAT, "buck2-overcurr-n"),
DEFINE_RES_IRQ_NAMED(BD96802_BUCK2_OVD_STAT, "buck2-overvolt"),
DEFINE_RES_IRQ_NAMED(BD96802_BUCK2_UVD_STAT, "buck2-undervolt"),
DEFINE_RES_IRQ_NAMED(BD96802_BUCK2_TW_CH_STAT, "buck2-thermal"),
};
enum {
@ -152,6 +216,20 @@ static struct mfd_cell bd96801_cells[] = {
[REGULATOR_CELL] = { .name = "bd96801-regulator", },
};
static struct mfd_cell bd96802_cells[] = {
[WDG_CELL] = { .name = "bd96801-wdt", },
[REGULATOR_CELL] = { .name = "bd96802-regulator", },
};
static struct mfd_cell bd96805_cells[] = {
[WDG_CELL] = { .name = "bd96801-wdt", },
[REGULATOR_CELL] = { .name = "bd96805-regulator", },
};
static struct mfd_cell bd96806_cells[] = {
[WDG_CELL] = { .name = "bd96806-wdt", },
[REGULATOR_CELL] = { .name = "bd96806-regulator", },
};
static const struct regmap_range bd96801_volatile_ranges[] = {
/* Status registers */
regmap_reg_range(BD96801_REG_WD_FEED, BD96801_REG_WD_FAILCOUNT),
@ -169,11 +247,28 @@ static const struct regmap_range bd96801_volatile_ranges[] = {
regmap_reg_range(BD96801_LDO5_VOL_LVL_REG, BD96801_LDO7_VOL_LVL_REG),
};
static const struct regmap_access_table volatile_regs = {
static const struct regmap_range bd96802_volatile_ranges[] = {
/* Status regs */
regmap_reg_range(BD96801_REG_WD_FEED, BD96801_REG_WD_FAILCOUNT),
regmap_reg_range(BD96801_REG_WD_ASK, BD96801_REG_WD_ASK),
regmap_reg_range(BD96801_REG_WD_STATUS, BD96801_REG_WD_STATUS),
regmap_reg_range(BD96801_REG_PMIC_STATE, BD96801_REG_INT_BUCK2_ERRB),
regmap_reg_range(BD96801_REG_INT_SYS_INTB, BD96801_REG_INT_BUCK2_INTB),
/* Registers which do not update value unless PMIC is in STBY */
regmap_reg_range(BD96801_REG_SSCG_CTRL, BD96801_REG_SHD_INTB),
regmap_reg_range(BD96801_REG_BUCK_OVP, BD96801_REG_BOOT_OVERTIME),
};
static const struct regmap_access_table bd96801_volatile_regs = {
.yes_ranges = bd96801_volatile_ranges,
.n_yes_ranges = ARRAY_SIZE(bd96801_volatile_ranges),
};
static const struct regmap_access_table bd96802_volatile_regs = {
.yes_ranges = bd96802_volatile_ranges,
.n_yes_ranges = ARRAY_SIZE(bd96802_volatile_ranges),
};
/*
* For ERRB we need main register bit mapping as bit(0) indicates active IRQ
* in one of the first 3 sub IRQ registers, For INTB we can use default 1 to 1
@ -188,7 +283,7 @@ static unsigned int bit5_offsets[] = {7}; /* LDO 5 stat */
static unsigned int bit6_offsets[] = {8}; /* LDO 6 stat */
static unsigned int bit7_offsets[] = {9}; /* LDO 7 stat */
static const struct regmap_irq_sub_irq_map errb_sub_irq_offsets[] = {
static const struct regmap_irq_sub_irq_map bd96801_errb_sub_irq_offsets[] = {
REGMAP_IRQ_MAIN_REG_OFFSET(bit0_offsets),
REGMAP_IRQ_MAIN_REG_OFFSET(bit1_offsets),
REGMAP_IRQ_MAIN_REG_OFFSET(bit2_offsets),
@ -199,6 +294,12 @@ static const struct regmap_irq_sub_irq_map errb_sub_irq_offsets[] = {
REGMAP_IRQ_MAIN_REG_OFFSET(bit7_offsets),
};
static const struct regmap_irq_sub_irq_map bd96802_errb_sub_irq_offsets[] = {
REGMAP_IRQ_MAIN_REG_OFFSET(bit0_offsets),
REGMAP_IRQ_MAIN_REG_OFFSET(bit1_offsets),
REGMAP_IRQ_MAIN_REG_OFFSET(bit2_offsets),
};
static const struct regmap_irq bd96801_errb_irqs[] = {
/* Reg 0x52 Fatal ERRB1 */
REGMAP_IRQ_REG(BD96801_OTP_ERR_STAT, 0, BD96801_OTP_ERR_MASK),
@ -259,6 +360,39 @@ static const struct regmap_irq bd96801_errb_irqs[] = {
REGMAP_IRQ_REG(BD96801_LDO7_SHDN_ERR_STAT, 9, BD96801_OUT_SHDN_ERR_MASK),
};
static const struct regmap_irq bd96802_errb_irqs[] = {
/* Reg 0x52 Fatal ERRB1 */
REGMAP_IRQ_REG(BD96802_OTP_ERR_STAT, 0, BD96801_OTP_ERR_MASK),
REGMAP_IRQ_REG(BD96802_DBIST_ERR_STAT, 0, BD96801_DBIST_ERR_MASK),
REGMAP_IRQ_REG(BD96802_EEP_ERR_STAT, 0, BD96801_EEP_ERR_MASK),
REGMAP_IRQ_REG(BD96802_ABIST_ERR_STAT, 0, BD96801_ABIST_ERR_MASK),
REGMAP_IRQ_REG(BD96802_PRSTB_ERR_STAT, 0, BD96801_PRSTB_ERR_MASK),
REGMAP_IRQ_REG(BD96802_DRMOS1_ERR_STAT, 0, BD96801_DRMOS1_ERR_MASK),
REGMAP_IRQ_REG(BD96802_DRMOS2_ERR_STAT, 0, BD96801_DRMOS2_ERR_MASK),
REGMAP_IRQ_REG(BD96802_SLAVE_ERR_STAT, 0, BD96801_SLAVE_ERR_MASK),
/* 0x53 Fatal ERRB2 */
REGMAP_IRQ_REG(BD96802_VREF_ERR_STAT, 1, BD96801_VREF_ERR_MASK),
REGMAP_IRQ_REG(BD96802_TSD_ERR_STAT, 1, BD96801_TSD_ERR_MASK),
REGMAP_IRQ_REG(BD96802_UVLO_ERR_STAT, 1, BD96801_UVLO_ERR_MASK),
REGMAP_IRQ_REG(BD96802_OVLO_ERR_STAT, 1, BD96801_OVLO_ERR_MASK),
REGMAP_IRQ_REG(BD96802_OSC_ERR_STAT, 1, BD96801_OSC_ERR_MASK),
REGMAP_IRQ_REG(BD96802_PON_ERR_STAT, 1, BD96801_PON_ERR_MASK),
REGMAP_IRQ_REG(BD96802_POFF_ERR_STAT, 1, BD96801_POFF_ERR_MASK),
REGMAP_IRQ_REG(BD96802_CMD_SHDN_ERR_STAT, 1, BD96801_CMD_SHDN_ERR_MASK),
/* 0x54 Fatal INTB shadowed to ERRB */
REGMAP_IRQ_REG(BD96802_INT_SHDN_ERR_STAT, 2, BD96801_INT_SHDN_ERR_MASK),
/* Reg 0x55 BUCK1 ERR IRQs */
REGMAP_IRQ_REG(BD96802_BUCK1_PVIN_ERR_STAT, 3, BD96801_OUT_PVIN_ERR_MASK),
REGMAP_IRQ_REG(BD96802_BUCK1_OVP_ERR_STAT, 3, BD96801_OUT_OVP_ERR_MASK),
REGMAP_IRQ_REG(BD96802_BUCK1_UVP_ERR_STAT, 3, BD96801_OUT_UVP_ERR_MASK),
REGMAP_IRQ_REG(BD96802_BUCK1_SHDN_ERR_STAT, 3, BD96801_OUT_SHDN_ERR_MASK),
/* Reg 0x56 BUCK2 ERR IRQs */
REGMAP_IRQ_REG(BD96802_BUCK2_PVIN_ERR_STAT, 4, BD96801_OUT_PVIN_ERR_MASK),
REGMAP_IRQ_REG(BD96802_BUCK2_OVP_ERR_STAT, 4, BD96801_OUT_OVP_ERR_MASK),
REGMAP_IRQ_REG(BD96802_BUCK2_UVP_ERR_STAT, 4, BD96801_OUT_UVP_ERR_MASK),
REGMAP_IRQ_REG(BD96802_BUCK2_SHDN_ERR_STAT, 4, BD96801_OUT_SHDN_ERR_MASK),
};
static const struct regmap_irq bd96801_intb_irqs[] = {
/* STATUS SYSTEM INTB */
REGMAP_IRQ_REG(BD96801_TW_STAT, 0, BD96801_TW_STAT_MASK),
@ -307,6 +441,69 @@ static const struct regmap_irq bd96801_intb_irqs[] = {
REGMAP_IRQ_REG(BD96801_LDO7_UVD_STAT, 7, BD96801_LDO_UVD_STAT_MASK),
};
static const struct regmap_irq bd96802_intb_irqs[] = {
/* STATUS SYSTEM INTB */
REGMAP_IRQ_REG(BD96802_TW_STAT, 0, BD96801_TW_STAT_MASK),
REGMAP_IRQ_REG(BD96802_WDT_ERR_STAT, 0, BD96801_WDT_ERR_STAT_MASK),
REGMAP_IRQ_REG(BD96802_I2C_ERR_STAT, 0, BD96801_I2C_ERR_STAT_MASK),
REGMAP_IRQ_REG(BD96802_CHIP_IF_ERR_STAT, 0, BD96801_CHIP_IF_ERR_STAT_MASK),
/* STATUS BUCK1 INTB */
REGMAP_IRQ_REG(BD96802_BUCK1_OCPH_STAT, 1, BD96801_BUCK_OCPH_STAT_MASK),
REGMAP_IRQ_REG(BD96802_BUCK1_OCPL_STAT, 1, BD96801_BUCK_OCPL_STAT_MASK),
REGMAP_IRQ_REG(BD96802_BUCK1_OCPN_STAT, 1, BD96801_BUCK_OCPN_STAT_MASK),
REGMAP_IRQ_REG(BD96802_BUCK1_OVD_STAT, 1, BD96801_BUCK_OVD_STAT_MASK),
REGMAP_IRQ_REG(BD96802_BUCK1_UVD_STAT, 1, BD96801_BUCK_UVD_STAT_MASK),
REGMAP_IRQ_REG(BD96802_BUCK1_TW_CH_STAT, 1, BD96801_BUCK_TW_CH_STAT_MASK),
/* BUCK 2 INTB */
REGMAP_IRQ_REG(BD96802_BUCK2_OCPH_STAT, 2, BD96801_BUCK_OCPH_STAT_MASK),
REGMAP_IRQ_REG(BD96802_BUCK2_OCPL_STAT, 2, BD96801_BUCK_OCPL_STAT_MASK),
REGMAP_IRQ_REG(BD96802_BUCK2_OCPN_STAT, 2, BD96801_BUCK_OCPN_STAT_MASK),
REGMAP_IRQ_REG(BD96802_BUCK2_OVD_STAT, 2, BD96801_BUCK_OVD_STAT_MASK),
REGMAP_IRQ_REG(BD96802_BUCK2_UVD_STAT, 2, BD96801_BUCK_UVD_STAT_MASK),
REGMAP_IRQ_REG(BD96802_BUCK2_TW_CH_STAT, 2, BD96801_BUCK_TW_CH_STAT_MASK),
};
/*
* The IRQ stuff is a bit hairy. The BD96801 / BD96802 provide two physical
* IRQ lines called INTB and ERRB. They share the same main status register.
*
* For ERRB, mapping from main status to sub-status is such that the
* 'global' faults are mapped to first 3 sub-status registers - and indicated
* by the first bit[0] in main status reg.
*
* Rest of the status registers are for indicating stuff for individual
* regulators, 1 sub register / regulator and 1 main status register bit /
* regulator, starting from bit[1].
*
* Eg, regulator specific stuff has 1 to 1 mapping from main-status to sub
* registers but 'global' ERRB IRQs require mapping from main status bit[0] to
* 3 status registers.
*
* Furthermore, the BD96801 has 7 regulators where the BD96802 has only 2.
*
* INTB has only 1 sub status register for 'global' events and then own sub
* status register for each of the regulators. So, for INTB we have direct
* 1 to 1 mapping - BD96801 just having 5 register and 5 main status bits
* more than the BD96802.
*
* Sharing the main status bits could be a problem if we had both INTB and
* ERRB IRQs asserted but for different sub-status offsets. This might lead
* IRQ controller code to go read a sub status register which indicates no
* active IRQs. I assume this occurring repeteadly might lead the IRQ to be
* disabled by core as a result of repeteadly returned IRQ_NONEs.
*
* I don't consider this as a fatal problem for now because:
* a) Having ERRB asserted leads to PMIC fault state which will kill
* the SoC powered by the PMIC. (So, relevant only for potential
* case of not powering the processor with this PMIC).
* b) Having ERRB set without having respective INTB is unlikely
* (haven't actually verified this).
*
* So, let's proceed with main status enabled for both INTB and ERRB. We can
* later disable main-status usage on systems where this ever proves to be
* a problem.
*/
static const struct regmap_irq_chip bd96801_irq_chip_errb = {
.name = "bd96801-irq-errb",
.domain_suffix = "errb",
@ -320,7 +517,23 @@ static const struct regmap_irq_chip bd96801_irq_chip_errb = {
.init_ack_masked = true,
.num_regs = 10,
.irq_reg_stride = 1,
.sub_reg_offsets = &errb_sub_irq_offsets[0],
.sub_reg_offsets = &bd96801_errb_sub_irq_offsets[0],
};
static const struct regmap_irq_chip bd96802_irq_chip_errb = {
.name = "bd96802-irq-errb",
.domain_suffix = "errb",
.main_status = BD96801_REG_INT_MAIN,
.num_main_regs = 1,
.irqs = &bd96802_errb_irqs[0],
.num_irqs = ARRAY_SIZE(bd96802_errb_irqs),
.status_base = BD96801_REG_INT_SYS_ERRB1,
.mask_base = BD96801_REG_MASK_SYS_ERRB,
.ack_base = BD96801_REG_INT_SYS_ERRB1,
.init_ack_masked = true,
.num_regs = 5,
.irq_reg_stride = 1,
.sub_reg_offsets = &bd96802_errb_sub_irq_offsets[0],
};
static const struct regmap_irq_chip bd96801_irq_chip_intb = {
@ -338,25 +551,124 @@ static const struct regmap_irq_chip bd96801_irq_chip_intb = {
.irq_reg_stride = 1,
};
static const struct regmap_irq_chip bd96802_irq_chip_intb = {
.name = "bd96802-irq-intb",
.domain_suffix = "intb",
.main_status = BD96801_REG_INT_MAIN,
.num_main_regs = 1,
.irqs = &bd96802_intb_irqs[0],
.num_irqs = ARRAY_SIZE(bd96802_intb_irqs),
.status_base = BD96801_REG_INT_SYS_INTB,
.mask_base = BD96801_REG_MASK_SYS_INTB,
.ack_base = BD96801_REG_INT_SYS_INTB,
.init_ack_masked = true,
.num_regs = 3,
.irq_reg_stride = 1,
};
static const struct regmap_config bd96801_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.volatile_table = &volatile_regs,
.volatile_table = &bd96801_volatile_regs,
.cache_type = REGCACHE_MAPLE,
};
static const struct regmap_config bd96802_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.volatile_table = &bd96802_volatile_regs,
.cache_type = REGCACHE_MAPLE,
};
static const struct bd968xx bd96801_data = {
.errb_irqs = bd96801_reg_errb_irqs,
.intb_irqs = bd96801_reg_intb_irqs,
.num_errb_irqs = ARRAY_SIZE(bd96801_reg_errb_irqs),
.num_intb_irqs = ARRAY_SIZE(bd96801_reg_intb_irqs),
.errb_irq_chip = &bd96801_irq_chip_errb,
.intb_irq_chip = &bd96801_irq_chip_intb,
.regmap_config = &bd96801_regmap_config,
.cells = bd96801_cells,
.num_cells = ARRAY_SIZE(bd96801_cells),
.unlock_reg = BD96801_LOCK_REG,
.unlock_val = BD96801_UNLOCK,
};
static const struct bd968xx bd96802_data = {
.errb_irqs = bd96802_reg_errb_irqs,
.intb_irqs = bd96802_reg_intb_irqs,
.num_errb_irqs = ARRAY_SIZE(bd96802_reg_errb_irqs),
.num_intb_irqs = ARRAY_SIZE(bd96802_reg_intb_irqs),
.errb_irq_chip = &bd96802_irq_chip_errb,
.intb_irq_chip = &bd96802_irq_chip_intb,
.regmap_config = &bd96802_regmap_config,
.cells = bd96802_cells,
.num_cells = ARRAY_SIZE(bd96802_cells),
.unlock_reg = BD96801_LOCK_REG,
.unlock_val = BD96801_UNLOCK,
};
static const struct bd968xx bd96805_data = {
.errb_irqs = bd96801_reg_errb_irqs,
.intb_irqs = bd96801_reg_intb_irqs,
.num_errb_irqs = ARRAY_SIZE(bd96801_reg_errb_irqs),
.num_intb_irqs = ARRAY_SIZE(bd96801_reg_intb_irqs),
.errb_irq_chip = &bd96801_irq_chip_errb,
.intb_irq_chip = &bd96801_irq_chip_intb,
.regmap_config = &bd96801_regmap_config,
.cells = bd96805_cells,
.num_cells = ARRAY_SIZE(bd96805_cells),
.unlock_reg = BD96801_LOCK_REG,
.unlock_val = BD96801_UNLOCK,
};
static struct bd968xx bd96806_data = {
.errb_irqs = bd96802_reg_errb_irqs,
.intb_irqs = bd96802_reg_intb_irqs,
.num_errb_irqs = ARRAY_SIZE(bd96802_reg_errb_irqs),
.num_intb_irqs = ARRAY_SIZE(bd96802_reg_intb_irqs),
.errb_irq_chip = &bd96802_irq_chip_errb,
.intb_irq_chip = &bd96802_irq_chip_intb,
.regmap_config = &bd96802_regmap_config,
.cells = bd96806_cells,
.num_cells = ARRAY_SIZE(bd96806_cells),
.unlock_reg = BD96801_LOCK_REG,
.unlock_val = BD96801_UNLOCK,
};
static int bd96801_i2c_probe(struct i2c_client *i2c)
{
struct regmap_irq_chip_data *intb_irq_data, *errb_irq_data;
struct irq_domain *intb_domain, *errb_domain;
const struct bd968xx *ddata;
const struct fwnode_handle *fwnode;
struct resource *regulator_res;
struct resource wdg_irq;
struct regmap *regmap;
int intb_irq, errb_irq, num_intb, num_errb = 0;
int intb_irq, errb_irq, num_errb = 0;
int num_regu_irqs, wdg_irq_no;
unsigned int chip_type;
int i, ret;
chip_type = (unsigned int)(uintptr_t)device_get_match_data(&i2c->dev);
switch (chip_type) {
case ROHM_CHIP_TYPE_BD96801:
ddata = &bd96801_data;
break;
case ROHM_CHIP_TYPE_BD96802:
ddata = &bd96802_data;
break;
case ROHM_CHIP_TYPE_BD96805:
ddata = &bd96805_data;
break;
case ROHM_CHIP_TYPE_BD96806:
ddata = &bd96806_data;
break;
default:
dev_err(&i2c->dev, "Unknown IC\n");
return -EINVAL;
}
fwnode = dev_fwnode(&i2c->dev);
if (!fwnode)
return dev_err_probe(&i2c->dev, -EINVAL, "Failed to find fwnode\n");
@ -365,34 +677,32 @@ static int bd96801_i2c_probe(struct i2c_client *i2c)
if (intb_irq < 0)
return dev_err_probe(&i2c->dev, intb_irq, "INTB IRQ not configured\n");
num_intb = ARRAY_SIZE(regulator_intb_irqs);
/* ERRB may be omitted if processor is powered by the PMIC */
errb_irq = fwnode_irq_get_byname(fwnode, "errb");
if (errb_irq < 0)
errb_irq = 0;
if (errb_irq == -EPROBE_DEFER)
return errb_irq;
if (errb_irq)
num_errb = ARRAY_SIZE(regulator_errb_irqs);
if (errb_irq > 0)
num_errb = ddata->num_errb_irqs;
num_regu_irqs = num_intb + num_errb;
num_regu_irqs = ddata->num_intb_irqs + num_errb;
regulator_res = devm_kcalloc(&i2c->dev, num_regu_irqs,
sizeof(*regulator_res), GFP_KERNEL);
if (!regulator_res)
return -ENOMEM;
regmap = devm_regmap_init_i2c(i2c, &bd96801_regmap_config);
regmap = devm_regmap_init_i2c(i2c, ddata->regmap_config);
if (IS_ERR(regmap))
return dev_err_probe(&i2c->dev, PTR_ERR(regmap),
"Regmap initialization failed\n");
ret = regmap_write(regmap, BD96801_LOCK_REG, BD96801_UNLOCK);
ret = regmap_write(regmap, ddata->unlock_reg, ddata->unlock_val);
if (ret)
return dev_err_probe(&i2c->dev, ret, "Failed to unlock PMIC\n");
ret = devm_regmap_add_irq_chip(&i2c->dev, regmap, intb_irq,
IRQF_ONESHOT, 0, &bd96801_irq_chip_intb,
IRQF_ONESHOT, 0, ddata->intb_irq_chip,
&intb_irq_data);
if (ret)
return dev_err_probe(&i2c->dev, ret, "Failed to add INTB IRQ chip\n");
@ -404,24 +714,25 @@ static int bd96801_i2c_probe(struct i2c_client *i2c)
* has two domains so we do IRQ mapping here and provide the
* already mapped IRQ numbers to sub-devices.
*/
for (i = 0; i < num_intb; i++) {
for (i = 0; i < ddata->num_intb_irqs; i++) {
struct resource *res = &regulator_res[i];
*res = regulator_intb_irqs[i];
*res = ddata->intb_irqs[i];
res->start = res->end = irq_create_mapping(intb_domain,
res->start);
}
wdg_irq_no = irq_create_mapping(intb_domain, BD96801_WDT_ERR_STAT);
wdg_irq = DEFINE_RES_IRQ_NAMED(wdg_irq_no, "bd96801-wdg");
bd96801_cells[WDG_CELL].resources = &wdg_irq;
bd96801_cells[WDG_CELL].num_resources = 1;
ddata->cells[WDG_CELL].resources = &wdg_irq;
ddata->cells[WDG_CELL].num_resources = 1;
if (!num_errb)
goto skip_errb;
ret = devm_regmap_add_irq_chip(&i2c->dev, regmap, errb_irq, IRQF_ONESHOT,
0, &bd96801_irq_chip_errb, &errb_irq_data);
0, ddata->errb_irq_chip, &errb_irq_data);
if (ret)
return dev_err_probe(&i2c->dev, ret,
"Failed to add ERRB IRQ chip\n");
@ -429,18 +740,17 @@ static int bd96801_i2c_probe(struct i2c_client *i2c)
errb_domain = regmap_irq_get_domain(errb_irq_data);
for (i = 0; i < num_errb; i++) {
struct resource *res = &regulator_res[num_intb + i];
struct resource *res = &regulator_res[ddata->num_intb_irqs + i];
*res = regulator_errb_irqs[i];
*res = ddata->errb_irqs[i];
res->start = res->end = irq_create_mapping(errb_domain, res->start);
}
skip_errb:
bd96801_cells[REGULATOR_CELL].resources = regulator_res;
bd96801_cells[REGULATOR_CELL].num_resources = num_regu_irqs;
ret = devm_mfd_add_devices(&i2c->dev, PLATFORM_DEVID_AUTO, bd96801_cells,
ARRAY_SIZE(bd96801_cells), NULL, 0, NULL);
ddata->cells[REGULATOR_CELL].resources = regulator_res;
ddata->cells[REGULATOR_CELL].num_resources = num_regu_irqs;
ret = devm_mfd_add_devices(&i2c->dev, PLATFORM_DEVID_AUTO, ddata->cells,
ddata->num_cells, NULL, 0, NULL);
if (ret)
dev_err_probe(&i2c->dev, ret, "Failed to create subdevices\n");
@ -448,7 +758,10 @@ skip_errb:
}
static const struct of_device_id bd96801_of_match[] = {
{ .compatible = "rohm,bd96801", },
{ .compatible = "rohm,bd96801", .data = (void *)ROHM_CHIP_TYPE_BD96801 },
{ .compatible = "rohm,bd96802", .data = (void *)ROHM_CHIP_TYPE_BD96802 },
{ .compatible = "rohm,bd96805", .data = (void *)ROHM_CHIP_TYPE_BD96805 },
{ .compatible = "rohm,bd96806", .data = (void *)ROHM_CHIP_TYPE_BD96806 },
{ }
};
MODULE_DEVICE_TABLE(of, bd96801_of_match);
@ -476,5 +789,5 @@ static void __exit bd96801_i2c_exit(void)
module_exit(bd96801_i2c_exit);
MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>");
MODULE_DESCRIPTION("ROHM BD96801 Power Management IC driver");
MODULE_DESCRIPTION("ROHM BD9680X Power Management IC driver");
MODULE_LICENSE("GPL");

View File

@ -98,7 +98,11 @@ static int rt5033_i2c_probe(struct i2c_client *i2c)
return ret;
}
device_init_wakeup(rt5033->dev, rt5033->wakeup);
if (rt5033->wakeup) {
ret = devm_device_init_wakeup(rt5033->dev);
if (ret)
return dev_err_probe(rt5033->dev, ret, "Failed to init wakeup\n");
}
return 0;
}

442
drivers/mfd/sec-acpm.c Normal file
View File

@ -0,0 +1,442 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright 2020 Google Inc
* Copyright 2025 Linaro Ltd.
*
* Samsung S2MPG1x ACPM driver
*/
#include <linux/array_size.h>
#include <linux/bitops.h>
#include <linux/device.h>
#include <linux/firmware/samsung/exynos-acpm-protocol.h>
#include <linux/mfd/samsung/core.h>
#include <linux/mfd/samsung/rtc.h>
#include <linux/mfd/samsung/s2mpg10.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pm.h>
#include <linux/property.h>
#include <linux/regmap.h>
#include "sec-core.h"
#define ACPM_ADDR_BITS 8
#define ACPM_MAX_BULK_DATA 8
struct sec_pmic_acpm_platform_data {
int device_type;
unsigned int acpm_chan_id;
u8 speedy_channel;
const struct regmap_config *regmap_cfg_common;
const struct regmap_config *regmap_cfg_pmic;
const struct regmap_config *regmap_cfg_rtc;
const struct regmap_config *regmap_cfg_meter;
};
static const struct regmap_range s2mpg10_common_registers[] = {
regmap_reg_range(0x00, 0x02), /* CHIP_ID_M, INT, INT_MASK */
regmap_reg_range(0x0a, 0x0c), /* Speedy control */
regmap_reg_range(0x1a, 0x2a), /* Debug */
};
static const struct regmap_range s2mpg10_common_ro_registers[] = {
regmap_reg_range(0x00, 0x01), /* CHIP_ID_M, INT */
regmap_reg_range(0x28, 0x2a), /* Debug */
};
static const struct regmap_range s2mpg10_common_nonvolatile_registers[] = {
regmap_reg_range(0x00, 0x00), /* CHIP_ID_M */
regmap_reg_range(0x02, 0x02), /* INT_MASK */
regmap_reg_range(0x0a, 0x0c), /* Speedy control */
};
static const struct regmap_range s2mpg10_common_precious_registers[] = {
regmap_reg_range(0x01, 0x01), /* INT */
};
static const struct regmap_access_table s2mpg10_common_wr_table = {
.yes_ranges = s2mpg10_common_registers,
.n_yes_ranges = ARRAY_SIZE(s2mpg10_common_registers),
.no_ranges = s2mpg10_common_ro_registers,
.n_no_ranges = ARRAY_SIZE(s2mpg10_common_ro_registers),
};
static const struct regmap_access_table s2mpg10_common_rd_table = {
.yes_ranges = s2mpg10_common_registers,
.n_yes_ranges = ARRAY_SIZE(s2mpg10_common_registers),
};
static const struct regmap_access_table s2mpg10_common_volatile_table = {
.no_ranges = s2mpg10_common_nonvolatile_registers,
.n_no_ranges = ARRAY_SIZE(s2mpg10_common_nonvolatile_registers),
};
static const struct regmap_access_table s2mpg10_common_precious_table = {
.yes_ranges = s2mpg10_common_precious_registers,
.n_yes_ranges = ARRAY_SIZE(s2mpg10_common_precious_registers),
};
static const struct regmap_config s2mpg10_regmap_config_common = {
.name = "common",
.reg_bits = ACPM_ADDR_BITS,
.val_bits = 8,
.max_register = S2MPG10_COMMON_SPD_DEBUG4,
.wr_table = &s2mpg10_common_wr_table,
.rd_table = &s2mpg10_common_rd_table,
.volatile_table = &s2mpg10_common_volatile_table,
.precious_table = &s2mpg10_common_precious_table,
.num_reg_defaults_raw = S2MPG10_COMMON_SPD_DEBUG4 + 1,
.cache_type = REGCACHE_FLAT,
};
static const struct regmap_range s2mpg10_pmic_registers[] = {
regmap_reg_range(0x00, 0xf6), /* All PMIC registers */
};
static const struct regmap_range s2mpg10_pmic_ro_registers[] = {
regmap_reg_range(0x00, 0x05), /* INTx */
regmap_reg_range(0x0c, 0x0f), /* STATUSx PWRONSRC OFFSRC */
regmap_reg_range(0xc7, 0xc7), /* GPIO input */
};
static const struct regmap_range s2mpg10_pmic_nonvolatile_registers[] = {
regmap_reg_range(0x06, 0x0b), /* INTxM */
};
static const struct regmap_range s2mpg10_pmic_precious_registers[] = {
regmap_reg_range(0x00, 0x05), /* INTx */
};
static const struct regmap_access_table s2mpg10_pmic_wr_table = {
.yes_ranges = s2mpg10_pmic_registers,
.n_yes_ranges = ARRAY_SIZE(s2mpg10_pmic_registers),
.no_ranges = s2mpg10_pmic_ro_registers,
.n_no_ranges = ARRAY_SIZE(s2mpg10_pmic_ro_registers),
};
static const struct regmap_access_table s2mpg10_pmic_rd_table = {
.yes_ranges = s2mpg10_pmic_registers,
.n_yes_ranges = ARRAY_SIZE(s2mpg10_pmic_registers),
};
static const struct regmap_access_table s2mpg10_pmic_volatile_table = {
.no_ranges = s2mpg10_pmic_nonvolatile_registers,
.n_no_ranges = ARRAY_SIZE(s2mpg10_pmic_nonvolatile_registers),
};
static const struct regmap_access_table s2mpg10_pmic_precious_table = {
.yes_ranges = s2mpg10_pmic_precious_registers,
.n_yes_ranges = ARRAY_SIZE(s2mpg10_pmic_precious_registers),
};
static const struct regmap_config s2mpg10_regmap_config_pmic = {
.name = "pmic",
.reg_bits = ACPM_ADDR_BITS,
.val_bits = 8,
.max_register = S2MPG10_PMIC_LDO_SENSE4,
.wr_table = &s2mpg10_pmic_wr_table,
.rd_table = &s2mpg10_pmic_rd_table,
.volatile_table = &s2mpg10_pmic_volatile_table,
.precious_table = &s2mpg10_pmic_precious_table,
.num_reg_defaults_raw = S2MPG10_PMIC_LDO_SENSE4 + 1,
.cache_type = REGCACHE_FLAT,
};
static const struct regmap_range s2mpg10_rtc_registers[] = {
regmap_reg_range(0x00, 0x2b), /* All RTC registers */
};
static const struct regmap_range s2mpg10_rtc_volatile_registers[] = {
regmap_reg_range(0x01, 0x01), /* RTC_UPDATE */
regmap_reg_range(0x05, 0x0c), /* Time / date */
};
static const struct regmap_access_table s2mpg10_rtc_rd_table = {
.yes_ranges = s2mpg10_rtc_registers,
.n_yes_ranges = ARRAY_SIZE(s2mpg10_rtc_registers),
};
static const struct regmap_access_table s2mpg10_rtc_volatile_table = {
.yes_ranges = s2mpg10_rtc_volatile_registers,
.n_yes_ranges = ARRAY_SIZE(s2mpg10_rtc_volatile_registers),
};
static const struct regmap_config s2mpg10_regmap_config_rtc = {
.name = "rtc",
.reg_bits = ACPM_ADDR_BITS,
.val_bits = 8,
.max_register = S2MPG10_RTC_OSC_CTRL,
.rd_table = &s2mpg10_rtc_rd_table,
.volatile_table = &s2mpg10_rtc_volatile_table,
.num_reg_defaults_raw = S2MPG10_RTC_OSC_CTRL + 1,
.cache_type = REGCACHE_FLAT,
};
static const struct regmap_range s2mpg10_meter_registers[] = {
regmap_reg_range(0x00, 0x21), /* Meter config */
regmap_reg_range(0x40, 0x8a), /* Meter data */
regmap_reg_range(0xee, 0xee), /* Offset */
regmap_reg_range(0xf1, 0xf1), /* Trim */
};
static const struct regmap_range s2mpg10_meter_ro_registers[] = {
regmap_reg_range(0x40, 0x8a), /* Meter data */
};
static const struct regmap_access_table s2mpg10_meter_wr_table = {
.yes_ranges = s2mpg10_meter_registers,
.n_yes_ranges = ARRAY_SIZE(s2mpg10_meter_registers),
.no_ranges = s2mpg10_meter_ro_registers,
.n_no_ranges = ARRAY_SIZE(s2mpg10_meter_ro_registers),
};
static const struct regmap_access_table s2mpg10_meter_rd_table = {
.yes_ranges = s2mpg10_meter_registers,
.n_yes_ranges = ARRAY_SIZE(s2mpg10_meter_registers),
};
static const struct regmap_access_table s2mpg10_meter_volatile_table = {
.yes_ranges = s2mpg10_meter_ro_registers,
.n_yes_ranges = ARRAY_SIZE(s2mpg10_meter_ro_registers),
};
static const struct regmap_config s2mpg10_regmap_config_meter = {
.name = "meter",
.reg_bits = ACPM_ADDR_BITS,
.val_bits = 8,
.max_register = S2MPG10_METER_BUCK_METER_TRIM3,
.wr_table = &s2mpg10_meter_wr_table,
.rd_table = &s2mpg10_meter_rd_table,
.volatile_table = &s2mpg10_meter_volatile_table,
.num_reg_defaults_raw = S2MPG10_METER_BUCK_METER_TRIM3 + 1,
.cache_type = REGCACHE_FLAT,
};
struct sec_pmic_acpm_shared_bus_context {
const struct acpm_handle *acpm;
unsigned int acpm_chan_id;
u8 speedy_channel;
};
enum sec_pmic_acpm_accesstype {
SEC_PMIC_ACPM_ACCESSTYPE_COMMON = 0x00,
SEC_PMIC_ACPM_ACCESSTYPE_PMIC = 0x01,
SEC_PMIC_ACPM_ACCESSTYPE_RTC = 0x02,
SEC_PMIC_ACPM_ACCESSTYPE_METER = 0x0a,
SEC_PMIC_ACPM_ACCESSTYPE_WLWP = 0x0b,
SEC_PMIC_ACPM_ACCESSTYPE_TRIM = 0x0f,
};
struct sec_pmic_acpm_bus_context {
struct sec_pmic_acpm_shared_bus_context *shared;
enum sec_pmic_acpm_accesstype type;
};
static int sec_pmic_acpm_bus_write(void *context, const void *data,
size_t count)
{
struct sec_pmic_acpm_bus_context *ctx = context;
const struct acpm_handle *acpm = ctx->shared->acpm;
const struct acpm_pmic_ops *pmic_ops = &acpm->ops.pmic_ops;
size_t val_count = count - BITS_TO_BYTES(ACPM_ADDR_BITS);
const u8 *d = data;
const u8 *vals = &d[BITS_TO_BYTES(ACPM_ADDR_BITS)];
u8 reg;
if (val_count < 1 || val_count > ACPM_MAX_BULK_DATA)
return -EINVAL;
reg = d[0];
return pmic_ops->bulk_write(acpm, ctx->shared->acpm_chan_id, ctx->type, reg,
ctx->shared->speedy_channel, val_count, vals);
}
static int sec_pmic_acpm_bus_read(void *context, const void *reg_buf, size_t reg_size,
void *val_buf, size_t val_size)
{
struct sec_pmic_acpm_bus_context *ctx = context;
const struct acpm_handle *acpm = ctx->shared->acpm;
const struct acpm_pmic_ops *pmic_ops = &acpm->ops.pmic_ops;
const u8 *r = reg_buf;
u8 reg;
if (reg_size != BITS_TO_BYTES(ACPM_ADDR_BITS) || !val_size ||
val_size > ACPM_MAX_BULK_DATA)
return -EINVAL;
reg = r[0];
return pmic_ops->bulk_read(acpm, ctx->shared->acpm_chan_id, ctx->type, reg,
ctx->shared->speedy_channel, val_size, val_buf);
}
static int sec_pmic_acpm_bus_reg_update_bits(void *context, unsigned int reg, unsigned int mask,
unsigned int val)
{
struct sec_pmic_acpm_bus_context *ctx = context;
const struct acpm_handle *acpm = ctx->shared->acpm;
const struct acpm_pmic_ops *pmic_ops = &acpm->ops.pmic_ops;
return pmic_ops->update_reg(acpm, ctx->shared->acpm_chan_id, ctx->type, reg & 0xff,
ctx->shared->speedy_channel, val, mask);
}
static const struct regmap_bus sec_pmic_acpm_regmap_bus = {
.write = sec_pmic_acpm_bus_write,
.read = sec_pmic_acpm_bus_read,
.reg_update_bits = sec_pmic_acpm_bus_reg_update_bits,
.max_raw_read = ACPM_MAX_BULK_DATA,
.max_raw_write = ACPM_MAX_BULK_DATA,
};
static struct regmap *sec_pmic_acpm_regmap_init(struct device *dev,
struct sec_pmic_acpm_shared_bus_context *shared_ctx,
enum sec_pmic_acpm_accesstype type,
const struct regmap_config *cfg, bool do_attach)
{
struct sec_pmic_acpm_bus_context *ctx;
struct regmap *regmap;
ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
if (!ctx)
return ERR_PTR(-ENOMEM);
ctx->shared = shared_ctx;
ctx->type = type;
regmap = devm_regmap_init(dev, &sec_pmic_acpm_regmap_bus, ctx, cfg);
if (IS_ERR(regmap))
return dev_err_cast_probe(dev, regmap, "regmap init (%s) failed\n", cfg->name);
if (do_attach) {
int ret;
ret = regmap_attach_dev(dev, regmap, cfg);
if (ret)
return dev_err_ptr_probe(dev, ret, "regmap attach (%s) failed\n",
cfg->name);
}
return regmap;
}
static void sec_pmic_acpm_mask_common_irqs(void *regmap_common)
{
regmap_write(regmap_common, S2MPG10_COMMON_INT_MASK, S2MPG10_COMMON_INT_SRC);
}
static int sec_pmic_acpm_probe(struct platform_device *pdev)
{
struct regmap *regmap_common, *regmap_pmic, *regmap;
const struct sec_pmic_acpm_platform_data *pdata;
struct sec_pmic_acpm_shared_bus_context *shared_ctx;
const struct acpm_handle *acpm;
struct device *dev = &pdev->dev;
int ret, irq;
pdata = device_get_match_data(dev);
if (!pdata)
return dev_err_probe(dev, -ENODEV, "unsupported device type\n");
acpm = devm_acpm_get_by_node(dev, dev->parent->of_node);
if (IS_ERR(acpm))
return dev_err_probe(dev, PTR_ERR(acpm), "failed to get acpm\n");
irq = platform_get_irq(pdev, 0);
if (irq < 0)
return irq;
shared_ctx = devm_kzalloc(dev, sizeof(*shared_ctx), GFP_KERNEL);
if (!shared_ctx)
return -ENOMEM;
shared_ctx->acpm = acpm;
shared_ctx->acpm_chan_id = pdata->acpm_chan_id;
shared_ctx->speedy_channel = pdata->speedy_channel;
regmap_common = sec_pmic_acpm_regmap_init(dev, shared_ctx, SEC_PMIC_ACPM_ACCESSTYPE_COMMON,
pdata->regmap_cfg_common, false);
if (IS_ERR(regmap_common))
return PTR_ERR(regmap_common);
/* Mask all interrupts from 'common' block, until successful init */
ret = regmap_write(regmap_common, S2MPG10_COMMON_INT_MASK, S2MPG10_COMMON_INT_SRC);
if (ret)
return dev_err_probe(dev, ret, "failed to mask common block interrupts\n");
regmap_pmic = sec_pmic_acpm_regmap_init(dev, shared_ctx, SEC_PMIC_ACPM_ACCESSTYPE_PMIC,
pdata->regmap_cfg_pmic, false);
if (IS_ERR(regmap_pmic))
return PTR_ERR(regmap_pmic);
regmap = sec_pmic_acpm_regmap_init(dev, shared_ctx, SEC_PMIC_ACPM_ACCESSTYPE_RTC,
pdata->regmap_cfg_rtc, true);
if (IS_ERR(regmap))
return PTR_ERR(regmap);
regmap = sec_pmic_acpm_regmap_init(dev, shared_ctx, SEC_PMIC_ACPM_ACCESSTYPE_METER,
pdata->regmap_cfg_meter, true);
if (IS_ERR(regmap))
return PTR_ERR(regmap);
ret = sec_pmic_probe(dev, pdata->device_type, irq, regmap_pmic, NULL);
if (ret)
return ret;
if (device_property_read_bool(dev, "wakeup-source"))
devm_device_init_wakeup(dev);
/* Unmask PMIC interrupt from 'common' block, now that everything is in place. */
ret = regmap_clear_bits(regmap_common, S2MPG10_COMMON_INT_MASK,
S2MPG10_COMMON_INT_SRC_PMIC);
if (ret)
return dev_err_probe(dev, ret, "failed to unmask PMIC interrupt\n");
/* Mask all interrupts from 'common' block on shutdown */
ret = devm_add_action_or_reset(dev, sec_pmic_acpm_mask_common_irqs, regmap_common);
if (ret)
return ret;
return 0;
}
static void sec_pmic_acpm_shutdown(struct platform_device *pdev)
{
sec_pmic_shutdown(&pdev->dev);
}
static const struct sec_pmic_acpm_platform_data s2mpg10_data = {
.device_type = S2MPG10,
.acpm_chan_id = 2,
.speedy_channel = 0,
.regmap_cfg_common = &s2mpg10_regmap_config_common,
.regmap_cfg_pmic = &s2mpg10_regmap_config_pmic,
.regmap_cfg_rtc = &s2mpg10_regmap_config_rtc,
.regmap_cfg_meter = &s2mpg10_regmap_config_meter,
};
static const struct of_device_id sec_pmic_acpm_of_match[] = {
{ .compatible = "samsung,s2mpg10-pmic", .data = &s2mpg10_data, },
{ },
};
MODULE_DEVICE_TABLE(of, sec_pmic_acpm_of_match);
static struct platform_driver sec_pmic_acpm_driver = {
.driver = {
.name = "sec-pmic-acpm",
.pm = pm_sleep_ptr(&sec_pmic_pm_ops),
.of_match_table = sec_pmic_acpm_of_match,
},
.probe = sec_pmic_acpm_probe,
.shutdown = sec_pmic_acpm_shutdown,
};
module_platform_driver(sec_pmic_acpm_driver);
MODULE_AUTHOR("André Draszik <andre.draszik@linaro.org>");
MODULE_DESCRIPTION("ACPM driver for the Samsung S2MPG1x");
MODULE_LICENSE("GPL");

301
drivers/mfd/sec-common.c Normal file
View File

@ -0,0 +1,301 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright 2012 Samsung Electronics Co., Ltd
* http://www.samsung.com
* Copyright 2025 Linaro Ltd.
*
* Samsung SxM core driver
*/
#include <linux/device.h>
#include <linux/err.h>
#include <linux/export.h>
#include <linux/interrupt.h>
#include <linux/mfd/core.h>
#include <linux/mfd/samsung/core.h>
#include <linux/mfd/samsung/irq.h>
#include <linux/mfd/samsung/s2mps11.h>
#include <linux/mfd/samsung/s2mps13.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/pm.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include "sec-core.h"
static const struct mfd_cell s5m8767_devs[] = {
MFD_CELL_NAME("s5m8767-pmic"),
MFD_CELL_NAME("s5m-rtc"),
MFD_CELL_OF("s5m8767-clk", NULL, NULL, 0, 0, "samsung,s5m8767-clk"),
};
static const struct mfd_cell s2dos05_devs[] = {
MFD_CELL_NAME("s2dos05-regulator"),
};
static const struct mfd_cell s2mpg10_devs[] = {
MFD_CELL_NAME("s2mpg10-meter"),
MFD_CELL_NAME("s2mpg10-regulator"),
MFD_CELL_NAME("s2mpg10-rtc"),
MFD_CELL_OF("s2mpg10-clk", NULL, NULL, 0, 0, "samsung,s2mpg10-clk"),
MFD_CELL_OF("s2mpg10-gpio", NULL, NULL, 0, 0, "samsung,s2mpg10-gpio"),
};
static const struct mfd_cell s2mps11_devs[] = {
MFD_CELL_NAME("s2mps11-regulator"),
MFD_CELL_NAME("s2mps14-rtc"),
MFD_CELL_OF("s2mps11-clk", NULL, NULL, 0, 0, "samsung,s2mps11-clk"),
};
static const struct mfd_cell s2mps13_devs[] = {
MFD_CELL_NAME("s2mps13-regulator"),
MFD_CELL_NAME("s2mps13-rtc"),
MFD_CELL_OF("s2mps13-clk", NULL, NULL, 0, 0, "samsung,s2mps13-clk"),
};
static const struct mfd_cell s2mps14_devs[] = {
MFD_CELL_NAME("s2mps14-regulator"),
MFD_CELL_NAME("s2mps14-rtc"),
MFD_CELL_OF("s2mps14-clk", NULL, NULL, 0, 0, "samsung,s2mps14-clk"),
};
static const struct mfd_cell s2mps15_devs[] = {
MFD_CELL_NAME("s2mps15-regulator"),
MFD_CELL_NAME("s2mps15-rtc"),
MFD_CELL_OF("s2mps13-clk", NULL, NULL, 0, 0, "samsung,s2mps13-clk"),
};
static const struct mfd_cell s2mpa01_devs[] = {
MFD_CELL_NAME("s2mpa01-pmic"),
MFD_CELL_NAME("s2mps14-rtc"),
};
static const struct mfd_cell s2mpu02_devs[] = {
MFD_CELL_NAME("s2mpu02-regulator"),
};
static const struct mfd_cell s2mpu05_devs[] = {
MFD_CELL_NAME("s2mpu05-regulator"),
MFD_CELL_NAME("s2mps15-rtc"),
};
static void sec_pmic_dump_rev(struct sec_pmic_dev *sec_pmic)
{
unsigned int val;
/* For s2mpg1x, the revision is in a different regmap */
if (sec_pmic->device_type == S2MPG10)
return;
/* For each device type, the REG_ID is always the first register */
if (!regmap_read(sec_pmic->regmap_pmic, S2MPS11_REG_ID, &val))
dev_dbg(sec_pmic->dev, "Revision: 0x%x\n", val);
}
static void sec_pmic_configure(struct sec_pmic_dev *sec_pmic)
{
int err;
if (sec_pmic->device_type != S2MPS13X)
return;
if (sec_pmic->pdata->disable_wrstbi) {
/*
* If WRSTBI pin is pulled down this feature must be disabled
* because each Suspend to RAM will trigger buck voltage reset
* to default values.
*/
err = regmap_update_bits(sec_pmic->regmap_pmic,
S2MPS13_REG_WRSTBI,
S2MPS13_REG_WRSTBI_MASK, 0x0);
if (err)
dev_warn(sec_pmic->dev,
"Cannot initialize WRSTBI config: %d\n",
err);
}
}
/*
* Only the common platform data elements for s5m8767 are parsed here from the
* device tree. Other sub-modules of s5m8767 such as pmic, rtc , charger and
* others have to parse their own platform data elements from device tree.
*
* The s5m8767 platform data structure is instantiated here and the drivers for
* the sub-modules need not instantiate another instance while parsing their
* platform data.
*/
static struct sec_platform_data *
sec_pmic_parse_dt_pdata(struct device *dev)
{
struct sec_platform_data *pd;
pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
if (!pd)
return ERR_PTR(-ENOMEM);
pd->manual_poweroff = of_property_read_bool(dev->of_node,
"samsung,s2mps11-acokb-ground");
pd->disable_wrstbi = of_property_read_bool(dev->of_node,
"samsung,s2mps11-wrstbi-ground");
return pd;
}
int sec_pmic_probe(struct device *dev, int device_type, unsigned int irq,
struct regmap *regmap, struct i2c_client *client)
{
struct sec_platform_data *pdata;
const struct mfd_cell *sec_devs;
struct sec_pmic_dev *sec_pmic;
int ret, num_sec_devs;
sec_pmic = devm_kzalloc(dev, sizeof(*sec_pmic), GFP_KERNEL);
if (!sec_pmic)
return -ENOMEM;
dev_set_drvdata(dev, sec_pmic);
sec_pmic->dev = dev;
sec_pmic->device_type = device_type;
sec_pmic->i2c = client;
sec_pmic->irq = irq;
sec_pmic->regmap_pmic = regmap;
pdata = sec_pmic_parse_dt_pdata(sec_pmic->dev);
if (IS_ERR(pdata)) {
ret = PTR_ERR(pdata);
return ret;
}
sec_pmic->pdata = pdata;
ret = sec_irq_init(sec_pmic);
if (ret)
return ret;
pm_runtime_set_active(sec_pmic->dev);
switch (sec_pmic->device_type) {
case S5M8767X:
sec_devs = s5m8767_devs;
num_sec_devs = ARRAY_SIZE(s5m8767_devs);
break;
case S2DOS05:
sec_devs = s2dos05_devs;
num_sec_devs = ARRAY_SIZE(s2dos05_devs);
break;
case S2MPA01:
sec_devs = s2mpa01_devs;
num_sec_devs = ARRAY_SIZE(s2mpa01_devs);
break;
case S2MPG10:
sec_devs = s2mpg10_devs;
num_sec_devs = ARRAY_SIZE(s2mpg10_devs);
break;
case S2MPS11X:
sec_devs = s2mps11_devs;
num_sec_devs = ARRAY_SIZE(s2mps11_devs);
break;
case S2MPS13X:
sec_devs = s2mps13_devs;
num_sec_devs = ARRAY_SIZE(s2mps13_devs);
break;
case S2MPS14X:
sec_devs = s2mps14_devs;
num_sec_devs = ARRAY_SIZE(s2mps14_devs);
break;
case S2MPS15X:
sec_devs = s2mps15_devs;
num_sec_devs = ARRAY_SIZE(s2mps15_devs);
break;
case S2MPU02:
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:
return dev_err_probe(sec_pmic->dev, -EINVAL,
"Unsupported device type %d\n",
sec_pmic->device_type);
}
ret = devm_mfd_add_devices(sec_pmic->dev, -1, sec_devs, num_sec_devs,
NULL, 0, NULL);
if (ret)
return ret;
sec_pmic_configure(sec_pmic);
sec_pmic_dump_rev(sec_pmic);
return ret;
}
EXPORT_SYMBOL_GPL(sec_pmic_probe);
void sec_pmic_shutdown(struct device *dev)
{
struct sec_pmic_dev *sec_pmic = dev_get_drvdata(dev);
unsigned int reg, mask;
if (!sec_pmic->pdata->manual_poweroff)
return;
switch (sec_pmic->device_type) {
case S2MPS11X:
reg = S2MPS11_REG_CTRL1;
mask = S2MPS11_CTRL1_PWRHOLD_MASK;
break;
default:
/*
* Currently only one board with S2MPS11 needs this, so just
* ignore the rest.
*/
dev_warn(sec_pmic->dev,
"Unsupported device %d for manual power off\n",
sec_pmic->device_type);
return;
}
regmap_update_bits(sec_pmic->regmap_pmic, reg, mask, 0);
}
EXPORT_SYMBOL_GPL(sec_pmic_shutdown);
static int sec_pmic_suspend(struct device *dev)
{
struct sec_pmic_dev *sec_pmic = dev_get_drvdata(dev);
if (device_may_wakeup(dev))
enable_irq_wake(sec_pmic->irq);
/*
* PMIC IRQ must be disabled during suspend for RTC alarm
* to work properly.
* When device is woken up from suspend, an
* interrupt occurs before resuming I2C bus controller.
* The interrupt is handled by regmap_irq_thread which tries
* to read RTC registers. This read fails (I2C is still
* suspended) and RTC Alarm interrupt is disabled.
*/
disable_irq(sec_pmic->irq);
return 0;
}
static int sec_pmic_resume(struct device *dev)
{
struct sec_pmic_dev *sec_pmic = dev_get_drvdata(dev);
if (device_may_wakeup(dev))
disable_irq_wake(sec_pmic->irq);
enable_irq(sec_pmic->irq);
return 0;
}
DEFINE_SIMPLE_DEV_PM_OPS(sec_pmic_pm_ops, sec_pmic_suspend, sec_pmic_resume);
EXPORT_SYMBOL_GPL(sec_pmic_pm_ops);
MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>");
MODULE_AUTHOR("Krzysztof Kozlowski <krzk@kernel.org>");
MODULE_AUTHOR("Sangbeom Kim <sbkim73@samsung.com>");
MODULE_AUTHOR("André Draszik <andre.draszik@linaro.org>");
MODULE_DESCRIPTION("Core driver for the Samsung S5M");
MODULE_LICENSE("GPL");

View File

@ -1,481 +0,0 @@
// SPDX-License-Identifier: GPL-2.0+
//
// Copyright (c) 2012 Samsung Electronics Co., Ltd
// http://www.samsung.com
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/err.h>
#include <linux/slab.h>
#include <linux/i2c.h>
#include <linux/of.h>
#include <linux/interrupt.h>
#include <linux/pm_runtime.h>
#include <linux/mutex.h>
#include <linux/mfd/core.h>
#include <linux/mfd/samsung/core.h>
#include <linux/mfd/samsung/irq.h>
#include <linux/mfd/samsung/s2mpa01.h>
#include <linux/mfd/samsung/s2mps11.h>
#include <linux/mfd/samsung/s2mps13.h>
#include <linux/mfd/samsung/s2mps14.h>
#include <linux/mfd/samsung/s2mps15.h>
#include <linux/mfd/samsung/s2mpu02.h>
#include <linux/mfd/samsung/s5m8767.h>
#include <linux/regmap.h>
static const struct mfd_cell s5m8767_devs[] = {
{ .name = "s5m8767-pmic", },
{ .name = "s5m-rtc", },
{
.name = "s5m8767-clk",
.of_compatible = "samsung,s5m8767-clk",
},
};
static const struct mfd_cell s2dos05_devs[] = {
{ .name = "s2dos05-regulator", },
};
static const struct mfd_cell s2mps11_devs[] = {
{ .name = "s2mps11-regulator", },
{ .name = "s2mps14-rtc", },
{
.name = "s2mps11-clk",
.of_compatible = "samsung,s2mps11-clk",
},
};
static const struct mfd_cell s2mps13_devs[] = {
{ .name = "s2mps13-regulator", },
{ .name = "s2mps13-rtc", },
{
.name = "s2mps13-clk",
.of_compatible = "samsung,s2mps13-clk",
},
};
static const struct mfd_cell s2mps14_devs[] = {
{ .name = "s2mps14-regulator", },
{ .name = "s2mps14-rtc", },
{
.name = "s2mps14-clk",
.of_compatible = "samsung,s2mps14-clk",
},
};
static const struct mfd_cell s2mps15_devs[] = {
{ .name = "s2mps15-regulator", },
{ .name = "s2mps15-rtc", },
{
.name = "s2mps13-clk",
.of_compatible = "samsung,s2mps13-clk",
},
};
static const struct mfd_cell s2mpa01_devs[] = {
{ .name = "s2mpa01-pmic", },
{ .name = "s2mps14-rtc", },
};
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",
.data = (void *)S5M8767X,
}, {
.compatible = "samsung,s2dos05",
.data = (void *)S2DOS05,
}, {
.compatible = "samsung,s2mps11-pmic",
.data = (void *)S2MPS11X,
}, {
.compatible = "samsung,s2mps13-pmic",
.data = (void *)S2MPS13X,
}, {
.compatible = "samsung,s2mps14-pmic",
.data = (void *)S2MPS14X,
}, {
.compatible = "samsung,s2mps15-pmic",
.data = (void *)S2MPS15X,
}, {
.compatible = "samsung,s2mpa01-pmic",
.data = (void *)S2MPA01,
}, {
.compatible = "samsung,s2mpu02-pmic",
.data = (void *)S2MPU02,
}, {
.compatible = "samsung,s2mpu05-pmic",
.data = (void *)S2MPU05,
}, {
/* Sentinel */
},
};
MODULE_DEVICE_TABLE(of, sec_dt_match);
static bool s2mpa01_volatile(struct device *dev, unsigned int reg)
{
switch (reg) {
case S2MPA01_REG_INT1M:
case S2MPA01_REG_INT2M:
case S2MPA01_REG_INT3M:
return false;
default:
return true;
}
}
static bool s2mps11_volatile(struct device *dev, unsigned int reg)
{
switch (reg) {
case S2MPS11_REG_INT1M:
case S2MPS11_REG_INT2M:
case S2MPS11_REG_INT3M:
return false;
default:
return true;
}
}
static bool s2mpu02_volatile(struct device *dev, unsigned int reg)
{
switch (reg) {
case S2MPU02_REG_INT1M:
case S2MPU02_REG_INT2M:
case S2MPU02_REG_INT3M:
return false;
default:
return true;
}
}
static const struct regmap_config sec_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
};
static const struct regmap_config s2mpa01_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = S2MPA01_REG_LDO_OVCB4,
.volatile_reg = s2mpa01_volatile,
.cache_type = REGCACHE_FLAT,
};
static const struct regmap_config s2mps11_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = S2MPS11_REG_L38CTRL,
.volatile_reg = s2mps11_volatile,
.cache_type = REGCACHE_FLAT,
};
static const struct regmap_config s2mps13_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = S2MPS13_REG_LDODSCH5,
.volatile_reg = s2mps11_volatile,
.cache_type = REGCACHE_FLAT,
};
static const struct regmap_config s2mps14_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = S2MPS14_REG_LDODSCH3,
.volatile_reg = s2mps11_volatile,
.cache_type = REGCACHE_FLAT,
};
static const struct regmap_config s2mps15_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = S2MPS15_REG_LDODSCH4,
.volatile_reg = s2mps11_volatile,
.cache_type = REGCACHE_FLAT,
};
static const struct regmap_config s2mpu02_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = S2MPU02_REG_DVSDATA,
.volatile_reg = s2mpu02_volatile,
.cache_type = REGCACHE_FLAT,
};
static const struct regmap_config s5m8767_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = S5M8767_REG_LDO28CTRL,
.volatile_reg = s2mps11_volatile,
.cache_type = REGCACHE_FLAT,
};
static void sec_pmic_dump_rev(struct sec_pmic_dev *sec_pmic)
{
unsigned int val;
/* For each device type, the REG_ID is always the first register */
if (!regmap_read(sec_pmic->regmap_pmic, S2MPS11_REG_ID, &val))
dev_dbg(sec_pmic->dev, "Revision: 0x%x\n", val);
}
static void sec_pmic_configure(struct sec_pmic_dev *sec_pmic)
{
int err;
if (sec_pmic->device_type != S2MPS13X)
return;
if (sec_pmic->pdata->disable_wrstbi) {
/*
* If WRSTBI pin is pulled down this feature must be disabled
* because each Suspend to RAM will trigger buck voltage reset
* to default values.
*/
err = regmap_update_bits(sec_pmic->regmap_pmic,
S2MPS13_REG_WRSTBI,
S2MPS13_REG_WRSTBI_MASK, 0x0);
if (err)
dev_warn(sec_pmic->dev,
"Cannot initialize WRSTBI config: %d\n",
err);
}
}
/*
* Only the common platform data elements for s5m8767 are parsed here from the
* device tree. Other sub-modules of s5m8767 such as pmic, rtc , charger and
* others have to parse their own platform data elements from device tree.
*
* The s5m8767 platform data structure is instantiated here and the drivers for
* the sub-modules need not instantiate another instance while parsing their
* platform data.
*/
static struct sec_platform_data *
sec_pmic_i2c_parse_dt_pdata(struct device *dev)
{
struct sec_platform_data *pd;
pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
if (!pd)
return ERR_PTR(-ENOMEM);
pd->manual_poweroff = of_property_read_bool(dev->of_node,
"samsung,s2mps11-acokb-ground");
pd->disable_wrstbi = of_property_read_bool(dev->of_node,
"samsung,s2mps11-wrstbi-ground");
return pd;
}
static int sec_pmic_probe(struct i2c_client *i2c)
{
const struct regmap_config *regmap;
struct sec_platform_data *pdata;
const struct mfd_cell *sec_devs;
struct sec_pmic_dev *sec_pmic;
int ret, num_sec_devs;
sec_pmic = devm_kzalloc(&i2c->dev, sizeof(struct sec_pmic_dev),
GFP_KERNEL);
if (sec_pmic == NULL)
return -ENOMEM;
i2c_set_clientdata(i2c, sec_pmic);
sec_pmic->dev = &i2c->dev;
sec_pmic->i2c = i2c;
sec_pmic->irq = i2c->irq;
pdata = sec_pmic_i2c_parse_dt_pdata(sec_pmic->dev);
if (IS_ERR(pdata)) {
ret = PTR_ERR(pdata);
return ret;
}
sec_pmic->device_type = (unsigned long)of_device_get_match_data(sec_pmic->dev);
sec_pmic->pdata = pdata;
switch (sec_pmic->device_type) {
case S2MPA01:
regmap = &s2mpa01_regmap_config;
break;
case S2MPS11X:
regmap = &s2mps11_regmap_config;
break;
case S2MPS13X:
regmap = &s2mps13_regmap_config;
break;
case S2MPS14X:
regmap = &s2mps14_regmap_config;
break;
case S2MPS15X:
regmap = &s2mps15_regmap_config;
break;
case S5M8767X:
regmap = &s5m8767_regmap_config;
break;
case S2MPU02:
regmap = &s2mpu02_regmap_config;
break;
default:
regmap = &sec_regmap_config;
break;
}
sec_pmic->regmap_pmic = devm_regmap_init_i2c(i2c, regmap);
if (IS_ERR(sec_pmic->regmap_pmic)) {
ret = PTR_ERR(sec_pmic->regmap_pmic);
dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
ret);
return ret;
}
sec_irq_init(sec_pmic);
pm_runtime_set_active(sec_pmic->dev);
switch (sec_pmic->device_type) {
case S5M8767X:
sec_devs = s5m8767_devs;
num_sec_devs = ARRAY_SIZE(s5m8767_devs);
break;
case S2DOS05:
sec_devs = s2dos05_devs;
num_sec_devs = ARRAY_SIZE(s2dos05_devs);
break;
case S2MPA01:
sec_devs = s2mpa01_devs;
num_sec_devs = ARRAY_SIZE(s2mpa01_devs);
break;
case S2MPS11X:
sec_devs = s2mps11_devs;
num_sec_devs = ARRAY_SIZE(s2mps11_devs);
break;
case S2MPS13X:
sec_devs = s2mps13_devs;
num_sec_devs = ARRAY_SIZE(s2mps13_devs);
break;
case S2MPS14X:
sec_devs = s2mps14_devs;
num_sec_devs = ARRAY_SIZE(s2mps14_devs);
break;
case S2MPS15X:
sec_devs = s2mps15_devs;
num_sec_devs = ARRAY_SIZE(s2mps15_devs);
break;
case S2MPU02:
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);
return -ENODEV;
}
ret = devm_mfd_add_devices(sec_pmic->dev, -1, sec_devs, num_sec_devs,
NULL, 0, NULL);
if (ret)
return ret;
sec_pmic_configure(sec_pmic);
sec_pmic_dump_rev(sec_pmic);
return ret;
}
static void sec_pmic_shutdown(struct i2c_client *i2c)
{
struct sec_pmic_dev *sec_pmic = i2c_get_clientdata(i2c);
unsigned int reg, mask;
if (!sec_pmic->pdata->manual_poweroff)
return;
switch (sec_pmic->device_type) {
case S2MPS11X:
reg = S2MPS11_REG_CTRL1;
mask = S2MPS11_CTRL1_PWRHOLD_MASK;
break;
default:
/*
* Currently only one board with S2MPS11 needs this, so just
* ignore the rest.
*/
dev_warn(sec_pmic->dev,
"Unsupported device %lu for manual power off\n",
sec_pmic->device_type);
return;
}
regmap_update_bits(sec_pmic->regmap_pmic, reg, mask, 0);
}
static int sec_pmic_suspend(struct device *dev)
{
struct i2c_client *i2c = to_i2c_client(dev);
struct sec_pmic_dev *sec_pmic = i2c_get_clientdata(i2c);
if (device_may_wakeup(dev))
enable_irq_wake(sec_pmic->irq);
/*
* PMIC IRQ must be disabled during suspend for RTC alarm
* to work properly.
* When device is woken up from suspend, an
* interrupt occurs before resuming I2C bus controller.
* The interrupt is handled by regmap_irq_thread which tries
* to read RTC registers. This read fails (I2C is still
* suspended) and RTC Alarm interrupt is disabled.
*/
disable_irq(sec_pmic->irq);
return 0;
}
static int sec_pmic_resume(struct device *dev)
{
struct i2c_client *i2c = to_i2c_client(dev);
struct sec_pmic_dev *sec_pmic = i2c_get_clientdata(i2c);
if (device_may_wakeup(dev))
disable_irq_wake(sec_pmic->irq);
enable_irq(sec_pmic->irq);
return 0;
}
static DEFINE_SIMPLE_DEV_PM_OPS(sec_pmic_pm_ops,
sec_pmic_suspend, sec_pmic_resume);
static struct i2c_driver sec_pmic_driver = {
.driver = {
.name = "sec_pmic",
.pm = pm_sleep_ptr(&sec_pmic_pm_ops),
.of_match_table = sec_dt_match,
},
.probe = sec_pmic_probe,
.shutdown = sec_pmic_shutdown,
};
module_i2c_driver(sec_pmic_driver);
MODULE_AUTHOR("Sangbeom Kim <sbkim73@samsung.com>");
MODULE_DESCRIPTION("Core support for the S5M MFD");
MODULE_LICENSE("GPL");

23
drivers/mfd/sec-core.h Normal file
View File

@ -0,0 +1,23 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Copyright 2012 Samsung Electronics Co., Ltd
* http://www.samsung.com
* Copyright 2025 Linaro Ltd.
*
* Samsung SxM core driver internal data
*/
#ifndef __SEC_CORE_INT_H
#define __SEC_CORE_INT_H
struct i2c_client;
extern const struct dev_pm_ops sec_pmic_pm_ops;
int sec_pmic_probe(struct device *dev, int device_type, unsigned int irq,
struct regmap *regmap, struct i2c_client *client);
void sec_pmic_shutdown(struct device *dev);
int sec_irq_init(struct sec_pmic_dev *sec_pmic);
#endif /* __SEC_CORE_INT_H */

239
drivers/mfd/sec-i2c.c Normal file
View File

@ -0,0 +1,239 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright 2012 Samsung Electronics Co., Ltd
* http://www.samsung.com
* Copyright 2025 Linaro Ltd.
*
* Samsung SxM I2C driver
*/
#include <linux/dev_printk.h>
#include <linux/err.h>
#include <linux/i2c.h>
#include <linux/mfd/samsung/core.h>
#include <linux/mfd/samsung/s2mpa01.h>
#include <linux/mfd/samsung/s2mps11.h>
#include <linux/mfd/samsung/s2mps13.h>
#include <linux/mfd/samsung/s2mps14.h>
#include <linux/mfd/samsung/s2mps15.h>
#include <linux/mfd/samsung/s2mpu02.h>
#include <linux/mfd/samsung/s5m8767.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/pm.h>
#include <linux/property.h>
#include <linux/regmap.h>
#include "sec-core.h"
struct sec_pmic_i2c_platform_data {
const struct regmap_config *regmap_cfg;
int device_type;
};
static bool s2mpa01_volatile(struct device *dev, unsigned int reg)
{
switch (reg) {
case S2MPA01_REG_INT1M:
case S2MPA01_REG_INT2M:
case S2MPA01_REG_INT3M:
return false;
default:
return true;
}
}
static bool s2mps11_volatile(struct device *dev, unsigned int reg)
{
switch (reg) {
case S2MPS11_REG_INT1M:
case S2MPS11_REG_INT2M:
case S2MPS11_REG_INT3M:
return false;
default:
return true;
}
}
static bool s2mpu02_volatile(struct device *dev, unsigned int reg)
{
switch (reg) {
case S2MPU02_REG_INT1M:
case S2MPU02_REG_INT2M:
case S2MPU02_REG_INT3M:
return false;
default:
return true;
}
}
static const struct regmap_config s2dos05_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
};
static const struct regmap_config s2mpa01_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = S2MPA01_REG_LDO_OVCB4,
.volatile_reg = s2mpa01_volatile,
.cache_type = REGCACHE_FLAT,
};
static const struct regmap_config s2mps11_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = S2MPS11_REG_L38CTRL,
.volatile_reg = s2mps11_volatile,
.cache_type = REGCACHE_FLAT,
};
static const struct regmap_config s2mps13_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = S2MPS13_REG_LDODSCH5,
.volatile_reg = s2mps11_volatile,
.cache_type = REGCACHE_FLAT,
};
static const struct regmap_config s2mps14_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = S2MPS14_REG_LDODSCH3,
.volatile_reg = s2mps11_volatile,
.cache_type = REGCACHE_FLAT,
};
static const struct regmap_config s2mps15_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = S2MPS15_REG_LDODSCH4,
.volatile_reg = s2mps11_volatile,
.cache_type = REGCACHE_FLAT,
};
static const struct regmap_config s2mpu02_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = S2MPU02_REG_DVSDATA,
.volatile_reg = s2mpu02_volatile,
.cache_type = REGCACHE_FLAT,
};
static const struct regmap_config s2mpu05_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
};
static const struct regmap_config s5m8767_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = S5M8767_REG_LDO28CTRL,
.volatile_reg = s2mps11_volatile,
.cache_type = REGCACHE_FLAT,
};
static int sec_pmic_i2c_probe(struct i2c_client *client)
{
const struct sec_pmic_i2c_platform_data *pdata;
struct regmap *regmap_pmic;
pdata = device_get_match_data(&client->dev);
if (!pdata)
return dev_err_probe(&client->dev, -ENODEV,
"Unsupported device type\n");
regmap_pmic = devm_regmap_init_i2c(client, pdata->regmap_cfg);
if (IS_ERR(regmap_pmic))
return dev_err_probe(&client->dev, PTR_ERR(regmap_pmic),
"regmap init failed\n");
return sec_pmic_probe(&client->dev, pdata->device_type, client->irq,
regmap_pmic, client);
}
static void sec_pmic_i2c_shutdown(struct i2c_client *i2c)
{
sec_pmic_shutdown(&i2c->dev);
}
static const struct sec_pmic_i2c_platform_data s2dos05_data = {
.regmap_cfg = &s2dos05_regmap_config,
.device_type = S2DOS05
};
static const struct sec_pmic_i2c_platform_data s2mpa01_data = {
.regmap_cfg = &s2mpa01_regmap_config,
.device_type = S2MPA01,
};
static const struct sec_pmic_i2c_platform_data s2mps11_data = {
.regmap_cfg = &s2mps11_regmap_config,
.device_type = S2MPS11X,
};
static const struct sec_pmic_i2c_platform_data s2mps13_data = {
.regmap_cfg = &s2mps13_regmap_config,
.device_type = S2MPS13X,
};
static const struct sec_pmic_i2c_platform_data s2mps14_data = {
.regmap_cfg = &s2mps14_regmap_config,
.device_type = S2MPS14X,
};
static const struct sec_pmic_i2c_platform_data s2mps15_data = {
.regmap_cfg = &s2mps15_regmap_config,
.device_type = S2MPS15X,
};
static const struct sec_pmic_i2c_platform_data s2mpu02_data = {
.regmap_cfg = &s2mpu02_regmap_config,
.device_type = S2MPU02,
};
static const struct sec_pmic_i2c_platform_data s2mpu05_data = {
.regmap_cfg = &s2mpu05_regmap_config,
.device_type = S2MPU05,
};
static const struct sec_pmic_i2c_platform_data s5m8767_data = {
.regmap_cfg = &s5m8767_regmap_config,
.device_type = S5M8767X,
};
static const struct of_device_id sec_pmic_i2c_of_match[] = {
{ .compatible = "samsung,s2dos05", .data = &s2dos05_data, },
{ .compatible = "samsung,s2mpa01-pmic", .data = &s2mpa01_data, },
{ .compatible = "samsung,s2mps11-pmic", .data = &s2mps11_data, },
{ .compatible = "samsung,s2mps13-pmic", .data = &s2mps13_data, },
{ .compatible = "samsung,s2mps14-pmic", .data = &s2mps14_data, },
{ .compatible = "samsung,s2mps15-pmic", .data = &s2mps15_data, },
{ .compatible = "samsung,s2mpu02-pmic", .data = &s2mpu02_data, },
{ .compatible = "samsung,s2mpu05-pmic", .data = &s2mpu05_data, },
{ .compatible = "samsung,s5m8767-pmic", .data = &s5m8767_data, },
{ },
};
MODULE_DEVICE_TABLE(of, sec_pmic_i2c_of_match);
static struct i2c_driver sec_pmic_i2c_driver = {
.driver = {
.name = "sec-pmic-i2c",
.pm = pm_sleep_ptr(&sec_pmic_pm_ops),
.of_match_table = sec_pmic_i2c_of_match,
},
.probe = sec_pmic_i2c_probe,
.shutdown = sec_pmic_i2c_shutdown,
};
module_i2c_driver(sec_pmic_i2c_driver);
MODULE_AUTHOR("Sangbeom Kim <sbkim73@samsung.com>");
MODULE_AUTHOR("André Draszik <andre.draszik@linaro.org>");
MODULE_DESCRIPTION("I2C driver for the Samsung S5M");
MODULE_LICENSE("GPL");

View File

@ -3,227 +3,139 @@
// Copyright (c) 2011-2014 Samsung Electronics Co., Ltd
// http://www.samsung.com
#include <linux/device.h>
#include <linux/array_size.h>
#include <linux/build_bug.h>
#include <linux/dev_printk.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/module.h>
#include <linux/regmap.h>
#include <linux/mfd/samsung/core.h>
#include <linux/mfd/samsung/irq.h>
#include <linux/mfd/samsung/s2mpg10.h>
#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>
#include <linux/regmap.h>
#include "sec-core.h"
static const struct regmap_irq s2mpg10_irqs[] = {
REGMAP_IRQ_REG(S2MPG10_IRQ_PWRONF, 0, S2MPG10_IRQ_PWRONF_MASK),
REGMAP_IRQ_REG(S2MPG10_IRQ_PWRONR, 0, S2MPG10_IRQ_PWRONR_MASK),
REGMAP_IRQ_REG(S2MPG10_IRQ_JIGONBF, 0, S2MPG10_IRQ_JIGONBF_MASK),
REGMAP_IRQ_REG(S2MPG10_IRQ_JIGONBR, 0, S2MPG10_IRQ_JIGONBR_MASK),
REGMAP_IRQ_REG(S2MPG10_IRQ_ACOKBF, 0, S2MPG10_IRQ_ACOKBF_MASK),
REGMAP_IRQ_REG(S2MPG10_IRQ_ACOKBR, 0, S2MPG10_IRQ_ACOKBR_MASK),
REGMAP_IRQ_REG(S2MPG10_IRQ_PWRON1S, 0, S2MPG10_IRQ_PWRON1S_MASK),
REGMAP_IRQ_REG(S2MPG10_IRQ_MRB, 0, S2MPG10_IRQ_MRB_MASK),
REGMAP_IRQ_REG(S2MPG10_IRQ_RTC60S, 1, S2MPG10_IRQ_RTC60S_MASK),
REGMAP_IRQ_REG(S2MPG10_IRQ_RTCA1, 1, S2MPG10_IRQ_RTCA1_MASK),
REGMAP_IRQ_REG(S2MPG10_IRQ_RTCA0, 1, S2MPG10_IRQ_RTCA0_MASK),
REGMAP_IRQ_REG(S2MPG10_IRQ_RTC1S, 1, S2MPG10_IRQ_RTC1S_MASK),
REGMAP_IRQ_REG(S2MPG10_IRQ_WTSR_COLDRST, 1, S2MPG10_IRQ_WTSR_COLDRST_MASK),
REGMAP_IRQ_REG(S2MPG10_IRQ_WTSR, 1, S2MPG10_IRQ_WTSR_MASK),
REGMAP_IRQ_REG(S2MPG10_IRQ_WRST, 1, S2MPG10_IRQ_WRST_MASK),
REGMAP_IRQ_REG(S2MPG10_IRQ_SMPL, 1, S2MPG10_IRQ_SMPL_MASK),
REGMAP_IRQ_REG(S2MPG10_IRQ_120C, 2, S2MPG10_IRQ_INT120C_MASK),
REGMAP_IRQ_REG(S2MPG10_IRQ_140C, 2, S2MPG10_IRQ_INT140C_MASK),
REGMAP_IRQ_REG(S2MPG10_IRQ_TSD, 2, S2MPG10_IRQ_TSD_MASK),
REGMAP_IRQ_REG(S2MPG10_IRQ_PIF_TIMEOUT1, 2, S2MPG10_IRQ_PIF_TIMEOUT1_MASK),
REGMAP_IRQ_REG(S2MPG10_IRQ_PIF_TIMEOUT2, 2, S2MPG10_IRQ_PIF_TIMEOUT2_MASK),
REGMAP_IRQ_REG(S2MPG10_IRQ_SPD_PARITY_ERR, 2, S2MPG10_IRQ_SPD_PARITY_ERR_MASK),
REGMAP_IRQ_REG(S2MPG10_IRQ_SPD_ABNORMAL_STOP, 2, S2MPG10_IRQ_SPD_ABNORMAL_STOP_MASK),
REGMAP_IRQ_REG(S2MPG10_IRQ_PMETER_OVERF, 2, S2MPG10_IRQ_PMETER_OVERF_MASK),
REGMAP_IRQ_REG(S2MPG10_IRQ_OCP_B1M, 3, S2MPG10_IRQ_OCP_B1M_MASK),
REGMAP_IRQ_REG(S2MPG10_IRQ_OCP_B2M, 3, S2MPG10_IRQ_OCP_B2M_MASK),
REGMAP_IRQ_REG(S2MPG10_IRQ_OCP_B3M, 3, S2MPG10_IRQ_OCP_B3M_MASK),
REGMAP_IRQ_REG(S2MPG10_IRQ_OCP_B4M, 3, S2MPG10_IRQ_OCP_B4M_MASK),
REGMAP_IRQ_REG(S2MPG10_IRQ_OCP_B5M, 3, S2MPG10_IRQ_OCP_B5M_MASK),
REGMAP_IRQ_REG(S2MPG10_IRQ_OCP_B6M, 3, S2MPG10_IRQ_OCP_B6M_MASK),
REGMAP_IRQ_REG(S2MPG10_IRQ_OCP_B7M, 3, S2MPG10_IRQ_OCP_B7M_MASK),
REGMAP_IRQ_REG(S2MPG10_IRQ_OCP_B8M, 3, S2MPG10_IRQ_OCP_B8M_MASK),
REGMAP_IRQ_REG(S2MPG10_IRQ_OCP_B9M, 4, S2MPG10_IRQ_OCP_B9M_MASK),
REGMAP_IRQ_REG(S2MPG10_IRQ_OCP_B10M, 4, S2MPG10_IRQ_OCP_B10M_MASK),
REGMAP_IRQ_REG(S2MPG10_IRQ_WLWP_ACC, 4, S2MPG10_IRQ_WLWP_ACC_MASK),
REGMAP_IRQ_REG(S2MPG10_IRQ_SMPL_TIMEOUT, 4, S2MPG10_IRQ_SMPL_TIMEOUT_MASK),
REGMAP_IRQ_REG(S2MPG10_IRQ_WTSR_TIMEOUT, 4, S2MPG10_IRQ_WTSR_TIMEOUT_MASK),
REGMAP_IRQ_REG(S2MPG10_IRQ_SPD_SRP_PKT_RST, 4, S2MPG10_IRQ_SPD_SRP_PKT_RST_MASK),
REGMAP_IRQ_REG(S2MPG10_IRQ_PWR_WARN_CH0, 5, S2MPG10_IRQ_PWR_WARN_CH0_MASK),
REGMAP_IRQ_REG(S2MPG10_IRQ_PWR_WARN_CH1, 5, S2MPG10_IRQ_PWR_WARN_CH1_MASK),
REGMAP_IRQ_REG(S2MPG10_IRQ_PWR_WARN_CH2, 5, S2MPG10_IRQ_PWR_WARN_CH2_MASK),
REGMAP_IRQ_REG(S2MPG10_IRQ_PWR_WARN_CH3, 5, S2MPG10_IRQ_PWR_WARN_CH3_MASK),
REGMAP_IRQ_REG(S2MPG10_IRQ_PWR_WARN_CH4, 5, S2MPG10_IRQ_PWR_WARN_CH4_MASK),
REGMAP_IRQ_REG(S2MPG10_IRQ_PWR_WARN_CH5, 5, S2MPG10_IRQ_PWR_WARN_CH5_MASK),
REGMAP_IRQ_REG(S2MPG10_IRQ_PWR_WARN_CH6, 5, S2MPG10_IRQ_PWR_WARN_CH6_MASK),
REGMAP_IRQ_REG(S2MPG10_IRQ_PWR_WARN_CH7, 5, S2MPG10_IRQ_PWR_WARN_CH7_MASK),
};
static const struct regmap_irq s2mps11_irqs[] = {
[S2MPS11_IRQ_PWRONF] = {
.reg_offset = 0,
.mask = S2MPS11_IRQ_PWRONF_MASK,
},
[S2MPS11_IRQ_PWRONR] = {
.reg_offset = 0,
.mask = S2MPS11_IRQ_PWRONR_MASK,
},
[S2MPS11_IRQ_JIGONBF] = {
.reg_offset = 0,
.mask = S2MPS11_IRQ_JIGONBF_MASK,
},
[S2MPS11_IRQ_JIGONBR] = {
.reg_offset = 0,
.mask = S2MPS11_IRQ_JIGONBR_MASK,
},
[S2MPS11_IRQ_ACOKBF] = {
.reg_offset = 0,
.mask = S2MPS11_IRQ_ACOKBF_MASK,
},
[S2MPS11_IRQ_ACOKBR] = {
.reg_offset = 0,
.mask = S2MPS11_IRQ_ACOKBR_MASK,
},
[S2MPS11_IRQ_PWRON1S] = {
.reg_offset = 0,
.mask = S2MPS11_IRQ_PWRON1S_MASK,
},
[S2MPS11_IRQ_MRB] = {
.reg_offset = 0,
.mask = S2MPS11_IRQ_MRB_MASK,
},
[S2MPS11_IRQ_RTC60S] = {
.reg_offset = 1,
.mask = S2MPS11_IRQ_RTC60S_MASK,
},
[S2MPS11_IRQ_RTCA1] = {
.reg_offset = 1,
.mask = S2MPS11_IRQ_RTCA1_MASK,
},
[S2MPS11_IRQ_RTCA0] = {
.reg_offset = 1,
.mask = S2MPS11_IRQ_RTCA0_MASK,
},
[S2MPS11_IRQ_SMPL] = {
.reg_offset = 1,
.mask = S2MPS11_IRQ_SMPL_MASK,
},
[S2MPS11_IRQ_RTC1S] = {
.reg_offset = 1,
.mask = S2MPS11_IRQ_RTC1S_MASK,
},
[S2MPS11_IRQ_WTSR] = {
.reg_offset = 1,
.mask = S2MPS11_IRQ_WTSR_MASK,
},
[S2MPS11_IRQ_INT120C] = {
.reg_offset = 2,
.mask = S2MPS11_IRQ_INT120C_MASK,
},
[S2MPS11_IRQ_INT140C] = {
.reg_offset = 2,
.mask = S2MPS11_IRQ_INT140C_MASK,
},
REGMAP_IRQ_REG(S2MPS11_IRQ_PWRONF, 0, S2MPS11_IRQ_PWRONF_MASK),
REGMAP_IRQ_REG(S2MPS11_IRQ_PWRONR, 0, S2MPS11_IRQ_PWRONR_MASK),
REGMAP_IRQ_REG(S2MPS11_IRQ_JIGONBF, 0, S2MPS11_IRQ_JIGONBF_MASK),
REGMAP_IRQ_REG(S2MPS11_IRQ_JIGONBR, 0, S2MPS11_IRQ_JIGONBR_MASK),
REGMAP_IRQ_REG(S2MPS11_IRQ_ACOKBF, 0, S2MPS11_IRQ_ACOKBF_MASK),
REGMAP_IRQ_REG(S2MPS11_IRQ_ACOKBR, 0, S2MPS11_IRQ_ACOKBR_MASK),
REGMAP_IRQ_REG(S2MPS11_IRQ_PWRON1S, 0, S2MPS11_IRQ_PWRON1S_MASK),
REGMAP_IRQ_REG(S2MPS11_IRQ_MRB, 0, S2MPS11_IRQ_MRB_MASK),
REGMAP_IRQ_REG(S2MPS11_IRQ_RTC60S, 1, S2MPS11_IRQ_RTC60S_MASK),
REGMAP_IRQ_REG(S2MPS11_IRQ_RTCA1, 1, S2MPS11_IRQ_RTCA1_MASK),
REGMAP_IRQ_REG(S2MPS11_IRQ_RTCA0, 1, S2MPS11_IRQ_RTCA0_MASK),
REGMAP_IRQ_REG(S2MPS11_IRQ_SMPL, 1, S2MPS11_IRQ_SMPL_MASK),
REGMAP_IRQ_REG(S2MPS11_IRQ_RTC1S, 1, S2MPS11_IRQ_RTC1S_MASK),
REGMAP_IRQ_REG(S2MPS11_IRQ_WTSR, 1, S2MPS11_IRQ_WTSR_MASK),
REGMAP_IRQ_REG(S2MPS11_IRQ_INT120C, 2, S2MPS11_IRQ_INT120C_MASK),
REGMAP_IRQ_REG(S2MPS11_IRQ_INT140C, 2, S2MPS11_IRQ_INT140C_MASK),
};
static const struct regmap_irq s2mps14_irqs[] = {
[S2MPS14_IRQ_PWRONF] = {
.reg_offset = 0,
.mask = S2MPS11_IRQ_PWRONF_MASK,
},
[S2MPS14_IRQ_PWRONR] = {
.reg_offset = 0,
.mask = S2MPS11_IRQ_PWRONR_MASK,
},
[S2MPS14_IRQ_JIGONBF] = {
.reg_offset = 0,
.mask = S2MPS11_IRQ_JIGONBF_MASK,
},
[S2MPS14_IRQ_JIGONBR] = {
.reg_offset = 0,
.mask = S2MPS11_IRQ_JIGONBR_MASK,
},
[S2MPS14_IRQ_ACOKBF] = {
.reg_offset = 0,
.mask = S2MPS11_IRQ_ACOKBF_MASK,
},
[S2MPS14_IRQ_ACOKBR] = {
.reg_offset = 0,
.mask = S2MPS11_IRQ_ACOKBR_MASK,
},
[S2MPS14_IRQ_PWRON1S] = {
.reg_offset = 0,
.mask = S2MPS11_IRQ_PWRON1S_MASK,
},
[S2MPS14_IRQ_MRB] = {
.reg_offset = 0,
.mask = S2MPS11_IRQ_MRB_MASK,
},
[S2MPS14_IRQ_RTC60S] = {
.reg_offset = 1,
.mask = S2MPS11_IRQ_RTC60S_MASK,
},
[S2MPS14_IRQ_RTCA1] = {
.reg_offset = 1,
.mask = S2MPS11_IRQ_RTCA1_MASK,
},
[S2MPS14_IRQ_RTCA0] = {
.reg_offset = 1,
.mask = S2MPS11_IRQ_RTCA0_MASK,
},
[S2MPS14_IRQ_SMPL] = {
.reg_offset = 1,
.mask = S2MPS11_IRQ_SMPL_MASK,
},
[S2MPS14_IRQ_RTC1S] = {
.reg_offset = 1,
.mask = S2MPS11_IRQ_RTC1S_MASK,
},
[S2MPS14_IRQ_WTSR] = {
.reg_offset = 1,
.mask = S2MPS11_IRQ_WTSR_MASK,
},
[S2MPS14_IRQ_INT120C] = {
.reg_offset = 2,
.mask = S2MPS11_IRQ_INT120C_MASK,
},
[S2MPS14_IRQ_INT140C] = {
.reg_offset = 2,
.mask = S2MPS11_IRQ_INT140C_MASK,
},
[S2MPS14_IRQ_TSD] = {
.reg_offset = 2,
.mask = S2MPS14_IRQ_TSD_MASK,
},
REGMAP_IRQ_REG(S2MPS14_IRQ_PWRONF, 0, S2MPS11_IRQ_PWRONF_MASK),
REGMAP_IRQ_REG(S2MPS14_IRQ_PWRONR, 0, S2MPS11_IRQ_PWRONR_MASK),
REGMAP_IRQ_REG(S2MPS14_IRQ_JIGONBF, 0, S2MPS11_IRQ_JIGONBF_MASK),
REGMAP_IRQ_REG(S2MPS14_IRQ_JIGONBR, 0, S2MPS11_IRQ_JIGONBR_MASK),
REGMAP_IRQ_REG(S2MPS14_IRQ_ACOKBF, 0, S2MPS11_IRQ_ACOKBF_MASK),
REGMAP_IRQ_REG(S2MPS14_IRQ_ACOKBR, 0, S2MPS11_IRQ_ACOKBR_MASK),
REGMAP_IRQ_REG(S2MPS14_IRQ_PWRON1S, 0, S2MPS11_IRQ_PWRON1S_MASK),
REGMAP_IRQ_REG(S2MPS14_IRQ_MRB, 0, S2MPS11_IRQ_MRB_MASK),
REGMAP_IRQ_REG(S2MPS14_IRQ_RTC60S, 1, S2MPS11_IRQ_RTC60S_MASK),
REGMAP_IRQ_REG(S2MPS14_IRQ_RTCA1, 1, S2MPS11_IRQ_RTCA1_MASK),
REGMAP_IRQ_REG(S2MPS14_IRQ_RTCA0, 1, S2MPS11_IRQ_RTCA0_MASK),
REGMAP_IRQ_REG(S2MPS14_IRQ_SMPL, 1, S2MPS11_IRQ_SMPL_MASK),
REGMAP_IRQ_REG(S2MPS14_IRQ_RTC1S, 1, S2MPS11_IRQ_RTC1S_MASK),
REGMAP_IRQ_REG(S2MPS14_IRQ_WTSR, 1, S2MPS11_IRQ_WTSR_MASK),
REGMAP_IRQ_REG(S2MPS14_IRQ_INT120C, 2, S2MPS11_IRQ_INT120C_MASK),
REGMAP_IRQ_REG(S2MPS14_IRQ_INT140C, 2, S2MPS11_IRQ_INT140C_MASK),
REGMAP_IRQ_REG(S2MPS14_IRQ_TSD, 2, S2MPS14_IRQ_TSD_MASK),
};
static const struct regmap_irq s2mpu02_irqs[] = {
[S2MPU02_IRQ_PWRONF] = {
.reg_offset = 0,
.mask = S2MPS11_IRQ_PWRONF_MASK,
},
[S2MPU02_IRQ_PWRONR] = {
.reg_offset = 0,
.mask = S2MPS11_IRQ_PWRONR_MASK,
},
[S2MPU02_IRQ_JIGONBF] = {
.reg_offset = 0,
.mask = S2MPS11_IRQ_JIGONBF_MASK,
},
[S2MPU02_IRQ_JIGONBR] = {
.reg_offset = 0,
.mask = S2MPS11_IRQ_JIGONBR_MASK,
},
[S2MPU02_IRQ_ACOKBF] = {
.reg_offset = 0,
.mask = S2MPS11_IRQ_ACOKBF_MASK,
},
[S2MPU02_IRQ_ACOKBR] = {
.reg_offset = 0,
.mask = S2MPS11_IRQ_ACOKBR_MASK,
},
[S2MPU02_IRQ_PWRON1S] = {
.reg_offset = 0,
.mask = S2MPS11_IRQ_PWRON1S_MASK,
},
[S2MPU02_IRQ_MRB] = {
.reg_offset = 0,
.mask = S2MPS11_IRQ_MRB_MASK,
},
[S2MPU02_IRQ_RTC60S] = {
.reg_offset = 1,
.mask = S2MPS11_IRQ_RTC60S_MASK,
},
[S2MPU02_IRQ_RTCA1] = {
.reg_offset = 1,
.mask = S2MPS11_IRQ_RTCA1_MASK,
},
[S2MPU02_IRQ_RTCA0] = {
.reg_offset = 1,
.mask = S2MPS11_IRQ_RTCA0_MASK,
},
[S2MPU02_IRQ_SMPL] = {
.reg_offset = 1,
.mask = S2MPS11_IRQ_SMPL_MASK,
},
[S2MPU02_IRQ_RTC1S] = {
.reg_offset = 1,
.mask = S2MPS11_IRQ_RTC1S_MASK,
},
[S2MPU02_IRQ_WTSR] = {
.reg_offset = 1,
.mask = S2MPS11_IRQ_WTSR_MASK,
},
[S2MPU02_IRQ_INT120C] = {
.reg_offset = 2,
.mask = S2MPS11_IRQ_INT120C_MASK,
},
[S2MPU02_IRQ_INT140C] = {
.reg_offset = 2,
.mask = S2MPS11_IRQ_INT140C_MASK,
},
[S2MPU02_IRQ_TSD] = {
.reg_offset = 2,
.mask = S2MPS14_IRQ_TSD_MASK,
},
REGMAP_IRQ_REG(S2MPU02_IRQ_PWRONF, 0, S2MPS11_IRQ_PWRONF_MASK),
REGMAP_IRQ_REG(S2MPU02_IRQ_PWRONR, 0, S2MPS11_IRQ_PWRONR_MASK),
REGMAP_IRQ_REG(S2MPU02_IRQ_JIGONBF, 0, S2MPS11_IRQ_JIGONBF_MASK),
REGMAP_IRQ_REG(S2MPU02_IRQ_JIGONBR, 0, S2MPS11_IRQ_JIGONBR_MASK),
REGMAP_IRQ_REG(S2MPU02_IRQ_ACOKBF, 0, S2MPS11_IRQ_ACOKBF_MASK),
REGMAP_IRQ_REG(S2MPU02_IRQ_ACOKBR, 0, S2MPS11_IRQ_ACOKBR_MASK),
REGMAP_IRQ_REG(S2MPU02_IRQ_PWRON1S, 0, S2MPS11_IRQ_PWRON1S_MASK),
REGMAP_IRQ_REG(S2MPU02_IRQ_MRB, 0, S2MPS11_IRQ_MRB_MASK),
REGMAP_IRQ_REG(S2MPU02_IRQ_RTC60S, 1, S2MPS11_IRQ_RTC60S_MASK),
REGMAP_IRQ_REG(S2MPU02_IRQ_RTCA1, 1, S2MPS11_IRQ_RTCA1_MASK),
REGMAP_IRQ_REG(S2MPU02_IRQ_RTCA0, 1, S2MPS11_IRQ_RTCA0_MASK),
REGMAP_IRQ_REG(S2MPU02_IRQ_SMPL, 1, S2MPS11_IRQ_SMPL_MASK),
REGMAP_IRQ_REG(S2MPU02_IRQ_RTC1S, 1, S2MPS11_IRQ_RTC1S_MASK),
REGMAP_IRQ_REG(S2MPU02_IRQ_WTSR, 1, S2MPS11_IRQ_WTSR_MASK),
REGMAP_IRQ_REG(S2MPU02_IRQ_INT120C, 2, S2MPS11_IRQ_INT120C_MASK),
REGMAP_IRQ_REG(S2MPU02_IRQ_INT140C, 2, S2MPS11_IRQ_INT140C_MASK),
REGMAP_IRQ_REG(S2MPU02_IRQ_TSD, 2, S2MPS14_IRQ_TSD_MASK),
};
static const struct regmap_irq s2mpu05_irqs[] = {
@ -247,74 +159,35 @@ static const struct regmap_irq s2mpu05_irqs[] = {
};
static const struct regmap_irq s5m8767_irqs[] = {
[S5M8767_IRQ_PWRR] = {
.reg_offset = 0,
.mask = S5M8767_IRQ_PWRR_MASK,
},
[S5M8767_IRQ_PWRF] = {
.reg_offset = 0,
.mask = S5M8767_IRQ_PWRF_MASK,
},
[S5M8767_IRQ_PWR1S] = {
.reg_offset = 0,
.mask = S5M8767_IRQ_PWR1S_MASK,
},
[S5M8767_IRQ_JIGR] = {
.reg_offset = 0,
.mask = S5M8767_IRQ_JIGR_MASK,
},
[S5M8767_IRQ_JIGF] = {
.reg_offset = 0,
.mask = S5M8767_IRQ_JIGF_MASK,
},
[S5M8767_IRQ_LOWBAT2] = {
.reg_offset = 0,
.mask = S5M8767_IRQ_LOWBAT2_MASK,
},
[S5M8767_IRQ_LOWBAT1] = {
.reg_offset = 0,
.mask = S5M8767_IRQ_LOWBAT1_MASK,
},
[S5M8767_IRQ_MRB] = {
.reg_offset = 1,
.mask = S5M8767_IRQ_MRB_MASK,
},
[S5M8767_IRQ_DVSOK2] = {
.reg_offset = 1,
.mask = S5M8767_IRQ_DVSOK2_MASK,
},
[S5M8767_IRQ_DVSOK3] = {
.reg_offset = 1,
.mask = S5M8767_IRQ_DVSOK3_MASK,
},
[S5M8767_IRQ_DVSOK4] = {
.reg_offset = 1,
.mask = S5M8767_IRQ_DVSOK4_MASK,
},
[S5M8767_IRQ_RTC60S] = {
.reg_offset = 2,
.mask = S5M8767_IRQ_RTC60S_MASK,
},
[S5M8767_IRQ_RTCA1] = {
.reg_offset = 2,
.mask = S5M8767_IRQ_RTCA1_MASK,
},
[S5M8767_IRQ_RTCA2] = {
.reg_offset = 2,
.mask = S5M8767_IRQ_RTCA2_MASK,
},
[S5M8767_IRQ_SMPL] = {
.reg_offset = 2,
.mask = S5M8767_IRQ_SMPL_MASK,
},
[S5M8767_IRQ_RTC1S] = {
.reg_offset = 2,
.mask = S5M8767_IRQ_RTC1S_MASK,
},
[S5M8767_IRQ_WTSR] = {
.reg_offset = 2,
.mask = S5M8767_IRQ_WTSR_MASK,
},
REGMAP_IRQ_REG(S5M8767_IRQ_PWRR, 0, S5M8767_IRQ_PWRR_MASK),
REGMAP_IRQ_REG(S5M8767_IRQ_PWRF, 0, S5M8767_IRQ_PWRF_MASK),
REGMAP_IRQ_REG(S5M8767_IRQ_PWR1S, 0, S5M8767_IRQ_PWR1S_MASK),
REGMAP_IRQ_REG(S5M8767_IRQ_JIGR, 0, S5M8767_IRQ_JIGR_MASK),
REGMAP_IRQ_REG(S5M8767_IRQ_JIGF, 0, S5M8767_IRQ_JIGF_MASK),
REGMAP_IRQ_REG(S5M8767_IRQ_LOWBAT2, 0, S5M8767_IRQ_LOWBAT2_MASK),
REGMAP_IRQ_REG(S5M8767_IRQ_LOWBAT1, 0, S5M8767_IRQ_LOWBAT1_MASK),
REGMAP_IRQ_REG(S5M8767_IRQ_MRB, 1, S5M8767_IRQ_MRB_MASK),
REGMAP_IRQ_REG(S5M8767_IRQ_DVSOK2, 1, S5M8767_IRQ_DVSOK2_MASK),
REGMAP_IRQ_REG(S5M8767_IRQ_DVSOK3, 1, S5M8767_IRQ_DVSOK3_MASK),
REGMAP_IRQ_REG(S5M8767_IRQ_DVSOK4, 1, S5M8767_IRQ_DVSOK4_MASK),
REGMAP_IRQ_REG(S5M8767_IRQ_RTC60S, 2, S5M8767_IRQ_RTC60S_MASK),
REGMAP_IRQ_REG(S5M8767_IRQ_RTCA1, 2, S5M8767_IRQ_RTCA1_MASK),
REGMAP_IRQ_REG(S5M8767_IRQ_RTCA2, 2, S5M8767_IRQ_RTCA2_MASK),
REGMAP_IRQ_REG(S5M8767_IRQ_SMPL, 2, S5M8767_IRQ_SMPL_MASK),
REGMAP_IRQ_REG(S5M8767_IRQ_RTC1S, 2, S5M8767_IRQ_RTC1S_MASK),
REGMAP_IRQ_REG(S5M8767_IRQ_WTSR, 2, S5M8767_IRQ_WTSR_MASK),
};
/* All S2MPG10 interrupt sources are read-only and don't require clearing */
static const struct regmap_irq_chip s2mpg10_irq_chip = {
.name = "s2mpg10",
.irqs = s2mpg10_irqs,
.num_irqs = ARRAY_SIZE(s2mpg10_irqs),
.num_regs = 6,
.status_base = S2MPG10_PMIC_INT1,
.mask_base = S2MPG10_PMIC_INT1M,
};
static const struct regmap_irq_chip s2mps11_irq_chip = {
@ -382,23 +255,21 @@ static const struct regmap_irq_chip s5m8767_irq_chip = {
int sec_irq_init(struct sec_pmic_dev *sec_pmic)
{
int ret = 0;
int type = sec_pmic->device_type;
const struct regmap_irq_chip *sec_irq_chip;
int ret;
if (!sec_pmic->irq) {
dev_warn(sec_pmic->dev,
"No interrupt specified, no interrupts\n");
return 0;
}
switch (type) {
switch (sec_pmic->device_type) {
case S5M8767X:
sec_irq_chip = &s5m8767_irq_chip;
break;
case S2DOS05:
return 0;
case S2MPA01:
sec_irq_chip = &s2mps14_irq_chip;
break;
case S2MPG10:
sec_irq_chip = &s2mpg10_irq_chip;
break;
case S2MPS11X:
sec_irq_chip = &s2mps11_irq_chip;
break;
@ -418,18 +289,24 @@ int sec_irq_init(struct sec_pmic_dev *sec_pmic)
sec_irq_chip = &s2mpu05_irq_chip;
break;
default:
dev_err(sec_pmic->dev, "Unknown device type %lu\n",
sec_pmic->device_type);
return -EINVAL;
return dev_err_probe(sec_pmic->dev, -EINVAL,
"Unsupported device type %d\n",
sec_pmic->device_type);
}
if (!sec_pmic->irq) {
dev_warn(sec_pmic->dev,
"No interrupt specified, no interrupts\n");
return 0;
}
ret = devm_regmap_add_irq_chip(sec_pmic->dev, sec_pmic->regmap_pmic,
sec_pmic->irq, IRQF_ONESHOT,
0, sec_irq_chip, &sec_pmic->irq_data);
if (ret != 0) {
dev_err(sec_pmic->dev, "Failed to register IRQ chip: %d\n", ret);
return ret;
}
if (ret)
return dev_err_probe(sec_pmic->dev, ret,
"Failed to add %s IRQ chip\n",
sec_irq_chip->name);
/*
* The rtc-s5m driver requests S2MPS14_IRQ_RTCA0 also for S2MPS11
@ -439,10 +316,3 @@ int sec_irq_init(struct sec_pmic_dev *sec_pmic)
return 0;
}
EXPORT_SYMBOL_GPL(sec_irq_init);
MODULE_AUTHOR("Sangbeom Kim <sbkim73@samsung.com>");
MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>");
MODULE_AUTHOR("Krzysztof Kozlowski <krzk@kernel.org>");
MODULE_DESCRIPTION("Interrupt support for the S5M MFD");
MODULE_LICENSE("GPL");

View File

@ -631,49 +631,6 @@ unsigned long sm501_set_clock(struct device *dev,
EXPORT_SYMBOL_GPL(sm501_set_clock);
/* sm501_find_clock
*
* finds the closest available frequency for a given clock
*/
unsigned long sm501_find_clock(struct device *dev,
int clksrc,
unsigned long req_freq)
{
struct sm501_devdata *sm = dev_get_drvdata(dev);
unsigned long sm501_freq; /* the frequency achieveable by the 501 */
struct sm501_clock to;
switch (clksrc) {
case SM501_CLOCK_P2XCLK:
if (sm->rev >= 0xC0) {
/* SM502 -> use the programmable PLL */
sm501_freq = (sm501_calc_pll(2 * req_freq,
&to, 5) / 2);
} else {
sm501_freq = (sm501_select_clock(2 * req_freq,
&to, 5) / 2);
}
break;
case SM501_CLOCK_V2XCLK:
sm501_freq = (sm501_select_clock(2 * req_freq, &to, 3) / 2);
break;
case SM501_CLOCK_MCLK:
case SM501_CLOCK_M1XCLK:
sm501_freq = sm501_select_clock(req_freq, &to, 3);
break;
default:
sm501_freq = 0; /* error */
}
return sm501_freq;
}
EXPORT_SYMBOL_GPL(sm501_find_clock);
static struct sm501_device *to_sm_device(struct platform_device *pdev)
{
return container_of(pdev, struct sm501_device, pdev);
@ -915,7 +872,8 @@ static void sm501_gpio_ensure_gpio(struct sm501_gpio_chip *smchip,
}
}
static void sm501_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
static int sm501_gpio_set(struct gpio_chip *chip, unsigned int offset,
int value)
{
struct sm501_gpio_chip *smchip = gpiochip_get_data(chip);
@ -939,6 +897,8 @@ static void sm501_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
sm501_gpio_ensure_gpio(smchip, bit);
spin_unlock_irqrestore(&smgpio->lock, save);
return 0;
}
static int sm501_gpio_input(struct gpio_chip *chip, unsigned offset)
@ -1005,7 +965,7 @@ static const struct gpio_chip gpio_chip_template = {
.ngpio = 32,
.direction_input = sm501_gpio_input,
.direction_output = sm501_gpio_output,
.set = sm501_gpio_set,
.set_rv = sm501_gpio_set,
.get = sm501_gpio_get,
};

View File

@ -210,7 +210,10 @@ static int sprd_pmic_probe(struct spi_device *spi)
return ret;
}
device_init_wakeup(&spi->dev, true);
ret = devm_device_init_wakeup(&spi->dev);
if (ret)
return dev_err_probe(&spi->dev, ret, "Failed to init wakeup\n");
return 0;
}

View File

@ -6,6 +6,7 @@
* Inspired by Benjamin Gaignard's stm32-timers driver
*/
#include <linux/bitfield.h>
#include <linux/mfd/stm32-lptimer.h>
#include <linux/module.h>
#include <linux/of_platform.h>
@ -49,6 +50,36 @@ static int stm32_lptimer_detect_encoder(struct stm32_lptimer *ddata)
return 0;
}
static int stm32_lptimer_detect_hwcfgr(struct stm32_lptimer *ddata)
{
u32 val;
int ret;
ret = regmap_read(ddata->regmap, STM32_LPTIM_VERR, &ddata->version);
if (ret)
return ret;
/* Try to guess parameters from HWCFGR: e.g. encoder mode (STM32MP15) */
ret = regmap_read(ddata->regmap, STM32_LPTIM_HWCFGR1, &val);
if (ret)
return ret;
/* Fallback to legacy init if HWCFGR isn't present */
if (!val)
return stm32_lptimer_detect_encoder(ddata);
ddata->has_encoder = FIELD_GET(STM32_LPTIM_HWCFGR1_ENCODER, val);
ret = regmap_read(ddata->regmap, STM32_LPTIM_HWCFGR2, &val);
if (ret)
return ret;
/* Number of capture/compare channels */
ddata->num_cc_chans = FIELD_GET(STM32_LPTIM_HWCFGR2_CHAN_NUM, val);
return 0;
}
static int stm32_lptimer_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@ -73,7 +104,7 @@ static int stm32_lptimer_probe(struct platform_device *pdev)
if (IS_ERR(ddata->clk))
return PTR_ERR(ddata->clk);
ret = stm32_lptimer_detect_encoder(ddata);
ret = stm32_lptimer_detect_hwcfgr(ddata);
if (ret)
return ret;

View File

@ -129,7 +129,7 @@ static const struct spi_device_id stmpe_spi_id[] = {
{ "stmpe2403", STMPE2403 },
{ }
};
MODULE_DEVICE_TABLE(spi, stmpe_id);
MODULE_DEVICE_TABLE(spi, stmpe_spi_id);
static struct spi_driver stmpe_spi_driver = {
.driver = {

View File

@ -446,7 +446,7 @@ static irqreturn_t tps65010_irq(int irq, void *_tps)
* offsets 4..5 == LED1/nPG, LED2 (we set one of the non-BLINK modes)
* offset 6 == vibrator motor driver
*/
static void
static int
tps65010_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
{
if (offset < 4)
@ -455,6 +455,8 @@ tps65010_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
tps65010_set_led(offset - 3, value ? ON : OFF);
else
tps65010_set_vib(value);
return 0;
}
static int
@ -512,7 +514,6 @@ static void tps65010_remove(struct i2c_client *client)
if (client->irq > 0)
free_irq(client->irq, tps);
cancel_delayed_work_sync(&tps->work);
debugfs_remove(tps->file);
the_tps = NULL;
}
@ -608,7 +609,7 @@ static int tps65010_probe(struct i2c_client *client)
tps65010_work(&tps->work.work);
tps->file = debugfs_create_file(DRIVER_NAME, S_IRUGO, NULL,
tps->file = debugfs_create_file(DRIVER_NAME, S_IRUGO, client->debugfs,
tps, DEBUG_FOPS);
/* optionally register GPIOs */
@ -619,7 +620,7 @@ static int tps65010_probe(struct i2c_client *client)
tps->chip.parent = &client->dev;
tps->chip.owner = THIS_MODULE;
tps->chip.set = tps65010_gpio_set;
tps->chip.set_rv = tps65010_gpio_set;
tps->chip.direction_output = tps65010_output;
/* NOTE: only partial support for inputs; nyet IRQs */

View File

@ -104,7 +104,8 @@ unsigned int ucb1x00_io_read(struct ucb1x00 *ucb)
return ucb1x00_reg_read(ucb, UCB_IO_DATA);
}
static void ucb1x00_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
static int ucb1x00_gpio_set(struct gpio_chip *chip, unsigned int offset,
int value)
{
struct ucb1x00 *ucb = gpiochip_get_data(chip);
unsigned long flags;
@ -119,6 +120,8 @@ static void ucb1x00_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
ucb1x00_reg_write(ucb, UCB_IO_DATA, ucb->io_out);
ucb1x00_disable(ucb);
spin_unlock_irqrestore(&ucb->io_lock, flags);
return 0;
}
static int ucb1x00_gpio_get(struct gpio_chip *chip, unsigned offset)
@ -567,7 +570,7 @@ static int ucb1x00_probe(struct mcp *mcp)
ucb->gpio.owner = THIS_MODULE;
ucb->gpio.base = pdata->gpio_base;
ucb->gpio.ngpio = 10;
ucb->gpio.set = ucb1x00_gpio_set;
ucb->gpio.set_rv = ucb1x00_gpio_set;
ucb->gpio.get = ucb1x00_gpio_get;
ucb->gpio.direction_input = ucb1x00_gpio_direction_input;
ucb->gpio.direction_output = ucb1x00_gpio_direction_output;

View File

@ -20,6 +20,7 @@
struct stm32_pwm_lp {
struct clk *clk;
struct regmap *regmap;
unsigned int num_cc_chans;
};
static inline struct stm32_pwm_lp *to_stm32_pwm_lp(struct pwm_chip *chip)
@ -30,13 +31,101 @@ static inline struct stm32_pwm_lp *to_stm32_pwm_lp(struct pwm_chip *chip)
/* STM32 Low-Power Timer is preceded by a configurable power-of-2 prescaler */
#define STM32_LPTIM_MAX_PRESCALER 128
static int stm32_pwm_lp_update_allowed(struct stm32_pwm_lp *priv, int channel)
{
int ret;
u32 ccmr1;
unsigned long ccmr;
/* Only one PWM on this LPTIMER: enable, prescaler and reload value can be changed */
if (!priv->num_cc_chans)
return true;
ret = regmap_read(priv->regmap, STM32_LPTIM_CCMR1, &ccmr1);
if (ret)
return ret;
ccmr = ccmr1 & (STM32_LPTIM_CC1E | STM32_LPTIM_CC2E);
/* More than one channel enabled: enable, prescaler or ARR value can't be changed */
if (bitmap_weight(&ccmr, sizeof(u32) * BITS_PER_BYTE) > 1)
return false;
/*
* Only one channel is enabled (or none): check status on the other channel, to
* report if enable, prescaler or ARR value can be changed.
*/
if (channel)
return !(ccmr1 & STM32_LPTIM_CC1E);
else
return !(ccmr1 & STM32_LPTIM_CC2E);
}
static int stm32_pwm_lp_compare_channel_apply(struct stm32_pwm_lp *priv, int channel,
bool enable, enum pwm_polarity polarity)
{
u32 ccmr1, val, mask;
bool reenable;
int ret;
/* No dedicated CC channel: nothing to do */
if (!priv->num_cc_chans)
return 0;
ret = regmap_read(priv->regmap, STM32_LPTIM_CCMR1, &ccmr1);
if (ret)
return ret;
if (channel) {
/* Must disable CC channel (CCxE) to modify polarity (CCxP), then re-enable */
reenable = (enable && FIELD_GET(STM32_LPTIM_CC2E, ccmr1)) &&
(polarity != FIELD_GET(STM32_LPTIM_CC2P, ccmr1));
mask = STM32_LPTIM_CC2SEL | STM32_LPTIM_CC2E | STM32_LPTIM_CC2P;
val = FIELD_PREP(STM32_LPTIM_CC2P, polarity);
val |= FIELD_PREP(STM32_LPTIM_CC2E, enable);
} else {
reenable = (enable && FIELD_GET(STM32_LPTIM_CC1E, ccmr1)) &&
(polarity != FIELD_GET(STM32_LPTIM_CC1P, ccmr1));
mask = STM32_LPTIM_CC1SEL | STM32_LPTIM_CC1E | STM32_LPTIM_CC1P;
val = FIELD_PREP(STM32_LPTIM_CC1P, polarity);
val |= FIELD_PREP(STM32_LPTIM_CC1E, enable);
}
if (reenable) {
u32 cfgr, presc;
unsigned long rate;
unsigned int delay_us;
ret = regmap_update_bits(priv->regmap, STM32_LPTIM_CCMR1,
channel ? STM32_LPTIM_CC2E : STM32_LPTIM_CC1E, 0);
if (ret)
return ret;
/*
* After a write to the LPTIM_CCMRx register, a new write operation can only be
* performed after a delay of at least (PRESC × 3) clock cycles
*/
ret = regmap_read(priv->regmap, STM32_LPTIM_CFGR, &cfgr);
if (ret)
return ret;
presc = FIELD_GET(STM32_LPTIM_PRESC, cfgr);
rate = clk_get_rate(priv->clk) >> presc;
if (!rate)
return -EINVAL;
delay_us = 3 * DIV_ROUND_UP(USEC_PER_SEC, rate);
usleep_range(delay_us, delay_us * 2);
}
return regmap_update_bits(priv->regmap, STM32_LPTIM_CCMR1, mask, val);
}
static int stm32_pwm_lp_apply(struct pwm_chip *chip, struct pwm_device *pwm,
const struct pwm_state *state)
{
struct stm32_pwm_lp *priv = to_stm32_pwm_lp(chip);
unsigned long long prd, div, dty;
struct pwm_state cstate;
u32 val, mask, cfgr, presc = 0;
u32 arr, val, mask, cfgr, presc = 0;
bool reenable;
int ret;
@ -45,10 +134,28 @@ static int stm32_pwm_lp_apply(struct pwm_chip *chip, struct pwm_device *pwm,
if (!state->enabled) {
if (cstate.enabled) {
/* Disable LP timer */
ret = regmap_write(priv->regmap, STM32_LPTIM_CR, 0);
/* Disable CC channel if any */
ret = stm32_pwm_lp_compare_channel_apply(priv, pwm->hwpwm, false,
state->polarity);
if (ret)
return ret;
ret = regmap_write(priv->regmap, pwm->hwpwm ?
STM32_LPTIM_CCR2 : STM32_LPTIM_CMP, 0);
if (ret)
return ret;
/* Check if the timer can be disabled */
ret = stm32_pwm_lp_update_allowed(priv, pwm->hwpwm);
if (ret < 0)
return ret;
if (ret) {
/* Disable LP timer */
ret = regmap_write(priv->regmap, STM32_LPTIM_CR, 0);
if (ret)
return ret;
}
/* disable clock to PWM counter */
clk_disable(priv->clk);
}
@ -79,6 +186,23 @@ static int stm32_pwm_lp_apply(struct pwm_chip *chip, struct pwm_device *pwm,
dty = prd * state->duty_cycle;
do_div(dty, state->period);
ret = regmap_read(priv->regmap, STM32_LPTIM_CFGR, &cfgr);
if (ret)
return ret;
/*
* When there are several channels, they share the same prescaler and reload value.
* Check if this can be changed, or the values are the same for all channels.
*/
if (!stm32_pwm_lp_update_allowed(priv, pwm->hwpwm)) {
ret = regmap_read(priv->regmap, STM32_LPTIM_ARR, &arr);
if (ret)
return ret;
if ((FIELD_GET(STM32_LPTIM_PRESC, cfgr) != presc) || (arr != prd - 1))
return -EBUSY;
}
if (!cstate.enabled) {
/* enable clock to drive PWM counter */
ret = clk_enable(priv->clk);
@ -86,15 +210,20 @@ static int stm32_pwm_lp_apply(struct pwm_chip *chip, struct pwm_device *pwm,
return ret;
}
ret = regmap_read(priv->regmap, STM32_LPTIM_CFGR, &cfgr);
if (ret)
goto err;
if ((FIELD_GET(STM32_LPTIM_PRESC, cfgr) != presc) ||
(FIELD_GET(STM32_LPTIM_WAVPOL, cfgr) != state->polarity)) {
((FIELD_GET(STM32_LPTIM_WAVPOL, cfgr) != state->polarity) && !priv->num_cc_chans)) {
val = FIELD_PREP(STM32_LPTIM_PRESC, presc);
val |= FIELD_PREP(STM32_LPTIM_WAVPOL, state->polarity);
mask = STM32_LPTIM_PRESC | STM32_LPTIM_WAVPOL;
mask = STM32_LPTIM_PRESC;
if (!priv->num_cc_chans) {
/*
* WAVPOL bit is only available when no capature compare channel is used,
* e.g. on LPTIMER instances that have only one output channel. CCMR1 is
* used otherwise.
*/
val |= FIELD_PREP(STM32_LPTIM_WAVPOL, state->polarity);
mask |= STM32_LPTIM_WAVPOL;
}
/* Must disable LP timer to modify CFGR */
reenable = true;
@ -120,20 +249,27 @@ static int stm32_pwm_lp_apply(struct pwm_chip *chip, struct pwm_device *pwm,
if (ret)
goto err;
ret = regmap_write(priv->regmap, STM32_LPTIM_CMP, prd - (1 + dty));
/* Write CMP/CCRx register and ensure it's been properly written */
ret = regmap_write(priv->regmap, pwm->hwpwm ? STM32_LPTIM_CCR2 : STM32_LPTIM_CMP,
prd - (1 + dty));
if (ret)
goto err;
/* ensure CMP & ARR registers are properly written */
ret = regmap_read_poll_timeout(priv->regmap, STM32_LPTIM_ISR, val,
/* ensure ARR and CMP/CCRx registers are properly written */
ret = regmap_read_poll_timeout(priv->regmap, STM32_LPTIM_ISR, val, pwm->hwpwm ?
(val & STM32_LPTIM_CMP2_ARROK) == STM32_LPTIM_CMP2_ARROK :
(val & STM32_LPTIM_CMPOK_ARROK) == STM32_LPTIM_CMPOK_ARROK,
100, 1000);
if (ret) {
dev_err(pwmchip_parent(chip), "ARR/CMP registers write issue\n");
goto err;
}
ret = regmap_write(priv->regmap, STM32_LPTIM_ICR,
STM32_LPTIM_CMPOKCF_ARROKCF);
ret = regmap_write(priv->regmap, STM32_LPTIM_ICR, pwm->hwpwm ?
STM32_LPTIM_CMP2OKCF_ARROKCF : STM32_LPTIM_CMPOKCF_ARROKCF);
if (ret)
goto err;
ret = stm32_pwm_lp_compare_channel_apply(priv, pwm->hwpwm, true, state->polarity);
if (ret)
goto err;
@ -161,11 +297,22 @@ static int stm32_pwm_lp_get_state(struct pwm_chip *chip,
{
struct stm32_pwm_lp *priv = to_stm32_pwm_lp(chip);
unsigned long rate = clk_get_rate(priv->clk);
u32 val, presc, prd;
u32 val, presc, prd, ccmr1;
bool enabled;
u64 tmp;
regmap_read(priv->regmap, STM32_LPTIM_CR, &val);
state->enabled = !!FIELD_GET(STM32_LPTIM_ENABLE, val);
enabled = !!FIELD_GET(STM32_LPTIM_ENABLE, val);
if (priv->num_cc_chans) {
/* There's a CC chan, need to also check if it's enabled */
regmap_read(priv->regmap, STM32_LPTIM_CCMR1, &ccmr1);
if (pwm->hwpwm)
enabled &= !!FIELD_GET(STM32_LPTIM_CC2E, ccmr1);
else
enabled &= !!FIELD_GET(STM32_LPTIM_CC1E, ccmr1);
}
state->enabled = enabled;
/* Keep PWM counter clock refcount in sync with PWM initial state */
if (state->enabled) {
int ret = clk_enable(priv->clk);
@ -176,14 +323,21 @@ static int stm32_pwm_lp_get_state(struct pwm_chip *chip,
regmap_read(priv->regmap, STM32_LPTIM_CFGR, &val);
presc = FIELD_GET(STM32_LPTIM_PRESC, val);
state->polarity = FIELD_GET(STM32_LPTIM_WAVPOL, val);
if (priv->num_cc_chans) {
if (pwm->hwpwm)
state->polarity = FIELD_GET(STM32_LPTIM_CC2P, ccmr1);
else
state->polarity = FIELD_GET(STM32_LPTIM_CC1P, ccmr1);
} else {
state->polarity = FIELD_GET(STM32_LPTIM_WAVPOL, val);
}
regmap_read(priv->regmap, STM32_LPTIM_ARR, &prd);
tmp = prd + 1;
tmp = (tmp << presc) * NSEC_PER_SEC;
state->period = DIV_ROUND_CLOSEST_ULL(tmp, rate);
regmap_read(priv->regmap, STM32_LPTIM_CMP, &val);
regmap_read(priv->regmap, pwm->hwpwm ? STM32_LPTIM_CCR2 : STM32_LPTIM_CMP, &val);
tmp = prd - val;
tmp = (tmp << presc) * NSEC_PER_SEC;
state->duty_cycle = DIV_ROUND_CLOSEST_ULL(tmp, rate);
@ -201,15 +355,25 @@ static int stm32_pwm_lp_probe(struct platform_device *pdev)
struct stm32_lptimer *ddata = dev_get_drvdata(pdev->dev.parent);
struct stm32_pwm_lp *priv;
struct pwm_chip *chip;
unsigned int npwm;
int ret;
chip = devm_pwmchip_alloc(&pdev->dev, 1, sizeof(*priv));
if (!ddata->num_cc_chans) {
/* No dedicated CC channel, so there's only one PWM channel */
npwm = 1;
} else {
/* There are dedicated CC channels, each with one PWM output */
npwm = ddata->num_cc_chans;
}
chip = devm_pwmchip_alloc(&pdev->dev, npwm, sizeof(*priv));
if (IS_ERR(chip))
return PTR_ERR(chip);
priv = to_stm32_pwm_lp(chip);
priv->regmap = ddata->regmap;
priv->clk = ddata->clk;
priv->num_cc_chans = ddata->num_cc_chans;
chip->ops = &stm32_pwm_lp_ops;
ret = devm_pwmchip_add(&pdev->dev, chip);
@ -225,12 +389,15 @@ static int stm32_pwm_lp_suspend(struct device *dev)
{
struct pwm_chip *chip = dev_get_drvdata(dev);
struct pwm_state state;
unsigned int i;
pwm_get_state(&chip->pwms[0], &state);
if (state.enabled) {
dev_err(dev, "The consumer didn't stop us (%s)\n",
chip->pwms[0].label);
return -EBUSY;
for (i = 0; i < chip->npwm; i++) {
pwm_get_state(&chip->pwms[i], &state);
if (state.enabled) {
dev_err(dev, "The consumer didn't stop us (%s)\n",
chip->pwms[i].label);
return -EBUSY;
}
}
return pinctrl_pm_select_sleep_state(dev);

File diff suppressed because it is too large Load Diff

View File

@ -83,6 +83,7 @@ enum {
#define BD96801_LDO6_VSEL_REG 0x26
#define BD96801_LDO7_VSEL_REG 0x27
#define BD96801_BUCK_VSEL_MASK 0x1F
#define BD96805_BUCK_VSEL_MASK 0x3f
#define BD96801_LDO_VSEL_MASK 0xff
#define BD96801_MASK_RAMP_DELAY 0xc0
@ -90,6 +91,7 @@ enum {
#define BD96801_BUCK_INT_VOUT_MASK 0xff
#define BD96801_BUCK_VOLTS 256
#define BD96805_BUCK_VOLTS 64
#define BD96801_LDO_VOLTS 256
#define BD96801_OVP_MASK 0x03
@ -160,6 +162,30 @@ static const struct linear_range bd96801_buck_init_volts[] = {
REGULATOR_LINEAR_RANGE(3300000 - 150000, 0xed, 0xff, 0),
};
/* BD96802 uses same voltage ranges for bucks as BD96801 */
#define bd96802_tune_volts bd96801_tune_volts
#define bd96802_buck_init_volts bd96801_buck_init_volts
/*
* On BD96805 we have similar "negative tuning range" as on BD96801, except
* that the max tuning is -310 ... +310 mV (instead of the 150mV). We use same
* approach as with the BD96801 ranges.
*/
static const struct linear_range bd96805_tune_volts[] = {
REGULATOR_LINEAR_RANGE(310000, 0x00, 0x1F, 10000),
REGULATOR_LINEAR_RANGE(0, 0x20, 0x3F, 10000),
};
static const struct linear_range bd96805_buck_init_volts[] = {
REGULATOR_LINEAR_RANGE(500000 - 310000, 0x00, 0xc8, 5000),
REGULATOR_LINEAR_RANGE(1550000 - 310000, 0xc9, 0xec, 50000),
REGULATOR_LINEAR_RANGE(3300000 - 310000, 0xed, 0xff, 0),
};
/* BD96806 uses same voltage ranges for bucks as BD96805 */
#define bd96806_tune_volts bd96805_tune_volts
#define bd96806_buck_init_volts bd96805_buck_init_volts
static const struct linear_range bd96801_ldo_int_volts[] = {
REGULATOR_LINEAR_RANGE(300000, 0x00, 0x78, 25000),
REGULATOR_LINEAR_RANGE(3300000, 0x79, 0xff, 0),
@ -198,89 +224,89 @@ struct bd96801_irqinfo {
static const struct bd96801_irqinfo buck1_irqinfo[] = {
BD96801_IRQINFO(BD96801_PROT_OCP, "buck1-over-curr-h", 500,
"bd96801-buck1-overcurr-h"),
"buck1-overcurr-h"),
BD96801_IRQINFO(BD96801_PROT_OCP, "buck1-over-curr-l", 500,
"bd96801-buck1-overcurr-l"),
"buck1-overcurr-l"),
BD96801_IRQINFO(BD96801_PROT_OCP, "buck1-over-curr-n", 500,
"bd96801-buck1-overcurr-n"),
"buck1-overcurr-n"),
BD96801_IRQINFO(BD96801_PROT_OVP, "buck1-over-voltage", 500,
"bd96801-buck1-overvolt"),
"buck1-overvolt"),
BD96801_IRQINFO(BD96801_PROT_UVP, "buck1-under-voltage", 500,
"bd96801-buck1-undervolt"),
"buck1-undervolt"),
BD96801_IRQINFO(BD96801_PROT_TEMP, "buck1-over-temp", 500,
"bd96801-buck1-thermal")
"buck1-thermal")
};
static const struct bd96801_irqinfo buck2_irqinfo[] = {
BD96801_IRQINFO(BD96801_PROT_OCP, "buck2-over-curr-h", 500,
"bd96801-buck2-overcurr-h"),
"buck2-overcurr-h"),
BD96801_IRQINFO(BD96801_PROT_OCP, "buck2-over-curr-l", 500,
"bd96801-buck2-overcurr-l"),
"buck2-overcurr-l"),
BD96801_IRQINFO(BD96801_PROT_OCP, "buck2-over-curr-n", 500,
"bd96801-buck2-overcurr-n"),
"buck2-overcurr-n"),
BD96801_IRQINFO(BD96801_PROT_OVP, "buck2-over-voltage", 500,
"bd96801-buck2-overvolt"),
"buck2-overvolt"),
BD96801_IRQINFO(BD96801_PROT_UVP, "buck2-under-voltage", 500,
"bd96801-buck2-undervolt"),
"buck2-undervolt"),
BD96801_IRQINFO(BD96801_PROT_TEMP, "buck2-over-temp", 500,
"bd96801-buck2-thermal")
"buck2-thermal")
};
static const struct bd96801_irqinfo buck3_irqinfo[] = {
BD96801_IRQINFO(BD96801_PROT_OCP, "buck3-over-curr-h", 500,
"bd96801-buck3-overcurr-h"),
"buck3-overcurr-h"),
BD96801_IRQINFO(BD96801_PROT_OCP, "buck3-over-curr-l", 500,
"bd96801-buck3-overcurr-l"),
"buck3-overcurr-l"),
BD96801_IRQINFO(BD96801_PROT_OCP, "buck3-over-curr-n", 500,
"bd96801-buck3-overcurr-n"),
"buck3-overcurr-n"),
BD96801_IRQINFO(BD96801_PROT_OVP, "buck3-over-voltage", 500,
"bd96801-buck3-overvolt"),
"buck3-overvolt"),
BD96801_IRQINFO(BD96801_PROT_UVP, "buck3-under-voltage", 500,
"bd96801-buck3-undervolt"),
"buck3-undervolt"),
BD96801_IRQINFO(BD96801_PROT_TEMP, "buck3-over-temp", 500,
"bd96801-buck3-thermal")
"buck3-thermal")
};
static const struct bd96801_irqinfo buck4_irqinfo[] = {
BD96801_IRQINFO(BD96801_PROT_OCP, "buck4-over-curr-h", 500,
"bd96801-buck4-overcurr-h"),
"buck4-overcurr-h"),
BD96801_IRQINFO(BD96801_PROT_OCP, "buck4-over-curr-l", 500,
"bd96801-buck4-overcurr-l"),
"buck4-overcurr-l"),
BD96801_IRQINFO(BD96801_PROT_OCP, "buck4-over-curr-n", 500,
"bd96801-buck4-overcurr-n"),
"buck4-overcurr-n"),
BD96801_IRQINFO(BD96801_PROT_OVP, "buck4-over-voltage", 500,
"bd96801-buck4-overvolt"),
"buck4-overvolt"),
BD96801_IRQINFO(BD96801_PROT_UVP, "buck4-under-voltage", 500,
"bd96801-buck4-undervolt"),
"buck4-undervolt"),
BD96801_IRQINFO(BD96801_PROT_TEMP, "buck4-over-temp", 500,
"bd96801-buck4-thermal")
"buck4-thermal")
};
static const struct bd96801_irqinfo ldo5_irqinfo[] = {
BD96801_IRQINFO(BD96801_PROT_OCP, "ldo5-overcurr", 500,
"bd96801-ldo5-overcurr"),
"ldo5-overcurr"),
BD96801_IRQINFO(BD96801_PROT_OVP, "ldo5-over-voltage", 500,
"bd96801-ldo5-overvolt"),
"ldo5-overvolt"),
BD96801_IRQINFO(BD96801_PROT_UVP, "ldo5-under-voltage", 500,
"bd96801-ldo5-undervolt"),
"ldo5-undervolt"),
};
static const struct bd96801_irqinfo ldo6_irqinfo[] = {
BD96801_IRQINFO(BD96801_PROT_OCP, "ldo6-overcurr", 500,
"bd96801-ldo6-overcurr"),
"ldo6-overcurr"),
BD96801_IRQINFO(BD96801_PROT_OVP, "ldo6-over-voltage", 500,
"bd96801-ldo6-overvolt"),
"ldo6-overvolt"),
BD96801_IRQINFO(BD96801_PROT_UVP, "ldo6-under-voltage", 500,
"bd96801-ldo6-undervolt"),
"ldo6-undervolt"),
};
static const struct bd96801_irqinfo ldo7_irqinfo[] = {
BD96801_IRQINFO(BD96801_PROT_OCP, "ldo7-overcurr", 500,
"bd96801-ldo7-overcurr"),
"ldo7-overcurr"),
BD96801_IRQINFO(BD96801_PROT_OVP, "ldo7-over-voltage", 500,
"bd96801-ldo7-overvolt"),
"ldo7-overvolt"),
BD96801_IRQINFO(BD96801_PROT_UVP, "ldo7-under-voltage", 500,
"bd96801-ldo7-undervolt"),
"ldo7-undervolt"),
};
struct bd96801_irq_desc {
@ -302,6 +328,7 @@ struct bd96801_pmic_data {
struct bd96801_regulator_data regulator_data[BD96801_NUM_REGULATORS];
struct regmap *regmap;
int fatal_ind;
int num_regulators;
};
static int ldo_map_notif(int irq, struct regulator_irq_data *rid,
@ -503,6 +530,70 @@ static int bd96801_walk_regulator_dt(struct device *dev, struct regmap *regmap,
* case later. What we can easly do for preparing is to not use static global
* data for regulators though.
*/
static const struct bd96801_pmic_data bd96802_data = {
.regulator_data = {
{
.desc = {
.name = "buck1",
.of_match = of_match_ptr("buck1"),
.regulators_node = of_match_ptr("regulators"),
.id = BD96801_BUCK1,
.ops = &bd96801_buck_ops,
.type = REGULATOR_VOLTAGE,
.linear_ranges = bd96802_tune_volts,
.n_linear_ranges = ARRAY_SIZE(bd96802_tune_volts),
.n_voltages = BD96801_BUCK_VOLTS,
.enable_reg = BD96801_REG_ENABLE,
.enable_mask = BD96801_BUCK1_EN_MASK,
.enable_is_inverted = true,
.vsel_reg = BD96801_BUCK1_VSEL_REG,
.vsel_mask = BD96801_BUCK_VSEL_MASK,
.ramp_reg = BD96801_BUCK1_VSEL_REG,
.ramp_mask = BD96801_MASK_RAMP_DELAY,
.ramp_delay_table = &buck_ramp_table[0],
.n_ramp_values = ARRAY_SIZE(buck_ramp_table),
.owner = THIS_MODULE,
},
.init_ranges = bd96802_buck_init_volts,
.num_ranges = ARRAY_SIZE(bd96802_buck_init_volts),
.irq_desc = {
.irqinfo = (struct bd96801_irqinfo *)&buck1_irqinfo[0],
.num_irqs = ARRAY_SIZE(buck1_irqinfo),
},
},
{
.desc = {
.name = "buck2",
.of_match = of_match_ptr("buck2"),
.regulators_node = of_match_ptr("regulators"),
.id = BD96801_BUCK2,
.ops = &bd96801_buck_ops,
.type = REGULATOR_VOLTAGE,
.linear_ranges = bd96802_tune_volts,
.n_linear_ranges = ARRAY_SIZE(bd96802_tune_volts),
.n_voltages = BD96801_BUCK_VOLTS,
.enable_reg = BD96801_REG_ENABLE,
.enable_mask = BD96801_BUCK2_EN_MASK,
.enable_is_inverted = true,
.vsel_reg = BD96801_BUCK2_VSEL_REG,
.vsel_mask = BD96801_BUCK_VSEL_MASK,
.ramp_reg = BD96801_BUCK2_VSEL_REG,
.ramp_mask = BD96801_MASK_RAMP_DELAY,
.ramp_delay_table = &buck_ramp_table[0],
.n_ramp_values = ARRAY_SIZE(buck_ramp_table),
.owner = THIS_MODULE,
},
.irq_desc = {
.irqinfo = (struct bd96801_irqinfo *)&buck2_irqinfo[0],
.num_irqs = ARRAY_SIZE(buck2_irqinfo),
},
.init_ranges = bd96802_buck_init_volts,
.num_ranges = ARRAY_SIZE(bd96802_buck_init_volts),
},
},
.num_regulators = 2,
};
static const struct bd96801_pmic_data bd96801_data = {
.regulator_data = {
{
@ -688,11 +779,265 @@ static const struct bd96801_pmic_data bd96801_data = {
.ldo_vol_lvl = BD96801_LDO7_VOL_LVL_REG,
},
},
.num_regulators = 7,
};
static int initialize_pmic_data(struct device *dev,
static const struct bd96801_pmic_data bd96805_data = {
.regulator_data = {
{
.desc = {
.name = "buck1",
.of_match = of_match_ptr("buck1"),
.regulators_node = of_match_ptr("regulators"),
.id = BD96801_BUCK1,
.ops = &bd96801_buck_ops,
.type = REGULATOR_VOLTAGE,
.linear_ranges = bd96805_tune_volts,
.n_linear_ranges = ARRAY_SIZE(bd96805_tune_volts),
.n_voltages = BD96805_BUCK_VOLTS,
.enable_reg = BD96801_REG_ENABLE,
.enable_mask = BD96801_BUCK1_EN_MASK,
.enable_is_inverted = true,
.vsel_reg = BD96801_BUCK1_VSEL_REG,
.vsel_mask = BD96805_BUCK_VSEL_MASK,
.ramp_reg = BD96801_BUCK1_VSEL_REG,
.ramp_mask = BD96801_MASK_RAMP_DELAY,
.ramp_delay_table = &buck_ramp_table[0],
.n_ramp_values = ARRAY_SIZE(buck_ramp_table),
.owner = THIS_MODULE,
},
.init_ranges = bd96805_buck_init_volts,
.num_ranges = ARRAY_SIZE(bd96805_buck_init_volts),
.irq_desc = {
.irqinfo = (struct bd96801_irqinfo *)&buck1_irqinfo[0],
.num_irqs = ARRAY_SIZE(buck1_irqinfo),
},
}, {
.desc = {
.name = "buck2",
.of_match = of_match_ptr("buck2"),
.regulators_node = of_match_ptr("regulators"),
.id = BD96801_BUCK2,
.ops = &bd96801_buck_ops,
.type = REGULATOR_VOLTAGE,
.linear_ranges = bd96805_tune_volts,
.n_linear_ranges = ARRAY_SIZE(bd96805_tune_volts),
.n_voltages = BD96805_BUCK_VOLTS,
.enable_reg = BD96801_REG_ENABLE,
.enable_mask = BD96801_BUCK2_EN_MASK,
.enable_is_inverted = true,
.vsel_reg = BD96801_BUCK2_VSEL_REG,
.vsel_mask = BD96805_BUCK_VSEL_MASK,
.ramp_reg = BD96801_BUCK2_VSEL_REG,
.ramp_mask = BD96801_MASK_RAMP_DELAY,
.ramp_delay_table = &buck_ramp_table[0],
.n_ramp_values = ARRAY_SIZE(buck_ramp_table),
.owner = THIS_MODULE,
},
.irq_desc = {
.irqinfo = (struct bd96801_irqinfo *)&buck2_irqinfo[0],
.num_irqs = ARRAY_SIZE(buck2_irqinfo),
},
.init_ranges = bd96805_buck_init_volts,
.num_ranges = ARRAY_SIZE(bd96805_buck_init_volts),
}, {
.desc = {
.name = "buck3",
.of_match = of_match_ptr("buck3"),
.regulators_node = of_match_ptr("regulators"),
.id = BD96801_BUCK3,
.ops = &bd96801_buck_ops,
.type = REGULATOR_VOLTAGE,
.linear_ranges = bd96805_tune_volts,
.n_linear_ranges = ARRAY_SIZE(bd96805_tune_volts),
.n_voltages = BD96805_BUCK_VOLTS,
.enable_reg = BD96801_REG_ENABLE,
.enable_mask = BD96801_BUCK3_EN_MASK,
.enable_is_inverted = true,
.vsel_reg = BD96801_BUCK3_VSEL_REG,
.vsel_mask = BD96805_BUCK_VSEL_MASK,
.ramp_reg = BD96801_BUCK3_VSEL_REG,
.ramp_mask = BD96801_MASK_RAMP_DELAY,
.ramp_delay_table = &buck_ramp_table[0],
.n_ramp_values = ARRAY_SIZE(buck_ramp_table),
.owner = THIS_MODULE,
},
.irq_desc = {
.irqinfo = (struct bd96801_irqinfo *)&buck3_irqinfo[0],
.num_irqs = ARRAY_SIZE(buck3_irqinfo),
},
.init_ranges = bd96805_buck_init_volts,
.num_ranges = ARRAY_SIZE(bd96805_buck_init_volts),
}, {
.desc = {
.name = "buck4",
.of_match = of_match_ptr("buck4"),
.regulators_node = of_match_ptr("regulators"),
.id = BD96801_BUCK4,
.ops = &bd96801_buck_ops,
.type = REGULATOR_VOLTAGE,
.linear_ranges = bd96805_tune_volts,
.n_linear_ranges = ARRAY_SIZE(bd96805_tune_volts),
.n_voltages = BD96805_BUCK_VOLTS,
.enable_reg = BD96801_REG_ENABLE,
.enable_mask = BD96801_BUCK4_EN_MASK,
.enable_is_inverted = true,
.vsel_reg = BD96801_BUCK4_VSEL_REG,
.vsel_mask = BD96805_BUCK_VSEL_MASK,
.ramp_reg = BD96801_BUCK4_VSEL_REG,
.ramp_mask = BD96801_MASK_RAMP_DELAY,
.ramp_delay_table = &buck_ramp_table[0],
.n_ramp_values = ARRAY_SIZE(buck_ramp_table),
.owner = THIS_MODULE,
},
.irq_desc = {
.irqinfo = (struct bd96801_irqinfo *)&buck4_irqinfo[0],
.num_irqs = ARRAY_SIZE(buck4_irqinfo),
},
.init_ranges = bd96805_buck_init_volts,
.num_ranges = ARRAY_SIZE(bd96805_buck_init_volts),
}, {
.desc = {
.name = "ldo5",
.of_match = of_match_ptr("ldo5"),
.regulators_node = of_match_ptr("regulators"),
.id = BD96801_LDO5,
.ops = &bd96801_ldo_ops,
.type = REGULATOR_VOLTAGE,
.linear_ranges = bd96801_ldo_int_volts,
.n_linear_ranges = ARRAY_SIZE(bd96801_ldo_int_volts),
.n_voltages = BD96801_LDO_VOLTS,
.enable_reg = BD96801_REG_ENABLE,
.enable_mask = BD96801_LDO5_EN_MASK,
.enable_is_inverted = true,
.vsel_reg = BD96801_LDO5_VSEL_REG,
.vsel_mask = BD96801_LDO_VSEL_MASK,
.owner = THIS_MODULE,
},
.irq_desc = {
.irqinfo = (struct bd96801_irqinfo *)&ldo5_irqinfo[0],
.num_irqs = ARRAY_SIZE(ldo5_irqinfo),
},
.ldo_vol_lvl = BD96801_LDO5_VOL_LVL_REG,
}, {
.desc = {
.name = "ldo6",
.of_match = of_match_ptr("ldo6"),
.regulators_node = of_match_ptr("regulators"),
.id = BD96801_LDO6,
.ops = &bd96801_ldo_ops,
.type = REGULATOR_VOLTAGE,
.linear_ranges = bd96801_ldo_int_volts,
.n_linear_ranges = ARRAY_SIZE(bd96801_ldo_int_volts),
.n_voltages = BD96801_LDO_VOLTS,
.enable_reg = BD96801_REG_ENABLE,
.enable_mask = BD96801_LDO6_EN_MASK,
.enable_is_inverted = true,
.vsel_reg = BD96801_LDO6_VSEL_REG,
.vsel_mask = BD96801_LDO_VSEL_MASK,
.owner = THIS_MODULE,
},
.irq_desc = {
.irqinfo = (struct bd96801_irqinfo *)&ldo6_irqinfo[0],
.num_irqs = ARRAY_SIZE(ldo6_irqinfo),
},
.ldo_vol_lvl = BD96801_LDO6_VOL_LVL_REG,
}, {
.desc = {
.name = "ldo7",
.of_match = of_match_ptr("ldo7"),
.regulators_node = of_match_ptr("regulators"),
.id = BD96801_LDO7,
.ops = &bd96801_ldo_ops,
.type = REGULATOR_VOLTAGE,
.linear_ranges = bd96801_ldo_int_volts,
.n_linear_ranges = ARRAY_SIZE(bd96801_ldo_int_volts),
.n_voltages = BD96801_LDO_VOLTS,
.enable_reg = BD96801_REG_ENABLE,
.enable_mask = BD96801_LDO7_EN_MASK,
.enable_is_inverted = true,
.vsel_reg = BD96801_LDO7_VSEL_REG,
.vsel_mask = BD96801_LDO_VSEL_MASK,
.owner = THIS_MODULE,
},
.irq_desc = {
.irqinfo = (struct bd96801_irqinfo *)&ldo7_irqinfo[0],
.num_irqs = ARRAY_SIZE(ldo7_irqinfo),
},
.ldo_vol_lvl = BD96801_LDO7_VOL_LVL_REG,
},
},
.num_regulators = 7,
};
static const struct bd96801_pmic_data bd96806_data = {
.regulator_data = {
{
.desc = {
.name = "buck1",
.of_match = of_match_ptr("buck1"),
.regulators_node = of_match_ptr("regulators"),
.id = BD96801_BUCK1,
.ops = &bd96801_buck_ops,
.type = REGULATOR_VOLTAGE,
.linear_ranges = bd96806_tune_volts,
.n_linear_ranges = ARRAY_SIZE(bd96806_tune_volts),
.n_voltages = BD96805_BUCK_VOLTS,
.enable_reg = BD96801_REG_ENABLE,
.enable_mask = BD96801_BUCK1_EN_MASK,
.enable_is_inverted = true,
.vsel_reg = BD96801_BUCK1_VSEL_REG,
.vsel_mask = BD96805_BUCK_VSEL_MASK,
.ramp_reg = BD96801_BUCK1_VSEL_REG,
.ramp_mask = BD96801_MASK_RAMP_DELAY,
.ramp_delay_table = &buck_ramp_table[0],
.n_ramp_values = ARRAY_SIZE(buck_ramp_table),
.owner = THIS_MODULE,
},
.init_ranges = bd96806_buck_init_volts,
.num_ranges = ARRAY_SIZE(bd96806_buck_init_volts),
.irq_desc = {
.irqinfo = (struct bd96801_irqinfo *)&buck1_irqinfo[0],
.num_irqs = ARRAY_SIZE(buck1_irqinfo),
},
},
{
.desc = {
.name = "buck2",
.of_match = of_match_ptr("buck2"),
.regulators_node = of_match_ptr("regulators"),
.id = BD96801_BUCK2,
.ops = &bd96801_buck_ops,
.type = REGULATOR_VOLTAGE,
.linear_ranges = bd96806_tune_volts,
.n_linear_ranges = ARRAY_SIZE(bd96806_tune_volts),
.n_voltages = BD96805_BUCK_VOLTS,
.enable_reg = BD96801_REG_ENABLE,
.enable_mask = BD96801_BUCK2_EN_MASK,
.enable_is_inverted = true,
.vsel_reg = BD96801_BUCK2_VSEL_REG,
.vsel_mask = BD96805_BUCK_VSEL_MASK,
.ramp_reg = BD96801_BUCK2_VSEL_REG,
.ramp_mask = BD96801_MASK_RAMP_DELAY,
.ramp_delay_table = &buck_ramp_table[0],
.n_ramp_values = ARRAY_SIZE(buck_ramp_table),
.owner = THIS_MODULE,
},
.irq_desc = {
.irqinfo = (struct bd96801_irqinfo *)&buck2_irqinfo[0],
.num_irqs = ARRAY_SIZE(buck2_irqinfo),
},
.init_ranges = bd96806_buck_init_volts,
.num_ranges = ARRAY_SIZE(bd96806_buck_init_volts),
},
},
.num_regulators = 2,
};
static int initialize_pmic_data(struct platform_device *pdev,
struct bd96801_pmic_data *pdata)
{
struct device *dev = &pdev->dev;
int r, i;
/*
@ -700,7 +1045,7 @@ static int initialize_pmic_data(struct device *dev,
* wish to modify IRQ information independently for each driver
* instance.
*/
for (r = 0; r < BD96801_NUM_REGULATORS; r++) {
for (r = 0; r < pdata->num_regulators; r++) {
const struct bd96801_irqinfo *template;
struct bd96801_irqinfo *new;
int num_infos;
@ -741,8 +1086,7 @@ static int bd96801_rdev_errb_irqs(struct platform_device *pdev,
int i;
void *retp;
static const char * const single_out_errb_irqs[] = {
"bd96801-%s-pvin-err", "bd96801-%s-ovp-err",
"bd96801-%s-uvp-err", "bd96801-%s-shdn-err",
"%s-pvin-err", "%s-ovp-err", "%s-uvp-err", "%s-shdn-err",
};
for (i = 0; i < ARRAY_SIZE(single_out_errb_irqs); i++) {
@ -779,12 +1123,10 @@ static int bd96801_global_errb_irqs(struct platform_device *pdev,
int i, num_irqs;
void *retp;
static const char * const global_errb_irqs[] = {
"bd96801-otp-err", "bd96801-dbist-err", "bd96801-eep-err",
"bd96801-abist-err", "bd96801-prstb-err", "bd96801-drmoserr1",
"bd96801-drmoserr2", "bd96801-slave-err", "bd96801-vref-err",
"bd96801-tsd", "bd96801-uvlo-err", "bd96801-ovlo-err",
"bd96801-osc-err", "bd96801-pon-err", "bd96801-poff-err",
"bd96801-cmd-shdn-err", "bd96801-int-shdn-err"
"otp-err", "dbist-err", "eep-err", "abist-err", "prstb-err",
"drmoserr1", "drmoserr2", "slave-err", "vref-err", "tsd",
"uvlo-err", "ovlo-err", "osc-err", "pon-err", "poff-err",
"cmd-shdn-err", "int-shdn-err"
};
num_irqs = ARRAY_SIZE(global_errb_irqs);
@ -869,6 +1211,7 @@ static int bd96801_probe(struct platform_device *pdev)
{
struct regulator_dev *ldo_errs_rdev_arr[BD96801_NUM_LDOS];
struct regulator_dev *all_rdevs[BD96801_NUM_REGULATORS];
struct bd96801_pmic_data *pdata_template;
struct bd96801_regulator_data *rdesc;
struct regulator_config config = {};
int ldo_errs_arr[BD96801_NUM_LDOS];
@ -881,12 +1224,16 @@ static int bd96801_probe(struct platform_device *pdev)
parent = pdev->dev.parent;
pdata = devm_kmemdup(&pdev->dev, &bd96801_data, sizeof(bd96801_data),
pdata_template = (struct bd96801_pmic_data *)platform_get_device_id(pdev)->driver_data;
if (!pdata_template)
return -ENODEV;
pdata = devm_kmemdup(&pdev->dev, pdata_template, sizeof(bd96801_data),
GFP_KERNEL);
if (!pdata)
return -ENOMEM;
if (initialize_pmic_data(&pdev->dev, pdata))
if (initialize_pmic_data(pdev, pdata))
return -ENOMEM;
pdata->regmap = dev_get_regmap(parent, NULL);
@ -909,11 +1256,11 @@ static int bd96801_probe(struct platform_device *pdev)
use_errb = true;
ret = bd96801_walk_regulator_dt(&pdev->dev, pdata->regmap, rdesc,
BD96801_NUM_REGULATORS);
pdata->num_regulators);
if (ret)
return ret;
for (i = 0; i < ARRAY_SIZE(pdata->regulator_data); i++) {
for (i = 0; i < pdata->num_regulators; i++) {
struct regulator_dev *rdev;
struct bd96801_irq_desc *idesc = &rdesc[i].irq_desc;
int j;
@ -926,6 +1273,7 @@ static int bd96801_probe(struct platform_device *pdev)
rdesc[i].desc.name);
return PTR_ERR(rdev);
}
all_rdevs[i] = rdev;
/*
* LDOs don't have own temperature monitoring. If temperature
@ -956,12 +1304,12 @@ static int bd96801_probe(struct platform_device *pdev)
if (temp_notif_ldos) {
int irq;
struct regulator_irq_desc tw_desc = {
.name = "bd96801-core-thermal",
.name = "core-thermal",
.irq_off_ms = 500,
.map_event = ldo_map_notif,
};
irq = platform_get_irq_byname(pdev, "bd96801-core-thermal");
irq = platform_get_irq_byname(pdev, "core-thermal");
if (irq < 0)
return irq;
@ -975,14 +1323,17 @@ static int bd96801_probe(struct platform_device *pdev)
if (use_errb)
return bd96801_global_errb_irqs(pdev, all_rdevs,
ARRAY_SIZE(all_rdevs));
pdata->num_regulators);
return 0;
}
static const struct platform_device_id bd96801_pmic_id[] = {
{ "bd96801-regulator", },
{ }
{ "bd96801-regulator", (kernel_ulong_t)&bd96801_data },
{ "bd96802-regulator", (kernel_ulong_t)&bd96802_data },
{ "bd96805-regulator", (kernel_ulong_t)&bd96805_data },
{ "bd96806-regulator", (kernel_ulong_t)&bd96806_data },
{ },
};
MODULE_DEVICE_TABLE(platform, bd96801_pmic_id);

View File

@ -133,9 +133,6 @@ struct aat2870_data {
int (*read)(struct aat2870_data *aat2870, u8 addr, u8 *val);
int (*write)(struct aat2870_data *aat2870, u8 addr, u8 val);
int (*update)(struct aat2870_data *aat2870, u8 addr, u8 mask, u8 val);
/* for debugfs */
struct dentry *dentry_root;
};
struct aat2870_subdev_info {

View File

@ -13,6 +13,26 @@
#include <linux/i2c.h>
#include <linux/regmap.h>
/* PMU ID register values; also used as device type */
#define BCM590XX_PMUID_BCM59054 0x54
#define BCM590XX_PMUID_BCM59056 0x56
/* Known chip revision IDs */
#define BCM59054_REV_DIGITAL_A1 1
#define BCM59054_REV_ANALOG_A1 2
#define BCM59056_REV_DIGITAL_A0 1
#define BCM59056_REV_ANALOG_A0 1
#define BCM59056_REV_DIGITAL_B0 2
#define BCM59056_REV_ANALOG_B0 2
/* regmap types */
enum bcm590xx_regmap_type {
BCM590XX_REGMAP_PRI,
BCM590XX_REGMAP_SEC,
};
/* max register address */
#define BCM590XX_MAX_REGISTER_PRI 0xe7
#define BCM590XX_MAX_REGISTER_SEC 0xf0
@ -23,7 +43,13 @@ struct bcm590xx {
struct i2c_client *i2c_sec;
struct regmap *regmap_pri;
struct regmap *regmap_sec;
unsigned int id;
/* PMU ID value; also used as device type */
u8 pmu_id;
/* Chip revision, read from PMUREV reg */
u8 rev_digital;
u8 rev_analog;
};
#endif /* __LINUX_MFD_BCM590XX_H */

View File

@ -2,7 +2,7 @@
/*
* max14577-private.h - Common API for the Maxim 14577/77836 internal sub chip
*
* Copyright (C) 2014 Samsung Electrnoics
* Copyright (C) 2014 Samsung Electronics
* Chanwoo Choi <cw00.choi@samsung.com>
* Krzysztof Kozlowski <krzk@kernel.org>
*/

View File

@ -2,7 +2,7 @@
/*
* max14577.h - Driver for the Maxim 14577/77836
*
* Copyright (C) 2014 Samsung Electrnoics
* Copyright (C) 2014 Samsung Electronics
* Chanwoo Choi <cw00.choi@samsung.com>
* Krzysztof Kozlowski <krzk@kernel.org>
*

View File

@ -2,7 +2,7 @@
/*
* max77686-private.h - Voltage regulator driver for the Maxim 77686/802
*
* Copyright (C) 2012 Samsung Electrnoics
* Copyright (C) 2012 Samsung Electronics
* Chiwoong Byun <woong.byun@samsung.com>
*/

View File

@ -2,7 +2,7 @@
/*
* max77686.h - Driver for the Maxim 77686/802
*
* Copyright (C) 2012 Samsung Electrnoics
* Copyright (C) 2012 Samsung Electronics
* Chiwoong Byun <woong.byun@samsung.com>
*
* This driver is based on max8997.h

View File

@ -2,7 +2,7 @@
/*
* max77693-private.h - Voltage regulator driver for the Maxim 77693
*
* Copyright (C) 2012 Samsung Electrnoics
* Copyright (C) 2012 Samsung Electronics
* SangYoung Son <hello.son@samsung.com>
*
* This program is not provided / owned by Maxim Integrated Products.

View File

@ -2,7 +2,7 @@
/*
* max77693.h - Driver for the Maxim 77693
*
* Copyright (C) 2012 Samsung Electrnoics
* Copyright (C) 2012 Samsung Electronics
* SangYoung Son <hello.son@samsung.com>
*
* This program is not provided / owned by Maxim Integrated Products.

View File

@ -2,7 +2,7 @@
/*
* max8997-private.h - Voltage regulator driver for the Maxim 8997
*
* Copyright (C) 2010 Samsung Electrnoics
* Copyright (C) 2010 Samsung Electronics
* MyungJoo Ham <myungjoo.ham@samsung.com>
*/

View File

@ -2,7 +2,7 @@
/*
* max8997.h - Driver for the Maxim 8997/8966
*
* Copyright (C) 2009-2010 Samsung Electrnoics
* Copyright (C) 2009-2010 Samsung Electronics
* MyungJoo Ham <myungjoo.ham@samsung.com>
*
* This driver is based on max8998.h

View File

@ -2,7 +2,7 @@
/*
* max8998-private.h - Voltage regulator driver for the Maxim 8998
*
* Copyright (C) 2009-2010 Samsung Electrnoics
* Copyright (C) 2009-2010 Samsung Electronics
* Kyungmin Park <kyungmin.park@samsung.com>
* Marek Szyprowski <m.szyprowski@samsung.com>
*/

View File

@ -2,7 +2,7 @@
/*
* max8998.h - Voltage regulator driver for the Maxim 8998
*
* Copyright (C) 2009-2010 Samsung Electrnoics
* Copyright (C) 2009-2010 Samsung Electronics
* Kyungmin Park <kyungmin.park@samsung.com>
* Marek Szyprowski <m.szyprowski@samsung.com>
*/

View File

@ -40,7 +40,9 @@
* INTB status registers are at range 0x5c ... 0x63
*/
#define BD96801_REG_INT_SYS_ERRB1 0x52
#define BD96801_REG_INT_BUCK2_ERRB 0x56
#define BD96801_REG_INT_SYS_INTB 0x5c
#define BD96801_REG_INT_BUCK2_INTB 0x5e
#define BD96801_REG_INT_LDO7_INTB 0x63
/* MASK registers */

View File

@ -0,0 +1,74 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Copyright (C) 2025 ROHM Semiconductors
*
* The digital interface of trhe BD96802 PMIC is a reduced version of the
* BD96801. Hence the BD96801 definitions are used for registers and masks
* while this header only holds the IRQ definitions - mainly to avoid gaps in
* IRQ numbers caused by the lack of some BUCKs / LDOs and their respective
* IRQs.
*/
#ifndef __LINUX_MFD_BD96802_H__
#define __LINUX_MFD_BD96802_H__
/* ERRB IRQs */
enum {
/* Reg 0x52, 0x53, 0x54 - ERRB system IRQs */
BD96802_OTP_ERR_STAT,
BD96802_DBIST_ERR_STAT,
BD96802_EEP_ERR_STAT,
BD96802_ABIST_ERR_STAT,
BD96802_PRSTB_ERR_STAT,
BD96802_DRMOS1_ERR_STAT,
BD96802_DRMOS2_ERR_STAT,
BD96802_SLAVE_ERR_STAT,
BD96802_VREF_ERR_STAT,
BD96802_TSD_ERR_STAT,
BD96802_UVLO_ERR_STAT,
BD96802_OVLO_ERR_STAT,
BD96802_OSC_ERR_STAT,
BD96802_PON_ERR_STAT,
BD96802_POFF_ERR_STAT,
BD96802_CMD_SHDN_ERR_STAT,
BD96802_INT_SHDN_ERR_STAT,
/* Reg 0x55 BUCK1 ERR IRQs */
BD96802_BUCK1_PVIN_ERR_STAT,
BD96802_BUCK1_OVP_ERR_STAT,
BD96802_BUCK1_UVP_ERR_STAT,
BD96802_BUCK1_SHDN_ERR_STAT,
/* Reg 0x56 BUCK2 ERR IRQs */
BD96802_BUCK2_PVIN_ERR_STAT,
BD96802_BUCK2_OVP_ERR_STAT,
BD96802_BUCK2_UVP_ERR_STAT,
BD96802_BUCK2_SHDN_ERR_STAT,
};
/* INTB IRQs */
enum {
/* Reg 0x5c (System INTB) */
BD96802_TW_STAT,
BD96802_WDT_ERR_STAT,
BD96802_I2C_ERR_STAT,
BD96802_CHIP_IF_ERR_STAT,
/* Reg 0x5d (BUCK1 INTB) */
BD96802_BUCK1_OCPH_STAT,
BD96802_BUCK1_OCPL_STAT,
BD96802_BUCK1_OCPN_STAT,
BD96802_BUCK1_OVD_STAT,
BD96802_BUCK1_UVD_STAT,
BD96802_BUCK1_TW_CH_STAT,
/* Reg 0x5e (BUCK2 INTB) */
BD96802_BUCK2_OCPH_STAT,
BD96802_BUCK2_OCPL_STAT,
BD96802_BUCK2_OCPN_STAT,
BD96802_BUCK2_OVD_STAT,
BD96802_BUCK2_UVD_STAT,
BD96802_BUCK2_TW_CH_STAT,
};
#endif

View File

@ -17,6 +17,9 @@ enum rohm_chip_type {
ROHM_CHIP_TYPE_BD71837,
ROHM_CHIP_TYPE_BD71847,
ROHM_CHIP_TYPE_BD96801,
ROHM_CHIP_TYPE_BD96802,
ROHM_CHIP_TYPE_BD96805,
ROHM_CHIP_TYPE_BD96806,
ROHM_CHIP_TYPE_AMOUNT
};

View File

@ -39,6 +39,7 @@ enum sec_device_type {
S5M8767X,
S2DOS05,
S2MPA01,
S2MPG10,
S2MPS11X,
S2MPS13X,
S2MPS14X,
@ -66,15 +67,11 @@ struct sec_pmic_dev {
struct regmap *regmap_pmic;
struct i2c_client *i2c;
unsigned long device_type;
int device_type;
int irq;
struct regmap_irq_chip_data *irq_data;
};
int sec_irq_init(struct sec_pmic_dev *sec_pmic);
void sec_irq_exit(struct sec_pmic_dev *sec_pmic);
int sec_irq_resume(struct sec_pmic_dev *sec_pmic);
struct sec_platform_data {
struct sec_regulator_data *regulators;
struct sec_opmode_data *opmode;

View File

@ -57,6 +57,109 @@ enum s2mpa01_irq {
#define S2MPA01_IRQ_B24_TSD_MASK (1 << 4)
#define S2MPA01_IRQ_B35_TSD_MASK (1 << 5)
enum s2mpg10_irq {
/* PMIC */
S2MPG10_IRQ_PWRONF,
S2MPG10_IRQ_PWRONR,
S2MPG10_IRQ_JIGONBF,
S2MPG10_IRQ_JIGONBR,
S2MPG10_IRQ_ACOKBF,
S2MPG10_IRQ_ACOKBR,
S2MPG10_IRQ_PWRON1S,
S2MPG10_IRQ_MRB,
#define S2MPG10_IRQ_PWRONF_MASK BIT(0)
#define S2MPG10_IRQ_PWRONR_MASK BIT(1)
#define S2MPG10_IRQ_JIGONBF_MASK BIT(2)
#define S2MPG10_IRQ_JIGONBR_MASK BIT(3)
#define S2MPG10_IRQ_ACOKBF_MASK BIT(4)
#define S2MPG10_IRQ_ACOKBR_MASK BIT(5)
#define S2MPG10_IRQ_PWRON1S_MASK BIT(6)
#define S2MPG10_IRQ_MRB_MASK BIT(7)
S2MPG10_IRQ_RTC60S,
S2MPG10_IRQ_RTCA1,
S2MPG10_IRQ_RTCA0,
S2MPG10_IRQ_RTC1S,
S2MPG10_IRQ_WTSR_COLDRST,
S2MPG10_IRQ_WTSR,
S2MPG10_IRQ_WRST,
S2MPG10_IRQ_SMPL,
#define S2MPG10_IRQ_RTC60S_MASK BIT(0)
#define S2MPG10_IRQ_RTCA1_MASK BIT(1)
#define S2MPG10_IRQ_RTCA0_MASK BIT(2)
#define S2MPG10_IRQ_RTC1S_MASK BIT(3)
#define S2MPG10_IRQ_WTSR_COLDRST_MASK BIT(4)
#define S2MPG10_IRQ_WTSR_MASK BIT(5)
#define S2MPG10_IRQ_WRST_MASK BIT(6)
#define S2MPG10_IRQ_SMPL_MASK BIT(7)
S2MPG10_IRQ_120C,
S2MPG10_IRQ_140C,
S2MPG10_IRQ_TSD,
S2MPG10_IRQ_PIF_TIMEOUT1,
S2MPG10_IRQ_PIF_TIMEOUT2,
S2MPG10_IRQ_SPD_PARITY_ERR,
S2MPG10_IRQ_SPD_ABNORMAL_STOP,
S2MPG10_IRQ_PMETER_OVERF,
#define S2MPG10_IRQ_INT120C_MASK BIT(0)
#define S2MPG10_IRQ_INT140C_MASK BIT(1)
#define S2MPG10_IRQ_TSD_MASK BIT(2)
#define S2MPG10_IRQ_PIF_TIMEOUT1_MASK BIT(3)
#define S2MPG10_IRQ_PIF_TIMEOUT2_MASK BIT(4)
#define S2MPG10_IRQ_SPD_PARITY_ERR_MASK BIT(5)
#define S2MPG10_IRQ_SPD_ABNORMAL_STOP_MASK BIT(6)
#define S2MPG10_IRQ_PMETER_OVERF_MASK BIT(7)
S2MPG10_IRQ_OCP_B1M,
S2MPG10_IRQ_OCP_B2M,
S2MPG10_IRQ_OCP_B3M,
S2MPG10_IRQ_OCP_B4M,
S2MPG10_IRQ_OCP_B5M,
S2MPG10_IRQ_OCP_B6M,
S2MPG10_IRQ_OCP_B7M,
S2MPG10_IRQ_OCP_B8M,
#define S2MPG10_IRQ_OCP_B1M_MASK BIT(0)
#define S2MPG10_IRQ_OCP_B2M_MASK BIT(1)
#define S2MPG10_IRQ_OCP_B3M_MASK BIT(2)
#define S2MPG10_IRQ_OCP_B4M_MASK BIT(3)
#define S2MPG10_IRQ_OCP_B5M_MASK BIT(4)
#define S2MPG10_IRQ_OCP_B6M_MASK BIT(5)
#define S2MPG10_IRQ_OCP_B7M_MASK BIT(6)
#define S2MPG10_IRQ_OCP_B8M_MASK BIT(7)
S2MPG10_IRQ_OCP_B9M,
S2MPG10_IRQ_OCP_B10M,
S2MPG10_IRQ_WLWP_ACC,
S2MPG10_IRQ_SMPL_TIMEOUT,
S2MPG10_IRQ_WTSR_TIMEOUT,
S2MPG10_IRQ_SPD_SRP_PKT_RST,
#define S2MPG10_IRQ_OCP_B9M_MASK BIT(0)
#define S2MPG10_IRQ_OCP_B10M_MASK BIT(1)
#define S2MPG10_IRQ_WLWP_ACC_MASK BIT(2)
#define S2MPG10_IRQ_SMPL_TIMEOUT_MASK BIT(5)
#define S2MPG10_IRQ_WTSR_TIMEOUT_MASK BIT(6)
#define S2MPG10_IRQ_SPD_SRP_PKT_RST_MASK BIT(7)
S2MPG10_IRQ_PWR_WARN_CH0,
S2MPG10_IRQ_PWR_WARN_CH1,
S2MPG10_IRQ_PWR_WARN_CH2,
S2MPG10_IRQ_PWR_WARN_CH3,
S2MPG10_IRQ_PWR_WARN_CH4,
S2MPG10_IRQ_PWR_WARN_CH5,
S2MPG10_IRQ_PWR_WARN_CH6,
S2MPG10_IRQ_PWR_WARN_CH7,
#define S2MPG10_IRQ_PWR_WARN_CH0_MASK BIT(0)
#define S2MPG10_IRQ_PWR_WARN_CH1_MASK BIT(1)
#define S2MPG10_IRQ_PWR_WARN_CH2_MASK BIT(2)
#define S2MPG10_IRQ_PWR_WARN_CH3_MASK BIT(3)
#define S2MPG10_IRQ_PWR_WARN_CH4_MASK BIT(4)
#define S2MPG10_IRQ_PWR_WARN_CH5_MASK BIT(5)
#define S2MPG10_IRQ_PWR_WARN_CH6_MASK BIT(6)
#define S2MPG10_IRQ_PWR_WARN_CH7_MASK BIT(7)
S2MPG10_IRQ_NR,
};
enum s2mps11_irq {
S2MPS11_IRQ_PWRONF,
S2MPS11_IRQ_PWRONR,

View File

@ -72,6 +72,37 @@ enum s2mps_rtc_reg {
S2MPS_RTC_REG_MAX,
};
enum s2mpg10_rtc_reg {
S2MPG10_RTC_CTRL,
S2MPG10_RTC_UPDATE,
S2MPG10_RTC_SMPL,
S2MPG10_RTC_WTSR,
S2MPG10_RTC_CAP_SEL,
S2MPG10_RTC_MSEC,
S2MPG10_RTC_SEC,
S2MPG10_RTC_MIN,
S2MPG10_RTC_HOUR,
S2MPG10_RTC_WEEK,
S2MPG10_RTC_DAY,
S2MPG10_RTC_MON,
S2MPG10_RTC_YEAR,
S2MPG10_RTC_A0SEC,
S2MPG10_RTC_A0MIN,
S2MPG10_RTC_A0HOUR,
S2MPG10_RTC_A0WEEK,
S2MPG10_RTC_A0DAY,
S2MPG10_RTC_A0MON,
S2MPG10_RTC_A0YEAR,
S2MPG10_RTC_A1SEC,
S2MPG10_RTC_A1MIN,
S2MPG10_RTC_A1HOUR,
S2MPG10_RTC_A1WEEK,
S2MPG10_RTC_A1DAY,
S2MPG10_RTC_A1MON,
S2MPG10_RTC_A1YEAR,
S2MPG10_RTC_OSC_CTRL,
};
#define RTC_I2C_ADDR (0x0C >> 1)
#define HOUR_12 (1 << 7)
@ -124,10 +155,16 @@ enum s2mps_rtc_reg {
#define ALARM_ENABLE_SHIFT 7
#define ALARM_ENABLE_MASK (1 << ALARM_ENABLE_SHIFT)
/* WTSR & SMPL registers */
#define SMPL_ENABLE_SHIFT 7
#define SMPL_ENABLE_MASK (1 << SMPL_ENABLE_SHIFT)
#define WTSR_ENABLE_SHIFT 6
#define WTSR_ENABLE_MASK (1 << WTSR_ENABLE_SHIFT)
#define S2MPG10_WTSR_COLDTIMER GENMASK(6, 5)
#define S2MPG10_WTSR_COLDRST BIT(4)
#define S2MPG10_WTSR_WTSRT GENMASK(3, 1)
#define S2MPG10_WTSR_WTSR_EN BIT(0)
#endif /* __LINUX_MFD_SEC_RTC_H */

View File

@ -0,0 +1,454 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Copyright 2015 Samsung Electronics
* Copyright 2020 Google Inc
* Copyright 2025 Linaro Ltd.
*/
#ifndef __LINUX_MFD_S2MPG10_H
#define __LINUX_MFD_S2MPG10_H
/* Common registers (type 0x000) */
enum s2mpg10_common_reg {
S2MPG10_COMMON_CHIPID,
S2MPG10_COMMON_INT,
S2MPG10_COMMON_INT_MASK,
S2MPG10_COMMON_SPD_CTRL1 = 0x0a,
S2MPG10_COMMON_SPD_CTRL2,
S2MPG10_COMMON_SPD_CTRL3,
S2MPG10_COMMON_MON1SEL = 0x1a,
S2MPG10_COMMON_MON2SEL,
S2MPG10_COMMON_MONR,
S2MPG10_COMMON_DEBUG_CTRL1,
S2MPG10_COMMON_DEBUG_CTRL2,
S2MPG10_COMMON_DEBUG_CTRL3,
S2MPG10_COMMON_DEBUG_CTRL4,
S2MPG10_COMMON_DEBUG_CTRL5,
S2MPG10_COMMON_DEBUG_CTRL6,
S2MPG10_COMMON_DEBUG_CTRL7,
S2MPG10_COMMON_DEBUG_CTRL8,
S2MPG10_COMMON_TEST_MODE1,
S2MPG10_COMMON_TEST_MODE2,
S2MPG10_COMMON_SPD_DEBUG1,
S2MPG10_COMMON_SPD_DEBUG2,
S2MPG10_COMMON_SPD_DEBUG3,
S2MPG10_COMMON_SPD_DEBUG4,
};
/* For S2MPG10_COMMON_INT and S2MPG10_COMMON_INT_MASK */
#define S2MPG10_COMMON_INT_SRC GENMASK(7, 0)
#define S2MPG10_COMMON_INT_SRC_PMIC BIT(0)
/* PMIC registers (type 0x100) */
enum s2mpg10_pmic_reg {
S2MPG10_PMIC_INT1,
S2MPG10_PMIC_INT2,
S2MPG10_PMIC_INT3,
S2MPG10_PMIC_INT4,
S2MPG10_PMIC_INT5,
S2MPG10_PMIC_INT6,
S2MPG10_PMIC_INT1M,
S2MPG10_PMIC_INT2M,
S2MPG10_PMIC_INT3M,
S2MPG10_PMIC_INT4M,
S2MPG10_PMIC_INT5M,
S2MPG10_PMIC_INT6M,
S2MPG10_PMIC_STATUS1,
S2MPG10_PMIC_STATUS2,
S2MPG10_PMIC_PWRONSRC,
S2MPG10_PMIC_OFFSRC,
S2MPG10_PMIC_BU_CHG,
S2MPG10_PMIC_RTCBUF,
S2MPG10_PMIC_COMMON_CTRL1,
S2MPG10_PMIC_COMMON_CTRL2,
S2MPG10_PMIC_COMMON_CTRL3,
S2MPG10_PMIC_COMMON_CTRL4,
S2MPG10_PMIC_SMPL_WARN_CTRL,
S2MPG10_PMIC_MIMICKING_CTRL,
S2MPG10_PMIC_B1M_CTRL,
S2MPG10_PMIC_B1M_OUT1,
S2MPG10_PMIC_B1M_OUT2,
S2MPG10_PMIC_B2M_CTRL,
S2MPG10_PMIC_B2M_OUT1,
S2MPG10_PMIC_B2M_OUT2,
S2MPG10_PMIC_B3M_CTRL,
S2MPG10_PMIC_B3M_OUT1,
S2MPG10_PMIC_B3M_OUT2,
S2MPG10_PMIC_B4M_CTRL,
S2MPG10_PMIC_B4M_OUT1,
S2MPG10_PMIC_B4M_OUT2,
S2MPG10_PMIC_B5M_CTRL,
S2MPG10_PMIC_B5M_OUT1,
S2MPG10_PMIC_B5M_OUT2,
S2MPG10_PMIC_B6M_CTRL,
S2MPG10_PMIC_B6M_OUT1,
S2MPG10_PMIC_B6M_OUT2,
S2MPG10_PMIC_B7M_CTRL,
S2MPG10_PMIC_B7M_OUT1,
S2MPG10_PMIC_B7M_OUT2,
S2MPG10_PMIC_B8M_CTRL,
S2MPG10_PMIC_B8M_OUT1,
S2MPG10_PMIC_B8M_OUT2,
S2MPG10_PMIC_B9M_CTRL,
S2MPG10_PMIC_B9M_OUT1,
S2MPG10_PMIC_B9M_OUT2,
S2MPG10_PMIC_B10M_CTRL,
S2MPG10_PMIC_B10M_OUT1,
S2MPG10_PMIC_B10M_OUT2,
S2MPG10_PMIC_BUCK1M_USONIC,
S2MPG10_PMIC_BUCK2M_USONIC,
S2MPG10_PMIC_BUCK3M_USONIC,
S2MPG10_PMIC_BUCK4M_USONIC,
S2MPG10_PMIC_BUCK5M_USONIC,
S2MPG10_PMIC_BUCK6M_USONIC,
S2MPG10_PMIC_BUCK7M_USONIC,
S2MPG10_PMIC_BUCK8M_USONIC,
S2MPG10_PMIC_BUCK9M_USONIC,
S2MPG10_PMIC_BUCK10M_USONIC,
S2MPG10_PMIC_L1M_CTRL,
S2MPG10_PMIC_L2M_CTRL,
S2MPG10_PMIC_L3M_CTRL,
S2MPG10_PMIC_L4M_CTRL,
S2MPG10_PMIC_L5M_CTRL,
S2MPG10_PMIC_L6M_CTRL,
S2MPG10_PMIC_L7M_CTRL,
S2MPG10_PMIC_L8M_CTRL,
S2MPG10_PMIC_L9M_CTRL,
S2MPG10_PMIC_L10M_CTRL,
S2MPG10_PMIC_L11M_CTRL1,
S2MPG10_PMIC_L11M_CTRL2,
S2MPG10_PMIC_L12M_CTRL1,
S2MPG10_PMIC_L12M_CTRL2,
S2MPG10_PMIC_L13M_CTRL1,
S2MPG10_PMIC_L13M_CTRL2,
S2MPG10_PMIC_L14M_CTRL,
S2MPG10_PMIC_L15M_CTRL1,
S2MPG10_PMIC_L15M_CTRL2,
S2MPG10_PMIC_L16M_CTRL,
S2MPG10_PMIC_L17M_CTRL,
S2MPG10_PMIC_L18M_CTRL,
S2MPG10_PMIC_L19M_CTRL,
S2MPG10_PMIC_L20M_CTRL,
S2MPG10_PMIC_L21M_CTRL,
S2MPG10_PMIC_L22M_CTRL,
S2MPG10_PMIC_L23M_CTRL,
S2MPG10_PMIC_L24M_CTRL,
S2MPG10_PMIC_L25M_CTRL,
S2MPG10_PMIC_L26M_CTRL,
S2MPG10_PMIC_L27M_CTRL,
S2MPG10_PMIC_L28M_CTRL,
S2MPG10_PMIC_L29M_CTRL,
S2MPG10_PMIC_L30M_CTRL,
S2MPG10_PMIC_L31M_CTRL,
S2MPG10_PMIC_LDO_CTRL1,
S2MPG10_PMIC_LDO_CTRL2,
S2MPG10_PMIC_LDO_DSCH1,
S2MPG10_PMIC_LDO_DSCH2,
S2MPG10_PMIC_LDO_DSCH3,
S2MPG10_PMIC_LDO_DSCH4,
S2MPG10_PMIC_LDO_BUCK7M_HLIMIT,
S2MPG10_PMIC_LDO_BUCK7M_LLIMIT,
S2MPG10_PMIC_LDO_LDO21M_HLIMIT,
S2MPG10_PMIC_LDO_LDO21M_LLIMIT,
S2MPG10_PMIC_LDO_LDO11M_HLIMIT,
S2MPG10_PMIC_DVS_RAMP1,
S2MPG10_PMIC_DVS_RAMP2,
S2MPG10_PMIC_DVS_RAMP3,
S2MPG10_PMIC_DVS_RAMP4,
S2MPG10_PMIC_DVS_RAMP5,
S2MPG10_PMIC_DVS_RAMP6,
S2MPG10_PMIC_DVS_SYNC_CTRL1,
S2MPG10_PMIC_DVS_SYNC_CTRL2,
S2MPG10_PMIC_DVS_SYNC_CTRL3,
S2MPG10_PMIC_DVS_SYNC_CTRL4,
S2MPG10_PMIC_DVS_SYNC_CTRL5,
S2MPG10_PMIC_DVS_SYNC_CTRL6,
S2MPG10_PMIC_OFF_CTRL1,
S2MPG10_PMIC_OFF_CTRL2,
S2MPG10_PMIC_OFF_CTRL3,
S2MPG10_PMIC_OFF_CTRL4,
S2MPG10_PMIC_SEQ_CTRL1,
S2MPG10_PMIC_SEQ_CTRL2,
S2MPG10_PMIC_SEQ_CTRL3,
S2MPG10_PMIC_SEQ_CTRL4,
S2MPG10_PMIC_SEQ_CTRL5,
S2MPG10_PMIC_SEQ_CTRL6,
S2MPG10_PMIC_SEQ_CTRL7,
S2MPG10_PMIC_SEQ_CTRL8,
S2MPG10_PMIC_SEQ_CTRL9,
S2MPG10_PMIC_SEQ_CTRL10,
S2MPG10_PMIC_SEQ_CTRL11,
S2MPG10_PMIC_SEQ_CTRL12,
S2MPG10_PMIC_SEQ_CTRL13,
S2MPG10_PMIC_SEQ_CTRL14,
S2MPG10_PMIC_SEQ_CTRL15,
S2MPG10_PMIC_SEQ_CTRL16,
S2MPG10_PMIC_SEQ_CTRL17,
S2MPG10_PMIC_SEQ_CTRL18,
S2MPG10_PMIC_SEQ_CTRL19,
S2MPG10_PMIC_SEQ_CTRL20,
S2MPG10_PMIC_SEQ_CTRL21,
S2MPG10_PMIC_SEQ_CTRL22,
S2MPG10_PMIC_SEQ_CTRL23,
S2MPG10_PMIC_SEQ_CTRL24,
S2MPG10_PMIC_SEQ_CTRL25,
S2MPG10_PMIC_SEQ_CTRL26,
S2MPG10_PMIC_SEQ_CTRL27,
S2MPG10_PMIC_SEQ_CTRL28,
S2MPG10_PMIC_SEQ_CTRL29,
S2MPG10_PMIC_SEQ_CTRL30,
S2MPG10_PMIC_SEQ_CTRL31,
S2MPG10_PMIC_SEQ_CTRL32,
S2MPG10_PMIC_SEQ_CTRL33,
S2MPG10_PMIC_SEQ_CTRL34,
S2MPG10_PMIC_SEQ_CTRL35,
S2MPG10_PMIC_OFF_SEQ_CTRL1,
S2MPG10_PMIC_OFF_SEQ_CTRL2,
S2MPG10_PMIC_OFF_SEQ_CTRL3,
S2MPG10_PMIC_OFF_SEQ_CTRL4,
S2MPG10_PMIC_OFF_SEQ_CTRL5,
S2MPG10_PMIC_OFF_SEQ_CTRL6,
S2MPG10_PMIC_OFF_SEQ_CTRL7,
S2MPG10_PMIC_OFF_SEQ_CTRL8,
S2MPG10_PMIC_OFF_SEQ_CTRL9,
S2MPG10_PMIC_OFF_SEQ_CTRL10,
S2MPG10_PMIC_OFF_SEQ_CTRL11,
S2MPG10_PMIC_OFF_SEQ_CTRL12,
S2MPG10_PMIC_OFF_SEQ_CTRL13,
S2MPG10_PMIC_OFF_SEQ_CTRL14,
S2MPG10_PMIC_OFF_SEQ_CTRL15,
S2MPG10_PMIC_OFF_SEQ_CTRL16,
S2MPG10_PMIC_OFF_SEQ_CTRL17,
S2MPG10_PMIC_OFF_SEQ_CTRL18,
S2MPG10_PMIC_PCTRLSEL1,
S2MPG10_PMIC_PCTRLSEL2,
S2MPG10_PMIC_PCTRLSEL3,
S2MPG10_PMIC_PCTRLSEL4,
S2MPG10_PMIC_PCTRLSEL5,
S2MPG10_PMIC_PCTRLSEL6,
S2MPG10_PMIC_PCTRLSEL7,
S2MPG10_PMIC_PCTRLSEL8,
S2MPG10_PMIC_PCTRLSEL9,
S2MPG10_PMIC_PCTRLSEL10,
S2MPG10_PMIC_PCTRLSEL11,
S2MPG10_PMIC_PCTRLSEL12,
S2MPG10_PMIC_PCTRLSEL13,
S2MPG10_PMIC_DCTRLSEL1,
S2MPG10_PMIC_DCTRLSEL2,
S2MPG10_PMIC_DCTRLSEL3,
S2MPG10_PMIC_DCTRLSEL4,
S2MPG10_PMIC_DCTRLSEL5,
S2MPG10_PMIC_DCTRLSEL6,
S2MPG10_PMIC_DCTRLSEL7,
S2MPG10_PMIC_GPIO_CTRL1,
S2MPG10_PMIC_GPIO_CTRL2,
S2MPG10_PMIC_GPIO_CTRL3,
S2MPG10_PMIC_GPIO_CTRL4,
S2MPG10_PMIC_GPIO_CTRL5,
S2MPG10_PMIC_GPIO_CTRL6,
S2MPG10_PMIC_GPIO_CTRL7,
S2MPG10_PMIC_B2M_OCP_WARN,
S2MPG10_PMIC_B2M_OCP_WARN_X,
S2MPG10_PMIC_B2M_OCP_WARN_Y,
S2MPG10_PMIC_B2M_OCP_WARN_Z,
S2MPG10_PMIC_B3M_OCP_WARN,
S2MPG10_PMIC_B3M_OCP_WARN_X,
S2MPG10_PMIC_B3M_OCP_WARN_Y,
S2MPG10_PMIC_B3M_OCP_WARN_Z,
S2MPG10_PMIC_B10M_OCP_WARN,
S2MPG10_PMIC_B10M_OCP_WARN_X,
S2MPG10_PMIC_B10M_OCP_WARN_Y,
S2MPG10_PMIC_B10M_OCP_WARN_Z,
S2MPG10_PMIC_B2M_SOFT_OCP_WARN,
S2MPG10_PMIC_B2M_SOFT_OCP_WARN_X,
S2MPG10_PMIC_B2M_SOFT_OCP_WARN_Y,
S2MPG10_PMIC_B2M_SOFT_OCP_WARN_Z,
S2MPG10_PMIC_B3M_SOFT_OCP_WARN,
S2MPG10_PMIC_B3M_SOFT_OCP_WARN_X,
S2MPG10_PMIC_B3M_SOFT_OCP_WARN_Y,
S2MPG10_PMIC_B3M_SOFT_OCP_WARN_Z,
S2MPG10_PMIC_B10M_SOFT_OCP_WARN,
S2MPG10_PMIC_B10M_SOFT_OCP_WARN_X,
S2MPG10_PMIC_B10M_SOFT_OCP_WARN_Y,
S2MPG10_PMIC_B10M_SOFT_OCP_WARN_Z,
S2MPG10_PMIC_BUCK_OCP_EN1,
S2MPG10_PMIC_BUCK_OCP_EN2,
S2MPG10_PMIC_BUCK_OCP_PD_EN1,
S2MPG10_PMIC_BUCK_OCP_PD_EN2,
S2MPG10_PMIC_BUCK_OCP_CTRL1,
S2MPG10_PMIC_BUCK_OCP_CTRL2,
S2MPG10_PMIC_BUCK_OCP_CTRL3,
S2MPG10_PMIC_BUCK_OCP_CTRL4,
S2MPG10_PMIC_BUCK_OCP_CTRL5,
S2MPG10_PMIC_PIF_CTRL,
S2MPG10_PMIC_BUCK_HR_MODE1,
S2MPG10_PMIC_BUCK_HR_MODE2,
S2MPG10_PMIC_FAULTOUT_CTRL,
S2MPG10_PMIC_LDO_SENSE1,
S2MPG10_PMIC_LDO_SENSE2,
S2MPG10_PMIC_LDO_SENSE3,
S2MPG10_PMIC_LDO_SENSE4,
};
/* Meter registers (type 0xa00) */
enum s2mpg10_meter_reg {
S2MPG10_METER_CTRL1,
S2MPG10_METER_CTRL2,
S2MPG10_METER_CTRL3,
S2MPG10_METER_CTRL4,
S2MPG10_METER_BUCKEN1,
S2MPG10_METER_BUCKEN2,
S2MPG10_METER_MUXSEL0,
S2MPG10_METER_MUXSEL1,
S2MPG10_METER_MUXSEL2,
S2MPG10_METER_MUXSEL3,
S2MPG10_METER_MUXSEL4,
S2MPG10_METER_MUXSEL5,
S2MPG10_METER_MUXSEL6,
S2MPG10_METER_MUXSEL7,
S2MPG10_METER_LPF_C0_0,
S2MPG10_METER_LPF_C0_1,
S2MPG10_METER_LPF_C0_2,
S2MPG10_METER_LPF_C0_3,
S2MPG10_METER_LPF_C0_4,
S2MPG10_METER_LPF_C0_5,
S2MPG10_METER_LPF_C0_6,
S2MPG10_METER_LPF_C0_7,
S2MPG10_METER_PWR_WARN0,
S2MPG10_METER_PWR_WARN1,
S2MPG10_METER_PWR_WARN2,
S2MPG10_METER_PWR_WARN3,
S2MPG10_METER_PWR_WARN4,
S2MPG10_METER_PWR_WARN5,
S2MPG10_METER_PWR_WARN6,
S2MPG10_METER_PWR_WARN7,
S2MPG10_METER_PWR_HYS1,
S2MPG10_METER_PWR_HYS2,
S2MPG10_METER_PWR_HYS3,
S2MPG10_METER_PWR_HYS4,
S2MPG10_METER_ACC_DATA_CH0_1 = 0x40,
S2MPG10_METER_ACC_DATA_CH0_2,
S2MPG10_METER_ACC_DATA_CH0_3,
S2MPG10_METER_ACC_DATA_CH0_4,
S2MPG10_METER_ACC_DATA_CH0_5,
S2MPG10_METER_ACC_DATA_CH0_6,
S2MPG10_METER_ACC_DATA_CH1_1,
S2MPG10_METER_ACC_DATA_CH1_2,
S2MPG10_METER_ACC_DATA_CH1_3,
S2MPG10_METER_ACC_DATA_CH1_4,
S2MPG10_METER_ACC_DATA_CH1_5,
S2MPG10_METER_ACC_DATA_CH1_6,
S2MPG10_METER_ACC_DATA_CH2_1,
S2MPG10_METER_ACC_DATA_CH2_2,
S2MPG10_METER_ACC_DATA_CH2_3,
S2MPG10_METER_ACC_DATA_CH2_4,
S2MPG10_METER_ACC_DATA_CH2_5,
S2MPG10_METER_ACC_DATA_CH2_6,
S2MPG10_METER_ACC_DATA_CH3_1,
S2MPG10_METER_ACC_DATA_CH3_2,
S2MPG10_METER_ACC_DATA_CH3_3,
S2MPG10_METER_ACC_DATA_CH3_4,
S2MPG10_METER_ACC_DATA_CH3_5,
S2MPG10_METER_ACC_DATA_CH3_6,
S2MPG10_METER_ACC_DATA_CH4_1,
S2MPG10_METER_ACC_DATA_CH4_2,
S2MPG10_METER_ACC_DATA_CH4_3,
S2MPG10_METER_ACC_DATA_CH4_4,
S2MPG10_METER_ACC_DATA_CH4_5,
S2MPG10_METER_ACC_DATA_CH4_6,
S2MPG10_METER_ACC_DATA_CH5_1,
S2MPG10_METER_ACC_DATA_CH5_2,
S2MPG10_METER_ACC_DATA_CH5_3,
S2MPG10_METER_ACC_DATA_CH5_4,
S2MPG10_METER_ACC_DATA_CH5_5,
S2MPG10_METER_ACC_DATA_CH5_6,
S2MPG10_METER_ACC_DATA_CH6_1,
S2MPG10_METER_ACC_DATA_CH6_2,
S2MPG10_METER_ACC_DATA_CH6_3,
S2MPG10_METER_ACC_DATA_CH6_4,
S2MPG10_METER_ACC_DATA_CH6_5,
S2MPG10_METER_ACC_DATA_CH6_6,
S2MPG10_METER_ACC_DATA_CH7_1,
S2MPG10_METER_ACC_DATA_CH7_2,
S2MPG10_METER_ACC_DATA_CH7_3,
S2MPG10_METER_ACC_DATA_CH7_4,
S2MPG10_METER_ACC_DATA_CH7_5,
S2MPG10_METER_ACC_DATA_CH7_6,
S2MPG10_METER_ACC_COUNT_1,
S2MPG10_METER_ACC_COUNT_2,
S2MPG10_METER_ACC_COUNT_3,
S2MPG10_METER_LPF_DATA_CH0_1,
S2MPG10_METER_LPF_DATA_CH0_2,
S2MPG10_METER_LPF_DATA_CH0_3,
S2MPG10_METER_LPF_DATA_CH1_1,
S2MPG10_METER_LPF_DATA_CH1_2,
S2MPG10_METER_LPF_DATA_CH1_3,
S2MPG10_METER_LPF_DATA_CH2_1,
S2MPG10_METER_LPF_DATA_CH2_2,
S2MPG10_METER_LPF_DATA_CH2_3,
S2MPG10_METER_LPF_DATA_CH3_1,
S2MPG10_METER_LPF_DATA_CH3_2,
S2MPG10_METER_LPF_DATA_CH3_3,
S2MPG10_METER_LPF_DATA_CH4_1,
S2MPG10_METER_LPF_DATA_CH4_2,
S2MPG10_METER_LPF_DATA_CH4_3,
S2MPG10_METER_LPF_DATA_CH5_1,
S2MPG10_METER_LPF_DATA_CH5_2,
S2MPG10_METER_LPF_DATA_CH5_3,
S2MPG10_METER_LPF_DATA_CH6_1,
S2MPG10_METER_LPF_DATA_CH6_2,
S2MPG10_METER_LPF_DATA_CH6_3,
S2MPG10_METER_LPF_DATA_CH7_1,
S2MPG10_METER_LPF_DATA_CH7_2,
S2MPG10_METER_LPF_DATA_CH7_3,
S2MPG10_METER_DSM_TRIM_OFFSET = 0xee,
S2MPG10_METER_BUCK_METER_TRIM3 = 0xf1,
};
/* S2MPG10 regulator IDs */
enum s2mpg10_regulators {
S2MPG10_LDO1,
S2MPG10_LDO2,
S2MPG10_LDO3,
S2MPG10_LDO4,
S2MPG10_LDO5,
S2MPG10_LDO6,
S2MPG10_LDO7,
S2MPG10_LDO8,
S2MPG10_LDO9,
S2MPG10_LDO10,
S2MPG10_LDO11,
S2MPG10_LDO12,
S2MPG10_LDO13,
S2MPG10_LDO14,
S2MPG10_LDO15,
S2MPG10_LDO16,
S2MPG10_LDO17,
S2MPG10_LDO18,
S2MPG10_LDO19,
S2MPG10_LDO20,
S2MPG10_LDO21,
S2MPG10_LDO22,
S2MPG10_LDO23,
S2MPG10_LDO24,
S2MPG10_LDO25,
S2MPG10_LDO26,
S2MPG10_LDO27,
S2MPG10_LDO28,
S2MPG10_LDO29,
S2MPG10_LDO30,
S2MPG10_LDO31,
S2MPG10_BUCK1,
S2MPG10_BUCK2,
S2MPG10_BUCK3,
S2MPG10_BUCK4,
S2MPG10_BUCK5,
S2MPG10_BUCK6,
S2MPG10_BUCK7,
S2MPG10_BUCK8,
S2MPG10_BUCK9,
S2MPG10_BUCK10,
S2MPG10_REGULATOR_MAX,
};
#endif /* __LINUX_MFD_S2MPG10_H */

View File

@ -17,20 +17,30 @@
#define STM32_LPTIM_IER 0x08 /* Interrupt Enable Reg */
#define STM32_LPTIM_CFGR 0x0C /* Configuration Reg */
#define STM32_LPTIM_CR 0x10 /* Control Reg */
#define STM32_LPTIM_CMP 0x14 /* Compare Reg */
#define STM32_LPTIM_CMP 0x14 /* Compare Reg (MP25 CCR1) */
#define STM32_LPTIM_ARR 0x18 /* Autoreload Reg */
#define STM32_LPTIM_CNT 0x1C /* Counter Reg */
#define STM32_LPTIM_CCMR1 0x2C /* Capture/Compare Mode MP25 */
#define STM32_LPTIM_CCR2 0x34 /* Compare Reg2 MP25 */
#define STM32_LPTIM_HWCFGR2 0x3EC /* Hardware configuration register 2 - MP25 */
#define STM32_LPTIM_HWCFGR1 0x3F0 /* Hardware configuration register 1 - MP15 */
#define STM32_LPTIM_VERR 0x3F4 /* Version identification register - MP15 */
/* STM32_LPTIM_ISR - bit fields */
#define STM32_LPTIM_DIEROK_ARROK (BIT(24) | BIT(4)) /* MP25 */
#define STM32_LPTIM_CMP2_ARROK (BIT(19) | BIT(4))
#define STM32_LPTIM_CMPOK_ARROK GENMASK(4, 3)
#define STM32_LPTIM_ARROK BIT(4)
#define STM32_LPTIM_CMPOK BIT(3)
/* STM32_LPTIM_ICR - bit fields */
#define STM32_LPTIM_ARRMCF BIT(1)
#define STM32_LPTIM_DIEROKCF_ARROKCF (BIT(24) | BIT(4)) /* MP25 */
#define STM32_LPTIM_CMP2OKCF_ARROKCF (BIT(19) | BIT(4))
#define STM32_LPTIM_CMPOKCF_ARROKCF GENMASK(4, 3)
#define STM32_LPTIM_ARRMCF BIT(1)
/* STM32_LPTIM_IER - bit flieds */
/* STM32_LPTIM_IER - bit fields */
#define STM32_LPTIM_ARRMIE BIT(1)
/* STM32_LPTIM_CR - bit fields */
@ -53,16 +63,37 @@
/* STM32_LPTIM_ARR */
#define STM32_LPTIM_MAX_ARR 0xFFFF
/* STM32_LPTIM_CCMR1 */
#define STM32_LPTIM_CC2P GENMASK(19, 18)
#define STM32_LPTIM_CC2E BIT(17)
#define STM32_LPTIM_CC2SEL BIT(16)
#define STM32_LPTIM_CC1P GENMASK(3, 2)
#define STM32_LPTIM_CC1E BIT(1)
#define STM32_LPTIM_CC1SEL BIT(0)
/* STM32_LPTIM_HWCFGR1 */
#define STM32_LPTIM_HWCFGR1_ENCODER BIT(16)
/* STM32_LPTIM_HWCFGR2 */
#define STM32_LPTIM_HWCFGR2_CHAN_NUM GENMASK(3, 0)
/* STM32_LPTIM_VERR */
#define STM32_LPTIM_VERR_23 0x23 /* STM32MP25 */
/**
* struct stm32_lptimer - STM32 Low-Power Timer data assigned by parent device
* @clk: clock reference for this instance
* @regmap: register map reference for this instance
* @has_encoder: indicates this Low-Power Timer supports encoder mode
* @num_cc_chans: indicates the number of capture/compare channels
* @version: indicates the major and minor revision of the controller
*/
struct stm32_lptimer {
struct clk *clk;
struct regmap *regmap;
bool has_encoder;
unsigned int num_cc_chans;
u32 version;
};
#endif

View File

@ -12,9 +12,6 @@ extern int sm501_unit_power(struct device *dev,
extern unsigned long sm501_set_clock(struct device *dev,
int clksrc, unsigned long freq);
extern unsigned long sm501_find_clock(struct device *dev,
int clksrc, unsigned long req_freq);
/* sm501_misc_control
*
* Modify the SM501's MISC_CONTROL register