MFD for v6.19

* Add Core, Regulator, Onkey and Battery Charger support for the NXP PF1550
     Power Management IC (PMIC).
   * Introduce __SMC_KEY macro to fix GCC 15.2.1 errors in macsmc.
   * Add board definitions for TQMxCU1-HPCM and TQMxCU2-HPCM to the tqmx86 driver.
   * Add support for Broadcom BCM2712 SoC to the bcm2835-pm driver.
   * Hook up the qnap-mcu-eeprom sub-device to qnap-mcu.
 
   * Enable compile testing for the Altera SOCFPGA System Manager driver.
   * Fix device reference leak in altr_sysmgr_regmap_lookup_by_phandle().
   * Reserve the unused second I2C address for DA9063 to prevent userspace
     interference.
   * Fix resource leak in da9055_device_init() by calling regmap_del_irq_chip()
     in the error path.
   * Fix potential IRQ chip conflict when probing multiple MAX77620 devices by
     using devm_kmemdup for regmap_irq_chip.
   * Return -EPROBE_DEFER when a syscon devuice is not found to allow deferred
     probing.
   * Update email address for the PF1550 PMIC driver in MAINTAINERS.
   * Correct file entry for PF1550 MFD driver in MAINTAINERS from pfd1550.h to
     pf1550.h.
   * Calculate checksum on the actual number of received bytes in qnap-mcu for
     error messages.
   * Use -EPROTO instead of -EIO for checksum errors in qnap-mcu.
   * Add proper error handling for command errors (e.g., "@8", "@9") in qnap-mcu.
   * Fix missing irq_domain_remove() in error path of mt63{58,97}_irq_init().
 
   * Mark SMC write buffer arguments as const in apple_smc_write(), apple_smc_rw(),
     and apple_smc_write_atomic().
   * Simplify the error handling path in da9055_device_init() by removing a
     redundant mfd_remove_devices() call.
   * Use regmap_reg_range() and a real one-element array for pmic_status_range in
     rohm-bd718x7 for cleaner initialization.
   * Remove select I2C_K1 from MFD_SPACEMIT_P1 to avoid build failures when
     I2C_K1's dependencies are disabled.
   * Remove unneeded semicolon from ls2k_bmc_recover_pci_data().
   * Drop OF dependency for MFD_MAX5970 in Kconfig to allow wider compile testing
     and non-OF systems.
   * Make OF ID table style consistent in simple-mfd-i2c driver.
   * Update header inclusions in simple-mfd-i2c to follow IWYU (Include What You
     Use) principle.
   * Move checksum verification logic to a separate function in qnap-mcu.
   * Use chained IRQs for S2MPG10 in the Samsung SEC driver to simplify interrupt
     handling.
   * Drop a stray semicolon from sec-irq.c.
 
   * Remove the unused TI WL1273 FM radio core driver.
   * Remove the unused wl1273-core.h header and tidy up its reference in
     documentation.
 
   * Add Device Tree binding for the NXP PF1550 PMIC.
   * Add missing GPIO pins and supply properties to the Silergy SY7636A PMIC
     binding.
   * Add interrupt-controller property to the Maxim MAX77705 binding for
     sub-device interrupt source determination.
   * Add Device Tree binding for the Renesas R2A11302FT PMIC.
   * Allow the wakeup-source property in the Dialog DA9063 binding.
   * Make interrupt-related properties optional in the TI TPS65910 PMIC binding.
   * Document the Qualcomm PMIV0104 PMIC compatible string.
   * Document the Qualcomm PM7550 PMIC compatible string.
   * Enable power button subnode for TWL603x in the TI TWL binding.
   * Convert the Dialog DA9052/53 I2C binding from .txt to .yaml format,
     including compatible string fallback and interrupt properties.
   * Document control-scb and sysreg-scb syscons on pic64gx with fallback
     compatibles.
   * Document sama7g5-sfrbu and sama7d65-sfrbu syscons with fallback to
     atmel,sama5d2-sfrbu.
   * Fix LEDs node schema in fsl,mc13xxx binding by adding led@ child nodes and
     missing properties.
   * Add mt7981-topmisc compatible string to the syscon binding.
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEdrbJNaO+IJqU8IdIUa+KL4f8d2EFAmkxtwoACgkQUa+KL4f8
 d2GiAw/9Ewvlpm+p0Ac/CjxwTRgeM08OJv7xzni3kHtefOvU/0dVTkqJsm3235yc
 SOO4zqCrpldUqAqLzycOmm1bDOMi3qCvmR/Es7gqhkskCHNZ9WDv3z6aZJEAo2g5
 A6RHb5W8lHWc8BqyyyahDfX0D5sHerh03CCWitHkr49oCqzMMaRssVY5Wp1tzKb/
 DYj+gCm8POLu5+0vuGm+I5t90mLOQA/MjHCVBMZ+4vtnXmre6w+fRWNSwGdqhTci
 zsrPUuKUgOy3PvVhjugk4dPHEEwxaZuQ/Az41fpeb8qj0Y0XEaLv6g2/O3Sc8E/j
 esyvbitg49noQCBWpefTUlWZjyxJivLIfIc2n3o+Tn+yWOVZ2+6AqXzhCYOqPeZw
 sodep1W8uweI66+MF67zwTfNuplVLQrRMWbv/mhnvQLxnc8cllhboUUu6SFGQ8hP
 phG5Zf1Gzmz3vJNGZRApwQnwj2nc7tY3FZdZnQW24gBU9tnrIH/LQyOEXoJsvRxC
 AU/VoRA6Tbr1PGuyXJuqaxzkYCbTXUX294wMW9w1HZiXB2wLGDEItLm55pcjZEYI
 ro3GRHW/7UjNg1Omwld5CuszNWFk06SSqBdP4XVJK5tpf02Rplk6EI6ftGH1zaoL
 n7FRKsc7W5Xhky0bTGrtqxNkXodUEVCR45n+wlkJv6VM66m9WeU=
 =2TS8
 -----END PGP SIGNATURE-----

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

Pull MFD updates from Lee Jones:
 "Updates:
   - Add Core, Regulator, Onkey and Battery Charger support for the NXP
     PF1550 Power Management IC (PMIC)
   - Introduce __SMC_KEY macro to fix GCC 15.2.1 errors in macsmc
   - Add board definitions for TQMxCU1-HPCM and TQMxCU2-HPCM to the
     tqmx86 driver
   - Add support for Broadcom BCM2712 SoC to the bcm2835-pm driver
   - Hook up the qnap-mcu-eeprom sub-device to qnap-mcu

  Fixes:
   - Enable compile testing for the Altera SOCFPGA System Manager driver
   - Fix device reference leak in altr_sysmgr_regmap_lookup_by_phandle()
   - Reserve the unused second I2C address for DA9063 to prevent
     userspace interference
   - Fix resource leak in da9055_device_init() by calling
     regmap_del_irq_chip() in the error path
   - Fix potential IRQ chip conflict when probing multiple MAX77620
     devices by using devm_kmemdup for regmap_irq_chip
   - Return -EPROBE_DEFER when a syscon devuice is not found to allow
     deferred probing
   - Update email address for the PF1550 PMIC driver in MAINTAINERS
   - Correct file entry for PF1550 MFD driver in MAINTAINERS from
     pfd1550.h to pf1550.h
   - Calculate checksum on the actual number of received bytes in
     qnap-mcu for error messages
   - Use -EPROTO instead of -EIO for checksum errors in qnap-mcu
   - Add proper error handling for command errors (e.g., "@8", "@9") in
     qnap-mcu
   - Fix missing irq_domain_remove() in error path of
     mt63{58,97}_irq_init()

  Cleanups:
   - Mark SMC write buffer arguments as const in apple_smc_write(),
     apple_smc_rw(), and apple_smc_write_atomic()
   - Simplify the error handling path in da9055_device_init() by
     removing a redundant mfd_remove_devices() call
   - Use regmap_reg_range() and a real one-element array for
     pmic_status_range in rohm-bd718x7 for cleaner initialization
   - Remove select I2C_K1 from MFD_SPACEMIT_P1 to avoid build failures
     when I2C_K1's dependencies are disabled
   - Remove unneeded semicolon from ls2k_bmc_recover_pci_data()
   - Drop OF dependency for MFD_MAX5970 in Kconfig to allow wider
     compile testing and non-OF systems
   - Make OF ID table style consistent in simple-mfd-i2c driver
   - Update header inclusions in simple-mfd-i2c to follow IWYU (Include
     What You Use) principle
   - Move checksum verification logic to a separate function in qnap-mcu
   - Use chained IRQs for S2MPG10 in the Samsung SEC driver to simplify
     interrupt handling
   - Drop a stray semicolon from sec-irq.c

  Removals:
   - Remove the unused TI WL1273 FM radio core driver
   - Remove the unused wl1273-core.h header and tidy up its reference in
     documentation

  Device tree bindings:
   - Add Device Tree binding for the NXP PF1550 PMIC
   - Add missing GPIO pins and supply properties to the Silergy SY7636A
     PMIC binding
   - Add interrupt-controller property to the Maxim MAX77705 binding for
     sub-device interrupt source determination
   - Add Device Tree binding for the Renesas R2A11302FT PMIC
   - Allow the wakeup-source property in the Dialog DA9063 binding
   - Make interrupt-related properties optional in the TI TPS65910 PMIC
     binding
   - Document the Qualcomm PMIV0104 PMIC compatible string
   - Document the Qualcomm PM7550 PMIC compatible string
   - Enable power button subnode for TWL603x in the TI TWL binding
   - Convert the Dialog DA9052/53 I2C binding from .txt to .yaml format,
     including compatible string fallback and interrupt properties
   - Document control-scb and sysreg-scb syscons on pic64gx with
     fallback compatibles
   - Document sama7g5-sfrbu and sama7d65-sfrbu syscons with fallback to
     atmel,sama5d2-sfrbu
   - Fix LEDs node schema in fsl,mc13xxx binding by adding led@ child
     nodes and missing properties
   - Add mt7981-topmisc compatible string to the syscon binding"

* tag 'mfd-next-6.19' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd: (42 commits)
  mfd: sec: Drop a stray semicolon
  mfd: qnap-mcu: Hook up the EEPROM sub-device
  dt-bindings: mfd: syscon: Add mt7981-topmisc
  dt-bindings: mfd: fsl,mc13xxx: Fix LEDs node schema
  mfd: mt6358-irq: Fix missing irq_domain_remove() in error path
  mfd: mt6397-irq: Fix missing irq_domain_remove() in error path
  dt-bindings: mfd: Document syscons falling back to atmel,sama5d2-sfrbu
  dt-bindings: mfd: Document control-scb and sysreg-scb on pic64gx
  dt-bindings: mfd: Convert dlg,da9052-i2c.txt to yaml format
  mfd: sec: Use chained IRQs for s2mpg10
  mfd: qnap-mcu: Add proper error handling for command errors
  mfd: qnap-mcu: Move checksum verification to its own function
  mfd: qnap-mcu: Use EPROTO in stead of EIO on checksum errors
  mfd: qnap-mcu: Calculate the checksum on the actual number of bytes received
  mfd: simple-mfd-i2c: Don't use "proxy" headers
  mfd: simple-mfd-i2c: Make ID table style consistent
  mfd: Kconfig: Drop OF dependency on MFD_MAX5970
  mfd: ls2kbmc: Remove unneeded semicolon from ls2k_bmc_recover_pci_data()
  dt-bindings: mfd: twl: Enable power button also for TWL603X
  MAINTAINERS: Adjust file entry in NXP PF1550 PMIC MFD DRIVER
  ...
This commit is contained in:
Linus Torvalds 2025-12-04 15:18:33 -08:00
commit 980190a947
36 changed files with 583 additions and 821 deletions

View File

@ -696,6 +696,7 @@ Sakari Ailus <sakari.ailus@linux.intel.com> <sakari.ailus@iki.fi>
Sam Protsenko <semen.protsenko@linaro.org> Sam Protsenko <semen.protsenko@linaro.org>
Sam Protsenko <semen.protsenko@linaro.org> <semen.protsenko@globallogic.com> Sam Protsenko <semen.protsenko@linaro.org> <semen.protsenko@globallogic.com>
Sam Ravnborg <sam@mars.ravnborg.org> Sam Ravnborg <sam@mars.ravnborg.org>
Samuel Kayode <samkay014@gmail.com> <samuel.kayode@savoirfairelinux.com>
Sankeerth Billakanti <quic_sbillaka@quicinc.com> <sbillaka@codeaurora.org> Sankeerth Billakanti <quic_sbillaka@quicinc.com> <sbillaka@codeaurora.org>
Santosh Shilimkar <santosh.shilimkar@oracle.org> Santosh Shilimkar <santosh.shilimkar@oracle.org>
Santosh Shilimkar <ssantosh@kernel.org> Santosh Shilimkar <ssantosh@kernel.org>

View File

@ -30,7 +30,6 @@ radio-terratec TerraTec ActiveRadio ISA Standalone
radio-timb Enable the Timberdale radio driver radio-timb Enable the Timberdale radio driver
radio-trust Trust FM radio card radio-trust Trust FM radio card
radio-typhoon Typhoon Radio (a.k.a. EcoRadio) radio-typhoon Typhoon Radio (a.k.a. EcoRadio)
radio-wl1273 Texas Instruments WL1273 I2C FM Radio
fm_drv ISA radio devices fm_drv ISA radio devices
fm_drv ISA radio devices fm_drv ISA radio devices
radio-zoltrix Zoltrix Radio radio-zoltrix Zoltrix Radio

View File

@ -1,67 +0,0 @@
* Dialog DA9052/53 Power Management Integrated Circuit (PMIC)
Required properties:
- compatible : Should be "dlg,da9052", "dlg,da9053-aa",
"dlg,da9053-ab", or "dlg,da9053-bb"
Optional properties:
- dlg,tsi-as-adc : Boolean, if set the X+, X-, Y+, Y- touchscreen
input lines are used as general purpose analogue
input.
- tsiref-supply: Phandle to the regulator, which provides the reference
voltage for the TSIREF pin. Must be provided when the
touchscreen pins are used for ADC purposes.
Sub-nodes:
- regulators : Contain the regulator nodes. The DA9052/53 regulators are
bound using their names as listed below:
buck1 : regulator BUCK CORE
buck2 : regulator BUCK PRO
buck3 : regulator BUCK MEM
buck4 : regulator BUCK PERI
ldo1 : regulator LDO1
ldo2 : regulator LDO2
ldo3 : regulator LDO3
ldo4 : regulator LDO4
ldo5 : regulator LDO5
ldo6 : regulator LDO6
ldo7 : regulator LDO7
ldo8 : regulator LDO8
ldo9 : regulator LDO9
ldo10 : regulator LDO10
The bindings details of individual regulator device can be found in:
Documentation/devicetree/bindings/regulator/regulator.txt
Examples:
i2c@63fc8000 { /* I2C1 */
pmic: dialog@48 {
compatible = "dlg,da9053-aa";
reg = <0x48>;
regulators {
buck1 {
regulator-min-microvolt = <500000>;
regulator-max-microvolt = <2075000>;
};
buck2 {
regulator-min-microvolt = <500000>;
regulator-max-microvolt = <2075000>;
};
buck3 {
regulator-min-microvolt = <925000>;
regulator-max-microvolt = <2500000>;
};
buck4 {
regulator-min-microvolt = <925000>;
regulator-max-microvolt = <2500000>;
};
};
};
};

View File

@ -0,0 +1,89 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/mfd/dlg,da9052.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Dialog DA9052/53 Power Management Integrated Circuit (PMIC)
maintainers:
- Frank Li <Frank.Li@nxp.com>
properties:
compatible:
oneOf:
- enum:
- dlg,da9053-aa
- dlg,da9053-ab
- dlg,da9053-bb
- dlg,da9053-bc
- dlg,da9052
reg:
maxItems: 1
interrupts:
maxItems: 1
dlg,tsi-as-adc:
type: boolean
description:
if set the X+, X-, Y+, Y- touchscreen input lines are used as general
purpose analogue input.
tsiref-supply:
description: The reference voltage for the TSIREF pin.
regulators:
type: object
additionalProperties: false
patternProperties:
"^(ldo([1-9]|10)|buck[1-4])$":
type: object
$ref: /schemas/regulator/regulator.yaml#
unevaluatedProperties: false
required:
- compatible
- reg
- regulators
allOf:
- $ref: /schemas/spi/spi-peripheral-props.yaml#
unevaluatedProperties: false
examples:
- |
i2c {
#address-cells = <1>;
#size-cells = <0>;
pmic@48 {
compatible = "dlg,da9053-aa";
reg = <0x48>;
regulators {
buck1 {
regulator-min-microvolt = <500000>;
regulator-max-microvolt = <2075000>;
};
buck2 {
regulator-min-microvolt = <500000>;
regulator-max-microvolt = <2075000>;
};
buck3 {
regulator-min-microvolt = <925000>;
regulator-max-microvolt = <2500000>;
};
buck4 {
regulator-min-microvolt = <925000>;
regulator-max-microvolt = <2500000>;
};
};
};
};

View File

@ -81,6 +81,8 @@ properties:
watchdog: watchdog:
$ref: /schemas/watchdog/dlg,da9062-watchdog.yaml $ref: /schemas/watchdog/dlg,da9062-watchdog.yaml
wakeup-source: true
patternProperties: patternProperties:
"^(.+-hog(-[0-9]+)?)$": "^(.+-hog(-[0-9]+)?)$":
type: object type: object

View File

@ -93,7 +93,25 @@ properties:
leds: leds:
type: object type: object
additionalProperties: false
properties:
'#address-cells':
const: 1
'#size-cells':
const: 0
led-control:
$ref: /schemas/types.yaml#/definitions/uint32-array
description: |
Setting for LED-Control register array length depends on model,
mc13783: 6, mc13892: 4, mc34708: 1
patternProperties:
'^led@[0-9a-b]$':
$ref: /schemas/leds/common.yaml# $ref: /schemas/leds/common.yaml#
unevaluatedProperties: false
properties: properties:
reg: reg:
@ -126,12 +144,6 @@ properties:
1: Charger Green 1: Charger Green
maxItems: 1 maxItems: 1
led-control:
$ref: /schemas/types.yaml#/definitions/uint32-array
description: |
Setting for LED-Control register array length depends on model,
mc13783: 6, mc13892: 4, mc34708: 1
regulators: regulators:
type: object type: object
@ -262,7 +274,7 @@ examples:
#size-cells = <0>; #size-cells = <0>;
led-control = <0x000 0x000 0x0e0 0x000>; led-control = <0x000 0x000 0x0e0 0x000>;
sysled@3 { led@3 {
reg = <3>; reg = <3>;
label = "system:red:live"; label = "system:red:live";
linux,default-trigger = "heartbeat"; linux,default-trigger = "heartbeat";

View File

@ -26,6 +26,18 @@ properties:
interrupts: interrupts:
maxItems: 1 maxItems: 1
interrupt-controller:
description:
The driver implements an interrupt controller for the sub devices.
The interrupt number mapping is as follows
0 - charger
1 - topsys
2 - fuelgauge
3 - usb type-c management block.
'#interrupt-cells':
const: 1
haptic: haptic:
type: object type: object
additionalProperties: false additionalProperties: false
@ -118,8 +130,10 @@ examples:
pmic@66 { pmic@66 {
compatible = "maxim,max77705"; compatible = "maxim,max77705";
reg = <0x66>; reg = <0x66>;
#interrupt-cells = <1>;
interrupt-parent = <&pm8998_gpios>; interrupt-parent = <&pm8998_gpios>;
interrupts = <11 IRQ_TYPE_LEVEL_LOW>; interrupts = <11 IRQ_TYPE_LEVEL_LOW>;
interrupt-controller;
pinctrl-0 = <&chg_int_default>; pinctrl-0 = <&chg_int_default>;
pinctrl-names = "default"; pinctrl-names = "default";

View File

@ -43,6 +43,7 @@ properties:
- qcom,pm7250b - qcom,pm7250b
- qcom,pm7550ba - qcom,pm7550ba
- qcom,pm7325 - qcom,pm7325
- qcom,pm7550
- qcom,pm8004 - qcom,pm8004
- qcom,pm8005 - qcom,pm8005
- qcom,pm8009 - qcom,pm8009
@ -84,6 +85,7 @@ properties:
- qcom,pmi8994 - qcom,pmi8994
- qcom,pmi8998 - qcom,pmi8998
- qcom,pmih0108 - qcom,pmih0108
- qcom,pmiv0104
- qcom,pmk8002 - qcom,pmk8002
- qcom,pmk8350 - qcom,pmk8350
- qcom,pmk8550 - qcom,pmk8550

View File

@ -0,0 +1,58 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/mfd/renesas,r2a11302ft.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Renesas R2A11302FT Power Supply ICs for R-Car
maintainers:
- Wolfram Sang <wsa+renesas@sang-engineering.com>
description: |
The Renesas R2A11302FT PMIC is used with Renesas R-Car Gen1/Gen2
based SoCs.
FIXME: The binding is incomplete and resembles the information gathered
so far.
properties:
compatible:
const: renesas,r2a11302ft
reg:
maxItems: 1
spi-max-frequency:
maximum: 6000000
spi-cpol: true
spi-cpha: true
required:
- compatible
- reg
- spi-cpol
- spi-cpha
allOf:
- $ref: /schemas/spi/spi-peripheral-props.yaml#
unevaluatedProperties: false
examples:
- |
spi {
#address-cells = <1>;
#size-cells = <0>;
pmic@0 {
compatible = "renesas,r2a11302ft";
reg = <0>;
spi-max-frequency = <6000000>;
spi-cpol;
spi-cpha;
};
};
...

View File

@ -32,6 +32,17 @@ properties:
Specifying the power good GPIOs. Specifying the power good GPIOs.
maxItems: 1 maxItems: 1
enable-gpios:
maxItems: 1
vcom-en-gpios:
maxItems: 1
vin-supply:
description:
Supply for the whole chip. Some vendor kernels and devicetrees
declare this as a non-existing GPIO named "pwrall".
regulators: regulators:
type: object type: object

View File

@ -85,6 +85,7 @@ select:
- mediatek,mt2701-pctl-a-syscfg - mediatek,mt2701-pctl-a-syscfg
- mediatek,mt2712-pctl-a-syscfg - mediatek,mt2712-pctl-a-syscfg
- mediatek,mt6397-pctl-pmic-syscfg - mediatek,mt6397-pctl-pmic-syscfg
- mediatek,mt7981-topmisc
- mediatek,mt7988-topmisc - mediatek,mt7988-topmisc
- mediatek,mt8135-pctl-a-syscfg - mediatek,mt8135-pctl-a-syscfg
- mediatek,mt8135-pctl-b-syscfg - mediatek,mt8135-pctl-b-syscfg
@ -133,7 +134,8 @@ select:
properties: properties:
compatible: compatible:
items: oneOf:
- items:
- enum: - enum:
- airoha,en7581-pbus-csr - airoha,en7581-pbus-csr
- al,alpine-sysfabric-service - al,alpine-sysfabric-service
@ -238,6 +240,20 @@ properties:
- ti,j784s4-pcie-ctrl - ti,j784s4-pcie-ctrl
- ti,keystone-pllctrl - ti,keystone-pllctrl
- const: syscon - const: syscon
- items:
- enum:
- microchip,sama7g5-sfrbu
- microchip,sama7d65-sfrbu
- const: atmel,sama5d2-sfrbu
- const: syscon
- items:
- const: microchip,pic64gx-control-scb
- const: microchip,mpfs-control-scb
- const: syscon
- items:
- const: microchip,pic64gx-sysreg-scb
- const: microchip,mpfs-sysreg-scb
- const: syscon
reg: reg:
maxItems: 1 maxItems: 1

View File

@ -166,9 +166,6 @@ patternProperties:
required: required:
- compatible - compatible
- reg - reg
- interrupts
- interrupt-controller
- '#interrupt-cells'
- gpio-controller - gpio-controller
- '#gpio-cells' - '#gpio-cells'
- regulators - regulators

View File

@ -55,6 +55,15 @@ allOf:
gpadc: false gpadc: false
pwrbutton:
properties:
compatible:
const: ti,twl4030-pwrbutton
interrupts:
items:
- items:
const: 8
usb-comparator: false usb-comparator: false
- if: - if:
@ -95,7 +104,14 @@ allOf:
compatible: compatible:
const: ti,twl6030-gpadc const: ti,twl6030-gpadc
pwrbutton: false pwrbutton:
properties:
compatible:
const: ti,twl6030-pwrbutton
interrupts:
items:
- items:
const: 0
madc: false madc: false
@ -146,7 +162,14 @@ allOf:
compatible: compatible:
const: ti,twl6032-gpadc const: ti,twl6032-gpadc
pwrbutton: false pwrbutton:
properties:
compatible:
const: ti,twl6030-pwrbutton
interrupts:
items:
- items:
const: 0
madc: false madc: false
@ -226,11 +249,11 @@ properties:
properties: properties:
compatible: compatible:
const: ti,twl4030-pwrbutton enum:
- ti,twl4030-pwrbutton
- ti,twl6030-pwrbutton
interrupts: interrupts:
items: maxItems: 1
- items:
const: 8
watchdog: watchdog:
type: object type: object
@ -459,6 +482,11 @@ examples:
#io-channel-cells = <1>; #io-channel-cells = <1>;
}; };
pwrbutton {
compatible = "ti,twl6030-pwrbutton";
interrupts = <0>;
};
rtc { rtc {
compatible = "ti,twl4030-rtc"; compatible = "ti,twl4030-rtc";
interrupts = <8>; interrupts = <8>;

View File

@ -18742,7 +18742,7 @@ F: Documentation/devicetree/bindings/regulator/nxp,pf5300.yaml
F: drivers/regulator/pf530x-regulator.c F: drivers/regulator/pf530x-regulator.c
NXP PF1550 PMIC MFD DRIVER NXP PF1550 PMIC MFD DRIVER
M: Samuel Kayode <samuel.kayode@savoirfairelinux.com> M: Samuel Kayode <samkay014@gmail.com>
L: imx@lists.linux.dev L: imx@lists.linux.dev
S: Maintained S: Maintained
F: Documentation/devicetree/bindings/mfd/nxp,pf1550.yaml F: Documentation/devicetree/bindings/mfd/nxp,pf1550.yaml
@ -18750,7 +18750,7 @@ F: drivers/input/misc/pf1550-onkey.c
F: drivers/mfd/pf1550.c F: drivers/mfd/pf1550.c
F: drivers/power/supply/pf1550-charger.c F: drivers/power/supply/pf1550-charger.c
F: drivers/regulator/pf1550-regulator.c F: drivers/regulator/pf1550-regulator.c
F: include/linux/mfd/pfd1550.h F: include/linux/mfd/pf1550.h
NXP PF8100/PF8121A/PF8200 PMIC REGULATOR DEVICE DRIVER NXP PF8100/PF8121A/PF8200 PMIC REGULATOR DEVICE DRIVER
M: Jagan Teki <jagan@amarulasolutions.com> M: Jagan Teki <jagan@amarulasolutions.com>

View File

@ -45,7 +45,8 @@ config MFD_ALTERA_A10SR
config MFD_ALTERA_SYSMGR config MFD_ALTERA_SYSMGR
bool "Altera SOCFPGA System Manager" bool "Altera SOCFPGA System Manager"
depends on ARCH_INTEL_SOCFPGA && OF depends on ARCH_INTEL_SOCFPGA || COMPILE_TEST
depends on OF
select MFD_SYSCON select MFD_SYSCON
help help
Select this to get System Manager support for all Altera branded Select this to get System Manager support for all Altera branded
@ -895,7 +896,7 @@ config MFD_88PM886_PMIC
config MFD_MAX5970 config MFD_MAX5970
tristate "Maxim 5970/5978 power switch and monitor" tristate "Maxim 5970/5978 power switch and monitor"
depends on I2C && OF depends on I2C
select MFD_SIMPLE_MFD_I2C select MFD_SIMPLE_MFD_I2C
help help
This driver controls a Maxim 5970/5978 switch via I2C bus. This driver controls a Maxim 5970/5978 switch via I2C bus.
@ -1274,7 +1275,6 @@ config MFD_SPACEMIT_P1
tristate "SpacemiT P1 PMIC" tristate "SpacemiT P1 PMIC"
depends on ARCH_SPACEMIT || COMPILE_TEST depends on ARCH_SPACEMIT || COMPILE_TEST
depends on I2C depends on I2C
select I2C_K1
select MFD_SIMPLE_MFD_I2C select MFD_SIMPLE_MFD_I2C
help help
This option supports the I2C-based SpacemiT P1 PMIC, which This option supports the I2C-based SpacemiT P1 PMIC, which
@ -2002,16 +2002,6 @@ config MENELAUS
and other features that are often used in portable devices like and other features that are often used in portable devices like
cell phones and PDAs. cell phones and PDAs.
config MFD_WL1273_CORE
tristate "TI WL1273 FM radio"
depends on I2C
select MFD_CORE
default n
help
This is the core driver for the TI WL1273 FM radio. This MFD
driver connects the radio-wl1273 V4L2 module and the wl1273
audio codec.
config MFD_LM3533 config MFD_LM3533
tristate "TI/National Semiconductor LM3533 Lighting Power chip" tristate "TI/National Semiconductor LM3533 Lighting Power chip"
depends on I2C depends on I2C

View File

@ -207,7 +207,6 @@ obj-$(CONFIG_MFD_RDC321X) += rdc321x-southbridge.o
obj-$(CONFIG_MFD_JANZ_CMODIO) += janz-cmodio.o obj-$(CONFIG_MFD_JANZ_CMODIO) += janz-cmodio.o
obj-$(CONFIG_MFD_TPS6586X) += tps6586x.o obj-$(CONFIG_MFD_TPS6586X) += tps6586x.o
obj-$(CONFIG_MFD_VX855) += vx855.o obj-$(CONFIG_MFD_VX855) += vx855.o
obj-$(CONFIG_MFD_WL1273_CORE) += wl1273-core.o
si476x-core-y := si476x-cmd.o si476x-prop.o si476x-i2c.o si476x-core-y := si476x-cmd.o si476x-prop.o si476x-i2c.o
obj-$(CONFIG_MFD_SI476X_CORE) += si476x-core.o obj-$(CONFIG_MFD_SI476X_CORE) += si476x-core.o

View File

@ -117,6 +117,8 @@ struct regmap *altr_sysmgr_regmap_lookup_by_phandle(struct device_node *np,
sysmgr = dev_get_drvdata(dev); sysmgr = dev_get_drvdata(dev);
put_device(dev);
return sysmgr->regmap; return sysmgr->regmap;
} }
EXPORT_SYMBOL_GPL(altr_sysmgr_regmap_lookup_by_phandle); EXPORT_SYMBOL_GPL(altr_sysmgr_regmap_lookup_by_phandle);

View File

@ -108,6 +108,7 @@ static const struct of_device_id bcm2835_pm_of_match[] = {
{ .compatible = "brcm,bcm2835-pm-wdt", }, { .compatible = "brcm,bcm2835-pm-wdt", },
{ .compatible = "brcm,bcm2835-pm", }, { .compatible = "brcm,bcm2835-pm", },
{ .compatible = "brcm,bcm2711-pm", }, { .compatible = "brcm,bcm2711-pm", },
{ .compatible = "brcm,bcm2712-pm", },
{}, {},
}; };
MODULE_DEVICE_TABLE(of, bcm2835_pm_of_match); MODULE_DEVICE_TABLE(of, bcm2835_pm_of_match);

View File

@ -387,7 +387,7 @@ int da9055_device_init(struct da9055 *da9055)
return 0; return 0;
err: err:
mfd_remove_devices(da9055->dev); regmap_del_irq_chip(da9055->chip_irq, da9055->irq_data);
return ret; return ret;
} }

View File

@ -469,6 +469,9 @@ static int da9063_i2c_probe(struct i2c_client *i2c)
} }
} }
/* Reserve our unused second address so userspace won't interfere */
devm_i2c_new_dummy_device(&i2c->dev, i2c->adapter, i2c->addr + 1);
return da9063_device_init(da9063, i2c->irq); return da9063_device_init(da9063, i2c->irq);
} }

View File

@ -265,7 +265,7 @@ static int ls2k_bmc_recover_pci_data(void *data)
if (!ls2k_bmc_bar0_addr_is_set(parent)) if (!ls2k_bmc_bar0_addr_is_set(parent))
break; break;
mdelay(1); mdelay(1);
}; }
if (i == 0) if (i == 0)
return false; return false;

View File

@ -173,7 +173,7 @@ int apple_smc_read(struct apple_smc *smc, smc_key key, void *buf, size_t size)
} }
EXPORT_SYMBOL(apple_smc_read); EXPORT_SYMBOL(apple_smc_read);
int apple_smc_write(struct apple_smc *smc, smc_key key, void *buf, size_t size) int apple_smc_write(struct apple_smc *smc, smc_key key, const void *buf, size_t size)
{ {
guard(mutex)(&smc->mutex); guard(mutex)(&smc->mutex);
@ -181,7 +181,7 @@ int apple_smc_write(struct apple_smc *smc, smc_key key, void *buf, size_t size)
} }
EXPORT_SYMBOL(apple_smc_write); EXPORT_SYMBOL(apple_smc_write);
int apple_smc_rw(struct apple_smc *smc, smc_key key, void *wbuf, size_t wsize, int apple_smc_rw(struct apple_smc *smc, smc_key key, const void *wbuf, size_t wsize,
void *rbuf, size_t rsize) void *rbuf, size_t rsize)
{ {
guard(mutex)(&smc->mutex); guard(mutex)(&smc->mutex);
@ -239,7 +239,7 @@ int apple_smc_enter_atomic(struct apple_smc *smc)
} }
EXPORT_SYMBOL(apple_smc_enter_atomic); EXPORT_SYMBOL(apple_smc_enter_atomic);
int apple_smc_write_atomic(struct apple_smc *smc, smc_key key, void *buf, size_t size) int apple_smc_write_atomic(struct apple_smc *smc, smc_key key, const void *buf, size_t size)
{ {
guard(spinlock_irqsave)(&smc->lock); guard(spinlock_irqsave)(&smc->lock);
u8 result; u8 result;

View File

@ -254,7 +254,7 @@ static int max77620_irq_global_unmask(void *irq_drv_data)
return ret; return ret;
} }
static struct regmap_irq_chip max77620_top_irq_chip = { static const struct regmap_irq_chip max77620_top_irq_chip = {
.name = "max77620-top", .name = "max77620-top",
.irqs = max77620_top_irqs, .irqs = max77620_top_irqs,
.num_irqs = ARRAY_SIZE(max77620_top_irqs), .num_irqs = ARRAY_SIZE(max77620_top_irqs),
@ -498,6 +498,7 @@ static int max77620_probe(struct i2c_client *client)
const struct i2c_device_id *id = i2c_client_get_device_id(client); const struct i2c_device_id *id = i2c_client_get_device_id(client);
const struct regmap_config *rmap_config; const struct regmap_config *rmap_config;
struct max77620_chip *chip; struct max77620_chip *chip;
struct regmap_irq_chip *chip_desc;
const struct mfd_cell *mfd_cells; const struct mfd_cell *mfd_cells;
int n_mfd_cells; int n_mfd_cells;
bool pm_off; bool pm_off;
@ -508,6 +509,14 @@ static int max77620_probe(struct i2c_client *client)
return -ENOMEM; return -ENOMEM;
i2c_set_clientdata(client, chip); i2c_set_clientdata(client, chip);
chip_desc = devm_kmemdup(&client->dev, &max77620_top_irq_chip,
sizeof(max77620_top_irq_chip),
GFP_KERNEL);
if (!chip_desc)
return -ENOMEM;
chip_desc->irq_drv_data = chip;
chip->dev = &client->dev; chip->dev = &client->dev;
chip->chip_irq = client->irq; chip->chip_irq = client->irq;
chip->chip_id = (enum max77620_chip_id)id->driver_data; chip->chip_id = (enum max77620_chip_id)id->driver_data;
@ -544,11 +553,9 @@ static int max77620_probe(struct i2c_client *client)
if (ret < 0) if (ret < 0)
return ret; return ret;
max77620_top_irq_chip.irq_drv_data = chip;
ret = devm_regmap_add_irq_chip(chip->dev, chip->rmap, client->irq, ret = devm_regmap_add_irq_chip(chip->dev, chip->rmap, client->irq,
IRQF_ONESHOT | IRQF_SHARED, 0, IRQF_ONESHOT | IRQF_SHARED, 0,
&max77620_top_irq_chip, chip_desc, &chip->top_irq_data);
&chip->top_irq_data);
if (ret < 0) { if (ret < 0) {
dev_err(chip->dev, "Failed to add regmap irq: %d\n", ret); dev_err(chip->dev, "Failed to add regmap irq: %d\n", ret);
return ret; return ret;

View File

@ -285,6 +285,7 @@ int mt6358_irq_init(struct mt6397_chip *chip)
if (ret) { if (ret) {
dev_err(chip->dev, "Failed to register IRQ=%d, ret=%d\n", dev_err(chip->dev, "Failed to register IRQ=%d, ret=%d\n",
chip->irq, ret); chip->irq, ret);
irq_domain_remove(chip->irq_domain);
return ret; return ret;
} }

View File

@ -229,6 +229,7 @@ int mt6397_irq_init(struct mt6397_chip *chip)
if (ret) { if (ret) {
dev_err(chip->dev, "failed to register irq=%d; err: %d\n", dev_err(chip->dev, "failed to register irq=%d; err: %d\n",
chip->irq, ret); chip->irq, ret);
irq_domain_remove(chip->irq_domain);
return ret; return ret;
} }

View File

@ -19,6 +19,7 @@
/* The longest command found so far is 5 bytes long */ /* The longest command found so far is 5 bytes long */
#define QNAP_MCU_MAX_CMD_SIZE 5 #define QNAP_MCU_MAX_CMD_SIZE 5
#define QNAP_MCU_MAX_DATA_SIZE 36 #define QNAP_MCU_MAX_DATA_SIZE 36
#define QNAP_MCU_ERROR_SIZE 2
#define QNAP_MCU_CHECKSUM_SIZE 1 #define QNAP_MCU_CHECKSUM_SIZE 1
#define QNAP_MCU_RX_BUFFER_SIZE \ #define QNAP_MCU_RX_BUFFER_SIZE \
@ -78,6 +79,13 @@ static u8 qnap_mcu_csum(const u8 *buf, size_t size)
return csum; return csum;
} }
static bool qnap_mcu_verify_checksum(const u8 *buf, size_t size)
{
u8 crc = qnap_mcu_csum(buf, size - QNAP_MCU_CHECKSUM_SIZE);
return crc == buf[size - QNAP_MCU_CHECKSUM_SIZE];
}
static int qnap_mcu_write(struct qnap_mcu *mcu, const u8 *data, u8 data_size) static int qnap_mcu_write(struct qnap_mcu *mcu, const u8 *data, u8 data_size)
{ {
unsigned char tx[QNAP_MCU_TX_BUFFER_SIZE]; unsigned char tx[QNAP_MCU_TX_BUFFER_SIZE];
@ -96,6 +104,48 @@ static int qnap_mcu_write(struct qnap_mcu *mcu, const u8 *data, u8 data_size)
return serdev_device_write(mcu->serdev, tx, length, HZ); return serdev_device_write(mcu->serdev, tx, length, HZ);
} }
static bool qnap_mcu_is_error_msg(size_t size)
{
return (size == QNAP_MCU_ERROR_SIZE + QNAP_MCU_CHECKSUM_SIZE);
}
static bool qnap_mcu_reply_is_generic_error(unsigned char *buf, size_t size)
{
if (!qnap_mcu_is_error_msg(size))
return false;
if (buf[0] == '@' && buf[1] == '9')
return true;
return false;
}
static bool qnap_mcu_reply_is_checksum_error(unsigned char *buf, size_t size)
{
if (!qnap_mcu_is_error_msg(size))
return false;
if (buf[0] == '@' && buf[1] == '8')
return true;
return false;
}
static bool qnap_mcu_reply_is_any_error(struct qnap_mcu *mcu, unsigned char *buf, size_t size)
{
if (qnap_mcu_reply_is_generic_error(buf, size)) {
dev_err(&mcu->serdev->dev, "Controller sent generic error response\n");
return true;
}
if (qnap_mcu_reply_is_checksum_error(buf, size)) {
dev_err(&mcu->serdev->dev, "Controller received invalid checksum for the command\n");
return true;
}
return false;
}
static size_t qnap_mcu_receive_buf(struct serdev_device *serdev, const u8 *buf, size_t size) static size_t qnap_mcu_receive_buf(struct serdev_device *serdev, const u8 *buf, size_t size)
{ {
struct device *dev = &serdev->dev; struct device *dev = &serdev->dev;
@ -129,6 +179,24 @@ static size_t qnap_mcu_receive_buf(struct serdev_device *serdev, const u8 *buf,
} }
} }
/*
* We received everything the uart had to offer for now.
* This could mean that either the uart will send more in a 2nd
* receive run, or that the MCU cut the reply short because it
* sent an error code instead of the expected reply.
*
* So check if the received data has the correct size for an error
* reply and if it matches, is an actual error code.
*/
if (qnap_mcu_is_error_msg(reply->received) &&
qnap_mcu_verify_checksum(reply->data, reply->received) &&
qnap_mcu_reply_is_any_error(mcu, reply->data, reply->received)) {
/* The reply was an error code, we're done */
reply->length = 0;
complete(&reply->done);
}
/* /*
* The only way to get out of the above loop and end up here * The only way to get out of the above loop and end up here
* is through consuming all of the supplied data, so here we * is through consuming all of the supplied data, so here we
@ -150,7 +218,6 @@ int qnap_mcu_exec(struct qnap_mcu *mcu,
size_t length = reply_data_size + QNAP_MCU_CHECKSUM_SIZE; size_t length = reply_data_size + QNAP_MCU_CHECKSUM_SIZE;
struct qnap_mcu_reply *reply = &mcu->reply; struct qnap_mcu_reply *reply = &mcu->reply;
int ret = 0; int ret = 0;
u8 crc;
if (length > sizeof(rx)) { if (length > sizeof(rx)) {
dev_err(&mcu->serdev->dev, "expected data too big for receive buffer"); dev_err(&mcu->serdev->dev, "expected data too big for receive buffer");
@ -175,12 +242,14 @@ int qnap_mcu_exec(struct qnap_mcu *mcu,
return -ETIMEDOUT; return -ETIMEDOUT;
} }
crc = qnap_mcu_csum(rx, reply_data_size); if (!qnap_mcu_verify_checksum(rx, reply->received)) {
if (crc != rx[reply_data_size]) { dev_err(&mcu->serdev->dev, "Invalid Checksum received from controller\n");
dev_err(&mcu->serdev->dev, "Invalid Checksum received\n"); return -EPROTO;
return -EIO;
} }
if (qnap_mcu_reply_is_any_error(mcu, rx, reply->received))
return -EPROTO;
memcpy(reply_data, rx, reply_data_size); memcpy(reply_data, rx, reply_data_size);
return 0; return 0;
@ -264,6 +333,7 @@ static const struct qnap_mcu_variant qnap_ts433_mcu = {
}; };
static struct mfd_cell qnap_mcu_cells[] = { static struct mfd_cell qnap_mcu_cells[] = {
{ .name = "qnap-mcu-eeprom", },
{ .name = "qnap-mcu-input", }, { .name = "qnap-mcu-input", },
{ .name = "qnap-mcu-leds", }, { .name = "qnap-mcu-leds", },
{ .name = "qnap-mcu-hwmon", } { .name = "qnap-mcu-hwmon", }

View File

@ -72,14 +72,13 @@ static const struct regmap_irq_chip bd718xx_irq_chip = {
.init_ack_masked = true, .init_ack_masked = true,
}; };
static const struct regmap_range pmic_status_range = { static const struct regmap_range pmic_status_range[] = {
.range_min = BD718XX_REG_IRQ, regmap_reg_range(BD718XX_REG_IRQ, BD718XX_REG_POW_STATE),
.range_max = BD718XX_REG_POW_STATE,
}; };
static const struct regmap_access_table volatile_regs = { static const struct regmap_access_table volatile_regs = {
.yes_ranges = &pmic_status_range, .yes_ranges = &pmic_status_range[0],
.n_yes_ranges = 1, .n_yes_ranges = ARRAY_SIZE(pmic_status_range),
}; };
static const struct regmap_config bd718xx_regmap_config = { static const struct regmap_config bd718xx_regmap_config = {

View File

@ -325,11 +325,6 @@ static struct regmap *sec_pmic_acpm_regmap_init(struct device *dev,
return regmap; return regmap;
} }
static void sec_pmic_acpm_mask_common_irqs(void *regmap_common)
{
regmap_write(regmap_common, S2MPG10_COMMON_INT_MASK, S2MPG10_COMMON_INT_SRC);
}
static int sec_pmic_acpm_probe(struct platform_device *pdev) static int sec_pmic_acpm_probe(struct platform_device *pdev)
{ {
struct regmap *regmap_common, *regmap_pmic, *regmap; struct regmap *regmap_common, *regmap_pmic, *regmap;
@ -360,15 +355,10 @@ static int sec_pmic_acpm_probe(struct platform_device *pdev)
shared_ctx->speedy_channel = pdata->speedy_channel; shared_ctx->speedy_channel = pdata->speedy_channel;
regmap_common = sec_pmic_acpm_regmap_init(dev, shared_ctx, SEC_PMIC_ACPM_ACCESSTYPE_COMMON, regmap_common = sec_pmic_acpm_regmap_init(dev, shared_ctx, SEC_PMIC_ACPM_ACCESSTYPE_COMMON,
pdata->regmap_cfg_common, false); pdata->regmap_cfg_common, true);
if (IS_ERR(regmap_common)) if (IS_ERR(regmap_common))
return PTR_ERR(regmap_common); return PTR_ERR(regmap_common);
/* Mask all interrupts from 'common' block, until successful init */
ret = regmap_write(regmap_common, S2MPG10_COMMON_INT_MASK, S2MPG10_COMMON_INT_SRC);
if (ret)
return dev_err_probe(dev, ret, "failed to mask common block interrupts\n");
regmap_pmic = sec_pmic_acpm_regmap_init(dev, shared_ctx, SEC_PMIC_ACPM_ACCESSTYPE_PMIC, regmap_pmic = sec_pmic_acpm_regmap_init(dev, shared_ctx, SEC_PMIC_ACPM_ACCESSTYPE_PMIC,
pdata->regmap_cfg_pmic, false); pdata->regmap_cfg_pmic, false);
if (IS_ERR(regmap_pmic)) if (IS_ERR(regmap_pmic))
@ -391,17 +381,6 @@ static int sec_pmic_acpm_probe(struct platform_device *pdev)
if (device_property_read_bool(dev, "wakeup-source")) if (device_property_read_bool(dev, "wakeup-source"))
devm_device_init_wakeup(dev); devm_device_init_wakeup(dev);
/* Unmask PMIC interrupt from 'common' block, now that everything is in place. */
ret = regmap_clear_bits(regmap_common, S2MPG10_COMMON_INT_MASK,
S2MPG10_COMMON_INT_SRC_PMIC);
if (ret)
return dev_err_probe(dev, ret, "failed to unmask PMIC interrupt\n");
/* Mask all interrupts from 'common' block on shutdown */
ret = devm_add_action_or_reset(dev, sec_pmic_acpm_mask_common_irqs, regmap_common);
if (ret)
return ret;
return 0; return 0;
} }

View File

@ -20,6 +20,12 @@
#include "sec-core.h" #include "sec-core.h"
static const struct regmap_irq s2mpg10_irqs[] = { static const struct regmap_irq s2mpg10_irqs[] = {
REGMAP_IRQ_REG(S2MPG10_COMMON_IRQ_PMIC, 0, S2MPG10_COMMON_INT_SRC_PMIC),
/* No documentation or other reference for remaining bits */
REGMAP_IRQ_REG(S2MPG10_COMMON_IRQ_UNUSED, 0, GENMASK(7, 1)),
};
static const struct regmap_irq s2mpg10_pmic_irqs[] = {
REGMAP_IRQ_REG(S2MPG10_IRQ_PWRONF, 0, S2MPG10_IRQ_PWRONF_MASK), REGMAP_IRQ_REG(S2MPG10_IRQ_PWRONF, 0, S2MPG10_IRQ_PWRONF_MASK),
REGMAP_IRQ_REG(S2MPG10_IRQ_PWRONR, 0, S2MPG10_IRQ_PWRONR_MASK), REGMAP_IRQ_REG(S2MPG10_IRQ_PWRONR, 0, S2MPG10_IRQ_PWRONR_MASK),
REGMAP_IRQ_REG(S2MPG10_IRQ_JIGONBF, 0, S2MPG10_IRQ_JIGONBF_MASK), REGMAP_IRQ_REG(S2MPG10_IRQ_JIGONBF, 0, S2MPG10_IRQ_JIGONBF_MASK),
@ -183,11 +189,20 @@ static const struct regmap_irq s5m8767_irqs[] = {
/* All S2MPG10 interrupt sources are read-only and don't require clearing */ /* All S2MPG10 interrupt sources are read-only and don't require clearing */
static const struct regmap_irq_chip s2mpg10_irq_chip = { static const struct regmap_irq_chip s2mpg10_irq_chip = {
.name = "s2mpg10", .name = "s2mpg10",
.status_base = S2MPG10_COMMON_INT,
.mask_base = S2MPG10_COMMON_INT_MASK,
.num_regs = 1,
.irqs = s2mpg10_irqs, .irqs = s2mpg10_irqs,
.num_irqs = ARRAY_SIZE(s2mpg10_irqs), .num_irqs = ARRAY_SIZE(s2mpg10_irqs),
.num_regs = 6, };
static const struct regmap_irq_chip s2mpg10_irq_chip_pmic = {
.name = "s2mpg10-pmic",
.status_base = S2MPG10_PMIC_INT1, .status_base = S2MPG10_PMIC_INT1,
.mask_base = S2MPG10_PMIC_INT1M, .mask_base = S2MPG10_PMIC_INT1M,
.num_regs = 6,
.irqs = s2mpg10_pmic_irqs,
.num_irqs = ARRAY_SIZE(s2mpg10_pmic_irqs),
}; };
static const struct regmap_irq_chip s2mps11_irq_chip = { static const struct regmap_irq_chip s2mps11_irq_chip = {
@ -253,6 +268,59 @@ static const struct regmap_irq_chip s5m8767_irq_chip = {
.ack_base = S5M8767_REG_INT1, .ack_base = S5M8767_REG_INT1,
}; };
static int s2mpg1x_add_chained_irq_chip(struct device *dev, struct regmap *regmap, int pirq,
struct regmap_irq_chip_data *parent,
const struct regmap_irq_chip *chip,
struct regmap_irq_chip_data **data)
{
int irq, ret;
irq = regmap_irq_get_virq(parent, pirq);
if (irq < 0)
return dev_err_probe(dev, irq, "Failed to get parent vIRQ(%d) for chip %s\n", pirq,
chip->name);
ret = devm_regmap_add_irq_chip(dev, regmap, irq, IRQF_ONESHOT | IRQF_SHARED, 0, chip, data);
if (ret)
return dev_err_probe(dev, ret, "Failed to add %s IRQ chip\n", chip->name);
return 0;
}
static int sec_irq_init_s2mpg1x(struct sec_pmic_dev *sec_pmic)
{
const struct regmap_irq_chip *irq_chip, *chained_irq_chip;
struct regmap_irq_chip_data *irq_data;
struct regmap *regmap_common;
int chained_pirq;
int ret;
switch (sec_pmic->device_type) {
case S2MPG10:
irq_chip = &s2mpg10_irq_chip;
chained_irq_chip = &s2mpg10_irq_chip_pmic;
chained_pirq = S2MPG10_COMMON_IRQ_PMIC;
break;
default:
return dev_err_probe(sec_pmic->dev, -EINVAL, "Unsupported device type %d\n",
sec_pmic->device_type);
}
regmap_common = dev_get_regmap(sec_pmic->dev, "common");
if (!regmap_common)
return dev_err_probe(sec_pmic->dev, -EINVAL, "No 'common' regmap %d\n",
sec_pmic->device_type);
ret = devm_regmap_add_irq_chip(sec_pmic->dev, regmap_common, sec_pmic->irq, IRQF_ONESHOT, 0,
irq_chip, &irq_data);
if (ret)
return dev_err_probe(sec_pmic->dev, ret, "Failed to add %s IRQ chip\n",
irq_chip->name);
return s2mpg1x_add_chained_irq_chip(sec_pmic->dev, sec_pmic->regmap_pmic, chained_pirq,
irq_data, chained_irq_chip, &sec_pmic->irq_data);
}
int sec_irq_init(struct sec_pmic_dev *sec_pmic) int sec_irq_init(struct sec_pmic_dev *sec_pmic)
{ {
const struct regmap_irq_chip *sec_irq_chip; const struct regmap_irq_chip *sec_irq_chip;
@ -268,8 +336,7 @@ int sec_irq_init(struct sec_pmic_dev *sec_pmic)
sec_irq_chip = &s2mps14_irq_chip; sec_irq_chip = &s2mps14_irq_chip;
break; break;
case S2MPG10: case S2MPG10:
sec_irq_chip = &s2mpg10_irq_chip; return sec_irq_init_s2mpg1x(sec_pmic);
break;
case S2MPS11X: case S2MPS11X:
sec_irq_chip = &s2mps11_irq_chip; sec_irq_chip = &s2mps11_irq_chip;
break; break;

View File

@ -15,12 +15,18 @@
* will be subsequently registered. * will be subsequently registered.
*/ */
#include <linux/array_size.h>
#include <linux/dev_printk.h>
#include <linux/err.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/kernel.h>
#include <linux/mfd/core.h> #include <linux/mfd/core.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of_platform.h> #include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/property.h>
#include <linux/regmap.h> #include <linux/regmap.h>
#include <linux/stddef.h>
#include "simple-mfd-i2c.h" #include "simple-mfd-i2c.h"
@ -118,7 +124,7 @@ static const struct of_device_id simple_mfd_i2c_of_match[] = {
{ .compatible = "maxim,max5978", .data = &maxim_max5970 }, { .compatible = "maxim,max5978", .data = &maxim_max5970 },
{ .compatible = "maxim,max77705-battery", .data = &maxim_mon_max77705 }, { .compatible = "maxim,max77705-battery", .data = &maxim_mon_max77705 },
{ .compatible = "silergy,sy7636a", .data = &silergy_sy7636a }, { .compatible = "silergy,sy7636a", .data = &silergy_sy7636a },
{ .compatible = "spacemit,p1", .data = &spacemit_p1, }, { .compatible = "spacemit,p1", .data = &spacemit_p1 },
{} {}
}; };
MODULE_DEVICE_TABLE(of, simple_mfd_i2c_of_match); MODULE_DEVICE_TABLE(of, simple_mfd_i2c_of_match);

View File

@ -183,7 +183,7 @@ static struct regmap *device_node_get_regmap(struct device_node *np,
if (create_regmap) if (create_regmap)
syscon = of_syscon_register(np, check_res); syscon = of_syscon_register(np, check_res);
else else
syscon = ERR_PTR(-EINVAL); syscon = ERR_PTR(-EPROBE_DEFER);
} }
mutex_unlock(&syscon_list_lock); mutex_unlock(&syscon_list_lock);

View File

@ -43,6 +43,8 @@
#define TQMX86_REG_BOARD_ID_E40C2 15 #define TQMX86_REG_BOARD_ID_E40C2 15
#define TQMX86_REG_BOARD_ID_130UC 16 #define TQMX86_REG_BOARD_ID_130UC 16
#define TQMX86_REG_BOARD_ID_E41S 19 #define TQMX86_REG_BOARD_ID_E41S 19
#define TQMX86_REG_BOARD_ID_CU1_HPCM 24
#define TQMX86_REG_BOARD_ID_CU2_HPCM 25
#define TQMX86_REG_BOARD_REV 0x01 #define TQMX86_REG_BOARD_REV 0x01
#define TQMX86_REG_IO_EXT_INT 0x06 #define TQMX86_REG_IO_EXT_INT 0x06
#define TQMX86_REG_IO_EXT_INT_NONE 0 #define TQMX86_REG_IO_EXT_INT_NONE 0
@ -165,6 +167,10 @@ static const char *tqmx86_board_id_to_name(u8 board_id, u8 sauc)
return "TQMx130UC"; return "TQMx130UC";
case TQMX86_REG_BOARD_ID_E41S: case TQMX86_REG_BOARD_ID_E41S:
return "TQMxE41S"; return "TQMxE41S";
case TQMX86_REG_BOARD_ID_CU1_HPCM:
return "TQMxCU1-HPCM";
case TQMX86_REG_BOARD_ID_CU2_HPCM:
return "TQMxCU2-HPCM";
default: default:
return "Unknown"; return "Unknown";
} }
@ -185,6 +191,8 @@ static int tqmx86_board_id_to_clk_rate(struct device *dev, u8 board_id)
case TQMX86_REG_BOARD_ID_E40C2: case TQMX86_REG_BOARD_ID_E40C2:
case TQMX86_REG_BOARD_ID_130UC: case TQMX86_REG_BOARD_ID_130UC:
case TQMX86_REG_BOARD_ID_E41S: case TQMX86_REG_BOARD_ID_E41S:
case TQMX86_REG_BOARD_ID_CU1_HPCM:
case TQMX86_REG_BOARD_ID_CU2_HPCM:
return 24000; return 24000;
case TQMX86_REG_BOARD_ID_E39MS: case TQMX86_REG_BOARD_ID_E39MS:
case TQMX86_REG_BOARD_ID_E39C1: case TQMX86_REG_BOARD_ID_E39C1:

View File

@ -1,262 +0,0 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* MFD driver for wl1273 FM radio and audio codec submodules.
*
* Copyright (C) 2011 Nokia Corporation
* Author: Matti Aaltonen <matti.j.aaltonen@nokia.com>
*/
#include <linux/mfd/wl1273-core.h>
#include <linux/slab.h>
#include <linux/module.h>
#define DRIVER_DESC "WL1273 FM Radio Core"
static const struct i2c_device_id wl1273_driver_id_table[] = {
{ WL1273_FM_DRIVER_NAME },
{ }
};
MODULE_DEVICE_TABLE(i2c, wl1273_driver_id_table);
static int wl1273_fm_read_reg(struct wl1273_core *core, u8 reg, u16 *value)
{
struct i2c_client *client = core->client;
u8 b[2];
int r;
r = i2c_smbus_read_i2c_block_data(client, reg, sizeof(b), b);
if (r != 2) {
dev_err(&client->dev, "%s: Read: %d fails.\n", __func__, reg);
return -EREMOTEIO;
}
*value = (u16)b[0] << 8 | b[1];
return 0;
}
static int wl1273_fm_write_cmd(struct wl1273_core *core, u8 cmd, u16 param)
{
struct i2c_client *client = core->client;
u8 buf[] = { (param >> 8) & 0xff, param & 0xff };
int r;
r = i2c_smbus_write_i2c_block_data(client, cmd, sizeof(buf), buf);
if (r) {
dev_err(&client->dev, "%s: Cmd: %d fails.\n", __func__, cmd);
return r;
}
return 0;
}
static int wl1273_fm_write_data(struct wl1273_core *core, u8 *data, u16 len)
{
struct i2c_client *client = core->client;
struct i2c_msg msg;
int r;
msg.addr = client->addr;
msg.flags = 0;
msg.buf = data;
msg.len = len;
r = i2c_transfer(client->adapter, &msg, 1);
if (r != 1) {
dev_err(&client->dev, "%s: write error.\n", __func__);
return -EREMOTEIO;
}
return 0;
}
/**
* wl1273_fm_set_audio() - Set audio mode.
* @core: A pointer to the device struct.
* @new_mode: The new audio mode.
*
* Audio modes are WL1273_AUDIO_DIGITAL and WL1273_AUDIO_ANALOG.
*/
static int wl1273_fm_set_audio(struct wl1273_core *core, unsigned int new_mode)
{
int r = 0;
if (core->mode == WL1273_MODE_OFF ||
core->mode == WL1273_MODE_SUSPENDED)
return -EPERM;
if (core->mode == WL1273_MODE_RX && new_mode == WL1273_AUDIO_DIGITAL) {
r = wl1273_fm_write_cmd(core, WL1273_PCM_MODE_SET,
WL1273_PCM_DEF_MODE);
if (r)
goto out;
r = wl1273_fm_write_cmd(core, WL1273_I2S_MODE_CONFIG_SET,
core->i2s_mode);
if (r)
goto out;
r = wl1273_fm_write_cmd(core, WL1273_AUDIO_ENABLE,
WL1273_AUDIO_ENABLE_I2S);
if (r)
goto out;
} else if (core->mode == WL1273_MODE_RX &&
new_mode == WL1273_AUDIO_ANALOG) {
r = wl1273_fm_write_cmd(core, WL1273_AUDIO_ENABLE,
WL1273_AUDIO_ENABLE_ANALOG);
if (r)
goto out;
} else if (core->mode == WL1273_MODE_TX &&
new_mode == WL1273_AUDIO_DIGITAL) {
r = wl1273_fm_write_cmd(core, WL1273_I2S_MODE_CONFIG_SET,
core->i2s_mode);
if (r)
goto out;
r = wl1273_fm_write_cmd(core, WL1273_AUDIO_IO_SET,
WL1273_AUDIO_IO_SET_I2S);
if (r)
goto out;
} else if (core->mode == WL1273_MODE_TX &&
new_mode == WL1273_AUDIO_ANALOG) {
r = wl1273_fm_write_cmd(core, WL1273_AUDIO_IO_SET,
WL1273_AUDIO_IO_SET_ANALOG);
if (r)
goto out;
}
core->audio_mode = new_mode;
out:
return r;
}
/**
* wl1273_fm_set_volume() - Set volume.
* @core: A pointer to the device struct.
* @volume: The new volume value.
*/
static int wl1273_fm_set_volume(struct wl1273_core *core, unsigned int volume)
{
int r;
if (volume > WL1273_MAX_VOLUME)
return -EINVAL;
if (core->volume == volume)
return 0;
r = wl1273_fm_write_cmd(core, WL1273_VOLUME_SET, volume);
if (r)
return r;
core->volume = volume;
return 0;
}
static int wl1273_core_probe(struct i2c_client *client)
{
struct wl1273_fm_platform_data *pdata = dev_get_platdata(&client->dev);
struct wl1273_core *core;
struct mfd_cell *cell;
int children = 0;
int r = 0;
dev_dbg(&client->dev, "%s\n", __func__);
if (!pdata) {
dev_err(&client->dev, "No platform data.\n");
return -EINVAL;
}
if (!(pdata->children & WL1273_RADIO_CHILD)) {
dev_err(&client->dev, "Cannot function without radio child.\n");
return -EINVAL;
}
core = devm_kzalloc(&client->dev, sizeof(*core), GFP_KERNEL);
if (!core)
return -ENOMEM;
core->pdata = pdata;
core->client = client;
mutex_init(&core->lock);
i2c_set_clientdata(client, core);
dev_dbg(&client->dev, "%s: Have V4L2.\n", __func__);
cell = &core->cells[children];
cell->name = "wl1273_fm_radio";
cell->platform_data = &core;
cell->pdata_size = sizeof(core);
children++;
core->read = wl1273_fm_read_reg;
core->write = wl1273_fm_write_cmd;
core->write_data = wl1273_fm_write_data;
core->set_audio = wl1273_fm_set_audio;
core->set_volume = wl1273_fm_set_volume;
if (pdata->children & WL1273_CODEC_CHILD) {
cell = &core->cells[children];
dev_dbg(&client->dev, "%s: Have codec.\n", __func__);
cell->name = "wl1273-codec";
cell->platform_data = &core;
cell->pdata_size = sizeof(core);
children++;
}
dev_dbg(&client->dev, "%s: number of children: %d.\n",
__func__, children);
r = devm_mfd_add_devices(&client->dev, -1, core->cells,
children, NULL, 0, NULL);
if (r)
goto err;
return 0;
err:
pdata->free_resources();
dev_dbg(&client->dev, "%s\n", __func__);
return r;
}
static struct i2c_driver wl1273_core_driver = {
.driver = {
.name = WL1273_FM_DRIVER_NAME,
},
.probe = wl1273_core_probe,
.id_table = wl1273_driver_id_table,
};
static int __init wl1273_core_init(void)
{
int r;
r = i2c_add_driver(&wl1273_core_driver);
if (r) {
pr_err(WL1273_FM_DRIVER_NAME
": driver registration failed\n");
return r;
}
return r;
}
static void __exit wl1273_core_exit(void)
{
i2c_del_driver(&wl1273_core_driver);
}
late_initcall(wl1273_core_init);
module_exit(wl1273_core_exit);
MODULE_AUTHOR("Matti Aaltonen <matti.j.aaltonen@nokia.com>");
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");

View File

@ -150,7 +150,7 @@ int apple_smc_read(struct apple_smc *smc, smc_key key, void *buf, size_t size);
* *
* Return: Zero on success, negative errno on error * Return: Zero on success, negative errno on error
*/ */
int apple_smc_write(struct apple_smc *smc, smc_key key, void *buf, size_t size); int apple_smc_write(struct apple_smc *smc, smc_key key, const void *buf, size_t size);
/** /**
* apple_smc_enter_atomic - Enter atomic mode to be able to use apple_smc_write_atomic * apple_smc_enter_atomic - Enter atomic mode to be able to use apple_smc_write_atomic
@ -177,7 +177,7 @@ int apple_smc_enter_atomic(struct apple_smc *smc);
* *
* Return: Zero on success, negative errno on error * Return: Zero on success, negative errno on error
*/ */
int apple_smc_write_atomic(struct apple_smc *smc, smc_key key, void *buf, size_t size); int apple_smc_write_atomic(struct apple_smc *smc, smc_key key, const void *buf, size_t size);
/** /**
* apple_smc_rw - Write and then read using the given SMC key * apple_smc_rw - Write and then read using the given SMC key
@ -190,7 +190,7 @@ int apple_smc_write_atomic(struct apple_smc *smc, smc_key key, void *buf, size_t
* *
* Return: Zero on success, negative errno on error * Return: Zero on success, negative errno on error
*/ */
int apple_smc_rw(struct apple_smc *smc, smc_key key, void *wbuf, size_t wsize, int apple_smc_rw(struct apple_smc *smc, smc_key key, const void *wbuf, size_t wsize,
void *rbuf, size_t rsize); void *rbuf, size_t rsize);
/** /**

View File

@ -57,6 +57,12 @@ enum s2mpa01_irq {
#define S2MPA01_IRQ_B24_TSD_MASK (1 << 4) #define S2MPA01_IRQ_B24_TSD_MASK (1 << 4)
#define S2MPA01_IRQ_B35_TSD_MASK (1 << 5) #define S2MPA01_IRQ_B35_TSD_MASK (1 << 5)
enum s2mpg10_common_irq {
/* Top-level (common) block */
S2MPG10_COMMON_IRQ_PMIC,
S2MPG10_COMMON_IRQ_UNUSED,
};
enum s2mpg10_irq { enum s2mpg10_irq {
/* PMIC */ /* PMIC */
S2MPG10_IRQ_PWRONF, S2MPG10_IRQ_PWRONF,

View File

@ -1,277 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* include/linux/mfd/wl1273-core.h
*
* Some definitions for the wl1273 radio receiver/transmitter chip.
*
* Copyright (C) 2010 Nokia Corporation
* Author: Matti J. Aaltonen <matti.j.aaltonen@nokia.com>
*/
#ifndef WL1273_CORE_H
#define WL1273_CORE_H
#include <linux/i2c.h>
#include <linux/mfd/core.h>
#define WL1273_FM_DRIVER_NAME "wl1273-fm"
#define RX71_FM_I2C_ADDR 0x22
#define WL1273_STEREO_GET 0
#define WL1273_RSSI_LVL_GET 1
#define WL1273_IF_COUNT_GET 2
#define WL1273_FLAG_GET 3
#define WL1273_RDS_SYNC_GET 4
#define WL1273_RDS_DATA_GET 5
#define WL1273_FREQ_SET 10
#define WL1273_AF_FREQ_SET 11
#define WL1273_MOST_MODE_SET 12
#define WL1273_MOST_BLEND_SET 13
#define WL1273_DEMPH_MODE_SET 14
#define WL1273_SEARCH_LVL_SET 15
#define WL1273_BAND_SET 16
#define WL1273_MUTE_STATUS_SET 17
#define WL1273_RDS_PAUSE_LVL_SET 18
#define WL1273_RDS_PAUSE_DUR_SET 19
#define WL1273_RDS_MEM_SET 20
#define WL1273_RDS_BLK_B_SET 21
#define WL1273_RDS_MSK_B_SET 22
#define WL1273_RDS_PI_MASK_SET 23
#define WL1273_RDS_PI_SET 24
#define WL1273_RDS_SYSTEM_SET 25
#define WL1273_INT_MASK_SET 26
#define WL1273_SEARCH_DIR_SET 27
#define WL1273_VOLUME_SET 28
#define WL1273_AUDIO_ENABLE 29
#define WL1273_PCM_MODE_SET 30
#define WL1273_I2S_MODE_CONFIG_SET 31
#define WL1273_POWER_SET 32
#define WL1273_INTX_CONFIG_SET 33
#define WL1273_PULL_EN_SET 34
#define WL1273_HILO_SET 35
#define WL1273_SWITCH2FREF 36
#define WL1273_FREQ_DRIFT_REPORT 37
#define WL1273_PCE_GET 40
#define WL1273_FIRM_VER_GET 41
#define WL1273_ASIC_VER_GET 42
#define WL1273_ASIC_ID_GET 43
#define WL1273_MAN_ID_GET 44
#define WL1273_TUNER_MODE_SET 45
#define WL1273_STOP_SEARCH 46
#define WL1273_RDS_CNTRL_SET 47
#define WL1273_WRITE_HARDWARE_REG 100
#define WL1273_CODE_DOWNLOAD 101
#define WL1273_RESET 102
#define WL1273_FM_POWER_MODE 254
#define WL1273_FM_INTERRUPT 255
/* Transmitter API */
#define WL1273_CHANL_SET 55
#define WL1273_SCAN_SPACING_SET 56
#define WL1273_REF_SET 57
#define WL1273_POWER_ENB_SET 90
#define WL1273_POWER_ATT_SET 58
#define WL1273_POWER_LEV_SET 59
#define WL1273_AUDIO_DEV_SET 60
#define WL1273_PILOT_DEV_SET 61
#define WL1273_RDS_DEV_SET 62
#define WL1273_PUPD_SET 91
#define WL1273_AUDIO_IO_SET 63
#define WL1273_PREMPH_SET 64
#define WL1273_MONO_SET 66
#define WL1273_MUTE 92
#define WL1273_MPX_LMT_ENABLE 67
#define WL1273_PI_SET 93
#define WL1273_ECC_SET 69
#define WL1273_PTY 70
#define WL1273_AF 71
#define WL1273_DISPLAY_MODE 74
#define WL1273_RDS_REP_SET 77
#define WL1273_RDS_CONFIG_DATA_SET 98
#define WL1273_RDS_DATA_SET 99
#define WL1273_RDS_DATA_ENB 94
#define WL1273_TA_SET 78
#define WL1273_TP_SET 79
#define WL1273_DI_SET 80
#define WL1273_MS_SET 81
#define WL1273_PS_SCROLL_SPEED 82
#define WL1273_TX_AUDIO_LEVEL_TEST 96
#define WL1273_TX_AUDIO_LEVEL_TEST_THRESHOLD 73
#define WL1273_TX_AUDIO_INPUT_LEVEL_RANGE_SET 54
#define WL1273_RX_ANTENNA_SELECT 87
#define WL1273_I2C_DEV_ADDR_SET 86
#define WL1273_REF_ERR_CALIB_PARAM_SET 88
#define WL1273_REF_ERR_CALIB_PERIODICITY_SET 89
#define WL1273_SOC_INT_TRIGGER 52
#define WL1273_SOC_AUDIO_PATH_SET 83
#define WL1273_SOC_PCMI_OVERRIDE 84
#define WL1273_SOC_I2S_OVERRIDE 85
#define WL1273_RSSI_BLOCK_SCAN_FREQ_SET 95
#define WL1273_RSSI_BLOCK_SCAN_START 97
#define WL1273_RSSI_BLOCK_SCAN_DATA_GET 5
#define WL1273_READ_FMANT_TUNE_VALUE 104
#define WL1273_RDS_OFF 0
#define WL1273_RDS_ON 1
#define WL1273_RDS_RESET 2
#define WL1273_AUDIO_DIGITAL 0
#define WL1273_AUDIO_ANALOG 1
#define WL1273_MODE_RX BIT(0)
#define WL1273_MODE_TX BIT(1)
#define WL1273_MODE_OFF BIT(2)
#define WL1273_MODE_SUSPENDED BIT(3)
#define WL1273_RADIO_CHILD BIT(0)
#define WL1273_CODEC_CHILD BIT(1)
#define WL1273_RX_MONO 1
#define WL1273_RX_STEREO 0
#define WL1273_TX_MONO 0
#define WL1273_TX_STEREO 1
#define WL1273_MAX_VOLUME 0xffff
#define WL1273_DEFAULT_VOLUME 0x78b8
/* I2S protocol, left channel first, data width 16 bits */
#define WL1273_PCM_DEF_MODE 0x00
/* Rx */
#define WL1273_AUDIO_ENABLE_I2S BIT(0)
#define WL1273_AUDIO_ENABLE_ANALOG BIT(1)
/* Tx */
#define WL1273_AUDIO_IO_SET_ANALOG 0
#define WL1273_AUDIO_IO_SET_I2S 1
#define WL1273_PUPD_SET_OFF 0x00
#define WL1273_PUPD_SET_ON 0x01
#define WL1273_PUPD_SET_RETENTION 0x10
/* I2S mode */
#define WL1273_IS2_WIDTH_32 0x0
#define WL1273_IS2_WIDTH_40 0x1
#define WL1273_IS2_WIDTH_22_23 0x2
#define WL1273_IS2_WIDTH_23_22 0x3
#define WL1273_IS2_WIDTH_48 0x4
#define WL1273_IS2_WIDTH_50 0x5
#define WL1273_IS2_WIDTH_60 0x6
#define WL1273_IS2_WIDTH_64 0x7
#define WL1273_IS2_WIDTH_80 0x8
#define WL1273_IS2_WIDTH_96 0x9
#define WL1273_IS2_WIDTH_128 0xa
#define WL1273_IS2_WIDTH 0xf
#define WL1273_IS2_FORMAT_STD (0x0 << 4)
#define WL1273_IS2_FORMAT_LEFT (0x1 << 4)
#define WL1273_IS2_FORMAT_RIGHT (0x2 << 4)
#define WL1273_IS2_FORMAT_USER (0x3 << 4)
#define WL1273_IS2_MASTER (0x0 << 6)
#define WL1273_IS2_SLAVEW (0x1 << 6)
#define WL1273_IS2_TRI_AFTER_SENDING (0x0 << 7)
#define WL1273_IS2_TRI_ALWAYS_ACTIVE (0x1 << 7)
#define WL1273_IS2_SDOWS_RR (0x0 << 8)
#define WL1273_IS2_SDOWS_RF (0x1 << 8)
#define WL1273_IS2_SDOWS_FR (0x2 << 8)
#define WL1273_IS2_SDOWS_FF (0x3 << 8)
#define WL1273_IS2_TRI_OPT (0x0 << 10)
#define WL1273_IS2_TRI_ALWAYS (0x1 << 10)
#define WL1273_IS2_RATE_48K (0x0 << 12)
#define WL1273_IS2_RATE_44_1K (0x1 << 12)
#define WL1273_IS2_RATE_32K (0x2 << 12)
#define WL1273_IS2_RATE_22_05K (0x4 << 12)
#define WL1273_IS2_RATE_16K (0x5 << 12)
#define WL1273_IS2_RATE_12K (0x8 << 12)
#define WL1273_IS2_RATE_11_025 (0x9 << 12)
#define WL1273_IS2_RATE_8K (0xa << 12)
#define WL1273_IS2_RATE (0xf << 12)
#define WL1273_I2S_DEF_MODE (WL1273_IS2_WIDTH_32 | \
WL1273_IS2_FORMAT_STD | \
WL1273_IS2_MASTER | \
WL1273_IS2_TRI_AFTER_SENDING | \
WL1273_IS2_SDOWS_RR | \
WL1273_IS2_TRI_OPT | \
WL1273_IS2_RATE_48K)
#define SCHAR_MIN (-128)
#define SCHAR_MAX 127
#define WL1273_FR_EVENT BIT(0)
#define WL1273_BL_EVENT BIT(1)
#define WL1273_RDS_EVENT BIT(2)
#define WL1273_BBLK_EVENT BIT(3)
#define WL1273_LSYNC_EVENT BIT(4)
#define WL1273_LEV_EVENT BIT(5)
#define WL1273_IFFR_EVENT BIT(6)
#define WL1273_PI_EVENT BIT(7)
#define WL1273_PD_EVENT BIT(8)
#define WL1273_STIC_EVENT BIT(9)
#define WL1273_MAL_EVENT BIT(10)
#define WL1273_POW_ENB_EVENT BIT(11)
#define WL1273_SCAN_OVER_EVENT BIT(12)
#define WL1273_ERROR_EVENT BIT(13)
#define TUNER_MODE_STOP_SEARCH 0
#define TUNER_MODE_PRESET 1
#define TUNER_MODE_AUTO_SEEK 2
#define TUNER_MODE_AF 3
#define TUNER_MODE_AUTO_SEEK_PI 4
#define TUNER_MODE_AUTO_SEEK_BULK 5
#define RDS_BLOCK_SIZE 3
struct wl1273_fm_platform_data {
int (*request_resources) (struct i2c_client *client);
void (*free_resources) (void);
void (*enable) (void);
void (*disable) (void);
u8 forbidden_modes;
unsigned int children;
};
#define WL1273_FM_CORE_CELLS 2
#define WL1273_BAND_OTHER 0
#define WL1273_BAND_JAPAN 1
#define WL1273_BAND_JAPAN_LOW 76000
#define WL1273_BAND_JAPAN_HIGH 90000
#define WL1273_BAND_OTHER_LOW 87500
#define WL1273_BAND_OTHER_HIGH 108000
#define WL1273_BAND_TX_LOW 76000
#define WL1273_BAND_TX_HIGH 108000
struct wl1273_core {
struct mfd_cell cells[WL1273_FM_CORE_CELLS];
struct wl1273_fm_platform_data *pdata;
unsigned int mode;
unsigned int i2s_mode;
unsigned int volume;
unsigned int audio_mode;
unsigned int channel_number;
struct mutex lock; /* for serializing fm radio operations */
struct i2c_client *client;
int (*read)(struct wl1273_core *core, u8, u16 *);
int (*write)(struct wl1273_core *core, u8, u16);
int (*write_data)(struct wl1273_core *core, u8 *, u16);
int (*set_audio)(struct wl1273_core *core, unsigned int);
int (*set_volume)(struct wl1273_core *core, unsigned int);
};
#endif /* ifndef WL1273_CORE_H */