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 + . +- 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 + . +- 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 + . +- 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 . + +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 #include #include +#include #include #include #include #include #include #include +#include #include #include #include @@ -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, ®, 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, ®, 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, ®, 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, ®, 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, ®, 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, ®, 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, ®, 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, ®, 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, ®, 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, ®, 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 +#include #include #include #include +#include #include #include #include @@ -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; + const char *pin_dev_name; + int num_dev_node; - 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); + 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 #include #include +#include #include #include #include @@ -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 +#include #include #include #include @@ -24,6 +25,7 @@ #include #include #include +#include #include #ifdef CONFIG_WAKELOCK #include @@ -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 +#include #include #include #include @@ -24,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -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,15 +581,10 @@ config LEDS_POWERNV depends on LEDS_CLASS depends on PPC_POWERNV depends on OF - help - This option enables support for the system LEDs present on - PowerNV platforms. Say 'y' to enable this support in kernel. - To compile this driver as a module, choose 'm' here: the module - will be called 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 +594,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 +604,36 @@ 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 option enables support for the system LEDs present on + PowerNV platforms. Say 'y' to enable this support in kernel. + To compile this driver as a module, choose 'm' here: the module + will be called leds-powernv. + +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 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 #include #include +#include #include #include #include #include #include +#include #include #include #include @@ -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, ®, 1); + rc = regmap_update_bits(led->regmap, addr, mask, val); if (rc) - dev_err(&led->spmi_dev->dev, - "Unable to read from addr=%x, rc(%d)\n", addr, rc); + dev_err(&led->pdev->dev, + "Unable to update_bits to 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, ®, 1); - if (rc) - dev_err(&led->spmi_dev->dev, - "Unable to write 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 #include #include +#include #include #include #include #include +#include #include +#include #include #include #include @@ -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 +#include #include #include #include @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -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, ®, 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, ®, 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, ®ulator_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 +#include #include #include #include +#include #include #include #include @@ -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, ®, 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, ®, 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, ®, 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 #include #include +#include #include #include #include #include #include +#include #include #include #include @@ -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, ®, 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 #include #include +#include #include #include #include +#include #include #include #include @@ -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, ®, 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, ®, 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), ®, 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, ®, 1); + rc = regmap_read(pon->regmap, addr, ®); 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), ®, 1); + rc = regmap_read(pon->regmap, QPNP_PON_XVDD_RB_SPARE(pon), ®); 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), ®, 1); + rc = regmap_read(pon->regmap, QPNP_PON_XVDD_RB_SPARE(pon), ®); 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), ®, 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), - ®, 1); + rc = regmap_read(pon->regmap, + QPNP_PON_OFF_REASON(pon), + ®); 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 #include #include +#include +#include #include #include +#include #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 #include #include +#include #include #include #include #include #include +#include #include #include #include @@ -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 #include #include +#include #include #include #include @@ -23,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -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, ®, 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, ®, 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"); + 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; } - 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 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; + if (of_get_available_child_count(pdev->dev.of_node) == 0) { + pr_err("no child nodes\n"); + rc = -ENXIO; + goto of_init_fail; + } + + 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; } - 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; - 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 +#include #include #include #include @@ -23,11 +23,13 @@ #include #include #include +#include #include #include #include #include #include +#include #include #include #include @@ -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,55 +496,24 @@ 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); + addr, to_spmi_device(pdev->dev.parent)->usid, + 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); - return rc; - } - - return 0; -} - /* * Writes a register to the specified by the base and limited by the bit mask * @@ -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, ®, 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, ®, 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; + } + + 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; } - 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; - } - - 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; + } + + 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; } - 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; - } - - 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 #include #include +#include +#include #include #include +#include #include #include @@ -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 #include #include +#include #include #include #include #include +#include #include #include #include @@ -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, ®, 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, ®, 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 #include #include +#include #include #include #include #include #include +#include #include #include #include @@ -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, ®_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 #include #include +#include #include #include #include #include #include +#include #include #include #include @@ -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, ®, 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, - ®, 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, ®, 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, ®, 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, ®, 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->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__); + 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->spmi_base_addr = res->start; + vreg->pdev = pdev; + vreg->bypass_spm = bypass_spm; + + 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 = 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 +#include #include #include #include #include #include #include +#include #include +#include #include -#include #include /* 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; + + + 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 */ - 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; + 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* 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, ®_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, ¬ify_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, ¬ify_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, ¶m); +} +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 #include #include +#include #include #include +#include #include #include #include @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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 +#include +#include +#include +#include + +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