MFD for v7.4

- New Support & Features
   - Cirrus Logic CS42L43: Add support for the CS42L44 variant
   - Khadas MCU: Add support for the VIM4 MCU variant along with per-variant fan duty-cycle
     levels and optional fan supply regulator support
   - Maxim MAX77705: Add support for the PASS2 hardware revision
   - MediaTek MT6397: Add AUXADC sub-device support for MT6397
   - Motorola CPCAP: Support per-board sub-device compositions and add the Tegra20 Mot
     composition
   - ROHM BD73800: Add support for the BD73800 PMIC core, regulator, RTC, clock gate, and
     GPIO sub-devices
   - TI LM3533: Add VIN regulator supply support, configure initial backlight mapping mode
     from Device Tree, and implement the `backlight_scale` property
   - X-Powers AC200: Add support for the AC200 I2C mixed-signal companion IC
 
 - Improvements & Fixes
   - Cirrus Logic CS42L43: Synchronize SoundWire enumeration work in `remove()` before
     devres cleanup begins
   - Dialog DA903x: Manage IRQ work cancellation and sub-device removal via devres to
     prevent use-after-free during teardown
   - Dialog DA9150: Balance `enable_irq_wake()` with `disable_irq_wake()` during probe
     failure and driver removal
   - Intel LPSS: Add DMI quirks for Dell Latitude 5285 and 7275 to ignore ACPI resource
     conflicts on the I2C4 controller
   - Intel Quark I2C/GPIO: Manage the fixed-rate clock and its clkdev lookup with devres to
     fix a resource leak on unbind
   - Maxim MAX77705: Select `REGMAP_I2C` and `REGMAP_IRQ` in Kconfig to fix build errors
   - Qualcomm WCD934x: Initialize the parent DMA mask to suppress "DMA mask not set"
     warnings on child devices
   - Qualcomm WCD934x: Pass the valid device pointer to `dev_err_probe()` on IRQ lookup
     failure to avoid a NULL pointer dereference
   - Rockchip RK8xx: Register the poweroff handler in the atomic `SYS_OFF_MODE_POWER_OFF`
     phase so polling I2C transfers complete during shutdown
   - ST-Ericsson AB8500: Use `devm_mfd_add_devices()` to prevent leaking child devices on
     probe failure
   - TI BQ257xx: Mark self-modifying BQ25792 configuration registers as volatile
   - TI LM3533: Set `coherent_dma_mask` to zero to suppress "DMA mask not set" warnings
   - TI TPS65217: Check for errors during IRQ initialization and masking, and manage IRQ
     domain and wake teardown with devres
   - TI TWL: Unregister the auxiliary platform device via a devres action on probe failure
     and driver unbind
 
 - Cleanups & Refactoring
   - Core: Convert drivers from deprecated `SIMPLE_DEV_PM_OPS()` to
     `DEFINE_SIMPLE_DEV_PM_OPS()` and `pm_sleep_ptr()`
   - Core: Fix spelling mistakes in comments across various MFD drivers and headers
   - Maintainers: Add ROHM BD73800 PMIC files under the ROHM PMIC entry
   - Maintainers: Specify the `for-mfd-next` branch for the MFD and Syscon git trees
   - Dialog DA9062: Use `DEFINE_RES_IRQ_NAMED()` for IRQ resource definitions
   - Intel LPSS: Simplify DebugFS handling by dropping redundant error checks and
     intermediate dentry variables, using octal permissions, and switching to
     `debugfs_remove()`
   - Khadas MCU: Convert MFD cell arrays to `const` and use `MFD_CELL_NAME()`
   - ST-Ericsson AB8500: Fix a spelling typo in a comment
   - TI LM3533: Convert from platform data to Device Tree bindings and pass only regmap and
     light sensor presence to child devices
   - TI LM3533: Remove driver-specific regmap wrappers, redundant pdata helpers, and
     unnecessary `extern` qualifiers, and use `dev_groups` for sysfs attributes
   - Wolfson WM831x: Fix a spelling typo in a comment
 
 - Device Tree Binding Updates
   - HiSilicon Hi6421 SPMI: Fix the compatible string to match `hisilicon,hi6421-spmi`
   - MediaTek MT6357: Allow an `adc` child node
   - MediaTek MT6360: Allow two-cell interrupt specifiers with trigger flags
   - MediaTek MT6397: Document the `#sound-dai-cells` property
   - MediaTek MT6397: Document the battery-backed NVMEM layout under the RTC child node
   - MediaTek MT6397: Document the MT6323 PMIC EFUSE child node
   - Motorola CPCAP: Convert MFD and power button bindings to DT schema and document the
     Mapphone and Mot compositions
   - Qualcomm SPMI PMIC: Document the PM4125 audio codec compatible
   - Qualcomm SPMI PMIC: Document the PMAU0102 PMIC compatible
   - Qualcomm TCSR: Document the MSM8952 TCSR compatible
   - Rockchip RK805: Fold the pin controller binding into the RK805 PMIC DT schema
   - ROHM BD73800: Document the BD73800 PMIC and its regulators
   - ROHM PMIC: Factor out common pin properties into `rohm,pmic-pins.yaml` and reference
     them across BD71815, BD71828, and BD72720 bindings
   - ST-Ericsson AB8500: Document AB8500 and AB8505 buck converter regulators
   - ST-Ericsson AB8500: Document codec audio graph ports, sound DAI cells, and analog
     microphone wiring properties
   - ST-Ericsson DB8500 PRCMU: Deprecate the `db8500-prcmu-regulators` child node and make
     it optional
   - Syscon: Document the Ambarella CV75 secure scratchpad compatible
   - TI BQ25703A: Add the BQ25798 compatible with fallback to BQ25792
   - TI Keystone: Convert Device State Control bindings to DT schema
   - TI LM3533: Document the LM3533 LED controller, backlight, and indicator LED bindings
   - TI LP3943: Convert MFD and PWM bindings to DT schema
   - TI TPS61050: Convert bindings to DT schema
   - TI TPS65086: Make the `regulators` child node optional
   - TI TPS65910: Document `wakeup-source` and GPIO hog child nodes
   - TI TWL6040: Convert bindings to DT schema and align property names with the driver
   - X-Powers AC200: Document the AC200 mixed-signal companion IC
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEdrbJNaO+IJqU8IdIUa+KL4f8d2EFAmrfbfQACgkQUa+KL4f8
 d2FqyxAAsju3PmhlmAdSaHEYXu3PQwzV4j9ZJ4jynWeMyVcKGPePiWfaaSqpyQ36
 gn95B6ZoFlVl9aRAKu0kaLCSx2oGTtD9BoQ6jjfvVW6yU4LzmhvdCw+Zr7Img61H
 rv+kYmZiqzwt1LGaGBbbDNtP1q+B+QFKvgdDGvaiRKGEvOtuKuASLnD4t8jtWuLT
 5VIMFcCFqySeYUwLMnLQk8C2Fqysx1dPvOe0doe90vPF5tpKI8ZNIrbk0OruQzlN
 tfQahrfUnmkZGdjO+lalbkwSvlSrs+6KTckr53fyrIYHILPJcbfnFPimLhDzBVG4
 Ko/WnjGWwt2XkfIkGJJALUZptyz5YpfKfwxl+Xi3NAyWkpVcKfI0nASLd6T8QO4h
 mJQsg2SQer3/HCY2z8Hs8IW1XBhzLPtZN+e5qPOIPBNW3D11y92KodvjMxfSRmdz
 lCeIJohs5md75f3aFUqFSi0iDv4tgTZ2BCUSz9BzqYgkA7cQYlmQrYEqFrhHQFjo
 sYAAFBlg4SLJ5J5N1cEp8DFrjompbqDCenm2csntvJhWQ6hmxHbm5zEKMKeXUYLw
 le+E+jpvg7EXoEsoy+3dVY89gdMpnVN68A7wRCH8EVIrIzq1pRpFpX2V9kd85sro
 SV1LOuEnnnyjEdJ3wSQGEKkPXdy/YZguMBDqoFKw3ODV0cez/cE=
 =Is2H
 -----END PGP SIGNATURE-----

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

Pull MFD updates from Lee Jones:
 "New Support & Features:
   - Cirrus Logic CS42L43: Add support for the CS42L44 variant
   - Khadas MCU: Add support for the VIM4 MCU variant along with
     per-variant fan duty-cycle levels and optional fan supply regulator
     support
   - Maxim MAX77705: Add support for the PASS2 hardware revision
   - MediaTek MT6397: Add AUXADC sub-device support for MT6397
   - Motorola CPCAP: Support per-board sub-device compositions and add
     the Tegra20 Mot composition
   - ROHM BD73800: Add support for the BD73800 PMIC core, regulator,
     RTC, clock gate, and GPIO sub-devices
   - TI LM3533: Add VIN regulator supply support, configure initial
     backlight mapping mode from Device Tree, and implement the
     `backlight_scale` property
   - X-Powers AC200: Add support for the AC200 I2C mixed-signal companion IC

  Improvements & Fixes:
   - Cirrus Logic CS42L43: Synchronize SoundWire enumeration work in
     `remove()` before devres cleanup begins
   - Dialog DA903x: Manage IRQ work cancellation and sub-device removal
     via devres to prevent use-after-free during teardown
   - Dialog DA9150: Balance `enable_irq_wake()` with
     `disable_irq_wake()` during probe failure and driver removal
   - Intel LPSS: Add DMI quirks for Dell Latitude 5285 and 7275 to
     ignore ACPI resource conflicts on the I2C4 controller
   - Intel Quark I2C/GPIO: Manage the fixed-rate clock and its clkdev
     lookup with devres to fix a resource leak on unbind
   - Maxim MAX77705: Select `REGMAP_I2C` and `REGMAP_IRQ` in Kconfig to
     fix build errors
   - Qualcomm WCD934x: Initialize the parent DMA mask to suppress "DMA
     mask not set" warnings on child devices
   - Qualcomm WCD934x: Pass the valid device pointer to
     `dev_err_probe()` on IRQ lookup failure to avoid a NULL pointer
     dereference
   - Rockchip RK8xx: Register the poweroff handler in the atomic
     `SYS_OFF_MODE_POWER_OFF` phase so polling I2C transfers complete
     during shutdown
   - ST-Ericsson AB8500: Use `devm_mfd_add_devices()` to prevent leaking
     child devices on probe failure
   - TI BQ257xx: Mark self-modifying BQ25792 configuration registers as
     volatile
   - TI LM3533: Set `coherent_dma_mask` to zero to suppress "DMA mask
     not set" warnings
   - TI TPS65217: Check for errors during IRQ initialization and
     masking, and manage IRQ domain and wake teardown with devres
   - TI TWL: Unregister the auxiliary platform device via a devres
     action on probe failure and driver unbind

  Cleanups & Refactoring
   - Core: Convert drivers from deprecated `SIMPLE_DEV_PM_OPS()` to
     `DEFINE_SIMPLE_DEV_PM_OPS()` and `pm_sleep_ptr()`
   - Core: Fix spelling mistakes in comments across various MFD drivers
     and headers
   - Maintainers: Add ROHM BD73800 PMIC files under the ROHM PMIC entry
   - Maintainers: Specify the `for-mfd-next` branch for the MFD and
     Syscon git trees
   - Dialog DA9062: Use `DEFINE_RES_IRQ_NAMED()` for IRQ resource
     definitions
   - Intel LPSS: Simplify DebugFS handling by dropping redundant error
     checks and intermediate dentry variables, using octal permissions,
     and switching to
    `debugfs_remove()`
   - Khadas MCU: Convert MFD cell arrays to `const` and use
     `MFD_CELL_NAME()`
   - ST-Ericsson AB8500: Fix a spelling typo in a comment
   - TI LM3533: Convert from platform data to Device Tree bindings and
     pass only regmap and light sensor presence to child devices
   - TI LM3533: Remove driver-specific regmap wrappers, redundant pdata
     helpers, and unnecessary `extern` qualifiers, and use `dev_groups`
     for sysfs attributes
   - Wolfson WM831x: Fix a spelling typo in a comment

  Device Tree Binding Updates
   - HiSilicon Hi6421 SPMI: Fix the compatible string to match
     `hisilicon,hi6421-spmi`
   - MediaTek MT6357: Allow an `adc` child node
   - MediaTek MT6360: Allow two-cell interrupt specifiers with trigger
     flags
   - MediaTek MT6397: Document the `#sound-dai-cells` property
   - MediaTek MT6397: Document the battery-backed NVMEM layout under the
     RTC child node
   - MediaTek MT6397: Document the MT6323 PMIC EFUSE child node
   - Motorola CPCAP: Convert MFD and power button bindings to DT schema
     and document the Mapphone and Mot compositions
   - Qualcomm SPMI PMIC: Document the PM4125 audio codec compatible
   - Qualcomm SPMI PMIC: Document the PMAU0102 PMIC compatible
   - Qualcomm TCSR: Document the MSM8952 TCSR compatible
   - Rockchip RK805: Fold the pin controller binding into the RK805 PMIC
     DT schema
   - ROHM BD73800: Document the BD73800 PMIC and its regulators
   - ROHM PMIC: Factor out common pin properties into
     `rohm,pmic-pins.yaml` and reference them across BD71815, BD71828,
     and BD72720 bindings
   - ST-Ericsson AB8500: Document AB8500 and AB8505 buck converter
     regulators
   - ST-Ericsson AB8500: Document codec audio graph ports, sound DAI
     cells, and analog microphone wiring properties
   - ST-Ericsson DB8500 PRCMU: Deprecate the `db8500-prcmu-regulators`
     child node and make it optional
   - Syscon: Document the Ambarella CV75 secure scratchpad compatible
   - TI BQ25703A: Add the BQ25798 compatible with fallback to BQ25792
   - TI Keystone: Convert Device State Control bindings to DT schema
   - TI LM3533: Document the LM3533 LED controller, backlight, and
     indicator LED bindings
   - TI LP3943: Convert MFD and PWM bindings to DT schema
   - TI TPS61050: Convert bindings to DT schema
   - TI TPS65086: Make the `regulators` child node optional
   - TI TPS65910: Document `wakeup-source` and GPIO hog child nodes
   - TI TWL6040: Convert bindings to DT schema and align property names
     with the driver
   - X-Powers AC200: Document the AC200 mixed-signal companion IC"

* tag 'mfd-next-7.4' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd: (74 commits)
  dt-bindings: mfd: db8500-prcmu: Deprecate EPOD regulators
  dt-bindings: mfd: syscon: Add Ambarella CV75 secure scratchpad
  dt-bindings: mfd: rockchip,rk805: Convert pinctrl to DT schema
  mfd: intel-lpss: Add Dell Latitude 7275 to the resource conflict quirk
  mfd: intel-lpss: Add resource conflict quirk for Dell Latitude 5285
  mfd: tps65217: Use devres for IRQ domain and wake teardown
  mfd: tps65217: Check return value when masking interrupt sources
  mfd: tps65217: Fix NULL pointer dereference on IRQ init failure
  dt-bindings: mfd: qcom,spmi-pmic: Add compatibles for pm4125-codec
  mfd: bq257xx: Mark self-modifying BQ25792 registers volatile
  dt-bindings: mfd: mediatek: mt6397: describe the RTC's nvmem layout
  mfd: mt6397-core: Add mt6397 AUXADC support
  mfd: max77705: Mark PASS2 revision as supported
  mfd: ab8500: Fix child device leaks on probe failure
  dt-bindings: mfd: Add MT6397 sound DAI cells
  dt-bindings: mfd: mediatek: mt6397: Add mt6323 PMIC EFUSE
  dt-bindings: mfd: hisilicon: Fix Hi6421 SPMI compatible
  dt-bindings: mfd: ti,bq25703a: Expand to include BQ25798
  dt-bindings: mfd: Allow MT6360 interrupt flags
  dt-bindings: mfd: mediatek: Allow MT6357 ADC
  ...
This commit is contained in:
Linus Torvalds 2026-10-26 08:38:17 -10:00
commit d857e1f3fa
89 changed files with 2899 additions and 1329 deletions

View File

@ -1,20 +0,0 @@
Motorola CPCAP on key
This module is part of the CPCAP. For more details about the whole
chip see Documentation/devicetree/bindings/mfd/motorola-cpcap.txt.
This module provides a simple power button event via an Interrupt.
Required properties:
- compatible: should be one of the following
- "motorola,cpcap-pwrbutton"
- interrupts: irq specifier for CPCAP's ON IRQ
Example:
&cpcap {
cpcap_pwrbutton: pwrbutton {
compatible = "motorola,cpcap-pwrbutton";
interrupts = <23 IRQ_TYPE_NONE>;
};
};

View File

@ -0,0 +1,32 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/input/motorola,cpcap-pwrbutton.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Motorola CPCAP PMIC power key
maintainers:
- Svyatoslav Ryhel <clamor95@gmail.com>
description:
This module is part of the Motorola CPCAP MFD device. For more details
see Documentation/devicetree/bindings/mfd/motorola,cpcap.yaml. The
power key is represented as a sub-node of the PMIC node on the device
tree.
properties:
compatible:
const: motorola,cpcap-pwrbutton
interrupts:
items:
- description: CPCAP's ON interrupt
required:
- compatible
- interrupts
additionalProperties: false
...

View File

@ -0,0 +1,69 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/leds/backlight/ti,lm3533-backlight.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: TI LM3533 high voltage series LED strings
description:
This is part of the TI LM3533 MFD device. It represents two high voltage series
LED strings for display backlight controlled by the TI LM3533.
maintainers:
- Svyatoslav Ryhel <clamor95@gmail.com>
allOf:
- $ref: /schemas/leds/backlight/common.yaml#
properties:
compatible:
const: ti,lm3533-backlight
reg:
description: Control bank selection (0 = bank A, 1 = bank B).
maximum: 1
led-max-microamp:
description: maximum current in uA with a 800 uA step.
minimum: 5000
maximum: 29800
default: 5000
led-sources:
description: |
HVLED strings associated with this control bank:
0 - HVLED1
1 - HVLED2
minItems: 1
maxItems: 2
items:
maximum: 1
ti,pwm-config-mask:
$ref: /schemas/types.yaml#/definitions/uint32
description: |
Control Bank PWM Configuration Register mask that allows to configure
PWM input in Zones 0-4
BIT(0) - PWM Input is enabled
BIT(1) - PWM Input is enabled in Zone 0
BIT(2) - PWM Input is enabled in Zone 1
BIT(3) - PWM Input is enabled in Zone 2
BIT(4) - PWM Input is enabled in Zone 3
BIT(5) - PWM Input is enabled in Zone 4
default: 0
ti,linear-mapping-mode:
description:
Enable linear mapping mode. If disabled, then it will use exponential
mapping mode in which the ramp up/down appears to have a more uniform
transition to the human eye.
type: boolean
required:
- compatible
- reg
unevaluatedProperties: false
# see ti,lm3533.yaml for an example

View File

@ -0,0 +1,67 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/leds/ti,lm3533-leds.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: TI LM3533 low voltage control banks for individual LEDs
description:
This is part of the TI LM3533 MFD device. It represents four low voltage
control banks for individual LEDs provided by the TI LM3533.
maintainers:
- Svyatoslav Ryhel <clamor95@gmail.com>
allOf:
- $ref: /schemas/leds/common.yaml#
properties:
compatible:
const: ti,lm3533-leds
reg:
description:
Control bank selection (2 = bank C, 3 = bank D, 4 = bank E, 5 = bank F).
minimum: 2
maximum: 5
led-max-microamp:
description: maximum current in uA with a 800 uA step.
minimum: 5000
maximum: 29800
default: 5000
led-sources:
description: |
LVLED associated with this control bank. May be more than 1 source per bank.
0 - LVLED1
1 - LVLED2
2 - LVLED3
3 - LVLED4
4 - LVLED5
minItems: 1
maxItems: 5
items:
maximum: 4
ti,pwm-config-mask:
$ref: /schemas/types.yaml#/definitions/uint32
description: |
Control Bank PWM Configuration Register mask that allows to configure
PWM input in Zones 0-4
BIT(0) - PWM Input is enabled
BIT(1) - PWM Input is enabled in Zone 0
BIT(2) - PWM Input is enabled in Zone 1
BIT(3) - PWM Input is enabled in Zone 2
BIT(4) - PWM Input is enabled in Zone 3
BIT(5) - PWM Input is enabled in Zone 4
default: 0
required:
- compatible
- reg
unevaluatedProperties: false
# see ti,lm3533.yaml for an example

View File

@ -0,0 +1,169 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/leds/ti,lm3533.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: TI LM3533 Complete Lighting Power Solution
description: >
The LM3533 is a complete power source for backlight, keypad, and indicator LEDs
in smartphone handsets. The high-voltage inductive boost converter provides the
power for two high voltage series LED strings for display backlight and four low
voltage control banks for individual LEDs. Additionally, LM3533 features an
interface for an external light sensor.
https://www.ti.com/product/LM3533
maintainers:
- Svyatoslav Ryhel <clamor95@gmail.com>
properties:
compatible:
const: ti,lm3533
reg:
maxItems: 1
enable-gpios:
description: GPIO connected to the HWEN pin.
maxItems: 1
vin-supply:
description: Supply connected to the IN line (2.7 V to 5.5 V).
'#address-cells':
const: 1
'#size-cells':
const: 0
ti,boost-ovp-microvolt:
description: boost OVP select (16V, 24V, 32V, 40V)
enum: [ 16000000, 24000000, 32000000, 40000000 ]
default: 16000000
ti,boost-freq-hz:
description: boost frequency select (500KHz or 1MHz)
enum: [ 500000, 1000000 ]
default: 500000
light-sensor:
type: object
additionalProperties: false
properties:
compatible:
const: ti,lm3533-als
interrupts:
maxItems: 1
ti,resistor-ohms:
description:
Internal configuration resistor value when light sensor is in
Analog Sensor mode and PWM mode is disabled. The expectation is
the input is a current from the external analog light sensor and
this is used to convert it to a voltage within the target range.
minimum: 1575
maximum: 200000
ti,pwm-mode:
type: boolean
description:
Switch for mode in which light sensor interface is running. If
this property is set then the light sensor interface is running
in PWM mode, internal resistor value is set to high-impedance (0)
and ti,resistor-ohms property is ignored.
required:
- compatible
oneOf:
- required:
- ti,resistor-ohms
- required:
- ti,pwm-mode
patternProperties:
"^backlight@[01]$":
$ref: /schemas/leds/backlight/ti,lm3533-backlight.yaml#
"^led@[2-5]$":
$ref: /schemas/leds/ti,lm3533-leds.yaml#
required:
- compatible
- reg
- '#address-cells'
- '#size-cells'
additionalProperties: false
examples:
- |
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/interrupt-controller/irq.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
led-controller@36 {
compatible = "ti,lm3533";
reg = <0x36>;
enable-gpios = <&gpio 110 GPIO_ACTIVE_HIGH>;
vin-supply = <&vdd_3v3_bat>;
ti,boost-ovp-microvolt = <24000000>;
ti,boost-freq-hz = <500000>;
#address-cells = <1>;
#size-cells = <0>;
backlight@0 {
compatible = "ti,lm3533-backlight";
reg = <0>;
default-brightness = <113>;
led-max-microamp = <23400>;
led-sources = <0 1>;
};
led@2 {
compatible = "ti,lm3533-leds";
reg = <2>;
led-max-microamp = <23400>;
led-sources = <0 1>;
};
led@4 {
compatible = "ti,lm3533-leds";
reg = <4>;
led-max-microamp = <23400>;
led-sources = <2>;
};
led@5 {
compatible = "ti,lm3533-leds";
reg = <5>;
led-max-microamp = <23400>;
led-sources = <3 4>;
};
light-sensor {
compatible = "ti,lm3533-als";
interrupt-parent = <&gpio>;
interrupts = <80 IRQ_TYPE_LEVEL_LOW>;
ti,pwm-mode;
};
};
};
...

View File

@ -24,7 +24,7 @@ properties:
pattern: "pmic@[0-9a-f]"
compatible:
const: hisilicon,hi6421v600-spmi
const: hisilicon,hi6421-spmi
reg:
maxItems: 1
@ -66,7 +66,7 @@ examples:
#size-cells = <0>;
pmic@0 {
compatible = "hisilicon,hi6421v600-spmi";
compatible = "hisilicon,hi6421-spmi";
reg = <0 SPMI_USID>;
#interrupt-cells = <2>;

View File

@ -1,33 +0,0 @@
TI/National Semiconductor LP3943 MFD driver
Required properties:
- compatible: "ti,lp3943"
- reg: I2C slave address. From 0x60 to 0x67.
LP3943 consists of two sub-devices, lp3943-gpio and lp3943-pwm.
For the LP3943 GPIO properties please refer to:
Documentation/devicetree/bindings/gpio/trivial-gpio.yaml
For the LP3943 PWM properties please refer to:
Documentation/devicetree/bindings/pwm/pwm-lp3943.txt
Example:
lp3943@60 {
compatible = "ti,lp3943";
reg = <0x60>;
gpioex: gpio {
compatible = "ti,lp3943-gpio";
gpio-controller;
#gpio-cells = <2>;
};
pwm3943: pwm {
compatible = "ti,lp3943-pwm";
#pwm-cells = <2>;
ti,pwm0 = <8 9 10>;
ti,pwm1 = <15>;
};
};

View File

@ -62,6 +62,13 @@ properties:
description:
List of MT6357 BUCKs and LDOs regulators.
adc:
type: object
$ref: /schemas/iio/adc/mediatek,mt6359-auxadc.yaml#
unevaluatedProperties: false
description:
MT6357 auxiliary ADC.
rtc:
type: object
$ref: /schemas/rtc/rtc.yaml#

View File

@ -33,9 +33,10 @@ properties:
interrupt-controller: true
"#interrupt-cells":
const: 1
enum: [1, 2]
description:
The first cell is the IRQ number.
The first cell is the IRQ number. The optional second cell is the IRQ
trigger type.
regulators:
$ref: /schemas/regulator/mt6360-regulator.yaml#

View File

@ -57,6 +57,9 @@ properties:
"#interrupt-cells":
const: 2
"#sound-dai-cells":
const: 1
rtc:
type: object
$ref: /schemas/rtc/rtc.yaml#
@ -81,6 +84,15 @@ properties:
start-year: true
nvmem-layout:
$ref: /schemas/nvmem/layouts/nvmem-layout.yaml
description:
The RTC carries four bytes of storage that neither the clock nor the
alarm uses, in the high half of four of the alarm registers, and
offers them as a battery-backed nvmem provider. MediaTek's
documentation names them RTC_NEW_SPARE0 to RTC_NEW_SPARE3 and gives
the first to a fuel gauge.
required:
- compatible

View File

@ -0,0 +1,408 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/mfd/motorola,cpcap.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Motorola CPCAP PMIC MFD
maintainers:
- Svyatoslav Ryhel <clamor95@gmail.com>
allOf:
- $ref: /schemas/spi/spi-peripheral-props.yaml#
properties:
compatible:
oneOf:
- enum:
- motorola,mapphone-cpcap
- motorola,mot-cpcap
- items:
- const: motorola,cpcap
- const: st,6556002
reg:
maxItems: 1
interrupts:
maxItems: 1
interrupt-controller: true
"#interrupt-cells":
const: 2
spi-max-frequency:
maximum: 9600000
spi-cs-high: true
spi-cpol: true
spi-cpha: true
adc:
$ref: /schemas/iio/adc/motorola,cpcap-adc.yaml#
audio-codec:
type: object
additionalProperties: false
properties:
interrupts:
items:
- description: headset detect interrupt
- description: microphone bias 2 detect interrupt
interrupt-names:
items:
- const: hs
- const: mb2
"#sound-dai-cells":
const: 1
VAUDIO-supply:
description:
Codec power supply, usually VAUDIO regulator of CPCAP.
ports:
$ref: /schemas/graph.yaml#/properties/ports
properties:
port@0:
$ref: /schemas/graph.yaml#/properties/port
description: port connected to the Stereo HiFi DAC
port@1:
$ref: /schemas/graph.yaml#/properties/port
description: port connected to the Voice DAC
required:
- port@0
- port@1
required:
- interrupts
- interrupt-names
- "#sound-dai-cells"
battery:
$ref: /schemas/power/supply/cpcap-battery.yaml#
charger:
$ref: /schemas/power/supply/cpcap-charger.yaml#
key-power:
$ref: /schemas/input/motorola,cpcap-pwrbutton.yaml#
phy:
$ref: /schemas/phy/motorola,cpcap-usb-phy.yaml#
regulator:
$ref: /schemas/regulator/motorola,cpcap-regulator.yaml#
rtc:
$ref: /schemas/rtc/motorola,cpcap-rtc.yaml#
patternProperties:
"^led(-[a-z]+)?$":
$ref: /schemas/leds/motorola,cpcap-leds.yaml#
required:
- compatible
- reg
- interrupts
- interrupt-controller
- "#interrupt-cells"
- spi-max-frequency
additionalProperties: false
examples:
- |
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/input/linux-event-codes.h>
spi {
#address-cells = <1>;
#size-cells = <0>;
cpcap: pmic@0 {
compatible = "motorola,cpcap", "st,6556002";
reg = <0>; /* cs0 */
interrupt-parent = <&gpio1>;
interrupts = <7 IRQ_TYPE_EDGE_RISING>;
interrupt-controller;
#interrupt-cells = <2>;
spi-max-frequency = <3000000>;
spi-cs-high;
spi-cpol;
spi-cpha;
cpcap_adc: adc {
compatible = "motorola,cpcap-adc";
interrupt-parent = <&cpcap>;
interrupts = <8 IRQ_TYPE_NONE>;
interrupt-names = "adcdone";
#io-channel-cells = <1>;
};
cpcap_audio: audio-codec {
interrupt-parent = <&cpcap>;
interrupts = <9 IRQ_TYPE_NONE>, <10 IRQ_TYPE_NONE>;
interrupt-names = "hs", "mb2";
VAUDIO-supply = <&vdd_audio>;
#sound-dai-cells = <1>;
ports {
#address-cells = <1>;
#size-cells = <0>;
/* HiFi */
port@0 {
reg = <0>;
cpcap_audio_codec0: endpoint {
};
};
/* Voice */
port@1 {
reg = <1>;
cpcap_audio_codec1: endpoint {
};
};
};
};
cpcap_battery: battery {
compatible = "motorola,cpcap-battery";
interrupt-parent = <&cpcap>;
interrupts = <6 IRQ_TYPE_NONE>, <5 IRQ_TYPE_NONE>,
<3 IRQ_TYPE_NONE>, <20 IRQ_TYPE_NONE>,
<54 IRQ_TYPE_NONE>, <57 IRQ_TYPE_NONE>;
interrupt-names = "eol", "lowbph", "lowbpl",
"chrgcurr1", "battdetb", "cccal";
io-channels = <&cpcap_adc 0>, <&cpcap_adc 1>,
<&cpcap_adc 5>, <&cpcap_adc 6>;
io-channel-names = "battdetb", "battp",
"chg_isense", "batti";
power-supplies = <&cpcap_charger>;
};
cpcap_charger: charger {
compatible = "motorola,mapphone-cpcap-charger";
interrupt-parent = <&cpcap>;
interrupts = <13 IRQ_TYPE_NONE>, <12 IRQ_TYPE_NONE>,
<29 IRQ_TYPE_NONE>, <28 IRQ_TYPE_NONE>,
<22 IRQ_TYPE_NONE>, <21 IRQ_TYPE_NONE>,
<20 IRQ_TYPE_NONE>, <19 IRQ_TYPE_NONE>,
<54 IRQ_TYPE_NONE>;
interrupt-names = "chrg_det", "rvrs_chrg", "chrg_se1b",
"se0conn", "rvrs_mode", "chrgcurr2",
"chrgcurr1", "vbusvld", "battdetb";
mode-gpios = <&gpio3 29 GPIO_ACTIVE_LOW>,
<&gpio3 23 GPIO_ACTIVE_LOW>;
io-channels = <&cpcap_adc 0>, <&cpcap_adc 1>,
<&cpcap_adc 2>, <&cpcap_adc 5>,
<&cpcap_adc 6>;
io-channel-names = "battdetb", "battp",
"vbus", "chg_isense",
"batti";
};
key-power {
compatible = "motorola,cpcap-pwrbutton";
interrupt-parent = <&cpcap>;
interrupts = <23 IRQ_TYPE_NONE>;
};
led-red {
compatible = "motorola,cpcap-led-red";
vdd-supply = <&vdd_led>;
label = "status-led::red";
};
led-green {
compatible = "motorola,cpcap-led-green";
vdd-supply = <&vdd_led>;
label = "status-led::green";
};
led-blue {
compatible = "motorola,cpcap-led-blue";
vdd-supply = <&vdd_led>;
label = "status-led::blue";
};
cpcap_usb2_phy: phy {
compatible = "motorola,cpcap-usb-phy";
pinctrl-0 = <&usb_gpio_mux_sel1>, <&usb_gpio_mux_sel2>;
pinctrl-1 = <&usb_ulpi_pins>;
pinctrl-2 = <&usb_utmi_pins>;
pinctrl-3 = <&uart3_pins>;
pinctrl-names = "default", "ulpi", "utmi", "uart";
#phy-cells = <0>;
interrupts-extended =
<&cpcap 15 IRQ_TYPE_NONE>, <&cpcap 14 IRQ_TYPE_NONE>,
<&cpcap 28 IRQ_TYPE_NONE>, <&cpcap 19 IRQ_TYPE_NONE>,
<&cpcap 18 IRQ_TYPE_NONE>, <&cpcap 17 IRQ_TYPE_NONE>,
<&cpcap 16 IRQ_TYPE_NONE>, <&cpcap 49 IRQ_TYPE_NONE>,
<&cpcap 48 IRQ_TYPE_NONE>;
interrupt-names = "id_ground", "id_float", "se0conn",
"vbusvld", "sessvld", "sessend",
"se1", "dm", "dp";
mode-gpios = <&gpio2 28 GPIO_ACTIVE_HIGH>,
<&gpio1 0 GPIO_ACTIVE_HIGH>;
io-channels = <&cpcap_adc 2>, <&cpcap_adc 7>;
io-channel-names = "vbus", "id";
vusb-supply = <&avdd_usb>;
};
regulator {
compatible = "motorola,cpcap-regulator";
regulators {
vdd_cpu: SW1 {
regulator-name = "vdd_cpu";
regulator-min-microvolt = <750000>;
regulator-max-microvolt = <1125000>;
regulator-enable-ramp-delay = <1500>;
regulator-always-on;
regulator-boot-on;
};
vdd_core: SW2 {
regulator-name = "vdd_core";
regulator-min-microvolt = <950000>;
regulator-max-microvolt = <1300000>;
regulator-enable-ramp-delay = <1500>;
regulator-always-on;
regulator-boot-on;
};
vdd_1v8_vio: SW3 {
regulator-name = "vdd_1v8_vio";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
regulator-enable-ramp-delay = <0>;
regulator-always-on;
regulator-boot-on;
};
vdd_aon: SW4 {
regulator-name = "vdd_aon";
regulator-min-microvolt = <950000>;
regulator-max-microvolt = <1300000>;
regulator-enable-ramp-delay = <1500>;
regulator-always-on;
regulator-boot-on;
};
vdd_led: SW5 {
regulator-name = "vdd_led";
regulator-min-microvolt = <5050000>;
regulator-max-microvolt = <5050000>;
regulator-enable-ramp-delay = <1500>;
regulator-boot-on;
};
vdd_hvio: VHVIO {
regulator-name = "vdd_hvio";
regulator-min-microvolt = <2775000>;
regulator-max-microvolt = <2775000>;
regulator-enable-ramp-delay = <1000>;
};
vcore_emmc: VSDIO {
regulator-name = "vcore_emmc";
regulator-min-microvolt = <1500000>;
regulator-max-microvolt = <3000000>;
regulator-enable-ramp-delay = <1000>;
regulator-always-on;
regulator-boot-on;
};
avdd_dsi_csi: VCSI {
regulator-name = "avdd_dsi_csi";
regulator-min-microvolt = <1200000>;
regulator-max-microvolt = <1200000>;
regulator-enable-ramp-delay = <1000>;
regulator-boot-on;
};
avdd_3v3_periph: VWLAN2 {
regulator-name = "avdd_3v3_periph";
regulator-min-microvolt = <2775000>;
regulator-max-microvolt = <3300000>;
regulator-enable-ramp-delay = <1000>;
regulator-boot-on;
};
vddio_usd: VSIMCARD {
regulator-name = "vddio_usd";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <2900000>;
regulator-enable-ramp-delay = <1000>;
regulator-boot-on;
};
vdd_haptic: VVIB {
regulator-name = "vdd_haptic";
regulator-min-microvolt = <1300000>;
regulator-max-microvolt = <3000000>;
regulator-enable-ramp-delay = <1000>;
};
avdd_usb: VUSB {
regulator-name = "avdd_usb";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-enable-ramp-delay = <1000>;
regulator-always-on;
regulator-boot-on;
};
vdd_audio: VAUDIO {
regulator-name = "vdd_audio";
regulator-min-microvolt = <2775000>;
regulator-max-microvolt = <2775000>;
regulator-enable-ramp-delay = <1000>;
regulator-always-on;
regulator-boot-on;
};
};
};
cpcap_rtc: rtc {
compatible = "motorola,cpcap-rtc";
interrupt-parent = <&cpcap>;
interrupts = <39 IRQ_TYPE_NONE>, <26 IRQ_TYPE_NONE>;
};
};
};
...

View File

@ -1,78 +0,0 @@
Motorola CPCAP PMIC device tree binding
Required properties:
- compatible : One or both of "motorola,cpcap" or "ste,6556002"
- reg : SPI chip select
- interrupts : The interrupt line the device is connected to
- interrupt-controller : Marks the device node as an interrupt controller
- #interrupt-cells : The number of cells to describe an IRQ, should be 2
- #address-cells : Child device offset number of cells, should be 1
- #size-cells : Child device size number of cells, should be 0
- spi-max-frequency : Typically set to 3000000
- spi-cs-high : SPI chip select direction
Optional subnodes:
The sub-functions of CPCAP get their own node with their own compatible values,
which are described in the following files:
- Documentation/devicetree/bindings/power/supply/cpcap-battery.yaml
- Documentation/devicetree/bindings/power/supply/cpcap-charger.yaml
- Documentation/devicetree/bindings/regulator/cpcap-regulator.txt
- Documentation/devicetree/bindings/phy/motorola,cpcap-usb-phy.yaml
- Documentation/devicetree/bindings/input/cpcap-pwrbutton.txt
- Documentation/devicetree/bindings/rtc/cpcap-rtc.txt
- Documentation/devicetree/bindings/leds/leds-cpcap.txt
- Documentation/devicetree/bindings/iio/adc/motorola,cpcap-adc.yaml
The only exception is the audio codec. Instead of a compatible value its
node must be named "audio-codec".
Required properties for the audio-codec subnode:
- #sound-dai-cells = <1>;
- interrupts : should contain jack detection interrupts, with headset
detect interrupt matching "hs" and microphone bias 2
detect interrupt matching "mb2" in interrupt-names.
- interrupt-names : Contains "hs", "mb2"
The audio-codec provides two DAIs. The first one is connected to the
Stereo HiFi DAC and the second one is connected to the Voice DAC.
Example:
&mcspi1 {
cpcap: pmic@0 {
compatible = "motorola,cpcap", "ste,6556002";
reg = <0>; /* cs0 */
interrupt-parent = <&gpio1>;
interrupts = <7 IRQ_TYPE_EDGE_RISING>;
interrupt-controller;
#interrupt-cells = <2>;
#address-cells = <1>;
#size-cells = <0>;
spi-max-frequency = <3000000>;
spi-cs-high;
audio-codec {
#sound-dai-cells = <1>;
interrupts-extended = <&cpcap 9 0>, <&cpcap 10 0>;
interrupt-names = "hs", "mb2";
/* HiFi */
port@0 {
endpoint {
remote-endpoint = <&cpu_dai1>;
};
};
/* Voice */
port@1 {
endpoint {
remote-endpoint = <&cpu_dai2>;
};
};
};
};
};

View File

@ -74,6 +74,7 @@ properties:
- qcom,pm8994
- qcom,pm8998
- qcom,pma8084
- qcom,pmau0102
- qcom,pmc8180
- qcom,pmc8180c
- qcom,pmc8380
@ -147,7 +148,9 @@ patternProperties:
"^audio-codec@[0-9a-f]+$":
type: object
$ref: /schemas/sound/qcom,pm8916-wcd-analog-codec.yaml#
oneOf:
- $ref: /schemas/sound/qcom,pm4125-codec.yaml#
- $ref: /schemas/sound/qcom,pm8916-wcd-analog-codec.yaml#
"^battery@[0-9a-f]+$":
type: object

View File

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

View File

@ -77,6 +77,16 @@ properties:
description:
The input supply for LDO_REG3.
# pinctrl-bindings.txt allows the pin configuration nodes to be grandchildren
# of the pin controller, and the text binding this replaces used that layout:
# a "pinmux" node holding the nodes that carry "pins". The driver reaches both
# layouts, because pinconf_generic_dt_node_to_map() parses the referenced node
# and then walks its children.
pinmux:
type: object
additionalProperties:
$ref: '#/$defs/rk805-pin-config'
regulators:
type: object
patternProperties:
@ -86,6 +96,38 @@ properties:
unevaluatedProperties: false
unevaluatedProperties: false
$defs:
rk805-pin-config:
type: object
description:
The RK805 has two output-only GPIOs which can be muxed to the GPIO
function and driven low or high at boot.
additionalProperties: false
properties:
pins:
description:
List of GPIO pins to configure.
items:
enum: [gpio0, gpio1]
minItems: 1
maxItems: 2
function:
description:
The RK805 only supports the GPIO function.
enum: [gpio]
output-low: true
output-high: true
required:
- pins
patternProperties:
'-pins$':
$ref: '#/$defs/rk805-pin-config'
allOf:
- if:
properties:
@ -125,9 +167,11 @@ examples:
interrupt-parent = <&gpio2>;
interrupts = <RK_PA6 IRQ_TYPE_LEVEL_LOW>;
pinctrl-names = "default";
pinctrl-0 = <&pmic_int_l>;
pinctrl-0 = <&pmic_int_l>, <&rk805_default>, <&rk805_grouped>;
rockchip,system-power-controller;
wakeup-source;
gpio-controller;
#gpio-cells = <2>;
#clock-cells = <0>;
vcc1-supply = <&vcc_sys>;
@ -137,6 +181,20 @@ examples:
vcc5-supply = <&vcc_io>;
vcc6-supply = <&vcc_io>;
rk805_default: rk805-default-pins {
pins = "gpio0";
function = "gpio";
output-high;
};
rk805_grouped: pinmux {
gpio01 {
pins = "gpio1";
function = "gpio";
output-low;
};
};
regulators {
vdd_logic: DCDC_REG1 {
regulator-name = "vdd_logic";

View File

@ -312,6 +312,33 @@ properties:
items:
- const: audioclk
'#sound-dai-cells':
description: Selects one of the two digital audio interfaces
const: 1
ports:
$ref: /schemas/sound/audio-graph-port.yaml#/definitions/ports
stericsson,amic1-type-single-ended:
description: Configure analog microphone 1 as single-ended
type: boolean
stericsson,amic2-type-single-ended:
description: Configure analog microphone 2 as single-ended
type: boolean
stericsson,amic1a-bias-vamic2:
description: Supply analog microphone 1A from VAMIC2 instead of VAMIC1
type: boolean
stericsson,amic1b-bias-vamic2:
description: Supply analog microphone 1B from VAMIC2 instead of VAMIC1
type: boolean
stericsson,amic2-bias-vamic1:
description: Supply analog microphone 2 from VAMIC1 instead of VAMIC2
type: boolean
stericsson,earpeice-cmv:
description: Earpiece voltage
$ref: /schemas/types.yaml#/definitions/uint32
@ -319,11 +346,14 @@ properties:
required:
- compatible
- '#sound-dai-cells'
additionalProperties: false
regulator:
description: Node describing the AB8500 internal regulators.
LDO means low-dropout regulator. SMPS means switched-mode power
supply; the SMPS regulators described here are buck converters.
type: object
properties:
@ -439,16 +469,117 @@ properties:
$ref: /schemas/regulator/regulator.yaml#
unevaluatedProperties: false
allOf:
- if:
properties:
compatible:
const: stericsson,ab8500-regulator
then:
properties:
ab8500_buck_smps1:
description: Analog buck converter for the VSMPS1 1.2V I/O
and memory supply.
type: object
$ref: /schemas/regulator/regulator.yaml#
unevaluatedProperties: false
ab8500_buck_smps2:
description: Analog buck converter for the VSMPS2 1.8V I/O
and memory supply.
type: object
$ref: /schemas/regulator/regulator.yaml#
unevaluatedProperties: false
ab8500_buck_smps3:
description: Analog buck converter for VSMPS3, which supplies
the VSAFE power domain.
type: object
$ref: /schemas/regulator/regulator.yaml#
unevaluatedProperties: false
ab8500_buck_arm:
description: Analog buck converter for the VARM processor
supply.
type: object
$ref: /schemas/regulator/regulator.yaml#
unevaluatedProperties: false
ab8500_buck_ape:
description: Analog buck converter for the VAPE application
processor supply.
type: object
$ref: /schemas/regulator/regulator.yaml#
unevaluatedProperties: false
ab8500_buck_mod:
description: Analog buck converter for the VMOD modem supply.
type: object
$ref: /schemas/regulator/regulator.yaml#
unevaluatedProperties: false
- if:
properties:
compatible:
const: stericsson,ab8505-regulator
then:
properties:
ab8505_buck_smpsa:
description: Analog buck converter for the VSMPSA 1.2V I/O
and memory supply. The selector range depends on OTP
configuration.
type: object
$ref: /schemas/regulator/regulator.yaml#
unevaluatedProperties: false
ab8505_buck_smpsb:
description: Analog buck converter for the VSMPSB 1.8V I/O
and memory supply. The selector range depends on OTP
configuration.
type: object
$ref: /schemas/regulator/regulator.yaml#
unevaluatedProperties: false
ab8505_buck_safe:
description: Analog buck converter for the VSAFE permanent
logic and DDR supply. The selector range depends on OTP
configuration.
type: object
$ref: /schemas/regulator/regulator.yaml#
unevaluatedProperties: false
ab8505_buck_arm:
description: Analog buck converter for the VARM processor
supply, with a 0.6V to 1.39375V selector range.
type: object
$ref: /schemas/regulator/regulator.yaml#
unevaluatedProperties: false
ab8505_buck_smpsc:
description: Analog buck converter for the VSMPSC multimedia
and graphics supply. The selector range depends on OTP
configuration.
type: object
$ref: /schemas/regulator/regulator.yaml#
unevaluatedProperties: false
ab8505_buck_smpsm:
description: Analog buck converter for the VSMPSM modem
supply. The selector range depends on OTP configuration.
type: object
$ref: /schemas/regulator/regulator.yaml#
unevaluatedProperties: false
required:
- compatible
additionalProperties: false
unevaluatedProperties: false
regulator-external:
description: Node describing the AB8500 external regulators. This
concerns the autonomous regulators VSMPS1, VSMPS2 and VSMPS3
that are normally controlled by external electronics but also
sometimes need to be explicitly controlled by software.
description: Node describing AB8500 control interfaces for external
regulators. AB8500 controls these external devices through the
ExtSupply1Ena, ExtSupply2Ena and ExtSupply3Ena signals and associated
low-power-mode signals. They are distinct from the VSMPS1, VSMPS2 and
VSMPS3 buck converters integrated into AB8500.
type: object
properties:
@ -456,19 +587,22 @@ properties:
const: stericsson,ab8500-ext-regulator
ab8500_ext1:
description: The voltage for the VSMPS1 external regulator
description: External regulator controlled through ExtSupply1Ena and
ExtSupply12LPn
type: object
$ref: /schemas/regulator/regulator.yaml#
unevaluatedProperties: false
ab8500_ext2:
description: The voltage for the VSMPS2 external regulator
description: External regulator controlled through ExtSupply2Ena and
ExtSupply12LPn
type: object
$ref: /schemas/regulator/regulator.yaml#
unevaluatedProperties: false
ab8500_ext3:
description: The voltage for the VSMPS3 external regulator
description: External regulator controlled through ExtSupply3Ena and
ExtSupply3LPn
type: object
$ref: /schemas/regulator/regulator.yaml#
unevaluatedProperties: false

View File

@ -58,6 +58,7 @@ properties:
const: 2
db8500-prcmu-regulators:
deprecated: true
description: Node describing the DB8500 regulators. These are mainly
power rails inside the silicon but some of those are also routed
out to external pins.
@ -207,26 +208,6 @@ properties:
required:
- compatible
- db8500_vape
- db8500_varm
- db8500_vmodem
- db8500_vpll
- db8500_vsmps1
- db8500_vsmps2
- db8500_vsmps3
- db8500_vrf1
- db8500_sva_mmdsp
- db8500_sva_mmdsp_ret
- db8500_sva_pipe
- db8500_sia_mmdsp
- db8500_sia_mmdsp_ret
- db8500_sia_pipe
- db8500_sga
- db8500_b2r2_mcde
- db8500_esram12
- db8500_esram12_ret
- db8500_esram34
- db8500_esram34_ret
additionalProperties: false
@ -294,6 +275,5 @@ required:
- interrupts
- interrupt-controller
- '#interrupt-cells'
- db8500-prcmu-regulators
additionalProperties: false

View File

@ -32,6 +32,7 @@ properties:
- allwinner,sun50i-a64-system-controller
- altr,l3regs
- altr,sdr-ctl
- ambarella,cv75-sec-scratchpad
- amd,pensando-elba-syscon
- amlogic,meson-mx-assist
- amlogic,meson-mx-bootrom

View File

@ -11,9 +11,14 @@ maintainers:
properties:
compatible:
enum:
- ti,bq25703a
- ti,bq25792
oneOf:
- enum:
- ti,bq25703a
- ti,bq25792
- items:
- enum:
- ti,bq25798
- const: ti,bq25792
reg:
const: 0x6b
@ -103,7 +108,8 @@ allOf:
- if:
properties:
compatible:
const: ti,bq25792
contains:
const: ti,bq25792
then:
properties:
input-current-limit-microamp:

View File

@ -0,0 +1,90 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/mfd/ti,keystone-devctrl.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Texas Instruments Keystone Device State Control
maintainers:
- Ivan Khoronzhuk <ivan.khoronzhuk@ti.com>
description:
The Keystone II devices have a set of registers that are used to control the
status of its peripherals. This node is intended to allow access to this
functionality.
properties:
compatible:
items:
- const: ti,keystone-devctrl
- const: syscon
- const: simple-mfd
reg:
maxItems: 1
"#address-cells":
const: 1
"#size-cells":
const: 1
ranges: true
patternProperties:
"^gpio@[0-9a-f]+$":
type: object
description: Keystone DSP GPIO controller
required:
- compatible
"^interrupt-controller@[0-9a-f]+$":
type: object
description: Keystone DSP to ARM interrupt controller
required:
- compatible
"^reset-controller@[0-9a-f]+$":
type: object
description: Keystone reset controller
required:
- compatible
required:
- compatible
- reg
- "#address-cells"
- "#size-cells"
- ranges
additionalProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
device-state-control@2620000 {
compatible = "ti,keystone-devctrl", "syscon", "simple-mfd";
reg = <0x02620000 0x1000>;
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x0 0x02620000 0x1000>;
interrupt-controller@2a0 {
compatible = "ti,keystone-irq";
reg = <0x2a0 0x4>;
interrupts = <GIC_SPI 4 IRQ_TYPE_EDGE_RISING>;
interrupt-controller;
#interrupt-cells = <1>;
ti,syscon-dev = <&devctrl 0x2a0>;
};
reset-controller@328 {
compatible = "ti,keystone-reset";
reg = <0x328 0x10>;
ti,syscon-pll = <&pllctrl 0xe4>;
ti,syscon-dev = <&devctrl 0x328>;
ti,wdt-list = <0>;
};
};

View File

@ -0,0 +1,64 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/mfd/ti,lp3943.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: TI/National Semiconductor LP3943 MFD driver
maintainers:
- Chaosheng Qu <quchaosheng000406@163.com>
description:
LP3943 is an integrated device capable of driving LEDs. It contains two
sub-devices, lp3943-gpio and lp3943-pwm, which are instantiated by the MFD
core from the child nodes described below.
properties:
compatible:
const: ti,lp3943
reg:
maxItems: 1
description: I2C slave address, from 0x60 to 0x67
patternProperties:
"^gpio":
type: object
$ref: /schemas/gpio/trivial-gpio.yaml#
"^pwm":
type: object
$ref: /schemas/pwm/pwm-lp3943.yaml#
required:
- compatible
- reg
additionalProperties: false
examples:
- |
i2c {
#address-cells = <1>;
#size-cells = <0>;
lp3943: gpio@60 {
compatible = "ti,lp3943";
reg = <0x60>;
gpio {
compatible = "ti,lp3943-gpio";
gpio-controller;
#gpio-cells = <2>;
};
pwm {
compatible = "ti,lp3943-pwm";
#pwm-cells = <2>;
ti,pwm0 = <8 9 10>;
ti,pwm1 = <15>;
};
};
};
...

View File

@ -0,0 +1,92 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/mfd/ti,tps61050.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Texas Instruments TPS61050/TPS61052 Boost Converter
maintainers:
- Eduard Bostina <egbostina@gmail.com>
description:
The TP61050/TPS61052 is a high-power "white LED driver". The device
provides LED, GPIO and regulator functionalities.
properties:
compatible:
enum:
- ti,tps61050
- ti,tps61052
reg:
maxItems: 1
regulator:
type: object
$ref: /schemas/regulator/regulator.yaml#
description: Puts the chip in regulator mode.
unevaluatedProperties: false
led:
type: object
$ref: /schemas/leds/common.yaml#
description: Puts the chip in LED mode.
unevaluatedProperties: false
required:
- compatible
- reg
allOf:
- not:
required:
- regulator
- led
additionalProperties: false
examples:
- |
i2c {
#address-cells = <1>;
#size-cells = <0>;
tps61052@33 {
compatible = "ti,tps61052";
reg = <0x33>;
};
};
- |
i2c {
#address-cells = <1>;
#size-cells = <0>;
tps61052@33 {
compatible = "ti,tps61052";
reg = <0x33>;
regulator {
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
regulator-always-on;
};
};
};
- |
#include <dt-bindings/leds/common.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
tps61052@33 {
compatible = "ti,tps61052";
reg = <0x33>;
led {
color = <LED_COLOR_ID_WHITE>;
};
};
};

View File

@ -90,7 +90,6 @@ required:
- reg
- gpio-controller
- '#gpio-cells'
- regulators
examples:
- |

View File

@ -37,6 +37,8 @@ properties:
interrupt-controller: true
wakeup-source: true
'#interrupt-cells':
description: Specifies the IRQ number and flags
const: 2
@ -169,6 +171,12 @@ patternProperties:
vcc7-supply: VRTC input.
vccio-supply: VIO input.
"^.+-hog$":
type: object
required:
- gpio-hog
required:
- compatible
- reg

View File

@ -0,0 +1,156 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/mfd/ti,twl6040.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Texas Instruments TWL6040 family audio codec
maintainers:
- Eduard Bostina <egbostina@gmail.com>
description:
The TWL6040s are 8-channel high quality low-power audio codecs providing
audio, vibra and GPO functionality on OMAP4+ platforms. They are connected
to the host processor via i2c for commands, McPDM for audio data and
commands.
properties:
compatible:
enum:
- ti,twl6040
- ti,twl6041
reg:
const: 0x4b
interrupts:
maxItems: 1
gpio-controller: true
"#gpio-cells":
const: 1
"#clock-cells":
const: 0
ti,audpwron-gpio:
maxItems: 1
description: Power on GPIO line for the twl6040
vio-supply:
description: Regulator for the twl6040 VIO supply
v2v1-supply:
description: Regulator for the twl6040 V2V1 supply
enable-active-high:
type: boolean
description: To power on the twl6040 during boot.
clocks:
minItems: 1
maxItems: 2
clock-names:
minItems: 1
maxItems: 2
items:
enum:
- clk32k
- mclk
vddvibl-supply:
description: Regulator for the left vibra motor
vddvibr-supply:
description: Regulator for the right vibra motor
vibra:
type: object
additionalProperties: false
properties:
ti,vibldrv-res:
$ref: /schemas/types.yaml#/definitions/uint32
description: Resistance parameter for left driver
ti,vibrdrv-res:
$ref: /schemas/types.yaml#/definitions/uint32
description: Resistance parameter for right driver
ti,viblmotor-res:
$ref: /schemas/types.yaml#/definitions/uint32
description: Resistance parameter for left motor
ti,vibrmotor-res:
$ref: /schemas/types.yaml#/definitions/uint32
description: Resistance parameter for right motor
ti,vddvibl-uV:
$ref: /schemas/types.yaml#/definitions/uint32
description: vddvibl default voltage if it needs to be changed
ti,vddvibr-uV:
$ref: /schemas/types.yaml#/definitions/uint32
description: vddvibr default voltage if it needs to be changed
required:
- ti,vibldrv-res
- ti,vibrdrv-res
- ti,viblmotor-res
- ti,vibrmotor-res
required:
- compatible
- reg
- interrupts
- "#clock-cells"
- vio-supply
- v2v1-supply
allOf:
- if:
required:
- vibra
then:
required:
- vddvibl-supply
- vddvibr-supply
additionalProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
audio-codec@4b {
compatible = "ti,twl6040";
reg = <0x4b>;
interrupts = <0 119 IRQ_TYPE_LEVEL_HIGH>;
interrupt-parent = <&gic>;
gpio-controller;
#gpio-cells = <1>;
#clock-cells = <0>;
ti,audpwron-gpio = <&gpio4 31 0>;
vio-supply = <&v1v8>;
v2v1-supply = <&v2v1>;
enable-active-high;
/* regulators for vibra motor */
vddvibl-supply = <&vbat>;
vddvibr-supply = <&vbat>;
vibra {
ti,vibldrv-res = <8>;
ti,vibrdrv-res = <3>;
ti,viblmotor-res = <10>;
ti,vibrmotor-res = <10>;
};
};
};

View File

@ -1,19 +0,0 @@
* Device tree bindings for Texas Instruments keystone device state control
The Keystone II devices have a set of registers that are used to control
the status of its peripherals. This node is intended to allow access to
this functionality.
Required properties:
- compatible: "ti,keystone-devctrl", "syscon"
- reg: contains offset/length value for device state control
registers space.
Example:
devctrl: device-state-control@02620000 {
compatible = "ti,keystone-devctrl", "syscon";
reg = <0x02620000 0x1000>;
};

View File

@ -1,62 +0,0 @@
* Device tree bindings for TI TPS61050/61052 Boost Converters
The TP61050/TPS61052 is a high-power "white LED driver". The
device provides LED, GPIO and regulator functionalities.
Required properties:
- compatible: "ti,tps61050" or "ti,tps61052"
- reg: Specifies the I2C slave address
Optional sub-node:
This subnode selects the chip's operational mode.
There can be at most one single available subnode.
- regulator: presence of this sub-node puts the chip in regulator mode.
see ../regulator/regulator.yaml
- led: presence of this sub-node puts the chip in led mode.
Optional properties:
- function : see ../leds/common.txt
- color : see ../leds/common.txt
- label : see ../leds/common.txt
(deprecated)
Example (GPIO operation only):
i2c0 {
tps61052@33 {
compatible = "ti,tps61052";
reg = <0x33>;
};
};
Example (GPIO + regulator operation):
i2c0 {
tps61052@33 {
compatible = "ti,tps61052";
reg = <0x33>;
regulator {
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
regulator-always-on;
};
};
};
Example (GPIO + led operation):
#include <dt-bindings/leds/common.h>
i2c0 {
tps61052@33 {
compatible = "ti,tps61052";
reg = <0x33>;
led {
color = <LED_COLOR_ID_WHITE>;
};
};
};

View File

@ -1,67 +0,0 @@
Texas Instruments TWL6040 family
The TWL6040s are 8-channel high quality low-power audio codecs providing audio,
vibra and GPO functionality on OMAP4+ platforms.
They are connected to the host processor via i2c for commands, McPDM for audio
data and commands.
Required properties:
- compatible : "ti,twl6040" for twl6040, "ti,twl6041" for twl6041
- reg: must be 0x4b for i2c address
- interrupts: twl6040 has one interrupt line connecteded to the main SoC
- gpio-controller:
- #gpio-cells = <1>: twl6040 provides GPO lines.
- #clock-cells = <0>; twl6040 is a provider of pdmclk which is used by McPDM
- twl6040,audpwron-gpio: Power on GPIO line for the twl6040
- vio-supply: Regulator for the twl6040 VIO supply
- v2v1-supply: Regulator for the twl6040 V2V1 supply
Optional properties, nodes:
- enable-active-high: To power on the twl6040 during boot.
- clocks: phandle to the clk32k and/or to mclk clock provider
- clock-names: Must be "clk32k" for the 32K clock and "mclk" for the MCLK.
Vibra functionality
Required properties:
- vddvibl-supply: Regulator for the left vibra motor
- vddvibr-supply: Regulator for the right vibra motor
- vibra { }: Configuration section for vibra parameters containing the following
properties:
- ti,vibldrv-res: Resistance parameter for left driver
- ti,vibrdrv-res: Resistance parameter for right driver
- ti,viblmotor-res: Resistance parameter for left motor
- ti,viblmotor-res: Resistance parameter for right motor
Optional properties within vibra { } section:
- vddvibl_uV: If the vddvibl default voltage need to be changed
- vddvibr_uV: If the vddvibr default voltage need to be changed
Example:
&i2c1 {
twl6040: twl@4b {
compatible = "ti,twl6040";
interrupts = <0 119 4>;
interrupt-parent = <&gic>;
twl6040,audpwron-gpio = <&gpio4 31 0>;
vio-supply = <&v1v8>;
v2v1-supply = <&v2v1>;
enable-active-high;
/* regulators for vibra motor */
vddvibl-supply = <&vbat>;
vddvibr-supply = <&vbat>;
vibra {
/* Vibra driver, motor resistance parameters */
ti,vibldrv-res = <8>;
ti,vibrdrv-res = <3>;
ti,viblmotor-res = <10>;
ti,vibrmotor-res = <10>;
};
};
};
/include/ "twl6040.dtsi"

View File

@ -0,0 +1,168 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/mfd/x-powers,ac200.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: X-Powers AC200 mixed-signal IC
maintainers:
- James Hilliard <james.hilliard1@gmail.com>
- Jernej Skrabec <jernej.skrabec@gmail.com>
description:
The AC200 is a mixed-signal companion IC containing audio, video, RTC and
Fast Ethernet PHY functions. Its control registers are accessed over I2C.
The audio codec and TV encoder are described by properties of this node.
The Ethernet PHY is described separately on its MDIO bus.
allOf:
- $ref: /schemas/sound/dai-common.yaml#
properties:
compatible:
const: x-powers,ac200
reg:
maxItems: 1
clocks:
maxItems: 1
description:
AC200 input clock. When using the Ethernet PHY, its configured rate must
be 24 or 27 MHz, matching the rates encoded by the documented EPHY clock
selector.
interrupts:
maxItems: 1
description:
The shared, level-triggered, open-drain INTB output for the TV encoder,
Ethernet PHY and RTC interrupts. Omit when INTB is not connected. TV
encoder cable detection status can also be read over I2C without an
interrupt.
'#sound-dai-cells':
const: 0
ac-ldoin-supply:
description:
The 3.3 V supply connected to the AC_LDOIN pin for the audio codec LDO
input. This may be the same regulator as tv-vcc-supply.
tv-vcc-supply:
description:
The 3.3 V supply connected to the TV_VCC pin for the composite-video
DAC. This may be the same regulator as ac-ldoin-supply.
nvmem-cells:
maxItems: 1
description: TV encoder bandgap calibration.
nvmem-cell-names:
items:
- const: bandgap
ports:
$ref: /schemas/graph.yaml#/properties/ports
properties:
port@0:
$ref: /schemas/graph.yaml#/properties/port
description: Input to the TV encoder, carrying CCIR656.
port@1:
$ref: /schemas/graph.yaml#/properties/port
description: Output to the composite-video connector.
required:
- port@0
- port@1
required:
- compatible
- reg
- clocks
dependencies:
'#sound-dai-cells': [ ac-ldoin-supply ]
ports: [ tv-vcc-supply ]
nvmem-cells: [ nvmem-cell-names ]
nvmem-cell-names: [ nvmem-cells ]
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
mixed-signal@10 {
compatible = "x-powers,ac200";
reg = <0x10>;
clocks = <&pwm 5>;
interrupt-parent = <&pio>;
interrupts = <1 20 IRQ_TYPE_LEVEL_LOW>;
#sound-dai-cells = <0>;
ac-ldoin-supply = <&reg_aldo2>;
tv-vcc-supply = <&reg_aldo2>;
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
tve_in: endpoint {
remote-endpoint = <&tcon_out_tve>;
};
};
port@1 {
reg = <1>;
tve_out: endpoint {
remote-endpoint = <&composite_in>;
};
};
};
};
};
- |
i2c {
#address-cells = <1>;
#size-cells = <0>;
mixed-signal@10 {
compatible = "x-powers,ac200";
reg = <0x10>;
clocks = <&pwm 5>;
/* INTB is not connected. */
tv-vcc-supply = <&reg_aldo2>;
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
endpoint {
remote-endpoint = <&tcon_out_tve>;
};
};
port@1 {
reg = <1>;
endpoint {
remote-endpoint = <&composite_in>;
};
};
};
};
};
...

View File

@ -1,63 +0,0 @@
Pincontrol driver for RK805 Power management IC.
RK805 has 2 pins which can be configured as GPIO output only.
Please refer file <devicetree/bindings/pinctrl/pinctrl-bindings.txt>
for details of the common pinctrl bindings used by client devices,
including the meaning of the phrase "pin configuration node".
Optional Pinmux properties:
--------------------------
Following properties are required if default setting of pins are required
at boot.
- pinctrl-names: A pinctrl state named per <pinctrl-bindings.txt>.
- pinctrl[0...n]: Properties to contain the phandle for pinctrl states per
<pinctrl-bindings.txt>.
The pin configurations are defined as child of the pinctrl states node. Each
sub-node have following properties:
Required properties:
------------------
- #gpio-cells: Should be two. The first cell is the pin number and the
second is the GPIO flags.
- gpio-controller: Marks the device node as a GPIO controller.
- pins: List of pins. Valid values of pins properties are: gpio0, gpio1.
First 2 properties must be added in the RK805 PMIC node, documented in
Documentation/devicetree/bindings/mfd/rockchip,rk808.yaml
Optional properties:
-------------------
Following are optional properties defined as pinmux DT binding document
<pinctrl-bindings.txt>. Absence of properties will leave the configuration
on default.
function,
output-low,
output-high.
Valid values for function properties are: gpio.
There are also not customised properties for any GPIO.
Example:
--------
rk805: rk805@18 {
compatible = "rockchip,rk805";
...
gpio-controller;
#gpio-cells = <2>;
pinctrl-names = "default";
pinctrl-0 = <&pmic_int_l>, <&rk805_default>;
rk805_default: pinmux {
gpio01 {
pins = "gpio0", "gpio1";
function = "gpio";
output-high;
};
};
};

View File

@ -1,58 +0,0 @@
TI/National Semiconductor LP3943 PWM controller
Required properties:
- compatible: "ti,lp3943-pwm"
- #pwm-cells: Should be 2. See pwm.yaml in this directory for a
description of the cells format.
Note that this hardware limits the period length to the
range 6250~1600000.
- ti,pwm0 or ti,pwm1: Output pin number(s) for PWM channel 0 or 1.
0 = output 0
1 = output 1
.
.
15 = output 15
Example:
PWM 0 is for RGB LED brightness control
PWM 1 is for brightness control of LP8557 backlight device
&i2c3 {
lp3943@60 {
compatible = "ti,lp3943";
reg = <0x60>;
/*
* PWM 0 : output 8, 9 and 10
* PWM 1 : output 15
*/
pwm3943: pwm {
compatible = "ti,lp3943-pwm";
#pwm-cells = <2>;
ti,pwm0 = <8 9 10>;
ti,pwm1 = <15>;
};
};
};
/* LEDs control with PWM 0 of LP3943 */
pwmleds {
compatible = "pwm-leds";
rgb {
label = "indi::rgb";
pwms = <&pwm3943 0 10000>;
max-brightness = <255>;
};
};
&i2c4 {
/* Backlight control with PWM 1 of LP3943 */
backlight@2c {
compatible = "ti,lp8557";
reg = <0x2c>;
pwms = <&pwm3943 1 10000>;
pwm-names = "lp8557";
};
};

View File

@ -0,0 +1,80 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/pwm/pwm-lp3943.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: TI/National Semiconductor LP3943 PWM controller
maintainers:
- Chaosheng Qu <quchaosheng000406@163.com>
description:
LP3943 has two internal PWM channels. Each channel can be routed to one or
more of the 16 outputs of the device.
Note that the hardware limits the period length to the range 6250~1600000.
allOf:
- $ref: pwm.yaml#
properties:
compatible:
const: ti,lp3943-pwm
"#pwm-cells":
const: 2
ti,pwm0:
description: Output pin number(s) for PWM channel 0.
$ref: /schemas/types.yaml#/definitions/uint32-array
minItems: 1
maxItems: 16
items:
minimum: 0
maximum: 15
ti,pwm1:
description: Output pin number(s) for PWM channel 1.
$ref: /schemas/types.yaml#/definitions/uint32-array
minItems: 1
maxItems: 16
items:
minimum: 0
maximum: 15
anyOf:
- required:
- ti,pwm0
- required:
- ti,pwm1
required:
- compatible
- "#pwm-cells"
unevaluatedProperties: false
examples:
- |
i2c {
#address-cells = <1>;
#size-cells = <0>;
gpio@60 {
compatible = "ti,lp3943";
reg = <0x60>;
/*
* PWM 0 : output 8, 9 and 10
* PWM 1 : output 15
*/
pwm {
compatible = "ti,lp3943-pwm";
#pwm-cells = <2>;
ti,pwm0 = <8 9 10>;
ti,pwm1 = <15>;
};
};
};
...

View File

@ -19007,7 +19007,7 @@ MULTIFUNCTION DEVICES (MFD)
M: Lee Jones <lee@kernel.org>
L: mfd@lists.linux.dev
S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd.git
T: git git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd.git for-mfd-next
F: Documentation/devicetree/bindings/mfd/
F: drivers/mfd/
F: include/dt-bindings/mfd/
@ -27145,7 +27145,7 @@ SYSTEM CONFIGURATION (SYSCON)
M: Lee Jones <lee@kernel.org>
M: Arnd Bergmann <arnd@arndb.de>
S: Supported
T: git git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd.git
T: git git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd.git for-mfd-next
F: drivers/mfd/syscon.c
SYSTEM CONTROL & POWER/MANAGEMENT INTERFACE (SCPI/SCMI) Message Protocol drivers
@ -30133,6 +30133,14 @@ F: drivers/net/wwan/
F: include/linux/wwan.h
F: include/uapi/linux/wwan.h
X-POWERS AC200 DRIVERS
M: Jernej Skrabec <jernej.skrabec@gmail.com>
M: James Hilliard <james.hilliard1@gmail.com>
L: linux-sunxi@lists.linux.dev
S: Maintained
F: Documentation/devicetree/bindings/mfd/x-powers,ac200.yaml
F: drivers/mfd/ac200.c
X-POWERS AXP288 PMIC DRIVERS
M: Hans de Goede <hansg@kernel.org>
S: Maintained

View File

@ -18,14 +18,17 @@
#include <linux/mutex.h>
#include <linux/mfd/core.h>
#include <linux/platform_device.h>
#include <linux/property.h>
#include <linux/regmap.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/units.h>
#include <linux/mfd/lm3533.h>
#define LM3533_ALS_RESISTOR_MIN 1
#define LM3533_ALS_RESISTOR_MAX 127
#define LM3533_ALS_RESISTOR_MIN_OHMS 1575
#define LM3533_ALS_RESISTOR_MAX_OHMS 200000
#define LM3533_ALS_CHANNEL_CURRENT_MAX 2
#define LM3533_ALS_THRESH_MAX 3
#define LM3533_ALS_ZONE_MAX 4
@ -49,7 +52,7 @@
struct lm3533_als {
struct lm3533 *lm3533;
struct regmap *regmap;
struct platform_device *pdev;
unsigned long flags;
@ -57,6 +60,9 @@ struct lm3533_als {
atomic_t zone;
struct mutex thresh_mutex;
u32 r_select;
bool pwm_mode;
};
@ -65,7 +71,7 @@ static int lm3533_als_get_adc(struct iio_dev *indio_dev, bool average,
{
struct lm3533_als *als = iio_priv(indio_dev);
u8 reg;
u8 val;
u32 val;
int ret;
if (average)
@ -73,7 +79,7 @@ static int lm3533_als_get_adc(struct iio_dev *indio_dev, bool average,
else
reg = LM3533_REG_ALS_READ_ADC_RAW;
ret = lm3533_read(als->lm3533, reg, &val);
ret = regmap_read(als->regmap, reg, &val);
if (ret) {
dev_err(&indio_dev->dev, "failed to read adc\n");
return ret;
@ -87,10 +93,10 @@ static int lm3533_als_get_adc(struct iio_dev *indio_dev, bool average,
static int _lm3533_als_get_zone(struct iio_dev *indio_dev, u8 *zone)
{
struct lm3533_als *als = iio_priv(indio_dev);
u8 val;
u32 val;
int ret;
ret = lm3533_read(als->lm3533, LM3533_REG_ALS_ZONE_INFO, &val);
ret = regmap_read(als->regmap, LM3533_REG_ALS_ZONE_INFO, &val);
if (ret) {
dev_err(&indio_dev->dev, "failed to read zone\n");
return ret;
@ -128,7 +134,7 @@ static inline u8 lm3533_als_get_target_reg(unsigned channel, unsigned zone)
}
static int lm3533_als_get_target(struct iio_dev *indio_dev, unsigned channel,
unsigned zone, u8 *val)
unsigned zone, u32 *val)
{
struct lm3533_als *als = iio_priv(indio_dev);
u8 reg;
@ -141,7 +147,7 @@ static int lm3533_als_get_target(struct iio_dev *indio_dev, unsigned channel,
return -EINVAL;
reg = lm3533_als_get_target_reg(channel, zone);
ret = lm3533_read(als->lm3533, reg, val);
ret = regmap_read(als->regmap, reg, val);
if (ret)
dev_err(&indio_dev->dev, "failed to get target current\n");
@ -162,7 +168,7 @@ static int lm3533_als_set_target(struct iio_dev *indio_dev, unsigned channel,
return -EINVAL;
reg = lm3533_als_get_target_reg(channel, zone);
ret = lm3533_write(als->lm3533, reg, val);
ret = regmap_write(als->regmap, reg, val);
if (ret)
dev_err(&indio_dev->dev, "failed to set target current\n");
@ -172,8 +178,8 @@ static int lm3533_als_set_target(struct iio_dev *indio_dev, unsigned channel,
static int lm3533_als_get_current(struct iio_dev *indio_dev, unsigned channel,
int *val)
{
u32 target;
u8 zone;
u8 target;
int ret;
ret = lm3533_als_get_zone(indio_dev, &zone);
@ -272,16 +278,10 @@ static irqreturn_t lm3533_als_isr(int irq, void *dev_id)
static int lm3533_als_set_int_mode(struct iio_dev *indio_dev, int enable)
{
struct lm3533_als *als = iio_priv(indio_dev);
u8 mask = LM3533_ALS_INT_ENABLE_MASK;
u8 val;
int ret;
if (enable)
val = mask;
else
val = 0;
ret = lm3533_update(als->lm3533, LM3533_REG_ALS_ZONE_INFO, val, mask);
ret = regmap_assign_bits(als->regmap, LM3533_REG_ALS_ZONE_INFO,
LM3533_ALS_INT_ENABLE_MASK, enable);
if (ret) {
dev_err(&indio_dev->dev, "failed to set int mode %d\n",
enable);
@ -294,17 +294,16 @@ static int lm3533_als_set_int_mode(struct iio_dev *indio_dev, int enable)
static int lm3533_als_get_int_mode(struct iio_dev *indio_dev, int *enable)
{
struct lm3533_als *als = iio_priv(indio_dev);
u8 mask = LM3533_ALS_INT_ENABLE_MASK;
u8 val;
int ret;
ret = lm3533_read(als->lm3533, LM3533_REG_ALS_ZONE_INFO, &val);
if (ret) {
ret = regmap_test_bits(als->regmap, LM3533_REG_ALS_ZONE_INFO,
LM3533_ALS_INT_ENABLE_MASK);
if (ret < 0) {
dev_err(&indio_dev->dev, "failed to get int mode\n");
return ret;
}
*enable = !!(val & mask);
*enable = ret;
return 0;
}
@ -317,7 +316,7 @@ static inline u8 lm3533_als_get_threshold_reg(unsigned nr, bool raising)
}
static int lm3533_als_get_threshold(struct iio_dev *indio_dev, unsigned nr,
bool raising, u8 *val)
bool raising, u32 *val)
{
struct lm3533_als *als = iio_priv(indio_dev);
u8 reg;
@ -327,7 +326,7 @@ static int lm3533_als_get_threshold(struct iio_dev *indio_dev, unsigned nr,
return -EINVAL;
reg = lm3533_als_get_threshold_reg(nr, raising);
ret = lm3533_read(als->lm3533, reg, val);
ret = regmap_read(als->regmap, reg, val);
if (ret)
dev_err(&indio_dev->dev, "failed to get threshold\n");
@ -338,8 +337,8 @@ static int lm3533_als_set_threshold(struct iio_dev *indio_dev, unsigned nr,
bool raising, u8 val)
{
struct lm3533_als *als = iio_priv(indio_dev);
u8 val2;
u8 reg, reg2;
u32 val2;
int ret;
if (nr > LM3533_ALS_THRESH_MAX)
@ -349,7 +348,7 @@ static int lm3533_als_set_threshold(struct iio_dev *indio_dev, unsigned nr,
reg2 = lm3533_als_get_threshold_reg(nr, !raising);
mutex_lock(&als->thresh_mutex);
ret = lm3533_read(als->lm3533, reg2, &val2);
ret = regmap_read(als->regmap, reg2, &val2);
if (ret) {
dev_err(&indio_dev->dev, "failed to get threshold\n");
goto out;
@ -364,7 +363,7 @@ static int lm3533_als_set_threshold(struct iio_dev *indio_dev, unsigned nr,
goto out;
}
ret = lm3533_write(als->lm3533, reg, val);
ret = regmap_write(als->regmap, reg, val);
if (ret) {
dev_err(&indio_dev->dev, "failed to set threshold\n");
goto out;
@ -376,11 +375,11 @@ static int lm3533_als_set_threshold(struct iio_dev *indio_dev, unsigned nr,
}
static int lm3533_als_get_hysteresis(struct iio_dev *indio_dev, unsigned nr,
u8 *val)
u32 *val)
{
struct lm3533_als *als = iio_priv(indio_dev);
u8 falling;
u8 raising;
u32 falling;
u32 raising;
int ret;
if (nr > LM3533_ALS_THRESH_MAX)
@ -410,7 +409,7 @@ static ssize_t show_thresh_either_en(struct device *dev,
int enable;
int ret;
if (als->irq) {
if (als->irq > 0) {
ret = lm3533_als_get_int_mode(indio_dev, &enable);
if (ret)
return ret;
@ -432,7 +431,7 @@ static ssize_t store_thresh_either_en(struct device *dev,
u8 zone;
int ret;
if (!als->irq)
if (als->irq <= 0)
return -EBUSY;
ret = kstrtoul(buf, 0, &enable);
@ -505,7 +504,7 @@ static ssize_t show_als_attr(struct device *dev,
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct lm3533_als_attribute *als_attr = to_lm3533_als_attr(attr);
u8 val;
u32 val;
int ret;
switch (als_attr->type) {
@ -717,71 +716,51 @@ static const struct attribute_group lm3533_als_attribute_group = {
.attrs = lm3533_als_attributes
};
static int lm3533_als_set_input_mode(struct lm3533_als *als, bool pwm_mode)
static int lm3533_als_setup(struct lm3533_als *als)
{
u8 mask = LM3533_ALS_INPUT_MODE_MASK;
u8 val;
struct device *dev = &als->pdev->dev;
int ret;
if (pwm_mode)
val = mask; /* pwm input */
else
val = 0; /* analog input */
als->pwm_mode = device_property_read_bool(dev, "ti,pwm-mode");
ret = lm3533_update(als->lm3533, LM3533_REG_ALS_CONF, val, mask);
if (ret) {
dev_err(&als->pdev->dev, "failed to set input mode %d\n",
pwm_mode);
return ret;
}
return 0;
}
static int lm3533_als_set_resistor(struct lm3533_als *als, u8 val)
{
int ret;
if (val < LM3533_ALS_RESISTOR_MIN || val > LM3533_ALS_RESISTOR_MAX) {
dev_err(&als->pdev->dev, "invalid resistor value\n");
return -EINVAL;
}
ret = lm3533_write(als->lm3533, LM3533_REG_ALS_RESISTOR_SELECT, val);
if (ret) {
dev_err(&als->pdev->dev, "failed to set resistor\n");
return ret;
}
return 0;
}
static int lm3533_als_setup(struct lm3533_als *als,
const struct lm3533_als_platform_data *pdata)
{
int ret;
ret = lm3533_als_set_input_mode(als, pdata->pwm_mode);
ret = regmap_assign_bits(als->regmap, LM3533_REG_ALS_CONF,
LM3533_ALS_INPUT_MODE_MASK, als->pwm_mode);
if (ret)
return ret;
return dev_err_probe(dev, ret, "failed to set input mode %d\n",
als->pwm_mode);
/* ALS input is always high impedance in PWM-mode. */
if (!pdata->pwm_mode) {
ret = lm3533_als_set_resistor(als, pdata->r_select);
if (ret)
return ret;
}
if (als->pwm_mode)
return 0;
ret = device_property_read_u32(dev, "ti,resistor-ohms",
&als->r_select);
if (ret)
return dev_err_probe(dev, ret,
"failed to ger resistor value\n");
if (als->r_select < LM3533_ALS_RESISTOR_MIN_OHMS ||
als->r_select > LM3533_ALS_RESISTOR_MAX_OHMS)
return dev_err_probe(dev, -EINVAL,
"invalid resistor value\n");
als->r_select = DIV_ROUND_UP(2 * MICRO, 10 * als->r_select);
ret = regmap_write(als->regmap, LM3533_REG_ALS_RESISTOR_SELECT,
als->r_select);
if (ret)
return dev_err_probe(dev, ret, "failed to set resistor\n");
return 0;
}
static int lm3533_als_setup_irq(struct lm3533_als *als, void *dev)
{
u8 mask = LM3533_ALS_INT_ENABLE_MASK;
int ret;
/* Make sure interrupts are disabled. */
ret = lm3533_update(als->lm3533, LM3533_REG_ALS_ZONE_INFO, 0, mask);
ret = regmap_clear_bits(als->regmap, LM3533_REG_ALS_ZONE_INFO,
LM3533_ALS_INT_ENABLE_MASK);
if (ret) {
dev_err(&als->pdev->dev, "failed to disable interrupts\n");
return ret;
@ -801,10 +780,10 @@ static int lm3533_als_setup_irq(struct lm3533_als *als, void *dev)
static int lm3533_als_enable(struct lm3533_als *als)
{
u8 mask = LM3533_ALS_ENABLE_MASK;
int ret;
ret = lm3533_update(als->lm3533, LM3533_REG_ALS_CONF, mask, mask);
ret = regmap_set_bits(als->regmap, LM3533_REG_ALS_CONF,
LM3533_ALS_ENABLE_MASK);
if (ret)
dev_err(&als->pdev->dev, "failed to enable ALS\n");
@ -813,10 +792,10 @@ static int lm3533_als_enable(struct lm3533_als *als)
static int lm3533_als_disable(struct lm3533_als *als)
{
u8 mask = LM3533_ALS_ENABLE_MASK;
int ret;
ret = lm3533_update(als->lm3533, LM3533_REG_ALS_CONF, 0, mask);
ret = regmap_clear_bits(als->regmap, LM3533_REG_ALS_CONF,
LM3533_ALS_ENABLE_MASK);
if (ret)
dev_err(&als->pdev->dev, "failed to disable ALS\n");
@ -831,7 +810,6 @@ static const struct iio_info lm3533_als_info = {
static int lm3533_als_probe(struct platform_device *pdev)
{
const struct lm3533_als_platform_data *pdata;
struct lm3533 *lm3533;
struct lm3533_als *als;
struct iio_dev *indio_dev;
@ -841,12 +819,6 @@ static int lm3533_als_probe(struct platform_device *pdev)
if (!lm3533)
return -EINVAL;
pdata = dev_get_platdata(&pdev->dev);
if (!pdata) {
dev_err(&pdev->dev, "no platform data\n");
return -EINVAL;
}
indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*als));
if (!indio_dev)
return -ENOMEM;
@ -855,25 +827,27 @@ static int lm3533_als_probe(struct platform_device *pdev)
indio_dev->channels = lm3533_als_channels;
indio_dev->num_channels = ARRAY_SIZE(lm3533_als_channels);
indio_dev->name = dev_name(&pdev->dev);
iio_device_set_parent(indio_dev, pdev->dev.parent);
indio_dev->modes = INDIO_DIRECT_MODE;
als = iio_priv(indio_dev);
als->lm3533 = lm3533;
als->regmap = lm3533->regmap;
als->pdev = pdev;
als->irq = lm3533->irq;
als->irq = platform_get_irq_optional(pdev, 0);
if (als->irq == -EPROBE_DEFER)
return -EPROBE_DEFER;
atomic_set(&als->zone, 0);
mutex_init(&als->thresh_mutex);
platform_set_drvdata(pdev, indio_dev);
if (als->irq) {
if (als->irq > 0) {
ret = lm3533_als_setup_irq(als, indio_dev);
if (ret)
return ret;
}
ret = lm3533_als_setup(als, pdata);
ret = lm3533_als_setup(als);
if (ret)
goto err_free_irq;
@ -892,7 +866,7 @@ static int lm3533_als_probe(struct platform_device *pdev)
err_disable:
lm3533_als_disable(als);
err_free_irq:
if (als->irq)
if (als->irq > 0)
free_irq(als->irq, indio_dev);
return ret;
@ -906,13 +880,20 @@ static void lm3533_als_remove(struct platform_device *pdev)
lm3533_als_set_int_mode(indio_dev, false);
iio_device_unregister(indio_dev);
lm3533_als_disable(als);
if (als->irq)
if (als->irq > 0)
free_irq(als->irq, indio_dev);
}
static const struct of_device_id lm3533_als_match_table[] = {
{ .compatible = "ti,lm3533-als" },
{ }
};
MODULE_DEVICE_TABLE(of, lm3533_als_match_table);
static struct platform_driver lm3533_als_driver = {
.driver = {
.name = "lm3533-als",
.of_match_table = lm3533_als_match_table,
},
.probe = lm3533_als_probe,
.remove = lm3533_als_remove,

View File

@ -12,6 +12,8 @@
#include <linux/mfd/core.h>
#include <linux/mutex.h>
#include <linux/platform_device.h>
#include <linux/property.h>
#include <linux/regmap.h>
#include <linux/slab.h>
#include <linux/mfd/lm3533.h>
@ -41,13 +43,18 @@
struct lm3533_led {
struct lm3533 *lm3533;
struct regmap *regmap;
struct lm3533_ctrlbank cb;
struct led_classdev cdev;
int id;
struct mutex mutex;
unsigned long flags;
u32 max_current;
u32 pwm;
bool have_als;
};
@ -80,7 +87,6 @@ static inline u8 lm3533_led_get_pattern_reg(struct lm3533_led *led,
static int lm3533_led_pattern_enable(struct lm3533_led *led, int enable)
{
u8 mask;
u8 val;
int pattern;
int state;
int ret = 0;
@ -96,12 +102,8 @@ static int lm3533_led_pattern_enable(struct lm3533_led *led, int enable)
pattern = lm3533_led_get_pattern(led);
mask = 1 << (2 * pattern);
if (enable)
val = mask;
else
val = 0;
ret = lm3533_update(led->lm3533, LM3533_REG_PATTERN_ENABLE, val, mask);
ret = regmap_assign_bits(led->regmap,
LM3533_REG_PATTERN_ENABLE, mask, enable);
if (ret) {
dev_err(led->cdev.dev, "failed to enable pattern %d (%d)\n",
pattern, enable);
@ -131,7 +133,7 @@ static int lm3533_led_set(struct led_classdev *cdev,
static enum led_brightness lm3533_led_get(struct led_classdev *cdev)
{
struct lm3533_led *led = to_lm3533_led(cdev);
u8 val;
u32 val;
int ret;
ret = lm3533_ctrlbank_get_brightness(&led->cb, &val);
@ -259,7 +261,7 @@ static u8 lm3533_led_delay_set(struct lm3533_led *led, u8 base,
dev_dbg(led->cdev.dev, "%s - %lu: %u (0x%02x)\n", __func__,
*delay, t, val);
reg = lm3533_led_get_pattern_reg(led, base);
ret = lm3533_write(led->lm3533, reg, val);
ret = regmap_write(led->regmap, reg, val);
if (ret)
dev_err(led->cdev.dev, "failed to set delay (%02x)\n", reg);
@ -337,10 +339,10 @@ static ssize_t show_risefalltime(struct device *dev,
struct lm3533_led *led = to_lm3533_led(led_cdev);
ssize_t ret;
u8 reg;
u8 val;
u32 val;
reg = lm3533_led_get_pattern_reg(led, base);
ret = lm3533_read(led->lm3533, reg, &val);
ret = regmap_read(led->regmap, reg, &val);
if (ret)
return ret;
@ -375,7 +377,7 @@ static ssize_t store_risefalltime(struct device *dev,
return -EINVAL;
reg = lm3533_led_get_pattern_reg(led, base);
ret = lm3533_write(led->lm3533, reg, val);
ret = regmap_write(led->regmap, reg, val);
if (ret)
return ret;
@ -405,11 +407,11 @@ static ssize_t show_als_channel(struct device *dev,
struct lm3533_led *led = to_lm3533_led(led_cdev);
unsigned channel;
u8 reg;
u8 val;
u32 val;
int ret;
reg = lm3533_led_get_lv_reg(led, LM3533_REG_CTRLBANK_BCONF_BASE);
ret = lm3533_read(led->lm3533, reg, &val);
ret = regmap_read(led->regmap, reg, &val);
if (ret)
return ret;
@ -441,7 +443,7 @@ static ssize_t store_als_channel(struct device *dev,
mask = LM3533_REG_CTRLBANK_BCONF_ALS_CHANNEL_MASK;
val = channel - 1;
ret = lm3533_update(led->lm3533, reg, val, mask);
ret = regmap_update_bits(led->regmap, reg, mask, val);
if (ret)
return ret;
@ -455,11 +457,11 @@ static ssize_t show_als_en(struct device *dev,
struct lm3533_led *led = to_lm3533_led(led_cdev);
bool enable;
u8 reg;
u8 val;
u32 val;
int ret;
reg = lm3533_led_get_lv_reg(led, LM3533_REG_CTRLBANK_BCONF_BASE);
ret = lm3533_read(led->lm3533, reg, &val);
ret = regmap_read(led->regmap, reg, &val);
if (ret)
return ret;
@ -476,22 +478,15 @@ static ssize_t store_als_en(struct device *dev,
struct lm3533_led *led = to_lm3533_led(led_cdev);
unsigned enable;
u8 reg;
u8 mask;
u8 val;
int ret;
if (kstrtouint(buf, 0, &enable))
return -EINVAL;
reg = lm3533_led_get_lv_reg(led, LM3533_REG_CTRLBANK_BCONF_BASE);
mask = LM3533_REG_CTRLBANK_BCONF_ALS_EN_MASK;
if (enable)
val = mask;
else
val = 0;
ret = lm3533_update(led->lm3533, reg, val, mask);
ret = regmap_assign_bits(led->regmap, reg,
LM3533_REG_CTRLBANK_BCONF_ALS_EN_MASK, enable);
if (ret)
return ret;
@ -504,12 +499,12 @@ static ssize_t show_linear(struct device *dev,
struct led_classdev *led_cdev = dev_get_drvdata(dev);
struct lm3533_led *led = to_lm3533_led(led_cdev);
u8 reg;
u8 val;
u32 val;
int linear;
int ret;
reg = lm3533_led_get_lv_reg(led, LM3533_REG_CTRLBANK_BCONF_BASE);
ret = lm3533_read(led->lm3533, reg, &val);
ret = regmap_read(led->regmap, reg, &val);
if (ret)
return ret;
@ -529,22 +524,15 @@ static ssize_t store_linear(struct device *dev,
struct lm3533_led *led = to_lm3533_led(led_cdev);
unsigned long linear;
u8 reg;
u8 mask;
u8 val;
int ret;
if (kstrtoul(buf, 0, &linear))
return -EINVAL;
reg = lm3533_led_get_lv_reg(led, LM3533_REG_CTRLBANK_BCONF_BASE);
mask = LM3533_REG_CTRLBANK_BCONF_MAPPING_MASK;
if (linear)
val = mask;
else
val = 0;
ret = lm3533_update(led->lm3533, reg, val, mask);
ret = regmap_assign_bits(led->regmap, reg,
LM3533_REG_CTRLBANK_BCONF_MAPPING_MASK, linear);
if (ret)
return ret;
@ -557,7 +545,7 @@ static ssize_t show_pwm(struct device *dev,
{
struct led_classdev *led_cdev = dev_get_drvdata(dev);
struct lm3533_led *led = to_lm3533_led(led_cdev);
u8 val;
u32 val;
int ret;
ret = lm3533_ctrlbank_get_pwm(&led->cb, &val);
@ -573,10 +561,10 @@ static ssize_t store_pwm(struct device *dev,
{
struct led_classdev *led_cdev = dev_get_drvdata(dev);
struct lm3533_led *led = to_lm3533_led(led_cdev);
u8 val;
u32 val;
int ret;
if (kstrtou8(buf, 0, &val))
if (kstrtou32(buf, 0, &val))
return -EINVAL;
ret = lm3533_ctrlbank_set_pwm(&led->cb, val);
@ -615,7 +603,7 @@ static umode_t lm3533_led_attr_is_visible(struct kobject *kobj,
if (attr == &dev_attr_als_channel.attr ||
attr == &dev_attr_als_en.attr) {
if (!led->lm3533->have_als)
if (!led->have_als)
mode = 0;
}
@ -632,22 +620,20 @@ static const struct attribute_group *lm3533_led_attribute_groups[] = {
NULL
};
static int lm3533_led_setup(struct lm3533_led *led,
struct lm3533_led_platform_data *pdata)
static int lm3533_led_setup(struct lm3533_led *led)
{
int ret;
ret = lm3533_ctrlbank_set_max_current(&led->cb, pdata->max_current);
ret = lm3533_ctrlbank_set_max_current(&led->cb, led->max_current);
if (ret)
return ret;
return lm3533_ctrlbank_set_pwm(&led->cb, pdata->pwm);
return lm3533_ctrlbank_set_pwm(&led->cb, led->pwm);
}
static int lm3533_led_probe(struct platform_device *pdev)
{
struct lm3533 *lm3533;
struct lm3533_led_platform_data *pdata;
struct lm3533_led *led;
int ret;
@ -657,12 +643,6 @@ static int lm3533_led_probe(struct platform_device *pdev)
if (!lm3533)
return -EINVAL;
pdata = dev_get_platdata(&pdev->dev);
if (!pdata) {
dev_err(&pdev->dev, "no platform data\n");
return -EINVAL;
}
if (pdev->id < 0 || pdev->id >= LM3533_LVCTRLBANK_COUNT) {
dev_err(&pdev->dev, "illegal LED id %d\n", pdev->id);
return -EINVAL;
@ -672,9 +652,9 @@ static int lm3533_led_probe(struct platform_device *pdev)
if (!led)
return -ENOMEM;
led->lm3533 = lm3533;
led->cdev.name = pdata->name;
led->cdev.default_trigger = pdata->default_trigger;
led->regmap = lm3533->regmap;
led->have_als = lm3533->have_als;
led->cdev.brightness_set_blocking = lm3533_led_set;
led->cdev.brightness_get = lm3533_led_get;
led->cdev.blink_set = lm3533_led_blink_set;
@ -682,19 +662,28 @@ static int lm3533_led_probe(struct platform_device *pdev)
led->cdev.groups = lm3533_led_attribute_groups;
led->id = pdev->id;
led->cdev.name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%s-%d",
pdev->name, led->id);
if (!led->cdev.name)
return -ENOMEM;
led->cdev.default_trigger = "none";
device_property_read_string(&pdev->dev, "linux,default-trigger",
&led->cdev.default_trigger);
mutex_init(&led->mutex);
/* The class framework makes a callback to get brightness during
* registration so use parent device (for error reporting) until
* registered.
*/
led->cb.lm3533 = lm3533;
led->cb.regmap = lm3533->regmap;
led->cb.id = lm3533_led_get_ctrlbank_id(led);
led->cb.dev = lm3533->dev;
platform_set_drvdata(pdev, led);
ret = led_classdev_register(pdev->dev.parent, &led->cdev);
ret = led_classdev_register(&pdev->dev, &led->cdev);
if (ret) {
dev_err(&pdev->dev, "failed to register LED %d\n", pdev->id);
return ret;
@ -702,7 +691,14 @@ static int lm3533_led_probe(struct platform_device *pdev)
led->cb.dev = led->cdev.dev;
ret = lm3533_led_setup(led, pdata);
device_property_read_u32(&pdev->dev, "led-max-microamp",
&led->max_current);
led->max_current = clamp(led->max_current, LM3533_MAX_CURRENT_MIN,
LM3533_MAX_CURRENT_MAX);
device_property_read_u32(&pdev->dev, "ti,pwm-config-mask", &led->pwm);
ret = lm3533_led_setup(led);
if (ret)
goto err_deregister;
@ -739,9 +735,16 @@ static void lm3533_led_shutdown(struct platform_device *pdev)
lm3533_led_set(&led->cdev, LED_OFF); /* disable blink */
}
static const struct of_device_id lm3533_led_match_table[] = {
{ .compatible = "ti,lm3533-leds" },
{ }
};
MODULE_DEVICE_TABLE(of, lm3533_led_match_table);
static struct platform_driver lm3533_led_driver = {
.driver = {
.name = "lm3533-leds",
.of_match_table = lm3533_led_match_table,
},
.probe = lm3533_led_probe,
.remove = lm3533_led_remove,

View File

@ -275,10 +275,10 @@ static int device_gpadc_init(struct pm80x_chip *chip,
goto out;
/*
* the defult of PM800 is GPADC operates at 100Ks/s rate
* the default of PM800 is GPADC operates at 100Ks/s rate
* and Number of GPADC slots with active current bias prior
* to GPADC sampling = 1 slot for all GPADCs set for
* Temprature mesurmants
* Temperature measurements
*/
mask = (PM800_GPADC_GP_BIAS_EN0 | PM800_GPADC_GP_BIAS_EN1 |
PM800_GPADC_GP_BIAS_EN2 | PM800_GPADC_GP_BIAS_EN3);

View File

@ -205,6 +205,20 @@ config MFD_AC100
This driver include only the core APIs. You have to select individual
components like codecs or RTC under the corresponding menus.
config MFD_AC200
tristate "X-Powers AC200"
depends on COMMON_CLK
depends on I2C
depends on OF
select MFD_CORE
select REGMAP_I2C
help
Support for the X-Powers AC200 mixed-signal companion IC. The AC200
contains audio, video, RTC and Fast Ethernet PHY functions and is
co-packaged with some Allwinner H6 and H616 SoCs. This driver provides
the shared register access and instantiates the individual function
devices.
config MFD_AXP20X
tristate
select MFD_CORE
@ -1006,6 +1020,8 @@ config MFD_MAX77705
depends on I2C
select MFD_CORE
select MFD_SIMPLE_MFD_I2C
select REGMAP_I2C
select REGMAP_IRQ
help
Say yes here to add support for Maxim Integrated MAX77705 PMIC.
This is a Power Management IC with Charger, safe LDOs, Flash, Haptic

View File

@ -150,6 +150,7 @@ obj-$(CONFIG_MFD_DA9052_SPI) += da9052-spi.o
obj-$(CONFIG_MFD_DA9052_I2C) += da9052-i2c.o
obj-$(CONFIG_MFD_AC100) += ac100.o
obj-$(CONFIG_MFD_AC200) += ac200.o
obj-$(CONFIG_MFD_AXP20X) += axp20x.o
obj-$(CONFIG_MFD_AXP20X_I2C) += axp20x-i2c.o
obj-$(CONFIG_MFD_AXP20X_RSB) += axp20x-rsb.o

View File

@ -125,7 +125,7 @@ static u8 turn_on_stat_set;
/*
* Map interrupt numbers to the LATCH and MASK register offsets, Interrupt
* numbers are indexed into this array with (num / 8). The interupts are
* numbers are indexed into this array with (num / 8). The interrupts are
* defined in linux/mfd/ab8500.h
*
* This is one off from the register names, i.e. AB8500_IT_MASK1_REG is at
@ -1194,39 +1194,41 @@ static int ab8500_probe(struct platform_device *pdev)
return ret;
if (is_ab9540(ab8500))
ret = mfd_add_devices(ab8500->dev, 0, ab9540_devs,
ARRAY_SIZE(ab9540_devs), NULL,
0, ab8500->domain);
ret = devm_mfd_add_devices(ab8500->dev, 0, ab9540_devs,
ARRAY_SIZE(ab9540_devs), NULL,
0, ab8500->domain);
else if (is_ab8540(ab8500)) {
ret = mfd_add_devices(ab8500->dev, 0, ab8540_devs,
ARRAY_SIZE(ab8540_devs), NULL,
0, ab8500->domain);
ret = devm_mfd_add_devices(ab8500->dev, 0, ab8540_devs,
ARRAY_SIZE(ab8540_devs), NULL,
0, ab8500->domain);
if (ret)
return ret;
if (is_ab8540_1p2_or_earlier(ab8500))
ret = mfd_add_devices(ab8500->dev, 0, ab8540_cut1_devs,
ARRAY_SIZE(ab8540_cut1_devs), NULL,
0, ab8500->domain);
ret = devm_mfd_add_devices(ab8500->dev, 0,
ab8540_cut1_devs,
ARRAY_SIZE(ab8540_cut1_devs),
NULL, 0, ab8500->domain);
else /* ab8540 >= cut2 */
ret = mfd_add_devices(ab8500->dev, 0, ab8540_cut2_devs,
ARRAY_SIZE(ab8540_cut2_devs), NULL,
0, ab8500->domain);
ret = devm_mfd_add_devices(ab8500->dev, 0,
ab8540_cut2_devs,
ARRAY_SIZE(ab8540_cut2_devs),
NULL, 0, ab8500->domain);
} else if (is_ab8505(ab8500))
ret = mfd_add_devices(ab8500->dev, 0, ab8505_devs,
ARRAY_SIZE(ab8505_devs), NULL,
0, ab8500->domain);
ret = devm_mfd_add_devices(ab8500->dev, 0, ab8505_devs,
ARRAY_SIZE(ab8505_devs), NULL,
0, ab8500->domain);
else
ret = mfd_add_devices(ab8500->dev, 0, ab8500_devs,
ARRAY_SIZE(ab8500_devs), NULL,
0, ab8500->domain);
ret = devm_mfd_add_devices(ab8500->dev, 0, ab8500_devs,
ARRAY_SIZE(ab8500_devs), NULL,
0, ab8500->domain);
if (ret)
return ret;
/* Add battery management devices */
ret = mfd_add_devices(ab8500->dev, 0, ab8500_bm_devs,
ARRAY_SIZE(ab8500_bm_devs), NULL,
0, ab8500->domain);
ret = devm_mfd_add_devices(ab8500->dev, 0, ab8500_bm_devs,
ARRAY_SIZE(ab8500_bm_devs), NULL,
0, ab8500->domain);
if (ret)
dev_err(ab8500->dev, "error adding bm devices\n");

222
drivers/mfd/ac200.c Normal file
View File

@ -0,0 +1,222 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* X-Powers AC200 Core driver
*
* Copyright (C) 2019 Jernej Skrabec <jernej.skrabec@gmail.com>
* Copyright (C) 2026 James Hilliard <james.hilliard1@gmail.com>
*/
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/irq.h>
#include <linux/mfd/core.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/regmap.h>
#define AC200_SYS_CONTROL_REG 0x0002
#define AC200_SYS_CONTROL_CHIP_RESET_DEASSERT BIT(0)
#define AC200_SYS_IRQ_ENABLE_REG 0x0004
#define AC200_SYS_IRQ_INTB_ENABLE BIT(15)
#define AC200_SYS_IRQ_INTB_ACTIVE_HIGH BIT(14)
#define AC200_SYS_IRQ_RTC BIT(12)
#define AC200_SYS_IRQ_EPHY BIT(8)
#define AC200_SYS_IRQ_TVE BIT(4)
/* Interface register accessible from every register page. */
#define AC200_TWI_REG_ADDR_H 0x00fe
#define AC200_MAX_REG 0xa1f2
static const struct regmap_range_cfg ac200_range_cfg[] = {
{
.range_max = AC200_MAX_REG,
.selector_reg = AC200_TWI_REG_ADDR_H,
.selector_mask = 0xff,
.window_len = 256,
},
};
/*
* Each AC200 sub-block can reset independently, invalidating its register
* contents without regmap's knowledge. Cache only the common page selector;
* this avoids a selector read-modify-write for every access on the same page
* without ever returning stale functional-register values.
*/
static bool ac200_volatile_reg(struct device *dev, unsigned int reg)
{
return reg != AC200_TWI_REG_ADDR_H;
}
static const struct regmap_config ac200_regmap_config = {
.name = "ac200",
.reg_bits = 8,
.reg_stride = 2,
.val_bits = 16,
.ranges = ac200_range_cfg,
.num_ranges = ARRAY_SIZE(ac200_range_cfg),
.max_register = AC200_MAX_REG,
.volatile_reg = ac200_volatile_reg,
.cache_type = REGCACHE_MAPLE,
};
static const char * const ac200_codec_supplies[] = {
"ac-ldoin",
};
static const char * const ac200_tve_supplies[] = {
"tv-vcc",
};
static const struct resource ac200_tve_resources[] = {
DEFINE_RES_IRQ_NAMED(0, "intb"),
};
#define AC200_CELL(_name, _supplies, _resources) \
{ \
.name = (_name), \
.parent_supplies = (_supplies), \
.num_parent_supplies = ARRAY_SIZE(_supplies), \
.resources = (_resources), \
.num_resources = MFD_RES_SIZE(_resources), \
}
static const struct mfd_cell ac200_cells[] = {
AC200_CELL("ac200-codec", ac200_codec_supplies, NULL),
AC200_CELL("ac200-tve", ac200_tve_supplies, ac200_tve_resources),
};
static const struct mfd_cell ac200_noirq_cells[] = {
AC200_CELL("ac200-codec", ac200_codec_supplies, NULL),
AC200_CELL("ac200-tve", ac200_tve_supplies, NULL),
};
static void ac200_disable_intb(void *data)
{
struct regmap *regmap = data;
int ret;
ret = regmap_clear_bits(regmap, AC200_SYS_IRQ_ENABLE_REG, AC200_SYS_IRQ_INTB_ENABLE);
if (ret)
dev_err(regmap_get_device(regmap), "failed to disable INTB: %d\n", ret);
}
static int ac200_init_irq(struct device *dev, struct regmap *regmap, int irq)
{
unsigned int trigger;
u16 value = 0;
int ret;
trigger = irq_get_trigger_type(irq);
switch (trigger) {
case IRQ_TYPE_LEVEL_HIGH:
value |= AC200_SYS_IRQ_INTB_ACTIVE_HIGH;
break;
case IRQ_TYPE_NONE:
case IRQ_TYPE_LEVEL_LOW:
break;
default:
return dev_err_probe(dev, -EINVAL,
"INTB is level triggered, not type %u\n", trigger);
}
/* Mask every source before enabling the shared output. */
ret = regmap_update_bits(regmap, AC200_SYS_IRQ_ENABLE_REG,
AC200_SYS_IRQ_INTB_ENABLE | AC200_SYS_IRQ_INTB_ACTIVE_HIGH |
AC200_SYS_IRQ_RTC | AC200_SYS_IRQ_EPHY | AC200_SYS_IRQ_TVE, value);
if (ret)
return ret;
/* Children are removed before INTB is disabled and the regmap released. */
ret = devm_add_action_or_reset(dev, ac200_disable_intb, regmap);
if (ret)
return ret;
if (trigger == IRQ_TYPE_NONE) {
ret = irq_set_irq_type(irq, IRQ_TYPE_LEVEL_LOW);
if (ret)
return dev_err_probe(dev, ret, "failed to set INTB trigger\n");
}
/*
* Function drivers request INTB with IRQF_SHARED | IRQF_ONESHOT before
* enabling their own source. They check and clear their own status and
* mask their source before freeing the IRQ. No IRQ domain is needed.
*/
return regmap_set_bits(regmap, AC200_SYS_IRQ_ENABLE_REG, AC200_SYS_IRQ_INTB_ENABLE);
}
static int ac200_probe(struct i2c_client *client)
{
const struct mfd_cell *cells = ac200_noirq_cells;
unsigned int num_cells = ARRAY_SIZE(ac200_noirq_cells);
struct device *dev = &client->dev;
struct regmap *regmap;
struct clk *clk;
int ret;
clk = devm_clk_get_enabled(dev, NULL);
if (IS_ERR(clk))
return dev_err_probe(dev, PTR_ERR(clk), "failed to enable input clock\n");
ret = devm_clk_rate_exclusive_get(dev, clk);
if (ret)
return dev_err_probe(dev, ret, "failed to lock clock rate\n");
/*
* No minimum delay is documented. Retain the vendor resume path's 40 ms
* wait after enabling the input clock and before register access.
*/
msleep(40);
regmap = devm_regmap_init_i2c(client, &ac200_regmap_config);
if (IS_ERR(regmap))
return dev_err_probe(dev, PTR_ERR(regmap), "failed to initialize regmap\n");
ret = regmap_set_bits(regmap, AC200_SYS_CONTROL_REG, AC200_SYS_CONTROL_CHIP_RESET_DEASSERT);
if (ret)
return ret;
if (client->irq > 0) {
ret = ac200_init_irq(dev, regmap, client->irq);
if (ret)
return ret;
cells = ac200_cells;
num_cells = ARRAY_SIZE(ac200_cells);
}
/* Function drivers read their firmware properties from the parent. */
ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO, cells, num_cells,
NULL, client->irq, NULL);
if (ret)
return dev_err_probe(dev, ret, "failed to add function devices\n");
return 0;
}
static const struct of_device_id ac200_of_match[] = {
{ .compatible = "x-powers,ac200" },
{ }
};
MODULE_DEVICE_TABLE(of, ac200_of_match);
static const struct i2c_device_id ac200_i2c_ids[] = {
{ .name = "ac200" },
{ }
};
MODULE_DEVICE_TABLE(i2c, ac200_i2c_ids);
static struct i2c_driver ac200_driver = {
.driver = {
.name = "ac200",
.of_match_table = ac200_of_match,
},
.probe = ac200_probe,
.id_table = ac200_i2c_ids,
};
module_i2c_driver(ac200_driver);
MODULE_AUTHOR("Jernej Skrabec <jernej.skrabec@gmail.com>");
MODULE_AUTHOR("James Hilliard <james.hilliard1@gmail.com>");
MODULE_DESCRIPTION("X-Powers AC200 Core driver");
MODULE_LICENSE("GPL");

View File

@ -52,8 +52,18 @@ static const struct regmap_access_table bq25792_writeable_regs = {
};
static const struct regmap_range bq25792_volatile_reg_ranges[] = {
regmap_reg_range(BQ25792_REG05_INPUT_VOLTAGE_LIMIT,
BQ25792_REG06_INPUT_CURRENT_LIMIT + 1),
regmap_reg_range(BQ25792_REG0F_CHARGER_CONTROL_0,
BQ25792_REG0F_CHARGER_CONTROL_0),
regmap_reg_range(BQ25792_REG11_CHARGER_CONTROL_2,
BQ25792_REG11_CHARGER_CONTROL_2),
regmap_reg_range(BQ25792_REG13_CHARGER_CONTROL_4,
BQ25792_REG13_CHARGER_CONTROL_4),
regmap_reg_range(BQ25792_REG19_ICO_CURRENT_LIMIT,
BQ25792_REG27_FAULT_FLAG_1),
regmap_reg_range(BQ25792_REG2E_ADC_CONTROL,
BQ25792_REG2E_ADC_CONTROL),
regmap_reg_range(BQ25792_REG31_IBUS_ADC,
BQ25792_REG47_DPDM_DRIVER),
};

View File

@ -54,10 +54,18 @@ static int cs42l43_i2c_probe(struct i2c_client *i2c)
return cs42l43_dev_probe(cs42l43);
}
static void cs42l43_i2c_remove(struct i2c_client *i2c)
{
struct cs42l43 *cs42l43 = dev_get_drvdata(&i2c->dev);
cs42l43_dev_remove(cs42l43);
}
#if IS_ENABLED(CONFIG_OF)
static const struct of_device_id cs42l43_of_match[] = {
{ .compatible = "cirrus,cs42l43", .data = (void *)CS42L43_DEVID_VAL },
{ .compatible = "cirrus,cs42l43b", .data = (void *)CS42L43B_DEVID_VAL },
{ .compatible = "cirrus,cs42l44", .data = (void *)CS42L43B_DEVID_VAL },
{}
};
MODULE_DEVICE_TABLE(of, cs42l43_of_match);
@ -67,6 +75,7 @@ MODULE_DEVICE_TABLE(of, cs42l43_of_match);
static const struct acpi_device_id cs42l43_acpi_match[] = {
{ "CSC4243", CS42L43_DEVID_VAL },
{ "CSC2A3B", CS42L43B_DEVID_VAL },
{ "CSC4244", CS42L43B_DEVID_VAL },
{}
};
MODULE_DEVICE_TABLE(acpi, cs42l43_acpi_match);
@ -81,6 +90,7 @@ static struct i2c_driver cs42l43_i2c_driver = {
},
.probe = cs42l43_i2c_probe,
.remove = cs42l43_i2c_remove,
};
module_i2c_driver(cs42l43_i2c_driver);

View File

@ -180,9 +180,17 @@ static int cs42l43_sdw_probe(struct sdw_slave *sdw, const struct sdw_device_id *
return cs42l43_dev_probe(cs42l43);
}
static void cs42l43_sdw_remove(struct sdw_slave *sdw)
{
struct cs42l43 *cs42l43 = dev_get_drvdata(&sdw->dev);
cs42l43_dev_remove(cs42l43);
}
static const struct sdw_device_id cs42l43_sdw_id[] = {
SDW_SLAVE_ENTRY(0x01FA, 0x4243, (void *)CS42L43_DEVID_VAL),
SDW_SLAVE_ENTRY(0x01FA, 0x2A3B, (void *)CS42L43B_DEVID_VAL),
SDW_SLAVE_ENTRY(0x01FA, 0x4244, (void *)CS42L43B_DEVID_VAL),
{ }
};
MODULE_DEVICE_TABLE(sdw, cs42l43_sdw_id);
@ -194,6 +202,7 @@ static struct sdw_driver cs42l43_sdw_driver = {
},
.probe = cs42l43_sdw_probe,
.remove = cs42l43_sdw_remove,
.id_table = cs42l43_sdw_id,
.ops = &cs42l43_sdw_ops,
};

View File

@ -959,6 +959,7 @@ static void cs42l43_boot_work(struct work_struct *work)
{
struct cs42l43 *cs42l43 = container_of(work, struct cs42l43, boot_work);
unsigned int devid, revid, otp;
bool valid_id;
int ret;
ret = cs42l43_wait_for_attach(cs42l43);
@ -973,19 +974,24 @@ static void cs42l43_boot_work(struct work_struct *work)
switch (devid) {
case CS42L43_DEVID_VAL:
valid_id = (cs42l43->variant_id == CS42L43_DEVID_VAL);
break;
case CS42L43B_DEVID_VAL:
if (devid != cs42l43->variant_id) {
dev_err(cs42l43->dev,
"Device ID (0x%06x) does not match variant ID (0x%06lx)\n",
devid, cs42l43->variant_id);
goto err;
}
case CS42L44_DEVID_VAL:
valid_id = (cs42l43->variant_id == CS42L43B_DEVID_VAL);
break;
default:
dev_err(cs42l43->dev, "Unrecognised devid: 0x%06x\n", devid);
goto err;
}
if (!valid_id) {
dev_err(cs42l43->dev,
"Device ID (0x%06x) does not match variant ID (0x%06lx)\n",
devid, cs42l43->variant_id);
goto err;
}
ret = regmap_read(cs42l43->regmap, CS42L43_REVID, &revid);
if (ret) {
dev_err(cs42l43->dev, "Failed to read rev: %d\n", ret);
@ -1099,15 +1105,19 @@ static int cs42l43_power_down(struct cs42l43 *cs42l43)
return 0;
}
static void cs42l43_dev_remove(void *data)
static void cs42l43_dev_power_down(void *data)
{
struct cs42l43 *cs42l43 = data;
cancel_work_sync(&cs42l43->boot_work);
cs42l43_power_down(cs42l43);
}
void cs42l43_dev_remove(struct cs42l43 *cs42l43)
{
flush_work(&cs42l43->boot_work);
}
EXPORT_SYMBOL_NS_GPL(cs42l43_dev_remove, "MFD_CS42L43");
int cs42l43_dev_probe(struct cs42l43 *cs42l43)
{
int i, ret;
@ -1153,7 +1163,7 @@ int cs42l43_dev_probe(struct cs42l43 *cs42l43)
if (ret)
return ret;
ret = devm_add_action_or_reset(cs42l43->dev, cs42l43_dev_remove, cs42l43);
ret = devm_add_action_or_reset(cs42l43->dev, cs42l43_dev_power_down, cs42l43);
if (ret)
return ret;

View File

@ -25,5 +25,6 @@ bool cs42l43_precious_register(struct device *dev, unsigned int reg);
bool cs42l43_volatile_register(struct device *dev, unsigned int reg);
int cs42l43_dev_probe(struct cs42l43 *cs42l43);
void cs42l43_dev_remove(struct cs42l43 *cs42l43);
#endif /* CS42L43_CORE_INT_H */

View File

@ -421,6 +421,14 @@ static irqreturn_t da903x_irq_handler(int irq, void *data)
return IRQ_HANDLED;
}
static void da903x_cancel_irq_work(void *data)
{
struct da903x_chip *chip = data;
disable_irq(chip->client->irq);
cancel_work_sync(&chip->irq_work);
}
static const struct da903x_chip_ops da903x_ops[] = {
[0] = {
.init_chip = da9030_init_chip,
@ -456,6 +464,13 @@ static int da903x_remove_subdevs(struct da903x_chip *chip)
return device_for_each_child(chip->dev, NULL, __remove_subdev);
}
static void da903x_remove_subdevs_action(void *data)
{
struct da903x_chip *chip = data;
da903x_remove_subdevs(chip);
}
static int da903x_add_subdevs(struct da903x_chip *chip,
struct da903x_platform_data *pdata)
{
@ -484,7 +499,6 @@ static int da903x_add_subdevs(struct da903x_chip *chip,
return 0;
failed:
da903x_remove_subdevs(chip);
return ret;
}
@ -520,6 +534,11 @@ static int da903x_probe(struct i2c_client *client)
chip->ops->mask_events(chip, chip->events_mask);
chip->ops->read_events(chip, &tmp);
ret = devm_add_action_or_reset(&client->dev,
da903x_remove_subdevs_action, chip);
if (ret)
return ret;
ret = devm_request_irq(&client->dev, client->irq, da903x_irq_handler,
IRQF_TRIGGER_FALLING,
"da903x", chip);
@ -529,22 +548,19 @@ static int da903x_probe(struct i2c_client *client)
return ret;
}
ret = devm_add_action_or_reset(&client->dev, da903x_cancel_irq_work,
chip);
if (ret)
return ret;
return da903x_add_subdevs(chip, pdata);
}
static void da903x_remove(struct i2c_client *client)
{
struct da903x_chip *chip = i2c_get_clientdata(client);
da903x_remove_subdevs(chip);
}
static struct i2c_driver da903x_driver = {
.driver = {
.name = "da903x",
},
.probe = da903x_probe,
.remove = da903x_remove,
.id_table = da903x_id_table,
};

View File

@ -203,36 +203,36 @@ static const struct mfd_cell da9061_devs_noirq[] = {
};
static const struct resource da9062_core_resources[] = {
DEFINE_RES_NAMED(DA9062_IRQ_VDD_WARN, 1, "VDD_WARN", IORESOURCE_IRQ),
DEFINE_RES_IRQ_NAMED(DA9062_IRQ_VDD_WARN, "VDD_WARN"),
};
static const struct resource da9062_regulators_resources[] = {
DEFINE_RES_NAMED(DA9062_IRQ_LDO_LIM, 1, "LDO_LIM", IORESOURCE_IRQ),
DEFINE_RES_IRQ_NAMED(DA9062_IRQ_LDO_LIM, "LDO_LIM"),
};
static const struct resource da9062_thermal_resources[] = {
DEFINE_RES_NAMED(DA9062_IRQ_TEMP, 1, "THERMAL", IORESOURCE_IRQ),
DEFINE_RES_IRQ_NAMED(DA9062_IRQ_TEMP, "THERMAL"),
};
static const struct resource da9062_wdt_resources[] = {
DEFINE_RES_NAMED(DA9062_IRQ_WDG_WARN, 1, "WD_WARN", IORESOURCE_IRQ),
DEFINE_RES_IRQ_NAMED(DA9062_IRQ_WDG_WARN, "WD_WARN"),
};
static const struct resource da9062_rtc_resources[] = {
DEFINE_RES_NAMED(DA9062_IRQ_ALARM, 1, "ALARM", IORESOURCE_IRQ),
DEFINE_RES_NAMED(DA9062_IRQ_TICK, 1, "TICK", IORESOURCE_IRQ),
DEFINE_RES_IRQ_NAMED(DA9062_IRQ_ALARM, "ALARM"),
DEFINE_RES_IRQ_NAMED(DA9062_IRQ_TICK, "TICK"),
};
static const struct resource da9062_onkey_resources[] = {
DEFINE_RES_NAMED(DA9062_IRQ_ONKEY, 1, "ONKEY", IORESOURCE_IRQ),
DEFINE_RES_IRQ_NAMED(DA9062_IRQ_ONKEY, "ONKEY"),
};
static const struct resource da9062_gpio_resources[] = {
DEFINE_RES_NAMED(DA9062_IRQ_GPI0, 1, "GPI0", IORESOURCE_IRQ),
DEFINE_RES_NAMED(DA9062_IRQ_GPI1, 1, "GPI1", IORESOURCE_IRQ),
DEFINE_RES_NAMED(DA9062_IRQ_GPI2, 1, "GPI2", IORESOURCE_IRQ),
DEFINE_RES_NAMED(DA9062_IRQ_GPI3, 1, "GPI3", IORESOURCE_IRQ),
DEFINE_RES_NAMED(DA9062_IRQ_GPI4, 1, "GPI4", IORESOURCE_IRQ),
DEFINE_RES_IRQ_NAMED(DA9062_IRQ_GPI0, "GPI0"),
DEFINE_RES_IRQ_NAMED(DA9062_IRQ_GPI1, "GPI1"),
DEFINE_RES_IRQ_NAMED(DA9062_IRQ_GPI2, "GPI2"),
DEFINE_RES_IRQ_NAMED(DA9062_IRQ_GPI3, "GPI3"),
DEFINE_RES_IRQ_NAMED(DA9062_IRQ_GPI4, "GPI4"),
};
static const struct mfd_cell da9062_devs_irq[] = {

View File

@ -450,7 +450,7 @@ static int da9150_probe(struct i2c_client *client)
da9150->irq_base = regmap_irq_chip_get_base(da9150->regmap_irq_data);
enable_irq_wake(da9150->irq);
da9150->irq_wake_enabled = !enable_irq_wake(da9150->irq);
ret = mfd_add_devices(da9150->dev, -1, da9150_devs,
ARRAY_SIZE(da9150_devs), NULL,
@ -463,6 +463,8 @@ static int da9150_probe(struct i2c_client *client)
return 0;
mfd_fail:
if (da9150->irq_wake_enabled)
disable_irq_wake(da9150->irq);
regmap_del_irq_chip(da9150->irq, da9150->regmap_irq_data);
regmap_irq_fail:
i2c_unregister_device(da9150->core_qif);
@ -474,8 +476,10 @@ static void da9150_remove(struct i2c_client *client)
{
struct da9150 *da9150 = i2c_get_clientdata(client);
regmap_del_irq_chip(da9150->irq, da9150->regmap_irq_data);
mfd_remove_devices(da9150->dev);
if (da9150->irq_wake_enabled)
disable_irq_wake(da9150->irq);
regmap_del_irq_chip(da9150->irq, da9150->regmap_irq_data);
i2c_unregister_device(da9150->core_qif);
}

View File

@ -8,7 +8,9 @@
* Mika Westerberg <mika.westerberg@linux.intel.com>
*/
#include <linux/acpi.h>
#include <linux/device.h>
#include <linux/dmi.h>
#include <linux/gfp_types.h>
#include <linux/ioport.h>
#include <linux/module.h>
@ -171,6 +173,33 @@ static const struct acpi_device_id intel_lpss_acpi_ids[] = {
};
MODULE_DEVICE_TABLE(acpi, intel_lpss_acpi_ids);
/*
* Devices that need a quirk applied only on the machines matched by
* intel_lpss_quirk_dmi[] below. The quirk to apply is carried in the
* matching entry's driver_data.
*/
static const struct acpi_device_id intel_lpss_acpi_quirk_ids[] = {
/* Dell Latitude 5285: ACPI GEXP device conflicts with I2C4 (INT3446) */
{ .id = "INT3446", .driver_data = QUIRK_IGNORE_RESOURCE_CONFLICTS },
{ }
};
static const struct dmi_system_id intel_lpss_quirk_dmi[] = {
{
.matches = {
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Latitude 5285"),
},
},
{
.matches = {
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Latitude 7275"),
},
},
{ }
};
static int intel_lpss_acpi_probe(struct platform_device *pdev)
{
const struct intel_lpss_platform_info *data;
@ -185,6 +214,15 @@ static int intel_lpss_acpi_probe(struct platform_device *pdev)
if (!info)
return -ENOMEM;
/* Apply per-device quirks that are only needed on certain machines */
if (dmi_check_system(intel_lpss_quirk_dmi)) {
const struct acpi_device_id *id;
id = acpi_match_device(intel_lpss_acpi_quirk_ids, &pdev->dev);
if (id)
info->quirks |= id->driver_data;
}
/* No need to check mem and irq here as intel_lpss_probe() does it for us */
info->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
info->irq = platform_get_irq(pdev, 0);

View File

@ -142,28 +142,21 @@ static void intel_lpss_cache_ltr(struct intel_lpss *lpss)
lpss->idle_ltr = readl(lpss->priv + LPSS_PRIV_IDLELTR);
}
static int intel_lpss_debugfs_add(struct intel_lpss *lpss)
static void intel_lpss_debugfs_add(struct intel_lpss *lpss)
{
struct dentry *dir;
dir = debugfs_create_dir(dev_name(lpss->dev), intel_lpss_debugfs);
if (IS_ERR(dir))
return PTR_ERR(dir);
lpss->debugfs = debugfs_create_dir(dev_name(lpss->dev), intel_lpss_debugfs);
/* Cache the values into lpss structure */
intel_lpss_cache_ltr(lpss);
debugfs_create_x32("capabilities", S_IRUGO, dir, &lpss->caps);
debugfs_create_x32("active_ltr", S_IRUGO, dir, &lpss->active_ltr);
debugfs_create_x32("idle_ltr", S_IRUGO, dir, &lpss->idle_ltr);
lpss->debugfs = dir;
return 0;
debugfs_create_x32("capabilities", 0444, lpss->debugfs, &lpss->caps);
debugfs_create_x32("active_ltr", 0444, lpss->debugfs, &lpss->active_ltr);
debugfs_create_x32("idle_ltr", 0444, lpss->debugfs, &lpss->idle_ltr);
}
static void intel_lpss_debugfs_remove(struct intel_lpss *lpss)
{
debugfs_remove_recursive(lpss->debugfs);
debugfs_remove(lpss->debugfs);
}
static void intel_lpss_ltr_set(struct device *dev, s32 val)
@ -432,10 +425,7 @@ int intel_lpss_probe(struct device *dev,
goto err_clk_register;
intel_lpss_ltr_expose(lpss);
ret = intel_lpss_debugfs_add(lpss);
if (ret)
dev_warn(dev, "Failed to create debugfs entries\n");
intel_lpss_debugfs_add(lpss);
if (intel_lpss_has_idma(lpss)) {
ret = mfd_add_devices(dev, lpss->devid, &intel_lpss_idma64_cell,

View File

@ -35,11 +35,6 @@
/* The Quark I2C controller source clock */
#define INTEL_QUARK_I2C_CLK_HZ 33000000
struct intel_quark_mfd {
struct clk *i2c_clk;
struct clk_lookup *i2c_clk_lookup;
};
static const struct property_entry intel_quark_i2c_controller_standard_properties[] = {
PROPERTY_ENTRY_U32("clock-frequency", I2C_MAX_STANDARD_MODE_FREQ),
{ }
@ -160,37 +155,12 @@ MODULE_DEVICE_TABLE(pci, intel_quark_mfd_ids);
static int intel_quark_register_i2c_clk(struct device *dev)
{
struct intel_quark_mfd *quark_mfd = dev_get_drvdata(dev);
struct clk *i2c_clk;
struct clk_hw *hw;
i2c_clk = clk_register_fixed_rate(dev,
INTEL_QUARK_I2C_CONTROLLER_CLK, NULL,
0, INTEL_QUARK_I2C_CLK_HZ);
if (IS_ERR(i2c_clk))
return PTR_ERR(i2c_clk);
quark_mfd->i2c_clk = i2c_clk;
quark_mfd->i2c_clk_lookup = clkdev_create(i2c_clk, NULL,
INTEL_QUARK_I2C_CONTROLLER_CLK);
if (!quark_mfd->i2c_clk_lookup) {
clk_unregister(quark_mfd->i2c_clk);
dev_err(dev, "Fixed clk register failed\n");
return -ENOMEM;
}
return 0;
}
static void intel_quark_unregister_i2c_clk(struct device *dev)
{
struct intel_quark_mfd *quark_mfd = dev_get_drvdata(dev);
if (!quark_mfd->i2c_clk_lookup)
return;
clkdev_drop(quark_mfd->i2c_clk_lookup);
clk_unregister(quark_mfd->i2c_clk);
hw = devm_clk_hw_register_fixed_rate(dev, INTEL_QUARK_I2C_CONTROLLER_CLK,
NULL, 0, INTEL_QUARK_I2C_CLK_HZ);
return devm_clk_hw_register_clkdev(dev, hw, NULL,
INTEL_QUARK_I2C_CONTROLLER_CLK);
}
static int intel_quark_i2c_setup(struct pci_dev *pdev)
@ -238,19 +208,12 @@ static int intel_quark_gpio_setup(struct pci_dev *pdev)
static int intel_quark_mfd_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
struct intel_quark_mfd *quark_mfd;
int ret;
ret = pcim_enable_device(pdev);
if (ret)
return ret;
quark_mfd = devm_kzalloc(&pdev->dev, sizeof(*quark_mfd), GFP_KERNEL);
if (!quark_mfd)
return -ENOMEM;
dev_set_drvdata(&pdev->dev, quark_mfd);
ret = intel_quark_register_i2c_clk(&pdev->dev);
if (ret)
return ret;
@ -260,7 +223,7 @@ static int intel_quark_mfd_probe(struct pci_dev *pdev,
/* This driver only requires 1 IRQ vector */
ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES);
if (ret < 0)
goto err_unregister_i2c_clk;
return ret;
ret = intel_quark_i2c_setup(pdev);
if (ret)
@ -282,8 +245,6 @@ static int intel_quark_mfd_probe(struct pci_dev *pdev,
software_node_unregister_node_group(intel_quark_gpio_node_group);
err_free_irq_vectors:
pci_free_irq_vectors(pdev);
err_unregister_i2c_clk:
intel_quark_unregister_i2c_clk(&pdev->dev);
return ret;
}
@ -292,7 +253,6 @@ static void intel_quark_mfd_remove(struct pci_dev *pdev)
mfd_remove_devices(&pdev->dev);
software_node_unregister_node_group(intel_quark_gpio_node_group);
pci_free_irq_vectors(pdev);
intel_quark_unregister_i2c_clk(&pdev->dev);
}
static struct pci_driver intel_quark_mfd_driver = {

View File

@ -1015,7 +1015,7 @@ static void iqs62x_remove(struct i2c_client *client)
wait_for_completion(&iqs62x->fw_done);
}
static int __maybe_unused iqs62x_suspend(struct device *dev)
static int iqs62x_suspend(struct device *dev)
{
struct iqs62x_core *iqs62x = dev_get_drvdata(dev);
int ret;
@ -1036,7 +1036,7 @@ static int __maybe_unused iqs62x_suspend(struct device *dev)
IQS62X_PWR_SETTINGS_PWR_MODE_HALT);
}
static int __maybe_unused iqs62x_resume(struct device *dev)
static int iqs62x_resume(struct device *dev)
{
struct iqs62x_core *iqs62x = dev_get_drvdata(dev);
int ret;
@ -1051,7 +1051,7 @@ static int __maybe_unused iqs62x_resume(struct device *dev)
IQS62X_PWR_SETTINGS_DIS_AUTO, 0);
}
static SIMPLE_DEV_PM_OPS(iqs62x_pm, iqs62x_suspend, iqs62x_resume);
static DEFINE_SIMPLE_DEV_PM_OPS(iqs62x_pm, iqs62x_suspend, iqs62x_resume);
static const struct of_device_id iqs62x_of_match[] = {
{ .compatible = "azoteq,iqs620a" },
@ -1067,7 +1067,7 @@ static struct i2c_driver iqs62x_i2c_driver = {
.driver = {
.name = "iqs62x",
.of_match_table = iqs62x_of_match,
.pm = &iqs62x_pm,
.pm = pm_sleep_ptr(&iqs62x_pm),
},
.probe = iqs62x_probe,
.remove = iqs62x_remove,

View File

@ -37,7 +37,7 @@ static void kempld_get_hardware_mutex(struct kempld_device_data *pld)
static void kempld_release_hardware_mutex(struct kempld_device_data *pld)
{
/* The harware mutex is released when 1 is written to the mutex bit. */
/* The hardware mutex is released when 1 is written to the mutex bit. */
iowrite8(KEMPLD_MUTEX_KEY, pld->io_index);
}

View File

@ -75,47 +75,116 @@ static const struct regmap_config khadas_mcu_regmap_config = {
.cache_type = REGCACHE_MAPLE,
};
static struct mfd_cell khadas_mcu_fan_cells[] = {
static const struct mfd_cell khadas_mcu_fan_cells[] = {
/* VIM1/2 Rev13+ and VIM3 only */
{ .name = "khadas-mcu-fan-ctrl", },
MFD_CELL_NAME("khadas-mcu-fan-ctrl"),
};
static struct mfd_cell khadas_mcu_cells[] = {
{ .name = "khadas-mcu-user-mem", },
static const struct mfd_cell khadas_mcu_cells[] = {
MFD_CELL_NAME("khadas-mcu-user-mem"),
};
static bool khadas_mcu_vim4_reg_volatile(struct device *dev, unsigned int reg)
{
switch (reg) {
case KHADAS_MCU_PWR_OFF_CMD_REG:
case KHADAS_MCU_VIM4_REST_CONF_REG:
case KHADAS_MCU_WOL_INIT_START_REG:
case KHADAS_MCU_VIM4_LED_ON_RAM_REG:
case KHADAS_MCU_VIM4_FAN_CTRL_REG:
case KHADAS_MCU_VIM4_WDT_EN_REG:
case KHADAS_MCU_VIM4_SYS_RST_REG:
return true;
default:
return false;
}
}
static bool khadas_mcu_vim4_reg_writeable(struct device *dev, unsigned int reg)
{
switch (reg) {
case KHADAS_MCU_VERSION_0_REG:
case KHADAS_MCU_VERSION_1_REG:
case KHADAS_MCU_SHUTDOWN_NORMAL_STATUS_REG:
return false;
default:
return true;
}
}
static const struct regmap_config khadas_mcu_vim4_regmap_config = {
.reg_bits = 8,
.reg_stride = 1,
.val_bits = 8,
.max_register = KHADAS_MCU_VIM4_SYS_RST_REG,
.volatile_reg = khadas_mcu_vim4_reg_volatile,
.writeable_reg = khadas_mcu_vim4_reg_writeable,
.cache_type = REGCACHE_MAPLE,
};
static const struct mfd_cell khadas_mcu_vim4_fan_cells[] = {
MFD_CELL_NAME("khadas-mcu-vim4-fan"),
};
static int khadas_mcu_probe(struct i2c_client *client)
{
const struct mfd_cell *cells, *fan_cells;
const struct regmap_config *regmap_cfg;
struct device *dev = &client->dev;
int ncells, nfan_cells, ret;
struct khadas_mcu *ddata;
int ret;
const void *mcu_variant;
ddata = devm_kzalloc(dev, sizeof(*ddata), GFP_KERNEL);
if (!ddata)
return -ENOMEM;
mcu_variant = i2c_get_match_data(client);
if (!mcu_variant)
return -ENODEV;
switch ((uintptr_t)mcu_variant) {
case KHADAS_MCU_GENERIC:
regmap_cfg = &khadas_mcu_regmap_config;
cells = khadas_mcu_cells;
ncells = ARRAY_SIZE(khadas_mcu_cells);
fan_cells = khadas_mcu_fan_cells;
nfan_cells = ARRAY_SIZE(khadas_mcu_fan_cells);
break;
case KHADAS_MCU_VIM4:
regmap_cfg = &khadas_mcu_vim4_regmap_config;
cells = NULL;
ncells = 0;
fan_cells = khadas_mcu_vim4_fan_cells;
nfan_cells = ARRAY_SIZE(khadas_mcu_vim4_fan_cells);
break;
default:
return -ENODEV;
}
i2c_set_clientdata(client, ddata);
ddata->dev = dev;
ddata->regmap = devm_regmap_init_i2c(client, &khadas_mcu_regmap_config);
ddata->regmap = devm_regmap_init_i2c(client, regmap_cfg);
if (IS_ERR(ddata->regmap)) {
ret = PTR_ERR(ddata->regmap);
dev_err(dev, "Failed to allocate register map: %d\n", ret);
return ret;
return dev_err_probe(dev, ret, "Failed to allocate register map\n");
}
ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE,
khadas_mcu_cells,
ARRAY_SIZE(khadas_mcu_cells),
NULL, 0, NULL);
if (ret)
return ret;
if (cells && ncells) {
ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE,
cells,
ncells,
NULL, 0, NULL);
if (ret)
return ret;
}
if (of_property_present(dev->of_node, "#cooling-cells"))
return devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE,
khadas_mcu_fan_cells,
ARRAY_SIZE(khadas_mcu_fan_cells),
fan_cells,
nfan_cells,
NULL, 0, NULL);
return 0;
@ -123,7 +192,8 @@ static int khadas_mcu_probe(struct i2c_client *client)
#ifdef CONFIG_OF
static const struct of_device_id khadas_mcu_of_match[] = {
{ .compatible = "khadas,mcu", },
{ .compatible = "khadas,mcu", .data = (void *)KHADAS_MCU_GENERIC },
{ .compatible = "khadas,vim4-mcu", .data = (void *)KHADAS_MCU_VIM4 },
{},
};
MODULE_DEVICE_TABLE(of, khadas_mcu_of_match);

View File

@ -7,6 +7,7 @@
* Author: Johan Hovold <jhovold@gmail.com>
*/
#include <linux/bitfield.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
@ -14,19 +15,24 @@
#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/mfd/core.h>
#include <linux/property.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/seq_file.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/units.h>
#include <linux/mfd/lm3533.h>
#define LM3533_BOOST_OVP_MASK 0x06
#define LM3533_BOOST_OVP_SHIFT 1
#define LM3533_BOOST_OVP_MIN (16 * MICRO)
#define LM3533_BOOST_OVP_MAX (40 * MICRO)
#define LM3533_BOOST_FREQ_MASK 0x01
#define LM3533_BOOST_FREQ_SHIFT 0
#define LM3533_BOOST_FREQ_MIN (500 * HZ_PER_KHZ)
#define LM3533_BOOST_FREQ_MAX (1000 * HZ_PER_KHZ)
#define LM3533_BL_ID_MASK 1
#define LM3533_LED_ID_MASK 3
@ -35,6 +41,7 @@
#define LM3533_HVLED_ID_MAX 2
#define LM3533_LVLED_ID_MAX 5
#define LM3533_CELLS_MAX 7
#define LM3533_REG_OUTPUT_CONF1 0x10
#define LM3533_REG_OUTPUT_CONF2 0x11
@ -42,125 +49,6 @@
#define LM3533_REG_MAX 0xb2
static struct mfd_cell lm3533_als_devs[] = {
{
.name = "lm3533-als",
.id = -1,
},
};
static struct mfd_cell lm3533_bl_devs[] = {
{
.name = "lm3533-backlight",
.id = 0,
},
{
.name = "lm3533-backlight",
.id = 1,
},
};
static struct mfd_cell lm3533_led_devs[] = {
{
.name = "lm3533-leds",
.id = 0,
},
{
.name = "lm3533-leds",
.id = 1,
},
{
.name = "lm3533-leds",
.id = 2,
},
{
.name = "lm3533-leds",
.id = 3,
},
};
int lm3533_read(struct lm3533 *lm3533, u8 reg, u8 *val)
{
int tmp;
int ret;
ret = regmap_read(lm3533->regmap, reg, &tmp);
if (ret < 0) {
dev_err(lm3533->dev, "failed to read register %02x: %d\n",
reg, ret);
return ret;
}
*val = tmp;
dev_dbg(lm3533->dev, "read [%02x]: %02x\n", reg, *val);
return ret;
}
EXPORT_SYMBOL_GPL(lm3533_read);
int lm3533_write(struct lm3533 *lm3533, u8 reg, u8 val)
{
int ret;
dev_dbg(lm3533->dev, "write [%02x]: %02x\n", reg, val);
ret = regmap_write(lm3533->regmap, reg, val);
if (ret < 0) {
dev_err(lm3533->dev, "failed to write register %02x: %d\n",
reg, ret);
}
return ret;
}
EXPORT_SYMBOL_GPL(lm3533_write);
int lm3533_update(struct lm3533 *lm3533, u8 reg, u8 val, u8 mask)
{
int ret;
dev_dbg(lm3533->dev, "update [%02x]: %02x/%02x\n", reg, val, mask);
ret = regmap_update_bits(lm3533->regmap, reg, mask, val);
if (ret < 0) {
dev_err(lm3533->dev, "failed to update register %02x: %d\n",
reg, ret);
}
return ret;
}
EXPORT_SYMBOL_GPL(lm3533_update);
static int lm3533_set_boost_freq(struct lm3533 *lm3533,
enum lm3533_boost_freq freq)
{
int ret;
ret = lm3533_update(lm3533, LM3533_REG_BOOST_PWM,
freq << LM3533_BOOST_FREQ_SHIFT,
LM3533_BOOST_FREQ_MASK);
if (ret)
dev_err(lm3533->dev, "failed to set boost frequency\n");
return ret;
}
static int lm3533_set_boost_ovp(struct lm3533 *lm3533,
enum lm3533_boost_ovp ovp)
{
int ret;
ret = lm3533_update(lm3533, LM3533_REG_BOOST_PWM,
ovp << LM3533_BOOST_OVP_SHIFT,
LM3533_BOOST_OVP_MASK);
if (ret)
dev_err(lm3533->dev, "failed to set boost ovp\n");
return ret;
}
/*
* HVLED output config -- output hvled controlled by backlight bl
*/
@ -181,7 +69,8 @@ static int lm3533_set_hvled_config(struct lm3533 *lm3533, u8 hvled, u8 bl)
mask = LM3533_BL_ID_MASK << shift;
val = bl << shift;
ret = lm3533_update(lm3533, LM3533_REG_OUTPUT_CONF1, val, mask);
ret = regmap_update_bits(lm3533->regmap, LM3533_REG_OUTPUT_CONF1,
mask, val);
if (ret)
dev_err(lm3533->dev, "failed to set hvled config\n");
@ -216,21 +105,32 @@ static int lm3533_set_lvled_config(struct lm3533 *lm3533, u8 lvled, u8 led)
mask = LM3533_LED_ID_MASK << shift;
val = led << shift;
ret = lm3533_update(lm3533, reg, val, mask);
ret = regmap_update_bits(lm3533->regmap, reg, mask, val);
if (ret)
dev_err(lm3533->dev, "failed to set lvled config\n");
return ret;
}
static void lm3533_enable(struct lm3533 *lm3533)
static int lm3533_enable(struct lm3533 *lm3533)
{
int ret;
ret = regulator_enable(lm3533->vin_supply);
if (ret) {
dev_err(lm3533->dev, "failed to enable vin power supply\n");
return ret;
}
gpiod_set_value(lm3533->hwen, 1);
return 0;
}
static void lm3533_disable(struct lm3533 *lm3533)
{
gpiod_set_value(lm3533->hwen, 0);
regulator_disable(lm3533->vin_supply);
}
enum lm3533_attribute_type {
@ -258,7 +158,7 @@ static ssize_t show_output(struct device *dev,
struct lm3533_device_attribute *lattr = to_lm3533_dev_attr(attr);
int id = lattr->u.output.id;
u8 reg;
u8 val;
u32 val;
u8 mask;
int shift;
int ret;
@ -278,7 +178,7 @@ static ssize_t show_output(struct device *dev,
mask = LM3533_LED_ID_MASK << shift;
}
ret = lm3533_read(lm3533, reg, &val);
ret = regmap_read(lm3533->regmap, reg, &val);
if (ret)
return ret;
@ -376,136 +276,102 @@ static struct attribute_group lm3533_attribute_group = {
.attrs = lm3533_attributes
};
static int lm3533_device_als_init(struct lm3533 *lm3533)
{
struct lm3533_platform_data *pdata = dev_get_platdata(lm3533->dev);
int ret;
if (!pdata->als)
return 0;
lm3533_als_devs[0].platform_data = pdata->als;
lm3533_als_devs[0].pdata_size = sizeof(*pdata->als);
ret = mfd_add_devices(lm3533->dev, 0, lm3533_als_devs, 1, NULL,
0, NULL);
if (ret) {
dev_err(lm3533->dev, "failed to add ALS device\n");
return ret;
}
lm3533->have_als = 1;
return 0;
}
static int lm3533_device_bl_init(struct lm3533 *lm3533)
{
struct lm3533_platform_data *pdata = dev_get_platdata(lm3533->dev);
int i;
int ret;
if (!pdata->backlights || pdata->num_backlights == 0)
return 0;
if (pdata->num_backlights > ARRAY_SIZE(lm3533_bl_devs))
pdata->num_backlights = ARRAY_SIZE(lm3533_bl_devs);
for (i = 0; i < pdata->num_backlights; ++i) {
lm3533_bl_devs[i].platform_data = &pdata->backlights[i];
lm3533_bl_devs[i].pdata_size = sizeof(pdata->backlights[i]);
}
ret = mfd_add_devices(lm3533->dev, 0, lm3533_bl_devs,
pdata->num_backlights, NULL, 0, NULL);
if (ret) {
dev_err(lm3533->dev, "failed to add backlight devices\n");
return ret;
}
lm3533->have_backlights = 1;
return 0;
}
static int lm3533_device_led_init(struct lm3533 *lm3533)
{
struct lm3533_platform_data *pdata = dev_get_platdata(lm3533->dev);
int i;
int ret;
if (!pdata->leds || pdata->num_leds == 0)
return 0;
if (pdata->num_leds > ARRAY_SIZE(lm3533_led_devs))
pdata->num_leds = ARRAY_SIZE(lm3533_led_devs);
for (i = 0; i < pdata->num_leds; ++i) {
lm3533_led_devs[i].platform_data = &pdata->leds[i];
lm3533_led_devs[i].pdata_size = sizeof(pdata->leds[i]);
}
ret = mfd_add_devices(lm3533->dev, 0, lm3533_led_devs,
pdata->num_leds, NULL, 0, NULL);
if (ret) {
dev_err(lm3533->dev, "failed to add LED devices\n");
return ret;
}
lm3533->have_leds = 1;
return 0;
}
static int lm3533_device_setup(struct lm3533 *lm3533,
struct lm3533_platform_data *pdata)
{
int ret;
ret = lm3533_set_boost_freq(lm3533, pdata->boost_freq);
if (ret)
return ret;
return lm3533_set_boost_ovp(lm3533, pdata->boost_ovp);
}
static const struct attribute_group *lm3533_attribute_groups[] = {
&lm3533_attribute_group,
NULL,
};
static int lm3533_device_init(struct lm3533 *lm3533)
{
struct lm3533_platform_data *pdata = dev_get_platdata(lm3533->dev);
struct device *dev = lm3533->dev;
struct mfd_cell *lm3533_devices;
u32 reg, nchilds;
u32 count = 0;
int ret;
dev_dbg(lm3533->dev, "%s\n", __func__);
nchilds = device_get_child_node_count(dev);
if (!nchilds || nchilds > LM3533_CELLS_MAX)
return dev_err_probe(dev, -ENODEV,
"num of child nodes is not supported\n");
if (!pdata) {
dev_err(lm3533->dev, "no platform data\n");
return -EINVAL;
lm3533_devices = devm_kcalloc(dev, nchilds, sizeof(*lm3533_devices),
GFP_KERNEL);
if (!lm3533_devices)
return -ENOMEM;
device_for_each_child_node_scoped(dev, child) {
if (count >= nchilds)
break;
if (fwnode_device_is_compatible(child, "ti,lm3533-als")) {
lm3533_devices[count].name = "lm3533-als";
lm3533_devices[count].of_compatible = "ti,lm3533-als";
lm3533_devices[count].id = PLATFORM_DEVID_NONE;
lm3533->have_als = true;
count++;
} else if (fwnode_device_is_compatible(child, "ti,lm3533-backlight")) {
ret = fwnode_property_read_u32(child, "reg", &reg);
if (ret || reg >= LM3533_HVLED_ID_MAX) {
dev_err(dev, "invalid backlight node %pfw\n", child);
continue;
}
lm3533_devices[count].name = "lm3533-backlight";
lm3533_devices[count].of_compatible = "ti,lm3533-backlight";
lm3533_devices[count].id = reg;
lm3533_devices[count].of_reg = reg;
lm3533_devices[count].use_of_reg = true;
lm3533->have_backlights = true;
count++;
} else if (fwnode_device_is_compatible(child, "ti,lm3533-leds")) {
ret = fwnode_property_read_u32(child, "reg", &reg);
if (ret || reg < LM3533_HVLED_ID_MAX ||
reg > LM3533_LVLED_ID_MAX) {
dev_err(dev, "invalid LED node %pfw\n", child);
continue;
}
lm3533_devices[count].name = "lm3533-leds";
lm3533_devices[count].of_compatible = "ti,lm3533-leds";
lm3533_devices[count].id = reg - LM3533_HVLED_ID_MAX;
lm3533_devices[count].of_reg = reg;
lm3533_devices[count].use_of_reg = true;
lm3533->have_leds = true;
count++;
}
}
lm3533->hwen = devm_gpiod_get(lm3533->dev, NULL, GPIOD_OUT_LOW);
if (IS_ERR(lm3533->hwen))
return dev_err_probe(lm3533->dev, PTR_ERR(lm3533->hwen), "failed to request HWEN GPIO\n");
gpiod_set_consumer_name(lm3533->hwen, "lm3533-hwen");
lm3533_enable(lm3533);
ret = lm3533_device_setup(lm3533, pdata);
ret = lm3533_enable(lm3533);
if (ret)
return ret;
ret = regmap_update_bits(lm3533->regmap, LM3533_REG_BOOST_PWM,
LM3533_BOOST_FREQ_MASK,
FIELD_PREP(LM3533_BOOST_FREQ_MASK, lm3533->boost_freq));
if (ret) {
dev_err(dev, "failed to set boost frequency\n");
goto err_disable;
}
lm3533_device_als_init(lm3533);
lm3533_device_bl_init(lm3533);
lm3533_device_led_init(lm3533);
ret = regmap_update_bits(lm3533->regmap, LM3533_REG_BOOST_PWM,
LM3533_BOOST_OVP_MASK,
FIELD_PREP(LM3533_BOOST_OVP_MASK, lm3533->boost_ovp));
if (ret) {
dev_err(dev, "failed to set boost ovp\n");
goto err_disable;
}
ret = sysfs_create_group(&lm3533->dev->kobj, &lm3533_attribute_group);
if (ret < 0) {
dev_err(lm3533->dev, "failed to create sysfs attributes\n");
goto err_unregister;
ret = mfd_add_devices(dev, 0, lm3533_devices, count, NULL, 0, NULL);
if (ret) {
dev_err(dev, "failed to add MFD devices: %d\n", ret);
goto err_disable;
}
return 0;
err_unregister:
mfd_remove_devices(lm3533->dev);
err_disable:
lm3533_disable(lm3533);
@ -516,8 +382,6 @@ static void lm3533_device_exit(struct lm3533 *lm3533)
{
dev_dbg(lm3533->dev, "%s\n", __func__);
sysfs_remove_group(&lm3533->dev->kobj, &lm3533_attribute_group);
mfd_remove_devices(lm3533->dev);
lm3533_disable(lm3533);
}
@ -589,7 +453,35 @@ static int lm3533_i2c_probe(struct i2c_client *i2c)
return PTR_ERR(lm3533->regmap);
lm3533->dev = &i2c->dev;
lm3533->irq = i2c->irq;
lm3533->hwen = devm_gpiod_get_optional(lm3533->dev, "enable",
GPIOD_OUT_LOW);
if (IS_ERR(lm3533->hwen))
return dev_err_probe(lm3533->dev, PTR_ERR(lm3533->hwen),
"failed to get HWEN GPIO\n");
lm3533->vin_supply = devm_regulator_get(lm3533->dev, "vin");
if (IS_ERR(lm3533->vin_supply))
return dev_err_probe(lm3533->dev, PTR_ERR(lm3533->vin_supply),
"failed to get vin-supply\n");
device_property_read_u32(lm3533->dev, "ti,boost-ovp-microvolt",
&lm3533->boost_ovp);
lm3533->boost_ovp = clamp(lm3533->boost_ovp, LM3533_BOOST_OVP_MIN,
LM3533_BOOST_OVP_MAX);
lm3533->boost_ovp = lm3533->boost_ovp / (8 * MICRO) - 2;
device_property_read_u32(lm3533->dev, "ti,boost-freq-hz",
&lm3533->boost_freq);
lm3533->boost_freq = clamp(lm3533->boost_freq, LM3533_BOOST_FREQ_MIN,
LM3533_BOOST_FREQ_MAX);
lm3533->boost_freq = lm3533->boost_freq / (500 * KILO) - 1;
/* LM3533 and child devices do not use DMA */
i2c->dev.coherent_dma_mask = 0;
i2c->dev.dma_mask = &i2c->dev.coherent_dma_mask;
return lm3533_device_init(lm3533);
}
@ -603,6 +495,12 @@ static void lm3533_i2c_remove(struct i2c_client *i2c)
lm3533_device_exit(lm3533);
}
static const struct of_device_id lm3533_match_table[] = {
{ .compatible = "ti,lm3533" },
{ }
};
MODULE_DEVICE_TABLE(of, lm3533_match_table);
static const struct i2c_device_id lm3533_i2c_ids[] = {
{ "lm3533" },
{ }
@ -612,6 +510,8 @@ MODULE_DEVICE_TABLE(i2c, lm3533_i2c_ids);
static struct i2c_driver lm3533_i2c_driver = {
.driver = {
.name = "lm3533",
.dev_groups = lm3533_attribute_groups,
.of_match_table = lm3533_match_table,
},
.id_table = lm3533_i2c_ids,
.probe = lm3533_i2c_probe,

View File

@ -9,14 +9,10 @@
#include <linux/device.h>
#include <linux/module.h>
#include <linux/regmap.h>
#include <linux/mfd/lm3533.h>
#define LM3533_MAX_CURRENT_MIN 5000
#define LM3533_MAX_CURRENT_MAX 29800
#define LM3533_MAX_CURRENT_STEP 800
#define LM3533_PWM_MAX 0x3f
#define LM3533_REG_PWM_BASE 0x14
@ -38,8 +34,8 @@ int lm3533_ctrlbank_enable(struct lm3533_ctrlbank *cb)
dev_dbg(cb->dev, "%s - %d\n", __func__, cb->id);
mask = 1 << cb->id;
ret = lm3533_update(cb->lm3533, LM3533_REG_CTRLBANK_ENABLE,
mask, mask);
ret = regmap_set_bits(cb->regmap, LM3533_REG_CTRLBANK_ENABLE,
mask);
if (ret)
dev_err(cb->dev, "failed to enable ctrlbank %d\n", cb->id);
@ -55,7 +51,8 @@ int lm3533_ctrlbank_disable(struct lm3533_ctrlbank *cb)
dev_dbg(cb->dev, "%s - %d\n", __func__, cb->id);
mask = 1 << cb->id;
ret = lm3533_update(cb->lm3533, LM3533_REG_CTRLBANK_ENABLE, 0, mask);
ret = regmap_clear_bits(cb->regmap, LM3533_REG_CTRLBANK_ENABLE,
mask);
if (ret)
dev_err(cb->dev, "failed to disable ctrlbank %d\n", cb->id);
@ -68,7 +65,7 @@ EXPORT_SYMBOL_GPL(lm3533_ctrlbank_disable);
*
* imax 5000 - 29800 uA (800 uA step)
*/
int lm3533_ctrlbank_set_max_current(struct lm3533_ctrlbank *cb, u16 imax)
int lm3533_ctrlbank_set_max_current(struct lm3533_ctrlbank *cb, u32 imax)
{
u8 reg;
u8 val;
@ -80,7 +77,7 @@ int lm3533_ctrlbank_set_max_current(struct lm3533_ctrlbank *cb, u16 imax)
val = (imax - LM3533_MAX_CURRENT_MIN) / LM3533_MAX_CURRENT_STEP;
reg = lm3533_ctrlbank_get_reg(cb, LM3533_REG_MAX_CURRENT_BASE);
ret = lm3533_write(cb->lm3533, reg, val);
ret = regmap_write(cb->regmap, reg, val);
if (ret)
dev_err(cb->dev, "failed to set max current\n");
@ -88,13 +85,13 @@ int lm3533_ctrlbank_set_max_current(struct lm3533_ctrlbank *cb, u16 imax)
}
EXPORT_SYMBOL_GPL(lm3533_ctrlbank_set_max_current);
int lm3533_ctrlbank_set_brightness(struct lm3533_ctrlbank *cb, u8 val)
int lm3533_ctrlbank_set_brightness(struct lm3533_ctrlbank *cb, u32 val)
{
u8 reg;
int ret;
reg = lm3533_ctrlbank_get_reg(cb, LM3533_REG_BRIGHTNESS_BASE);
ret = lm3533_write(cb->lm3533, reg, val);
ret = regmap_write(cb->regmap, reg, val);
if (ret)
dev_err(cb->dev, "failed to set brightness\n");
@ -102,13 +99,13 @@ int lm3533_ctrlbank_set_brightness(struct lm3533_ctrlbank *cb, u8 val)
}
EXPORT_SYMBOL_GPL(lm3533_ctrlbank_set_brightness);
int lm3533_ctrlbank_get_brightness(struct lm3533_ctrlbank *cb, u8 *val)
int lm3533_ctrlbank_get_brightness(struct lm3533_ctrlbank *cb, u32 *val)
{
u8 reg;
int ret;
reg = lm3533_ctrlbank_get_reg(cb, LM3533_REG_BRIGHTNESS_BASE);
ret = lm3533_read(cb->lm3533, reg, val);
ret = regmap_read(cb->regmap, reg, val);
if (ret)
dev_err(cb->dev, "failed to get brightness\n");
@ -126,7 +123,7 @@ EXPORT_SYMBOL_GPL(lm3533_ctrlbank_get_brightness);
* bit 1 - PWM-input enabled in Zone 0
* bit 0 - PWM-input enabled
*/
int lm3533_ctrlbank_set_pwm(struct lm3533_ctrlbank *cb, u8 val)
int lm3533_ctrlbank_set_pwm(struct lm3533_ctrlbank *cb, u32 val)
{
u8 reg;
int ret;
@ -135,7 +132,7 @@ int lm3533_ctrlbank_set_pwm(struct lm3533_ctrlbank *cb, u8 val)
return -EINVAL;
reg = lm3533_ctrlbank_get_reg(cb, LM3533_REG_PWM_BASE);
ret = lm3533_write(cb->lm3533, reg, val);
ret = regmap_write(cb->regmap, reg, val);
if (ret)
dev_err(cb->dev, "failed to set PWM mask\n");
@ -143,13 +140,13 @@ int lm3533_ctrlbank_set_pwm(struct lm3533_ctrlbank *cb, u8 val)
}
EXPORT_SYMBOL_GPL(lm3533_ctrlbank_set_pwm);
int lm3533_ctrlbank_get_pwm(struct lm3533_ctrlbank *cb, u8 *val)
int lm3533_ctrlbank_get_pwm(struct lm3533_ctrlbank *cb, u32 *val)
{
u8 reg;
int ret;
reg = lm3533_ctrlbank_get_reg(cb, LM3533_REG_PWM_BASE);
ret = lm3533_read(cb->lm3533, reg, val);
ret = regmap_read(cb->regmap, reg, val);
if (ret)
dev_err(cb->dev, "failed to get PWM mask\n");

View File

@ -105,7 +105,7 @@ static int max77705_i2c_probe(struct i2c_client *i2c)
return -ENODEV;
pmic_rev = pmic_rev_value & MAX77705_REVISION_MASK;
if (pmic_rev != MAX77705_PASS3)
if (pmic_rev != MAX77705_PASS2 && pmic_rev != MAX77705_PASS3)
return dev_err_probe(dev, -ENODEV, "Rev.0x%x is not tested\n", pmic_rev);
/* Active Discharge Enable */

View File

@ -173,7 +173,7 @@ static const struct i2c_device_id max77843_id[] = {
{ },
};
static int __maybe_unused max77843_suspend(struct device *dev)
static int max77843_suspend(struct device *dev)
{
struct i2c_client *i2c = to_i2c_client(dev);
struct max77693_dev *max77843 = i2c_get_clientdata(i2c);
@ -185,7 +185,7 @@ static int __maybe_unused max77843_suspend(struct device *dev)
return 0;
}
static int __maybe_unused max77843_resume(struct device *dev)
static int max77843_resume(struct device *dev)
{
struct i2c_client *i2c = to_i2c_client(dev);
struct max77693_dev *max77843 = i2c_get_clientdata(i2c);
@ -197,12 +197,12 @@ static int __maybe_unused max77843_resume(struct device *dev)
return 0;
}
static SIMPLE_DEV_PM_OPS(max77843_pm, max77843_suspend, max77843_resume);
static DEFINE_SIMPLE_DEV_PM_OPS(max77843_pm, max77843_suspend, max77843_resume);
static struct i2c_driver max77843_i2c_driver = {
.driver = {
.name = "max77843",
.pm = &max77843_pm,
.pm = pm_sleep_ptr(&max77843_pm),
.of_match_table = max77843_dt_match,
.suppress_bind_attrs = true,
},

View File

@ -146,7 +146,7 @@ static struct max8998_platform_data *max8998_i2c_parse_dt_pdata(
/*
* ToDo: the 'wakeup' member in the platform data is more of a linux
* specfic information. Hence, there is no binding for that yet and
* specific information. Hence, there is no binding for that yet and
* not parsed here.
*/
return pd;

View File

@ -11,6 +11,7 @@
#include <linux/irq.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/property.h>
#include <linux/regmap.h>
#include <linux/sysfs.h>
@ -29,6 +30,7 @@ struct cpcap_ddata {
struct regmap_irq_chip_data *irqdata[CPCAP_NR_IRQ_CHIPS];
const struct regmap_config *regmap_conf;
struct regmap *regmap;
enum cpcap_variant variant;
};
static int cpcap_sense_irq(struct regmap *regmap, int irq)
@ -194,20 +196,6 @@ static int cpcap_init_irq(struct cpcap_ddata *cpcap)
return 0;
}
static const struct of_device_id cpcap_of_match[] = {
{ .compatible = "motorola,cpcap", },
{ .compatible = "st,6556002", },
{},
};
MODULE_DEVICE_TABLE(of, cpcap_of_match);
static const struct spi_device_id cpcap_spi_ids[] = {
{ .name = "cpcap" },
{ .name = "6556002" },
{ }
};
MODULE_DEVICE_TABLE(spi, cpcap_spi_ids);
static const struct regmap_config cpcap_regmap_config = {
.reg_bits = 16,
.reg_stride = 4,
@ -240,62 +228,74 @@ static int cpcap_resume(struct device *dev)
static DEFINE_SIMPLE_DEV_PM_OPS(cpcap_pm, cpcap_suspend, cpcap_resume);
static const struct mfd_cell cpcap_mfd_devices[] = {
{
.name = "cpcap_adc",
.of_compatible = "motorola,mapphone-cpcap-adc",
}, {
.name = "cpcap_battery",
.of_compatible = "motorola,cpcap-battery",
}, {
.name = "cpcap-charger",
.of_compatible = "motorola,mapphone-cpcap-charger",
}, {
.name = "cpcap-regulator",
.of_compatible = "motorola,mapphone-cpcap-regulator",
}, {
.name = "cpcap-rtc",
.of_compatible = "motorola,cpcap-rtc",
}, {
.name = "cpcap-pwrbutton",
.of_compatible = "motorola,cpcap-pwrbutton",
}, {
.name = "cpcap-usb-phy",
.of_compatible = "motorola,mapphone-cpcap-usb-phy",
}, {
.name = "cpcap-led",
.id = 0,
.of_compatible = "motorola,cpcap-led-red",
}, {
.name = "cpcap-led",
.id = 1,
.of_compatible = "motorola,cpcap-led-green",
}, {
.name = "cpcap-led",
.id = 2,
.of_compatible = "motorola,cpcap-led-blue",
}, {
.name = "cpcap-led",
.id = 3,
.of_compatible = "motorola,cpcap-led-adl",
}, {
.name = "cpcap-led",
.id = 4,
.of_compatible = "motorola,cpcap-led-cp",
}, {
.name = "cpcap-codec",
}
static const struct mfd_cell cpcap_common_devices[] = {
MFD_CELL_OF("cpcap_battery", NULL, NULL, 0, 0, "motorola,cpcap-battery"),
MFD_CELL_OF("cpcap-rtc", NULL, NULL, 0, 0, "motorola,cpcap-rtc"),
MFD_CELL_OF("cpcap-pwrbutton", NULL, NULL, 0, 0, "motorola,cpcap-pwrbutton"),
MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 0, "motorola,cpcap-led-red"),
MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 1, "motorola,cpcap-led-green"),
MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 2, "motorola,cpcap-led-blue"),
MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 3, "motorola,cpcap-led-adl"),
MFD_CELL_NAME("cpcap-codec"),
};
static const struct mfd_cell cpcap_default_devices[] = {
MFD_CELL_OF("cpcap_adc", NULL, NULL, 0, 0, "motorola,cpcap-adc"),
MFD_CELL_OF("cpcap-regulator", NULL, NULL, 0, 0, "motorola,cpcap-regulator"),
MFD_CELL_OF("cpcap-usb-phy", NULL, NULL, 0, 0, "motorola,cpcap-usb-phy"),
MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 4, "motorola,cpcap-led-cp"),
};
static const struct mfd_cell cpcap_mapphone_devices[] = {
MFD_CELL_OF("cpcap_adc", NULL, NULL, 0, 0, "motorola,mapphone-cpcap-adc"),
MFD_CELL_OF("cpcap-charger", NULL, NULL, 0, 0, "motorola,mapphone-cpcap-charger"),
MFD_CELL_OF("cpcap-regulator", NULL, NULL, 0, 0, "motorola,mapphone-cpcap-regulator"),
MFD_CELL_OF("cpcap-usb-phy", NULL, NULL, 0, 0, "motorola,mapphone-cpcap-usb-phy"),
MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 4, "motorola,cpcap-led-cp"),
};
/*
* The Mot board features a USB-PHY and charger similar to the ones in
* Mapphone; however, because Mot is based on Tegra20, it is incompatible
* with the existing implementation, which is tightly interconnected with
* the OMAP USB PHY.
*/
static const struct mfd_cell cpcap_mot_devices[] = {
MFD_CELL_OF("cpcap_adc", NULL, NULL, 0, 0, "motorola,mot-cpcap-adc"),
MFD_CELL_OF("cpcap-regulator", NULL, NULL, 0, 0, "motorola,mot-cpcap-regulator"),
};
static int cpcap_probe(struct spi_device *spi)
{
struct cpcap_ddata *cpcap;
const struct mfd_cell *cells;
unsigned int num_cells;
int ret;
cpcap = devm_kzalloc(&spi->dev, sizeof(*cpcap), GFP_KERNEL);
if (!cpcap)
return -ENOMEM;
cpcap->variant = (enum cpcap_variant)spi_get_device_match_data(spi);
switch (cpcap->variant) {
case CPCAP_DEFAULT:
cells = cpcap_default_devices;
num_cells = ARRAY_SIZE(cpcap_default_devices);
break;
case CPCAP_MAPPHONE:
cells = cpcap_mapphone_devices;
num_cells = ARRAY_SIZE(cpcap_mapphone_devices);
break;
case CPCAP_MOT:
cells = cpcap_mot_devices;
num_cells = ARRAY_SIZE(cpcap_mot_devices);
break;
default:
return dev_err_probe(&spi->dev, -ENODEV,
"Unknown device %d\n", cpcap->variant);
}
cpcap->spi = spi;
spi_set_drvdata(spi, cpcap);
@ -330,10 +330,31 @@ static int cpcap_probe(struct spi_device *spi)
spi->dev.coherent_dma_mask = 0;
spi->dev.dma_mask = &spi->dev.coherent_dma_mask;
return devm_mfd_add_devices(&spi->dev, 0, cpcap_mfd_devices,
ARRAY_SIZE(cpcap_mfd_devices), NULL, 0, NULL);
ret = devm_mfd_add_devices(&spi->dev, 0, cpcap_common_devices,
ARRAY_SIZE(cpcap_common_devices), NULL, 0, NULL);
if (ret)
return dev_err_probe(&spi->dev, ret,
"Failed to add common child devices\n");
return devm_mfd_add_devices(&spi->dev, 0, cells, num_cells, NULL, 0, NULL);
}
static const struct of_device_id cpcap_of_match[] = {
{ .compatible = "motorola,cpcap", .data = (void *)CPCAP_DEFAULT },
{ .compatible = "motorola,mapphone-cpcap", .data = (void *)CPCAP_MAPPHONE },
{ .compatible = "motorola,mot-cpcap", .data = (void *)CPCAP_MOT },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, cpcap_of_match);
static const struct spi_device_id cpcap_spi_ids[] = {
{ .name = "cpcap", .driver_data = CPCAP_DEFAULT },
{ .name = "mapphone-cpcap", .driver_data = CPCAP_MAPPHONE },
{ .name = "mot-cpcap", .driver_data = CPCAP_MOT },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(spi, cpcap_spi_ids);
static struct spi_driver cpcap_driver = {
.driver = {
.name = "cpcap-core",

View File

@ -583,7 +583,7 @@ static int mt6360_probe(struct i2c_client *client)
return 0;
}
static int __maybe_unused mt6360_suspend(struct device *dev)
static int mt6360_suspend(struct device *dev)
{
struct i2c_client *i2c = to_i2c_client(dev);
@ -593,7 +593,7 @@ static int __maybe_unused mt6360_suspend(struct device *dev)
return 0;
}
static int __maybe_unused mt6360_resume(struct device *dev)
static int mt6360_resume(struct device *dev)
{
struct i2c_client *i2c = to_i2c_client(dev);
@ -604,7 +604,7 @@ static int __maybe_unused mt6360_resume(struct device *dev)
return 0;
}
static SIMPLE_DEV_PM_OPS(mt6360_pm_ops, mt6360_suspend, mt6360_resume);
static DEFINE_SIMPLE_DEV_PM_OPS(mt6360_pm_ops, mt6360_suspend, mt6360_resume);
static const struct of_device_id __maybe_unused mt6360_of_id[] = {
{ .compatible = "mediatek,mt6360", },
@ -615,7 +615,7 @@ MODULE_DEVICE_TABLE(of, mt6360_of_id);
static struct i2c_driver mt6360_driver = {
.driver = {
.name = "mt6360",
.pm = &mt6360_pm_ops,
.pm = pm_sleep_ptr(&mt6360_pm_ops),
.of_match_table = of_match_ptr(mt6360_of_id),
},
.probe = mt6360_probe,

View File

@ -261,6 +261,9 @@ static const struct mfd_cell mt6359_devs[] = {
static const struct mfd_cell mt6397_devs[] = {
{
.name = "mt6397-auxadc",
.of_compatible = "mediatek,mt6397-auxadc",
}, {
.name = "mt6397-rtc",
.num_resources = ARRAY_SIZE(mt6397_rtc_resources),
.resources = mt6397_rtc_resources,

View File

@ -331,7 +331,7 @@ static u8 rave_sp_reply_code(u8 command)
return command + 0x20;
case 0xE0 ... 0xEF:
/*
* Events emitted by all versions of the firmare use
* Events emitted by all versions of the firmware use
* least significant bit to get an ACK code
*/
return command | 0x01;
@ -544,7 +544,7 @@ static size_t rave_sp_receive_buf(struct serdev_device *serdev,
* NOTE: The above means that only the
* frame started by third SOF, sent
* after this one will have a chance
* to get throught.
* to get through.
*/
goto reset_framer;
case RAVE_SP_DLE:
@ -595,7 +595,7 @@ static size_t rave_sp_receive_buf(struct serdev_device *serdev,
/*
* The only way to get out of the above loop and end up here
* is throught consuming all of the supplied data, so here we
* is through consuming all of the supplied data, so here we
* report that we processed it all.
*/
return size;

View File

@ -875,7 +875,7 @@ int rk8xx_probe(struct device *dev, int variant, unsigned int irq, struct regmap
if (device_property_read_bool(dev, "system-power-controller") ||
device_property_read_bool(dev, "rockchip,system-power-controller")) {
ret = devm_register_sys_off_handler(dev,
SYS_OFF_MODE_POWER_OFF_PREPARE, SYS_OFF_PRIO_HIGH,
SYS_OFF_MODE_POWER_OFF, SYS_OFF_PRIO_HIGH,
&rk808_power_off, rk808);
if (ret)
return dev_err_probe(dev, ret,

View File

@ -251,7 +251,7 @@ static void rk8xx_i2c_shutdown(struct i2c_client *client)
rk8xx_shutdown(&client->dev);
}
static SIMPLE_DEV_PM_OPS(rk8xx_i2c_pm_ops, rk8xx_suspend, rk8xx_resume);
static DEFINE_SIMPLE_DEV_PM_OPS(rk8xx_i2c_pm_ops, rk8xx_suspend, rk8xx_resume);
static const struct of_device_id rk8xx_i2c_of_match[] = {
{ .compatible = "rockchip,rk801", .data = &rk801_data },
@ -270,7 +270,7 @@ static struct i2c_driver rk8xx_i2c_driver = {
.driver = {
.name = "rk8xx-i2c",
.of_match_table = rk8xx_i2c_of_match,
.pm = &rk8xx_i2c_pm_ops,
.pm = pm_sleep_ptr(&rk8xx_i2c_pm_ops),
},
.probe = rk8xx_i2c_probe,
.shutdown = rk8xx_i2c_shutdown,

View File

@ -243,7 +243,7 @@ static void rn5t618_i2c_remove(struct i2c_client *i2c)
unregister_restart_handler(&rn5t618_restart_handler);
}
static int __maybe_unused rn5t618_i2c_suspend(struct device *dev)
static int rn5t618_i2c_suspend(struct device *dev)
{
struct rn5t618 *priv = dev_get_drvdata(dev);
@ -253,7 +253,7 @@ static int __maybe_unused rn5t618_i2c_suspend(struct device *dev)
return 0;
}
static int __maybe_unused rn5t618_i2c_resume(struct device *dev)
static int rn5t618_i2c_resume(struct device *dev)
{
struct rn5t618 *priv = dev_get_drvdata(dev);
@ -263,7 +263,7 @@ static int __maybe_unused rn5t618_i2c_resume(struct device *dev)
return 0;
}
static SIMPLE_DEV_PM_OPS(rn5t618_i2c_dev_pm_ops,
static DEFINE_SIMPLE_DEV_PM_OPS(rn5t618_i2c_dev_pm_ops,
rn5t618_i2c_suspend,
rn5t618_i2c_resume);
@ -271,7 +271,7 @@ static struct i2c_driver rn5t618_i2c_driver = {
.driver = {
.name = "rn5t618",
.of_match_table = rn5t618_of_match,
.pm = &rn5t618_i2c_dev_pm_ops,
.pm = pm_sleep_ptr(&rn5t618_i2c_dev_pm_ops),
},
.probe = rn5t618_i2c_probe,
.remove = rn5t618_i2c_remove,

View File

@ -222,7 +222,7 @@ int si476x_core_stop(struct si476x_core *core, bool soft)
atomic_set(&core->is_alive, 0);
if (soft) {
/* TODO: This probably shoud be a configurable option,
/* TODO: This probably should be a configurable option,
* so it is possible to have the chips keep their
* oscillators running
*/

View File

@ -313,7 +313,7 @@ static int __maybe_unused ti_tscadc_can_wakeup(struct device *dev, void *data)
return device_may_wakeup(dev);
}
static int __maybe_unused tscadc_suspend(struct device *dev)
static int tscadc_suspend(struct device *dev)
{
struct ti_tscadc_dev *tscadc = dev_get_drvdata(dev);
@ -331,7 +331,7 @@ static int __maybe_unused tscadc_suspend(struct device *dev)
return 0;
}
static int __maybe_unused tscadc_resume(struct device *dev)
static int tscadc_resume(struct device *dev)
{
struct ti_tscadc_dev *tscadc = dev_get_drvdata(dev);
@ -345,7 +345,7 @@ static int __maybe_unused tscadc_resume(struct device *dev)
return 0;
}
static SIMPLE_DEV_PM_OPS(tscadc_pm_ops, tscadc_suspend, tscadc_resume);
static DEFINE_SIMPLE_DEV_PM_OPS(tscadc_pm_ops, tscadc_suspend, tscadc_resume);
static const struct ti_tscadc_data tscdata = {
.adc_feature_name = "TI-am335x-adc",
@ -373,7 +373,7 @@ MODULE_DEVICE_TABLE(of, ti_tscadc_dt_ids);
static struct platform_driver ti_tscadc_driver = {
.driver = {
.name = "ti_am3359-tscadc",
.pm = &tscadc_pm_ops,
.pm = pm_sleep_ptr(&tscadc_pm_ops),
.of_match_table = ti_tscadc_dt_ids,
},
.probe = ti_tscadc_probe,

View File

@ -146,6 +146,31 @@ static const struct irq_domain_ops tps65217_irq_domain_ops = {
.map = tps65217_irq_map,
};
static void tps65217_irq_cleanup(void *data)
{
struct tps65217 *tps = data;
unsigned int virq;
if (!tps->irq_domain)
return;
for (int i = 0; i < TPS65217_NUM_IRQ; i++) {
virq = irq_find_mapping(tps->irq_domain, i);
if (virq)
irq_dispose_mapping(virq);
}
irq_domain_remove(tps->irq_domain);
tps->irq_domain = NULL;
}
static void tps65217_irq_wake_disable(void *data)
{
unsigned long irq = (unsigned long)data;
disable_irq_wake(irq);
}
static int tps65217_irq_init(struct tps65217 *tps, int irq)
{
int ret;
@ -155,8 +180,12 @@ static int tps65217_irq_init(struct tps65217 *tps, int irq)
/* Mask all interrupt sources */
tps->irq_mask = TPS65217_INT_MASK;
tps65217_set_bits(tps, TPS65217_REG_INT, TPS65217_INT_MASK,
TPS65217_INT_MASK, TPS65217_PROTECT_NONE);
ret = tps65217_set_bits(tps, TPS65217_REG_INT, TPS65217_INT_MASK,
TPS65217_INT_MASK, TPS65217_PROTECT_NONE);
if (ret) {
dev_err(tps->dev, "Failed to mask interrupt sources: %d\n", ret);
return ret;
}
tps->irq_domain = irq_domain_create_linear(dev_fwnode(tps->dev), TPS65217_NUM_IRQ,
&tps65217_irq_domain_ops, tps);
@ -165,6 +194,10 @@ static int tps65217_irq_init(struct tps65217 *tps, int irq)
return -ENOMEM;
}
ret = devm_add_action_or_reset(tps->dev, tps65217_irq_cleanup, tps);
if (ret)
return ret;
ret = devm_request_threaded_irq(tps->dev, irq, NULL,
tps65217_irq_thread, IRQF_ONESHOT,
"tps65217-irq", tps);
@ -174,7 +207,16 @@ static int tps65217_irq_init(struct tps65217 *tps, int irq)
return ret;
}
enable_irq_wake(irq);
ret = enable_irq_wake(irq);
if (ret) {
dev_warn(tps->dev, "failed to enable IRQ wake: %d\n", ret);
return 0;
}
ret = devm_add_action_or_reset(tps->dev, tps65217_irq_wake_disable,
(void *)(unsigned long)irq);
if (ret)
return ret;
return 0;
}
@ -333,7 +375,9 @@ static int tps65217_probe(struct i2c_client *client)
}
if (client->irq) {
tps65217_irq_init(tps, client->irq);
ret = tps65217_irq_init(tps, client->irq);
if (ret)
return ret;
} else {
int i;
@ -373,22 +417,6 @@ static int tps65217_probe(struct i2c_client *client)
return 0;
}
static void tps65217_remove(struct i2c_client *client)
{
struct tps65217 *tps = i2c_get_clientdata(client);
unsigned int virq;
int i;
for (i = 0; i < TPS65217_NUM_IRQ; i++) {
virq = irq_find_mapping(tps->irq_domain, i);
if (virq)
irq_dispose_mapping(virq);
}
irq_domain_remove(tps->irq_domain);
tps->irq_domain = NULL;
}
static const struct i2c_device_id tps65217_id_table[] = {
{"tps65217", TPS65217},
{ /* sentinel */ }
@ -402,7 +430,6 @@ static struct i2c_driver tps65217_driver = {
},
.id_table = tps65217_id_table,
.probe = tps65217_probe,
.remove = tps65217_remove,
};
static int __init tps65217_init(void)

View File

@ -618,7 +618,7 @@ static void tps6586x_i2c_remove(struct i2c_client *client)
free_irq(client->irq, tps6586x);
}
static int __maybe_unused tps6586x_i2c_suspend(struct device *dev)
static int tps6586x_i2c_suspend(struct device *dev)
{
struct tps6586x *tps6586x = dev_get_drvdata(dev);
@ -628,7 +628,7 @@ static int __maybe_unused tps6586x_i2c_suspend(struct device *dev)
return 0;
}
static int __maybe_unused tps6586x_i2c_resume(struct device *dev)
static int tps6586x_i2c_resume(struct device *dev)
{
struct tps6586x *tps6586x = dev_get_drvdata(dev);
@ -638,7 +638,7 @@ static int __maybe_unused tps6586x_i2c_resume(struct device *dev)
return 0;
}
static SIMPLE_DEV_PM_OPS(tps6586x_pm_ops, tps6586x_i2c_suspend,
static DEFINE_SIMPLE_DEV_PM_OPS(tps6586x_pm_ops, tps6586x_i2c_suspend,
tps6586x_i2c_resume);
static const struct i2c_device_id tps6586x_id_table[] = {
@ -651,7 +651,7 @@ static struct i2c_driver tps6586x_driver = {
.driver = {
.name = "tps6586x",
.of_match_table = of_match_ptr(tps6586x_of_match),
.pm = &tps6586x_pm_ops,
.pm = pm_sleep_ptr(&tps6586x_pm_ops),
},
.probe = tps6586x_i2c_probe,
.remove = tps6586x_i2c_remove,

View File

@ -719,6 +719,11 @@ static const struct mfd_cell twl6032_cells[] = {
{ .name = "twl6032-clk" },
};
static void twl_unregister_device(void *data)
{
platform_device_unregister(data);
}
/* NOTE: This driver only handles a single twl4030/tps659x0 chip */
static int
twl_probe(struct i2c_client *client)
@ -754,17 +759,22 @@ twl_probe(struct i2c_client *client)
return status;
}
status = devm_add_action_or_reset(&client->dev, twl_unregister_device,
pdev);
if (status)
return status;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
dev_dbg(&client->dev, "can't talk I2C?\n");
status = -EIO;
goto free;
goto out;
}
twl_priv = devm_kzalloc(&client->dev, sizeof(struct twl_private),
GFP_KERNEL);
if (!twl_priv) {
status = -ENOMEM;
goto free;
goto out;
}
if ((id->driver_data) & TWL6030_CLASS) {
@ -784,7 +794,7 @@ twl_probe(struct i2c_client *client)
GFP_KERNEL);
if (!twl_priv->twl_modules) {
status = -ENOMEM;
goto free;
goto out;
}
for (i = 0; i < num_slaves; i++) {
@ -880,7 +890,7 @@ twl_probe(struct i2c_client *client)
status = devm_mfd_add_devices(&client->dev, PLATFORM_DEVID_NONE,
cells, num_cells, NULL, 0, NULL);
if (status < 0)
goto free;
goto out;
if (of_device_is_system_power_controller(node)) {
if (!pm_power_off)
@ -896,14 +906,11 @@ twl_probe(struct i2c_client *client)
fail:
if (status < 0)
twl_remove(client);
free:
if (status < 0)
platform_device_unregister(pdev);
out:
return status;
}
static int __maybe_unused twl_suspend(struct device *dev)
static int twl_suspend(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
@ -913,7 +920,7 @@ static int __maybe_unused twl_suspend(struct device *dev)
return 0;
}
static int __maybe_unused twl_resume(struct device *dev)
static int twl_resume(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
@ -923,7 +930,7 @@ static int __maybe_unused twl_resume(struct device *dev)
return 0;
}
static SIMPLE_DEV_PM_OPS(twl_dev_pm_ops, twl_suspend, twl_resume);
static DEFINE_SIMPLE_DEV_PM_OPS(twl_dev_pm_ops, twl_suspend, twl_resume);
static const struct i2c_device_id twl_ids[] = {
{ "twl4030", TWL4030_VAUX2 }, /* "Triton 2" */
@ -942,7 +949,7 @@ static const struct i2c_device_id twl_ids[] = {
/* One Client Driver , 4 Clients */
static struct i2c_driver twl_driver = {
.driver.name = DRIVER_NAME,
.driver.pm = &twl_dev_pm_ops,
.driver.pm = pm_sleep_ptr(&twl_dev_pm_ops),
.id_table = twl_ids,
.probe = twl_probe,
.remove = twl_remove,

View File

@ -2,6 +2,7 @@
// Copyright (c) 2019, Linaro Limited
#include <linux/clk.h>
#include <linux/dma-mapping.h>
#include <linux/gpio/consumer.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
@ -217,13 +218,18 @@ static int wcd934x_slim_probe(struct slim_device *sdev)
struct gpio_desc *reset_gpio;
int ret;
ret = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(32));
if (ret)
return dev_err_probe(dev, ret,
"Failed to set DMA mask\n");
ddata = devm_kzalloc(dev, sizeof(*ddata), GFP_KERNEL);
if (!ddata)
return -ENOMEM;
ddata->irq = of_irq_get(np, 0);
if (ddata->irq < 0)
return dev_err_probe(ddata->dev, ddata->irq,
return dev_err_probe(dev, ddata->irq,
"Failed to get IRQ\n");
ddata->extclk = devm_clk_get(dev, "extclk");

View File

@ -132,7 +132,7 @@ static irqreturn_t wm831x_auxadc_irq(int irq, void *irq_data)
1 << input, 0);
wm831x->auxadc_active &= ~(1 << input);
/* Turn off the entire convertor if idle */
/* Turn off the entire converter if idle */
if (!wm831x->auxadc_active)
wm831x_reg_write(wm831x, WM831X_AUXADC_CONTROL, 0);

View File

@ -13,34 +13,33 @@
#include <linux/regmap.h>
#include <linux/sysfs.h>
#include <linux/thermal.h>
#include <linux/regulator/consumer.h>
#include <linux/minmax.h>
#define MAX_LEVEL 3
#define MAX_LEVEL 5
struct khadas_mcu_fan_ctx {
struct khadas_mcu *mcu;
unsigned int fan_reg;
unsigned int level;
const unsigned int *levels;
unsigned int nlevels;
struct thermal_cooling_device *cdev;
struct regulator *power;
};
static int khadas_mcu_fan_set_level(struct khadas_mcu_fan_ctx *ctx,
unsigned int level)
{
int ret;
ret = regmap_write(ctx->mcu->regmap, KHADAS_MCU_CMD_FAN_STATUS_CTRL_REG,
level);
if (ret)
return ret;
ctx->level = level;
return 0;
return regmap_write(ctx->mcu->regmap, ctx->fan_reg, level);
}
static int khadas_mcu_fan_get_max_state(struct thermal_cooling_device *cdev,
unsigned long *state)
{
*state = MAX_LEVEL;
struct khadas_mcu_fan_ctx *ctx = cdev->devdata;
*state = min_t(unsigned int, MAX_LEVEL, ctx->nlevels - 1);
return 0;
}
@ -60,14 +59,21 @@ khadas_mcu_fan_set_cur_state(struct thermal_cooling_device *cdev,
unsigned long state)
{
struct khadas_mcu_fan_ctx *ctx = cdev->devdata;
int ret;
if (state > MAX_LEVEL)
if (state > MAX_LEVEL || state >= ctx->nlevels)
return -EINVAL;
if (state == ctx->level)
return 0;
return khadas_mcu_fan_set_level(ctx, state);
ret = khadas_mcu_fan_set_level(ctx, ctx->levels[state]);
if (ret)
return ret;
ctx->level = state;
return 0;
}
static const struct thermal_cooling_device_ops khadas_mcu_fan_cooling_ops = {
@ -76,22 +82,71 @@ static const struct thermal_cooling_device_ops khadas_mcu_fan_cooling_ops = {
.set_cur_state = khadas_mcu_fan_set_cur_state,
};
static void khadas_mcu_fan_regulator_disable(void *data)
{
struct regulator *power = data;
regulator_disable(power);
}
static const unsigned int khadas_mcu_fan_levels[] = { 0, 1, 2, 3 };
static const unsigned int khadas_mcu_vim4_fan_levels[] = { 0, 30, 40, 55, 75, 100 };
static int khadas_mcu_fan_probe(struct platform_device *pdev)
{
const struct platform_device_id *id = platform_get_device_id(pdev);
struct khadas_mcu *mcu = dev_get_drvdata(pdev->dev.parent);
struct thermal_cooling_device *cdev;
struct device *dev = &pdev->dev;
struct khadas_mcu_fan_ctx *ctx;
int ret;
if (!dev->of_node)
dev->of_node = of_node_get(dev->parent->of_node);
if (!id)
return -EINVAL;
ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
if (!ctx)
return -ENOMEM;
ctx->mcu = mcu;
switch (id->driver_data) {
case KHADAS_MCU_GENERIC:
ctx->fan_reg = KHADAS_MCU_CMD_FAN_STATUS_CTRL_REG;
ctx->levels = khadas_mcu_fan_levels;
ctx->nlevels = ARRAY_SIZE(khadas_mcu_fan_levels);
break;
case KHADAS_MCU_VIM4:
ctx->fan_reg = KHADAS_MCU_VIM4_FAN_CTRL_REG;
ctx->levels = khadas_mcu_vim4_fan_levels;
ctx->nlevels = ARRAY_SIZE(khadas_mcu_vim4_fan_levels);
break;
default:
return -ENODEV;
}
ctx->power = devm_regulator_get(dev, "fan");
if (IS_ERR(ctx->power))
return PTR_ERR(ctx->power);
ret = regulator_enable(ctx->power);
if (ret) {
dev_err(dev, "Failed to enable fan power supply: %d\n", ret);
return ret;
}
ret = devm_add_action_or_reset(dev, khadas_mcu_fan_regulator_disable, ctx->power);
if (ret)
return ret;
platform_set_drvdata(pdev, ctx);
cdev = devm_thermal_of_child_cooling_device_register(dev->parent,
dev->parent->of_node,
cdev = devm_thermal_of_child_cooling_device_register(dev,
dev->of_node,
"khadas-mcu-fan", ctx,
&khadas_mcu_fan_cooling_ops);
if (IS_ERR(cdev)) {
@ -109,21 +164,24 @@ static void khadas_mcu_fan_shutdown(struct platform_device *pdev)
{
struct khadas_mcu_fan_ctx *ctx = platform_get_drvdata(pdev);
khadas_mcu_fan_set_level(ctx, 0);
khadas_mcu_fan_set_level(ctx, ctx->levels[0]);
}
#ifdef CONFIG_PM_SLEEP
static int khadas_mcu_fan_suspend(struct device *dev)
{
struct khadas_mcu_fan_ctx *ctx = dev_get_drvdata(dev);
unsigned int level_save = ctx->level;
int ret;
ret = khadas_mcu_fan_set_level(ctx, 0);
ret = khadas_mcu_fan_set_level(ctx, ctx->levels[0]);
if (ret)
return ret;
ctx->level = level_save;
ret = regulator_disable(ctx->power);
if (ret) {
khadas_mcu_fan_set_level(ctx, ctx->levels[ctx->level]);
return ret;
}
return 0;
}
@ -131,8 +189,13 @@ static int khadas_mcu_fan_suspend(struct device *dev)
static int khadas_mcu_fan_resume(struct device *dev)
{
struct khadas_mcu_fan_ctx *ctx = dev_get_drvdata(dev);
int ret;
return khadas_mcu_fan_set_level(ctx, ctx->level);
ret = regulator_enable(ctx->power);
if (ret)
return ret;
return khadas_mcu_fan_set_level(ctx, ctx->levels[ctx->level]);
}
#endif
@ -140,7 +203,8 @@ static SIMPLE_DEV_PM_OPS(khadas_mcu_fan_pm, khadas_mcu_fan_suspend,
khadas_mcu_fan_resume);
static const struct platform_device_id khadas_mcu_fan_id_table[] = {
{ .name = "khadas-mcu-fan-ctrl", },
{ .name = "khadas-mcu-fan-ctrl", .driver_data = KHADAS_MCU_GENERIC },
{ .name = "khadas-mcu-vim4-fan", .driver_data = KHADAS_MCU_VIM4 },
{},
};
MODULE_DEVICE_TABLE(platform, khadas_mcu_fan_id_table);

View File

@ -10,7 +10,9 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/property.h>
#include <linux/backlight.h>
#include <linux/regmap.h>
#include <linux/slab.h>
#include <linux/mfd/lm3533.h>
@ -20,13 +22,21 @@
#define LM3533_BL_MAX_BRIGHTNESS 255
#define LM3533_REG_CTRLBANK_AB_BCONF 0x1a
#define CTRLBANK_AB_BCONF_ALS(n) BIT(2 * (n))
#define CTRLBANK_AB_BCONF_MODE(n) BIT(2 * (n) + 1)
struct lm3533_bl {
struct lm3533 *lm3533;
struct regmap *regmap;
struct lm3533_ctrlbank cb;
struct backlight_device *bd;
int id;
u32 max_current;
u32 pwm;
bool have_als;
bool linear;
};
@ -45,7 +55,7 @@ static int lm3533_bl_update_status(struct backlight_device *bd)
static int lm3533_bl_get_brightness(struct backlight_device *bd)
{
struct lm3533_bl *bl = bl_get_data(bd);
u8 val;
u32 val;
int ret;
ret = lm3533_ctrlbank_get_brightness(&bl->cb, &val);
@ -77,103 +87,75 @@ static ssize_t show_als_channel(struct device *dev,
return scnprintf(buf, PAGE_SIZE, "%u\n", channel);
}
static ssize_t show_als_en(struct device *dev,
struct device_attribute *attr, char *buf)
static ssize_t show_als_en(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct lm3533_bl *bl = dev_get_drvdata(dev);
int ctrlbank = lm3533_bl_get_ctrlbank_id(bl);
u8 val;
u8 mask;
bool enable;
int ret;
ret = lm3533_read(bl->lm3533, LM3533_REG_CTRLBANK_AB_BCONF, &val);
if (ret)
ret = regmap_test_bits(bl->regmap, LM3533_REG_CTRLBANK_AB_BCONF,
CTRLBANK_AB_BCONF_ALS(ctrlbank));
if (ret < 0)
return ret;
mask = 1 << (2 * ctrlbank);
enable = val & mask;
return scnprintf(buf, PAGE_SIZE, "%d\n", enable);
return scnprintf(buf, PAGE_SIZE, "%d\n", ret);
}
static ssize_t store_als_en(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t len)
static ssize_t store_als_en(struct device *dev, struct device_attribute *attr,
const char *buf, size_t len)
{
struct lm3533_bl *bl = dev_get_drvdata(dev);
int ctrlbank = lm3533_bl_get_ctrlbank_id(bl);
int enable;
u8 val;
u8 mask;
int ret;
if (kstrtoint(buf, 0, &enable))
return -EINVAL;
mask = 1 << (2 * ctrlbank);
if (enable)
val = mask;
else
val = 0;
ret = lm3533_update(bl->lm3533, LM3533_REG_CTRLBANK_AB_BCONF, val,
mask);
ret = regmap_assign_bits(bl->regmap, LM3533_REG_CTRLBANK_AB_BCONF,
CTRLBANK_AB_BCONF_ALS(ctrlbank), enable);
if (ret)
return ret;
return len;
}
static ssize_t show_linear(struct device *dev,
struct device_attribute *attr, char *buf)
static ssize_t show_linear(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct lm3533_bl *bl = dev_get_drvdata(dev);
u8 val;
u8 mask;
int linear;
int ctrlbank = lm3533_bl_get_ctrlbank_id(bl);
int ret;
ret = lm3533_read(bl->lm3533, LM3533_REG_CTRLBANK_AB_BCONF, &val);
if (ret)
ret = regmap_test_bits(bl->regmap, LM3533_REG_CTRLBANK_AB_BCONF,
CTRLBANK_AB_BCONF_MODE(ctrlbank));
if (ret < 0)
return ret;
mask = 1 << (2 * lm3533_bl_get_ctrlbank_id(bl) + 1);
if (val & mask)
linear = 1;
else
linear = 0;
return scnprintf(buf, PAGE_SIZE, "%x\n", linear);
return scnprintf(buf, PAGE_SIZE, "%x\n", ret);
}
static ssize_t store_linear(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t len)
static ssize_t store_linear(struct device *dev, struct device_attribute *attr,
const char *buf, size_t len)
{
struct lm3533_bl *bl = dev_get_drvdata(dev);
int ctrlbank = lm3533_bl_get_ctrlbank_id(bl);
struct backlight_device *bd = bl->bd;
unsigned long linear;
u8 mask;
u8 val;
int ret;
if (kstrtoul(buf, 0, &linear))
return -EINVAL;
mask = 1 << (2 * lm3533_bl_get_ctrlbank_id(bl) + 1);
if (linear)
val = mask;
else
val = 0;
ret = lm3533_update(bl->lm3533, LM3533_REG_CTRLBANK_AB_BCONF, val,
mask);
ret = regmap_assign_bits(bl->regmap, LM3533_REG_CTRLBANK_AB_BCONF,
CTRLBANK_AB_BCONF_MODE(ctrlbank), linear);
if (ret)
return ret;
bd->props.scale = linear ? BACKLIGHT_SCALE_LINEAR :
BACKLIGHT_SCALE_NON_LINEAR;
return len;
}
@ -182,7 +164,7 @@ static ssize_t show_pwm(struct device *dev,
char *buf)
{
struct lm3533_bl *bl = dev_get_drvdata(dev);
u8 val;
u32 val;
int ret;
ret = lm3533_ctrlbank_get_pwm(&bl->cb, &val);
@ -197,10 +179,10 @@ static ssize_t store_pwm(struct device *dev,
const char *buf, size_t len)
{
struct lm3533_bl *bl = dev_get_drvdata(dev);
u8 val;
u32 val;
int ret;
if (kstrtou8(buf, 0, &val))
if (kstrtou32(buf, 0, &val))
return -EINVAL;
ret = lm3533_ctrlbank_set_pwm(&bl->cb, val);
@ -234,7 +216,7 @@ static umode_t lm3533_bl_attr_is_visible(struct kobject *kobj,
if (attr == &dev_attr_als_channel.attr ||
attr == &dev_attr_als_en.attr) {
if (!bl->lm3533->have_als)
if (!bl->have_als)
mode = 0;
}
@ -246,25 +228,36 @@ static struct attribute_group lm3533_bl_attribute_group = {
.attrs = lm3533_bl_attributes
};
static int lm3533_bl_setup(struct lm3533_bl *bl,
struct lm3533_bl_platform_data *pdata)
static const struct attribute_group *lm3533_bl_attribute_groups[] = {
&lm3533_bl_attribute_group,
NULL,
};
static int lm3533_bl_setup(struct lm3533_bl *bl)
{
int ctrlbank = lm3533_bl_get_ctrlbank_id(bl);
int ret;
ret = lm3533_ctrlbank_set_max_current(&bl->cb, pdata->max_current);
ret = regmap_assign_bits(bl->regmap, LM3533_REG_CTRLBANK_AB_BCONF,
CTRLBANK_AB_BCONF_MODE(ctrlbank), bl->linear);
if (ret)
return ret;
return lm3533_ctrlbank_set_pwm(&bl->cb, pdata->pwm);
ret = lm3533_ctrlbank_set_max_current(&bl->cb, bl->max_current);
if (ret)
return ret;
return lm3533_ctrlbank_set_pwm(&bl->cb, bl->pwm);
}
static int lm3533_bl_probe(struct platform_device *pdev)
{
struct lm3533 *lm3533;
struct lm3533_bl_platform_data *pdata;
struct lm3533_bl *bl;
struct backlight_device *bd;
struct backlight_properties props;
char *name = NULL;
u32 default_brightness = LM3533_BL_MAX_BRIGHTNESS;
int ret;
dev_dbg(&pdev->dev, "%s\n", __func__);
@ -273,12 +266,6 @@ static int lm3533_bl_probe(struct platform_device *pdev)
if (!lm3533)
return -EINVAL;
pdata = dev_get_platdata(&pdev->dev);
if (!pdata) {
dev_err(&pdev->dev, "no platform data\n");
return -EINVAL;
}
if (pdev->id < 0 || pdev->id >= LM3533_HVCTRLBANK_COUNT) {
dev_err(&pdev->dev, "illegal backlight id %d\n", pdev->id);
return -EINVAL;
@ -288,20 +275,34 @@ static int lm3533_bl_probe(struct platform_device *pdev)
if (!bl)
return -ENOMEM;
bl->lm3533 = lm3533;
bl->regmap = lm3533->regmap;
bl->have_als = lm3533->have_als;
bl->id = pdev->id;
bl->cb.lm3533 = lm3533;
bl->cb.regmap = lm3533->regmap;
bl->cb.id = lm3533_bl_get_ctrlbank_id(bl);
bl->cb.dev = NULL; /* until registered */
name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%s-%d",
pdev->name, pdev->id);
if (!name)
return -ENOMEM;
device_property_read_u32(&pdev->dev, "default-brightness",
&default_brightness);
memset(&props, 0, sizeof(props));
props.type = BACKLIGHT_RAW;
props.max_brightness = LM3533_BL_MAX_BRIGHTNESS;
props.brightness = pdata->default_brightness;
bd = devm_backlight_device_register(&pdev->dev, pdata->name,
pdev->dev.parent, bl, &lm3533_bl_ops,
&props);
props.brightness = default_brightness;
bl->linear = device_property_read_bool(&pdev->dev,
"ti,linear-mapping-mode");
props.scale = bl->linear ? BACKLIGHT_SCALE_LINEAR :
BACKLIGHT_SCALE_NON_LINEAR;
bd = devm_backlight_device_register(&pdev->dev, name, &pdev->dev,
bl, &lm3533_bl_ops, &props);
if (IS_ERR(bd)) {
dev_err(&pdev->dev, "failed to register backlight device\n");
return PTR_ERR(bd);
@ -312,28 +313,24 @@ static int lm3533_bl_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, bl);
ret = sysfs_create_group(&bd->dev.kobj, &lm3533_bl_attribute_group);
if (ret < 0) {
dev_err(&pdev->dev, "failed to create sysfs attributes\n");
device_property_read_u32(&pdev->dev, "led-max-microamp",
&bl->max_current);
bl->max_current = clamp(bl->max_current, LM3533_MAX_CURRENT_MIN,
LM3533_MAX_CURRENT_MAX);
device_property_read_u32(&pdev->dev, "ti,pwm-config-mask", &bl->pwm);
ret = lm3533_bl_setup(bl);
if (ret)
return ret;
}
backlight_update_status(bd);
ret = lm3533_bl_setup(bl, pdata);
if (ret)
goto err_sysfs_remove;
ret = lm3533_ctrlbank_enable(&bl->cb);
if (ret)
goto err_sysfs_remove;
return ret;
return 0;
err_sysfs_remove:
sysfs_remove_group(&bd->dev.kobj, &lm3533_bl_attribute_group);
return ret;
}
static void lm3533_bl_remove(struct platform_device *pdev)
@ -347,7 +344,6 @@ static void lm3533_bl_remove(struct platform_device *pdev)
bd->props.brightness = 0;
lm3533_ctrlbank_disable(&bl->cb);
sysfs_remove_group(&bd->dev.kobj, &lm3533_bl_attribute_group);
}
#ifdef CONFIG_PM_SLEEP
@ -381,10 +377,18 @@ static void lm3533_bl_shutdown(struct platform_device *pdev)
lm3533_ctrlbank_disable(&bl->cb);
}
static const struct of_device_id lm3533_bl_match_table[] = {
{ .compatible = "ti,lm3533-backlight" },
{ }
};
MODULE_DEVICE_TABLE(of, lm3533_bl_match_table);
static struct platform_driver lm3533_bl_driver = {
.driver = {
.name = "lm3533-backlight",
.pm = &lm3533_bl_pm_ops,
.dev_groups = lm3533_bl_attribute_groups,
.of_match_table = lm3533_bl_match_table,
},
.probe = lm3533_bl_probe,
.remove = lm3533_bl_remove,

View File

@ -1183,6 +1183,7 @@
/* CS42L43B VARIANT REGISTERS */
#define CS42L43B_DEVID_VAL 0x0042A43B
#define CS42L44_DEVID_VAL 0x00042A44
#define CS42L43B_DECIM_VOL_CTRL_CH1_CH2 0x00008280
#define CS42L43B_DECIM_VOL_CTRL_CH3_CH4 0x00008284

View File

@ -14,7 +14,7 @@
#define DA9063_I2C_PAGE_SEL_SHIFT 1
#define DA9063_EVENT_REG_NUM 4
/* Page selection I2C or SPI always in the begining of any page. */
/* Page selection I2C or SPI always in the beginning of any page. */
/* Page 0 : I2C access 0x000 - 0x0FF SPI access 0x000 - 0x07F */
/* Page 1 : SPI access 0x080 - 0x0FF */
/* Page 2 : I2C access 0x100 - 0x1FF SPI access 0x100 - 0x17F */

View File

@ -65,6 +65,7 @@ struct da9150 {
struct regmap_irq_chip_data *regmap_irq_data;
int irq;
int irq_base;
bool irq_wake_enabled;
};
/* Device I/O - Query Interface for FG and standard register access */

View File

@ -337,31 +337,31 @@ enum sia_mmdsp_stat {
* @SYSCLKOK_ERR: The SYSCLK is not available in the given time
* @BOOT_ERR: Romcode has not validated the XP70 self reset in the given time
* @ROMCODESAVECONTEXT: The Romcode didn.t correctly save it secure context
* @VARMHIGHSPEEDVALTO_ERR: The ARM high speed supply value transfered
* @VARMHIGHSPEEDVALTO_ERR: The ARM high speed supply value transferred
* through I2C has not been correctly executed in the given time
* @VARMHIGHSPEEDACCESS_ERR: The command value of VarmHighSpeedVal transfered
* @VARMHIGHSPEEDACCESS_ERR: The command value of VarmHighSpeedVal transferred
* through I2C has not been correctly executed in the given time
* @VARMLOWSPEEDVALTO_ERR:The ARM low speed supply value transfered through
* @VARMLOWSPEEDVALTO_ERR:The ARM low speed supply value transferred through
* I2C has not been correctly executed in the given time
* @VARMLOWSPEEDACCESS_ERR: The command value of VarmLowSpeedVal transfered
* @VARMLOWSPEEDACCESS_ERR: The command value of VarmLowSpeedVal transferred
* through I2C has not been correctly executed in the given time
* @VARMRETENTIONVALTO_ERR: The ARM retention supply value transfered through
* @VARMRETENTIONVALTO_ERR: The ARM retention supply value transferred through
* I2C has not been correctly executed in the given time
* @VARMRETENTIONACCESS_ERR: The command value of VarmRetentionVal transfered
* @VARMRETENTIONACCESS_ERR: The command value of VarmRetentionVal transferred
* through I2C has not been correctly executed in the given time
* @VAPEHIGHSPEEDVALTO_ERR: The APE highspeed supply value transfered through
* @VAPEHIGHSPEEDVALTO_ERR: The APE highspeed supply value transferred through
* I2C has not been correctly executed in the given time
* @VSAFEHPVALTO_ERR: The SAFE high power supply value transfered through I2C
* @VSAFEHPVALTO_ERR: The SAFE high power supply value transferred through I2C
* has not been correctly executed in the given time
* @VMODSEL1VALTO_ERR: The MODEM sel1 supply value transfered through I2C has
* @VMODSEL1VALTO_ERR: The MODEM sel1 supply value transferred through I2C has
* not been correctly executed in the given time
* @VMODSEL2VALTO_ERR: The MODEM sel2 supply value transfered through I2C has
* @VMODSEL2VALTO_ERR: The MODEM sel2 supply value transferred through I2C has
* not been correctly executed in the given time
* @VARMOFFACCESS_ERR: The command value of Varm ON/OFF transfered through
* @VARMOFFACCESS_ERR: The command value of Varm ON/OFF transferred through
* I2C has not been correctly executed in the given time
* @VAPEOFFACCESS_ERR: The command value of Vape ON/OFF transfered through
* @VAPEOFFACCESS_ERR: The command value of Vape ON/OFF transferred through
* I2C has not been correctly executed in the given time
* @VARMRETACCES_ERR: The command value of Varm retention ON/OFF transfered
* @VARMRETACCES_ERR: The command value of Varm retention ON/OFF transferred
* through I2C has not been correctly executed in the given time
* @CURAPPWRSTISNOTBOOT:Generated when Arm want to do power state transition
* ApBoot to ApExecute but the power current state is not Apboot
@ -376,11 +376,11 @@ enum sia_mmdsp_stat {
* been correctly executed in the given time
* @ARMREGU2VALTO_ERR: The ArmRegu2 value transferred through I2C has not
* been correctly executed in the given time
* @VAPEREGUVALTO_ERR: The VApeRegu value transfered through I2C has not
* @VAPEREGUVALTO_ERR: The VApeRegu value transferred through I2C has not
* been correctly executed in the given time
* @VSMPS3REGUVALTO_ERR: The VSmps3Regu value transfered through I2C has not
* @VSMPS3REGUVALTO_ERR: The VSmps3Regu value transferred through I2C has not
* been correctly executed in the given time
* @VMODREGUVALTO_ERR: The VModemRegu value transfered through I2C has not
* @VMODREGUVALTO_ERR: The VModemRegu value transferred through I2C has not
* been correctly executed in the given time
*/
enum mbox_to_arm_err {

View File

@ -70,6 +70,13 @@
#define KHADAS_MCU_WOL_INIT_START_REG 0x87 /* WO */
#define KHADAS_MCU_CMD_FAN_STATUS_CTRL_REG 0x88 /* WO */
/* VIM4 specific registers */
#define KHADAS_MCU_VIM4_REST_CONF_REG 0x2c /* WO - reset EEPROM */
#define KHADAS_MCU_VIM4_LED_ON_RAM_REG 0x89 /* WO - LED volatile */
#define KHADAS_MCU_VIM4_FAN_CTRL_REG 0x8a /* WO */
#define KHADAS_MCU_VIM4_WDT_EN_REG 0x8b /* WO */
#define KHADAS_MCU_VIM4_SYS_RST_REG 0x91 /* WO */
enum {
KHADAS_BOARD_VIM1 = 0x1,
KHADAS_BOARD_VIM2,
@ -80,7 +87,7 @@ enum {
/**
* struct khadas_mcu - Khadas MCU structure
* @device: device reference used for logs
* @dev: device reference used for logs
* @regmap: register map
*/
struct khadas_mcu {
@ -88,4 +95,14 @@ struct khadas_mcu {
struct regmap *regmap;
};
/**
* enum khadas_mcu_type - Khadas MCU hardware variant
* @KHADAS_MCU_GENERIC: VIM1, VIM2, VIM3, Edge, Edge-V (shared register map)
* @KHADAS_MCU_VIM4: VIM4 (extended register map, distinct fan/LED/WDT regs)
*/
enum khadas_mcu_type {
KHADAS_MCU_GENERIC = 1,
KHADAS_MCU_VIM4,
};
#endif /* MFD_KHADAS_MCU_H */

View File

@ -15,9 +15,14 @@
#define LM3533_ATTR_RW(_name) \
DEVICE_ATTR(_name, S_IRUGO | S_IWUSR , show_##_name, store_##_name)
#define LM3533_MAX_CURRENT_MIN 5000
#define LM3533_MAX_CURRENT_MAX 29800
#define LM3533_MAX_CURRENT_STEP 800
struct device;
struct gpio_desc;
struct regmap;
struct regulator;
struct lm3533 {
struct device *dev;
@ -25,7 +30,10 @@ struct lm3533 {
struct regmap *regmap;
struct gpio_desc *hwen;
int irq;
struct regulator *vin_supply;
u32 boost_ovp;
u32 boost_freq;
unsigned have_als:1;
unsigned have_backlights:1;
@ -33,67 +41,18 @@ struct lm3533 {
};
struct lm3533_ctrlbank {
struct lm3533 *lm3533;
struct regmap *regmap;
struct device *dev;
int id;
};
struct lm3533_als_platform_data {
unsigned pwm_mode:1; /* PWM input mode (default analog) */
u8 r_select; /* 1 - 127 (ignored in PWM-mode) */
};
int lm3533_ctrlbank_enable(struct lm3533_ctrlbank *cb);
int lm3533_ctrlbank_disable(struct lm3533_ctrlbank *cb);
struct lm3533_bl_platform_data {
char *name;
u16 max_current; /* 5000 - 29800 uA (800 uA step) */
u8 default_brightness; /* 0 - 255 */
u8 pwm; /* 0 - 0x3f */
};
struct lm3533_led_platform_data {
char *name;
const char *default_trigger;
u16 max_current; /* 5000 - 29800 uA (800 uA step) */
u8 pwm; /* 0 - 0x3f */
};
enum lm3533_boost_freq {
LM3533_BOOST_FREQ_500KHZ,
LM3533_BOOST_FREQ_1000KHZ,
};
enum lm3533_boost_ovp {
LM3533_BOOST_OVP_16V,
LM3533_BOOST_OVP_24V,
LM3533_BOOST_OVP_32V,
LM3533_BOOST_OVP_40V,
};
struct lm3533_platform_data {
enum lm3533_boost_ovp boost_ovp;
enum lm3533_boost_freq boost_freq;
struct lm3533_als_platform_data *als;
struct lm3533_bl_platform_data *backlights;
int num_backlights;
struct lm3533_led_platform_data *leds;
int num_leds;
};
extern int lm3533_ctrlbank_enable(struct lm3533_ctrlbank *cb);
extern int lm3533_ctrlbank_disable(struct lm3533_ctrlbank *cb);
extern int lm3533_ctrlbank_set_brightness(struct lm3533_ctrlbank *cb, u8 val);
extern int lm3533_ctrlbank_get_brightness(struct lm3533_ctrlbank *cb, u8 *val);
extern int lm3533_ctrlbank_set_max_current(struct lm3533_ctrlbank *cb,
u16 imax);
extern int lm3533_ctrlbank_set_pwm(struct lm3533_ctrlbank *cb, u8 val);
extern int lm3533_ctrlbank_get_pwm(struct lm3533_ctrlbank *cb, u8 *val);
extern int lm3533_read(struct lm3533 *lm3533, u8 reg, u8 *val);
extern int lm3533_write(struct lm3533 *lm3533, u8 reg, u8 val);
extern int lm3533_update(struct lm3533 *lm3533, u8 reg, u8 val, u8 mask);
int lm3533_ctrlbank_set_brightness(struct lm3533_ctrlbank *cb, u32 val);
int lm3533_ctrlbank_get_brightness(struct lm3533_ctrlbank *cb, u32 *val);
int lm3533_ctrlbank_set_max_current(struct lm3533_ctrlbank *cb, u32 imax);
int lm3533_ctrlbank_set_pwm(struct lm3533_ctrlbank *cb, u32 val);
int lm3533_ctrlbank_get_pwm(struct lm3533_ctrlbank *cb, u32 *val);
#endif /* __LINUX_MFD_LM3533_H */

View File

@ -34,7 +34,7 @@
#define LP8788_ALM_IRQ "ALARM_IRQ"
enum lp8788_int_id {
/* interrup register 1 : Addr 00h */
/* interrupt register 1 : Addr 00h */
LP8788_INT_TSDL,
LP8788_INT_TSDH,
LP8788_INT_UVLO,

View File

@ -45,7 +45,7 @@ enum {
/**
* max8998_regulator_data - regulator data
* @id: regulator id
* @initdata: regulator init data (contraints, supplies, ...)
* @initdata: regulator init data (constraints, supplies, ...)
* @reg_node: DT node of regulator (unused on non-DT platforms)
*/
struct max8998_regulator_data {

View File

@ -25,6 +25,13 @@
#define CPCAP_REVISION_2_0 0x10
#define CPCAP_REVISION_2_1 0x11
enum cpcap_variant {
CPCAP_DEFAULT = 1,
CPCAP_MAPPHONE,
CPCAP_MOT,
CPCAP_MAX
};
/* CPCAP registers */
#define CPCAP_REG_INT1 0x0000 /* Interrupt 1 */
#define CPCAP_REG_INT2 0x0004 /* Interrupt 2 */

View File

@ -251,7 +251,7 @@ enum tps65917_regulators {
TPS65917_NUM_REGS,
};
/* External controll signal name */
/* External control signal name */
enum {
PALMAS_EXT_CONTROL_ENABLE1 = 0x1,
PALMAS_EXT_CONTROL_ENABLE2 = 0x2,

View File

@ -186,7 +186,7 @@ enum {
#define BD71828_REG_RTC_ALM2 0x63
#define BD71828_REG_RTC_START BD71828_REG_RTC_SEC
/* Charger/Battey */
/* Charger/Battery */
#define BD71828_REG_CHG_STATE 0x65
#define BD71828_REG_CHG_FULL 0xd2
#define BD71828_REG_CHG_EN 0x6F

View File

@ -106,7 +106,7 @@ struct sec_platform_data {
/**
* sec_regulator_data - regulator data
* @id: regulator id
* @initdata: regulator init data (contraints, supplies, ...)
* @initdata: regulator init data (constraints, supplies, ...)
*/
struct sec_regulator_data {
int id;

View File

@ -94,10 +94,10 @@ enum si476x_power_state {
* of the @rds_fifo_drainer.
* @rds_drainer_status_lock: Lock used to guard access to the
* @rds_drainer_is_working variable.
* @command: Wait queue for wainting on the command comapletion.
* @command: Wait queue for waiting on the command completion.
* @cts: Clear To Send flag set upon receiving first status with CTS
* set.
* @tuning: Wait queue used for wainting for tune/seek comand
* @tuning: Wait queue used for waiting for tune/seek command
* completion.
* @stc: Similar to @cts, but for the STC bit of the status value.
* @power_up_parameters: Parameters used as argument for POWER_UP

View File

@ -739,7 +739,7 @@ int twl4030_sih_setup(struct device *dev, int module, int irq_base);
#define TWL4030_REG_VUSB3V1 19
/* TWL6030 SMPS/LDO's */
/* EXTERNAL dc-to-dc buck convertor controllable via SR */
/* EXTERNAL dc-to-dc buck converter controllable via SR */
#define TWL6030_REG_VDD1 30
#define TWL6030_REG_VDD2 31
#define TWL6030_REG_VDD3 32