mirror of
https://github.com/torvalds/linux.git
synced 2026-11-06 21:58:01 +01:00
Merge branches 'ib-mfd-thermal-7.4', 'ib-mfd-clk-gpio-regulator-rtc-7.4' and 'ib-mfd-backlight-iio-leds-7.4' into ibs-for-mfd-merged
This commit is contained in:
commit
5f4e029576
|
|
@ -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
|
||||
67
Documentation/devicetree/bindings/leds/ti,lm3533-leds.yaml
Normal file
67
Documentation/devicetree/bindings/leds/ti,lm3533-leds.yaml
Normal 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
|
||||
169
Documentation/devicetree/bindings/leds/ti,lm3533.yaml
Normal file
169
Documentation/devicetree/bindings/leds/ti,lm3533.yaml
Normal 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;
|
||||
};
|
||||
};
|
||||
};
|
||||
...
|
||||
|
|
@ -15,6 +15,9 @@ description: |
|
|||
for LED and a 500 mA single-cell linear charger. Also included is a Coulomb
|
||||
counter, a real-time clock (RTC), and a 32.768 kHz clock gate and two GPOs.
|
||||
|
||||
allOf:
|
||||
- $ref: rohm,pmic-pins.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: rohm,bd71815
|
||||
|
|
@ -44,11 +47,7 @@ properties:
|
|||
clock-output-names:
|
||||
const: bd71815-32k-out
|
||||
|
||||
rohm,clkout-open-drain:
|
||||
description: clk32kout mode. Set to 1 for "open-drain" or 0 for "cmos".
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
minimum: 0
|
||||
maximum: 1
|
||||
rohm,clkout-open-drain: true
|
||||
|
||||
rohm,charger-sense-resistor-micro-ohms:
|
||||
minimum: 10000
|
||||
|
|
|
|||
|
|
@ -15,6 +15,9 @@ description: |
|
|||
single-cell linear charger. Also included is a Coulomb counter, a real-time
|
||||
clock (RTC), and a 32.768 kHz clock gate.
|
||||
|
||||
allOf:
|
||||
- $ref: rohm,pmic-pins.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
|
|
@ -49,11 +52,7 @@ properties:
|
|||
clock-output-names:
|
||||
const: bd71828-32k-out
|
||||
|
||||
rohm,clkout-open-drain:
|
||||
description: clk32kout mode. Set to 1 for "open-drain" or 0 for "cmos".
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
minimum: 0
|
||||
maximum: 1
|
||||
rohm,clkout-open-drain: true
|
||||
|
||||
rohm,charger-sense-resistor-micro-ohms:
|
||||
minimum: 10000
|
||||
|
|
|
|||
|
|
@ -15,6 +15,9 @@ description:
|
|||
and a 3000 mA switching charger. ICs also include a Coulomb counter,
|
||||
a real-time clock (RTC), GPIOs and a 32.768 kHz clock gate.
|
||||
|
||||
allOf:
|
||||
- $ref: rohm,pmic-pins.yaml#
|
||||
|
||||
# In addition to the properties found from the charger node, PMICs
|
||||
# use properties from a static battery node. Please see the:
|
||||
# Documentation/devicetree/bindings/power/supply/battery.yaml
|
||||
|
|
@ -80,10 +83,7 @@ properties:
|
|||
clock-output-names:
|
||||
const: bd71828-32k-out
|
||||
|
||||
rohm,clkout-open-drain:
|
||||
description: clk32kout mode. Set to 1 for "open-drain" or 0 for "cmos".
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
maximum: 1
|
||||
rohm,clkout-open-drain: true
|
||||
|
||||
rohm,charger-sense-resistor-micro-ohms:
|
||||
minimum: 10000
|
||||
|
|
@ -103,14 +103,6 @@ properties:
|
|||
$ref: /schemas/leds/rohm,bd71828-leds.yaml
|
||||
|
||||
rohm,pin-fault_b:
|
||||
$ref: /schemas/types.yaml#/definitions/string
|
||||
description:
|
||||
PMIC has an OTP option to use fault_b-pin for different
|
||||
purposes. Set this property accordingly. OTP options are
|
||||
OTP0 - bi-directional FAULT_B or READY indicator depending on a
|
||||
'sub option'
|
||||
OTP1 - GPO
|
||||
OTP2 - Power sequencer output.
|
||||
enum:
|
||||
- faultb
|
||||
- readyind
|
||||
|
|
@ -119,14 +111,6 @@ properties:
|
|||
|
||||
patternProperties:
|
||||
"^rohm,pin-dvs[0-1]$":
|
||||
$ref: /schemas/types.yaml#/definitions/string
|
||||
description:
|
||||
PMIC has 4 different OTP options to determine the use of dvs<X>-pins.
|
||||
OTP0 - regulator RUN state control.
|
||||
OTP1 - GPI.
|
||||
OTP2 - GPO.
|
||||
OTP3 - Power sequencer output.
|
||||
This property specifies the use of the pin.
|
||||
enum:
|
||||
- dvs-input
|
||||
- gpi
|
||||
|
|
@ -134,11 +118,6 @@ patternProperties:
|
|||
- pwrseq
|
||||
|
||||
"^rohm,pin-exten[0-1]$":
|
||||
$ref: /schemas/types.yaml#/definitions/string
|
||||
description: PMIC has an OTP option to use exten0-pin for different
|
||||
purposes. Set this property accordingly.
|
||||
OTP0 - GPO
|
||||
OTP1 - Power sequencer output.
|
||||
enum:
|
||||
- gpo
|
||||
- pwrseq
|
||||
|
|
|
|||
218
Documentation/devicetree/bindings/mfd/rohm,bd73800-pmic.yaml
Normal file
218
Documentation/devicetree/bindings/mfd/rohm,bd73800-pmic.yaml
Normal file
|
|
@ -0,0 +1,218 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/mfd/rohm,bd73800-pmic.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: ROHM BD73800 Power Management Integrated Circuit
|
||||
|
||||
maintainers:
|
||||
- Matti Vaittinen <mazziesaccount@gmail.com>
|
||||
|
||||
description:
|
||||
BD73800GW is a single-chip power management IC for battery-powered
|
||||
portable devices. It integrates 8 buck converters, 4 LDOs and a current
|
||||
sense amplifier with ADC. Also included is a Real Time Clock (RTC) and a
|
||||
32.768 kHz clock gate. Depending on the OTP configuration the BD73800
|
||||
may also have interrupt controller and GPIOs.
|
||||
|
||||
There are also different variants called BD71851 and BD71885 which are
|
||||
almost identical from the software point of view.
|
||||
|
||||
allOf:
|
||||
- $ref: rohm,pmic-pins.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- const: rohm,bd73800
|
||||
|
||||
- items:
|
||||
- enum:
|
||||
- rohm,bd71851
|
||||
- rohm,bd71885
|
||||
- const: rohm,bd73800
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
# The GPIO1, CLKOUT (GPIO2), FAULT_B and EXTEN_OUT pins can be
|
||||
# configured to interrupt pins by OTP.
|
||||
interrupt-controller: true
|
||||
|
||||
"#interrupt-cells":
|
||||
const: 1
|
||||
description:
|
||||
The IRQ number. 0 is GPIO1, 1 CLKOUT (GPIO2), 2 FAULT_B and 3 EXTEN_OUT.
|
||||
NOTE, A pin can operate as IRQ source only when the OTP
|
||||
configuration for it has been set to GPI.
|
||||
|
||||
gpio-controller: true
|
||||
|
||||
"#gpio-cells":
|
||||
const: 2
|
||||
|
||||
rohm,pin-gpio1:
|
||||
$ref: /schemas/types.yaml#/definitions/string
|
||||
description:
|
||||
Indicate if the GPIO1 pin has been set to GPI or GPO at manufacturing.
|
||||
The GPIO1, CLKOUT, FAULT_B and EXTEN_OUT pins may be configured for a
|
||||
specific purpose (like ADC input, 32.768 clk output, fault indicator or
|
||||
delivering power sequence to a companion PMIC when multiple PMICs are
|
||||
used) - but also to be either a GPO or GPI. (When used as a GPI the pin
|
||||
can also be used as an IRQ source). The pin purpose is determined by
|
||||
OTP (One Time Programmable memory), typically during device
|
||||
manufacturing. The OTP can't be read at runtime so device-tree should
|
||||
describe the GPIO pins.
|
||||
enum: [gpi, gpo]
|
||||
|
||||
rohm,pin-clkout:
|
||||
enum: [gpi, gpo]
|
||||
|
||||
rohm,pin-fault_b:
|
||||
enum: [gpi, gpo]
|
||||
|
||||
rohm,pin-exten:
|
||||
enum: [gpi, gpo]
|
||||
|
||||
clocks:
|
||||
description:
|
||||
The CLKOUT pin may have its purpose overridden by OTP configuration. It
|
||||
is possible the BD73800 does not output a clock signal. Hence the clk
|
||||
properties are optional.
|
||||
maxItems: 1
|
||||
|
||||
"#clock-cells":
|
||||
const: 0
|
||||
|
||||
clock-output-names:
|
||||
maxItems: 1
|
||||
|
||||
rohm,clkout-open-drain: true
|
||||
|
||||
regulators:
|
||||
$ref: /schemas/regulator/rohm,bd73800-regulator.yaml
|
||||
description:
|
||||
List of child nodes that specify the regulators.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- regulators
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
#include <dt-bindings/leds/common.h>
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
pmic: pmic@4b {
|
||||
compatible = "rohm,bd73800";
|
||||
reg = <0x4b>;
|
||||
|
||||
interrupt-parent = <&gpio1>;
|
||||
interrupts = <29 IRQ_TYPE_LEVEL_LOW>;
|
||||
|
||||
clocks = <&osc 0>;
|
||||
#clock-cells = <0>;
|
||||
clock-output-names = "bd73800-32k-out";
|
||||
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
rohm,pin-gpio1 = "gpo";
|
||||
rohm,pin-exten = "gpi";
|
||||
|
||||
regulators {
|
||||
buck1: buck1 {
|
||||
regulator-name = "buck1";
|
||||
regulator-min-microvolt = <800000>;
|
||||
regulator-max-microvolt = <2000000>;
|
||||
regulator-always-on;
|
||||
regulator-ramp-delay = <1250>;
|
||||
rohm,dvs-run-voltage = <1150000>;
|
||||
rohm,dvs-suspend-voltage = <950000>;
|
||||
};
|
||||
buck2: buck2 {
|
||||
regulator-name = "buck2";
|
||||
regulator-min-microvolt = <800000>;
|
||||
regulator-max-microvolt = <2000000>;
|
||||
regulator-always-on;
|
||||
regulator-ramp-delay = <1250>;
|
||||
rohm,dvs-run-voltage = <1150000>;
|
||||
rohm,dvs-suspend-voltage = <950000>;
|
||||
};
|
||||
buck3: buck3 {
|
||||
regulator-name = "buck3";
|
||||
regulator-min-microvolt = <1200000>;
|
||||
regulator-max-microvolt = <2700000>;
|
||||
rohm,dvs-run-voltage = <1150000>;
|
||||
rohm,dvs-idle-voltage = <1100000>;
|
||||
rohm,dvs-suspend-voltage = <950000>;
|
||||
regulator-always-on;
|
||||
};
|
||||
buck4: buck4 {
|
||||
regulator-name = "buck4";
|
||||
regulator-min-microvolt = <1100000>;
|
||||
regulator-max-microvolt = <1850000>;
|
||||
regulator-always-on;
|
||||
};
|
||||
buck5: buck5 {
|
||||
regulator-name = "buck5";
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
regulator-always-on;
|
||||
};
|
||||
buck6: buck6 {
|
||||
regulator-name = "buck6";
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
regulator-always-on;
|
||||
};
|
||||
buck7: buck7 {
|
||||
regulator-name = "buck7";
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
regulator-always-on;
|
||||
};
|
||||
buck8: buck8 {
|
||||
regulator-name = "buck8";
|
||||
regulator-min-microvolt = <500000>;
|
||||
regulator-max-microvolt = <1300000>;
|
||||
regulator-always-on;
|
||||
};
|
||||
ldo1: ldo1 {
|
||||
regulator-name = "ldo1";
|
||||
rohm,ldo-range-high;
|
||||
regulator-min-microvolt = <800000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
regulator-always-on;
|
||||
};
|
||||
ldo2: ldo2 {
|
||||
regulator-name = "ldo2";
|
||||
regulator-min-microvolt = <800000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
regulator-always-on;
|
||||
};
|
||||
ldo3: ldo3 {
|
||||
regulator-name = "ldo3";
|
||||
regulator-min-microvolt = <800000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
regulator-always-on;
|
||||
};
|
||||
ldo4: ldo4 {
|
||||
regulator-name = "ldo4";
|
||||
regulator-min-microvolt = <650000>;
|
||||
regulator-max-microvolt = <1750000>;
|
||||
regulator-always-on;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
72
Documentation/devicetree/bindings/mfd/rohm,pmic-pins.yaml
Normal file
72
Documentation/devicetree/bindings/mfd/rohm,pmic-pins.yaml
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/mfd/rohm,pmic-pins.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: ROHM PMICs' OTP configured pin descriptions
|
||||
|
||||
maintainers:
|
||||
- Matti Vaittinen <mazziesaccount@gmail.com>
|
||||
|
||||
description:
|
||||
Collection of properties which are commonly used to describe various
|
||||
ROHM PMIC's pins.
|
||||
|
||||
properties:
|
||||
rohm,clkout-open-drain:
|
||||
description: clk32kout mode. Set to 1 for "open-drain" or 0 for "cmos"
|
||||
a.k.a "push-pull".
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
maximum: 1
|
||||
|
||||
rohm,pin-clkout:
|
||||
$ref: /schemas/types.yaml#/definitions/string
|
||||
description:
|
||||
The IC has different OTP options to use clkout-pin for different
|
||||
purposes. Set this property to indicate the OTP variant.
|
||||
|
||||
Many of the ROHM ICs have pins, which function can be defined in
|
||||
OTP. Some of them provide no means to detect the pin configuration
|
||||
at run-time, leaving software unaware of which features the IC
|
||||
really has. These properties can be used to inform which pins
|
||||
provide which functionality. IOW, these properties aren't used to
|
||||
configure pin, they are used to tell what functionality pins on
|
||||
this specific IC have.
|
||||
|
||||
# Supported functionalities depend on the exact IC model. Following
|
||||
# values are already defined: gpi, gpo.
|
||||
# Please, re-use them when adding new ICs.
|
||||
|
||||
rohm,pin-fault_b:
|
||||
$ref: /schemas/types.yaml#/definitions/string
|
||||
description:
|
||||
The IC has different OTP options to use fault_b-pin for different
|
||||
purposes. Set this property to indicate the OTP variant.
|
||||
|
||||
# Supported functionalities depend on the exact IC model. Following
|
||||
# values are already defined: gpi, gpo, faultb, readyind, pwrseq.
|
||||
# Please, re-use them when adding new ICs.
|
||||
|
||||
patternProperties:
|
||||
"^rohm,pin-dvs[0-1]$":
|
||||
$ref: /schemas/types.yaml#/definitions/string
|
||||
description:
|
||||
The IC has different OTP options to use dvs<X>-pins for different
|
||||
purposes. Set this property to indicate the OTP variant.
|
||||
# Supported functionalities depend on the exact IC model. Following
|
||||
# values are already defined: dvs-input, gpi, gpo, pwrseq.
|
||||
# Please, re-use them when adding new ICs.
|
||||
|
||||
"^rohm,pin-exten([0-1])?$":
|
||||
$ref: /schemas/types.yaml#/definitions/string
|
||||
description:
|
||||
The IC has an OTP option to use exten -pin(s) for different purposes.
|
||||
Set this property to indicate the OTP variant.
|
||||
# Supported functionalities depend on the exact IC model. Following
|
||||
# values are already defined: gpi, gpo, pwrseq.
|
||||
# Please, re-use them when adding new ICs.
|
||||
|
||||
# The schema is expected to be reference by IC schemas, which may introduce
|
||||
# other properties that must be allowed.
|
||||
additionalProperties: true
|
||||
|
|
@ -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,6 +346,7 @@ properties:
|
|||
|
||||
required:
|
||||
- compatible
|
||||
- '#sound-dai-cells'
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,99 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/regulator/rohm,bd73800-regulator.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: ROHM BD73800 Power Management Integrated Circuit regulators
|
||||
|
||||
maintainers:
|
||||
- Matti Vaittinen <mazziesaccount@gmail.com>
|
||||
|
||||
description: |
|
||||
This module is part of the ROHM BD73800 MFD device. For more details
|
||||
see Documentation/devicetree/bindings/mfd/rohm,bd73800-pmic.yaml.
|
||||
|
||||
The regulator controller is represented as a sub-node of the PMIC node
|
||||
on the device tree.
|
||||
|
||||
Regulator nodes should be named to buck<number> and ldo<number>.
|
||||
The valid names for BD73800 regulator nodes are
|
||||
buck1, buck2, buck3, buck4, buck5, buck6, buck7, buck8
|
||||
ldo1, ldo2, ldo3, ldo4
|
||||
|
||||
patternProperties:
|
||||
"^buck[1-8]$":
|
||||
type: object
|
||||
description:
|
||||
Properties for a single BUCK regulator.
|
||||
allOf:
|
||||
- $ref: regulator.yaml#
|
||||
- $ref: rohm,pmic-states.yaml#
|
||||
|
||||
properties:
|
||||
regulator-name:
|
||||
pattern: "^buck[1-8]$"
|
||||
description:
|
||||
should be "buck1", ..., "buck8"
|
||||
|
||||
rohm,dvs-run-voltage:
|
||||
minimum: 0
|
||||
maximum: 3500000
|
||||
|
||||
rohm,dvs-idle-voltage:
|
||||
minimum: 0
|
||||
maximum: 3500000
|
||||
|
||||
rohm,dvs-suspend-voltage:
|
||||
minimum: 0
|
||||
maximum: 3500000
|
||||
|
||||
# BUCKs 1,2,3,4 and 8 support voltages 0.5 - 1.3V
|
||||
# BUCK 5 supports voltages 0.3 - 1.3V
|
||||
# BUCKs 6 and 7 support voltages 1.5 - 3.5V
|
||||
|
||||
required:
|
||||
- regulator-name
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
"^ldo[1-4]$":
|
||||
type: object
|
||||
description:
|
||||
Properties for single LDO regulator.
|
||||
allOf:
|
||||
- $ref: regulator.yaml#
|
||||
- $ref: rohm,pmic-states.yaml#
|
||||
|
||||
properties:
|
||||
regulator-name:
|
||||
pattern: "^ldo[1-4]$"
|
||||
description:
|
||||
should be "ldo1", ..., "ldo4"
|
||||
|
||||
rohm,dvs-run-voltage:
|
||||
minimum: 0
|
||||
maximum: 1
|
||||
|
||||
rohm,dvs-idle-voltage:
|
||||
minimum: 0
|
||||
maximum: 1
|
||||
|
||||
rohm,dvs-suspend-voltage:
|
||||
minimum: 0
|
||||
maximum: 1
|
||||
|
||||
rohm,ldo-range-high:
|
||||
type: boolean
|
||||
description:
|
||||
LDO1 and LDO3 voltage ranges can be "high" or "low" depending on
|
||||
OTP. Indicate that the "high" range is used. See comment below
|
||||
for voltages.
|
||||
|
||||
# LDOs 2 and 4 support voltages 0.75 - 3.3V
|
||||
# LDOs 1 and 3 may support different ranges depending on OTP.
|
||||
# either 0.6 - 1.8V or 0.75 - 3.3V.
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
additionalProperties: false
|
||||
|
|
@ -23821,6 +23821,7 @@ F: drivers/clk/clk-bd718x7.c
|
|||
F: drivers/gpio/gpio-bd71815.c
|
||||
F: drivers/gpio/gpio-bd71828.c
|
||||
F: drivers/gpio/gpio-bd72720.c
|
||||
F: drivers/gpio/gpio-bd73800.c
|
||||
F: drivers/mfd/rohm-bd71828.c
|
||||
F: drivers/mfd/rohm-bd718x7.c
|
||||
F: drivers/mfd/rohm-bd9576.c
|
||||
|
|
@ -23840,6 +23841,7 @@ F: include/linux/mfd/rohm-bd71815.h
|
|||
F: include/linux/mfd/rohm-bd71828.h
|
||||
F: include/linux/mfd/rohm-bd718x7.h
|
||||
F: include/linux/mfd/rohm-bd72720.h
|
||||
F: include/linux/mfd/rohm-bd73800.h
|
||||
F: include/linux/mfd/rohm-bd957x.h
|
||||
F: include/linux/mfd/rohm-bd96801.h
|
||||
F: include/linux/mfd/rohm-bd96802.h
|
||||
|
|
|
|||
|
|
@ -21,6 +21,9 @@
|
|||
#define BD718XX_REG_OUT32K 0x2E
|
||||
/* BD72720 */
|
||||
#define BD72720_REG_OUT32K 0x9a
|
||||
/* BD73800 */
|
||||
#define BD73800_REG_OUT32K 0x50
|
||||
|
||||
/*
|
||||
* BD71837, BD71847, and BD71828 all use bit [0] to clk output control
|
||||
*/
|
||||
|
|
@ -123,6 +126,10 @@ static int bd71837_clk_probe(struct platform_device *pdev)
|
|||
c->reg = BD72720_REG_OUT32K;
|
||||
c->mask = CLK_OUT_EN_MASK;
|
||||
break;
|
||||
case ROHM_CHIP_TYPE_BD73800:
|
||||
c->reg = BD73800_REG_OUT32K;
|
||||
c->mask = CLK_OUT_EN_MASK;
|
||||
break;
|
||||
default:
|
||||
dev_err(&pdev->dev, "Unknown clk chip\n");
|
||||
return -EINVAL;
|
||||
|
|
@ -152,6 +159,7 @@ static const struct platform_device_id bd718x7_clk_id[] = {
|
|||
{ .name = "bd71828-clk", .driver_data = ROHM_CHIP_TYPE_BD71828 },
|
||||
{ .name = "bd71815-clk", .driver_data = ROHM_CHIP_TYPE_BD71815 },
|
||||
{ .name = "bd72720-clk", .driver_data = ROHM_CHIP_TYPE_BD72720 },
|
||||
{ .name = "bd73800-clk", .driver_data = ROHM_CHIP_TYPE_BD73800 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(platform, bd718x7_clk_id);
|
||||
|
|
|
|||
|
|
@ -1385,6 +1385,18 @@ config GPIO_BD72720
|
|||
be configured to GPO on the ROHM PMIC. The pin configuration is done
|
||||
on OTP at manufacturing.
|
||||
|
||||
config GPIO_BD73800
|
||||
tristate "ROHM BD73800 GPIO support"
|
||||
depends on MFD_ROHM_BD71828
|
||||
select GPIO_REGMAP
|
||||
help
|
||||
Support for GPIOs on ROHM BD73800 PMIC. There can be up to 4
|
||||
GPI or GPO pins available on the PMIC in total. The purpose of
|
||||
the pins is decided at the device manufacturing by OTP
|
||||
configuration and can't be reconfigured later. Enable this
|
||||
if your PMIC has pins set as GPIs or GPOs and if you wish to
|
||||
control the pins via the GPIO framework.
|
||||
|
||||
config GPIO_BD9571MWV
|
||||
tristate "ROHM BD9571 GPIO support"
|
||||
depends on MFD_BD9571MWV
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ obj-$(CONFIG_GPIO_BCM_XGS_IPROC) += gpio-xgs-iproc.o
|
|||
obj-$(CONFIG_GPIO_BD71815) += gpio-bd71815.o
|
||||
obj-$(CONFIG_GPIO_BD71828) += gpio-bd71828.o
|
||||
obj-$(CONFIG_GPIO_BD72720) += gpio-bd72720.o
|
||||
obj-$(CONFIG_GPIO_BD73800) += gpio-bd73800.o
|
||||
obj-$(CONFIG_GPIO_BD9571MWV) += gpio-bd9571mwv.o
|
||||
obj-$(CONFIG_GPIO_BLZP1600) += gpio-blzp1600.o
|
||||
obj-$(CONFIG_GPIO_BRCMSTB) += gpio-brcmstb.o
|
||||
|
|
|
|||
209
drivers/gpio/gpio-bd73800.c
Normal file
209
drivers/gpio/gpio-bd73800.c
Normal file
|
|
@ -0,0 +1,209 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Support to GPIOs on ROHM BD73800
|
||||
* Copyright 2024 ROHM Semiconductors.
|
||||
* Author: Matti Vaittinen <mazziesaccount@gmail.com>
|
||||
*/
|
||||
|
||||
#include <linux/bitmap.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/gpio/regmap.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/mfd/rohm-bd73800.h>
|
||||
|
||||
#define BD73800_GPIO_MAX_PINS 4
|
||||
/*
|
||||
* The BD73800 has several "one time programmable" (OTP) configurations which
|
||||
* can be set at manufacturing phase. Some of these options allow using
|
||||
* individual pins as GPI or GPO (not both at the same time). The OTP
|
||||
* configuration can't be read at run-time, so drivers rely on device-tree to
|
||||
* advertise the OTP programmed in manufacturing.
|
||||
*
|
||||
* The pins which can be used as GPIO are:
|
||||
* GPIO1, CLKOUT (GPIO2), FAULT_B, EXTEN_OUT.
|
||||
*
|
||||
* The OTP options 2 and 3 state for all the pins:
|
||||
* - OTP2: GPI (also IRQ source)
|
||||
* - OTP3: GPO (NOTE: This is actually 2 different OTP options. Either a
|
||||
* register controllable output or a power-sequence controlled output.
|
||||
* The "gpo" referred here means only the register controllable output.)
|
||||
* The datasheet refers to this as: "<pin> output is controlled by
|
||||
* GPIO<N>_OUT or power on/off sequencer to control external VRs. ON/OFF
|
||||
* sequence timing is configurable."
|
||||
*
|
||||
* The data-sheet further says that the GPI/GPO is not a default OTP
|
||||
* configuration for any of the pins. Hence the GPIO driver defaults to a pin
|
||||
* not being a GPI or GPO, but requires the pin to be explicitly marked as a
|
||||
* GPI or GPO in the device-tree.
|
||||
*
|
||||
* DT properties:
|
||||
* "rohm,pin-gpio1", "rohm,pin-clkout", "rohm,pin-fault_b", "rohm,pin-exten"
|
||||
* can be set to one of the values "gpi" or "gpo" to enable them to be used as
|
||||
* GPIO.
|
||||
*
|
||||
* The amount of GPIO lines the chip exposes to the user-space (chip.ngpio) is
|
||||
* always the same, regardless of the OTP variant in use. The lines which are
|
||||
* not usable as GPIO on a given OTP variant are marked invalid via the GPIO
|
||||
* valid_mask. This way the user-space always sees a constant amount of GPIO
|
||||
* lines, where numbering (relative to the chip's base) stays also the same.
|
||||
* Users can then use the valid_mask to find out which of the lines are usable.
|
||||
*/
|
||||
|
||||
struct bd73800_gpio {
|
||||
/* dev points to the platform device for devm and prints */
|
||||
struct device *dev;
|
||||
struct regmap *regmap;
|
||||
/* Pins which have been OTP configured as GPI or GPO */
|
||||
DECLARE_BITMAP(valid_mask, BD73800_GPIO_MAX_PINS);
|
||||
/* Subset of valid_mask - pins which have been OTP configured as GPO */
|
||||
DECLARE_BITMAP(output_mask, BD73800_GPIO_MAX_PINS);
|
||||
};
|
||||
|
||||
static const char * const bd73800_gpio_properties[BD73800_GPIO_MAX_PINS] = {
|
||||
"rohm,pin-gpio1",
|
||||
"rohm,pin-clkout",
|
||||
"rohm,pin-fault_b",
|
||||
"rohm,pin-exten"
|
||||
};
|
||||
|
||||
static int bd73800_gpio_get_pins(struct bd73800_gpio *data)
|
||||
{
|
||||
struct device *parent = data->dev->parent;
|
||||
const char *val;
|
||||
int i, ret;
|
||||
|
||||
for (i = 0; i < BD73800_GPIO_MAX_PINS; i++) {
|
||||
ret = device_property_read_string(parent,
|
||||
bd73800_gpio_properties[i],
|
||||
&val);
|
||||
if (ret) {
|
||||
if (ret == -EINVAL)
|
||||
continue;
|
||||
|
||||
return dev_err_probe(data->dev, ret,
|
||||
"pin %d (%s), bad configuration\n", i,
|
||||
bd73800_gpio_properties[i]);
|
||||
}
|
||||
|
||||
if (!strcmp(val, "gpi")) {
|
||||
__set_bit(i, data->valid_mask);
|
||||
} else if (!strcmp(val, "gpo")) {
|
||||
__set_bit(i, data->valid_mask);
|
||||
__set_bit(i, data->output_mask);
|
||||
} else {
|
||||
dev_warn(data->dev,
|
||||
"pin %d (%s), unknown value '%s' ignored\n", i,
|
||||
bd73800_gpio_properties[i], val);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bd73800_gpio_init_valid_mask(struct gpio_chip *gc,
|
||||
unsigned long *valid_mask,
|
||||
unsigned int ngpios)
|
||||
{
|
||||
struct gpio_regmap *gpio = gpiochip_get_data(gc);
|
||||
struct bd73800_gpio *data = gpio_regmap_get_drvdata(gpio);
|
||||
|
||||
bitmap_copy(valid_mask, data->valid_mask, ngpios);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* The used register depends on OTP:
|
||||
* - If OTP has set pin as GPO, only the GPO_OUT register is valid.
|
||||
* - If OTP has set pin as GPI, only the INT_5_SRC register is valid.
|
||||
*/
|
||||
static int bd73800_gpio_reg_mask_xlate(struct gpio_regmap *gpio,
|
||||
enum gpio_regmap_operation op,
|
||||
unsigned int base, unsigned int offset,
|
||||
unsigned int *reg, unsigned int *mask)
|
||||
{
|
||||
struct bd73800_gpio *data = gpio_regmap_get_drvdata(gpio);
|
||||
bool is_output = test_bit(offset, data->output_mask);
|
||||
|
||||
if (is_output)
|
||||
*reg = BD73800_REG_GPO_OUT;
|
||||
else
|
||||
*reg = base;
|
||||
|
||||
*mask = BIT(offset);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gpo_bd73800_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct gpio_regmap_config config = { };
|
||||
struct bd73800_gpio *data;
|
||||
struct device *parent, *dev;
|
||||
int ret;
|
||||
|
||||
dev = &pdev->dev;
|
||||
/* The device-tree and regmap come from MFD => use parent for that */
|
||||
parent = dev->parent;
|
||||
|
||||
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
data->dev = dev;
|
||||
data->regmap = dev_get_regmap(parent, NULL);
|
||||
if (!data->regmap)
|
||||
return dev_err_probe(dev, -ENODEV, "no parent regmap\n");
|
||||
|
||||
ret = bd73800_gpio_get_pins(data);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (bitmap_empty(data->valid_mask, BD73800_GPIO_MAX_PINS)) {
|
||||
/*
|
||||
* The BD73800 may or may not have pins allocated for GPIO
|
||||
* depending on the OTP used at manufacturing.
|
||||
* If there are no pins, then we have nothing to do.
|
||||
*/
|
||||
dev_dbg(dev, "no GPIO pins\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
config.parent = parent;
|
||||
config.regmap = data->regmap;
|
||||
config.label = "bd73800";
|
||||
config.ngpio = BD73800_GPIO_MAX_PINS;
|
||||
config.reg_dat_base = BD73800_REG_INT_5_SRC;
|
||||
config.reg_set_base = BD73800_REG_GPO_OUT;
|
||||
config.reg_mask_xlate = bd73800_gpio_reg_mask_xlate;
|
||||
config.init_valid_mask = bd73800_gpio_init_valid_mask;
|
||||
/* All pins that are valid GPIO lines also have a fixed direction */
|
||||
config.fixed_direction_mask = data->valid_mask;
|
||||
config.fixed_direction_output = data->output_mask;
|
||||
config.drvdata = data;
|
||||
|
||||
return PTR_ERR_OR_ZERO(devm_gpio_regmap_register(dev, &config));
|
||||
}
|
||||
|
||||
static const struct platform_device_id bd73800_gpio_id[] = {
|
||||
{ "bd73800-gpio" },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(platform, bd73800_gpio_id);
|
||||
|
||||
static struct platform_driver gpo_bd73800_driver = {
|
||||
.driver = {
|
||||
.name = "bd73800-gpio",
|
||||
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
|
||||
},
|
||||
.probe = gpo_bd73800_probe,
|
||||
.id_table = bd73800_gpio_id,
|
||||
};
|
||||
module_platform_driver(gpo_bd73800_driver);
|
||||
|
||||
MODULE_AUTHOR("Matti Vaittinen <mazziesaccount@gmail.com>");
|
||||
MODULE_DESCRIPTION("GPIO interface for BD73800");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
@ -17,14 +17,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
|
||||
|
|
@ -48,7 +51,7 @@
|
|||
|
||||
|
||||
struct lm3533_als {
|
||||
struct lm3533 *lm3533;
|
||||
struct regmap *regmap;
|
||||
struct platform_device *pdev;
|
||||
|
||||
unsigned long flags;
|
||||
|
|
@ -56,6 +59,9 @@ struct lm3533_als {
|
|||
|
||||
atomic_t zone;
|
||||
struct mutex thresh_mutex;
|
||||
|
||||
u32 r_select;
|
||||
bool pwm_mode;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -64,7 +70,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)
|
||||
|
|
@ -72,7 +78,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;
|
||||
|
|
@ -86,10 +92,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;
|
||||
|
|
@ -127,7 +133,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;
|
||||
|
|
@ -140,7 +146,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");
|
||||
|
||||
|
|
@ -161,7 +167,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");
|
||||
|
||||
|
|
@ -171,8 +177,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);
|
||||
|
|
@ -271,16 +277,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);
|
||||
|
|
@ -293,17 +293,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;
|
||||
}
|
||||
|
|
@ -316,7 +315,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;
|
||||
|
|
@ -326,7 +325,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");
|
||||
|
||||
|
|
@ -337,8 +336,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)
|
||||
|
|
@ -348,7 +347,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;
|
||||
|
|
@ -363,7 +362,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;
|
||||
|
|
@ -375,11 +374,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)
|
||||
|
|
@ -409,7 +408,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;
|
||||
|
|
@ -431,7 +430,7 @@ static ssize_t store_thresh_either_en(struct device *dev,
|
|||
u8 zone;
|
||||
int ret;
|
||||
|
||||
if (!als->irq)
|
||||
if (als->irq <= 0)
|
||||
return -EBUSY;
|
||||
|
||||
if (kstrtoul(buf, 0, &enable))
|
||||
|
|
@ -503,7 +502,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) {
|
||||
|
|
@ -714,71 +713,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;
|
||||
|
|
@ -798,10 +777,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");
|
||||
|
||||
|
|
@ -810,10 +789,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");
|
||||
|
||||
|
|
@ -828,7 +807,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;
|
||||
|
|
@ -838,12 +816,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;
|
||||
|
|
@ -852,25 +824,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;
|
||||
|
||||
|
|
@ -889,7 +863,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;
|
||||
|
|
@ -903,13 +877,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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -2226,7 +2226,7 @@ config MFD_ROHM_BD718XX
|
|||
and emergency shut down as well as 32,768KHz clock output.
|
||||
|
||||
config MFD_ROHM_BD71828
|
||||
tristate "ROHM BD718[15/28/79], BD72720 and BD73900 PMICs"
|
||||
tristate "ROHM BD718[15/28/79], BD72720 and BD73[8/9]00 PMICs"
|
||||
depends on I2C=y
|
||||
depends on OF
|
||||
select REGMAP_I2C
|
||||
|
|
@ -2235,14 +2235,17 @@ config MFD_ROHM_BD71828
|
|||
select MFD_ROHM_PWRBUTTON
|
||||
help
|
||||
Select this option to get support for the ROHM BD71815, BD71828,
|
||||
BD71879, BD72720 and BD73900 Power Management ICs (PMICs). These are
|
||||
single-chip Power Management ICs (PMIC), mainly for battery-powered
|
||||
portable devices.
|
||||
BD71879, BD72720, BD73800 and BD73900 Power Management ICs (PMICs).
|
||||
These are single-chip Power Management ICs (PMIC), mainly for
|
||||
battery-powered portable devices.
|
||||
The BD71815 has 5 bucks, 7 LDOs, and a boost for driving LEDs.
|
||||
The BD718[28/79] have 7 buck converters and 7 LDOs.
|
||||
The BD72720 and the BD73900 have 10 bucks and 11 LDOs.
|
||||
All ICs provide a single-cell linear charger, a Coulomb counter,
|
||||
a Real-Time Clock (RTC), GPIOs and a 32.768 kHz clock gate.
|
||||
All the above ICs provide a single-cell linear charger, and a Coulomb
|
||||
counter.
|
||||
The BD73800 has 8 bucks, 4 LDOs and ADC for power/current
|
||||
accumulation but no charging logic. All these PMICs integrate also a
|
||||
Real-Time Clock (RTC), GPIOs and a 32.768 kHz clock gate.
|
||||
|
||||
config MFD_ROHM_BD957XMUF
|
||||
tristate "ROHM BD9576MUF and BD9573MUF Power Management ICs"
|
||||
|
|
|
|||
|
|
@ -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", ®);
|
||||
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", ®);
|
||||
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,
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (C) 2019 ROHM Semiconductors
|
||||
* Copyright (C) 2019, 2026 ROHM Semiconductor
|
||||
*
|
||||
* ROHM BD718[15/28/79] and BD72720 PMIC driver
|
||||
* ROHM BD718[15/28/79], BD72720 and BD73[8/9]00 PMIC driver
|
||||
*/
|
||||
|
||||
#include <linux/i2c.h>
|
||||
|
|
@ -14,6 +14,7 @@
|
|||
#include <linux/mfd/rohm-bd71815.h>
|
||||
#include <linux/mfd/rohm-bd71828.h>
|
||||
#include <linux/mfd/rohm-bd72720.h>
|
||||
#include <linux/mfd/rohm-bd73800.h>
|
||||
#include <linux/mfd/rohm-generic.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
|
|
@ -56,6 +57,12 @@ static const struct resource bd72720_rtc_irqs[] = {
|
|||
DEFINE_RES_IRQ_NAMED(BD72720_INT_RTC2, "bd70528-rtc-alm-2"),
|
||||
};
|
||||
|
||||
static const struct resource bd73800_rtc_irqs[] = {
|
||||
DEFINE_RES_IRQ_NAMED(BD73800_INT_RTC0, "bd70528-rtc-alm-0"),
|
||||
DEFINE_RES_IRQ_NAMED(BD73800_INT_RTC1, "bd70528-rtc-alm-1"),
|
||||
DEFINE_RES_IRQ_NAMED(BD73800_INT_RTC2, "bd70528-rtc-alm-2"),
|
||||
};
|
||||
|
||||
static const struct resource bd71815_power_irqs[] = {
|
||||
DEFINE_RES_IRQ_NAMED(BD71815_INT_DCIN_RMV, "bd71815-dcin-rmv"),
|
||||
DEFINE_RES_IRQ_NAMED(BD71815_INT_CLPS_OUT, "bd71815-dcin-clps-out"),
|
||||
|
|
@ -230,6 +237,17 @@ static const struct mfd_cell bd72720_mfd_cells[] = {
|
|||
/* Power button is registered separately */
|
||||
};
|
||||
|
||||
static const struct mfd_cell bd73800_mfd_cells[] = {
|
||||
{ .name = "bd73800-pmic", },
|
||||
{ .name = "bd73800-clk", },
|
||||
{ .name = "bd73800-gpio", },
|
||||
{
|
||||
.name = "bd73800-rtc",
|
||||
.num_resources = ARRAY_SIZE(bd73800_rtc_irqs),
|
||||
.resources = bd73800_rtc_irqs,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct regmap_range bd71815_volatile_ranges[] = {
|
||||
regmap_reg_range(BD71815_REG_SEC, BD71815_REG_YEAR),
|
||||
regmap_reg_range(BD71815_REG_CONF, BD71815_REG_BAT_TEMP),
|
||||
|
|
@ -339,6 +357,17 @@ static const struct regmap_range bd72720_volatile_ranges_4c[] = {
|
|||
BD72720_UNWRAP_REG_RANGE(BD72720_REG_IMPCHK_CTRL, BD72720_REG_IMPCHK_CTRL),
|
||||
};
|
||||
|
||||
static const struct regmap_range bd73800_volatile_ranges[] = {
|
||||
regmap_reg_range(BD73800_REG_POR_REASON, BD73800_REG_POW_STATE),
|
||||
regmap_reg_range(BD73800_REG_PS_CTRL_1, BD73800_REG_PS_CTRL_2),
|
||||
regmap_reg_range(BD73800_REG_RCVNUM, BD73800_REG_RCVNUM),
|
||||
regmap_reg_range(BD73800_REG_RTC_SEC, BD73800_REG_RTC_YEAR),
|
||||
regmap_reg_range(BD73800_REG_RTC_CONF, BD73800_REG_RTC_CONF),
|
||||
regmap_reg_range(BD73800_REG_ADC_ACCUM_KICK, BD73800_REG_ADC_TEMP_VAL0),
|
||||
regmap_reg_range(BD73800_REG_INT_MAIN_STAT, BD73800_REG_INT_5_STAT),
|
||||
regmap_reg_range(BD73800_REG_INT_MAIN_SRC, BD73800_REG_INT_5_SRC),
|
||||
};
|
||||
|
||||
static const struct regmap_access_table bd71815_volatile_regs = {
|
||||
.yes_ranges = &bd71815_volatile_ranges[0],
|
||||
.n_yes_ranges = ARRAY_SIZE(bd71815_volatile_ranges),
|
||||
|
|
@ -364,6 +393,24 @@ static const struct regmap_access_table bd72720_volatile_regs_4c = {
|
|||
.n_yes_ranges = ARRAY_SIZE(bd72720_volatile_ranges_4c),
|
||||
};
|
||||
|
||||
static const struct regmap_access_table bd73800_volatile_regs = {
|
||||
.yes_ranges = bd73800_volatile_ranges,
|
||||
.n_yes_ranges = ARRAY_SIZE(bd73800_volatile_ranges),
|
||||
};
|
||||
|
||||
static const struct regmap_range bd73800_read_only_ranges[] = {
|
||||
regmap_reg_range(BD73800_REG_PRODUCT_ID, BD73800_REG_NVMVERSION),
|
||||
regmap_reg_range(BD73800_REG_POW_STATE, BD73800_REG_POW_STATE),
|
||||
regmap_reg_range(BD73800_REG_ADC_ACCUM_CNT2, BD73800_REG_ADC_TEMP_VAL0),
|
||||
regmap_reg_range(BD73800_REG_INT_MAIN_STAT, BD73800_REG_INT_MAIN_STAT),
|
||||
regmap_reg_range(BD73800_REG_INT_MAIN_SRC, BD73800_REG_INT_5_SRC),
|
||||
};
|
||||
|
||||
static const struct regmap_access_table bd73800_ro_regs = {
|
||||
.no_ranges = bd73800_read_only_ranges,
|
||||
.n_no_ranges = ARRAY_SIZE(bd73800_read_only_ranges),
|
||||
};
|
||||
|
||||
static const struct regmap_config bd71815_regmap = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
|
|
@ -448,6 +495,15 @@ static const struct regmap_config bd72720_regmap_4c = {
|
|||
.cache_type = REGCACHE_MAPLE,
|
||||
};
|
||||
|
||||
static const struct regmap_config bd73800_regmap = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
.wr_table = &bd73800_ro_regs,
|
||||
.volatile_table = &bd73800_volatile_regs,
|
||||
.max_register = BD73800_MAX_REGISTER - 1,
|
||||
.cache_type = REGCACHE_MAPLE,
|
||||
};
|
||||
|
||||
/*
|
||||
* Mapping of main IRQ register bits to sub-IRQ register offsets so that we can
|
||||
* access corect sub-IRQ registers based on bits that are set in main IRQ
|
||||
|
|
@ -779,6 +835,60 @@ static int bd72720_set_type_config(unsigned int **buf, unsigned int type,
|
|||
return regmap_irq_set_type_config_simple(buf, type, irq_data, idx, irq_drv_data);
|
||||
}
|
||||
|
||||
static const struct regmap_irq bd73800_irqs[] = {
|
||||
/* INT_STAT_1 register IRQs, ADC and RTC */
|
||||
REGMAP_IRQ_REG(BD73800_INT_ADC_ACCUM_DONE, 0, BD73800_INT_ADC_ACCUM_DONE_MASK),
|
||||
REGMAP_IRQ_REG(BD73800_INT_ADC_ACCUM_OVF, 0, BD73800_INT_ADC_ACCUM_OVF_MASK),
|
||||
REGMAP_IRQ_REG(BD73800_INT_ADC_ACCUM_VAL, 0, BD73800_INT_ADC_ACCUM_VAL_MASK),
|
||||
REGMAP_IRQ_REG(BD73800_INT_ADC_ACCUM_TW, 0, BD73800_INT_ADC_ACCUM_TW_MASK),
|
||||
REGMAP_IRQ_REG(BD73800_INT_ADC_POW_VAL, 0, BD73800_INT_ADC_POW_VAL_MASK),
|
||||
REGMAP_IRQ_REG(BD73800_INT_RTC0, 0, BD73800_INT_RTC0_MASK),
|
||||
REGMAP_IRQ_REG(BD73800_INT_RTC1, 0, BD73800_INT_RTC1_MASK),
|
||||
REGMAP_IRQ_REG(BD73800_INT_RTC2, 0, BD73800_INT_RTC2_MASK),
|
||||
|
||||
/* BUCK reg interrupts */
|
||||
/* INT_STAT_2 IRQs */
|
||||
REGMAP_IRQ_REG(BD73800_INT_BUCK1_DVS_DONE, 1, BD73800_INT_BUCK1_DVS_DONE_MASK),
|
||||
REGMAP_IRQ_REG(BD73800_INT_BUCK2_DVS_DONE, 1, BD73800_INT_BUCK2_DVS_DONE_MASK),
|
||||
REGMAP_IRQ_REG(BD73800_INT_BUCK3_DVS_DONE, 1, BD73800_INT_BUCK3_DVS_DONE_MASK),
|
||||
REGMAP_IRQ_REG(BD73800_INT_BUCK4_DVS_DONE, 1, BD73800_INT_BUCK4_DVS_DONE_MASK),
|
||||
REGMAP_IRQ_REG(BD73800_INT_BUCK5_DVS_DONE, 1, BD73800_INT_BUCK5_DVS_DONE_MASK),
|
||||
REGMAP_IRQ_REG(BD73800_INT_BUCK6_DVS_DONE, 1, BD73800_INT_BUCK6_DVS_DONE_MASK),
|
||||
REGMAP_IRQ_REG(BD73800_INT_BUCK7_DVS_DONE, 1, BD73800_INT_BUCK7_DVS_DONE_MASK),
|
||||
REGMAP_IRQ_REG(BD73800_INT_BUCK8_DVS_DONE, 1, BD73800_INT_BUCK8_DVS_DONE_MASK),
|
||||
/* INT_STAT_3 IRQs */
|
||||
REGMAP_IRQ_REG(BD73800_INT_BUCK1_OCP, 2, BD73800_INT_BUCK1_OCP_MASK),
|
||||
REGMAP_IRQ_REG(BD73800_INT_BUCK2_OCP, 2, BD73800_INT_BUCK2_OCP_MASK),
|
||||
REGMAP_IRQ_REG(BD73800_INT_BUCK3_OCP, 2, BD73800_INT_BUCK3_OCP_MASK),
|
||||
REGMAP_IRQ_REG(BD73800_INT_BUCK4_OCP, 2, BD73800_INT_BUCK4_OCP_MASK),
|
||||
REGMAP_IRQ_REG(BD73800_INT_BUCK5_OCP, 2, BD73800_INT_BUCK5_OCP_MASK),
|
||||
REGMAP_IRQ_REG(BD73800_INT_BUCK6_OCP, 2, BD73800_INT_BUCK6_OCP_MASK),
|
||||
REGMAP_IRQ_REG(BD73800_INT_BUCK7_OCP, 2, BD73800_INT_BUCK7_OCP_MASK),
|
||||
REGMAP_IRQ_REG(BD73800_INT_BUCK8_OCP, 2, BD73800_INT_BUCK8_OCP_MASK),
|
||||
|
||||
/* INT_STAT_4 IRQs, power-button, WDG and reset */
|
||||
REGMAP_IRQ_REG(BD73800_INT_PBTN_LONG_PRESS, 3, BD73800_INT_PBTN_LONG_PRESS_MASK),
|
||||
REGMAP_IRQ_REG(BD73800_INT_PBTN_MID_PRESS, 3, BD73800_INT_PBTN_MID_PRESS_MASK),
|
||||
/*
|
||||
* The SHORT_PUSH is generated when button is first pressed (longer
|
||||
* than configured time limit), and then released before the MID_PRESS
|
||||
* time limit. The SHORT_PRESS is generated immediately when button is
|
||||
* pressed for longer than configured limit, whether it is released or
|
||||
* not.
|
||||
*/
|
||||
REGMAP_IRQ_REG(BD73800_INT_PBTN_SHORT_PUSH, 3, BD73800_INT_PBTN_SHORT_PUSH_MASK),
|
||||
REGMAP_IRQ_REG(BD73800_INT_PBTN_SHORT_PRESS, 3, BD73800_INT_PBTN_SHORT_PRESS_MASK),
|
||||
REGMAP_IRQ_REG(BD73800_INT_WDG, 3, BD73800_INT_WDG_MASK),
|
||||
REGMAP_IRQ_REG(BD73800_INT_SWRESET, 3, BD73800_INT_SWRESET_MASK),
|
||||
REGMAP_IRQ_REG(BD73800_INT_SEQ_DONE, 3, BD73800_INT_SEQ_DONE_MASK),
|
||||
|
||||
/* INT_STAT_5 IRQs, GPIO */
|
||||
REGMAP_IRQ_REG(BD73800_INT_GPIO1, 4, BD73800_INT_GPIO1_MASK),
|
||||
REGMAP_IRQ_REG(BD73800_INT_GPIO2, 4, BD73800_INT_GPIO2_MASK),
|
||||
REGMAP_IRQ_REG(BD73800_INT_GPIO3, 4, BD73800_INT_GPIO3_MASK),
|
||||
REGMAP_IRQ_REG(BD73800_INT_GPIO4, 4, BD73800_INT_GPIO4_MASK),
|
||||
};
|
||||
|
||||
static const struct regmap_irq_chip bd71828_irq_chip = {
|
||||
.name = "bd71828_irq",
|
||||
.main_status = BD71828_REG_INT_MAIN,
|
||||
|
|
@ -833,6 +943,25 @@ static const struct regmap_irq_chip bd72720_irq_chip = {
|
|||
.irq_reg_stride = 1,
|
||||
};
|
||||
|
||||
static const struct regmap_irq_chip bd73800_irq_chip = {
|
||||
.name = "bd73800_irq",
|
||||
.main_status = BD73800_REG_INT_MAIN_STAT,
|
||||
.irqs = bd73800_irqs,
|
||||
.num_irqs = ARRAY_SIZE(bd73800_irqs),
|
||||
.status_base = BD73800_REG_INT_1_STAT,
|
||||
.unmask_base = BD73800_REG_INT_1_EN,
|
||||
.ack_base = BD73800_REG_INT_1_STAT,
|
||||
.init_ack_masked = true,
|
||||
.num_regs = 5,
|
||||
.num_main_regs = 1,
|
||||
/*
|
||||
* Ignore mirrored bits [7:5]. They are handled as part of normal INT_4
|
||||
* handling.
|
||||
*/
|
||||
.num_main_status_bits = 5,
|
||||
.irq_reg_stride = 1,
|
||||
};
|
||||
|
||||
static int set_clk_mode(struct device *dev, struct regmap *regmap,
|
||||
int clkmode_reg)
|
||||
{
|
||||
|
|
@ -971,6 +1100,17 @@ static int bd71828_i2c_probe(struct i2c_client *i2c)
|
|||
main_lvl_val = BD72720_MASK_LVL1_EN_ALL;
|
||||
break;
|
||||
}
|
||||
case ROHM_CHIP_TYPE_BD73800:
|
||||
mfd = bd73800_mfd_cells;
|
||||
cells = ARRAY_SIZE(bd73800_mfd_cells);
|
||||
regmap_config = &bd73800_regmap;
|
||||
irqchip = &bd73800_irq_chip;
|
||||
clkmode_reg = BD73800_REG_OUT32K;
|
||||
button_irq = BD73800_INT_PBTN_SHORT_PUSH;
|
||||
main_lvl_mask_reg = BD73800_REG_INT_MAIN_EN;
|
||||
main_lvl_val = BD73800_INT_MAIN_EN_ALL;
|
||||
break;
|
||||
|
||||
default:
|
||||
dev_err(&i2c->dev, "Unknown device type");
|
||||
return -EINVAL;
|
||||
|
|
@ -1051,6 +1191,9 @@ static const struct of_device_id bd71828_of_match[] = {
|
|||
}, {
|
||||
.compatible = "rohm,bd72720",
|
||||
.data = (void *)ROHM_CHIP_TYPE_BD72720,
|
||||
}, {
|
||||
.compatible = "rohm,bd73800",
|
||||
.data = (void *)ROHM_CHIP_TYPE_BD73800,
|
||||
},
|
||||
{ },
|
||||
};
|
||||
|
|
|
|||
|
|
@ -241,12 +241,12 @@ config REGULATOR_BD71815
|
|||
will be called bd71815-regulator.
|
||||
|
||||
config REGULATOR_BD71828
|
||||
tristate "ROHM BD71828, BD72720 and BD73900 Power Regulators"
|
||||
tristate "ROHM BD71828, BD72720 and BD73[8/9]00 Power Regulators"
|
||||
depends on MFD_ROHM_BD71828
|
||||
select REGULATOR_ROHM
|
||||
help
|
||||
This driver supports voltage regulators on ROHM BD71828,
|
||||
BD71879, BD72720 and BD73900 PMICs. This will enable
|
||||
BD71879, BD72720 and BD73[8/9]00 PMICs. This will enable
|
||||
support for the software controllable buck and LDO regulators.
|
||||
|
||||
This driver can also be built as a module. If so, the module
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
// Copyright (C) 2019 ROHM Semiconductors
|
||||
// bd71828-regulator.c ROHM BD71828GW-DS1 regulator driver
|
||||
//
|
||||
|
||||
#include <linux/cleanup.h>
|
||||
#include <linux/delay.h>
|
||||
|
|
@ -10,6 +9,7 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/mfd/rohm-bd71828.h>
|
||||
#include <linux/mfd/rohm-bd72720.h>
|
||||
#include <linux/mfd/rohm-bd73800.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
|
@ -31,6 +31,13 @@ struct bd71828_regulator_data {
|
|||
int reg_init_amnt;
|
||||
};
|
||||
|
||||
/*
|
||||
* LDO1 and LDO3 node names are used also in the driver to find OTP setting for
|
||||
* the used voltage range.
|
||||
*/
|
||||
#define LDO1_NODE_NAME "ldo1"
|
||||
#define LDO3_NODE_NAME "ldo3"
|
||||
|
||||
static const struct reg_init bd71828_buck1_inits[] = {
|
||||
/*
|
||||
* DVS Buck voltages can be changed by register values or via GPIO.
|
||||
|
|
@ -172,6 +179,55 @@ static const struct linear_range bd72720_ldo6_volts[] = {
|
|||
REGULATOR_LINEAR_RANGE(1800000, 0x79, 0x7f, 0),
|
||||
};
|
||||
|
||||
static const struct linear_range bd73800_buck12348_volts[] = {
|
||||
REGULATOR_LINEAR_RANGE(500000, 0x00, 0x50, 10000),
|
||||
REGULATOR_LINEAR_RANGE(1300000, 0x51, 0xff, 0),
|
||||
};
|
||||
|
||||
static const unsigned int bd73800_buck5_volt_range_sel[] = {
|
||||
0x0, 0x0, 0x1, 0x1,
|
||||
};
|
||||
|
||||
static const struct linear_range bd73800_buck5_volts[] = {
|
||||
/* range selector 0 */
|
||||
REGULATOR_LINEAR_RANGE(500000, 0x00, 0x50, 10000),
|
||||
REGULATOR_LINEAR_RANGE(1300000, 0x51, 0x7f, 0),
|
||||
/* range selector 1 */
|
||||
REGULATOR_LINEAR_RANGE(300000, 0x00, 0x46, 10000),
|
||||
REGULATOR_LINEAR_RANGE(1000000, 0x47, 0x7f, 0),
|
||||
};
|
||||
|
||||
/*
|
||||
* BUCK5 has two different pickable ranges, each having voltages matching
|
||||
* selectors 0x0 to 0x7f. This gives 0x7f + 1 different voltages for each of
|
||||
* the ranges.
|
||||
*/
|
||||
#define BD73800_NUM_BUCK5_VOLTS ((0x7f + 1) * 2)
|
||||
|
||||
static const struct linear_range bd73800_buck67_volts[] = {
|
||||
REGULATOR_LINEAR_RANGE(1500000, 0x00, 0xc8, 10000),
|
||||
REGULATOR_LINEAR_RANGE(3500000, 0xc9, 0xff, 0),
|
||||
};
|
||||
|
||||
/*
|
||||
* On the BD73800 the LDO1 and LDO3 support two different voltage areas.
|
||||
* Whether to use 'high' or 'low' ranges is configured by OTP. There seems
|
||||
* to be no register to read the configured area so it must be given via
|
||||
* device-tree properties.
|
||||
*/
|
||||
static const struct linear_range bd73800_ldo13_low_volts[] = {
|
||||
REGULATOR_LINEAR_RANGE(600000, 0x00, 0x78, 10000),
|
||||
REGULATOR_LINEAR_RANGE(1800000, 0x79, 0xff, 0),
|
||||
};
|
||||
|
||||
static const struct linear_range bd73800_ldo13_high_volts[] = {
|
||||
REGULATOR_LINEAR_RANGE(750000, 0x00, 0xff, 10000),
|
||||
};
|
||||
|
||||
static const struct linear_range bd73800_ldo24_volts[] = {
|
||||
REGULATOR_LINEAR_RANGE(750000, 0x00, 0xff, 10000),
|
||||
};
|
||||
|
||||
static const unsigned int bd71828_ramp_delay[] = { 2500, 5000, 10000, 20000 };
|
||||
|
||||
/*
|
||||
|
|
@ -225,6 +281,36 @@ static int bd71828_ldo6_parse_dt(struct device_node *np,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Operations for all other BUCKs but BUCK 5 */
|
||||
static const struct regulator_ops bd73800_buck_ops = {
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
.list_voltage = regulator_list_voltage_linear_range,
|
||||
.set_voltage_sel = regulator_set_voltage_sel_regmap,
|
||||
.get_voltage_sel = regulator_get_voltage_sel_regmap,
|
||||
.set_ramp_delay = regulator_set_ramp_delay_regmap,
|
||||
};
|
||||
|
||||
static const struct regulator_ops bd73800_buck5_ops = {
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
.list_voltage = regulator_list_voltage_pickable_linear_range,
|
||||
.set_voltage_sel = regulator_set_voltage_sel_pickable_regmap,
|
||||
.get_voltage_sel = regulator_get_voltage_sel_pickable_regmap,
|
||||
.set_ramp_delay = regulator_set_ramp_delay_regmap,
|
||||
};
|
||||
|
||||
static const struct regulator_ops bd73800_ldo_ops = {
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
.list_voltage = regulator_list_voltage_linear_range,
|
||||
.set_voltage_sel = regulator_set_voltage_sel_regmap,
|
||||
.get_voltage_sel = regulator_get_voltage_sel_regmap,
|
||||
};
|
||||
|
||||
static const struct regulator_ops bd71828_buck_ops = {
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
|
|
@ -1565,6 +1651,412 @@ static const struct bd71828_regulator_data bd72720_rdata[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static const struct bd71828_regulator_data bd73800_rdata[] = {
|
||||
{
|
||||
.desc = {
|
||||
.name = "buck1",
|
||||
.of_match = of_match_ptr("buck1"),
|
||||
.regulators_node = of_match_ptr("regulators"),
|
||||
.id = BD73800_BUCK1,
|
||||
.ops = &bd73800_buck_ops,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.linear_ranges = bd73800_buck12348_volts,
|
||||
.n_linear_ranges = ARRAY_SIZE(bd73800_buck12348_volts),
|
||||
.n_voltages = BD73800_NUM_VOLTS,
|
||||
.enable_reg = BD73800_REG_BUCK1_ON,
|
||||
.enable_mask = BD73800_MASK_RUN_EN,
|
||||
.vsel_reg = BD73800_REG_BUCK1_VOLT_RUN,
|
||||
.vsel_mask = BD73800_MASK_VOLT,
|
||||
.ramp_delay_table = bd71828_ramp_delay,
|
||||
.n_ramp_values = ARRAY_SIZE(bd71828_ramp_delay),
|
||||
.ramp_reg = BD73800_REG_BUCK1_MODE,
|
||||
.ramp_mask = BD73800_MASK_RAMP_DELAY,
|
||||
.owner = THIS_MODULE,
|
||||
.of_parse_cb = buck_set_hw_dvs_levels,
|
||||
},
|
||||
.dvs = {
|
||||
.level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE |
|
||||
ROHM_DVS_LEVEL_SUSPEND,
|
||||
.run_reg = BD73800_REG_BUCK1_VOLT_RUN,
|
||||
.run_mask = BD73800_MASK_VOLT,
|
||||
.idle_reg = BD73800_REG_BUCK1_VOLT_IDLE,
|
||||
.idle_mask = BD73800_MASK_VOLT,
|
||||
.idle_on_mask = BD73800_MASK_IDLE_EN,
|
||||
.suspend_reg = BD73800_REG_BUCK1_VOLT_SUSP,
|
||||
.suspend_mask = BD73800_MASK_VOLT,
|
||||
.suspend_on_mask = BD73800_MASK_SUSP_EN,
|
||||
},
|
||||
}, {
|
||||
.desc = {
|
||||
.name = "buck2",
|
||||
.of_match = of_match_ptr("buck2"),
|
||||
.regulators_node = of_match_ptr("regulators"),
|
||||
.id = BD73800_BUCK2,
|
||||
.ops = &bd73800_buck_ops,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.linear_ranges = bd73800_buck12348_volts,
|
||||
.n_linear_ranges = ARRAY_SIZE(bd73800_buck12348_volts),
|
||||
.n_voltages = BD73800_NUM_VOLTS,
|
||||
.enable_reg = BD73800_REG_BUCK2_ON,
|
||||
.enable_mask = BD73800_MASK_RUN_EN,
|
||||
.vsel_reg = BD73800_REG_BUCK2_VOLT_RUN,
|
||||
.vsel_mask = BD73800_MASK_VOLT,
|
||||
.ramp_delay_table = bd71828_ramp_delay,
|
||||
.n_ramp_values = ARRAY_SIZE(bd71828_ramp_delay),
|
||||
.ramp_reg = BD73800_REG_BUCK2_MODE,
|
||||
.ramp_mask = BD73800_MASK_RAMP_DELAY,
|
||||
.owner = THIS_MODULE,
|
||||
.of_parse_cb = buck_set_hw_dvs_levels,
|
||||
},
|
||||
.dvs = {
|
||||
.level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE |
|
||||
ROHM_DVS_LEVEL_SUSPEND,
|
||||
.run_reg = BD73800_REG_BUCK2_VOLT_RUN,
|
||||
.run_mask = BD73800_MASK_VOLT,
|
||||
.idle_reg = BD73800_REG_BUCK2_VOLT_IDLE,
|
||||
.idle_mask = BD73800_MASK_VOLT,
|
||||
.idle_on_mask = BD73800_MASK_IDLE_EN,
|
||||
.suspend_reg = BD73800_REG_BUCK2_VOLT_SUSP,
|
||||
.suspend_mask = BD73800_MASK_VOLT,
|
||||
.suspend_on_mask = BD73800_MASK_SUSP_EN,
|
||||
},
|
||||
}, {
|
||||
.desc = {
|
||||
.name = "buck3",
|
||||
.of_match = of_match_ptr("buck3"),
|
||||
.regulators_node = of_match_ptr("regulators"),
|
||||
.id = BD73800_BUCK3,
|
||||
.ops = &bd73800_buck_ops,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.linear_ranges = bd73800_buck12348_volts,
|
||||
.n_linear_ranges = ARRAY_SIZE(bd73800_buck12348_volts),
|
||||
.n_voltages = BD73800_NUM_VOLTS,
|
||||
.enable_reg = BD73800_REG_BUCK3_ON,
|
||||
.enable_mask = BD73800_MASK_RUN_EN,
|
||||
.vsel_reg = BD73800_REG_BUCK3_VOLT_RUN,
|
||||
.vsel_mask = BD73800_MASK_VOLT,
|
||||
.ramp_delay_table = bd71828_ramp_delay,
|
||||
.n_ramp_values = ARRAY_SIZE(bd71828_ramp_delay),
|
||||
.ramp_reg = BD73800_REG_BUCK3_MODE,
|
||||
.ramp_mask = BD73800_MASK_RAMP_DELAY,
|
||||
.owner = THIS_MODULE,
|
||||
.of_parse_cb = buck_set_hw_dvs_levels,
|
||||
},
|
||||
.dvs = {
|
||||
.level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE |
|
||||
ROHM_DVS_LEVEL_SUSPEND,
|
||||
.run_reg = BD73800_REG_BUCK3_VOLT_RUN,
|
||||
.run_mask = BD73800_MASK_VOLT,
|
||||
.idle_reg = BD73800_REG_BUCK3_VOLT_IDLE,
|
||||
.idle_mask = BD73800_MASK_VOLT,
|
||||
.idle_on_mask = BD73800_MASK_IDLE_EN,
|
||||
.suspend_reg = BD73800_REG_BUCK3_VOLT_SUSP,
|
||||
.suspend_mask = BD73800_MASK_VOLT,
|
||||
.suspend_on_mask = BD73800_MASK_SUSP_EN,
|
||||
},
|
||||
|
||||
}, {
|
||||
.desc = {
|
||||
.name = "buck4",
|
||||
.of_match = of_match_ptr("buck4"),
|
||||
.regulators_node = of_match_ptr("regulators"),
|
||||
.id = BD73800_BUCK4,
|
||||
.ops = &bd73800_buck_ops,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.linear_ranges = bd73800_buck12348_volts,
|
||||
.n_linear_ranges = ARRAY_SIZE(bd73800_buck12348_volts),
|
||||
.n_voltages = BD73800_NUM_VOLTS,
|
||||
.enable_reg = BD73800_REG_BUCK4_ON,
|
||||
.enable_mask = BD73800_MASK_RUN_EN,
|
||||
.vsel_reg = BD73800_REG_BUCK4_VOLT_RUN,
|
||||
.vsel_mask = BD73800_MASK_VOLT,
|
||||
.ramp_delay_table = bd71828_ramp_delay,
|
||||
.n_ramp_values = ARRAY_SIZE(bd71828_ramp_delay),
|
||||
.ramp_reg = BD73800_REG_BUCK4_MODE,
|
||||
.ramp_mask = BD73800_MASK_RAMP_DELAY,
|
||||
.owner = THIS_MODULE,
|
||||
.of_parse_cb = buck_set_hw_dvs_levels,
|
||||
},
|
||||
.dvs = {
|
||||
.level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE |
|
||||
ROHM_DVS_LEVEL_SUSPEND,
|
||||
.run_reg = BD73800_REG_BUCK4_VOLT_RUN,
|
||||
.run_mask = BD73800_MASK_VOLT,
|
||||
.idle_reg = BD73800_REG_BUCK4_VOLT_IDLE,
|
||||
.idle_mask = BD73800_MASK_VOLT,
|
||||
.idle_on_mask = BD73800_MASK_IDLE_EN,
|
||||
.suspend_reg = BD73800_REG_BUCK4_VOLT_SUSP,
|
||||
.suspend_mask = BD73800_MASK_VOLT,
|
||||
.suspend_on_mask = BD73800_MASK_SUSP_EN,
|
||||
},
|
||||
}, {
|
||||
.desc = {
|
||||
.name = "buck5",
|
||||
.of_match = of_match_ptr("buck5"),
|
||||
.regulators_node = of_match_ptr("regulators"),
|
||||
.id = BD73800_BUCK5,
|
||||
.ops = &bd73800_buck5_ops,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.linear_ranges = bd73800_buck5_volts,
|
||||
.n_linear_ranges = ARRAY_SIZE(bd73800_buck5_volts),
|
||||
.linear_range_selectors_bitfield =
|
||||
bd73800_buck5_volt_range_sel,
|
||||
.n_voltages = BD73800_NUM_BUCK5_VOLTS,
|
||||
.enable_reg = BD73800_REG_BUCK5_ON,
|
||||
.enable_mask = BD73800_MASK_RUN_EN,
|
||||
.vsel_reg = BD73800_REG_BUCK5_VOLT_RUN,
|
||||
.vsel_mask = BD73800_MASK_BUCK5_VOLT,
|
||||
.vsel_range_reg = BD73800_REG_BUCK5_MODE,
|
||||
.vsel_range_mask = BD73800_BUCK5_RANGE_MASK,
|
||||
.range_applied_by_vsel = true,
|
||||
.ramp_delay_table = bd71828_ramp_delay,
|
||||
.n_ramp_values = ARRAY_SIZE(bd71828_ramp_delay),
|
||||
.ramp_reg = BD73800_REG_BUCK5_MODE,
|
||||
.ramp_mask = BD73800_MASK_RAMP_DELAY,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.dvs = {
|
||||
/*
|
||||
* We don't support setting the IDLE / SUSPEND voltages
|
||||
* for the BUCK 5 for now. Reason is that the pickable
|
||||
* range selector bit is common for all states (RUN,
|
||||
* SUSPEND and IDLE), and toggling it for one impacts
|
||||
* also others.
|
||||
* Furthermore, writing the BD73800 range selector does
|
||||
* not impact the RUN voltage until a new voltage value
|
||||
* is also written to the vsel register. Hence the
|
||||
* voltage change can be done without any 'intermediate
|
||||
* voltages', even when the range is changed when the
|
||||
* BUCK is enabled.
|
||||
* It, however, is not documented how the IDLE / SUSPEND
|
||||
* states work in this regard. I expect the full
|
||||
* combination of the range selector and vsel is taken
|
||||
* into account at the state change, no matter when they
|
||||
* have been written to.
|
||||
*/
|
||||
.level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE |
|
||||
ROHM_DVS_LEVEL_SUSPEND,
|
||||
.run_reg = BD73800_REG_BUCK5_VOLT_RUN,
|
||||
.run_mask = BD73800_MASK_VOLT,
|
||||
.idle_on_mask = BD73800_MASK_IDLE_EN,
|
||||
.suspend_on_mask = BD73800_MASK_SUSP_EN,
|
||||
},
|
||||
|
||||
}, {
|
||||
.desc = {
|
||||
.name = "buck6",
|
||||
.of_match = of_match_ptr("buck6"),
|
||||
.regulators_node = of_match_ptr("regulators"),
|
||||
.id = BD73800_BUCK6,
|
||||
.ops = &bd73800_buck_ops,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.linear_ranges = bd73800_buck67_volts,
|
||||
.n_linear_ranges = ARRAY_SIZE(bd73800_buck67_volts),
|
||||
.n_voltages = BD73800_NUM_VOLTS,
|
||||
.enable_reg = BD73800_REG_BUCK6_ON,
|
||||
.enable_mask = BD73800_MASK_RUN_EN,
|
||||
.vsel_reg = BD73800_REG_BUCK6_VOLT_RUN,
|
||||
.vsel_mask = BD73800_MASK_VOLT,
|
||||
.ramp_delay_table = bd71828_ramp_delay,
|
||||
.n_ramp_values = ARRAY_SIZE(bd71828_ramp_delay),
|
||||
.ramp_reg = BD73800_REG_BUCK6_MODE,
|
||||
.ramp_mask = BD73800_MASK_RAMP_DELAY,
|
||||
.owner = THIS_MODULE,
|
||||
.of_parse_cb = buck_set_hw_dvs_levels,
|
||||
},
|
||||
.dvs = {
|
||||
.level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE |
|
||||
ROHM_DVS_LEVEL_SUSPEND,
|
||||
.run_reg = BD73800_REG_BUCK6_VOLT_RUN,
|
||||
.run_mask = BD73800_MASK_VOLT,
|
||||
.idle_reg = BD73800_REG_BUCK6_VOLT_IDLE,
|
||||
.idle_mask = BD73800_MASK_VOLT,
|
||||
.idle_on_mask = BD73800_MASK_IDLE_EN,
|
||||
.suspend_reg = BD73800_REG_BUCK6_VOLT_SUSP,
|
||||
.suspend_mask = BD73800_MASK_VOLT,
|
||||
.suspend_on_mask = BD73800_MASK_SUSP_EN,
|
||||
},
|
||||
}, {
|
||||
.desc = {
|
||||
.name = "buck7",
|
||||
.of_match = of_match_ptr("buck7"),
|
||||
.regulators_node = of_match_ptr("regulators"),
|
||||
.id = BD73800_BUCK7,
|
||||
.ops = &bd73800_buck_ops,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.linear_ranges = bd73800_buck67_volts,
|
||||
.n_linear_ranges = ARRAY_SIZE(bd73800_buck67_volts),
|
||||
.n_voltages = BD73800_NUM_VOLTS,
|
||||
.enable_reg = BD73800_REG_BUCK7_ON,
|
||||
.enable_mask = BD73800_MASK_RUN_EN,
|
||||
.vsel_reg = BD73800_REG_BUCK7_VOLT_RUN,
|
||||
.vsel_mask = BD73800_MASK_VOLT,
|
||||
.ramp_delay_table = bd71828_ramp_delay,
|
||||
.n_ramp_values = ARRAY_SIZE(bd71828_ramp_delay),
|
||||
.ramp_reg = BD73800_REG_BUCK7_MODE,
|
||||
.ramp_mask = BD73800_MASK_RAMP_DELAY,
|
||||
.owner = THIS_MODULE,
|
||||
.of_parse_cb = buck_set_hw_dvs_levels,
|
||||
},
|
||||
.dvs = {
|
||||
.level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE |
|
||||
ROHM_DVS_LEVEL_SUSPEND,
|
||||
.run_reg = BD73800_REG_BUCK7_VOLT_RUN,
|
||||
.run_mask = BD73800_MASK_VOLT,
|
||||
.idle_reg = BD73800_REG_BUCK7_VOLT_IDLE,
|
||||
.idle_mask = BD73800_MASK_VOLT,
|
||||
.idle_on_mask = BD73800_MASK_IDLE_EN,
|
||||
.suspend_reg = BD73800_REG_BUCK7_VOLT_SUSP,
|
||||
.suspend_mask = BD73800_MASK_VOLT,
|
||||
.suspend_on_mask = BD73800_MASK_SUSP_EN,
|
||||
},
|
||||
}, {
|
||||
.desc = {
|
||||
.name = "buck8",
|
||||
.of_match = of_match_ptr("buck8"),
|
||||
.regulators_node = of_match_ptr("regulators"),
|
||||
.id = BD73800_BUCK8,
|
||||
.ops = &bd73800_buck_ops,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.linear_ranges = bd73800_buck12348_volts,
|
||||
.n_linear_ranges = ARRAY_SIZE(bd73800_buck12348_volts),
|
||||
.n_voltages = BD73800_NUM_VOLTS,
|
||||
.enable_reg = BD73800_REG_BUCK8_ON,
|
||||
.enable_mask = BD73800_MASK_RUN_EN,
|
||||
.vsel_reg = BD73800_REG_BUCK8_VOLT_RUN,
|
||||
.vsel_mask = BD73800_MASK_VOLT,
|
||||
.ramp_delay_table = bd71828_ramp_delay,
|
||||
.n_ramp_values = ARRAY_SIZE(bd71828_ramp_delay),
|
||||
.ramp_reg = BD73800_REG_BUCK8_MODE,
|
||||
.ramp_mask = BD73800_MASK_RAMP_DELAY,
|
||||
.owner = THIS_MODULE,
|
||||
.of_parse_cb = buck_set_hw_dvs_levels,
|
||||
},
|
||||
.dvs = {
|
||||
.level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE |
|
||||
ROHM_DVS_LEVEL_SUSPEND,
|
||||
.run_reg = BD73800_REG_BUCK8_VOLT_RUN,
|
||||
.run_mask = BD73800_MASK_VOLT,
|
||||
.idle_reg = BD73800_REG_BUCK8_VOLT_IDLE,
|
||||
.idle_mask = BD73800_MASK_VOLT,
|
||||
.idle_on_mask = BD73800_MASK_IDLE_EN,
|
||||
.suspend_reg = BD73800_REG_BUCK8_VOLT_SUSP,
|
||||
.suspend_mask = BD73800_MASK_VOLT,
|
||||
.suspend_on_mask = BD73800_MASK_SUSP_EN,
|
||||
},
|
||||
}, {
|
||||
.desc = {
|
||||
.name = "ldo1",
|
||||
.of_match = of_match_ptr(LDO1_NODE_NAME),
|
||||
.regulators_node = of_match_ptr("regulators"),
|
||||
.id = BD73800_LDO1,
|
||||
.ops = &bd73800_ldo_ops,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.linear_ranges = bd73800_ldo13_low_volts,
|
||||
.n_linear_ranges = ARRAY_SIZE(bd73800_ldo13_low_volts),
|
||||
.n_voltages = BD73800_NUM_VOLTS,
|
||||
.enable_reg = BD73800_REG_LDO1_ON,
|
||||
.enable_mask = BD73800_MASK_RUN_EN,
|
||||
.vsel_reg = BD73800_REG_LDO1_VOLT,
|
||||
.vsel_mask = BD73800_MASK_VOLT,
|
||||
.owner = THIS_MODULE,
|
||||
.of_parse_cb = buck_set_hw_dvs_levels,
|
||||
},
|
||||
.dvs = {
|
||||
/*
|
||||
* LDOs support only single voltage for all states.
|
||||
* Voltage can be individually enabled for each state
|
||||
* though. Allow setting enable/disable config by
|
||||
* setting the <state>_on_mask for all supported states.
|
||||
*/
|
||||
.level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE |
|
||||
ROHM_DVS_LEVEL_SUSPEND,
|
||||
.run_reg = BD73800_REG_LDO1_VOLT,
|
||||
.run_mask = BD73800_MASK_VOLT,
|
||||
.idle_on_mask = BD73800_MASK_IDLE_EN,
|
||||
.suspend_on_mask = BD73800_MASK_SUSP_EN,
|
||||
},
|
||||
}, {
|
||||
.desc = {
|
||||
.name = "ldo2",
|
||||
.of_match = of_match_ptr("ldo2"),
|
||||
.regulators_node = of_match_ptr("regulators"),
|
||||
.id = BD73800_LDO2,
|
||||
.ops = &bd73800_ldo_ops,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.linear_ranges = bd73800_ldo24_volts,
|
||||
.n_linear_ranges = ARRAY_SIZE(bd73800_ldo24_volts),
|
||||
.n_voltages = BD73800_NUM_VOLTS,
|
||||
.enable_reg = BD73800_REG_LDO2_ON,
|
||||
.enable_mask = BD73800_MASK_RUN_EN,
|
||||
.vsel_reg = BD73800_REG_LDO2_VOLT,
|
||||
.vsel_mask = BD73800_MASK_VOLT,
|
||||
.owner = THIS_MODULE,
|
||||
.of_parse_cb = buck_set_hw_dvs_levels,
|
||||
},
|
||||
.dvs = {
|
||||
.level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE |
|
||||
ROHM_DVS_LEVEL_SUSPEND,
|
||||
.run_reg = BD73800_REG_LDO2_VOLT,
|
||||
.run_mask = BD73800_MASK_VOLT,
|
||||
.idle_on_mask = BD73800_MASK_IDLE_EN,
|
||||
.suspend_on_mask = BD73800_MASK_SUSP_EN,
|
||||
},
|
||||
}, {
|
||||
.desc = {
|
||||
.name = "ldo3",
|
||||
.of_match = of_match_ptr(LDO3_NODE_NAME),
|
||||
.regulators_node = of_match_ptr("regulators"),
|
||||
.id = BD73800_LDO3,
|
||||
.ops = &bd73800_ldo_ops,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.linear_ranges = bd73800_ldo13_low_volts,
|
||||
.n_linear_ranges = ARRAY_SIZE(bd73800_ldo13_low_volts),
|
||||
.n_voltages = BD73800_NUM_VOLTS,
|
||||
.enable_reg = BD73800_REG_LDO3_ON,
|
||||
.enable_mask = BD73800_MASK_RUN_EN,
|
||||
.vsel_reg = BD73800_REG_LDO3_VOLT,
|
||||
.vsel_mask = BD73800_MASK_VOLT,
|
||||
.owner = THIS_MODULE,
|
||||
.of_parse_cb = buck_set_hw_dvs_levels,
|
||||
},
|
||||
.dvs = {
|
||||
.level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE |
|
||||
ROHM_DVS_LEVEL_SUSPEND,
|
||||
.run_reg = BD73800_REG_LDO3_VOLT,
|
||||
.run_mask = BD73800_MASK_VOLT,
|
||||
.idle_on_mask = BD73800_MASK_IDLE_EN,
|
||||
.suspend_on_mask = BD73800_MASK_SUSP_EN,
|
||||
},
|
||||
}, {
|
||||
.desc = {
|
||||
.name = "ldo4",
|
||||
.of_match = of_match_ptr("ldo4"),
|
||||
.regulators_node = of_match_ptr("regulators"),
|
||||
.id = BD73800_LDO4,
|
||||
.ops = &bd73800_ldo_ops,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.linear_ranges = bd73800_ldo24_volts,
|
||||
.n_linear_ranges = ARRAY_SIZE(bd73800_ldo24_volts),
|
||||
.n_voltages = BD73800_NUM_VOLTS,
|
||||
.enable_reg = BD73800_REG_LDO4_ON,
|
||||
.enable_mask = BD73800_MASK_RUN_EN,
|
||||
.vsel_reg = BD73800_REG_LDO4_VOLT,
|
||||
.vsel_mask = BD73800_MASK_VOLT,
|
||||
.owner = THIS_MODULE,
|
||||
.of_parse_cb = buck_set_hw_dvs_levels,
|
||||
},
|
||||
.dvs = {
|
||||
.level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE |
|
||||
ROHM_DVS_LEVEL_SUSPEND,
|
||||
.run_reg = BD73800_REG_LDO4_VOLT,
|
||||
.run_mask = BD73800_MASK_VOLT,
|
||||
.idle_on_mask = BD73800_MASK_IDLE_EN,
|
||||
.suspend_on_mask = BD73800_MASK_SUSP_EN,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
static int bd72720_buck10_ldon_head_mode(struct device *dev,
|
||||
struct device_node *npreg,
|
||||
struct regmap *regmap,
|
||||
|
|
@ -1619,6 +2111,52 @@ static int bd72720_dt_parse(struct device *dev,
|
|||
return bd72720_buck10_ldon_head_mode(dev, nproot, regmap, buck10_desc);
|
||||
}
|
||||
|
||||
static bool bd73800_use_ldo_high_range(struct device_node *nproot,
|
||||
const char *ldo_node)
|
||||
{
|
||||
struct device_node *np __free(device_node) =
|
||||
of_get_child_by_name(nproot, ldo_node);
|
||||
|
||||
if (!np)
|
||||
return false;
|
||||
|
||||
return of_property_read_bool(np, "rohm,ldo-range-high");
|
||||
}
|
||||
|
||||
static int bd73800_check_ldo_otp_options(struct device *dev,
|
||||
struct bd71828_regulator_data *d,
|
||||
unsigned int num_reg_data)
|
||||
{
|
||||
struct device_node *nproot __free(device_node) =
|
||||
of_get_child_by_name(dev->parent->of_node, "regulators");
|
||||
|
||||
/*
|
||||
* The code assumes regulator IDs to start from 0 and to match the
|
||||
* indexing of regulator data arrays. WARN if someone changes this.
|
||||
*/
|
||||
WARN_ON(d[BD73800_LDO1].desc.id != BD73800_LDO1);
|
||||
WARN_ON(d[BD73800_LDO3].desc.id != BD73800_LDO3);
|
||||
|
||||
if (!nproot) {
|
||||
dev_err(dev, "failed to find regulators node\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (bd73800_use_ldo_high_range(nproot, LDO1_NODE_NAME)) {
|
||||
d[BD73800_LDO1].desc.linear_ranges = bd73800_ldo13_high_volts;
|
||||
d[BD73800_LDO1].desc.n_linear_ranges =
|
||||
ARRAY_SIZE(bd73800_ldo13_high_volts);
|
||||
}
|
||||
|
||||
if (bd73800_use_ldo_high_range(nproot, LDO3_NODE_NAME)) {
|
||||
d[BD73800_LDO3].desc.linear_ranges = bd73800_ldo13_high_volts;
|
||||
d[BD73800_LDO3].desc.n_linear_ranges =
|
||||
ARRAY_SIZE(bd73800_ldo13_high_volts);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bd71828_probe(struct platform_device *pdev)
|
||||
{
|
||||
int i, j, ret, num_regulators;
|
||||
|
|
@ -1656,6 +2194,23 @@ static int bd71828_probe(struct platform_device *pdev)
|
|||
num_regulators = ARRAY_SIZE(bd71828_rdata);
|
||||
|
||||
break;
|
||||
|
||||
case ROHM_CHIP_TYPE_BD73800:
|
||||
{
|
||||
rdata = devm_kmemdup(&pdev->dev, bd73800_rdata,
|
||||
sizeof(bd73800_rdata), GFP_KERNEL);
|
||||
if (!rdata)
|
||||
return -ENOMEM;
|
||||
|
||||
num_regulators = ARRAY_SIZE(bd73800_rdata);
|
||||
|
||||
ret = bd73800_check_ldo_otp_options(&pdev->dev, rdata,
|
||||
num_regulators);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return dev_err_probe(&pdev->dev, -EINVAL,
|
||||
"Unsupported device\n");
|
||||
|
|
@ -1692,6 +2247,7 @@ static int bd71828_probe(struct platform_device *pdev)
|
|||
static const struct platform_device_id bd71828_pmic_id[] = {
|
||||
{ .name = "bd71828-pmic", .driver_data = ROHM_CHIP_TYPE_BD71828 },
|
||||
{ .name = "bd72720-pmic", .driver_data = ROHM_CHIP_TYPE_BD72720 },
|
||||
{ .name = "bd73800-pmic", .driver_data = ROHM_CHIP_TYPE_BD73800 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(platform, bd71828_pmic_id);
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
#include <linux/mfd/rohm-bd71815.h>
|
||||
#include <linux/mfd/rohm-bd71828.h>
|
||||
#include <linux/mfd/rohm-bd72720.h>
|
||||
#include <linux/mfd/rohm-bd73800.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
|
@ -284,6 +285,12 @@ static int bd70528_probe(struct platform_device *pdev)
|
|||
bd_rtc->bd718xx_alm_block_start = BD72720_REG_RTC_ALM_START;
|
||||
hour_reg = BD72720_REG_RTC_HOUR;
|
||||
break;
|
||||
case ROHM_CHIP_TYPE_BD73800:
|
||||
bd_rtc->reg_time_start = BD73800_REG_RTC_START;
|
||||
bd_rtc->bd718xx_alm_block_start = BD73800_REG_RTC_ALM_START;
|
||||
hour_reg = BD73800_REG_RTC_HOUR;
|
||||
break;
|
||||
|
||||
default:
|
||||
dev_err(&pdev->dev, "Unknown chip\n");
|
||||
return -ENOENT;
|
||||
|
|
@ -344,6 +351,7 @@ static const struct platform_device_id bd718x7_rtc_id[] = {
|
|||
{ .name = "bd71828-rtc", .driver_data = ROHM_CHIP_TYPE_BD71828 },
|
||||
{ .name = "bd71815-rtc", .driver_data = ROHM_CHIP_TYPE_BD71815 },
|
||||
{ .name = "bd72720-rtc", .driver_data = ROHM_CHIP_TYPE_BD72720 },
|
||||
{ .name = "bd73800-rtc", .driver_data = ROHM_CHIP_TYPE_BD73800 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(platform, bd718x7_rtc_id);
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
306
include/linux/mfd/rohm-bd73800.h
Normal file
306
include/linux/mfd/rohm-bd73800.h
Normal file
|
|
@ -0,0 +1,306 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Copyright 2026 ROHM Semiconductors.
|
||||
*
|
||||
* Author: Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>
|
||||
*/
|
||||
|
||||
#ifndef _MFD_BD73800_H
|
||||
#define _MFD_BD73800_H
|
||||
|
||||
#include <linux/regmap.h>
|
||||
|
||||
enum {
|
||||
BD73800_BUCK1 = 0,
|
||||
BD73800_BUCK2,
|
||||
BD73800_BUCK3,
|
||||
BD73800_BUCK4,
|
||||
BD73800_BUCK5,
|
||||
BD73800_BUCK6,
|
||||
BD73800_BUCK7,
|
||||
BD73800_BUCK8,
|
||||
BD73800_LDO1,
|
||||
BD73800_LDO2,
|
||||
BD73800_LDO3,
|
||||
BD73800_LDO4,
|
||||
};
|
||||
|
||||
/*
|
||||
* All regulators except BUCK 5 have full 8-bit register of valid voltage
|
||||
* values, including 0.
|
||||
*/
|
||||
#define BD73800_NUM_VOLTS (0xff + 1)
|
||||
/*
|
||||
* BUCK 5 has two sets of voltage ranges, both having valid voltage selectors
|
||||
* from 0x0 to 0x7f
|
||||
*/
|
||||
#define BD73800_BUCK5_VOLTS (0x80 + 0x80)
|
||||
|
||||
/* BD73800 interrupts */
|
||||
enum {
|
||||
/* INT_STAT_1 register IRQs, ADC and RTC */
|
||||
BD73800_INT_ADC_ACCUM_DONE,
|
||||
BD73800_INT_ADC_ACCUM_OVF,
|
||||
BD73800_INT_ADC_ACCUM_VAL,
|
||||
BD73800_INT_ADC_ACCUM_TW,
|
||||
BD73800_INT_ADC_POW_VAL,
|
||||
BD73800_INT_RTC0,
|
||||
BD73800_INT_RTC1,
|
||||
BD73800_INT_RTC2,
|
||||
|
||||
/* BUCK reg interrupts */
|
||||
/* INT_STAT_2 IRQs */
|
||||
BD73800_INT_BUCK1_DVS_DONE,
|
||||
BD73800_INT_BUCK2_DVS_DONE,
|
||||
BD73800_INT_BUCK3_DVS_DONE,
|
||||
BD73800_INT_BUCK4_DVS_DONE,
|
||||
BD73800_INT_BUCK5_DVS_DONE,
|
||||
BD73800_INT_BUCK6_DVS_DONE,
|
||||
BD73800_INT_BUCK7_DVS_DONE,
|
||||
BD73800_INT_BUCK8_DVS_DONE,
|
||||
/* INT_STAT_3 IRQs */
|
||||
BD73800_INT_BUCK1_OCP,
|
||||
BD73800_INT_BUCK2_OCP,
|
||||
BD73800_INT_BUCK3_OCP,
|
||||
BD73800_INT_BUCK4_OCP,
|
||||
BD73800_INT_BUCK5_OCP,
|
||||
BD73800_INT_BUCK6_OCP,
|
||||
BD73800_INT_BUCK7_OCP,
|
||||
BD73800_INT_BUCK8_OCP,
|
||||
|
||||
/* INT_STAT_4 IRQs, power-button, WDG and reset */
|
||||
BD73800_INT_PBTN_LONG_PRESS,
|
||||
BD73800_INT_PBTN_MID_PRESS,
|
||||
/*
|
||||
* The SHORT_PUSH is generated when button is first pressed (longer
|
||||
* than configured time limit), and then released before the MID_PRESS
|
||||
* time limit. The SHORT_PRESS is generated immediately when button is
|
||||
* pressed for longer than configured limit, whether it is released or
|
||||
* not.
|
||||
*/
|
||||
BD73800_INT_PBTN_SHORT_PUSH,
|
||||
BD73800_INT_PBTN_SHORT_PRESS,
|
||||
BD73800_INT_WDG,
|
||||
BD73800_INT_SWRESET,
|
||||
BD73800_INT_SEQ_DONE,
|
||||
|
||||
/* INT_STAT_5 IRQs, GPIO */
|
||||
BD73800_INT_GPIO1,
|
||||
BD73800_INT_GPIO2,
|
||||
BD73800_INT_GPIO3,
|
||||
BD73800_INT_GPIO4,
|
||||
};
|
||||
|
||||
#define BD73800_MASK_RUN_EN BIT(2)
|
||||
#define BD73800_MASK_SUSP_EN BIT(1)
|
||||
#define BD73800_MASK_IDLE_EN BIT(0)
|
||||
#define BD73800_MASK_VOLT GENMASK(7, 0)
|
||||
#define BD73800_MASK_BUCK5_VOLT GENMASK(6, 0)
|
||||
#define BD73800_MASK_RAMP_DELAY GENMASK(2, 1)
|
||||
#define BD73800_BUCK5_RANGE_MASK BIT(7)
|
||||
|
||||
/* BD73800 registers */
|
||||
enum {
|
||||
BD73800_REG_PRODUCT_ID = 0x0,
|
||||
BD73800_REG_MANUFACTURER_ID,
|
||||
BD73800_REG_REVISION,
|
||||
BD73800_REG_NVMVERSION,
|
||||
BD73800_REG_POR_REASON,
|
||||
BD73800_REG_RESET_REASON1,
|
||||
BD73800_REG_RESET_REASON2,
|
||||
BD73800_REG_RESET_REASON3,
|
||||
BD73800_REG_POW_STATE,
|
||||
BD73800_REG_WRST_SEL,
|
||||
BD73800_REG_PS_CTRL_1,
|
||||
BD73800_REG_PS_CTRL_2,
|
||||
BD73800_REG_RCVCFG,
|
||||
BD73800_REG_RCVNUM,
|
||||
BD73800_REG_CRDCFG, /* 0x0f, followed by undocumented reg */
|
||||
|
||||
BD73800_REG_BUCK1_ON = 0x11,
|
||||
BD73800_REG_BUCK1_MODE,
|
||||
BD73800_REG_BUCK1_VOLT_RUN,
|
||||
BD73800_REG_BUCK1_VOLT_IDLE,
|
||||
BD73800_REG_BUCK1_VOLT_SUSP, /* 0x15, followed by undocumented reg */
|
||||
|
||||
BD73800_REG_BUCK2_ON = 0x17,
|
||||
BD73800_REG_BUCK2_MODE,
|
||||
BD73800_REG_BUCK2_VOLT_RUN,
|
||||
BD73800_REG_BUCK2_VOLT_IDLE,
|
||||
BD73800_REG_BUCK2_VOLT_SUSP, /* 0x1b */
|
||||
|
||||
BD73800_REG_BUCK3_ON = 0x1d,
|
||||
BD73800_REG_BUCK3_MODE,
|
||||
BD73800_REG_BUCK3_VOLT_RUN,
|
||||
BD73800_REG_BUCK3_VOLT_IDLE,
|
||||
BD73800_REG_BUCK3_VOLT_SUSP, /* 0x21 */
|
||||
|
||||
BD73800_REG_BUCK4_ON = 0x23,
|
||||
BD73800_REG_BUCK4_MODE,
|
||||
BD73800_REG_BUCK4_VOLT_RUN,
|
||||
BD73800_REG_BUCK4_VOLT_IDLE,
|
||||
BD73800_REG_BUCK4_VOLT_SUSP, /* 0x27 */
|
||||
|
||||
BD73800_REG_BUCK5_ON = 0x29,
|
||||
BD73800_REG_BUCK5_MODE,
|
||||
BD73800_REG_BUCK5_VOLT_RUN,
|
||||
BD73800_REG_BUCK5_VOLT_IDLE,
|
||||
BD73800_REG_BUCK5_VOLT_SUSP, /* 0x2d */
|
||||
|
||||
BD73800_REG_BUCK6_ON = 0x2f,
|
||||
BD73800_REG_BUCK6_MODE,
|
||||
BD73800_REG_BUCK6_VOLT_RUN,
|
||||
BD73800_REG_BUCK6_VOLT_IDLE,
|
||||
BD73800_REG_BUCK6_VOLT_SUSP, /* 0x33 */
|
||||
|
||||
BD73800_REG_BUCK7_ON = 0x35,
|
||||
BD73800_REG_BUCK7_MODE,
|
||||
BD73800_REG_BUCK7_VOLT_RUN,
|
||||
BD73800_REG_BUCK7_VOLT_IDLE,
|
||||
BD73800_REG_BUCK7_VOLT_SUSP, /* 0x39 */
|
||||
|
||||
BD73800_REG_BUCK8_ON = 0x3b,
|
||||
BD73800_REG_BUCK8_MODE,
|
||||
BD73800_REG_BUCK8_VOLT_RUN,
|
||||
BD73800_REG_BUCK8_VOLT_IDLE,
|
||||
BD73800_REG_BUCK8_VOLT_SUSP, /* 0x3f */
|
||||
|
||||
BD73800_REG_LDO1_ON = 0x41,
|
||||
BD73800_REG_LDO1_VOLT,
|
||||
BD73800_REG_LDO1_MODE,
|
||||
BD73800_REG_LDO2_ON,
|
||||
BD73800_REG_LDO2_VOLT,
|
||||
BD73800_REG_LDO2_MODE,
|
||||
BD73800_REG_LDO3_ON,
|
||||
BD73800_REG_LDO3_VOLT,
|
||||
BD73800_REG_LDO3_MODE,
|
||||
BD73800_REG_LDO4_ON,
|
||||
BD73800_REG_LDO4_VOLT,
|
||||
BD73800_REG_LDO4_MODE, /* 0x4c */
|
||||
|
||||
BD73800_REG_GPO_OUT = 0x4e,
|
||||
BD73800_REG_OUT32K = 0x50,
|
||||
BD73800_REG_RTC_SEC,
|
||||
BD73800_REG_RTC_MIN,
|
||||
BD73800_REG_RTC_HOUR,
|
||||
BD73800_REG_RTC_WEEK,
|
||||
BD73800_REG_RTC_DAY,
|
||||
BD73800_REG_RTC_MONTH,
|
||||
BD73800_REG_RTC_YEAR,
|
||||
BD73800_REG_RTC_ALM0_SEC,
|
||||
BD73800_REG_RTC_ALM0_MIN,
|
||||
BD73800_REG_RTC_ALM0_HOUR,
|
||||
BD73800_REG_RTC_ALM0_WEEK,
|
||||
BD73800_REG_RTC_ALM0_DAY,
|
||||
BD73800_REG_RTC_ALM0_MONTH,
|
||||
BD73800_REG_RTC_ALM0_YEAR,
|
||||
BD73800_REG_RTC_ALM1_SEC,
|
||||
BD73800_REG_RTC_ALM1_MIN,
|
||||
BD73800_REG_RTC_ALM1_HOUR,
|
||||
BD73800_REG_RTC_ALM1_WEEK,
|
||||
BD73800_REG_RTC_ALM1_DAY,
|
||||
BD73800_REG_RTC_ALM1_MONTH,
|
||||
BD73800_REG_RTC_ALM1_YEAR,
|
||||
BD73800_REG_RTC_ALM2,
|
||||
BD73800_REG_RTC_CONF, /* 0x69 */
|
||||
|
||||
BD73800_REG_ADC_CTRL_1 = 0x6b,
|
||||
BD73800_REG_ADC_CTRL_2,
|
||||
BD73800_REG_ADC_ACCUM_NUM2,
|
||||
BD73800_REG_ADC_ACCUM_NUM1,
|
||||
BD73800_REG_ADC_ACCUM_NUM0,
|
||||
BD73800_REG_ADC_ACCUM_KICK,
|
||||
BD73800_REG_ADC_ACCUM_CNT2,
|
||||
BD73800_REG_ADC_ACCUM_CNT1,
|
||||
BD73800_REG_ADC_ACCUM_CNT0,
|
||||
BD73800_REG_ADC_ACCUM_VAL2,
|
||||
BD73800_REG_ADC_ACCUM_VAL1,
|
||||
BD73800_REG_ADC_ACCUM_VAL0,
|
||||
BD73800_REG_ADC_VOL_VAL1,
|
||||
BD73800_REG_ADC_VOL_VAL0,
|
||||
BD73800_REG_ADC_CUR_VAL1,
|
||||
BD73800_REG_ADC_CUR_VAL0,
|
||||
BD73800_REG_ADC_POW_VAL1,
|
||||
BD73800_REG_ADC_POW_VAL0,
|
||||
BD73800_REG_ADC_TEMP_VAL1,
|
||||
BD73800_REG_ADC_TEMP_VAL0,
|
||||
BD73800_REG_ADC_ACCUM_VAL_INT_TH4,
|
||||
BD73800_REG_ADC_ACCUM_VAL_INT_TH3,
|
||||
BD73800_REG_ADC_ACCUM_VAL_INT_TH2,
|
||||
BD73800_REG_ADC_ACCUM_VAL_INT_TH1,
|
||||
BD73800_REG_ADC_ACCUM_VAL_INT_TH0,
|
||||
BD73800_REG_ADC_WARN_TEMP_INT_TH1,
|
||||
BD73800_REG_ADC_WARN_TEMP_INT_TH0,
|
||||
BD73800_REG_ADC_POW_VAL_INT_TH1,
|
||||
BD73800_REG_ADC_POW_VAL_INT_TH0, /* 0x89 */
|
||||
|
||||
BD73800_REG_PBTN_CONF = 0x8b,
|
||||
|
||||
BD73800_REG_INT_MAIN_EN = 0x8f,
|
||||
BD73800_REG_INT_1_EN,
|
||||
BD73800_REG_INT_2_EN,
|
||||
BD73800_REG_INT_3_EN,
|
||||
BD73800_REG_INT_4_EN,
|
||||
BD73800_REG_INT_5_EN, /* 0x94 */
|
||||
|
||||
BD73800_REG_INT_MAIN_STAT = 0x96,
|
||||
BD73800_REG_INT_1_STAT,
|
||||
BD73800_REG_INT_2_STAT,
|
||||
BD73800_REG_INT_3_STAT,
|
||||
BD73800_REG_INT_4_STAT,
|
||||
BD73800_REG_INT_5_STAT, /* 0x9b */
|
||||
|
||||
BD73800_REG_INT_MAIN_SRC = 0x9d,
|
||||
BD73800_REG_INT_1_SRC,
|
||||
BD73800_REG_INT_2_SRC,
|
||||
BD73800_REG_INT_3_SRC,
|
||||
BD73800_REG_INT_4_SRC,
|
||||
BD73800_REG_INT_5_SRC, /* 0xa2 */
|
||||
|
||||
BD73800_REG_RST_MASK = 0xaf,
|
||||
BD73800_MAX_REGISTER,
|
||||
};
|
||||
|
||||
#define BD73800_REG_RTC_START BD73800_REG_RTC_SEC
|
||||
#define BD73800_REG_RTC_ALM_START BD73800_REG_RTC_ALM0_SEC
|
||||
|
||||
/* BD73800 IRQ register masks */
|
||||
|
||||
#define BD73800_INT_MAIN_EN_ALL GENMASK(4, 0)
|
||||
#define BD73800_INT_ADC_ACCUM_DONE_MASK BIT(0)
|
||||
#define BD73800_INT_ADC_ACCUM_OVF_MASK BIT(1)
|
||||
#define BD73800_INT_ADC_ACCUM_VAL_MASK BIT(2)
|
||||
#define BD73800_INT_ADC_ACCUM_TW_MASK BIT(3)
|
||||
#define BD73800_INT_ADC_POW_VAL_MASK BIT(4)
|
||||
#define BD73800_INT_RTC0_MASK BIT(5)
|
||||
#define BD73800_INT_RTC1_MASK BIT(6)
|
||||
#define BD73800_INT_RTC2_MASK BIT(7)
|
||||
#define BD73800_INT_BUCK1_DVS_DONE_MASK BIT(0)
|
||||
#define BD73800_INT_BUCK2_DVS_DONE_MASK BIT(1)
|
||||
#define BD73800_INT_BUCK3_DVS_DONE_MASK BIT(2)
|
||||
#define BD73800_INT_BUCK4_DVS_DONE_MASK BIT(3)
|
||||
#define BD73800_INT_BUCK5_DVS_DONE_MASK BIT(4)
|
||||
#define BD73800_INT_BUCK6_DVS_DONE_MASK BIT(5)
|
||||
#define BD73800_INT_BUCK7_DVS_DONE_MASK BIT(6)
|
||||
#define BD73800_INT_BUCK8_DVS_DONE_MASK BIT(7)
|
||||
#define BD73800_INT_BUCK1_OCP_MASK BIT(0)
|
||||
#define BD73800_INT_BUCK2_OCP_MASK BIT(1)
|
||||
#define BD73800_INT_BUCK3_OCP_MASK BIT(2)
|
||||
#define BD73800_INT_BUCK4_OCP_MASK BIT(3)
|
||||
#define BD73800_INT_BUCK5_OCP_MASK BIT(4)
|
||||
#define BD73800_INT_BUCK6_OCP_MASK BIT(5)
|
||||
#define BD73800_INT_BUCK7_OCP_MASK BIT(6)
|
||||
#define BD73800_INT_BUCK8_OCP_MASK BIT(7)
|
||||
#define BD73800_INT_PBTN_LONG_PRESS_MASK BIT(0)
|
||||
#define BD73800_INT_PBTN_MID_PRESS_MASK BIT(1)
|
||||
#define BD73800_INT_PBTN_SHORT_PUSH_MASK BIT(2)
|
||||
#define BD73800_INT_PBTN_SHORT_PRESS_MASK BIT(3)
|
||||
#define BD73800_INT_WDG_MASK BIT(4)
|
||||
#define BD73800_INT_SWRESET_MASK BIT(5)
|
||||
#define BD73800_INT_SEQ_DONE_MASK BIT(6)
|
||||
#define BD73800_INT_GPIO1_MASK BIT(0)
|
||||
#define BD73800_INT_GPIO2_MASK BIT(1)
|
||||
#define BD73800_INT_GPIO3_MASK BIT(2)
|
||||
#define BD73800_INT_GPIO4_MASK BIT(3)
|
||||
|
||||
#endif /* _MFD_BD73800_H */
|
||||
|
|
@ -17,6 +17,7 @@ enum rohm_chip_type {
|
|||
ROHM_CHIP_TYPE_BD71837,
|
||||
ROHM_CHIP_TYPE_BD71847,
|
||||
ROHM_CHIP_TYPE_BD72720,
|
||||
ROHM_CHIP_TYPE_BD73800,
|
||||
ROHM_CHIP_TYPE_BD96801,
|
||||
ROHM_CHIP_TYPE_BD96802,
|
||||
ROHM_CHIP_TYPE_BD96805,
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user