summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/gpio/qpnp-pin.txt6
-rw-r--r--Documentation/devicetree/bindings/power/qpnp-charger.txt350
-rw-r--r--Documentation/devicetree/bindings/power/qpnp-fg.txt265
-rw-r--r--Documentation/devicetree/bindings/power/qpnp-linear-charger.txt209
-rw-r--r--Documentation/devicetree/bindings/power/qpnp-smbcharger.txt394
-rw-r--r--Documentation/devicetree/bindings/power/qpnp-vm-bms.txt179
-rw-r--r--Documentation/devicetree/bindings/regulator/qpnp-labibb-regulator.txt265
-rw-r--r--Documentation/devicetree/bindings/regulator/qpnp-regulator.txt151
-rw-r--r--Documentation/devicetree/bindings/rtc/qpnp-rtc.txt4
-rw-r--r--arch/arm64/configs/msm_defconfig2
-rw-r--r--drivers/bif/Kconfig3
-rw-r--r--drivers/bif/qpnp-bsi.c247
-rw-r--r--drivers/gpio/Kconfig8
-rw-r--r--drivers/gpio/qpnp-pin.c198
-rw-r--r--drivers/hwmon/Kconfig4
-rw-r--r--drivers/hwmon/qpnp-adc-common.c41
-rw-r--r--drivers/hwmon/qpnp-adc-current.c120
-rw-r--r--drivers/hwmon/qpnp-adc-voltage.c110
-rw-r--r--drivers/leds/Kconfig30
-rw-r--r--drivers/leds/leds-qpnp-flash.c434
-rw-r--r--drivers/leds/leds-qpnp-wled.c287
-rw-r--r--drivers/leds/leds-qpnp.c755
-rw-r--r--drivers/mfd/Kconfig2
-rw-r--r--drivers/platform/msm/Kconfig7
-rw-r--r--drivers/platform/msm/qpnp-coincell.c97
-rw-r--r--drivers/platform/msm/qpnp-haptic.c325
-rw-r--r--drivers/platform/msm/qpnp-power-on.c547
-rw-r--r--drivers/platform/msm/qpnp-revid.c63
-rw-r--r--drivers/power/Kconfig132
-rw-r--r--drivers/power/bcl_peripheral.c97
-rw-r--r--drivers/power/qpnp-fg.c224
-rw-r--r--drivers/power/qpnp-smbcharger.c437
-rw-r--r--drivers/pwm/Kconfig3
-rw-r--r--drivers/pwm/pwm-qpnp.c156
-rw-r--r--drivers/regulator/Kconfig8
-rw-r--r--drivers/regulator/qpnp-labibb-regulator.c104
-rw-r--r--drivers/regulator/qpnp-regulator.c103
-rw-r--r--drivers/regulator/spm-regulator.c166
-rw-r--r--drivers/rtc/Kconfig11
-rw-r--r--drivers/rtc/qpnp-rtc.c168
-rw-r--r--drivers/thermal/Kconfig5
-rw-r--r--drivers/thermal/qpnp-adc-tm.c2675
-rw-r--r--drivers/thermal/qpnp-temp-alarm.c120
-rw-r--r--include/linux/qpnp/qpnp-adc.h5
-rw-r--r--sound/soc/codecs/msm8916-wcd-irq.c445
-rw-r--r--sound/soc/codecs/msm8916-wcd-irq.h34
46 files changed, 7611 insertions, 2385 deletions
diff --git a/Documentation/devicetree/bindings/gpio/qpnp-pin.txt b/Documentation/devicetree/bindings/gpio/qpnp-pin.txt
index 1a1fd454b095..0f61ae72f766 100644
--- a/Documentation/devicetree/bindings/gpio/qpnp-pin.txt
+++ b/Documentation/devicetree/bindings/gpio/qpnp-pin.txt
@@ -1,7 +1,7 @@
* msm-qpnp-pin
msm-qpnp-pin is a GPIO chip driver for the MSM SPMI implementation.
-It creates a spmi_device for every spmi-dev-container block of device_nodes.
+It creates a platform_device for every block of device_nodes.
These device_nodes contained within specify the PMIC pin number associated
with each gpio chip. The driver will map these to Linux GPIO numbers.
@@ -10,8 +10,6 @@ with each gpio chip. The driver will map these to Linux GPIO numbers.
-Root Node-
Required properties :
- - spmi-dev-container : Used to specify the following child nodes as part of the
- same SPMI device.
- gpio-controller : Specify as gpio-contoller. All child nodes will belong to
this gpio_chip.
- #gpio-cells: We encode a PMIC pin number and a 32-bit flag field to
@@ -188,13 +186,11 @@ qpnp: qcom,spmi@fc4c0000 {
#interrupt-cells = <3>;
qcom,pm8941@0 {
- spmi-slave-container;
reg = <0x0>;
#address-cells = <1>;
#size-cells = <1>;
pm8941_gpios: gpios {
- spmi-dev-container;
compatible = "qcom,qpnp-pin";
gpio-controller;
#gpio-cells = <2>;
diff --git a/Documentation/devicetree/bindings/power/qpnp-charger.txt b/Documentation/devicetree/bindings/power/qpnp-charger.txt
new file mode 100644
index 000000000000..cfb7aaa0450d
--- /dev/null
+++ b/Documentation/devicetree/bindings/power/qpnp-charger.txt
@@ -0,0 +1,350 @@
+Qualcomm QPNP Charger
+
+The charger supports the switch mode battery charger and boost (SMBB)
+peripherals on Qualcomm PMIC chips.
+
+There are seven different peripherals adding the following functionality.
+Each of these peripherals are implemented as subnodes in the example at the
+end of this file.
+
+- qcom,chgr: Supports charging control and status
+ reporting.
+- qcom,bat-if: Battery status reporting such as presence,
+ temperature reporting and voltage collapse
+ protection.
+- qcom,buck: Charger buck configuration and status
+ reporting with regards to several regulation
+ loops such as vdd, ibat etc.
+- qcom,usb-chgpth: USB charge path detection and input current
+ limiting configuration.
+- qcom,dc-chgpth: DC charge path detection and input current
+ limiting configuration.
+- qcom,chg-misc: Miscellaneous features such as buck frequency
+ settings, comparator override features etc.
+
+Parent node required properties:
+- qcom,vddmax-mv: Target voltage of battery in mV.
+- qcom,vddsafe-mv: Maximum Vdd voltage in mV.
+- qcom,vinmin-mv: Minimum input voltage in mV.
+- qcom,ibatmax-ma: Maximum battery charge current in mA
+- qcom,ibatsafe-ma: Safety battery current setting
+- qcom,thermal-mitigation: Array of ibatmax values for different
+ system thermal mitigation level.
+
+Parent node optional properties:
+- qcom,ibatterm-ma: Current at which charging is terminated when
+ the analog end of charge option is selected.
+- qcom,maxinput-usb-ma: Maximum input current USB.
+- qcom,maxinput-dc-ma: Maximum input current DC.
+- qcom,vbatdet-delta-mv: Battery charging resume delta.
+- qcom,vbatweak-mv: Weak battery voltage threshold in mV, above which
+ fast charging can start. The supported voltage range is
+ from 2100mV to 3600mV with a step size of 100mV.
+- qcom,charging-disabled: Set this property to disable charging
+ by default. This can then be overriden
+ writing the the module parameter
+ "charging_disabled".
+- qcom,duty-cycle-100p: Set this property to enable the 100% duty
+ cycle feature.
+- qcom,use-default-batt-values: Set this flag to force reporting of
+ battery temperature of 250 decidegree
+ Celsius, state of charge to be 50%
+ and disable charging.
+- qcom,warm-bat-decidegc: Warm battery temperature in decidegC.
+- qcom,cool-bat-decidegc: Cool battery temperature in decidegC.
+ Note that if both warm and cool battery
+ temperatures are set, the corresponding
+ ibatmax and bat-mv properties are
+ required to be set.
+- qcom,ibatmax-cool-ma: Maximum cool battery charge current.
+- qcom,ibatmax-warm-ma: Maximum warm battery charge current.
+- qcom,warm-bat-mv: Warm temperature battery target voltage.
+- qcom,cool-bat-mv: Cool temperature battery target voltage.
+- qcom,tchg-mins: Maximum total software initialized charge time.
+- qcom,bpd-detection: Select a battery presence detection scheme by
+ specifying either "bpd_thm", "bpd_id" or
+ "bpd_thm_id". "bpd_thm" selects the temperature
+ pin, "bpd_id" uses the id pin for battery presence
+ detection, "bpd_thm_id" selects both.
+ If the property is not set, the temperatue pin will
+ be used.
+- qcom,btc-disabled: If flag is set battery hot and cold monitoring is
+ disabled in hardware. This monitoring is turned on
+ by default.
+- qcom,batt-hot-percent: Specify a supported hot threshold percentage.
+ Supported thresholds: 25% and 35%. If none is specified
+ hardware defaults will be used.
+- qcom,batt-cold-percent: Specify a supported cold threshold percentage.
+ Supported thresholds: 70% and 80%. If none is specified
+ hardware defaults will be used.
+- otg-parent-supply Specify a phandle to a parent supply regulator
+ for the OTG regulator.
+- boost-parent-supply Specify a phandle to a parent supply regulator
+ for the boost regulator.
+- qcom,resume-soc Capacity in percent at which charging should resume
+ when a fully charged battery drops below this level.
+- qcom,chg-vadc Corresponding VADC device's phandle.
+- qcom,pmic-revid The phandle to the revid node of the pmic on which charger
+ peripheral is present. This property is a must on PMIC chips
+ that exhibit inaccuracies in battery current readings. This
+ phandle is used to check the version of the PMIC and apply
+ necessary software workarounds.
+- qcom,ext-ovp-present Indicates if an external OVP exists which reduces the
+ overall input resistance of the charge path.
+- qcom,ovp-monitor-en The ovp is enabled on hw by default. If this flag is
+ set, the charger ovp status is monitored in software.
+- qcom,ibat-calibration-enabled Indicates if ibat calibration is enabled. This is
+ required for devices which have a ibat trim error
+ causing ibatmax to go out of spec.
+- qcom,power-stage-reduced Indicates if power stage workaround is enabled. This work
+ around reduces the power stage segments while charging
+ under high load during low battery voltages. It's for
+ improving IADC accuracy while board has a bad layout.
+- qcom,use-external-rsense A boolean that controls whether BMS will use
+ an external sensor resistor instead of the default
+ RDS of the batfet.
+- qcom,vbatdet-maxerr-mv This property in mV is a hystersis value for the charge
+ resume voltage property qcom,vbatdet-delta-mv. If this
+ property is not defined it defaults to 50 mV.
+- qcom,parallel-ovp-mode When this option is enabled, it allows charging through both
+ DC and USB OVP FETs. Please note that this should only
+ be enabled in board designs with PM8941 which have DC_IN
+ and USB_IN connected via a short.
+ - qcom,ext-ovp-isns-enable-gpio External OVP enable GPIO.
+ - qcom,ext-ovp-isns-r-ohm External ISNS OVP resistance in ohm.
+
+Sub node required structure:
+- A qcom,chg node must be a child of an spmi device. Each subnode reflects
+ a hardware peripheral which adds a unique set of features
+ to the collective charging device. For example USB detection
+ and the battery interface are each seperate peripherals and
+ each should be their own subnode.
+- qcom,chg-adc_tm Corresponding ADC TM device's phandle to set recurring
+ measurements and receive notification for batt_therm.
+
+Sub node required properties:
+- compatible: Must be "qcom,qpnp-charger".
+- reg: Specifies the SPMI address and size for this peripheral.
+- interrupts: Specifies the interrupt associated with the peripheral.
+- interrupt-names: Specifies the interrupt names for the peripheral. Every
+ available interrupt needs to have an associated name
+ with it to indentify its purpose.
+
+ The following lists each subnode and their corresponding
+ required interrupt names:
+
+ qcom,usb-chgpth:
+ - usbin-valid
+ - usb-ocp (only for SMBBP and SMBCL)
+
+ qcom,chgr:
+ - chg-done
+ - chg-failed
+
+ The following interrupts are available:
+
+ qcom,chgr:
+ - chg-done: Triggers on charge completion.
+ - chg-failed: Notifies of charge failures.
+ - fast-chg-on: Notifies of fast charging state.
+ - trkl-chg-on: Indicates trickle charging.
+ - state-change: Notifies of a state change in
+ the charger state machine.
+ - chgwdog: Charger watchdog interrupt.
+ - vbat-det-hi: Triggers on vbat-det-hi voltage
+ setting,can be used as
+ battery alarm.
+ - vbat-det-hi: Triggers on vbat-det-low voltage
+ setting, can be used as
+ battery alarm.
+
+ qcom,buck:
+ - vdd-loop: VDD loop change interrupt.
+ - ibat-loop: Ibat loop change interrupt.
+ - ichg-loop: Charge current loop change.
+ - vchg-loop: Charge voltage loop change.
+ - overtemp: Overtemperature interrupt.
+ - vref-ov: Reference overvoltage interrupt.
+ - vbat-ov: Battery overvoltage interrupt.
+
+ qcom,bat-if:
+ - psi: PMIC serial interface interrupt.
+ - vcp-on: Voltage collapse protection
+ status interrupt.
+ - bat-fet-on: BATFET status interrupt.
+ - bat-temp-ok: Battery temperature status
+ interrupt.
+ - batt-pres: Battery presence status
+ interrupt.
+
+ qcom,usb-chgpth:
+ - usbin-valid: Indicates valid USB connection.
+ - coarse-det-usb: Coarse detect interrupt triggers
+ at low voltage on USB_IN.
+ - chg-gone: Triggers on VCHG line.
+ - usb-ocp Triggers on over current conditions when
+ reverse boosting. (Only available on
+ SMBCL and SMBBP devices).
+
+ qcom,dc-chgpth:
+ - dcin-valid: Indicates a valid DC charger
+ connection.
+ - coarse-det-dc: Coarse detect interrupt triggers
+ at low voltage on DC_IN.
+
+ qcom,boost:
+ - limit-error: Limiting error on SMBB boost.
+ - boost-pwr-ok: Status of boost power.
+
+Sub node optional properties:
+ qcom,usb-chgpth:
+ - regulator-name: A string used as a descriptive name
+ for the OTG regulator.
+ qcom,boost:
+ - regulator-min-microvolt: Minimum boost voltage setting.
+ - regulator-max-microvolt: Maximum boost voltage setting.
+ - regulator-name: A string used as a descriptive name
+ for the boost regulator.
+
+ qcom,batfet:
+ - regulator-name: A string used as a descriptive name
+ for the batfet regulator.
+
+ qcom,chgr:
+ - regulator-name: A string used as a descriptive name
+ for the flash workarounds regulator.
+Example:
+ pm8941-chg {
+ compatible = "qcom,qpnp-charger";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ otg-parent-supply = <&pm8941_boost>;
+ boost-parent-supply = <&foo_parent_reg>;
+
+ qcom,vddmax-mv = <4200>;
+ qcom,vddsafe-mv = <4200>;
+ qcom,vinmin-mv = <4200>;
+ qcom,ibatmax-ma = <1500>;
+ qcom,ibatterm-ma = <200>;
+ qcom,ibatsafe-ma = <1500>;
+ qcom,vbatweak-mv = <3200>;
+ qcom,thermal-mitigation = <1500 700 600 325>;
+ qcom,cool-bat-degc = <10>;
+ qcom,cool-bat-mv = <4100>;
+ qcom,ibatmax-warm-ma = <350>;
+ qcom,warm-bat-degc = <45>;
+ qcom,warm-bat-mv = <4100>;
+ qcom,ibatmax-cool-ma = <350>;
+ qcom,vbatdet-delta-mv = <60>;
+ qcom,batt-hot-percent = <25>;
+ qcom,batt-cold-percent = <85>;
+ qcom,btc-disabled = <0>;
+ qcom,chg-vadc = <&pm8941_vadc>;
+ qcom,chg-adc_tm = <&pm8941_adc_tm>;
+ qcom,pmic-revid = <&pm8941_revid>;
+
+ qcom,chgr@1000 {
+ reg = <0x1000 0x100>;
+ interrupts = <0x0 0x10 0x0>,
+ <0x0 0x10 0x1>,
+ <0x0 0x10 0x2>,
+ <0x0 0x10 0x3>,
+ <0x0 0x10 0x4>,
+ <0x0 0x10 0x5>,
+ <0x0 0x10 0x6>,
+ <0x0 0x10 0x7>;
+
+ interrupt-names = "chg-done",
+ "chg-failed",
+ "fast-chg-on",
+ "trkl-chg-on",
+ "state-change",
+ "chgwdog",
+ "vbat-det-hi",
+ "vbat-det-lo";
+ };
+
+ qcom,buck@1100 {
+ reg = <0x1100 0x100>;
+ interrupts = <0x0 0x11 0x0>,
+ <0x0 0x11 0x1>,
+ <0x0 0x11 0x2>,
+ <0x0 0x11 0x3>,
+ <0x0 0x11 0x4>,
+ <0x0 0x11 0x5>,
+ <0x0 0x11 0x6>;
+
+ interrupt-names = "vdd-loop",
+ "ibat-loop",
+ "ichg-loop",
+ "vchg-loop",
+ "overtemp",
+ "vref-ov",
+ "vbat-ov";
+ };
+
+ qcom,bat-if@1200 {
+ reg = <0x1200 0x100>;
+ interrupts = <0x0 0x12 0x0>,
+ <0x0 0x12 0x1>,
+ <0x0 0x12 0x2>,
+ <0x0 0x12 0x3>,
+ <0x0 0x12 0x4>;
+
+ interrupt-names = "psi",
+ "vcp-on",
+ "bat-fet-on",
+ "bat-temp-ok",
+ "batt-pres";
+ };
+
+ pm8941_chg_otg: qcom,usb-chgpth@1300 {
+ reg = <0x1300 0x100>;
+ interrupts = <0 0x13 0x0>,
+ <0 0x13 0x1>,
+ <0x0 0x13 0x2>;
+
+ interrupt-names = "usbin-valid",
+ "coarse-det-usb",
+ "chg-gone";
+ };
+
+ qcom,dc-chgpth@1400 {
+ reg = <0x1400 0x100>;
+ interrupts = <0x0 0x14 0x0>,
+ <0x0 0x14 0x1>;
+
+ interrupt-names = "dcin-valid",
+ "coarse-det-dc";
+ };
+
+ pm8941_chg_boost: qcom,boost@1500 {
+ reg = <0x1500 0x100>;
+ interrupts = <0x0 0x15 0x0>,
+ <0x0 0x15 0x1>;
+
+ interrupt-names = "limit-error",
+ "boost-pwr-ok";
+ };
+
+ qcom,misc@1600 {
+ reg = <0x1600 0x100>;
+ };
+ };
+
+In regulator specific device tree file:
+
+ &pm8941_chg_boost {
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ regulator-name = "8941_smbb_boost";
+ };
+
+ &pm8941_chg_batif {
+ regulator-name = "batfet";
+ };
+
+ &pm8941_chg_otg {
+ regulator-name = "8941_smbb_otg";
+ };
diff --git a/Documentation/devicetree/bindings/power/qpnp-fg.txt b/Documentation/devicetree/bindings/power/qpnp-fg.txt
new file mode 100644
index 000000000000..d32a364d40a7
--- /dev/null
+++ b/Documentation/devicetree/bindings/power/qpnp-fg.txt
@@ -0,0 +1,265 @@
+QTI's QPNP PMIC Fuel Gauge Device
+
+QPNP PMIC FG provides interface to clients to read properties related
+to the battery. Its main function is to retrieve the State of Charge (SOC),
+a 0-100 percentage representing the amount of charge left in the battery.
+
+There are two required peripherals in the FG driver, both implemented as
+subnodes in the example. These peripherals must not be disabled if the FG
+device is to enabled:
+
+- qcom,fg-soc : The main FG device. Supports battery fuel gauge controls and
+ sensors.
+- qcom,fg-batt : The FG battery device supports interrupts and controls with
+ respect to the state of the connected battery.For example: the
+ peripheral informs the driver if the battery has been identified
+ by the fuel gauge based on a given battery resistance range.
+
+Optionally ADC nodes can be added
+- qcom,revid-tp-rev: A subnode with a register address for the TP_REV register
+ in the REVID peripheral. This is used to apply workarounds that
+ may depend on the trim program.
+- qcom,fg-adc-vbat : A subnode with a register address for the FG_ADC_USR
+ peripheral which is used mainly for battery current limiting (BCL).
+ This node maps out the VBAT reading register which allows to have
+ a +/- 32 mV accurate reading of VBAT.
+- qcom,fg-adc-ibat : A subnode with a register address for the FG_ADC_USR
+ peripheral which is used mainly for battery current limiting (BCL).
+ This node maps out the IBAT current reading register which allows
+ to have a +/- 32 mA accurate reading of IBAT.
+
+Parent node required properties:
+- compatible : should be "qcom,qpnp-fg" for the FG driver.
+- qcom,pmic-revid : Should specify the phandle of PMIC
+ revid module. This is used to identify
+ the PMIC subtype.
+
+Parent node optional properties:
+- qcom,warm-bat-decidegc: Warm battery temperature in decidegC.
+- qcom,cool-bat-decidegc: Cool battery temperature in decidegC.
+- qcom,hot-bat-decidegc: Hot battery temperature in decidegC.
+- qcom,cold-bat-decidegc: Cold battery temperature in decidegC.
+- qcom,cold-hot-jeita-hysteresis: A tuple of 2. Index[0] is cold
+ hysteresis and index[1] is hot
+ hysterisis(in decidegC).
+- qcom,ext-sense-type: Current sense channel used by the FG.
+ Set this to use external rsense.
+- qcom,thermal-coefficients: Byte array of thermal coefficients for
+ reading battery thermistor. This should
+ be exactly 6 bytes in length.
+ Example: [01 02 03 04 05 06]
+- qcom,resume-soc: soc to resume charging in percentage.
+- qcom,resume-soc-raw: soc to resume charging in the scale of
+ [0-255]. This overrides qcom,resume-soc
+ if defined.
+- qcom,hold-soc-while-full: A boolean property that when defined
+ holds SOC at 100% when the battery is
+ full.
+- qcom,bcl-lm-threshold-ma: BCL LPM to MPM mode transition threshold
+ in milliAmpere.
+- qcom,bcl-mh-threshold-ma: BCL MPM to HPM mode transition threshold
+ in milliAmpere.
+- qcom,use-otp-profile: Specify this flag to avoid RAM loading
+ any battery profile.
+- qcom,sw-rbias-control: Boolean property which defines whether
+ the Rbias needs to be controlled by
+ software. If this is not set, it will
+ be controlled by hardware (default).
+- qcom,fg-iterm-ma: Battery current at which the fuel gauge
+ will try to scale 100% towards. When
+ the charge current goes above this, the
+ SoC should be at 100%.
+- qcom,fg-chg-iterm-ma: Battery current at which the fuel gauge
+ will issue end of charge if the charger
+ is configured to use the fuel gauge
+ ADCs for end of charge detection. This
+ property is in milliamps and should be
+ positive (e.g. 100mA to terminate at
+ -100mA).
+- qcom,irq-volt-empty-mv: The voltage threshold that the empty
+ soc interrupt will be triggered. When
+ the empty soc interrupt fires, battery
+ soc will be pulled to 0 and the
+ userspace will be notified via the
+ power supply framework. The userspace
+ will read 0% soc and immediately
+ shutdown.
+- qcom,fg-cutoff-voltage-mv: The voltage where the fuel gauge will
+ steer the SOC to be zero. For example,
+ if the cutoff voltage is set to 3400mv,
+ the fuel gauge will try to count SoC so
+ that the battery SoC will be 0 when it
+ is 3400mV.
+- qcom,fg-vbat-estimate-diff-mv: If the estimated voltage based on SoC
+ and battery current/resistance differs
+ from the actual voltage by more than
+ this amount, the fuel gauge will
+ redo the first SoC estimate when the
+ driver probes.
+- qcom,fg-delta-soc: How many percent the monotonic SoC must
+ change before a new delta_soc interrupt
+ is asserted. If this value is raised
+ above 3-4, some period workarounds may
+ not function well, so it's best to
+ leave this at 1 or 2%.
+- qcom,fg-vbatt-low-threshold: Voltage (in mV) which upon set will be
+ used for configuring the low battery
+ voltage threshold. Interrupt will be
+ asserted and handled based upon
+ this. If this property is not specified,
+ low battery voltage threshold will be
+ configured to 4200 mV.
+- qcom,cycle-counter-en: Boolean property which enables the cycle
+ counter feature. If this property is
+ present, then the following properties
+ to specify low and high soc thresholds
+ should be defined.
+- qcom,capacity-learning-on: A boolean property to have the fuel
+ gauge driver attempt to learn the
+ battery capacity when charging. Takes
+ precedence over capacity-estimation-on.
+- qcom,capacity-learning-feedback: A boolean property to have the fuel
+ gauge driver to feedback the learned
+ capacity into the capacity learning
+ algorithm. This has to be used only if
+ the property "qcom,capacity-learning-on"
+ is specified.
+- qcom,cl-max-increment-deciperc: The maximum percent that the capacity
+ can rise as the result of a single
+ charge cycle. This property corresponds
+ to .1% increments.
+- qcom,cl-max-decrement-deciperc: The maximum percent that the capacity
+ can fall as the result of a single
+ charge cycle. This property corresponds
+ to .1% decrements.
+- qcom,cl-max-temp-decidegc: Above this temperature, capacity
+ learning will be canceled.
+- qcom,cl-mix-temp-decidegc: Below this temperature, capacity
+ learning will be canceled.
+- qcom,cl-max-start-soc: The battery soc has to be below this
+ value at the start of a charge cycle
+ for capacity learning to be run.
+- qcom,cl-vbat-est-thr-uv: The maximum difference between the
+ battery voltage shadow and the current
+ predicted voltage in uV to initiate
+ capacity learning.
+- qcom,capacity-estimation-on: A boolean property to have the fuel
+ gauge driver attempt to estimate the
+ battery capacity using battery
+ resistance.
+- qcom,aging-eval-current-ma: Current used to evaluate battery aging.
+ This value should be around the steady
+ state current drawn from the battery
+ when the phone is low on battery.
+- qcom,fg-cc-cv-threshold-mv: Voltage threshold in mV for configuring
+ constant charge (CC) to constant
+ voltage (CV) setpoint in FG upon
+ which the battery EOC status will
+ be determined. This value should be
+ 10 mV less than the float voltage
+ configured in the charger.
+ This property should only be specified
+ if "qcom,autoadjust-vfloat" property is
+ specified in the charger driver to
+ ensure a proper operation.
+- qcom,bad-battery-detection-enable: A boolean property to enable the fuel
+ gauge driver to detect the damaged battery
+ when the safety-timer expires by using the
+ coulomb count.
+- qcom,fg-therm-delay-us: The time in microseconds to delay battery
+ thermistor biasing.
+
+qcom,fg-soc node required properties:
+- reg : offset and length of the PMIC peripheral register map.
+- interrupts : the interrupt mappings.
+ The format should be
+ <slave-id peripheral-id interrupt-number>.
+- interrupt-names : names for the mapped fg soc interrupts
+ The following interrupts are required:
+ 0: high-soc
+ 1: low-soc
+ 2: full-soc
+ 3: empty-soc
+ 4: delta-soc
+ 5: first-est-done
+ 6: sw-fallbk-ocv
+ 7: sw-fallbk-new-batt
+
+qcom,fg-memif node required properties:
+- reg : offset and length of the PMIC peripheral register map.
+- interrupts : the interrupt mappings.
+ The format should be
+ <slave-id peripheral-id interrupt-number>.
+- interrupt-names : names for the mapped fg adc interrupts
+ The following interrupts are required:
+ 0: mem-avail
+
+Example:
+pmi8994_fg: qcom,fg {
+ compatible = "qcom,qpnp-fg";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ status = "disabled";
+ qcom,pmic-revid = <&pmi8994_revid>;
+
+ qcom,fg-soc@4000 {
+ reg = <0x4000 0x100>;
+ interrupts = <0x2 0x40 0x0>,
+ <0x2 0x40 0x1>,
+ <0x2 0x40 0x2>,
+ <0x2 0x40 0x3>,
+ <0x2 0x40 0x4>,
+ <0x2 0x40 0x5>,
+ <0x2 0x40 0x6>,
+ <0x2 0x40 0x7>;
+
+ interrupt-names = "high-soc",
+ "low-soc",
+ "full-soc",
+ "empty-soc",
+ "delta-soc",
+ "first-est-done",
+ "sw-fallbk-ocv",
+ "sw-fallbk-new-batt";
+ };
+
+ qcom,fg-batt@4100 {
+ reg = <0x4100 0x100>;
+ interrupts = <0x2 0x41 0x0>,
+ <0x2 0x41 0x1>,
+ <0x2 0x41 0x2>,
+ <0x2 0x41 0x3>,
+ <0x2 0x41 0x4>,
+ <0x2 0x41 0x5>,
+ <0x2 0x41 0x6>,
+ <0x2 0x41 0x7>;
+
+ interrupt-names = "soft-cold",
+ "soft-hot",
+ "vbatt-low",
+ "batt-ided",
+ "batt-id-req",
+ "batt-unknown",
+ "batt-missing",
+ "batt-match";
+ };
+
+ qcom,fg-adc-vbat@4254 {
+ reg = <0x4254 0x1>;
+ };
+
+ qcom,fg-adc-ibat@4255 {
+ reg = <0x4255 0x1>;
+ };
+
+ qcom,fg-memif@4400 {
+ reg = <0x4400 0x100>;
+ interrupts = <0x2 0x44 0x0>,
+ <0x2 0x44 0x1>;
+
+ interrupt-names = "mem-avail",
+ "data-rcvry-sug";
+
+ qcom,cold-hot-jeita-hysteresis = <30 50>;
+ };
+};
diff --git a/Documentation/devicetree/bindings/power/qpnp-linear-charger.txt b/Documentation/devicetree/bindings/power/qpnp-linear-charger.txt
new file mode 100644
index 000000000000..35a71584508b
--- /dev/null
+++ b/Documentation/devicetree/bindings/power/qpnp-linear-charger.txt
@@ -0,0 +1,209 @@
+Qualcomm QPNP Linear Charger
+
+The charger module supports the linear battery charger peripherals on
+Qualcomm PMIC chips.
+
+There are four different peripherals in the charger module.
+Each of these peripherals are implemented as subnodes.
+
+- qcom,chgr: Supports charging control and status reporting
+- qcom,bat-if: Battery status reporting such as presence and
+ temperature reporting.
+- qcom,usb-chgpth: USB charge path detection and input current
+ limiting configuration.
+- qcom,chg-misc: Miscellaneous features such as comparator override
+ features etc.
+
+Parent node required properties:
+- qcom,vddmax-mv: Target voltage of battery in mV.
+- qcom,vddsafe-mv: Maximum Vdd voltage in mV.
+- qcom,vinmin-mv: Minimum input voltage in mV.
+- qcom,ibatsafe-ma: Safety battery current setting
+
+Parent node optional properties:
+- qcom,vbatweak-uv: Weak battery voltage threshold in uV,
+ above which fast charging can start.
+ The supported voltage range is from
+ 3000000uV to 3581250uV with a step
+ size of 18750000 uV.
+- qcom,charging-disabled: Set this property to disable charging
+ by default.
+- qcom,use-default-batt-values: Set this flag to force reporting of
+ fake battery.
+- qcom,warm-bat-decidegc: Warm battery temperature in decidegC.
+- qcom,cool-bat-decidegc: Cool battery temperature in decidegC.
+ Note that if both warm and cool
+ battery temperatures are set, the
+ corresponding ibatmax and bat-mv
+ properties are required to be set.
+- qcom,ibatmax-cool-ma: Maximum cool battery charge current.
+- qcom,ibatmax-warm-ma: Maximum warm battery charge current.
+- qcom,warm-bat-mv: Warm temperature battery target
+ voltage.
+- qcom,cool-bat-mv: Cool temperature battery target
+ voltage.
+- qcom,thermal-mitigation: Array of ibatmax values for different
+ system thermal mitigation level.
+- qcom,tchg-mins: Maximum total software initialized
+ charge time.
+- qcom,bpd-detection: Select a battery presence detection
+ scheme by specifying either "bpd_thm"
+ "bpd_id" or "bpd_thm_id". "bpd_thm"
+ selects the temperature pin, "bpd_id"
+ uses the id pin for battery presence
+ detection, "bpd_thm_id" selects both.
+ If the property is not set, the
+ temperatue pin will be used.
+- qcom,btc-disabled: If flag is set battery hot and cold
+ monitoring is disabled in hardware.
+ This monitoring is turned on by
+ default.
+- qcom,batt-hot-percentage: Specify a supported hot threshold
+ percentage.
+ Supported thresholds: 25% and 35%. If
+ none is specified hardware defaults
+ will be used.
+- qcom,batt-cold-percentage: Specify a supported cold threshold
+ percentage. Supported thresholds: 70%
+ and 80%. If none is specified
+ hardwaredefaults will be used.
+- qcom,chg-adc_tm Corresponding ADC TM device's phandle
+ to set recurring measurements and
+ receive notification for batt_therm.
+-qcom,float-charge If specified enable float charging.
+- qcom,chg-vadc Corresponding VADC device's phandle.
+- qcom,charger-detect-eoc If specified charger hardware will
+ detect end-of-charge.
+ If not specified charger driver
+ depends on BMSfor end-of-charge
+ detection.
+- qcom,disable-vbatdet-based-recharge If specified disable VBATDET irq
+ and charging can only be resumed
+ if charger is re-inserted or SOC
+ falls below resume SOC.
+ This property should always be used
+ along with the BMS property:
+ "qcom,disable-suspend-on-usb".
+- qcom,use-external-charger If specifed the LBC module will
+ be disabled and the driver will not
+ register. It also enables BID for
+ BPD and disables BTC. Declare this node
+ only if you are using an external charger
+ and not the PMIC internal LBC.
+- qcom,chgr-led-support There is a current sink device in linear
+ charger module, it is used to control a
+ led which can act as a charger led as well
+ as a general notification led.
+- qcom,parallel-charger This is a bool property to indicate the
+ LBC will operate as a secondary charger
+ in the parallel mode. If this is enabled
+ the charging operations will be controlled by
+ the primary-charger.
+- qcom,collapsible-chgr-support If specifed the collapsible charger feature
+ will be supported. LBC will disable VIN_MIN
+ comparator and use chg_gone interrupt to
+ detect charger removal.
+
+
+Sub node required structure:
+- A qcom,charger node must be a child of an spmi_device nod. Each subnode
+ reflects a hardware peripheral which adds a unique set of features
+ to the collective charging device. For example USB detection
+ and the battery interface are each seperate peripherals and
+ each should be their own subnode.
+
+Sub node required properties:
+- compatible: Must be "qcom,qpnp-linear-charger".
+- reg: Specifies the SPMI address and size for this
+ peripheral.
+- interrupts: Specifies the interrupt associated with the
+ peripheral.
+- interrupt-names: Specifies the interrupt names for the peripheral.
+ Every available interrupt needs to have an associated
+ name with it to indentify its purpose.
+
+ The following lists each subnode and their
+ corresponding required interrupt names:
+
+ qcom,usb-chgpth:
+ - usbin-valid
+
+ The following interrupts are available:
+
+ qcom,usb-chgpth:
+ - usbin-valid: Indicates valid USB
+ connection.
+ - coarse-det-usb: Coarse detect interrupt
+ triggers at low voltage on
+ USB_IN.
+ - chg-gone: Triggers on VCHG line.
+ - overtemp: Triggers on over temperature
+ condition
+
+ qcom,chgr:
+ - chg-done: Triggers on charge completion.
+ - chg-failed: Notifies of charge failures.
+ - fast-chg-on: Notifies of fast charging.
+ - vbat-det-lo: Triggers on vbat-det-lo
+ voltage.
+
+Example:
+ pm8916-chg: qcom,charger {
+ compatible = "qcom,qpnp-linear-charger";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ qcom,vddmax-mv = <4200>;
+ qcom,vddsafe-mv = <4200>;
+ qcom,vinmin-mv = <4200>;
+ qcom,ibatsafe-ma = <1440>;
+ qcom,vbatweak-uv = <3200>;
+ qcom,thermal-mitigation = <1500 700 600 325>;
+ qcom,cool-bat-decidegc = <100>;
+ qcom,warm-bat-decidegc = <450>;
+ qcom,cool-bat-mv = <4100>;
+ qcom,ibatmax-warm-ma = <360>;
+ qcom,ibatmax-cool-ma = <360>;
+ qcom,warm-bat-mv = <4100>;
+ qcom,batt-hot-percentage = <25>;
+ qcom,batt-cold-percentage = <85>;
+ qcom,tchg-mins = <152>;
+ qcom,resume-soc = <99>;
+ qcom,btc-disabled = <0>;
+ qcom,chg-vadc = <&pm8916_vadc>;
+
+ qcom,chgr@1000 {
+ reg = <0x1000 0x100>;
+ interrupts = <0x0 0x10 0x7>,
+ <0x0 0x10 0x6>,
+ <0x0 0x10 0x5>,
+ <0x0 0x10 0x0>;
+
+ interrupt-names = "chg-done",
+ "chg-failed",
+ "fast-chg-on",
+ "vbat-det-lo";
+ };
+
+ qcom,bat-if@1200 {
+ reg = <0x1200 0x100>;
+ interrupts = <0x0 0x12 0x1>,
+ <0x0 0x12 0x0>;
+
+ interrupt-names = "bat-temp-ok",
+ "batt-pres";
+ };
+
+ qcom,usb-chgpth@1300 {
+ reg = <0x1300 0x100>;
+ interrupts = <0 0x13 0x2>,
+ <0 0x13 0x1>;
+
+ interrupt-names = "chg-gone",
+ "usbin-valid";
+ };
+
+ qcom,chg-misc@1600 {
+ reg = <0x1600 0x100>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/power/qpnp-smbcharger.txt b/Documentation/devicetree/bindings/power/qpnp-smbcharger.txt
new file mode 100644
index 000000000000..efd64cd90878
--- /dev/null
+++ b/Documentation/devicetree/bindings/power/qpnp-smbcharger.txt
@@ -0,0 +1,394 @@
+QPNP SMB Battery Charger
+
+QPNP SMB Charger is a single-cell switching mode battery charger. It can charge
+the battery and power the system via the USB and AC adapter input.
+
+The QPNP SMB Charger interfaces via the SPMI bus.
+
+There are six different peripherals adding the following functionality.
+Each of these peripherals are implemented as subnodes in the example at the
+end of this file.
+
+- qcom,chgr: Supports charging control and status
+ reporting.
+- qcom,bat-if: Battery status reporting such as presence,
+ temperature reporting and voltage collapse
+ protection.
+- qcom,usb-chgpth: USB charge path detection and input current
+ limiting configuration.
+- qcom,dc-chgpth: DC charge path detection and input current
+ limiting configuration.
+- qcom,chg-misc: Miscellaneous features such as watchdog timers
+ and SYSOK pin control
+- qcom,chg-otg: OTG configuration control.
+
+Parent node required properties:
+- compatible: Must be "qcom,qpnp-smbcharger"
+- #address-cells: Must be <1>
+- #size-cells: Must be <1>
+- qcom,pmic-revid: Should specify the phandle of PMIC
+ revid module. This is used to identify
+ the PMIC subtype.
+
+
+
+Sub node required properties:
+- reg: The SPMI address for this peripheral
+- interrupts: Specifies the interrupt associated with the peripheral.
+- interrupt-names: Specifies the interrupt names for the peripheral. Every
+ available interrupt needs to have an associated name
+ with it to indentify its purpose.
+
+ The following lists each subnode and their corresponding
+ required interrupt names:
+
+ qcom,chgr:
+ - chg-tcc-thr: Triggers on charge completion.
+ - chg-taper-thr: Triggers on the taper charge
+ transtion.
+ - chg-inhibit: Notifies on battery voltage
+ being too high to resume
+ charging.
+ - chg-p2f-thr: Triggers on transitioning from
+ precharge to fastcharge.
+ - chg-rechg-thr: Triggers on battery voltage
+ falling below the resume
+ threshold.
+
+ qcom,bat-if:
+ - batt-hot: Triggers on battery temperature
+ hitting the hot threshold.
+ Charging stops.
+ - batt-warm: Triggers on battery temperature
+ hitting the warm threshold.
+ Charging current is reduced.
+ - batt-cool: Triggers on battery temperature
+ hitting the cool threshold.
+ Charging current is reduced
+ - batt-cold: Triggers on battery temperature
+ hitting the cold threshold.
+ Charging stops.
+ - batt-missing: Battery missing status
+ interrupt.
+ - batt-low: Triggers on battery voltage
+ falling across a low threshold.
+
+ qcom,usb-chgpth:
+ - usbin-uv: USB input voltage falls below a
+ valid threshold.
+ - usbin-src-det: USB automatic source detection
+ finishes.
+
+ qcom,dc-chgpth:
+ - dcin-uv: DC input voltage falls below a
+ valid threshold.
+
+ qcom,chgr-misc:
+ - wdog-timeout-mins: Charger watchdog timer
+ interrupt.
+ - temp-shutdown: Triggers when charger goes
+ overtemp and causes a shutdown.
+ - power-ok: Triggers when the charger
+ switcher turns on or off.
+
+Regulator Subnodes:
+- qcom,smbcharger-boost-otg A subnode for a regulator device that turns on
+ the charger boost for OTG operation.
+- qcom,smbcharger-external-otg A subnode for a regulator device that switches
+ off charging and the USB input charge path
+ in order to allow an external regulator to
+ operate. This can be used in place of the
+ qcom,smbcharger-boost-otg if an external boost
+ is available.
+
+Regulator Sub node required properties:
+- regulator-name A name string for the regulator in question
+
+Optional Properties:
+- qcom,battery-psy-name The name of the main battery power supply that
+ the charger will register. Failing to define
+ this property will default the name to
+ "battery".
+- qcom,bms-psy-name The psy name to use for reporting battery
+ capacity. If left unspecified the capacity uses
+ a preprogrammed default value of 50.
+- qcom,float-voltage-mv Float Voltage in mV - the maximum voltage up
+ to which the battery is charged. Supported
+ range 3600mV to 4500mV
+- qcom,float-voltage-comp Specifies the JEITA float voltage compensation.
+ Value ranges from 0 to 63.
+- qcom,fastchg-current-ma Specifies the fast charge current in mA. Supported
+ range is from 300mA to 3000mA.
+- qcom,fastchg-current-comp Specifies the fast charge current compensation in
+ mA. Supported values are 250, 700, 900 and 1200mA.
+- qcom,charging-timeout-mins Maximum duration in minutes that a single
+ charge cycle may last. Supported values are:
+ 0, 192, 384, 768, and 1536. A value of 0
+ means that no charge cycle timeout is used and
+ charging can continue indefinitely.
+- qcom,precharging-timeout-mins Maximum duration in minutes that a single
+ precharge cycle may last. Supported values
+ are: 0, 24, 48, 96, 192. A value of 0 means
+ that no precharge cycle timeout is used and
+ charging can continue indefinitely. Note that
+ the qcom,charging-timeout-mins property must
+ be specified in order for this to take effect.
+- qcom,dc-psy-type The type of charger connected to the DC path.
+ Can be "Mains", "Wireless" or "Wipower"
+- qcom,dc-psy-ma The current in mA dc path can support. Must be
+ specified if dc-psy-type is specified. Valid
+ range 300mA to 2000mA.
+- qcom,dcin-vadc The phandle to pmi8994 voltage adc. The ADC is
+ used to get notifications when the DCIN voltage
+ crosses a programmed min/max threshold. This is
+ used to make configurations for optimized power
+ draw for Wipower.
+- qcom,wipower-div2-ilim-map
+- qcom,wipower-pt-ilim-map
+- qcom,wipower-default-ilim-map
+ Array of 5 elements to indicate the voltage ranges and their corresponding
+ current limits. The 5 elements with index [0..4] are:
+ [0] => voltage_low in uV
+ [1] => voltage_high in uV
+ [2] => current limit for pass through in mA
+ [3] => current limit for div2 mode dcin low voltage in mA
+ [4] => current limit for div2 mode dcin high voltage in mA
+ The div2 and pt tables indicate the current limits
+ to use when Wipower is operating in divide_by_2 mode
+ and pass through mode respectively.
+ The default table is used when the voltage ranges
+ are beyond the ones specified in the mapping table.
+ Note that if dcin-vadc or any of these mapping
+ tables are not specified, dynamic dcin input
+ is disabled.
+- qcom,charging-disabled Set this if charging should be disabled in the
+ build by default.
+- qcom,resume-delta-mv Specifies the minimum voltage drop in
+ millivolts below the float voltage that is
+ required in order to initiate a new charging
+ cycle. Supported values are: 50, 100, 200 and
+ 300mV.
+- qcom,chg-inhibit-en Boolean that indicates whether the charge inhibit
+ feature needs to be enabled. If this is not set,
+ charge inhibit feature is disabled by default.
+- qcom,chg-inhibit-fg Indicates if the recharge threshold source has
+ to be Fuel gauge ADC. If this is not set, it
+ will be analog sensor by default.
+- qcom,bmd-algo-disabled Indicates if the battery missing detection
+ algorithm is disabled. If this node is present
+ SMB uses the THERM pin for battery missing
+ detection.
+- qcom,charge-unknown-battery Boolean that indicates whether an unknown
+ battery without a matching profile will be
+ charged. If this is not set, if the fuel gauge
+ does not recognize the battery based on its
+ battery ID, the charger will not start
+ charging.
+- qcom,bmd-pin-src A string that indicates the source pin for the
+ battery missind detection. This can be either:
+ - "bpd_none"
+ battery is considered always present
+ - "bpd_id"
+ battery id pin is used
+ - "bpd_thm"
+ battery therm pin is used
+ - "bpd_thm_id"
+ both pins are used (battery is
+ considered missing if either pin is
+ floating).
+- qcom,iterm-ma Specifies the termination current to indicate
+ end-of-charge. Possible values in mA:
+ 50, 100, 150, 200, 250, 300, 500, 600.
+- qcom,iterm-disabled Disables the termination current feature. This
+ is a boolean property.
+- otg-parent-supply A phandle to an external boost regulator for
+ OTG if it exists.
+- qcom,thermal-mitigation: Array of input current limit values for
+ different system thermal mitigation levels.
+ This should be a flat array that denotates the
+ maximum charge current in mA for each thermal
+ level.
+- qcom,rparasitics-uohm: The parasitic resistance of the board following
+ the line from the battery connectors through
+ vph_power. This is used to calculate maximum
+ available current of the battery.
+- qcom,vled-max-uv: The maximum input voltage of the flash leds.
+ This is used to calculate maximum available
+ current of the battery.
+- qcom,autoadjust-vfloat A boolean property that when set, makes the
+ driver automatically readjust vfloat using the
+ fuel gauge ADC readings to make charging more
+ accurate.
+- qcom,jeita-temp-hard-limit property when present will enable or disable
+ the jeita temperature hard limit based on the
+ value 1 or 0. Specify 0 if the jeita temp hard
+ limit needs to be disabled. If it is not present,
+ jeita temperature hard limit will be based on what
+ the bootloader had set earlier.
+- qcom,low-volt-dcin: A boolean property which upon set will enable the
+ AICL deglitch configuration dynamically. This needs
+ to be set if the DCIN supply is going to be less
+ than or equal to 5V.
+- qcom,force-aicl-rerun: A boolean property which upon set will enable the
+ AICL rerun by default along with the deglitch time
+ configured to long interval (20 ms). Also, specifying
+ this property will not adjust the AICL deglitch time
+ dynamically for handling the battery over-voltage
+ oscillations when the charger is headroom limited.
+- qcom,aicl-rerun-period-s If force-aicl-rerun is on, this property dictates
+ how often aicl is reran in seconds. Possible values
+ are 45, 90, 180, and 360.
+- qcom,ibat-ocp-threshold-ua Maximum current before the battery will trigger
+ overcurrent protection. Use the recommended
+ battery pack value minus some margin.
+- qcom,soft-vfloat-comp-disabled Set this property when the battery is
+ powered via external source and could
+ go above the float voltage.
+- qcom,parallel-usb-min-current-ma Minimum current drawn by the primary
+ charger before enabling the parallel
+ charger if one exists. Do not define
+ this property if no parallel chargers
+ exist.
+- qcom,parallel-usb-9v-min-current-ma Minimum current drawn by the primary
+ charger before enabling the parallel
+ charger if one exists. This property
+ applies only for 9V chargers.
+- qcom,parallel-allowed-lowering-ma Acceptable current drop from the initial limit
+ to keep parallel charger activated. If the
+ charger current reduces beyond this threshold
+ parallel charger is disabled. Must be specified
+ if parallel charger is used.
+- qcom,parallel-main-chg-fcc-percent Percentage of the fast charge current allotted to the
+ main charger when parallel charging is enabled and
+ operational. If this property is not defined, the
+ driver defaults to a 50%/50% split between the main
+ and parallel charger.
+- qcom,parallel-main-chg-icl-percent Percentage of the input current allotted to the
+ main charger when parallel charging is enabled and
+ operational. If this property is not defined, the
+ driver defaults to a 60%/40% split between the main
+ and parallel charger.
+- qcom,battery-data Points to the phandle of node which
+ contains the battery-profiles supported
+ by the charger/FG.
+- qcom,chg-led-support A bool property to support the charger led feature.
+- qcom,chg-led-sw-controls A bool property to allow the software to control
+ the charger led without a valid charger.
+- qcom,skip-usb-notification A boolean property to be used when usb gets present
+ and type from other means. Especially true on
+ liquid hardware, where usb presence is detected based on GPIO.
+- qcom,skip-usb-suspend-for-fake-battery A boolean property to skip
+ suspending USB path for fake
+ battery.
+- qcom,vchg_sns-vadc Phandle of the VADC node.
+- qcom,vchg-adc-channel-id The ADC channel to which the VCHG is routed.
+
+Example:
+ qcom,qpnp-smbcharger {
+ compatible = "qcom,qpnp-smbcharger";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ qcom,iterm-ma = <100>;
+ qcom,float-voltage-mv = <4200>;
+ qcom,resume-delta-mv = <100>;
+ qcom,bmd-pin-src = "bpd_thm_id";
+ qcom,dc-psy-type = "Mains";
+ qcom,dc-psy-ma = <1500>;
+ qcom,bms-psy-name = "bms";
+ qcom,battery-psy-name = "battery";
+ qcom,thermal-mitigation = <1500 700 600 325>;
+ qcom,vchg_sns-vadc = <&pmi8950_vadc>;
+ qcom,vchg-adc-channel-id = <3>;
+
+ qcom,chgr@1000 {
+ reg = <0x1000 0x100>;
+ interrupts = <0x2 0x10 0x0>,
+ <0x2 0x10 0x1>,
+ <0x2 0x10 0x2>,
+ <0x2 0x10 0x3>,
+ <0x2 0x10 0x4>,
+ <0x2 0x10 0x5>,
+ <0x2 0x10 0x6>,
+ <0x2 0x10 0x7>;
+
+ interrupt-names = "chg-error",
+ "chg-inhibit",
+ "chg-prechg-sft",
+ "chg-complete-chg-sft",
+ "chg-p2f-thr",
+ "chg-rechg-thr",
+ "chg-taper-thr",
+ "chg-tcc-thr";
+ };
+
+ qcom,otg@1100 {
+ reg = <0x1100 0x100>;
+ };
+
+ qcom,bat-if@1200 {
+ reg = <0x1200 0x100>;
+ interrupts = <0x2 0x12 0x0>,
+ <0x2 0x12 0x1>,
+ <0x2 0x12 0x2>,
+ <0x2 0x12 0x3>,
+ <0x2 0x12 0x4>,
+ <0x2 0x12 0x5>,
+ <0x2 0x12 0x6>,
+ <0x2 0x12 0x7>;
+
+ interrupt-names = "batt-hot",
+ "batt-warm",
+ "batt-cold",
+ "batt-cool",
+ "batt-ov",
+ "batt-low",
+ "batt-missing",
+ "batt-term-missing";
+ };
+
+ qcom,usb-chgpth@1300 {
+ reg = <0x1300 0x100>;
+ interrupts = <0x2 0x13 0x0>,
+ <0x2 0x13 0x1>,
+ <0x2 0x13 0x2>,
+ <0x2 0x13 0x3>,
+ <0x2 0x13 0x4>,
+ <0x2 0x13 0x5>,
+ <0x2 0x13 0x6>;
+
+ interrupt-names = "usbin-uv",
+ "usbin-ov",
+ "usbin-src-det",
+ "otg-fail",
+ "otg-oc",
+ "aicl-done",
+ "usbid-change";
+ };
+
+ qcom,dc-chgpth@1400 {
+ reg = <0x1400 0x100>;
+ interrupts = <0x2 0x14 0x0>,
+ <0x2 0x14 0x1>;
+
+ interrupt-names = "dcin-uv",
+ "dcin-ov";
+ };
+
+ qcom,chgr-misc@1600 {
+ reg = <0x1600 0x100>;
+ interrupts = <0x2 0x16 0x0>,
+ <0x2 0x16 0x1>,
+ <0x2 0x16 0x2>,
+ <0x2 0x16 0x3>,
+ <0x2 0x16 0x4>,
+ <0x2 0x16 0x5>;
+
+ interrupt-names = "power-ok",
+ "temp-shutdown",
+ "wdog-timeout",
+ "flash-fail",
+ "otst2",
+ "otst3";
+ };
+ };
diff --git a/Documentation/devicetree/bindings/power/qpnp-vm-bms.txt b/Documentation/devicetree/bindings/power/qpnp-vm-bms.txt
new file mode 100644
index 000000000000..82871b58a847
--- /dev/null
+++ b/Documentation/devicetree/bindings/power/qpnp-vm-bms.txt
@@ -0,0 +1,179 @@
+Qualcomm's QPNP Voltage-Mode(VM) PMIC Battery Management System
+
+QPNP PMIC VM BMS provides interface to clients to read properties related
+to the battery. Its main function is to calculate the SOC (state of charge)
+of the battery based on periodic sampling of the VBAT (battery voltage).
+
+Parent node required properties:
+- compatible : Must be "qcom,qpnp-vm-bms" for the BM driver.
+- reg : Offset and length of the PMIC peripheral register map.
+- interrupts : The interrupt mappings.
+ The format should be
+ <slave-id peripheral-id interrupt-number>.
+- interrupt-names : names for the mapped bms interrupt
+ The following interrupts are required:
+ 0 : leave CV state
+ 1 : enter CV state
+ 2 : good ocv generated
+ 3 : ocv_thr
+ 4 : fifo update
+ 5 : fsm state chnaged
+
+Additionally, optional subnodes may be included:
+- qcom,batt-pres-status : A subnode with a register address for the SMBB
+ battery interface's BATT_PRES_STATUS register. If this node is
+ added, then the BMS will try to detect offmode battery removal
+ via the battery interface's offmode battery removal circuit.
+- qcom,battery-data : A phandle to a node containing the available batterydata
+ profiles. See the batterydata bindings documentation for more
+ details.
+
+Parent node required properties:
+- qcom,v-cutoff-uv : cutoff voltage where the battery is considered dead in
+ micro-volts.
+- qcom,max-voltage-uv : maximum voltage for the battery in micro-volts.
+- qcom,r-conn-mohm : connector resistance in milli-ohms.
+- qcom,shutdown-soc-valid-limit : If the ocv upon restart is within this
+ distance of the shutdown ocv, the BMS will try to force
+ the new SoC to the old one to provide charge continuity.
+ That is to say,
+ if (abs(shutdown-soc - current-soc) < limit)
+ then use old SoC.
+- qcom,low-soc-calculate-soc-threshold : The SoC threshold for when
+ the periodic calculate_soc work speeds up. This ensures
+ SoC is updated in userspace constantly when we are near
+ shutdown.
+- qcom,low-voltage-threshold : The battery voltage threshold in micro-volts for
+ when the BMS tries to wake up and hold a wakelock to
+ ensure a clean shutdown.
+- qcom,low-voltage-calculate-soc-ms : The time period between subsequent
+ SoC recalculations when the current voltage is below
+ qcom,low-voltage threshold. This takes precedence over
+ qcom,low-soc-calculate-soc-ms.
+- qcom,low-soc-calculate-soc-ms : The time period between subsequent
+ SoC recalculations when the current SoC is below
+ qcom,low-soc-calculate-soc-threshold. This takes
+ precedence over qcom,calculate-soc-ms.
+- qcom,calculate-soc-ms : The time period between subsequent SoC
+ recalculations when the current SoC is above or equal
+ qcom,low-soc-calculate-soc-threshold.
+- qcom,volatge-soc-timeout-ms : The timeout period after which the module starts
+ reporting volage based SOC and does not use the VMBMS
+ algorithm for SOC calculation.
+- qcom,bms-vadc: Corresponding VADC device's phandle.
+- qcom,bms-adc_tm: Corresponding ADC_TM device's phandle to set recurring
+ measurements and receive notifications for vbatt.
+- qcom,pmic-revid : Phandle pointing to the revision peripheral node.
+
+Parent node Optional properties
+- qcom,s1-sample-interval-ms: The sampling rate in ms of the accumulator in state
+ S1. (i.e) the rate at which the accumulator is being
+ filled with vbat samples. Minimum value = 0 and
+ Maximum value = 2550ms.
+- qcom,s2-sample-interval-ms: The sampling rate in ms of the accumulator in state
+ S2. (i.e) the rate at which the accumulator is being
+ filled with vbat samples. Minimum value = 0 and
+ Maximum value = 2550ms.
+- qcom,s1-sample-count: The number of samples to be accululated for one FIFO in
+ state S1. Possible values are - 0, 4, 8, 16, 32, 64, 128,
+ 256.
+- qcom,s2-sample-count: The number of samples to be accululated for one FIFO in
+ state S2. Possible values are - 0, 4, 8, 16, 32, 64, 128,
+ 256.
+- qcom,s1-fifo-legth: Number of FIFO's to be filled in state S1, to generate
+ the fifo_update_done interrupt. Possile values - 0 to 8
+- qcom,s2-fifo-legth: Number of FIFO's to be filled in state S2, to generate
+ the fifo_update_done interrupt. Possible values- 0 to 8
+- qcom,force-s3-on-suspend : Bool property to force the BMS into S3 (sleep) state
+ while entering into system suspend.
+- qcom,force-bms-active-on-charger: Bool property to keep BMS FSM active
+ if charger is present.
+- qcom,report-charger-eoc : Bool property to indicate if BMS needs to indicate
+ EOC to charger.
+- qcom,ignore-shutdown-soc: A boolean that controls whether BMS will
+ try to force the startup SoC to be the same as the
+ shutdown SoC. Defining it will make BMS ignore the
+ shutdown SoC.
+- qcom,use-voltage-soc : A boolean that controls whether BMS will use
+ voltage-based SoC instead of a coulomb counter based
+ one. Voltage-based SoC will not guarantee linearity.
+- qcom,disable-bms : Bool property to disable the VMBMS hardware module.
+ Enable this property if BMS is not supported or an external
+ fuel gauge is used.
+- qcom,s3-ocv-tolerence-uv : The S3 state OCV tolerence threshold in uV. The
+ LSB value is 300uV and maximum value is 76500uV.
+- qcom,low-soc-fifo-length : The fifo length (of S2 STATE) to be used at lower
+ SOCs. If this value is not specified the system uses
+ default lenght.
+- qcom,resume-soc: Capacity in percent at which charging should resume
+ when a fully charged battery drops below this level.
+- qcom,low-temp-threshold : The temperature threshold below which the IBAT
+ averaging and UUC smoothening is disabled. This value
+ is in deci-degrees centigrade. If not specified it
+ defaults to 0.
+- qcom,ibat-avg-samples : The number of samples to be averaged for IBAT
+ estimation. If not specified it defaults to 16.
+ The possible values are 1 to 16.
+- qcom,batt-aging-comp : A boolean that defines if battery aging compensation
+ is enabled.
+- qcom,use-reported-soc : Bool property to enable the reported_soc logic. To
+ enable this feature, qcom,resume-soc must be defined as
+ a proper value. The BMS is also required to control the
+ charging, discharging and recharging.
+
+qcom,batt-pres-status node required properties:
+- reg : offset and length of the PMIC LBC battery interface BATT_PRES_STATUS
+ register.
+
+qcom,qpnp-chg-pres required properties:
+- reg : offset and length of the PMIC LBC charger interafce CHARGER_OPTION
+ register.
+
+Example:
+pm8916_bms: qcom,qpnp-vm-bms {
+ compatible = "qcom,qpnp-vm-bms";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ status = "disabled";
+
+ qcom,v-cutoff-uv = <3400000>;
+ qcom,max-voltage-uv = <4200000>;
+ qcom,r-conn-mohm = <18>;
+ qcom,shutdown-soc-valid-limit = <20>;
+ qcom,low-soc-calculate-soc-threshold = <15>;
+ qcom,low-voltage-threshold = <3420000>;
+ qcom,low-voltage-calculate-soc-ms = <1000>;
+ qcom,low-soc-calculate-soc-ms = <5000>;
+ qcom,low-soc-fifo-length = <2>;
+ qcom,calculate-soc-ms = <20000>;
+ qcom,s3-ocv-tolerence-uv = <1200>;
+ qcom,volatge-soc-timeout-ms = <60000>;
+ qcom,battery-data = <&mtp_batterydata>;
+ qcom,bms-vadc = <&pm8916_vadc>;
+ qcom,bms-adc_tm = <&pm8916_adc_tm>;
+
+ qcom,batt-pres-status@1208 {
+ reg = <0x1208 0x1>;
+ }
+
+ qcom,qpnp-chg-pres@1208 {
+ reg = <0x1108 0x1>;
+ }
+
+ qcom,bms-bms@4000 {
+ reg = <0x4000 0x100>;
+ interrupts = <0x0 0x40 0x0>,
+ <0x0 0x40 0x1>,
+ <0x0 0x40 0x2>,
+ <0x0 0x40 0x3>,
+ <0x0 0x40 0x4>,
+ <0x0 0x40 0x5>,
+
+ interrupt-names = "leave_cv",
+ "enter_cv",
+ "good_ocv",
+ "ocv_thr",
+ "fifo_updtaed",
+ "fsm_state_change";
+ };
+};
diff --git a/Documentation/devicetree/bindings/regulator/qpnp-labibb-regulator.txt b/Documentation/devicetree/bindings/regulator/qpnp-labibb-regulator.txt
new file mode 100644
index 000000000000..e19f9b9aef9d
--- /dev/null
+++ b/Documentation/devicetree/bindings/regulator/qpnp-labibb-regulator.txt
@@ -0,0 +1,265 @@
+QTI's LAB (LCD/AMOLED BOOST)/IBB (Inverting Buck-Boost) Regulator
+
+LAB can be used as a standalone positive boost power supply for general purpose
+applications. IBB can be used as a standalone negative power supply for general
+applications. Also, LAB and IBB can be used together to provide power supply for
+display panels, LCD or AMOLED.
+
+Main node required properties:
+
+- compatible: Must be "qcom,qpnp-labibb-regulator"
+- qpnp,qpnp-labibb-mode: A string used to specify the working mode of LAB/IBB
+ regulators when bootloader does not turned on the
+ display panel. Could be "lcd", "amoled" or
+ "stand-alone".
+ "lcd" means using LAB and IBB regulators are
+ configured for LCD mode together.
+ "amoled" means using LAB and IBB regulators are
+ configured for AMOLED mode together.
+ "stand-alone" means using LAB and IBB regulators
+ as stand alone regulators.
+
+Main node optional properties:
+
+- qcom,qpnp-labibb-touch-to-wake-en: A boolean property which upon set will
+ enable support for touch-to-wake mode
+ by configuring the required settings
+ in LAB and IBB modules. Make sure the
+ hardware has needed support before
+ enabling this property.
+- qpnp,swire-control: A bool property which indicates if the LAB/IBB is
+ controlled by the SWIRE interface. Enable only
+ if qpnp,qpnp-labibb-mode = "amoled".
+
+LAB subnode required properties:
+
+- reg: Specifies the SPMI address and size for this peripheral.
+- reg-names: Register names. Must be "lab".
+- regulator-name: A string used to describe the regulator.
+- regulator-min-microvolt: Minimum voltage in microvolts supported by this regulator.
+- regulator-max-microvolt: Maximum voltage in microvolts supported by this regulator.
+
+- qcom,qpnp-lab-min-voltage: The minimum voltage in microvolts LAB regulator can support.
+- qcom,qpnp-lab-step-size: The step size in microvolts of LAB regulator.
+- qcom,qpnp-lab-slew-rate: The time in us taken by the regulator to change
+ voltage value in one step.
+
+- qcom,qpnp-lab-init-voltage: The default initial voltage when the bootloader
+ does not turn on LAB regulator.
+- qcom,qpnp-lab-init-amoled-voltage: The default output voltage when LAB regulator
+ is configured in amoled mode.
+- qcom,qpnp-lab-init-lcd-voltage: The default output voltage when LAB regulator
+ is configured in lcd mode.
+- qcom,qpnp-lab-soft-start: The soft start time in us of LAB regulator.
+ Supported value are 200, 400, 600 and 800.
+
+- qcom,qpnp-lab-ps-threshold: The threshold in mA of Pulse Skip Mode for
+ LAB regulator. Supported values are 20, 30,
+ 40 and 50.
+- qcom,qpnp-lab-pfet-size: PFET size in percentage. Supported values
+ are 25, 50, 75 and 100.
+- qcom,qpnp-lab-nfet-size: NFET size in percentage. Supported values
+ are 25, 50, 75 and 100.
+- qcom,qpnp-lab-max-precharge-time: Precharge time in us of LAB regulator.
+ Supported values are 200, 300, 400 and 500.
+- qcom,qpnp-lab-switching-clock-frequency: The PWM switching clock frequency in
+ kHz of Lab regulator, Supported values
+ are: 3200, 2740, 2400, 2130, 1920,
+ 1750, 1600, 1480, 1370, 1280, 1200,
+ 1130, 1070, 1010, 960, 910.
+- qcom,qpnp-lab-limit-maximum-current: The maximum inductor current limit in
+ mA of LAB regulator. Supported values
+ are 200, 400, 600 and 800.
+
+LAB subnode optional properties:
+
+- qpnp,qpnp-lab-current-sense: If this property is specified, the LAB current
+ sense gain will be programmed for LAB regulator.
+ Otherwise, LAB current sense gain will be
+ default to "1x". A string is used to specify the
+ LAB current sense gain. Could be "0.5x" or "1x"
+ or "1.5x" or "2x". For e.g. "0.5x" means current
+ sense gain is 0.5.
+- qcom,qpnp-lab-ps-enable: A boolean proerty which upon set will enable
+ pulse skip mode for LAB regulator. Otherwise,
+ it is disabled.
+- qcom,qpnp-lab-full-pull-down: A boolean property which upon set will enable
+ the pull down strength of LAB regulator to
+ full. Otherwise, the pull down strength is
+ configured to half.
+- qcom,qpnp-lab-pull-down-enable: A boolean property which upon set will enable
+ the pull down for LAB regulator. Otherwise,
+ it is disabled.
+- qcom,qpnp-lab-max-precharge-enable: A boolean property which upon set will
+ enable fast precharge. Otherwise, it is
+ disabled.
+- qcom,qpnp-lab-ring-suppression-enable: A boolean property which upon set will
+ enable ring suppression for LAB
+ regulator. Otherwise, it is disabled.
+- qcom,qpnp-lab-limit-max-current-enable: A boolean property which upon set will
+ enforce maximum inductor current constraint
+ for LAB regulator. Otherwise, there is no
+ maximum current constraint.
+- qcom,qpnp-lab-use-default-voltage: A boolean property which upon set will
+ use the value specified in
+ qcom,qpnp-lab-init-voltage property.
+ This will be used only if the bootloader
+ doesn't configure the output voltage
+ already. If it it not specified, then
+ output voltage can be configured to
+ any value in the allowed limit.
+
+IBB subnode required properties:
+
+- reg: Specifies the SPMI address and size for this peripheral.
+- reg-names: Register names. Must be "ibb".
+- regulator-name: A string used to describe the regulator.
+- regulator-min-microvolt: Minimum voltage in microvolts supported by this regulator.
+- regulator-max-microvolt: Maximum voltage in microvolts supported by this regulator.
+
+- qcom,qpnp-ibb-min-voltage: The minimum voltage in microvolts IBB regulator can support.
+- qcom,qpnp-ibb-step-size: The step size in microvolts of IBB regulator.
+- qcom,qpnp-ibb-slew-rate: The time in us taken by the regulator to change
+ voltage value in one step.
+- qcom,qpnp-ibb-soft-start: The soft start time in us of IBB regulator.
+
+- qcom,qpnp-ibb-init-voltage: The default initial voltage when the bootloader does
+ not turn on IBB regulator.
+- qcom,qpnp-ibb-init-amoled-voltage: The default output voltage when IBB regulator
+ is configured in amoled mode.
+- qcom,qpnp-ibb-init-lcd-voltage: The default output voltage when IBB regulator
+ is configured in lcd mode.
+
+- qcom,qpnp-ibb-discharge-resistor: The discharge resistor in Kilo Ohms which
+ controls the soft start time. Supported values
+ are 300, 64, 32 and 16.
+- qcom,qpnp-ibb-lab-pwrup-delay: Power up delay (in us) for IBB regulator when
+ it is enabled or turned on. Supported values
+ are 1000, 2000, 4000 and 8000.
+- qcom,qpnp-ibb-lab-pwrdn-delay: Power down delay (in us) for IBB regulator
+ when it is disabled or turned off. Supported
+ values are 1000, 2000, 4000 and 8000.
+
+- qcom,qpnp-ibb-switching-clock-frequency: The PWM switching clock frequency in
+ kHz of IBB regulator. Supported values
+ are: 3200, 2740, 2400, 2130, 1920,
+ 1750, 1600, 1480, 1370, 1280, 1200,
+ 1130, 1070, 1010, 960, 910.
+- qcom,qpnp-ibb-limit-maximum-current: The maximum inductor current limit in
+ mA of IBB regulator. Supported values
+ are: 0, 50, 100, 150, 200, 250, 300,
+ 350, 400, 450, 500, 550, 600, 650, 700,
+ 750, 800, 850, 900, 950, 1000, 1050,
+ 1100, 1150, 1200, 1250, 1300, 1350,
+ 1400, 1450, 1500 and 1550.
+- qcom,qpnp-ibb-debounce-cycle: The debounce cycle of IBB regulator.
+ Supported values are 8, 16, 32 and 64.
+
+IBB subnode optional properties:
+
+- qcom,qpnp-ibb-ps-enable: A boolean property which upon set will enable
+ pulse skip mode for IBB regulator. Otherwise,
+ it is disabled.
+- qcom,qpnp-ibb-full-pull-down: A boolean property which upon set will enable
+ the pull down strength of IBB regulator to
+ full. Otherwise, the pull down strength is
+ configured to half.
+- qcom,qpnp-ibb-pull-down-enable: A boolean property which upon set will enable
+ the pull down for IBB regulator. Otherwise,
+ it is disabled.
+- qcom,qpnp-ibb-en-discharge: A boolean property which upon set will
+ enable discharge for IBB regulator.
+ Otherwise, it is kept disabled.
+- qcom,qpnp-ibb-ring-suppression-enable: A boolean property which upon set will
+ enable ring suppression for IBB
+ regulator. Otherwise, it is disabled.
+- qcom,qpnp-ibb-limit-max-current-enable: A boolean property which upon set will
+ enforce maximum inductor current constraint
+ for IBB regulator. Otherwise, there is no
+ maximum current constraint.
+- qcom,qpnp-ibb-use-default-voltage: A boolean property which upon set will
+ use the value specified in
+ qcom,qpnp-ibb-init-voltage property.
+ This will be used only if the bootloader
+ doesn't configure the output voltage
+ already. If it it not specified, then
+ output voltage can be configured to
+ any value in the allowed limit.
+- qcom,output-voltage-one-pulse The expected voltage (in mV) of VDISN signal
+ on the first SWIRE pulse. This property
+ can be specified only if 'qpnp,swire-control'
+ is defined. The minimum and maximum values
+ are 1400mV and 7700mV.
+
+Example:
+ qcom,pmi8994@3 {
+ qpnp-labibb-regulator {
+ compatible = "qcom,qpnp-labibb-regulator";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ qpnp,qpnp-labibb-mode = "lcd";
+
+ lab_regulator: qcom,lab@de00 {
+ reg = <0xde00 0x100>;
+ reg-names = "lab";
+ regulator-name = "lab_reg";
+
+ regulator-min-microvolt = <4600000>;
+ regulator-max-microvolt = <6000000>;
+
+ qcom,qpnp-lab-min-voltage = <4600000>;
+ qcom,qpnp-lab-step-size = <100000>;
+ qcom,qpnp-lab-slew-rate = <5000>;
+ qcom,qpnp-lab-use-default-voltage;
+ qcom,qpnp-lab-init-voltage = <5500000>;
+ qcom,qpnp-lab-init-amoled-voltage = <4600000>;
+ qcom,qpnp-lab-init-lcd-voltage = <5500000>;
+
+ qcom,qpnp-lab-soft-start = <400>;
+
+ qcom,qpnp-lab-full-pull-down;
+ qcom,qpnp-lab-pull-down-enable;
+ qcom,qpnp-lab-switching-clock-frequency = <1600>;
+ qcom,qpnp-lab-limit-maximum-current = <800>;
+ qcom,qpnp-lab-limit-max-current-enable;
+ qcom,qpnp-lab-ps-threshold = <40>;
+ qcom,qpnp-lab-ps-enable;
+ qcom,qpnp-lab-nfet-size = <100>;
+ qcom,qpnp-lab-pfet-size = <100>;
+ qcom,qpnp-lab-max-precharge-time = <200>;
+ };
+
+ ibb_regulator: qcom,ibb@dc00 {
+ reg = <0xdc00 0x100>;
+ reg-names = "ibb_reg";
+ regulator-name = "ibb_reg";
+
+ regulator-min-microvolt = <4600000>;
+ regulator-max-microvolt = <6000000>;
+
+ qcom,qpnp-ibb-min-voltage = <1400000>;
+ qcom,qpnp-ibb-step-size = <100000>;
+ qcom,qpnp-ibb-slew-rate = <2000000>;
+ qcom,qpnp-ibb-use-default-voltage;
+ qcom,qpnp-ibb-init-voltage = <5500000>;
+ qcom,qpnp-ibb-init-amoled-voltage = <4000000>;
+ qcom,qpnp-ibb-init-lcd-voltage = <5500000>;
+
+ qcom,qpnp-ibb-soft-start = <400>;
+
+ qcom,qpnp-ibb-discharge-resistor = <300>;
+ qcom,qpnp-ibb-lab-pwrup-delay = <8000>;
+ qcom,qpnp-ibb-lab-pwrdn-delay = <8000>;
+ qcom,qpnp-ibb-en-discharge;
+
+ qcom,qpnp-ibb-full-pull-down;
+ qcom,qpnp-ibb-pull-down-enable;
+ qcom,qpnp-ibb-switching-clock-frequency = <1480>;
+ qcom,qpnp-ibb-limit-maximum-current = <1550>;
+ qcom,qpnp-ibb-debounce-cycle = <16>;
+ qcom,qpnp-ibb-limit-max-current-enable;
+ qcom,qpnp-ibb-ps-enable;
+ };
+
+ };
+ };
diff --git a/Documentation/devicetree/bindings/regulator/qpnp-regulator.txt b/Documentation/devicetree/bindings/regulator/qpnp-regulator.txt
new file mode 100644
index 000000000000..e1ebaf636ec3
--- /dev/null
+++ b/Documentation/devicetree/bindings/regulator/qpnp-regulator.txt
@@ -0,0 +1,151 @@
+Qualcomm QPNP Regulators
+
+qpnp-regulator is a regulator driver which supports regulators inside of PMICs
+that utilize the MSM SPMI implementation.
+
+Required properties:
+- compatible: Must be "qcom,qpnp-regulator"
+- reg: Specifies the SPMI address and size for this regulator device
+ Note, this is the only property which can be used within a
+ subnode.
+- regulator-name: A string used as a descriptive name for regulator outputs
+- parent-supply: phandle to the parent supply/regulator node
+
+Required structure:
+- A qcom,qpnp-regulator node must be a child of an spmi_device node.
+
+Optional properties:
+- interrupts: List of interrupts used by the regulator.
+- interrupt-names: List of strings defining the names of the
+ interrupts in the 'interrupts' property 1-to-1.
+ Supported values are "ocp" for voltage switch
+ type regulators. If an OCP interrupt is
+ specified, then the voltage switch will be
+ toggled off and back on when OCP triggers in
+ order to handle high in-rush current.
+- qcom,system-load: Load in uA present on regulator that is not
+ captured by any consumer request
+- qcom,enable-time: Time in us to delay after enabling the regulator
+- qcom,auto-mode-enable: 1 = Enable automatic hardware selection of
+ regulator mode (HPM vs LPM); not available on
+ boost type regulators
+ 0 = Disable auto mode selection
+- qcom,bypass-mode-enable: 1 = Enable bypass mode for an LDO type regulator
+ so that it acts like a switch and simply outputs
+ its input voltage
+ 0 = Do not enable bypass mode
+- qcom,ocp-enable: 1 = Allow over current protection (OCP) to be
+ enabled for voltage switch type regulators so
+ that they latch off automatically when over
+ current is detected. OCP is enabled when in
+ HPM or auto mode.
+ 0 = Disable OCP
+- qcom,ocp-max-retries: Maximum number of times to try toggling a voltage
+ switch off and back on as a result of
+ consecutive over current events.
+- qcom,ocp-retry-delay: Time to delay in milliseconds between each
+ voltage switch toggle after an over current
+ event takes place.
+- qcom,pull-down-enable: 1 = Enable output pull down resistor when the
+ regulator is disabled
+ 0 = Disable pull down resistor
+- qcom,soft-start-enable: 1 = Enable soft start for LDO and voltage switch
+ type regulators so that output voltage slowly
+ ramps up when the regulator is enabled
+ 0 = Disable soft start
+- qcom,boost-current-limit: This property sets the current limit of boost
+ type regulators; supported values are:
+ 0 = 300 mA
+ 1 = 600 mA
+ 2 = 900 mA
+ 3 = 1200 mA
+ 4 = 1500 mA
+ 5 = 1800 mA
+ 6 = 2100 mA
+ 7 = 2400 mA
+- qcom,pin-ctrl-enable: Bit mask specifying which hardware pins should be
+ used to enable the regulator, if any; supported
+ bits are:
+ 0 = ignore all hardware enable signals
+ BIT(0) = follow HW0_EN signal
+ BIT(1) = follow HW1_EN signal
+ BIT(2) = follow HW2_EN signal
+ BIT(3) = follow HW3_EN signal
+- qcom,pin-ctrl-hpm: Bit mask specifying which hardware pins should be
+ used to force the regulator into high power
+ mode, if any; supported bits are:
+ 0 = ignore all hardware enable signals
+ BIT(0) = follow HW0_EN signal
+ BIT(1) = follow HW1_EN signal
+ BIT(2) = follow HW2_EN signal
+ BIT(3) = follow HW3_EN signal
+ BIT(4) = follow PMIC awake state
+- qcom,vs-soft-start-strength: This property sets the soft start strength for
+ voltage switch type regulators; supported values
+ are:
+ 0 = 0.05 uA
+ 1 = 0.25 uA
+ 2 = 0.55 uA
+ 3 = 0.75 uA
+- qcom,hpm-enable: 1 = Enable high power mode (HPM), also referred
+ to as NPM. HPM consumes more ground current
+ than LPM, but it can source significantly higher
+ load current. HPM is not available on boost
+ type regulators. For voltage switch type
+ regulators, HPM implies that over current
+ protection and soft start are active all the
+ time. This configuration can be overwritten
+ by changing the regulator's mode dynamically.
+ 0 = Do not enable HPM
+- qcom,force-type: Override the type and subtype register values. Useful for some
+ regulators that have invalid types advertised by the hardware.
+ The format is two unsigned integers of the form <type subtype>.
+
+Note, if a given optional qcom,* binding is not present, then the qpnp-regulator
+driver will leave that feature in the default hardware state.
+
+All properties specified within the core regulator framework can also be used.
+These bindings can be found in regulator.txt.
+
+Example:
+ qcom,spmi@fc4c0000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupt-controller;
+ #interrupt-cells = <3>;
+
+ qcom,pm8941@1 {
+ reg = <0x1>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ regulator@1400 {
+ regulator-name = "8941_s1";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "qcom,qpnp-regulator";
+ reg = <0x1400 0x300>;
+ regulator-min-microvolt = <1300000>;
+ regulator-max-microvolt = <1400000>;
+
+ qcom,ctl@1400 {
+ reg = <0x1400 0x100>;
+ };
+ qcom,ps@1500 {
+ reg = <0x1500 0x100>;
+ };
+ qcom,freq@1600 {
+ reg = <0x1600 0x100>;
+ };
+ };
+
+ regulator@4000 {
+ regulator-name = "8941_l1";
+ reg = <0x4000 0x100>;
+ compatible = "qcom,qpnp-regulator";
+ regulator-min-microvolt = <1225000>;
+ regulator-max-microvolt = <1300000>;
+ qcom,pull-down-enable = <1>;
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/rtc/qpnp-rtc.txt b/Documentation/devicetree/bindings/rtc/qpnp-rtc.txt
index 156141fef71c..e0934b2aa82f 100644
--- a/Documentation/devicetree/bindings/rtc/qpnp-rtc.txt
+++ b/Documentation/devicetree/bindings/rtc/qpnp-rtc.txt
@@ -15,9 +15,6 @@ Required properties :
This must be set to '1'.
- #size-cells: The number of cells dedicated to represent address
space range of a peripheral. This must be set to '1'.
- - spmi-dev-container: This specifies that all the device nodes specified
- within this node should have their resources
- coalesced into a single spmi_device.
Optional properties:
- qcom,qpnp-rtc-write: This property enables/disables rtc write
@@ -44,7 +41,6 @@ Required properties :
Example:
qcom,pm8941_rtc {
- spmi-dev-container;
compatible = "qcom,qpnp-rtc";
#address-cells = <1>;
#size-cells = <1>;
diff --git a/arch/arm64/configs/msm_defconfig b/arch/arm64/configs/msm_defconfig
index 9fa187eb1228..5d229d82849a 100644
--- a/arch/arm64/configs/msm_defconfig
+++ b/arch/arm64/configs/msm_defconfig
@@ -205,3 +205,5 @@ CONFIG_CRYPTO_AES_ARM64_CE_CCM=y
CONFIG_CRYPTO_AES_ARM64_CE_BLK=y
CONFIG_CRYPTO_AES_ARM64_NEON_BLK=y
CONFIG_CRYPTO_CRC32_ARM64=y
+CONFIG_SPMI=y
+CONFIG_MFD_SPMI_PMIC=y
diff --git a/drivers/bif/Kconfig b/drivers/bif/Kconfig
index 917920bb9151..1a79ce8fbb08 100644
--- a/drivers/bif/Kconfig
+++ b/drivers/bif/Kconfig
@@ -13,8 +13,7 @@ menuconfig BIF
if BIF
config BIF_QPNP
- depends on SPMI || MSM_SPMI
- depends on OF_SPMI
+ depends on SPMI
tristate "Qualcomm QPNP BIF support"
help
This driver supports the QPNP BSI peripheral found inside of Qualcomm
diff --git a/drivers/bif/qpnp-bsi.c b/drivers/bif/qpnp-bsi.c
index c378a40a411d..d61eb39dc5bf 100644
--- a/drivers/bif/qpnp-bsi.c
+++ b/drivers/bif/qpnp-bsi.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -17,12 +17,14 @@
#include <linux/device.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
+#include <linux/regmap.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/spmi.h>
+#include <linux/platform_device.h>
#include <linux/workqueue.h>
#include <linux/bif/driver.h>
#include <linux/qpnp/qpnp-adc.h>
@@ -41,7 +43,8 @@ enum qpnp_bsi_com_mode {
struct qpnp_bsi_chip {
struct bif_ctrl_desc bdesc;
- struct spmi_device *spmi_dev;
+ struct platform_device *pdev;
+ struct regmap *regmap;
struct bif_ctrl_dev *bdev;
struct work_struct slave_irq_work;
u16 base_addr;
@@ -202,11 +205,13 @@ static inline int qpnp_bsi_read(struct qpnp_bsi_chip *chip, u16 addr, u8 *buf,
{
int rc;
- rc = spmi_ext_register_readl(chip->spmi_dev->ctrl,
- chip->spmi_dev->sid, chip->base_addr + addr, buf, len);
+ rc = regmap_bulk_read(chip->regmap, chip->base_addr + addr, buf, len);
if (rc)
- dev_err(&chip->spmi_dev->dev, "%s: spmi_ext_register_readl() failed. sid=%d, addr=%04X, len=%d, rc=%d\n",
- __func__, chip->spmi_dev->sid, chip->base_addr + addr,
+ dev_err(&chip->pdev->dev,
+ "%s: regmap_bulk_readl failed. sid=%d, addr=%04X, len=%d, rc=%d\n",
+ __func__,
+ to_spmi_device(chip->pdev->dev.parent)->usid,
+ chip->base_addr + addr,
len, rc);
return rc;
@@ -217,12 +222,14 @@ static inline int qpnp_bsi_write(struct qpnp_bsi_chip *chip, u16 addr, u8 *buf,
{
int rc;
- rc = spmi_ext_register_writel(chip->spmi_dev->ctrl,
- chip->spmi_dev->sid, chip->base_addr + addr, buf, len);
+ rc = regmap_bulk_write(chip->regmap, chip->base_addr + addr, buf, len);
if (rc)
- dev_err(&chip->spmi_dev->dev, "%s: spmi_ext_register_writel() failed. sid=%d, addr=%04X, len=%d, rc=%d\n",
- __func__, chip->spmi_dev->sid, chip->base_addr + addr,
+ dev_err(&chip->pdev->dev,
+ "%s: regmap_bulk_write failed. sid=%d, addr=%04X, len=%d, rc=%d\n",
+ __func__,
+ to_spmi_device(chip->pdev->dev.parent)->usid,
+ chip->base_addr + addr,
len, rc);
return rc;
@@ -278,14 +285,15 @@ static int qpnp_bsi_rx_tx_config(struct qpnp_bsi_chip *chip,
buf[1] = QPNP_BSI_TX_DISABLE | QPNP_BSI_RX_DISABLE;
break;
default:
- dev_err(&chip->spmi_dev->dev, "%s: invalid state=%d\n",
+ dev_err(&chip->pdev->dev, "%s: invalid state=%d\n",
__func__, state);
return -EINVAL;
}
rc = qpnp_bsi_write(chip, QPNP_BSI_REG_MODE, buf, 2);
if (rc)
- dev_err(&chip->spmi_dev->dev, "%s: qpnp_bsi_write() failed, rc=%d\n",
+ dev_err(&chip->pdev->dev,
+ "%s: qpnp_bsi_write() failed, rc=%d\n",
__func__, rc);
return rc;
@@ -403,7 +411,8 @@ static int qpnp_bsi_clear_bsi_error(struct qpnp_bsi_chip *chip)
rc = qpnp_bsi_read(chip, QPNP_BSI_REG_BSI_ERROR, &reg, 1);
if (rc) {
- dev_err(&chip->spmi_dev->dev, "%s: qpnp_bsi_read() failed, rc=%d\n",
+ dev_err(&chip->pdev->dev,
+ "%s: qpnp_bsi_read() failed, rc=%d\n",
__func__, rc);
return rc;
}
@@ -422,7 +431,8 @@ static int qpnp_bsi_clear_bsi_error(struct qpnp_bsi_chip *chip)
reg = QPNP_BSI_BSI_ERROR_CLEAR;
rc = qpnp_bsi_write(chip, QPNP_BSI_REG_CLEAR_ERROR, &reg, 1);
if (rc)
- dev_err(&chip->spmi_dev->dev, "%s: qpnp_bsi_write() failed, rc=%d\n",
+ dev_err(&chip->pdev->dev,
+ "%s: qpnp_bsi_write() failed, rc=%d\n",
__func__, rc);
}
@@ -436,7 +446,8 @@ static int qpnp_bsi_get_bsi_error(struct qpnp_bsi_chip *chip)
rc = qpnp_bsi_read(chip, QPNP_BSI_REG_BSI_ERROR, &reg, 1);
if (rc) {
- dev_err(&chip->spmi_dev->dev, "%s: qpnp_bsi_read() failed, rc=%d\n",
+ dev_err(&chip->pdev->dev,
+ "%s: qpnp_bsi_read() failed, rc=%d\n",
__func__, rc);
return rc;
}
@@ -451,7 +462,8 @@ static int qpnp_bsi_wait_for_tx(struct qpnp_bsi_chip *chip, int timeout)
/* Wait for TX or ERR IRQ. */
while (timeout > 0) {
if (qpnp_bsi_check_irq(chip, QPNP_BSI_IRQ_ERR)) {
- dev_err(&chip->spmi_dev->dev, "%s: transaction error occurred, BSI error=%d\n",
+ dev_err(&chip->pdev->dev,
+ "%s: transaction error occurred, BSI error=%d\n",
__func__, qpnp_bsi_get_bsi_error(chip));
return -EIO;
}
@@ -465,7 +477,8 @@ static int qpnp_bsi_wait_for_tx(struct qpnp_bsi_chip *chip, int timeout)
if (timeout == 0) {
rc = -ETIMEDOUT;
- dev_err(&chip->spmi_dev->dev, "%s: transaction timed out, no interrupts received, rc=%d\n",
+ dev_err(&chip->pdev->dev,
+ "%s: transaction timed out, no interrupts received, rc=%d\n",
__func__, rc);
return rc;
}
@@ -491,7 +504,8 @@ static int qpnp_bsi_issue_transaction(struct qpnp_bsi_chip *chip,
/* Write the TX_DATA bytes and initiate the transaction. */
rc = qpnp_bsi_write(chip, QPNP_BSI_REG_TX_DATA_LOW, buf, 4);
if (rc)
- dev_err(&chip->spmi_dev->dev, "%s: qpnp_bsi_write() failed, rc=%d\n",
+ dev_err(&chip->pdev->dev,
+ "%s: qpnp_bsi_write() failed, rc=%d\n",
__func__, rc);
return rc;
}
@@ -520,7 +534,8 @@ static int qpnp_bsi_wait_for_rx(struct qpnp_bsi_chip *chip, int timeout)
/* Wait for RX IRQ to indicate that data is ready to read. */
while (timeout > 0) {
if (qpnp_bsi_check_irq(chip, QPNP_BSI_IRQ_ERR)) {
- dev_err(&chip->spmi_dev->dev, "%s: transaction error occurred, BSI error=%d\n",
+ dev_err(&chip->pdev->dev,
+ "%s: transaction error occurred, BSI error=%d\n",
__func__, qpnp_bsi_get_bsi_error(chip));
return -EIO;
}
@@ -548,7 +563,8 @@ static int qpnp_bsi_bus_transaction(struct bif_ctrl_dev *bdev, int transaction,
rc = qpnp_bsi_set_bus_state(bdev, BIF_BUS_STATE_ACTIVE);
if (rc) {
- dev_err(&chip->spmi_dev->dev, "%s: failed to set bus state, rc=%d\n",
+ dev_err(&chip->pdev->dev,
+ "%s: failed to set bus state, rc=%d\n",
__func__, rc);
return rc;
}
@@ -582,7 +598,8 @@ static int qpnp_bsi_bus_transaction_query(struct bif_ctrl_dev *bdev,
rc = qpnp_bsi_set_bus_state(bdev, BIF_BUS_STATE_ACTIVE);
if (rc) {
- dev_err(&chip->spmi_dev->dev, "%s: failed to set bus state, rc=%d\n",
+ dev_err(&chip->pdev->dev,
+ "%s: failed to set bus state, rc=%d\n",
__func__, rc);
return rc;
}
@@ -628,7 +645,8 @@ static int qpnp_bsi_bus_transaction_read(struct bif_ctrl_dev *bdev,
rc = qpnp_bsi_set_bus_state(bdev, BIF_BUS_STATE_ACTIVE);
if (rc) {
- dev_err(&chip->spmi_dev->dev, "%s: failed to set bus state, rc=%d\n",
+ dev_err(&chip->pdev->dev,
+ "%s: failed to set bus state, rc=%d\n",
__func__, rc);
return rc;
}
@@ -658,7 +676,8 @@ static int qpnp_bsi_bus_transaction_read(struct bif_ctrl_dev *bdev,
* to provide silent operation when checking if a slave
* is selected using the transaction query bus command.
*/
- dev_dbg(&chip->spmi_dev->dev, "%s: transaction timed out, no interrupts received, rc=%d\n",
+ dev_dbg(&chip->pdev->dev,
+ "%s: transaction timed out, no interrupts received, rc=%d\n",
__func__, rc);
}
return rc;
@@ -667,14 +686,16 @@ static int qpnp_bsi_bus_transaction_read(struct bif_ctrl_dev *bdev,
/* Read the RX_DATA bytes. */
rc = qpnp_bsi_read(chip, QPNP_BSI_REG_RX_DATA_LOW, buf, 3);
if (rc) {
- dev_err(&chip->spmi_dev->dev, "%s: qpnp_bsi_read() failed, rc=%d\n",
+ dev_err(&chip->pdev->dev,
+ "%s: qpnp_bsi_read() failed, rc=%d\n",
__func__, rc);
return rc;
}
if (buf[2] & QPNP_BSI_RX_SRC_LOOPBACK_FLAG) {
rc = -EIO;
- dev_err(&chip->spmi_dev->dev, "%s: unexpected loopback data read, rc=%d\n",
+ dev_err(&chip->pdev->dev,
+ "%s: unexpected loopback data read, rc=%d\n",
__func__, rc);
return rc;
}
@@ -702,13 +723,15 @@ static int qpnp_bsi_wait_for_rx_data(struct qpnp_bsi_chip *chip)
while (timeout > 0) {
rc = qpnp_bsi_read(chip, QPNP_BSI_REG_STATUS, &reg, 1);
if (rc) {
- dev_err(&chip->spmi_dev->dev, "%s: qpnp_bsi_write() failed, rc=%d\n",
+ dev_err(&chip->pdev->dev,
+ "%s: qpnp_bsi_write() failed, rc=%d\n",
__func__, rc);
return rc;
}
if (reg & QPNP_BSI_STATUS_ERROR) {
- dev_err(&chip->spmi_dev->dev, "%s: transaction error occurred, BSI error=%d\n",
+ dev_err(&chip->pdev->dev,
+ "%s: transaction error occurred, BSI error=%d\n",
__func__, qpnp_bsi_get_bsi_error(chip));
return -EIO;
}
@@ -723,7 +746,8 @@ static int qpnp_bsi_wait_for_rx_data(struct qpnp_bsi_chip *chip)
}
rc = -ETIMEDOUT;
- dev_err(&chip->spmi_dev->dev, "%s: transaction timed out, RX_FLOW_STATUS never set to 1, rc=%d\n",
+ dev_err(&chip->pdev->dev,
+ "%s: transaction timed out, RX_FLOW_STATUS never set to 1, rc=%d\n",
__func__, rc);
return rc;
@@ -745,13 +769,15 @@ static int qpnp_bsi_wait_for_tx_go(struct qpnp_bsi_chip *chip)
while (timeout > 0) {
rc = qpnp_bsi_read(chip, QPNP_BSI_REG_STATUS, &reg, 1);
if (rc) {
- dev_err(&chip->spmi_dev->dev, "%s: qpnp_bsi_write() failed, rc=%d\n",
+ dev_err(&chip->pdev->dev,
+ "%s: qpnp_bsi_write() failed, rc=%d\n",
__func__, rc);
return rc;
}
if (reg & QPNP_BSI_STATUS_ERROR) {
- dev_err(&chip->spmi_dev->dev, "%s: transaction error occurred, BSI error=%d\n",
+ dev_err(&chip->pdev->dev,
+ "%s: transaction error occurred, BSI error=%d\n",
__func__, qpnp_bsi_get_bsi_error(chip));
return -EIO;
}
@@ -766,7 +792,8 @@ static int qpnp_bsi_wait_for_tx_go(struct qpnp_bsi_chip *chip)
}
rc = -ETIMEDOUT;
- dev_err(&chip->spmi_dev->dev, "%s: transaction timed out, TX_GO_STATUS never set to 0, rc=%d\n",
+ dev_err(&chip->pdev->dev,
+ "%s: transaction timed out, TX_GO_STATUS never set to 0, rc=%d\n",
__func__, rc);
return rc;
@@ -788,13 +815,15 @@ static int qpnp_bsi_wait_for_tx_idle(struct qpnp_bsi_chip *chip)
while (timeout > 0) {
rc = qpnp_bsi_read(chip, QPNP_BSI_REG_STATUS, &reg, 1);
if (rc) {
- dev_err(&chip->spmi_dev->dev, "%s: qpnp_bsi_write() failed, rc=%d\n",
+ dev_err(&chip->pdev->dev,
+ "%s: qpnp_bsi_write() failed, rc=%d\n",
__func__, rc);
return rc;
}
if (reg & QPNP_BSI_STATUS_ERROR) {
- dev_err(&chip->spmi_dev->dev, "%s: transaction error occurred, BSI error=%d\n",
+ dev_err(&chip->pdev->dev,
+ "%s: transaction error occurred, BSI error=%d\n",
__func__, qpnp_bsi_get_bsi_error(chip));
return -EIO;
}
@@ -809,7 +838,8 @@ static int qpnp_bsi_wait_for_tx_idle(struct qpnp_bsi_chip *chip)
}
rc = -ETIMEDOUT;
- dev_err(&chip->spmi_dev->dev, "%s: transaction timed out, TX_BUSY never set to 0, rc=%d\n",
+ dev_err(&chip->pdev->dev,
+ "%s: transaction timed out, TX_BUSY never set to 0, rc=%d\n",
__func__, rc);
return rc;
@@ -872,23 +902,27 @@ static int qpnp_bsi_validate_rx_data(struct qpnp_bsi_chip *chip, int response,
int err = -EIO;
if (rx2_data & QPNP_BSI_RX_SRC_LOOPBACK_FLAG) {
- dev_err(&chip->spmi_dev->dev, "%s: unexpected loopback data read, rc=%d\n",
+ dev_err(&chip->pdev->dev,
+ "%s: unexpected loopback data read, rc=%d\n",
__func__, err);
return err;
}
if (!(response & BIF_SLAVE_RD_ACK)) {
- dev_err(&chip->spmi_dev->dev, "%s: BIF register read error=0x%02X\n",
+ dev_err(&chip->pdev->dev,
+ "%s: BIF register read error=0x%02X\n",
__func__, response & BIF_SLAVE_RD_ERR);
return err;
}
if (last_word && !(response & BIF_SLAVE_RD_EOT)) {
- dev_err(&chip->spmi_dev->dev, "%s: BIF register read error, last RD packet has EOT=0\n",
+ dev_err(&chip->pdev->dev,
+ "%s: BIF register read error, last RD packet has EOT=0\n",
__func__);
return err;
} else if (!last_word && (response & BIF_SLAVE_RD_EOT)) {
- dev_err(&chip->spmi_dev->dev, "%s: BIF register read error, RD packet other than last has EOT=1\n",
+ dev_err(&chip->pdev->dev,
+ "%s: BIF register read error, RD packet other than last has EOT=1\n",
__func__);
return err;
}
@@ -910,7 +944,8 @@ static int qpnp_bsi_read_slave_registers(struct bif_ctrl_dev *bdev, u16 addr,
rc = qpnp_bsi_set_bus_state(bdev, BIF_BUS_STATE_ACTIVE);
if (rc) {
- dev_err(&chip->spmi_dev->dev, "%s: failed to set bus state, rc=%d\n",
+ dev_err(&chip->pdev->dev,
+ "%s: failed to set bus state, rc=%d\n",
__func__, rc);
return rc;
}
@@ -957,7 +992,8 @@ static int qpnp_bsi_read_slave_registers(struct bif_ctrl_dev *bdev, u16 addr,
rc = qpnp_bsi_read(chip, QPNP_BSI_REG_RX_DATA_LOW, buf,
3);
if (rc) {
- dev_err(&chip->spmi_dev->dev, "%s: qpnp_bsi_read() failed, rc=%d\n",
+ dev_err(&chip->pdev->dev,
+ "%s: qpnp_bsi_read() failed, rc=%d\n",
__func__, rc);
goto burst_err;
}
@@ -1005,7 +1041,8 @@ static int qpnp_bsi_write_slave_registers(struct bif_ctrl_dev *bdev, u16 addr,
rc = qpnp_bsi_set_bus_state(bdev, BIF_BUS_STATE_ACTIVE);
if (rc) {
- dev_err(&chip->spmi_dev->dev, "%s: failed to set bus state, rc=%d\n",
+ dev_err(&chip->pdev->dev,
+ "%s: failed to set bus state, rc=%d\n",
__func__, rc);
return rc;
}
@@ -1083,7 +1120,8 @@ static int qpnp_bsi_bus_set_interrupt_mode(struct bif_ctrl_dev *bdev)
*/
rc = qpnp_bsi_set_bus_state(bdev, BIF_BUS_STATE_ACTIVE);
if (rc) {
- dev_err(&chip->spmi_dev->dev, "%s: failed to set bus state, rc=%d\n",
+ dev_err(&chip->pdev->dev,
+ "%s: failed to set bus state, rc=%d\n",
__func__, rc);
return rc;
}
@@ -1138,7 +1176,8 @@ static int qpnp_bsi_bus_set_active_mode(struct bif_ctrl_dev *bdev,
rc = qpnp_bsi_write(chip, QPNP_BSI_REG_MODE, buf, 2);
if (rc) {
- dev_err(&chip->spmi_dev->dev, "%s: qpnp_bsi_write() failed, rc=%d\n",
+ dev_err(&chip->pdev->dev,
+ "%s: qpnp_bsi_write() failed, rc=%d\n",
__func__, rc);
return rc;
}
@@ -1147,7 +1186,8 @@ static int qpnp_bsi_bus_set_active_mode(struct bif_ctrl_dev *bdev,
/* Initiate BCL low pulse. */
rc = qpnp_bsi_write(chip, QPNP_BSI_REG_TX_CTRL, buf, 1);
if (rc) {
- dev_err(&chip->spmi_dev->dev, "%s: qpnp_bsi_write() failed, rc=%d\n",
+ dev_err(&chip->pdev->dev,
+ "%s: qpnp_bsi_write() failed, rc=%d\n",
__func__, rc);
return rc;
}
@@ -1195,7 +1235,8 @@ static int qpnp_bsi_set_bus_state(struct bif_ctrl_dev *bdev, int state)
reg = QPNP_BSI_ENABLE;
rc = qpnp_bsi_write(chip, QPNP_BSI_REG_ENABLE, &reg, 1);
if (rc) {
- dev_err(&chip->spmi_dev->dev, "%s: qpnp_bsi_write() failed, rc=%d\n",
+ dev_err(&chip->pdev->dev,
+ "%s: qpnp_bsi_write() failed, rc=%d\n",
__func__, rc);
return rc;
}
@@ -1207,25 +1248,29 @@ static int qpnp_bsi_set_bus_state(struct bif_ctrl_dev *bdev, int state)
reg = QPNP_BSI_DISABLE;
rc = qpnp_bsi_write(chip, QPNP_BSI_REG_ENABLE, &reg, 1);
if (rc)
- dev_err(&chip->spmi_dev->dev, "%s: qpnp_bsi_write() failed, rc=%d\n",
+ dev_err(&chip->pdev->dev,
+ "%s: qpnp_bsi_write() failed, rc=%d\n",
__func__, rc);
break;
case BIF_BUS_STATE_POWER_DOWN:
rc = qpnp_bsi_bus_transaction(bdev, BIF_TRANS_BC, BIF_CMD_PDWN);
if (rc)
- dev_err(&chip->spmi_dev->dev, "%s: failed to enable power down mode, rc=%d\n",
+ dev_err(&chip->pdev->dev,
+ "%s: failed to enable power down mode, rc=%d\n",
__func__, rc);
break;
case BIF_BUS_STATE_STANDBY:
rc = qpnp_bsi_bus_transaction(bdev, BIF_TRANS_BC, BIF_CMD_STBY);
if (rc)
- dev_err(&chip->spmi_dev->dev, "%s: failed to enable standby mode, rc=%d\n",
+ dev_err(&chip->pdev->dev,
+ "%s: failed to enable standby mode, rc=%d\n",
__func__, rc);
break;
case BIF_BUS_STATE_ACTIVE:
rc = qpnp_bsi_bus_set_active_mode(bdev, chip->state);
if (rc)
- dev_err(&chip->spmi_dev->dev, "%s: failed to enable active mode, rc=%d\n",
+ dev_err(&chip->pdev->dev,
+ "%s: failed to enable active mode, rc=%d\n",
__func__, rc);
break;
case BIF_BUS_STATE_INTERRUPT:
@@ -1236,7 +1281,8 @@ static int qpnp_bsi_set_bus_state(struct bif_ctrl_dev *bdev, int state)
*/
rc = qpnp_bsi_bus_set_interrupt_mode(bdev);
if (rc) {
- dev_err(&chip->spmi_dev->dev, "%s: failed to enable interrupt mode, rc=%d\n",
+ dev_err(&chip->pdev->dev,
+ "%s: failed to enable interrupt mode, rc=%d\n",
__func__, rc);
} else if (chip->state == BIF_BUS_STATE_ACTIVE) {
/*
@@ -1249,7 +1295,7 @@ static int qpnp_bsi_set_bus_state(struct bif_ctrl_dev *bdev, int state)
break;
default:
rc = -EINVAL;
- dev_err(&chip->spmi_dev->dev, "%s: invalid state=%d\n",
+ dev_err(&chip->pdev->dev, "%s: invalid state=%d\n",
__func__, state);
}
@@ -1329,7 +1375,8 @@ static int qpnp_bsi_set_tau_bif(struct qpnp_bsi_chip *chip, int period_ns)
reg = chip->tau_sampling_mask | idx;
rc = qpnp_bsi_write(chip, QPNP_BSI_REG_TAU_CONFIG, &reg, 1);
if (rc) {
- dev_err(&chip->spmi_dev->dev, "%s: qpnp_bsi_write() failed, rc=%d\n",
+ dev_err(&chip->pdev->dev,
+ "%s: qpnp_bsi_write() failed, rc=%d\n",
__func__, rc);
return rc;
}
@@ -1361,7 +1408,8 @@ static int qpnp_bsi_get_battery_rid(struct bif_ctrl_dev *bdev)
s64 temp;
if (chip->batt_id_adc_channel >= ADC_MAX_NUM) {
- dev_err(&chip->spmi_dev->dev, "%s: no ADC channel specified for Rid measurement\n",
+ dev_err(&chip->pdev->dev,
+ "%s: no ADC channel specified for Rid measurement\n",
__func__);
return -ENXIO;
}
@@ -1382,7 +1430,8 @@ static int qpnp_bsi_get_battery_rid(struct bif_ctrl_dev *bdev)
rid_ohm = temp;
}
} else {
- dev_err(&chip->spmi_dev->dev, "%s: qpnp_vadc_read(%d) failed, rc=%d\n",
+ dev_err(&chip->pdev->dev,
+ "%s: qpnp_vadc_read(%d) failed, rc=%d\n",
__func__, chip->batt_id_adc_channel, rc);
rid_ohm = rc;
}
@@ -1399,18 +1448,18 @@ static int qpnp_bsi_get_battery_rid(struct bif_ctrl_dev *bdev)
static int qpnp_bsi_get_battery_presence(struct bif_ctrl_dev *bdev)
{
struct qpnp_bsi_chip *chip = bdev_get_drvdata(bdev);
- u8 reg = 0x00;
int rc;
+ uint val;
- rc = spmi_ext_register_readl(chip->spmi_dev->ctrl, chip->spmi_dev->sid,
- chip->batt_id_stat_addr, &reg, 1);
+ rc = regmap_read(chip->regmap, chip->batt_id_stat_addr, &val);
if (rc) {
- dev_err(&chip->spmi_dev->dev, "%s: spmi_ext_register_readl() failed, rc=%d\n",
+ dev_err(&chip->pdev->dev,
+ "%s: regmap_bulk_readl failed, rc=%d\n",
__func__, rc);
return rc;
}
- return !!(reg & QPNP_SMBB_BAT_IF_BATT_PRES_MASK);
+ return !!(val & QPNP_SMBB_BAT_IF_BATT_PRES_MASK);
}
static struct bif_ctrl_ops qpnp_bsi_ops = {
@@ -1429,11 +1478,11 @@ static struct bif_ctrl_ops qpnp_bsi_ops = {
/* Load all BSI properties from device tree. */
static int qpnp_bsi_parse_dt(struct qpnp_bsi_chip *chip,
- struct spmi_device *spmi)
+ struct platform_device *pdev)
{
- struct device *dev = &spmi->dev;
- struct device_node *node = spmi->dev.of_node;
- struct resource *res;
+ struct device *dev = &pdev->dev;
+ struct device_node *node = pdev->dev.of_node;
+ unsigned int base;
int rc, temp;
chip->batt_id_adc_channel = ADC_MAX_NUM;
@@ -1466,27 +1515,28 @@ static int qpnp_bsi_parse_dt(struct qpnp_bsi_chip *chip,
return -EINVAL;
}
- res = spmi_get_resource_byname(spmi, NULL, IORESOURCE_MEM, "bsi-base");
- if (!res) {
- dev_err(dev, "%s: node is missing BSI base address\n",
- __func__);
- return -EINVAL;
+ rc = of_property_read_u32(pdev->dev.of_node, "bsi-base", &base);
+ if (rc < 0) {
+ dev_err(&pdev->dev,
+ "Couldn't find bsi-base in node = %s rc = %d\n",
+ pdev->dev.of_node->full_name, rc);
+ return rc;
}
- chip->base_addr = res->start;
+ chip->base_addr = base;
- res = spmi_get_resource_byname(spmi, NULL, IORESOURCE_MEM,
- "batt-id-status");
- if (!res) {
- dev_err(dev, "%s: node is missing BATT_ID status address\n",
- __func__);
- return -EINVAL;
+ rc = of_property_read_u32(pdev->dev.of_node, "batt-id-status", &base);
+ if (rc < 0) {
+ dev_err(&pdev->dev,
+ "Couldn't find batt-if-status in node = %s rc = %d\n",
+ pdev->dev.of_node->full_name, rc);
+ return rc;
}
- chip->batt_id_stat_addr = res->start;
+ chip->batt_id_stat_addr = base;
- chip->bdesc.name = spmi_get_primary_dev_name(spmi);
+ chip->bdesc.name = dev_name(&pdev->dev);
if (!chip->bdesc.name) {
dev_err(dev, "%s: label binding undefined for node %s\n",
- __func__, spmi->dev.of_node->full_name);
+ __func__, pdev->dev.of_node->full_name);
return -EINVAL;
}
@@ -1524,26 +1574,25 @@ static int qpnp_bsi_parse_dt(struct qpnp_bsi_chip *chip,
return -EINVAL;
}
- chip->irq[QPNP_BSI_IRQ_ERR] = spmi_get_irq_byname(spmi, NULL, "err");
+ chip->irq[QPNP_BSI_IRQ_ERR] = platform_get_irq_byname(pdev, "err");
if (chip->irq[QPNP_BSI_IRQ_ERR] < 0) {
dev_err(dev, "%s: node is missing err irq\n", __func__);
return chip->irq[QPNP_BSI_IRQ_ERR];
}
- chip->irq[QPNP_BSI_IRQ_RX] = spmi_get_irq_byname(spmi, NULL, "rx");
+ chip->irq[QPNP_BSI_IRQ_RX] = platform_get_irq_byname(pdev, "rx");
if (chip->irq[QPNP_BSI_IRQ_RX] < 0) {
dev_err(dev, "%s: node is missing rx irq\n", __func__);
return chip->irq[QPNP_BSI_IRQ_RX];
}
- chip->irq[QPNP_BSI_IRQ_TX] = spmi_get_irq_byname(spmi, NULL, "tx");
+ chip->irq[QPNP_BSI_IRQ_TX] = platform_get_irq_byname(pdev, "tx");
if (chip->irq[QPNP_BSI_IRQ_TX] < 0) {
dev_err(dev, "%s: node is missing tx irq\n", __func__);
return chip->irq[QPNP_BSI_IRQ_TX];
}
- chip->batt_present_irq = spmi_get_irq_byname(spmi, NULL,
- "batt-present");
+ chip->batt_present_irq = platform_get_irq_byname(pdev, "batt-present");
if (chip->batt_present_irq < 0) {
dev_err(dev, "%s: node is missing batt-present irq\n",
__func__);
@@ -1641,14 +1690,14 @@ static void qpnp_bsi_cleanup_irqs(struct qpnp_bsi_chip *chip)
irq_set_irq_wake(chip->batt_present_irq, 0);
}
-static int qpnp_bsi_probe(struct spmi_device *spmi)
+static int qpnp_bsi_probe(struct platform_device *pdev)
{
- struct device *dev = &spmi->dev;
+ struct device *dev = &pdev->dev;
struct qpnp_bsi_chip *chip;
int rc;
u8 type[2];
- if (!spmi->dev.of_node) {
+ if (!pdev->dev.of_node) {
dev_err(dev, "%s: device node missing\n", __func__);
return -ENODEV;
}
@@ -1658,8 +1707,13 @@ static int qpnp_bsi_probe(struct spmi_device *spmi)
dev_err(dev, "%s: Can't allocate qpnp_bsi\n", __func__);
return -ENOMEM;
}
+ chip->regmap = dev_get_regmap(pdev->dev.parent, NULL);
+ if (!chip->regmap) {
+ dev_err(&pdev->dev, "Couldn't get parent's regmap\n");
+ return -EINVAL;
+ }
- rc = qpnp_bsi_parse_dt(chip, spmi);
+ rc = qpnp_bsi_parse_dt(chip, pdev);
if (rc) {
dev_err(dev, "%s: device tree parsing failed, rc=%d\n",
__func__, rc);
@@ -1675,7 +1729,7 @@ static int qpnp_bsi_probe(struct spmi_device *spmi)
return rc;
}
- chip->spmi_dev = spmi;
+ chip->pdev = pdev;
chip->bdesc.ops = &qpnp_bsi_ops;
chip->state = BIF_BUS_STATE_MASTER_DISABLED;
chip->com_mode = QPNP_BSI_COM_MODE_IRQ;
@@ -1714,7 +1768,7 @@ static int qpnp_bsi_probe(struct spmi_device *spmi)
}
chip->bdev = bif_ctrl_register(&chip->bdesc, dev, chip,
- spmi->dev.of_node);
+ pdev->dev.of_node);
if (IS_ERR(chip->bdev)) {
rc = PTR_ERR(chip->bdev);
dev_err(dev, "%s: bif_ctrl_register failed, rc=%d\n",
@@ -1731,10 +1785,11 @@ cleanup_irqs:
return rc;
}
-static int qpnp_bsi_remove(struct spmi_device *spmi)
+static int qpnp_bsi_remove(struct platform_device *pdev)
{
- struct qpnp_bsi_chip *chip = dev_get_drvdata(&spmi->dev);
- dev_set_drvdata(&spmi->dev, NULL);
+ struct qpnp_bsi_chip *chip = dev_get_drvdata(&pdev->dev);
+
+ dev_set_drvdata(&pdev->dev, NULL);
if (chip) {
bif_ctrl_unregister(chip->bdev);
@@ -1749,13 +1804,13 @@ static struct of_device_id spmi_match_table[] = {
{}
};
-static const struct spmi_device_id qpnp_bsi_id[] = {
+static const struct platform_device_id qpnp_bsi_id[] = {
{ QPNP_BSI_DRIVER_NAME, 0 },
{ }
};
MODULE_DEVICE_TABLE(spmi, qpnp_bsi_id);
-static struct spmi_driver qpnp_bsi_driver = {
+static struct platform_driver qpnp_bsi_driver = {
.driver = {
.name = QPNP_BSI_DRIVER_NAME,
.of_match_table = spmi_match_table,
@@ -1768,12 +1823,12 @@ static struct spmi_driver qpnp_bsi_driver = {
static int __init qpnp_bsi_init(void)
{
- return spmi_driver_register(&qpnp_bsi_driver);
+ return platform_driver_register(&qpnp_bsi_driver);
}
static void __exit qpnp_bsi_exit(void)
{
- spmi_driver_unregister(&qpnp_bsi_driver);
+ platform_driver_unregister(&qpnp_bsi_driver);
}
MODULE_DESCRIPTION("QPNP PMIC BSI driver");
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 5931c1afded4..438ffcbe6654 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -338,16 +338,14 @@ config GPIO_PXA
Say yes here to support the PXA GPIO device
config GPIO_QPNP_PIN
- depends on SPMI || MSM_SPMI
- depends on OF_SPMI
- depends on MSM_QPNP_INT
+ depends on SPMI
tristate "Qualcomm QPNP gpio support"
help
Say 'y' here to include support for the Qualcomm QPNP gpio
driver. This driver supports Device Tree and allows a
device_node to be registered as a gpio-controller. It
- does not handle gpio interrupts directly. That work is handled
- by CONFIG_MSM_QPNP_INT.
+ does not handle gpio interrupts directly, they are handled
+ via the spmi arbiter interrupt driver.
config GPIO_QPNP_PIN_DEBUG
depends on GPIO_QPNP_PIN
diff --git a/drivers/gpio/qpnp-pin.c b/drivers/gpio/qpnp-pin.c
index 6f797190d732..eeda1dd6f590 100644
--- a/drivers/gpio/qpnp-pin.c
+++ b/drivers/gpio/qpnp-pin.c
@@ -13,9 +13,11 @@
#define pr_fmt(fmt) "%s: " fmt, __func__
#include <linux/interrupt.h>
+#include <linux/regmap.h>
#include <linux/types.h>
#include <linux/spmi.h>
#include <linux/platform_device.h>
+#include <linux/platform_device.h>
#include <linux/debugfs.h>
#include <linux/gpio.h>
#include <linux/slab.h>
@@ -209,7 +211,8 @@ struct qpnp_pin_spec {
struct qpnp_pin_chip {
struct gpio_chip gpio_chip;
- struct spmi_device *spmi;
+ struct platform_device *pdev;
+ struct regmap *regmap;
struct qpnp_pin_spec **pmic_pins;
struct qpnp_pin_spec **chip_gpios;
uint32_t pmic_pin_lowest;
@@ -539,8 +542,8 @@ static int qpnp_pin_read_regs(struct qpnp_pin_chip *q_chip,
u16 reg_addr = Q_REG_ADDR(q_spec, Q_REG_MODE_CTL);
while (bytes_left > 0) {
- rc = spmi_ext_register_readl(q_chip->spmi->ctrl, q_spec->slave,
- reg_addr, buf_p, bytes_left < 8 ? bytes_left : 8);
+ rc = regmap_bulk_read(q_chip->regmap, reg_addr, buf_p,
+ bytes_left < 8 ? bytes_left : 8);
if (rc)
return rc;
bytes_left -= 8;
@@ -559,8 +562,8 @@ static int qpnp_pin_write_regs(struct qpnp_pin_chip *q_chip,
u16 reg_addr = Q_REG_ADDR(q_spec, Q_REG_MODE_CTL);
while (bytes_left > 0) {
- rc = spmi_ext_register_writel(q_chip->spmi->ctrl, q_spec->slave,
- reg_addr, buf_p, bytes_left < 8 ? bytes_left : 8);
+ rc = regmap_bulk_write(q_chip->regmap, reg_addr, buf_p,
+ bytes_left < 8 ? bytes_left : 8);
if (rc)
return rc;
bytes_left -= 8;
@@ -574,7 +577,7 @@ static int qpnp_pin_cache_regs(struct qpnp_pin_chip *q_chip,
struct qpnp_pin_spec *q_spec)
{
int rc;
- struct device *dev = &q_chip->spmi->dev;
+ struct device *dev = &q_chip->pdev->dev;
rc = qpnp_pin_read_regs(q_chip, q_spec);
if (rc)
@@ -590,7 +593,7 @@ static int _qpnp_pin_config(struct qpnp_pin_chip *q_chip,
struct qpnp_pin_spec *q_spec,
struct qpnp_pin_cfg *param)
{
- struct device *dev = &q_chip->spmi->dev;
+ struct device *dev = &q_chip->pdev->dev;
int rc;
u8 shift, mask, *reg;
@@ -699,7 +702,8 @@ static int _qpnp_pin_config(struct qpnp_pin_chip *q_chip,
rc = qpnp_pin_write_regs(q_chip, q_spec);
if (rc) {
- dev_err(&q_chip->spmi->dev, "%s: unable to write master enable\n",
+ dev_err(&q_chip->pdev->dev,
+ "%s: unable to write master enable\n",
__func__);
goto gpio_cfg;
}
@@ -789,14 +793,15 @@ static int qpnp_pin_to_irq(struct gpio_chip *gpio_chip, unsigned offset)
/* call into irq_domain to get irq mapping */
oirq.np = q_chip->int_ctrl;
- oirq.args[0] = q_chip->spmi->sid;
+ oirq.args[0] = to_spmi_device(q_chip->pdev->dev.parent)->usid;
oirq.args[1] = (q_spec->offset >> 8) & 0xFF;
oirq.args[2] = 0;
- oirq.args_count = 3;
+ oirq.args[3] = IRQ_TYPE_NONE;
+ oirq.args_count = 4;
q_spec->irq = irq_create_of_mapping(&oirq);
if (!q_spec->irq) {
- dev_err(&q_chip->spmi->dev, "%s: invalid irq for gpio %u\n",
+ dev_err(&q_chip->pdev->dev, "%s: invalid irq for gpio %u\n",
__func__, q_spec->pmic_pin);
WARN_ON(1);
return -EINVAL;
@@ -812,6 +817,7 @@ static int qpnp_pin_get(struct gpio_chip *gpio_chip, unsigned offset)
struct qpnp_pin_spec *q_spec = NULL;
u8 buf[1], en_mask;
u8 shift, mask, reg;
+ int val;
if (WARN_ON(!q_chip))
return -ENODEV;
@@ -823,9 +829,9 @@ static int qpnp_pin_get(struct gpio_chip *gpio_chip, unsigned offset)
/* gpio val is from RT status iff input is enabled */
if ((q_spec->regs[Q_REG_I_MODE_CTL] & Q_REG_MODE_SEL_MASK)
== QPNP_PIN_MODE_DIG_IN) {
- rc = spmi_ext_register_readl(q_chip->spmi->ctrl, q_spec->slave,
- Q_REG_ADDR(q_spec, Q_REG_STATUS1),
- &buf[0], 1);
+ rc = regmap_read(q_chip->regmap,
+ Q_REG_ADDR(q_spec, Q_REG_STATUS1), &val);
+ buf[0] = (u8)val;
if (q_spec->type == Q_GPIO_TYPE && q_spec->dig_major_rev == 0)
en_mask = Q_REG_STATUS1_GPIO_EN_REV0_MASK;
@@ -839,7 +845,6 @@ static int qpnp_pin_get(struct gpio_chip *gpio_chip, unsigned offset)
return -EPERM;
return buf[0] & Q_REG_STATUS1_VAL_MASK;
-
} else {
if (is_gpio_lv_mv(q_spec)) {
shift = Q_REG_DIG_OUT_SRC_INVERT_SHIFT;
@@ -882,10 +887,9 @@ static int __qpnp_pin_set(struct qpnp_pin_chip *q_chip,
q_reg_clr_set(reg, shift, mask, !!value);
- rc = spmi_ext_register_writel(q_chip->spmi->ctrl, q_spec->slave,
- address, reg, 1);
+ rc = regmap_write(q_chip->regmap, address, *reg);
if (rc)
- dev_err(&q_chip->spmi->dev, "%s: spmi write failed\n",
+ dev_err(&q_chip->pdev->dev, "%s: spmi write failed\n",
__func__);
return rc;
}
@@ -929,12 +933,10 @@ static int qpnp_pin_set_mode(struct qpnp_pin_chip *q_chip,
mask = Q_REG_MODE_SEL_MASK;
}
- q_reg_clr_set(&q_spec->regs[Q_REG_I_MODE_CTL],
- shift, mask, mode);
+ q_reg_clr_set(&q_spec->regs[Q_REG_I_MODE_CTL], shift, mask, mode);
- rc = spmi_ext_register_writel(q_chip->spmi->ctrl, q_spec->slave,
- Q_REG_ADDR(q_spec, Q_REG_MODE_CTL),
- &q_spec->regs[Q_REG_I_MODE_CTL], 1);
+ rc = regmap_write(q_chip->regmap, Q_REG_ADDR(q_spec, Q_REG_MODE_CTL),
+ *&q_spec->regs[Q_REG_I_MODE_CTL]);
return rc;
}
@@ -1114,11 +1116,11 @@ static int qpnp_pin_apply_config(struct qpnp_pin_chip *q_chip,
static int qpnp_pin_free_chip(struct qpnp_pin_chip *q_chip)
{
- struct spmi_device *spmi = q_chip->spmi;
+ struct platform_device *pdev = q_chip->pdev;
int i, rc = 0;
if (q_chip->chip_gpios)
- for (i = 0; i < spmi->num_dev_node; i++)
+ for (i = 0; i < of_get_child_count(pdev->dev.of_node); i++)
kfree(q_chip->chip_gpios[i]);
mutex_lock(&qpnp_pin_chips_lock);
@@ -1293,9 +1295,8 @@ static int qpnp_pin_debugfs_set(void *data, u64 val)
if (rc)
return rc;
q_reg_clr_set(&q_spec->regs[cfg.idx], cfg.shift, cfg.mask, val);
- rc = spmi_ext_register_writel(q_chip->spmi->ctrl, q_spec->slave,
- Q_REG_ADDR(q_spec, cfg.addr),
- &q_spec->regs[cfg.idx], 1);
+ rc = regmap_write(q_chip->regmap, Q_REG_ADDR(q_spec, cfg.addr),
+ *&q_spec->regs[cfg.idx]);
return rc;
}
@@ -1327,8 +1328,8 @@ static struct qpnp_pin_debugfs_args dfs_args[] = {
static int qpnp_pin_debugfs_create(struct qpnp_pin_chip *q_chip)
{
- struct spmi_device *spmi = q_chip->spmi;
- struct device *dev = &spmi->dev;
+ struct platform_device *pdev = q_chip->pdev;
+ struct device *dev = &pdev->dev;
struct qpnp_pin_spec *q_spec;
enum qpnp_pin_param_type *params;
enum qpnp_pin_param_type type;
@@ -1347,7 +1348,7 @@ static int qpnp_pin_debugfs_create(struct qpnp_pin_chip *q_chip)
return -ENODEV;
}
- for (i = 0; i < spmi->num_dev_node; i++) {
+ for (i = 0; i < of_get_child_count(pdev->dev.of_node); i++) {
q_spec = qpnp_chip_gpio_get_spec(q_chip, i);
params = q_spec->params;
snprintf(pmic_pin, DEBUGFS_BUF_SIZE, "%u", q_spec->pmic_pin);
@@ -1419,44 +1420,53 @@ static int qpnp_pin_is_valid_pin(struct qpnp_pin_spec *q_spec)
return 0;
}
-static int qpnp_pin_probe(struct spmi_device *spmi)
+static int qpnp_pin_probe(struct platform_device *pdev)
{
struct qpnp_pin_chip *q_chip;
struct qpnp_pin_spec *q_spec;
- struct resource *res;
- struct spmi_resource *d_node;
+ unsigned int base;
+ struct device_node *child;
int i, rc;
u32 lowest_gpio = UINT_MAX, highest_gpio = 0;
u32 gpio;
char version[Q_REG_SUBTYPE - Q_REG_DIG_MAJOR_REV + 1];
- const char *dev_name;
-
- dev_name = spmi_get_primary_dev_name(spmi);
- if (!dev_name) {
- dev_err(&spmi->dev, "%s: label binding undefined for node %s\n",
- __func__, spmi->dev.of_node->full_name);
+ const char *pin_dev_name;
+ int num_dev_node;
+
+ pin_dev_name = dev_name(&pdev->dev);
+ if (!pin_dev_name) {
+ dev_err(&pdev->dev,
+ "%s: label binding undefined for node %s\n",
+ __func__,
+ pdev->dev.of_node->full_name);
return -EINVAL;
}
q_chip = kzalloc(sizeof(*q_chip), GFP_KERNEL);
- if (!q_chip) {
- dev_err(&spmi->dev, "%s: Can't allocate gpio_chip\n",
- __func__);
+ if (!q_chip)
return -ENOMEM;
+
+ q_chip->regmap = dev_get_regmap(pdev->dev.parent, NULL);
+ if (!q_chip->regmap) {
+ dev_err(&pdev->dev, "Couldn't get parent's regmap\n");
+ return -EINVAL;
}
- q_chip->spmi = spmi;
- dev_set_drvdata(&spmi->dev, q_chip);
+ q_chip->pdev = pdev;
+ dev_set_drvdata(&pdev->dev, q_chip);
mutex_lock(&qpnp_pin_chips_lock);
list_add(&q_chip->chip_list, &qpnp_pin_chips);
mutex_unlock(&qpnp_pin_chips_lock);
/* first scan through nodes to find the range required for allocation */
- for (i = 0; i < spmi->num_dev_node; i++) {
- rc = of_property_read_u32(spmi->dev_node[i].of_node,
- "qcom,pin-num", &gpio);
+ i = 0;
+ for_each_child_of_node(pdev->dev.of_node, child) {
+ if (!of_device_is_available(child))
+ continue;
+ rc = of_property_read_u32(child, "qcom,pin-num", &gpio);
if (rc) {
- dev_err(&spmi->dev, "%s: unable to get qcom,pin-num property\n",
+ dev_err(&pdev->dev,
+ "%s: unable to get qcom,pin-num property\n",
__func__);
goto err_probe;
}
@@ -1465,15 +1475,18 @@ static int qpnp_pin_probe(struct spmi_device *spmi)
lowest_gpio = gpio;
if (gpio > highest_gpio)
highest_gpio = gpio;
+ i++;
}
+ num_dev_node = i;
if (highest_gpio < lowest_gpio) {
- dev_err(&spmi->dev, "%s: no device nodes specified in topology\n",
+ dev_err(&pdev->dev,
+ "%s: no device nodes specified in topology\n",
__func__);
rc = -EINVAL;
goto err_probe;
} else if (lowest_gpio == 0) {
- dev_err(&spmi->dev, "%s: 0 is not a valid PMIC GPIO\n",
+ dev_err(&pdev->dev, "%s: 0 is not a valid PMIC GPIO\n",
__func__);
rc = -EINVAL;
goto err_probe;
@@ -1487,63 +1500,63 @@ static int qpnp_pin_probe(struct spmi_device *spmi)
(highest_gpio - lowest_gpio + 1),
GFP_KERNEL);
q_chip->chip_gpios = kzalloc(sizeof(struct qpnp_pin_spec *) *
- spmi->num_dev_node, GFP_KERNEL);
+ num_dev_node,
+ GFP_KERNEL);
if (!q_chip->pmic_pins || !q_chip->chip_gpios) {
- dev_err(&spmi->dev, "%s: unable to allocate memory\n",
+ dev_err(&pdev->dev, "%s: unable to allocate memory\n",
__func__);
rc = -ENOMEM;
goto err_probe;
}
/* get interrupt controller device_node */
- q_chip->int_ctrl = of_irq_find_parent(spmi->dev.of_node);
+ q_chip->int_ctrl = of_irq_find_parent(pdev->dev.of_node);
if (!q_chip->int_ctrl) {
- dev_err(&spmi->dev, "%s: Can't find interrupt parent\n",
+ dev_err(&pdev->dev, "%s: Can't find interrupt parent\n",
__func__);
rc = -EINVAL;
goto err_probe;
}
-
+ i = 0;
/* now scan through again and populate the lookup table */
- for (i = 0; i < spmi->num_dev_node; i++) {
- d_node = &spmi->dev_node[i];
- res = spmi_get_resource(spmi, d_node, IORESOURCE_MEM, 0);
- if (!res) {
- dev_err(&spmi->dev, "%s: node %s is missing has no base address definition\n",
- __func__, d_node->of_node->full_name);
- rc = -EINVAL;
+ for_each_child_of_node(pdev->dev.of_node, child) {
+ if (!of_device_is_available(child))
+ continue;
+ rc = of_property_read_u32(child, "reg", &base);
+ if (rc < 0) {
+ dev_err(&pdev->dev,
+ "Couldn't find reg in node = %s rc = %d\n",
+ child->full_name, rc);
goto err_probe;
}
- rc = of_property_read_u32(d_node->of_node,
- "qcom,pin-num", &gpio);
+ rc = of_property_read_u32(child, "qcom,pin-num", &gpio);
if (rc) {
- dev_err(&spmi->dev, "%s: unable to get qcom,pin-num property\n",
+ dev_err(&pdev->dev,
+ "%s: unable to get qcom,pin-num property\n",
__func__);
goto err_probe;
}
- q_spec = kzalloc(sizeof(struct qpnp_pin_spec),
- GFP_KERNEL);
+ q_spec = kzalloc(sizeof(struct qpnp_pin_spec), GFP_KERNEL);
if (!q_spec) {
- dev_err(&spmi->dev, "%s: unable to allocate memory\n",
- __func__);
rc = -ENOMEM;
goto err_probe;
}
- q_spec->slave = spmi->sid;
- q_spec->offset = res->start;
+ q_spec->slave = to_spmi_device(pdev->dev.parent)->usid;
+ q_spec->offset = base;
q_spec->gpio_chip_idx = i;
q_spec->pmic_pin = gpio;
- q_spec->node = d_node->of_node;
+ q_spec->node = child;
q_spec->q_chip = q_chip;
- rc = spmi_ext_register_readl(spmi->ctrl, q_spec->slave,
+ rc = regmap_bulk_read(q_chip->regmap,
Q_REG_ADDR(q_spec, Q_REG_DIG_MAJOR_REV),
- &version[0], ARRAY_SIZE(version));
+ &version[0],
+ ARRAY_SIZE(version));
if (rc) {
- dev_err(&spmi->dev, "%s: unable to read type regs\n",
+ dev_err(&pdev->dev, "%s: unable to read type regs\n",
__func__);
goto err_probe;
}
@@ -1553,7 +1566,8 @@ static int qpnp_pin_probe(struct spmi_device *spmi)
q_spec->subtype = version[Q_REG_SUBTYPE - Q_REG_DIG_MAJOR_REV];
if (!qpnp_pin_is_valid_pin(q_spec)) {
- dev_err(&spmi->dev, "%s: invalid pin type (type=0x%x subtype=0x%x)\n",
+ dev_err(&pdev->dev,
+ "%s: invalid pin type (type=0x%x subtype=0x%x)\n",
__func__, q_spec->type, q_spec->subtype);
goto err_probe;
}
@@ -1565,31 +1579,32 @@ static int qpnp_pin_probe(struct spmi_device *spmi)
/* initialize lookup table params */
qpnp_pmic_pin_set_spec(q_chip, gpio, q_spec);
qpnp_chip_gpio_set_spec(q_chip, i, q_spec);
+ i++;
}
q_chip->gpio_chip.base = -1;
- q_chip->gpio_chip.ngpio = spmi->num_dev_node;
- q_chip->gpio_chip.label = dev_name;
+ q_chip->gpio_chip.ngpio = num_dev_node;
+ q_chip->gpio_chip.label = pin_dev_name;
q_chip->gpio_chip.direction_input = qpnp_pin_direction_input;
q_chip->gpio_chip.direction_output = qpnp_pin_direction_output;
q_chip->gpio_chip.to_irq = qpnp_pin_to_irq;
q_chip->gpio_chip.get = qpnp_pin_get;
q_chip->gpio_chip.set = qpnp_pin_set;
- q_chip->gpio_chip.dev = &spmi->dev;
+ q_chip->gpio_chip.dev = &pdev->dev;
q_chip->gpio_chip.of_xlate = qpnp_pin_of_gpio_xlate;
q_chip->gpio_chip.of_gpio_n_cells = 2;
q_chip->gpio_chip.can_sleep = 0;
rc = gpiochip_add(&q_chip->gpio_chip);
if (rc) {
- dev_err(&spmi->dev, "%s: Can't add gpio chip, rc = %d\n",
+ dev_err(&pdev->dev, "%s: Can't add gpio chip, rc = %d\n",
__func__, rc);
goto err_probe;
}
q_chip->chip_registered = true;
/* now configure gpio config defaults if they exist */
- for (i = 0; i < spmi->num_dev_node; i++) {
+ for (i = 0; i < num_dev_node; i++) {
q_spec = qpnp_chip_gpio_get_spec(q_chip, i);
if (WARN_ON(!q_spec)) {
rc = -ENODEV;
@@ -1605,13 +1620,14 @@ static int qpnp_pin_probe(struct spmi_device *spmi)
goto err_probe;
}
- dev_dbg(&spmi->dev, "%s: gpio_chip registered between %d-%u\n",
+ dev_dbg(&pdev->dev, "%s: gpio_chip registered between %d-%u\n",
__func__, q_chip->gpio_chip.base,
(q_chip->gpio_chip.base + q_chip->gpio_chip.ngpio) - 1);
rc = qpnp_pin_debugfs_create(q_chip);
if (rc) {
- dev_err(&spmi->dev, "%s: debugfs creation failed\n", __func__);
+ dev_err(&pdev->dev, "%s: debugfs creation failed\n",
+ __func__);
goto err_probe;
}
@@ -1622,9 +1638,9 @@ err_probe:
return rc;
}
-static int qpnp_pin_remove(struct spmi_device *spmi)
+static int qpnp_pin_remove(struct platform_device *pdev)
{
- struct qpnp_pin_chip *q_chip = dev_get_drvdata(&spmi->dev);
+ struct qpnp_pin_chip *q_chip = dev_get_drvdata(&pdev->dev);
debugfs_remove_recursive(q_chip->dfs_dir);
@@ -1637,15 +1653,15 @@ static struct of_device_id spmi_match_table[] = {
{}
};
-static const struct spmi_device_id qpnp_pin_id[] = {
+static const struct platform_device_id qpnp_pin_id[] = {
{ "qcom,qpnp-pin", 0 },
{ }
};
MODULE_DEVICE_TABLE(spmi, qpnp_pin_id);
-static struct spmi_driver qpnp_pin_driver = {
+static struct platform_driver qpnp_pin_driver = {
.driver = {
- .name = "qcom,qpnp-pin",
+ .name = "qcom,qpnp-pin",
.of_match_table = spmi_match_table,
},
.probe = qpnp_pin_probe,
@@ -1661,7 +1677,7 @@ static int __init qpnp_pin_init(void)
pr_err("Cannot register top level debugfs directory\n");
#endif
- return spmi_driver_register(&qpnp_pin_driver);
+ return platform_driver_register(&qpnp_pin_driver);
}
static void __exit qpnp_pin_exit(void)
@@ -1669,7 +1685,7 @@ static void __exit qpnp_pin_exit(void)
#ifdef CONFIG_GPIO_QPNP_PIN_DEBUG
debugfs_remove_recursive(driver_dfs_dir);
#endif
- spmi_driver_unregister(&qpnp_pin_driver);
+ platform_driver_unregister(&qpnp_pin_driver);
}
MODULE_DESCRIPTION("QPNP PMIC gpio driver");
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 635a075c7667..19ed2ef9aa04 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -1202,7 +1202,7 @@ config SENSORS_PCF8591
config SENSORS_QPNP_ADC_VOLTAGE
tristate "Support for Qualcomm QPNP Voltage ADC"
- depends on MSM_SPMI
+ depends on SPMI
help
This is the VADC arbiter driver for Qualcomm QPNP ADC Chip.
@@ -1212,7 +1212,7 @@ config SENSORS_QPNP_ADC_VOLTAGE
config SENSORS_QPNP_ADC_CURRENT
tristate "Support for Qualcomm QPNP current ADC"
- depends on MSM_SPMI
+ depends on SPMI
help
This is the IADC driver for Qualcomm QPNP ADC Chip.
diff --git a/drivers/hwmon/qpnp-adc-common.c b/drivers/hwmon/qpnp-adc-common.c
index 43716ab7e3bf..dc2050ce4b46 100644
--- a/drivers/hwmon/qpnp-adc-common.c
+++ b/drivers/hwmon/qpnp-adc-common.c
@@ -24,6 +24,7 @@
#include <linux/module.h>
#include <linux/debugfs.h>
#include <linux/spmi.h>
+#include <linux/platform_device.h>
#include <linux/of_irq.h>
#include <linux/interrupt.h>
#include <linux/completion.h>
@@ -1771,11 +1772,11 @@ int qpnp_adc_get_revid_version(struct device *dev)
}
EXPORT_SYMBOL(qpnp_adc_get_revid_version);
-int32_t qpnp_adc_get_devicetree_data(struct spmi_device *spmi,
+int32_t qpnp_adc_get_devicetree_data(struct platform_device *pdev,
struct qpnp_adc_drv *adc_qpnp)
{
- struct device_node *node = spmi->dev.of_node;
- struct resource *res;
+ struct device_node *node = pdev->dev.of_node;
+ unsigned int base;
struct device_node *child;
struct qpnp_adc_amux *adc_channel_list;
struct qpnp_adc_properties *adc_prop;
@@ -1794,24 +1795,25 @@ int32_t qpnp_adc_get_devicetree_data(struct spmi_device *spmi,
return -EINVAL;
}
- adc_qpnp->spmi = spmi;
+ adc_qpnp->pdev = pdev;
- adc_prop = devm_kzalloc(&spmi->dev, sizeof(struct qpnp_adc_properties),
+ adc_prop = devm_kzalloc(&pdev->dev,
+ sizeof(struct qpnp_adc_properties),
GFP_KERNEL);
if (!adc_prop)
return -ENOMEM;
- adc_channel_list = devm_kzalloc(&spmi->dev,
+ adc_channel_list = devm_kzalloc(&pdev->dev,
((sizeof(struct qpnp_adc_amux)) * count_adc_channel_list),
GFP_KERNEL);
if (!adc_channel_list)
return -ENOMEM;
- amux_prop = devm_kzalloc(&spmi->dev,
+ amux_prop = devm_kzalloc(&pdev->dev,
sizeof(struct qpnp_adc_amux_properties) +
sizeof(struct qpnp_vadc_chan_properties), GFP_KERNEL);
if (!amux_prop) {
- dev_err(&spmi->dev, "Unable to allocate memory\n");
+ dev_err(&pdev->dev, "Unable to allocate memory\n");
return -ENOMEM;
}
@@ -1928,18 +1930,20 @@ int32_t qpnp_adc_get_devicetree_data(struct spmi_device *spmi,
adc_qpnp->adc_prop = adc_prop;
/* Get the peripheral address */
- res = spmi_get_resource(spmi, 0, IORESOURCE_MEM, 0);
- if (!res) {
- pr_err("No base address definition\n");
- return -EINVAL;
+ rc = of_property_read_u32(pdev->dev.of_node, "reg", &base);
+ if (rc < 0) {
+ dev_err(&pdev->dev,
+ "Couldn't find reg in node = %s rc = %d\n",
+ pdev->dev.of_node->full_name, rc);
+ return rc;
}
- adc_qpnp->slave = spmi->sid;
- adc_qpnp->offset = res->start;
+ adc_qpnp->slave = to_spmi_device(pdev->dev.parent)->usid;
+ adc_qpnp->offset = base;
/* Register the ADC peripheral interrupt */
- adc_qpnp->adc_irq_eoc = spmi_get_irq_byname(spmi, NULL,
- "eoc-int-en-set");
+ adc_qpnp->adc_irq_eoc = platform_get_irq_byname(pdev,
+ "eoc-int-en-set");
if (adc_qpnp->adc_irq_eoc < 0) {
pr_err("Invalid irq\n");
return -ENXIO;
@@ -1948,8 +1952,7 @@ int32_t qpnp_adc_get_devicetree_data(struct spmi_device *spmi,
init_completion(&adc_qpnp->adc_rslt_completion);
if (of_get_property(node, "hkadc_ldo-supply", NULL)) {
- adc_qpnp->hkadc_ldo = regulator_get(&spmi->dev,
- "hkadc_ldo");
+ adc_qpnp->hkadc_ldo = regulator_get(&pdev->dev, "hkadc_ldo");
if (IS_ERR(adc_qpnp->hkadc_ldo)) {
pr_err("hkadc_ldo-supply node not found\n");
return -EINVAL;
@@ -1972,7 +1975,7 @@ int32_t qpnp_adc_get_devicetree_data(struct spmi_device *spmi,
}
if (of_get_property(node, "hkadc_ok-supply", NULL)) {
- adc_qpnp->hkadc_ldo_ok = regulator_get(&spmi->dev,
+ adc_qpnp->hkadc_ldo_ok = regulator_get(&pdev->dev,
"hkadc_ok");
if (IS_ERR(adc_qpnp->hkadc_ldo_ok)) {
pr_err("hkadc_ok node not found\n");
diff --git a/drivers/hwmon/qpnp-adc-current.c b/drivers/hwmon/qpnp-adc-current.c
index b9a9fbad94ab..b156224dc26f 100644
--- a/drivers/hwmon/qpnp-adc-current.c
+++ b/drivers/hwmon/qpnp-adc-current.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -13,6 +13,7 @@
#define pr_fmt(fmt) "%s: " fmt, __func__
#include <linux/kernel.h>
+#include <linux/regmap.h>
#include <linux/of.h>
#include <linux/err.h>
#include <linux/init.h>
@@ -24,6 +25,7 @@
#include <linux/module.h>
#include <linux/debugfs.h>
#include <linux/spmi.h>
+#include <linux/platform_device.h>
#include <linux/of_irq.h>
#ifdef CONFIG_WAKELOCK
#include <linux/wakelock.h>
@@ -184,13 +186,14 @@ static int32_t qpnp_iadc_read_reg(struct qpnp_iadc_chip *iadc,
uint32_t reg, u8 *data)
{
int rc;
+ uint val;
- rc = spmi_ext_register_readl(iadc->adc->spmi->ctrl, iadc->adc->slave,
- (iadc->adc->offset + reg), data, 1);
+ rc = regmap_read(iadc->adc->regmap, (iadc->adc->offset + reg), &val);
if (rc < 0) {
pr_err("qpnp iadc read reg %d failed with %d\n", reg, rc);
return rc;
}
+ *data = (u8)val;
return 0;
}
@@ -202,8 +205,7 @@ static int32_t qpnp_iadc_write_reg(struct qpnp_iadc_chip *iadc,
u8 *buf;
buf = &data;
- rc = spmi_ext_register_writel(iadc->adc->spmi->ctrl, iadc->adc->slave,
- (iadc->adc->offset + reg), buf, 1);
+ rc = regmap_write(iadc->adc->regmap, (iadc->adc->offset + reg), *buf);
if (rc < 0) {
pr_err("qpnp iadc write reg %d failed with %d\n", reg, rc);
return rc;
@@ -649,7 +651,8 @@ EXPORT_SYMBOL(qpnp_iadc_comp_result);
static int qpnp_iadc_rds_trim_update_check(struct qpnp_iadc_chip *iadc)
{
int rc = 0;
- u8 trim2_val = 0, smbb_batt_trm_data = 0;
+ u8 trim2_val = 0;
+ uint smbb_batt_trm_data = 0;
u8 smbb_batt_trm_cnst_rds = 0;
if (!iadc->rds_trim_default_check) {
@@ -663,17 +666,17 @@ static int qpnp_iadc_rds_trim_update_check(struct qpnp_iadc_chip *iadc)
return rc;
}
- rc = spmi_ext_register_readl(iadc->adc->spmi->ctrl, iadc->adc->slave,
- iadc->batt_id_trim_cnst_rds, &smbb_batt_trm_data, 1);
+ rc = regmap_read(iadc->adc->regmap, iadc->batt_id_trim_cnst_rds,
+ &smbb_batt_trm_data);
if (rc < 0) {
pr_err("batt_id trim_cnst rds reg read failed %d\n", rc);
return rc;
}
- smbb_batt_trm_cnst_rds = smbb_batt_trm_data &
+ smbb_batt_trm_cnst_rds = (u8)smbb_batt_trm_data &
SMBB_BAT_IF_TRIM_CNST_RDS_MASK;
- pr_debug("n_trim:0x%x smb_trm:0x%x\n", trim2_val, smbb_batt_trm_data);
+ pr_debug("n_trim:0x%x smb_trm:0x%02x\n", trim2_val, smbb_batt_trm_data);
if (iadc->rds_trim_default_type == QPNP_IADC_RDS_DEFAULT_TYPEA) {
@@ -1084,7 +1087,7 @@ struct qpnp_iadc_chip *qpnp_get_iadc(struct device *dev, const char *name)
return ERR_PTR(-ENODEV);
list_for_each_entry(iadc, &qpnp_iadc_device_list, list)
- if (iadc->adc->spmi->dev.of_node == node)
+ if (iadc->adc->pdev->dev.of_node == node)
return iadc;
return ERR_PTR(-EPROBE_DEFER);
}
@@ -1430,10 +1433,10 @@ static struct sensor_device_attribute qpnp_adc_attr =
SENSOR_ATTR(NULL, S_IRUGO, qpnp_iadc_show, NULL, 0);
static int32_t qpnp_iadc_init_hwmon(struct qpnp_iadc_chip *iadc,
- struct spmi_device *spmi)
+ struct platform_device *pdev)
{
struct device_node *child;
- struct device_node *node = spmi->dev.of_node;
+ struct device_node *node = pdev->dev.of_node;
int rc = 0, i = 0, channel;
for_each_child_of_node(node, child) {
@@ -1444,10 +1447,10 @@ static int32_t qpnp_iadc_init_hwmon(struct qpnp_iadc_chip *iadc,
memcpy(&iadc->sens_attr[i], &qpnp_adc_attr,
sizeof(qpnp_adc_attr));
sysfs_attr_init(&iadc->sens_attr[i].dev_attr.attr);
- rc = device_create_file(&spmi->dev,
+ rc = device_create_file(&pdev->dev,
&iadc->sens_attr[i].dev_attr);
if (rc) {
- dev_err(&spmi->dev,
+ dev_err(&pdev->dev,
"device_create_file failed for dev %s\n",
iadc->adc->adc_channels[i].name);
goto hwmon_err_sens;
@@ -1461,13 +1464,13 @@ hwmon_err_sens:
return rc;
}
-static int qpnp_iadc_probe(struct spmi_device *spmi)
+static int qpnp_iadc_probe(struct platform_device *pdev)
{
struct qpnp_iadc_chip *iadc;
struct qpnp_adc_drv *adc_qpnp;
- struct device_node *node = spmi->dev.of_node;
+ struct device_node *node = pdev->dev.of_node;
struct device_node *child;
- struct resource *res;
+ unsigned int base;
int rc, count_adc_channel_list = 0, i = 0;
for_each_child_of_node(node, child)
@@ -1478,37 +1481,45 @@ static int qpnp_iadc_probe(struct spmi_device *spmi)
return -EINVAL;
}
- iadc = devm_kzalloc(&spmi->dev, sizeof(struct qpnp_iadc_chip) +
+ iadc = devm_kzalloc(&pdev->dev, sizeof(struct qpnp_iadc_chip) +
(sizeof(struct sensor_device_attribute) *
count_adc_channel_list), GFP_KERNEL);
if (!iadc) {
- dev_err(&spmi->dev, "Unable to allocate memory\n");
+ dev_err(&pdev->dev, "Unable to allocate memory\n");
return -ENOMEM;
}
- adc_qpnp = devm_kzalloc(&spmi->dev, sizeof(struct qpnp_adc_drv),
+ adc_qpnp = devm_kzalloc(&pdev->dev, sizeof(struct qpnp_adc_drv),
GFP_KERNEL);
if (!adc_qpnp) {
- dev_err(&spmi->dev, "Unable to allocate memory\n");
+ dev_err(&pdev->dev, "Unable to allocate memory\n");
return -ENOMEM;
}
- iadc->dev = &(spmi->dev);
+ adc_qpnp->regmap = dev_get_regmap(pdev->dev.parent, NULL);
+ if (!adc_qpnp->regmap) {
+ dev_err(&pdev->dev, "Couldn't get parent's regmap\n");
+ return -EINVAL;
+ }
+
+ iadc->dev = &(pdev->dev);
iadc->adc = adc_qpnp;
- rc = qpnp_adc_get_devicetree_data(spmi, iadc->adc);
+ rc = qpnp_adc_get_devicetree_data(pdev, iadc->adc);
if (rc) {
- dev_err(&spmi->dev, "failed to read device tree\n");
+ dev_err(&pdev->dev, "failed to read device tree\n");
return rc;
}
- res = spmi_get_resource_byname(spmi, NULL, IORESOURCE_MEM,
- "batt-id-trim-cnst-rds");
- if (!res) {
- dev_err(&spmi->dev, "failed to read batt_id trim register\n");
- return -EINVAL;
+ rc = of_property_read_u32(pdev->dev.of_node, "batt-id-trim-cnst-rds",
+ &base);
+ if (rc < 0) {
+ dev_err(&pdev->dev,
+ "Couldn't find batt-id-trim-cnst-rds in node = %s rc = %d\n",
+ pdev->dev.of_node->full_name, rc);
+ return rc;
}
- iadc->batt_id_trim_cnst_rds = res->start;
+ iadc->batt_id_trim_cnst_rds = base;
rc = of_property_read_u32(node, "qcom,use-default-rds-trim",
&iadc->rds_trim_default_type);
if (rc)
@@ -1518,7 +1529,7 @@ static int qpnp_iadc_probe(struct spmi_device *spmi)
iadc->rds_trim_default_check = true;
}
- iadc->vadc_dev = qpnp_get_vadc(&spmi->dev, "iadc");
+ iadc->vadc_dev = qpnp_get_vadc(&pdev->dev, "iadc");
if (IS_ERR(iadc->vadc_dev)) {
rc = PTR_ERR(iadc->vadc_dev);
if (rc != -EPROBE_DEFER)
@@ -1540,26 +1551,27 @@ static int qpnp_iadc_probe(struct spmi_device *spmi)
iadc->iadc_poll_eoc = of_property_read_bool(node,
"qcom,iadc-poll-eoc");
if (!iadc->iadc_poll_eoc) {
- rc = devm_request_irq(&spmi->dev, iadc->adc->adc_irq_eoc,
+ rc = devm_request_irq(&pdev->dev, iadc->adc->adc_irq_eoc,
qpnp_iadc_isr, IRQF_TRIGGER_RISING,
"qpnp_iadc_interrupt", iadc);
if (rc) {
- dev_err(&spmi->dev, "failed to request adc irq\n");
+ dev_err(&pdev->dev, "failed to request adc irq\n");
return rc;
- } else
+ } else {
enable_irq_wake(iadc->adc->adc_irq_eoc);
+ }
}
- rc = qpnp_iadc_init_hwmon(iadc, spmi);
+ rc = qpnp_iadc_init_hwmon(iadc, pdev);
if (rc) {
- dev_err(&spmi->dev, "failed to initialize qpnp hwmon adc\n");
+ dev_err(&pdev->dev, "failed to initialize qpnp hwmon adc\n");
return rc;
}
- iadc->iadc_hwmon = hwmon_device_register(&iadc->adc->spmi->dev);
+ iadc->iadc_hwmon = hwmon_device_register(&iadc->adc->pdev->dev);
rc = qpnp_iadc_version_check(iadc);
if (rc) {
- dev_err(&spmi->dev, "IADC version not supported\n");
+ dev_err(&pdev->dev, "IADC version not supported\n");
goto fail;
}
@@ -1568,21 +1580,21 @@ static int qpnp_iadc_probe(struct spmi_device *spmi)
INIT_DELAYED_WORK(&iadc->iadc_work, qpnp_iadc_work);
rc = qpnp_iadc_comp_info(iadc);
if (rc) {
- dev_err(&spmi->dev, "abstracting IADC comp info failed!\n");
+ dev_err(&pdev->dev, "abstracting IADC comp info failed!\n");
goto fail;
}
rc = qpnp_iadc_rds_trim_update_check(iadc);
if (rc) {
- dev_err(&spmi->dev, "Rds trim update failed!\n");
+ dev_err(&pdev->dev, "Rds trim update failed!\n");
goto fail;
}
- dev_set_drvdata(&spmi->dev, iadc);
+ dev_set_drvdata(&pdev->dev, iadc);
list_add(&iadc->list, &qpnp_iadc_device_list);
rc = qpnp_iadc_calibrate_for_trim(iadc, true);
if (rc)
- dev_err(&spmi->dev, "failed to calibrate for USR trim\n");
+ dev_err(&pdev->dev, "failed to calibrate for USR trim\n");
if (iadc->iadc_poll_eoc)
device_init_wakeup(iadc->dev, 1);
@@ -1593,8 +1605,7 @@ static int qpnp_iadc_probe(struct spmi_device *spmi)
return 0;
fail:
for_each_child_of_node(node, child) {
- device_remove_file(&spmi->dev,
- &iadc->sens_attr[i].dev_attr);
+ device_remove_file(&pdev->dev, &iadc->sens_attr[i].dev_attr);
i++;
}
hwmon_device_unregister(iadc->iadc_hwmon);
@@ -1602,23 +1613,22 @@ fail:
return rc;
}
-static int qpnp_iadc_remove(struct spmi_device *spmi)
+static int qpnp_iadc_remove(struct platform_device *pdev)
{
- struct qpnp_iadc_chip *iadc = dev_get_drvdata(&spmi->dev);
- struct device_node *node = spmi->dev.of_node;
+ struct qpnp_iadc_chip *iadc = dev_get_drvdata(&pdev->dev);
+ struct device_node *node = pdev->dev.of_node;
struct device_node *child;
int i = 0;
cancel_delayed_work(&iadc->iadc_work);
for_each_child_of_node(node, child) {
- device_remove_file(&spmi->dev,
- &iadc->sens_attr[i].dev_attr);
+ device_remove_file(&pdev->dev, &iadc->sens_attr[i].dev_attr);
i++;
}
hwmon_device_unregister(iadc->iadc_hwmon);
if (iadc->iadc_poll_eoc)
pm_relax(iadc->dev);
- dev_set_drvdata(&spmi->dev, NULL);
+ dev_set_drvdata(&pdev->dev, NULL);
return 0;
}
@@ -1629,9 +1639,9 @@ static const struct of_device_id qpnp_iadc_match_table[] = {
{}
};
-static struct spmi_driver qpnp_iadc_driver = {
+static struct platform_driver qpnp_iadc_driver = {
.driver = {
- .name = "qcom,qpnp-iadc",
+ .name = "qcom,qpnp-iadc",
.of_match_table = qpnp_iadc_match_table,
},
.probe = qpnp_iadc_probe,
@@ -1640,13 +1650,13 @@ static struct spmi_driver qpnp_iadc_driver = {
static int __init qpnp_iadc_init(void)
{
- return spmi_driver_register(&qpnp_iadc_driver);
+ return platform_driver_register(&qpnp_iadc_driver);
}
module_init(qpnp_iadc_init);
static void __exit qpnp_iadc_exit(void)
{
- spmi_driver_unregister(&qpnp_iadc_driver);
+ platform_driver_unregister(&qpnp_iadc_driver);
}
module_exit(qpnp_iadc_exit);
diff --git a/drivers/hwmon/qpnp-adc-voltage.c b/drivers/hwmon/qpnp-adc-voltage.c
index 5799957771e8..ba80b4ce68a0 100644
--- a/drivers/hwmon/qpnp-adc-voltage.c
+++ b/drivers/hwmon/qpnp-adc-voltage.c
@@ -13,6 +13,7 @@
#define pr_fmt(fmt) "%s: " fmt, __func__
#include <linux/kernel.h>
+#include <linux/regmap.h>
#include <linux/of.h>
#include <linux/err.h>
#include <linux/init.h>
@@ -24,6 +25,7 @@
#include <linux/module.h>
#include <linux/debugfs.h>
#include <linux/spmi.h>
+#include <linux/platform_device.h>
#include <linux/of_irq.h>
#include <linux/interrupt.h>
#include <linux/completion.h>
@@ -179,7 +181,6 @@ struct qpnp_vadc_chip {
struct device *dev;
struct qpnp_adc_drv *adc;
struct list_head list;
- struct dentry *dent;
struct device *vadc_hwmon;
bool vadc_init_calib;
int max_channels_available;
@@ -190,8 +191,6 @@ struct qpnp_vadc_chip {
bool vadc_recalib_check;
u8 revision_ana_minor;
u8 revision_dig_major;
- struct workqueue_struct *high_thr_wq;
- struct workqueue_struct *low_thr_wq;
struct work_struct trigger_high_thr_work;
struct work_struct trigger_low_thr_work;
struct qpnp_vadc_mode_state *state_copy;
@@ -228,13 +227,15 @@ static int32_t qpnp_vadc_read_reg(struct qpnp_vadc_chip *vadc, int16_t reg,
u8 *data, int len)
{
int rc;
+ uint val;
- rc = spmi_ext_register_readl(vadc->adc->spmi->ctrl, vadc->adc->slave,
+ rc = regmap_bulk_read(vadc->adc->regmap,
(vadc->adc->offset + reg), data, len);
if (rc < 0) {
pr_err("qpnp adc read reg %d failed with %d\n", reg, rc);
return rc;
}
+ *data = (u8)val;
return 0;
}
@@ -244,7 +245,7 @@ static int32_t qpnp_vadc_write_reg(struct qpnp_vadc_chip *vadc, int16_t reg,
{
int rc;
- rc = spmi_ext_register_writel(vadc->adc->spmi->ctrl, vadc->adc->slave,
+ rc = regmap_bulk_write(vadc->adc->regmap,
(vadc->adc->offset + reg), buf, len);
if (rc < 0) {
pr_err("qpnp adc write reg %d failed with %d\n", reg, rc);
@@ -1530,7 +1531,7 @@ struct qpnp_vadc_chip *qpnp_get_vadc(struct device *dev, const char *name)
return ERR_PTR(-ENODEV);
list_for_each_entry(vadc, &qpnp_vadc_device_list, list)
- if (vadc->adc->spmi->dev.of_node == node)
+ if (vadc->adc->pdev->dev.of_node == node)
return vadc;
return ERR_PTR(-EPROBE_DEFER);
}
@@ -2437,10 +2438,10 @@ static struct sensor_device_attribute qpnp_adc_attr =
SENSOR_ATTR(NULL, S_IRUGO, qpnp_adc_show, NULL, 0);
static int32_t qpnp_vadc_init_hwmon(struct qpnp_vadc_chip *vadc,
- struct spmi_device *spmi)
+ struct platform_device *pdev)
{
struct device_node *child;
- struct device_node *node = spmi->dev.of_node;
+ struct device_node *node = pdev->dev.of_node;
int rc = 0, i = 0, channel;
for_each_child_of_node(node, child) {
@@ -2451,10 +2452,10 @@ static int32_t qpnp_vadc_init_hwmon(struct qpnp_vadc_chip *vadc,
memcpy(&vadc->sens_attr[i], &qpnp_adc_attr,
sizeof(qpnp_adc_attr));
sysfs_attr_init(&vadc->sens_attr[i].dev_attr.attr);
- rc = device_create_file(&spmi->dev,
+ rc = device_create_file(&pdev->dev,
&vadc->sens_attr[i].dev_attr);
if (rc) {
- dev_err(&spmi->dev,
+ dev_err(&pdev->dev,
"device_create_file failed for dev %s\n",
vadc->adc->adc_channels[i].name);
goto hwmon_err_sens;
@@ -2493,10 +2494,10 @@ static struct thermal_zone_device_ops qpnp_vadc_thermal_ops = {
};
static int32_t qpnp_vadc_init_thermal(struct qpnp_vadc_chip *vadc,
- struct spmi_device *spmi)
+ struct platform_device *pdev)
{
struct device_node *child;
- struct device_node *node = spmi->dev.of_node;
+ struct device_node *node = pdev->dev.of_node;
int rc = 0, i = 0;
bool thermal_node = false;
@@ -2542,12 +2543,12 @@ static const struct of_device_id qpnp_vadc_match_table[] = {
{}
};
-static int qpnp_vadc_probe(struct spmi_device *spmi)
+static int qpnp_vadc_probe(struct platform_device *pdev)
{
struct qpnp_vadc_chip *vadc;
struct qpnp_adc_drv *adc_qpnp;
struct qpnp_vadc_thermal_data *adc_thermal;
- struct device_node *node = spmi->dev.of_node;
+ struct device_node *node = pdev->dev.of_node;
struct device_node *child;
const struct of_device_id *id;
int rc, count_adc_channel_list = 0, i = 0;
@@ -2567,54 +2568,61 @@ static int qpnp_vadc_probe(struct spmi_device *spmi)
return -ENODEV;
}
- vadc = devm_kzalloc(&spmi->dev, sizeof(struct qpnp_vadc_chip) +
+ vadc = devm_kzalloc(&pdev->dev, sizeof(struct qpnp_vadc_chip) +
(sizeof(struct sensor_device_attribute) *
count_adc_channel_list), GFP_KERNEL);
if (!vadc) {
- dev_err(&spmi->dev, "Unable to allocate memory\n");
+ dev_err(&pdev->dev, "Unable to allocate memory\n");
return -ENOMEM;
}
- vadc->dev = &(spmi->dev);
- adc_qpnp = devm_kzalloc(&spmi->dev, sizeof(struct qpnp_adc_drv),
+ vadc->dev = &(pdev->dev);
+ adc_qpnp = devm_kzalloc(&pdev->dev, sizeof(struct qpnp_adc_drv),
GFP_KERNEL);
if (!adc_qpnp)
return -ENOMEM;
- vadc->state_copy = devm_kzalloc(&spmi->dev,
+ adc_qpnp->regmap = dev_get_regmap(pdev->dev.parent, NULL);
+ if (!adc_qpnp->regmap) {
+ dev_err(&pdev->dev, "Couldn't get parent's regmap\n");
+ return -EINVAL;
+ }
+
+ vadc->state_copy = devm_kzalloc(&pdev->dev,
sizeof(struct qpnp_vadc_mode_state), GFP_KERNEL);
if (!vadc->state_copy)
return -ENOMEM;
vadc->adc = adc_qpnp;
- adc_thermal = devm_kzalloc(&spmi->dev,
+ adc_thermal = devm_kzalloc(&pdev->dev,
(sizeof(struct qpnp_vadc_thermal_data) *
count_adc_channel_list), GFP_KERNEL);
if (!adc_thermal) {
- dev_err(&spmi->dev, "Unable to allocate memory\n");
+ dev_err(&pdev->dev, "Unable to allocate memory\n");
return -ENOMEM;
}
vadc->vadc_therm_chan = adc_thermal;
+
if (!strcmp(id->compatible, "qcom,qpnp-vadc-hc"))
vadc->vadc_hc = true;
- rc = qpnp_adc_get_devicetree_data(spmi, vadc->adc);
+ rc = qpnp_adc_get_devicetree_data(pdev, vadc->adc);
if (rc) {
- dev_err(&spmi->dev, "failed to read device tree\n");
+ dev_err(&pdev->dev, "failed to read device tree\n");
return rc;
}
mutex_init(&vadc->adc->adc_lock);
- rc = qpnp_vadc_init_hwmon(vadc, spmi);
+ rc = qpnp_vadc_init_hwmon(vadc, pdev);
if (rc) {
- dev_err(&spmi->dev, "failed to initialize qpnp hwmon adc\n");
+ dev_err(&pdev->dev, "failed to initialize qpnp hwmon adc\n");
return rc;
}
- vadc->vadc_hwmon = hwmon_device_register(&vadc->adc->spmi->dev);
- rc = qpnp_vadc_init_thermal(vadc, spmi);
+ vadc->vadc_hwmon = hwmon_device_register(&vadc->adc->pdev->dev);
+ rc = qpnp_vadc_init_thermal(vadc, pdev);
if (rc) {
- dev_err(&spmi->dev, "failed to initialize qpnp thermal adc\n");
+ dev_err(&pdev->dev, "failed to initialize qpnp thermal adc\n");
return rc;
}
vadc->vadc_init_calib = false;
@@ -2655,11 +2663,11 @@ static int qpnp_vadc_probe(struct spmi_device *spmi)
vadc->vadc_poll_eoc = of_property_read_bool(node,
"qcom,vadc-poll-eoc");
if (!vadc->vadc_poll_eoc) {
- rc = devm_request_irq(&spmi->dev, vadc->adc->adc_irq_eoc,
+ rc = devm_request_irq(&pdev->dev, vadc->adc->adc_irq_eoc,
qpnp_vadc_isr, IRQF_TRIGGER_RISING,
"qpnp_vadc_interrupt", vadc);
if (rc) {
- dev_err(&spmi->dev,
+ dev_err(&pdev->dev,
"failed to request adc irq with error %d\n", rc);
goto err_setup;
} else {
@@ -2671,37 +2679,37 @@ static int qpnp_vadc_probe(struct spmi_device *spmi)
vadc->state_copy->vadc_meas_int_enable = of_property_read_bool(node,
"qcom,vadc-meas-int-mode");
if (vadc->state_copy->vadc_meas_int_enable) {
- vadc->adc->adc_high_thr_irq = spmi_get_irq_byname(spmi,
- NULL, "high-thr-en-set");
+ vadc->adc->adc_high_thr_irq = platform_get_irq_byname(pdev,
+ "high-thr-en-set");
if (vadc->adc->adc_high_thr_irq < 0) {
pr_err("Invalid irq\n");
rc = -ENXIO;
goto err_setup;
}
- vadc->adc->adc_low_thr_irq = spmi_get_irq_byname(spmi,
- NULL, "low-thr-en-set");
+ vadc->adc->adc_low_thr_irq = platform_get_irq_byname(pdev,
+ "low-thr-en-set");
if (vadc->adc->adc_low_thr_irq < 0) {
pr_err("Invalid irq\n");
rc = -ENXIO;
goto err_setup;
}
- rc = devm_request_irq(&spmi->dev, vadc->adc->adc_high_thr_irq,
+ rc = devm_request_irq(&pdev->dev, vadc->adc->adc_high_thr_irq,
qpnp_vadc_high_thr_isr,
IRQF_TRIGGER_RISING, "qpnp_vadc_high_interrupt", vadc);
if (rc) {
- dev_err(&spmi->dev, "failed to request adc irq\n");
+ dev_err(&pdev->dev, "failed to request adc irq\n");
goto err_setup;
} else {
enable_irq_wake(vadc->adc->adc_high_thr_irq);
}
- rc = devm_request_irq(&spmi->dev, vadc->adc->adc_low_thr_irq,
+ rc = devm_request_irq(&pdev->dev, vadc->adc->adc_low_thr_irq,
qpnp_vadc_low_thr_isr,
IRQF_TRIGGER_RISING, "qpnp_vadc_low_interrupt", vadc);
if (rc) {
- dev_err(&spmi->dev, "failed to request adc irq\n");
+ dev_err(&pdev->dev, "failed to request adc irq\n");
goto err_setup;
} else {
enable_irq_wake(vadc->adc->adc_low_thr_irq);
@@ -2712,15 +2720,14 @@ static int qpnp_vadc_probe(struct spmi_device *spmi)
}
vadc->vadc_iadc_sync_lock = false;
- dev_set_drvdata(&spmi->dev, vadc);
+ dev_set_drvdata(&pdev->dev, vadc);
list_add(&vadc->list, &qpnp_vadc_device_list);
return 0;
err_setup:
for_each_child_of_node(node, child) {
- device_remove_file(&spmi->dev,
- &vadc->sens_attr[i].dev_attr);
+ device_remove_file(&pdev->dev, &vadc->sens_attr[i].dev_attr);
if (vadc->vadc_therm_chan[i].thermal_node)
thermal_zone_device_unregister(
vadc->vadc_therm_chan[i].tz_dev);
@@ -2731,16 +2738,15 @@ err_setup:
return rc;
}
-static int qpnp_vadc_remove(struct spmi_device *spmi)
+static int qpnp_vadc_remove(struct platform_device *pdev)
{
- struct qpnp_vadc_chip *vadc = dev_get_drvdata(&spmi->dev);
- struct device_node *node = spmi->dev.of_node;
+ struct qpnp_vadc_chip *vadc = dev_get_drvdata(&pdev->dev);
+ struct device_node *node = pdev->dev.of_node;
struct device_node *child;
int i = 0;
for_each_child_of_node(node, child) {
- device_remove_file(&spmi->dev,
- &vadc->sens_attr[i].dev_attr);
+ device_remove_file(&pdev->dev, &vadc->sens_attr[i].dev_attr);
if (vadc->vadc_therm_chan[i].thermal_node)
thermal_zone_device_unregister(
vadc->vadc_therm_chan[i].tz_dev);
@@ -2750,7 +2756,7 @@ static int qpnp_vadc_remove(struct spmi_device *spmi)
list_del(&vadc->list);
if (vadc->adc->hkadc_ldo && vadc->adc->hkadc_ldo_ok)
qpnp_adc_free_voltage_resource(vadc->adc);
- dev_set_drvdata(&spmi->dev, NULL);
+ dev_set_drvdata(&pdev->dev, NULL);
return 0;
}
@@ -2781,10 +2787,10 @@ static const struct dev_pm_ops qpnp_vadc_pm_ops = {
.suspend_noirq = qpnp_vadc_suspend_noirq,
};
-static struct spmi_driver qpnp_vadc_driver = {
+static struct platform_driver qpnp_vadc_driver = {
.driver = {
- .name = "qcom,qpnp-vadc",
- .of_match_table = qpnp_vadc_match_table,
+ .name = "qcom,qpnp-vadc",
+ .of_match_table = qpnp_vadc_match_table,
.pm = &qpnp_vadc_pm_ops,
},
.probe = qpnp_vadc_probe,
@@ -2793,13 +2799,13 @@ static struct spmi_driver qpnp_vadc_driver = {
static int __init qpnp_vadc_init(void)
{
- return spmi_driver_register(&qpnp_vadc_driver);
+ return platform_driver_register(&qpnp_vadc_driver);
}
module_init(qpnp_vadc_init);
static void __exit qpnp_vadc_exit(void)
{
- spmi_driver_unregister(&qpnp_vadc_driver);
+ platform_driver_unregister(&qpnp_vadc_driver);
}
module_exit(qpnp_vadc_exit);
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index d971205be2d3..608f0c12e3ab 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -581,6 +581,30 @@ config LEDS_POWERNV
depends on LEDS_CLASS
depends on PPC_POWERNV
depends on OF
+
+config LEDS_QPNP
+ tristate "Support for QPNP LEDs"
+ depends on LEDS_CLASS && SPMI
+ help
+ This driver supports the leds functionality of Qualcomm PNP PMIC. It
+ includes RGB Leds, WLED and Flash Led.
+
+ To compile this driver as a module, choose M here: the module will
+ be called leds-qpnp.
+
+config LEDS_QPNP_FLASH
+ tristate "Support for QPNP Flash LEDs"
+ depends on LEDS_CLASS && SPMI
+ help
+ This driver supports the leds functionality of Qualcomm Technologies
+ PNP PMIC. It includes Flash Led.
+
+ To compile this driver as a module, choose M here: the module will
+ be called leds-qpnp-flash.
+
+config LEDS_QPNP_WLED
+ tristate "Support for QPNP WLED"
+ depends on LEDS_CLASS && SPMI
help
This option enables support for the system LEDs present on
PowerNV platforms. Say 'y' to enable this support in kernel.
@@ -589,7 +613,7 @@ config LEDS_POWERNV
config LEDS_QPNP
tristate "Support for QPNP LEDs"
- depends on LEDS_CLASS && MSM_SPMI && OF_SPMI
+ depends on LEDS_CLASS && SPMI
help
This driver supports the leds functionality of Qualcomm PNP PMIC. It
includes RGB Leds, WLED and Flash Led.
@@ -599,7 +623,7 @@ config LEDS_QPNP
config LEDS_QPNP_FLASH
tristate "Support for QPNP Flash LEDs"
- depends on LEDS_CLASS && MSM_SPMI && OF_SPMI
+ depends on LEDS_CLASS && SPMI
help
This driver supports the leds functionality of Qualcomm Technologies
PNP PMIC. It includes Flash Led.
@@ -609,7 +633,7 @@ config LEDS_QPNP_FLASH
config LEDS_QPNP_WLED
tristate "Support for QPNP WLED"
- depends on LEDS_CLASS && MSM_SPMI && OF_SPMI
+ depends on LEDS_CLASS && SPMI
help
This driver supports the WLED (White LED) functionality of
Qualcomm Technologies PNP PMIC. WLED is used for display backlight.
diff --git a/drivers/leds/leds-qpnp-flash.c b/drivers/leds/leds-qpnp-flash.c
index a82f5741d344..edefb9c5558d 100644
--- a/drivers/leds/leds-qpnp-flash.c
+++ b/drivers/leds/leds-qpnp-flash.c
@@ -13,11 +13,13 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
+#include <linux/regmap.h>
#include <linux/errno.h>
#include <linux/leds.h>
#include <linux/slab.h>
#include <linux/of_device.h>
#include <linux/spmi.h>
+#include <linux/platform_device.h>
#include <linux/err.h>
#include <linux/delay.h>
#include <linux/of.h>
@@ -176,7 +178,8 @@ struct flash_regulator_data {
* Configurations for each individual LED
*/
struct flash_node_data {
- struct spmi_device *spmi_dev;
+ struct platform_device *pdev;
+ struct regmap *regmap;
struct led_classdev cdev;
struct work_struct work;
struct flash_regulator_data *reg_data;
@@ -234,7 +237,8 @@ struct qpnp_flash_led_buffer {
*/
struct qpnp_flash_led {
struct pmic_revid_data *revid_data;
- struct spmi_device *spmi_dev;
+ struct platform_device *pdev;
+ struct regmap *regmap;
struct flash_led_platform_data *pdata;
struct pinctrl *pinctrl;
struct pinctrl_state *gpio_state_active;
@@ -325,7 +329,7 @@ static ssize_t flash_led_dfs_latched_reg_read(struct file *fp, char __user *buf,
size_t count, loff_t *ppos) {
struct qpnp_flash_led *led = fp->private_data;
struct qpnp_flash_led_buffer *log = led->log;
- u8 val;
+ uint val;
int rc;
size_t len;
size_t ret;
@@ -333,10 +337,9 @@ static ssize_t flash_led_dfs_latched_reg_read(struct file *fp, char __user *buf,
if (log->rpos >= log->wpos && led->buffer_cnt == 0)
return 0;
- rc = spmi_ext_register_readl(led->spmi_dev->ctrl,
- led->spmi_dev->sid, INT_LATCHED_STS(led->base), &val, 1);
+ rc = regmap_read(led->regmap, INT_LATCHED_STS(led->base), &val);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Unable to read from address %x, rc(%d)\n",
INT_LATCHED_STS(led->base), rc);
return -EINVAL;
@@ -519,25 +522,13 @@ static int
qpnp_led_masked_write(struct qpnp_flash_led *led, u16 addr, u8 mask, u8 val)
{
int rc;
- u8 reg;
-
- rc = spmi_ext_register_readl(led->spmi_dev->ctrl, led->spmi_dev->sid,
- addr, &reg, 1);
- if (rc)
- dev_err(&led->spmi_dev->dev,
- "Unable to read from addr=%x, rc(%d)\n", addr, rc);
-
- reg &= ~mask;
- reg |= val;
- rc = spmi_ext_register_writel(led->spmi_dev->ctrl, led->spmi_dev->sid,
- addr, &reg, 1);
+ rc = regmap_update_bits(led->regmap, addr, mask, val);
if (rc)
- dev_err(&led->spmi_dev->dev,
- "Unable to write to addr=%x, rc(%d)\n", addr, rc);
+ dev_err(&led->pdev->dev,
+ "Unable to update_bits to addr=%x, rc(%d)\n", addr, rc);
- dev_dbg(&led->spmi_dev->dev, "Write 0x%02X to addr 0x%02X\n",
- val, addr);
+ dev_dbg(&led->pdev->dev, "Write 0x%02X to addr 0x%02X\n", val, addr);
return rc;
}
@@ -581,10 +572,10 @@ static int qpnp_get_pmic_revid(struct qpnp_flash_led *led)
{
struct device_node *revid_dev_node;
- revid_dev_node = of_parse_phandle(led->spmi_dev->dev.of_node,
+ revid_dev_node = of_parse_phandle(led->pdev->dev.of_node,
"qcom,pmic-revid", 0);
if (!revid_dev_node) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"qcom,pmic-revid property missing\n");
return -EINVAL;
}
@@ -611,7 +602,7 @@ qpnp_flash_led_get_max_avail_current(struct flash_node_data *flash_node,
if (led->pdata->power_detect_en) {
if (!led->battery_psy) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Failed to query power supply\n");
return -EINVAL;
}
@@ -626,7 +617,7 @@ qpnp_flash_led_get_max_avail_current(struct flash_node_data *flash_node,
FLASH_MODULE_ENABLE_CTRL(led->base),
FLASH_MODULE_ENABLE, FLASH_MODULE_ENABLE);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Module enable reg write failed\n");
return -EINVAL;
}
@@ -638,7 +629,7 @@ qpnp_flash_led_get_max_avail_current(struct flash_node_data *flash_node,
led->battery_psy->get_property(led->battery_psy,
POWER_SUPPLY_PROP_FLASH_CURRENT_MAX, &prop);
if (!prop.intval) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"battery too low for flash\n");
return -EINVAL;
}
@@ -684,7 +675,7 @@ static ssize_t qpnp_flash_led_die_temp_store(struct device *dev,
return ret;
flash_node = container_of(led_cdev, struct flash_node_data, cdev);
- led = dev_get_drvdata(&flash_node->spmi_dev->dev);
+ led = dev_get_drvdata(&flash_node->pdev->dev);
/*'0' for disable die_temp feature; non-zero to enable feature*/
if (val == 0)
@@ -727,23 +718,22 @@ static ssize_t qpnp_flash_led_dump_regs_show(struct device *dev,
struct led_classdev *led_cdev = dev_get_drvdata(dev);
int rc, i, count = 0;
u16 addr;
- u8 val;
+ uint val;
flash_node = container_of(led_cdev, struct flash_node_data, cdev);
- led = dev_get_drvdata(&flash_node->spmi_dev->dev);
+ led = dev_get_drvdata(&flash_node->pdev->dev);
for (i = 0; i < ARRAY_SIZE(qpnp_flash_led_ctrl_dbg_regs); i++) {
addr = led->base + qpnp_flash_led_ctrl_dbg_regs[i];
- rc = spmi_ext_register_readl(led->spmi_dev->ctrl,
- led->spmi_dev->sid, addr, &val, 1);
+ rc = regmap_read(led->regmap, addr, &val);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Unable to read from addr=%x, rc(%d)\n",
addr, rc);
return -EINVAL;
}
count += snprintf(buf + count, PAGE_SIZE - count,
- "REG_0x%x = 0x%x\n", addr, val);
+ "REG_0x%x = 0x%02x\n", addr, val);
if (count >= PAGE_SIZE)
return PAGE_SIZE - 1;
@@ -767,7 +757,7 @@ static ssize_t qpnp_flash_led_current_derate_store(struct device *dev,
return ret;
flash_node = container_of(led_cdev, struct flash_node_data, cdev);
- led = dev_get_drvdata(&flash_node->spmi_dev->dev);
+ led = dev_get_drvdata(&flash_node->pdev->dev);
/*'0' for disable derate feature; non-zero to enable derate feature */
if (val == 0)
@@ -787,7 +777,7 @@ static ssize_t qpnp_flash_led_max_current_show(struct device *dev,
int max_curr_avail_ma = 0;
flash_node = container_of(led_cdev, struct flash_node_data, cdev);
- led = dev_get_drvdata(&flash_node->spmi_dev->dev);
+ led = dev_get_drvdata(&flash_node->pdev->dev);
if (led->flash_node[0].flash_on)
max_curr_avail_ma += led->flash_node[0].max_current;
@@ -912,14 +902,12 @@ static int
qpnp_flash_led_get_peripheral_type(struct qpnp_flash_led *led)
{
int rc;
- u8 val;
+ uint val;
- rc = spmi_ext_register_readl(led->spmi_dev->ctrl,
- led->spmi_dev->sid,
- FLASH_LED_PERIPHERAL_SUBTYPE(led->base),
- &val, 1);
+ rc = regmap_read(led->regmap,
+ FLASH_LED_PERIPHERAL_SUBTYPE(led->base), &val);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Unable to read peripheral subtype\n");
return -EINVAL;
}
@@ -932,15 +920,11 @@ static int qpnp_flash_led_module_disable(struct qpnp_flash_led *led,
{
union power_supply_propval psy_prop;
int rc;
- u8 val, tmp;
+ uint val, tmp;
- rc = spmi_ext_register_readl(led->spmi_dev->ctrl,
- led->spmi_dev->sid,
- FLASH_LED_STROBE_CTRL(led->base),
- &val, 1);
+ rc = regmap_read(led->regmap, FLASH_LED_STROBE_CTRL(led->base), &val);
if (rc) {
- dev_err(&led->spmi_dev->dev,
- "Unable to read strobe reg\n");
+ dev_err(&led->pdev->dev, "Unable to read strobe reg\n");
return -EINVAL;
}
@@ -951,7 +935,7 @@ static int qpnp_flash_led_module_disable(struct qpnp_flash_led *led,
FLASH_LED_UNLOCK_SECURE(led->base),
FLASH_SECURE_MASK, FLASH_UNLOCK_SECURE);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Secure reg write failed\n");
return -EINVAL;
}
@@ -960,7 +944,7 @@ static int qpnp_flash_led_module_disable(struct qpnp_flash_led *led,
FLASH_TORCH(led->base),
FLASH_TORCH_MASK, FLASH_LED_TORCH_DISABLE);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Torch reg write failed\n");
return -EINVAL;
}
@@ -974,7 +958,7 @@ static int qpnp_flash_led_module_disable(struct qpnp_flash_led *led,
POWER_SUPPLY_PROP_FLASH_TRIGGER,
&psy_prop);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Failed to enble charger i/p current limit\n");
return -EINVAL;
}
@@ -985,8 +969,7 @@ static int qpnp_flash_led_module_disable(struct qpnp_flash_led *led,
FLASH_MODULE_ENABLE_MASK,
FLASH_LED_MODULE_CTRL_DEFAULT);
if (rc) {
- dev_err(&led->spmi_dev->dev,
- "Module disable failed\n");
+ dev_err(&led->pdev->dev, "Module disable failed\n");
return -EINVAL;
}
@@ -994,7 +977,7 @@ static int qpnp_flash_led_module_disable(struct qpnp_flash_led *led,
rc = pinctrl_select_state(led->pinctrl,
led->gpio_state_suspend);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"failed to disable GPIO\n");
return -EINVAL;
}
@@ -1007,7 +990,7 @@ static int qpnp_flash_led_module_disable(struct qpnp_flash_led *led,
POWER_SUPPLY_PROP_FLASH_ACTIVE,
&psy_prop);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Failed to setup OTG pulse skip enable\n");
return -EINVAL;
}
@@ -1019,7 +1002,7 @@ static int qpnp_flash_led_module_disable(struct qpnp_flash_led *led,
led->current_addr,
FLASH_CURRENT_MASK, 0x00);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"current register write failed\n");
return -EINVAL;
}
@@ -1030,7 +1013,7 @@ static int qpnp_flash_led_module_disable(struct qpnp_flash_led *led,
led->current2_addr,
FLASH_CURRENT_MASK, 0x00);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"current register write failed\n");
return -EINVAL;
}
@@ -1057,12 +1040,12 @@ static int flash_regulator_parse_dt(struct qpnp_flash_led *led,
const char *temp_string;
u32 val;
- flash_node->reg_data = devm_kzalloc(&led->spmi_dev->dev,
+ flash_node->reg_data = devm_kzalloc(&led->pdev->dev,
sizeof(struct flash_regulator_data *) *
flash_node->num_regulators,
GFP_KERNEL);
if (!flash_node->reg_data) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Unable to allocate memory\n");
return -ENOMEM;
}
@@ -1073,7 +1056,7 @@ static int flash_regulator_parse_dt(struct qpnp_flash_led *led,
if (!rc)
flash_node->reg_data[i].reg_name = temp_string;
else {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Unable to read regulator name\n");
return rc;
}
@@ -1082,7 +1065,7 @@ static int flash_regulator_parse_dt(struct qpnp_flash_led *led,
if (!rc) {
flash_node->reg_data[i].max_volt_uv = val;
} else if (rc != -EINVAL) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Unable to read max voltage\n");
return rc;
}
@@ -1109,7 +1092,7 @@ static int flash_regulator_setup(struct qpnp_flash_led *led,
flash_node->reg_data[i].reg_name);
if (IS_ERR(flash_node->reg_data[i].regs)) {
rc = PTR_ERR(flash_node->reg_data[i].regs);
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Failed to get regulator\n");
goto error_regulator_setup;
}
@@ -1120,7 +1103,7 @@ static int flash_regulator_setup(struct qpnp_flash_led *led,
flash_node->reg_data[i].max_volt_uv,
flash_node->reg_data[i].max_volt_uv);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"regulator set voltage failed\n");
regulator_put(flash_node->reg_data[i].regs);
goto error_regulator_setup;
@@ -1157,7 +1140,7 @@ static int flash_regulator_enable(struct qpnp_flash_led *led,
for (i = 0; i < flash_node->num_regulators; i++) {
rc = regulator_enable(flash_node->reg_data[i].regs);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"regulator enable failed\n");
goto error_regulator_enable;
}
@@ -1176,14 +1159,14 @@ static void qpnp_flash_led_work(struct work_struct *work)
{
struct flash_node_data *flash_node = container_of(work,
struct flash_node_data, work);
- struct qpnp_flash_led *led =
- dev_get_drvdata(&flash_node->spmi_dev->dev);
+ struct qpnp_flash_led *led = dev_get_drvdata(&flash_node->pdev->dev);
union power_supply_propval psy_prop;
int rc, brightness = flash_node->cdev.brightness;
int max_curr_avail_ma = 0;
int total_curr_ma = 0;
int i;
u8 val;
+ uint temp;
mutex_lock(&led->flash_led_lock);
@@ -1191,7 +1174,7 @@ static void qpnp_flash_led_work(struct work_struct *work)
goto turn_off;
if (led->open_fault) {
- dev_err(&led->spmi_dev->dev, "Open fault detected\n");
+ dev_err(&led->pdev->dev, "Open fault detected\n");
mutex_unlock(&led->flash_led_lock);
return;
}
@@ -1208,8 +1191,7 @@ static void qpnp_flash_led_work(struct work_struct *work)
rc = pinctrl_select_state(led->pinctrl,
led->gpio_state_active);
if (rc) {
- dev_err(&led->spmi_dev->dev,
- "failed to enable GPIO\n");
+ dev_err(&led->pdev->dev, "failed to enable GPIO\n");
goto error_enable_gpio;
}
led->gpio_enabled = true;
@@ -1220,7 +1202,7 @@ static void qpnp_flash_led_work(struct work_struct *work)
INT_SET_TYPE(led->base),
FLASH_STATUS_REG_MASK, 0x1F);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"INT_SET_TYPE write failed\n");
goto exit_flash_led_work;
}
@@ -1229,7 +1211,7 @@ static void qpnp_flash_led_work(struct work_struct *work)
IN_POLARITY_HIGH(led->base),
FLASH_STATUS_REG_MASK, 0x1F);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"IN_POLARITY_HIGH write failed\n");
goto exit_flash_led_work;
}
@@ -1238,8 +1220,7 @@ static void qpnp_flash_led_work(struct work_struct *work)
INT_EN_SET(led->base),
FLASH_STATUS_REG_MASK, 0x1F);
if (rc) {
- dev_err(&led->spmi_dev->dev,
- "INT_EN_SET write failed\n");
+ dev_err(&led->pdev->dev, "INT_EN_SET write failed\n");
goto exit_flash_led_work;
}
@@ -1247,7 +1228,7 @@ static void qpnp_flash_led_work(struct work_struct *work)
INT_LATCHED_CLR(led->base),
FLASH_STATUS_REG_MASK, 0x1F);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"INT_LATCHED_CLR write failed\n");
goto exit_flash_led_work;
}
@@ -1258,8 +1239,7 @@ static void qpnp_flash_led_work(struct work_struct *work)
FLASH_LED_UNLOCK_SECURE(led->base),
FLASH_SECURE_MASK, FLASH_UNLOCK_SECURE);
if (rc) {
- dev_err(&led->spmi_dev->dev,
- "Secure reg write failed\n");
+ dev_err(&led->pdev->dev, "Secure reg write failed\n");
goto exit_flash_led_work;
}
@@ -1267,8 +1247,7 @@ static void qpnp_flash_led_work(struct work_struct *work)
FLASH_TORCH(led->base),
FLASH_TORCH_MASK, FLASH_LED_TORCH_ENABLE);
if (rc) {
- dev_err(&led->spmi_dev->dev,
- "Torch reg write failed\n");
+ dev_err(&led->pdev->dev, "Torch reg write failed\n");
goto exit_flash_led_work;
}
@@ -1280,7 +1259,7 @@ static void qpnp_flash_led_work(struct work_struct *work)
led->current_addr,
FLASH_CURRENT_MASK, val);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Torch reg write failed\n");
goto exit_flash_led_work;
}
@@ -1292,7 +1271,7 @@ static void qpnp_flash_led_work(struct work_struct *work)
led->current2_addr,
FLASH_CURRENT_MASK, val);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Torch reg write failed\n");
goto exit_flash_led_work;
}
@@ -1305,7 +1284,7 @@ static void qpnp_flash_led_work(struct work_struct *work)
led->current_addr,
FLASH_CURRENT_MASK, val);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"current reg write failed\n");
goto exit_flash_led_work;
}
@@ -1314,7 +1293,7 @@ static void qpnp_flash_led_work(struct work_struct *work)
led->current2_addr,
FLASH_CURRENT_MASK, val);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"current reg write failed\n");
goto exit_flash_led_work;
}
@@ -1325,7 +1304,7 @@ static void qpnp_flash_led_work(struct work_struct *work)
FLASH_MAX_CURRENT(led->base),
FLASH_CURRENT_MASK, FLASH_TORCH_MAX_LEVEL);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Max current reg write failed\n");
goto exit_flash_led_work;
}
@@ -1334,7 +1313,7 @@ static void qpnp_flash_led_work(struct work_struct *work)
FLASH_MODULE_ENABLE_CTRL(led->base),
FLASH_MODULE_ENABLE_MASK, FLASH_MODULE_ENABLE);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Module enable reg write failed\n");
goto exit_flash_led_work;
}
@@ -1350,7 +1329,7 @@ static void qpnp_flash_led_work(struct work_struct *work)
FLASH_LED_HDRM_SNS_ENABLE :
FLASH_LED_HDRM_SNS_DISABLE);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Headroom sense enable failed\n");
goto exit_flash_led_work;
}
@@ -1363,7 +1342,7 @@ static void qpnp_flash_led_work(struct work_struct *work)
FLASH_LED_HDRM_SNS_ENABLE :
FLASH_LED_HDRM_SNS_DISABLE);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Headroom sense enable failed\n");
goto exit_flash_led_work;
}
@@ -1373,7 +1352,7 @@ static void qpnp_flash_led_work(struct work_struct *work)
FLASH_LED_HDRM_SNS_ENABLE_MASK,
FLASH_LED_HDRM_SNS_ENABLE);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Headroom sense disable failed\n");
goto exit_flash_led_work;
}
@@ -1383,7 +1362,7 @@ static void qpnp_flash_led_work(struct work_struct *work)
FLASH_LED_HDRM_SNS_ENABLE_MASK,
FLASH_LED_HDRM_SNS_ENABLE);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Headroom sense disable failed\n");
goto exit_flash_led_work;
}
@@ -1398,8 +1377,7 @@ static void qpnp_flash_led_work(struct work_struct *work)
FLASH_LED_STROBE_TYPE_HW),
flash_node->trigger);
if (rc) {
- dev_err(&led->spmi_dev->dev,
- "Strobe reg write failed\n");
+ dev_err(&led->pdev->dev, "Strobe reg write failed\n");
goto exit_flash_led_work;
}
} else if (flash_node->type == FLASH) {
@@ -1413,7 +1391,7 @@ static void qpnp_flash_led_work(struct work_struct *work)
POWER_SUPPLY_PROP_FLASH_ACTIVE,
&psy_prop);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Failed to setup OTG pulse skip enable\n");
goto exit_flash_led_work;
}
@@ -1425,7 +1403,7 @@ static void qpnp_flash_led_work(struct work_struct *work)
POWER_SUPPLY_PROP_STATUS,
&psy_prop);
if (psy_prop.intval < 0) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Invalid battery status\n");
goto exit_flash_led_work;
}
@@ -1443,7 +1421,7 @@ static void qpnp_flash_led_work(struct work_struct *work)
qpnp_flash_led_get_max_avail_current
(flash_node, led);
if (max_curr_avail_ma < 0) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Failed to get max avail curr\n");
goto exit_flash_led_work;
}
@@ -1469,7 +1447,7 @@ static void qpnp_flash_led_work(struct work_struct *work)
rc = qpnp_led_masked_write(led,
led->current_addr, FLASH_CURRENT_MASK, val);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Current register write failed\n");
goto exit_flash_led_work;
}
@@ -1479,14 +1457,13 @@ static void qpnp_flash_led_work(struct work_struct *work)
rc = qpnp_led_masked_write(led,
led->current2_addr, FLASH_CURRENT_MASK, val);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Current register write failed\n");
goto exit_flash_led_work;
}
} else {
- if (max_curr_avail_ma <
- flash_node->prgm_current) {
- dev_err(&led->spmi_dev->dev,
+ if (max_curr_avail_ma < flash_node->prgm_current) {
+ dev_err(&led->pdev->dev,
"battery only supprots %d mA\n",
max_curr_avail_ma);
flash_node->prgm_current =
@@ -1502,7 +1479,7 @@ static void qpnp_flash_led_work(struct work_struct *work)
led->current_addr,
FLASH_CURRENT_MASK, val);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"current reg write failed\n");
goto exit_flash_led_work;
}
@@ -1512,7 +1489,7 @@ static void qpnp_flash_led_work(struct work_struct *work)
led->current2_addr,
FLASH_CURRENT_MASK, val);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"current reg write failed\n");
goto exit_flash_led_work;
}
@@ -1525,7 +1502,7 @@ static void qpnp_flash_led_work(struct work_struct *work)
FLASH_SAFETY_TIMER(led->base),
FLASH_SAFETY_TIMER_MASK, val);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Safety timer reg write failed\n");
goto exit_flash_led_work;
}
@@ -1534,7 +1511,7 @@ static void qpnp_flash_led_work(struct work_struct *work)
FLASH_MAX_CURRENT(led->base),
FLASH_CURRENT_MASK, FLASH_MAX_LEVEL);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Max current reg write failed\n");
goto exit_flash_led_work;
}
@@ -1544,7 +1521,7 @@ static void qpnp_flash_led_work(struct work_struct *work)
FLASH_MODULE_ENABLE_CTRL(led->base),
FLASH_MODULE_ENABLE, FLASH_MODULE_ENABLE);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Module enable reg write failed\n");
goto exit_flash_led_work;
}
@@ -1559,7 +1536,7 @@ static void qpnp_flash_led_work(struct work_struct *work)
POWER_SUPPLY_PROP_FLASH_TRIGGER,
&psy_prop);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Failed to disable charger i/p curr limit\n");
goto exit_flash_led_work;
}
@@ -1576,7 +1553,7 @@ static void qpnp_flash_led_work(struct work_struct *work)
FLASH_LED_HDRM_SNS_ENABLE :
FLASH_LED_HDRM_SNS_DISABLE));
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Headroom sense enable failed\n");
goto exit_flash_led_work;
}
@@ -1589,7 +1566,7 @@ static void qpnp_flash_led_work(struct work_struct *work)
FLASH_LED_HDRM_SNS_ENABLE :
FLASH_LED_HDRM_SNS_DISABLE));
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Headroom sense enable failed\n");
goto exit_flash_led_work;
}
@@ -1599,7 +1576,7 @@ static void qpnp_flash_led_work(struct work_struct *work)
FLASH_LED_HDRM_SNS_ENABLE_MASK,
FLASH_LED_HDRM_SNS_ENABLE);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Headroom sense disable failed\n");
goto exit_flash_led_work;
}
@@ -1609,7 +1586,7 @@ static void qpnp_flash_led_work(struct work_struct *work)
FLASH_LED_HDRM_SNS_ENABLE_MASK,
FLASH_LED_HDRM_SNS_ENABLE);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Headroom sense disable failed\n");
goto exit_flash_led_work;
}
@@ -1624,24 +1601,22 @@ static void qpnp_flash_led_work(struct work_struct *work)
FLASH_LED_STROBE_TYPE_HW),
flash_node->trigger);
if (rc) {
- dev_err(&led->spmi_dev->dev,
- "Strobe reg write failed\n");
+ dev_err(&led->pdev->dev, "Strobe reg write failed\n");
goto exit_flash_led_work;
}
if (led->strobe_debug && led->dbg_feature_en) {
udelay(2000);
- rc = spmi_ext_register_readl(led->spmi_dev->ctrl,
- led->spmi_dev->sid,
- FLASH_LED_FAULT_STATUS(led->base),
- &val, 1);
+ rc = regmap_read(led->regmap,
+ FLASH_LED_FAULT_STATUS(led->base),
+ &temp);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Unable to read from addr= %x, rc(%d)\n",
FLASH_LED_FAULT_STATUS(led->base), rc);
goto exit_flash_led_work;
}
- led->fault_reg = val;
+ led->fault_reg = temp;
}
} else {
pr_err("Both Torch and Flash cannot be select at same time\n");
@@ -1662,16 +1637,15 @@ turn_off:
* If fault occurs, all subsequent LED enablement requests
* will be rejected to protect hardware.
*/
- rc = spmi_ext_register_readl(led->spmi_dev->ctrl,
- led->spmi_dev->sid,
- FLASH_LED_FAULT_STATUS(led->base), &val, 1);
+ rc = regmap_read(led->regmap,
+ FLASH_LED_FAULT_STATUS(led->base), &temp);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Failed to read out fault status register\n");
goto exit_flash_led_work;
}
- led->open_fault = (val & FLASH_LED_OPEN_FAULT_DETECTED);
+ led->open_fault = (temp & FLASH_LED_OPEN_FAULT_DETECTED);
}
rc = qpnp_led_masked_write(led,
@@ -1682,7 +1656,7 @@ turn_off:
| FLASH_LED_STROBE_TYPE_HW),
FLASH_LED_DISABLE);
if (rc) {
- dev_err(&led->spmi_dev->dev, "Strobe disable failed\n");
+ dev_err(&led->pdev->dev, "Strobe disable failed\n");
goto exit_flash_led_work;
}
@@ -1696,7 +1670,7 @@ exit_flash_hdrm_sns:
FLASH_LED_HDRM_SNS_ENABLE_MASK,
FLASH_LED_HDRM_SNS_DISABLE);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Headroom sense disable failed\n");
goto exit_flash_hdrm_sns;
}
@@ -1711,7 +1685,7 @@ exit_flash_hdrm_sns:
FLASH_LED_HDRM_SNS_ENABLE_MASK,
FLASH_LED_HDRM_SNS_DISABLE);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Headroom sense disable failed\n");
goto exit_flash_hdrm_sns;
}
@@ -1720,7 +1694,7 @@ exit_flash_hdrm_sns:
exit_flash_led_work:
rc = qpnp_flash_led_module_disable(led, flash_node);
if (rc) {
- dev_err(&led->spmi_dev->dev, "Module disable failed\n");
+ dev_err(&led->pdev->dev, "Module disable failed\n");
goto exit_flash_led_work;
}
error_enable_gpio:
@@ -1738,8 +1712,9 @@ static void qpnp_flash_led_brightness_set(struct led_classdev *led_cdev,
{
struct flash_node_data *flash_node;
struct qpnp_flash_led *led;
+
flash_node = container_of(led_cdev, struct flash_node_data, cdev);
- led = dev_get_drvdata(&flash_node->spmi_dev->dev);
+ led = dev_get_drvdata(&flash_node->pdev->dev);
if (value < LED_OFF) {
pr_err("Invalid brightness value\n");
@@ -1804,13 +1779,14 @@ static int qpnp_flash_led_init_settings(struct qpnp_flash_led *led)
{
int rc;
u8 val, temp_val;
+ uint val_int;
rc = qpnp_led_masked_write(led,
FLASH_MODULE_ENABLE_CTRL(led->base),
FLASH_MODULE_ENABLE_MASK,
FLASH_LED_MODULE_CTRL_DEFAULT);
if (rc) {
- dev_err(&led->spmi_dev->dev, "Module disable failed\n");
+ dev_err(&led->pdev->dev, "Module disable failed\n");
return rc;
}
@@ -1818,7 +1794,7 @@ static int qpnp_flash_led_init_settings(struct qpnp_flash_led *led)
FLASH_LED_STROBE_CTRL(led->base),
FLASH_STROBE_MASK, FLASH_LED_DISABLE);
if (rc) {
- dev_err(&led->spmi_dev->dev, "Strobe disable failed\n");
+ dev_err(&led->pdev->dev, "Strobe disable failed\n");
return rc;
}
@@ -1826,7 +1802,7 @@ static int qpnp_flash_led_init_settings(struct qpnp_flash_led *led)
FLASH_LED_TMR_CTRL(led->base),
FLASH_TMR_MASK, FLASH_TMR_SAFETY);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"LED timer ctrl reg write failed(%d)\n", rc);
return rc;
}
@@ -1837,7 +1813,7 @@ static int qpnp_flash_led_init_settings(struct qpnp_flash_led *led)
FLASH_HEADROOM(led->base),
FLASH_HEADROOM_MASK, val);
if (rc) {
- dev_err(&led->spmi_dev->dev, "Headroom reg write failed\n");
+ dev_err(&led->pdev->dev, "Headroom reg write failed\n");
return rc;
}
@@ -1847,8 +1823,7 @@ static int qpnp_flash_led_init_settings(struct qpnp_flash_led *led)
FLASH_STARTUP_DELAY(led->base),
FLASH_STARTUP_DLY_MASK, val);
if (rc) {
- dev_err(&led->spmi_dev->dev,
- "Startup delay reg write failed\n");
+ dev_err(&led->pdev->dev, "Startup delay reg write failed\n");
return rc;
}
@@ -1858,8 +1833,7 @@ static int qpnp_flash_led_init_settings(struct qpnp_flash_led *led)
FLASH_CLAMP_CURRENT(led->base),
FLASH_CURRENT_MASK, val);
if (rc) {
- dev_err(&led->spmi_dev->dev,
- "Clamp current reg write failed\n");
+ dev_err(&led->pdev->dev, "Clamp current reg write failed\n");
return rc;
}
@@ -1871,8 +1845,7 @@ static int qpnp_flash_led_init_settings(struct qpnp_flash_led *led)
FLASH_VREG_OK_FORCE(led->base),
FLASH_VREG_OK_FORCE_MASK, val);
if (rc) {
- dev_err(&led->spmi_dev->dev,
- "VREG OK force reg write failed\n");
+ dev_err(&led->pdev->dev, "VREG OK force reg write failed\n");
return rc;
}
@@ -1884,8 +1857,7 @@ static int qpnp_flash_led_init_settings(struct qpnp_flash_led *led)
FLASH_FAULT_DETECT(led->base),
FLASH_FAULT_DETECT_MASK, val);
if (rc) {
- dev_err(&led->spmi_dev->dev,
- "Fault detect reg write failed\n");
+ dev_err(&led->pdev->dev, "Fault detect reg write failed\n");
return rc;
}
@@ -1895,28 +1867,26 @@ static int qpnp_flash_led_init_settings(struct qpnp_flash_led *led)
rc = qpnp_led_masked_write(led, FLASH_MASK_ENABLE(led->base),
FLASH_MASK_MODULE_CONTRL_MASK, val);
if (rc) {
- dev_err(&led->spmi_dev->dev, "Mask module enable failed\n");
+ dev_err(&led->pdev->dev, "Mask module enable failed\n");
return rc;
}
- rc = spmi_ext_register_readl(led->spmi_dev->ctrl,
- led->spmi_dev->sid,
- FLASH_PERPH_RESET_CTRL(led->base),
- &val, 1);
+ rc = regmap_read(led->regmap, FLASH_PERPH_RESET_CTRL(led->base),
+ &val_int);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Unable to read from address %x, rc(%d)\n",
FLASH_PERPH_RESET_CTRL(led->base), rc);
return -EINVAL;
}
+ val = (u8)val_int;
if (led->pdata->follow_rb_disable) {
rc = qpnp_led_masked_write(led,
FLASH_LED_UNLOCK_SECURE(led->base),
FLASH_SECURE_MASK, FLASH_UNLOCK_SECURE);
if (rc) {
- dev_err(&led->spmi_dev->dev,
- "Secure reg write failed\n");
+ dev_err(&led->pdev->dev, "Secure reg write failed\n");
return -EINVAL;
}
@@ -1925,7 +1895,7 @@ static int qpnp_flash_led_init_settings(struct qpnp_flash_led *led)
FLASH_PERPH_RESET_CTRL(led->base),
FLASH_FOLLOW_OTST2_RB_MASK, val);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"failed to reset OTST2_RB bit\n");
return rc;
}
@@ -1934,8 +1904,7 @@ static int qpnp_flash_led_init_settings(struct qpnp_flash_led *led)
FLASH_LED_UNLOCK_SECURE(led->base),
FLASH_SECURE_MASK, FLASH_UNLOCK_SECURE);
if (rc) {
- dev_err(&led->spmi_dev->dev,
- "Secure reg write failed\n");
+ dev_err(&led->pdev->dev, "Secure reg write failed\n");
return -EINVAL;
}
@@ -1944,7 +1913,7 @@ static int qpnp_flash_led_init_settings(struct qpnp_flash_led *led)
FLASH_PERPH_RESET_CTRL(led->base),
FLASH_FOLLOW_OTST2_RB_MASK, val);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"failed to reset OTST2_RB bit\n");
return rc;
}
@@ -1963,7 +1932,7 @@ static int qpnp_flash_led_init_settings(struct qpnp_flash_led *led)
FLASH_THERMAL_DRATE(led->base),
FLASH_THERMAL_DERATE_MASK, val);
if (rc) {
- dev_err(&led->spmi_dev->dev, "Thermal derate reg write failed\n");
+ dev_err(&led->pdev->dev, "Thermal derate reg write failed\n");
return rc;
}
@@ -1978,7 +1947,7 @@ static int qpnp_flash_led_init_settings(struct qpnp_flash_led *led)
FLASH_CURRENT_RAMP(led->base),
FLASH_CURRENT_RAMP_MASK, val);
if (rc) {
- dev_err(&led->spmi_dev->dev, "Current ramp reg write failed\n");
+ dev_err(&led->pdev->dev, "Current ramp reg write failed\n");
return rc;
}
@@ -1993,7 +1962,7 @@ static int qpnp_flash_led_init_settings(struct qpnp_flash_led *led)
qpnp_flash_led_get_droop_debounce_time(
led->pdata->vph_pwr_droop_debounce_time);
if (temp_val == 0xFF) {
- dev_err(&led->spmi_dev->dev, "Invalid debounce time\n");
+ dev_err(&led->pdev->dev, "Invalid debounce time\n");
return temp_val;
}
@@ -2003,13 +1972,13 @@ static int qpnp_flash_led_init_settings(struct qpnp_flash_led *led)
FLASH_VPH_PWR_DROOP(led->base),
FLASH_VPH_PWR_DROOP_MASK, val);
if (rc) {
- dev_err(&led->spmi_dev->dev, "VPH PWR droop reg write failed\n");
+ dev_err(&led->pdev->dev, "VPH PWR droop reg write failed\n");
return rc;
}
led->battery_psy = power_supply_get_by_name("battery");
if (!led->battery_psy) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Failed to get battery power supply\n");
return -EINVAL;
}
@@ -2035,13 +2004,11 @@ static int qpnp_flash_led_parse_each_led_dt(struct qpnp_flash_led *led,
else if (strcmp(temp_string, "switch") == 0)
flash_node->type = SWITCH;
else {
- dev_err(&led->spmi_dev->dev,
- "Wrong flash LED type\n");
+ dev_err(&led->pdev->dev, "Wrong flash LED type\n");
return -EINVAL;
}
} else if (rc < 0) {
- dev_err(&led->spmi_dev->dev,
- "Unable to read flash type\n");
+ dev_err(&led->pdev->dev, "Unable to read flash type\n");
return rc;
}
@@ -2051,8 +2018,7 @@ static int qpnp_flash_led_parse_each_led_dt(struct qpnp_flash_led *led,
val = FLASH_LED_MIN_CURRENT_MA;
flash_node->prgm_current = val;
} else if (rc != -EINVAL) {
- dev_err(&led->spmi_dev->dev,
- "Unable to read current\n");
+ dev_err(&led->pdev->dev, "Unable to read current\n");
return rc;
}
@@ -2060,7 +2026,7 @@ static int qpnp_flash_led_parse_each_led_dt(struct qpnp_flash_led *led,
if (!rc)
flash_node->id = (u8)val;
else if (rc != -EINVAL) {
- dev_err(&led->spmi_dev->dev, "Unable to read led ID\n");
+ dev_err(&led->pdev->dev, "Unable to read led ID\n");
return rc;
}
@@ -2069,8 +2035,7 @@ static int qpnp_flash_led_parse_each_led_dt(struct qpnp_flash_led *led,
if (!rc)
flash_node->duration = (u16)val;
else if (rc != -EINVAL) {
- dev_err(&led->spmi_dev->dev,
- "Unable to read duration\n");
+ dev_err(&led->pdev->dev, "Unable to read duration\n");
return rc;
}
}
@@ -2086,7 +2051,7 @@ static int qpnp_flash_led_parse_each_led_dt(struct qpnp_flash_led *led,
flash_node->trigger = FLASH_LED1_TRIGGER;
break;
default:
- dev_err(&led->spmi_dev->dev, "Invalid peripheral type\n");
+ dev_err(&led->pdev->dev, "Invalid peripheral type\n");
}
while ((temp = of_get_next_child(node, temp))) {
@@ -2113,7 +2078,7 @@ static int qpnp_flash_led_parse_common_dt(
if (!rc)
led->pdata->headroom = (u16)val;
else if (rc != -EINVAL) {
- dev_err(&led->spmi_dev->dev, "Unable to read headroom\n");
+ dev_err(&led->pdev->dev, "Unable to read headroom\n");
return rc;
}
@@ -2122,8 +2087,7 @@ static int qpnp_flash_led_parse_common_dt(
if (!rc)
led->pdata->startup_dly = (u8)val;
else if (rc != -EINVAL) {
- dev_err(&led->spmi_dev->dev,
- "Unable to read startup delay\n");
+ dev_err(&led->pdev->dev, "Unable to read startup delay\n");
return rc;
}
@@ -2134,8 +2098,7 @@ static int qpnp_flash_led_parse_common_dt(
val = FLASH_LED_MIN_CURRENT_MA;
led->pdata->clamp_current = (u16)val;
} else if (rc != -EINVAL) {
- dev_err(&led->spmi_dev->dev,
- "Unable to read clamp current\n");
+ dev_err(&led->pdev->dev, "Unable to read clamp current\n");
return rc;
}
@@ -2159,14 +2122,14 @@ static int qpnp_flash_led_parse_common_dt(
temp_val =
qpnp_flash_led_get_thermal_derate_rate(temp);
if (temp_val < 0) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Invalid thermal derate rate\n");
return -EINVAL;
}
led->pdata->thermal_derate_rate = (u8)temp_val;
} else {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Unable to read thermal derate rate\n");
return -EINVAL;
}
@@ -2178,7 +2141,7 @@ static int qpnp_flash_led_parse_common_dt(
if (!rc)
led->pdata->thermal_derate_threshold = (u8)val;
else if (rc != -EINVAL) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Unable to read thermal derate threshold\n");
return rc;
}
@@ -2193,13 +2156,13 @@ static int qpnp_flash_led_parse_common_dt(
if (!rc) {
temp_val = qpnp_flash_led_get_ramp_step(temp);
if (temp_val < 0) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Invalid ramp up step values\n");
return -EINVAL;
}
led->pdata->ramp_up_step = (u8)temp_val;
} else if (rc != -EINVAL) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Unable to read ramp up steps\n");
return rc;
}
@@ -2209,13 +2172,13 @@ static int qpnp_flash_led_parse_common_dt(
if (!rc) {
temp_val = qpnp_flash_led_get_ramp_step(temp);
if (temp_val < 0) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Invalid ramp down step values\n");
return rc;
}
led->pdata->ramp_dn_step = (u8)temp_val;
} else if (rc != -EINVAL) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Unable to read ramp down steps\n");
return rc;
}
@@ -2231,7 +2194,7 @@ static int qpnp_flash_led_parse_common_dt(
if (!rc) {
led->pdata->vph_pwr_droop_threshold = (u16)val;
} else if (rc != -EINVAL) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Unable to read VPH PWR droop threshold\n");
return rc;
}
@@ -2243,7 +2206,7 @@ static int qpnp_flash_led_parse_common_dt(
if (!rc)
led->pdata->vph_pwr_droop_debounce_time = (u8)val;
else if (rc != -EINVAL) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Unable to read VPH PWR droop debounce time\n");
return rc;
}
@@ -2268,8 +2231,7 @@ static int qpnp_flash_led_parse_common_dt(
"qcom,die-current-derate-enabled");
if (led->pdata->die_current_derate_en) {
- led->vadc_dev = qpnp_get_vadc(&led->spmi_dev->dev,
- "die-temp");
+ led->vadc_dev = qpnp_get_vadc(&led->pdev->dev, "die-temp");
if (IS_ERR(led->vadc_dev)) {
pr_err("VADC channel property Missing\n");
return -EINVAL;
@@ -2277,16 +2239,15 @@ static int qpnp_flash_led_parse_common_dt(
if (of_find_property(node, "qcom,die-temp-threshold",
&led->pdata->temp_threshold_num)) {
-
if (led->pdata->temp_threshold_num > 0) {
led->pdata->die_temp_threshold_degc =
- devm_kzalloc(&led->spmi_dev->dev,
+ devm_kzalloc(&led->pdev->dev,
led->pdata->temp_threshold_num,
GFP_KERNEL);
if (led->pdata->die_temp_threshold_degc
== NULL) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"failed to allocate die temp array\n");
return -ENOMEM;
}
@@ -2298,7 +2259,7 @@ static int qpnp_flash_led_parse_common_dt(
led->pdata->die_temp_threshold_degc,
led->pdata->temp_threshold_num);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"couldn't read temp threshold rc=%d\n",
rc);
return rc;
@@ -2310,12 +2271,12 @@ static int qpnp_flash_led_parse_common_dt(
&led->pdata->temp_derate_curr_num)) {
if (led->pdata->temp_derate_curr_num > 0) {
led->pdata->die_temp_derate_curr_ma =
- devm_kzalloc(&led->spmi_dev->dev,
+ devm_kzalloc(&led->pdev->dev,
led->pdata->temp_derate_curr_num,
GFP_KERNEL);
if (led->pdata->die_temp_derate_curr_ma
== NULL) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"failed to allocate die derate current array\n");
return -ENOMEM;
}
@@ -2327,7 +2288,7 @@ static int qpnp_flash_led_parse_common_dt(
led->pdata->die_temp_derate_curr_ma,
led->pdata->temp_derate_curr_num);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"couldn't read temp limits rc =%d\n",
rc);
return rc;
@@ -2341,17 +2302,16 @@ static int qpnp_flash_led_parse_common_dt(
}
}
- led->pinctrl = devm_pinctrl_get(&led->spmi_dev->dev);
+ led->pinctrl = devm_pinctrl_get(&led->pdev->dev);
if (IS_ERR_OR_NULL(led->pinctrl)) {
- dev_err(&led->spmi_dev->dev,
- "Unable to acquire pinctrl\n");
+ dev_err(&led->pdev->dev, "Unable to acquire pinctrl\n");
led->pinctrl = NULL;
return 0;
} else {
led->gpio_state_active =
pinctrl_lookup_state(led->pinctrl, "flash_led_enable");
if (IS_ERR_OR_NULL(led->gpio_state_active)) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Can not lookup LED active state\n");
devm_pinctrl_put(led->pinctrl);
led->pinctrl = NULL;
@@ -2361,7 +2321,7 @@ static int qpnp_flash_led_parse_common_dt(
pinctrl_lookup_state(led->pinctrl,
"flash_led_disable");
if (IS_ERR_OR_NULL(led->gpio_state_suspend)) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Can not lookup LED disable state\n");
devm_pinctrl_put(led->pinctrl);
led->pinctrl = NULL;
@@ -2372,65 +2332,71 @@ static int qpnp_flash_led_parse_common_dt(
return 0;
}
-static int qpnp_flash_led_probe(struct spmi_device *spmi)
+static int qpnp_flash_led_probe(struct platform_device *pdev)
{
struct qpnp_flash_led *led;
- struct resource *flash_resource;
+ unsigned int base;
struct device_node *node, *temp;
struct dentry *root, *file;
int rc, i = 0, j, num_leds = 0;
u32 val;
- node = spmi->dev.of_node;
+ node = pdev->dev.of_node;
if (node == NULL) {
- dev_info(&spmi->dev, "No flash device defined\n");
+ dev_info(&pdev->dev, "No flash device defined\n");
return -ENODEV;
}
- flash_resource = spmi_get_resource(spmi, 0, IORESOURCE_MEM, 0);
- if (!flash_resource) {
- dev_err(&spmi->dev, "Unable to get flash LED base address\n");
- return -EINVAL;
+ rc = of_property_read_u32(pdev->dev.of_node, "reg", &base);
+ if (rc < 0) {
+ dev_err(&pdev->dev,
+ "Couldn't find reg in node = %s rc = %d\n",
+ pdev->dev.of_node->full_name, rc);
+ return rc;
}
- led = devm_kzalloc(&spmi->dev, sizeof(struct qpnp_flash_led),
+ led = devm_kzalloc(&pdev->dev, sizeof(struct qpnp_flash_led),
GFP_KERNEL);
if (!led) {
- dev_err(&spmi->dev,
+ dev_err(&pdev->dev,
"Unable to allocate memory for flash LED\n");
return -ENOMEM;
}
+ led->regmap = dev_get_regmap(pdev->dev.parent, NULL);
+ if (!led->regmap) {
+ dev_err(&pdev->dev, "Couldn't get parent's regmap\n");
+ return -EINVAL;
+ }
- led->base = flash_resource->start;
- led->spmi_dev = spmi;
+ led->base = base;
+ led->pdev = pdev;
led->current_addr = FLASH_LED0_CURRENT(led->base);
led->current2_addr = FLASH_LED1_CURRENT(led->base);
- led->pdata = devm_kzalloc(&spmi->dev,
+ led->pdata = devm_kzalloc(&pdev->dev,
sizeof(struct flash_led_platform_data), GFP_KERNEL);
if (!led->pdata) {
- dev_err(&spmi->dev,
+ dev_err(&pdev->dev,
"Unable to allocate memory for platform data\n");
return -ENOMEM;
}
- led->peripheral_type =
- (u8)qpnp_flash_led_get_peripheral_type(led);
+ led->peripheral_type = (u8)qpnp_flash_led_get_peripheral_type(led);
if (led->peripheral_type < 0) {
- dev_err(&spmi->dev, "Failed to get peripheral type\n");
+ dev_err(&pdev->dev, "Failed to get peripheral type\n");
return rc;
}
rc = qpnp_flash_led_parse_common_dt(led, node);
if (rc) {
- dev_err(&spmi->dev,
+ dev_err(&pdev->dev,
"Failed to get common config for flash LEDs\n");
return rc;
}
rc = qpnp_flash_led_init_settings(led);
if (rc) {
- dev_err(&spmi->dev, "Failed to initialize flash LED\n");
+ dev_err(&pdev->dev, "Failed to initialize flash LED\n");
return rc;
}
@@ -2445,11 +2411,11 @@ static int qpnp_flash_led_probe(struct spmi_device *spmi)
if (!num_leds)
return -ECHILD;
- led->flash_node = devm_kzalloc(&spmi->dev,
+ led->flash_node = devm_kzalloc(&pdev->dev,
(sizeof(struct flash_node_data) * num_leds),
GFP_KERNEL);
if (!led->flash_node) {
- dev_err(&spmi->dev, "Unable to allocate memory\n");
+ dev_err(&pdev->dev, "Unable to allocate memory\n");
return -ENOMEM;
}
@@ -2457,8 +2423,7 @@ static int qpnp_flash_led_probe(struct spmi_device *spmi)
led->ordered_workq = alloc_ordered_workqueue("flash_led_workqueue", 0);
if (!led->ordered_workq) {
- dev_err(&spmi->dev,
- "Failed to allocate ordered workqueue\n");
+ dev_err(&pdev->dev, "Failed to allocate ordered workqueue\n");
return -ENOMEM;
}
@@ -2467,13 +2432,13 @@ static int qpnp_flash_led_probe(struct spmi_device *spmi)
qpnp_flash_led_brightness_set;
led->flash_node[i].cdev.brightness_get =
qpnp_flash_led_brightness_get;
- led->flash_node[i].spmi_dev = spmi;
+ led->flash_node[i].pdev = pdev;
INIT_WORK(&led->flash_node[i].work, qpnp_flash_led_work);
rc = of_property_read_string(temp, "qcom,led-name",
&led->flash_node[i].cdev.name);
if (rc < 0) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Unable to read flash name\n");
return rc;
}
@@ -2481,7 +2446,7 @@ static int qpnp_flash_led_probe(struct spmi_device *spmi)
rc = of_property_read_string(temp, "qcom,default-led-trigger",
&led->flash_node[i].cdev.default_trigger);
if (rc < 0) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Unable to read trigger name\n");
return rc;
}
@@ -2493,14 +2458,14 @@ static int qpnp_flash_led_probe(struct spmi_device *spmi)
led->flash_node[i].max_current = (u16)val;
led->flash_node[i].cdev.max_brightness = val;
} else {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Unable to read max current\n");
return rc;
}
- rc = led_classdev_register(&spmi->dev,
+ rc = led_classdev_register(&pdev->dev,
&led->flash_node[i].cdev);
if (rc) {
- dev_err(&spmi->dev, "Unable to register led\n");
+ dev_err(&pdev->dev, "Unable to register led\n");
goto error_led_register;
}
@@ -2508,7 +2473,7 @@ static int qpnp_flash_led_probe(struct spmi_device *spmi)
rc = qpnp_flash_led_parse_each_led_dt(led, &led->flash_node[i]);
if (rc) {
- dev_err(&spmi->dev,
+ dev_err(&pdev->dev,
"Failed to parse config for each LED\n");
goto error_led_register;
}
@@ -2516,7 +2481,7 @@ static int qpnp_flash_led_probe(struct spmi_device *spmi)
if (led->flash_node[i].num_regulators) {
rc = flash_regulator_parse_dt(led, &led->flash_node[i]);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&pdev->dev,
"Unable to parse regulator data\n");
goto error_led_register;
}
@@ -2524,11 +2489,10 @@ static int qpnp_flash_led_probe(struct spmi_device *spmi)
rc = flash_regulator_setup(led, &led->flash_node[i],
true);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&pdev->dev,
"Unable to set up regulator\n");
goto error_led_register;
}
-
}
for (j = 0; j < ARRAY_SIZE(qpnp_flash_led_attrs); j++) {
@@ -2575,7 +2539,7 @@ static int qpnp_flash_led_probe(struct spmi_device *spmi)
goto error_led_debugfs;
}
- dev_set_drvdata(&spmi->dev, led);
+ dev_set_drvdata(&pdev->dev, led);
return 0;
@@ -2597,9 +2561,9 @@ error_led_register:
return rc;
}
-static int qpnp_flash_led_remove(struct spmi_device *spmi)
+static int qpnp_flash_led_remove(struct platform_device *pdev)
{
- struct qpnp_flash_led *led = dev_get_drvdata(&spmi->dev);
+ struct qpnp_flash_led *led = dev_get_drvdata(&pdev->dev);
int i, j;
for (i = led->num_leds - 1; i >= 0; i--) {
@@ -2627,10 +2591,10 @@ static struct of_device_id spmi_match_table[] = {
{ },
};
-static struct spmi_driver qpnp_flash_led_driver = {
+static struct platform_driver qpnp_flash_led_driver = {
.driver = {
- .name = "qcom,qpnp-flash-led",
- .of_match_table = spmi_match_table,
+ .name = "qcom,qpnp-flash-led",
+ .of_match_table = spmi_match_table,
},
.probe = qpnp_flash_led_probe,
.remove = qpnp_flash_led_remove,
@@ -2638,13 +2602,13 @@ static struct spmi_driver qpnp_flash_led_driver = {
static int __init qpnp_flash_led_init(void)
{
- return spmi_driver_register(&qpnp_flash_led_driver);
+ return platform_driver_register(&qpnp_flash_led_driver);
}
late_initcall(qpnp_flash_led_init);
static void __exit qpnp_flash_led_exit(void)
{
- spmi_driver_unregister(&qpnp_flash_led_driver);
+ platform_driver_unregister(&qpnp_flash_led_driver);
}
module_exit(qpnp_flash_led_exit);
diff --git a/drivers/leds/leds-qpnp-wled.c b/drivers/leds/leds-qpnp-wled.c
index 7d4e394d6be1..a7a25f54f992 100644
--- a/drivers/leds/leds-qpnp-wled.c
+++ b/drivers/leds/leds-qpnp-wled.c
@@ -13,11 +13,14 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
+#include <linux/regmap.h>
#include <linux/errno.h>
#include <linux/leds.h>
#include <linux/slab.h>
#include <linux/of_device.h>
+#include <linux/of_address.h>
#include <linux/spmi.h>
+#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <linux/err.h>
#include <linux/delay.h>
@@ -269,54 +272,55 @@ static u8 qpnp_wled_sink_dbg_regs[] = {
*/
struct qpnp_wled {
struct led_classdev cdev;
- struct spmi_device *spmi;
- struct work_struct work;
- struct mutex lock;
- enum qpnp_wled_fdbk_op fdbk_op;
- enum qpnp_wled_dim_mode dim_mode;
- int ovp_irq;
- int sc_irq;
- u32 sc_cnt;
- u32 avdd_trim_steps_from_center;
- u16 ctrl_base;
- u16 sink_base;
- u16 mod_freq_khz;
- u16 hyb_thres;
- u16 sync_dly_us;
- u16 vref_mv;
- u16 vref_psm_mv;
- u16 loop_comp_res_kohm;
- u16 loop_ea_gm;
- u16 sc_deb_cycles;
- u16 switch_freq_khz;
- u16 ovp_mv;
- u16 ilim_ma;
- u16 boost_duty_ns;
- u16 fs_curr_ua;
- u16 ramp_ms;
- u16 ramp_step;
- u16 cons_sync_write_delay_us;
- u8 strings[QPNP_WLED_MAX_STRINGS];
- u8 num_strings;
- bool en_9b_dim_res;
- bool en_phase_stag;
- bool en_cabc;
- bool disp_type_amoled;
- bool en_ext_pfet_sc_pro;
- bool prev_state;
+ struct platform_device *pdev;
+ struct regmap *regmap;
+ struct work_struct work;
+ struct mutex lock;
+ enum qpnp_wled_fdbk_op fdbk_op;
+ enum qpnp_wled_dim_mode dim_mode;
+ int ovp_irq;
+ int sc_irq;
+ u32 sc_cnt;
+ u32 avdd_trim_steps_from_center;
+ u16 ctrl_base;
+ u16 sink_base;
+ u16 mod_freq_khz;
+ u16 hyb_thres;
+ u16 sync_dly_us;
+ u16 vref_mv;
+ u16 vref_psm_mv;
+ u16 loop_comp_res_kohm;
+ u16 loop_ea_gm;
+ u16 sc_deb_cycles;
+ u16 switch_freq_khz;
+ u16 ovp_mv;
+ u16 ilim_ma;
+ u16 boost_duty_ns;
+ u16 fs_curr_ua;
+ u16 ramp_ms;
+ u16 ramp_step;
+ u16 cons_sync_write_delay_us;
+ u8 strings[QPNP_WLED_MAX_STRINGS];
+ u8 num_strings;
+ bool en_9b_dim_res;
+ bool en_phase_stag;
+ bool en_cabc;
+ bool disp_type_amoled;
+ bool en_ext_pfet_sc_pro;
+ bool prev_state;
};
/* helper to read a pmic register */
static int qpnp_wled_read_reg(struct qpnp_wled *wled, u8 *data, u16 addr)
{
int rc;
+ uint val;
- rc = spmi_ext_register_readl(wled->spmi->ctrl, wled->spmi->sid,
- addr, data, 1);
+ rc = regmap_read(wled->regmap, addr, &val);
if (rc < 0)
- dev_err(&wled->spmi->dev,
+ dev_err(&wled->pdev->dev,
"Error reading address: %x(%d)\n", addr, rc);
-
+ *data = (u8)val;
return rc;
}
@@ -325,13 +329,12 @@ static int qpnp_wled_write_reg(struct qpnp_wled *wled, u8 *data, u16 addr)
{
int rc;
- rc = spmi_ext_register_writel(wled->spmi->ctrl, wled->spmi->sid,
- addr, data, 1);
+ rc = regmap_write(wled->regmap, addr, *data);
if (rc < 0)
- dev_err(&wled->spmi->dev,
+ dev_err(&wled->pdev->dev,
"Error writing address: %x(%d)\n", addr, rc);
- dev_dbg(&wled->spmi->dev, "write: WLED_0x%x = 0x%x\n", addr, *data);
+ dev_dbg(&wled->pdev->dev, "write: WLED_0x%x = 0x%x\n", addr, *data);
return rc;
}
@@ -400,7 +403,7 @@ static int qpnp_wled_set_level(struct qpnp_wled *wled, int level)
rc = qpnp_wled_sync_reg_toggle(wled);
if (rc < 0) {
- dev_err(&wled->spmi->dev, "Failed to toggle sync reg %d\n", rc);
+ dev_err(&wled->pdev->dev, "Failed to toggle sync reg %d\n", rc);
return rc;
}
@@ -458,7 +461,7 @@ static ssize_t qpnp_wled_ramp_store(struct device *dev,
if (!wled->cdev.brightness) {
rc = qpnp_wled_module_en(wled, wled->ctrl_base, true);
if (rc) {
- dev_err(&wled->spmi->dev, "wled enable failed\n");
+ dev_err(&wled->pdev->dev, "wled enable failed\n");
goto unlock_mutex;
}
}
@@ -467,7 +470,7 @@ static ssize_t qpnp_wled_ramp_store(struct device *dev,
for (i = 0; i <= wled->cdev.max_brightness;) {
rc = qpnp_wled_set_level(wled, i);
if (rc) {
- dev_err(&wled->spmi->dev, "wled set level failed\n");
+ dev_err(&wled->pdev->dev, "wled set level failed\n");
goto restore_brightness;
}
@@ -489,7 +492,7 @@ static ssize_t qpnp_wled_ramp_store(struct device *dev,
for (i = wled->cdev.max_brightness; i >= 0;) {
rc = qpnp_wled_set_level(wled, i);
if (rc) {
- dev_err(&wled->spmi->dev, "wled set level failed\n");
+ dev_err(&wled->pdev->dev, "wled set level failed\n");
goto restore_brightness;
}
@@ -507,7 +510,7 @@ static ssize_t qpnp_wled_ramp_store(struct device *dev,
i = 0;
}
- dev_info(&wled->spmi->dev, "wled ramp complete\n");
+ dev_info(&wled->pdev->dev, "wled ramp complete\n");
restore_brightness:
/* restore the old brightness */
@@ -515,7 +518,7 @@ restore_brightness:
if (!wled->cdev.brightness) {
rc = qpnp_wled_module_en(wled, wled->ctrl_base, false);
if (rc)
- dev_err(&wled->spmi->dev, "wled enable failed\n");
+ dev_err(&wled->pdev->dev, "wled enable failed\n");
}
unlock_mutex:
mutex_unlock(&wled->lock);
@@ -728,7 +731,7 @@ static ssize_t qpnp_wled_fs_curr_ua_store(struct device *dev,
rc = qpnp_wled_sync_reg_toggle(wled);
if (rc < 0) {
- dev_err(&wled->spmi->dev, "Failed to toggle sync reg %d\n", rc);
+ dev_err(&wled->pdev->dev, "Failed to toggle sync reg %d\n", rc);
return rc;
}
@@ -772,7 +775,7 @@ static void qpnp_wled_work(struct work_struct *work)
if (level) {
rc = qpnp_wled_set_level(wled, level);
if (rc) {
- dev_err(&wled->spmi->dev, "wled set level failed\n");
+ dev_err(&wled->pdev->dev, "wled set level failed\n");
goto unlock_mutex;
}
}
@@ -781,7 +784,7 @@ static void qpnp_wled_work(struct work_struct *work)
rc = qpnp_wled_module_en(wled, wled->ctrl_base, !!level);
if (rc) {
- dev_err(&wled->spmi->dev, "wled %sable failed\n",
+ dev_err(&wled->pdev->dev, "wled %sable failed\n",
level ? "en" : "dis");
goto unlock_mutex;
}
@@ -950,7 +953,7 @@ static irqreturn_t qpnp_wled_ovp_irq(int irq, void *_wled)
{
struct qpnp_wled *wled = _wled;
- dev_dbg(&wled->spmi->dev, "ovp detected\n");
+ dev_dbg(&wled->pdev->dev, "ovp detected\n");
return IRQ_HANDLED;
}
@@ -960,7 +963,7 @@ static irqreturn_t qpnp_wled_sc_irq(int irq, void *_wled)
{
struct qpnp_wled *wled = _wled;
- dev_err(&wled->spmi->dev,
+ dev_err(&wled->pdev->dev,
"Short circuit detected %d times\n", ++wled->sc_cnt);
qpnp_wled_module_en(wled, wled->ctrl_base, false);
@@ -1205,7 +1208,7 @@ static int qpnp_wled_config(struct qpnp_wled *wled)
for (i = 0; i < wled->num_strings; i++) {
if (wled->strings[i] >= QPNP_WLED_MAX_STRINGS) {
- dev_err(&wled->spmi->dev, "Invalid string number\n");
+ dev_err(&wled->pdev->dev, "Invalid string number\n");
return -EINVAL;
}
@@ -1294,18 +1297,19 @@ static int qpnp_wled_config(struct qpnp_wled *wled)
rc = qpnp_wled_sync_reg_toggle(wled);
if (rc < 0) {
- dev_err(&wled->spmi->dev, "Failed to toggle sync reg %d\n", rc);
+ dev_err(&wled->pdev->dev, "Failed to toggle sync reg %d\n", rc);
return rc;
}
/* setup ovp and sc irqs */
if (wled->ovp_irq >= 0) {
- rc = devm_request_threaded_irq(&wled->spmi->dev, wled->ovp_irq,
+ rc = devm_request_threaded_irq(&wled->pdev->dev,
+ wled->ovp_irq,
NULL, qpnp_wled_ovp_irq,
QPNP_IRQ_FLAGS,
"qpnp_wled_ovp_irq", wled);
if (rc < 0) {
- dev_err(&wled->spmi->dev,
+ dev_err(&wled->pdev->dev,
"Unable to request ovp(%d) IRQ(err:%d)\n",
wled->ovp_irq, rc);
return rc;
@@ -1314,12 +1318,12 @@ static int qpnp_wled_config(struct qpnp_wled *wled)
if (wled->sc_irq >= 0) {
wled->sc_cnt = 0;
- rc = devm_request_threaded_irq(&wled->spmi->dev, wled->sc_irq,
+ rc = devm_request_threaded_irq(&wled->pdev->dev, wled->sc_irq,
NULL, qpnp_wled_sc_irq,
QPNP_IRQ_FLAGS,
"qpnp_wled_sc_irq", wled);
if (rc < 0) {
- dev_err(&wled->spmi->dev,
+ dev_err(&wled->pdev->dev,
"Unable to request sc(%d) IRQ(err:%d)\n",
wled->sc_irq, rc);
return rc;
@@ -1369,7 +1373,7 @@ static int qpnp_wled_config(struct qpnp_wled *wled)
/* parse wled dtsi parameters */
static int qpnp_wled_parse_dt(struct qpnp_wled *wled)
{
- struct spmi_device *spmi = wled->spmi;
+ struct platform_device *pdev = wled->pdev;
struct property *prop;
const char *temp_str;
u32 temp_val;
@@ -1377,78 +1381,78 @@ static int qpnp_wled_parse_dt(struct qpnp_wled *wled)
u8 *strings;
wled->cdev.name = "wled";
- rc = of_property_read_string(spmi->dev.of_node,
+ rc = of_property_read_string(pdev->dev.of_node,
"linux,name", &wled->cdev.name);
if (rc && (rc != -EINVAL)) {
- dev_err(&spmi->dev, "Unable to read led name\n");
+ dev_err(&pdev->dev, "Unable to read led name\n");
return rc;
}
wled->cdev.default_trigger = QPNP_WLED_TRIGGER_NONE;
- rc = of_property_read_string(spmi->dev.of_node, "linux,default-trigger",
+ rc = of_property_read_string(pdev->dev.of_node, "linux,default-trigger",
&wled->cdev.default_trigger);
if (rc && (rc != -EINVAL)) {
- dev_err(&spmi->dev, "Unable to read led trigger\n");
+ dev_err(&pdev->dev, "Unable to read led trigger\n");
return rc;
}
- wled->disp_type_amoled = of_property_read_bool(spmi->dev.of_node,
+ wled->disp_type_amoled = of_property_read_bool(pdev->dev.of_node,
"qcom,disp-type-amoled");
if (wled->disp_type_amoled) {
wled->vref_psm_mv = QPNP_WLED_VREF_PSM_DFLT_AMOLED_MV;
- rc = of_property_read_u32(spmi->dev.of_node,
+ rc = of_property_read_u32(pdev->dev.of_node,
"qcom,vref-psm-mv", &temp_val);
if (!rc) {
wled->vref_psm_mv = temp_val;
} else if (rc != -EINVAL) {
- dev_err(&spmi->dev, "Unable to read vref-psm\n");
+ dev_err(&pdev->dev, "Unable to read vref-psm\n");
return rc;
}
wled->loop_comp_res_kohm =
QPNP_WLED_LOOP_COMP_RES_DFLT_AMOLED_KOHM;
- rc = of_property_read_u32(spmi->dev.of_node,
+ rc = of_property_read_u32(pdev->dev.of_node,
"qcom,loop-comp-res-kohm", &temp_val);
if (!rc) {
wled->loop_comp_res_kohm = temp_val;
} else if (rc != -EINVAL) {
- dev_err(&spmi->dev, "Unable to read loop-comp-res-kohm\n");
+ dev_err(&pdev->dev, "Unable to read loop-comp-res-kohm\n");
return rc;
}
wled->loop_ea_gm = QPNP_WLED_LOOP_EA_GM_DFLT_AMOLED;
- rc = of_property_read_u32(spmi->dev.of_node,
+ rc = of_property_read_u32(pdev->dev.of_node,
"qcom,loop-ea-gm", &temp_val);
if (!rc) {
wled->loop_ea_gm = temp_val;
} else if (rc != -EINVAL) {
- dev_err(&spmi->dev, "Unable to read loop-ea-gm\n");
+ dev_err(&pdev->dev, "Unable to read loop-ea-gm\n");
return rc;
}
wled->sc_deb_cycles = QPNP_WLED_SC_DEB_CYCLES_DFLT_AMOLED;
- rc = of_property_read_u32(spmi->dev.of_node,
+ rc = of_property_read_u32(pdev->dev.of_node,
"qcom,sc-deb-cycles", &temp_val);
if (!rc) {
wled->sc_deb_cycles = temp_val;
} else if (rc != -EINVAL) {
- dev_err(&spmi->dev, "Unable to read sc debounce cycles\n");
+ dev_err(&pdev->dev, "Unable to read sc debounce cycles\n");
return rc;
}
wled->avdd_trim_steps_from_center = 0;
- rc = of_property_read_u32(spmi->dev.of_node,
+ rc = of_property_read_u32(pdev->dev.of_node,
"qcom,avdd-trim-steps-from-center", &temp_val);
if (!rc) {
wled->avdd_trim_steps_from_center = temp_val;
} else if (rc != -EINVAL) {
- dev_err(&spmi->dev, "Unable to read avdd trim steps from center value\n");
+ dev_err(&pdev->dev, "Unable to read avdd trim steps from center value\n");
return rc;
}
}
wled->fdbk_op = QPNP_WLED_FDBK_AUTO;
- rc = of_property_read_string(spmi->dev.of_node,
+ rc = of_property_read_string(pdev->dev.of_node,
"qcom,fdbk-output", &temp_str);
if (!rc) {
if (strcmp(temp_str, "wled1") == 0)
@@ -1462,72 +1466,72 @@ static int qpnp_wled_parse_dt(struct qpnp_wled *wled)
else
wled->fdbk_op = QPNP_WLED_FDBK_AUTO;
} else if (rc != -EINVAL) {
- dev_err(&spmi->dev, "Unable to read feedback output\n");
+ dev_err(&pdev->dev, "Unable to read feedback output\n");
return rc;
}
wled->vref_mv = QPNP_WLED_DFLT_VREF_MV;
- rc = of_property_read_u32(spmi->dev.of_node,
+ rc = of_property_read_u32(pdev->dev.of_node,
"qcom,vref-mv", &temp_val);
if (!rc) {
wled->vref_mv = temp_val;
} else if (rc != -EINVAL) {
- dev_err(&spmi->dev, "Unable to read vref\n");
+ dev_err(&pdev->dev, "Unable to read vref\n");
return rc;
}
wled->switch_freq_khz = QPNP_WLED_SWITCH_FREQ_800_KHZ;
- rc = of_property_read_u32(spmi->dev.of_node,
+ rc = of_property_read_u32(pdev->dev.of_node,
"qcom,switch-freq-khz", &temp_val);
if (!rc) {
wled->switch_freq_khz = temp_val;
} else if (rc != -EINVAL) {
- dev_err(&spmi->dev, "Unable to read switch freq\n");
+ dev_err(&pdev->dev, "Unable to read switch freq\n");
return rc;
}
wled->ovp_mv = QPNP_WLED_OVP_29500_MV;
- rc = of_property_read_u32(spmi->dev.of_node,
+ rc = of_property_read_u32(pdev->dev.of_node,
"qcom,ovp-mv", &temp_val);
if (!rc) {
wled->ovp_mv = temp_val;
} else if (rc != -EINVAL) {
- dev_err(&spmi->dev, "Unable to read vref\n");
+ dev_err(&pdev->dev, "Unable to read vref\n");
return rc;
}
wled->ilim_ma = QPNP_WLED_DFLT_ILIM_MA;
- rc = of_property_read_u32(spmi->dev.of_node,
+ rc = of_property_read_u32(pdev->dev.of_node,
"qcom,ilim-ma", &temp_val);
if (!rc) {
wled->ilim_ma = temp_val;
} else if (rc != -EINVAL) {
- dev_err(&spmi->dev, "Unable to read ilim\n");
+ dev_err(&pdev->dev, "Unable to read ilim\n");
return rc;
}
wled->boost_duty_ns = QPNP_WLED_DEF_BOOST_DUTY_NS;
- rc = of_property_read_u32(spmi->dev.of_node,
+ rc = of_property_read_u32(pdev->dev.of_node,
"qcom,boost-duty-ns", &temp_val);
if (!rc) {
wled->boost_duty_ns = temp_val;
} else if (rc != -EINVAL) {
- dev_err(&spmi->dev, "Unable to read boost duty\n");
+ dev_err(&pdev->dev, "Unable to read boost duty\n");
return rc;
}
wled->mod_freq_khz = QPNP_WLED_MOD_FREQ_9600_KHZ;
- rc = of_property_read_u32(spmi->dev.of_node,
+ rc = of_property_read_u32(pdev->dev.of_node,
"qcom,mod-freq-khz", &temp_val);
if (!rc) {
wled->mod_freq_khz = temp_val;
} else if (rc != -EINVAL) {
- dev_err(&spmi->dev, "Unable to read modulation freq\n");
+ dev_err(&pdev->dev, "Unable to read modulation freq\n");
return rc;
}
wled->dim_mode = QPNP_WLED_DIM_HYBRID;
- rc = of_property_read_string(spmi->dev.of_node,
+ rc = of_property_read_string(pdev->dev.of_node,
"qcom,dim-mode", &temp_str);
if (!rc) {
if (strcmp(temp_str, "analog") == 0)
@@ -1537,59 +1541,59 @@ static int qpnp_wled_parse_dt(struct qpnp_wled *wled)
else
wled->dim_mode = QPNP_WLED_DIM_HYBRID;
} else if (rc != -EINVAL) {
- dev_err(&spmi->dev, "Unable to read dim mode\n");
+ dev_err(&pdev->dev, "Unable to read dim mode\n");
return rc;
}
if (wled->dim_mode == QPNP_WLED_DIM_HYBRID) {
wled->hyb_thres = QPNP_WLED_DEF_HYB_THRES;
- rc = of_property_read_u32(spmi->dev.of_node,
+ rc = of_property_read_u32(pdev->dev.of_node,
"qcom,hyb-thres", &temp_val);
if (!rc) {
wled->hyb_thres = temp_val;
} else if (rc != -EINVAL) {
- dev_err(&spmi->dev, "Unable to read hyb threshold\n");
+ dev_err(&pdev->dev, "Unable to read hyb threshold\n");
return rc;
}
}
wled->sync_dly_us = QPNP_WLED_DEF_SYNC_DLY_US;
- rc = of_property_read_u32(spmi->dev.of_node,
+ rc = of_property_read_u32(pdev->dev.of_node,
"qcom,sync-dly-us", &temp_val);
if (!rc) {
wled->sync_dly_us = temp_val;
} else if (rc != -EINVAL) {
- dev_err(&spmi->dev, "Unable to read sync delay\n");
+ dev_err(&pdev->dev, "Unable to read sync delay\n");
return rc;
}
wled->fs_curr_ua = QPNP_WLED_FS_CURR_MAX_UA;
- rc = of_property_read_u32(spmi->dev.of_node,
+ rc = of_property_read_u32(pdev->dev.of_node,
"qcom,fs-curr-ua", &temp_val);
if (!rc) {
wled->fs_curr_ua = temp_val;
} else if (rc != -EINVAL) {
- dev_err(&spmi->dev, "Unable to read full scale current\n");
+ dev_err(&pdev->dev, "Unable to read full scale current\n");
return rc;
}
wled->cons_sync_write_delay_us = 0;
- rc = of_property_read_u32(spmi->dev.of_node,
+ rc = of_property_read_u32(pdev->dev.of_node,
"qcom,cons-sync-write-delay-us", &temp_val);
if (!rc)
wled->cons_sync_write_delay_us = temp_val;
- wled->en_9b_dim_res = of_property_read_bool(spmi->dev.of_node,
+ wled->en_9b_dim_res = of_property_read_bool(pdev->dev.of_node,
"qcom,en-9b-dim-res");
- wled->en_phase_stag = of_property_read_bool(spmi->dev.of_node,
+ wled->en_phase_stag = of_property_read_bool(pdev->dev.of_node,
"qcom,en-phase-stag");
- wled->en_cabc = of_property_read_bool(spmi->dev.of_node,
+ wled->en_cabc = of_property_read_bool(pdev->dev.of_node,
"qcom,en-cabc");
- prop = of_find_property(spmi->dev.of_node,
+ prop = of_find_property(pdev->dev.of_node,
"qcom,led-strings-list", &temp_val);
if (!prop || !temp_val || temp_val > QPNP_WLED_MAX_STRINGS) {
- dev_err(&spmi->dev, "Invalid strings info, use default");
+ dev_err(&pdev->dev, "Invalid strings info, use default");
wled->num_strings = QPNP_WLED_MAX_STRINGS;
for (i = 0; i < wled->num_strings; i++)
wled->strings[i] = i;
@@ -1600,61 +1604,64 @@ static int qpnp_wled_parse_dt(struct qpnp_wled *wled)
wled->strings[i] = strings[i];
}
- wled->ovp_irq = spmi_get_irq_byname(spmi, NULL, "ovp-irq");
+ wled->ovp_irq = platform_get_irq_byname(pdev, "ovp-irq");
if (wled->ovp_irq < 0)
- dev_dbg(&spmi->dev, "ovp irq is not used\n");
+ dev_dbg(&pdev->dev, "ovp irq is not used\n");
- wled->sc_irq = spmi_get_irq_byname(spmi, NULL, "sc-irq");
+ wled->sc_irq = platform_get_irq_byname(pdev, "sc-irq");
if (wled->sc_irq < 0)
- dev_dbg(&spmi->dev, "sc irq is not used\n");
+ dev_dbg(&pdev->dev, "sc irq is not used\n");
- wled->en_ext_pfet_sc_pro = of_property_read_bool(spmi->dev.of_node,
+ wled->en_ext_pfet_sc_pro = of_property_read_bool(pdev->dev.of_node,
"qcom,en-ext-pfet-sc-pro");
return 0;
}
-static int qpnp_wled_probe(struct spmi_device *spmi)
+static int qpnp_wled_probe(struct platform_device *pdev)
{
struct qpnp_wled *wled;
- struct resource *wled_resource;
int rc, i;
+ const __be32 *prop;
- wled = devm_kzalloc(&spmi->dev, sizeof(*wled), GFP_KERNEL);
+ wled = devm_kzalloc(&pdev->dev, sizeof(*wled), GFP_KERNEL);
if (!wled)
return -ENOMEM;
+ wled->regmap = dev_get_regmap(pdev->dev.parent, NULL);
+ if (!wled->regmap) {
+ dev_err(&pdev->dev, "Couldn't get parent's regmap\n");
+ return -EINVAL;
+ }
- wled->spmi = spmi;
+ wled->pdev = pdev;
- wled_resource = spmi_get_resource_byname(spmi, NULL, IORESOURCE_MEM,
- QPNP_WLED_SINK_BASE);
- if (!wled_resource) {
- dev_err(&spmi->dev, "Unable to get wled sink base address\n");
- return -EINVAL;
+ prop = of_get_address_by_name(pdev->dev.of_node, QPNP_WLED_SINK_BASE,
+ 0, 0);
+ if (!prop) {
+ dev_err(&pdev->dev, "Couldnt find sink's addr rc %d\n", rc);
+ return rc;
}
+ wled->sink_base = be32_to_cpu(*prop);
- wled->sink_base = wled_resource->start;
-
- wled_resource = spmi_get_resource_byname(spmi, NULL, IORESOURCE_MEM,
- QPNP_WLED_CTRL_BASE);
- if (!wled_resource) {
- dev_err(&spmi->dev, "Unable to get wled ctrl base address\n");
- return -EINVAL;
+ prop = of_get_address_by_name(pdev->dev.of_node, QPNP_WLED_CTRL_BASE,
+ 0, 0);
+ if (!prop) {
+ dev_err(&pdev->dev, "Couldnt find ctrl's addr rc = %d\n", rc);
+ return rc;
}
+ wled->ctrl_base = be32_to_cpu(*prop);
- wled->ctrl_base = wled_resource->start;
-
- dev_set_drvdata(&spmi->dev, wled);
+ dev_set_drvdata(&pdev->dev, wled);
rc = qpnp_wled_parse_dt(wled);
if (rc) {
- dev_err(&spmi->dev, "DT parsing failed\n");
+ dev_err(&pdev->dev, "DT parsing failed\n");
return rc;
}
rc = qpnp_wled_config(wled);
if (rc) {
- dev_err(&spmi->dev, "wled config failed\n");
+ dev_err(&pdev->dev, "wled config failed\n");
return rc;
}
@@ -1668,9 +1675,9 @@ static int qpnp_wled_probe(struct spmi_device *spmi)
wled->cdev.max_brightness = WLED_MAX_LEVEL_4095;
- rc = led_classdev_register(&spmi->dev, &wled->cdev);
+ rc = led_classdev_register(&pdev->dev, &wled->cdev);
if (rc) {
- dev_err(&spmi->dev, "wled registration failed(%d)\n", rc);
+ dev_err(&pdev->dev, "wled registration failed(%d)\n", rc);
goto wled_register_fail;
}
@@ -1678,7 +1685,7 @@ static int qpnp_wled_probe(struct spmi_device *spmi)
rc = sysfs_create_file(&wled->cdev.dev->kobj,
&qpnp_wled_attrs[i].attr);
if (rc < 0) {
- dev_err(&spmi->dev, "sysfs creation failed\n");
+ dev_err(&pdev->dev, "sysfs creation failed\n");
goto sysfs_fail;
}
}
@@ -1696,9 +1703,9 @@ wled_register_fail:
return rc;
}
-static int qpnp_wled_remove(struct spmi_device *spmi)
+static int qpnp_wled_remove(struct platform_device *pdev)
{
- struct qpnp_wled *wled = dev_get_drvdata(&spmi->dev);
+ struct qpnp_wled *wled = dev_get_drvdata(&pdev->dev);
int i;
for (i = 0; i < ARRAY_SIZE(qpnp_wled_attrs); i++)
@@ -1717,10 +1724,10 @@ static struct of_device_id spmi_match_table[] = {
{ },
};
-static struct spmi_driver qpnp_wled_driver = {
+static struct platform_driver qpnp_wled_driver = {
.driver = {
- .name = "qcom,qpnp-wled",
- .of_match_table = spmi_match_table,
+ .name = "qcom,qpnp-wled",
+ .of_match_table = spmi_match_table,
},
.probe = qpnp_wled_probe,
.remove = qpnp_wled_remove,
@@ -1728,13 +1735,13 @@ static struct spmi_driver qpnp_wled_driver = {
static int __init qpnp_wled_init(void)
{
- return spmi_driver_register(&qpnp_wled_driver);
+ return platform_driver_register(&qpnp_wled_driver);
}
module_init(qpnp_wled_init);
static void __exit qpnp_wled_exit(void)
{
- spmi_driver_unregister(&qpnp_wled_driver);
+ platform_driver_unregister(&qpnp_wled_driver);
}
module_exit(qpnp_wled_exit);
diff --git a/drivers/leds/leds-qpnp.c b/drivers/leds/leds-qpnp.c
index 466dfef62a2c..d16fcc3c97ae 100644
--- a/drivers/leds/leds-qpnp.c
+++ b/drivers/leds/leds-qpnp.c
@@ -1,5 +1,4 @@
-
-/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -12,6 +11,7 @@
*/
#include <linux/kernel.h>
+#include <linux/regmap.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
@@ -21,6 +21,7 @@
#include <linux/of_platform.h>
#include <linux/of_device.h>
#include <linux/spmi.h>
+#include <linux/platform_device.h>
#include <linux/qpnp/pwm.h>
#include <linux/workqueue.h>
#include <linux/delay.h>
@@ -534,26 +535,27 @@ struct gpio_config_data {
* @turn_off_delay_ms - number of msec before turning off the LED
*/
struct qpnp_led_data {
- struct led_classdev cdev;
- struct spmi_device *spmi_dev;
- struct delayed_work dwork;
- struct workqueue_struct *workqueue;
- struct work_struct work;
- int id;
- u16 base;
- u8 reg;
- u8 num_leds;
- struct mutex lock;
- struct wled_config_data *wled_cfg;
+ struct led_classdev cdev;
+ struct platform_device *pdev;
+ struct regmap *regmap;
+ struct delayed_work dwork;
+ struct workqueue_struct *workqueue;
+ struct work_struct work;
+ int id;
+ u16 base;
+ u8 reg;
+ u8 num_leds;
+ struct mutex lock;
+ struct wled_config_data *wled_cfg;
struct flash_config_data *flash_cfg;
struct kpdbl_config_data *kpdbl_cfg;
- struct rgb_config_data *rgb_cfg;
- struct mpp_config_data *mpp_cfg;
- struct gpio_config_data *gpio_cfg;
- int max_current;
- bool default_on;
- bool in_order_command_processing;
- int turn_off_delay_ms;
+ struct rgb_config_data *rgb_cfg;
+ struct mpp_config_data *mpp_cfg;
+ struct gpio_config_data *gpio_cfg;
+ int max_current;
+ bool default_on;
+ bool in_order_command_processing;
+ int turn_off_delay_ms;
};
static DEFINE_MUTEX(flash_lock);
@@ -566,23 +568,12 @@ static int
qpnp_led_masked_write(struct qpnp_led_data *led, u16 addr, u8 mask, u8 val)
{
int rc;
- u8 reg;
-
- rc = spmi_ext_register_readl(led->spmi_dev->ctrl, led->spmi_dev->sid,
- addr, &reg, 1);
- if (rc) {
- dev_err(&led->spmi_dev->dev,
- "Unable to read from addr=%x, rc(%d)\n", addr, rc);
- }
-
- reg &= ~mask;
- reg |= val;
- rc = spmi_ext_register_writel(led->spmi_dev->ctrl, led->spmi_dev->sid,
- addr, &reg, 1);
+ rc = regmap_update_bits(led->regmap, addr, mask, val);
if (rc)
- dev_err(&led->spmi_dev->dev,
- "Unable to write to addr=%x, rc(%d)\n", addr, rc);
+ dev_err(&led->pdev->dev,
+ "Unable to regmap_update_bits to addr=%x, rc(%d)\n",
+ addr, rc);
return rc;
}
@@ -593,10 +584,8 @@ static void qpnp_dump_regs(struct qpnp_led_data *led, u8 regs[], u8 array_size)
pr_debug("===== %s LED register dump start =====\n", led->cdev.name);
for (i = 0; i < array_size; i++) {
- spmi_ext_register_readl(led->spmi_dev->ctrl,
- led->spmi_dev->sid,
- led->base + regs[i],
- &val, sizeof(val));
+ regmap_bulk_read(led->regmap, led->base + regs[i], &val,
+ sizeof(val));
pr_debug("%s: 0x%x = 0x%x\n", led->cdev.name,
led->base + regs[i], val);
}
@@ -610,19 +599,17 @@ static int qpnp_wled_sync(struct qpnp_led_data *led)
/* sync */
val = WLED_SYNC_VAL;
- rc = spmi_ext_register_writel(led->spmi_dev->ctrl, led->spmi_dev->sid,
- WLED_SYNC_REG(led->base), &val, 1);
+ rc = regmap_write(led->regmap, WLED_SYNC_REG(led->base), val);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"WLED set sync reg failed(%d)\n", rc);
return rc;
}
val = WLED_SYNC_RESET_VAL;
- rc = spmi_ext_register_writel(led->spmi_dev->ctrl, led->spmi_dev->sid,
- WLED_SYNC_REG(led->base), &val, 1);
+ rc = regmap_write(led->regmap, WLED_SYNC_REG(led->base), val);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"WLED reset sync reg failed(%d)\n", rc);
return rc;
}
@@ -632,7 +619,8 @@ static int qpnp_wled_sync(struct qpnp_led_data *led)
static int qpnp_wled_set(struct qpnp_led_data *led)
{
int rc, duty, level, tries = 0;
- u8 val, i, num_wled_strings, sink_val, ilim_val, ovp_val;
+ u8 val, i, num_wled_strings;
+ uint sink_val, ilim_val, ovp_val;
num_wled_strings = led->wled_cfg->num_strings;
@@ -646,7 +634,7 @@ static int qpnp_wled_set(struct qpnp_led_data *led)
WLED_FULL_SCALE_REG(led->base, i),
WLED_MAX_CURR_MASK, WLED_NO_CURRENT);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Write max current failure (%d)\n",
rc);
return rc;
@@ -655,27 +643,25 @@ static int qpnp_wled_set(struct qpnp_led_data *led)
rc = qpnp_wled_sync(led);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"WLED sync failed(%d)\n", rc);
return rc;
}
- rc = spmi_ext_register_readl(led->spmi_dev->ctrl,
- led->spmi_dev->sid, WLED_CURR_SINK_REG(led->base),
- &sink_val, 1);
+ rc = regmap_read(led->regmap, WLED_CURR_SINK_REG(led->base),
+ &sink_val);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"WLED read sink reg failed(%d)\n", rc);
return rc;
}
if (led->wled_cfg->pmic_version == PMIC_VER_8026) {
val = WLED_DISABLE_ALL_SINKS;
- rc = spmi_ext_register_writel(led->spmi_dev->ctrl,
- led->spmi_dev->sid,
- WLED_CURR_SINK_REG(led->base), &val, 1);
+ rc = regmap_write(led->regmap,
+ WLED_CURR_SINK_REG(led->base), val);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"WLED write sink reg failed(%d)\n", rc);
return rc;
}
@@ -685,58 +671,50 @@ static int qpnp_wled_set(struct qpnp_led_data *led)
if (led->wled_cfg->num_physical_strings <=
WLED_THREE_STRINGS) {
val = WLED_DISABLE_1_2_SINKS;
- rc = spmi_ext_register_writel(
- led->spmi_dev->ctrl,
- led->spmi_dev->sid,
- WLED_CURR_SINK_REG(led->base), &val, 1);
+ rc = regmap_write(led->regmap,
+ WLED_CURR_SINK_REG(led->base),
+ val);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"WLED write sink reg failed");
return rc;
}
- rc = spmi_ext_register_readl(
- led->spmi_dev->ctrl,
- led->spmi_dev->sid,
- WLED_BOOST_LIMIT_REG(led->base),
- &ilim_val, 1);
+ rc = regmap_read(led->regmap,
+ WLED_BOOST_LIMIT_REG(led->base),
+ &ilim_val);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Unable to read boost reg");
}
val = WLED_SET_ILIM_CODE;
- rc = spmi_ext_register_writel(
- led->spmi_dev->ctrl,
- led->spmi_dev->sid,
- WLED_BOOST_LIMIT_REG(led->base),
- &val, 1);
+ rc = regmap_write(led->regmap,
+ WLED_BOOST_LIMIT_REG(led->base),
+ val);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"WLED write sink reg failed");
return rc;
}
usleep_range(WLED_OVP_DELAY, WLED_OVP_DELAY);
} else {
val = WLED_DISABLE_ALL_SINKS;
- rc = spmi_ext_register_writel(
- led->spmi_dev->ctrl,
- led->spmi_dev->sid,
- WLED_CURR_SINK_REG(led->base), &val, 1);
+ rc = regmap_write(led->regmap,
+ WLED_CURR_SINK_REG(led->base),
+ val);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"WLED write sink reg failed");
return rc;
}
msleep(WLED_OVP_DELAY_INT);
while (tries < WLED_MAX_TRIES) {
- rc = spmi_ext_register_readl(
- led->spmi_dev->ctrl,
- led->spmi_dev->sid,
- WLED_OVP_INT_STATUS(led->base),
- &ovp_val, 1);
+ rc = regmap_read(led->regmap,
+ WLED_OVP_INT_STATUS(led->base),
+ &ovp_val);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Unable to read boost reg");
}
@@ -751,11 +729,10 @@ static int qpnp_wled_set(struct qpnp_led_data *led)
}
val = WLED_BOOST_OFF;
- rc = spmi_ext_register_writel(led->spmi_dev->ctrl,
- led->spmi_dev->sid, WLED_MOD_CTRL_REG(led->base),
- &val, 1);
+ rc = regmap_write(led->regmap, WLED_MOD_CTRL_REG(led->base),
+ val);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"WLED write ctrl reg failed(%d)\n", rc);
return rc;
}
@@ -765,7 +742,7 @@ static int qpnp_wled_set(struct qpnp_led_data *led)
WLED_FULL_SCALE_REG(led->base, i),
WLED_MAX_CURR_MASK, (u8)led->max_current);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Write max current failure (%d)\n",
rc);
return rc;
@@ -774,7 +751,7 @@ static int qpnp_wled_set(struct qpnp_led_data *led)
rc = qpnp_wled_sync(led);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"WLED sync failed(%d)\n", rc);
return rc;
}
@@ -782,25 +759,21 @@ static int qpnp_wled_set(struct qpnp_led_data *led)
if (led->wled_cfg->pmic_version == PMIC_VER_8941) {
if (led->wled_cfg->num_physical_strings <=
WLED_THREE_STRINGS) {
- rc = spmi_ext_register_writel(
- led->spmi_dev->ctrl,
- led->spmi_dev->sid,
- WLED_BOOST_LIMIT_REG(led->base),
- &ilim_val, 1);
+ rc = regmap_write(led->regmap,
+ WLED_BOOST_LIMIT_REG(led->base),
+ ilim_val);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"WLED write sink reg failed");
return rc;
}
} else {
/* restore OVP to original value */
- rc = spmi_ext_register_writel(
- led->spmi_dev->ctrl,
- led->spmi_dev->sid,
- WLED_OVP_CFG_REG(led->base),
- &led->wled_cfg->ovp_val, 1);
+ rc = regmap_write(led->regmap,
+ WLED_OVP_CFG_REG(led->base),
+ *&led->wled_cfg->ovp_val);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"WLED write sink reg failed");
return rc;
}
@@ -808,22 +781,20 @@ static int qpnp_wled_set(struct qpnp_led_data *led)
}
/* re-enable all sinks */
- rc = spmi_ext_register_writel(led->spmi_dev->ctrl,
- led->spmi_dev->sid, WLED_CURR_SINK_REG(led->base),
- &sink_val, 1);
+ rc = regmap_write(led->regmap, WLED_CURR_SINK_REG(led->base),
+ sink_val);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"WLED write sink reg failed(%d)\n", rc);
return rc;
}
} else {
val = WLED_BOOST_ON;
- rc = spmi_ext_register_writel(led->spmi_dev->ctrl,
- led->spmi_dev->sid, WLED_MOD_CTRL_REG(led->base),
- &val, 1);
+ rc = regmap_write(led->regmap, WLED_MOD_CTRL_REG(led->base),
+ val);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"WLED write ctrl reg failed(%d)\n", rc);
return rc;
}
@@ -837,16 +808,15 @@ static int qpnp_wled_set(struct qpnp_led_data *led)
WLED_BRIGHTNESS_CNTL_MSB(led->base, i), WLED_MSB_MASK,
(duty >> WLED_8_BIT_SHFT) & WLED_4_BIT_MASK);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"WLED set brightness MSB failed(%d)\n", rc);
return rc;
}
val = duty & WLED_8_BIT_MASK;
- rc = spmi_ext_register_writel(led->spmi_dev->ctrl,
- led->spmi_dev->sid,
- WLED_BRIGHTNESS_CNTL_LSB(led->base, i), &val, 1);
+ rc = regmap_write(led->regmap,
+ WLED_BRIGHTNESS_CNTL_LSB(led->base, i), val);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"WLED set brightness LSB failed(%d)\n", rc);
return rc;
}
@@ -854,7 +824,7 @@ static int qpnp_wled_set(struct qpnp_led_data *led)
rc = qpnp_wled_sync(led);
if (rc) {
- dev_err(&led->spmi_dev->dev, "WLED sync failed(%d)\n", rc);
+ dev_err(&led->pdev->dev, "WLED sync failed(%d)\n", rc);
return rc;
}
return 0;
@@ -872,7 +842,7 @@ static int qpnp_mpp_set(struct qpnp_led_data *led)
led->mpp_cfg->min_uV,
led->mpp_cfg->max_uV);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Regulator voltage set failed rc=%d\n",
rc);
return rc;
@@ -880,7 +850,7 @@ static int qpnp_mpp_set(struct qpnp_led_data *led)
rc = regulator_enable(led->mpp_cfg->mpp_reg);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Regulator enable failed(%d)\n", rc);
goto err_reg_enable;
}
@@ -889,7 +859,7 @@ static int qpnp_mpp_set(struct qpnp_led_data *led)
led->mpp_cfg->enable = true;
if (led->cdev.brightness < led->mpp_cfg->min_brightness) {
- dev_warn(&led->spmi_dev->dev,
+ dev_warn(&led->pdev->dev,
"brightness is less than supported..." \
"set to minimum supported\n");
led->cdev.brightness = led->mpp_cfg->min_brightness;
@@ -922,8 +892,7 @@ static int qpnp_mpp_set(struct qpnp_led_data *led)
period_us * NSEC_PER_USEC);
}
if (rc < 0) {
- dev_err(&led->spmi_dev->dev, "Failed to " \
- "configure pwm for new values\n");
+ dev_err(&led->pdev->dev, "Failed to configure pwm for new values\n");
goto err_mpp_reg_write;
}
}
@@ -949,7 +918,7 @@ static int qpnp_mpp_set(struct qpnp_led_data *led)
LED_MPP_SINK_CTRL(led->base),
LED_MPP_SINK_MASK, val);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Failed to write sink control reg\n");
goto err_mpp_reg_write;
}
@@ -962,7 +931,7 @@ static int qpnp_mpp_set(struct qpnp_led_data *led)
LED_MPP_MODE_CTRL(led->base), LED_MPP_MODE_MASK,
val);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Failed to write led mode reg\n");
goto err_mpp_reg_write;
}
@@ -971,7 +940,7 @@ static int qpnp_mpp_set(struct qpnp_led_data *led)
LED_MPP_EN_CTRL(led->base), LED_MPP_EN_MASK,
LED_MPP_EN_ENABLE);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Failed to write led enable " \
"reg\n");
goto err_mpp_reg_write;
@@ -989,7 +958,7 @@ static int qpnp_mpp_set(struct qpnp_led_data *led)
LED_MPP_MODE_MASK,
LED_MPP_MODE_DISABLE);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Failed to write led mode reg\n");
goto err_mpp_reg_write;
}
@@ -999,7 +968,7 @@ static int qpnp_mpp_set(struct qpnp_led_data *led)
LED_MPP_EN_MASK,
LED_MPP_EN_DISABLE);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Failed to write led enable reg\n");
goto err_mpp_reg_write;
}
@@ -1007,7 +976,7 @@ static int qpnp_mpp_set(struct qpnp_led_data *led)
if (led->mpp_cfg->mpp_reg && led->mpp_cfg->enable) {
rc = regulator_disable(led->mpp_cfg->mpp_reg);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"MPP regulator disable failed(%d)\n",
rc);
return rc;
@@ -1016,7 +985,7 @@ static int qpnp_mpp_set(struct qpnp_led_data *led)
rc = regulator_set_voltage(led->mpp_cfg->mpp_reg,
0, led->mpp_cfg->max_uV);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"MPP regulator voltage set failed(%d)\n",
rc);
return rc;
@@ -1057,7 +1026,7 @@ static int qpnp_gpio_set(struct qpnp_led_data *led)
LED_GPIO_MODE_MASK,
val);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Failed to write led mode reg\n");
goto err_gpio_reg_write;
}
@@ -1067,7 +1036,7 @@ static int qpnp_gpio_set(struct qpnp_led_data *led)
LED_GPIO_EN_MASK,
LED_GPIO_EN_ENABLE);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Failed to write led enable reg\n");
goto err_gpio_reg_write;
}
@@ -1079,7 +1048,7 @@ static int qpnp_gpio_set(struct qpnp_led_data *led)
LED_GPIO_MODE_MASK,
LED_GPIO_MODE_DISABLE);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Failed to write led mode reg\n");
goto err_gpio_reg_write;
}
@@ -1089,7 +1058,7 @@ static int qpnp_gpio_set(struct qpnp_led_data *led)
LED_GPIO_EN_MASK,
LED_GPIO_EN_DISABLE);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Failed to write led enable reg\n");
goto err_gpio_reg_write;
}
@@ -1113,10 +1082,9 @@ static int qpnp_flash_regulator_operate(struct qpnp_led_data *led, bool on)
struct qpnp_led_data *led_array;
bool regulator_on = false;
- led_array = dev_get_drvdata(&led->spmi_dev->dev);
+ led_array = dev_get_drvdata(&led->pdev->dev);
if (!led_array) {
- dev_err(&led->spmi_dev->dev,
- "Unable to get LED array\n");
+ dev_err(&led->pdev->dev, "Unable to get LED array\n");
return -EINVAL;
}
@@ -1134,7 +1102,7 @@ static int qpnp_flash_regulator_operate(struct qpnp_led_data *led, bool on)
led_array[i].flash_cfg->
flash_wa_reg);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Flash wa regulator"
"enable failed(%d)\n",
rc);
@@ -1155,7 +1123,7 @@ static int qpnp_flash_regulator_operate(struct qpnp_led_data *led, bool on)
regulator_disable(
led_array[i].flash_cfg->
flash_wa_reg);
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Flash boost regulator enable"
"failed(%d)\n", rc);
return rc;
@@ -1177,7 +1145,7 @@ regulator_turn_off:
FLASH_ENABLE_MASK,
FLASH_DISABLE_ALL);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Enable reg write failed(%d)\n",
rc);
}
@@ -1185,7 +1153,7 @@ regulator_turn_off:
rc = regulator_disable(led_array[i].flash_cfg->\
flash_boost_reg);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Flash boost regulator disable"
"failed(%d)\n", rc);
return rc;
@@ -1195,7 +1163,7 @@ regulator_turn_off:
led_array[i].flash_cfg->
flash_wa_reg);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Flash_wa regulator"
"disable failed(%d)\n",
rc);
@@ -1221,7 +1189,7 @@ static int qpnp_torch_regulator_operate(struct qpnp_led_data *led, bool on)
if (!led->flash_cfg->torch_on) {
rc = regulator_enable(led->flash_cfg->torch_boost_reg);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Regulator enable failed(%d)\n", rc);
return rc;
}
@@ -1234,13 +1202,13 @@ regulator_turn_off:
rc = qpnp_led_masked_write(led, FLASH_ENABLE_CONTROL(led->base),
FLASH_ENABLE_MODULE_MASK, FLASH_DISABLE_ALL);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Enable reg write failed(%d)\n", rc);
}
rc = regulator_disable(led->flash_cfg->torch_boost_reg);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Regulator disable failed(%d)\n", rc);
return rc;
}
@@ -1273,7 +1241,7 @@ static int qpnp_flash_set(struct qpnp_led_data *led)
rc = qpnp_flash_regulator_operate(led,
true);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Torch regulator operate failed(%d)\n",
rc);
return rc;
@@ -1282,7 +1250,7 @@ static int qpnp_flash_set(struct qpnp_led_data *led)
FLASH_SUBTYPE_SINGLE) {
rc = qpnp_flash_regulator_operate(led, true);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Flash regulator operate failed(%d)\n",
rc);
goto error_flash_set;
@@ -1293,7 +1261,7 @@ static int qpnp_flash_set(struct qpnp_led_data *led)
FLASH_CURRENT_MASK,
TORCH_MAX_LEVEL);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Max current reg write failed(%d)\n",
rc);
goto error_reg_write;
@@ -1304,7 +1272,7 @@ static int qpnp_flash_set(struct qpnp_led_data *led)
FLASH_TMR_MASK,
FLASH_TMR_WATCHDOG);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Timer control reg write failed(%d)\n",
rc);
goto error_reg_write;
@@ -1315,7 +1283,7 @@ static int qpnp_flash_set(struct qpnp_led_data *led)
FLASH_CURRENT_MASK,
led->flash_cfg->current_prgm);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Current reg write failed(%d)\n", rc);
goto error_reg_write;
}
@@ -1325,7 +1293,7 @@ static int qpnp_flash_set(struct qpnp_led_data *led)
FLASH_CURRENT_MASK,
led->flash_cfg->current_prgm);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"2nd Current reg write failed(%d)\n",
rc);
goto error_reg_write;
@@ -1336,7 +1304,7 @@ static int qpnp_flash_set(struct qpnp_led_data *led)
FLASH_WATCHDOG_MASK,
led->flash_cfg->duration);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Max current reg write failed(%d)\n",
rc);
goto error_reg_write;
@@ -1347,7 +1315,7 @@ static int qpnp_flash_set(struct qpnp_led_data *led)
FLASH_ENABLE_MASK,
led->flash_cfg->enable_module);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Enable reg write failed(%d)\n",
rc);
goto error_reg_write;
@@ -1365,7 +1333,7 @@ static int qpnp_flash_set(struct qpnp_led_data *led)
led->flash_cfg->trigger_flash,
led->flash_cfg->trigger_flash);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"LED %d strobe reg write failed(%d)\n",
led->id, rc);
goto error_reg_write;
@@ -1373,7 +1341,7 @@ static int qpnp_flash_set(struct qpnp_led_data *led)
} else {
rc = qpnp_flash_regulator_operate(led, true);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Flash regulator operate failed(%d)\n",
rc);
goto error_flash_set;
@@ -1384,7 +1352,7 @@ static int qpnp_flash_set(struct qpnp_led_data *led)
FLASH_TMR_MASK,
FLASH_TMR_SAFETY);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Timer control reg write failed(%d)\n",
rc);
goto error_reg_write;
@@ -1396,7 +1364,7 @@ static int qpnp_flash_set(struct qpnp_led_data *led)
FLASH_SAFETY_TIMER_MASK,
led->flash_cfg->duration);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Safety timer reg write failed(%d)\n",
rc);
goto error_flash_set;
@@ -1407,7 +1375,7 @@ static int qpnp_flash_set(struct qpnp_led_data *led)
FLASH_MAX_CURR(led->base), FLASH_CURRENT_MASK,
FLASH_MAX_LEVEL);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Max current reg write failed(%d)\n",
rc);
goto error_flash_set;
@@ -1419,7 +1387,7 @@ static int qpnp_flash_set(struct qpnp_led_data *led)
FLASH_CURRENT_MASK,
led->flash_cfg->clamp_curr);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Clamp current reg write failed(%d)\n",
rc);
goto error_flash_set;
@@ -1430,7 +1398,7 @@ static int qpnp_flash_set(struct qpnp_led_data *led)
FLASH_CURRENT_MASK,
led->flash_cfg->current_prgm);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Current reg write failed(%d)\n", rc);
goto error_flash_set;
}
@@ -1440,7 +1408,7 @@ static int qpnp_flash_set(struct qpnp_led_data *led)
led->flash_cfg->enable_module,
led->flash_cfg->enable_module);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Enable reg write failed(%d)\n", rc);
goto error_flash_set;
}
@@ -1462,7 +1430,7 @@ static int qpnp_flash_set(struct qpnp_led_data *led)
led->flash_cfg->trigger_flash,
led->flash_cfg->trigger_flash);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"LED %d strobe reg write failed(%d)\n",
led->id, rc);
goto error_flash_set;
@@ -1474,7 +1442,7 @@ static int qpnp_flash_set(struct qpnp_led_data *led)
led->flash_cfg->trigger_flash,
FLASH_DISABLE_ALL);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"LED %d flash write failed(%d)\n", led->id, rc);
if (led->flash_cfg->torch_enable)
goto error_torch_set;
@@ -1492,7 +1460,7 @@ static int qpnp_flash_set(struct qpnp_led_data *led)
rc = qpnp_flash_regulator_operate(led,
false);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Torch regulator operate failed(%d)\n",
rc);
return rc;
@@ -1501,7 +1469,7 @@ static int qpnp_flash_set(struct qpnp_led_data *led)
FLASH_SUBTYPE_SINGLE) {
rc = qpnp_flash_regulator_operate(led, false);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Flash regulator operate failed(%d)\n",
rc);
return rc;
@@ -1520,7 +1488,7 @@ static int qpnp_flash_set(struct qpnp_led_data *led)
~FLASH_ENABLE_MODULE_MASK,
FLASH_DISABLE_ALL);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Enable reg write failed(%d)\n", rc);
if (led->flash_cfg->torch_enable)
goto error_torch_set;
@@ -1530,7 +1498,7 @@ static int qpnp_flash_set(struct qpnp_led_data *led)
rc = qpnp_flash_regulator_operate(led, false);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Flash regulator operate failed(%d)\n",
rc);
return rc;
@@ -1552,7 +1520,7 @@ error_torch_set:
else
error = qpnp_flash_regulator_operate(led, false);
if (error) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Torch regulator operate failed(%d)\n", rc);
return error;
}
@@ -1561,7 +1529,7 @@ error_torch_set:
error_flash_set:
error = qpnp_flash_regulator_operate(led, false);
if (error) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Flash regulator operate failed(%d)\n", rc);
return error;
}
@@ -1582,7 +1550,7 @@ static int qpnp_kpdbl_set(struct qpnp_led_data *led)
rc = qpnp_led_masked_write(led, KPDBL_ENABLE(led->base),
KPDBL_MODULE_EN_MASK, KPDBL_MODULE_EN);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Enable reg write failed(%d)\n", rc);
return rc;
}
@@ -1600,14 +1568,14 @@ static int qpnp_kpdbl_set(struct qpnp_led_data *led)
rc = pwm_config_us(kpdbl_master, 0,
kpdbl_master_period_us);
if (rc < 0) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"pwm config failed\n");
return rc;
}
rc = pwm_enable(kpdbl_master);
if (rc < 0) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"pwm enable failed\n");
return rc;
}
@@ -1633,14 +1601,15 @@ static int qpnp_kpdbl_set(struct qpnp_led_data *led)
period_us * NSEC_PER_USEC);
}
if (rc < 0) {
- dev_err(&led->spmi_dev->dev, "pwm config failed\n");
+ dev_err(&led->pdev->dev,
+ "pwm config failed\n");
return rc;
}
}
rc = pwm_enable(led->kpdbl_cfg->pwm_cfg->pwm_dev);
if (rc < 0) {
- dev_err(&led->spmi_dev->dev, "pwm enable failed\n");
+ dev_err(&led->pdev->dev, "pwm enable failed\n");
return rc;
}
@@ -1667,7 +1636,7 @@ static int qpnp_kpdbl_set(struct qpnp_led_data *led)
led->kpdbl_cfg->pwm_cfg->pwm_dev, 0,
led->kpdbl_cfg->pwm_cfg->pwm_period_us);
if (rc < 0) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"pwm config failed\n");
return rc;
}
@@ -1675,7 +1644,7 @@ static int qpnp_kpdbl_set(struct qpnp_led_data *led)
rc = pwm_enable(led->kpdbl_cfg->pwm_cfg->
pwm_dev);
if (rc < 0) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"pwm enable failed\n");
return rc;
}
@@ -1689,7 +1658,7 @@ static int qpnp_kpdbl_set(struct qpnp_led_data *led)
KPDBL_MODULE_EN_MASK,
KPDBL_MODULE_DIS);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Failed to write led"
" enable reg\n");
return rc;
@@ -1710,7 +1679,7 @@ static int qpnp_kpdbl_set(struct qpnp_led_data *led)
led, KPDBL_ENABLE(led->base),
KPDBL_MODULE_EN_MASK, KPDBL_MODULE_DIS);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Failed to write led enable reg\n");
return rc;
}
@@ -1753,7 +1722,7 @@ static int qpnp_rgb_set(struct qpnp_led_data *led)
period_us * NSEC_PER_USEC);
}
if (rc < 0) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"pwm config failed\n");
return rc;
}
@@ -1762,7 +1731,7 @@ static int qpnp_rgb_set(struct qpnp_led_data *led)
RGB_LED_EN_CTL(led->base),
led->rgb_cfg->enable, led->rgb_cfg->enable);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Failed to write led enable reg\n");
return rc;
}
@@ -1784,7 +1753,7 @@ static int qpnp_rgb_set(struct qpnp_led_data *led)
RGB_LED_EN_CTL(led->base),
led->rgb_cfg->enable, RGB_LED_DISABLE);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Failed to write led enable reg\n");
return rc;
}
@@ -1803,7 +1772,7 @@ static void qpnp_led_set(struct led_classdev *led_cdev,
led = container_of(led_cdev, struct qpnp_led_data, cdev);
if (value < LED_OFF) {
- dev_err(&led->spmi_dev->dev, "Invalid brightness value\n");
+ dev_err(&led->pdev->dev, "Invalid brightness value\n");
return;
}
@@ -1831,14 +1800,14 @@ static void __qpnp_led_work(struct qpnp_led_data *led,
case QPNP_ID_WLED:
rc = qpnp_wled_set(led);
if (rc < 0)
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"WLED set brightness failed (%d)\n", rc);
break;
case QPNP_ID_FLASH1_LED0:
case QPNP_ID_FLASH1_LED1:
rc = qpnp_flash_set(led);
if (rc < 0)
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"FLASH set brightness failed (%d)\n", rc);
break;
case QPNP_ID_RGB_RED:
@@ -1846,30 +1815,30 @@ static void __qpnp_led_work(struct qpnp_led_data *led,
case QPNP_ID_RGB_BLUE:
rc = qpnp_rgb_set(led);
if (rc < 0)
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"RGB set brightness failed (%d)\n", rc);
break;
case QPNP_ID_LED_MPP:
rc = qpnp_mpp_set(led);
if (rc < 0)
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"MPP set brightness failed (%d)\n", rc);
break;
case QPNP_ID_LED_GPIO:
rc = qpnp_gpio_set(led);
if (rc < 0)
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"GPIO set brightness failed (%d)\n",
rc);
break;
case QPNP_ID_KPDBL:
rc = qpnp_kpdbl_set(led);
if (rc < 0)
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"KPDBL set brightness failed (%d)\n", rc);
break;
default:
- dev_err(&led->spmi_dev->dev, "Invalid LED(%d)\n", led->id);
+ dev_err(&led->pdev->dev, "Invalid LED(%d)\n", led->id);
break;
}
if (led->id == QPNP_ID_FLASH1_LED0 || led->id == QPNP_ID_FLASH1_LED1)
@@ -1917,7 +1886,7 @@ static int qpnp_led_set_max_brightness(struct qpnp_led_data *led)
led->cdev.max_brightness = KPDBL_MAX_LEVEL;
break;
default:
- dev_err(&led->spmi_dev->dev, "Invalid LED(%d)\n", led->id);
+ dev_err(&led->pdev->dev, "Invalid LED(%d)\n", led->id);
return -EINVAL;
}
@@ -1959,28 +1928,28 @@ static int qpnp_wled_init(struct qpnp_led_data *led)
/* verify ranges */
if (led->wled_cfg->ovp_val > WLED_OVP_27V) {
- dev_err(&led->spmi_dev->dev, "Invalid ovp value\n");
+ dev_err(&led->pdev->dev, "Invalid ovp value\n");
return -EINVAL;
}
if (led->wled_cfg->boost_curr_lim > WLED_CURR_LIMIT_1680mA) {
- dev_err(&led->spmi_dev->dev, "Invalid boost current limit\n");
+ dev_err(&led->pdev->dev, "Invalid boost current limit\n");
return -EINVAL;
}
if (led->wled_cfg->cp_select > WLED_CP_SELECT_MAX) {
- dev_err(&led->spmi_dev->dev, "Invalid pole capacitance\n");
+ dev_err(&led->pdev->dev, "Invalid pole capacitance\n");
return -EINVAL;
}
if ((led->max_current > WLED_MAX_CURR)) {
- dev_err(&led->spmi_dev->dev, "Invalid max current\n");
+ dev_err(&led->pdev->dev, "Invalid max current\n");
return -EINVAL;
}
if ((led->wled_cfg->ctrl_delay_us % WLED_CTL_DLY_STEP) ||
(led->wled_cfg->ctrl_delay_us > WLED_CTL_DLY_MAX)) {
- dev_err(&led->spmi_dev->dev, "Invalid control delay\n");
+ dev_err(&led->pdev->dev, "Invalid control delay\n");
return -EINVAL;
}
@@ -1989,7 +1958,7 @@ static int qpnp_wled_init(struct qpnp_led_data *led)
WLED_OVP_VAL_MASK,
(led->wled_cfg->ovp_val << WLED_OVP_VAL_BIT_SHFT));
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"WLED OVP reg write failed(%d)\n", rc);
return rc;
}
@@ -1998,7 +1967,7 @@ static int qpnp_wled_init(struct qpnp_led_data *led)
rc = qpnp_led_masked_write(led, WLED_BOOST_LIMIT_REG(led->base),
WLED_BOOST_LIMIT_MASK, led->wled_cfg->boost_curr_lim);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"WLED boost limit reg write failed(%d)\n", rc);
return rc;
}
@@ -2008,7 +1977,7 @@ static int qpnp_wled_init(struct qpnp_led_data *led)
WLED_OP_FDBCK_MASK,
(led->wled_cfg->op_fdbck << WLED_OP_FDBCK_BIT_SHFT));
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"WLED fdbck ctrl reg write failed(%d)\n", rc);
return rc;
}
@@ -2018,7 +1987,7 @@ static int qpnp_wled_init(struct qpnp_led_data *led)
WLED_SWITCHING_FREQ_REG(led->base),
WLED_SWITCH_FREQ_MASK, led->wled_cfg->switch_freq);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"WLED switch freq reg write failed(%d)\n", rc);
return rc;
}
@@ -2030,7 +1999,7 @@ static int qpnp_wled_init(struct qpnp_led_data *led)
rc = qpnp_led_masked_write(led, WLED_CURR_SINK_REG(led->base),
WLED_CURR_SINK_MASK, (val << WLED_CURR_SINK_SHFT));
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"WLED curr sink reg write failed(%d)\n", rc);
return rc;
}
@@ -2040,7 +2009,7 @@ static int qpnp_wled_init(struct qpnp_led_data *led)
rc = qpnp_led_masked_write(led, WLED_HIGH_POLE_CAP_REG(led->base),
WLED_CP_SELECT_MASK, led->wled_cfg->cp_select);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"WLED pole cap reg write failed(%d)\n", rc);
return rc;
}
@@ -2050,7 +2019,7 @@ static int qpnp_wled_init(struct qpnp_led_data *led)
rc = qpnp_led_masked_write(led, WLED_MOD_EN_REG(led->base, i),
WLED_NO_MASK, WLED_EN_MASK);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"WLED mod enable reg write failed(%d)\n", rc);
return rc;
}
@@ -2060,7 +2029,7 @@ static int qpnp_wled_init(struct qpnp_led_data *led)
WLED_MOD_SRC_SEL_REG(led->base, i),
WLED_NO_MASK, WLED_USE_EXT_GEN_MOD_SRC);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"WLED dig mod en reg write failed(%d)\n", rc);
}
}
@@ -2069,7 +2038,7 @@ static int qpnp_wled_init(struct qpnp_led_data *led)
WLED_FULL_SCALE_REG(led->base, i), WLED_MAX_CURR_MASK,
(u8)led->max_current);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"WLED max current reg write failed(%d)\n", rc);
return rc;
}
@@ -2080,7 +2049,7 @@ static int qpnp_wled_init(struct qpnp_led_data *led)
rc = qpnp_led_masked_write(led, WLED_MOD_CTRL_REG(led->base),
WLED_8_BIT_MASK, WLED_BOOST_OFF);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"WLED write ctrl reg failed(%d)\n", rc);
return rc;
}
@@ -2140,7 +2109,7 @@ static ssize_t led_strobe_type_store(struct device *dev,
}
static int qpnp_pwm_init(struct pwm_config_data *pwm_cfg,
- struct spmi_device *spmi_dev,
+ struct platform_device *pdev,
const char *name)
{
int rc, start_idx, idx_len, lut_max_size;
@@ -2158,14 +2127,13 @@ static int qpnp_pwm_init(struct pwm_config_data *pwm_cfg,
lut_max_size = PWM_LUT_MAX_SIZE;
if (idx_len >= lut_max_size && start_idx) {
- dev_err(&spmi_dev->dev,
+ dev_err(&pdev->dev,
"Wrong LUT size or index\n");
return -EINVAL;
}
if ((start_idx + idx_len) > lut_max_size) {
- dev_err(&spmi_dev->dev,
- "Exceed LUT limit\n");
+ dev_err(&pdev->dev, "Exceed LUT limit\n");
return -EINVAL;
}
rc = pwm_lut_config(pwm_cfg->pwm_dev,
@@ -2173,14 +2141,12 @@ static int qpnp_pwm_init(struct pwm_config_data *pwm_cfg,
pwm_cfg->duty_cycles->duty_pcts,
pwm_cfg->lut_params);
if (rc < 0) {
- dev_err(&spmi_dev->dev, "Failed to " \
- "configure pwm LUT\n");
+ dev_err(&pdev->dev, "Failed to configure pwm LUT\n");
return rc;
}
}
} else {
- dev_err(&spmi_dev->dev,
- "Invalid PWM device\n");
+ dev_err(&pdev->dev, "Invalid PWM device\n");
return -EINVAL;
}
@@ -2217,8 +2183,7 @@ static ssize_t pwm_us_store(struct device *dev,
pwm_cfg = led->kpdbl_cfg->pwm_cfg;
break;
default:
- dev_err(&led->spmi_dev->dev,
- "Invalid LED id type for pwm_us\n");
+ dev_err(&led->pdev->dev, "Invalid LED id type for pwm_us\n");
return -EINVAL;
}
@@ -2229,13 +2194,13 @@ static ssize_t pwm_us_store(struct device *dev,
pwm_cfg->pwm_period_us = pwm_us;
pwm_free(pwm_cfg->pwm_dev);
- ret = qpnp_pwm_init(pwm_cfg, led->spmi_dev, led->cdev.name);
+ ret = qpnp_pwm_init(pwm_cfg, led->pdev, led->cdev.name);
if (ret) {
pwm_cfg->pwm_period_us = previous_pwm_us;
pwm_free(pwm_cfg->pwm_dev);
- qpnp_pwm_init(pwm_cfg, led->spmi_dev, led->cdev.name);
+ qpnp_pwm_init(pwm_cfg, led->pdev, led->cdev.name);
qpnp_led_set(&led->cdev, led->cdev.brightness);
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Failed to initialize pwm with new pwm_us value\n");
return ret;
}
@@ -2272,7 +2237,7 @@ static ssize_t pause_lo_store(struct device *dev,
pwm_cfg = led->kpdbl_cfg->pwm_cfg;
break;
default:
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Invalid LED id type for pause lo\n");
return -EINVAL;
}
@@ -2284,13 +2249,13 @@ static ssize_t pause_lo_store(struct device *dev,
pwm_free(pwm_cfg->pwm_dev);
pwm_cfg->lut_params.lut_pause_lo = pause_lo;
- ret = qpnp_pwm_init(pwm_cfg, led->spmi_dev, led->cdev.name);
+ ret = qpnp_pwm_init(pwm_cfg, led->pdev, led->cdev.name);
if (ret) {
pwm_cfg->lut_params.lut_pause_lo = previous_pause_lo;
pwm_free(pwm_cfg->pwm_dev);
- qpnp_pwm_init(pwm_cfg, led->spmi_dev, led->cdev.name);
+ qpnp_pwm_init(pwm_cfg, led->pdev, led->cdev.name);
qpnp_led_set(&led->cdev, led->cdev.brightness);
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Failed to initialize pwm with new pause lo value\n");
return ret;
}
@@ -2327,7 +2292,7 @@ static ssize_t pause_hi_store(struct device *dev,
pwm_cfg = led->kpdbl_cfg->pwm_cfg;
break;
default:
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Invalid LED id type for pause hi\n");
return -EINVAL;
}
@@ -2339,13 +2304,13 @@ static ssize_t pause_hi_store(struct device *dev,
pwm_free(pwm_cfg->pwm_dev);
pwm_cfg->lut_params.lut_pause_hi = pause_hi;
- ret = qpnp_pwm_init(pwm_cfg, led->spmi_dev, led->cdev.name);
+ ret = qpnp_pwm_init(pwm_cfg, led->pdev, led->cdev.name);
if (ret) {
pwm_cfg->lut_params.lut_pause_hi = previous_pause_hi;
pwm_free(pwm_cfg->pwm_dev);
- qpnp_pwm_init(pwm_cfg, led->spmi_dev, led->cdev.name);
+ qpnp_pwm_init(pwm_cfg, led->pdev, led->cdev.name);
qpnp_led_set(&led->cdev, led->cdev.brightness);
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Failed to initialize pwm with new pause hi value\n");
return ret;
}
@@ -2382,7 +2347,7 @@ static ssize_t start_idx_store(struct device *dev,
pwm_cfg = led->kpdbl_cfg->pwm_cfg;
break;
default:
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Invalid LED id type for start idx\n");
return -EINVAL;
}
@@ -2394,14 +2359,14 @@ static ssize_t start_idx_store(struct device *dev,
pwm_cfg->duty_cycles->start_idx = start_idx;
pwm_cfg->lut_params.start_idx = pwm_cfg->duty_cycles->start_idx;
pwm_free(pwm_cfg->pwm_dev);
- ret = qpnp_pwm_init(pwm_cfg, led->spmi_dev, led->cdev.name);
+ ret = qpnp_pwm_init(pwm_cfg, led->pdev, led->cdev.name);
if (ret) {
pwm_cfg->duty_cycles->start_idx = previous_start_idx;
pwm_cfg->lut_params.start_idx = pwm_cfg->duty_cycles->start_idx;
pwm_free(pwm_cfg->pwm_dev);
- qpnp_pwm_init(pwm_cfg, led->spmi_dev, led->cdev.name);
+ qpnp_pwm_init(pwm_cfg, led->pdev, led->cdev.name);
qpnp_led_set(&led->cdev, led->cdev.brightness);
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Failed to initialize pwm with new start idx value\n");
return ret;
}
@@ -2438,7 +2403,7 @@ static ssize_t ramp_step_ms_store(struct device *dev,
pwm_cfg = led->kpdbl_cfg->pwm_cfg;
break;
default:
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Invalid LED id type for ramp step\n");
return -EINVAL;
}
@@ -2450,13 +2415,13 @@ static ssize_t ramp_step_ms_store(struct device *dev,
pwm_free(pwm_cfg->pwm_dev);
pwm_cfg->lut_params.ramp_step_ms = ramp_step_ms;
- ret = qpnp_pwm_init(pwm_cfg, led->spmi_dev, led->cdev.name);
+ ret = qpnp_pwm_init(pwm_cfg, led->pdev, led->cdev.name);
if (ret) {
pwm_cfg->lut_params.ramp_step_ms = previous_ramp_step_ms;
pwm_free(pwm_cfg->pwm_dev);
- qpnp_pwm_init(pwm_cfg, led->spmi_dev, led->cdev.name);
+ qpnp_pwm_init(pwm_cfg, led->pdev, led->cdev.name);
qpnp_led_set(&led->cdev, led->cdev.brightness);
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Failed to initialize pwm with new ramp step value\n");
return ret;
}
@@ -2493,7 +2458,7 @@ static ssize_t lut_flags_store(struct device *dev,
pwm_cfg = led->kpdbl_cfg->pwm_cfg;
break;
default:
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Invalid LED id type for lut flags\n");
return -EINVAL;
}
@@ -2505,13 +2470,13 @@ static ssize_t lut_flags_store(struct device *dev,
pwm_free(pwm_cfg->pwm_dev);
pwm_cfg->lut_params.flags = lut_flags;
- ret = qpnp_pwm_init(pwm_cfg, led->spmi_dev, led->cdev.name);
+ ret = qpnp_pwm_init(pwm_cfg, led->pdev, led->cdev.name);
if (ret) {
pwm_cfg->lut_params.flags = previous_lut_flags;
pwm_free(pwm_cfg->pwm_dev);
- qpnp_pwm_init(pwm_cfg, led->spmi_dev, led->cdev.name);
+ qpnp_pwm_init(pwm_cfg, led->pdev, led->cdev.name);
qpnp_led_set(&led->cdev, led->cdev.brightness);
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Failed to initialize pwm with new lut flags value\n");
return ret;
}
@@ -2553,7 +2518,7 @@ static ssize_t duty_pcts_store(struct device *dev,
max_duty_pcts = PWM_GPLED_LUT_MAX_SIZE;
break;
default:
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Invalid LED id type for duty pcts\n");
return -EINVAL;
}
@@ -2574,7 +2539,7 @@ static ssize_t duty_pcts_store(struct device *dev,
}
if (num_duty_pcts >= max_duty_pcts) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Number of duty pcts given exceeds max (%d)\n",
max_duty_pcts);
return -EINVAL;
@@ -2589,7 +2554,7 @@ static ssize_t duty_pcts_store(struct device *dev,
pwm_cfg->lut_params.idx_len = pwm_cfg->duty_cycles->num_duty_pcts;
pwm_free(pwm_cfg->pwm_dev);
- ret = qpnp_pwm_init(pwm_cfg, led->spmi_dev, led->cdev.name);
+ ret = qpnp_pwm_init(pwm_cfg, led->pdev, led->cdev.name);
if (ret)
goto restore;
@@ -2597,14 +2562,14 @@ static ssize_t duty_pcts_store(struct device *dev,
return count;
restore:
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Failed to initialize pwm with new duty pcts value\n");
pwm_cfg->duty_cycles->num_duty_pcts = previous_num_duty_pcts;
pwm_cfg->old_duty_pcts = pwm_cfg->duty_cycles->duty_pcts;
pwm_cfg->duty_cycles->duty_pcts = previous_duty_pcts;
pwm_cfg->lut_params.idx_len = pwm_cfg->duty_cycles->num_duty_pcts;
pwm_free(pwm_cfg->pwm_dev);
- qpnp_pwm_init(pwm_cfg, led->spmi_dev, led->cdev.name);
+ qpnp_pwm_init(pwm_cfg, led->pdev, led->cdev.name);
qpnp_led_set(&led->cdev, led->cdev.brightness);
return ret;
}
@@ -2634,22 +2599,22 @@ static void led_blink(struct qpnp_led_data *led,
pwm_cfg->default_mode;
}
pwm_free(pwm_cfg->pwm_dev);
- qpnp_pwm_init(pwm_cfg, led->spmi_dev, led->cdev.name);
+ qpnp_pwm_init(pwm_cfg, led->pdev, led->cdev.name);
if (led->id == QPNP_ID_RGB_RED || led->id == QPNP_ID_RGB_GREEN
|| led->id == QPNP_ID_RGB_BLUE) {
rc = qpnp_rgb_set(led);
if (rc < 0)
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"RGB set brightness failed (%d)\n", rc);
} else if (led->id == QPNP_ID_LED_MPP) {
rc = qpnp_mpp_set(led);
if (rc < 0)
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"MPP set brightness failed (%d)\n", rc);
} else if (led->id == QPNP_ID_KPDBL) {
rc = qpnp_kpdbl_set(led);
if (rc < 0)
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"KPDBL set brightness failed (%d)\n", rc);
}
}
@@ -2684,7 +2649,7 @@ static ssize_t blink_store(struct device *dev,
led_blink(led, led->kpdbl_cfg->pwm_cfg);
break;
default:
- dev_err(&led->spmi_dev->dev, "Invalid LED id type for blink\n");
+ dev_err(&led->pdev->dev, "Invalid LED id type for blink\n");
return -EINVAL;
}
return count;
@@ -2753,7 +2718,7 @@ static int qpnp_flash_init(struct qpnp_led_data *led)
FLASH_LED_STROBE_CTRL(led->base),
FLASH_STROBE_MASK, FLASH_DISABLE_ALL);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"LED %d flash write failed(%d)\n", led->id, rc);
return rc;
}
@@ -2762,8 +2727,7 @@ static int qpnp_flash_init(struct qpnp_led_data *led)
rc = qpnp_led_masked_write(led, FLASH_ENABLE_CONTROL(led->base),
FLASH_ENABLE_MASK, FLASH_DISABLE_ALL);
if (rc) {
- dev_err(&led->spmi_dev->dev,
- "Enable reg write failed(%d)\n", rc);
+ dev_err(&led->pdev->dev, "Enable reg write failed(%d)\n", rc);
return rc;
}
@@ -2774,7 +2738,7 @@ static int qpnp_flash_init(struct qpnp_led_data *led)
rc = qpnp_led_masked_write(led, FLASH_HEADROOM(led->base),
FLASH_HEADROOM_MASK, led->flash_cfg->headroom);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Headroom reg write failed(%d)\n", rc);
return rc;
}
@@ -2784,7 +2748,7 @@ static int qpnp_flash_init(struct qpnp_led_data *led)
FLASH_STARTUP_DELAY(led->base), FLASH_STARTUP_DLY_MASK,
led->flash_cfg->startup_dly);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Startup delay reg write failed(%d)\n", rc);
return rc;
}
@@ -2795,7 +2759,7 @@ static int qpnp_flash_init(struct qpnp_led_data *led)
FLASH_LED_TMR_CTRL(led->base),
FLASH_TMR_MASK, FLASH_TMR_SAFETY);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"LED timer ctrl reg write failed(%d)\n",
rc);
return rc;
@@ -2811,7 +2775,7 @@ static int qpnp_flash_init(struct qpnp_led_data *led)
FLASH_VREG_MASK, FLASH_HW_VREG_OK);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Vreg OK reg write failed(%d)\n", rc);
return rc;
}
@@ -2820,7 +2784,7 @@ static int qpnp_flash_init(struct qpnp_led_data *led)
rc = qpnp_led_masked_write(led, FLASH_FAULT_DETECT(led->base),
FLASH_FAULT_DETECT_MASK, FLASH_SELFCHECK_ENABLE);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Fault detect reg write failed(%d)\n", rc);
return rc;
}
@@ -2829,7 +2793,7 @@ static int qpnp_flash_init(struct qpnp_led_data *led)
rc = qpnp_led_masked_write(led, FLASH_MASK_ENABLE(led->base),
FLASH_MASK_REG_MASK, FLASH_MASK_1);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Mask enable reg write failed(%d)\n", rc);
return rc;
}
@@ -2838,7 +2802,7 @@ static int qpnp_flash_init(struct qpnp_led_data *led)
rc = qpnp_led_masked_write(led, FLASH_CURRENT_RAMP(led->base),
FLASH_CURRENT_RAMP_MASK, FLASH_RAMP_STEP_27US);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Current ramp reg write failed(%d)\n", rc);
return rc;
}
@@ -2854,13 +2818,12 @@ static int qpnp_flash_init(struct qpnp_led_data *led)
static int qpnp_kpdbl_init(struct qpnp_led_data *led)
{
int rc;
- u8 val;
+ uint val;
/* select row source - vbst or vph */
- rc = spmi_ext_register_readl(led->spmi_dev->ctrl, led->spmi_dev->sid,
- KPDBL_ROW_SRC_SEL(led->base), &val, 1);
+ rc = regmap_read(led->regmap, KPDBL_ROW_SRC_SEL(led->base), &val);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Unable to read from addr=%x, rc(%d)\n",
KPDBL_ROW_SRC_SEL(led->base), rc);
return rc;
@@ -2871,20 +2834,18 @@ static int qpnp_kpdbl_init(struct qpnp_led_data *led)
else
val &= ~(1 << led->kpdbl_cfg->row_id);
- rc = spmi_ext_register_writel(led->spmi_dev->ctrl, led->spmi_dev->sid,
- KPDBL_ROW_SRC_SEL(led->base), &val, 1);
+ rc = regmap_write(led->regmap, KPDBL_ROW_SRC_SEL(led->base), val);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Unable to read from addr=%x, rc(%d)\n",
KPDBL_ROW_SRC_SEL(led->base), rc);
return rc;
}
/* row source enable */
- rc = spmi_ext_register_readl(led->spmi_dev->ctrl, led->spmi_dev->sid,
- KPDBL_ROW_SRC(led->base), &val, 1);
+ rc = regmap_read(led->regmap, KPDBL_ROW_SRC(led->base), &val);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Unable to read from addr=%x, rc(%d)\n",
KPDBL_ROW_SRC(led->base), rc);
return rc;
@@ -2895,10 +2856,9 @@ static int qpnp_kpdbl_init(struct qpnp_led_data *led)
else
val &= ~(1 << led->kpdbl_cfg->row_id);
- rc = spmi_ext_register_writel(led->spmi_dev->ctrl, led->spmi_dev->sid,
- KPDBL_ROW_SRC(led->base), &val, 1);
+ rc = regmap_write(led->regmap, KPDBL_ROW_SRC(led->base), val);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Unable to write to addr=%x, rc(%d)\n",
KPDBL_ROW_SRC(led->base), rc);
return rc;
@@ -2908,16 +2868,15 @@ static int qpnp_kpdbl_init(struct qpnp_led_data *led)
rc = qpnp_led_masked_write(led, KPDBL_ENABLE(led->base),
KPDBL_MODULE_EN_MASK, KPDBL_MODULE_EN);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Enable module write failed(%d)\n", rc);
return rc;
}
- rc = qpnp_pwm_init(led->kpdbl_cfg->pwm_cfg, led->spmi_dev,
+ rc = qpnp_pwm_init(led->kpdbl_cfg->pwm_cfg, led->pdev,
led->cdev.name);
if (rc) {
- dev_err(&led->spmi_dev->dev,
- "Failed to initialize pwm\n");
+ dev_err(&led->pdev->dev, "Failed to initialize pwm\n");
return rc;
}
@@ -2939,16 +2898,14 @@ static int qpnp_rgb_init(struct qpnp_led_data *led)
rc = qpnp_led_masked_write(led, RGB_LED_SRC_SEL(led->base),
RGB_LED_SRC_MASK, RGB_LED_SOURCE_VPH_PWR);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Failed to write led source select register\n");
return rc;
}
- rc = qpnp_pwm_init(led->rgb_cfg->pwm_cfg, led->spmi_dev,
- led->cdev.name);
+ rc = qpnp_pwm_init(led->rgb_cfg->pwm_cfg, led->pdev, led->cdev.name);
if (rc) {
- dev_err(&led->spmi_dev->dev,
- "Failed to initialize pwm\n");
+ dev_err(&led->pdev->dev, "Failed to initialize pwm\n");
return rc;
}
/* Initialize led for use in auto trickle charging mode */
@@ -2966,7 +2923,7 @@ static int qpnp_mpp_init(struct qpnp_led_data *led)
if (led->max_current < LED_MPP_CURRENT_MIN ||
led->max_current > LED_MPP_CURRENT_MAX) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"max current for mpp is not valid\n");
return -EINVAL;
}
@@ -2979,7 +2936,7 @@ static int qpnp_mpp_init(struct qpnp_led_data *led)
rc = qpnp_led_masked_write(led, LED_MPP_VIN_CTRL(led->base),
LED_MPP_VIN_MASK, led->mpp_cfg->vin_ctrl);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Failed to write led vin control reg\n");
return rc;
}
@@ -2987,16 +2944,16 @@ static int qpnp_mpp_init(struct qpnp_led_data *led)
rc = qpnp_led_masked_write(led, LED_MPP_SINK_CTRL(led->base),
LED_MPP_SINK_MASK, val);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Failed to write sink control reg\n");
return rc;
}
if (led->mpp_cfg->pwm_mode != MANUAL_MODE) {
- rc = qpnp_pwm_init(led->mpp_cfg->pwm_cfg, led->spmi_dev,
+ rc = qpnp_pwm_init(led->mpp_cfg->pwm_cfg, led->pdev,
led->cdev.name);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Failed to initialize pwm\n");
return rc;
}
@@ -3012,7 +2969,7 @@ static int qpnp_gpio_init(struct qpnp_led_data *led)
rc = qpnp_led_masked_write(led, LED_GPIO_VIN_CTRL(led->base),
LED_GPIO_VIN_MASK, led->gpio_cfg->vin_ctrl);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Failed to write led vin control reg\n");
return rc;
}
@@ -3028,14 +2985,14 @@ static int qpnp_led_initialize(struct qpnp_led_data *led)
case QPNP_ID_WLED:
rc = qpnp_wled_init(led);
if (rc)
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"WLED initialize failed(%d)\n", rc);
break;
case QPNP_ID_FLASH1_LED0:
case QPNP_ID_FLASH1_LED1:
rc = qpnp_flash_init(led);
if (rc)
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"FLASH initialize failed(%d)\n", rc);
break;
case QPNP_ID_RGB_RED:
@@ -3043,29 +3000,29 @@ static int qpnp_led_initialize(struct qpnp_led_data *led)
case QPNP_ID_RGB_BLUE:
rc = qpnp_rgb_init(led);
if (rc)
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"RGB initialize failed(%d)\n", rc);
break;
case QPNP_ID_LED_MPP:
rc = qpnp_mpp_init(led);
if (rc)
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"MPP initialize failed(%d)\n", rc);
break;
case QPNP_ID_LED_GPIO:
rc = qpnp_gpio_init(led);
if (rc)
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"GPIO initialize failed(%d)\n", rc);
break;
case QPNP_ID_KPDBL:
rc = qpnp_kpdbl_init(led);
if (rc)
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"KPDBL initialize failed(%d)\n", rc);
break;
default:
- dev_err(&led->spmi_dev->dev, "Invalid LED(%d)\n", led->id);
+ dev_err(&led->pdev->dev, "Invalid LED(%d)\n", led->id);
return -EINVAL;
}
@@ -3113,21 +3070,22 @@ static int qpnp_get_config_wled(struct qpnp_led_data *led,
struct device_node *node)
{
u32 val;
+ uint tmp;
int rc;
- led->wled_cfg = devm_kzalloc(&led->spmi_dev->dev,
+ led->wled_cfg = devm_kzalloc(&led->pdev->dev,
sizeof(struct wled_config_data), GFP_KERNEL);
if (!led->wled_cfg) {
- dev_err(&led->spmi_dev->dev, "Unable to allocate memory\n");
+ dev_err(&led->pdev->dev, "Unable to allocate memory\n");
return -ENOMEM;
}
- rc = spmi_ext_register_readl(led->spmi_dev->ctrl, led->spmi_dev->sid,
- PMIC_VERSION_REG, &led->wled_cfg->pmic_version, 1);
+ rc = regmap_read(led->regmap, PMIC_VERSION_REG, &tmp);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Unable to read pmic ver, rc(%d)\n", rc);
}
+ led->wled_cfg->pmic_version = (u8)tmp;
led->wled_cfg->num_strings = WLED_DEFAULT_STRINGS;
rc = of_property_read_u32(node, "qcom,num-strings", &val);
@@ -3199,22 +3157,23 @@ static int qpnp_get_config_flash(struct qpnp_led_data *led,
{
int rc;
u32 val;
+ uint tmp;
- led->flash_cfg = devm_kzalloc(&led->spmi_dev->dev,
+ led->flash_cfg = devm_kzalloc(&led->pdev->dev,
sizeof(struct flash_config_data), GFP_KERNEL);
if (!led->flash_cfg) {
- dev_err(&led->spmi_dev->dev, "Unable to allocate memory\n");
+ dev_err(&led->pdev->dev, "Unable to allocate memory\n");
return -ENOMEM;
}
- rc = spmi_ext_register_readl(led->spmi_dev->ctrl, led->spmi_dev->sid,
- FLASH_PERIPHERAL_SUBTYPE(led->base),
- &led->flash_cfg->peripheral_subtype, 1);
+ rc = regmap_read(led->regmap, FLASH_PERIPHERAL_SUBTYPE(led->base),
+ &tmp);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Unable to read from addr=%x, rc(%d)\n",
FLASH_PERIPHERAL_SUBTYPE(led->base), rc);
}
+ led->flash_cfg->peripheral_subtype = (u8)tmp;
led->flash_cfg->torch_enable =
of_property_read_bool(node, "qcom,torch-enable");
@@ -3225,11 +3184,11 @@ static int qpnp_get_config_flash(struct qpnp_led_data *led,
if (of_find_property(of_get_parent(node), "flash-wa-supply",
NULL) && (!*reg_set)) {
led->flash_cfg->flash_wa_reg =
- devm_regulator_get(&led->spmi_dev->dev, "flash-wa");
+ devm_regulator_get(&led->pdev->dev, "flash-wa");
if (IS_ERR_OR_NULL(led->flash_cfg->flash_wa_reg)) {
rc = PTR_ERR(led->flash_cfg->flash_wa_reg);
if (rc != EPROBE_DEFER) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Flash wa regulator get failed(%d)\n",
rc);
}
@@ -3244,11 +3203,11 @@ static int qpnp_get_config_flash(struct qpnp_led_data *led,
led->flash_cfg->trigger_flash = FLASH_LED_0_OUTPUT;
if (!*reg_set) {
led->flash_cfg->flash_boost_reg =
- regulator_get(&led->spmi_dev->dev,
+ regulator_get(&led->pdev->dev,
"flash-boost");
if (IS_ERR(led->flash_cfg->flash_boost_reg)) {
rc = PTR_ERR(led->flash_cfg->flash_boost_reg);
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Regulator get failed(%d)\n", rc);
goto error_get_flash_reg;
}
@@ -3267,11 +3226,11 @@ static int qpnp_get_config_flash(struct qpnp_led_data *led,
led->flash_cfg->trigger_flash = FLASH_LED_1_OUTPUT;
if (!*reg_set) {
led->flash_cfg->flash_boost_reg =
- regulator_get(&led->spmi_dev->dev,
+ regulator_get(&led->pdev->dev,
"flash-boost");
if (IS_ERR(led->flash_cfg->flash_boost_reg)) {
rc = PTR_ERR(led->flash_cfg->flash_boost_reg);
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Regulator get failed(%d)\n", rc);
goto error_get_flash_reg;
}
@@ -3285,7 +3244,7 @@ static int qpnp_get_config_flash(struct qpnp_led_data *led,
FLASH_LED_0_CURR(led->base);
}
} else {
- dev_err(&led->spmi_dev->dev, "Unknown flash LED name given\n");
+ dev_err(&led->pdev->dev, "Unknown flash LED name given\n");
return -EINVAL;
}
@@ -3294,12 +3253,12 @@ static int qpnp_get_config_flash(struct qpnp_led_data *led,
NULL)) {
if (!led->flash_cfg->no_smbb_support) {
led->flash_cfg->torch_boost_reg =
- regulator_get(&led->spmi_dev->dev,
+ regulator_get(&led->pdev->dev,
"torch-boost");
if (IS_ERR(led->flash_cfg->torch_boost_reg)) {
rc = PTR_ERR(led->flash_cfg->
torch_boost_reg);
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Torch regulator get failed(%d)\n", rc);
goto error_get_torch_reg;
}
@@ -3401,7 +3360,7 @@ error_get_flash_reg:
}
static int qpnp_get_config_pwm(struct pwm_config_data *pwm_cfg,
- struct spmi_device *spmi_dev,
+ struct platform_device *pdev,
struct device_node *node)
{
struct property *prop;
@@ -3414,7 +3373,7 @@ static int qpnp_get_config_pwm(struct pwm_config_data *pwm_cfg,
if (IS_ERR(pwm_cfg->pwm_dev)) {
rc = PTR_ERR(pwm_cfg->pwm_dev);
- dev_err(&spmi_dev->dev, "Cannot get PWM device rc:(%d)\n", rc);
+ dev_err(&pdev->dev, "Cannot get PWM device rc:(%d)\n", rc);
pwm_cfg->pwm_dev = NULL;
return rc;
}
@@ -3432,11 +3391,10 @@ static int qpnp_get_config_pwm(struct pwm_config_data *pwm_cfg,
if (pwm_cfg->mode == LPG_MODE || pwm_cfg->use_blink) {
pwm_cfg->duty_cycles =
- devm_kzalloc(&spmi_dev->dev,
+ devm_kzalloc(&pdev->dev,
sizeof(struct pwm_duty_cycles), GFP_KERNEL);
if (!pwm_cfg->duty_cycles) {
- dev_err(&spmi_dev->dev,
- "Unable to allocate memory\n");
+ dev_err(&pdev->dev, "Unable to allocate memory\n");
rc = -ENOMEM;
goto bad_lpg_params;
}
@@ -3444,13 +3402,11 @@ static int qpnp_get_config_pwm(struct pwm_config_data *pwm_cfg,
prop = of_find_property(node, "qcom,duty-pcts",
&pwm_cfg->duty_cycles->num_duty_pcts);
if (!prop) {
- dev_err(&spmi_dev->dev, "Looking up property " \
- "node qcom,duty-pcts failed\n");
+ dev_err(&pdev->dev, "Looking up property node qcom,duty-pcts failed\n");
rc = -ENODEV;
goto bad_lpg_params;
} else if (!pwm_cfg->duty_cycles->num_duty_pcts) {
- dev_err(&spmi_dev->dev, "Invalid length of " \
- "duty pcts\n");
+ dev_err(&pdev->dev, "Invalid length of duty pcts\n");
rc = -EINVAL;
goto bad_lpg_params;
}
@@ -3458,7 +3414,7 @@ static int qpnp_get_config_pwm(struct pwm_config_data *pwm_cfg,
rc = of_property_read_string(node, "label", &led_label);
if (rc < 0) {
- dev_err(&spmi_dev->dev,
+ dev_err(&pdev->dev,
"Failure reading label, rc = %d\n", rc);
return rc;
}
@@ -3469,33 +3425,30 @@ static int qpnp_get_config_pwm(struct pwm_config_data *pwm_cfg,
lut_max_size = PWM_LUT_MAX_SIZE;
pwm_cfg->duty_cycles->duty_pcts =
- devm_kzalloc(&spmi_dev->dev,
+ devm_kzalloc(&pdev->dev,
sizeof(int) * lut_max_size,
GFP_KERNEL);
if (!pwm_cfg->duty_cycles->duty_pcts) {
- dev_err(&spmi_dev->dev,
- "Unable to allocate memory\n");
+ dev_err(&pdev->dev, "Unable to allocate memory\n");
rc = -ENOMEM;
goto bad_lpg_params;
}
pwm_cfg->old_duty_pcts =
- devm_kzalloc(&spmi_dev->dev,
+ devm_kzalloc(&pdev->dev,
sizeof(int) * lut_max_size,
GFP_KERNEL);
if (!pwm_cfg->old_duty_pcts) {
- dev_err(&spmi_dev->dev,
- "Unable to allocate memory\n");
+ dev_err(&pdev->dev, "Unable to allocate memory\n");
rc = -ENOMEM;
goto bad_lpg_params;
}
- temp_cfg = devm_kzalloc(&spmi_dev->dev,
+ temp_cfg = devm_kzalloc(&pdev->dev,
pwm_cfg->duty_cycles->num_duty_pcts *
sizeof(u8), GFP_KERNEL);
if (!temp_cfg) {
- dev_err(&spmi_dev->dev, "Failed to allocate " \
- "memory for duty pcts\n");
+ dev_err(&pdev->dev, "Failed to allocate memory for duty pcts\n");
rc = -ENOMEM;
goto bad_lpg_params;
}
@@ -3551,8 +3504,7 @@ static int qpnp_get_config_pwm(struct pwm_config_data *pwm_cfg,
bad_lpg_params:
pwm_cfg->use_blink = false;
if (pwm_cfg->mode == PWM_MODE) {
- dev_err(&spmi_dev->dev, "LPG parameters not set for" \
- " blink mode, defaulting to PWM mode\n");
+ dev_err(&pdev->dev, "LPG parameters not set for blink mode, defaulting to PWM mode\n");
return 0;
}
return rc;
@@ -3578,10 +3530,10 @@ static int qpnp_get_config_kpdbl(struct qpnp_led_data *led,
u8 led_mode;
const char *mode;
- led->kpdbl_cfg = devm_kzalloc(&led->spmi_dev->dev,
+ led->kpdbl_cfg = devm_kzalloc(&led->pdev->dev,
sizeof(struct kpdbl_config_data), GFP_KERNEL);
if (!led->kpdbl_cfg) {
- dev_err(&led->spmi_dev->dev, "Unable to allocate memory\n");
+ dev_err(&led->pdev->dev, "Unable to allocate memory\n");
return -ENOMEM;
}
@@ -3589,24 +3541,24 @@ static int qpnp_get_config_kpdbl(struct qpnp_led_data *led,
if (!rc) {
led_mode = qpnp_led_get_mode(mode);
if ((led_mode == MANUAL_MODE) || (led_mode == -EINVAL)) {
- dev_err(&led->spmi_dev->dev, "Selected mode not " \
- "supported for kpdbl.\n");
+ dev_err(&led->pdev->dev, "Selected mode not supported for kpdbl.\n");
return -EINVAL;
}
- led->kpdbl_cfg->pwm_cfg = devm_kzalloc(&led->spmi_dev->dev,
+ led->kpdbl_cfg->pwm_cfg = devm_kzalloc(&led->pdev->dev,
sizeof(struct pwm_config_data),
GFP_KERNEL);
if (!led->kpdbl_cfg->pwm_cfg) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Unable to allocate memory\n");
return -ENOMEM;
}
led->kpdbl_cfg->pwm_cfg->mode = led_mode;
led->kpdbl_cfg->pwm_cfg->default_mode = led_mode;
- } else
+ } else {
return rc;
+ }
- rc = qpnp_get_config_pwm(led->kpdbl_cfg->pwm_cfg, led->spmi_dev, node);
+ rc = qpnp_get_config_pwm(led->kpdbl_cfg->pwm_cfg, led->pdev, node);
if (rc < 0)
return rc;
@@ -3635,10 +3587,10 @@ static int qpnp_get_config_rgb(struct qpnp_led_data *led,
u8 led_mode;
const char *mode;
- led->rgb_cfg = devm_kzalloc(&led->spmi_dev->dev,
+ led->rgb_cfg = devm_kzalloc(&led->pdev->dev,
sizeof(struct rgb_config_data), GFP_KERNEL);
if (!led->rgb_cfg) {
- dev_err(&led->spmi_dev->dev, "Unable to allocate memory\n");
+ dev_err(&led->pdev->dev, "Unable to allocate memory\n");
return -ENOMEM;
}
@@ -3655,24 +3607,24 @@ static int qpnp_get_config_rgb(struct qpnp_led_data *led,
if (!rc) {
led_mode = qpnp_led_get_mode(mode);
if ((led_mode == MANUAL_MODE) || (led_mode == -EINVAL)) {
- dev_err(&led->spmi_dev->dev, "Selected mode not " \
- "supported for rgb.\n");
+ dev_err(&led->pdev->dev, "Selected mode not supported for rgb\n");
return -EINVAL;
}
- led->rgb_cfg->pwm_cfg = devm_kzalloc(&led->spmi_dev->dev,
+ led->rgb_cfg->pwm_cfg = devm_kzalloc(&led->pdev->dev,
sizeof(struct pwm_config_data),
GFP_KERNEL);
if (!led->rgb_cfg->pwm_cfg) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Unable to allocate memory\n");
return -ENOMEM;
}
led->rgb_cfg->pwm_cfg->mode = led_mode;
led->rgb_cfg->pwm_cfg->default_mode = led_mode;
- } else
+ } else {
return rc;
+ }
- rc = qpnp_get_config_pwm(led->rgb_cfg->pwm_cfg, led->spmi_dev, node);
+ rc = qpnp_get_config_pwm(led->rgb_cfg->pwm_cfg, led->pdev, node);
if (rc < 0)
return rc;
@@ -3687,20 +3639,20 @@ static int qpnp_get_config_mpp(struct qpnp_led_data *led,
u8 led_mode;
const char *mode;
- led->mpp_cfg = devm_kzalloc(&led->spmi_dev->dev,
+ led->mpp_cfg = devm_kzalloc(&led->pdev->dev,
sizeof(struct mpp_config_data), GFP_KERNEL);
if (!led->mpp_cfg) {
- dev_err(&led->spmi_dev->dev, "Unable to allocate memory\n");
+ dev_err(&led->pdev->dev, "Unable to allocate memory\n");
return -ENOMEM;
}
if (of_find_property(of_get_parent(node), "mpp-power-supply", NULL)) {
led->mpp_cfg->mpp_reg =
- regulator_get(&led->spmi_dev->dev,
+ regulator_get(&led->pdev->dev,
"mpp-power");
if (IS_ERR(led->mpp_cfg->mpp_reg)) {
rc = PTR_ERR(led->mpp_cfg->mpp_reg);
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"MPP regulator get failed(%d)\n", rc);
return rc;
}
@@ -3720,19 +3672,16 @@ static int qpnp_get_config_mpp(struct qpnp_led_data *led,
led->mpp_cfg->min_uV = val;
else
goto err_config_mpp;
-
} else {
rc = of_property_read_u32(of_get_parent(node),
"qcom,mpp-power-max-voltage", &val);
if (!rc)
- dev_warn(&led->spmi_dev->dev,
- "No regulator specified\n");
+ dev_warn(&led->pdev->dev, "No regulator specified\n");
rc = of_property_read_u32(of_get_parent(node),
"qcom,mpp-power-min-voltage", &val);
if (!rc)
- dev_warn(&led->spmi_dev->dev,
- "No regulator specified\n");
+ dev_warn(&led->pdev->dev, "No regulator specified\n");
}
led->mpp_cfg->current_setting = LED_MPP_CURRENT_MIN;
@@ -3782,26 +3731,26 @@ static int qpnp_get_config_mpp(struct qpnp_led_data *led,
if (led_mode == MANUAL_MODE)
return MANUAL_MODE;
else if (led_mode == -EINVAL) {
- dev_err(&led->spmi_dev->dev, "Selected mode not " \
- "supported for mpp.\n");
+ dev_err(&led->pdev->dev, "Selected mode not supported for mpp\n");
rc = -EINVAL;
goto err_config_mpp;
}
- led->mpp_cfg->pwm_cfg = devm_kzalloc(&led->spmi_dev->dev,
+ led->mpp_cfg->pwm_cfg = devm_kzalloc(&led->pdev->dev,
sizeof(struct pwm_config_data),
GFP_KERNEL);
if (!led->mpp_cfg->pwm_cfg) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Unable to allocate memory\n");
rc = -ENOMEM;
goto err_config_mpp;
}
led->mpp_cfg->pwm_cfg->mode = led_mode;
led->mpp_cfg->pwm_cfg->default_mode = led_mode;
- } else
+ } else {
return rc;
+ }
- rc = qpnp_get_config_pwm(led->mpp_cfg->pwm_cfg, led->spmi_dev, node);
+ rc = qpnp_get_config_pwm(led->mpp_cfg->pwm_cfg, led->pdev, node);
if (rc < 0)
goto err_config_mpp;
@@ -3819,10 +3768,11 @@ static int qpnp_get_config_gpio(struct qpnp_led_data *led,
int rc;
u32 val;
- led->gpio_cfg = devm_kzalloc(&led->spmi_dev->dev,
+ led->gpio_cfg = devm_kzalloc(&led->pdev->dev,
sizeof(struct gpio_config_data), GFP_KERNEL);
if (!led->gpio_cfg) {
- dev_err(&led->spmi_dev->dev, "Unable to allocate memory gpio struct\n");
+ dev_err(&led->pdev->dev,
+ "Unable to allocate memory gpio struct\n");
return -ENOMEM;
}
@@ -3853,16 +3803,16 @@ err_config_gpio:
return rc;
}
-static int qpnp_leds_probe(struct spmi_device *spmi)
+static int qpnp_leds_probe(struct platform_device *pdev)
{
struct qpnp_led_data *led, *led_array;
- struct resource *led_resource;
+ unsigned int base;
struct device_node *node, *temp;
int rc, i, num_leds = 0, parsed_leds = 0;
const char *led_label;
bool regulator_probe = false;
- node = spmi->dev.of_node;
+ node = pdev->dev.of_node;
if (node == NULL)
return -ENODEV;
@@ -3873,29 +3823,35 @@ static int qpnp_leds_probe(struct spmi_device *spmi)
if (!num_leds)
return -ECHILD;
- led_array = devm_kzalloc(&spmi->dev,
+ led_array = devm_kzalloc(&pdev->dev,
(sizeof(struct qpnp_led_data) * num_leds), GFP_KERNEL);
if (!led_array) {
- dev_err(&spmi->dev, "Unable to allocate memory\n");
+ dev_err(&pdev->dev, "Unable to allocate memory\n");
return -ENOMEM;
}
for_each_child_of_node(node, temp) {
led = &led_array[parsed_leds];
led->num_leds = num_leds;
- led->spmi_dev = spmi;
+ led->regmap = dev_get_regmap(pdev->dev.parent, NULL);
+ if (!led->regmap) {
+ dev_err(&pdev->dev, "Couldn't get parent's regmap\n");
+ return -EINVAL;
+ }
+ led->pdev = pdev;
- led_resource = spmi_get_resource(spmi, NULL, IORESOURCE_MEM, 0);
- if (!led_resource) {
- dev_err(&spmi->dev, "Unable to get LED base address\n");
- rc = -ENXIO;
+ rc = of_property_read_u32(pdev->dev.of_node, "reg", &base);
+ if (rc < 0) {
+ dev_err(&pdev->dev,
+ "Couldn't find reg in node = %s rc = %d\n",
+ pdev->dev.of_node->full_name, rc);
goto fail_id_check;
}
- led->base = led_resource->start;
+ led->base = base;
rc = of_property_read_string(temp, "label", &led_label);
if (rc < 0) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Failure reading label, rc = %d\n", rc);
goto fail_id_check;
}
@@ -3903,7 +3859,7 @@ static int qpnp_leds_probe(struct spmi_device *spmi)
rc = of_property_read_string(temp, "linux,name",
&led->cdev.name);
if (rc < 0) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Failure reading led name, rc = %d\n", rc);
goto fail_id_check;
}
@@ -3911,21 +3867,21 @@ static int qpnp_leds_probe(struct spmi_device *spmi)
rc = of_property_read_u32(temp, "qcom,max-current",
&led->max_current);
if (rc < 0) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Failure reading max_current, rc = %d\n", rc);
goto fail_id_check;
}
rc = of_property_read_u32(temp, "qcom,id", &led->id);
if (rc < 0) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Failure reading led id, rc = %d\n", rc);
goto fail_id_check;
}
rc = qpnp_get_common_configs(led, temp);
if (rc) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Failure reading common led configuration," \
" rc = %d\n", rc);
goto fail_id_check;
@@ -3937,7 +3893,7 @@ static int qpnp_leds_probe(struct spmi_device *spmi)
if (strncmp(led_label, "wled", sizeof("wled")) == 0) {
rc = qpnp_get_config_wled(led, temp);
if (rc < 0) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Unable to read wled config data\n");
goto fail_id_check;
}
@@ -3947,28 +3903,28 @@ static int qpnp_leds_probe(struct spmi_device *spmi)
regulator_probe = true;
rc = qpnp_get_config_flash(led, temp, &regulator_probe);
if (rc < 0) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Unable to read flash config data\n");
goto fail_id_check;
}
} else if (strncmp(led_label, "rgb", sizeof("rgb")) == 0) {
rc = qpnp_get_config_rgb(led, temp);
if (rc < 0) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Unable to read rgb config data\n");
goto fail_id_check;
}
} else if (strncmp(led_label, "mpp", sizeof("mpp")) == 0) {
rc = qpnp_get_config_mpp(led, temp);
if (rc < 0) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Unable to read mpp config data\n");
goto fail_id_check;
}
} else if (strcmp(led_label, "gpio") == 0) {
rc = qpnp_get_config_gpio(led, temp);
if (rc < 0) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Unable to read gpio config data\n");
goto fail_id_check;
}
@@ -3977,12 +3933,12 @@ static int qpnp_leds_probe(struct spmi_device *spmi)
is_kpdbl_master_turn_on = false;
rc = qpnp_get_config_kpdbl(led, temp);
if (rc < 0) {
- dev_err(&led->spmi_dev->dev,
+ dev_err(&led->pdev->dev,
"Unable to read kpdbl config data\n");
goto fail_id_check;
}
} else {
- dev_err(&led->spmi_dev->dev, "No LED matching label\n");
+ dev_err(&led->pdev->dev, "No LED matching label\n");
rc = -EINVAL;
goto fail_id_check;
}
@@ -4018,9 +3974,10 @@ static int qpnp_leds_probe(struct spmi_device *spmi)
if (rc < 0)
goto fail_id_check;
- rc = led_classdev_register(&spmi->dev, &led->cdev);
+ rc = led_classdev_register(&pdev->dev, &led->cdev);
if (rc) {
- dev_err(&spmi->dev, "unable to register led %d,rc=%d\n",
+ dev_err(&pdev->dev,
+ "unable to register led %d,rc=%d\n",
led->id, rc);
goto fail_id_check;
}
@@ -4120,7 +4077,7 @@ static int qpnp_leds_probe(struct spmi_device *spmi)
parsed_leds++;
}
- dev_set_drvdata(&spmi->dev, led_array);
+ dev_set_drvdata(&pdev->dev, led_array);
return 0;
fail_id_check:
@@ -4136,9 +4093,9 @@ fail_id_check:
return rc;
}
-static int qpnp_leds_remove(struct spmi_device *spmi)
+static int qpnp_leds_remove(struct platform_device *pdev)
{
- struct qpnp_led_data *led_array = dev_get_drvdata(&spmi->dev);
+ struct qpnp_led_data *led_array = dev_get_drvdata(&pdev->dev);
int i, parsed_leds = led_array->num_leds;
for (i = 0; i < parsed_leds; i++) {
@@ -4214,7 +4171,7 @@ static int qpnp_leds_remove(struct spmi_device *spmi)
kobj, &lpg_attr_group);
break;
default:
- dev_err(&led_array[i].spmi_dev->dev,
+ dev_err(&led_array->pdev->dev,
"Invalid LED(%d)\n",
led_array[i].id);
return -EINVAL;
@@ -4233,10 +4190,10 @@ static struct of_device_id spmi_match_table[] = {
#define spmi_match_table NULL
#endif
-static struct spmi_driver qpnp_leds_driver = {
+static struct platform_driver qpnp_leds_driver = {
.driver = {
- .name = "qcom,leds-qpnp",
- .of_match_table = spmi_match_table,
+ .name = "qcom,leds-qpnp",
+ .of_match_table = spmi_match_table,
},
.probe = qpnp_leds_probe,
.remove = qpnp_leds_remove,
@@ -4244,13 +4201,13 @@ static struct spmi_driver qpnp_leds_driver = {
static int __init qpnp_led_init(void)
{
- return spmi_driver_register(&qpnp_leds_driver);
+ return platform_driver_register(&qpnp_leds_driver);
}
module_init(qpnp_led_init);
static void __exit qpnp_led_exit(void)
{
- spmi_driver_unregister(&qpnp_leds_driver);
+ platform_driver_unregister(&qpnp_leds_driver);
}
module_exit(qpnp_led_exit);
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 4d92df6ef9fe..38c36532e036 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -708,7 +708,7 @@ config MFD_QCOM_RPM
config MFD_SPMI_PMIC
tristate "Qualcomm SPMI PMICs"
- depends on ARCH_QCOM || COMPILE_TEST
+ depends on ARCH_QCOM || COMPILE_TEST || ARCH_MSM
depends on OF
depends on SPMI
select REGMAP_SPMI
diff --git a/drivers/platform/msm/Kconfig b/drivers/platform/msm/Kconfig
index 2f394f3fdcee..3d75cb1882d1 100644
--- a/drivers/platform/msm/Kconfig
+++ b/drivers/platform/msm/Kconfig
@@ -3,7 +3,7 @@ menu "Qualcomm MSM specific device drivers"
config QPNP_POWER_ON
tristate "QPNP PMIC POWER-ON Driver"
- depends on OF_SPMI && (SPMI || MSM_SPMI) && MSM_QPNP_INT && INPUT
+ depends on SPMI && INPUT
help
This driver supports the power-on functionality on Qualcomm
PNP PMIC. It currently supports reporting the change in status of
@@ -11,7 +11,7 @@ config QPNP_POWER_ON
config QPNP_REVID
tristate "QPNP Revision ID Peripheral"
- depends on SPMI || MSM_SPMI
+ depends on SPMI
help
Say 'y' here to include support for the Qualcomm QPNP REVID
peripheral. REVID prints out the PMIC type and revision numbers
@@ -20,7 +20,7 @@ config QPNP_REVID
config QPNP_COINCELL
tristate "Qualcomm QPNP coincell charger support"
- depends on (SPMI || MSM_SPMI) && OF_SPMI
+ depends on SPMI
help
This driver supports the QPNP coincell peripheral found inside of
Qualcomm QPNP PMIC devices. The coincell charger provides a means to
@@ -30,7 +30,6 @@ config QPNP_COINCELL
config QPNP_HAPTIC
tristate "Haptic support for QPNP PMIC"
- depends on OF_SPMI
help
This option enables device driver support for the Haptic
on the Qualcomm Technologies' QPNP PMICs. It uses the android
diff --git a/drivers/platform/msm/qpnp-coincell.c b/drivers/platform/msm/qpnp-coincell.c
index ec060bbc4171..6aaa53526868 100644
--- a/drivers/platform/msm/qpnp-coincell.c
+++ b/drivers/platform/msm/qpnp-coincell.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -13,9 +13,11 @@
#define pr_fmt(fmt) "%s: " fmt, __func__
#include <linux/kernel.h>
+#include <linux/regmap.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/spmi.h>
+#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
@@ -23,7 +25,8 @@
#define QPNP_COINCELL_DRIVER_NAME "qcom,qpnp-coincell"
struct qpnp_coincell {
- struct spmi_device *spmi_dev;
+ struct platform_device *pdev;
+ struct regmap *regmap;
u16 base_addr;
};
@@ -56,10 +59,11 @@ static int qpnp_coincell_set_resistance(struct qpnp_coincell *chip, int rset)
}
reg = i;
- rc = spmi_ext_register_writel(chip->spmi_dev->ctrl, chip->spmi_dev->sid,
- chip->base_addr + QPNP_COINCELL_REG_RSET, &reg, 1);
+ rc = regmap_write(chip->regmap,
+ chip->base_addr + QPNP_COINCELL_REG_RSET, reg);
if (rc)
- dev_err(&chip->spmi_dev->dev, "%s: could not write to RSET register, rc=%d\n",
+ dev_err(&chip->pdev->dev,
+ "%s: could not write to RSET register, rc=%d\n",
__func__, rc);
return rc;
@@ -80,10 +84,11 @@ static int qpnp_coincell_set_voltage(struct qpnp_coincell *chip, int vset)
}
reg = i;
- rc = spmi_ext_register_writel(chip->spmi_dev->ctrl, chip->spmi_dev->sid,
- chip->base_addr + QPNP_COINCELL_REG_VSET, &reg, 1);
+ rc = regmap_write(chip->regmap,
+ chip->base_addr + QPNP_COINCELL_REG_VSET, reg);
if (rc)
- dev_err(&chip->spmi_dev->dev, "%s: could not write to VSET register, rc=%d\n",
+ dev_err(&chip->pdev->dev,
+ "%s: could not write to VSET register, rc=%d\n",
__func__, rc);
return rc;
@@ -95,10 +100,11 @@ static int qpnp_coincell_set_charge(struct qpnp_coincell *chip, bool enabled)
u8 reg;
reg = enabled ? QPNP_COINCELL_ENABLE : QPNP_COINCELL_DISABLE;
- rc = spmi_ext_register_writel(chip->spmi_dev->ctrl, chip->spmi_dev->sid,
- chip->base_addr + QPNP_COINCELL_REG_ENABLE, &reg, 1);
+ rc = regmap_write(chip->regmap,
+ chip->base_addr + QPNP_COINCELL_REG_ENABLE, reg);
if (rc)
- dev_err(&chip->spmi_dev->dev, "%s: could not write to ENABLE register, rc=%d\n",
+ dev_err(&chip->pdev->dev,
+ "%s: could not write to ENABLE register, rc=%d\n",
__func__, rc);
return rc;
@@ -110,17 +116,20 @@ static void qpnp_coincell_charger_show_state(struct qpnp_coincell *chip)
bool enabled;
u8 reg[QPNP_COINCELL_REG_ENABLE - QPNP_COINCELL_REG_RSET + 1];
- rc = spmi_ext_register_readl(chip->spmi_dev->ctrl, chip->spmi_dev->sid,
- chip->base_addr + QPNP_COINCELL_REG_RSET, reg, ARRAY_SIZE(reg));
+ rc = regmap_bulk_read(chip->regmap,
+ chip->base_addr + QPNP_COINCELL_REG_RSET, reg,
+ ARRAY_SIZE(reg));
if (rc) {
- dev_err(&chip->spmi_dev->dev, "%s: could not read RSET register, rc=%d\n",
+ dev_err(&chip->pdev->dev,
+ "%s: could not read RSET register, rc=%d\n",
__func__, rc);
return;
}
temp = reg[QPNP_COINCELL_REG_RSET - QPNP_COINCELL_REG_RSET];
if (temp >= ARRAY_SIZE(qpnp_rset_map)) {
- dev_err(&chip->spmi_dev->dev, "unknown RSET=0x%02X register value\n",
+ dev_err(&chip->pdev->dev,
+ "unknown RSET=0x%02X register value\n",
temp);
return;
}
@@ -128,7 +137,8 @@ static void qpnp_coincell_charger_show_state(struct qpnp_coincell *chip)
temp = reg[QPNP_COINCELL_REG_VSET - QPNP_COINCELL_REG_RSET];
if (temp >= ARRAY_SIZE(qpnp_vset_map)) {
- dev_err(&chip->spmi_dev->dev, "unknown VSET=0x%02X register value\n",
+ dev_err(&chip->pdev->dev,
+ "unknown VSET=0x%02X register value\n",
temp);
return;
}
@@ -146,16 +156,19 @@ static int qpnp_coincell_check_type(struct qpnp_coincell *chip)
int rc;
u8 type[2];
- rc = spmi_ext_register_readl(chip->spmi_dev->ctrl, chip->spmi_dev->sid,
- chip->base_addr + QPNP_COINCELL_REG_TYPE, type, 2);
+ rc = regmap_bulk_read(chip->regmap,
+ chip->base_addr + QPNP_COINCELL_REG_TYPE, type,
+ 2);
if (rc) {
- dev_err(&chip->spmi_dev->dev, "%s: could not read type register, rc=%d\n",
+ dev_err(&chip->pdev->dev,
+ "%s: could not read type register, rc=%d\n",
__func__, rc);
return rc;
}
if (type[0] != QPNP_COINCELL_TYPE || type[1] != QPNP_COINCELL_SUBTYPE) {
- dev_err(&chip->spmi_dev->dev, "%s: invalid type=0x%02X or subtype=0x%02X register value\n",
+ dev_err(&chip->pdev->dev,
+ "%s: invalid type=0x%02X or subtype=0x%02X register value\n",
__func__, type[0], type[1]);
return -ENODEV;
}
@@ -163,34 +176,38 @@ static int qpnp_coincell_check_type(struct qpnp_coincell *chip)
return rc;
}
-static int qpnp_coincell_probe(struct spmi_device *spmi)
+static int qpnp_coincell_probe(struct platform_device *pdev)
{
- struct device_node *node = spmi->dev.of_node;
+ struct device_node *node = pdev->dev.of_node;
struct qpnp_coincell *chip;
- struct resource *res;
+ unsigned int base;
u32 temp;
int rc = 0;
if (!node) {
- dev_err(&spmi->dev, "%s: device node missing\n", __func__);
+ dev_err(&pdev->dev, "%s: device node missing\n", __func__);
return -ENODEV;
}
- chip = devm_kzalloc(&spmi->dev, sizeof(*chip), GFP_KERNEL);
- if (!chip) {
- dev_err(&spmi->dev, "%s: cannot allocate qpnp_coincell\n",
- __func__);
+ chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
+ if (!chip)
return -ENOMEM;
- }
- chip->spmi_dev = spmi;
- res = spmi_get_resource(spmi, NULL, IORESOURCE_MEM, 0);
- if (!res) {
- dev_err(&spmi->dev, "%s: node is missing base address\n",
- __func__);
+ chip->regmap = dev_get_regmap(pdev->dev.parent, NULL);
+ if (!chip->regmap) {
+ dev_err(&pdev->dev, "Couldn't get parent's regmap\n");
return -EINVAL;
}
- chip->base_addr = res->start;
+ chip->pdev = pdev;
+
+ rc = of_property_read_u32(pdev->dev.of_node, "reg", &base);
+ if (rc < 0) {
+ dev_err(&pdev->dev,
+ "Couldn't find reg in node = %s rc = %d\n",
+ pdev->dev.of_node->full_name, rc);
+ return rc;
+ }
+ chip->base_addr = base;
rc = qpnp_coincell_check_type(chip);
if (rc)
@@ -222,7 +239,7 @@ static int qpnp_coincell_probe(struct spmi_device *spmi)
return 0;
}
-static int qpnp_coincell_remove(struct spmi_device *spmi)
+static int qpnp_coincell_remove(struct platform_device *pdev)
{
return 0;
}
@@ -232,13 +249,13 @@ static struct of_device_id qpnp_coincell_match_table[] = {
{}
};
-static const struct spmi_device_id qpnp_coincell_id[] = {
+static const struct platform_device_id qpnp_coincell_id[] = {
{ QPNP_COINCELL_DRIVER_NAME, 0 },
{}
};
MODULE_DEVICE_TABLE(spmi, qpnp_coincell_id);
-static struct spmi_driver qpnp_coincell_driver = {
+static struct platform_driver qpnp_coincell_driver = {
.driver = {
.name = QPNP_COINCELL_DRIVER_NAME,
.of_match_table = qpnp_coincell_match_table,
@@ -251,12 +268,12 @@ static struct spmi_driver qpnp_coincell_driver = {
static int __init qpnp_coincell_init(void)
{
- return spmi_driver_register(&qpnp_coincell_driver);
+ return platform_driver_register(&qpnp_coincell_driver);
}
static void __exit qpnp_coincell_exit(void)
{
- spmi_driver_unregister(&qpnp_coincell_driver);
+ platform_driver_unregister(&qpnp_coincell_driver);
}
MODULE_DESCRIPTION("QPNP PMIC coincell charger driver");
diff --git a/drivers/platform/msm/qpnp-haptic.c b/drivers/platform/msm/qpnp-haptic.c
index 45be1b11a2c2..54638c5a883c 100644
--- a/drivers/platform/msm/qpnp-haptic.c
+++ b/drivers/platform/msm/qpnp-haptic.c
@@ -13,11 +13,13 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
+#include <linux/regmap.h>
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/hrtimer.h>
#include <linux/of_device.h>
#include <linux/spmi.h>
+#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
#include <linux/interrupt.h>
#include <linux/qpnp/pwm.h>
@@ -280,56 +282,57 @@ struct qpnp_pwm_info {
* @ misc_trim_error_rc19p2_clk_reg_present - if MISC Trim Error reg is present
*/
struct qpnp_hap {
- struct spmi_device *spmi;
- struct regulator *vcc_pon;
- struct hrtimer hap_timer;
- struct hrtimer auto_res_err_poll_timer;
- struct timed_output_dev timed_dev;
- struct work_struct work;
- struct work_struct auto_res_err_work;
- struct delayed_work sc_work;
- struct hrtimer hap_test_timer;
- struct work_struct test_work;
- struct qpnp_pwm_info pwm_info;
- struct mutex lock;
- struct mutex wf_lock;
- struct completion completion;
- enum qpnp_hap_mode play_mode;
- enum qpnp_hap_auto_res_mode auto_res_mode;
- enum qpnp_hap_high_z lra_high_z;
- u32 timeout_ms;
- u32 vmax_mv;
- u32 ilim_ma;
- u32 sc_deb_cycles;
- u32 int_pwm_freq_khz;
- u32 wave_play_rate_us;
- u32 ext_pwm_freq_khz;
- u32 wave_rep_cnt;
- u32 wave_s_rep_cnt;
- u32 play_irq;
- u32 sc_irq;
- u16 base;
- u8 act_type;
- u8 wave_shape;
+ struct platform_device *pdev;
+ struct regmap *regmap;
+ struct regulator *vcc_pon;
+ struct hrtimer hap_timer;
+ struct hrtimer auto_res_err_poll_timer;
+ struct timed_output_dev timed_dev;
+ struct work_struct work;
+ struct work_struct auto_res_err_work;
+ struct delayed_work sc_work;
+ struct hrtimer hap_test_timer;
+ struct work_struct test_work;
+ struct qpnp_pwm_info pwm_info;
+ struct mutex lock;
+ struct mutex wf_lock;
+ struct completion completion;
+ enum qpnp_hap_mode play_mode;
+ enum qpnp_hap_auto_res_mode auto_res_mode;
+ enum qpnp_hap_high_z lra_high_z;
+ u32 timeout_ms;
+ u32 vmax_mv;
+ u32 ilim_ma;
+ u32 sc_deb_cycles;
+ u32 int_pwm_freq_khz;
+ u32 wave_play_rate_us;
+ u32 ext_pwm_freq_khz;
+ u32 wave_rep_cnt;
+ u32 wave_s_rep_cnt;
+ u32 play_irq;
+ u32 sc_irq;
+ u16 base;
+ u8 act_type;
+ u8 wave_shape;
u8 wave_samp[QPNP_HAP_WAV_SAMP_LEN];
u8 shadow_wave_samp[QPNP_HAP_WAV_SAMP_LEN];
u8 brake_pat[QPNP_HAP_BRAKE_PAT_LEN];
- u8 reg_en_ctl;
- u8 reg_play;
- u8 lra_res_cal_period;
- u8 sc_duration;
- u8 ext_pwm_dtest_line;
- bool state;
- bool use_play_irq;
- bool use_sc_irq;
- bool manage_pon_supply;
- bool wf_update;
- bool pwm_cfg_state;
- bool buffer_cfg_state;
- bool en_brake;
- bool sup_brake_pat;
- bool correct_lra_drive_freq;
- bool misc_trim_error_rc19p2_clk_reg_present;
+ u8 reg_en_ctl;
+ u8 reg_play;
+ u8 lra_res_cal_period;
+ u8 sc_duration;
+ u8 ext_pwm_dtest_line;
+ bool state;
+ bool use_play_irq;
+ bool use_sc_irq;
+ bool manage_pon_supply;
+ bool wf_update;
+ bool pwm_cfg_state;
+ bool buffer_cfg_state;
+ bool en_brake;
+ bool sup_brake_pat;
+ bool correct_lra_drive_freq;
+ bool misc_trim_error_rc19p2_clk_reg_present;
};
static struct qpnp_hap *ghap;
@@ -338,13 +341,13 @@ static struct qpnp_hap *ghap;
static int qpnp_hap_read_reg(struct qpnp_hap *hap, u8 *data, u16 addr)
{
int rc;
+ uint val;
- rc = spmi_ext_register_readl(hap->spmi->ctrl, hap->spmi->sid,
- addr, data, 1);
+ rc = regmap_read(hap->regmap, addr, &val);
if (rc < 0)
- dev_err(&hap->spmi->dev,
+ dev_err(&hap->pdev->dev,
"Error reading address: %X - ret %X\n", addr, rc);
-
+ *data = (u8)val;
return rc;
}
@@ -353,13 +356,12 @@ static int qpnp_hap_write_reg(struct qpnp_hap *hap, u8 *data, u16 addr)
{
int rc;
- rc = spmi_ext_register_writel(hap->spmi->ctrl, hap->spmi->sid,
- addr, data, 1);
+ rc = regmap_write(hap->regmap, addr, *data);
if (rc < 0)
- dev_err(&hap->spmi->dev,
+ dev_err(&hap->pdev->dev,
"Error writing address: %X - ret %X\n", addr, rc);
- dev_dbg(&hap->spmi->dev, "write: HAP_0x%x = 0x%x\n", addr, *data);
+ dev_dbg(&hap->pdev->dev, "write: HAP_0x%x = 0x%x\n", addr, *data);
return rc;
}
@@ -410,7 +412,7 @@ static int qpnp_hap_mod_enable(struct qpnp_hap *hap, int on)
rc = qpnp_hap_read_reg(hap, &val,
QPNP_HAP_STATUS(hap->base));
- dev_dbg(&hap->spmi->dev, "HAP_STATUS=0x%x\n", val);
+ dev_dbg(&hap->pdev->dev, "HAP_STATUS=0x%x\n", val);
/* wait for QPNP_HAP_CYCLS cycles of play rate */
if (val & QPNP_HAP_STATUS_BUSY) {
@@ -423,7 +425,7 @@ static int qpnp_hap_mod_enable(struct qpnp_hap *hap, int on)
}
if (i >= QPNP_HAP_MAX_RETRIES)
- dev_dbg(&hap->spmi->dev,
+ dev_dbg(&hap->pdev->dev,
"Haptics Busy. Force disable\n");
val &= ~QPNP_HAP_EN;
@@ -517,7 +519,7 @@ static irqreturn_t qpnp_hap_sc_irq(int irq, void *_hap)
u8 disable_haptics = 0x00;
u8 val;
- dev_dbg(&hap->spmi->dev, "Short circuit detected\n");
+ dev_dbg(&hap->pdev->dev, "Short circuit detected\n");
if (hap->sc_duration < SC_MAX_DURATION) {
qpnp_hap_read_reg(hap, &val, QPNP_HAP_STATUS(hap->base));
@@ -532,7 +534,7 @@ static irqreturn_t qpnp_hap_sc_irq(int irq, void *_hap)
*/
rc = qpnp_hap_write_reg(hap, &disable_haptics,
QPNP_HAP_EN_CTL_REG(hap->base));
- dev_err(&hap->spmi->dev,
+ dev_err(&hap->pdev->dev,
"Haptics disabled permanently due to short circuit\n");
}
@@ -582,12 +584,12 @@ static int qpnp_hap_buffer_config(struct qpnp_hap *hap)
/* setup play irq */
if (hap->use_play_irq) {
- rc = devm_request_threaded_irq(&hap->spmi->dev, hap->play_irq,
+ rc = devm_request_threaded_irq(&hap->pdev->dev, hap->play_irq,
NULL, qpnp_hap_play_irq,
QPNP_IRQ_FLAGS,
"qpnp_play_irq", hap);
if (rc < 0) {
- dev_err(&hap->spmi->dev,
+ dev_err(&hap->pdev->dev,
"Unable to request play(%d) IRQ(err:%d)\n",
hap->play_irq, rc);
return rc;
@@ -638,7 +640,7 @@ static int qpnp_hap_pwm_config(struct qpnp_hap *hap)
return rc;
if (!hap->ext_pwm_dtest_line ||
hap->ext_pwm_dtest_line > PWM_MAX_DTEST_LINES) {
- dev_err(&hap->spmi->dev, "invalid dtest line\n");
+ dev_err(&hap->pdev->dev, "invalid dtest line\n");
return -EINVAL;
}
@@ -661,7 +663,7 @@ static int qpnp_hap_pwm_config(struct qpnp_hap *hap)
hap->pwm_info.duty_us * NSEC_PER_USEC,
hap->pwm_info.period_us * NSEC_PER_USEC);
if (rc < 0) {
- dev_err(&hap->spmi->dev, "hap pwm config failed\n");
+ dev_err(&hap->pdev->dev, "hap pwm config failed\n");
pwm_free(hap->pwm_info.pwm_dev);
return -ENODEV;
}
@@ -742,48 +744,47 @@ static int qpnp_hap_sc_deb_config(struct qpnp_hap *hap)
/* DT parsing api for buffer mode */
static int qpnp_hap_parse_buffer_dt(struct qpnp_hap *hap)
{
- struct spmi_device *spmi = hap->spmi;
+ struct platform_device *pdev = hap->pdev;
struct property *prop;
u32 temp;
int rc, i;
hap->wave_rep_cnt = QPNP_HAP_WAV_REP_MIN;
- rc = of_property_read_u32(spmi->dev.of_node,
+ rc = of_property_read_u32(pdev->dev.of_node,
"qcom,wave-rep-cnt", &temp);
if (!rc) {
hap->wave_rep_cnt = temp;
} else if (rc != -EINVAL) {
- dev_err(&spmi->dev, "Unable to read rep cnt\n");
+ dev_err(&pdev->dev, "Unable to read rep cnt\n");
return rc;
}
hap->wave_s_rep_cnt = QPNP_HAP_WAV_S_REP_MIN;
- rc = of_property_read_u32(spmi->dev.of_node,
+ rc = of_property_read_u32(pdev->dev.of_node,
"qcom,wave-samp-rep-cnt", &temp);
if (!rc) {
hap->wave_s_rep_cnt = temp;
} else if (rc != -EINVAL) {
- dev_err(&spmi->dev, "Unable to read samp rep cnt\n");
+ dev_err(&pdev->dev, "Unable to read samp rep cnt\n");
return rc;
}
- prop = of_find_property(spmi->dev.of_node,
+ prop = of_find_property(pdev->dev.of_node,
"qcom,wave-samples", &temp);
if (!prop || temp != QPNP_HAP_WAV_SAMP_LEN) {
- dev_err(&spmi->dev, "Invalid wave samples, use default");
+ dev_err(&pdev->dev, "Invalid wave samples, use default");
for (i = 0; i < QPNP_HAP_WAV_SAMP_LEN; i++)
hap->wave_samp[i] = QPNP_HAP_WAV_SAMP_MAX;
} else {
memcpy(hap->wave_samp, prop->value, QPNP_HAP_WAV_SAMP_LEN);
}
- hap->use_play_irq = of_property_read_bool(spmi->dev.of_node,
+ hap->use_play_irq = of_property_read_bool(pdev->dev.of_node,
"qcom,use-play-irq");
if (hap->use_play_irq) {
- hap->play_irq = spmi_get_irq_byname(hap->spmi,
- NULL, "play-irq");
+ hap->play_irq = platform_get_irq_byname(hap->pdev, "play-irq");
if (hap->play_irq < 0) {
- dev_err(&spmi->dev, "Unable to get play irq\n");
+ dev_err(&pdev->dev, "Unable to get play irq\n");
return hap->play_irq;
}
}
@@ -794,51 +795,49 @@ static int qpnp_hap_parse_buffer_dt(struct qpnp_hap *hap)
/* DT parsing api for PWM mode */
static int qpnp_hap_parse_pwm_dt(struct qpnp_hap *hap)
{
- struct spmi_device *spmi = hap->spmi;
+ struct platform_device *pdev = hap->pdev;
u32 temp;
int rc;
hap->ext_pwm_freq_khz = QPNP_HAP_EXT_PWM_FREQ_25_KHZ;
- rc = of_property_read_u32(spmi->dev.of_node,
+ rc = of_property_read_u32(pdev->dev.of_node,
"qcom,ext-pwm-freq-khz", &temp);
if (!rc) {
hap->ext_pwm_freq_khz = temp;
} else if (rc != -EINVAL) {
- dev_err(&spmi->dev, "Unable to read ext pwm freq\n");
+ dev_err(&pdev->dev, "Unable to read ext pwm freq\n");
return rc;
}
- rc = of_property_read_u32(spmi->dev.of_node,
+ rc = of_property_read_u32(pdev->dev.of_node,
"qcom,pwm-channel", &temp);
if (!rc)
hap->pwm_info.pwm_channel = temp;
else
return rc;
- hap->pwm_info.pwm_dev = of_pwm_get(spmi->dev.of_node, NULL);
+ hap->pwm_info.pwm_dev = of_pwm_get(pdev->dev.of_node, NULL);
if (IS_ERR(hap->pwm_info.pwm_dev)) {
rc = PTR_ERR(hap->pwm_info.pwm_dev);
- dev_err(&spmi->dev, "Cannot get PWM device rc:(%d)\n", rc);
+ dev_err(&pdev->dev, "Cannot get PWM device rc:(%d)\n", rc);
hap->pwm_info.pwm_dev = NULL;
return rc;
}
- rc = of_property_read_u32(spmi->dev.of_node,
- "qcom,period-us", &temp);
+ rc = of_property_read_u32(pdev->dev.of_node, "qcom,period-us", &temp);
if (!rc)
hap->pwm_info.period_us = temp;
else
return rc;
- rc = of_property_read_u32(spmi->dev.of_node,
- "qcom,duty-us", &temp);
+ rc = of_property_read_u32(pdev->dev.of_node, "qcom,duty-us", &temp);
if (!rc)
hap->pwm_info.duty_us = temp;
else
return rc;
- rc = of_property_read_u32(spmi->dev.of_node,
+ rc = of_property_read_u32(pdev->dev.of_node,
"qcom,ext-pwm-dtest-line", &temp);
if (!rc)
hap->ext_pwm_dtest_line = temp;
@@ -1587,7 +1586,7 @@ int qpnp_hap_play_byte(u8 data, bool on)
}
if (hap->play_mode != QPNP_HAP_PWM) {
- dev_err(&hap->spmi->dev, "only PWM mode is supported\n");
+ dev_err(&hap->pdev->dev, "only PWM mode is supported\n");
return -EINVAL;
}
@@ -1624,7 +1623,8 @@ int qpnp_hap_play_byte(u8 data, bool on)
if (rc)
return rc;
- dev_dbg(&hap->spmi->dev, "data=0x%x duty_per=%d\n", data, duty_percent);
+ dev_dbg(&hap->pdev->dev, "data=0x%x duty_per=%d\n", data,
+ duty_percent);
rc = qpnp_hap_set(hap, true);
@@ -1723,8 +1723,9 @@ static SIMPLE_DEV_PM_OPS(qpnp_haptic_pm_ops, qpnp_haptic_suspend, NULL);
/* Configuration api for haptics registers */
static int qpnp_hap_config(struct qpnp_hap *hap)
{
- u8 reg = 0, error_code = 0, unlock_val, error_value;
+ u8 reg = 0, unlock_val, error_value;
int rc, i, temp;
+ uint error_code = 0;
/* Configure the ACTUATOR TYPE register */
rc = qpnp_hap_read_reg(hap, &reg, QPNP_HAP_ACT_TYPE_REG(hap->base));
@@ -1862,15 +1863,13 @@ static int qpnp_hap_config(struct qpnp_hap *hap)
if ((hap->act_type == QPNP_HAP_LRA) && hap->correct_lra_drive_freq
&& hap->misc_trim_error_rc19p2_clk_reg_present) {
unlock_val = MISC_SEC_UNLOCK;
- rc = spmi_ext_register_writel(hap->spmi->ctrl,
- PMI8950_MISC_SID, MISC_SEC_ACCESS,
- &unlock_val, 1);
+ rc = regmap_write(hap->regmap, MISC_SEC_ACCESS, unlock_val);
if (rc)
- dev_err(&hap->spmi->dev,
+ dev_err(&hap->pdev->dev,
"Unable to do SEC_ACCESS rc:%d\n", rc);
- spmi_ext_register_readl(hap->spmi->ctrl, PMI8950_MISC_SID,
- MISC_TRIM_ERROR_RC19P2_CLK, &error_code, 1);
+ regmap_read(hap->regmap, MISC_TRIM_ERROR_RC19P2_CLK,
+ &error_code);
error_value = (error_code & 0x0F) * 7;
@@ -1947,12 +1946,12 @@ static int qpnp_hap_config(struct qpnp_hap *hap)
/* setup short circuit irq */
if (hap->use_sc_irq) {
- rc = devm_request_threaded_irq(&hap->spmi->dev, hap->sc_irq,
+ rc = devm_request_threaded_irq(&hap->pdev->dev, hap->sc_irq,
NULL, qpnp_hap_sc_irq,
QPNP_IRQ_FLAGS,
"qpnp_sc_irq", hap);
if (rc < 0) {
- dev_err(&hap->spmi->dev,
+ dev_err(&hap->pdev->dev,
"Unable to request sc(%d) IRQ(err:%d)\n",
hap->sc_irq, rc);
return rc;
@@ -1967,24 +1966,24 @@ static int qpnp_hap_config(struct qpnp_hap *hap)
/* DT parsing for haptics parameters */
static int qpnp_hap_parse_dt(struct qpnp_hap *hap)
{
- struct spmi_device *spmi = hap->spmi;
+ struct platform_device *pdev = hap->pdev;
struct property *prop;
const char *temp_str;
u32 temp;
int rc;
hap->timeout_ms = QPNP_HAP_TIMEOUT_MS_MAX;
- rc = of_property_read_u32(spmi->dev.of_node,
+ rc = of_property_read_u32(pdev->dev.of_node,
"qcom,timeout-ms", &temp);
if (!rc) {
hap->timeout_ms = temp;
} else if (rc != -EINVAL) {
- dev_err(&spmi->dev, "Unable to read timeout\n");
+ dev_err(&pdev->dev, "Unable to read timeout\n");
return rc;
}
hap->act_type = QPNP_HAP_LRA;
- rc = of_property_read_string(spmi->dev.of_node,
+ rc = of_property_read_string(pdev->dev.of_node,
"qcom,actuator-type", &temp_str);
if (!rc) {
if (strcmp(temp_str, "erm") == 0)
@@ -1992,17 +1991,17 @@ static int qpnp_hap_parse_dt(struct qpnp_hap *hap)
else if (strcmp(temp_str, "lra") == 0)
hap->act_type = QPNP_HAP_LRA;
else {
- dev_err(&spmi->dev, "Invalid actuator type\n");
+ dev_err(&pdev->dev, "Invalid actuator type\n");
return -EINVAL;
}
} else if (rc != -EINVAL) {
- dev_err(&spmi->dev, "Unable to read actuator type\n");
+ dev_err(&pdev->dev, "Unable to read actuator type\n");
return rc;
}
if (hap->act_type == QPNP_HAP_LRA) {
hap->auto_res_mode = QPNP_HAP_AUTO_RES_ZXD_EOP;
- rc = of_property_read_string(spmi->dev.of_node,
+ rc = of_property_read_string(pdev->dev.of_node,
"qcom,lra-auto-res-mode", &temp_str);
if (!rc) {
if (strcmp(temp_str, "none") == 0)
@@ -2016,12 +2015,12 @@ static int qpnp_hap_parse_dt(struct qpnp_hap *hap)
else
hap->auto_res_mode = QPNP_HAP_AUTO_RES_ZXD_EOP;
} else if (rc != -EINVAL) {
- dev_err(&spmi->dev, "Unable to read auto res mode\n");
+ dev_err(&pdev->dev, "Unable to read auto res mode\n");
return rc;
}
hap->lra_high_z = QPNP_HAP_LRA_HIGH_Z_OPT3;
- rc = of_property_read_string(spmi->dev.of_node,
+ rc = of_property_read_string(pdev->dev.of_node,
"qcom,lra-high-z", &temp_str);
if (!rc) {
if (strcmp(temp_str, "none") == 0)
@@ -2033,30 +2032,30 @@ static int qpnp_hap_parse_dt(struct qpnp_hap *hap)
else
hap->lra_high_z = QPNP_HAP_LRA_HIGH_Z_OPT3;
} else if (rc != -EINVAL) {
- dev_err(&spmi->dev, "Unable to read LRA high-z\n");
+ dev_err(&pdev->dev, "Unable to read LRA high-z\n");
return rc;
}
hap->lra_res_cal_period = QPNP_HAP_RES_CAL_PERIOD_MAX;
- rc = of_property_read_u32(spmi->dev.of_node,
+ rc = of_property_read_u32(pdev->dev.of_node,
"qcom,lra-res-cal-period", &temp);
if (!rc) {
hap->lra_res_cal_period = temp;
} else if (rc != -EINVAL) {
- dev_err(&spmi->dev, "Unable to read cal period\n");
+ dev_err(&pdev->dev, "Unable to read cal period\n");
return rc;
}
hap->correct_lra_drive_freq =
- of_property_read_bool(spmi->dev.of_node,
+ of_property_read_bool(pdev->dev.of_node,
"qcom,correct-lra-drive-freq");
hap->misc_trim_error_rc19p2_clk_reg_present =
- of_property_read_bool(spmi->dev.of_node,
+ of_property_read_bool(pdev->dev.of_node,
"qcom,misc-trim-error-rc19p2-clk-reg-present");
}
- rc = of_property_read_string(spmi->dev.of_node,
+ rc = of_property_read_string(pdev->dev.of_node,
"qcom,play-mode", &temp_str);
if (!rc) {
if (strcmp(temp_str, "direct") == 0)
@@ -2068,56 +2067,54 @@ static int qpnp_hap_parse_dt(struct qpnp_hap *hap)
else if (strcmp(temp_str, "audio") == 0)
hap->play_mode = QPNP_HAP_AUDIO;
else {
- dev_err(&spmi->dev, "Invalid play mode\n");
+ dev_err(&pdev->dev, "Invalid play mode\n");
return -EINVAL;
}
} else {
- dev_err(&spmi->dev, "Unable to read play mode\n");
+ dev_err(&pdev->dev, "Unable to read play mode\n");
return rc;
}
hap->vmax_mv = QPNP_HAP_VMAX_MAX_MV;
- rc = of_property_read_u32(spmi->dev.of_node,
- "qcom,vmax-mv", &temp);
+ rc = of_property_read_u32(pdev->dev.of_node, "qcom,vmax-mv", &temp);
if (!rc) {
hap->vmax_mv = temp;
} else if (rc != -EINVAL) {
- dev_err(&spmi->dev, "Unable to read vmax\n");
+ dev_err(&pdev->dev, "Unable to read vmax\n");
return rc;
}
hap->ilim_ma = QPNP_HAP_ILIM_MIN_MV;
- rc = of_property_read_u32(spmi->dev.of_node,
- "qcom,ilim-ma", &temp);
+ rc = of_property_read_u32(pdev->dev.of_node, "qcom,ilim-ma", &temp);
if (!rc) {
hap->ilim_ma = temp;
} else if (rc != -EINVAL) {
- dev_err(&spmi->dev, "Unable to read ILim\n");
+ dev_err(&pdev->dev, "Unable to read ILim\n");
return rc;
}
hap->sc_deb_cycles = QPNP_HAP_DEF_SC_DEB_CYCLES;
- rc = of_property_read_u32(spmi->dev.of_node,
+ rc = of_property_read_u32(pdev->dev.of_node,
"qcom,sc-deb-cycles", &temp);
if (!rc) {
hap->sc_deb_cycles = temp;
} else if (rc != -EINVAL) {
- dev_err(&spmi->dev, "Unable to read sc debounce\n");
+ dev_err(&pdev->dev, "Unable to read sc debounce\n");
return rc;
}
hap->int_pwm_freq_khz = QPNP_HAP_INT_PWM_FREQ_505_KHZ;
- rc = of_property_read_u32(spmi->dev.of_node,
+ rc = of_property_read_u32(pdev->dev.of_node,
"qcom,int-pwm-freq-khz", &temp);
if (!rc) {
hap->int_pwm_freq_khz = temp;
} else if (rc != -EINVAL) {
- dev_err(&spmi->dev, "Unable to read int pwm freq\n");
+ dev_err(&pdev->dev, "Unable to read int pwm freq\n");
return rc;
}
hap->wave_shape = QPNP_HAP_WAV_SQUARE;
- rc = of_property_read_string(spmi->dev.of_node,
+ rc = of_property_read_string(pdev->dev.of_node,
"qcom,wave-shape", &temp_str);
if (!rc) {
if (strcmp(temp_str, "sine") == 0)
@@ -2125,21 +2122,21 @@ static int qpnp_hap_parse_dt(struct qpnp_hap *hap)
else if (strcmp(temp_str, "square") == 0)
hap->wave_shape = QPNP_HAP_WAV_SQUARE;
else {
- dev_err(&spmi->dev, "Unsupported wav shape\n");
+ dev_err(&pdev->dev, "Unsupported wav shape\n");
return -EINVAL;
}
} else if (rc != -EINVAL) {
- dev_err(&spmi->dev, "Unable to read wav shape\n");
+ dev_err(&pdev->dev, "Unable to read wav shape\n");
return rc;
}
hap->wave_play_rate_us = QPNP_HAP_DEF_WAVE_PLAY_RATE_US;
- rc = of_property_read_u32(spmi->dev.of_node,
+ rc = of_property_read_u32(pdev->dev.of_node,
"qcom,wave-play-rate-us", &temp);
if (!rc) {
hap->wave_play_rate_us = temp;
} else if (rc != -EINVAL) {
- dev_err(&spmi->dev, "Unable to read play rate\n");
+ dev_err(&pdev->dev, "Unable to read play rate\n");
return rc;
}
@@ -2151,16 +2148,16 @@ static int qpnp_hap_parse_dt(struct qpnp_hap *hap)
if (rc < 0)
return rc;
- hap->en_brake = of_property_read_bool(spmi->dev.of_node,
+ hap->en_brake = of_property_read_bool(pdev->dev.of_node,
"qcom,en-brake");
if (hap->en_brake) {
- prop = of_find_property(spmi->dev.of_node,
+ prop = of_find_property(pdev->dev.of_node,
"qcom,brake-pattern", &temp);
if (!prop) {
- dev_info(&spmi->dev, "brake pattern not found");
+ dev_info(&pdev->dev, "brake pattern not found");
} else if (temp != QPNP_HAP_BRAKE_PAT_LEN) {
- dev_err(&spmi->dev, "Invalid len of brake pattern\n");
+ dev_err(&pdev->dev, "Invalid len of brake pattern\n");
return -EINVAL;
} else {
hap->sup_brake_pat = true;
@@ -2169,54 +2166,60 @@ static int qpnp_hap_parse_dt(struct qpnp_hap *hap)
}
}
- hap->use_sc_irq = of_property_read_bool(spmi->dev.of_node,
+ hap->use_sc_irq = of_property_read_bool(pdev->dev.of_node,
"qcom,use-sc-irq");
if (hap->use_sc_irq) {
- hap->sc_irq = spmi_get_irq_byname(hap->spmi,
- NULL, "sc-irq");
+ hap->sc_irq = platform_get_irq_byname(hap->pdev, "sc-irq");
if (hap->sc_irq < 0) {
- dev_err(&spmi->dev, "Unable to get sc irq\n");
+ dev_err(&pdev->dev, "Unable to get sc irq\n");
return hap->sc_irq;
}
}
- if (of_find_property(spmi->dev.of_node, "vcc_pon-supply", NULL))
+ if (of_find_property(pdev->dev.of_node, "vcc_pon-supply", NULL))
hap->manage_pon_supply = true;
return 0;
}
-static int qpnp_haptic_probe(struct spmi_device *spmi)
+static int qpnp_haptic_probe(struct platform_device *pdev)
{
struct qpnp_hap *hap;
- struct resource *hap_resource;
+ unsigned int base;
struct regulator *vcc_pon;
int rc, i;
- hap = devm_kzalloc(&spmi->dev, sizeof(*hap), GFP_KERNEL);
+ hap = devm_kzalloc(&pdev->dev, sizeof(*hap), GFP_KERNEL);
if (!hap)
return -ENOMEM;
+ hap->regmap = dev_get_regmap(pdev->dev.parent, NULL);
+ if (!hap->regmap) {
+ dev_err(&pdev->dev, "Couldn't get parent's regmap\n");
+ return -EINVAL;
+ }
- hap->spmi = spmi;
+ hap->pdev = pdev;
- hap_resource = spmi_get_resource(spmi, 0, IORESOURCE_MEM, 0);
- if (!hap_resource) {
- dev_err(&spmi->dev, "Unable to get haptic base address\n");
- return -EINVAL;
+ rc = of_property_read_u32(pdev->dev.of_node, "reg", &base);
+ if (rc < 0) {
+ dev_err(&pdev->dev,
+ "Couldn't find reg in node = %s rc = %d\n",
+ pdev->dev.of_node->full_name, rc);
+ return rc;
}
- hap->base = hap_resource->start;
+ hap->base = base;
- dev_set_drvdata(&spmi->dev, hap);
+ dev_set_drvdata(&pdev->dev, hap);
rc = qpnp_hap_parse_dt(hap);
if (rc) {
- dev_err(&spmi->dev, "DT parsing failed\n");
+ dev_err(&pdev->dev, "DT parsing failed\n");
return rc;
}
rc = qpnp_hap_config(hap);
if (rc) {
- dev_err(&spmi->dev, "hap config failed\n");
+ dev_err(&pdev->dev, "hap config failed\n");
return rc;
}
@@ -2245,7 +2248,7 @@ static int qpnp_haptic_probe(struct spmi_device *spmi)
rc = timed_output_dev_register(&hap->timed_dev);
if (rc < 0) {
- dev_err(&spmi->dev, "timed_output registration failed\n");
+ dev_err(&pdev->dev, "timed_output registration failed\n");
goto timed_output_fail;
}
@@ -2253,16 +2256,16 @@ static int qpnp_haptic_probe(struct spmi_device *spmi)
rc = sysfs_create_file(&hap->timed_dev.dev->kobj,
&qpnp_hap_attrs[i].attr);
if (rc < 0) {
- dev_err(&spmi->dev, "sysfs creation failed\n");
+ dev_err(&pdev->dev, "sysfs creation failed\n");
goto sysfs_fail;
}
}
if (hap->manage_pon_supply) {
- vcc_pon = regulator_get(&spmi->dev, "vcc_pon");
+ vcc_pon = regulator_get(&pdev->dev, "vcc_pon");
if (IS_ERR(vcc_pon)) {
rc = PTR_ERR(vcc_pon);
- dev_err(&spmi->dev,
+ dev_err(&pdev->dev,
"regulator get failed vcc_pon rc=%d\n", rc);
goto sysfs_fail;
}
@@ -2289,9 +2292,9 @@ timed_output_fail:
return rc;
}
-static int qpnp_haptic_remove(struct spmi_device *spmi)
+static int qpnp_haptic_remove(struct platform_device *pdev)
{
- struct qpnp_hap *hap = dev_get_drvdata(&spmi->dev);
+ struct qpnp_hap *hap = dev_get_drvdata(&pdev->dev);
int i;
for (i = 0; i < ARRAY_SIZE(qpnp_hap_attrs); i++)
@@ -2316,11 +2319,11 @@ static struct of_device_id spmi_match_table[] = {
{ },
};
-static struct spmi_driver qpnp_haptic_driver = {
+static struct platform_driver qpnp_haptic_driver = {
.driver = {
- .name = "qcom,qpnp-haptic",
- .of_match_table = spmi_match_table,
- .pm = &qpnp_haptic_pm_ops,
+ .name = "qcom,qpnp-haptic",
+ .of_match_table = spmi_match_table,
+ .pm = &qpnp_haptic_pm_ops,
},
.probe = qpnp_haptic_probe,
.remove = qpnp_haptic_remove,
@@ -2328,13 +2331,13 @@ static struct spmi_driver qpnp_haptic_driver = {
static int __init qpnp_haptic_init(void)
{
- return spmi_driver_register(&qpnp_haptic_driver);
+ return platform_driver_register(&qpnp_haptic_driver);
}
module_init(qpnp_haptic_init);
static void __exit qpnp_haptic_exit(void)
{
- return spmi_driver_unregister(&qpnp_haptic_driver);
+ return platform_driver_unregister(&qpnp_haptic_driver);
}
module_exit(qpnp_haptic_exit);
diff --git a/drivers/platform/msm/qpnp-power-on.c b/drivers/platform/msm/qpnp-power-on.c
index 964ecfd483ed..135c484d071e 100644
--- a/drivers/platform/msm/qpnp-power-on.c
+++ b/drivers/platform/msm/qpnp-power-on.c
@@ -14,9 +14,11 @@
#include <linux/init.h>
#include <linux/debugfs.h>
#include <linux/kernel.h>
+#include <linux/regmap.h>
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/spmi.h>
+#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/of.h>
#include <linux/of_device.h>
@@ -194,7 +196,8 @@ struct pon_regulator {
};
struct qpnp_pon {
- struct spmi_device *spmi;
+ struct platform_device *pdev;
+ struct regmap *regmap;
struct input_dev *pon_input;
struct qpnp_pon_config *pon_cfg;
struct pon_regulator *pon_reg_cfg;
@@ -205,7 +208,6 @@ struct qpnp_pon {
int pon_power_off_reason;
int num_pon_reg;
int num_pon_config;
- int reg_count;
u32 dbc;
u32 uvlo;
int warm_reset_poff_type;
@@ -302,24 +304,12 @@ static int
qpnp_pon_masked_write(struct qpnp_pon *pon, u16 addr, u8 mask, u8 val)
{
int rc;
- u8 reg;
- rc = spmi_ext_register_readl(pon->spmi->ctrl, pon->spmi->sid,
- addr, &reg, 1);
- if (rc) {
- dev_err(&pon->spmi->dev,
- "Unable to read from addr=%hx, rc(%d)\n",
- addr, rc);
- return rc;
- }
-
- reg &= ~mask;
- reg |= val & mask;
- rc = spmi_ext_register_writel(pon->spmi->ctrl, pon->spmi->sid,
- addr, &reg, 1);
+ rc = regmap_update_bits(pon->regmap, addr, mask, val);
if (rc)
- dev_err(&pon->spmi->dev,
- "Unable to write to addr=%hx, rc(%d)\n", addr, rc);
+ dev_err(&pon->pdev->dev,
+ "Unable to regmap_update_bits to addr=%hx, rc(%d)\n",
+ addr, rc);
return rc;
}
@@ -360,7 +350,7 @@ int qpnp_pon_set_restart_reason(enum pon_restart_reason reason)
rc = qpnp_pon_masked_write(pon, QPNP_PON_SOFT_RB_SPARE(pon),
PON_MASK(7, 2), (reason << 2));
if (rc)
- dev_err(&pon->spmi->dev,
+ dev_err(&pon->pdev->dev,
"Unable to write to addr=%x, rc(%d)\n",
QPNP_PON_SOFT_RB_SPARE(pon), rc);
return rc;
@@ -406,7 +396,7 @@ static int qpnp_pon_set_dbc(struct qpnp_pon *pon, u32 delay)
QPNP_PON_DBC_DELAY_MASK(pon),
delay_reg);
if (rc) {
- dev_err(&pon->spmi->dev, "Unable to set PON debounce\n");
+ dev_err(&pon->pdev->dev, "Unable to set PON debounce\n");
goto unlock;
}
@@ -485,7 +475,7 @@ static int qpnp_pon_reset_config(struct qpnp_pon *pon,
rc = qpnp_pon_masked_write(pon, rst_en_reg, QPNP_PON_RESET_EN, 0);
if (rc)
- dev_err(&pon->spmi->dev,
+ dev_err(&pon->pdev->dev,
"Unable to write to addr=%hx, rc(%d)\n",
rst_en_reg, rc);
@@ -499,18 +489,18 @@ static int qpnp_pon_reset_config(struct qpnp_pon *pon,
rc = qpnp_pon_masked_write(pon, QPNP_PON_PS_HOLD_RST_CTL(pon),
QPNP_PON_POWER_OFF_MASK, type);
if (rc)
- dev_err(&pon->spmi->dev,
+ dev_err(&pon->pdev->dev,
"Unable to write to addr=%x, rc(%d)\n",
QPNP_PON_PS_HOLD_RST_CTL(pon), rc);
rc = qpnp_pon_masked_write(pon, rst_en_reg, QPNP_PON_RESET_EN,
QPNP_PON_RESET_EN);
if (rc)
- dev_err(&pon->spmi->dev,
+ dev_err(&pon->pdev->dev,
"Unable to write to addr=%hx, rc(%d)\n",
rst_en_reg, rc);
- dev_dbg(&pon->spmi->dev, "power off type = 0x%02X\n", type);
+ dev_dbg(&pon->pdev->dev, "power off type = 0x%02X\n", type);
return rc;
}
@@ -537,7 +527,8 @@ int qpnp_pon_system_pwr_off(enum pon_power_off_type type)
rc = qpnp_pon_reset_config(pon, type);
if (rc) {
- dev_err(&pon->spmi->dev, "Error configuring main PON rc: %d\n",
+ dev_err(&pon->pdev->dev,
+ "Error configuring main PON rc: %d\n",
rc);
return rc;
}
@@ -552,12 +543,13 @@ int qpnp_pon_system_pwr_off(enum pon_power_off_type type)
goto out;
list_for_each_entry_safe(pon, tmp, &spon_dev_list, list) {
- dev_emerg(&pon->spmi->dev,
+ dev_emerg(&pon->pdev->dev,
"PMIC@SID%d: configuring PON for reset\n",
- pon->spmi->sid);
+ to_spmi_device(pon->pdev->dev.parent)->usid);
rc = qpnp_pon_reset_config(pon, type);
if (rc) {
- dev_err(&pon->spmi->dev, "Error configuring secondary PON rc: %d\n",
+ dev_err(&pon->pdev->dev,
+ "Error configuring secondary PON rc: %d\n",
rc);
goto out;
}
@@ -608,7 +600,7 @@ int qpnp_pon_wd_config(bool enable)
rc = qpnp_pon_masked_write(pon, QPNP_PON_WD_RST_S2_CTL2(pon),
QPNP_PON_WD_EN, enable ? QPNP_PON_WD_EN : 0);
if (rc)
- dev_err(&pon->spmi->dev,
+ dev_err(&pon->pdev->dev,
"Unable to write to addr=%x, rc(%d)\n",
QPNP_PON_WD_RST_S2_CTL2(pon), rc);
@@ -622,7 +614,7 @@ static int qpnp_pon_get_trigger_config(enum pon_trigger_source pon_src,
struct qpnp_pon *pon = sys_reset_dev;
int rc;
u16 addr;
- u8 val;
+ int val;
u8 mask;
if (!pon)
@@ -640,8 +632,8 @@ static int qpnp_pon_get_trigger_config(enum pon_trigger_source pon_src,
mask = QPNP_PON_SMPL_EN;
}
- rc = spmi_ext_register_readl(pon->spmi->ctrl, pon->spmi->sid,
- addr, &val, 1);
+
+ rc = regmap_read(pon->regmap, addr, &val);
if (rc)
dev_err(&pon->spmi->dev,
"Unable to read from addr=%hx, rc(%d)\n",
@@ -671,7 +663,7 @@ int qpnp_pon_trigger_config(enum pon_trigger_source pon_src, bool enable)
return -EPROBE_DEFER;
if (pon_src < PON_SMPL || pon_src > PON_KPDPWR_N) {
- dev_err(&pon->spmi->dev, "Invalid PON source\n");
+ dev_err(&pon->pdev->dev, "Invalid PON source\n");
return -EINVAL;
}
@@ -679,13 +671,15 @@ int qpnp_pon_trigger_config(enum pon_trigger_source pon_src, bool enable)
rc = qpnp_pon_masked_write(pon, QPNP_PON_SMPL_CTL(pon),
QPNP_PON_SMPL_EN, enable ? QPNP_PON_SMPL_EN : 0);
if (rc)
- dev_err(&pon->spmi->dev, "Unable to write to addr=%x, rc(%d)\n",
+ dev_err(&pon->pdev->dev,
+ "Unable to write to addr=%x, rc(%d)\n",
QPNP_PON_SMPL_CTL(pon), rc);
} else {
rc = qpnp_pon_masked_write(pon, QPNP_PON_TRIGGER_EN(pon),
BIT(pon_src), enable ? BIT(pon_src) : 0);
if (rc)
- dev_err(&pon->spmi->dev, "Unable to write to addr=%x, rc(%d)\n",
+ dev_err(&pon->pdev->dev,
+ "Unable to write to addr=%x, rc(%d)\n",
QPNP_PON_TRIGGER_EN(pon), rc);
}
@@ -702,34 +696,35 @@ static int qpnp_pon_store_and_clear_warm_reset(struct qpnp_pon *pon)
{
int rc;
u8 reg = 0;
+ uint val;
- rc = spmi_ext_register_readl(pon->spmi->ctrl, pon->spmi->sid,
- QPNP_PON_WARM_RESET_REASON1(pon),
- &pon->warm_reset_reason1, 1);
+ rc = regmap_read(pon->regmap, QPNP_PON_WARM_RESET_REASON1(pon),
+ &val);
if (rc) {
- dev_err(&pon->spmi->dev, "Unable to read addr=%x, rc(%d)\n",
+ dev_err(&pon->pdev->dev, "Unable to read addr=%x, rc(%d)\n",
QPNP_PON_WARM_RESET_REASON1(pon), rc);
return rc;
}
+ pon->warm_reset_reason1 = (u8)val;
if (is_pon_gen1(pon) || pon->subtype == PON_1REG) {
- rc = spmi_ext_register_readl(pon->spmi->ctrl, pon->spmi->sid,
- QPNP_PON_WARM_RESET_REASON2(pon),
- &pon->warm_reset_reason2, 1);
+ rc = regmap_read(pon->regmap, QPNP_PON_WARM_RESET_REASON2(pon),
+ &val);
if (rc) {
- dev_err(&pon->spmi->dev,
+ dev_err(&pon->pdev->dev,
"Unable to read addr=%x, rc(%d)\n",
QPNP_PON_WARM_RESET_REASON2(pon), rc);
return rc;
}
+ pon->warm_reset_reason2 = (u8)val;
}
- if (of_property_read_bool(pon->spmi->dev.of_node,
+ if (of_property_read_bool(pon->pdev->dev.of_node,
"qcom,clear-warm-reset")) {
- rc = spmi_ext_register_writel(pon->spmi->ctrl, pon->spmi->sid,
- QPNP_PON_WARM_RESET_REASON1(pon), &reg, 1);
+ rc = regmap_write(pon->regmap,
+ QPNP_PON_WARM_RESET_REASON1(pon), reg);
if (rc)
- dev_err(&pon->spmi->dev,
+ dev_err(&pon->pdev->dev,
"Unable to write to addr=%hx, rc(%d)\n",
QPNP_PON_WARM_RESET_REASON1(pon), rc);
}
@@ -755,8 +750,9 @@ qpnp_pon_input_dispatch(struct qpnp_pon *pon, u32 pon_type)
{
int rc;
struct qpnp_pon_config *cfg = NULL;
- u8 pon_rt_sts = 0, pon_rt_bit = 0;
+ u8 pon_rt_bit = 0;
u32 key_status;
+ uint pon_rt_sts;
cfg = qpnp_get_cfg(pon, pon_type);
if (!cfg)
@@ -767,10 +763,9 @@ qpnp_pon_input_dispatch(struct qpnp_pon *pon, u32 pon_type)
return 0;
/* check the RT status to get the current status of the line */
- rc = spmi_ext_register_readl(pon->spmi->ctrl, pon->spmi->sid,
- QPNP_PON_RT_STS(pon), &pon_rt_sts, 1);
+ rc = regmap_read(pon->regmap, QPNP_PON_RT_STS(pon), &pon_rt_sts);
if (rc) {
- dev_err(&pon->spmi->dev, "Unable to read PON RT status\n");
+ dev_err(&pon->pdev->dev, "Unable to read PON RT status\n");
return rc;
}
@@ -818,7 +813,7 @@ static irqreturn_t qpnp_kpdpwr_irq(int irq, void *_pon)
rc = qpnp_pon_input_dispatch(pon, PON_KPDPWR);
if (rc)
- dev_err(&pon->spmi->dev, "Unable to send input event\n");
+ dev_err(&pon->pdev->dev, "Unable to send input event\n");
return IRQ_HANDLED;
}
@@ -835,7 +830,7 @@ static irqreturn_t qpnp_resin_irq(int irq, void *_pon)
rc = qpnp_pon_input_dispatch(pon, PON_RESIN);
if (rc)
- dev_err(&pon->spmi->dev, "Unable to send input event\n");
+ dev_err(&pon->pdev->dev, "Unable to send input event\n");
return IRQ_HANDLED;
}
@@ -851,7 +846,7 @@ static irqreturn_t qpnp_cblpwr_irq(int irq, void *_pon)
rc = qpnp_pon_input_dispatch(pon, PON_CBLPWR);
if (rc)
- dev_err(&pon->spmi->dev, "Unable to send input event\n");
+ dev_err(&pon->pdev->dev, "Unable to send input event\n");
return IRQ_HANDLED;
}
@@ -860,16 +855,15 @@ static void print_pon_reg(struct qpnp_pon *pon, u16 offset)
{
int rc;
u16 addr;
- u8 reg;
+ uint reg;
addr = pon->base + offset;
- rc = spmi_ext_register_readl(pon->spmi->ctrl, pon->spmi->sid,
- addr, &reg, 1);
+ rc = regmap_read(pon->regmap, addr, &reg);
if (rc)
- dev_emerg(&pon->spmi->dev,
+ dev_emerg(&pon->pdev->dev,
"Unable to read reg at 0x%04hx\n", addr);
else
- dev_emerg(&pon->spmi->dev, "reg@0x%04hx: %02hhx\n", addr, reg);
+ dev_emerg(&pon->pdev->dev, "reg@0x%04hx: %02hhx\n", addr, reg);
}
#define PON_PBL_STATUS 0x7
@@ -913,14 +907,14 @@ static irqreturn_t qpnp_pmic_wd_bark_irq(int irq, void *_pon)
static void bark_work_func(struct work_struct *work)
{
int rc;
- u8 pon_rt_sts = 0;
+ uint pon_rt_sts = 0;
struct qpnp_pon_config *cfg;
struct qpnp_pon *pon =
container_of(work, struct qpnp_pon, bark_work.work);
cfg = qpnp_get_cfg(pon, PON_RESIN);
if (!cfg) {
- dev_err(&pon->spmi->dev, "Invalid config pointer\n");
+ dev_err(&pon->pdev->dev, "Invalid config pointer\n");
goto err_return;
}
@@ -928,16 +922,15 @@ static void bark_work_func(struct work_struct *work)
rc = qpnp_pon_masked_write(pon, cfg->s2_cntl2_addr,
QPNP_PON_S2_CNTL_EN, QPNP_PON_S2_CNTL_EN);
if (rc) {
- dev_err(&pon->spmi->dev, "Unable to configure S2 enable\n");
+ dev_err(&pon->pdev->dev, "Unable to configure S2 enable\n");
goto err_return;
}
/* bark RT status update delay */
msleep(100);
/* read the bark RT status */
- rc = spmi_ext_register_readl(pon->spmi->ctrl, pon->spmi->sid,
- QPNP_PON_RT_STS(pon), &pon_rt_sts, 1);
+ rc = regmap_read(pon->regmap, QPNP_PON_RT_STS(pon), &pon_rt_sts);
if (rc) {
- dev_err(&pon->spmi->dev, "Unable to read PON RT status\n");
+ dev_err(&pon->pdev->dev, "Unable to read PON RT status\n");
goto err_return;
}
@@ -951,7 +944,7 @@ static void bark_work_func(struct work_struct *work)
rc = qpnp_pon_masked_write(pon, cfg->s2_cntl2_addr,
QPNP_PON_S2_CNTL_EN, 0);
if (rc) {
- dev_err(&pon->spmi->dev,
+ dev_err(&pon->pdev->dev,
"Unable to configure S2 enable\n");
goto err_return;
}
@@ -974,7 +967,7 @@ static irqreturn_t qpnp_resin_bark_irq(int irq, void *_pon)
cfg = qpnp_get_cfg(pon, PON_RESIN);
if (!cfg) {
- dev_err(&pon->spmi->dev, "Invalid config pointer\n");
+ dev_err(&pon->pdev->dev, "Invalid config pointer\n");
goto err_exit;
}
@@ -982,7 +975,7 @@ static irqreturn_t qpnp_resin_bark_irq(int irq, void *_pon)
rc = qpnp_pon_masked_write(pon, cfg->s2_cntl2_addr,
QPNP_PON_S2_CNTL_EN, 0);
if (rc) {
- dev_err(&pon->spmi->dev, "Unable to configure S2 enable\n");
+ dev_err(&pon->pdev->dev, "Unable to configure S2 enable\n");
goto err_exit;
}
@@ -1021,7 +1014,7 @@ qpnp_config_pull(struct qpnp_pon *pon, struct qpnp_pon_config *cfg)
rc = qpnp_pon_masked_write(pon, QPNP_PON_PULL_CTL(pon),
pull_bit, cfg->pull_up ? pull_bit : 0);
if (rc)
- dev_err(&pon->spmi->dev, "Unable to config pull-up\n");
+ dev_err(&pon->pdev->dev, "Unable to config pull-up\n");
return rc;
}
@@ -1053,7 +1046,7 @@ qpnp_config_reset(struct qpnp_pon *pon, struct qpnp_pon_config *cfg)
rc = qpnp_pon_masked_write(pon, cfg->s2_cntl2_addr,
QPNP_PON_S2_CNTL_EN, 0);
if (rc) {
- dev_err(&pon->spmi->dev, "Unable to configure S2 enable\n");
+ dev_err(&pon->pdev->dev, "Unable to configure S2 enable\n");
return rc;
}
@@ -1067,7 +1060,7 @@ qpnp_config_reset(struct qpnp_pon *pon, struct qpnp_pon_config *cfg)
rc = qpnp_pon_masked_write(pon, s1_timer_addr,
QPNP_PON_S1_TIMER_MASK, i);
if (rc) {
- dev_err(&pon->spmi->dev, "Unable to configure S1 timer\n");
+ dev_err(&pon->pdev->dev, "Unable to configure S1 timer\n");
return rc;
}
@@ -1080,14 +1073,15 @@ qpnp_config_reset(struct qpnp_pon *pon, struct qpnp_pon_config *cfg)
rc = qpnp_pon_masked_write(pon, s2_timer_addr,
QPNP_PON_S2_TIMER_MASK, i);
if (rc) {
- dev_err(&pon->spmi->dev, "Unable to configure S2 timer\n");
+ dev_err(&pon->pdev->dev, "Unable to configure S2 timer\n");
return rc;
}
rc = qpnp_pon_masked_write(pon, cfg->s2_cntl_addr,
QPNP_PON_S2_CNTL_TYPE_MASK, (u8)cfg->s2_type);
if (rc) {
- dev_err(&pon->spmi->dev, "Unable to configure S2 reset type\n");
+ dev_err(&pon->pdev->dev,
+ "Unable to configure S2 reset type\n");
return rc;
}
@@ -1095,7 +1089,7 @@ qpnp_config_reset(struct qpnp_pon *pon, struct qpnp_pon_config *cfg)
rc = qpnp_pon_masked_write(pon, cfg->s2_cntl2_addr,
QPNP_PON_S2_CNTL_EN, QPNP_PON_S2_CNTL_EN);
if (rc) {
- dev_err(&pon->spmi->dev, "Unable to configure S2 enable\n");
+ dev_err(&pon->pdev->dev, "Unable to configure S2 enable\n");
return rc;
}
@@ -1109,22 +1103,22 @@ qpnp_pon_request_irqs(struct qpnp_pon *pon, struct qpnp_pon_config *cfg)
switch (cfg->pon_type) {
case PON_KPDPWR:
- rc = devm_request_irq(&pon->spmi->dev, cfg->state_irq,
+ rc = devm_request_irq(&pon->pdev->dev, cfg->state_irq,
qpnp_kpdpwr_irq,
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
"qpnp_kpdpwr_status", pon);
if (rc < 0) {
- dev_err(&pon->spmi->dev, "Can't request %d IRQ\n",
+ dev_err(&pon->pdev->dev, "Can't request %d IRQ\n",
cfg->state_irq);
return rc;
}
if (cfg->use_bark) {
- rc = devm_request_irq(&pon->spmi->dev, cfg->bark_irq,
+ rc = devm_request_irq(&pon->pdev->dev, cfg->bark_irq,
qpnp_kpdpwr_bark_irq,
IRQF_TRIGGER_RISING,
"qpnp_kpdpwr_bark", pon);
if (rc < 0) {
- dev_err(&pon->spmi->dev,
+ dev_err(&pon->pdev->dev,
"Can't request %d IRQ\n",
cfg->bark_irq);
return rc;
@@ -1132,22 +1126,22 @@ qpnp_pon_request_irqs(struct qpnp_pon *pon, struct qpnp_pon_config *cfg)
}
break;
case PON_RESIN:
- rc = devm_request_irq(&pon->spmi->dev, cfg->state_irq,
+ rc = devm_request_irq(&pon->pdev->dev, cfg->state_irq,
qpnp_resin_irq,
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
"qpnp_resin_status", pon);
if (rc < 0) {
- dev_err(&pon->spmi->dev, "Can't request %d IRQ\n",
+ dev_err(&pon->pdev->dev, "Can't request %d IRQ\n",
cfg->state_irq);
return rc;
}
if (cfg->use_bark) {
- rc = devm_request_irq(&pon->spmi->dev, cfg->bark_irq,
+ rc = devm_request_irq(&pon->pdev->dev, cfg->bark_irq,
qpnp_resin_bark_irq,
IRQF_TRIGGER_RISING,
"qpnp_resin_bark", pon);
if (rc < 0) {
- dev_err(&pon->spmi->dev,
+ dev_err(&pon->pdev->dev,
"Can't request %d IRQ\n",
cfg->bark_irq);
return rc;
@@ -1155,24 +1149,24 @@ qpnp_pon_request_irqs(struct qpnp_pon *pon, struct qpnp_pon_config *cfg)
}
break;
case PON_CBLPWR:
- rc = devm_request_irq(&pon->spmi->dev, cfg->state_irq,
+ rc = devm_request_irq(&pon->pdev->dev, cfg->state_irq,
qpnp_cblpwr_irq,
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
"qpnp_cblpwr_status", pon);
if (rc < 0) {
- dev_err(&pon->spmi->dev, "Can't request %d IRQ\n",
+ dev_err(&pon->pdev->dev, "Can't request %d IRQ\n",
cfg->state_irq);
return rc;
}
break;
case PON_KPDPWR_RESIN:
if (cfg->use_bark) {
- rc = devm_request_irq(&pon->spmi->dev, cfg->bark_irq,
+ rc = devm_request_irq(&pon->pdev->dev, cfg->bark_irq,
qpnp_kpdpwr_resin_bark_irq,
IRQF_TRIGGER_RISING,
"qpnp_kpdpwr_resin_bark", pon);
if (rc < 0) {
- dev_err(&pon->spmi->dev,
+ dev_err(&pon->pdev->dev,
"Can't request %d IRQ\n",
cfg->bark_irq);
return rc;
@@ -1200,7 +1194,7 @@ qpnp_pon_config_input(struct qpnp_pon *pon, struct qpnp_pon_config *cfg)
if (!pon->pon_input) {
pon->pon_input = input_allocate_device();
if (!pon->pon_input) {
- dev_err(&pon->spmi->dev,
+ dev_err(&pon->pdev->dev,
"Can't allocate pon input device\n");
return -ENOMEM;
}
@@ -1220,17 +1214,17 @@ static int qpnp_pon_config_init(struct qpnp_pon *pon)
int rc = 0, i = 0, pmic_wd_bark_irq;
struct device_node *pp = NULL;
struct qpnp_pon_config *cfg;
- u8 pmic_type;
- u8 revid_rev4;
+ uint pmic_type;
+ uint revid_rev4;
if (!pon->num_pon_config) {
- dev_dbg(&pon->spmi->dev, "num_pon_config: %d\n",
+ dev_dbg(&pon->pdev->dev, "num_pon_config: %d\n",
pon->num_pon_config);
return 0;
}
/* iterate through the list of pon configs */
- for_each_available_child_of_node(pon->spmi->dev.of_node, pp) {
+ for_each_available_child_of_node(pon->pdev->dev.of_node, pp) {
if (!of_find_property(pp, "qcom,pon-type", NULL))
continue;
@@ -1238,16 +1232,16 @@ static int qpnp_pon_config_init(struct qpnp_pon *pon)
rc = of_property_read_u32(pp, "qcom,pon-type", &cfg->pon_type);
if (rc) {
- dev_err(&pon->spmi->dev, "PON type not specified\n");
+ dev_err(&pon->pdev->dev, "PON type not specified\n");
return rc;
}
switch (cfg->pon_type) {
case PON_KPDPWR:
- cfg->state_irq = spmi_get_irq_byname(pon->spmi,
- NULL, "kpdpwr");
+ cfg->state_irq = platform_get_irq_byname(pon->pdev,
+ "kpdpwr");
if (cfg->state_irq < 0) {
- dev_err(&pon->spmi->dev,
+ dev_err(&pon->pdev->dev,
"Unable to get kpdpwr irq\n");
return cfg->state_irq;
}
@@ -1257,10 +1251,10 @@ static int qpnp_pon_config_init(struct qpnp_pon *pon)
if (rc) {
if (rc == -EINVAL) {
- dev_dbg(&pon->spmi->dev,
+ dev_dbg(&pon->pdev->dev,
"'qcom,support-reset' DT property doesn't exist\n");
} else {
- dev_err(&pon->spmi->dev,
+ dev_err(&pon->pdev->dev,
"Unable to read 'qcom,support-reset'\n");
return rc;
}
@@ -1271,10 +1265,11 @@ static int qpnp_pon_config_init(struct qpnp_pon *pon)
cfg->use_bark = of_property_read_bool(pp,
"qcom,use-bark");
if (cfg->use_bark) {
- cfg->bark_irq = spmi_get_irq_byname(pon->spmi,
- NULL, "kpdpwr-bark");
+ cfg->bark_irq
+ = platform_get_irq_byname(pon->pdev,
+ "kpdpwr-bark");
if (cfg->bark_irq < 0) {
- dev_err(&pon->spmi->dev,
+ dev_err(&pon->pdev->dev,
"Unable to get kpdpwr-bark irq\n");
return cfg->bark_irq;
}
@@ -1296,10 +1291,10 @@ static int qpnp_pon_config_init(struct qpnp_pon *pon)
break;
case PON_RESIN:
- cfg->state_irq = spmi_get_irq_byname(pon->spmi,
- NULL, "resin");
+ cfg->state_irq = platform_get_irq_byname(pon->pdev,
+ "resin");
if (cfg->state_irq < 0) {
- dev_err(&pon->spmi->dev,
+ dev_err(&pon->pdev->dev,
"Unable to get resin irq\n");
return cfg->bark_irq;
}
@@ -1309,10 +1304,10 @@ static int qpnp_pon_config_init(struct qpnp_pon *pon)
if (rc) {
if (rc == -EINVAL) {
- dev_dbg(&pon->spmi->dev,
+ dev_dbg(&pon->pdev->dev,
"'qcom,support-reset' DT property doesn't exist\n");
} else {
- dev_err(&pon->spmi->dev,
+ dev_err(&pon->pdev->dev,
"Unable to read 'qcom,support-reset'\n");
return rc;
}
@@ -1323,24 +1318,23 @@ static int qpnp_pon_config_init(struct qpnp_pon *pon)
cfg->use_bark = of_property_read_bool(pp,
"qcom,use-bark");
- rc = spmi_ext_register_readl(pon->spmi->ctrl,
- pon->spmi->sid, PMIC_VERSION_REG,
- &pmic_type, 1);
+ rc = regmap_read(pon->regmap, PMIC_VERSION_REG,
+ &pmic_type);
if (rc) {
- dev_err(&pon->spmi->dev,
+ dev_err(&pon->pdev->dev,
"Unable to read PMIC type\n");
return rc;
}
if (pmic_type == PMIC_VER_8941) {
- rc = spmi_ext_register_readl(pon->spmi->ctrl,
- pon->spmi->sid, PMIC_VERSION_REV4_REG,
- &revid_rev4, 1);
+ rc = regmap_read(pon->regmap,
+ PMIC_VERSION_REV4_REG,
+ &revid_rev4);
if (rc) {
- dev_err(&pon->spmi->dev,
+ dev_err(&pon->pdev->dev,
"Unable to read PMIC revision ID\n");
return rc;
}
@@ -1355,10 +1349,11 @@ static int qpnp_pon_config_init(struct qpnp_pon *pon)
}
if (cfg->use_bark) {
- cfg->bark_irq = spmi_get_irq_byname(pon->spmi,
- NULL, "resin-bark");
+ cfg->bark_irq
+ = platform_get_irq_byname(pon->pdev,
+ "resin-bark");
if (cfg->bark_irq < 0) {
- dev_err(&pon->spmi->dev,
+ dev_err(&pon->pdev->dev,
"Unable to get resin-bark irq\n");
return cfg->bark_irq;
}
@@ -1376,10 +1371,10 @@ static int qpnp_pon_config_init(struct qpnp_pon *pon)
break;
case PON_CBLPWR:
- cfg->state_irq = spmi_get_irq_byname(pon->spmi,
- NULL, "cblpwr");
+ cfg->state_irq = platform_get_irq_byname(pon->pdev,
+ "cblpwr");
if (cfg->state_irq < 0) {
- dev_err(&pon->spmi->dev,
+ dev_err(&pon->pdev->dev,
"Unable to get cblpwr irq\n");
return rc;
}
@@ -1390,10 +1385,10 @@ static int qpnp_pon_config_init(struct qpnp_pon *pon)
if (rc) {
if (rc == -EINVAL) {
- dev_dbg(&pon->spmi->dev,
+ dev_dbg(&pon->pdev->dev,
"'qcom,support-reset' DT property doesn't exist\n");
} else {
- dev_err(&pon->spmi->dev,
+ dev_err(&pon->pdev->dev,
"Unable to read 'qcom,support-reset'\n");
return rc;
}
@@ -1404,10 +1399,11 @@ static int qpnp_pon_config_init(struct qpnp_pon *pon)
cfg->use_bark = of_property_read_bool(pp,
"qcom,use-bark");
if (cfg->use_bark) {
- cfg->bark_irq = spmi_get_irq_byname(pon->spmi,
- NULL, "kpdpwr-resin-bark");
+ cfg->bark_irq
+ = platform_get_irq_byname(pon->pdev,
+ "kpdpwr-resin-bark");
if (cfg->bark_irq < 0) {
- dev_err(&pon->spmi->dev,
+ dev_err(&pon->pdev->dev,
"Unable to get kpdpwr-resin-bark irq\n");
return cfg->bark_irq;
}
@@ -1425,7 +1421,7 @@ static int qpnp_pon_config_init(struct qpnp_pon *pon)
break;
default:
- dev_err(&pon->spmi->dev, "PON RESET %d not supported",
+ dev_err(&pon->pdev->dev, "PON RESET %d not supported",
cfg->pon_type);
return -EINVAL;
}
@@ -1438,40 +1434,39 @@ static int qpnp_pon_config_init(struct qpnp_pon *pon)
rc = of_property_read_u32(pp, "qcom,s1-timer",
&cfg->s1_timer);
if (rc) {
- dev_err(&pon->spmi->dev,
+ dev_err(&pon->pdev->dev,
"Unable to read s1-timer\n");
return rc;
}
if (cfg->s1_timer > QPNP_PON_S1_TIMER_MAX) {
- dev_err(&pon->spmi->dev,
+ dev_err(&pon->pdev->dev,
"Incorrect S1 debounce time\n");
return -EINVAL;
}
rc = of_property_read_u32(pp, "qcom,s2-timer",
&cfg->s2_timer);
if (rc) {
- dev_err(&pon->spmi->dev,
+ dev_err(&pon->pdev->dev,
"Unable to read s2-timer\n");
return rc;
}
if (cfg->s2_timer > QPNP_PON_S2_TIMER_MAX) {
- dev_err(&pon->spmi->dev,
+ dev_err(&pon->pdev->dev,
"Incorrect S2 debounce time\n");
return -EINVAL;
}
rc = of_property_read_u32(pp, "qcom,s2-type",
&cfg->s2_type);
if (rc) {
- dev_err(&pon->spmi->dev,
+ dev_err(&pon->pdev->dev,
"Unable to read s2-type\n");
return rc;
}
if (cfg->s2_type > QPNP_PON_RESET_TYPE_MAX) {
- dev_err(&pon->spmi->dev,
+ dev_err(&pon->pdev->dev,
"Incorrect reset type specified\n");
return -EINVAL;
}
-
}
/*
* Get the standard-key parameters. This might not be
@@ -1479,8 +1474,7 @@ static int qpnp_pon_config_init(struct qpnp_pon *pon)
*/
rc = of_property_read_u32(pp, "linux,code", &cfg->key_code);
if (rc && rc != -EINVAL) {
- dev_err(&pon->spmi->dev,
- "Unable to read key-code\n");
+ dev_err(&pon->pdev->dev, "Unable to read key-code\n");
return rc;
}
/* Register key configuration */
@@ -1492,20 +1486,20 @@ static int qpnp_pon_config_init(struct qpnp_pon *pon)
/* get the pull-up configuration */
rc = of_property_read_u32(pp, "qcom,pull-up", &cfg->pull_up);
if (rc && rc != -EINVAL) {
- dev_err(&pon->spmi->dev, "Unable to read pull-up\n");
+ dev_err(&pon->pdev->dev, "Unable to read pull-up\n");
return rc;
}
}
- pmic_wd_bark_irq = spmi_get_irq_byname(pon->spmi, NULL, "pmic-wd-bark");
+ pmic_wd_bark_irq = platform_get_irq_byname(pon->pdev, "pmic-wd-bark");
/* request the pmic-wd-bark irq only if it is defined */
if (pmic_wd_bark_irq >= 0) {
- rc = devm_request_irq(&pon->spmi->dev, pmic_wd_bark_irq,
+ rc = devm_request_irq(&pon->pdev->dev, pmic_wd_bark_irq,
qpnp_pmic_wd_bark_irq,
IRQF_TRIGGER_RISING,
"qpnp_pmic_wd_bark", pon);
if (rc < 0) {
- dev_err(&pon->spmi->dev,
+ dev_err(&pon->pdev->dev,
"Can't request %d IRQ\n",
pmic_wd_bark_irq);
goto free_input_dev;
@@ -1516,7 +1510,7 @@ static int qpnp_pon_config_init(struct qpnp_pon *pon)
if (pon->pon_input) {
rc = input_register_device(pon->pon_input);
if (rc) {
- dev_err(&pon->spmi->dev,
+ dev_err(&pon->pdev->dev,
"Can't register pon key: %d\n", rc);
goto free_input_dev;
}
@@ -1527,7 +1521,7 @@ static int qpnp_pon_config_init(struct qpnp_pon *pon)
/* Configure the pull-up */
rc = qpnp_config_pull(pon, cfg);
if (rc) {
- dev_err(&pon->spmi->dev, "Unable to config pull-up\n");
+ dev_err(&pon->pdev->dev, "Unable to config pull-up\n");
goto unreg_input_dev;
}
@@ -1536,7 +1530,7 @@ static int qpnp_pon_config_init(struct qpnp_pon *pon)
if (cfg->support_reset) {
rc = qpnp_config_reset(pon, cfg);
if (rc) {
- dev_err(&pon->spmi->dev,
+ dev_err(&pon->pdev->dev,
"Unable to config pon reset\n");
goto unreg_input_dev;
}
@@ -1547,7 +1541,7 @@ static int qpnp_pon_config_init(struct qpnp_pon *pon)
cfg->s2_cntl2_addr,
QPNP_PON_S2_CNTL_EN, 0);
if (rc) {
- dev_err(&pon->spmi->dev,
+ dev_err(&pon->pdev->dev,
"Unable to disable S2 reset\n");
goto unreg_input_dev;
}
@@ -1557,12 +1551,12 @@ static int qpnp_pon_config_init(struct qpnp_pon *pon)
rc = qpnp_pon_request_irqs(pon, cfg);
if (rc) {
- dev_err(&pon->spmi->dev, "Unable to request-irq's\n");
+ dev_err(&pon->pdev->dev, "Unable to request-irq's\n");
goto unreg_input_dev;
}
}
- device_init_wakeup(&pon->spmi->dev, 1);
+ device_init_wakeup(&pon->pdev->dev, 1);
return rc;
@@ -1588,7 +1582,7 @@ static int pon_spare_regulator_enable(struct regulator_dev *rdev)
rc = qpnp_pon_masked_write(pon_reg->pon, pon_reg->pon->base +
pon_reg->addr, value, value);
if (rc)
- dev_err(&pon_reg->pon->spmi->dev, "Unable to write to %x\n",
+ dev_err(&pon_reg->pon->pdev->dev, "Unable to write to %x\n",
pon_reg->pon->base + pon_reg->addr);
else
pon_reg->enabled = true;
@@ -1608,7 +1602,7 @@ static int pon_spare_regulator_disable(struct regulator_dev *rdev)
rc = qpnp_pon_masked_write(pon_reg->pon, pon_reg->pon->base +
pon_reg->addr, mask, 0);
if (rc)
- dev_err(&pon_reg->pon->spmi->dev, "Unable to write to %x\n",
+ dev_err(&pon_reg->pon->pdev->dev, "Unable to write to %x\n",
pon_reg->pon->base + pon_reg->addr);
else
pon_reg->enabled = false;
@@ -1634,7 +1628,7 @@ static int pon_regulator_init(struct qpnp_pon *pon)
struct regulator_init_data *init_data;
struct regulator_config reg_cfg = {};
struct device_node *node = NULL;
- struct device *dev = &pon->spmi->dev;
+ struct device *dev = &pon->pdev->dev;
struct pon_regulator *pon_reg;
if (!pon->num_pon_reg)
@@ -1749,15 +1743,14 @@ static int qpnp_pon_debugfs_uvlo_dload_get(char *buf,
{
struct qpnp_pon *pon = sys_reset_dev;
int rc = 0;
- u8 reg;
+ uint reg;
if (!pon)
return -ENODEV;
- rc = spmi_ext_register_readl(pon->spmi->ctrl, pon->spmi->sid,
- QPNP_PON_XVDD_RB_SPARE(pon), &reg, 1);
+ rc = regmap_read(pon->regmap, QPNP_PON_XVDD_RB_SPARE(pon), &reg);
if (rc) {
- dev_err(&pon->spmi->dev,
+ dev_err(&pon->pdev->dev,
"Unable to read addr=%x, rc(%d)\n",
QPNP_PON_XVDD_RB_SPARE(pon), rc);
return rc;
@@ -1772,7 +1765,7 @@ static int qpnp_pon_debugfs_uvlo_dload_set(const char *val,
{
struct qpnp_pon *pon = sys_reset_dev;
int rc = 0;
- u8 reg;
+ uint reg;
if (!pon)
return -ENODEV;
@@ -1783,10 +1776,9 @@ static int qpnp_pon_debugfs_uvlo_dload_set(const char *val,
return rc;
}
- rc = spmi_ext_register_readl(pon->spmi->ctrl, pon->spmi->sid,
- QPNP_PON_XVDD_RB_SPARE(pon), &reg, 1);
+ rc = regmap_read(pon->regmap, QPNP_PON_XVDD_RB_SPARE(pon), &reg);
if (rc) {
- dev_err(&pon->spmi->dev,
+ dev_err(&pon->pdev->dev,
"Unable to read addr=%x, rc(%d)\n",
QPNP_PON_XVDD_RB_SPARE(pon), rc);
return rc;
@@ -1796,10 +1788,9 @@ static int qpnp_pon_debugfs_uvlo_dload_set(const char *val,
if (*(bool *)kp->arg)
reg |= QPNP_PON_UVLO_DLOAD_EN;
- rc = spmi_ext_register_writel(pon->spmi->ctrl, pon->spmi->sid,
- QPNP_PON_XVDD_RB_SPARE(pon), &reg, 1);
+ rc = regmap_write(pon->regmap, QPNP_PON_XVDD_RB_SPARE(pon), reg);
if (rc) {
- dev_err(&pon->spmi->dev,
+ dev_err(&pon->pdev->dev,
"Unable to write to addr=%hx, rc(%d)\n",
QPNP_PON_XVDD_RB_SPARE(pon), rc);
return rc;
@@ -1841,36 +1832,38 @@ static int qpnp_pon_debugfs_uvlo_set(void *data, u64 val)
DEFINE_SIMPLE_ATTRIBUTE(qpnp_pon_debugfs_uvlo_fops, qpnp_pon_debugfs_uvlo_get,
qpnp_pon_debugfs_uvlo_set, "0x%02llx\n");
-static void qpnp_pon_debugfs_init(struct spmi_device *spmi)
+static void qpnp_pon_debugfs_init(struct platform_device *pdev)
{
- struct qpnp_pon *pon = dev_get_drvdata(&spmi->dev);
+ struct qpnp_pon *pon = dev_get_drvdata(&pdev->dev);
struct dentry *ent;
- pon->debugfs = debugfs_create_dir(dev_name(&spmi->dev), NULL);
+ pon->debugfs = debugfs_create_dir(dev_name(&pdev->dev), NULL);
if (!pon->debugfs) {
- dev_err(&pon->spmi->dev, "Unable to create debugfs directory\n");
+ dev_err(&pon->pdev->dev,
+ "Unable to create debugfs directory\n");
} else {
ent = debugfs_create_file("uvlo_panic",
S_IFREG | S_IWUSR | S_IRUGO,
pon->debugfs, pon, &qpnp_pon_debugfs_uvlo_fops);
if (!ent)
- dev_err(&pon->spmi->dev, "Unable to create uvlo_panic debugfs file.\n");
+ dev_err(&pon->pdev->dev,
+ "Unable to create uvlo_panic debugfs file.\n");
}
}
-static void qpnp_pon_debugfs_remove(struct spmi_device *spmi)
+static void qpnp_pon_debugfs_remove(struct platform_device *pdev)
{
- struct qpnp_pon *pon = dev_get_drvdata(&spmi->dev);
+ struct qpnp_pon *pon = dev_get_drvdata(&pdev->dev);
debugfs_remove_recursive(pon->debugfs);
}
#else
-static void qpnp_pon_debugfs_init(struct spmi_device *spmi)
+static void qpnp_pon_debugfs_init(struct platform_device *pdev)
{}
-static void qpnp_pon_debugfs_remove(struct spmi_device *spmi)
+static void qpnp_pon_debugfs_remove(struct platform_device *pdev)
{}
#endif
@@ -1878,96 +1871,104 @@ static int read_gen2_pon_off_reason(struct qpnp_pon *pon, u16 *reason,
int *reason_index_offset)
{
int rc;
- u8 buf[2], reg;
+ int buf[2], reg;
- rc = spmi_ext_register_readl(pon->spmi->ctrl, pon->spmi->sid,
- QPNP_PON_OFF_REASON(pon),
- &reg, 1);
+ rc = regmap_read(pon->regmap,
+ QPNP_PON_OFF_REASON(pon),
+ &reg);
if (rc) {
- dev_err(&pon->spmi->dev, "Unable to read PON_OFF_REASON reg rc:%d\n",
+ dev_err(&pon->pdev->dev, "Unable to read PON_OFF_REASON reg rc:%d\n",
rc);
return rc;
}
if (reg & QPNP_GEN2_POFF_SEQ) {
- rc = spmi_ext_register_readl(pon->spmi->ctrl, pon->spmi->sid,
- QPNP_POFF_REASON1(pon),
- buf, 1);
+ rc = regmap_read(pon->regmap,
+ QPNP_POFF_REASON1(pon),
+ buf);
if (rc) {
- dev_err(&pon->spmi->dev, "Unable to read POFF_REASON1 reg rc:%d\n",
+ dev_err(&pon->pdev->dev, "Unable to read POFF_REASON1 reg rc:%d\n",
rc);
return rc;
}
- *reason = buf[0];
+ *reason = (u8)buf[0];
*reason_index_offset = 0;
} else if (reg & QPNP_GEN2_FAULT_SEQ) {
- rc = spmi_ext_register_readl(pon->spmi->ctrl, pon->spmi->sid,
- QPNP_FAULT_REASON1(pon),
- buf, 2);
+ rc = regmap_bulk_read(pon->regmap,
+ QPNP_FAULT_REASON1(pon),
+ buf, 2);
if (rc) {
- dev_err(&pon->spmi->dev, "Unable to read FAULT_REASON regs rc:%d\n",
+ dev_err(&pon->pdev->dev, "Unable to read FAULT_REASON regs rc:%d\n",
rc);
return rc;
}
- *reason = buf[0] | (buf[1] << 8);
+ *reason = (u8)buf[0] | (u16)(buf[1] << 8);
*reason_index_offset = POFF_REASON_FAULT_OFFSET;
} else if (reg & QPNP_GEN2_S3_RESET_SEQ) {
- rc = spmi_ext_register_readl(pon->spmi->ctrl, pon->spmi->sid,
- QPNP_S3_RESET_REASON(pon),
- buf, 1);
+ rc = regmap_read(pon->regmap,
+ QPNP_S3_RESET_REASON(pon),
+ buf);
if (rc) {
- dev_err(&pon->spmi->dev, "Unable to read S3_RESET_REASON reg rc:%d\n",
+ dev_err(&pon->pdev->dev, "Unable to read S3_RESET_REASON reg rc:%d\n",
rc);
return rc;
}
- *reason = buf[0];
+ *reason = (u8)buf[0];
*reason_index_offset = POFF_REASON_S3_RESET_OFFSET;
}
return 0;
}
-static int qpnp_pon_probe(struct spmi_device *spmi)
+static int qpnp_pon_probe(struct platform_device *pdev)
{
struct qpnp_pon *pon;
- struct resource *pon_resource;
+ unsigned int base;
struct device_node *node = NULL;
u32 delay = 0, s3_debounce = 0;
int rc, sys_reset, index;
int reason_index_offset = 0;
- u8 pon_sts = 0, buf[2];
+ u8 buf[2];
+ uint pon_sts = 0;
u16 poff_sts = 0;
const char *s3_src;
u8 s3_src_reg;
unsigned long flags;
+ uint temp = 0;
- pon = devm_kzalloc(&spmi->dev, sizeof(struct qpnp_pon),
- GFP_KERNEL);
- if (!pon) {
- dev_err(&spmi->dev, "Can't allocate qpnp_pon\n");
+ pon = devm_kzalloc(&pdev->dev, sizeof(struct qpnp_pon), GFP_KERNEL);
+ if (!pon)
return -ENOMEM;
+
+ pon->regmap = dev_get_regmap(pdev->dev.parent, NULL);
+ if (!pon->regmap) {
+ dev_err(&pdev->dev, "Couldn't get parent's regmap\n");
+ return -EINVAL;
}
- sys_reset = of_property_read_bool(spmi->dev.of_node,
+ sys_reset = of_property_read_bool(pdev->dev.of_node,
"qcom,system-reset");
if (sys_reset && sys_reset_dev) {
- dev_err(&spmi->dev, "qcom,system-reset property can only be specified for one device on the system\n");
+ dev_err(&pdev->dev,
+ "qcom,system-reset property can only be specified for one device on the system\n");
return -EINVAL;
} else if (sys_reset) {
sys_reset_dev = pon;
}
- pon->spmi = spmi;
+ pon->pdev = pdev;
- pon_resource = spmi_get_resource(spmi, NULL, IORESOURCE_MEM, 0);
- if (!pon_resource) {
- dev_err(&spmi->dev, "Unable to get PON base address\n");
- return -ENXIO;
+ rc = of_property_read_u32(pdev->dev.of_node, "reg", &base);
+ if (rc < 0) {
+ dev_err(&pdev->dev,
+ "Couldn't find reg in node = %s rc = %d\n",
+ pdev->dev.of_node->full_name, rc);
+ return rc;
}
- pon->base = pon_resource->start;
+ pon->base = base;
/* get the total number of pon configurations */
- for_each_available_child_of_node(spmi->dev.of_node, node) {
+ for_each_available_child_of_node(pdev->dev.of_node, node) {
if (of_find_property(node, "regulator-name", NULL)) {
pon->num_pon_reg++;
} else if (of_find_property(node, "qcom,pon-type", NULL)) {
@@ -1979,43 +1980,47 @@ static int qpnp_pon_probe(struct spmi_device *spmi)
}
pr_debug("PON@SID %d: num_pon_config: %d num_pon_reg: %d\n",
- pon->spmi->sid, pon->num_pon_config, pon->num_pon_reg);
+ to_spmi_device(pon->pdev->dev.parent)->usid,
+ pon->num_pon_config, pon->num_pon_reg);
rc = pon_regulator_init(pon);
if (rc) {
- dev_err(&pon->spmi->dev, "Error in pon_regulator_init rc: %d\n",
+ dev_err(&pdev->dev, "Error in pon_regulator_init rc: %d\n",
rc);
return rc;
}
if (!pon->num_pon_config)
/* No PON config., do not register the driver */
- dev_info(&spmi->dev, "No PON config. specified\n");
+ dev_info(&pdev->dev, "No PON config. specified\n");
else
- pon->pon_cfg = devm_kzalloc(&spmi->dev,
+ pon->pon_cfg = devm_kzalloc(&pdev->dev,
sizeof(struct qpnp_pon_config) *
pon->num_pon_config, GFP_KERNEL);
/* Read PON_PERPH_SUBTYPE register to get PON type */
- rc = spmi_ext_register_readl(pon->spmi->ctrl, pon->spmi->sid,
+ rc = regmap_read(pon->regmap,
QPNP_PON_PERPH_SUBTYPE(pon),
- &pon->subtype, 1);
+ &temp);
if (rc) {
- dev_err(&pon->spmi->dev,
+ dev_err(&pon->pdev->dev,
"Unable to read PON_PERPH_SUBTYPE register rc: %d\n",
rc);
return rc;
}
+ pon->subtype = temp;
/* Check if it is rev B */
- rc = spmi_ext_register_readl(pon->spmi->ctrl, pon->spmi->sid,
- QPNP_PON_REVISION2(pon), &pon->pon_ver, 1);
+ rc = regmap_read(pon->regmap,
+ QPNP_PON_REVISION2(pon), &temp);
if (rc) {
- dev_err(&pon->spmi->dev,
+ dev_err(&pon->pdev->dev,
"Unable to read addr=%x, rc(%d)\n",
QPNP_PON_REVISION2(pon), rc);
return rc;
}
+
+ pon->pon_ver = temp;
if (is_pon_gen1(pon)) {
if (pon->pon_ver == 0)
pon->pon_ver = QPNP_PON_GEN1_V1;
@@ -2026,7 +2031,7 @@ static int qpnp_pon_probe(struct spmi_device *spmi)
} else if (pon->subtype == PON_1REG) {
pon->pon_ver = QPNP_PON_GEN1_V2;
} else {
- dev_err(&pon->spmi->dev,
+ dev_err(&pon->pdev->dev,
"Invalid PON_PERPH_SUBTYPE value %x\n",
pon->subtype);
return -EINVAL;
@@ -2037,17 +2042,17 @@ static int qpnp_pon_probe(struct spmi_device *spmi)
rc = qpnp_pon_store_and_clear_warm_reset(pon);
if (rc) {
- dev_err(&pon->spmi->dev,
+ dev_err(&pon->pdev->dev,
"Unable to store/clear WARM_RESET_REASONx registers rc: %d\n",
rc);
return rc;
}
/* PON reason */
- rc = spmi_ext_register_readl(pon->spmi->ctrl, pon->spmi->sid,
- QPNP_PON_REASON1(pon), &pon_sts, 1);
+ rc = regmap_read(pon->regmap, QPNP_PON_REASON1(pon), &pon_sts);
if (rc) {
- dev_err(&pon->spmi->dev, "Unable to read PON_REASON1 reg rc: %d\n",
+ dev_err(&pon->pdev->dev,
+ "Unable to read PON_RESASON1 reg rc: %d\n",
rc);
return rc;
}
@@ -2055,14 +2060,16 @@ static int qpnp_pon_probe(struct spmi_device *spmi)
index = ffs(pon_sts) - 1;
cold_boot = !qpnp_pon_is_warm_reset();
if (index >= ARRAY_SIZE(qpnp_pon_reason) || index < 0) {
- dev_info(&pon->spmi->dev,
+ dev_info(&pon->pdev->dev,
"PMIC@SID%d Power-on reason: Unknown and '%s' boot\n",
- pon->spmi->sid, cold_boot ? "cold" : "warm");
+ to_spmi_device(pon->pdev->dev.parent)->usid,
+ cold_boot ? "cold" : "warm");
} else {
pon->pon_trigger_reason = index;
- dev_info(&pon->spmi->dev,
+ dev_info(&pon->pdev->dev,
"PMIC@SID%d Power-on reason: %s and '%s' boot\n",
- pon->spmi->sid, qpnp_pon_reason[index],
+ to_spmi_device(pon->pdev->dev.parent)->usid,
+ qpnp_pon_reason[index],
cold_boot ? "cold" : "warm");
}
@@ -2073,11 +2080,10 @@ static int qpnp_pon_probe(struct spmi_device *spmi)
if (rc)
return rc;
} else {
- rc = spmi_ext_register_readl(pon->spmi->ctrl, pon->spmi->sid,
- QPNP_POFF_REASON1(pon),
- buf, 2);
+ rc = regmap_bulk_read(pon->regmap, QPNP_POFF_REASON1(pon),
+ buf, 2);
if (rc) {
- dev_err(&pon->spmi->dev, "Unable to read POFF_REASON regs rc:%d\n",
+ dev_err(&pon->pdev->dev, "Unable to read POFF_REASON regs rc:%d\n",
rc);
return rc;
}
@@ -2085,36 +2091,37 @@ static int qpnp_pon_probe(struct spmi_device *spmi)
}
index = ffs(poff_sts) - 1 + reason_index_offset;
if (index >= ARRAY_SIZE(qpnp_poff_reason) || index < 0) {
- dev_info(&pon->spmi->dev,
+ dev_info(&pon->pdev->dev,
"PMIC@SID%d: Unknown power-off reason\n",
- pon->spmi->sid);
+ to_spmi_device(pon->pdev->dev.parent)->usid);
} else {
pon->pon_power_off_reason = index;
- dev_info(&pon->spmi->dev,
+ dev_info(&pon->pdev->dev,
"PMIC@SID%d: Power-off reason: %s\n",
- pon->spmi->sid,
+ to_spmi_device(pon->pdev->dev.parent)->usid,
qpnp_poff_reason[index]);
}
if (pon->pon_trigger_reason == PON_SMPL ||
pon->pon_power_off_reason == QPNP_POFF_REASON_UVLO) {
- if (of_property_read_bool(spmi->dev.of_node,
+ if (of_property_read_bool(pdev->dev.of_node,
"qcom,uvlo-panic"))
panic("An UVLO was occurred.");
}
/* program s3 debounce */
- rc = of_property_read_u32(pon->spmi->dev.of_node,
+ rc = of_property_read_u32(pon->pdev->dev.of_node,
"qcom,s3-debounce", &s3_debounce);
if (rc) {
if (rc != -EINVAL) {
- dev_err(&pon->spmi->dev, "Unable to read s3 timer rc:%d\n",
+ dev_err(&pon->pdev->dev,
+ "Unable to read s3 timer rc:%d\n",
rc);
return rc;
}
} else {
if (s3_debounce > QPNP_PON_S3_TIMER_SECS_MAX) {
- dev_info(&pon->spmi->dev,
+ dev_info(&pon->pdev->dev,
"Exceeded S3 max value, set it to max\n");
s3_debounce = QPNP_PON_S3_TIMER_SECS_MAX;
}
@@ -2127,7 +2134,7 @@ static int qpnp_pon_probe(struct spmi_device *spmi)
rc = qpnp_pon_masked_write(pon, QPNP_PON_SEC_ACCESS(pon),
0xFF, QPNP_PON_SEC_UNLOCK);
if (rc) {
- dev_err(&spmi->dev, "Unable to do SEC_ACCESS rc:%d\n",
+ dev_err(&pdev->dev, "Unable to do SEC_ACCESS rc:%d\n",
rc);
return rc;
}
@@ -2135,7 +2142,8 @@ static int qpnp_pon_probe(struct spmi_device *spmi)
rc = qpnp_pon_masked_write(pon, QPNP_PON_S3_DBC_CTL(pon),
QPNP_PON_S3_DBC_DELAY_MASK, s3_debounce);
if (rc) {
- dev_err(&spmi->dev, "Unable to set S3 debounce rc:%d\n",
+ dev_err(&pdev->dev,
+ "Unable to set S3 debounce rc:%d\n",
rc);
return rc;
}
@@ -2143,10 +2151,10 @@ static int qpnp_pon_probe(struct spmi_device *spmi)
/* program s3 source */
s3_src = "kpdpwr-and-resin";
- rc = of_property_read_string(pon->spmi->dev.of_node,
+ rc = of_property_read_string(pon->pdev->dev.of_node,
"qcom,s3-src", &s3_src);
if (rc && rc != -EINVAL) {
- dev_err(&pon->spmi->dev, "Unable to read s3 timer rc: %d\n",
+ dev_err(&pon->pdev->dev, "Unable to read s3 timer rc: %d\n",
rc);
return rc;
}
@@ -2168,27 +2176,29 @@ static int qpnp_pon_probe(struct spmi_device *spmi)
rc = qpnp_pon_masked_write(pon, QPNP_PON_S3_SRC(pon),
QPNP_PON_S3_SRC_MASK, s3_src_reg);
if (rc) {
- dev_err(&spmi->dev, "Unable to program s3 source rc: %d\n", rc);
+ dev_err(&pdev->dev, "Unable to program s3 source rc: %d\n",
+ rc);
return rc;
}
- dev_set_drvdata(&spmi->dev, pon);
+ dev_set_drvdata(&pdev->dev, pon);
INIT_DELAYED_WORK(&pon->bark_work, bark_work_func);
/* register the PON configurations */
rc = qpnp_pon_config_init(pon);
if (rc) {
- dev_err(&spmi->dev,
+ dev_err(&pdev->dev,
"Unable to initialize PON configurations rc: %d\n", rc);
return rc;
}
- rc = of_property_read_u32(pon->spmi->dev.of_node,
+ rc = of_property_read_u32(pon->pdev->dev.of_node,
"qcom,pon-dbc-delay", &delay);
if (rc) {
if (rc != -EINVAL) {
- dev_err(&spmi->dev, "Unable to read debounce delay rc: %d\n",
+ dev_err(&pdev->dev,
+ "Unable to read debounce delay rc: %d\n",
rc);
return rc;
}
@@ -2196,65 +2206,65 @@ static int qpnp_pon_probe(struct spmi_device *spmi)
rc = qpnp_pon_set_dbc(pon, delay);
}
- rc = of_property_read_u32(pon->spmi->dev.of_node,
+ rc = of_property_read_u32(pon->pdev->dev.of_node,
"qcom,warm-reset-poweroff-type",
&pon->warm_reset_poff_type);
if (rc) {
if (rc != -EINVAL) {
- dev_err(&spmi->dev, "Unable to read warm reset poweroff type rc: %d\n",
+ dev_err(&pdev->dev, "Unable to read warm reset poweroff type rc: %d\n",
rc);
return rc;
}
pon->warm_reset_poff_type = -EINVAL;
} else if (pon->warm_reset_poff_type <= PON_POWER_OFF_RESERVED ||
pon->warm_reset_poff_type >= PON_POWER_OFF_MAX_TYPE) {
- dev_err(&spmi->dev, "Invalid warm-reset-poweroff-type\n");
+ dev_err(&pdev->dev, "Invalid warm-reset-poweroff-type\n");
pon->warm_reset_poff_type = -EINVAL;
}
- rc = of_property_read_u32(pon->spmi->dev.of_node,
+ rc = of_property_read_u32(pon->pdev->dev.of_node,
"qcom,hard-reset-poweroff-type",
&pon->hard_reset_poff_type);
if (rc) {
if (rc != -EINVAL) {
- dev_err(&spmi->dev, "Unable to read hard reset poweroff type rc: %d\n",
+ dev_err(&pdev->dev, "Unable to read hard reset poweroff type rc: %d\n",
rc);
return rc;
}
pon->hard_reset_poff_type = -EINVAL;
} else if (pon->hard_reset_poff_type <= PON_POWER_OFF_RESERVED ||
pon->hard_reset_poff_type >= PON_POWER_OFF_MAX_TYPE) {
- dev_err(&spmi->dev, "Invalid hard-reset-poweroff-type\n");
+ dev_err(&pdev->dev, "Invalid hard-reset-poweroff-type\n");
pon->hard_reset_poff_type = -EINVAL;
}
- rc = of_property_read_u32(pon->spmi->dev.of_node,
+ rc = of_property_read_u32(pon->pdev->dev.of_node,
"qcom,shutdown-poweroff-type",
&pon->shutdown_poff_type);
if (rc) {
if (rc != -EINVAL) {
- dev_err(&spmi->dev, "Unable to read shutdown poweroff type rc: %d\n",
+ dev_err(&pdev->dev, "Unable to read shutdown poweroff type rc: %d\n",
rc);
return rc;
}
pon->shutdown_poff_type = -EINVAL;
} else if (pon->shutdown_poff_type <= PON_POWER_OFF_RESERVED ||
pon->shutdown_poff_type >= PON_POWER_OFF_MAX_TYPE) {
- dev_err(&spmi->dev, "Invalid shutdown-poweroff-type\n");
+ dev_err(&pdev->dev, "Invalid shutdown-poweroff-type\n");
pon->shutdown_poff_type = -EINVAL;
}
- rc = device_create_file(&spmi->dev, &dev_attr_debounce_us);
+ rc = device_create_file(&pdev->dev, &dev_attr_debounce_us);
if (rc) {
- dev_err(&spmi->dev, "sys file creation failed rc: %d\n",
- rc);
+ dev_err(&pdev->dev, "sys file creation failed rc: %d\n", rc);
return rc;
}
- if (of_property_read_bool(spmi->dev.of_node,
+ if (of_property_read_bool(pdev->dev.of_node,
"qcom,secondary-pon-reset")) {
if (sys_reset) {
- dev_err(&spmi->dev, "qcom,system-reset property shouldn't be used along with qcom,secondary-pon-reset property\n");
+ dev_err(&pdev->dev,
+ "qcom,system-reset property shouldn't be used along with qcom,secondary-pon-reset property\n");
return -EINVAL;
}
spin_lock_irqsave(&spon_list_slock, flags);
@@ -2266,26 +2276,25 @@ static int qpnp_pon_probe(struct spmi_device *spmi)
}
/* config whether store the hard reset reason */
- pon->store_hard_reset_reason = of_property_read_bool(
- spmi->dev.of_node,
+ pon->store_hard_reset_reason = of_property_read_bool(pdev->dev.of_node,
"qcom,store-hard-reset-reason");
- qpnp_pon_debugfs_init(spmi);
+ qpnp_pon_debugfs_init(pdev);
return 0;
}
-static int qpnp_pon_remove(struct spmi_device *spmi)
+static int qpnp_pon_remove(struct platform_device *pdev)
{
- struct qpnp_pon *pon = dev_get_drvdata(&spmi->dev);
+ struct qpnp_pon *pon = dev_get_drvdata(&pdev->dev);
unsigned long flags;
- device_remove_file(&spmi->dev, &dev_attr_debounce_us);
+ device_remove_file(&pdev->dev, &dev_attr_debounce_us);
cancel_delayed_work_sync(&pon->bark_work);
if (pon->pon_input)
input_unregister_device(pon->pon_input);
- qpnp_pon_debugfs_remove(spmi);
+ qpnp_pon_debugfs_remove(pdev);
if (pon->is_spon) {
spin_lock_irqsave(&spon_list_slock, flags);
list_del(&pon->list);
@@ -2299,10 +2308,10 @@ static struct of_device_id spmi_match_table[] = {
{}
};
-static struct spmi_driver qpnp_pon_driver = {
+static struct platform_driver qpnp_pon_driver = {
.driver = {
- .name = "qcom,qpnp-power-on",
- .of_match_table = spmi_match_table,
+ .name = "qcom,qpnp-power-on",
+ .of_match_table = spmi_match_table,
},
.probe = qpnp_pon_probe,
.remove = qpnp_pon_remove,
@@ -2310,13 +2319,13 @@ static struct spmi_driver qpnp_pon_driver = {
static int __init qpnp_pon_init(void)
{
- return spmi_driver_register(&qpnp_pon_driver);
+ return platform_driver_register(&qpnp_pon_driver);
}
subsys_initcall(qpnp_pon_init);
static void __exit qpnp_pon_exit(void)
{
- return spmi_driver_unregister(&qpnp_pon_driver);
+ return platform_driver_unregister(&qpnp_pon_driver);
}
module_exit(qpnp_pon_exit);
diff --git a/drivers/platform/msm/qpnp-revid.c b/drivers/platform/msm/qpnp-revid.c
index 4c16a77e9749..0706572d2777 100644
--- a/drivers/platform/msm/qpnp-revid.c
+++ b/drivers/platform/msm/qpnp-revid.c
@@ -13,8 +13,11 @@
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/spmi.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
#include <linux/err.h>
#include <linux/qpnp/qpnp-revid.h>
+#include <linux/of.h>
#define REVID_REVISION1 0x0
#define REVID_REVISION2 0x1
@@ -66,17 +69,17 @@ static struct of_device_id qpnp_revid_match_table[] = {
{}
};
-static u8 qpnp_read_byte(struct spmi_device *spmi, u16 addr)
+static u8 qpnp_read_byte(struct regmap *regmap, u16 addr)
{
int rc;
- u8 val;
+ int val;
- rc = spmi_ext_register_readl(spmi->ctrl, spmi->sid, addr, &val, 1);
+ rc = regmap_read(regmap, addr, &val);
if (rc) {
- pr_err("SPMI read failed rc=%d\n", rc);
+ pr_err("read failed rc=%d\n", rc);
return 0;
}
- return val;
+ return (u8)val;
}
/**
@@ -145,51 +148,60 @@ static size_t build_pmic_string(char *buf, size_t n, int sid,
#define PMIC_PERIPHERAL_TYPE 0x51
#define PMIC_STRING_MAXLENGTH 80
-static int qpnp_revid_probe(struct spmi_device *spmi)
+static int qpnp_revid_probe(struct platform_device *pdev)
{
u8 rev1, rev2, rev3, rev4, pmic_type, pmic_subtype, pmic_status;
u8 option1, option2, option3, option4, spare0;
- struct resource *resource;
+ unsigned int base;
+ int rc;
char pmic_string[PMIC_STRING_MAXLENGTH] = {'\0'};
struct revid_chip *revid_chip;
+ struct regmap *regmap;
- resource = spmi_get_resource(spmi, NULL, IORESOURCE_MEM, 0);
- if (!resource) {
- pr_err("Unable to get spmi resource for REVID\n");
+ regmap = dev_get_regmap(pdev->dev.parent, NULL);
+ if (!regmap) {
+ dev_err(&pdev->dev, "Couldn't get parent's regmap\n");
return -EINVAL;
}
- pmic_type = qpnp_read_byte(spmi, resource->start + REVID_TYPE);
+
+ rc = of_property_read_u32(pdev->dev.of_node, "reg", &base);
+ if (rc < 0) {
+ dev_err(&pdev->dev,
+ "Couldn't find reg in node = %s rc = %d\n",
+ pdev->dev.of_node->full_name, rc);
+ return rc;
+ }
+ pmic_type = qpnp_read_byte(regmap, base + REVID_TYPE);
if (pmic_type != PMIC_PERIPHERAL_TYPE) {
pr_err("Invalid REVID peripheral type: %02X\n", pmic_type);
return -EINVAL;
}
- rev1 = qpnp_read_byte(spmi, resource->start + REVID_REVISION1);
- rev2 = qpnp_read_byte(spmi, resource->start + REVID_REVISION2);
- rev3 = qpnp_read_byte(spmi, resource->start + REVID_REVISION3);
- rev4 = qpnp_read_byte(spmi, resource->start + REVID_REVISION4);
+ rev1 = qpnp_read_byte(regmap, base + REVID_REVISION1);
+ rev2 = qpnp_read_byte(regmap, base + REVID_REVISION2);
+ rev3 = qpnp_read_byte(regmap, base + REVID_REVISION3);
+ rev4 = qpnp_read_byte(regmap, base + REVID_REVISION4);
- pmic_subtype = qpnp_read_byte(spmi, resource->start + REVID_SUBTYPE);
+ pmic_subtype = qpnp_read_byte(regmap, base + REVID_SUBTYPE);
if (pmic_subtype != PMD9655_PERIPHERAL_SUBTYPE)
- pmic_status = qpnp_read_byte(spmi,
- resource->start + REVID_STATUS1);
+ pmic_status = qpnp_read_byte(regmap, base + REVID_STATUS1);
else
pmic_status = 0;
/* special case for PMI8937 */
if (pmic_subtype == PMI8950_PERIPHERAL_SUBTYPE) {
/* read spare register */
- spare0 = qpnp_read_byte(spmi, resource->start + REVID_SPARE_0);
+ spare0 = qpnp_read_byte(regmap, base + REVID_SPARE_0);
if (spare0)
pmic_subtype = PMI8937_PERIPHERAL_SUBTYPE;
}
- revid_chip = devm_kzalloc(&spmi->dev, sizeof(struct revid_chip),
+ revid_chip = devm_kzalloc(&pdev->dev, sizeof(struct revid_chip),
GFP_KERNEL);
if (!revid_chip)
return -ENOMEM;
- revid_chip->dev_node = spmi->dev.of_node;
+ revid_chip->dev_node = pdev->dev.of_node;
revid_chip->data.rev1 = rev1;
revid_chip->data.rev2 = rev2;
revid_chip->data.rev3 = rev3;
@@ -211,14 +223,15 @@ static int qpnp_revid_probe(struct spmi_device *spmi)
option3 = (pmic_status >> 4) & 0x3;
option4 = (pmic_status >> 6) & 0x3;
- build_pmic_string(pmic_string, PMIC_STRING_MAXLENGTH, spmi->sid,
+ build_pmic_string(pmic_string, PMIC_STRING_MAXLENGTH,
+ to_spmi_device(pdev->dev.parent)->usid,
pmic_subtype, rev1, rev2, rev3, rev4);
pr_info("%s options: %d, %d, %d, %d\n",
pmic_string, option1, option2, option3, option4);
return 0;
}
-static struct spmi_driver qpnp_revid_driver = {
+static struct platform_driver qpnp_revid_driver = {
.probe = qpnp_revid_probe,
.driver = {
.name = QPNP_REVID_DEV_NAME,
@@ -229,12 +242,12 @@ static struct spmi_driver qpnp_revid_driver = {
static int __init qpnp_revid_init(void)
{
- return spmi_driver_register(&qpnp_revid_driver);
+ return platform_driver_register(&qpnp_revid_driver);
}
static void __exit qpnp_revid_exit(void)
{
- return spmi_driver_unregister(&qpnp_revid_driver);
+ return platform_driver_unregister(&qpnp_revid_driver);
}
subsys_initcall(qpnp_revid_init);
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index 4db923cc870e..9a6bd0ca1935 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -449,6 +449,130 @@ config CHARGER_SMB347
Say Y to include support for Summit Microelectronics SMB347
Battery Charger.
+config SMB349_USB_CHARGER
+ tristate "smb349 usb charger (with VBUS detection)"
+ depends on I2C
+ help
+ Say Y to enable support for the SMB349 switching mode based charger.
+ The driver supports charging control (enable/disable) and
+ charge-current limiting. It also provides USB VBUS detection and
+ notification support. The driver controls SMB349 via I2C and
+ supports device-tree interface.
+
+config SMB349_DUAL_CHARGER
+ tristate "smb349 dual charger"
+ depends on I2C
+ help
+ Say Y to enable support for the SMB349 dual charger single path
+ switching mode charger. The driver supports charging in conjuction
+ with an external charger on the same path by providing hand-off
+ control and charge-current limiting. The driver controls SMB349
+ via I2C in STAT IRQ driven mode and supports device-tree interface.
+
+config SMB1351_USB_CHARGER
+ tristate "smb1351 usb charger (with VBUS detection)"
+ depends on I2C
+ help
+ Say Y to enable support for the SMB1351 switching mode based charger.
+ The driver supports charging control (enable/disable) and
+ charge-current limiting. It also provides USB VBUS detection and
+ notification support. The driver controls SMB1351 via I2C and
+ supports device-tree interface.
+
+config SMB350_CHARGER
+ tristate "smb350 charger"
+ depends on I2C
+ help
+ Say Y to enable battery charging by SMB350 switching mode based
+ external charger. The device supports stack-cell battery charging.
+ The driver configures the device volatile parameters
+ and the charger device works autonomously.
+ The driver supports charger-enable and charger-suspend/resume.
+ The driver reports the charger status via the power supply framework.
+ A charger status change triggers an IRQ via the device STAT pin.
+
+config SMB135X_CHARGER
+ tristate "SMB135X Battery Charger"
+ depends on I2C
+ help
+ Say Y to include support for SMB135X Battery Charger.
+ SMB135X is a dual path switching mode charger capable of charging
+ the battery with 3Amps of current.
+ The driver supports charger enable/disable.
+ The driver reports the charger status via the power supply framework.
+ A charger status change triggers an IRQ via the device STAT pin.
+
+config SMB1360_CHARGER_FG
+ tristate "SMB1360 Charger and Fuel Guage"
+ depends on I2C
+ help
+ Say Y to include support for SMB1360 Charger and Fuel Guage.
+ SMB1360 is a single path switching mode charger capable of charging
+ the battery with 1.5Amps of current. It supports a fuel gauge which
+ uses voltage and coloumb counting for state of charge reporting.
+ The driver reports the status via the power supply framework.
+ A status change triggers an IRQ via the device STAT pin.
+
+config SMB358_CHARGER
+ tristate "SMB358 Battery Charger"
+ depends on I2C
+ help
+ Say Y to include support for SMB358 Battery Charger.
+ SMB358 is a single path switching mode charger capable of charging
+ the battery with 2Amps of current.
+ The driver supports charger enable/disable.
+ The driver reports the charger status via the power supply framework.
+ A charger status change triggers an IRQ via the device STAT pin.
+
+config BATTERY_BQ28400
+ tristate "BQ28400 battery driver"
+ depends on I2C
+ default n
+ help
+ Say Y here to enable support for batteries with BQ28400 (I2C) chips.
+ The bq28400 Texas Instruments Inc device monitors the battery
+ charging/discharging status via Rsens resistor, typically 10 mohm.
+ It monitors the battery temperature via Thermistor.
+ The device monitors the battery level (Relative-State-Of-Charge).
+ The device is SBS compliant, providing battery info over I2C.
+
+config QPNP_CHARGER
+ tristate "QPNP Charger driver"
+ depends on SPMI
+ depends on THERMAL_QPNP_ADC_TM
+ help
+ Say Y here to enable the switch mode battery charger
+ and boost device which supports USB detection and charging. The driver
+ also offers relevant information to userspace via the power supply
+ framework.
+
+config QPNP_SMBCHARGER
+ tristate "QPNP SMB Charger driver"
+ depends on SPMI
+ help
+ Say Y here to enable the dual path switch mode battery charger which
+ supports USB detection and battery charging up to 3A.
+ The driver also offers relevant information to userspace via the
+ power supply framework.
+
+config QPNP_FG
+ tristate "QPNP fuel gauge driver"
+ depends on SPMI
+ help
+ Say Y here to enable the Fuel Gauge driver. This adds support for
+ battery fuel gauging and state of charge of battery connected to the
+ fuel gauge. The state of charge is reported through a BMS power
+ supply property and also sends uevents when the capacity is updated.
+
+config BATTERY_BCL
+ tristate "Battery Current Limit driver"
+ depends on THERMAL_MONITOR
+ help
+ Say Y here to enable support for battery current limit
+ device. The BCL driver will poll BMS if
+ thermal daemon enables BCL.
+ It will notify thermal daemon if IBat crosses Imax threshold.
+
config CHARGER_TPS65090
tristate "TPS65090 battery charger driver"
depends on MFD_TPS65090
@@ -510,8 +634,7 @@ config AXP20X_POWER
config QPNP_SMBCHARGER
tristate "QPNP SMB Charger driver"
- depends on SPMI || MSM_SPMI
- depends on OF_SPMI
+ depends on SPMI
help
Say Y here to enable the dual path switch mode battery charger which
supports USB detection and battery charging up to 3A.
@@ -520,8 +643,7 @@ config QPNP_SMBCHARGER
config QPNP_FG
tristate "QPNP fuel gauge driver"
- depends on SPMI || MSM_SPMI
- depends on OF_SPMI
+ depends on SPMI
help
Say Y here to enable the Fuel Gauge driver. This adds support for
battery fuel gauging and state of charge of battery connected to the
@@ -559,7 +681,7 @@ config MSM_BCL_CTL
config MSM_BCL_PERIPHERAL_CTL
bool "BCL driver to control the PMIC BCL peripheral"
- depends on SPMI || MSM_SPMI
+ depends on SPMI
depends on MSM_BCL_CTL
help
Say Y here to enable this BCL PMIC peripheral driver. This driver
diff --git a/drivers/power/bcl_peripheral.c b/drivers/power/bcl_peripheral.c
index 00f8f9db1694..d655b54979a0 100644
--- a/drivers/power/bcl_peripheral.c
+++ b/drivers/power/bcl_peripheral.c
@@ -18,11 +18,13 @@
#include <linux/interrupt.h>
#include <linux/workqueue.h>
#include <linux/kernel.h>
+#include <linux/regmap.h>
#include <linux/io.h>
#include <linux/err.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/spmi.h>
+#include <linux/platform_device.h>
#include <linux/mutex.h>
#include <linux/msm_bcl.h>
#include <linux/power_supply.h>
@@ -114,14 +116,14 @@ struct bcl_peripheral_data {
};
struct bcl_device {
- bool enabled;
- struct device *dev;
- struct spmi_device *spmi;
- uint16_t base_addr;
- uint16_t pon_spare_addr;
- uint8_t slave_id;
- int i_src;
- struct bcl_peripheral_data param[BCL_PARAM_MAX];
+ bool enabled;
+ struct device *dev;
+ struct platform_device *pdev;
+ struct regmap *regmap;
+ uint16_t base_addr;
+ uint16_t pon_spare_addr;
+ int i_src;
+ struct bcl_peripheral_data param[BCL_PARAM_MAX];
};
static struct bcl_device *bcl_perph;
@@ -139,9 +141,8 @@ static int bcl_read_multi_register(int16_t reg_offset, uint8_t *data, int len)
pr_err("BCL device not initialized\n");
return -EINVAL;
}
- ret = spmi_ext_register_readl(bcl_perph->spmi->ctrl,
- bcl_perph->slave_id, (bcl_perph->base_addr + reg_offset),
- data, len);
+ ret = regmap_bulk_read(bcl_perph->regmap,
+ (bcl_perph->base_addr + reg_offset), data, len);
if (ret < 0) {
pr_err("Error reading register %d. err:%d", reg_offset, ret);
return ret;
@@ -171,9 +172,7 @@ static int bcl_write_general_register(int16_t reg_offset,
pr_err("BCL device not initialized\n");
return -EINVAL;
}
- ret = spmi_ext_register_writel(bcl_perph->spmi->ctrl,
- bcl_perph->slave_id, (base + reg_offset),
- write_buf, 1);
+ ret = regmap_write(bcl_perph->regmap, (base + reg_offset), *write_buf);
if (ret < 0) {
pr_err("Error reading register %d. err:%d", reg_offset, ret);
return ret;
@@ -773,28 +772,19 @@ exit_intr:
return IRQ_HANDLED;
}
-static int bcl_get_devicetree_data(struct spmi_device *spmi)
+static int bcl_get_devicetree_data(struct platform_device *pdev)
{
int ret = 0, irq_num = 0, temp_val = 0;
- struct resource *resource = NULL;
char *key = NULL;
const __be32 *prop = NULL;
- struct device_node *dev_node = spmi->dev.of_node;
+ struct device_node *dev_node = pdev->dev.of_node;
- /* Get SPMI peripheral address */
- resource = spmi_get_resource(spmi, NULL, IORESOURCE_MEM, 0);
- if (!resource) {
- pr_err("No base address defined\n");
- return -EINVAL;
- }
- bcl_perph->slave_id = spmi->sid;
- prop = of_get_address_by_name(dev_node,
- "fg_user_adc", 0, 0);
+ prop = of_get_address_by_name(dev_node, "fg_user_adc", 0, 0);
if (prop) {
bcl_perph->base_addr = be32_to_cpu(*prop);
pr_debug("fg_user_adc@%04x\n", bcl_perph->base_addr);
} else {
- dev_err(&spmi->dev, "No fg_user_adc registers found\n");
+ dev_err(&pdev->dev, "No fg_user_adc registers found\n");
return -EINVAL;
}
@@ -806,16 +796,14 @@ static int bcl_get_devicetree_data(struct spmi_device *spmi)
}
/* Register SPMI peripheral interrupt */
- irq_num = spmi_get_irq_byname(spmi, NULL,
- BCL_VBAT_INT_NAME);
+ irq_num = platform_get_irq_byname(pdev, BCL_VBAT_INT_NAME);
if (irq_num < 0) {
pr_err("Invalid vbat IRQ\n");
ret = -ENXIO;
goto bcl_dev_exit;
}
bcl_perph->param[BCL_PARAM_VOLTAGE].irq_num = irq_num;
- irq_num = spmi_get_irq_byname(spmi, NULL,
- BCL_IBAT_INT_NAME);
+ irq_num = platform_get_irq_byname(pdev, BCL_IBAT_INT_NAME);
if (irq_num < 0) {
pr_err("Invalid ibat IRQ\n");
ret = -ENXIO;
@@ -1009,20 +997,25 @@ update_data_exit:
return ret;
}
-static int bcl_probe(struct spmi_device *spmi)
+static int bcl_probe(struct platform_device *pdev)
{
int ret = 0;
- bcl_perph = devm_kzalloc(&spmi->dev, sizeof(struct bcl_device),
+ bcl_perph = devm_kzalloc(&pdev->dev, sizeof(struct bcl_device),
GFP_KERNEL);
if (!bcl_perph) {
pr_err("Memory alloc failed\n");
return -ENOMEM;
}
- bcl_perph->spmi = spmi;
- bcl_perph->dev = &(spmi->dev);
+ bcl_perph->regmap = dev_get_regmap(pdev->dev.parent, NULL);
+ if (!bcl_perph->regmap) {
+ dev_err(&pdev->dev, "Couldn't get parent's regmap\n");
+ return -EINVAL;
+ }
+ bcl_perph->pdev = pdev;
+ bcl_perph->dev = &(pdev->dev);
- ret = bcl_get_devicetree_data(spmi);
+ ret = bcl_get_devicetree_data(pdev);
if (ret) {
pr_err("Device tree data fetch error. err:%d", ret);
goto bcl_probe_exit;
@@ -1038,7 +1031,7 @@ static int bcl_probe(struct spmi_device *spmi)
bcl_psy.set_property = bcl_psy_set_property;
bcl_psy.num_properties = 0;
bcl_psy.external_power_changed = power_supply_callback;
- ret = power_supply_register(&spmi->dev, &bcl_psy);
+ ret = power_supply_register(&pdev->dev, &bcl_psy);
if (ret < 0) {
pr_err("Unable to register bcl_psy rc = %d\n", ret);
return ret;
@@ -1050,14 +1043,14 @@ static int bcl_probe(struct spmi_device *spmi)
goto bcl_probe_exit;
}
mutex_lock(&bcl_perph->param[BCL_PARAM_VOLTAGE].state_trans_lock);
- ret = devm_request_threaded_irq(&spmi->dev,
+ ret = devm_request_threaded_irq(&pdev->dev,
bcl_perph->param[BCL_PARAM_VOLTAGE].irq_num,
NULL, bcl_handle_vbat,
IRQF_TRIGGER_RISING | IRQF_ONESHOT,
"bcl_vbat_interrupt",
&bcl_perph->param[BCL_PARAM_VOLTAGE]);
if (ret) {
- dev_err(&spmi->dev, "Error requesting VBAT irq. err:%d", ret);
+ dev_err(&pdev->dev, "Error requesting VBAT irq. err:%d", ret);
mutex_unlock(
&bcl_perph->param[BCL_PARAM_VOLTAGE].state_trans_lock);
goto bcl_probe_exit;
@@ -1070,14 +1063,14 @@ static int bcl_probe(struct spmi_device *spmi)
mutex_unlock(&bcl_perph->param[BCL_PARAM_VOLTAGE].state_trans_lock);
mutex_lock(&bcl_perph->param[BCL_PARAM_CURRENT].state_trans_lock);
- ret = devm_request_threaded_irq(&spmi->dev,
+ ret = devm_request_threaded_irq(&pdev->dev,
bcl_perph->param[BCL_PARAM_CURRENT].irq_num,
NULL, bcl_handle_ibat,
IRQF_TRIGGER_RISING | IRQF_ONESHOT,
"bcl_ibat_interrupt",
&bcl_perph->param[BCL_PARAM_CURRENT]);
if (ret) {
- dev_err(&spmi->dev, "Error requesting IBAT irq. err:%d", ret);
+ dev_err(&pdev->dev, "Error requesting IBAT irq. err:%d", ret);
mutex_unlock(
&bcl_perph->param[BCL_PARAM_CURRENT].state_trans_lock);
goto bcl_probe_exit;
@@ -1085,7 +1078,7 @@ static int bcl_probe(struct spmi_device *spmi)
disable_irq_nosync(bcl_perph->param[BCL_PARAM_CURRENT].irq_num);
mutex_unlock(&bcl_perph->param[BCL_PARAM_CURRENT].state_trans_lock);
- dev_set_drvdata(&spmi->dev, bcl_perph);
+ dev_set_drvdata(&pdev->dev, bcl_perph);
ret = bcl_write_register(BCL_MONITOR_EN, BIT(7));
if (ret) {
pr_err("Error accessing BCL peripheral. err:%d\n", ret);
@@ -1099,7 +1092,7 @@ bcl_probe_exit:
return ret;
}
-static int bcl_remove(struct spmi_device *spmi)
+static int bcl_remove(struct platform_device *pdev)
{
int ret = 0, i = 0;
@@ -1126,25 +1119,25 @@ static struct of_device_id bcl_match[] = {
{},
};
-static struct spmi_driver bcl_driver = {
- .probe = bcl_probe,
- .remove = bcl_remove,
- .driver = {
- .name = BCL_DRIVER_NAME,
- .owner = THIS_MODULE,
- .of_match_table = bcl_match,
+static struct platform_driver bcl_driver = {
+ .probe = bcl_probe,
+ .remove = bcl_remove,
+ .driver = {
+ .name = BCL_DRIVER_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = bcl_match,
},
};
static int __init bcl_perph_init(void)
{
pr_info("BCL Initialized\n");
- return spmi_driver_register(&bcl_driver);
+ return platform_driver_register(&bcl_driver);
}
static void __exit bcl_perph_exit(void)
{
- spmi_driver_unregister(&bcl_driver);
+ platform_driver_unregister(&bcl_driver);
}
fs_initcall(bcl_perph_init);
module_exit(bcl_perph_exit);
diff --git a/drivers/power/qpnp-fg.c b/drivers/power/qpnp-fg.c
index a9cffbc59eaf..f5e358c0b11c 100644
--- a/drivers/power/qpnp-fg.c
+++ b/drivers/power/qpnp-fg.c
@@ -15,6 +15,7 @@
#include <linux/atomic.h>
#include <linux/delay.h>
#include <linux/kernel.h>
+#include <linux/regmap.h>
#include <linux/of.h>
#include <linux/rtc.h>
#include <linux/err.h>
@@ -23,6 +24,7 @@
#include <linux/uaccess.h>
#include <linux/init.h>
#include <linux/spmi.h>
+#include <linux/platform_device.h>
#include <linux/of_irq.h>
#include <linux/interrupt.h>
#include <linux/bitops.h>
@@ -396,7 +398,8 @@ static void fg_relax(struct fg_wakeup_source *source)
#define THERMAL_COEFF_N_BYTES 6
struct fg_chip {
struct device *dev;
- struct spmi_device *spmi;
+ struct platform_device *pdev;
+ struct regmap *regmap;
u8 pmic_subtype;
u8 pmic_revision[4];
u8 revision[4];
@@ -591,19 +594,19 @@ static void fill_string(char *str, size_t str_len, u8 *buf, int buf_len)
static int fg_write(struct fg_chip *chip, u8 *val, u16 addr, int len)
{
int rc = 0;
- struct spmi_device *spmi = chip->spmi;
+ struct platform_device *pdev = chip->pdev;
char str[DEBUG_PRINT_BUFFER_SIZE];
if ((addr & 0xff00) == 0) {
pr_err("addr cannot be zero base=0x%02x sid=0x%02x rc=%d\n",
- addr, spmi->sid, rc);
+ addr, to_spmi_device(pdev->dev.parent)->usid, rc);
return -EINVAL;
}
- rc = spmi_ext_register_writel(spmi->ctrl, spmi->sid, addr, val, len);
+ rc = regmap_bulk_write(chip->regmap, addr, val, len);
if (rc) {
pr_err("write failed addr=0x%02x sid=0x%02x rc=%d\n",
- addr, spmi->sid, rc);
+ addr, to_spmi_device(pdev->dev.parent)->usid, rc);
return rc;
}
@@ -611,7 +614,8 @@ static int fg_write(struct fg_chip *chip, u8 *val, u16 addr, int len)
str[0] = '\0';
fill_string(str, DEBUG_PRINT_BUFFER_SIZE, val, len);
pr_info("write(0x%04X), sid=%d, len=%d; %s\n",
- addr, spmi->sid, len, str);
+ addr, to_spmi_device(pdev->dev.parent)->usid, len,
+ str);
}
return rc;
@@ -620,19 +624,19 @@ static int fg_write(struct fg_chip *chip, u8 *val, u16 addr, int len)
static int fg_read(struct fg_chip *chip, u8 *val, u16 addr, int len)
{
int rc = 0;
- struct spmi_device *spmi = chip->spmi;
+ struct platform_device *pdev = chip->pdev;
char str[DEBUG_PRINT_BUFFER_SIZE];
if ((addr & 0xff00) == 0) {
pr_err("base cannot be zero base=0x%02x sid=0x%02x rc=%d\n",
- addr, spmi->sid, rc);
+ addr, to_spmi_device(pdev->dev.parent)->usid, rc);
return -EINVAL;
}
- rc = spmi_ext_register_readl(spmi->ctrl, spmi->sid, addr, val, len);
+ rc = regmap_bulk_read(chip->regmap, addr, val, len);
if (rc) {
pr_err("SPMI read failed base=0x%02x sid=0x%02x rc=%d\n", addr,
- spmi->sid, rc);
+ to_spmi_device(pdev->dev.parent)->usid, rc);
return rc;
}
@@ -640,7 +644,8 @@ static int fg_read(struct fg_chip *chip, u8 *val, u16 addr, int len)
str[0] = '\0';
fill_string(str, DEBUG_PRINT_BUFFER_SIZE, val, len);
pr_info("read(0x%04x), sid=%d, len=%d; %s\n",
- addr, spmi->sid, len, str);
+ addr, to_spmi_device(pdev->dev.parent)->usid, len,
+ str);
}
return rc;
@@ -650,21 +655,8 @@ static int fg_masked_write(struct fg_chip *chip, u16 addr,
u8 mask, u8 val, int len)
{
int rc;
- u8 reg;
-
- rc = fg_read(chip, &reg, addr, len);
- if (rc) {
- pr_err("spmi read failed: addr=%03X, rc=%d\n", addr, rc);
- return rc;
- }
- pr_debug("addr = 0x%x read 0x%x\n", addr, reg);
-
- reg &= ~mask;
- reg |= val & mask;
-
- pr_debug("Writing 0x%x\n", reg);
- rc = fg_write(chip, &reg, addr, len);
+ rc = regmap_update_bits(chip->regmap, addr, mask, val);
if (rc) {
pr_err("spmi write failed: addr=%03X, rc=%d\n", addr, rc);
return rc;
@@ -4563,7 +4555,7 @@ static int fg_batt_profile_init(struct fg_chip *chip)
{
int rc = 0, ret;
int len;
- struct device_node *node = chip->spmi->dev.of_node;
+ struct device_node *node = chip->pdev->dev.of_node;
struct device_node *batt_node, *profile_node;
const char *data, *batt_type_str;
bool tried_again = false, vbat_in_range, profiles_same;
@@ -4642,7 +4634,7 @@ wait:
* Only configure from profile if fg-cc-cv-threshold-mv is not
* defined in the charger device node.
*/
- if (!of_find_property(chip->spmi->dev.of_node,
+ if (!of_find_property(chip->pdev->dev.of_node,
"qcom,fg-cc-cv-threshold-mv", NULL)) {
of_property_read_u32(profile_node,
"qcom,fg-cc-cv-threshold-mv",
@@ -4757,7 +4749,7 @@ wait:
* Only configure from profile if thermal-coefficients is not
* defined in the FG device node.
*/
- if (!of_find_property(chip->spmi->dev.of_node,
+ if (!of_find_property(chip->pdev->dev.of_node,
"qcom,thermal-coefficients", NULL)) {
data = of_get_property(profile_node,
"qcom,thermal-coefficients", &len);
@@ -5048,7 +5040,7 @@ do { \
if (retval) \
break; \
\
- retval = of_property_read_u32(chip->spmi->dev.of_node, \
+ retval = of_property_read_u32(chip->pdev->dev.of_node, \
"qcom," qpnp_dt_property, \
&settings[type].value); \
\
@@ -5064,7 +5056,7 @@ do { \
if (retval) \
break; \
\
- retval = of_property_read_u32(chip->spmi->dev.of_node, \
+ retval = of_property_read_u32(chip->pdev->dev.of_node, \
"qcom," qpnp_dt_property, \
&store); \
\
@@ -5082,7 +5074,7 @@ static int fg_of_init(struct fg_chip *chip)
{
int rc = 0, sense_type, len = 0;
const char *data;
- struct device_node *node = chip->spmi->dev.of_node;
+ struct device_node *node = chip->pdev->dev.of_node;
u32 temp[2] = {0};
OF_READ_SETTING(FG_MEM_SOFT_HOT, "warm-bat-decidegc", rc, 1);
@@ -5126,7 +5118,7 @@ static int fg_of_init(struct fg_chip *chip)
OF_READ_SETTING(FG_MEM_TERM_CURRENT, "fg-iterm-ma", rc, 1);
OF_READ_SETTING(FG_MEM_CHG_TERM_CURRENT, "fg-chg-iterm-ma", rc, 1);
OF_READ_SETTING(FG_MEM_CUTOFF_VOLTAGE, "fg-cutoff-voltage-mv", rc, 1);
- data = of_get_property(chip->spmi->dev.of_node,
+ data = of_get_property(chip->pdev->dev.of_node,
"qcom,thermal-coefficients", &len);
if (data && len == THERMAL_COEFF_N_BYTES) {
memcpy(chip->thermal_coefficients, data, len);
@@ -5159,31 +5151,30 @@ static int fg_of_init(struct fg_chip *chip)
DEFAULT_EVALUATION_CURRENT_MA);
OF_READ_PROPERTY(chip->cc_cv_threshold_mv,
"fg-cc-cv-threshold-mv", rc, 0);
- if (of_property_read_bool(chip->spmi->dev.of_node,
+ if (of_property_read_bool(chip->pdev->dev.of_node,
"qcom,capacity-learning-on"))
chip->batt_aging_mode = FG_AGING_CC;
- else if (of_property_read_bool(chip->spmi->dev.of_node,
+ else if (of_property_read_bool(chip->pdev->dev.of_node,
"qcom,capacity-estimation-on"))
chip->batt_aging_mode = FG_AGING_ESR;
else
chip->batt_aging_mode = FG_AGING_NONE;
if (chip->batt_aging_mode == FG_AGING_CC) {
- chip->learning_data.feedback_on = of_property_read_bool(
- chip->spmi->dev.of_node,
+ chip->learning_data.feedback_on
+ = of_property_read_bool(chip->pdev->dev.of_node,
"qcom,capacity-learning-feedback");
}
if (fg_debug_mask & FG_AGING)
pr_info("battery aging mode: %d\n", chip->batt_aging_mode);
/* Get the use-otp-profile property */
- chip->use_otp_profile = of_property_read_bool(
- chip->spmi->dev.of_node,
+ chip->use_otp_profile = of_property_read_bool(chip->pdev->dev.of_node,
"qcom,use-otp-profile");
- chip->hold_soc_while_full = of_property_read_bool(
- chip->spmi->dev.of_node,
+ chip->hold_soc_while_full
+ = of_property_read_bool(chip->pdev->dev.of_node,
"qcom,hold-soc-while-full");
- sense_type = of_property_read_bool(chip->spmi->dev.of_node,
+ sense_type = of_property_read_bool(chip->pdev->dev.of_node,
"qcom,ext-sense-type");
if (rc == 0) {
if (fg_sense_type < 0)
@@ -5218,32 +5209,32 @@ static int fg_of_init(struct fg_chip *chip)
static int fg_init_irqs(struct fg_chip *chip)
{
int rc = 0;
- struct resource *resource;
- struct spmi_resource *spmi_resource;
+ unsigned int base;
+ struct device_node *child;
u8 subtype;
- struct spmi_device *spmi = chip->spmi;
+ struct platform_device *pdev = chip->pdev;
- spmi_for_each_container_dev(spmi_resource, spmi) {
- if (!spmi_resource) {
- pr_err("fg: spmi resource absent\n");
- return rc;
- }
+ if (of_get_available_child_count(pdev->dev.of_node) == 0) {
+ pr_err("no child nodes\n");
+ return -ENXIO;
+ }
- resource = spmi_get_resource(spmi, spmi_resource,
- IORESOURCE_MEM, 0);
- if (!(resource && resource->start)) {
- pr_err("node %s IO resource absent!\n",
- spmi->dev.of_node->full_name);
+ for_each_available_child_of_node(pdev->dev.of_node, child) {
+ rc = of_property_read_u32(child, "reg", &base);
+ if (rc < 0) {
+ dev_err(&pdev->dev,
+ "Couldn't find reg in node = %s rc = %d\n",
+ child->full_name, rc);
return rc;
}
- if ((resource->start == chip->vbat_adc_addr) ||
- (resource->start == chip->ibat_adc_addr) ||
- (resource->start == chip->tp_rev_addr))
+ if ((base == chip->vbat_adc_addr) ||
+ (base == chip->ibat_adc_addr) ||
+ (base == chip->tp_rev_addr))
continue;
rc = fg_read(chip, &subtype,
- resource->start + REG_OFFSET_PERP_SUBTYPE, 1);
+ base + REG_OFFSET_PERP_SUBTYPE, 1);
if (rc) {
pr_err("Peripheral subtype read failed rc=%d\n", rc);
return rc;
@@ -5251,26 +5242,26 @@ static int fg_init_irqs(struct fg_chip *chip)
switch (subtype) {
case FG_SOC:
- chip->soc_irq[FULL_SOC].irq = spmi_get_irq_byname(
- chip->spmi, spmi_resource, "full-soc");
+ chip->soc_irq[FULL_SOC].irq = of_irq_get_byname(child,
+ "full-soc");
if (chip->soc_irq[FULL_SOC].irq < 0) {
pr_err("Unable to get full-soc irq\n");
return rc;
}
- chip->soc_irq[EMPTY_SOC].irq = spmi_get_irq_byname(
- chip->spmi, spmi_resource, "empty-soc");
+ chip->soc_irq[EMPTY_SOC].irq = of_irq_get_byname(child,
+ "empty-soc");
if (chip->soc_irq[EMPTY_SOC].irq < 0) {
pr_err("Unable to get low-soc irq\n");
return rc;
}
- chip->soc_irq[DELTA_SOC].irq = spmi_get_irq_byname(
- chip->spmi, spmi_resource, "delta-soc");
+ chip->soc_irq[DELTA_SOC].irq = of_irq_get_byname(child,
+ "delta-soc");
if (chip->soc_irq[DELTA_SOC].irq < 0) {
pr_err("Unable to get delta-soc irq\n");
return rc;
}
- chip->soc_irq[FIRST_EST_DONE].irq = spmi_get_irq_byname(
- chip->spmi, spmi_resource, "first-est-done");
+ chip->soc_irq[FIRST_EST_DONE].irq
+ = of_irq_get_byname(child, "first-est-done");
if (chip->soc_irq[FIRST_EST_DONE].irq < 0) {
pr_err("Unable to get first-est-done irq\n");
return rc;
@@ -5319,8 +5310,8 @@ static int fg_init_irqs(struct fg_chip *chip)
enable_irq_wake(chip->soc_irq[EMPTY_SOC].irq);
break;
case FG_MEMIF:
- chip->mem_irq[FG_MEM_AVAIL].irq = spmi_get_irq_byname(
- chip->spmi, spmi_resource, "mem-avail");
+ chip->mem_irq[FG_MEM_AVAIL].irq
+ = of_irq_get_byname(child, "mem-avail");
if (chip->mem_irq[FG_MEM_AVAIL].irq < 0) {
pr_err("Unable to get mem-avail irq\n");
return rc;
@@ -5338,9 +5329,8 @@ static int fg_init_irqs(struct fg_chip *chip)
}
break;
case FG_BATT:
- chip->batt_irq[BATT_MISSING].irq = spmi_get_irq_byname(
- chip->spmi, spmi_resource,
- "batt-missing");
+ chip->batt_irq[BATT_MISSING].irq
+ = of_irq_get_byname(child, "batt-missing");
if (chip->batt_irq[BATT_MISSING].irq < 0) {
pr_err("Unable to get batt-missing irq\n");
rc = -EINVAL;
@@ -5359,9 +5349,8 @@ static int fg_init_irqs(struct fg_chip *chip)
chip->batt_irq[BATT_MISSING].irq, rc);
return rc;
}
- chip->batt_irq[VBATT_LOW].irq = spmi_get_irq_byname(
- chip->spmi, spmi_resource,
- "vbatt-low");
+ chip->batt_irq[VBATT_LOW].irq
+ = of_irq_get_byname(child, "vbatt-low");
if (chip->batt_irq[VBATT_LOW].irq < 0) {
pr_err("Unable to get vbatt-low irq\n");
rc = -EINVAL;
@@ -5427,12 +5416,12 @@ static void fg_cleanup(struct fg_chip *chip)
wakeup_source_trash(&chip->capacity_learning_wakeup_source.source);
}
-static int fg_remove(struct spmi_device *spmi)
+static int fg_remove(struct platform_device *pdev)
{
- struct fg_chip *chip = dev_get_drvdata(&spmi->dev);
+ struct fg_chip *chip = dev_get_drvdata(&pdev->dev);
fg_cleanup(chip);
- dev_set_drvdata(&spmi->dev, NULL);
+ dev_set_drvdata(&pdev->dev, NULL);
return 0;
}
@@ -6176,7 +6165,7 @@ static int fg_detect_pmic_type(struct fg_chip *chip)
struct pmic_revid_data *pmic_rev_id;
struct device_node *revid_dev_node;
- revid_dev_node = of_parse_phandle(chip->spmi->dev.of_node,
+ revid_dev_node = of_parse_phandle(chip->pdev->dev.of_node,
"qcom,pmic-revid", 0);
if (!revid_dev_node) {
pr_err("Missing qcom,pmic-revid property - driver failed\n");
@@ -6309,21 +6298,21 @@ done:
fg_cleanup(chip);
}
-static int fg_probe(struct spmi_device *spmi)
+static int fg_probe(struct platform_device *pdev)
{
- struct device *dev = &(spmi->dev);
+ struct device *dev = &(pdev->dev);
struct fg_chip *chip;
- struct spmi_resource *spmi_resource;
- struct resource *resource;
+ struct device_node *child;
+ unsigned int base;
u8 subtype, reg;
int rc = 0;
- if (!spmi) {
+ if (!pdev) {
pr_err("no valid spmi pointer\n");
return -ENODEV;
}
- if (!spmi->dev.of_node) {
+ if (!pdev->dev.of_node) {
pr_err("device node missing\n");
return -ENODEV;
}
@@ -6333,9 +6322,14 @@ static int fg_probe(struct spmi_device *spmi)
pr_err("Can't allocate fg_chip\n");
return -ENOMEM;
}
+ chip->regmap = dev_get_regmap(pdev->dev.parent, NULL);
+ if (!chip->regmap) {
+ dev_err(&pdev->dev, "Couldn't get parent's regmap\n");
+ return -EINVAL;
+ }
- chip->spmi = spmi;
- chip->dev = &(spmi->dev);
+ chip->pdev = pdev;
+ chip->dev = &(pdev->dev);
wakeup_source_init(&chip->empty_check_wakeup_source.source,
"qpnp_fg_empty_check");
@@ -6383,40 +6377,36 @@ static int fg_probe(struct spmi_device *spmi)
complete_all(&chip->sram_access_revoked);
init_completion(&chip->batt_id_avail);
init_completion(&chip->first_soc_done);
- dev_set_drvdata(&spmi->dev, chip);
+ dev_set_drvdata(&pdev->dev, chip);
- spmi_for_each_container_dev(spmi_resource, spmi) {
- if (!spmi_resource) {
- pr_err("qpnp_chg: spmi resource absent\n");
- rc = -ENXIO;
- goto of_init_fail;
- }
+ if (of_get_available_child_count(pdev->dev.of_node) == 0) {
+ pr_err("no child nodes\n");
+ rc = -ENXIO;
+ goto of_init_fail;
+ }
- resource = spmi_get_resource(spmi, spmi_resource,
- IORESOURCE_MEM, 0);
- if (!(resource && resource->start)) {
- pr_err("node %s IO resource absent!\n",
- spmi->dev.of_node->full_name);
- rc = -ENXIO;
+ for_each_available_child_of_node(pdev->dev.of_node, child) {
+ rc = of_property_read_u32(child, "reg", &base);
+ if (rc < 0) {
+ dev_err(&pdev->dev,
+ "Couldn't find reg in node = %s rc = %d\n",
+ child->full_name, rc);
goto of_init_fail;
}
- if (strcmp("qcom,fg-adc-vbat",
- spmi_resource->of_node->name) == 0) {
- chip->vbat_adc_addr = resource->start;
+ if (strcmp("qcom,fg-adc-vbat", child->name) == 0) {
+ chip->vbat_adc_addr = base;
continue;
- } else if (strcmp("qcom,fg-adc-ibat",
- spmi_resource->of_node->name) == 0) {
- chip->ibat_adc_addr = resource->start;
+ } else if (strcmp("qcom,fg-adc-ibat", child->name) == 0) {
+ chip->ibat_adc_addr = base;
continue;
- } else if (strcmp("qcom,revid-tp-rev",
- spmi_resource->of_node->name) == 0) {
- chip->tp_rev_addr = resource->start;
+ } else if (strcmp("qcom,revid-tp-rev", child->name) == 0) {
+ chip->tp_rev_addr = base;
continue;
}
rc = fg_read(chip, &subtype,
- resource->start + REG_OFFSET_PERP_SUBTYPE, 1);
+ base + REG_OFFSET_PERP_SUBTYPE, 1);
if (rc) {
pr_err("Peripheral subtype read failed rc=%d\n", rc);
goto of_init_fail;
@@ -6424,13 +6414,13 @@ static int fg_probe(struct spmi_device *spmi)
switch (subtype) {
case FG_SOC:
- chip->soc_base = resource->start;
+ chip->soc_base = base;
break;
case FG_MEMIF:
- chip->mem_base = resource->start;
+ chip->mem_base = base;
break;
case FG_BATT:
- chip->batt_base = resource->start;
+ chip->batt_base = base;
break;
default:
pr_err("Invalid peripheral subtype=0x%x\n", subtype);
@@ -6693,11 +6683,11 @@ static struct kernel_param_ops fg_restart_ops = {
module_param_cb(restart, &fg_restart_ops, &fg_restart, 0644);
-static struct spmi_driver fg_driver = {
+static struct platform_driver fg_driver = {
.driver = {
- .name = QPNP_FG_DEV_NAME,
+ .name = QPNP_FG_DEV_NAME,
.of_match_table = fg_match_table,
- .pm = &qpnp_fg_pm_ops,
+ .pm = &qpnp_fg_pm_ops,
},
.probe = fg_probe,
.remove = fg_remove,
@@ -6705,12 +6695,12 @@ static struct spmi_driver fg_driver = {
static int __init fg_init(void)
{
- return spmi_driver_register(&fg_driver);
+ return platform_driver_register(&fg_driver);
}
static void __exit fg_exit(void)
{
- return spmi_driver_unregister(&fg_driver);
+ return platform_driver_unregister(&fg_driver);
}
module_init(fg_init);
diff --git a/drivers/power/qpnp-smbcharger.c b/drivers/power/qpnp-smbcharger.c
index d9d90ae66eae..5a32b1c7c098 100644
--- a/drivers/power/qpnp-smbcharger.c
+++ b/drivers/power/qpnp-smbcharger.c
@@ -11,7 +11,7 @@
*/
#define pr_fmt(fmt) "SMBCHG: %s: " fmt, __func__
-#include <linux/spmi.h>
+#include <linux/regmap.h>
#include <linux/spinlock.h>
#include <linux/gpio.h>
#include <linux/errno.h>
@@ -23,11 +23,13 @@
#include <linux/power_supply.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
+#include <linux/of_irq.h>
#include <linux/bitops.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/of_regulator.h>
#include <linux/regulator/machine.h>
#include <linux/spmi.h>
+#include <linux/platform_device.h>
#include <linux/printk.h>
#include <linux/ratelimit.h>
#include <linux/debugfs.h>
@@ -94,7 +96,8 @@ struct smbchg_version_tables {
struct smbchg_chip {
struct device *dev;
- struct spmi_device *spmi;
+ struct platform_device *pdev;
+ struct regmap *regmap;
int schg_version;
/* peripheral register address bases */
@@ -493,52 +496,21 @@ static int smbchg_read(struct smbchg_chip *chip, u8 *val,
u16 addr, int count)
{
int rc = 0;
- struct spmi_device *spmi = chip->spmi;
+ struct platform_device *pdev = chip->pdev;
if (addr == 0) {
dev_err(chip->dev, "addr cannot be zero addr=0x%02x sid=0x%02x rc=%d\n",
- addr, spmi->sid, rc);
+ addr, to_spmi_device(pdev->dev.parent)->usid, rc);
return -EINVAL;
}
- rc = spmi_ext_register_readl(spmi->ctrl, spmi->sid, addr, val, count);
+ rc = regmap_bulk_read(chip->regmap, addr, val, count);
if (rc) {
dev_err(chip->dev, "spmi read failed addr=0x%02x sid=0x%02x rc=%d\n",
- addr, spmi->sid, rc);
- return rc;
- }
- return 0;
-}
-
-/*
- * Writes an arbitrary number of bytes to a specified register
- *
- * Do not use this function for register writes if possible. Instead use the
- * smbchg_masked_write function.
- *
- * The sec_access_lock must be held for all register writes and this function
- * does not do that. If this function is used, please hold the spinlock or
- * random secure access writes may fail.
- */
-static int smbchg_write(struct smbchg_chip *chip, u8 *val,
- u16 addr, int count)
-{
- int rc = 0;
- struct spmi_device *spmi = chip->spmi;
-
- if (addr == 0) {
- dev_err(chip->dev, "addr cannot be zero addr=0x%02x sid=0x%02x rc=%d\n",
- addr, spmi->sid, rc);
- return -EINVAL;
- }
-
- rc = spmi_ext_register_writel(spmi->ctrl, spmi->sid, addr, val, count);
- if (rc) {
- dev_err(chip->dev, "write failed addr=0x%02x sid=0x%02x rc=%d\n",
- addr, spmi->sid, rc);
+ addr, to_spmi_device(pdev->dev.parent)->usid,
+ rc);
return rc;
}
-
return 0;
}
@@ -556,21 +528,8 @@ static int smbchg_masked_write_raw(struct smbchg_chip *chip, u16 base, u8 mask,
u8 val)
{
int rc;
- u8 reg;
- rc = smbchg_read(chip, &reg, base, 1);
- if (rc) {
- dev_err(chip->dev, "spmi read failed: addr=%03X, rc=%d\n",
- base, rc);
- return rc;
- }
-
- reg &= ~mask;
- reg |= val & mask;
-
- pr_smb(PR_REGISTER, "addr = 0x%x writing 0x%x\n", base, reg);
-
- rc = smbchg_write(chip, &reg, base, 1);
+ rc = regmap_update_bits(chip->regmap, base, mask, val);
if (rc) {
dev_err(chip->dev, "spmi write failed: addr=%03X, rc=%d\n",
base, rc);
@@ -3428,7 +3387,7 @@ static int smbchg_config_chg_battery_type(struct smbchg_chip *chip)
{
int rc = 0, max_voltage_uv = 0, fastchg_ma = 0, ret = 0, iterm_ua = 0;
struct device_node *batt_node, *profile_node;
- struct device_node *node = chip->spmi->dev.of_node;
+ struct device_node *node = chip->pdev->dev.of_node;
union power_supply_propval prop = {0,};
rc = chip->bms_psy->get_property(chip->bms_psy,
@@ -3508,7 +3467,7 @@ static int smbchg_config_chg_battery_type(struct smbchg_chip *chip)
* Only configure from profile if fastchg-ma is not defined in the
* charger device node.
*/
- if (!of_find_property(chip->spmi->dev.of_node,
+ if (!of_find_property(chip->pdev->dev.of_node,
"qcom,fastchg-current-ma", NULL)) {
rc = of_property_read_u32(profile_node,
"qcom,fastchg-current-ma", &fastchg_ma);
@@ -7044,7 +7003,7 @@ do { \
if (optional) \
prop = -EINVAL; \
\
- retval = of_property_read_u32(chip->spmi->dev.of_node, \
+ retval = of_property_read_u32(chip->pdev->dev.of_node, \
"qcom," dt_property , \
&prop); \
\
@@ -7213,11 +7172,9 @@ static int smb_parse_dt(struct smbchg_chip *chip)
/*
* use the dt values if they exist, otherwise do not touch the params
*/
- of_property_read_u32(chip->spmi->dev.of_node,
- "qcom,parallel-main-chg-fcc-percent",
+ of_property_read_u32(node, "qcom,parallel-main-chg-fcc-percent",
&smbchg_main_chg_fcc_percent);
- of_property_read_u32(chip->spmi->dev.of_node,
- "qcom,parallel-main-chg-icl-percent",
+ of_property_read_u32(node, "qcom,parallel-main-chg-icl-percent",
&smbchg_main_chg_icl_percent);
pr_smb(PR_STATUS, "parallel usb thr: %d, 9v thr: %d\n",
chip->parallel.min_current_thr_ma,
@@ -7254,7 +7211,7 @@ static int smb_parse_dt(struct smbchg_chip *chip)
"qcom,skip-usb-suspend-for-fake-battery");
/* parse the battery missing detection pin source */
- rc = of_property_read_string(chip->spmi->dev.of_node,
+ rc = of_property_read_string(chip->pdev->dev.of_node,
"qcom,bmd-pin-src", &bpd);
if (rc) {
/* Select BAT_THM as default BPD scheme */
@@ -7360,50 +7317,52 @@ static int smb_parse_dt(struct smbchg_chip *chip)
#define SMBCHG_LITE_USB_CHGPTH_SUBTYPE 0x54
#define SMBCHG_LITE_DC_CHGPTH_SUBTYPE 0x55
#define SMBCHG_LITE_MISC_SUBTYPE 0x57
-#define REQUEST_IRQ(chip, resource, irq_num, irq_name, irq_handler, flags, rc)\
-do { \
- irq_num = spmi_get_irq_byname(chip->spmi, \
- resource, irq_name); \
- if (irq_num < 0) { \
- dev_err(chip->dev, "Unable to get " irq_name " irq\n"); \
- return -ENXIO; \
- } \
- rc = devm_request_threaded_irq(chip->dev, \
- irq_num, NULL, irq_handler, flags, irq_name, \
- chip); \
- if (rc < 0) { \
- dev_err(chip->dev, "Unable to request " irq_name " irq: %d\n",\
- rc); \
- return -ENXIO; \
- } \
-} while (0)
+static int smbchg_request_irq(struct smbchg_chip *chip,
+ struct device_node *child,
+ int irq_num, char *irq_name,
+ irqreturn_t (irq_handler)(int irq, void *_chip),
+ int flags)
+{
+ int rc;
+
+ irq_num = of_irq_get_byname(child, irq_name);
+ if (irq_num < 0) {
+ dev_err(chip->dev, "Unable to get %s irqn", irq_name);
+ rc = -ENXIO;
+ }
+ rc = devm_request_threaded_irq(chip->dev,
+ irq_num, NULL, irq_handler, flags, irq_name,
+ chip);
+ if (rc < 0) {
+ dev_err(chip->dev, "Unable to request %s irq: %dn",
+ irq_name, rc);
+ rc = -ENXIO;
+ }
+ return 0;
+}
static int smbchg_request_irqs(struct smbchg_chip *chip)
{
int rc = 0;
- struct resource *resource;
- struct spmi_resource *spmi_resource;
+ unsigned int base;
+ struct device_node *child;
u8 subtype;
- struct spmi_device *spmi = chip->spmi;
unsigned long flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING
| IRQF_ONESHOT;
- spmi_for_each_container_dev(spmi_resource, chip->spmi) {
- if (!spmi_resource) {
- dev_err(chip->dev, "spmi resource absent\n");
- return rc;
- }
+ if (of_get_available_child_count(chip->pdev->dev.of_node) == 0) {
+ pr_err("no child nodes\n");
+ return -ENXIO;
+ }
- resource = spmi_get_resource(spmi, spmi_resource,
- IORESOURCE_MEM, 0);
- if (!(resource && resource->start)) {
- dev_err(chip->dev, "node %s IO resource absent!\n",
- spmi->dev.of_node->full_name);
- return rc;
+ for_each_available_child_of_node(chip->pdev->dev.of_node, child) {
+ rc = of_property_read_u32(child, "reg", &base);
+ if (rc < 0) {
+ rc = 0;
+ continue;
}
- rc = smbchg_read(chip, &subtype,
- resource->start + SUBTYPE_REG, 1);
+ rc = smbchg_read(chip, &subtype, base + SUBTYPE_REG, 1);
if (rc) {
dev_err(chip->dev, "Peripheral subtype read failed rc=%d\n",
rc);
@@ -7413,37 +7372,66 @@ static int smbchg_request_irqs(struct smbchg_chip *chip)
switch (subtype) {
case SMBCHG_CHGR_SUBTYPE:
case SMBCHG_LITE_CHGR_SUBTYPE:
- REQUEST_IRQ(chip, spmi_resource, chip->chg_error_irq,
- "chg-error", chg_error_handler, flags, rc);
- REQUEST_IRQ(chip, spmi_resource, chip->taper_irq,
+ rc = smbchg_request_irq(chip, child,
+ chip->chg_error_irq, "chg-error",
+ chg_error_handler, flags);
+ if (rc < 0)
+ return rc;
+ rc = smbchg_request_irq(chip, child, chip->taper_irq,
"chg-taper-thr", taper_handler,
- (IRQF_TRIGGER_RISING | IRQF_ONESHOT), rc);
+ (IRQF_TRIGGER_RISING | IRQF_ONESHOT));
+ if (rc < 0)
+ return rc;
disable_irq_nosync(chip->taper_irq);
- REQUEST_IRQ(chip, spmi_resource, chip->chg_term_irq,
+ rc = smbchg_request_irq(chip, child, chip->chg_term_irq,
"chg-tcc-thr", chg_term_handler,
- (IRQF_TRIGGER_RISING | IRQF_ONESHOT), rc);
- REQUEST_IRQ(chip, spmi_resource, chip->recharge_irq,
- "chg-rechg-thr", recharge_handler, flags, rc);
- REQUEST_IRQ(chip, spmi_resource, chip->fastchg_irq,
- "chg-p2f-thr", fastchg_handler, flags, rc);
+ (IRQF_TRIGGER_RISING | IRQF_ONESHOT));
+ if (rc < 0)
+ return rc;
+ rc = smbchg_request_irq(chip, child, chip->recharge_irq,
+ "chg-rechg-thr", recharge_handler, flags);
+ if (rc < 0)
+ return rc;
+ rc = smbchg_request_irq(chip, child, chip->fastchg_irq,
+ "chg-p2f-thr", fastchg_handler, flags);
+ if (rc < 0)
+ return rc;
enable_irq_wake(chip->chg_term_irq);
enable_irq_wake(chip->chg_error_irq);
enable_irq_wake(chip->fastchg_irq);
break;
case SMBCHG_BAT_IF_SUBTYPE:
case SMBCHG_LITE_BAT_IF_SUBTYPE:
- REQUEST_IRQ(chip, spmi_resource, chip->batt_hot_irq,
- "batt-hot", batt_hot_handler, flags, rc);
- REQUEST_IRQ(chip, spmi_resource, chip->batt_warm_irq,
- "batt-warm", batt_warm_handler, flags, rc);
- REQUEST_IRQ(chip, spmi_resource, chip->batt_cool_irq,
- "batt-cool", batt_cool_handler, flags, rc);
- REQUEST_IRQ(chip, spmi_resource, chip->batt_cold_irq,
- "batt-cold", batt_cold_handler, flags, rc);
- REQUEST_IRQ(chip, spmi_resource, chip->batt_missing_irq,
- "batt-missing", batt_pres_handler, flags, rc);
- REQUEST_IRQ(chip, spmi_resource, chip->vbat_low_irq,
- "batt-low", vbat_low_handler, flags, rc);
+ rc = smbchg_request_irq(chip, child, chip->batt_hot_irq,
+ "batt-hot", batt_hot_handler, flags);
+ if (rc < 0)
+ return rc;
+ rc = smbchg_request_irq(chip, child,
+ chip->batt_warm_irq,
+ "batt-warm", batt_warm_handler, flags);
+ if (rc < 0)
+ return rc;
+ rc = smbchg_request_irq(chip, child,
+ chip->batt_cool_irq,
+ "batt-cool", batt_cool_handler, flags);
+ if (rc < 0)
+ return rc;
+ rc = smbchg_request_irq(chip, child,
+ chip->batt_cold_irq,
+ "batt-cold", batt_cold_handler, flags);
+ if (rc < 0)
+ return rc;
+ rc = smbchg_request_irq(chip, child,
+ chip->batt_missing_irq,
+ "batt-missing", batt_pres_handler, flags);
+ if (rc < 0)
+ return rc;
+ rc = smbchg_request_irq(chip, child,
+ chip->vbat_low_irq,
+ "batt-low", vbat_low_handler, flags);
+ if (rc < 0)
+ return rc;
+
enable_irq_wake(chip->batt_hot_irq);
enable_irq_wake(chip->batt_warm_irq);
enable_irq_wake(chip->batt_cool_irq);
@@ -7453,33 +7441,49 @@ static int smbchg_request_irqs(struct smbchg_chip *chip)
break;
case SMBCHG_USB_CHGPTH_SUBTYPE:
case SMBCHG_LITE_USB_CHGPTH_SUBTYPE:
- REQUEST_IRQ(chip, spmi_resource, chip->usbin_uv_irq,
+ rc = smbchg_request_irq(chip, child,
+ chip->usbin_uv_irq,
"usbin-uv", usbin_uv_handler,
- flags | IRQF_EARLY_RESUME, rc);
- REQUEST_IRQ(chip, spmi_resource, chip->usbin_ov_irq,
- "usbin-ov", usbin_ov_handler, flags, rc);
- REQUEST_IRQ(chip, spmi_resource, chip->src_detect_irq,
+ flags | IRQF_EARLY_RESUME);
+ if (rc < 0)
+ return rc;
+ rc = smbchg_request_irq(chip, child,
+ chip->usbin_ov_irq,
+ "usbin-ov", usbin_ov_handler, flags);
+ if (rc < 0)
+ return rc;
+ rc = smbchg_request_irq(chip, child,
+ chip->src_detect_irq,
"usbin-src-det",
- src_detect_handler, flags, rc);
- REQUEST_IRQ(chip, spmi_resource, chip->aicl_done_irq,
+ src_detect_handler, flags);
+ if (rc < 0)
+ return rc;
+ rc = smbchg_request_irq(chip, child,
+ chip->aicl_done_irq,
"aicl-done",
aicl_done_handler,
- (IRQF_TRIGGER_RISING | IRQF_ONESHOT),
- rc);
+ (IRQF_TRIGGER_RISING | IRQF_ONESHOT));
+ if (rc < 0)
+ return rc;
+
if (chip->schg_version != QPNP_SCHG_LITE) {
- REQUEST_IRQ(chip, spmi_resource,
+ rc = smbchg_request_irq(chip, child,
chip->otg_fail_irq, "otg-fail",
- otg_fail_handler, flags, rc);
- REQUEST_IRQ(chip, spmi_resource,
+ otg_fail_handler, flags);
+ if (rc < 0)
+ return rc;
+ rc = smbchg_request_irq(chip, child,
chip->otg_oc_irq, "otg-oc",
otg_oc_handler,
- (IRQF_TRIGGER_RISING | IRQF_ONESHOT),
- rc);
- REQUEST_IRQ(chip, spmi_resource,
+ (IRQF_TRIGGER_RISING | IRQF_ONESHOT));
+ if (rc < 0)
+ return rc;
+ rc = smbchg_request_irq(chip, child,
chip->usbid_change_irq, "usbid-change",
usbid_change_handler,
- (IRQF_TRIGGER_FALLING | IRQF_ONESHOT),
- rc);
+ (IRQF_TRIGGER_FALLING | IRQF_ONESHOT));
+ if (rc < 0)
+ return rc;
enable_irq_wake(chip->otg_oc_irq);
enable_irq_wake(chip->usbid_change_irq);
enable_irq_wake(chip->otg_fail_irq);
@@ -7494,38 +7498,50 @@ static int smbchg_request_irqs(struct smbchg_chip *chip)
break;
case SMBCHG_DC_CHGPTH_SUBTYPE:
case SMBCHG_LITE_DC_CHGPTH_SUBTYPE:
- REQUEST_IRQ(chip, spmi_resource, chip->dcin_uv_irq,
- "dcin-uv", dcin_uv_handler, flags, rc);
+ rc = smbchg_request_irq(chip, child, chip->dcin_uv_irq,
+ "dcin-uv", dcin_uv_handler, flags);
+ if (rc < 0)
+ return rc;
enable_irq_wake(chip->dcin_uv_irq);
break;
case SMBCHG_MISC_SUBTYPE:
case SMBCHG_LITE_MISC_SUBTYPE:
- REQUEST_IRQ(chip, spmi_resource, chip->power_ok_irq,
- "power-ok", power_ok_handler, flags, rc);
- REQUEST_IRQ(chip, spmi_resource, chip->chg_hot_irq,
- "temp-shutdown", chg_hot_handler, flags, rc);
- REQUEST_IRQ(chip, spmi_resource,
- chip->wdog_timeout_irq,
+ rc = smbchg_request_irq(chip, child, chip->power_ok_irq,
+ "power-ok", power_ok_handler, flags);
+ if (rc < 0)
+ return rc;
+ rc = smbchg_request_irq(chip, child, chip->chg_hot_irq,
+ "temp-shutdown", chg_hot_handler, flags);
+ if (rc < 0)
+ return rc;
+ rc = smbchg_request_irq(chip, child, chip->wdog_timeout_irq,
"wdog-timeout",
- wdog_timeout_handler, flags, rc);
+ wdog_timeout_handler, flags);
+ if (rc < 0)
+ return rc;
enable_irq_wake(chip->chg_hot_irq);
enable_irq_wake(chip->wdog_timeout_irq);
break;
case SMBCHG_OTG_SUBTYPE:
break;
case SMBCHG_LITE_OTG_SUBTYPE:
- REQUEST_IRQ(chip, spmi_resource,
+ rc = smbchg_request_irq(chip, child,
chip->usbid_change_irq, "usbid-change",
usbid_change_handler,
- (IRQF_TRIGGER_FALLING | IRQF_ONESHOT),
- rc);
- REQUEST_IRQ(chip, spmi_resource,
+ (IRQF_TRIGGER_FALLING | IRQF_ONESHOT));
+ if (rc < 0)
+ return rc;
+ rc = smbchg_request_irq(chip, child,
chip->otg_oc_irq, "otg-oc",
otg_oc_handler,
- (IRQF_TRIGGER_RISING | IRQF_ONESHOT), rc);
- REQUEST_IRQ(chip, spmi_resource,
+ (IRQF_TRIGGER_RISING | IRQF_ONESHOT));
+ if (rc < 0)
+ return rc;
+ rc = smbchg_request_irq(chip, child,
chip->otg_fail_irq, "otg-fail",
- otg_fail_handler, flags, rc);
+ otg_fail_handler, flags);
+ if (rc < 0)
+ return rc;
enable_irq_wake(chip->usbid_change_irq);
enable_irq_wake(chip->otg_oc_irq);
enable_irq_wake(chip->otg_fail_irq);
@@ -7547,27 +7563,23 @@ do { \
static int smbchg_parse_peripherals(struct smbchg_chip *chip)
{
int rc = 0;
- struct resource *resource;
- struct spmi_resource *spmi_resource;
+ unsigned int base;
+ struct device_node *child;
u8 subtype;
- struct spmi_device *spmi = chip->spmi;
- spmi_for_each_container_dev(spmi_resource, chip->spmi) {
- if (!spmi_resource) {
- dev_err(chip->dev, "spmi resource absent\n");
- return rc;
- }
+ if (of_get_available_child_count(chip->pdev->dev.of_node) == 0) {
+ pr_err("no child nodes\n");
+ return -ENXIO;
+ }
- resource = spmi_get_resource(spmi, spmi_resource,
- IORESOURCE_MEM, 0);
- if (!(resource && resource->start)) {
- dev_err(chip->dev, "node %s IO resource absent!\n",
- spmi->dev.of_node->full_name);
- return rc;
+ for_each_available_child_of_node(chip->pdev->dev.of_node, child) {
+ rc = of_property_read_u32(child, "reg", &base);
+ if (rc < 0) {
+ rc = 0;
+ continue;
}
- rc = smbchg_read(chip, &subtype,
- resource->start + SUBTYPE_REG, 1);
+ rc = smbchg_read(chip, &subtype, base + SUBTYPE_REG, 1);
if (rc) {
dev_err(chip->dev, "Peripheral subtype read failed rc=%d\n",
rc);
@@ -7577,27 +7589,27 @@ static int smbchg_parse_peripherals(struct smbchg_chip *chip)
switch (subtype) {
case SMBCHG_CHGR_SUBTYPE:
case SMBCHG_LITE_CHGR_SUBTYPE:
- chip->chgr_base = resource->start;
+ chip->chgr_base = base;
break;
case SMBCHG_BAT_IF_SUBTYPE:
case SMBCHG_LITE_BAT_IF_SUBTYPE:
- chip->bat_if_base = resource->start;
+ chip->bat_if_base = base;
break;
case SMBCHG_USB_CHGPTH_SUBTYPE:
case SMBCHG_LITE_USB_CHGPTH_SUBTYPE:
- chip->usb_chgpth_base = resource->start;
+ chip->usb_chgpth_base = base;
break;
case SMBCHG_DC_CHGPTH_SUBTYPE:
case SMBCHG_LITE_DC_CHGPTH_SUBTYPE:
- chip->dc_chgpth_base = resource->start;
+ chip->dc_chgpth_base = base;
break;
case SMBCHG_MISC_SUBTYPE:
case SMBCHG_LITE_MISC_SUBTYPE:
- chip->misc_base = resource->start;
+ chip->misc_base = base;
break;
case SMBCHG_OTG_SUBTYPE:
case SMBCHG_LITE_OTG_SUBTYPE:
- chip->otg_base = resource->start;
+ chip->otg_base = base;
break;
}
}
@@ -7680,7 +7692,7 @@ static int smbchg_check_chg_version(struct smbchg_chip *chip)
struct device_node *revid_dev_node;
int rc;
- revid_dev_node = of_parse_phandle(chip->spmi->dev.of_node,
+ revid_dev_node = of_parse_phandle(chip->pdev->dev.of_node,
"qcom,pmic-revid", 0);
if (!revid_dev_node) {
pr_err("Missing qcom,pmic-revid property - driver failed\n");
@@ -7786,7 +7798,7 @@ static void rerun_hvdcp_det_if_necessary(struct smbchg_chip *chip)
}
}
-static int smbchg_probe(struct spmi_device *spmi)
+static int smbchg_probe(struct platform_device *pdev)
{
int rc;
struct smbchg_chip *chip;
@@ -7800,9 +7812,9 @@ static int smbchg_probe(struct spmi_device *spmi)
return -EPROBE_DEFER;
}
- if (of_property_read_bool(spmi->dev.of_node, "qcom,external-typec")) {
+ if (of_property_read_bool(pdev->dev.of_node, "qcom,external-typec")) {
/* read the type power supply name */
- rc = of_property_read_string(spmi->dev.of_node,
+ rc = of_property_read_string(pdev->dev.of_node,
"qcom,typec-psy-name", &typec_psy_name);
if (rc) {
pr_err("failed to get prop typec-psy-name rc=%d\n",
@@ -7818,91 +7830,97 @@ static int smbchg_probe(struct spmi_device *spmi)
}
}
- if (of_find_property(spmi->dev.of_node, "qcom,dcin-vadc", NULL)) {
- vadc_dev = qpnp_get_vadc(&spmi->dev, "dcin");
+ if (of_find_property(pdev->dev.of_node, "qcom,dcin-vadc", NULL)) {
+ vadc_dev = qpnp_get_vadc(&pdev->dev, "dcin");
if (IS_ERR(vadc_dev)) {
rc = PTR_ERR(vadc_dev);
if (rc != -EPROBE_DEFER)
- dev_err(&spmi->dev, "Couldn't get vadc rc=%d\n",
+ dev_err(&pdev->dev,
+ "Couldn't get vadc rc=%d\n",
rc);
return rc;
}
}
- if (of_find_property(spmi->dev.of_node, "qcom,vchg_sns-vadc", NULL)) {
- vchg_vadc_dev = qpnp_get_vadc(&spmi->dev, "vchg_sns");
+ if (of_find_property(pdev->dev.of_node, "qcom,vchg_sns-vadc", NULL)) {
+ vchg_vadc_dev = qpnp_get_vadc(&pdev->dev, "vchg_sns");
if (IS_ERR(vchg_vadc_dev)) {
rc = PTR_ERR(vchg_vadc_dev);
if (rc != -EPROBE_DEFER)
- dev_err(&spmi->dev, "Couldn't get vadc 'vchg' rc=%d\n",
+ dev_err(&pdev->dev, "Couldn't get vadc 'vchg' rc=%d\n",
rc);
return rc;
}
}
- chip = devm_kzalloc(&spmi->dev, sizeof(*chip), GFP_KERNEL);
- if (!chip) {
- dev_err(&spmi->dev, "Unable to allocate memory\n");
+
+ chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
+ if (!chip)
return -ENOMEM;
+
+ chip->regmap = dev_get_regmap(pdev->dev.parent, NULL);
+ if (!chip->regmap) {
+ dev_err(&pdev->dev, "Couldn't get parent's regmap\n");
+ return -EINVAL;
}
- chip->fcc_votable = create_votable(&spmi->dev,
+ chip->fcc_votable = create_votable(&pdev->dev,
"SMBCHG: fcc",
VOTE_MIN, NUM_FCC_VOTER, 2000,
set_fastchg_current_vote_cb);
if (IS_ERR(chip->fcc_votable))
return PTR_ERR(chip->fcc_votable);
- chip->usb_icl_votable = create_votable(&spmi->dev,
+ chip->usb_icl_votable = create_votable(&pdev->dev,
"SMBCHG: usb_icl",
VOTE_MIN, NUM_ICL_VOTER, 3000,
set_usb_current_limit_vote_cb);
if (IS_ERR(chip->usb_icl_votable))
return PTR_ERR(chip->usb_icl_votable);
- chip->dc_icl_votable = create_votable(&spmi->dev,
+ chip->dc_icl_votable = create_votable(&pdev->dev,
"SMBCHG: dcl_icl",
VOTE_MIN, NUM_ICL_VOTER, 3000,
set_dc_current_limit_vote_cb);
if (IS_ERR(chip->dc_icl_votable))
return PTR_ERR(chip->dc_icl_votable);
- chip->usb_suspend_votable = create_votable(&spmi->dev,
+ chip->usb_suspend_votable = create_votable(&pdev->dev,
"SMBCHG: usb_suspend",
VOTE_SET_ANY, NUM_EN_VOTERS, 0,
usb_suspend_vote_cb);
if (IS_ERR(chip->usb_suspend_votable))
return PTR_ERR(chip->usb_suspend_votable);
- chip->dc_suspend_votable = create_votable(&spmi->dev,
+ chip->dc_suspend_votable = create_votable(&pdev->dev,
"SMBCHG: dc_suspend",
VOTE_SET_ANY, NUM_EN_VOTERS, 0,
dc_suspend_vote_cb);
if (IS_ERR(chip->dc_suspend_votable))
return PTR_ERR(chip->dc_suspend_votable);
- chip->battchg_suspend_votable = create_votable(&spmi->dev,
+ chip->battchg_suspend_votable = create_votable(&pdev->dev,
"SMBCHG: battchg_suspend",
VOTE_SET_ANY, NUM_BATTCHG_EN_VOTERS, 0,
charging_suspend_vote_cb);
if (IS_ERR(chip->battchg_suspend_votable))
return PTR_ERR(chip->battchg_suspend_votable);
- chip->hw_aicl_rerun_disable_votable = create_votable(&spmi->dev,
+ chip->hw_aicl_rerun_disable_votable = create_votable(&pdev->dev,
"SMBCHG: hwaicl_disable",
VOTE_SET_ANY, NUM_HW_AICL_DISABLE_VOTERS, 0,
smbchg_hw_aicl_rerun_disable_cb);
if (IS_ERR(chip->hw_aicl_rerun_disable_votable))
return PTR_ERR(chip->hw_aicl_rerun_disable_votable);
- chip->hw_aicl_rerun_enable_indirect_votable = create_votable(&spmi->dev,
+ chip->hw_aicl_rerun_enable_indirect_votable = create_votable(&pdev->dev,
"SMBCHG: hwaicl_enable_indirect",
VOTE_SET_ANY, NUM_HW_AICL_RERUN_ENABLE_INDIRECT_VOTERS,
0, smbchg_hw_aicl_rerun_enable_indirect_cb);
if (IS_ERR(chip->hw_aicl_rerun_enable_indirect_votable))
return PTR_ERR(chip->hw_aicl_rerun_enable_indirect_votable);
- chip->aicl_deglitch_short_votable = create_votable(&spmi->dev,
+ chip->aicl_deglitch_short_votable = create_votable(&pdev->dev,
"SMBCHG: hwaicl_short_deglitch",
VOTE_SET_ANY, NUM_HW_SHORT_DEGLITCH_VOTERS, 0,
smbchg_aicl_deglitch_config_cb);
@@ -7920,13 +7938,14 @@ static int smbchg_probe(struct spmi_device *spmi)
init_completion(&chip->usbin_uv_raised);
chip->vadc_dev = vadc_dev;
chip->vchg_vadc_dev = vchg_vadc_dev;
- chip->spmi = spmi;
- chip->dev = &spmi->dev;
+ chip->pdev = pdev;
+ chip->dev = &pdev->dev;
+
chip->usb_psy = usb_psy;
chip->typec_psy = typec_psy;
chip->fake_battery_soc = -EINVAL;
chip->usb_online = -EINVAL;
- dev_set_drvdata(&spmi->dev, chip);
+ dev_set_drvdata(&pdev->dev, chip);
spin_lock_init(&chip->sec_access_lock);
mutex_init(&chip->therm_lvl_lock);
@@ -7952,27 +7971,27 @@ static int smbchg_probe(struct spmi_device *spmi)
rc = smb_parse_dt(chip);
if (rc < 0) {
- dev_err(&spmi->dev, "Unable to parse DT nodes: %d\n", rc);
+ dev_err(&pdev->dev, "Unable to parse DT nodes: %d\n", rc);
return rc;
}
rc = smbchg_regulator_init(chip);
if (rc) {
- dev_err(&spmi->dev,
+ dev_err(&pdev->dev,
"Couldn't initialize regulator rc=%d\n", rc);
return rc;
}
rc = smbchg_hw_init(chip);
if (rc < 0) {
- dev_err(&spmi->dev,
+ dev_err(&pdev->dev,
"Unable to intialize hardware rc = %d\n", rc);
goto out;
}
rc = determine_initial_status(chip);
if (rc < 0) {
- dev_err(&spmi->dev,
+ dev_err(&pdev->dev,
"Unable to determine init status rc = %d\n", rc);
goto out;
}
@@ -7989,7 +8008,7 @@ static int smbchg_probe(struct spmi_device *spmi)
rc = power_supply_register(chip->dev, &chip->batt_psy);
if (rc < 0) {
- dev_err(&spmi->dev,
+ dev_err(&pdev->dev,
"Unable to register batt_psy rc = %d\n", rc);
goto out;
}
@@ -8006,7 +8025,7 @@ static int smbchg_probe(struct spmi_device *spmi)
= ARRAY_SIZE(smbchg_dc_supplicants);
rc = power_supply_register(chip->dev, &chip->dc_psy);
if (rc < 0) {
- dev_err(&spmi->dev,
+ dev_err(&pdev->dev,
"Unable to register dc_psy rc = %d\n", rc);
goto unregister_batt_psy;
}
@@ -8034,7 +8053,7 @@ static int smbchg_probe(struct spmi_device *spmi)
rc = smbchg_request_irqs(chip);
if (rc < 0) {
- dev_err(&spmi->dev, "Unable to request irqs rc = %d\n", rc);
+ dev_err(&pdev->dev, "Unable to request irqs rc = %d\n", rc);
goto unregister_led_class;
}
@@ -8069,9 +8088,9 @@ out:
return rc;
}
-static int smbchg_remove(struct spmi_device *spmi)
+static int smbchg_remove(struct platform_device *pdev)
{
- struct smbchg_chip *chip = dev_get_drvdata(&spmi->dev);
+ struct smbchg_chip *chip = dev_get_drvdata(&pdev->dev);
debugfs_remove_recursive(chip->debug_root);
@@ -8083,9 +8102,9 @@ static int smbchg_remove(struct spmi_device *spmi)
return 0;
}
-static void smbchg_shutdown(struct spmi_device *spmi)
+static void smbchg_shutdown(struct platform_device *pdev)
{
- struct smbchg_chip *chip = dev_get_drvdata(&spmi->dev);
+ struct smbchg_chip *chip = dev_get_drvdata(&pdev->dev);
int i, rc;
if (!(chip->wa_flags & SMBCHG_RESTART_WA))
@@ -8191,7 +8210,7 @@ static const struct dev_pm_ops smbchg_pm_ops = {
MODULE_DEVICE_TABLE(spmi, smbchg_id);
-static struct spmi_driver smbchg_driver = {
+static struct platform_driver smbchg_driver = {
.driver = {
.name = "qpnp-smbcharger",
.owner = THIS_MODULE,
@@ -8205,12 +8224,12 @@ static struct spmi_driver smbchg_driver = {
static int __init smbchg_init(void)
{
- return spmi_driver_register(&smbchg_driver);
+ return platform_driver_register(&smbchg_driver);
}
static void __exit smbchg_exit(void)
{
- return spmi_driver_unregister(&smbchg_driver);
+ return platform_driver_unregister(&smbchg_driver);
}
module_init(smbchg_init);
diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
index 33163b6dd289..40e1afdfc286 100644
--- a/drivers/pwm/Kconfig
+++ b/drivers/pwm/Kconfig
@@ -310,8 +310,7 @@ config PWM_RCAR
will be called pwm-rcar.
config PWM_QPNP
- depends on SPMI || MSM_SPMI
- depends on OF_SPMI
+ depends on SPMI
tristate "Qualcomm QPNP LPG/PWM support"
help
This driver supports PWM/LPG devices in Qualcomm PMIC chips which
diff --git a/drivers/pwm/pwm-qpnp.c b/drivers/pwm/pwm-qpnp.c
index 0ab6af3e59b5..b4f1553056f8 100644
--- a/drivers/pwm/pwm-qpnp.c
+++ b/drivers/pwm/pwm-qpnp.c
@@ -21,8 +21,11 @@
#include <linux/slab.h>
#include <linux/err.h>
#include <linux/spmi.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
#include <linux/of.h>
#include <linux/of_device.h>
+#include <linux/of_address.h>
#include <linux/radix-tree.h>
#include <linux/qpnp/pwm.h>
@@ -308,7 +311,8 @@ struct _qpnp_pwm_config {
/* Public facing structure */
struct qpnp_pwm_chip {
- struct spmi_device *spmi_dev;
+ struct platform_device *pdev;
+ struct regmap *regmap;
struct pwm_chip chip;
bool enabled;
struct _qpnp_pwm_config pwm_config;
@@ -429,8 +433,7 @@ static int qpnp_lpg_save_and_write(u8 value, u8 mask, u8 *reg, u16 addr,
{
qpnp_lpg_save(reg, mask, value);
- return spmi_ext_register_writel(chip->spmi_dev->ctrl,
- chip->spmi_dev->sid, addr, reg, size);
+ return regmap_bulk_write(chip->regmap, addr, reg, size);
}
/*
@@ -617,10 +620,10 @@ static int qpnp_lpg_change_table(struct qpnp_pwm_chip *chip,
for (i = 0; i < list_len; i += burst_size) {
if (i + burst_size >= list_len)
burst_size = list_len - i;
- rc = spmi_ext_register_writel(chip->spmi_dev->ctrl,
- chip->spmi_dev->sid,
- chip->lpg_config.lut_base_addr + offset + i,
- lut->duty_pct_list + i, burst_size);
+ rc = regmap_bulk_write(chip->regmap,
+ chip->lpg_config.lut_base_addr + offset + i,
+ lut->duty_pct_list + i,
+ burst_size);
}
return rc;
@@ -702,10 +705,10 @@ static int qpnp_lpg_save_pwm_value(struct qpnp_pwm_chip *chip)
if (chip->sub_type == QPNP_PWM_MODE_ONLY_SUB_TYPE ||
chip->sub_type == QPNP_LPG_S_CHAN_SUB_TYPE) {
value = QPNP_PWM_SYNC_VALUE & QPNP_PWM_SYNC_MASK;
- rc = spmi_ext_register_writel(chip->spmi_dev->ctrl,
- chip->spmi_dev->sid,
- SPMI_LPG_REG_ADDR(lpg_config->base_addr,
- SPMI_LPG_PWM_SYNC), &value, 1);
+ rc = regmap_write(chip->regmap,
+ SPMI_LPG_REG_ADDR(lpg_config->base_addr,
+ SPMI_LPG_PWM_SYNC),
+ value);
}
return rc;
@@ -735,17 +738,18 @@ static int qpnp_lpg_configure_pwm(struct qpnp_pwm_chip *chip)
int rc;
u8 value, mask;
- rc = spmi_ext_register_writel(chip->spmi_dev->ctrl, chip->spmi_dev->sid,
- SPMI_LPG_REG_ADDR(lpg_config->base_addr, QPNP_LPG_PWM_SIZE_CLK),
- &chip->qpnp_lpg_registers[QPNP_LPG_PWM_SIZE_CLK], 1);
+ rc = regmap_write(chip->regmap,
+ SPMI_LPG_REG_ADDR(lpg_config->base_addr,
+ QPNP_LPG_PWM_SIZE_CLK),
+ *&chip->qpnp_lpg_registers[QPNP_LPG_PWM_SIZE_CLK]);
if (rc)
return rc;
- rc = spmi_ext_register_writel(chip->spmi_dev->ctrl, chip->spmi_dev->sid,
+ rc = regmap_write(chip->regmap,
SPMI_LPG_REG_ADDR(lpg_config->base_addr,
QPNP_LPG_PWM_FREQ_PREDIV_CLK),
- &chip->qpnp_lpg_registers[QPNP_LPG_PWM_FREQ_PREDIV_CLK], 1);
+ *&chip->qpnp_lpg_registers[QPNP_LPG_PWM_FREQ_PREDIV_CLK]);
if (rc)
return rc;
@@ -1013,8 +1017,7 @@ static int qpnp_dtest_config(struct qpnp_pwm_chip *chip, bool enable)
addr = SPMI_LPG_REG_ADDR(lpg_config->base_addr, QPNP_LPG_SEC_ACCESS);
- rc = spmi_ext_register_writel(chip->spmi_dev->ctrl,
- chip->spmi_dev->sid, addr, &value, 1);
+ rc = regmap_write(chip->regmap, addr, value);
if (rc) {
pr_err("Couldn't set the access for test mode\n");
@@ -1032,8 +1035,7 @@ static int qpnp_dtest_config(struct qpnp_pwm_chip *chip, bool enable)
pr_debug("Setting TEST mode for channel %d addr:%x value: %x\n",
chip->channel_id, addr, value);
- rc = spmi_ext_register_writel(chip->spmi_dev->ctrl,
- chip->spmi_dev->sid, addr, &value, 1);
+ rc = regmap_write(chip->regmap, addr, value);
return rc;
}
@@ -1483,10 +1485,10 @@ int pwm_config_period(struct pwm_device *pwm,
qpnp_lpg_save_period(chip);
- rc = spmi_ext_register_writel(chip->spmi_dev->ctrl, chip->spmi_dev->sid,
+ rc = regmap_write(chip->regmap,
SPMI_LPG_REG_ADDR(lpg_config->base_addr,
QPNP_LPG_PWM_SIZE_CLK),
- &chip->qpnp_lpg_registers[QPNP_LPG_PWM_SIZE_CLK], 1);
+ *&chip->qpnp_lpg_registers[QPNP_LPG_PWM_SIZE_CLK]);
if (rc) {
pr_err("Write failed: QPNP_LPG_PWM_SIZE_CLK register, rc: %d\n",
@@ -1494,10 +1496,10 @@ int pwm_config_period(struct pwm_device *pwm,
goto out_unlock;
}
- rc = spmi_ext_register_writel(chip->spmi_dev->ctrl, chip->spmi_dev->sid,
- SPMI_LPG_REG_ADDR(lpg_config->base_addr,
- QPNP_LPG_PWM_FREQ_PREDIV_CLK),
- &chip->qpnp_lpg_registers[QPNP_LPG_PWM_FREQ_PREDIV_CLK], 1);
+ rc = regmap_write(chip->regmap,
+ SPMI_LPG_REG_ADDR(lpg_config->base_addr,
+ QPNP_LPG_PWM_FREQ_PREDIV_CLK),
+ *&chip->qpnp_lpg_registers[QPNP_LPG_PWM_FREQ_PREDIV_CLK]);
if (rc) {
pr_err("Failed to write to QPNP_LPG_PWM_FREQ_PREDIV_CLK\n");
pr_err("register, rc = %d\n", rc);
@@ -1779,26 +1781,27 @@ out:
static int qpnp_lpg_get_rev_subtype(struct qpnp_pwm_chip *chip)
{
int rc;
+ uint val;
- rc = spmi_ext_register_readl(chip->spmi_dev->ctrl,
- chip->spmi_dev->sid,
- chip->lpg_config.base_addr + SPMI_LPG_SUB_TYPE_OFFSET,
- &chip->sub_type, 1);
+ rc = regmap_read(chip->regmap,
+ chip->lpg_config.base_addr + SPMI_LPG_SUB_TYPE_OFFSET,
+ &val);
if (rc) {
pr_err("Couldn't read subtype rc: %d\n", rc);
goto out;
}
+ chip->sub_type = (u8)val;
- rc = spmi_ext_register_readl(chip->spmi_dev->ctrl,
- chip->spmi_dev->sid,
- chip->lpg_config.base_addr + SPMI_LPG_REVISION2_OFFSET,
- (u8 *) &chip->revision, 1);
+ rc = regmap_read(chip->regmap,
+ chip->lpg_config.base_addr + SPMI_LPG_REVISION2_OFFSET,
+ &val);
if (rc) {
pr_err("Couldn't read revision2 rc: %d\n", rc);
goto out;
}
+ chip->revision = (u8)val;
if (chip->revision < QPNP_LPG_REVISION_0 ||
chip->revision > QPNP_LPG_REVISION_1) {
@@ -1822,16 +1825,17 @@ out:
}
/* Fill in lpg device elements based on values found in device tree. */
-static int qpnp_parse_dt_config(struct spmi_device *spmi,
+static int qpnp_parse_dt_config(struct platform_device *pdev,
struct qpnp_pwm_chip *chip)
{
int rc, enable, lut_entry_size, list_size, i;
const char *lable;
- struct resource *res;
+ const __be32 *prop;
+ u64 size;
struct device_node *node;
int found_pwm_subnode = 0;
int found_lpg_subnode = 0;
- struct device_node *of_node = spmi->dev.of_node;
+ struct device_node *of_node = pdev->dev.of_node;
struct qpnp_lpg_config *lpg_config = &chip->lpg_config;
struct qpnp_lut_config *lut_config = &lpg_config->lut_config;
struct _qpnp_pwm_config *pwm_config = &chip->pwm_config;
@@ -1841,7 +1845,7 @@ static int qpnp_parse_dt_config(struct spmi_device *spmi,
rc = of_property_read_u32(of_node, "qcom,channel-id",
&chip->channel_id);
if (rc) {
- dev_err(&spmi->dev, "%s: node is missing LPG channel id\n",
+ dev_err(&pdev->dev, "%s: node is missing LPG channel id\n",
__func__);
return -EINVAL;
}
@@ -1900,34 +1904,36 @@ static int qpnp_parse_dt_config(struct spmi_device *spmi,
}
pwm_config->force_pwm_size = force_pwm_size;
- res = spmi_get_resource_byname(spmi, NULL, IORESOURCE_MEM,
- QPNP_LPG_CHANNEL_BASE);
- if (!res) {
- dev_err(&spmi->dev, "%s: node is missing base address\n",
- __func__);
- return -EINVAL;
- }
- lpg_config->base_addr = res->start;
+
+ prop = of_get_address_by_name(pdev->dev.of_node, QPNP_LPG_CHANNEL_BASE,
+ 0, 0);
+ if (!prop) {
+ dev_err(&pdev->dev, "Couldnt find channel's base addr rc %d\n",
+ rc);
+ return rc;
+ }
+ lpg_config->base_addr = be32_to_cpu(*prop);
rc = qpnp_lpg_get_rev_subtype(chip);
if (rc)
return rc;
- res = spmi_get_resource_byname(spmi, NULL, IORESOURCE_MEM,
- QPNP_LPG_LUT_BASE);
- if (!res) {
+ prop = of_get_address_by_name(pdev->dev.of_node, QPNP_LPG_LUT_BASE,
+ &size, 0);
+ if (!prop) {
chip->flags |= QPNP_PWM_LUT_NOT_SUPPORTED;
} else {
- lpg_config->lut_base_addr = res->start;
- /* Each entry of LUT is of 2 bytes for generic LUT and of 1 byte
+ lpg_config->lut_base_addr = be32_to_cpu(*prop);
+ /*
+ * Each entry of LUT is of 2 bytes for generic LUT and of 1 byte
* for KPDBL/GLED LUT.
*/
- lpg_config->lut_size = resource_size(res) >> 1;
+ lpg_config->lut_size = size >> 1;
lut_entry_size = sizeof(u16);
if (pwm_config->supported_sizes == QPNP_PWM_SIZE_7_8_BIT) {
- lpg_config->lut_size = resource_size(res);
+ lpg_config->lut_size = size;
lut_entry_size = sizeof(u8);
}
@@ -1964,7 +1970,7 @@ static int qpnp_parse_dt_config(struct spmi_device *spmi,
for_each_child_of_node(of_node, node) {
rc = of_property_read_string(node, "label", &lable);
if (rc) {
- dev_err(&spmi->dev, "%s: Missing lable property\n",
+ dev_err(&pdev->dev, "%s: Missing lable property\n",
__func__);
goto out;
}
@@ -1980,7 +1986,8 @@ static int qpnp_parse_dt_config(struct spmi_device *spmi,
goto out;
found_lpg_subnode = 1;
} else {
- dev_err(&spmi->dev, "%s: Invalid value for lable prop",
+ dev_err(&pdev->dev,
+ "%s: Invalid value for lable prop",
__func__);
}
}
@@ -1991,7 +1998,7 @@ static int qpnp_parse_dt_config(struct spmi_device *spmi,
if ((enable == PM_PWM_MODE_PWM && found_pwm_subnode == 0) ||
(enable == PM_PWM_MODE_LPG && found_lpg_subnode == 0)) {
- dev_err(&spmi->dev, "%s: Invalid mode select\n", __func__);
+ dev_err(&pdev->dev, "%s: Invalid mode select\n", __func__);
rc = -EINVAL;
goto out;
}
@@ -2019,7 +2026,7 @@ static struct pwm_ops qpnp_pwm_ops = {
.owner = THIS_MODULE,
};
-static int qpnp_pwm_probe(struct spmi_device *spmi)
+static int qpnp_pwm_probe(struct platform_device *pdev)
{
struct qpnp_pwm_chip *pwm_chip;
int rc;
@@ -2029,18 +2036,23 @@ static int qpnp_pwm_probe(struct spmi_device *spmi)
pr_err("kzalloc() failed.\n");
return -ENOMEM;
}
+ pwm_chip->regmap = dev_get_regmap(pdev->dev.parent, NULL);
+ if (!pwm_chip->regmap) {
+ dev_err(&pdev->dev, "Couldn't get parent's regmap\n");
+ return -EINVAL;
+ }
spin_lock_init(&pwm_chip->lpg_lock);
- pwm_chip->spmi_dev = spmi;
- dev_set_drvdata(&spmi->dev, pwm_chip);
+ pwm_chip->pdev = pdev;
+ dev_set_drvdata(&pdev->dev, pwm_chip);
- rc = qpnp_parse_dt_config(spmi, pwm_chip);
+ rc = qpnp_parse_dt_config(pdev, pwm_chip);
if (rc)
goto failed_config;
- pwm_chip->chip.dev = &spmi->dev;
+ pwm_chip->chip.dev = &pdev->dev;
pwm_chip->chip.ops = &qpnp_pwm_ops;
pwm_chip->chip.base = -1;
pwm_chip->chip.npwm = 1;
@@ -2059,19 +2071,19 @@ static int qpnp_pwm_probe(struct spmi_device *spmi)
failed_insert:
kfree(pwm_chip->lpg_config.lut_config.duty_pct_list);
failed_config:
- dev_set_drvdata(&spmi->dev, NULL);
+ dev_set_drvdata(&pdev->dev, NULL);
kfree(pwm_chip);
return rc;
}
-static int qpnp_pwm_remove(struct spmi_device *spmi)
+static int qpnp_pwm_remove(struct platform_device *pdev)
{
struct qpnp_pwm_chip *pwm_chip;
struct qpnp_lpg_config *lpg_config;
- pwm_chip = dev_get_drvdata(&spmi->dev);
+ pwm_chip = dev_get_drvdata(&pdev->dev);
- dev_set_drvdata(&spmi->dev, NULL);
+ dev_set_drvdata(&pdev->dev, NULL);
if (pwm_chip) {
lpg_config = &pwm_chip->lpg_config;
@@ -2088,17 +2100,17 @@ static struct of_device_id spmi_match_table[] = {
{}
};
-static const struct spmi_device_id qpnp_lpg_id[] = {
+static const struct platform_device_id qpnp_lpg_id[] = {
{ QPNP_LPG_DRIVER_NAME, 0 },
{ }
};
MODULE_DEVICE_TABLE(spmi, qpnp_lpg_id);
-static struct spmi_driver qpnp_lpg_driver = {
+static struct platform_driver qpnp_lpg_driver = {
.driver = {
- .name = QPNP_LPG_DRIVER_NAME,
- .of_match_table = spmi_match_table,
- .owner = THIS_MODULE,
+ .name = QPNP_LPG_DRIVER_NAME,
+ .of_match_table = spmi_match_table,
+ .owner = THIS_MODULE,
},
.probe = qpnp_pwm_probe,
.remove = qpnp_pwm_remove,
@@ -2110,12 +2122,12 @@ static struct spmi_driver qpnp_lpg_driver = {
*/
int __init qpnp_lpg_init(void)
{
- return spmi_driver_register(&qpnp_lpg_driver);
+ return platform_driver_register(&qpnp_lpg_driver);
}
static void __exit qpnp_lpg_exit(void)
{
- spmi_driver_unregister(&qpnp_lpg_driver);
+ platform_driver_unregister(&qpnp_lpg_driver);
}
MODULE_DESCRIPTION("QPNP PMIC LPG driver");
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index b07545fbc2a5..44ecb5cc7142 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -796,8 +796,7 @@ config REGULATOR_RPM_SMD
application processor over SMD.
config REGULATOR_QPNP
- depends on SPMI || MSM_SPMI
- depends on OF_SPMI
+ depends on SPMI
tristate "Qualcomm QPNP regulator support"
help
This driver supports voltage regulators in Qualcomm PMIC chips which
@@ -806,8 +805,7 @@ config REGULATOR_QPNP
regulators. They also provide voltage switches and boost regulators.
config REGULATOR_QPNP_LABIBB
- depends on SPMI || MSM_SPMI
- depends on OF_SPMI
+ depends on SPMI
tristate "Qualcomm Technologies, Inc QPNP LAB/IBB regulator support"
help
This driver supports voltage regulators in Qualcomm Technologies, Inc
@@ -819,7 +817,7 @@ config REGULATOR_QPNP_LABIBB
config REGULATOR_SPM
bool "SPM regulator driver"
- depends on (SPMI || MSM_SPMI) && OF_SPMI
+ depends on SPMI
help
Enable support for the SPM regulator driver which is used for
setting voltages of processor supply regulators via the SPM module
diff --git a/drivers/regulator/qpnp-labibb-regulator.c b/drivers/regulator/qpnp-labibb-regulator.c
index dabcae1e78b0..47d6d987868c 100644
--- a/drivers/regulator/qpnp-labibb-regulator.c
+++ b/drivers/regulator/qpnp-labibb-regulator.c
@@ -16,10 +16,12 @@
#include <linux/err.h>
#include <linux/init.h>
#include <linux/kernel.h>
+#include <linux/regmap.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/spmi.h>
+#include <linux/platform_device.h>
#include <linux/string.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
@@ -428,7 +430,8 @@ struct ibb_regulator {
struct qpnp_labibb {
struct device *dev;
- struct spmi_device *spmi;
+ struct platform_device *pdev;
+ struct regmap *regmap;
u16 lab_base;
u16 ibb_base;
struct lab_regulator lab_vreg;
@@ -483,18 +486,18 @@ qpnp_labibb_read(struct qpnp_labibb *labibb, u8 *val,
u16 base, int count)
{
int rc = 0;
- struct spmi_device *spmi = labibb->spmi;
+ struct platform_device *pdev = labibb->pdev;
if (base == 0) {
pr_err("base cannot be zero base=0x%02x sid=0x%02x rc=%d\n",
- base, spmi->sid, rc);
+ base, to_spmi_device(pdev->dev.parent)->usid, rc);
return -EINVAL;
}
- rc = spmi_ext_register_readl(spmi->ctrl, spmi->sid, base, val, count);
+ rc = regmap_bulk_read(labibb->regmap, base, val, count);
if (rc) {
pr_err("SPMI read failed base=0x%02x sid=0x%02x rc=%d\n", base,
- spmi->sid, rc);
+ to_spmi_device(pdev->dev.parent)->usid, rc);
return rc;
}
return 0;
@@ -505,18 +508,18 @@ qpnp_labibb_write(struct qpnp_labibb *labibb, u16 base,
u8 *val, int count)
{
int rc = 0;
- struct spmi_device *spmi = labibb->spmi;
+ struct platform_device *pdev = labibb->pdev;
if (base == 0) {
pr_err("base cannot be zero base=0x%02x sid=0x%02x rc=%d\n",
- base, spmi->sid, rc);
+ base, to_spmi_device(pdev->dev.parent)->usid, rc);
return -EINVAL;
}
- rc = spmi_ext_register_writel(spmi->ctrl, spmi->sid, base, val, count);
+ rc = regmap_bulk_write(labibb->regmap, base, val, count);
if (rc) {
pr_err("write failed base=0x%02x sid=0x%02x rc=%d\n",
- base, spmi->sid, rc);
+ base, to_spmi_device(pdev->dev.parent)->usid, rc);
return rc;
}
@@ -528,21 +531,8 @@ qpnp_labibb_masked_write(struct qpnp_labibb *labibb, u16 base,
u8 mask, u8 val)
{
int rc;
- u8 reg;
- rc = qpnp_labibb_read(labibb, &reg, base, 1);
- if (rc) {
- pr_err("spmi read failed: addr=%03X, rc=%d\n", base, rc);
- return rc;
- }
- pr_debug("addr = 0x%x read 0x%x\n", base, reg);
-
- reg &= ~mask;
- reg |= val & mask;
-
- pr_debug("Writing 0x%x\n", reg);
-
- rc = qpnp_labibb_write(labibb, base, &reg, 1);
+ rc = regmap_update_bits(labibb->regmap, base, mask, val);
if (rc) {
pr_err("spmi write failed: addr=%03X, rc=%d\n", base, rc);
return rc;
@@ -2341,24 +2331,29 @@ static int register_qpnp_ibb_regulator(struct qpnp_labibb *labibb,
return 0;
}
-static int qpnp_labibb_regulator_probe(struct spmi_device *spmi)
+static int qpnp_labibb_regulator_probe(struct platform_device *pdev)
{
struct qpnp_labibb *labibb;
- struct resource *resource;
- struct spmi_resource *spmi_resource;
+ unsigned int base;
+ struct device_node *child;
const char *mode_name;
u8 type;
int rc = 0;
- labibb = devm_kzalloc(&spmi->dev,
+ labibb = devm_kzalloc(&pdev->dev,
sizeof(struct qpnp_labibb), GFP_KERNEL);
if (labibb == NULL) {
pr_err("labibb allocation failed.\n");
return -ENOMEM;
}
+ labibb->regmap = dev_get_regmap(pdev->dev.parent, NULL);
+ if (!labibb->regmap) {
+ dev_err(&pdev->dev, "Couldn't get parent's regmap\n");
+ return -EINVAL;
+ }
- labibb->dev = &(spmi->dev);
- labibb->spmi = spmi;
+ labibb->dev = &(pdev->dev);
+ labibb->pdev = pdev;
rc = of_property_read_string(labibb->dev->of_node,
"qpnp,qpnp-labibb-mode", &mode_name);
@@ -2393,22 +2388,21 @@ static int qpnp_labibb_regulator_probe(struct spmi_device *spmi)
return -EINVAL;
}
- spmi_for_each_container_dev(spmi_resource, spmi) {
- if (!spmi_resource) {
- pr_err("qpnp_labibb: spmi resource absent\n");
- return -ENXIO;
- }
-
- resource = spmi_get_resource(spmi, spmi_resource,
- IORESOURCE_MEM, 0);
- if (!(resource && resource->start)) {
- pr_err("node %s IO resource absent!\n",
- spmi->dev.of_node->full_name);
- return -ENXIO;
+ if (of_get_available_child_count(pdev->dev.of_node) == 0) {
+ pr_err("no child nodes\n");
+ return -ENXIO;
+ }
+ for_each_available_child_of_node(pdev->dev.of_node, child) {
+ rc = of_property_read_u32(child, "reg", &base);
+ if (rc < 0) {
+ dev_err(&pdev->dev,
+ "Couldn't find reg in node = %s rc = %d\n",
+ child->full_name, rc);
+ return rc;
}
rc = qpnp_labibb_read(labibb, &type,
- resource->start + REG_PERPH_TYPE, 1);
+ base + REG_PERPH_TYPE, 1);
if (rc) {
pr_err("Peripheral type read failed rc=%d\n", rc);
goto fail_registration;
@@ -2416,17 +2410,15 @@ static int qpnp_labibb_regulator_probe(struct spmi_device *spmi)
switch (type) {
case QPNP_LAB_TYPE:
- labibb->lab_base = resource->start;
- rc = register_qpnp_lab_regulator(labibb,
- spmi_resource->of_node);
+ labibb->lab_base = base;
+ rc = register_qpnp_lab_regulator(labibb, child);
if (rc)
goto fail_registration;
break;
case QPNP_IBB_TYPE:
- labibb->ibb_base = resource->start;
- rc = register_qpnp_ibb_regulator(labibb,
- spmi_resource->of_node);
+ labibb->ibb_base = base;
+ rc = register_qpnp_ibb_regulator(labibb, child);
if (rc)
goto fail_registration;
break;
@@ -2439,7 +2431,7 @@ static int qpnp_labibb_regulator_probe(struct spmi_device *spmi)
}
}
- dev_set_drvdata(&spmi->dev, labibb);
+ dev_set_drvdata(&pdev->dev, labibb);
return 0;
fail_registration:
@@ -2451,9 +2443,9 @@ fail_registration:
return rc;
}
-static int qpnp_labibb_regulator_remove(struct spmi_device *spmi)
+static int qpnp_labibb_regulator_remove(struct platform_device *pdev)
{
- struct qpnp_labibb *labibb = dev_get_drvdata(&spmi->dev);
+ struct qpnp_labibb *labibb = dev_get_drvdata(&pdev->dev);
if (labibb) {
if (labibb->lab_vreg.rdev)
@@ -2469,10 +2461,10 @@ static struct of_device_id spmi_match_table[] = {
{ },
};
-static struct spmi_driver qpnp_labibb_regulator_driver = {
+static struct platform_driver qpnp_labibb_regulator_driver = {
.driver = {
- .name = QPNP_LABIBB_REGULATOR_DRIVER_NAME,
- .of_match_table = spmi_match_table,
+ .name = QPNP_LABIBB_REGULATOR_DRIVER_NAME,
+ .of_match_table = spmi_match_table,
},
.probe = qpnp_labibb_regulator_probe,
.remove = qpnp_labibb_regulator_remove,
@@ -2480,13 +2472,13 @@ static struct spmi_driver qpnp_labibb_regulator_driver = {
static int __init qpnp_labibb_regulator_init(void)
{
- return spmi_driver_register(&qpnp_labibb_regulator_driver);
+ return platform_driver_register(&qpnp_labibb_regulator_driver);
}
arch_initcall(qpnp_labibb_regulator_init);
static void __exit qpnp_labibb_regulator_exit(void)
{
- spmi_driver_unregister(&qpnp_labibb_regulator_driver);
+ platform_driver_unregister(&qpnp_labibb_regulator_driver);
}
module_exit(qpnp_labibb_regulator_exit);
diff --git a/drivers/regulator/qpnp-regulator.c b/drivers/regulator/qpnp-regulator.c
index a5b92d3a0660..f42e65cc6e89 100644
--- a/drivers/regulator/qpnp-regulator.c
+++ b/drivers/regulator/qpnp-regulator.c
@@ -18,11 +18,13 @@
#include <linux/err.h>
#include <linux/string.h>
#include <linux/kernel.h>
+#include <linux/regmap.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/bitops.h>
#include <linux/slab.h>
#include <linux/spmi.h>
+#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
@@ -282,7 +284,8 @@ struct qpnp_regulator_mapping {
struct qpnp_regulator {
struct regulator_desc rdesc;
struct delayed_work ocp_work;
- struct spmi_device *spmi_dev;
+ struct platform_device *pdev;
+ struct regmap *regmap;
struct regulator_dev *rdev;
struct qpnp_voltage_set_points *set_points;
enum qpnp_regulator_logical_type logical_type;
@@ -483,15 +486,15 @@ static inline int qpnp_vreg_read(struct qpnp_regulator *vreg, u16 addr, u8 *buf,
char str[DEBUG_PRINT_BUFFER_SIZE];
int rc = 0;
- rc = spmi_ext_register_readl(vreg->spmi_dev->ctrl, vreg->spmi_dev->sid,
- vreg->base_addr + addr, buf, len);
+ rc = regmap_bulk_read(vreg->regmap, vreg->base_addr + addr, buf, len);
if (!rc && (qpnp_vreg_debug_mask & QPNP_VREG_DEBUG_READS)) {
str[0] = '\0';
fill_string(str, DEBUG_PRINT_BUFFER_SIZE, buf, len);
pr_info(" %-11s: read(0x%04X), sid=%d, len=%d; %s\n",
vreg->rdesc.name, vreg->base_addr + addr,
- vreg->spmi_dev->sid, len, str);
+ to_spmi_device(vreg->pdev->dev.parent)->usid, len,
+ str);
}
return rc;
@@ -508,11 +511,11 @@ static inline int qpnp_vreg_write(struct qpnp_regulator *vreg, u16 addr,
fill_string(str, DEBUG_PRINT_BUFFER_SIZE, buf, len);
pr_info("%-11s: write(0x%04X), sid=%d, len=%d; %s\n",
vreg->rdesc.name, vreg->base_addr + addr,
- vreg->spmi_dev->sid, len, str);
+ to_spmi_device(vreg->pdev->dev.parent)->usid, len,
+ str);
}
- rc = spmi_ext_register_writel(vreg->spmi_dev->ctrl,
- vreg->spmi_dev->sid, vreg->base_addr + addr, buf, len);
+ rc = regmap_bulk_write(vreg->regmap, vreg->base_addr + addr, buf, len);
if (!rc)
vreg->write_count += len;
@@ -1511,7 +1514,7 @@ static const struct qpnp_regulator_mapping supported_regulators[] = {
static int qpnp_regulator_match(struct qpnp_regulator *vreg)
{
const struct qpnp_regulator_mapping *mapping;
- struct device_node *node = vreg->spmi_dev->dev.of_node;
+ struct device_node *node = vreg->pdev->dev.of_node;
int rc, i;
u32 type_reg[2], dig_major_rev;
u8 version[QPNP_COMMON_REG_SUBTYPE - QPNP_COMMON_REG_DIG_MAJOR_REV + 1];
@@ -1834,26 +1837,27 @@ static int qpnp_regulator_init_registers(struct qpnp_regulator *vreg,
}
/* Fill in pdata elements based on values found in device tree. */
-static int qpnp_regulator_get_dt_config(struct spmi_device *spmi,
+static int qpnp_regulator_get_dt_config(struct platform_device *pdev,
struct qpnp_regulator_platform_data *pdata)
{
- struct resource *res;
- struct device_node *node = spmi->dev.of_node;
+ unsigned int base;
+ struct device_node *node = pdev->dev.of_node;
int rc = 0;
pdata->init_data.constraints.input_uV
= pdata->init_data.constraints.max_uV;
- res = spmi_get_resource(spmi, NULL, IORESOURCE_MEM, 0);
- if (!res) {
- dev_err(&spmi->dev, "%s: node is missing base address\n",
- __func__);
- return -EINVAL;
+ rc = of_property_read_u32(pdev->dev.of_node, "reg", &base);
+ if (rc < 0) {
+ dev_err(&pdev->dev,
+ "Couldn't find reg in node = %s rc = %d\n",
+ pdev->dev.of_node->full_name, rc);
+ return rc;
}
- pdata->base_addr = res->start;
+ pdata->base_addr = base;
/* OCP IRQ is optional so ignore get errors. */
- pdata->ocp_irq = spmi_get_irq_byname(spmi, NULL, "ocp");
+ pdata->ocp_irq = platform_get_irq_byname(pdev, "ocp");
if (pdata->ocp_irq < 0)
pdata->ocp_irq = 0;
@@ -1904,7 +1908,7 @@ static struct of_device_id spmi_match_table[];
#define MAX_NAME_LEN 127
-static int qpnp_regulator_probe(struct spmi_device *spmi)
+static int qpnp_regulator_probe(struct platform_device *pdev)
{
struct regulator_config reg_config = {};
struct qpnp_regulator_platform_data *pdata;
@@ -1917,20 +1921,23 @@ static int qpnp_regulator_probe(struct spmi_device *spmi)
bool is_dt;
vreg = kzalloc(sizeof(struct qpnp_regulator), GFP_KERNEL);
- if (!vreg) {
- dev_err(&spmi->dev, "%s: Can't allocate qpnp_regulator\n",
- __func__);
+ if (!vreg)
return -ENOMEM;
+
+ vreg->regmap = dev_get_regmap(pdev->dev.parent, NULL);
+ if (!vreg->regmap) {
+ dev_err(&pdev->dev, "Couldn't get parent's regmap\n");
+ return -EINVAL;
}
- is_dt = of_match_device(spmi_match_table, &spmi->dev);
+ is_dt = of_match_device(spmi_match_table, &pdev->dev);
/* Check if device tree is in use. */
if (is_dt) {
- init_data = of_get_regulator_init_data(&spmi->dev,
- spmi->dev.of_node);
+ init_data = of_get_regulator_init_data(&pdev->dev,
+ pdev->dev.of_node);
if (!init_data) {
- dev_err(&spmi->dev, "%s: unable to allocate memory\n",
+ dev_err(&pdev->dev, "%s: unable to allocate memory\n",
__func__);
kfree(vreg);
return -ENOMEM;
@@ -1940,12 +1947,12 @@ static int qpnp_regulator_probe(struct spmi_device *spmi)
memcpy(&of_pdata.init_data, init_data,
sizeof(struct regulator_init_data));
- if (of_get_property(spmi->dev.of_node, "parent-supply", NULL))
+ if (of_get_property(pdev->dev.of_node, "parent-supply", NULL))
of_pdata.init_data.supply_regulator = "parent";
- rc = qpnp_regulator_get_dt_config(spmi, &of_pdata);
+ rc = qpnp_regulator_get_dt_config(pdev, &of_pdata);
if (rc) {
- dev_err(&spmi->dev, "%s: DT parsing failed, rc=%d\n",
+ dev_err(&pdev->dev, "%s: DT parsing failed, rc=%d\n",
__func__, rc);
kfree(vreg);
return -ENOMEM;
@@ -1953,17 +1960,17 @@ static int qpnp_regulator_probe(struct spmi_device *spmi)
pdata = &of_pdata;
} else {
- pdata = spmi->dev.platform_data;
+ pdata = pdev->dev.platform_data;
}
if (pdata == NULL) {
- dev_err(&spmi->dev, "%s: no platform data specified\n",
+ dev_err(&pdev->dev, "%s: no platform data specified\n",
__func__);
kfree(vreg);
return -EINVAL;
}
- vreg->spmi_dev = spmi;
+ vreg->pdev = pdev;
vreg->prev_write_count = -1;
vreg->write_count = 0;
vreg->base_addr = pdata->base_addr;
@@ -1980,14 +1987,14 @@ static int qpnp_regulator_probe(struct spmi_device *spmi)
vreg->ocp_retry_delay_ms = QPNP_VS_OCP_DEFAULT_RETRY_DELAY_MS;
rdesc = &vreg->rdesc;
- rdesc->id = spmi->ctrl->nr;
+ rdesc->id = to_spmi_device(pdev->dev.parent)->ctrl->nr;
rdesc->owner = THIS_MODULE;
rdesc->type = REGULATOR_VOLTAGE;
reg_name = kzalloc(strnlen(pdata->init_data.constraints.name,
MAX_NAME_LEN) + 1, GFP_KERNEL);
if (!reg_name) {
- dev_err(&spmi->dev, "%s: Can't allocate regulator name\n",
+ dev_err(&pdev->dev, "%s: Can't allocate regulator name\n",
__func__);
kfree(vreg);
return -ENOMEM;
@@ -1996,7 +2003,7 @@ static int qpnp_regulator_probe(struct spmi_device *spmi)
strnlen(pdata->init_data.constraints.name, MAX_NAME_LEN) + 1);
rdesc->name = reg_name;
- dev_set_drvdata(&spmi->dev, vreg);
+ dev_set_drvdata(&pdev->dev, vreg);
rc = qpnp_regulator_match(vreg);
if (rc)
@@ -2029,7 +2036,7 @@ static int qpnp_regulator_probe(struct spmi_device *spmi)
vreg->ocp_irq = 0;
if (vreg->ocp_irq) {
- rc = devm_request_irq(&spmi->dev, vreg->ocp_irq,
+ rc = devm_request_irq(&pdev->dev, vreg->ocp_irq,
qpnp_regulator_vs_ocp_isr, IRQF_TRIGGER_RISING, "ocp",
vreg);
if (rc < 0) {
@@ -2041,10 +2048,10 @@ static int qpnp_regulator_probe(struct spmi_device *spmi)
INIT_DELAYED_WORK(&vreg->ocp_work, qpnp_regulator_vs_ocp_work);
}
- reg_config.dev = &spmi->dev;
+ reg_config.dev = &pdev->dev;
reg_config.init_data = &pdata->init_data;
reg_config.driver_data = vreg;
- reg_config.of_node = spmi->dev.of_node;
+ reg_config.of_node = pdev->dev.of_node;
vreg->rdev = regulator_register(rdesc, &reg_config);
if (IS_ERR(vreg->rdev)) {
rc = PTR_ERR(vreg->rdev);
@@ -2071,12 +2078,12 @@ bail:
return rc;
}
-static int qpnp_regulator_remove(struct spmi_device *spmi)
+static int qpnp_regulator_remove(struct platform_device *pdev)
{
struct qpnp_regulator *vreg;
- vreg = dev_get_drvdata(&spmi->dev);
- dev_set_drvdata(&spmi->dev, NULL);
+ vreg = dev_get_drvdata(&pdev->dev);
+ dev_set_drvdata(&pdev->dev, NULL);
if (vreg) {
regulator_unregister(vreg->rdev);
@@ -2094,17 +2101,17 @@ static struct of_device_id spmi_match_table[] = {
{}
};
-static const struct spmi_device_id qpnp_regulator_id[] = {
+static const struct platform_device_id qpnp_regulator_id[] = {
{ QPNP_REGULATOR_DRIVER_NAME, 0 },
{ }
};
MODULE_DEVICE_TABLE(spmi, qpnp_regulator_id);
-static struct spmi_driver qpnp_regulator_driver = {
+static struct platform_driver qpnp_regulator_driver = {
.driver = {
- .name = QPNP_REGULATOR_DRIVER_NAME,
- .of_match_table = spmi_match_table,
- .owner = THIS_MODULE,
+ .name = QPNP_REGULATOR_DRIVER_NAME,
+ .of_match_table = spmi_match_table,
+ .owner = THIS_MODULE,
},
.probe = qpnp_regulator_probe,
.remove = qpnp_regulator_remove,
@@ -2154,13 +2161,13 @@ int __init qpnp_regulator_init(void)
qpnp_regulator_set_point_init();
- return spmi_driver_register(&qpnp_regulator_driver);
+ return platform_driver_register(&qpnp_regulator_driver);
}
EXPORT_SYMBOL(qpnp_regulator_init);
static void __exit qpnp_regulator_exit(void)
{
- spmi_driver_unregister(&qpnp_regulator_driver);
+ platform_driver_unregister(&qpnp_regulator_driver);
}
MODULE_DESCRIPTION("QPNP PMIC regulator driver");
diff --git a/drivers/regulator/spm-regulator.c b/drivers/regulator/spm-regulator.c
index 73bea0ada363..839a2b2eb2fa 100644
--- a/drivers/regulator/spm-regulator.c
+++ b/drivers/regulator/spm-regulator.c
@@ -16,11 +16,13 @@
#include <linux/err.h>
#include <linux/init.h>
#include <linux/kernel.h>
+#include <linux/regmap.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/slab.h>
#include <linux/spmi.h>
+#include <linux/platform_device.h>
#include <linux/string.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
@@ -122,7 +124,8 @@ static const struct voltage_range hf_range1 = {1550000, 1550000, 3125000,
struct spm_vreg {
struct regulator_desc rdesc;
struct regulator_dev *rdev;
- struct spmi_device *spmi_dev;
+ struct platform_device *pdev;
+ struct regmap *regmap;
const struct voltage_range *range;
int uV;
int last_set_uV;
@@ -196,14 +199,18 @@ static int qpnp_smps_read_voltage(struct spm_vreg *vreg)
{
int rc;
u8 reg = 0;
+ uint val;
- rc = spmi_ext_register_readl(vreg->spmi_dev->ctrl, vreg->spmi_dev->sid,
- vreg->spmi_base_addr + QPNP_SMPS_REG_VOLTAGE_SETPOINT, &reg, 1);
+ rc = regmap_read(vreg->regmap,
+ vreg->spmi_base_addr + QPNP_SMPS_REG_VOLTAGE_SETPOINT,
+ &val);
if (rc) {
- dev_err(&vreg->spmi_dev->dev, "%s: could not read voltage setpoint register, rc=%d\n",
+ dev_err(&vreg->pdev->dev,
+ "%s: could not read voltage setpoint register, rc=%d\n",
__func__, rc);
return rc;
}
+ reg = (u8)val;
vreg->last_set_vlevel = reg;
vreg->last_set_uV = spm_regulator_vlevel_to_uv(vreg, reg);
@@ -215,10 +222,11 @@ static int qpnp_smps_set_mode(struct spm_vreg *vreg, u8 mode)
{
int rc;
- rc = spmi_ext_register_writel(vreg->spmi_dev->ctrl, vreg->spmi_dev->sid,
- vreg->spmi_base_addr + QPNP_SMPS_REG_MODE, &mode, 1);
+ rc = regmap_write(vreg->regmap,
+ vreg->spmi_base_addr + QPNP_SMPS_REG_MODE, mode);
if (rc)
- dev_err(&vreg->spmi_dev->dev, "%s: could not write to mode register, rc=%d\n",
+ dev_err(&vreg->pdev->dev,
+ "%s: could not write to mode register, rc=%d\n",
__func__, rc);
return rc;
@@ -275,12 +283,11 @@ static int spm_regulator_write_voltage(struct spm_vreg *vreg, int uV)
if (unlikely(vreg->bypass_spm || spm_failed)) {
/* Set voltage control register via SPMI. */
reg = vlevel;
- rc = spmi_ext_register_writel(vreg->spmi_dev->ctrl,
- vreg->spmi_dev->sid,
- vreg->spmi_base_addr + QPNP_SMPS_REG_VOLTAGE_SETPOINT,
- &reg, 1);
+ rc = regmap_write(vreg->regmap,
+ vreg->spmi_base_addr + QPNP_SMPS_REG_VOLTAGE_SETPOINT,
+ reg);
if (rc) {
- pr_err("%s: spmi_ext_register_writel failed, rc=%d\n",
+ pr_err("%s: regmap_write failed, rc=%d\n",
vreg->rdesc.name, rc);
return rc;
}
@@ -607,10 +614,13 @@ static int qpnp_smps_check_type(struct spm_vreg *vreg)
int rc;
u8 type[2];
- rc = spmi_ext_register_readl(vreg->spmi_dev->ctrl, vreg->spmi_dev->sid,
- vreg->spmi_base_addr + QPNP_SMPS_REG_TYPE, type, 2);
+ rc = regmap_bulk_read(vreg->regmap,
+ vreg->spmi_base_addr + QPNP_SMPS_REG_TYPE,
+ type,
+ 2);
if (rc) {
- dev_err(&vreg->spmi_dev->dev, "%s: could not read type register, rc=%d\n",
+ dev_err(&vreg->pdev->dev,
+ "%s: could not read type register, rc=%d\n",
__func__, rc);
return rc;
}
@@ -627,7 +637,8 @@ static int qpnp_smps_check_type(struct spm_vreg *vreg)
&& type[1] == QPNP_HF_SUBTYPE) {
vreg->regulator_type = QPNP_TYPE_HF;
} else {
- dev_err(&vreg->spmi_dev->dev, "%s: invalid type=0x%02X, subtype=0x%02X register pair\n",
+ dev_err(&vreg->pdev->dev,
+ "%s: invalid type=0x%02X, subtype=0x%02X register pair\n",
__func__, type[0], type[1]);
return -ENODEV;
};
@@ -640,21 +651,25 @@ static int qpnp_smps_init_range(struct spm_vreg *vreg,
{
int rc;
u8 reg = 0;
+ uint val;
- rc = spmi_ext_register_readl(vreg->spmi_dev->ctrl, vreg->spmi_dev->sid,
- vreg->spmi_base_addr + QPNP_SMPS_REG_VOLTAGE_RANGE, &reg, 1);
+ rc = regmap_read(vreg->regmap,
+ vreg->spmi_base_addr + QPNP_SMPS_REG_VOLTAGE_RANGE,
+ &val);
if (rc) {
- dev_err(&vreg->spmi_dev->dev, "%s: could not read voltage range register, rc=%d\n",
+ dev_err(&vreg->pdev->dev,
+ "%s: could not read voltage range register, rc=%d\n",
__func__, rc);
return rc;
}
+ reg = (u8)val;
if (reg == 0x00) {
vreg->range = range0;
} else if (reg == 0x01) {
vreg->range = range1;
} else {
- dev_err(&vreg->spmi_dev->dev, "%s: voltage range=%d is invalid\n",
+ dev_err(&vreg->pdev->dev, "%s: voltage range=%d is invalid\n",
__func__, reg);
rc = -EINVAL;
}
@@ -666,14 +681,18 @@ static int qpnp_ult_hf_init_range(struct spm_vreg *vreg)
{
int rc;
u8 reg = 0;
+ uint val;
- rc = spmi_ext_register_readl(vreg->spmi_dev->ctrl, vreg->spmi_dev->sid,
- vreg->spmi_base_addr + QPNP_SMPS_REG_VOLTAGE_SETPOINT, &reg, 1);
+ rc = regmap_read(vreg->regmap,
+ vreg->spmi_base_addr + QPNP_SMPS_REG_VOLTAGE_SETPOINT,
+ &val);
if (rc) {
- dev_err(&vreg->spmi_dev->dev, "%s: could not read voltage range register, rc=%d\n",
+ dev_err(&vreg->pdev->dev,
+ "%s: could not read voltage range register, rc=%d\n",
__func__, rc);
return rc;
}
+ reg = (u8)val;
vreg->range = (reg < ULT_SMPS_RANGE_SPLIT) ? &ult_hf_range0 :
&ult_hf_range1;
@@ -709,8 +728,9 @@ static int qpnp_smps_init_mode(struct spm_vreg *vreg)
{
const char *mode_name;
int rc;
+ uint val;
- rc = of_property_read_string(vreg->spmi_dev->dev.of_node, "qcom,mode",
+ rc = of_property_read_string(vreg->pdev->dev.of_node, "qcom,mode",
&mode_name);
if (!rc) {
if (strcmp("pwm", mode_name) == 0) {
@@ -719,26 +739,28 @@ static int qpnp_smps_init_mode(struct spm_vreg *vreg)
(vreg->regulator_type != QPNP_TYPE_ULT_HF)) {
vreg->init_mode = QPNP_SMPS_MODE_AUTO;
} else {
- dev_err(&vreg->spmi_dev->dev, "%s: unknown regulator mode: %s\n",
+ dev_err(&vreg->pdev->dev,
+ "%s: unknown regulator mode: %s\n",
__func__, mode_name);
return -EINVAL;
}
- rc = spmi_ext_register_writel(vreg->spmi_dev->ctrl,
- vreg->spmi_dev->sid,
- vreg->spmi_base_addr + QPNP_SMPS_REG_MODE,
- &vreg->init_mode, 1);
+ rc = regmap_write(vreg->regmap,
+ vreg->spmi_base_addr + QPNP_SMPS_REG_MODE,
+ *&vreg->init_mode);
if (rc)
- dev_err(&vreg->spmi_dev->dev, "%s: could not write mode register, rc=%d\n",
+ dev_err(&vreg->pdev->dev,
+ "%s: could not write mode register, rc=%d\n",
__func__, rc);
} else {
- rc = spmi_ext_register_readl(vreg->spmi_dev->ctrl,
- vreg->spmi_dev->sid,
- vreg->spmi_base_addr + QPNP_SMPS_REG_MODE,
- &vreg->init_mode, 1);
+ rc = regmap_read(vreg->regmap,
+ vreg->spmi_base_addr + QPNP_SMPS_REG_MODE,
+ &val);
if (rc)
- dev_err(&vreg->spmi_dev->dev, "%s: could not read mode register, rc=%d\n",
+ dev_err(&vreg->pdev->dev,
+ "%s: could not read mode register, rc=%d\n",
__func__, rc);
+ vreg->init_mode = (u8)val;
}
vreg->mode = vreg->init_mode;
@@ -751,14 +773,17 @@ static int qpnp_smps_init_step_rate(struct spm_vreg *vreg)
int rc;
u8 reg = 0;
int step = 0, delay;
+ uint val;
- rc = spmi_ext_register_readl(vreg->spmi_dev->ctrl, vreg->spmi_dev->sid,
- vreg->spmi_base_addr + QPNP_SMPS_REG_STEP_CTRL, &reg, 1);
+ rc = regmap_read(vreg->regmap,
+ vreg->spmi_base_addr + QPNP_SMPS_REG_STEP_CTRL, &val);
if (rc) {
- dev_err(&vreg->spmi_dev->dev, "%s: could not read stepping control register, rc=%d\n",
+ dev_err(&vreg->pdev->dev,
+ "%s: could not read stepping control register, rc=%d\n",
__func__, rc);
return rc;
}
+ reg = (u8)val;
/* ULT buck does not support steps */
if (vreg->regulator_type != QPNP_TYPE_ULT_HF)
@@ -858,18 +883,18 @@ static int spm_regulator_avs_register(struct spm_vreg *vreg,
return 0;
}
-static int spm_regulator_probe(struct spmi_device *spmi)
+static int spm_regulator_probe(struct platform_device *pdev)
{
struct regulator_config reg_config = {};
- struct device_node *node = spmi->dev.of_node;
+ struct device_node *node = pdev->dev.of_node;
struct regulator_init_data *init_data;
struct spm_vreg *vreg;
- struct resource *res;
+ unsigned int base;
bool bypass_spm;
int rc;
if (!node) {
- dev_err(&spmi->dev, "%s: device node missing\n", __func__);
+ dev_err(&pdev->dev, "%s: device node missing\n", __func__);
return -ENODEV;
}
@@ -878,27 +903,34 @@ static int spm_regulator_probe(struct spmi_device *spmi)
rc = msm_spm_probe_done();
if (rc) {
if (rc != -EPROBE_DEFER)
- dev_err(&spmi->dev, "%s: spm unavailable, rc=%d\n",
+ dev_err(&pdev->dev,
+ "%s: spm unavailable, rc=%d\n",
__func__, rc);
return rc;
}
}
- vreg = devm_kzalloc(&spmi->dev, sizeof(*vreg), GFP_KERNEL);
+ vreg = devm_kzalloc(&pdev->dev, sizeof(*vreg), GFP_KERNEL);
if (!vreg) {
pr_err("allocation failed.\n");
return -ENOMEM;
}
- vreg->spmi_dev = spmi;
+ vreg->regmap = dev_get_regmap(pdev->dev.parent, NULL);
+ if (!vreg->regmap) {
+ dev_err(&pdev->dev, "Couldn't get parent's regmap\n");
+ return -EINVAL;
+ }
+ vreg->pdev = pdev;
vreg->bypass_spm = bypass_spm;
- res = spmi_get_resource(spmi, NULL, IORESOURCE_MEM, 0);
- if (!res) {
- dev_err(&spmi->dev, "%s: node is missing base address\n",
- __func__);
- return -EINVAL;
+ rc = of_property_read_u32(pdev->dev.of_node, "reg", &base);
+ if (rc < 0) {
+ dev_err(&pdev->dev,
+ "Couldn't find reg in node = %s rc = %d\n",
+ pdev->dev.of_node->full_name, rc);
+ return rc;
}
- vreg->spmi_base_addr = res->start;
+ vreg->spmi_base_addr = base;
rc = qpnp_smps_check_type(vreg);
if (rc)
@@ -906,10 +938,10 @@ static int spm_regulator_probe(struct spmi_device *spmi)
/* Specify CPU 0 as default in order to handle shared regulator case. */
vreg->cpu_num = 0;
- of_property_read_u32(vreg->spmi_dev->dev.of_node, "qcom,cpu-num",
+ of_property_read_u32(vreg->pdev->dev.of_node, "qcom,cpu-num",
&vreg->cpu_num);
- of_property_read_u32(vreg->spmi_dev->dev.of_node, "qcom,recal-mask",
+ of_property_read_u32(vreg->pdev->dev.of_node, "qcom,recal-mask",
&vreg->recal_cluster_mask);
/*
@@ -940,9 +972,9 @@ static int spm_regulator_probe(struct spmi_device *spmi)
if (rc)
return rc;
- init_data = of_get_regulator_init_data(&spmi->dev, node);
+ init_data = of_get_regulator_init_data(&pdev->dev, node);
if (!init_data) {
- dev_err(&spmi->dev, "%s: unable to allocate memory\n",
+ dev_err(&pdev->dev, "%s: unable to allocate memory\n",
__func__);
return -ENOMEM;
}
@@ -953,7 +985,7 @@ static int spm_regulator_probe(struct spmi_device *spmi)
= REGULATOR_MODE_NORMAL | REGULATOR_MODE_IDLE;
if (!init_data->constraints.name) {
- dev_err(&spmi->dev, "%s: node is missing regulator name\n",
+ dev_err(&pdev->dev, "%s: node is missing regulator name\n",
__func__);
return -EINVAL;
}
@@ -967,7 +999,7 @@ static int spm_regulator_probe(struct spmi_device *spmi)
/ vreg->range->step_uV + 1;
vreg->max_step_uV = SPM_REGULATOR_MAX_STEP_UV;
- of_property_read_u32(vreg->spmi_dev->dev.of_node,
+ of_property_read_u32(vreg->pdev->dev.of_node,
"qcom,max-voltage-step", &vreg->max_step_uV);
if (vreg->max_step_uV > SPM_REGULATOR_MAX_STEP_UV)
@@ -977,7 +1009,7 @@ static int spm_regulator_probe(struct spmi_device *spmi)
pr_debug("%s: max single voltage step size=%u uV\n",
vreg->rdesc.name, vreg->max_step_uV);
- reg_config.dev = &spmi->dev;
+ reg_config.dev = &pdev->dev;
reg_config.init_data = init_data;
reg_config.driver_data = vreg;
reg_config.of_node = node;
@@ -985,18 +1017,18 @@ static int spm_regulator_probe(struct spmi_device *spmi)
if (IS_ERR(vreg->rdev)) {
rc = PTR_ERR(vreg->rdev);
- dev_err(&spmi->dev, "%s: regulator_register failed, rc=%d\n",
+ dev_err(&pdev->dev, "%s: regulator_register failed, rc=%d\n",
__func__, rc);
return rc;
}
- rc = spm_regulator_avs_register(vreg, &spmi->dev, node);
+ rc = spm_regulator_avs_register(vreg, &pdev->dev, node);
if (rc) {
regulator_unregister(vreg->rdev);
return rc;
}
- dev_set_drvdata(&spmi->dev, vreg);
+ dev_set_drvdata(&pdev->dev, vreg);
pr_info("name=%s, range=%s, voltage=%d uV, mode=%s, step rate=%d uV/us\n",
vreg->rdesc.name,
@@ -1009,9 +1041,9 @@ static int spm_regulator_probe(struct spmi_device *spmi)
return rc;
}
-static int spm_regulator_remove(struct spmi_device *spmi)
+static int spm_regulator_remove(struct platform_device *pdev)
{
- struct spm_vreg *vreg = dev_get_drvdata(&spmi->dev);
+ struct spm_vreg *vreg = dev_get_drvdata(&pdev->dev);
if (vreg->avs_rdev)
regulator_unregister(vreg->avs_rdev);
@@ -1025,13 +1057,13 @@ static struct of_device_id spm_regulator_match_table[] = {
{}
};
-static const struct spmi_device_id spm_regulator_id[] = {
+static const struct platform_device_id spm_regulator_id[] = {
{ SPM_REGULATOR_DRIVER_NAME, 0 },
{}
};
MODULE_DEVICE_TABLE(spmi, spm_regulator_id);
-static struct spmi_driver spm_regulator_driver = {
+static struct platform_driver spm_regulator_driver = {
.driver = {
.name = SPM_REGULATOR_DRIVER_NAME,
.of_match_table = spm_regulator_match_table,
@@ -1059,13 +1091,13 @@ int __init spm_regulator_init(void)
else
has_registered = true;
- return spmi_driver_register(&spm_regulator_driver);
+ return platform_driver_register(&spm_regulator_driver);
}
EXPORT_SYMBOL(spm_regulator_init);
static void __exit spm_regulator_exit(void)
{
- spmi_driver_unregister(&spm_regulator_driver);
+ platform_driver_unregister(&spm_regulator_driver);
}
arch_initcall(spm_regulator_init);
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index da25ffeb520d..ef3ff5e16e86 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -1593,7 +1593,7 @@ config RTC_DRV_MOXART
config RTC_DRV_QPNP
tristate "Qualcomm QPNP PMIC RTC"
- depends on (SPMI || MSM_SPMI) && OF_SPMI && MSM_QPNP_INT
+ depends on SPMI && OF_SPMI && MSM_QPNP_INT
help
Say Y here if you want to support the Qualcomm QPNP PMIC RTC.
@@ -1610,6 +1610,15 @@ config RTC_DRV_MT6397
If you want to use Mediatek(R) RTC interface, select Y or M here.
+config RTC_DRV_QPNP
+ tristate "Qualcomm QPNP PMIC RTC"
+ depends on SPMI
+ help
+ Say Y here if you want to support the Qualcomm QPNP PMIC RTC.
+
+ To compile this driver as a module, choose M here: the
+ module will be called qpnp-rtc.
+
config RTC_DRV_XGENE
tristate "APM X-Gene RTC"
depends on HAS_IOMEM
diff --git a/drivers/rtc/qpnp-rtc.c b/drivers/rtc/qpnp-rtc.c
index bb69b892d5e6..1b74b94796ba 100644
--- a/drivers/rtc/qpnp-rtc.c
+++ b/drivers/rtc/qpnp-rtc.c
@@ -11,15 +11,17 @@
*/
#include <linux/module.h>
+#include <linux/regmap.h>
#include <linux/init.h>
#include <linux/rtc.h>
#include <linux/pm.h>
#include <linux/slab.h>
#include <linux/idr.h>
#include <linux/of_device.h>
+#include <linux/of_irq.h>
#include <linux/spmi.h>
+#include <linux/platform_device.h>
#include <linux/spinlock.h>
-#include <linux/spmi.h>
#include <linux/alarmtimer.h>
/* RTC/ALARM Register offsets */
@@ -54,27 +56,26 @@ EXPORT_SYMBOL(poweron_alarm);
/* rtc driver internal structure */
struct qpnp_rtc {
- u8 rtc_ctrl_reg;
- u8 alarm_ctrl_reg1;
- u16 rtc_base;
- u16 alarm_base;
- u32 rtc_write_enable;
- u32 rtc_alarm_powerup;
- int rtc_alarm_irq;
- struct device *rtc_dev;
- struct rtc_device *rtc;
- struct spmi_device *spmi;
- spinlock_t alarm_ctrl_lock;
+ u8 rtc_ctrl_reg;
+ u8 alarm_ctrl_reg1;
+ u16 rtc_base;
+ u16 alarm_base;
+ u32 rtc_write_enable;
+ u32 rtc_alarm_powerup;
+ int rtc_alarm_irq;
+ struct device *rtc_dev;
+ struct rtc_device *rtc;
+ struct platform_device *pdev;
+ struct regmap *regmap;
+ spinlock_t alarm_ctrl_lock;
};
static int qpnp_read_wrapper(struct qpnp_rtc *rtc_dd, u8 *rtc_val,
u16 base, int count)
{
int rc;
- struct spmi_device *spmi = rtc_dd->spmi;
- rc = spmi_ext_register_readl(spmi->ctrl, spmi->sid, base, rtc_val,
- count);
+ rc = regmap_bulk_read(rtc_dd->regmap, base, rtc_val, count);
if (rc) {
dev_err(rtc_dd->rtc_dev, "SPMI read failed\n");
return rc;
@@ -86,10 +87,8 @@ static int qpnp_write_wrapper(struct qpnp_rtc *rtc_dd, u8 *rtc_val,
u16 base, int count)
{
int rc;
- struct spmi_device *spmi = rtc_dd->spmi;
- rc = spmi_ext_register_writel(spmi->ctrl, spmi->sid, base, rtc_val,
- count);
+ rc = regmap_bulk_write(rtc_dd->regmap, base, rtc_val, count);
if (rc) {
dev_err(rtc_dd->rtc_dev, "SPMI write failed\n");
return rc;
@@ -464,34 +463,38 @@ rtc_alarm_handled:
return IRQ_HANDLED;
}
-static int qpnp_rtc_probe(struct spmi_device *spmi)
+static int qpnp_rtc_probe(struct platform_device *pdev)
{
int rc;
u8 subtype;
struct qpnp_rtc *rtc_dd;
- struct resource *resource;
- struct spmi_resource *spmi_resource;
+ unsigned int base;
+ struct device_node *child;
- rtc_dd = devm_kzalloc(&spmi->dev, sizeof(*rtc_dd), GFP_KERNEL);
- if (rtc_dd == NULL) {
- dev_err(&spmi->dev, "Unable to allocate memory!\n");
+ rtc_dd = devm_kzalloc(&pdev->dev, sizeof(*rtc_dd), GFP_KERNEL);
+ if (rtc_dd == NULL)
return -ENOMEM;
+
+ rtc_dd->regmap = dev_get_regmap(pdev->dev.parent, NULL);
+ if (!rtc_dd->regmap) {
+ dev_err(&pdev->dev, "Couldn't get parent's regmap\n");
+ return -EINVAL;
}
/* Get the rtc write property */
- rc = of_property_read_u32(spmi->dev.of_node, "qcom,qpnp-rtc-write",
+ rc = of_property_read_u32(pdev->dev.of_node, "qcom,qpnp-rtc-write",
&rtc_dd->rtc_write_enable);
if (rc && rc != -EINVAL) {
- dev_err(&spmi->dev,
+ dev_err(&pdev->dev,
"Error reading rtc_write_enable property %d\n", rc);
return rc;
}
- rc = of_property_read_u32(spmi->dev.of_node,
+ rc = of_property_read_u32(pdev->dev.of_node,
"qcom,qpnp-rtc-alarm-pwrup",
&rtc_dd->rtc_alarm_powerup);
if (rc && rc != -EINVAL) {
- dev_err(&spmi->dev,
+ dev_err(&pdev->dev,
"Error reading rtc_alarm_powerup property %d\n", rc);
return rc;
}
@@ -499,53 +502,49 @@ static int qpnp_rtc_probe(struct spmi_device *spmi)
/* Initialise spinlock to protect RTC control register */
spin_lock_init(&rtc_dd->alarm_ctrl_lock);
- rtc_dd->rtc_dev = &(spmi->dev);
- rtc_dd->spmi = spmi;
+ rtc_dd->rtc_dev = &(pdev->dev);
+ rtc_dd->pdev = pdev;
- /* Get RTC/ALARM resources */
- spmi_for_each_container_dev(spmi_resource, spmi) {
- if (!spmi_resource) {
- dev_err(&spmi->dev,
- "%s: rtc_alarm: spmi resource absent!\n",
- __func__);
- rc = -ENXIO;
- goto fail_rtc_enable;
- }
- resource = spmi_get_resource(spmi, spmi_resource,
- IORESOURCE_MEM, 0);
- if (!(resource && resource->start)) {
- dev_err(&spmi->dev,
- "%s: node %s IO resource absent!\n",
- __func__, spmi->dev.of_node->full_name);
- rc = -ENXIO;
+ if (of_get_available_child_count(pdev->dev.of_node) == 0) {
+ pr_err("no child nodes\n");
+ rc = -ENXIO;
+ goto fail_rtc_enable;
+ }
+
+ /* Get RTC/ALARM resources */
+ for_each_available_child_of_node(pdev->dev.of_node, child) {
+ rc = of_property_read_u32(child, "reg", &base);
+ if (rc < 0) {
+ dev_err(&pdev->dev,
+ "Couldn't find reg in node = %s rc = %d\n",
+ child->full_name, rc);
goto fail_rtc_enable;
}
rc = qpnp_read_wrapper(rtc_dd, &subtype,
- resource->start + REG_OFFSET_PERP_SUBTYPE, 1);
+ base + REG_OFFSET_PERP_SUBTYPE, 1);
if (rc) {
- dev_err(&spmi->dev,
+ dev_err(&pdev->dev,
"Peripheral subtype read failed\n");
goto fail_rtc_enable;
}
switch (subtype) {
case RTC_PERPH_SUBTYPE:
- rtc_dd->rtc_base = resource->start;
+ rtc_dd->rtc_base = base;
break;
case ALARM_PERPH_SUBTYPE:
- rtc_dd->alarm_base = resource->start;
- rtc_dd->rtc_alarm_irq =
- spmi_get_irq(spmi, spmi_resource, 0);
+ rtc_dd->alarm_base = base;
+ rtc_dd->rtc_alarm_irq = of_irq_get(child, 0);
if (rtc_dd->rtc_alarm_irq < 0) {
- dev_err(&spmi->dev, "ALARM IRQ absent\n");
+ dev_err(&pdev->dev, "ALARM IRQ absent\n");
rc = -ENXIO;
goto fail_rtc_enable;
}
break;
default:
- dev_err(&spmi->dev, "Invalid peripheral subtype\n");
+ dev_err(&pdev->dev, "Invalid peripheral subtype\n");
rc = -EINVAL;
goto fail_rtc_enable;
}
@@ -554,22 +553,19 @@ static int qpnp_rtc_probe(struct spmi_device *spmi)
rc = qpnp_read_wrapper(rtc_dd, &rtc_dd->rtc_ctrl_reg,
rtc_dd->rtc_base + REG_OFFSET_RTC_CTRL, 1);
if (rc) {
- dev_err(&spmi->dev,
- "Read from RTC control reg failed\n");
+ dev_err(&pdev->dev, "Read from RTC control reg failed\n");
goto fail_rtc_enable;
}
if (!(rtc_dd->rtc_ctrl_reg & BIT_RTC_ENABLE)) {
- dev_err(&spmi->dev,
- "RTC h/w disabled, rtc not registered\n");
+ dev_err(&pdev->dev, "RTC h/w disabled, rtc not registered\n");
goto fail_rtc_enable;
}
rc = qpnp_read_wrapper(rtc_dd, &rtc_dd->alarm_ctrl_reg1,
rtc_dd->alarm_base + REG_OFFSET_ALARM_CTRL1, 1);
if (rc) {
- dev_err(&spmi->dev,
- "Read from Alarm control reg failed\n");
+ dev_err(&pdev->dev, "Read from Alarm control reg failed\n");
goto fail_rtc_enable;
}
/* Enable abort enable feature */
@@ -577,20 +573,20 @@ static int qpnp_rtc_probe(struct spmi_device *spmi)
rc = qpnp_write_wrapper(rtc_dd, &rtc_dd->alarm_ctrl_reg1,
rtc_dd->alarm_base + REG_OFFSET_ALARM_CTRL1, 1);
if (rc) {
- dev_err(&spmi->dev, "SPMI write failed!\n");
+ dev_err(&pdev->dev, "SPMI write failed!\n");
goto fail_rtc_enable;
}
if (rtc_dd->rtc_write_enable == true)
qpnp_rtc_ops.set_time = qpnp_rtc_set_time;
- dev_set_drvdata(&spmi->dev, rtc_dd);
+ dev_set_drvdata(&pdev->dev, rtc_dd);
/* Register the RTC device */
- rtc_dd->rtc = rtc_device_register("qpnp_rtc", &spmi->dev,
+ rtc_dd->rtc = rtc_device_register("qpnp_rtc", &pdev->dev,
&qpnp_rtc_ops, THIS_MODULE);
if (IS_ERR(rtc_dd->rtc)) {
- dev_err(&spmi->dev, "%s: RTC registration failed (%ld)\n",
+ dev_err(&pdev->dev, "%s: RTC registration failed (%ld)\n",
__func__, PTR_ERR(rtc_dd->rtc));
rc = PTR_ERR(rtc_dd->rtc);
goto fail_rtc_enable;
@@ -604,38 +600,38 @@ static int qpnp_rtc_probe(struct spmi_device *spmi)
qpnp_alarm_trigger, IRQF_TRIGGER_RISING,
"qpnp_rtc_alarm", rtc_dd);
if (rc) {
- dev_err(&spmi->dev, "Request IRQ failed (%d)\n", rc);
+ dev_err(&pdev->dev, "Request IRQ failed (%d)\n", rc);
goto fail_req_irq;
}
- device_init_wakeup(&spmi->dev, 1);
+ device_init_wakeup(&pdev->dev, 1);
enable_irq_wake(rtc_dd->rtc_alarm_irq);
- dev_dbg(&spmi->dev, "Probe success !!\n");
+ dev_dbg(&pdev->dev, "Probe success !!\n");
return 0;
fail_req_irq:
rtc_device_unregister(rtc_dd->rtc);
fail_rtc_enable:
- dev_set_drvdata(&spmi->dev, NULL);
+ dev_set_drvdata(&pdev->dev, NULL);
return rc;
}
-static int qpnp_rtc_remove(struct spmi_device *spmi)
+static int qpnp_rtc_remove(struct platform_device *pdev)
{
- struct qpnp_rtc *rtc_dd = dev_get_drvdata(&spmi->dev);
+ struct qpnp_rtc *rtc_dd = dev_get_drvdata(&pdev->dev);
- device_init_wakeup(&spmi->dev, 0);
+ device_init_wakeup(&pdev->dev, 0);
free_irq(rtc_dd->rtc_alarm_irq, rtc_dd);
rtc_device_unregister(rtc_dd->rtc);
- dev_set_drvdata(&spmi->dev, NULL);
+ dev_set_drvdata(&pdev->dev, NULL);
return 0;
}
-static void qpnp_rtc_shutdown(struct spmi_device *spmi)
+static void qpnp_rtc_shutdown(struct platform_device *pdev)
{
u8 value[4] = {0};
u8 reg;
@@ -644,11 +640,11 @@ static void qpnp_rtc_shutdown(struct spmi_device *spmi)
struct qpnp_rtc *rtc_dd;
bool rtc_alarm_powerup;
- if (!spmi) {
+ if (!pdev) {
pr_err("qpnp-rtc: spmi device not found\n");
return;
}
- rtc_dd = dev_get_drvdata(&spmi->dev);
+ rtc_dd = dev_get_drvdata(&pdev->dev);
if (!rtc_dd) {
pr_err("qpnp-rtc: rtc driver data not found\n");
return;
@@ -656,7 +652,7 @@ static void qpnp_rtc_shutdown(struct spmi_device *spmi)
rtc_alarm_powerup = rtc_dd->rtc_alarm_powerup;
if (!rtc_alarm_powerup && !poweron_alarm) {
spin_lock_irqsave(&rtc_dd->alarm_ctrl_lock, irq_flags);
- dev_dbg(&spmi->dev, "Disabling alarm interrupts\n");
+ dev_dbg(&pdev->dev, "Disabling alarm interrupts\n");
/* Disable RTC alarms */
reg = rtc_dd->alarm_ctrl_reg1;
@@ -687,26 +683,26 @@ static struct of_device_id spmi_match_table[] = {
{}
};
-static struct spmi_driver qpnp_rtc_driver = {
- .probe = qpnp_rtc_probe,
- .remove = qpnp_rtc_remove,
- .shutdown = qpnp_rtc_shutdown,
- .driver = {
- .name = "qcom,qpnp-rtc",
- .owner = THIS_MODULE,
- .of_match_table = spmi_match_table,
+static struct platform_driver qpnp_rtc_driver = {
+ .probe = qpnp_rtc_probe,
+ .remove = qpnp_rtc_remove,
+ .shutdown = qpnp_rtc_shutdown,
+ .driver = {
+ .name = "qcom,qpnp-rtc",
+ .owner = THIS_MODULE,
+ .of_match_table = spmi_match_table,
},
};
static int __init qpnp_rtc_init(void)
{
- return spmi_driver_register(&qpnp_rtc_driver);
+ return platform_driver_register(&qpnp_rtc_driver);
}
module_init(qpnp_rtc_init);
static void __exit qpnp_rtc_exit(void)
{
- spmi_driver_unregister(&qpnp_rtc_driver);
+ platform_driver_unregister(&qpnp_rtc_driver);
}
module_exit(qpnp_rtc_exit);
diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index 5cfce4246b7a..5407b49ccf62 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -369,8 +369,7 @@ config THERMAL_QPNP
tristate "Qualcomm Plug-and-Play PMIC Temperature Alarm"
depends on THERMAL
depends on OF
- depends on SPMI || MSM_SPMI
- depends on OF_SPMI
+ depends on SPMI
help
This enables a thermal Sysfs driver for Qualcomm plug-and-play (QPNP)
PMIC devices. It shows up in Sysfs as a thermal zone with multiple
@@ -384,7 +383,7 @@ config THERMAL_QPNP
config THERMAL_QPNP_ADC_TM
tristate "Qualcomm 8974 Thermal Monitor ADC Driver"
depends on THERMAL
- depends on SPMI || MSM_SPMI
+ depends on SPMI
help
This enables the thermal Sysfs driver for the ADC thermal monitoring
device. It shows up in Sysfs as a thermal zone with multiple trip points.
diff --git a/drivers/thermal/qpnp-adc-tm.c b/drivers/thermal/qpnp-adc-tm.c
new file mode 100644
index 000000000000..53bc0b28f19a
--- /dev/null
+++ b/drivers/thermal/qpnp-adc-tm.c
@@ -0,0 +1,2675 @@
+/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+#include <linux/kernel.h>
+#include <linux/regmap.h>
+#include <linux/of.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/mutex.h>
+#include <linux/types.h>
+#include <linux/hwmon.h>
+#include <linux/module.h>
+#include <linux/debugfs.h>
+#include <linux/spmi.h>
+#include <linux/platform_device.h>
+#include <linux/of_irq.h>
+#include <linux/interrupt.h>
+#include <linux/completion.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/qpnp/qpnp-adc.h>
+#include <linux/thermal.h>
+#include <linux/platform_device.h>
+
+/* QPNP VADC TM register definition */
+#define QPNP_REVISION3 0x2
+#define QPNP_PERPH_SUBTYPE 0x5
+#define QPNP_PERPH_TYPE2 0x2
+#define QPNP_REVISION_EIGHT_CHANNEL_SUPPORT 2
+#define QPNP_PERPH_SUBTYPE_TWO_CHANNEL_SUPPORT 0x22
+#define QPNP_STATUS1 0x8
+#define QPNP_STATUS1_OP_MODE 4
+#define QPNP_STATUS1_MEAS_INTERVAL_EN_STS BIT(2)
+#define QPNP_STATUS1_REQ_STS BIT(1)
+#define QPNP_STATUS1_EOC BIT(0)
+#define QPNP_STATUS2 0x9
+#define QPNP_STATUS2_CONV_SEQ_STATE 6
+#define QPNP_STATUS2_FIFO_NOT_EMPTY_FLAG BIT(1)
+#define QPNP_STATUS2_CONV_SEQ_TIMEOUT_STS BIT(0)
+#define QPNP_CONV_TIMEOUT_ERR 2
+
+#define QPNP_MODE_CTL 0x40
+#define QPNP_OP_MODE_SHIFT 3
+#define QPNP_VREF_XO_THM_FORCE BIT(2)
+#define QPNP_AMUX_TRIM_EN BIT(1)
+#define QPNP_ADC_TRIM_EN BIT(0)
+#define QPNP_EN_CTL1 0x46
+#define QPNP_ADC_TM_EN BIT(7)
+#define QPNP_ADC_CH_SEL_CTL 0x48
+#define QPNP_ADC_DIG_PARAM 0x50
+#define QPNP_ADC_DIG_DEC_RATIO_SEL_SHIFT 3
+#define QPNP_HW_SETTLE_DELAY 0x51
+#define QPNP_CONV_REQ 0x52
+#define QPNP_CONV_REQ_SET BIT(7)
+#define QPNP_CONV_SEQ_CTL 0x54
+#define QPNP_CONV_SEQ_HOLDOFF_SHIFT 4
+#define QPNP_CONV_SEQ_TRIG_CTL 0x55
+#define QPNP_ADC_TM_MEAS_INTERVAL_CTL 0x57
+#define QPNP_ADC_TM_MEAS_INTERVAL_TIME_SHIFT 0x3
+#define QPNP_ADC_TM_MEAS_INTERVAL_CTL2 0x58
+#define QPNP_ADC_TM_MEAS_INTERVAL_CTL2_SHIFT 0x4
+#define QPNP_ADC_TM_MEAS_INTERVAL_CTL2_MASK 0xf0
+#define QPNP_ADC_TM_MEAS_INTERVAL_CTL3_MASK 0xf
+
+#define QPNP_ADC_MEAS_INTERVAL_OP_CTL 0x59
+#define QPNP_ADC_MEAS_INTERVAL_OP BIT(7)
+
+#define QPNP_FAST_AVG_CTL 0x5a
+#define QPNP_FAST_AVG_EN 0x5b
+#define QPNP_FAST_AVG_ENABLED BIT(7)
+
+#define QPNP_M0_LOW_THR_LSB 0x5c
+#define QPNP_M0_LOW_THR_MSB 0x5d
+#define QPNP_M0_HIGH_THR_LSB 0x5e
+#define QPNP_M0_HIGH_THR_MSB 0x5f
+#define QPNP_M1_ADC_CH_SEL_CTL 0x68
+#define QPNP_M1_LOW_THR_LSB 0x69
+#define QPNP_M1_LOW_THR_MSB 0x6a
+#define QPNP_M1_HIGH_THR_LSB 0x6b
+#define QPNP_M1_HIGH_THR_MSB 0x6c
+#define QPNP_M2_ADC_CH_SEL_CTL 0x70
+#define QPNP_M2_LOW_THR_LSB 0x71
+#define QPNP_M2_LOW_THR_MSB 0x72
+#define QPNP_M2_HIGH_THR_LSB 0x73
+#define QPNP_M2_HIGH_THR_MSB 0x74
+#define QPNP_M3_ADC_CH_SEL_CTL 0x78
+#define QPNP_M3_LOW_THR_LSB 0x79
+#define QPNP_M3_LOW_THR_MSB 0x7a
+#define QPNP_M3_HIGH_THR_LSB 0x7b
+#define QPNP_M3_HIGH_THR_MSB 0x7c
+#define QPNP_M4_ADC_CH_SEL_CTL 0x80
+#define QPNP_M4_LOW_THR_LSB 0x81
+#define QPNP_M4_LOW_THR_MSB 0x82
+#define QPNP_M4_HIGH_THR_LSB 0x83
+#define QPNP_M4_HIGH_THR_MSB 0x84
+#define QPNP_M5_ADC_CH_SEL_CTL 0x88
+#define QPNP_M5_LOW_THR_LSB 0x89
+#define QPNP_M5_LOW_THR_MSB 0x8a
+#define QPNP_M5_HIGH_THR_LSB 0x8b
+#define QPNP_M5_HIGH_THR_MSB 0x8c
+#define QPNP_M6_ADC_CH_SEL_CTL 0x90
+#define QPNP_M6_LOW_THR_LSB 0x91
+#define QPNP_M6_LOW_THR_MSB 0x92
+#define QPNP_M6_HIGH_THR_LSB 0x93
+#define QPNP_M6_HIGH_THR_MSB 0x94
+#define QPNP_M7_ADC_CH_SEL_CTL 0x98
+#define QPNP_M7_LOW_THR_LSB 0x99
+#define QPNP_M7_LOW_THR_MSB 0x9a
+#define QPNP_M7_HIGH_THR_LSB 0x9b
+#define QPNP_M7_HIGH_THR_MSB 0x9c
+
+#define QPNP_ADC_TM_MULTI_MEAS_EN 0x41
+#define QPNP_ADC_TM_MULTI_MEAS_EN_M0 BIT(0)
+#define QPNP_ADC_TM_MULTI_MEAS_EN_M1 BIT(1)
+#define QPNP_ADC_TM_MULTI_MEAS_EN_M2 BIT(2)
+#define QPNP_ADC_TM_MULTI_MEAS_EN_M3 BIT(3)
+#define QPNP_ADC_TM_MULTI_MEAS_EN_M4 BIT(4)
+#define QPNP_ADC_TM_MULTI_MEAS_EN_M5 BIT(5)
+#define QPNP_ADC_TM_MULTI_MEAS_EN_M6 BIT(6)
+#define QPNP_ADC_TM_MULTI_MEAS_EN_M7 BIT(7)
+#define QPNP_ADC_TM_LOW_THR_INT_EN 0x42
+#define QPNP_ADC_TM_LOW_THR_INT_EN_M0 BIT(0)
+#define QPNP_ADC_TM_LOW_THR_INT_EN_M1 BIT(1)
+#define QPNP_ADC_TM_LOW_THR_INT_EN_M2 BIT(2)
+#define QPNP_ADC_TM_LOW_THR_INT_EN_M3 BIT(3)
+#define QPNP_ADC_TM_LOW_THR_INT_EN_M4 BIT(4)
+#define QPNP_ADC_TM_LOW_THR_INT_EN_M5 BIT(5)
+#define QPNP_ADC_TM_LOW_THR_INT_EN_M6 BIT(6)
+#define QPNP_ADC_TM_LOW_THR_INT_EN_M7 BIT(7)
+#define QPNP_ADC_TM_HIGH_THR_INT_EN 0x43
+#define QPNP_ADC_TM_HIGH_THR_INT_EN_M0 BIT(0)
+#define QPNP_ADC_TM_HIGH_THR_INT_EN_M1 BIT(1)
+#define QPNP_ADC_TM_HIGH_THR_INT_EN_M2 BIT(2)
+#define QPNP_ADC_TM_HIGH_THR_INT_EN_M3 BIT(3)
+#define QPNP_ADC_TM_HIGH_THR_INT_EN_M4 BIT(4)
+#define QPNP_ADC_TM_HIGH_THR_INT_EN_M5 BIT(5)
+#define QPNP_ADC_TM_HIGH_THR_INT_EN_M6 BIT(6)
+#define QPNP_ADC_TM_HIGH_THR_INT_EN_M7 BIT(7)
+
+#define QPNP_ADC_TM_M0_MEAS_INTERVAL_CTL 0x59
+#define QPNP_ADC_TM_M1_MEAS_INTERVAL_CTL 0x6d
+#define QPNP_ADC_TM_M2_MEAS_INTERVAL_CTL 0x75
+#define QPNP_ADC_TM_M3_MEAS_INTERVAL_CTL 0x7d
+#define QPNP_ADC_TM_M4_MEAS_INTERVAL_CTL 0x85
+#define QPNP_ADC_TM_M5_MEAS_INTERVAL_CTL 0x8d
+#define QPNP_ADC_TM_M6_MEAS_INTERVAL_CTL 0x95
+#define QPNP_ADC_TM_M7_MEAS_INTERVAL_CTL 0x9d
+#define QPNP_ADC_TM_STATUS1 0x8
+#define QPNP_ADC_TM_STATUS_LOW 0xa
+#define QPNP_ADC_TM_STATUS_HIGH 0xb
+
+#define QPNP_ADC_TM_M0_LOW_THR 0x5d5c
+#define QPNP_ADC_TM_M0_HIGH_THR 0x5f5e
+#define QPNP_ADC_TM_MEAS_INTERVAL 0x0
+
+#define QPNP_ADC_TM_THR_LSB_MASK(val) (val & 0xff)
+#define QPNP_ADC_TM_THR_MSB_MASK(val) ((val & 0xff00) >> 8)
+
+#define QPNP_MIN_TIME 2000
+#define QPNP_MAX_TIME 2100
+#define QPNP_RETRY 1000
+
+struct qpnp_adc_thr_info {
+ u8 status_low;
+ u8 status_high;
+ u8 qpnp_adc_tm_meas_en;
+ u8 adc_tm_low_enable;
+ u8 adc_tm_high_enable;
+ u8 adc_tm_low_thr_set;
+ u8 adc_tm_high_thr_set;
+};
+
+struct qpnp_adc_thr_client_info {
+ struct list_head list;
+ struct qpnp_adc_tm_btm_param *btm_param;
+ int32_t low_thr_requested;
+ int32_t high_thr_requested;
+ enum qpnp_state_request state_requested;
+ enum qpnp_state_request state_req_copy;
+ bool low_thr_set;
+ bool high_thr_set;
+ bool notify_low_thr;
+ bool notify_high_thr;
+};
+
+struct qpnp_adc_tm_sensor {
+ struct thermal_zone_device *tz_dev;
+ struct qpnp_adc_tm_chip *chip;
+ enum thermal_device_mode mode;
+ uint32_t sensor_num;
+ enum qpnp_adc_meas_timer_select timer_select;
+ uint32_t meas_interval;
+ uint32_t low_thr;
+ uint32_t high_thr;
+ uint32_t btm_channel_num;
+ uint32_t vadc_channel_num;
+ struct workqueue_struct *req_wq;
+ struct work_struct work;
+ bool thermal_node;
+ uint32_t scale_type;
+ struct list_head thr_list;
+};
+
+struct qpnp_adc_tm_chip {
+ struct device *dev;
+ struct qpnp_adc_drv *adc;
+ struct list_head list;
+ bool adc_tm_initialized;
+ bool adc_tm_recalib_check;
+ int max_channels_available;
+ atomic_t wq_cnt;
+ struct qpnp_vadc_chip *vadc_dev;
+ struct workqueue_struct *high_thr_wq;
+ struct workqueue_struct *low_thr_wq;
+ struct work_struct trigger_high_thr_work;
+ struct work_struct trigger_low_thr_work;
+ bool adc_vote_enable;
+ struct qpnp_adc_thr_info th_info;
+ struct qpnp_adc_tm_sensor sensor[0];
+};
+
+LIST_HEAD(qpnp_adc_tm_device_list);
+
+struct qpnp_adc_tm_trip_reg_type {
+ enum qpnp_adc_tm_channel_select btm_amux_chan;
+ uint16_t low_thr_lsb_addr;
+ uint16_t low_thr_msb_addr;
+ uint16_t high_thr_lsb_addr;
+ uint16_t high_thr_msb_addr;
+ u8 multi_meas_en;
+ u8 low_thr_int_chan_en;
+ u8 high_thr_int_chan_en;
+ u8 meas_interval_ctl;
+};
+
+static struct qpnp_adc_tm_trip_reg_type adc_tm_data[] = {
+ [QPNP_ADC_TM_CHAN0] = {QPNP_ADC_TM_M0_ADC_CH_SEL_CTL,
+ QPNP_M0_LOW_THR_LSB,
+ QPNP_M0_LOW_THR_MSB, QPNP_M0_HIGH_THR_LSB,
+ QPNP_M0_HIGH_THR_MSB, QPNP_ADC_TM_MULTI_MEAS_EN_M0,
+ QPNP_ADC_TM_LOW_THR_INT_EN_M0, QPNP_ADC_TM_HIGH_THR_INT_EN_M0,
+ QPNP_ADC_TM_M0_MEAS_INTERVAL_CTL},
+ [QPNP_ADC_TM_CHAN1] = {QPNP_ADC_TM_M1_ADC_CH_SEL_CTL,
+ QPNP_M1_LOW_THR_LSB,
+ QPNP_M1_LOW_THR_MSB, QPNP_M1_HIGH_THR_LSB,
+ QPNP_M1_HIGH_THR_MSB, QPNP_ADC_TM_MULTI_MEAS_EN_M1,
+ QPNP_ADC_TM_LOW_THR_INT_EN_M1, QPNP_ADC_TM_HIGH_THR_INT_EN_M1,
+ QPNP_ADC_TM_M1_MEAS_INTERVAL_CTL},
+ [QPNP_ADC_TM_CHAN2] = {QPNP_ADC_TM_M2_ADC_CH_SEL_CTL,
+ QPNP_M2_LOW_THR_LSB,
+ QPNP_M2_LOW_THR_MSB, QPNP_M2_HIGH_THR_LSB,
+ QPNP_M2_HIGH_THR_MSB, QPNP_ADC_TM_MULTI_MEAS_EN_M2,
+ QPNP_ADC_TM_LOW_THR_INT_EN_M2, QPNP_ADC_TM_HIGH_THR_INT_EN_M2,
+ QPNP_ADC_TM_M2_MEAS_INTERVAL_CTL},
+ [QPNP_ADC_TM_CHAN3] = {QPNP_ADC_TM_M3_ADC_CH_SEL_CTL,
+ QPNP_M3_LOW_THR_LSB,
+ QPNP_M3_LOW_THR_MSB, QPNP_M3_HIGH_THR_LSB,
+ QPNP_M3_HIGH_THR_MSB, QPNP_ADC_TM_MULTI_MEAS_EN_M3,
+ QPNP_ADC_TM_LOW_THR_INT_EN_M3, QPNP_ADC_TM_HIGH_THR_INT_EN_M3,
+ QPNP_ADC_TM_M3_MEAS_INTERVAL_CTL},
+ [QPNP_ADC_TM_CHAN4] = {QPNP_ADC_TM_M4_ADC_CH_SEL_CTL,
+ QPNP_M4_LOW_THR_LSB,
+ QPNP_M4_LOW_THR_MSB, QPNP_M4_HIGH_THR_LSB,
+ QPNP_M4_HIGH_THR_MSB, QPNP_ADC_TM_MULTI_MEAS_EN_M4,
+ QPNP_ADC_TM_LOW_THR_INT_EN_M4, QPNP_ADC_TM_HIGH_THR_INT_EN_M4,
+ QPNP_ADC_TM_M4_MEAS_INTERVAL_CTL},
+ [QPNP_ADC_TM_CHAN5] = {QPNP_ADC_TM_M5_ADC_CH_SEL_CTL,
+ QPNP_M5_LOW_THR_LSB,
+ QPNP_M5_LOW_THR_MSB, QPNP_M5_HIGH_THR_LSB,
+ QPNP_M5_HIGH_THR_MSB, QPNP_ADC_TM_MULTI_MEAS_EN_M5,
+ QPNP_ADC_TM_LOW_THR_INT_EN_M5, QPNP_ADC_TM_HIGH_THR_INT_EN_M5,
+ QPNP_ADC_TM_M5_MEAS_INTERVAL_CTL},
+ [QPNP_ADC_TM_CHAN6] = {QPNP_ADC_TM_M6_ADC_CH_SEL_CTL,
+ QPNP_M6_LOW_THR_LSB,
+ QPNP_M6_LOW_THR_MSB, QPNP_M6_HIGH_THR_LSB,
+ QPNP_M6_HIGH_THR_MSB, QPNP_ADC_TM_MULTI_MEAS_EN_M6,
+ QPNP_ADC_TM_LOW_THR_INT_EN_M6, QPNP_ADC_TM_HIGH_THR_INT_EN_M6,
+ QPNP_ADC_TM_M6_MEAS_INTERVAL_CTL},
+ [QPNP_ADC_TM_CHAN7] = {QPNP_ADC_TM_M7_ADC_CH_SEL_CTL,
+ QPNP_M7_LOW_THR_LSB,
+ QPNP_M7_LOW_THR_MSB, QPNP_M7_HIGH_THR_LSB,
+ QPNP_M7_HIGH_THR_MSB, QPNP_ADC_TM_MULTI_MEAS_EN_M7,
+ QPNP_ADC_TM_LOW_THR_INT_EN_M7, QPNP_ADC_TM_HIGH_THR_INT_EN_M7,
+ QPNP_ADC_TM_M7_MEAS_INTERVAL_CTL},
+};
+
+static struct qpnp_adc_tm_reverse_scale_fn adc_tm_rscale_fn[] = {
+ [SCALE_R_VBATT] = {qpnp_adc_vbatt_rscaler},
+ [SCALE_RBATT_THERM] = {qpnp_adc_btm_scaler},
+ [SCALE_R_USB_ID] = {qpnp_adc_usb_scaler},
+ [SCALE_RPMIC_THERM] = {qpnp_adc_scale_millidegc_pmic_voltage_thr},
+ [SCALE_R_SMB_BATT_THERM] = {qpnp_adc_smb_btm_rscaler},
+ [SCALE_R_ABSOLUTE] = {qpnp_adc_absolute_rthr},
+ [SCALE_QRD_SKUH_RBATT_THERM] = {qpnp_adc_qrd_skuh_btm_scaler},
+ [SCALE_QRD_SKUT1_RBATT_THERM] = {qpnp_adc_qrd_skut1_btm_scaler},
+};
+
+static int32_t qpnp_adc_tm_read_reg(struct qpnp_adc_tm_chip *chip,
+ int16_t reg, u8 *data)
+{
+ int rc = 0;
+ uint val;
+
+ rc = regmap_read(chip->adc->regmap, (chip->adc->offset + reg), &val);
+ if (rc < 0)
+ pr_err("adc-tm read reg %d failed with %d\n", reg, rc);
+ *data = (u8)val;
+ return rc;
+}
+
+static int32_t qpnp_adc_tm_write_reg(struct qpnp_adc_tm_chip *chip,
+ int16_t reg, u8 data)
+{
+ int rc = 0;
+ u8 *buf;
+
+ buf = &data;
+
+ rc = regmap_write(chip->adc->regmap, (chip->adc->offset + reg), *buf);
+ if (rc < 0)
+ pr_err("adc-tm write reg %d failed with %d\n", reg, rc);
+
+ return rc;
+}
+
+static int32_t qpnp_adc_tm_fast_avg_en(struct qpnp_adc_tm_chip *chip,
+ uint32_t *fast_avg_sample)
+{
+ int rc = 0, version = 0;
+ u8 fast_avg_en = 0;
+
+ version = qpnp_adc_get_revid_version(chip->dev);
+ if (!((version == QPNP_REV_ID_8916_1_0) ||
+ (version == QPNP_REV_ID_8916_1_1) ||
+ (version == QPNP_REV_ID_8916_2_0))) {
+ pr_debug("fast-avg-en not required for this version\n");
+ return rc;
+ }
+
+ fast_avg_en = QPNP_FAST_AVG_ENABLED;
+ rc = qpnp_adc_tm_write_reg(chip, QPNP_FAST_AVG_EN, fast_avg_en);
+ if (rc < 0) {
+ pr_err("adc-tm fast-avg enable err\n");
+ return rc;
+ }
+
+ if (*fast_avg_sample >= 3)
+ *fast_avg_sample = 2;
+
+ return rc;
+}
+
+static int qpnp_adc_tm_check_vreg_vote(struct qpnp_adc_tm_chip *chip)
+{
+ int rc = 0;
+
+ if (!chip->adc_vote_enable) {
+ if (chip->adc->hkadc_ldo && chip->adc->hkadc_ldo_ok) {
+ rc = qpnp_adc_enable_voltage(chip->adc);
+ if (rc) {
+ pr_err("failed enabling VADC LDO\n");
+ return rc;
+ }
+ chip->adc_vote_enable = true;
+ }
+ }
+
+ return rc;
+}
+
+static int32_t qpnp_adc_tm_enable(struct qpnp_adc_tm_chip *chip)
+{
+ int rc = 0;
+ u8 data = 0;
+
+ rc = qpnp_adc_tm_check_vreg_vote(chip);
+ if (rc) {
+ pr_err("ADC TM VREG enable failed:%d\n", rc);
+ return rc;
+ }
+
+ data = QPNP_ADC_TM_EN;
+ rc = qpnp_adc_tm_write_reg(chip, QPNP_EN_CTL1, data);
+ if (rc < 0)
+ pr_err("adc-tm enable failed\n");
+
+ return rc;
+}
+
+static int32_t qpnp_adc_tm_disable(struct qpnp_adc_tm_chip *chip)
+{
+ u8 data = 0;
+ int rc = 0;
+
+ rc = qpnp_adc_tm_write_reg(chip, QPNP_EN_CTL1, data);
+ if (rc < 0) {
+ pr_err("adc-tm disable failed\n");
+ return rc;
+ }
+
+ return rc;
+}
+
+static int qpnp_adc_tm_is_valid(struct qpnp_adc_tm_chip *chip)
+{
+ struct qpnp_adc_tm_chip *adc_tm_chip = NULL;
+
+ list_for_each_entry(adc_tm_chip, &qpnp_adc_tm_device_list, list)
+ if (chip == adc_tm_chip)
+ return 0;
+
+ return -EINVAL;
+}
+
+static int32_t qpnp_adc_tm_enable_if_channel_meas(
+ struct qpnp_adc_tm_chip *chip)
+{
+ u8 adc_tm_meas_en = 0, status_low = 0, status_high = 0;
+ int rc = 0;
+
+ /* Check if a measurement request is still required */
+ rc = qpnp_adc_tm_read_reg(chip, QPNP_ADC_TM_MULTI_MEAS_EN,
+ &adc_tm_meas_en);
+ if (rc) {
+ pr_err("adc-tm-tm read status high failed with %d\n", rc);
+ return rc;
+ }
+
+ rc = qpnp_adc_tm_read_reg(chip, QPNP_ADC_TM_LOW_THR_INT_EN,
+ &status_low);
+ if (rc) {
+ pr_err("adc-tm-tm read status low failed with %d\n", rc);
+ return rc;
+ }
+
+ rc = qpnp_adc_tm_read_reg(chip, QPNP_ADC_TM_HIGH_THR_INT_EN,
+ &status_high);
+ if (rc) {
+ pr_err("adc-tm-tm read status high failed with %d\n", rc);
+ return rc;
+ }
+
+ /* Enable only if there are pending measurement requests */
+ if ((adc_tm_meas_en && status_high) || (adc_tm_meas_en && status_low)) {
+ qpnp_adc_tm_enable(chip);
+
+ /* Request conversion */
+ rc = qpnp_adc_tm_write_reg(chip, QPNP_CONV_REQ,
+ QPNP_CONV_REQ_SET);
+ if (rc < 0) {
+ pr_err("adc-tm request conversion failed\n");
+ return rc;
+ }
+ } else {
+ /* disable the vote if applicable */
+ if (chip->adc_vote_enable && chip->adc->hkadc_ldo &&
+ chip->adc->hkadc_ldo_ok) {
+ qpnp_adc_disable_voltage(chip->adc);
+ chip->adc_vote_enable = false;
+ }
+ }
+
+ return rc;
+}
+
+static int32_t qpnp_adc_tm_mode_select(struct qpnp_adc_tm_chip *chip,
+ u8 mode_ctl)
+{
+ int rc;
+
+ mode_ctl |= (QPNP_ADC_TRIM_EN | QPNP_AMUX_TRIM_EN);
+
+ /* VADC_BTM current sets mode to recurring measurements */
+ rc = qpnp_adc_tm_write_reg(chip, QPNP_MODE_CTL, mode_ctl);
+ if (rc < 0)
+ pr_err("adc-tm write mode selection err\n");
+
+ return rc;
+}
+
+static int32_t qpnp_adc_tm_req_sts_check(struct qpnp_adc_tm_chip *chip)
+{
+ u8 status1 = 0, mode_ctl = 0;
+ int rc, count = 0;
+
+ /* Re-enable the peripheral */
+ rc = qpnp_adc_tm_enable(chip);
+ if (rc) {
+ pr_err("adc-tm re-enable peripheral failed\n");
+ return rc;
+ }
+
+ /* The VADC_TM bank needs to be disabled for new conversion request */
+ rc = qpnp_adc_tm_read_reg(chip, QPNP_ADC_TM_STATUS1, &status1);
+ if (rc) {
+ pr_err("adc-tm read status1 failed\n");
+ return rc;
+ }
+
+ /* Disable the bank if a conversion is occuring */
+ while (status1 & QPNP_STATUS1_REQ_STS) {
+ if (count > QPNP_RETRY) {
+ pr_err("adc-tm conversion not completed in retry=%d\n",
+ count);
+ break;
+ }
+ /* Wait time is based on the optimum sampling rate
+ * and adding enough time buffer to account for ADC conversions
+ * occuring on different peripheral banks */
+ usleep_range(QPNP_MIN_TIME, QPNP_MAX_TIME);
+ rc = qpnp_adc_tm_read_reg(chip, QPNP_ADC_TM_STATUS1, &status1);
+ if (rc < 0) {
+ pr_err("adc-tm disable failed\n");
+ return rc;
+ }
+ count++;
+ }
+
+ /* Change the mode back to recurring measurement mode */
+ mode_ctl = ADC_OP_MEASUREMENT_INTERVAL << QPNP_OP_MODE_SHIFT;
+ rc = qpnp_adc_tm_mode_select(chip, mode_ctl);
+ if (rc < 0) {
+ pr_err("adc-tm mode change to recurring failed\n");
+ return rc;
+ }
+
+ /* Disable the peripheral */
+ rc = qpnp_adc_tm_disable(chip);
+ if (rc < 0) {
+ pr_err("adc-tm peripheral disable failed\n");
+ return rc;
+ }
+
+ return rc;
+}
+
+static int32_t qpnp_adc_tm_get_btm_idx(uint32_t btm_chan,
+ uint32_t *btm_chan_idx)
+{
+ int rc = 0, i;
+ bool chan_found = false;
+
+ for (i = 0; i < QPNP_ADC_TM_CHAN_NONE; i++) {
+ if (adc_tm_data[i].btm_amux_chan == btm_chan) {
+ *btm_chan_idx = i;
+ chan_found = true;
+ }
+ }
+
+ if (!chan_found)
+ return -EINVAL;
+
+ return rc;
+}
+
+static int32_t qpnp_adc_tm_check_revision(struct qpnp_adc_tm_chip *chip,
+ uint32_t btm_chan_num)
+{
+ u8 rev, perph_subtype;
+ int rc = 0;
+
+ rc = qpnp_adc_tm_read_reg(chip, QPNP_REVISION3, &rev);
+ if (rc) {
+ pr_err("adc-tm revision read failed\n");
+ return rc;
+ }
+
+ rc = qpnp_adc_tm_read_reg(chip, QPNP_PERPH_SUBTYPE, &perph_subtype);
+ if (rc) {
+ pr_err("adc-tm perph_subtype read failed\n");
+ return rc;
+ }
+
+ if (perph_subtype == QPNP_PERPH_TYPE2) {
+ if ((rev < QPNP_REVISION_EIGHT_CHANNEL_SUPPORT) &&
+ (btm_chan_num > QPNP_ADC_TM_M4_ADC_CH_SEL_CTL)) {
+ pr_debug("Version does not support more than 5 channels\n");
+ return -EINVAL;
+ }
+ }
+
+ if (perph_subtype == QPNP_PERPH_SUBTYPE_TWO_CHANNEL_SUPPORT) {
+ if (btm_chan_num > QPNP_ADC_TM_M1_ADC_CH_SEL_CTL) {
+ pr_debug("Version does not support more than 2 channels\n");
+ return -EINVAL;
+ }
+ }
+
+ return rc;
+}
+
+static int32_t qpnp_adc_tm_timer_interval_select(
+ struct qpnp_adc_tm_chip *chip, uint32_t btm_chan,
+ struct qpnp_vadc_chan_properties *chan_prop)
+{
+ int rc, chan_idx = 0, i = 0;
+ bool chan_found = false;
+ u8 meas_interval_timer2 = 0, timer_interval_store = 0;
+ uint32_t btm_chan_idx = 0;
+
+ while (i < chip->max_channels_available) {
+ if (chip->sensor[i].btm_channel_num == btm_chan) {
+ chan_idx = i;
+ chan_found = true;
+ i++;
+ } else
+ i++;
+ }
+
+ if (!chan_found) {
+ pr_err("Channel not found\n");
+ return -EINVAL;
+ }
+
+ switch (chip->sensor[chan_idx].timer_select) {
+ case ADC_MEAS_TIMER_SELECT1:
+ rc = qpnp_adc_tm_write_reg(chip,
+ QPNP_ADC_TM_MEAS_INTERVAL_CTL,
+ chip->sensor[chan_idx].meas_interval);
+ if (rc < 0) {
+ pr_err("timer1 configure failed\n");
+ return rc;
+ }
+ break;
+ case ADC_MEAS_TIMER_SELECT2:
+ /* Thermal channels uses timer2, default to 1 second */
+ rc = qpnp_adc_tm_read_reg(chip,
+ QPNP_ADC_TM_MEAS_INTERVAL_CTL2,
+ &meas_interval_timer2);
+ if (rc < 0) {
+ pr_err("timer2 configure read failed\n");
+ return rc;
+ }
+ timer_interval_store = chip->sensor[chan_idx].meas_interval;
+ timer_interval_store <<= QPNP_ADC_TM_MEAS_INTERVAL_CTL2_SHIFT;
+ timer_interval_store &= QPNP_ADC_TM_MEAS_INTERVAL_CTL2_MASK;
+ meas_interval_timer2 |= timer_interval_store;
+ rc = qpnp_adc_tm_write_reg(chip,
+ QPNP_ADC_TM_MEAS_INTERVAL_CTL2,
+ meas_interval_timer2);
+ if (rc < 0) {
+ pr_err("timer2 configure failed\n");
+ return rc;
+ }
+ break;
+ case ADC_MEAS_TIMER_SELECT3:
+ rc = qpnp_adc_tm_read_reg(chip,
+ QPNP_ADC_TM_MEAS_INTERVAL_CTL2,
+ &meas_interval_timer2);
+ if (rc < 0) {
+ pr_err("timer3 read failed\n");
+ return rc;
+ }
+ timer_interval_store = chip->sensor[chan_idx].meas_interval;
+ timer_interval_store &= QPNP_ADC_TM_MEAS_INTERVAL_CTL3_MASK;
+ meas_interval_timer2 |= timer_interval_store;
+ rc = qpnp_adc_tm_write_reg(chip,
+ QPNP_ADC_TM_MEAS_INTERVAL_CTL2,
+ meas_interval_timer2);
+ if (rc < 0) {
+ pr_err("timer3 configure failed\n");
+ return rc;
+ }
+ break;
+ default:
+ pr_err("Invalid timer selection\n");
+ return -EINVAL;
+ }
+
+ /* Select the timer to use for the corresponding channel */
+ rc = qpnp_adc_tm_get_btm_idx(btm_chan, &btm_chan_idx);
+ if (rc < 0) {
+ pr_err("Invalid btm channel idx\n");
+ return rc;
+ }
+ rc = qpnp_adc_tm_write_reg(chip,
+ adc_tm_data[btm_chan_idx].meas_interval_ctl,
+ chip->sensor[chan_idx].timer_select);
+ if (rc < 0) {
+ pr_err("TM channel timer configure failed\n");
+ return rc;
+ }
+
+ pr_debug("timer select:%d, timer_value_within_select:%d, channel:%x\n",
+ chip->sensor[chan_idx].timer_select,
+ chip->sensor[chan_idx].meas_interval,
+ btm_chan);
+
+ return rc;
+}
+
+static int32_t qpnp_adc_tm_add_to_list(struct qpnp_adc_tm_chip *chip,
+ uint32_t dt_index,
+ struct qpnp_adc_tm_btm_param *param,
+ struct qpnp_vadc_chan_properties *chan_prop)
+{
+ struct qpnp_adc_thr_client_info *client_info = NULL;
+ bool client_info_exists = false;
+
+ list_for_each_entry(client_info,
+ &chip->sensor[dt_index].thr_list, list) {
+ if (client_info->btm_param == param) {
+ client_info->low_thr_requested = chan_prop->low_thr;
+ client_info->high_thr_requested = chan_prop->high_thr;
+ client_info->state_requested = param->state_request;
+ client_info->state_req_copy = param->state_request;
+ client_info->notify_low_thr = false;
+ client_info->notify_high_thr = false;
+ client_info_exists = true;
+ pr_debug("client found\n");
+ }
+ }
+
+ if (!client_info_exists) {
+ client_info = devm_kzalloc(chip->dev,
+ sizeof(struct qpnp_adc_thr_client_info), GFP_KERNEL);
+ if (!client_info) {
+ pr_err("%s: kzalloc() failed.\n", __func__);
+ return -ENOMEM;
+ }
+
+ pr_debug("new client\n");
+ client_info->btm_param = param;
+ client_info->low_thr_requested = chan_prop->low_thr;
+ client_info->high_thr_requested = chan_prop->high_thr;
+ client_info->state_requested = param->state_request;
+ client_info->state_req_copy = param->state_request;
+
+ list_add_tail(&client_info->list,
+ &chip->sensor[dt_index].thr_list);
+ }
+
+ return 0;
+}
+
+static int32_t qpnp_adc_tm_reg_update(struct qpnp_adc_tm_chip *chip,
+ uint16_t addr, u8 mask, bool state)
+{
+ u8 reg_value = 0;
+ int rc = 0;
+
+ rc = qpnp_adc_tm_read_reg(chip, addr, &reg_value);
+ if (rc < 0) {
+ pr_err("read failed for addr:0x%x\n", addr);
+ return rc;
+ }
+
+ reg_value = reg_value & ~mask;
+ if (state)
+ reg_value |= mask;
+
+ pr_debug("state:%d, reg:0x%x with bits:0x%x and mask:0x%x\n",
+ state, addr, reg_value, ~mask);
+ rc = qpnp_adc_tm_write_reg(chip, addr, reg_value);
+ if (rc < 0) {
+ pr_err("write failed for addr:%x\n", addr);
+ return rc;
+ }
+
+ return rc;
+}
+
+static int32_t qpnp_adc_tm_read_thr_value(struct qpnp_adc_tm_chip *chip,
+ uint32_t btm_chan)
+{
+ int rc = 0;
+ u8 data_lsb = 0, data_msb = 0;
+ uint32_t btm_chan_idx = 0;
+ int32_t low_thr = 0, high_thr = 0;
+
+ rc = qpnp_adc_tm_get_btm_idx(btm_chan, &btm_chan_idx);
+ if (rc < 0) {
+ pr_err("Invalid btm channel idx\n");
+ return rc;
+ }
+
+ rc = qpnp_adc_tm_read_reg(chip,
+ adc_tm_data[btm_chan_idx].low_thr_lsb_addr,
+ &data_lsb);
+ if (rc < 0) {
+ pr_err("low threshold lsb setting failed\n");
+ return rc;
+ }
+
+ rc = qpnp_adc_tm_read_reg(chip,
+ adc_tm_data[btm_chan_idx].low_thr_msb_addr,
+ &data_msb);
+ if (rc < 0) {
+ pr_err("low threshold msb setting failed\n");
+ return rc;
+ }
+
+ low_thr = (data_msb << 8) | data_lsb;
+
+ rc = qpnp_adc_tm_read_reg(chip,
+ adc_tm_data[btm_chan_idx].high_thr_lsb_addr,
+ &data_lsb);
+ if (rc < 0) {
+ pr_err("high threshold lsb setting failed\n");
+ return rc;
+ }
+
+ rc = qpnp_adc_tm_read_reg(chip,
+ adc_tm_data[btm_chan_idx].high_thr_msb_addr,
+ &data_msb);
+ if (rc < 0) {
+ pr_err("high threshold msb setting failed\n");
+ return rc;
+ }
+
+ high_thr = (data_msb << 8) | data_lsb;
+
+ pr_debug("configured thresholds high:0x%x and low:0x%x\n",
+ high_thr, low_thr);
+
+ return rc;
+}
+
+static int32_t qpnp_adc_tm_thr_update(struct qpnp_adc_tm_chip *chip,
+ uint32_t btm_chan, int32_t high_thr, int32_t low_thr)
+{
+ int rc = 0;
+ uint32_t btm_chan_idx = 0;
+
+ rc = qpnp_adc_tm_get_btm_idx(btm_chan, &btm_chan_idx);
+ if (rc < 0) {
+ pr_err("Invalid btm channel idx\n");
+ return rc;
+ }
+
+ rc = qpnp_adc_tm_write_reg(chip,
+ adc_tm_data[btm_chan_idx].low_thr_lsb_addr,
+ QPNP_ADC_TM_THR_LSB_MASK(low_thr));
+ if (rc < 0) {
+ pr_err("low threshold lsb setting failed\n");
+ return rc;
+ }
+
+ rc = qpnp_adc_tm_write_reg(chip,
+ adc_tm_data[btm_chan_idx].low_thr_msb_addr,
+ QPNP_ADC_TM_THR_MSB_MASK(low_thr));
+ if (rc < 0) {
+ pr_err("low threshold msb setting failed\n");
+ return rc;
+ }
+
+ rc = qpnp_adc_tm_write_reg(chip,
+ adc_tm_data[btm_chan_idx].high_thr_lsb_addr,
+ QPNP_ADC_TM_THR_LSB_MASK(high_thr));
+ if (rc < 0) {
+ pr_err("high threshold lsb setting failed\n");
+ return rc;
+ }
+
+ rc = qpnp_adc_tm_write_reg(chip,
+ adc_tm_data[btm_chan_idx].high_thr_msb_addr,
+ QPNP_ADC_TM_THR_MSB_MASK(high_thr));
+ if (rc < 0)
+ pr_err("high threshold msb setting failed\n");
+
+ pr_debug("client requested high:%d and low:%d\n",
+ high_thr, low_thr);
+
+ return rc;
+}
+
+static int32_t qpnp_adc_tm_manage_thresholds(struct qpnp_adc_tm_chip *chip,
+ uint32_t dt_index, uint32_t btm_chan)
+{
+ struct qpnp_adc_thr_client_info *client_info = NULL;
+ struct list_head *thr_list;
+ int high_thr = 0, low_thr = 0, rc = 0;
+
+
+ /* high_thr/low_thr starting point and reset the high_thr_set and
+ low_thr_set back to reset since the thresholds will be
+ recomputed */
+ list_for_each(thr_list,
+ &chip->sensor[dt_index].thr_list) {
+ client_info = list_entry(thr_list,
+ struct qpnp_adc_thr_client_info, list);
+ high_thr = client_info->high_thr_requested;
+ low_thr = client_info->low_thr_requested;
+ client_info->high_thr_set = false;
+ client_info->low_thr_set = false;
+ }
+
+ pr_debug("init threshold is high:%d and low:%d\n", high_thr, low_thr);
+
+ /* Find the min of high_thr and max of low_thr */
+ list_for_each(thr_list,
+ &chip->sensor[dt_index].thr_list) {
+ client_info = list_entry(thr_list,
+ struct qpnp_adc_thr_client_info, list);
+ if ((client_info->state_req_copy == ADC_TM_HIGH_THR_ENABLE) ||
+ (client_info->state_req_copy ==
+ ADC_TM_HIGH_LOW_THR_ENABLE))
+ if (client_info->high_thr_requested < high_thr)
+ high_thr = client_info->high_thr_requested;
+
+ if ((client_info->state_req_copy == ADC_TM_LOW_THR_ENABLE) ||
+ (client_info->state_req_copy ==
+ ADC_TM_HIGH_LOW_THR_ENABLE))
+ if (client_info->low_thr_requested > low_thr)
+ low_thr = client_info->low_thr_requested;
+
+ pr_debug("threshold compared is high:%d and low:%d\n",
+ client_info->high_thr_requested,
+ client_info->low_thr_requested);
+ pr_debug("current threshold is high:%d and low:%d\n",
+ high_thr, low_thr);
+ }
+
+ /* Check which of the high_thr and low_thr got set */
+ list_for_each(thr_list,
+ &chip->sensor[dt_index].thr_list) {
+ client_info = list_entry(thr_list,
+ struct qpnp_adc_thr_client_info, list);
+ if ((client_info->state_req_copy == ADC_TM_HIGH_THR_ENABLE) ||
+ (client_info->state_req_copy ==
+ ADC_TM_HIGH_LOW_THR_ENABLE))
+ if (high_thr == client_info->high_thr_requested)
+ client_info->high_thr_set = true;
+
+ if ((client_info->state_req_copy == ADC_TM_LOW_THR_ENABLE) ||
+ (client_info->state_req_copy ==
+ ADC_TM_HIGH_LOW_THR_ENABLE))
+ if (low_thr == client_info->low_thr_requested)
+ client_info->low_thr_set = true;
+ }
+
+ rc = qpnp_adc_tm_thr_update(chip, btm_chan, high_thr, low_thr);
+ if (rc < 0)
+ pr_err("setting chan:%d threshold failed\n", btm_chan);
+
+ pr_debug("threshold written is high:%d and low:%d\n",
+ high_thr, low_thr);
+
+ return 0;
+}
+
+static int32_t qpnp_adc_tm_channel_configure(struct qpnp_adc_tm_chip *chip,
+ uint32_t btm_chan,
+ struct qpnp_vadc_chan_properties *chan_prop,
+ uint32_t amux_channel)
+{
+ int rc = 0, i = 0, chan_idx = 0;
+ bool chan_found = false, high_thr_set = false, low_thr_set = false;
+ u8 sensor_mask = 0;
+ struct qpnp_adc_thr_client_info *client_info = NULL;
+
+ while (i < chip->max_channels_available) {
+ if (chip->sensor[i].btm_channel_num == btm_chan) {
+ chan_idx = i;
+ chan_found = true;
+ i++;
+ } else
+ i++;
+ }
+
+ if (!chan_found) {
+ pr_err("Channel not found\n");
+ return -EINVAL;
+ }
+
+ sensor_mask = 1 << chan_idx;
+ if (!chip->sensor[chan_idx].thermal_node) {
+ /* Update low and high notification thresholds */
+ rc = qpnp_adc_tm_manage_thresholds(chip, chan_idx,
+ btm_chan);
+ if (rc < 0) {
+ pr_err("setting chan:%d threshold failed\n", btm_chan);
+ return rc;
+ }
+
+ list_for_each_entry(client_info,
+ &chip->sensor[chan_idx].thr_list, list) {
+ if (client_info->high_thr_set == true)
+ high_thr_set = true;
+ if (client_info->low_thr_set == true)
+ low_thr_set = true;
+ }
+
+ if (low_thr_set) {
+ pr_debug("low sensor mask:%x with state:%d\n",
+ sensor_mask, chan_prop->state_request);
+ /* Enable low threshold's interrupt */
+ rc = qpnp_adc_tm_reg_update(chip,
+ QPNP_ADC_TM_LOW_THR_INT_EN, sensor_mask, true);
+ if (rc < 0) {
+ pr_err("low thr enable err:%d\n", btm_chan);
+ return rc;
+ }
+ }
+
+ if (high_thr_set) {
+ /* Enable high threshold's interrupt */
+ pr_debug("high sensor mask:%x\n", sensor_mask);
+ rc = qpnp_adc_tm_reg_update(chip,
+ QPNP_ADC_TM_HIGH_THR_INT_EN, sensor_mask, true);
+ if (rc < 0) {
+ pr_err("high thr enable err:%d\n", btm_chan);
+ return rc;
+ }
+ }
+ }
+
+ /* Enable corresponding BTM channel measurement */
+ rc = qpnp_adc_tm_reg_update(chip,
+ QPNP_ADC_TM_MULTI_MEAS_EN, sensor_mask, true);
+ if (rc < 0) {
+ pr_err("multi measurement en failed\n");
+ return rc;
+ }
+
+ return rc;
+}
+
+static int32_t qpnp_adc_tm_configure(struct qpnp_adc_tm_chip *chip,
+ struct qpnp_adc_amux_properties *chan_prop)
+{
+ u8 decimation = 0, op_cntrl = 0, mode_ctl = 0;
+ int rc = 0;
+ uint32_t btm_chan = 0;
+
+ /* Set measurement in single measurement mode */
+ mode_ctl = ADC_OP_NORMAL_MODE << QPNP_OP_MODE_SHIFT;
+ rc = qpnp_adc_tm_mode_select(chip, mode_ctl);
+ if (rc < 0) {
+ pr_err("adc-tm single mode select failed\n");
+ return rc;
+ }
+
+ /* Disable bank */
+ rc = qpnp_adc_tm_disable(chip);
+ if (rc)
+ return rc;
+
+ /* Check if a conversion is in progress */
+ rc = qpnp_adc_tm_req_sts_check(chip);
+ if (rc < 0) {
+ pr_err("adc-tm req_sts check failed\n");
+ return rc;
+ }
+
+ /* Configure AMUX channel select for the corresponding BTM channel*/
+ btm_chan = chan_prop->chan_prop->tm_channel_select;
+ rc = qpnp_adc_tm_write_reg(chip, btm_chan, chan_prop->amux_channel);
+ if (rc < 0) {
+ pr_err("adc-tm channel selection err\n");
+ return rc;
+ }
+
+ /* Digital paramater setup */
+ decimation |= chan_prop->decimation <<
+ QPNP_ADC_DIG_DEC_RATIO_SEL_SHIFT;
+ rc = qpnp_adc_tm_write_reg(chip, QPNP_ADC_DIG_PARAM, decimation);
+ if (rc < 0) {
+ pr_err("adc-tm digital parameter setup err\n");
+ return rc;
+ }
+
+ /* Hardware setting time */
+ rc = qpnp_adc_tm_write_reg(chip, QPNP_HW_SETTLE_DELAY,
+ chan_prop->hw_settle_time);
+ if (rc < 0) {
+ pr_err("adc-tm hw settling time setup err\n");
+ return rc;
+ }
+
+ /* Fast averaging setup/enable */
+ rc = qpnp_adc_tm_fast_avg_en(chip, &chan_prop->fast_avg_setup);
+ if (rc < 0) {
+ pr_err("adc-tm fast-avg enable err\n");
+ return rc;
+ }
+
+ rc = qpnp_adc_tm_write_reg(chip, QPNP_FAST_AVG_CTL,
+ chan_prop->fast_avg_setup);
+ if (rc < 0) {
+ pr_err("adc-tm fast-avg setup err\n");
+ return rc;
+ }
+
+ /* Measurement interval setup */
+ rc = qpnp_adc_tm_timer_interval_select(chip, btm_chan,
+ chan_prop->chan_prop);
+ if (rc < 0) {
+ pr_err("adc-tm timer select failed\n");
+ return rc;
+ }
+
+ /* Channel configuration setup */
+ rc = qpnp_adc_tm_channel_configure(chip, btm_chan,
+ chan_prop->chan_prop, chan_prop->amux_channel);
+ if (rc < 0) {
+ pr_err("adc-tm channel configure failed\n");
+ return rc;
+ }
+
+ /* Recurring interval measurement enable */
+ rc = qpnp_adc_tm_read_reg(chip, QPNP_ADC_MEAS_INTERVAL_OP_CTL,
+ &op_cntrl);
+ op_cntrl |= QPNP_ADC_MEAS_INTERVAL_OP;
+ rc = qpnp_adc_tm_reg_update(chip, QPNP_ADC_MEAS_INTERVAL_OP_CTL,
+ op_cntrl, true);
+ if (rc < 0) {
+ pr_err("adc-tm meas interval op configure failed\n");
+ return rc;
+ }
+
+ /* Enable bank */
+ rc = qpnp_adc_tm_enable(chip);
+ if (rc)
+ return rc;
+
+ /* Request conversion */
+ rc = qpnp_adc_tm_write_reg(chip, QPNP_CONV_REQ, QPNP_CONV_REQ_SET);
+ if (rc < 0) {
+ pr_err("adc-tm request conversion failed\n");
+ return rc;
+ }
+
+ return 0;
+}
+
+static int qpnp_adc_tm_get_mode(struct thermal_zone_device *thermal,
+ enum thermal_device_mode *mode)
+{
+ struct qpnp_adc_tm_sensor *adc_tm = thermal->devdata;
+
+ if ((IS_ERR(adc_tm)) || qpnp_adc_tm_check_revision(
+ adc_tm->chip, adc_tm->btm_channel_num))
+ return -EINVAL;
+
+ *mode = adc_tm->mode;
+
+ return 0;
+}
+
+static int qpnp_adc_tm_set_mode(struct thermal_zone_device *thermal,
+ enum thermal_device_mode mode)
+{
+ struct qpnp_adc_tm_sensor *adc_tm = thermal->devdata;
+ struct qpnp_adc_tm_chip *chip = adc_tm->chip;
+ int rc = 0, channel;
+ u8 sensor_mask = 0, mode_ctl = 0;
+
+ if (qpnp_adc_tm_is_valid(chip)) {
+ pr_err("invalid device\n");
+ return -ENODEV;
+ }
+
+ if (qpnp_adc_tm_check_revision(chip, adc_tm->btm_channel_num))
+ return -EINVAL;
+
+ if (mode == THERMAL_DEVICE_ENABLED) {
+ chip->adc->amux_prop->amux_channel =
+ adc_tm->vadc_channel_num;
+ channel = adc_tm->sensor_num;
+ chip->adc->amux_prop->decimation =
+ chip->adc->adc_channels[channel].adc_decimation;
+ chip->adc->amux_prop->hw_settle_time =
+ chip->adc->adc_channels[channel].hw_settle_time;
+ chip->adc->amux_prop->fast_avg_setup =
+ chip->adc->adc_channels[channel].fast_avg_setup;
+ chip->adc->amux_prop->mode_sel =
+ ADC_OP_MEASUREMENT_INTERVAL << QPNP_OP_MODE_SHIFT;
+ chip->adc->amux_prop->chan_prop->low_thr = adc_tm->low_thr;
+ chip->adc->amux_prop->chan_prop->high_thr = adc_tm->high_thr;
+ chip->adc->amux_prop->chan_prop->tm_channel_select =
+ adc_tm->btm_channel_num;
+
+ rc = qpnp_adc_tm_configure(chip, chip->adc->amux_prop);
+ if (rc) {
+ pr_err("adc-tm tm configure failed with %d\n", rc);
+ return -EINVAL;
+ }
+ } else if (mode == THERMAL_DEVICE_DISABLED) {
+ sensor_mask = 1 << adc_tm->sensor_num;
+
+ mode_ctl = ADC_OP_NORMAL_MODE << QPNP_OP_MODE_SHIFT;
+ rc = qpnp_adc_tm_mode_select(chip, mode_ctl);
+ if (rc < 0) {
+ pr_err("adc-tm single mode select failed\n");
+ return rc;
+ }
+
+ /* Disable bank */
+ rc = qpnp_adc_tm_disable(chip);
+ if (rc < 0) {
+ pr_err("adc-tm disable failed\n");
+ return rc;
+ }
+
+ /* Check if a conversion is in progress */
+ rc = qpnp_adc_tm_req_sts_check(chip);
+ if (rc < 0) {
+ pr_err("adc-tm req_sts check failed\n");
+ return rc;
+ }
+
+ rc = qpnp_adc_tm_reg_update(chip,
+ QPNP_ADC_TM_MULTI_MEAS_EN, sensor_mask, false);
+ if (rc < 0) {
+ pr_err("multi measurement update failed\n");
+ return rc;
+ }
+
+ rc = qpnp_adc_tm_enable_if_channel_meas(chip);
+ if (rc < 0) {
+ pr_err("re-enabling measurement failed\n");
+ return rc;
+ }
+ }
+
+ adc_tm->mode = mode;
+
+ return 0;
+}
+
+static int qpnp_adc_tm_get_trip_type(struct thermal_zone_device *thermal,
+ int trip, enum thermal_trip_type *type)
+{
+ struct qpnp_adc_tm_sensor *adc_tm = thermal->devdata;
+ struct qpnp_adc_tm_chip *chip = adc_tm->chip;
+
+ if (qpnp_adc_tm_is_valid(chip))
+ return -ENODEV;
+
+ if (qpnp_adc_tm_check_revision(chip, adc_tm->btm_channel_num))
+ return -EINVAL;
+
+ switch (trip) {
+ case ADC_TM_TRIP_HIGH_WARM:
+ *type = THERMAL_TRIP_CONFIGURABLE_HI;
+ break;
+ case ADC_TM_TRIP_LOW_COOL:
+ *type = THERMAL_TRIP_CONFIGURABLE_LOW;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int qpnp_adc_tm_get_trip_temp(struct thermal_zone_device *thermal,
+ int trip, unsigned long *temp)
+{
+ struct qpnp_adc_tm_sensor *adc_tm_sensor = thermal->devdata;
+ struct qpnp_adc_tm_chip *chip = adc_tm_sensor->chip;
+ int64_t result = 0;
+ u8 trip_cool_thr0, trip_cool_thr1, trip_warm_thr0, trip_warm_thr1;
+ unsigned int reg, rc = 0;
+ uint16_t reg_low_thr_lsb, reg_low_thr_msb;
+ uint16_t reg_high_thr_lsb, reg_high_thr_msb;
+ uint32_t btm_chan_idx = 0, btm_chan = 0;
+
+ if (qpnp_adc_tm_is_valid(chip))
+ return -ENODEV;
+
+ if (qpnp_adc_tm_check_revision(chip, adc_tm_sensor->btm_channel_num))
+ return -EINVAL;
+
+ btm_chan = adc_tm_sensor->btm_channel_num;
+ rc = qpnp_adc_tm_get_btm_idx(btm_chan, &btm_chan_idx);
+ if (rc < 0) {
+ pr_err("Invalid btm channel idx\n");
+ return rc;
+ }
+
+ reg_low_thr_lsb = adc_tm_data[btm_chan_idx].low_thr_lsb_addr;
+ reg_low_thr_msb = adc_tm_data[btm_chan_idx].low_thr_msb_addr;
+ reg_high_thr_lsb = adc_tm_data[btm_chan_idx].high_thr_lsb_addr;
+ reg_high_thr_msb = adc_tm_data[btm_chan_idx].high_thr_msb_addr;
+
+ switch (trip) {
+ case ADC_TM_TRIP_HIGH_WARM:
+ rc = qpnp_adc_tm_read_reg(chip, reg_low_thr_lsb,
+ &trip_warm_thr0);
+ if (rc) {
+ pr_err("adc-tm low_thr_lsb err\n");
+ return rc;
+ }
+
+ rc = qpnp_adc_tm_read_reg(chip, reg_low_thr_msb,
+ &trip_warm_thr1);
+ if (rc) {
+ pr_err("adc-tm low_thr_msb err\n");
+ return rc;
+ }
+ reg = (trip_warm_thr1 << 8) | trip_warm_thr0;
+ break;
+ case ADC_TM_TRIP_LOW_COOL:
+ rc = qpnp_adc_tm_read_reg(chip, reg_high_thr_lsb,
+ &trip_cool_thr0);
+ if (rc) {
+ pr_err("adc-tm_tm high_thr_lsb err\n");
+ return rc;
+ }
+
+ rc = qpnp_adc_tm_read_reg(chip, reg_high_thr_msb,
+ &trip_cool_thr1);
+ if (rc) {
+ pr_err("adc-tm_tm high_thr_lsb err\n");
+ return rc;
+ }
+ reg = (trip_cool_thr1 << 8) | trip_cool_thr0;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ rc = qpnp_adc_tm_scale_voltage_therm_pu2(chip->vadc_dev, reg,
+ &result);
+ if (rc < 0) {
+ pr_err("Failed to lookup the therm thresholds\n");
+ return rc;
+ }
+
+ *temp = result;
+
+ return 0;
+}
+
+static int qpnp_adc_tm_set_trip_temp(struct thermal_zone_device *thermal,
+ int trip, unsigned long temp)
+{
+ struct qpnp_adc_tm_sensor *adc_tm = thermal->devdata;
+ struct qpnp_adc_tm_chip *chip = adc_tm->chip;
+ struct qpnp_adc_tm_config tm_config;
+ u8 trip_cool_thr0, trip_cool_thr1, trip_warm_thr0, trip_warm_thr1;
+ uint16_t reg_low_thr_lsb, reg_low_thr_msb;
+ uint16_t reg_high_thr_lsb, reg_high_thr_msb;
+ int rc = 0;
+ uint32_t btm_chan = 0, btm_chan_idx = 0;
+
+ if (qpnp_adc_tm_is_valid(chip))
+ return -ENODEV;
+
+ if (qpnp_adc_tm_check_revision(chip, adc_tm->btm_channel_num))
+ return -EINVAL;
+
+ tm_config.channel = adc_tm->vadc_channel_num;
+ switch (trip) {
+ case ADC_TM_TRIP_HIGH_WARM:
+ tm_config.high_thr_temp = temp;
+ break;
+ case ADC_TM_TRIP_LOW_COOL:
+ tm_config.low_thr_temp = temp;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ pr_debug("requested a high - %d and low - %d with trip - %d\n",
+ tm_config.high_thr_temp, tm_config.low_thr_temp, trip);
+ rc = qpnp_adc_tm_scale_therm_voltage_pu2(chip->vadc_dev, &tm_config);
+ if (rc < 0) {
+ pr_err("Failed to lookup the adc-tm thresholds\n");
+ return rc;
+ }
+
+ trip_warm_thr0 = ((tm_config.low_thr_voltage << 24) >> 24);
+ trip_warm_thr1 = ((tm_config.low_thr_voltage << 16) >> 24);
+ trip_cool_thr0 = ((tm_config.high_thr_voltage << 24) >> 24);
+ trip_cool_thr1 = ((tm_config.high_thr_voltage << 16) >> 24);
+
+ btm_chan = adc_tm->btm_channel_num;
+ rc = qpnp_adc_tm_get_btm_idx(btm_chan, &btm_chan_idx);
+ if (rc < 0) {
+ pr_err("Invalid btm channel idx\n");
+ return rc;
+ }
+
+ reg_low_thr_lsb = adc_tm_data[btm_chan_idx].low_thr_lsb_addr;
+ reg_low_thr_msb = adc_tm_data[btm_chan_idx].low_thr_msb_addr;
+ reg_high_thr_lsb = adc_tm_data[btm_chan_idx].high_thr_lsb_addr;
+ reg_high_thr_msb = adc_tm_data[btm_chan_idx].high_thr_msb_addr;
+
+ switch (trip) {
+ case ADC_TM_TRIP_HIGH_WARM:
+ rc = qpnp_adc_tm_write_reg(chip, reg_low_thr_lsb,
+ trip_cool_thr0);
+ if (rc) {
+ pr_err("adc-tm_tm read threshold err\n");
+ return rc;
+ }
+
+ rc = qpnp_adc_tm_write_reg(chip, reg_low_thr_msb,
+ trip_cool_thr1);
+ if (rc) {
+ pr_err("adc-tm_tm read threshold err\n");
+ return rc;
+ }
+ adc_tm->low_thr = tm_config.high_thr_voltage;
+ break;
+ case ADC_TM_TRIP_LOW_COOL:
+ rc = qpnp_adc_tm_write_reg(chip, reg_high_thr_lsb,
+ trip_warm_thr0);
+ if (rc) {
+ pr_err("adc-tm_tm read threshold err\n");
+ return rc;
+ }
+
+ rc = qpnp_adc_tm_write_reg(chip, reg_high_thr_msb,
+ trip_warm_thr1);
+ if (rc) {
+ pr_err("adc-tm_tm read threshold err\n");
+ return rc;
+ }
+ adc_tm->high_thr = tm_config.low_thr_voltage;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static void notify_battery_therm(struct qpnp_adc_tm_sensor *adc_tm)
+{
+ struct qpnp_adc_thr_client_info *client_info = NULL;
+
+ list_for_each_entry(client_info,
+ &adc_tm->thr_list, list) {
+ /* Batt therm's warm temperature translates to low voltage */
+ if (client_info->notify_low_thr) {
+ /* HIGH_STATE = WARM_TEMP for battery client */
+ client_info->btm_param->threshold_notification(
+ ADC_TM_WARM_STATE, client_info->btm_param->btm_ctx);
+ client_info->notify_low_thr = false;
+ }
+
+ /* Batt therm's cool temperature translates to high voltage */
+ if (client_info->notify_high_thr) {
+ /* LOW_STATE = COOL_TEMP for battery client */
+ client_info->btm_param->threshold_notification(
+ ADC_TM_COOL_STATE, client_info->btm_param->btm_ctx);
+ client_info->notify_high_thr = false;
+ }
+ }
+
+ return;
+}
+
+static void notify_clients(struct qpnp_adc_tm_sensor *adc_tm)
+{
+ struct qpnp_adc_thr_client_info *client_info = NULL;
+
+ list_for_each_entry(client_info,
+ &adc_tm->thr_list, list) {
+ /* For non batt therm clients */
+ if (client_info->notify_low_thr) {
+ if (client_info->btm_param->threshold_notification
+ != NULL) {
+ pr_debug("notify kernel with low state\n");
+ client_info->btm_param->threshold_notification(
+ ADC_TM_LOW_STATE,
+ client_info->btm_param->btm_ctx);
+ client_info->notify_low_thr = false;
+ }
+ }
+
+ if (client_info->notify_high_thr) {
+ if (client_info->btm_param->threshold_notification
+ != NULL) {
+ pr_debug("notify kernel with high state\n");
+ client_info->btm_param->threshold_notification(
+ ADC_TM_HIGH_STATE,
+ client_info->btm_param->btm_ctx);
+ client_info->notify_high_thr = false;
+ }
+ }
+ }
+
+ return;
+}
+
+static void notify_adc_tm_fn(struct work_struct *work)
+{
+ struct qpnp_adc_tm_sensor *adc_tm = container_of(work,
+ struct qpnp_adc_tm_sensor, work);
+ struct qpnp_adc_tm_chip *chip = adc_tm->chip;
+
+ if (adc_tm->thermal_node) {
+ sysfs_notify(&adc_tm->tz_dev->device.kobj,
+ NULL, "type");
+ pr_debug("notifying uspace client\n");
+ } else {
+ if (adc_tm->scale_type == SCALE_RBATT_THERM)
+ notify_battery_therm(adc_tm);
+ else
+ notify_clients(adc_tm);
+ }
+
+ atomic_dec(&chip->wq_cnt);
+ return;
+}
+
+static int qpnp_adc_tm_activate_trip_type(struct thermal_zone_device *thermal,
+ int trip, enum thermal_trip_activation_mode mode)
+{
+ struct qpnp_adc_tm_sensor *adc_tm = thermal->devdata;
+ struct qpnp_adc_tm_chip *chip = adc_tm->chip;
+ int rc = 0, sensor_mask = 0;
+ u8 thr_int_en = 0;
+ bool state = false;
+ uint32_t btm_chan_idx = 0, btm_chan = 0;
+
+ if (qpnp_adc_tm_is_valid(chip))
+ return -ENODEV;
+
+ if (qpnp_adc_tm_check_revision(chip, adc_tm->btm_channel_num))
+ return -EINVAL;
+
+ if (mode == THERMAL_TRIP_ACTIVATION_ENABLED)
+ state = true;
+
+ sensor_mask = 1 << adc_tm->sensor_num;
+
+ pr_debug("Sensor number:%x with state:%d\n", adc_tm->sensor_num, state);
+
+ btm_chan = adc_tm->btm_channel_num;
+ rc = qpnp_adc_tm_get_btm_idx(btm_chan, &btm_chan_idx);
+ if (rc < 0) {
+ pr_err("Invalid btm channel idx\n");
+ return rc;
+ }
+
+ switch (trip) {
+ case ADC_TM_TRIP_HIGH_WARM:
+ /* low_thr (lower voltage) for higher temp */
+ thr_int_en = adc_tm_data[btm_chan_idx].low_thr_int_chan_en;
+ rc = qpnp_adc_tm_reg_update(chip, QPNP_ADC_TM_LOW_THR_INT_EN,
+ sensor_mask, state);
+ if (rc)
+ pr_err("channel:%x failed\n", btm_chan);
+ break;
+ case ADC_TM_TRIP_LOW_COOL:
+ /* high_thr (higher voltage) for cooler temp */
+ thr_int_en = adc_tm_data[btm_chan_idx].high_thr_int_chan_en;
+ rc = qpnp_adc_tm_reg_update(chip, QPNP_ADC_TM_HIGH_THR_INT_EN,
+ sensor_mask, state);
+ if (rc)
+ pr_err("channel:%x failed\n", btm_chan);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return rc;
+}
+
+static int qpnp_adc_tm_recalib_request_check(struct qpnp_adc_tm_chip *chip,
+ int sensor_num, u8 status_high, u8 *notify_check)
+{
+ int rc = 0;
+ u8 sensor_mask = 0, mode_ctl = 0;
+ int32_t old_thr = 0, new_thr = 0;
+ uint32_t channel, btm_chan_num, scale_type;
+ struct qpnp_vadc_result result;
+ struct qpnp_adc_thr_client_info *client_info = NULL;
+ struct list_head *thr_list;
+ bool status = false;
+
+ if (!chip->adc_tm_recalib_check) {
+ *notify_check = 1;
+ return rc;
+ }
+
+ list_for_each(thr_list, &chip->sensor[sensor_num].thr_list) {
+ client_info = list_entry(thr_list,
+ struct qpnp_adc_thr_client_info, list);
+ channel = client_info->btm_param->channel;
+ btm_chan_num = chip->sensor[sensor_num].btm_channel_num;
+ sensor_mask = 1 << sensor_num;
+
+ rc = qpnp_vadc_read(chip->vadc_dev, channel, &result);
+ if (rc < 0) {
+ pr_err("failure to read vadc channel=%d\n",
+ client_info->btm_param->channel);
+ goto fail;
+ }
+ new_thr = result.physical;
+
+ if (status_high)
+ old_thr = client_info->btm_param->high_thr;
+ else
+ old_thr = client_info->btm_param->low_thr;
+
+ if (new_thr > old_thr)
+ status = (status_high) ? true : false;
+ else
+ status = (status_high) ? false : true;
+
+ pr_debug(
+ "recalib:sen=%d, new_thr=%d, new_thr_adc_code=0x%x, old_thr=%d status=%d valid_status=%d\n",
+ sensor_num, new_thr, result.adc_code,
+ old_thr, status_high, status);
+
+ rc = qpnp_adc_tm_read_thr_value(chip, btm_chan_num);
+ if (rc < 0) {
+ pr_err("adc-tm thresholds read failed\n");
+ goto fail;
+ }
+
+ if (status) {
+ *notify_check = 1;
+ pr_debug("Client can be notify\n");
+ return rc;
+ }
+
+ pr_debug("Client can not be notify, restart measurement\n");
+ /* Set measurement in single measurement mode */
+ mode_ctl = ADC_OP_NORMAL_MODE << QPNP_OP_MODE_SHIFT;
+ rc = qpnp_adc_tm_mode_select(chip, mode_ctl);
+ if (rc < 0) {
+ pr_err("adc-tm single mode select failed\n");
+ goto fail;
+ }
+
+ /* Disable bank */
+ rc = qpnp_adc_tm_disable(chip);
+ if (rc < 0) {
+ pr_err("adc-tm disable failed\n");
+ goto fail;
+ }
+
+ /* Check if a conversion is in progress */
+ rc = qpnp_adc_tm_req_sts_check(chip);
+ if (rc < 0) {
+ pr_err("adc-tm req_sts check failed\n");
+ goto fail;
+ }
+
+ rc = qpnp_adc_tm_reg_update(chip, QPNP_ADC_TM_LOW_THR_INT_EN,
+ sensor_mask, false);
+ if (rc < 0) {
+ pr_err("low threshold int write failed\n");
+ goto fail;
+ }
+
+ rc = qpnp_adc_tm_reg_update(chip, QPNP_ADC_TM_HIGH_THR_INT_EN,
+ sensor_mask, false);
+ if (rc < 0) {
+ pr_err("high threshold int enable failed\n");
+ goto fail;
+ }
+
+ rc = qpnp_adc_tm_reg_update(chip, QPNP_ADC_TM_MULTI_MEAS_EN,
+ sensor_mask, false);
+ if (rc < 0) {
+ pr_err("multi measurement en failed\n");
+ goto fail;
+ }
+
+ /* restart measurement */
+ scale_type = chip->sensor[sensor_num].scale_type;
+ chip->adc->amux_prop->amux_channel = channel;
+ chip->adc->amux_prop->decimation =
+ chip->adc->adc_channels[sensor_num].adc_decimation;
+ chip->adc->amux_prop->hw_settle_time =
+ chip->adc->adc_channels[sensor_num].hw_settle_time;
+ chip->adc->amux_prop->fast_avg_setup =
+ chip->adc->adc_channels[sensor_num].fast_avg_setup;
+ chip->adc->amux_prop->mode_sel =
+ ADC_OP_MEASUREMENT_INTERVAL << QPNP_OP_MODE_SHIFT;
+ adc_tm_rscale_fn[scale_type].chan(chip->vadc_dev,
+ client_info->btm_param,
+ &chip->adc->amux_prop->chan_prop->low_thr,
+ &chip->adc->amux_prop->chan_prop->high_thr);
+ qpnp_adc_tm_add_to_list(chip, sensor_num,
+ client_info->btm_param,
+ chip->adc->amux_prop->chan_prop);
+ chip->adc->amux_prop->chan_prop->tm_channel_select =
+ chip->sensor[sensor_num].btm_channel_num;
+ chip->adc->amux_prop->chan_prop->state_request =
+ client_info->btm_param->state_request;
+
+ rc = qpnp_adc_tm_configure(chip, chip->adc->amux_prop);
+ if (rc) {
+ pr_err("adc-tm configure failed with %d\n", rc);
+ goto fail;
+ }
+ *notify_check = 0;
+ pr_debug("BTM channel reconfigured for measuremnt\n");
+ }
+fail:
+ return rc;
+}
+
+static int qpnp_adc_tm_read_status(struct qpnp_adc_tm_chip *chip)
+{
+ u8 sensor_mask = 0, notify_check = 0;
+ int rc = 0, sensor_notify_num = 0, i = 0, sensor_num = 0;
+ uint32_t btm_chan_num = 0;
+ struct qpnp_adc_thr_client_info *client_info = NULL;
+ struct list_head *thr_list;
+
+ if (qpnp_adc_tm_is_valid(chip))
+ return -ENODEV;
+
+ mutex_lock(&chip->adc->adc_lock);
+
+ rc = qpnp_adc_tm_req_sts_check(chip);
+ if (rc) {
+ pr_err("adc-tm-tm req sts check failed with %d\n", rc);
+ goto fail;
+ }
+
+ if (chip->th_info.adc_tm_high_enable) {
+ sensor_notify_num = chip->th_info.adc_tm_high_enable;
+ while (i < chip->max_channels_available) {
+ if ((sensor_notify_num & 0x1) == 1)
+ sensor_num = i;
+ sensor_notify_num >>= 1;
+ i++;
+ }
+
+ btm_chan_num = chip->sensor[sensor_num].btm_channel_num;
+ pr_debug("high:sen:%d, hs:0x%x, ls:0x%x, meas_en:0x%x\n",
+ sensor_num, chip->th_info.adc_tm_high_enable,
+ chip->th_info.adc_tm_low_enable,
+ chip->th_info.qpnp_adc_tm_meas_en);
+ if (!chip->sensor[sensor_num].thermal_node) {
+ /* For non thermal registered clients
+ such as usb_id, vbatt, pmic_therm */
+ sensor_mask = 1 << sensor_num;
+ pr_debug("non thermal node - mask:%x\n", sensor_mask);
+ rc = qpnp_adc_tm_recalib_request_check(chip,
+ sensor_num, true, &notify_check);
+ if (rc < 0 || !notify_check) {
+ pr_debug("Calib recheck re-armed rc=%d\n", rc);
+ chip->th_info.adc_tm_high_enable = 0;
+ goto fail;
+ }
+ } else {
+ /* Uses the thermal sysfs registered device to disable
+ the corresponding high voltage threshold which
+ is triggered by low temp */
+ pr_debug("thermal node with mask:%x\n", sensor_mask);
+ }
+ list_for_each(thr_list, &chip->sensor[sensor_num].thr_list) {
+ client_info = list_entry(thr_list,
+ struct qpnp_adc_thr_client_info, list);
+ if (client_info->high_thr_set) {
+ client_info->high_thr_set = false;
+ client_info->notify_high_thr = true;
+ if (client_info->state_req_copy ==
+ ADC_TM_HIGH_LOW_THR_ENABLE)
+ client_info->state_req_copy =
+ ADC_TM_LOW_THR_ENABLE;
+ else
+ client_info->state_req_copy =
+ ADC_TM_HIGH_THR_DISABLE;
+ }
+ }
+ }
+
+ if (chip->th_info.adc_tm_low_enable) {
+ sensor_notify_num = chip->th_info.adc_tm_low_enable;
+ i = 0;
+ while (i < chip->max_channels_available) {
+ if ((sensor_notify_num & 0x1) == 1)
+ sensor_num = i;
+ sensor_notify_num >>= 1;
+ i++;
+ }
+
+ btm_chan_num = chip->sensor[sensor_num].btm_channel_num;
+ pr_debug("low:sen:%d, hs:0x%x, ls:0x%x, meas_en:0x%x\n",
+ sensor_num, chip->th_info.adc_tm_high_enable,
+ chip->th_info.adc_tm_low_enable,
+ chip->th_info.qpnp_adc_tm_meas_en);
+ if (!chip->sensor[sensor_num].thermal_node) {
+ /* For non thermal registered clients
+ such as usb_id, vbatt, pmic_therm */
+ pr_debug("non thermal node - mask:%x\n", sensor_mask);
+ rc = qpnp_adc_tm_recalib_request_check(chip,
+ sensor_num, false, &notify_check);
+ if (rc < 0 || !notify_check) {
+ pr_debug("Calib recheck re-armed rc=%d\n", rc);
+ chip->th_info.adc_tm_low_enable = 0;
+ goto fail;
+ }
+ sensor_mask = 1 << sensor_num;
+ rc = qpnp_adc_tm_reg_update(chip,
+ QPNP_ADC_TM_LOW_THR_INT_EN,
+ sensor_mask, false);
+ if (rc < 0) {
+ pr_err("low threshold int read failed\n");
+ goto fail;
+ }
+ } else {
+ /* Uses the thermal sysfs registered device to disable
+ the corresponding low voltage threshold which
+ is triggered by high temp */
+ pr_debug("thermal node with mask:%x\n", sensor_mask);
+ rc = qpnp_adc_tm_activate_trip_type(
+ chip->sensor[sensor_num].tz_dev,
+ ADC_TM_TRIP_HIGH_WARM,
+ THERMAL_TRIP_ACTIVATION_DISABLED);
+ if (rc < 0) {
+ pr_err("notify error:%d\n", sensor_num);
+ goto fail;
+ }
+ }
+ list_for_each(thr_list, &chip->sensor[sensor_num].thr_list) {
+ client_info = list_entry(thr_list,
+ struct qpnp_adc_thr_client_info, list);
+ if (client_info->low_thr_set) {
+ /* mark the corresponding clients threshold
+ as not set */
+ client_info->low_thr_set = false;
+ client_info->notify_low_thr = true;
+ if (client_info->state_req_copy ==
+ ADC_TM_HIGH_LOW_THR_ENABLE)
+ client_info->state_req_copy =
+ ADC_TM_HIGH_THR_ENABLE;
+ else
+ client_info->state_req_copy =
+ ADC_TM_LOW_THR_DISABLE;
+ }
+ }
+ }
+
+ qpnp_adc_tm_manage_thresholds(chip, sensor_num, btm_chan_num);
+
+ if (chip->th_info.adc_tm_high_enable ||
+ chip->th_info.adc_tm_low_enable) {
+ rc = qpnp_adc_tm_reg_update(chip, QPNP_ADC_TM_MULTI_MEAS_EN,
+ sensor_mask, false);
+ if (rc < 0) {
+ pr_err("multi meas disable for channel failed\n");
+ goto fail;
+ }
+
+ rc = qpnp_adc_tm_enable_if_channel_meas(chip);
+ if (rc < 0) {
+ pr_err("re-enabling measurement failed\n");
+ return rc;
+ }
+ } else
+ pr_debug("No threshold status enable %d for high/low??\n",
+ sensor_mask);
+
+fail:
+ mutex_unlock(&chip->adc->adc_lock);
+
+ if (chip->th_info.adc_tm_high_enable || chip->th_info.adc_tm_low_enable)
+ queue_work(chip->sensor[sensor_num].req_wq,
+ &chip->sensor[sensor_num].work);
+ if (rc < 0 || (!chip->th_info.adc_tm_high_enable &&
+ !chip->th_info.adc_tm_low_enable))
+ atomic_dec(&chip->wq_cnt);
+
+ return rc;
+}
+
+static void qpnp_adc_tm_high_thr_work(struct work_struct *work)
+{
+ struct qpnp_adc_tm_chip *chip = container_of(work,
+ struct qpnp_adc_tm_chip, trigger_high_thr_work);
+ int rc;
+
+ /* disable the vote if applicable */
+ if (chip->adc_vote_enable && chip->adc->hkadc_ldo &&
+ chip->adc->hkadc_ldo_ok) {
+ qpnp_adc_disable_voltage(chip->adc);
+ chip->adc_vote_enable = false;
+ }
+
+ rc = qpnp_adc_tm_read_status(chip);
+ if (rc < 0)
+ pr_err("adc-tm high thr work failed\n");
+
+ return;
+}
+
+static irqreturn_t qpnp_adc_tm_high_thr_isr(int irq, void *data)
+{
+ struct qpnp_adc_tm_chip *chip = data;
+ u8 mode_ctl = 0, status1 = 0, sensor_mask = 0;
+ int rc = 0, sensor_notify_num = 0, i = 0, sensor_num = 0;
+
+ mode_ctl = ADC_OP_NORMAL_MODE << QPNP_OP_MODE_SHIFT;
+ /* Set measurement in single measurement mode */
+ qpnp_adc_tm_mode_select(chip, mode_ctl);
+
+ qpnp_adc_tm_disable(chip);
+
+ rc = qpnp_adc_tm_read_reg(chip, QPNP_ADC_TM_STATUS1, &status1);
+ if (rc) {
+ pr_err("adc-tm read status1 failed\n");
+ return IRQ_HANDLED;
+ }
+
+ rc = qpnp_adc_tm_read_reg(chip, QPNP_ADC_TM_STATUS_HIGH,
+ &chip->th_info.status_high);
+ if (rc) {
+ pr_err("adc-tm-tm read status high failed with %d\n", rc);
+ return IRQ_HANDLED;
+ }
+
+ rc = qpnp_adc_tm_read_reg(chip, QPNP_ADC_TM_HIGH_THR_INT_EN,
+ &chip->th_info.adc_tm_high_thr_set);
+ if (rc) {
+ pr_err("adc-tm-tm read high thr failed with %d\n", rc);
+ return IRQ_HANDLED;
+ }
+
+ /* Check which interrupt threshold is lower and measure against the
+ * enabled channel */
+ rc = qpnp_adc_tm_read_reg(chip, QPNP_ADC_TM_MULTI_MEAS_EN,
+ &chip->th_info.qpnp_adc_tm_meas_en);
+ if (rc) {
+ pr_err("adc-tm-tm read status high failed with %d\n", rc);
+ return IRQ_HANDLED;
+ }
+
+ chip->th_info.adc_tm_high_enable = chip->th_info.qpnp_adc_tm_meas_en &
+ chip->th_info.status_high;
+ chip->th_info.adc_tm_high_enable &= chip->th_info.adc_tm_high_thr_set;
+
+ sensor_notify_num = chip->th_info.adc_tm_high_enable;
+ while (i < chip->max_channels_available) {
+ if ((sensor_notify_num & 0x1) == 1)
+ sensor_num = i;
+ sensor_notify_num >>= 1;
+ i++;
+ }
+
+ if (!chip->sensor[sensor_num].thermal_node) {
+ sensor_mask = 1 << sensor_num;
+ rc = qpnp_adc_tm_reg_update(chip,
+ QPNP_ADC_TM_HIGH_THR_INT_EN,
+ sensor_mask, false);
+ if (rc < 0) {
+ pr_err("high threshold int read failed\n");
+ return IRQ_HANDLED;
+ }
+ } else {
+ /* Uses the thermal sysfs registered device to disable
+ the corresponding high voltage threshold which
+ is triggered by low temp */
+ pr_debug("thermal node with mask:%x\n", sensor_mask);
+ rc = qpnp_adc_tm_activate_trip_type(
+ chip->sensor[sensor_num].tz_dev,
+ ADC_TM_TRIP_LOW_COOL,
+ THERMAL_TRIP_ACTIVATION_DISABLED);
+ if (rc < 0) {
+ pr_err("notify error:%d\n", sensor_num);
+ return IRQ_HANDLED;
+ }
+ }
+
+ atomic_inc(&chip->wq_cnt);
+ queue_work(chip->high_thr_wq, &chip->trigger_high_thr_work);
+
+ return IRQ_HANDLED;
+}
+
+static void qpnp_adc_tm_low_thr_work(struct work_struct *work)
+{
+ struct qpnp_adc_tm_chip *chip = container_of(work,
+ struct qpnp_adc_tm_chip, trigger_low_thr_work);
+ int rc;
+
+ /* disable the vote if applicable */
+ if (chip->adc_vote_enable && chip->adc->hkadc_ldo &&
+ chip->adc->hkadc_ldo_ok) {
+ qpnp_adc_disable_voltage(chip->adc);
+ chip->adc_vote_enable = false;
+ }
+
+ rc = qpnp_adc_tm_read_status(chip);
+ if (rc < 0)
+ pr_err("adc-tm low thr work failed\n");
+
+ return;
+}
+
+static irqreturn_t qpnp_adc_tm_low_thr_isr(int irq, void *data)
+{
+ struct qpnp_adc_tm_chip *chip = data;
+ u8 mode_ctl = 0, status1 = 0, sensor_mask = 0;
+ int rc = 0, sensor_notify_num = 0, i = 0, sensor_num = 0;
+
+ mode_ctl = ADC_OP_NORMAL_MODE << QPNP_OP_MODE_SHIFT;
+ /* Set measurement in single measurement mode */
+ qpnp_adc_tm_mode_select(chip, mode_ctl);
+
+ qpnp_adc_tm_disable(chip);
+
+ rc = qpnp_adc_tm_read_reg(chip, QPNP_ADC_TM_STATUS1, &status1);
+ if (rc) {
+ pr_err("adc-tm read status1 failed\n");
+ return IRQ_HANDLED;
+ }
+
+ rc = qpnp_adc_tm_read_reg(chip, QPNP_ADC_TM_STATUS_LOW,
+ &chip->th_info.status_low);
+ if (rc) {
+ pr_err("adc-tm-tm read status low failed with %d\n", rc);
+ return IRQ_HANDLED;
+ }
+
+ rc = qpnp_adc_tm_read_reg(chip, QPNP_ADC_TM_LOW_THR_INT_EN,
+ &chip->th_info.adc_tm_low_thr_set);
+ if (rc) {
+ pr_err("adc-tm-tm read low thr failed with %d\n", rc);
+ return IRQ_HANDLED;
+ }
+
+ rc = qpnp_adc_tm_read_reg(chip, QPNP_ADC_TM_MULTI_MEAS_EN,
+ &chip->th_info.qpnp_adc_tm_meas_en);
+ if (rc) {
+ pr_err("adc-tm-tm read status high failed with %d\n", rc);
+ return IRQ_HANDLED;
+ }
+
+ chip->th_info.adc_tm_low_enable = chip->th_info.qpnp_adc_tm_meas_en &
+ chip->th_info.status_low;
+ chip->th_info.adc_tm_low_enable &= chip->th_info.adc_tm_low_thr_set;
+
+ sensor_notify_num = chip->th_info.adc_tm_low_enable;
+ while (i < chip->max_channels_available) {
+ if ((sensor_notify_num & 0x1) == 1)
+ sensor_num = i;
+ sensor_notify_num >>= 1;
+ i++;
+ }
+
+ if (!chip->sensor[sensor_num].thermal_node) {
+ sensor_mask = 1 << sensor_num;
+ rc = qpnp_adc_tm_reg_update(chip,
+ QPNP_ADC_TM_LOW_THR_INT_EN,
+ sensor_mask, false);
+ if (rc < 0) {
+ pr_err("low threshold int read failed\n");
+ return IRQ_HANDLED;
+ }
+ } else {
+ /* Uses the thermal sysfs registered device to disable
+ the corresponding low voltage threshold which
+ is triggered by high temp */
+ pr_debug("thermal node with mask:%x\n", sensor_mask);
+ rc = qpnp_adc_tm_activate_trip_type(
+ chip->sensor[sensor_num].tz_dev,
+ ADC_TM_TRIP_HIGH_WARM,
+ THERMAL_TRIP_ACTIVATION_DISABLED);
+ if (rc < 0) {
+ pr_err("notify error:%d\n", sensor_num);
+ return IRQ_HANDLED;
+ }
+ }
+
+ atomic_inc(&chip->wq_cnt);
+ queue_work(chip->low_thr_wq, &chip->trigger_low_thr_work);
+
+ return IRQ_HANDLED;
+}
+
+static int qpnp_adc_read_temp(struct thermal_zone_device *thermal,
+ unsigned long *temp)
+{
+ struct qpnp_adc_tm_sensor *adc_tm_sensor = thermal->devdata;
+ struct qpnp_adc_tm_chip *chip = adc_tm_sensor->chip;
+ struct qpnp_vadc_result result;
+ int rc = 0;
+
+ rc = qpnp_vadc_read(chip->vadc_dev,
+ adc_tm_sensor->vadc_channel_num, &result);
+ if (rc)
+ return rc;
+
+ *temp = result.physical;
+
+ return rc;
+}
+
+static struct thermal_zone_device_ops qpnp_adc_tm_thermal_ops = {
+ .get_temp = qpnp_adc_read_temp,
+ .get_mode = qpnp_adc_tm_get_mode,
+ .set_mode = qpnp_adc_tm_set_mode,
+ .get_trip_type = qpnp_adc_tm_get_trip_type,
+ .activate_trip_type = qpnp_adc_tm_activate_trip_type,
+ .get_trip_temp = qpnp_adc_tm_get_trip_temp,
+ .set_trip_temp = qpnp_adc_tm_set_trip_temp,
+};
+
+int32_t qpnp_adc_tm_channel_measure(struct qpnp_adc_tm_chip *chip,
+ struct qpnp_adc_tm_btm_param *param)
+{
+ uint32_t channel, amux_prescaling, dt_index = 0, scale_type = 0;
+ int rc = 0, i = 0, version = 0;
+ bool chan_found = false;
+
+ if (qpnp_adc_tm_is_valid(chip)) {
+ pr_err("chip not valid\n");
+ return -ENODEV;
+ }
+
+ if (param->threshold_notification == NULL) {
+ pr_debug("No notification for high/low temp??\n");
+ return -EINVAL;
+ }
+
+ mutex_lock(&chip->adc->adc_lock);
+
+ channel = param->channel;
+
+ if (channel == VSYS) {
+ version = qpnp_adc_get_revid_version(chip->dev);
+ if (version == QPNP_REV_ID_PM8950_1_0) {
+ pr_debug("Channel not supported\n");
+ rc = -EINVAL;
+ goto fail_unlock;
+ }
+ }
+
+ while (i < chip->max_channels_available) {
+ if (chip->adc->adc_channels[i].channel_num ==
+ channel) {
+ dt_index = i;
+ chan_found = true;
+ i++;
+ } else
+ i++;
+ }
+
+ if (!chan_found) {
+ pr_err("not a valid ADC_TM channel\n");
+ rc = -EINVAL;
+ goto fail_unlock;
+ }
+
+ rc = qpnp_adc_tm_check_revision(chip,
+ chip->sensor[dt_index].btm_channel_num);
+ if (rc < 0)
+ goto fail_unlock;
+
+ scale_type = chip->adc->adc_channels[dt_index].adc_scale_fn;
+ if (scale_type >= SCALE_RSCALE_NONE) {
+ rc = -EBADF;
+ goto fail_unlock;
+ }
+
+
+ amux_prescaling =
+ chip->adc->adc_channels[dt_index].chan_path_prescaling;
+
+ if (amux_prescaling >= PATH_SCALING_NONE) {
+ rc = -EINVAL;
+ goto fail_unlock;
+ }
+
+ pr_debug("channel:%d, scale_type:%d, dt_idx:%d",
+ channel, scale_type, dt_index);
+ param->gain_num = qpnp_vadc_amux_scaling_ratio[amux_prescaling].num;
+ param->gain_den = qpnp_vadc_amux_scaling_ratio[amux_prescaling].den;
+ chip->adc->amux_prop->amux_channel = channel;
+ chip->adc->amux_prop->decimation =
+ chip->adc->adc_channels[dt_index].adc_decimation;
+ chip->adc->amux_prop->hw_settle_time =
+ chip->adc->adc_channels[dt_index].hw_settle_time;
+ chip->adc->amux_prop->fast_avg_setup =
+ chip->adc->adc_channels[dt_index].fast_avg_setup;
+ chip->adc->amux_prop->mode_sel =
+ ADC_OP_MEASUREMENT_INTERVAL << QPNP_OP_MODE_SHIFT;
+ adc_tm_rscale_fn[scale_type].chan(chip->vadc_dev, param,
+ &chip->adc->amux_prop->chan_prop->low_thr,
+ &chip->adc->amux_prop->chan_prop->high_thr);
+ qpnp_adc_tm_add_to_list(chip, dt_index, param,
+ chip->adc->amux_prop->chan_prop);
+ chip->adc->amux_prop->chan_prop->tm_channel_select =
+ chip->sensor[dt_index].btm_channel_num;
+ chip->adc->amux_prop->chan_prop->state_request =
+ param->state_request;
+ rc = qpnp_adc_tm_configure(chip, chip->adc->amux_prop);
+ if (rc) {
+ pr_err("adc-tm configure failed with %d\n", rc);
+ goto fail_unlock;
+ }
+
+ chip->sensor[dt_index].scale_type = scale_type;
+
+fail_unlock:
+ mutex_unlock(&chip->adc->adc_lock);
+
+ return rc;
+}
+EXPORT_SYMBOL(qpnp_adc_tm_channel_measure);
+
+int32_t qpnp_adc_tm_disable_chan_meas(struct qpnp_adc_tm_chip *chip,
+ struct qpnp_adc_tm_btm_param *param)
+{
+ uint32_t channel, dt_index = 0, btm_chan_num;
+ u8 sensor_mask = 0, mode_ctl = 0;
+ int rc = 0;
+
+ if (qpnp_adc_tm_is_valid(chip))
+ return -ENODEV;
+
+ mutex_lock(&chip->adc->adc_lock);
+
+ /* Set measurement in single measurement mode */
+ mode_ctl = ADC_OP_NORMAL_MODE << QPNP_OP_MODE_SHIFT;
+ rc = qpnp_adc_tm_mode_select(chip, mode_ctl);
+ if (rc < 0) {
+ pr_err("adc-tm single mode select failed\n");
+ goto fail;
+ }
+
+ /* Disable bank */
+ rc = qpnp_adc_tm_disable(chip);
+ if (rc < 0) {
+ pr_err("adc-tm disable failed\n");
+ goto fail;
+ }
+
+ /* Check if a conversion is in progress */
+ rc = qpnp_adc_tm_req_sts_check(chip);
+ if (rc < 0) {
+ pr_err("adc-tm req_sts check failed\n");
+ goto fail;
+ }
+
+ channel = param->channel;
+ while ((chip->adc->adc_channels[dt_index].channel_num
+ != channel) && (dt_index < chip->max_channels_available))
+ dt_index++;
+
+ if (dt_index >= chip->max_channels_available) {
+ pr_err("not a valid ADC_TMN channel\n");
+ rc = -EINVAL;
+ goto fail;
+ }
+
+ btm_chan_num = chip->sensor[dt_index].btm_channel_num;
+ sensor_mask = 1 << chip->sensor[dt_index].sensor_num;
+
+ rc = qpnp_adc_tm_reg_update(chip, QPNP_ADC_TM_LOW_THR_INT_EN,
+ sensor_mask, false);
+ if (rc < 0) {
+ pr_err("low threshold int write failed\n");
+ goto fail;
+ }
+
+ rc = qpnp_adc_tm_reg_update(chip, QPNP_ADC_TM_HIGH_THR_INT_EN,
+ sensor_mask, false);
+ if (rc < 0) {
+ pr_err("high threshold int enable failed\n");
+ goto fail;
+ }
+
+ rc = qpnp_adc_tm_reg_update(chip, QPNP_ADC_TM_MULTI_MEAS_EN,
+ sensor_mask, false);
+ if (rc < 0) {
+ pr_err("multi measurement en failed\n");
+ goto fail;
+ }
+
+ rc = qpnp_adc_tm_enable_if_channel_meas(chip);
+ if (rc < 0)
+ pr_err("re-enabling measurement failed\n");
+
+fail:
+ mutex_unlock(&chip->adc->adc_lock);
+
+ return rc;
+}
+EXPORT_SYMBOL(qpnp_adc_tm_disable_chan_meas);
+
+int32_t qpnp_adc_tm_usbid_configure(struct qpnp_adc_tm_chip *chip,
+ struct qpnp_adc_tm_btm_param *param)
+{
+ param->channel = LR_MUX10_PU2_AMUX_USB_ID_LV;
+ return qpnp_adc_tm_channel_measure(chip, param);
+}
+EXPORT_SYMBOL(qpnp_adc_tm_usbid_configure);
+
+int32_t qpnp_adc_tm_usbid_end(struct qpnp_adc_tm_chip *chip)
+{
+ struct qpnp_adc_tm_btm_param param;
+
+ return qpnp_adc_tm_disable_chan_meas(chip, &param);
+}
+EXPORT_SYMBOL(qpnp_adc_tm_usbid_end);
+
+struct qpnp_adc_tm_chip *qpnp_get_adc_tm(struct device *dev, const char *name)
+{
+ struct qpnp_adc_tm_chip *chip;
+ struct device_node *node = NULL;
+ char prop_name[QPNP_MAX_PROP_NAME_LEN];
+
+ snprintf(prop_name, QPNP_MAX_PROP_NAME_LEN, "qcom,%s-adc_tm", name);
+
+ node = of_parse_phandle(dev->of_node, prop_name, 0);
+ if (node == NULL)
+ return ERR_PTR(-ENODEV);
+
+ list_for_each_entry(chip, &qpnp_adc_tm_device_list, list)
+ if (chip->adc->pdev->dev.of_node == node)
+ return chip;
+
+ return ERR_PTR(-EPROBE_DEFER);
+}
+EXPORT_SYMBOL(qpnp_get_adc_tm);
+
+static int qpnp_adc_tm_probe(struct platform_device *pdev)
+{
+ struct device_node *node = pdev->dev.of_node, *child;
+ struct qpnp_adc_tm_chip *chip;
+ struct qpnp_adc_drv *adc_qpnp;
+ int32_t count_adc_channel_list = 0, rc, sen_idx = 0, i = 0;
+ u8 thr_init = 0;
+ bool thermal_node = false;
+
+ for_each_child_of_node(node, child)
+ count_adc_channel_list++;
+
+ if (!count_adc_channel_list) {
+ pr_err("No channel listing\n");
+ return -EINVAL;
+ }
+
+ chip = devm_kzalloc(&pdev->dev, sizeof(struct qpnp_adc_tm_chip) +
+ (count_adc_channel_list *
+ sizeof(struct qpnp_adc_tm_sensor)),
+ GFP_KERNEL);
+ if (!chip) {
+ dev_err(&pdev->dev, "Unable to allocate memory\n");
+ return -ENOMEM;
+ }
+
+ adc_qpnp = devm_kzalloc(&pdev->dev, sizeof(struct qpnp_adc_drv),
+ GFP_KERNEL);
+ if (!adc_qpnp) {
+ dev_err(&pdev->dev, "Unable to allocate memory\n");
+ rc = -ENOMEM;
+ goto fail;
+ }
+
+ chip->dev = &(pdev->dev);
+ chip->adc = adc_qpnp;
+ chip->adc->regmap = dev_get_regmap(pdev->dev.parent, NULL);
+ if (!chip->adc->regmap) {
+ dev_err(&pdev->dev, "Couldn't get parent's regmap\n");
+ rc = -EINVAL;
+ goto fail;
+ }
+
+ rc = qpnp_adc_get_devicetree_data(pdev, chip->adc);
+ if (rc) {
+ dev_err(&pdev->dev, "failed to read device tree\n");
+ goto fail;
+ }
+ mutex_init(&chip->adc->adc_lock);
+
+ /* Register the ADC peripheral interrupt */
+ chip->adc->adc_high_thr_irq = platform_get_irq_byname(pdev,
+ "high-thr-en-set");
+ if (chip->adc->adc_high_thr_irq < 0) {
+ pr_err("Invalid irq\n");
+ rc = -ENXIO;
+ goto fail;
+ }
+
+ chip->adc->adc_low_thr_irq = platform_get_irq_byname(pdev,
+ "low-thr-en-set");
+ if (chip->adc->adc_low_thr_irq < 0) {
+ pr_err("Invalid irq\n");
+ rc = -ENXIO;
+ goto fail;
+ }
+
+ chip->vadc_dev = qpnp_get_vadc(&pdev->dev, "adc_tm");
+ if (IS_ERR(chip->vadc_dev)) {
+ rc = PTR_ERR(chip->vadc_dev);
+ if (rc != -EPROBE_DEFER)
+ pr_err("vadc property missing, rc=%d\n", rc);
+ goto fail;
+ }
+ chip->adc_tm_recalib_check = of_property_read_bool(node,
+ "qcom,adc-tm-recalib-check");
+
+ for_each_child_of_node(node, child) {
+ char name[25];
+ int btm_channel_num, timer_select = 0;
+
+ rc = of_property_read_u32(child,
+ "qcom,btm-channel-number", &btm_channel_num);
+ if (rc) {
+ pr_err("Invalid btm channel number\n");
+ goto fail;
+ }
+ rc = of_property_read_u32(child,
+ "qcom,meas-interval-timer-idx", &timer_select);
+ if (rc) {
+ pr_debug("Default to timer2 with interval of 1 sec\n");
+ chip->sensor[sen_idx].timer_select =
+ ADC_MEAS_TIMER_SELECT2;
+ chip->sensor[sen_idx].meas_interval =
+ ADC_MEAS2_INTERVAL_1S;
+ } else {
+ if (timer_select >= ADC_MEAS_TIMER_NUM) {
+ pr_err("Invalid timer selection number\n");
+ goto fail;
+ }
+ chip->sensor[sen_idx].timer_select = timer_select;
+ if (timer_select == ADC_MEAS_TIMER_SELECT1)
+ chip->sensor[sen_idx].meas_interval =
+ ADC_MEAS1_INTERVAL_3P9MS;
+ else if (timer_select == ADC_MEAS_TIMER_SELECT3)
+ chip->sensor[sen_idx].meas_interval =
+ ADC_MEAS3_INTERVAL_4S;
+ else if (timer_select == ADC_MEAS_TIMER_SELECT2)
+ chip->sensor[sen_idx].meas_interval =
+ ADC_MEAS2_INTERVAL_1S;
+ }
+
+ chip->sensor[sen_idx].btm_channel_num = btm_channel_num;
+ chip->sensor[sen_idx].vadc_channel_num =
+ chip->adc->adc_channels[sen_idx].channel_num;
+ chip->sensor[sen_idx].sensor_num = sen_idx;
+ chip->sensor[sen_idx].chip = chip;
+ pr_debug("btm_chan:%x, vadc_chan:%x\n", btm_channel_num,
+ chip->adc->adc_channels[sen_idx].channel_num);
+ thermal_node = of_property_read_bool(child,
+ "qcom,thermal-node");
+ if (thermal_node) {
+ /* Register with the thermal zone */
+ pr_debug("thermal node%x\n", btm_channel_num);
+ chip->sensor[sen_idx].mode = THERMAL_DEVICE_DISABLED;
+ chip->sensor[sen_idx].thermal_node = true;
+ snprintf(name, sizeof(name), "%s",
+ chip->adc->adc_channels[sen_idx].name);
+ chip->sensor[sen_idx].meas_interval =
+ QPNP_ADC_TM_MEAS_INTERVAL;
+ chip->sensor[sen_idx].low_thr =
+ QPNP_ADC_TM_M0_LOW_THR;
+ chip->sensor[sen_idx].high_thr =
+ QPNP_ADC_TM_M0_HIGH_THR;
+ chip->sensor[sen_idx].tz_dev =
+ thermal_zone_device_register(name,
+ ADC_TM_TRIP_NUM, ADC_TM_WRITABLE_TRIPS_MASK,
+ &chip->sensor[sen_idx],
+ &qpnp_adc_tm_thermal_ops, NULL, 0, 0);
+ if (IS_ERR(chip->sensor[sen_idx].tz_dev))
+ pr_err("thermal device register failed.\n");
+ }
+ chip->sensor[sen_idx].req_wq = alloc_workqueue(
+ "qpnp_adc_notify_wq", WQ_HIGHPRI, 0);
+ if (!chip->sensor[sen_idx].req_wq) {
+ pr_err("Requesting priority wq failed\n");
+ goto fail;
+ }
+ INIT_WORK(&chip->sensor[sen_idx].work, notify_adc_tm_fn);
+ INIT_LIST_HEAD(&chip->sensor[sen_idx].thr_list);
+ sen_idx++;
+ }
+ chip->max_channels_available = count_adc_channel_list;
+ chip->high_thr_wq = alloc_workqueue("qpnp_adc_tm_high_thr_wq",
+ WQ_HIGHPRI, 0);
+ if (!chip->high_thr_wq) {
+ pr_err("Requesting high thr priority wq failed\n");
+ goto fail;
+ }
+ chip->low_thr_wq = alloc_workqueue("qpnp_adc_tm_low_thr_wq",
+ WQ_HIGHPRI, 0);
+ if (!chip->low_thr_wq) {
+ pr_err("Requesting low thr priority wq failed\n");
+ goto fail;
+ }
+ INIT_WORK(&chip->trigger_high_thr_work, qpnp_adc_tm_high_thr_work);
+ INIT_WORK(&chip->trigger_low_thr_work, qpnp_adc_tm_low_thr_work);
+ atomic_set(&chip->wq_cnt, 0);
+
+ rc = qpnp_adc_tm_write_reg(chip, QPNP_ADC_TM_HIGH_THR_INT_EN,
+ thr_init);
+ if (rc < 0) {
+ pr_err("high thr init failed\n");
+ goto fail;
+ }
+
+ rc = qpnp_adc_tm_write_reg(chip, QPNP_ADC_TM_LOW_THR_INT_EN,
+ thr_init);
+ if (rc < 0) {
+ pr_err("low thr init failed\n");
+ goto fail;
+ }
+
+ rc = qpnp_adc_tm_write_reg(chip, QPNP_ADC_TM_MULTI_MEAS_EN,
+ thr_init);
+ if (rc < 0) {
+ pr_err("multi meas en failed\n");
+ goto fail;
+ }
+
+ rc = devm_request_irq(&pdev->dev, chip->adc->adc_high_thr_irq,
+ qpnp_adc_tm_high_thr_isr,
+ IRQF_TRIGGER_RISING, "qpnp_adc_tm_high_interrupt", chip);
+ if (rc) {
+ dev_err(&pdev->dev, "failed to request adc irq\n");
+ goto fail;
+ } else {
+ enable_irq_wake(chip->adc->adc_high_thr_irq);
+ }
+
+ rc = devm_request_irq(&pdev->dev, chip->adc->adc_low_thr_irq,
+ qpnp_adc_tm_low_thr_isr,
+ IRQF_TRIGGER_RISING, "qpnp_adc_tm_low_interrupt", chip);
+ if (rc) {
+ dev_err(&pdev->dev, "failed to request adc irq\n");
+ goto fail;
+ } else {
+ enable_irq_wake(chip->adc->adc_low_thr_irq);
+ }
+
+ chip->adc_vote_enable = false;
+ dev_set_drvdata(&pdev->dev, chip);
+ list_add(&chip->list, &qpnp_adc_tm_device_list);
+
+ pr_debug("OK\n");
+ return 0;
+fail:
+ for_each_child_of_node(node, child) {
+ thermal_node = of_property_read_bool(child,
+ "qcom,thermal-node");
+ if (thermal_node) {
+ thermal_zone_device_unregister(chip->sensor[i].tz_dev);
+ if (chip->sensor[i].req_wq)
+ destroy_workqueue(chip->sensor[sen_idx].req_wq);
+ }
+ i++;
+ }
+ if (chip->high_thr_wq)
+ destroy_workqueue(chip->high_thr_wq);
+ if (chip->low_thr_wq)
+ destroy_workqueue(chip->low_thr_wq);
+ dev_set_drvdata(&pdev->dev, NULL);
+ return rc;
+}
+
+static int qpnp_adc_tm_remove(struct platform_device *pdev)
+{
+ struct qpnp_adc_tm_chip *chip = dev_get_drvdata(&pdev->dev);
+ struct device_node *node = pdev->dev.of_node, *child;
+ bool thermal_node = false;
+ int i = 0;
+
+ for_each_child_of_node(node, child) {
+ thermal_node = of_property_read_bool(child,
+ "qcom,thermal-node");
+ if (thermal_node) {
+ thermal_zone_device_unregister(chip->sensor[i].tz_dev);
+ if (chip->sensor[i].req_wq)
+ destroy_workqueue(chip->sensor[i].req_wq);
+ }
+ i++;
+ }
+
+ if (chip->high_thr_wq)
+ destroy_workqueue(chip->high_thr_wq);
+ if (chip->low_thr_wq)
+ destroy_workqueue(chip->low_thr_wq);
+ if (chip->adc->hkadc_ldo && chip->adc->hkadc_ldo_ok)
+ qpnp_adc_free_voltage_resource(chip->adc);
+ dev_set_drvdata(&pdev->dev, NULL);
+
+ return 0;
+}
+
+static void qpnp_adc_tm_shutdown(struct platform_device *pdev)
+{
+ struct qpnp_adc_tm_chip *chip = dev_get_drvdata(&pdev->dev);
+ int rc = 0;
+ u8 reg_val = 0, status1 = 0, en_ctl1 = 0;
+
+ /* Set measurement in single measurement mode */
+ reg_val = ADC_OP_NORMAL_MODE << QPNP_OP_MODE_SHIFT;
+ rc = qpnp_adc_tm_mode_select(chip, reg_val);
+ if (rc < 0)
+ pr_err("adc-tm single mode select failed\n");
+
+ /* Disable bank */
+ rc = qpnp_adc_tm_disable(chip);
+ if (rc < 0)
+ pr_err("adc-tm disable failed\n");
+
+ /* Check if a conversion is in progress */
+ rc = qpnp_adc_tm_req_sts_check(chip);
+ if (rc < 0)
+ pr_err("adc-tm req_sts check failed\n");
+
+ /* Disable multimeasurement */
+ reg_val = 0;
+ rc = qpnp_adc_tm_write_reg(chip, QPNP_ADC_TM_MULTI_MEAS_EN, reg_val);
+ if (rc < 0)
+ pr_err("adc-tm multi-measurement mode disable failed\n");
+
+ rc = qpnp_adc_tm_read_reg(chip, QPNP_ADC_TM_STATUS1, &status1);
+ if (rc < 0)
+ pr_err("adc-tm status1 read failed\n");
+
+ rc = qpnp_adc_tm_read_reg(chip, QPNP_EN_CTL1, &en_ctl1);
+ if (rc < 0)
+ pr_err("adc-tm en_ctl1 read failed\n");
+
+ pr_debug("adc-tm status1=0%x, en_ctl1=0x%x\n", status1, en_ctl1);
+ pr_debug("stopping all recurring measurements on adc-tm\n");
+}
+
+static int qpnp_adc_tm_suspend_noirq(struct device *dev)
+{
+ struct qpnp_adc_tm_chip *chip = dev_get_drvdata(dev);
+
+ if (0 != atomic_read(&chip->wq_cnt)) {
+ pr_err(
+ "Aborting suspend, adc_tm notification running while suspending\n");
+ return -EBUSY;
+ }
+ return 0;
+}
+
+static const struct dev_pm_ops qpnp_adc_tm_pm_ops = {
+ .suspend_noirq = qpnp_adc_tm_suspend_noirq,
+};
+
+static const struct of_device_id qpnp_adc_tm_match_table[] = {
+ { .compatible = "qcom,qpnp-adc-tm" },
+ {}
+};
+
+static struct platform_driver qpnp_adc_tm_driver = {
+ .driver = {
+ .name = "qcom,qpnp-adc-tm",
+ .of_match_table = qpnp_adc_tm_match_table,
+ .pm = &qpnp_adc_tm_pm_ops,
+ },
+ .probe = qpnp_adc_tm_probe,
+ .remove = qpnp_adc_tm_remove,
+ .shutdown = qpnp_adc_tm_shutdown,
+};
+
+static int __init qpnp_adc_tm_init(void)
+{
+ return platform_driver_register(&qpnp_adc_tm_driver);
+}
+module_init(qpnp_adc_tm_init);
+
+static void __exit qpnp_adc_tm_exit(void)
+{
+ platform_driver_unregister(&qpnp_adc_tm_driver);
+}
+module_exit(qpnp_adc_tm_exit);
+
+MODULE_DESCRIPTION("QPNP PMIC ADC Threshold Monitoring driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/thermal/qpnp-temp-alarm.c b/drivers/thermal/qpnp-temp-alarm.c
index 19b599c0f1ff..3b33fbaa5e25 100644
--- a/drivers/thermal/qpnp-temp-alarm.c
+++ b/drivers/thermal/qpnp-temp-alarm.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2015, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -19,8 +19,10 @@
#include <linux/string.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
+#include <linux/regmap.h>
#include <linux/slab.h>
#include <linux/spmi.h>
+#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/thermal.h>
@@ -80,7 +82,8 @@ enum qpnp_tm_adc_type {
struct qpnp_tm_chip {
struct delayed_work irq_work;
- struct spmi_device *spmi_dev;
+ struct platform_device *pdev;
+ struct regmap *regmap;
struct thermal_zone_device *tz_dev;
const char *tm_name;
enum qpnp_tm_adc_type adc_type;
@@ -109,12 +112,14 @@ static inline int qpnp_tm_read(struct qpnp_tm_chip *chip, u16 addr, u8 *buf,
{
int rc;
- rc = spmi_ext_register_readl(chip->spmi_dev->ctrl,
- chip->spmi_dev->sid, chip->base_addr + addr, buf, len);
+ rc = regmap_bulk_read(chip->regmap, chip->base_addr + addr, buf, len);
if (rc)
- dev_err(&chip->spmi_dev->dev, "%s: spmi_ext_register_readl() failed. sid=%d, addr=%04X, len=%d, rc=%d\n",
- __func__, chip->spmi_dev->sid, chip->base_addr + addr,
+ dev_err(&chip->pdev->dev,
+ "%s: regmap_bulk_readl failed. sid=%d, addr=%04X, len=%d, rc=%d\n",
+ __func__,
+ to_spmi_device(chip->pdev->dev.parent)->usid,
+ chip->base_addr + addr,
len, rc);
return rc;
@@ -125,12 +130,14 @@ static inline int qpnp_tm_write(struct qpnp_tm_chip *chip, u16 addr, u8 *buf,
{
int rc;
- rc = spmi_ext_register_writel(chip->spmi_dev->ctrl,
- chip->spmi_dev->sid, chip->base_addr + addr, buf, len);
+ rc = regmap_bulk_write(chip->regmap, chip->base_addr + addr, buf, len);
if (rc)
- dev_err(&chip->spmi_dev->dev, "%s: spmi_ext_register_writel() failed. sid=%d, addr=%04X, len=%d, rc=%d\n",
- __func__, chip->spmi_dev->sid, chip->base_addr + addr,
+ dev_err(&chip->pdev->dev,
+ "%s: regmap_bulk_write failed. sid=%d, addr=%04X, len=%d, rc=%d\n",
+ __func__,
+ to_spmi_device(chip->pdev->dev.parent)->usid,
+ chip->base_addr + addr,
len, rc);
return rc;
@@ -165,7 +172,8 @@ static int qpnp_tm_update_temp(struct qpnp_tm_chip *chip)
if (!rc)
chip->temperature = adc_result.physical;
else
- dev_err(&chip->spmi_dev->dev, "%s: qpnp_vadc_read(%d) failed, rc=%d\n",
+ dev_err(&chip->pdev->dev,
+ "%s: qpnp_vadc_read(%d) failed, rc=%d\n",
__func__, chip->adc_channel, rc);
return rc;
@@ -256,7 +264,8 @@ static int qpnp_tz_get_temp_qpnp_adc(struct thermal_zone_device *thermal,
rc = qpnp_tm_update_temp(chip);
if (rc < 0) {
- dev_err(&chip->spmi_dev->dev, "%s: %s: adc read failed, rc = %d\n",
+ dev_err(&chip->pdev->dev,
+ "%s: %s: adc read failed, rc = %d\n",
__func__, chip->tm_name, rc);
return rc;
}
@@ -464,10 +473,10 @@ static int qpnp_tm_init_reg(struct qpnp_tm_chip *chip)
return rc;
}
-static int qpnp_tm_probe(struct spmi_device *spmi)
+static int qpnp_tm_probe(struct platform_device *pdev)
{
struct device_node *node;
- struct resource *res;
+ unsigned int base;
struct qpnp_tm_chip *chip;
struct thermal_zone_device_ops *tz_ops;
char *tm_name;
@@ -475,53 +484,53 @@ static int qpnp_tm_probe(struct spmi_device *spmi)
int rc = 0;
u8 raw_type[2], type, subtype;
- if (!spmi || !(&spmi->dev) || !spmi->dev.of_node) {
- dev_err(&spmi->dev, "%s: device tree node not found\n",
+ if (!pdev || !(&pdev->dev) || !pdev->dev.of_node) {
+ dev_err(&pdev->dev, "%s: device tree node not found\n",
__func__);
return -EINVAL;
}
- node = spmi->dev.of_node;
+ node = pdev->dev.of_node;
chip = kzalloc(sizeof(struct qpnp_tm_chip), GFP_KERNEL);
- if (!chip) {
- dev_err(&spmi->dev, "%s: Can't allocate qpnp_tm_chip\n",
- __func__);
+ if (!chip)
return -ENOMEM;
+
+ chip->regmap = dev_get_regmap(pdev->dev.parent, NULL);
+ if (!chip->regmap) {
+ dev_err(&pdev->dev, "Couldn't get parent's regmap\n");
+ return -EINVAL;
}
- dev_set_drvdata(&spmi->dev, chip);
+ dev_set_drvdata(&pdev->dev, chip);
- res = spmi_get_resource(spmi, NULL, IORESOURCE_MEM, 0);
- if (!res) {
- dev_err(&spmi->dev, "%s: node is missing base address\n",
- __func__);
- rc = -EINVAL;
+ rc = of_property_read_u32(pdev->dev.of_node, "reg", &base);
+ if (rc < 0) {
+ dev_err(&pdev->dev,
+ "Couldn't find reg in node = %s rc = %d\n",
+ pdev->dev.of_node->full_name, rc);
goto free_chip;
}
- chip->base_addr = res->start;
- chip->spmi_dev = spmi;
+ chip->base_addr = base;
+ chip->pdev = pdev;
- chip->irq = spmi_get_irq(spmi, NULL, 0);
+ chip->irq = platform_get_irq(pdev, 0);
if (chip->irq < 0) {
rc = chip->irq;
- dev_err(&spmi->dev, "%s: node is missing irq, rc=%d\n",
+ dev_err(&pdev->dev, "%s: node is missing irq, rc=%d\n",
__func__, rc);
goto free_chip;
}
chip->tm_name = of_get_property(node, "label", NULL);
if (chip->tm_name == NULL) {
- dev_err(&spmi->dev, "%s: node is missing label\n",
- __func__);
+ dev_err(&pdev->dev, "%s: node is missing label\n", __func__);
rc = -EINVAL;
goto free_chip;
}
tm_name = kstrdup(chip->tm_name, GFP_KERNEL);
if (tm_name == NULL) {
- dev_err(&spmi->dev, "%s: could not allocate memory for label\n",
- __func__);
rc = -ENOMEM;
goto free_chip;
}
@@ -533,18 +542,20 @@ static int qpnp_tm_probe(struct spmi_device *spmi)
chip->thresh = THRESH_MAX + 1;
rc = of_property_read_u32(node, "qcom,threshold-set", &chip->thresh);
if (!rc && (chip->thresh < THRESH_MIN || chip->thresh > THRESH_MAX))
- dev_err(&spmi->dev, "%s: invalid qcom,threshold-set=%u specified\n",
+ dev_err(&pdev->dev,
+ "%s: invalid qcom,threshold-set=%u specified\n",
__func__, chip->thresh);
chip->adc_type = QPNP_TM_ADC_NONE;
rc = of_property_read_u32(node, "qcom,channel-num", &chip->adc_channel);
if (!rc) {
if (chip->adc_channel < 0 || chip->adc_channel >= ADC_MAX_NUM) {
- dev_err(&spmi->dev, "%s: invalid qcom,channel-num=%d specified\n",
+ dev_err(&pdev->dev,
+ "%s: invalid qcom,channel-num=%d specified\n",
__func__, chip->adc_channel);
} else {
chip->adc_type = QPNP_TM_ADC_QPNP_ADC;
- chip->vadc_dev = qpnp_get_vadc(&spmi->dev,
+ chip->vadc_dev = qpnp_get_vadc(&pdev->dev,
"temp_alarm");
if (IS_ERR(chip->vadc_dev)) {
rc = PTR_ERR(chip->vadc_dev);
@@ -570,7 +581,8 @@ static int qpnp_tm_probe(struct spmi_device *spmi)
rc = qpnp_tm_read(chip, QPNP_TM_REG_TYPE, raw_type, 2);
if (rc) {
- dev_err(&spmi->dev, "%s: could not read type register, rc=%d\n",
+ dev_err(&pdev->dev,
+ "%s: could not read type register, rc=%d\n",
__func__, rc);
goto err_cancel_work;
}
@@ -578,7 +590,8 @@ static int qpnp_tm_probe(struct spmi_device *spmi)
subtype = raw_type[1];
if (type != QPNP_TM_TYPE || subtype != QPNP_TM_SUBTYPE) {
- dev_err(&spmi->dev, "%s: invalid type=%02X or subtype=%02X register value\n",
+ dev_err(&pdev->dev,
+ "%s: invalid type=%02X or subtype=%02X register value\n",
__func__, type, subtype);
rc = -ENODEV;
goto err_cancel_work;
@@ -586,7 +599,7 @@ static int qpnp_tm_probe(struct spmi_device *spmi)
rc = qpnp_tm_init_reg(chip);
if (rc) {
- dev_err(&spmi->dev, "%s: qpnp_tm_init_reg() failed, rc=%d\n",
+ dev_err(&pdev->dev, "%s: qpnp_tm_init_reg() failed, rc=%d\n",
__func__, rc);
goto err_cancel_work;
}
@@ -594,7 +607,8 @@ static int qpnp_tm_probe(struct spmi_device *spmi)
if (chip->adc_type == QPNP_TM_ADC_NONE) {
rc = qpnp_tm_init_temp_no_adc(chip);
if (rc) {
- dev_err(&spmi->dev, "%s: qpnp_tm_init_temp_no_adc() failed, rc=%d\n",
+ dev_err(&pdev->dev,
+ "%s: qpnp_tm_init_temp_no_adc() failed, rc=%d\n",
__func__, rc);
goto err_cancel_work;
}
@@ -604,7 +618,8 @@ static int qpnp_tm_probe(struct spmi_device *spmi)
chip->mode = THERMAL_DEVICE_DISABLED;
rc = qpnp_tm_shutdown_override(chip, SOFTWARE_OVERRIDE_DISABLED);
if (rc) {
- dev_err(&spmi->dev, "%s: qpnp_tm_shutdown_override() failed, rc=%d\n",
+ dev_err(&pdev->dev,
+ "%s: qpnp_tm_shutdown_override() failed, rc=%d\n",
__func__, rc);
goto err_cancel_work;
}
@@ -612,7 +627,8 @@ static int qpnp_tm_probe(struct spmi_device *spmi)
chip->tz_dev = thermal_zone_device_register(tm_name, TRIP_NUM, 0, chip,
tz_ops, NULL, 0, 0);
if (chip->tz_dev == NULL) {
- dev_err(&spmi->dev, "%s: thermal_zone_device_register() failed.\n",
+ dev_err(&pdev->dev,
+ "%s: thermal_zone_device_register() failed.\n",
__func__);
rc = -ENODEV;
goto err_cancel_work;
@@ -621,7 +637,7 @@ static int qpnp_tm_probe(struct spmi_device *spmi)
rc = request_irq(chip->irq, qpnp_tm_isr, IRQF_TRIGGER_RISING, tm_name,
chip);
if (rc < 0) {
- dev_err(&spmi->dev, "%s: request_irq(%d) failed: %d\n",
+ dev_err(&pdev->dev, "%s: request_irq(%d) failed: %d\n",
__func__, chip->irq, rc);
goto err_free_tz;
}
@@ -634,16 +650,16 @@ err_cancel_work:
cancel_delayed_work_sync(&chip->irq_work);
kfree(chip->tm_name);
free_chip:
- dev_set_drvdata(&spmi->dev, NULL);
+ dev_set_drvdata(&pdev->dev, NULL);
kfree(chip);
return rc;
}
-static int qpnp_tm_remove(struct spmi_device *spmi)
+static int qpnp_tm_remove(struct platform_device *pdev)
{
- struct qpnp_tm_chip *chip = dev_get_drvdata(&spmi->dev);
+ struct qpnp_tm_chip *chip = dev_get_drvdata(&pdev->dev);
- dev_set_drvdata(&spmi->dev, NULL);
+ dev_set_drvdata(&pdev->dev, NULL);
thermal_zone_device_unregister(chip->tz_dev);
kfree(chip->tm_name);
qpnp_tm_shutdown_override(chip, SOFTWARE_OVERRIDE_DISABLED);
@@ -691,12 +707,12 @@ static struct of_device_id qpnp_tm_match_table[] = {
{}
};
-static const struct spmi_device_id qpnp_tm_id[] = {
+static const struct platform_device_id qpnp_tm_id[] = {
{ QPNP_TM_DRIVER_NAME, 0 },
{}
};
-static struct spmi_driver qpnp_tm_driver = {
+static struct platform_driver qpnp_tm_driver = {
.driver = {
.name = QPNP_TM_DRIVER_NAME,
.of_match_table = qpnp_tm_match_table,
@@ -710,12 +726,12 @@ static struct spmi_driver qpnp_tm_driver = {
int __init qpnp_tm_init(void)
{
- return spmi_driver_register(&qpnp_tm_driver);
+ return platform_driver_register(&qpnp_tm_driver);
}
static void __exit qpnp_tm_exit(void)
{
- spmi_driver_unregister(&qpnp_tm_driver);
+ platform_driver_unregister(&qpnp_tm_driver);
}
module_init(qpnp_tm_init);
diff --git a/include/linux/qpnp/qpnp-adc.h b/include/linux/qpnp/qpnp-adc.h
index 63bbbd69a94a..d7bdb2cce396 100644
--- a/include/linux/qpnp/qpnp-adc.h
+++ b/include/linux/qpnp/qpnp-adc.h
@@ -1213,7 +1213,8 @@ struct qpnp_iadc_result {
* @calib - Internal rsens calibration values for gain and offset.
*/
struct qpnp_adc_drv {
- struct spmi_device *spmi;
+ struct platform_device *pdev;
+ struct regmap *regmap;
uint8_t slave;
uint16_t offset;
struct qpnp_adc_properties *adc_prop;
@@ -1315,7 +1316,7 @@ int32_t qpnp_vadc_conv_seq_request(struct qpnp_vadc_chip *dev,
* @spmi: spmi ADC device.
* @adc_qpnp: spmi device tree node structure
*/
-int32_t qpnp_adc_get_devicetree_data(struct spmi_device *spmi,
+int32_t qpnp_adc_get_devicetree_data(struct platform_device *pdev,
struct qpnp_adc_drv *adc_qpnp);
/**
diff --git a/sound/soc/codecs/msm8916-wcd-irq.c b/sound/soc/codecs/msm8916-wcd-irq.c
new file mode 100644
index 000000000000..8fbd72964108
--- /dev/null
+++ b/sound/soc/codecs/msm8916-wcd-irq.c
@@ -0,0 +1,445 @@
+/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/bitops.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/spmi.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/interrupt.h>
+#include <linux/pm_qos.h>
+#include <soc/qcom/pm.h>
+#include <sound/soc.h>
+#include "msm8x16-wcd.h"
+#include "msm8916-wcd-irq.h"
+#include "msm8x16_wcd_registers.h"
+
+#define MAX_NUM_IRQS 14
+#define NUM_IRQ_REGS 2
+#define WCD9XXX_SYSTEM_RESUME_TIMEOUT_MS 700
+
+#define BYTE_BIT_MASK(nr) (1UL << ((nr) % BITS_PER_BYTE))
+#define BIT_BYTE(nr) ((nr) / BITS_PER_BYTE)
+
+static irqreturn_t wcd9xxx_spmi_irq_handler(int linux_irq, void *data);
+
+char *irq_names[MAX_NUM_IRQS] = {
+ "spk_cnp_int",
+ "spk_clip_int",
+ "spk_ocp_int",
+ "ins_rem_det1",
+ "but_rel_det",
+ "but_press_det",
+ "ins_rem_det",
+ "mbhc_int",
+ "ear_ocp_int",
+ "hphr_ocp_int",
+ "hphl_ocp_det",
+ "ear_cnp_int",
+ "hphr_cnp_int",
+ "hphl_cnp_int"
+};
+
+int order[MAX_NUM_IRQS] = {
+ MSM8X16_WCD_IRQ_SPKR_CNP,
+ MSM8X16_WCD_IRQ_SPKR_CLIP,
+ MSM8X16_WCD_IRQ_SPKR_OCP,
+ MSM8X16_WCD_IRQ_MBHC_INSREM_DET1,
+ MSM8X16_WCD_IRQ_MBHC_RELEASE,
+ MSM8X16_WCD_IRQ_MBHC_PRESS,
+ MSM8X16_WCD_IRQ_MBHC_INSREM_DET,
+ MSM8X16_WCD_IRQ_MBHC_HS_DET,
+ MSM8X16_WCD_IRQ_EAR_OCP,
+ MSM8X16_WCD_IRQ_HPHR_OCP,
+ MSM8X16_WCD_IRQ_HPHL_OCP,
+ MSM8X16_WCD_IRQ_EAR_CNP,
+ MSM8X16_WCD_IRQ_HPHR_CNP,
+ MSM8X16_WCD_IRQ_HPHL_CNP,
+};
+
+enum wcd9xxx_spmi_pm_state {
+ WCD9XXX_PM_SLEEPABLE,
+ WCD9XXX_PM_AWAKE,
+ WCD9XXX_PM_ASLEEP,
+};
+
+struct wcd9xxx_spmi_map {
+ uint8_t handled[NUM_IRQ_REGS];
+ uint8_t mask[NUM_IRQ_REGS];
+ int linuxirq[MAX_NUM_IRQS];
+ irq_handler_t handler[MAX_NUM_IRQS];
+ struct spmi_device *spmi[NUM_IRQ_REGS];
+ struct snd_soc_codec *codec;
+
+ enum wcd9xxx_spmi_pm_state pm_state;
+ struct mutex pm_lock;
+ /* pm_wq notifies change of pm_state */
+ wait_queue_head_t pm_wq;
+ struct pm_qos_request pm_qos_req;
+ int wlock_holders;
+};
+
+struct wcd9xxx_spmi_map map;
+
+void wcd9xxx_spmi_enable_irq(int irq)
+{
+ pr_debug("%s: irqno =%d\n", __func__, irq);
+ if ((irq >= 0) && (irq <= 7)) {
+ snd_soc_update_bits(map.codec,
+ MSM8X16_WCD_A_DIGITAL_INT_EN_CLR,
+ (0x01 << irq), 0x00);
+ snd_soc_update_bits(map.codec,
+ MSM8X16_WCD_A_DIGITAL_INT_EN_SET,
+ (0x01 << irq), (0x01 << irq));
+ }
+ if ((irq > 7) && (irq <= 15)) {
+ snd_soc_update_bits(map.codec,
+ MSM8X16_WCD_A_ANALOG_INT_EN_CLR,
+ (0x01 << (irq - 8)), 0x00);
+ snd_soc_update_bits(map.codec,
+ MSM8X16_WCD_A_ANALOG_INT_EN_SET,
+ (0x01 << (irq - 8)), (0x01 << (irq - 8)));
+ }
+
+ if (!(map.mask[BIT_BYTE(irq)] & (BYTE_BIT_MASK(irq))))
+ return;
+
+ map.mask[BIT_BYTE(irq)] &=
+ ~(BYTE_BIT_MASK(irq));
+
+ enable_irq(map.linuxirq[irq]);
+}
+
+void wcd9xxx_spmi_disable_irq(int irq)
+{
+ pr_debug("%s: irqno =%d\n", __func__, irq);
+ if ((irq >= 0) && (irq <= 7)) {
+ snd_soc_update_bits(map.codec,
+ MSM8X16_WCD_A_DIGITAL_INT_EN_SET,
+ (0x01 << (irq)), 0x00);
+ snd_soc_update_bits(map.codec,
+ MSM8X16_WCD_A_DIGITAL_INT_EN_CLR,
+ (0x01 << irq), (0x01 << irq));
+ }
+
+ if ((irq > 7) && (irq <= 15)) {
+ snd_soc_update_bits(map.codec,
+ MSM8X16_WCD_A_ANALOG_INT_EN_SET,
+ (0x01 << (irq - 8)), 0x00);
+ snd_soc_update_bits(map.codec,
+ MSM8X16_WCD_A_ANALOG_INT_EN_CLR,
+ (0x01 << (irq - 8)), (0x01 << (irq - 8)));
+ }
+
+ if (map.mask[BIT_BYTE(irq)] & (BYTE_BIT_MASK(irq)))
+ return;
+
+ map.mask[BIT_BYTE(irq)] |=
+ (BYTE_BIT_MASK(irq));
+
+ disable_irq_nosync(map.linuxirq[irq]);
+}
+
+int wcd9xxx_spmi_request_irq(int irq, irq_handler_t handler,
+ const char *name, void *priv)
+{
+ int rc;
+ unsigned long irq_flags;
+
+ map.linuxirq[irq] =
+ spmi_get_irq_byname(map.spmi[BIT_BYTE(irq)], NULL,
+ irq_names[irq]);
+
+ if (strcmp(name, "mbhc sw intr"))
+ irq_flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
+ IRQF_ONESHOT;
+ else
+ irq_flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
+ IRQF_ONESHOT | IRQF_NO_SUSPEND;
+ pr_debug("%s: name:%s irq_flags = %lx\n", __func__, name, irq_flags);
+
+ rc = devm_request_threaded_irq(&map.spmi[BIT_BYTE(irq)]->dev,
+ map.linuxirq[irq], NULL,
+ wcd9xxx_spmi_irq_handler,
+ irq_flags,
+ name, priv);
+ if (rc < 0) {
+ dev_err(&map.spmi[BIT_BYTE(irq)]->dev,
+ "Can't request %d IRQ\n", irq);
+ return rc;
+ }
+
+ dev_dbg(&map.spmi[BIT_BYTE(irq)]->dev,
+ "irq %d linuxIRQ: %d\n", irq, map.linuxirq[irq]);
+ map.mask[BIT_BYTE(irq)] &= ~BYTE_BIT_MASK(irq);
+ map.handler[irq] = handler;
+ enable_irq_wake(map.linuxirq[irq]);
+ return 0;
+}
+
+int wcd9xxx_spmi_free_irq(int irq, void *priv)
+{
+ devm_free_irq(&map.spmi[BIT_BYTE(irq)]->dev, map.linuxirq[irq],
+ priv);
+ map.mask[BIT_BYTE(irq)] |= BYTE_BIT_MASK(irq);
+ return 0;
+}
+
+static int get_irq_bit(int linux_irq)
+{
+ int i = 0;
+
+ for (; i < MAX_NUM_IRQS; i++)
+ if (map.linuxirq[i] == linux_irq)
+ return i;
+
+ return i;
+}
+
+static int get_order_irq(int i)
+{
+ return order[i];
+}
+
+static irqreturn_t wcd9xxx_spmi_irq_handler(int linux_irq, void *data)
+{
+ int irq, i, j;
+ unsigned long status[NUM_IRQ_REGS] = {0};
+
+ if (unlikely(wcd9xxx_spmi_lock_sleep() == false)) {
+ pr_err("Failed to hold suspend\n");
+ return IRQ_NONE;
+ }
+
+ irq = get_irq_bit(linux_irq);
+ if (irq == MAX_NUM_IRQS)
+ return IRQ_HANDLED;
+
+ status[BIT_BYTE(irq)] |= BYTE_BIT_MASK(irq);
+ for (i = 0; i < NUM_IRQ_REGS; i++) {
+ status[i] |= snd_soc_read(map.codec,
+ BIT_BYTE(irq) * 0x100 +
+ MSM8X16_WCD_A_DIGITAL_INT_LATCHED_STS);
+ status[i] &= ~map.mask[i];
+ }
+ for (i = 0; i < MAX_NUM_IRQS; i++) {
+ j = get_order_irq(i);
+ if ((status[BIT_BYTE(j)] & BYTE_BIT_MASK(j)) &&
+ ((map.handled[BIT_BYTE(j)] &
+ BYTE_BIT_MASK(j)) == 0)) {
+ map.handler[j](irq, data);
+ map.handled[BIT_BYTE(j)] |=
+ BYTE_BIT_MASK(j);
+ }
+ }
+ map.handled[BIT_BYTE(irq)] &= ~BYTE_BIT_MASK(irq);
+ wcd9xxx_spmi_unlock_sleep();
+
+ return IRQ_HANDLED;
+}
+
+enum wcd9xxx_spmi_pm_state wcd9xxx_spmi_pm_cmpxchg(
+ enum wcd9xxx_spmi_pm_state o,
+ enum wcd9xxx_spmi_pm_state n)
+{
+ enum wcd9xxx_spmi_pm_state old;
+
+ mutex_lock(&map.pm_lock);
+ old = map.pm_state;
+ if (old == o)
+ map.pm_state = n;
+ pr_debug("%s: map.pm_state = %d\n", __func__, map.pm_state);
+ mutex_unlock(&map.pm_lock);
+ return old;
+}
+EXPORT_SYMBOL(wcd9xxx_spmi_pm_cmpxchg);
+
+int wcd9xxx_spmi_suspend(pm_message_t pmesg)
+{
+ int ret = 0;
+
+ pr_debug("%s: enter\n", __func__);
+ /*
+ * pm_qos_update_request() can be called after this suspend chain call
+ * started. thus suspend can be called while lock is being held
+ */
+ mutex_lock(&map.pm_lock);
+ if (map.pm_state == WCD9XXX_PM_SLEEPABLE) {
+ pr_debug("%s: suspending system, state %d, wlock %d\n",
+ __func__, map.pm_state,
+ map.wlock_holders);
+ map.pm_state = WCD9XXX_PM_ASLEEP;
+ } else if (map.pm_state == WCD9XXX_PM_AWAKE) {
+ /*
+ * unlock to wait for pm_state == WCD9XXX_PM_SLEEPABLE
+ * then set to WCD9XXX_PM_ASLEEP
+ */
+ pr_debug("%s: waiting to suspend system, state %d, wlock %d\n",
+ __func__, map.pm_state,
+ map.wlock_holders);
+ mutex_unlock(&map.pm_lock);
+ if (!(wait_event_timeout(map.pm_wq,
+ wcd9xxx_spmi_pm_cmpxchg(
+ WCD9XXX_PM_SLEEPABLE,
+ WCD9XXX_PM_ASLEEP) ==
+ WCD9XXX_PM_SLEEPABLE,
+ HZ))) {
+ pr_debug("%s: suspend failed state %d, wlock %d\n",
+ __func__, map.pm_state,
+ map.wlock_holders);
+ ret = -EBUSY;
+ } else {
+ pr_debug("%s: done, state %d, wlock %d\n", __func__,
+ map.pm_state,
+ map.wlock_holders);
+ }
+ mutex_lock(&map.pm_lock);
+ } else if (map.pm_state == WCD9XXX_PM_ASLEEP) {
+ pr_warn("%s: system is already suspended, state %d, wlock %dn",
+ __func__, map.pm_state,
+ map.wlock_holders);
+ }
+ mutex_unlock(&map.pm_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL(wcd9xxx_spmi_suspend);
+
+int wcd9xxx_spmi_resume(void)
+{
+ int ret = 0;
+
+ pr_debug("%s: enter\n", __func__);
+ mutex_lock(&map.pm_lock);
+ if (map.pm_state == WCD9XXX_PM_ASLEEP) {
+ pr_debug("%s: resuming system, state %d, wlock %d\n", __func__,
+ map.pm_state,
+ map.wlock_holders);
+ map.pm_state = WCD9XXX_PM_SLEEPABLE;
+ } else {
+ pr_warn("%s: system is already awake, state %d wlock %d\n",
+ __func__, map.pm_state,
+ map.wlock_holders);
+ }
+ mutex_unlock(&map.pm_lock);
+ wake_up_all(&map.pm_wq);
+
+ return ret;
+}
+EXPORT_SYMBOL(wcd9xxx_spmi_resume);
+
+bool wcd9xxx_spmi_lock_sleep(void)
+{
+ /*
+ * wcd9xxx_spmi_{lock/unlock}_sleep will be called by
+ * wcd9xxx_spmi_irq_thread
+ * and its subroutines only motly.
+ * but btn0_lpress_fn is not wcd9xxx_spmi_irq_thread's subroutine and
+ * It can race with wcd9xxx_spmi_irq_thread.
+ * So need to embrace wlock_holders with mutex.
+ */
+ mutex_lock(&map.pm_lock);
+ if (map.wlock_holders++ == 0) {
+ pr_debug("%s: holding wake lock\n", __func__);
+ pm_qos_update_request(&map.pm_qos_req,
+ msm_cpuidle_get_deep_idle_latency());
+ pm_stay_awake(&map.spmi[0]->dev);
+ }
+ mutex_unlock(&map.pm_lock);
+ pr_debug("%s: wake lock counter %d\n", __func__,
+ map.wlock_holders);
+ pr_debug("%s: map.pm_state = %d\n", __func__, map.pm_state);
+
+ if (!wait_event_timeout(map.pm_wq,
+ ((wcd9xxx_spmi_pm_cmpxchg(
+ WCD9XXX_PM_SLEEPABLE,
+ WCD9XXX_PM_AWAKE)) ==
+ WCD9XXX_PM_SLEEPABLE ||
+ (wcd9xxx_spmi_pm_cmpxchg(
+ WCD9XXX_PM_SLEEPABLE,
+ WCD9XXX_PM_AWAKE) ==
+ WCD9XXX_PM_AWAKE)),
+ msecs_to_jiffies(
+ WCD9XXX_SYSTEM_RESUME_TIMEOUT_MS))) {
+ pr_warn("%s: system didn't resume within %dms, s %d, w %d\n",
+ __func__,
+ WCD9XXX_SYSTEM_RESUME_TIMEOUT_MS, map.pm_state,
+ map.wlock_holders);
+ wcd9xxx_spmi_unlock_sleep();
+ return false;
+ }
+ wake_up_all(&map.pm_wq);
+ pr_debug("%s: leaving pm_state = %d\n", __func__, map.pm_state);
+ return true;
+}
+EXPORT_SYMBOL(wcd9xxx_spmi_lock_sleep);
+
+void wcd9xxx_spmi_unlock_sleep(void)
+{
+ mutex_lock(&map.pm_lock);
+ if (--map.wlock_holders == 0) {
+ pr_debug("%s: releasing wake lock pm_state %d -> %d\n",
+ __func__, map.pm_state, WCD9XXX_PM_SLEEPABLE);
+ /*
+ * if wcd9xxx_spmi_lock_sleep failed, pm_state would be still
+ * WCD9XXX_PM_ASLEEP, don't overwrite
+ */
+ if (likely(map.pm_state == WCD9XXX_PM_AWAKE))
+ map.pm_state = WCD9XXX_PM_SLEEPABLE;
+ pm_qos_update_request(&map.pm_qos_req,
+ PM_QOS_DEFAULT_VALUE);
+ pm_relax(&map.spmi[0]->dev);
+ }
+ mutex_unlock(&map.pm_lock);
+ pr_debug("%s: wake lock counter %d\n", __func__,
+ map.wlock_holders);
+ pr_debug("%s: map.pm_state = %d\n", __func__, map.pm_state);
+ wake_up_all(&map.pm_wq);
+}
+EXPORT_SYMBOL(wcd9xxx_spmi_unlock_sleep);
+
+void wcd9xxx_spmi_set_codec(struct snd_soc_codec *codec)
+{
+ map.codec = codec;
+}
+
+void wcd9xxx_spmi_set_dev(struct platform_device *pdev, int i)
+{
+ if (i < NUM_IRQ_REGS)
+ map.spmi[i] = pdev;
+}
+
+int wcd9xxx_spmi_irq_init(void)
+{
+ int i = 0;
+
+ for (; i < MAX_NUM_IRQS; i++)
+ map.mask[BIT_BYTE(i)] |= BYTE_BIT_MASK(i);
+ mutex_init(&map.pm_lock);
+ map.wlock_holders = 0;
+ map.pm_state = WCD9XXX_PM_SLEEPABLE;
+ init_waitqueue_head(&map.pm_wq);
+ pm_qos_add_request(&map.pm_qos_req,
+ PM_QOS_CPU_DMA_LATENCY,
+ PM_QOS_DEFAULT_VALUE);
+
+ return 0;
+}
+
+MODULE_DESCRIPTION("MSM8x16 SPMI IRQ driver");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/codecs/msm8916-wcd-irq.h b/sound/soc/codecs/msm8916-wcd-irq.h
new file mode 100644
index 000000000000..659e52cc2a5e
--- /dev/null
+++ b/sound/soc/codecs/msm8916-wcd-irq.h
@@ -0,0 +1,34 @@
+/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#ifndef __WCD9XXX_SPMI_IRQ_H__
+#define __WCD9XXX_SPMI_IRQ_H__
+
+#include <sound/soc.h>
+#include <linux/spmi.h>
+#include <linux/platform_device.h>
+#include <linux/irq.h>
+#include <linux/pm_qos.h>
+
+extern void wcd9xxx_spmi_enable_irq(int irq);
+extern void wcd9xxx_spmi_disable_irq(int irq);
+extern int wcd9xxx_spmi_request_irq(int irq, irq_handler_t handler,
+ const char *name, void *priv);
+extern int wcd9xxx_spmi_free_irq(int irq, void *priv);
+extern void wcd9xxx_spmi_set_codec(struct snd_soc_codec *codec);
+extern void wcd9xxx_spmi_set_dev(struct spmi_device *spmi, int i);
+extern int wcd9xxx_spmi_irq_init(void);
+extern int wcd9xxx_spmi_suspend(pm_message_t);
+extern int wcd9xxx_spmi_resume(void);
+bool wcd9xxx_spmi_lock_sleep(void);
+void wcd9xxx_spmi_unlock_sleep(void);
+
+#endif