Merge "ASoC: msm: qdsp6v2: Update the routing for aux pcm usecase"
diff --git a/Documentation/devicetree/bindings/arm/msm/cpr-regulator.txt b/Documentation/devicetree/bindings/arm/msm/cpr-regulator.txt
index 04310ec..b489f7a 100644
--- a/Documentation/devicetree/bindings/arm/msm/cpr-regulator.txt
+++ b/Documentation/devicetree/bindings/arm/msm/cpr-regulator.txt
@@ -13,21 +13,17 @@
Required properties:
- compatible: Must be "qcom,cpr-regulator"
- reg: Register addresses for RBCPR, RBCPR clock
- select, PVS eFuse and CPR eFuse
+ select, PVS and CPR eFuse address
- reg-names: Register names. Must be "rbcpr", "rbcpr_clk",
- "pvs_efuse" and "cpr_efuse"
+ "efuse_addr"
- regulator-name: A string used to describe the regulator
- interrupts: Interrupt line from RBCPR to interrupt controller.
- regulator-min-microvolt: Minimum corner value as min constraint, which
should be 1 for SVS corner
- regulator-max-microvolt: Maximum corner value as max constraint, which
should be 4 for SUPER_TURBO or 3 for TURBO
-- qcom,num-efuse-bits: The number of bits used in efuse memory to
- represent total number of PVS bins. It should
- not exceed a maximum of 5 for total number of
- 32 bins.
- qcom,pvs-bin-process: A list of integers whose length is equal to 2 to
- the power of qcom,num-efuse-bits. The location or
+ the power of qcom,pvs-fuse[num-of-bits]. The location or
0-based index of an element in the list corresponds
to the bin number. The value of each integer
corresponds to the PVS process speed of the APC
@@ -54,7 +50,7 @@
- qcom,cpr-timer-cons-down: Consecutive number of timer interval (qcom,cpr-timer-delay)
occurred before issuing DOWN interrupt.
- qcom,cpr-irq-line: Internal interrupt route signal of RBCPR, one of 0, 1 or 2.
-- qcom,cpr-step-quotient: Number of CPR quotient (RO count) per vdd-apc-supply step
+- qcom,cpr-step-quotient: Number of CPR quotient (Ring Oscillator(RO) count) per vdd-apc-supply step
to issue error_steps.
- qcom,cpr-up-threshold: The threshold for CPR to issue interrupt when
error_steps is greater than it when stepping up.
@@ -64,6 +60,62 @@
- qcom,cpr-gcnt-time: The time for gate count in microseconds.
- qcom,cpr-apc-volt-step: The voltage in microvolt per CPR step, such as 5000uV.
+- qcom,pvs-fuse-redun-sel: Array of 4 elements to indicate where to read the bits and what value to
+ compare with in order to decide if the redundant PVS fuse bits would be
+ used instead of the original bits. The 4 elements with index [0..3] are:
+ [0] => the fuse row number of the selector
+ [1] => LSB bit position of the bits
+ [2] => number of bits
+ [3] => the value to indicate redundant selection
+ When the value of the fuse bits specified by first 3 elements equals to
+ the value in 4th element, redundant PVS fuse bits should be selected.
+ Otherwise, the original PVS bits should be selected.
+- qcom,pvs-fuse: Array of three elements to indicate the bits for PVS fuse. The array
+ should have index and value like this:
+ [0] => the PVS fuse row number
+ [1] => LSB bit position of the bits
+ [2] => number of bits
+- qcom,pvs-fuse-redun: Array of three elements to indicate the bits for redundant PVS fuse.
+ The array should have index and value like this:
+ [0] => the redundant PVS fuse row number
+ [1] => LSB bit position of the bits
+ [2] => number of bits
+
+- qcom,cpr-fuse-redun-sel: Array of 4 elements to indicate where to read the bits and what value to
+ compare with in order to decide if the redundant CPR fuse bits would be
+ used instead of the original bits. The 4 elements with index [0..3] are:
+ [0] => the fuse row number of the selector
+ [1] => LSB bit position of the bits
+ [2] => number of bits
+ [3] => the value to indicate redundant selection
+ When the value of the fuse bits specified by first 3 elements equals to
+ the value in 4th element, redundant CPR fuse bits should be selected.
+ Otherwise, the original CPR bits should be selected.
+- qcom,cpr-fuse-row: Row number of CPR fuse
+- qcom,cpr-fuse-bp-cpr-disable: Bit position of the bit to indicate if CPR should be disable
+- qcom,cpr-fuse-bp-scheme: Bit position of the bit to indicate if it's a global/local scheme
+- qcom,cpr-fuse-target-quot: Array of bit positions in fuse for Target Quotient of all corners.
+ It should have index and value like this:
+ [0] => bit position of the LSB bit for SVS target quotient
+ [1] => bit position of the LSB bit for NOMINAL target quotient
+ [2] => bit position of the LSB bit for TURBO target quotient
+- qcom,cpr-fuse-ro-sel: Array of bit positions in fuse for RO select of all corners.
+ It should have index and value like this:
+ [0] => bit position of the LSB bit for SVS RO select bits
+ [1] => bit position of the LSB bit for NOMINAL RO select bits
+ [2] => bit position of the LSB bit for TURBO RO select bits
+- qcom,cpr-fuse-redun-row: Row number of the redundant CPR fuse
+- qcom,cpr-fuse-redun-target-quot: Array of bit positions in fuse for redundant Target Quotient of all corners.
+ It should have index and value like this:
+ [0] => bit position of the LSB bit for redundant SVS target quotient
+ [1] => bit position of the LSB bit for redundant NOMINAL target quotient
+ [2] => bit position of the LSB bit for redundant TURBO target quotient
+- qcom,cpr-fuse-redun-ro-sel: Array of bit positions in eFuse for redundant RO select.
+ It should have index and value like this:
+ [0] => bit position of the LSB bit for redundant SVS RO select bits
+ [1] => bit position of the LSB bit for redundant NOMINAL RO select bits
+ [2] => bit position of the LSB bit for redundant TURBO RO select bits
+
Optional properties:
- vdd-mx-supply: Regulator to supply memory power as dependency
@@ -78,6 +130,10 @@
2 => equal to slow speed corner ceiling
3 => equal to qcom,vdd-mx-vmax
This is required when vdd-mx-supply is present.
+- qcom,cpr-fuse-redun-bp-cpr-disable: Redundant bit position of the bit to indicate if CPR should be disable
+- qcom,cpr-fuse-redun-bp-scheme: Redundant bit position of the bit to indicate if it's a global/local scheme
+ This property is required if cpr-fuse-redun-bp-cpr-disable
+ is present, and vise versa.
- qcom,cpr-enable: Present: CPR enabled by default.
Not Present: CPR disable by default.
@@ -86,13 +142,17 @@
apc_vreg_corner: regulator@f9018000 {
status = "okay";
compatible = "qcom,cpr-regulator";
- reg = <0xf9018000 0x1000>, <0xfc4b80b0 8>, <0xfc4bc450 16>;
- reg-names = "rbcpr", "pvs_efuse", "cpr_efuse";
+ reg = <0xf9018000 0x1000>, <0xfc4b8000 0x1000>;
+ reg-names = "rbcpr", "efuse_addr";
interrupts = <0 15 0>;
regulator-name = "apc_corner";
regulator-min-microvolt = <1>;
regulator-max-microvolt = <3>;
- qcom,num-efuse-bits = <5>;
+
+ qcom,pvs-fuse = <22 6 5>;
+ qcom,pvs-fuse-redun-sel = <22 24 3 2>;
+ qcom,pvs-fuse-redun = <22 27 5>;
+
qcom,pvs-bin-process = <0 0 0 0 0 1 1 1 1 1 2 2 2 2 2 2
2 2 2 2 3 3 3 3 3 3 3 3 0 0 0 0>;
qcom,pvs-corner-ceiling-slow = <1050000 1160000 1275000>;
@@ -115,5 +175,15 @@
qcom,cpr-idle-clocks = <5>;
qcom,cpr-gcnt-time = <1>;
qcom,cpr-apc-volt-step = <5000>;
+
+ qcom,cpr-fuse-row = <138>;
+ qcom,cpr-fuse-bp-cpr-disable = <36>;
+ qcom,cpr-fuse-bp-scheme = <37>;
+ qcom,cpr-fuse-target-quot = <24 12 0>;
+ qcom,cpr-fuse-ro-sel = <54 38 41>;
+ qcom,cpr-fuse-redun-sel = <138 57 1 1>;
+ qcom,cpr-fuse-redun-row = <139>;
+ qcom,cpr-fuse-redun-target-quot = <24 12 0>;
+ qcom,cpr-fuse-redun-ro-sel = <46 36 39>;
};
diff --git a/Documentation/devicetree/bindings/arm/msm/msm_thermal.txt b/Documentation/devicetree/bindings/arm/msm/msm_thermal.txt
index 6ef2b77..d07eba6 100644
--- a/Documentation/devicetree/bindings/arm/msm/msm_thermal.txt
+++ b/Documentation/devicetree/bindings/arm/msm/msm_thermal.txt
@@ -85,19 +85,19 @@
qcom,core-control-mask = <7>;
qcom,pmic-sw-mode-temp = <90>;
qcom,pmic-sw-mode-temp-hysteresis = <80>;
- qcom,pmic-sw-mode-regs = "vdd_dig";
+ qcom,pmic-sw-mode-regs = "vdd-dig";
qcom,vdd-restriction-temp = <5>;
qcom,vdd-restriction-temp-hysteresis = <10>;
- vdd_dig-supply=<&pm8841_s2_floor_corner>
+ vdd-dig-supply=<&pm8841_s2_floor_corner>
qcom,vdd-dig-rstr{
- qcom,vdd-rstr-reg = "vdd_dig";
+ qcom,vdd-rstr-reg = "vdd-dig";
qcom,levels = <5 7 7>; /* Nominal, Super Turbo, Super Turbo */
qcom,min-level = <1>; /* No Request */
};
qcom,vdd-apps-rstr{
- qcom,vdd-rstr-reg = "vdd_apps";
+ qcom,vdd-rstr-reg = "vdd-apps";
qcom,levels = <1881600 1958400 2265600>;
qcom,freq-req;
};
diff --git a/Documentation/devicetree/bindings/fb/mdss-mdp.txt b/Documentation/devicetree/bindings/fb/mdss-mdp.txt
index 514160e..7093fb8 100644
--- a/Documentation/devicetree/bindings/fb/mdss-mdp.txt
+++ b/Documentation/devicetree/bindings/fb/mdss-mdp.txt
@@ -126,6 +126,11 @@
- qcom,mdss-has-wfd-blk: Boolean property to indicate the presence of dedicated
writeback wfd block in MDSS as opposed to writeback
block that is shared between rotator and wfd.
+- qcom,mdss-smp-mb-per-pipe: Maximum number of shared memory pool blocks
+ restricted for a source surface pipe. If this
+ property is not specified, no such restriction
+ would be applied.
+
Optional subnodes:
Child nodes representing the frame buffer virtual devices.
@@ -161,6 +166,7 @@
qcom,mdss-pipe-dma-fetch-id = <10 13>;
qcom,mdss-smp-data = <22 4096>;
qcom,mdss-rot-block-size = <64>;
+ qcom,mdss-smp-mb-per-pipe = <2>;
qcom,mdss-has-bwc;
qcom,mdss-has-decimation;
qcom,mdss-has-wfd-blk;
diff --git a/Documentation/devicetree/bindings/input/misc/bmp180.txt b/Documentation/devicetree/bindings/input/misc/bmp180.txt
new file mode 100644
index 0000000..13e0839
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/misc/bmp180.txt
@@ -0,0 +1,35 @@
+Bosch BMP18x-series altimeter driver
+
+Required properties:
+
+ - compatible : Should be "bosch,bmp180".
+ - reg : i2c slave address of the device.
+ - vdd-supply : Analog power supply needed to power device.
+ - vddio-supply : Digital IO power supply needed for IO and I2C.
+ - bosch,chip-id : Chip id for the bmp18x altimeter sensor.
+ - bosch,oversample : Sensor default oversampling value.
+ Default oversampling value to be used at startup.
+ Value range is 0-3 with rising sensitivity.
+ - bosch,period : Temperature measurement period (milliseconds).
+ Set to zero if unsure.
+
+Optional properties:
+
+ - bosch,sw-oversample : Boolean to enable software oversampling if
+ this property is defined. Only take effect when
+ default_oversampling is 3.
+
+Example:
+ i2c@f9925000 {
+ bmp180@77 {
+ status = "okay";
+ reg = <0x77>;
+ compatible = "bosch,bmp180";
+ vdd-supply = <&pm8110_l19>;
+ vddio-supply = <&pm8110_l14>;
+ bosch,chip-id = <0x55>;
+ bosch,oversample = <3>;
+ bosch,period = <1000>;
+ bosch,sw-oversample;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/input/misc/mma8x5x.txt b/Documentation/devicetree/bindings/input/misc/mma8x5x.txt
new file mode 100644
index 0000000..854939c
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/misc/mma8x5x.txt
@@ -0,0 +1,39 @@
+Freescale MMA8x5x 3-Axis Orientation/Motion Detection Sensor series
+(MMA8451/MMA8452/MMA8453/MMA8652/MMA8653)
+
+The Freescale 3-Axis Orientation/Motion Detection Sensor is
+connected to host processor via i2c.
+The sensor can be polling for acceleration data or configure to
+generates interrupts when a motion is detected.
+
+Required properties:
+
+ - compatible : should be "fsl,mma8x5x"
+ - reg : i2c slave address of the device
+ - vdd-supply : power supply needed to power up the device.
+ - vio-supply : power supply needed for device IO and to pullup i2c bus.
+ - fsl,sensors-position : select from 0 to 7 depends on how the sensor is
+ mounting on the board, this will decide how the 3-axis reading
+ of data will be translated to X/Y/Z axis of acceleration data.
+
+Optional properties:
+ Sensor can work on polling mode or interrupt mode, following interrupt
+ is required if the sensor need to work on interrupt mode.
+ - interrupt-parent : parent of interrupt.
+ - interrupts : sensor signal interrupt to indicate new data ready or
+ a motion is detected.
+ - fsl,irq-gpio : First irq gpio which is to provide interrupts to host, same
+ as "interrupts" node. It will also contain active low or active
+ high information.
+
+Example:
+ fsl@1c {
+ compatible = "fsl,mma8x5x";
+ reg = <0x1c>;
+ interrupt-parent = <&msmgpio>;
+ interrupts = <81 0x2>;
+ vdd-supply = <&pm8110_l19>;
+ vio-supply = <&pm8110_l14>;
+ fsl,sensors-position = <5>;
+ fsl,irq-gpio = <&msmgpio 0x81 0x02>;
+ };
\ No newline at end of file
diff --git a/Documentation/devicetree/bindings/input/misc/mpu3050.txt b/Documentation/devicetree/bindings/input/misc/mpu3050.txt
new file mode 100644
index 0000000..edbe147
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/misc/mpu3050.txt
@@ -0,0 +1,31 @@
+InvenSense MPU30X0-series gyrometer driver
+
+Required properties:
+
+ - compatible : Should be "invn,mpu3050".
+ - reg : i2c slave address of the device.
+ - interrupt-parent : Parent of interrupt.
+ - interrupts : Gyrometer sample interrupt to indicate new data ready.
+ - vdd-supply : Analog power supply needed to power device.
+ - vlogic-supply : Digital IO power supply needed for IO and I2C.
+ - invn,gpio-int : GPIO used for interrupt.
+ - invn,gpio-en : GPIO used for power enabling.
+ - invn,poll-interval : Initial data polling interval in milliseconds.
+
+Example:
+ i2c@f9925000 {
+ mpu3050@68 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "okay";
+ reg = <0x68>;
+ compatible = "invn,mpu3050";
+ interrupt-parent = <&msmgpio>;
+ interrupts = <84 0x2>;
+ vlogic-supply = <&pm8110_l14>;
+ vdd-supply = <&pm8110_l19>;
+ invn,gpio-int = <&msmgpio 84 0x2>;
+ invn,gpio-en = <&pm8110_gpios 2 0x2>;
+ invn,poll-interval = <200>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/input/touchscreen/atmel-mxt-ts.txt b/Documentation/devicetree/bindings/input/touchscreen/atmel-mxt-ts.txt
index 6fe88a9..4c6ae93 100644
--- a/Documentation/devicetree/bindings/input/touchscreen/atmel-mxt-ts.txt
+++ b/Documentation/devicetree/bindings/input/touchscreen/atmel-mxt-ts.txt
@@ -35,6 +35,8 @@
needed during wakeup.
- atmel,no-force-update : flag that signifies whether force configuration
update is applicable or not
+ - atmel,no-lpm-support : flag that signifies whether low power mode is
+ supported or not on this platform
Example:
i2c@f9966000 {
diff --git a/Documentation/devicetree/bindings/leds/leds-qpnp.txt b/Documentation/devicetree/bindings/leds/leds-qpnp.txt
index ff95d43..e9c5061 100644
--- a/Documentation/devicetree/bindings/leds/leds-qpnp.txt
+++ b/Documentation/devicetree/bindings/leds/leds-qpnp.txt
@@ -81,7 +81,9 @@
- qcom,source-sel: select power source, default 1 (enabled)
- qcom,mode-ctrl: select operation mode, default 0x60 = Mode Sink
- qcom,mode: mode the led should operate in, options "pwm", "lpg" and "manual"
+- qcom,vin-ctrl: select input source, supported values are 0 to 3
- qcom,use-blink: Use blink sysfs entry for switching into lpg mode. For optimal use, set default mode to pwm. All required lpg parameters must be supplied.
+- qcom,min-brightness - Lowest possible brightness supported on this LED other than 0.
Required properties for PWM mode only:
- qcom,pwm-channel: pwm channel the led will operate on
@@ -136,6 +138,8 @@
qcom,id = <6>;
qcom,source-sel = <1>;
qcom,mode-ctrl = <0x10>;
+ qcom,vin-ctrl = <0x03>;
+ qcom,min-brightness = <20>;
};
};
diff --git a/Documentation/devicetree/bindings/media/video/msm-cci.txt b/Documentation/devicetree/bindings/media/video/msm-cci.txt
index 583fbfa..8e988be 100644
--- a/Documentation/devicetree/bindings/media/video/msm-cci.txt
+++ b/Documentation/devicetree/bindings/media/video/msm-cci.txt
@@ -95,6 +95,11 @@
#gpio-cells specifying specific gpio (controller specific)
- qcom,gpio-reset : should contain index to gpio used by sensors reset_n
- qcom,gpio-standby : should contain index to gpio used by sensors standby_n
+- qcom,gpio-vio : should contain index to gpio used by sensors io vreg enable
+- qcom,gpio-vana : should contain index to gpio used by sensors analog vreg enable
+- qcom,gpio-vdig : should contain index to gpio used by sensors digital vreg enable
+- qcom,gpio-vaf : should contain index to gpio used by sensors af vreg enable
+- qcom,gpio-af-pwdm : should contain index to gpio used by sensors af pwdm_n
- qcom,gpio-req-tbl-num : should contain index to gpios specific to this sensor
- qcom,gpio-req-tbl-flags : should contain direction of gpios present in
qcom,gpio-req-tbl-num property (in the same order)
diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt b/Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
new file mode 100644
index 0000000..2d730e3
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
@@ -0,0 +1,186 @@
+== Introduction ==
+
+Hardware modules that control pin multiplexing or configuration parameters
+such as pull-up/down, tri-state, drive-strength etc are designated as pin
+controllers. Each pin controller must be represented as a node in device tree,
+just like any other hardware module.
+
+Hardware modules whose signals are affected by pin configuration are
+designated client devices. Again, each client device must be represented as a
+node in device tree, just like any other hardware module.
+
+For a client device to operate correctly, certain pin controllers must
+set up certain specific pin configurations. Some client devices need a
+single static pin configuration, e.g. set up during initialization. Others
+need to reconfigure pins at run-time, for example to tri-state pins when the
+device is inactive. Hence, each client device can define a set of named
+states. The number and names of those states is defined by the client device's
+own binding.
+
+The common pinctrl bindings defined in this file provide an infrastructure
+for client device device tree nodes to map those state names to the pin
+configuration used by those states.
+
+Note that pin controllers themselves may also be client devices of themselves.
+For example, a pin controller may set up its own "active" state when the
+driver loads. This would allow representing a board's static pin configuration
+in a single place, rather than splitting it across multiple client device
+nodes. The decision to do this or not somewhat rests with the author of
+individual board device tree files, and any requirements imposed by the
+bindings for the individual client devices in use by that board, i.e. whether
+they require certain specific named states for dynamic pin configuration.
+
+== Pinctrl client devices ==
+
+For each client device individually, every pin state is assigned an integer
+ID. These numbers start at 0, and are contiguous. For each state ID, a unique
+property exists to define the pin configuration. Each state may also be
+assigned a name. When names are used, another property exists to map from
+those names to the integer IDs.
+
+Each client device's own binding determines the set of states the must be
+defined in its device tree node, and whether to define the set of state
+IDs that must be provided, or whether to define the set of state names that
+must be provided.
+
+Required properties:
+pinctrl-0: List of phandles, each pointing at a pin configuration
+ node. These referenced pin configuration nodes must be child
+ nodes of the pin controller that they configure. Multiple
+ entries may exist in this list so that multiple pin
+ controllers may be configured, or so that a state may be built
+ from multiple nodes for a single pin controller, each
+ contributing part of the overall configuration. See the next
+ section of this document for details of the format of these
+ pin configuration nodes.
+
+ In some cases, it may be useful to define a state, but for it
+ to be empty. This may be required when a common IP block is
+ used in an SoC either without a pin controller, or where the
+ pin controller does not affect the HW module in question. If
+ the binding for that IP block requires certain pin states to
+ exist, they must still be defined, but may be left empty.
+
+Optional properties:
+pinctrl-1: List of phandles, each pointing at a pin configuration
+ node within a pin controller.
+...
+pinctrl-n: List of phandles, each pointing at a pin configuration
+ node within a pin controller.
+pinctrl-names: The list of names to assign states. List entry 0 defines the
+ name for integer state ID 0, list entry 1 for state ID 1, and
+ so on.
+
+For example:
+
+ /* For a client device requiring named states */
+ device {
+ pinctrl-names = "active", "idle";
+ pinctrl-0 = <&state_0_node_a>;
+ pinctrl-1 = <&state_1_node_a &state_1_node_b>;
+ };
+
+ /* For the same device if using state IDs */
+ device {
+ pinctrl-0 = <&state_0_node_a>;
+ pinctrl-1 = <&state_1_node_a &state_1_node_b>;
+ };
+
+ /*
+ * For an IP block whose binding supports pin configuration,
+ * but in use on an SoC that doesn't have any pin control hardware
+ */
+ device {
+ pinctrl-names = "active", "idle";
+ pinctrl-0 = <>;
+ pinctrl-1 = <>;
+ };
+
+== Pin controller devices ==
+
+Pin controller devices should contain the pin configuration nodes that client
+devices reference.
+
+For example:
+
+ pincontroller {
+ ... /* Standard DT properties for the device itself elided */
+
+ state_0_node_a {
+ ...
+ };
+ state_1_node_a {
+ ...
+ };
+ state_1_node_b {
+ ...
+ };
+ }
+
+The contents of each of those pin configuration child nodes is defined
+entirely by the binding for the individual pin controller device. There
+exists no common standard for this content.
+
+The pin configuration nodes need not be direct children of the pin controller
+device; they may be grandchildren, for example. Whether this is legal, and
+whether there is any interaction between the child and intermediate parent
+nodes, is again defined entirely by the binding for the individual pin
+controller device.
+
+== Using generic pinconfig options ==
+
+Generic pinconfig parameters can be used by defining a separate node containing
+the applicable parameters (and optional values), like:
+
+pcfg_pull_up: pcfg_pull_up {
+ bias-pull-up;
+ drive-strength = <20>;
+};
+
+This node should then be referenced in the appropriate pinctrl node as a phandle
+and parsed in the driver using the pinconf_generic_parse_dt_config function.
+
+Supported configuration parameters are:
+
+bias-disable - disable any pin bias
+bias-high-impedance - high impedance mode ("third-state", "floating")
+bias-bus-hold - latch weakly
+bias-pull-up - pull up the pin
+bias-pull-down - pull down the pin
+bias-pull-pin-default - use pin-default pull state
+drive-push-pull - drive actively high and low
+drive-open-drain - drive with open drain
+drive-open-source - drive with open source
+drive-strength - sink or source at most X mA
+input-schmitt-enable - enable schmitt-trigger mode
+input-schmitt-disable - disable schmitt-trigger mode
+input-schmitt - run in schmitt-trigger mode with hysteresis X
+input-debounce - debounce mode with debound time X
+power-source - select power source X
+slew-rate - use slew-rate X
+low-power-enable - enable low power mode
+low-power-disable - disable low power mode
+output-low - set the pin to output mode with low level
+output-high - set the pin to output mode with high level
+
+Arguments for parameters:
+
+- bias-pull-up, -down and -pin-default take as optional argument 0 to disable
+ the pull, on hardware supporting it the pull strength in Ohm. bias-disable
+ will also disable any active pull.
+
+- drive-strength takes as argument the target strength in mA.
+
+- input-schmitt takes as argument the adjustable hysteresis in a
+ driver-specific format
+
+- input-debounce takes the debounce time as argument or 0 to disable debouncing
+
+- power-source argument is the custom value describing the source to select
+
+- slew-rate takes as argument the target rate in a driver-specific format
+
+All parameters not listed here, do not take an argument.
+
+More in-depth documentation on these parameters can be found in
+<include/linux/pinctrl/pinconfig-generic.h>
diff --git a/Documentation/devicetree/bindings/power/qpnp-bms.txt b/Documentation/devicetree/bindings/power/qpnp-bms.txt
index 3cac311..3e7a578 100644
--- a/Documentation/devicetree/bindings/power/qpnp-bms.txt
+++ b/Documentation/devicetree/bindings/power/qpnp-bms.txt
@@ -77,6 +77,10 @@
number of the FCC measurement cycles required to
generate an FCC update. This is applicable only
if the FCC learning is enabled.
+- qcom,fcc-resolution: An integer which defines the fcc resolution used
+ for storing the FCC(mAh) in the 8-bit BMS register.
+ For example - A value of 10 indicates:
+ FCC value (in mAh) = (8-bit register value) * 10.
Parent node optional properties:
- qcom,ignore-shutdown-soc: A boolean that controls whether BMS will
diff --git a/Documentation/devicetree/bindings/power/qpnp-charger.txt b/Documentation/devicetree/bindings/power/qpnp-charger.txt
index 66949af..e3c3555 100644
--- a/Documentation/devicetree/bindings/power/qpnp-charger.txt
+++ b/Documentation/devicetree/bindings/power/qpnp-charger.txt
@@ -78,6 +78,8 @@
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.
Sub node required structure:
- A qcom,chg node must be a child of an SPMI node that has specified
diff --git a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
index c799ffb..b618597 100644
--- a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
+++ b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
@@ -661,7 +661,9 @@
prim-gpio-tert : Primary AUXPCM shares GPIOs with Tertiary MI2S
Optional Properties:
-- qcom,us-euro-gpios : GPIO on which gnd/mic swap signal is coming.
+- qcom,cdc-us-euro-gpios : GPIO on which gnd/mic swap signal is coming.
+- qcom,cdc-lineout-spkr-gpios : GPIO which controls external PAs to enable Lineout1/2 speaker
+- qcom,cdc-vdd-spkr-gpios : GPIO which controls PA for VDD speaker
Example:
@@ -675,4 +677,6 @@
qcom,prim-auxpcm-gpio-dout = <&msmgpio 66 0>;
qcom,prim-auxpcm-gpio-set = "prim-gpio-prim";
qcom,cdc-us-euro-gpios = <&msmgpio 69 0>;
+ qcom,cdc-lineout-spkr-gpios = <&pm8226_gpios 2 0>;
+ qcom,cdc-vdd-spkr-gpios = <&pm8226_gpios 3 0>;
};
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index 0ebbe63..a3a3807 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -8,6 +8,7 @@
apm Applied Micro Circuits Corporation (APM)
arm ARM Ltd.
atmel Atmel Corporation
+bosch Bosch Sensortec GmbH
cavium Cavium, Inc.
chrp Common Hardware Reference Platform
cortina Cortina Systems, Inc.
@@ -23,6 +24,7 @@
ibm International Business Machines (IBM)
idt Integrated Device Technologies, Inc.
intercontrol Inter Control Group
+invn InvenSense Inc.
linux Linux-specific binding
kionix Kionix Inc.
marvell Marvell Technology Group Ltd.
diff --git a/arch/arm/boot/dts/apq8026-v1.dtsi b/arch/arm/boot/dts/apq8026-v1.dtsi
index f15a96f..7fbfcb5 100644
--- a/arch/arm/boot/dts/apq8026-v1.dtsi
+++ b/arch/arm/boot/dts/apq8026-v1.dtsi
@@ -22,3 +22,8 @@
model = "Qualcomm APQ 8026";
compatible = "qcom,apq8026";
};
+
+&tsens {
+ qcom,sensors = <4>;
+ qcom,slope = <2901 2846 3038 2955>;
+};
diff --git a/arch/arm/boot/dts/apq8026-v2.dtsi b/arch/arm/boot/dts/apq8026-v2.dtsi
index d87b500..4c0d3ce 100644
--- a/arch/arm/boot/dts/apq8026-v2.dtsi
+++ b/arch/arm/boot/dts/apq8026-v2.dtsi
@@ -22,3 +22,8 @@
model = "Qualcomm APQ 8026";
compatible = "qcom,apq8026";
};
+
+&tsens {
+ qcom,sensors = <6>;
+ qcom,slope = <2901 2846 3038 2955 2901 2846>;
+};
diff --git a/arch/arm/boot/dts/apq8074-dragonboard.dtsi b/arch/arm/boot/dts/apq8074-dragonboard.dtsi
index 21e92ab..53e9b3b 100644
--- a/arch/arm/boot/dts/apq8074-dragonboard.dtsi
+++ b/arch/arm/boot/dts/apq8074-dragonboard.dtsi
@@ -191,10 +191,10 @@
"MIC BIAS2 External", "ANCRight Headset Mic",
"AMIC4", "MIC BIAS2 External",
"MIC BIAS2 External", "ANCLeft Headset Mic",
- "AMIC5", "MIC BIAS1 External",
- "MIC BIAS1 External", "Analog Mic6",
- "AMIC6", "MIC BIAS1 External",
- "MIC BIAS1 External", "Analog Mic7",
+ "AMIC5", "MIC BIAS4 External",
+ "MIC BIAS4 External", "Analog Mic6",
+ "AMIC6", "MIC BIAS3 External",
+ "MIC BIAS3 External", "Analog Mic7",
"DMIC1", "MIC BIAS3 External",
"MIC BIAS3 External", "Digital Mic1",
"DMIC2", "MIC BIAS3 External",
@@ -208,11 +208,14 @@
"DMIC6", "MIC BIAS4 External",
"MIC BIAS4 External", "Digital Mic6";
+
qcom,prim-auxpcm-gpio-clk = <&msmgpio 74 0>;
qcom,prim-auxpcm-gpio-sync = <&msmgpio 75 0>;
qcom,prim-auxpcm-gpio-din = <&msmgpio 76 0>;
qcom,prim-auxpcm-gpio-dout = <&msmgpio 77 0>;
qcom,prim-auxpcm-gpio-set = "prim-gpio-tert";
+
+ qcom,cdc-micbias2-headset-only;
};
qcom,pronto@fb21b000 {
@@ -287,6 +290,7 @@
};
&usb3 {
+ interrupts = <0>; /* remove pmic_id_irq; used by &usb_otg */
qcom,charging-disabled;
vbus_dwc3-supply = <0>;
dwc3@f9200000 {
@@ -296,8 +300,17 @@
&slim_msm {
taiko_codec {
+ qcom,cdc-micbias1-ext-cap;
qcom,cdc-micbias2-ext-cap;
qcom,cdc-micbias3-ext-cap;
+ qcom,cdc-micbias4-ext-cap;
+
+ /* If boot isn't available, vph_pwr_vreg can be used instead */
+ cdc-vdd-spkdrv-supply = <&pm8941_boost>;
+ qcom,cdc-vdd-spkdrv-voltage = <5000000 5000000>;
+ qcom,cdc-vdd-spkdrv-current = <1250000>;
+
+ qcom,cdc-on-demand-supplies = "cdc-vdd-spkdrv";
};
};
@@ -542,34 +555,32 @@
status = "disabled";
};
-&spmi_bus {
- qcom,pm8941@1 {
- qcom,leds@d000 {
- qcom,rgb_2 {
- status = "ok";
- qcom,default-state = "on";
- qcom,turn-off-delay-ms = <1000>;
- };
+&pm8941_lsid1 {
+ qcom,leds@d000 {
+ qcom,rgb_2 {
+ status = "ok";
+ qcom,default-state = "on";
+ qcom,turn-off-delay-ms = <1000>;
};
+ };
- qcom,leds@d800 {
- status = "okay";
- qcom,wled_0 {
- label = "wled";
- linux,name = "wled:backlight";
- linux,default-trigger = "bkl-trigger";
- qcom,cs-out-en;
- qcom,op-fdbck = <1>;
- qcom,default-state = "on";
- qcom,max-current = <20>;
- qcom,ctrl-delay-us = <0>;
- qcom,boost-curr-lim = <3>;
- qcom,cp-sel = <0>;
- qcom,switch-freq = <2>;
- qcom,ovp-val = <1>;
- qcom,num-strings = <1>;
- qcom,id = <0>;
- };
+ qcom,leds@d800 {
+ status = "okay";
+ qcom,wled_0 {
+ label = "wled";
+ linux,name = "wled:backlight";
+ linux,default-trigger = "bkl-trigger";
+ qcom,cs-out-en;
+ qcom,op-fdbck = <1>;
+ qcom,default-state = "on";
+ qcom,max-current = <20>;
+ qcom,ctrl-delay-us = <0>;
+ qcom,boost-curr-lim = <3>;
+ qcom,cp-sel = <0>;
+ qcom,switch-freq = <2>;
+ qcom,ovp-val = <1>;
+ qcom,num-strings = <1>;
+ qcom,id = <0>;
};
};
};
diff --git a/arch/arm/boot/dts/apq8074-v2-cdp.dts b/arch/arm/boot/dts/apq8074-v2-cdp.dts
new file mode 100644
index 0000000..1dc0912
--- /dev/null
+++ b/arch/arm/boot/dts/apq8074-v2-cdp.dts
@@ -0,0 +1,34 @@
+/* Copyright (c) 2013, 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.
+ */
+
+/dts-v1/;
+
+/include/ "apq8074-v2.dtsi"
+/include/ "msm8974-cdp.dtsi"
+
+/ {
+ model = "Qualcomm APQ 8074v2 CDP";
+ compatible = "qcom,apq8074-cdp", "qcom,apq8074", "qcom,cdp";
+ qcom,msm-id = <184 1 0x20000>;
+};
+
+&usb3 {
+ interrupt-parent = <&usb3>;
+ interrupts = <0 1>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0x0 0xffffffff>;
+ interrupt-map = <0x0 0 &intc 0 133 0
+ 0x0 1 &spmi_bus 0x0 0x0 0x9 0x0>;
+ interrupt-names = "hs_phy_irq", "pmic_id_irq";
+
+ qcom,misc-ref = <&pm8941_misc>;
+};
diff --git a/arch/arm/boot/dts/apq8084-gpu.dtsi b/arch/arm/boot/dts/apq8084-gpu.dtsi
new file mode 100644
index 0000000..8570b4f
--- /dev/null
+++ b/arch/arm/boot/dts/apq8084-gpu.dtsi
@@ -0,0 +1,95 @@
+/* Copyright (c) 2013, 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.
+ */
+
+&soc {
+ msm_gpu: qcom,kgsl-3d0@fdb00000 {
+ label = "kgsl-3d0";
+ compatible = "qcom,kgsl-3d0", "qcom,kgsl-3d";
+ reg = <0xfdb00000 0x10000
+ 0xfdb20000 0x20000>;
+ reg-names = "kgsl_3d0_reg_memory" , "kgsl_3d0_shader_memory";
+ interrupts = <0 33 0>;
+ interrupt-names = "kgsl_3d0_irq";
+ qcom,id = <0>;
+
+ qcom,chipid = <0x04020000>;
+
+ qcom,initial-pwrlevel = <2>;
+
+ qcom,idle-timeout = <8>; //<HZ/12>
+ qcom,strtstp-sleepwake;
+ qcom,clk-map = <0x00000016>; //KGSL_CLK_CORE | KGSL_CLK_IFACE | KGSL_CLK_MEM_IFACE
+
+ /* Bus Scale Settings */
+ qcom,msm-bus,name = "grp3d";
+ qcom,msm-bus,num-cases = <5>;
+ qcom,msm-bus,num-paths = <2>;
+ qcom,msm-bus,vectors-KBps =
+ <26 512 0 0>, <89 604 0 0>,
+ <26 512 0 3144000>, <89 604 0 3200000>,
+ <26 512 0 4800000>, <89 604 0 4800000>,
+ <26 512 0 6400000>, <89 604 0 6400000>,
+ <26 512 0 8528000>, <89 604 0 9600000>;
+
+ /* GDSC oxili regulators */
+ vddcx-supply = <&gdsc_oxili_cx>;
+ vdd-supply = <&gdsc_oxili_gx>;
+
+ /* IOMMU Data */
+ iommu = <&kgsl_iommu>;
+
+ /* Power levels */
+ qcom,gpu-pwrlevels {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ compatible = "qcom,gpu-pwrlevels";
+
+ qcom,gpu-pwrlevel@0 {
+ reg = <0>;
+ qcom,gpu-freq = <600000000>;
+ qcom,bus-freq = <4>;
+ qcom,io-fraction = <33>;
+ };
+
+ qcom,gpu-pwrlevel@1 {
+ reg = <1>;
+ qcom,gpu-freq = <400000000>;
+ qcom,bus-freq = <3>;
+ qcom,io-fraction = <66>;
+ };
+
+ qcom,gpu-pwrlevel@2 {
+ reg = <2>;
+ qcom,gpu-freq = <300000000>;
+ qcom,bus-freq = <2>;
+ qcom,io-fraction = <100>;
+ };
+
+ qcom,gpu-pwrlevel@3 {
+ reg = <3>;
+ qcom,gpu-freq = <200000000>;
+ qcom,bus-freq = <1>;
+ qcom,io-fraction = <100>;
+ };
+
+ qcom,gpu-pwrlevel@4 {
+ reg = <4>;
+ qcom,gpu-freq = <27000000>;
+ qcom,bus-freq = <0>;
+ qcom,io-fraction = <0>;
+ };
+ };
+
+ };
+};
+
diff --git a/arch/arm/boot/dts/apq8084.dtsi b/arch/arm/boot/dts/apq8084.dtsi
index 80fedee..3014813 100644
--- a/arch/arm/boot/dts/apq8084.dtsi
+++ b/arch/arm/boot/dts/apq8084.dtsi
@@ -25,6 +25,7 @@
/include/ "apq8084-smp2p.dtsi"
/include/ "apq8084-coresight.dtsi"
/include/ "apq8084-mdss.dtsi"
+/include/ "apq8084-gpu.dtsi"
&soc {
#address-cells = <1>;
@@ -197,7 +198,7 @@
tsens: tsens@fc4a8000 {
compatible = "qcom,msm-tsens";
reg = <0xfc4a8000 0x2000>,
- <0xfc4b8000 0x1000>;
+ <0xfc4bc000 0x1000>;
reg-names = "tsens_physical", "tsens_eeprom_physical";
interrupts = <0 184 0>;
qcom,sensors = <11>;
@@ -244,7 +245,7 @@
memory_hole: qcom,msm-mem-hole {
compatible = "qcom,msm-mem-hole";
- qcom,memblock-remove = <0x0dc00000 0x2000000>; /* Address and Size of Hole */
+ qcom,memblock-remove = <0x0d200000 0x02c00000>; /* Address and Size of Hole */
};
qcom,ipc-spinlock@fd484000 {
@@ -305,6 +306,62 @@
};
};
+&gdsc_venus {
+ status = "ok";
+};
+
+&gdsc_venus_core0 {
+ status = "ok";
+};
+
+&gdsc_venus_core1 {
+ status = "ok";
+};
+
+&gdsc_vpu {
+ status = "ok";
+};
+
+&gdsc_mdss {
+ status = "ok";
+};
+
+&gdsc_jpeg {
+ status = "ok";
+};
+
+&gdsc_vfe {
+ status = "ok";
+};
+
+&gdsc_oxili_gx {
+ status = "ok";
+};
+
+&gdsc_oxili_cx {
+ status = "ok";
+};
+
+&gdsc_usb_hsic {
+ status = "ok";
+};
+
+&gdsc_pcie_0{
+ status = "ok";
+};
+
+&gdsc_pcie_1{
+ status = "ok";
+};
+
+&gdsc_usb30{
+ status = "ok";
+};
+
+&gdsc_usb30_sec{
+ status = "ok";
+};
+
/include/ "msm-pma8084.dtsi"
/include/ "apq8084-regulator.dtsi"
diff --git a/arch/arm/boot/dts/dsi-v2-panel-hx8379a-wvga-video.dtsi b/arch/arm/boot/dts/dsi-v2-panel-hx8379a-wvga-video.dtsi
index b9ed050..befc29c 100644
--- a/arch/arm/boot/dts/dsi-v2-panel-hx8379a-wvga-video.dtsi
+++ b/arch/arm/boot/dts/dsi-v2-panel-hx8379a-wvga-video.dtsi
@@ -40,7 +40,7 @@
qcom,mdss-pan-dsi-mdp-tr = <0x0>;/*todo*/
qcom,mdss-pan-dsi-dma-tr = <0x04>;
qcom,mdss-pan-dsi-frame-rate = <60>;
- qcom,panel-phy-regulatorSettings =[09 08 05 00 20 03];
+ qcom,panel-phy-regulatorSettings =[02 08 05 00 20 03];
qcom,panel-phy-timingSettings = [5D 12 0C 00 33 39
10 16 15 03 04 00];
qcom,panel-phy-strengthCtrl = [ff 06];
diff --git a/arch/arm/boot/dts/dsi-v2-panel-truly-wvga-cmd.dtsi b/arch/arm/boot/dts/dsi-v2-panel-truly-wvga-cmd.dtsi
new file mode 100644
index 0000000..f57a7bd
--- /dev/null
+++ b/arch/arm/boot/dts/dsi-v2-panel-truly-wvga-cmd.dtsi
@@ -0,0 +1,124 @@
+/* Copyright (c) 2013, 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.
+ */
+
+/ {
+ qcom,dsi_v2_truly_wvga_video {
+ compatible = "qcom,dsi-panel-v2";
+ label = "Truly WVGA command mode dsi panel";
+ qcom,dsi-ctrl-phandle = <&mdss_dsi0>;
+ qcom,rst-gpio = <&msmgpio 41 0>;
+ qcom,mode-selection-gpio = <&msmgpio 7 0>;
+ qcom,te-gpio = <&msmgpio 12 0>;
+ vdda-supply = <&pm8110_l19>;
+ vddio-supply=<&pm8110_l14>;
+ qcom,mdss-pan-res = <480 800>;
+ qcom,mdss-pan-bpp = <24>;
+ qcom,mdss-pan-dest = "display_1";
+ qcom,mdss-pan-porch-values = <40 8 160 10 2 12>;
+ qcom,mdss-pan-underflow-clr = <0xff>;
+ qcom,mdss-pan-bl-levels = <1 255>;
+ qcom,mdss-pan-bl-ctrl = "bl_ctrl_wled";
+ qcom,mdss-pan-dsi-mode = <1>;
+ qcom,mdss-pan-dsi-h-pulse-mode = <0>;
+ qcom,mdss-pan-dsi-h-power-stop = <0 0 0>;
+ qcom,mdss-pan-dsi-bllp-power-stop = <1 1>;
+ qcom,mdss-pan-dsi-traffic-mode = <1>;
+ qcom,mdss-pan-dsi-dst-format = <8>;
+ qcom,mdss-pan-insert-dcs-cmd = <1>;
+ qcom,mdss-pan-wr-mem-continue = <0x3c>;
+ qcom,mdss-pan-wr-mem-start = <0x2c>;
+ qcom,mdss-pan-dsi-vc = <0>;
+ qcom,mdss-pan-dsi-rgb-swap = <0>;
+ qcom,mdss-pan-dsi-data-lanes = <1 1 0 0>;
+ qcom,mdss-pan-dsi-dlane-swap = <0>;
+ qcom,mdss-pan-dsi-t-clk = <0x1b 0x04>;
+ qcom,mdss-pan-dsi-stream = <0>;
+ qcom,mdss-pan-dsi-mdp-tr = <0x02>;
+ qcom,mdss-pan-dsi-dma-tr = <0x04>;
+ qcom,mdss-pan-dsi-frame-rate = <60>;
+ qcom,panel-phy-regulatorSettings =[02 08 05 00 20 03];
+ qcom,panel-phy-timingSettings = [5D 12 0C 00 33 38
+ 10 16 1E 03 04 00];
+ qcom,panel-phy-strengthCtrl = [ff 06];
+ qcom,panel-phy-bistCtrl = [03 03 00 00 0f 00];
+ qcom,panel-phy-laneConfig =
+ [80 45 00 00 01 66 /*lane0**/
+ 80 45 00 00 01 66 /*lane1*/
+ 80 45 00 00 01 66 /*lane2*/
+ 80 45 00 00 01 66 /*lane3*/
+ 40 67 00 00 01 88]; /*Clk*/
+
+ qcom,on-cmds-dsi-state = "DSI_LP_MODE";
+ qcom,panel-on-cmds = [
+ 05 01 00 00 00 02
+ 01 00
+ 23 01 00 00 00 02
+ b0 04
+ 29 01 00 00 00 03
+ b3 02 00
+ 23 01 00 00 00 02
+ bd 00
+ 29 01 00 00 00 03
+ c0 18 66
+ 29 01 00 00 00 10
+ c1 23 31 99 21 20 00 30 28 0c 0c
+ 00 00 00 21 01
+ 29 01 00 00 00 07
+ c2 00 06 06 01 03 00
+ 29 01 00 00 00 19
+ c8 04 10 18 20 2e 46 3c 28 1f 18
+ 10 04 04 10 18 20 2e 46 3c 28 1f 18 10 04
+ 29 01 00 00 00 19
+ c9 04 10 18 20 2e 46 3c 28 1f 18
+ 10 04 04 10 18 20 2e 46 3c 28 1f 18 10 04
+ 29 01 00 00 00 19
+ ca 04 10 18 20 2e 46 3c 28 1f 18
+ 10 04 04 10 18 20 2e 46 3c 28 1f 18 10 04
+ 29 01 00 00 00 11
+ d0 29 03 ce a6 00 43 20 10 01 00
+ 01 01 00 03 01 00
+ 29 01 00 00 00 08
+ d1 18 0C 23 03 75 02 50
+ 23 01 00 00 00 02
+ d3 11
+ 29 01 00 00 00 03
+ d5 2a 2a
+ 29 01 00 00 00 03
+ de 01 51
+ 23 01 00 00 00 02
+ e6 51
+ 23 01 00 00 00 02
+ fa 03
+ 23 01 00 00 64 02
+ d6 28
+ 15 01 00 00 00 02
+ 36 41
+ 39 01 00 00 00 05
+ 2a 00 00 01 df
+ 39 01 00 00 00 05
+ 2b 00 00 03 1f
+ 15 01 00 00 00 02
+ 35 00
+ 39 01 00 00 00 03
+ 44 00 50
+ 15 01 00 00 00 02
+ 3a 77
+ 05 01 00 00 7D 02
+ 11 00
+ 05 01 00 00 14 02
+ 29 00
+ ];
+ qcom,panel-off-cmds = [05 01 00 00 32 02 28 00
+ 05 01 00 00 78 02 10 00];
+ qcom,off-cmds-dsi-state = "DSI_LP_MODE";
+ };
+};
diff --git a/arch/arm/boot/dts/dsi-v2-panel-truly-wvga-video.dtsi b/arch/arm/boot/dts/dsi-v2-panel-truly-wvga-video.dtsi
index 891eac3..8be8d71 100644
--- a/arch/arm/boot/dts/dsi-v2-panel-truly-wvga-video.dtsi
+++ b/arch/arm/boot/dts/dsi-v2-panel-truly-wvga-video.dtsi
@@ -41,7 +41,7 @@
qcom,mdss-pan-dsi-mdp-tr = <0x0>;/*todo*/
qcom,mdss-pan-dsi-dma-tr = <0x04>;
qcom,mdss-pan-dsi-frame-rate = <60>;
- qcom,panel-phy-regulatorSettings =[09 08 05 00 20 03];
+ qcom,panel-phy-regulatorSettings =[02 08 05 00 20 03];
qcom,panel-phy-timingSettings = [5D 12 0C 00 33 38
10 16 1E 03 04 00];
qcom,panel-phy-strengthCtrl = [ff 06];
@@ -69,7 +69,7 @@
c1 23 31 99 21 20 00 30 28 0c 0c
00 00 00 21 01
29 01 00 00 00 07
- c2 10 06 06 01 03 00
+ c2 00 06 06 01 03 00
29 01 00 00 00 19
c8 04 10 18 20 2e 46 3c 28 1f 18
10 04 04 10 18 20 2e 46 3c 28 1f 18 10 04
@@ -89,7 +89,7 @@
29 01 00 00 00 03
d5 2a 2a
29 01 00 00 00 03
- de 01 41
+ de 01 51
23 01 00 00 00 02
e6 51
23 01 00 00 00 02
diff --git a/arch/arm/boot/dts/mpq8092-iommu.dtsi b/arch/arm/boot/dts/mpq8092-iommu.dtsi
index 56369dc..3a86814 100644
--- a/arch/arm/boot/dts/mpq8092-iommu.dtsi
+++ b/arch/arm/boot/dts/mpq8092-iommu.dtsi
@@ -14,27 +14,205 @@
&jpeg_iommu {
status = "ok";
- vdd-supply = <&gdsc_jpeg>;
+
+ qcom,iommu-bfb-regs = <0x204c
+ 0x2514
+ 0x2540
+ 0x256c
+ 0x2314
+ 0x2394
+ 0x2414
+ 0x2494
+ 0x20ac
+ 0x215c
+ 0x220c
+ 0x22bc
+ 0x2008
+ 0x200c
+ 0x2010>;
+
+ qcom,iommu-bfb-data = <0x3FFF
+ 0x4
+ 0x4
+ 0x0
+ 0x0
+ 0x10
+ 0x50
+ 0x0
+ 0x2000
+ 0x2804
+ 0x9614
+ 0x0
+ 0x0
+ 0x0
+ 0x0>;
};
&mdp_iommu {
status = "ok";
- vdd-supply = <&gdsc_mdss>;
+
+ qcom,iommu-bfb-regs = <0x204c
+ 0x2514
+ 0x2540
+ 0x256c
+ 0x20ac
+ 0x215c
+ 0x220c
+ 0x22bc
+ 0x2314
+ 0x2394
+ 0x2414
+ 0x2494
+ 0x2008
+ 0x200c
+ 0x2010
+ 0x2014
+ 0x2018>;
+
+ qcom,iommu-bfb-data = <0x7FFFFF
+ 0x4
+ 0x10
+ 0x0
+ 0x5000
+ 0x5a1d
+ 0x1822d
+ 0x0
+ 0x0
+ 0x28
+ 0x68
+ 0x0
+ 0x0
+ 0x0
+ 0x0
+ 0x0
+ 0x0>;
};
&venus_iommu {
status = "ok";
- vdd-supply = <&gdsc_venus>;
+
+ qcom,iommu-bfb-regs = <0x204c
+ 0x2514
+ 0x2540
+ 0x256c
+ 0x20ac
+ 0x215c
+ 0x220c
+ 0x22bc
+ 0x2314
+ 0x2394
+ 0x2414
+ 0x2494
+ 0x2008
+ 0x200c
+ 0x2010
+ 0x2014
+ 0x2018
+ 0x201c>;
+
+ qcom,iommu-bfb-data = <0x7FFFFFF
+ 0x4
+ 0x8
+ 0x0
+ 0x13607
+ 0x4201
+ 0x14221
+ 0x0
+ 0x0
+ 0x94
+ 0x114
+ 0x0
+ 0x0
+ 0x0
+ 0x0
+ 0x0
+ 0x0
+ 0x0>;
+
+ venus_ns: qcom,iommu-ctx@fdc8c000 {
+ qcom,iommu-ctx-sids = <0 1 2 3 4 5 7>;
+ };
+
+ venus_sec_bitstream: qcom,iommu-ctx@fdc8d000 {
+ qcom,iommu-ctx-sids = <0x80 0x81 0x82 0x83 0x84>;
+ label = "venus_sec_bitstream";
+ };
+
+ venus_sec_pixel: qcom,iommu-ctx@fdc8f000 {
+ compatible = "qcom,msm-smmu-v1-ctx";
+ reg = <0xfdc8f000 0x1000>;
+ interrupts = <0 42 0>;
+ qcom,iommu-ctx-sids = <0x85>;
+ label = "venus_sec_pixel";
+ qcom,secure-context;
+ };
+
+ venus_sec_non_pixel: qcom,iommu-ctx@fdc90000 {
+ compatible = "qcom,msm-smmu-v1-ctx";
+ reg = <0xfdc90000 0x1000>;
+ interrupts = <0 42 0>;
+ qcom,iommu-ctx-sids = <0x87 0xA0>;
+ label = "venus_sec_non_pixel";
+ qcom,secure-context;
+ };
};
&kgsl_iommu {
status = "ok";
- qcom,needs-alt-core-clk;
- vdd-supply = <&gdsc_oxili_cx>;
- qcom,alt-vdd-supply = <&gdsc_oxili_gx>;
+
+ qcom,iommu-bfb-regs = <0x204c
+ 0x2514
+ 0x2540
+ 0x256c
+ 0x20ac
+ 0x215c
+ 0x220c
+ 0x22bc
+ 0x2314
+ 0x2394
+ 0x2414
+ 0x2494
+ 0x2008
+ 0x2600
+ 0x2604
+ 0x2608
+ 0x260c
+ 0x2610
+ 0x2614
+ 0x2618
+ 0x261c
+ 0x2620
+ 0x2624
+ 0x2628
+ 0x262c>;
+
+ qcom,iommu-bfb-data = <0x3
+ 0x8
+ 0x10
+ 0x0
+ 0x0
+ 0x0
+ 0x20
+ 0x0
+ 0x0
+ 0x1
+ 0x101
+ 0x0
+ 0x0
+ 0x7
+ 0x4
+ 0x8
+ 0x14
+ 0x0
+ 0x0
+ 0xc
+ 0x6c
+ 0x0
+ 0x8
+ 0x10
+ 0x0>;
};
-&vfe_iommu {
+&vpu_iommu {
status = "ok";
- vdd-supply = <&gdsc_vfe>;
};
diff --git a/arch/arm/boot/dts/mpq8092-rumi.dtsi b/arch/arm/boot/dts/mpq8092-rumi.dtsi
index 2016998..cc345d8 100644
--- a/arch/arm/boot/dts/mpq8092-rumi.dtsi
+++ b/arch/arm/boot/dts/mpq8092-rumi.dtsi
@@ -24,13 +24,13 @@
};
qcom,sdcc@f9824000 {
- status = "disabled";
qcom,clk-rates = <400000 19200000>;
+ status = "ok";
};
qcom,sdcc@f98a4000 {
- status = "disabled";
qcom,clk-rates = <400000 19200000>;
+ status = "ok";
};
qcom,sps@f998000 {
diff --git a/arch/arm/boot/dts/mpq8092.dtsi b/arch/arm/boot/dts/mpq8092.dtsi
index 2eaa32f..04f0945 100644
--- a/arch/arm/boot/dts/mpq8092.dtsi
+++ b/arch/arm/boot/dts/mpq8092.dtsi
@@ -140,6 +140,38 @@
reg = <0xfe805000 0x1000>; /* Address and size of IMEM */
};
+ usb@f9a55000 {
+ compatible = "qcom,hsusb-otg";
+ reg = <0xf9a55000 0x400>;
+ interrupts = <0 134 0>, <0 140 0>;
+ interrupt-names = "core_irq", "async_irq";
+
+ HSUSB_VDDCX-supply = <&pma8084_s8>;
+ HSUSB_1p8-supply = <&pma8084_l22>;
+ HSUSB_3p3-supply = <&pma8084_l24>;
+ qcom,vdd-voltage-level = <1050000 1050000>;
+
+ qcom,hsusb-otg-phy-type = <2>;
+ qcom,hsusb-otg-mode = <1>;
+ qcom,hsusb-otg-otg-control = <1>;
+ qcom,hsusb-otg-disable-reset;
+
+ qcom,msm_bus,name = "usb_otg";
+ qcom,msm_bus,num_cases = <3>;
+ qcom,msm_bus,active_only = <0>;
+ qcom,msm_bus,num_paths = <1>;
+ qcom,msm-bus,vectors-KBps =
+ <87 512 0 0>,
+ <87 512 60000 960000>,
+ <87 512 6000 6000>;
+ };
+
+ android_usb@fe8050c8 {
+ compatible = "qcom,android-usb";
+ reg = <0xfe8050c8 0xc8>;
+ qcom,android-usb-swfi-latency = <1>;
+ };
+
spmi_bus: qcom,spmi@fc4c0000 {
cell-index = <0>;
compatible = "qcom,spmi-pmic-arb";
@@ -259,6 +291,10 @@
status = "ok";
};
+&gdsc_vpu {
+ status = "ok";
+};
+
&gdsc_oxili_gx {
status = "ok";
};
diff --git a/arch/arm/boot/dts/msm-gdsc.dtsi b/arch/arm/boot/dts/msm-gdsc.dtsi
index 78234e8..495f65a 100644
--- a/arch/arm/boot/dts/msm-gdsc.dtsi
+++ b/arch/arm/boot/dts/msm-gdsc.dtsi
@@ -19,6 +19,27 @@
status = "disabled";
};
+ gdsc_venus_core0: qcom,gdsc@fd8c1040 {
+ compatible = "qcom,gdsc";
+ regulator-name = "gdsc_venus_core0";
+ reg = <0xfd8c1040 0x4>;
+ status = "disabled";
+ };
+
+ gdsc_venus_core1: qcom,gdsc@fd8c1044 {
+ compatible = "qcom,gdsc";
+ regulator-name = "gdsc_venus_core1";
+ reg = <0xfd8c1044 0x4>;
+ status = "disabled";
+ };
+
+ gdsc_vpu: qcom,gdsc@fd8c1404 {
+ compatible = "qcom,gdsc";
+ regulator-name = "gdsc_vpu";
+ reg = <0xfd8c1404 0x4>;
+ status = "disabled";
+ };
+
gdsc_mdss: qcom,gdsc@fd8c2304 {
compatible = "qcom,gdsc";
regulator-name = "gdsc_mdss";
@@ -60,4 +81,32 @@
reg = <0xfc400404 0x4>;
status = "disabled";
};
+
+ gdsc_pcie_0: qcom,gdsc@fc401ac4 {
+ compatible = "qcom,gdsc";
+ regulator-name = "gdsc_pcie_0";
+ reg = <0xfc401ac4 0x4>;
+ status = "disabled";
+ };
+
+ gdsc_pcie_1: qcom,gdsc@fc401b44 {
+ compatible = "qcom,gdsc";
+ regulator-name = "gdsc_pcie_1";
+ reg = <0xfc401b44 0x4>;
+ status = "disabled";
+ };
+
+ gdsc_usb30: qcom,gdsc@fc401e84 {
+ compatible = "qcom,gdsc";
+ regulator-name = "gdsc_usb30";
+ reg = <0xfc401e84 0x4>;
+ status = "disabled";
+ };
+
+ gdsc_usb30_sec: qcom,gdsc@fc401ec0 {
+ compatible = "qcom,gdsc";
+ regulator-name = "gdsc_usb30_sec";
+ reg = <0xfc401ec0 0x4>;
+ status = "disabled";
+ };
};
diff --git a/arch/arm/boot/dts/msm-pm8226-rpm-regulator.dtsi b/arch/arm/boot/dts/msm-pm8226-rpm-regulator.dtsi
index ded9494..1ee7076 100644
--- a/arch/arm/boot/dts/msm-pm8226-rpm-regulator.dtsi
+++ b/arch/arm/boot/dts/msm-pm8226-rpm-regulator.dtsi
@@ -427,6 +427,22 @@
};
};
+ rpm-regulator-ldoa25 {
+ compatible = "qcom,rpm-regulator-smd-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <25>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ status = "disabled";
+
+ regulator-l25 {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8226_l25";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
rpm-regulator-ldoa26 {
compatible = "qcom,rpm-regulator-smd-resource";
qcom,resource-name = "ldoa";
diff --git a/arch/arm/boot/dts/msm-pm8226.dtsi b/arch/arm/boot/dts/msm-pm8226.dtsi
index 2008e1e..0f93c8e 100644
--- a/arch/arm/boot/dts/msm-pm8226.dtsi
+++ b/arch/arm/boot/dts/msm-pm8226.dtsi
@@ -32,10 +32,13 @@
reg = <0x800 0x100>;
interrupts = <0x0 0x8 0x0>,
<0x0 0x8 0x1>,
- <0x0 0x8 0x4>;
- interrupt-names = "kpdpwr", "resin", "resin-bark";
+ <0x0 0x8 0x4>,
+ <0x0 0x8 0x5>;
+ interrupt-names = "kpdpwr", "resin",
+ "resin-bark", "kpdpwr-resin-bark";
qcom,pon-dbc-delay = <15625>;
qcom,system-reset;
+ qcom,s3-debounce = <32>;
qcom,pon_1 {
qcom,pon-type = <0>;
@@ -52,6 +55,15 @@
qcom,s2-type = <1>;
linux,code = <114>;
};
+
+ qcom,pon_3 {
+ qcom,pon-type = <3>;
+ qcom,support-reset = <1>;
+ qcom,pull-up = <1>;
+ qcom,s1-timer = <6720>;
+ qcom,s2-timer = <2000>;
+ qcom,s2-type = <7>;
+ };
};
pm8226_chg: qcom,charger {
diff --git a/arch/arm/boot/dts/msm-pm8941.dtsi b/arch/arm/boot/dts/msm-pm8941.dtsi
index 40f9a7c..fc828b7 100644
--- a/arch/arm/boot/dts/msm-pm8941.dtsi
+++ b/arch/arm/boot/dts/msm-pm8941.dtsi
@@ -15,1383 +15,1381 @@
#size-cells = <0>;
interrupt-controller;
#interrupt-cells = <3>;
+};
- qcom,pm8941@0 {
- spmi-slave-container;
- reg = <0x0>;
- #address-cells = <1>;
- #size-cells = <1>;
+&pm8941_lsid0 {
+ spmi-slave-container;
+ #address-cells = <1>;
+ #size-cells = <1>;
- pm8941_misc: qcom,misc@900 {
- compatible = "qcom,qpnp-misc";
- reg = <0x900 0x100>;
+ pm8941_misc: qcom,misc@900 {
+ compatible = "qcom,qpnp-misc";
+ reg = <0x900 0x100>;
+ };
+
+ qcom,revid@100 {
+ compatible = "qcom,qpnp-revid";
+ reg = <0x100 0x100>;
+ };
+
+ qcom,temp-alarm@2400 {
+ compatible = "qcom,qpnp-temp-alarm";
+ reg = <0x2400 0x100>;
+ interrupts = <0x0 0x24 0x0>;
+ label = "pm8941_tz";
+ qcom,channel-num = <8>;
+ qcom,threshold-set = <0>;
+ };
+
+ qcom,power-on@800 {
+ compatible = "qcom,qpnp-power-on";
+ reg = <0x800 0x100>;
+ interrupts = <0x0 0x8 0x0>,
+ <0x0 0x8 0x1>,
+ <0x0 0x8 0x4>,
+ <0x0 0x8 0x5>;
+ interrupt-names = "kpdpwr", "resin",
+ "resin-bark", "kpdpwr-resin-bark";
+ qcom,pon-dbc-delay = <15625>;
+ qcom,system-reset;
+ qcom,s3-debounce = <32>;
+
+ qcom,pon_1 {
+ qcom,pon-type = <0>;
+ qcom,pull-up = <1>;
+ linux,code = <116>;
};
- qcom,revid@100 {
- compatible = "qcom,qpnp-revid";
- reg = <0x100 0x100>;
+ qcom,pon_2 {
+ qcom,pon-type = <1>;
+ qcom,support-reset = <1>;
+ qcom,pull-up = <1>;
+ qcom,s1-timer = <0>;
+ qcom,s2-timer = <2000>;
+ qcom,s2-type = <1>;
+ linux,code = <114>;
};
- qcom,temp-alarm@2400 {
- compatible = "qcom,qpnp-temp-alarm";
- reg = <0x2400 0x100>;
- interrupts = <0x0 0x24 0x0>;
- label = "pm8941_tz";
- qcom,channel-num = <8>;
- qcom,threshold-set = <0>;
- };
-
- qcom,power-on@800 {
- compatible = "qcom,qpnp-power-on";
- reg = <0x800 0x100>;
- interrupts = <0x0 0x8 0x0>,
- <0x0 0x8 0x1>,
- <0x0 0x8 0x4>,
- <0x0 0x8 0x5>;
- interrupt-names = "kpdpwr", "resin",
- "resin-bark", "kpdpwr-resin-bark";
- qcom,pon-dbc-delay = <15625>;
- qcom,system-reset;
- qcom,s3-debounce = <32>;
-
- qcom,pon_1 {
- qcom,pon-type = <0>;
- qcom,pull-up = <1>;
- linux,code = <116>;
- };
-
- qcom,pon_2 {
- qcom,pon-type = <1>;
- qcom,support-reset = <1>;
- qcom,pull-up = <1>;
- qcom,s1-timer = <0>;
- qcom,s2-timer = <2000>;
- qcom,s2-type = <1>;
- linux,code = <114>;
- };
-
- qcom,pon_3 {
- qcom,pon-type = <3>;
- qcom,support-reset = <1>;
- qcom,s1-timer = <6720>;
- qcom,s2-timer = <2000>;
- qcom,s2-type = <7>;
- qcom,pull-up = <1>;
- };
- };
-
- bif_ctrl: qcom,bsi@1b00 {
- compatible = "qcom,qpnp-bsi";
- reg = <0x1b00 0x100>,
- <0x1208 0x1>;
- reg-names = "bsi-base", "batt-id-status";
- label = "pm8941-bsi";
- interrupts = <0x0 0x1b 0x0>,
- <0x0 0x1b 0x1>,
- <0x0 0x1b 0x2>,
- <0x0 0x12 0x0>;
- interrupt-names = "err",
- "rx",
- "tx",
- "batt-present";
- qcom,channel-num = <0x31>;
- qcom,pullup-ohms = <100000>;
- qcom,vref-microvolts = <1800000>;
- qcom,min-clock-period = <1000>;
- qcom,max-clock-period = <160000>;
- qcom,sample-rate = <4>;
- };
-
- pm8941_coincell: qcom,coincell@2800 {
- compatible = "qcom,qpnp-coincell";
- reg = <0x2800 0x100>;
- };
-
- pm8941_bms: qcom,bms {
- spmi-dev-container;
- compatible = "qcom,qpnp-bms";
- #address-cells = <1>;
- #size-cells = <1>;
- status = "disabled";
-
- qcom,r-sense-uohm = <10000>;
- qcom,v-cutoff-uv = <3400000>;
- qcom,max-voltage-uv = <4200000>;
- qcom,r-conn-mohm = <0>;
- qcom,shutdown-soc-valid-limit = <20>;
- qcom,adjust-soc-low-threshold = <15>;
- qcom,ocv-voltage-high-threshold-uv = <3750000>;
- qcom,ocv-voltage-low-threshold-uv = <3650000>;
- qcom,low-soc-calculate-soc-threshold = <15>;
- qcom,low-soc-calculate-soc-ms = <5000>;
- qcom,calculate-soc-ms = <20000>;
- qcom,chg-term-ua = <100000>;
- qcom,batt-type = <0>;
- qcom,low-voltage-threshold = <3420000>;
- qcom,tm-temp-margin = <5000>;
- qcom,low-ocv-correction-limit-uv = <100>;
- qcom,high-ocv-correction-limit-uv = <50>;
- qcom,hold-soc-est = <3>;
-
- qcom,bms-iadc@3800 {
- reg = <0x3800 0x100>;
- };
-
- 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>,
- <0x0 0x40 0x6>,
- <0x0 0x40 0x7>;
-
- interrupt-names = "cc_thr",
- "ocv_for_r",
- "good_ocv",
- "charge_begin",
- "ocv_thr",
- "sw_cc_thr",
- "vsense_avg",
- "vsense_for_r";
-
- };
- };
-
- clkdiv@5b00 {
- reg = <0x5b00 0x100>;
- compatible = "qcom,qpnp-clkdiv";
- qcom,cxo-freq = <19200000>;
- };
-
- clkdiv@5c00 {
- reg = <0x5c00 0x100>;
- compatible = "qcom,qpnp-clkdiv";
- qcom,cxo-freq = <19200000>;
- };
-
- clkdiv@5d00 {
- reg = <0x5d00 0x1000>;
- compatible = "qcom,qpnp-clkdiv";
- qcom,cxo-freq = <19200000>;
- };
-
- pm8941_chg: qcom,charger {
- spmi-dev-container;
- compatible = "qcom,qpnp-charger";
- #address-cells = <1>;
- #size-cells = <1>;
- status = "disabled";
-
- qcom,vddmax-mv = <4200>;
- qcom,vddsafe-mv = <4230>;
- qcom,vinmin-mv = <4300>;
- qcom,ibatmax-ma = <1500>;
- qcom,ibatterm-ma = <100>;
- qcom,ibatsafe-ma = <1500>;
- qcom,thermal-mitigation = <1500 700 600 325>;
- qcom,cool-bat-decidegc = <100>;
- qcom,cool-bat-mv = <4100>;
- qcom,ibatmax-warm-ma = <350>;
- qcom,warm-bat-decidegc = <450>;
- qcom,warm-bat-mv = <4100>;
- qcom,ibatmax-cool-ma = <350>;
- qcom,vbatdet-delta-mv = <100>;
- qcom,tchg-mins = <150>;
-
- qcom,chgr@1000 {
- status = "disabled";
- 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 = "vbat-det-lo",
- "vbat-det-hi",
- "chgwdog",
- "state-change",
- "trkl-chg-on",
- "fast-chg-on",
- "chg-failed",
- "chg-done";
- };
-
- qcom,buck@1100 {
- status = "disabled";
- 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 = "vbat-ov",
- "vreg-ov",
- "overtemp",
- "vchg-loop",
- "ichg-loop",
- "ibat-loop",
- "vdd-loop";
- };
-
- qcom,bat-if@1200 {
- status = "disabled";
- reg = <0x1200 0x100>;
- interrupts = <0x0 0x12 0x0>,
- <0x0 0x12 0x1>,
- <0x0 0x12 0x2>,
- <0x0 0x12 0x3>,
- <0x0 0x12 0x4>;
-
- interrupt-names = "batt-pres",
- "bat-temp-ok",
- "bat-fet-on",
- "vcp-on",
- "psi";
-
- };
-
- pm8941_chg_otg: qcom,usb-chgpth@1300 {
- status = "disabled";
- reg = <0x1300 0x100>;
- interrupts = <0 0x13 0x0>,
- <0 0x13 0x1>,
- <0x0 0x13 0x2>;
-
- interrupt-names = "coarse-det-usb",
- "usbin-valid",
- "chg-gone";
- };
-
- qcom,dc-chgpth@1400 {
- status = "disabled";
- reg = <0x1400 0x100>;
- interrupts = <0x0 0x14 0x0>,
- <0x0 0x14 0x1>;
-
- interrupt-names = "coarse-det-dc",
- "dcin-valid";
- };
-
- pm8941_chg_boost: qcom,boost@1500 {
- status = "disabled";
- reg = <0x1500 0x100>;
- interrupts = <0x0 0x15 0x0>,
- <0x0 0x15 0x1>;
-
- interrupt-names = "boost-pwr-ok",
- "limit-error";
- };
-
- qcom,chg-misc@1600 {
- status = "disabled";
- reg = <0x1600 0x100>;
- };
- };
-
- pm8941_gpios: gpios {
- spmi-dev-container;
- compatible = "qcom,qpnp-pin";
- gpio-controller;
- #gpio-cells = <2>;
- #address-cells = <1>;
- #size-cells = <1>;
- label = "pm8941-gpio";
-
- gpio@c000 {
- reg = <0xc000 0x100>;
- qcom,pin-num = <1>;
- };
-
- gpio@c100 {
- reg = <0xc100 0x100>;
- qcom,pin-num = <2>;
- };
-
- gpio@c200 {
- reg = <0xc200 0x100>;
- qcom,pin-num = <3>;
- };
-
- gpio@c300 {
- reg = <0xc300 0x100>;
- qcom,pin-num = <4>;
- };
-
- gpio@c400 {
- reg = <0xc400 0x100>;
- qcom,pin-num = <5>;
- };
-
- gpio@c500 {
- reg = <0xc500 0x100>;
- qcom,pin-num = <6>;
- };
-
- gpio@c600 {
- reg = <0xc600 0x100>;
- qcom,pin-num = <7>;
- };
-
- gpio@c700 {
- reg = <0xc700 0x100>;
- qcom,pin-num = <8>;
- };
-
- gpio@c800 {
- reg = <0xc800 0x100>;
- qcom,pin-num = <9>;
- };
-
- gpio@c900 {
- reg = <0xc900 0x100>;
- qcom,pin-num = <10>;
- };
-
- gpio@ca00 {
- reg = <0xca00 0x100>;
- qcom,pin-num = <11>;
- };
-
- gpio@cb00 {
- reg = <0xcb00 0x100>;
- qcom,pin-num = <12>;
- };
-
- gpio@cc00 {
- reg = <0xcc00 0x100>;
- qcom,pin-num = <13>;
- };
-
- gpio@cd00 {
- reg = <0xcd00 0x100>;
- qcom,pin-num = <14>;
- };
-
- gpio@ce00 {
- reg = <0xce00 0x100>;
- qcom,pin-num = <15>;
- };
-
- gpio@cf00 {
- reg = <0xcf00 0x100>;
- qcom,pin-num = <16>;
- };
-
- gpio@d000 {
- reg = <0xd000 0x100>;
- qcom,pin-num = <17>;
- };
-
- gpio@d100 {
- reg = <0xd100 0x100>;
- qcom,pin-num = <18>;
- };
-
- gpio@d200 {
- reg = <0xd200 0x100>;
- qcom,pin-num = <19>;
- };
-
- gpio@d300 {
- reg = <0xd300 0x100>;
- qcom,pin-num = <20>;
- };
-
- gpio@d400 {
- reg = <0xd400 0x100>;
- qcom,pin-num = <21>;
- };
-
- gpio@d500 {
- reg = <0xd500 0x100>;
- qcom,pin-num = <22>;
- };
-
- gpio@d600 {
- reg = <0xd600 0x100>;
- qcom,pin-num = <23>;
- };
-
- gpio@d700 {
- reg = <0xd700 0x100>;
- qcom,pin-num = <24>;
- };
-
- gpio@d800 {
- reg = <0xd800 0x100>;
- qcom,pin-num = <25>;
- };
-
- gpio@d900 {
- reg = <0xd900 0x100>;
- qcom,pin-num = <26>;
- };
-
- gpio@da00 {
- reg = <0xda00 0x100>;
- qcom,pin-num = <27>;
- };
-
- gpio@db00 {
- reg = <0xdb00 0x100>;
- qcom,pin-num = <28>;
- };
-
- gpio@dc00 {
- reg = <0xdc00 0x100>;
- qcom,pin-num = <29>;
- };
-
- gpio@dd00 {
- reg = <0xdd00 0x100>;
- qcom,pin-num = <30>;
- };
-
- gpio@de00 {
- reg = <0xde00 0x100>;
- qcom,pin-num = <31>;
- };
-
- gpio@df00 {
- reg = <0xdf00 0x100>;
- qcom,pin-num = <32>;
- };
-
- gpio@e000 {
- reg = <0xe000 0x100>;
- qcom,pin-num = <33>;
- };
-
- gpio@e100 {
- reg = <0xe100 0x100>;
- qcom,pin-num = <34>;
- };
-
- gpio@e200 {
- reg = <0xe200 0x100>;
- qcom,pin-num = <35>;
- };
-
- gpio@e300 {
- reg = <0xe300 0x100>;
- qcom,pin-num = <36>;
- };
- };
-
- pm8941_mpps: mpps {
- spmi-dev-container;
- compatible = "qcom,qpnp-pin";
- gpio-controller;
- #gpio-cells = <2>;
- #address-cells = <1>;
- #size-cells = <1>;
- label = "pm8941-mpp";
-
- mpp@a000 {
- reg = <0xa000 0x100>;
- qcom,pin-num = <1>;
- };
-
- mpp@a100 {
- reg = <0xa100 0x100>;
- qcom,pin-num = <2>;
- };
-
- mpp@a200 {
- reg = <0xa200 0x100>;
- qcom,pin-num = <3>;
- };
-
- mpp@a300 {
- reg = <0xa300 0x100>;
- qcom,pin-num = <4>;
- };
-
- mpp@a400 {
- reg = <0xa400 0x100>;
- qcom,pin-num = <5>;
- };
-
- mpp@a500 {
- reg = <0xa500 0x100>;
- qcom,pin-num = <6>;
- };
-
- mpp@a600 {
- reg = <0xa600 0x100>;
- qcom,pin-num = <7>;
- };
-
- mpp@a700 {
- reg = <0xa700 0x100>;
- qcom,pin-num = <8>;
- };
- };
-
- qcom,pm8941_rtc {
- spmi-dev-container;
- compatible = "qcom,qpnp-rtc";
- #address-cells = <1>;
- #size-cells = <1>;
- qcom,qpnp-rtc-write = <0>;
- qcom,qpnp-rtc-alarm-pwrup = <0>;
-
- qcom,pm8941_rtc_rw@6000 {
- reg = <0x6000 0x100>;
- };
- qcom,pm8941_rtc_alarm@6100 {
- reg = <0x6100 0x100>;
- interrupts = <0x0 0x61 0x1>;
- };
- };
-
- pm8941_vadc: vadc@3100 {
- compatible = "qcom,qpnp-vadc";
- reg = <0x3100 0x100>;
- #address-cells = <1>;
- #size-cells = <0>;
- interrupts = <0x0 0x31 0x0>;
- interrupt-names = "eoc-int-en-set";
- qcom,adc-bit-resolution = <15>;
- qcom,adc-vdd-reference = <1800>;
-
- chan@0 {
- label = "usb_in";
- reg = <0>;
- qcom,decimation = <0>;
- qcom,pre-div-channel-scaling = <4>;
- qcom,calibration-type = "absolute";
- qcom,scale-function = <0>;
- qcom,hw-settle-time = <0>;
- qcom,fast-avg-setup = <0>;
- };
-
- chan@1 {
- label = "dc_in";
- reg = <1>;
- qcom,decimation = <0>;
- qcom,pre-div-channel-scaling = <4>;
- qcom,calibration-type = "absolute";
- qcom,scale-function = <0>;
- qcom,hw-settle-time = <0>;
- qcom,fast-avg-setup = <0>;
- };
-
- chan@2 {
- label = "vchg_sns";
- reg = <2>;
- qcom,decimation = <0>;
- qcom,pre-div-channel-scaling = <3>;
- qcom,calibration-type = "absolute";
- qcom,scale-function = <0>;
- qcom,hw-settle-time = <0>;
- qcom,fast-avg-setup = <0>;
- };
-
- chan@3 {
- label = "spare1_div3";
- reg = <3>;
- qcom,decimation = <0>;
- qcom,pre-div-channel-scaling = <1>;
- qcom,calibration-type = "absolute";
- qcom,scale-function = <0>;
- qcom,hw-settle-time = <0>;
- qcom,fast-avg-setup = <0>;
- };
-
- chan@4 {
- label = "usb_id_mv";
- reg = <4>;
- qcom,decimation = <0>;
- qcom,pre-div-channel-scaling = <1>;
- qcom,calibration-type = "absolute";
- qcom,scale-function = <0>;
- qcom,hw-settle-time = <0>;
- qcom,fast-avg-setup = <0>;
- };
-
- chan@5 {
- label = "vcoin";
- reg = <5>;
- qcom,decimation = <0>;
- qcom,pre-div-channel-scaling = <1>;
- qcom,calibration-type = "absolute";
- qcom,scale-function = <0>;
- qcom,hw-settle-time = <0>;
- qcom,fast-avg-setup = <0>;
- };
-
- chan@6 {
- label = "vbat_sns";
- reg = <6>;
- qcom,decimation = <0>;
- qcom,pre-div-channel-scaling = <1>;
- qcom,calibration-type = "absolute";
- qcom,scale-function = <0>;
- qcom,hw-settle-time = <0>;
- qcom,fast-avg-setup = <0>;
- };
-
- chan@7 {
- label = "vph_pwr";
- reg = <7>;
- qcom,decimation = <0>;
- qcom,pre-div-channel-scaling = <1>;
- qcom,calibration-type = "absolute";
- qcom,scale-function = <0>;
- qcom,hw-settle-time = <0>;
- qcom,fast-avg-setup = <0>;
- };
-
- chan@8 {
- label = "die_temp";
- reg = <8>;
- qcom,decimation = <0>;
- qcom,pre-div-channel-scaling = <0>;
- qcom,calibration-type = "absolute";
- qcom,scale-function = <3>;
- qcom,hw-settle-time = <0>;
- qcom,fast-avg-setup = <0>;
- };
-
- chan@9 {
- label = "ref_625mv";
- reg = <9>;
- qcom,decimation = <0>;
- qcom,pre-div-channel-scaling = <0>;
- qcom,calibration-type = "absolute";
- qcom,scale-function = <0>;
- qcom,hw-settle-time = <0>;
- qcom,fast-avg-setup = <0>;
- };
-
- chan@a {
- label = "ref_1250v";
- reg = <0xa>;
- qcom,decimation = <0>;
- qcom,pre-div-channel-scaling = <0>;
- qcom,calibration-type = "absolute";
- qcom,scale-function = <0>;
- qcom,hw-settle-time = <0>;
- qcom,fast-avg-setup = <0>;
- };
-
- chan@30 {
- label = "batt_therm";
- reg = <0x30>;
- qcom,decimation = <0>;
- qcom,pre-div-channel-scaling = <0>;
- qcom,calibration-type = "ratiometric";
- qcom,scale-function = <1>;
- qcom,hw-settle-time = <2>;
- qcom,fast-avg-setup = <0>;
- };
-
- chan@31 {
- label = "batt_id";
- reg = <0x31>;
- qcom,decimation = <0>;
- qcom,pre-div-channel-scaling = <0>;
- qcom,calibration-type = "ratiometric";
- qcom,scale-function = <0>;
- qcom,hw-settle-time = <2>;
- qcom,fast-avg-setup = <0>;
- };
-
- chan@b2 {
- label = "xo_therm_pu2";
- reg = <0xb2>;
- qcom,decimation = <0>;
- qcom,pre-div-channel-scaling = <0>;
- qcom,calibration-type = "ratiometric";
- qcom,scale-function = <4>;
- qcom,hw-settle-time = <2>;
- qcom,fast-avg-setup = <0>;
- };
-
- chan@b3 {
- label = "msm_therm";
- reg = <0xb3>;
- qcom,decimation = <0>;
- qcom,pre-div-channel-scaling = <0>;
- qcom,calibration-type = "ratiometric";
- qcom,scale-function = <2>;
- qcom,hw-settle-time = <2>;
- qcom,fast-avg-setup = <0>;
- };
-
- chan@b4 {
- label = "emmc_therm";
- reg = <0xb4>;
- qcom,decimation = <0>;
- qcom,pre-div-channel-scaling = <0>;
- qcom,calibration-type = "ratiometric";
- qcom,scale-function = <2>;
- qcom,hw-settle-time = <2>;
- qcom,fast-avg-setup = <0>;
- };
-
- chan@b5 {
- label = "pa_therm0";
- reg = <0xb5>;
- qcom,decimation = <0>;
- qcom,pre-div-channel-scaling = <0>;
- qcom,calibration-type = "ratiometric";
- qcom,scale-function = <2>;
- qcom,hw-settle-time = <2>;
- qcom,fast-avg-setup = <0>;
- };
-
- chan@b7 {
- label = "pa_therm1";
- reg = <0xb7>;
- qcom,decimation = <0>;
- qcom,pre-div-channel-scaling = <0>;
- qcom,calibration-type = "ratiometric";
- qcom,scale-function = <2>;
- qcom,hw-settle-time = <2>;
- qcom,fast-avg-setup = <0>;
- };
-
- chan@b8 {
- label = "quiet_therm";
- reg = <0xb8>;
- qcom,decimation = <0>;
- qcom,pre-div-channel-scaling = <0>;
- qcom,calibration-type = "ratiometric";
- qcom,scale-function = <2>;
- qcom,hw-settle-time = <2>;
- qcom,fast-avg-setup = <0>;
- };
-
- chan@b9 {
- label = "usb_id";
- reg = <0xb9>;
- qcom,decimation = <0>;
- qcom,pre-div-channel-scaling = <0>;
- qcom,calibration-type = "ratiometric";
- qcom,scale-function = <0>;
- qcom,hw-settle-time = <2>;
- qcom,fast-avg-setup = <0>;
- };
-
- chan@39 {
- label = "usb_id_nopull";
- reg = <0x39>;
- qcom,decimation = <0>;
- qcom,pre-div-channel-scaling = <0>;
- qcom,calibration-type = "ratiometric";
- qcom,scale-function = <0>;
- qcom,hw-settle-time = <2>;
- qcom,fast-avg-setup = <0>;
- };
- };
-
- pm8941_iadc: iadc@3600 {
- compatible = "qcom,qpnp-iadc";
- reg = <0x3600 0x100>;
- #address-cells = <1>;
- #size-cells = <0>;
- interrupts = <0x0 0x36 0x0>;
- interrupt-names = "eoc-int-en-set";
- qcom,adc-bit-resolution = <16>;
- qcom,adc-vdd-reference = <1800>;
-
- chan@0 {
- label = "internal_rsense";
- reg = <0>;
- qcom,decimation = <0>;
- qcom,pre-div-channel-scaling = <1>;
- qcom,calibration-type = "absolute";
- qcom,scale-function = <0>;
- qcom,hw-settle-time = <0>;
- qcom,fast-avg-setup = <0>;
- };
- };
-
- pm8941_adc_tm: qcom,vadc@3400 {
- compatible = "qcom,qpnp-adc-tm";
- reg = <0x3400 0x100>;
- #address-cells = <1>;
- #size-cells = <0>;
- interrupts = <0x0 0x34 0x0>,
- <0x0 0x34 0x3>,
- <0x0 0x34 0x4>;
- interrupt-names = "eoc-int-en-set",
- "high-thr-en-set",
- "low-thr-en-set";
- qcom,adc-bit-resolution = <15>;
- qcom,adc-vdd-reference = <1800>;
-
- /* Channel Node */
- chan@b9 {
- label = "usb_id";
- reg = <0xb9>;
- qcom,decimation = <0>;
- qcom,pre-div-channel-scaling = <0>;
- qcom,calibration-type = "ratiometric";
- qcom,scale-function = <2>;
- qcom,hw-settle-time = <2>;
- qcom,fast-avg-setup = <3>;
- qcom,btm-channel-number = <0x48>;
- };
-
- chan@30 {
- label = "batt_therm";
- reg = <0x30>;
- qcom,decimation = <0>;
- qcom,pre-div-channel-scaling = <0>;
- qcom,calibration-type = "ratiometric";
- qcom,scale-function = <1>;
- qcom,hw-settle-time = <2>;
- qcom,fast-avg-setup = <3>;
- qcom,btm-channel-number = <0x68>;
- };
-
- chan@8 {
- label = "die_temp";
- reg = <8>;
- qcom,decimation = <0>;
- qcom,pre-div-channel-scaling = <0>;
- qcom,calibration-type = "absolute";
- qcom,scale-function = <3>;
- qcom,hw-settle-time = <0>;
- qcom,fast-avg-setup = <3>;
- qcom,btm-channel-number = <0x70>;
- };
-
- chan@6 {
- label = "vbat_sns";
- reg = <6>;
- qcom,decimation = <0>;
- qcom,pre-div-channel-scaling = <1>;
- qcom,calibration-type = "absolute";
- qcom,scale-function = <0>;
- qcom,hw-settle-time = <0>;
- qcom,fast-avg-setup = <3>;
- qcom,btm-channel-number = <0x78>;
- };
-
- chan@b5 {
- label = "pa_therm0";
- reg = <0xb5>;
- qcom,decimation = <0>;
- qcom,pre-div-channel-scaling = <0>;
- qcom,calibration-type = "ratiometric";
- qcom,scale-function = <2>;
- qcom,hw-settle-time = <2>;
- qcom,fast-avg-setup = <3>;
- qcom,btm-channel-number = <0x80>;
- qcom,thermal-node;
- };
-
- chan@b7 {
- label = "pa_therm1";
- reg = <0xb7>;
- qcom,decimation = <0>;
- qcom,pre-div-channel-scaling = <0>;
- qcom,calibration-type = "ratiometric";
- qcom,scale-function = <2>;
- qcom,hw-settle-time = <2>;
- qcom,fast-avg-setup = <3>;
- qcom,btm-channel-number = <0x88>;
- qcom,thermal-node;
- };
-
- chan@b4 {
- label = "emmc_therm";
- reg = <0xb4>;
- qcom,decimation = <0>;
- qcom,pre-div-channel-scaling = <0>;
- qcom,calibration-type = "ratiometric";
- qcom,scale-function = <2>;
- qcom,hw-settle-time = <2>;
- qcom,fast-avg-setup = <3>;
- qcom,btm-channel-number = <0x90>;
- qcom,thermal-node;
- };
-
- chan@b3 {
- label = "msm_therm";
- reg = <0xb3>;
- qcom,decimation = <0>;
- qcom,pre-div-channel-scaling = <0>;
- qcom,calibration-type = "ratiometric";
- qcom,scale-function = <2>;
- qcom,hw-settle-time = <2>;
- qcom,fast-avg-setup = <3>;
- qcom,btm-channel-number = <0x98>;
- qcom,thermal-node;
- };
+ qcom,pon_3 {
+ qcom,pon-type = <3>;
+ qcom,support-reset = <1>;
+ qcom,s1-timer = <6720>;
+ qcom,s2-timer = <2000>;
+ qcom,s2-type = <7>;
+ qcom,pull-up = <1>;
};
};
- qcom,pm8941@1 {
- spmi-slave-container;
- reg = <0x1>;
+ bif_ctrl: qcom,bsi@1b00 {
+ compatible = "qcom,qpnp-bsi";
+ reg = <0x1b00 0x100>,
+ <0x1208 0x1>;
+ reg-names = "bsi-base", "batt-id-status";
+ label = "pm8941-bsi";
+ interrupts = <0x0 0x1b 0x0>,
+ <0x0 0x1b 0x1>,
+ <0x0 0x1b 0x2>,
+ <0x0 0x12 0x0>;
+ interrupt-names = "err",
+ "rx",
+ "tx",
+ "batt-present";
+ qcom,channel-num = <0x31>;
+ qcom,pullup-ohms = <100000>;
+ qcom,vref-microvolts = <1800000>;
+ qcom,min-clock-period = <1000>;
+ qcom,max-clock-period = <160000>;
+ qcom,sample-rate = <4>;
+ };
+
+ pm8941_coincell: qcom,coincell@2800 {
+ compatible = "qcom,qpnp-coincell";
+ reg = <0x2800 0x100>;
+ };
+
+ pm8941_bms: qcom,bms {
+ spmi-dev-container;
+ compatible = "qcom,qpnp-bms";
#address-cells = <1>;
#size-cells = <1>;
+ status = "disabled";
- regulator@1400 {
- regulator-name = "8941_s1";
- spmi-dev-container;
- #address-cells = <1>;
- #size-cells = <1>;
- compatible = "qcom,qpnp-regulator";
- reg = <0x1400 0x300>;
- status = "disabled";
+ qcom,r-sense-uohm = <10000>;
+ qcom,v-cutoff-uv = <3400000>;
+ qcom,max-voltage-uv = <4200000>;
+ qcom,r-conn-mohm = <0>;
+ qcom,shutdown-soc-valid-limit = <20>;
+ qcom,adjust-soc-low-threshold = <15>;
+ qcom,ocv-voltage-high-threshold-uv = <3750000>;
+ qcom,ocv-voltage-low-threshold-uv = <3650000>;
+ qcom,low-soc-calculate-soc-threshold = <15>;
+ qcom,low-soc-calculate-soc-ms = <5000>;
+ qcom,calculate-soc-ms = <20000>;
+ qcom,chg-term-ua = <100000>;
+ qcom,batt-type = <0>;
+ qcom,low-voltage-threshold = <3420000>;
+ qcom,tm-temp-margin = <5000>;
+ qcom,low-ocv-correction-limit-uv = <100>;
+ qcom,high-ocv-correction-limit-uv = <50>;
+ qcom,hold-soc-est = <3>;
- qcom,ctl@1400 {
- reg = <0x1400 0x100>;
- };
- qcom,ps@1500 {
- reg = <0x1500 0x100>;
- };
- qcom,freq@1600 {
- reg = <0x1600 0x100>;
- };
+ qcom,bms-iadc@3800 {
+ reg = <0x3800 0x100>;
};
- regulator@1700 {
- regulator-name = "8941_s2";
- spmi-dev-container;
- #address-cells = <1>;
- #size-cells = <1>;
- compatible = "qcom,qpnp-regulator";
- reg = <0x1700 0x300>;
- status = "disabled";
-
- qcom,ctl@1700 {
- reg = <0x1700 0x100>;
- };
- qcom,ps@1800 {
- reg = <0x1800 0x100>;
- };
- qcom,freq@1900 {
- reg = <0x1900 0x100>;
- };
- };
-
- regulator@1a00 {
- regulator-name = "8941_s3";
- spmi-dev-container;
- #address-cells = <1>;
- #size-cells = <1>;
- compatible = "qcom,qpnp-regulator";
- reg = <0x1a00 0x300>;
- status = "disabled";
-
- qcom,ctl@1a00 {
- reg = <0x1a00 0x100>;
- };
- qcom,ps@1b00 {
- reg = <0x1b00 0x100>;
- };
- qcom,freq@1c00 {
- reg = <0x1c00 0x100>;
- };
- };
-
- regulator@a000 {
- regulator-name = "8941_boost";
- reg = <0xa000 0x100>;
- compatible = "qcom,qpnp-regulator";
- status = "disabled";
- };
-
- regulator@4000 {
- regulator-name = "8941_l1";
+ qcom,bms-bms@4000 {
reg = <0x4000 0x100>;
- compatible = "qcom,qpnp-regulator";
+ interrupts = <0x0 0x40 0x0>,
+ <0x0 0x40 0x1>,
+ <0x0 0x40 0x2>,
+ <0x0 0x40 0x3>,
+ <0x0 0x40 0x4>,
+ <0x0 0x40 0x5>,
+ <0x0 0x40 0x6>,
+ <0x0 0x40 0x7>;
+
+ interrupt-names = "cc_thr",
+ "ocv_for_r",
+ "good_ocv",
+ "charge_begin",
+ "ocv_thr",
+ "sw_cc_thr",
+ "vsense_avg",
+ "vsense_for_r";
+ };
+ };
+
+ clkdiv@5b00 {
+ reg = <0x5b00 0x100>;
+ compatible = "qcom,qpnp-clkdiv";
+ qcom,cxo-freq = <19200000>;
+ };
+
+ clkdiv@5c00 {
+ reg = <0x5c00 0x100>;
+ compatible = "qcom,qpnp-clkdiv";
+ qcom,cxo-freq = <19200000>;
+ };
+
+ clkdiv@5d00 {
+ reg = <0x5d00 0x1000>;
+ compatible = "qcom,qpnp-clkdiv";
+ qcom,cxo-freq = <19200000>;
+ };
+
+ pm8941_chg: qcom,charger {
+ spmi-dev-container;
+ compatible = "qcom,qpnp-charger";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ status = "disabled";
+
+ qcom,vddmax-mv = <4200>;
+ qcom,vddsafe-mv = <4230>;
+ qcom,vinmin-mv = <4300>;
+ qcom,ibatmax-ma = <1500>;
+ qcom,ibatterm-ma = <100>;
+ qcom,ibatsafe-ma = <1500>;
+ qcom,thermal-mitigation = <1500 700 600 325>;
+ qcom,cool-bat-decidegc = <100>;
+ qcom,cool-bat-mv = <4100>;
+ qcom,ibatmax-warm-ma = <350>;
+ qcom,warm-bat-decidegc = <450>;
+ qcom,warm-bat-mv = <4100>;
+ qcom,ibatmax-cool-ma = <350>;
+ qcom,vbatdet-delta-mv = <100>;
+ qcom,resume-soc = <99>;
+ qcom,tchg-mins = <150>;
+
+ qcom,chgr@1000 {
status = "disabled";
+ 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 = "vbat-det-lo",
+ "vbat-det-hi",
+ "chgwdog",
+ "state-change",
+ "trkl-chg-on",
+ "fast-chg-on",
+ "chg-failed",
+ "chg-done";
};
- regulator@4100 {
- regulator-name = "8941_l2";
- reg = <0x4100 0x100>;
- compatible = "qcom,qpnp-regulator";
+ qcom,buck@1100 {
status = "disabled";
+ 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 = "vbat-ov",
+ "vreg-ov",
+ "overtemp",
+ "vchg-loop",
+ "ichg-loop",
+ "ibat-loop",
+ "vdd-loop";
};
- regulator@4200 {
- regulator-name = "8941_l3";
- reg = <0x4200 0x100>;
- compatible = "qcom,qpnp-regulator";
+ qcom,bat-if@1200 {
status = "disabled";
+ reg = <0x1200 0x100>;
+ interrupts = <0x0 0x12 0x0>,
+ <0x0 0x12 0x1>,
+ <0x0 0x12 0x2>,
+ <0x0 0x12 0x3>,
+ <0x0 0x12 0x4>;
+
+ interrupt-names = "batt-pres",
+ "bat-temp-ok",
+ "bat-fet-on",
+ "vcp-on",
+ "psi";
+
};
- regulator@4300 {
- regulator-name = "8941_l4";
- reg = <0x4300 0x100>;
- compatible = "qcom,qpnp-regulator";
+ pm8941_chg_otg: qcom,usb-chgpth@1300 {
status = "disabled";
+ reg = <0x1300 0x100>;
+ interrupts = <0 0x13 0x0>,
+ <0 0x13 0x1>,
+ <0x0 0x13 0x2>;
+
+ interrupt-names = "coarse-det-usb",
+ "usbin-valid",
+ "chg-gone";
};
- regulator@4400 {
- regulator-name = "8941_l5";
- reg = <0x4400 0x100>;
- compatible = "qcom,qpnp-regulator";
- qcom,force-type = <0x04 0x10>;
+ qcom,dc-chgpth@1400 {
status = "disabled";
+ reg = <0x1400 0x100>;
+ interrupts = <0x0 0x14 0x0>,
+ <0x0 0x14 0x1>;
+
+ interrupt-names = "coarse-det-dc",
+ "dcin-valid";
};
- regulator@4500 {
- regulator-name = "8941_l6";
- reg = <0x4500 0x100>;
- compatible = "qcom,qpnp-regulator";
+ pm8941_chg_boost: qcom,boost@1500 {
status = "disabled";
+ reg = <0x1500 0x100>;
+ interrupts = <0x0 0x15 0x0>,
+ <0x0 0x15 0x1>;
+
+ interrupt-names = "boost-pwr-ok",
+ "limit-error";
};
- regulator@4600 {
- regulator-name = "8941_l7";
- reg = <0x4600 0x100>;
- compatible = "qcom,qpnp-regulator";
- qcom,force-type = <0x04 0x10>;
+ qcom,chg-misc@1600 {
status = "disabled";
+ reg = <0x1600 0x100>;
};
+ };
- regulator@4700 {
- regulator-name = "8941_l8";
- reg = <0x4700 0x100>;
- compatible = "qcom,qpnp-regulator";
- status = "disabled";
- };
+ pm8941_gpios: gpios {
+ spmi-dev-container;
+ compatible = "qcom,qpnp-pin";
+ gpio-controller;
+ #gpio-cells = <2>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ label = "pm8941-gpio";
- regulator@4800 {
- regulator-name = "8941_l9";
- reg = <0x4800 0x100>;
- compatible = "qcom,qpnp-regulator";
- status = "disabled";
- };
-
- regulator@4900 {
- regulator-name = "8941_l10";
- reg = <0x4900 0x100>;
- compatible = "qcom,qpnp-regulator";
- status = "disabled";
- };
-
- regulator@4a00 {
- regulator-name = "8941_l11";
- reg = <0x4a00 0x100>;
- compatible = "qcom,qpnp-regulator";
- status = "disabled";
- };
-
- regulator@4b00 {
- regulator-name = "8941_l12";
- reg = <0x4b00 0x100>;
- compatible = "qcom,qpnp-regulator";
- status = "disabled";
- };
-
- regulator@4c00 {
- regulator-name = "8941_l13";
- reg = <0x4c00 0x100>;
- compatible = "qcom,qpnp-regulator";
- status = "disabled";
- };
-
- regulator@4d00 {
- regulator-name = "8941_l14";
- reg = <0x4d00 0x100>;
- compatible = "qcom,qpnp-regulator";
- status = "disabled";
- };
-
- regulator@4e00 {
- regulator-name = "8941_l15";
- reg = <0x4e00 0x100>;
- compatible = "qcom,qpnp-regulator";
- status = "disabled";
- };
-
- regulator@4f00 {
- regulator-name = "8941_l16";
- reg = <0x4f00 0x100>;
- compatible = "qcom,qpnp-regulator";
- status = "disabled";
- };
-
- regulator@5000 {
- regulator-name = "8941_l17";
- reg = <0x5000 0x100>;
- compatible = "qcom,qpnp-regulator";
- status = "disabled";
- };
-
- regulator@5100 {
- regulator-name = "8941_l18";
- reg = <0x5100 0x100>;
- compatible = "qcom,qpnp-regulator";
- status = "disabled";
- };
-
- regulator@5200 {
- regulator-name = "8941_l19";
- reg = <0x5200 0x100>;
- compatible = "qcom,qpnp-regulator";
- status = "disabled";
- };
-
- regulator@5300 {
- regulator-name = "8941_l20";
- reg = <0x5300 0x100>;
- compatible = "qcom,qpnp-regulator";
- status = "disabled";
- };
-
- regulator@5400 {
- regulator-name = "8941_l21";
- reg = <0x5400 0x100>;
- compatible = "qcom,qpnp-regulator";
- status = "disabled";
- };
-
- regulator@5500 {
- regulator-name = "8941_l22";
- reg = <0x5500 0x100>;
- compatible = "qcom,qpnp-regulator";
- status = "disabled";
- };
-
- regulator@5600 {
- regulator-name = "8941_l23";
- reg = <0x5600 0x100>;
- compatible = "qcom,qpnp-regulator";
- status = "disabled";
- };
-
- regulator@5700 {
- regulator-name = "8941_l24";
- reg = <0x5700 0x100>;
- compatible = "qcom,qpnp-regulator";
- status = "disabled";
- };
-
- regulator@8000 {
- regulator-name = "8941_lvs1";
- reg = <0x8000 0x100>;
- compatible = "qcom,qpnp-regulator";
- status = "disabled";
- };
-
- regulator@8100 {
- regulator-name = "8941_lvs2";
- reg = <0x8100 0x100>;
- compatible = "qcom,qpnp-regulator";
- status = "disabled";
- };
-
- regulator@8200 {
- regulator-name = "8941_lvs3";
- reg = <0x8200 0x100>;
- compatible = "qcom,qpnp-regulator";
- status = "disabled";
- };
-
- regulator@8300 {
- regulator-name = "8941_mvs1";
- reg = <0x8300 0x100>;
- compatible = "qcom,qpnp-regulator";
- status = "disabled";
- };
-
- regulator@8400 {
- regulator-name = "8941_mvs2";
- reg = <0x8400 0x100>;
- compatible = "qcom,qpnp-regulator";
- status = "disabled";
- };
-
- qcom,vibrator@c000 {
- compatible = "qcom,qpnp-vibrator";
+ gpio@c000 {
reg = <0xc000 0x100>;
- label = "vibrator";
- status = "disabled";
+ qcom,pin-num = <1>;
};
- qcom,leds@d000 {
- compatible = "qcom,leds-qpnp";
+ gpio@c100 {
+ reg = <0xc100 0x100>;
+ qcom,pin-num = <2>;
+ };
+
+ gpio@c200 {
+ reg = <0xc200 0x100>;
+ qcom,pin-num = <3>;
+ };
+
+ gpio@c300 {
+ reg = <0xc300 0x100>;
+ qcom,pin-num = <4>;
+ };
+
+ gpio@c400 {
+ reg = <0xc400 0x100>;
+ qcom,pin-num = <5>;
+ };
+
+ gpio@c500 {
+ reg = <0xc500 0x100>;
+ qcom,pin-num = <6>;
+ };
+
+ gpio@c600 {
+ reg = <0xc600 0x100>;
+ qcom,pin-num = <7>;
+ };
+
+ gpio@c700 {
+ reg = <0xc700 0x100>;
+ qcom,pin-num = <8>;
+ };
+
+ gpio@c800 {
+ reg = <0xc800 0x100>;
+ qcom,pin-num = <9>;
+ };
+
+ gpio@c900 {
+ reg = <0xc900 0x100>;
+ qcom,pin-num = <10>;
+ };
+
+ gpio@ca00 {
+ reg = <0xca00 0x100>;
+ qcom,pin-num = <11>;
+ };
+
+ gpio@cb00 {
+ reg = <0xcb00 0x100>;
+ qcom,pin-num = <12>;
+ };
+
+ gpio@cc00 {
+ reg = <0xcc00 0x100>;
+ qcom,pin-num = <13>;
+ };
+
+ gpio@cd00 {
+ reg = <0xcd00 0x100>;
+ qcom,pin-num = <14>;
+ };
+
+ gpio@ce00 {
+ reg = <0xce00 0x100>;
+ qcom,pin-num = <15>;
+ };
+
+ gpio@cf00 {
+ reg = <0xcf00 0x100>;
+ qcom,pin-num = <16>;
+ };
+
+ gpio@d000 {
reg = <0xd000 0x100>;
- label = "rgb";
+ qcom,pin-num = <17>;
};
- qcom,leds@d100 {
- compatible = "qcom,leds-qpnp";
+ gpio@d100 {
reg = <0xd100 0x100>;
- label = "rgb";
+ qcom,pin-num = <18>;
};
- qcom,leds@d200 {
- compatible = "qcom,leds-qpnp";
+ gpio@d200 {
reg = <0xd200 0x100>;
- label = "rgb";
+ qcom,pin-num = <19>;
};
- qcom,leds@d300 {
- compatible = "qcom,leds-qpnp";
+ gpio@d300 {
reg = <0xd300 0x100>;
- label = "flash";
- flash_boost-supply = <&pm8941_chg_boost>;
+ qcom,pin-num = <20>;
};
- qcom,leds@d400 {
- compatible = "qcom,leds-qpnp";
+ gpio@d400 {
reg = <0xd400 0x100>;
- label = "flash";
+ qcom,pin-num = <21>;
};
- qcom,leds@d500 {
- compatible = "qcom,leds-qpnp";
+ gpio@d500 {
reg = <0xd500 0x100>;
- label = "flash";
+ qcom,pin-num = <22>;
};
- qcom,leds@d600 {
- compatible = "qcom,leds-qpnp";
+ gpio@d600 {
reg = <0xd600 0x100>;
- label = "flash";
+ qcom,pin-num = <23>;
};
- qcom,leds@d700 {
- compatible = "qcom,leds-qpnp";
+ gpio@d700 {
reg = <0xd700 0x100>;
- label = "flash";
+ qcom,pin-num = <24>;
};
- qcom,leds@d800 {
- compatible = "qcom,leds-qpnp";
+ gpio@d800 {
reg = <0xd800 0x100>;
- label = "wled";
+ qcom,pin-num = <25>;
};
- qcom,leds@d900 {
- compatible = "qcom,leds-qpnp";
+ gpio@d900 {
reg = <0xd900 0x100>;
- label = "wled";
+ qcom,pin-num = <26>;
};
- qcom,leds@da00 {
- compatible = "qcom,leds-qpnp";
+ gpio@da00 {
reg = <0xda00 0x100>;
- label = "wled";
+ qcom,pin-num = <27>;
};
- qcom,leds@db00 {
- compatible = "qcom,leds-qpnp";
+ gpio@db00 {
reg = <0xdb00 0x100>;
- label = "wled";
+ qcom,pin-num = <28>;
};
- qcom,leds@dc00 {
- compatible = "qcom,leds-qpnp";
+ gpio@dc00 {
reg = <0xdc00 0x100>;
- label = "wled";
+ qcom,pin-num = <29>;
};
- qcom,leds@dd00 {
- compatible = "qcom,leds-qpnp";
+ gpio@dd00 {
reg = <0xdd00 0x100>;
- label = "wled";
+ qcom,pin-num = <30>;
};
- qcom,leds@de00 {
- compatible = "qcom,leds-qpnp";
+ gpio@de00 {
reg = <0xde00 0x100>;
- label = "wled";
+ qcom,pin-num = <31>;
};
- qcom,leds@df00 {
- compatible = "qcom,leds-qpnp";
+ gpio@df00 {
reg = <0xdf00 0x100>;
- label = "wled";
+ qcom,pin-num = <32>;
};
- qcom,leds@e000 {
- compatible = "qcom,leds-qpnp";
+ gpio@e000 {
reg = <0xe000 0x100>;
- label = "wled";
+ qcom,pin-num = <33>;
};
- qcom,leds@e100 {
- compatible = "qcom,leds-qpnp";
+ gpio@e100 {
reg = <0xe100 0x100>;
- label = "wled";
+ qcom,pin-num = <34>;
};
- pwm@b100 {
- compatible = "qcom,qpnp-pwm";
- reg = <0xb100 0x100>,
- <0xb042 0x7e>;
- reg-names = "qpnp-lpg-channel-base", "qpnp-lpg-lut-base";
- qcom,channel-id = <0>;
+ gpio@e200 {
+ reg = <0xe200 0x100>;
+ qcom,pin-num = <35>;
};
- pwm@b200 {
- compatible = "qcom,qpnp-pwm";
- reg = <0xb200 0x100>,
- <0xb042 0x7e>;
- reg-names = "qpnp-lpg-channel-base", "qpnp-lpg-lut-base";
- qcom,channel-id = <1>;
+ gpio@e300 {
+ reg = <0xe300 0x100>;
+ qcom,pin-num = <36>;
+ };
+ };
+
+ pm8941_mpps: mpps {
+ spmi-dev-container;
+ compatible = "qcom,qpnp-pin";
+ gpio-controller;
+ #gpio-cells = <2>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ label = "pm8941-mpp";
+
+ mpp@a000 {
+ reg = <0xa000 0x100>;
+ qcom,pin-num = <1>;
};
- pwm@b300 {
- compatible = "qcom,qpnp-pwm";
- reg = <0xb300 0x100>,
- <0xb042 0x7e>;
- reg-names = "qpnp-lpg-channel-base", "qpnp-lpg-lut-base";
- qcom,channel-id = <2>;
+ mpp@a100 {
+ reg = <0xa100 0x100>;
+ qcom,pin-num = <2>;
};
- pwm@b400 {
- compatible = "qcom,qpnp-pwm";
- reg = <0xb400 0x100>,
- <0xb042 0x7e>;
- reg-names = "qpnp-lpg-channel-base", "qpnp-lpg-lut-base";
- qcom,channel-id = <3>;
+ mpp@a200 {
+ reg = <0xa200 0x100>;
+ qcom,pin-num = <3>;
};
- pwm@b500 {
- compatible = "qcom,qpnp-pwm";
- reg = <0xb500 0x100>,
- <0xb042 0x7e>;
- reg-names = "qpnp-lpg-channel-base", "qpnp-lpg-lut-base";
- qcom,channel-id = <4>;
+ mpp@a300 {
+ reg = <0xa300 0x100>;
+ qcom,pin-num = <4>;
};
- pwm@b600 {
- compatible = "qcom,qpnp-pwm";
- reg = <0xb600 0x100>,
- <0xb042 0x7e>;
- reg-names = "qpnp-lpg-channel-base", "qpnp-lpg-lut-base";
- qcom,channel-id = <5>;
+ mpp@a400 {
+ reg = <0xa400 0x100>;
+ qcom,pin-num = <5>;
};
- pwm@b700 {
- compatible = "qcom,qpnp-pwm";
- reg = <0xb700 0x100>,
- <0xb042 0x7e>;
- reg-names = "qpnp-lpg-channel-base", "qpnp-lpg-lut-base";
- qcom,channel-id = <6>;
+ mpp@a500 {
+ reg = <0xa500 0x100>;
+ qcom,pin-num = <6>;
};
- pwm@b800 {
- compatible = "qcom,qpnp-pwm";
- reg = <0xb800 0x100>,
- <0xb042 0x7e>;
- reg-names = "qpnp-lpg-channel-base", "qpnp-lpg-lut-base";
- qcom,channel-id = <7>;
+ mpp@a600 {
+ reg = <0xa600 0x100>;
+ qcom,pin-num = <7>;
};
+
+ mpp@a700 {
+ reg = <0xa700 0x100>;
+ qcom,pin-num = <8>;
+ };
+ };
+
+ qcom,pm8941_rtc {
+ spmi-dev-container;
+ compatible = "qcom,qpnp-rtc";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ qcom,qpnp-rtc-write = <0>;
+ qcom,qpnp-rtc-alarm-pwrup = <0>;
+
+ qcom,pm8941_rtc_rw@6000 {
+ reg = <0x6000 0x100>;
+ };
+ qcom,pm8941_rtc_alarm@6100 {
+ reg = <0x6100 0x100>;
+ interrupts = <0x0 0x61 0x1>;
+ };
+ };
+
+ pm8941_vadc: vadc@3100 {
+ compatible = "qcom,qpnp-vadc";
+ reg = <0x3100 0x100>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupts = <0x0 0x31 0x0>;
+ interrupt-names = "eoc-int-en-set";
+ qcom,adc-bit-resolution = <15>;
+ qcom,adc-vdd-reference = <1800>;
+
+ chan@0 {
+ label = "usb_in";
+ reg = <0>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <4>;
+ qcom,calibration-type = "absolute";
+ qcom,scale-function = <0>;
+ qcom,hw-settle-time = <0>;
+ qcom,fast-avg-setup = <0>;
+ };
+
+ chan@1 {
+ label = "dc_in";
+ reg = <1>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <4>;
+ qcom,calibration-type = "absolute";
+ qcom,scale-function = <0>;
+ qcom,hw-settle-time = <0>;
+ qcom,fast-avg-setup = <0>;
+ };
+
+ chan@2 {
+ label = "vchg_sns";
+ reg = <2>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <3>;
+ qcom,calibration-type = "absolute";
+ qcom,scale-function = <0>;
+ qcom,hw-settle-time = <0>;
+ qcom,fast-avg-setup = <0>;
+ };
+
+ chan@3 {
+ label = "spare1_div3";
+ reg = <3>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <1>;
+ qcom,calibration-type = "absolute";
+ qcom,scale-function = <0>;
+ qcom,hw-settle-time = <0>;
+ qcom,fast-avg-setup = <0>;
+ };
+
+ chan@4 {
+ label = "usb_id_mv";
+ reg = <4>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <1>;
+ qcom,calibration-type = "absolute";
+ qcom,scale-function = <0>;
+ qcom,hw-settle-time = <0>;
+ qcom,fast-avg-setup = <0>;
+ };
+
+ chan@5 {
+ label = "vcoin";
+ reg = <5>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <1>;
+ qcom,calibration-type = "absolute";
+ qcom,scale-function = <0>;
+ qcom,hw-settle-time = <0>;
+ qcom,fast-avg-setup = <0>;
+ };
+
+ chan@6 {
+ label = "vbat_sns";
+ reg = <6>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <1>;
+ qcom,calibration-type = "absolute";
+ qcom,scale-function = <0>;
+ qcom,hw-settle-time = <0>;
+ qcom,fast-avg-setup = <0>;
+ };
+
+ chan@7 {
+ label = "vph_pwr";
+ reg = <7>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <1>;
+ qcom,calibration-type = "absolute";
+ qcom,scale-function = <0>;
+ qcom,hw-settle-time = <0>;
+ qcom,fast-avg-setup = <0>;
+ };
+
+ chan@8 {
+ label = "die_temp";
+ reg = <8>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "absolute";
+ qcom,scale-function = <3>;
+ qcom,hw-settle-time = <0>;
+ qcom,fast-avg-setup = <0>;
+ };
+
+ chan@9 {
+ label = "ref_625mv";
+ reg = <9>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "absolute";
+ qcom,scale-function = <0>;
+ qcom,hw-settle-time = <0>;
+ qcom,fast-avg-setup = <0>;
+ };
+
+ chan@a {
+ label = "ref_1250v";
+ reg = <0xa>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "absolute";
+ qcom,scale-function = <0>;
+ qcom,hw-settle-time = <0>;
+ qcom,fast-avg-setup = <0>;
+ };
+
+ chan@30 {
+ label = "batt_therm";
+ reg = <0x30>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <1>;
+ qcom,hw-settle-time = <2>;
+ qcom,fast-avg-setup = <0>;
+ };
+
+ chan@31 {
+ label = "batt_id";
+ reg = <0x31>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <0>;
+ qcom,hw-settle-time = <2>;
+ qcom,fast-avg-setup = <0>;
+ };
+
+ chan@b2 {
+ label = "xo_therm_pu2";
+ reg = <0xb2>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <4>;
+ qcom,hw-settle-time = <2>;
+ qcom,fast-avg-setup = <0>;
+ };
+
+ chan@b3 {
+ label = "msm_therm";
+ reg = <0xb3>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <2>;
+ qcom,hw-settle-time = <2>;
+ qcom,fast-avg-setup = <0>;
+ };
+
+ chan@b4 {
+ label = "emmc_therm";
+ reg = <0xb4>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <2>;
+ qcom,hw-settle-time = <2>;
+ qcom,fast-avg-setup = <0>;
+ };
+
+ chan@b5 {
+ label = "pa_therm0";
+ reg = <0xb5>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <2>;
+ qcom,hw-settle-time = <2>;
+ qcom,fast-avg-setup = <0>;
+ };
+
+ chan@b7 {
+ label = "pa_therm1";
+ reg = <0xb7>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <2>;
+ qcom,hw-settle-time = <2>;
+ qcom,fast-avg-setup = <0>;
+ };
+
+ chan@b8 {
+ label = "quiet_therm";
+ reg = <0xb8>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <2>;
+ qcom,hw-settle-time = <2>;
+ qcom,fast-avg-setup = <0>;
+ };
+
+ chan@b9 {
+ label = "usb_id";
+ reg = <0xb9>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <0>;
+ qcom,hw-settle-time = <2>;
+ qcom,fast-avg-setup = <0>;
+ };
+
+ chan@39 {
+ label = "usb_id_nopull";
+ reg = <0x39>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <0>;
+ qcom,hw-settle-time = <2>;
+ qcom,fast-avg-setup = <0>;
+ };
+ };
+
+ pm8941_iadc: iadc@3600 {
+ compatible = "qcom,qpnp-iadc";
+ reg = <0x3600 0x100>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupts = <0x0 0x36 0x0>;
+ interrupt-names = "eoc-int-en-set";
+ qcom,adc-bit-resolution = <16>;
+ qcom,adc-vdd-reference = <1800>;
+
+ chan@0 {
+ label = "internal_rsense";
+ reg = <0>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <1>;
+ qcom,calibration-type = "absolute";
+ qcom,scale-function = <0>;
+ qcom,hw-settle-time = <0>;
+ qcom,fast-avg-setup = <0>;
+ };
+ };
+
+ pm8941_adc_tm: qcom,vadc@3400 {
+ compatible = "qcom,qpnp-adc-tm";
+ reg = <0x3400 0x100>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupts = <0x0 0x34 0x0>,
+ <0x0 0x34 0x3>,
+ <0x0 0x34 0x4>;
+ interrupt-names = "eoc-int-en-set",
+ "high-thr-en-set",
+ "low-thr-en-set";
+ qcom,adc-bit-resolution = <15>;
+ qcom,adc-vdd-reference = <1800>;
+
+ /* Channel Node */
+ chan@b9 {
+ label = "usb_id";
+ reg = <0xb9>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <2>;
+ qcom,hw-settle-time = <2>;
+ qcom,fast-avg-setup = <3>;
+ qcom,btm-channel-number = <0x48>;
+ };
+
+ chan@30 {
+ label = "batt_therm";
+ reg = <0x30>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <1>;
+ qcom,hw-settle-time = <2>;
+ qcom,fast-avg-setup = <3>;
+ qcom,btm-channel-number = <0x68>;
+ };
+
+ chan@8 {
+ label = "die_temp";
+ reg = <8>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "absolute";
+ qcom,scale-function = <3>;
+ qcom,hw-settle-time = <0>;
+ qcom,fast-avg-setup = <3>;
+ qcom,btm-channel-number = <0x70>;
+ };
+
+ chan@6 {
+ label = "vbat_sns";
+ reg = <6>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <1>;
+ qcom,calibration-type = "absolute";
+ qcom,scale-function = <0>;
+ qcom,hw-settle-time = <0>;
+ qcom,fast-avg-setup = <3>;
+ qcom,btm-channel-number = <0x78>;
+ };
+
+ chan@b5 {
+ label = "pa_therm0";
+ reg = <0xb5>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <2>;
+ qcom,hw-settle-time = <2>;
+ qcom,fast-avg-setup = <3>;
+ qcom,btm-channel-number = <0x80>;
+ qcom,thermal-node;
+ };
+
+ chan@b7 {
+ label = "pa_therm1";
+ reg = <0xb7>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <2>;
+ qcom,hw-settle-time = <2>;
+ qcom,fast-avg-setup = <3>;
+ qcom,btm-channel-number = <0x88>;
+ qcom,thermal-node;
+ };
+
+ chan@b4 {
+ label = "emmc_therm";
+ reg = <0xb4>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <2>;
+ qcom,hw-settle-time = <2>;
+ qcom,fast-avg-setup = <3>;
+ qcom,btm-channel-number = <0x90>;
+ qcom,thermal-node;
+ };
+
+ chan@b3 {
+ label = "msm_therm";
+ reg = <0xb3>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <2>;
+ qcom,hw-settle-time = <2>;
+ qcom,fast-avg-setup = <3>;
+ qcom,btm-channel-number = <0x98>;
+ qcom,thermal-node;
+ };
+ };
+};
+
+&pm8941_lsid1 {
+ spmi-slave-container;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ regulator@1400 {
+ regulator-name = "8941_s1";
+ spmi-dev-container;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "qcom,qpnp-regulator";
+ reg = <0x1400 0x300>;
+ status = "disabled";
+
+ qcom,ctl@1400 {
+ reg = <0x1400 0x100>;
+ };
+ qcom,ps@1500 {
+ reg = <0x1500 0x100>;
+ };
+ qcom,freq@1600 {
+ reg = <0x1600 0x100>;
+ };
+ };
+
+ regulator@1700 {
+ regulator-name = "8941_s2";
+ spmi-dev-container;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "qcom,qpnp-regulator";
+ reg = <0x1700 0x300>;
+ status = "disabled";
+
+ qcom,ctl@1700 {
+ reg = <0x1700 0x100>;
+ };
+ qcom,ps@1800 {
+ reg = <0x1800 0x100>;
+ };
+ qcom,freq@1900 {
+ reg = <0x1900 0x100>;
+ };
+ };
+
+ regulator@1a00 {
+ regulator-name = "8941_s3";
+ spmi-dev-container;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "qcom,qpnp-regulator";
+ reg = <0x1a00 0x300>;
+ status = "disabled";
+
+ qcom,ctl@1a00 {
+ reg = <0x1a00 0x100>;
+ };
+ qcom,ps@1b00 {
+ reg = <0x1b00 0x100>;
+ };
+ qcom,freq@1c00 {
+ reg = <0x1c00 0x100>;
+ };
+ };
+
+ regulator@a000 {
+ regulator-name = "8941_boost";
+ reg = <0xa000 0x100>;
+ compatible = "qcom,qpnp-regulator";
+ status = "disabled";
+ };
+
+ regulator@4000 {
+ regulator-name = "8941_l1";
+ reg = <0x4000 0x100>;
+ compatible = "qcom,qpnp-regulator";
+ status = "disabled";
+ };
+
+ regulator@4100 {
+ regulator-name = "8941_l2";
+ reg = <0x4100 0x100>;
+ compatible = "qcom,qpnp-regulator";
+ status = "disabled";
+ };
+
+ regulator@4200 {
+ regulator-name = "8941_l3";
+ reg = <0x4200 0x100>;
+ compatible = "qcom,qpnp-regulator";
+ status = "disabled";
+ };
+
+ regulator@4300 {
+ regulator-name = "8941_l4";
+ reg = <0x4300 0x100>;
+ compatible = "qcom,qpnp-regulator";
+ status = "disabled";
+ };
+
+ regulator@4400 {
+ regulator-name = "8941_l5";
+ reg = <0x4400 0x100>;
+ compatible = "qcom,qpnp-regulator";
+ qcom,force-type = <0x04 0x10>;
+ status = "disabled";
+ };
+
+ regulator@4500 {
+ regulator-name = "8941_l6";
+ reg = <0x4500 0x100>;
+ compatible = "qcom,qpnp-regulator";
+ status = "disabled";
+ };
+
+ regulator@4600 {
+ regulator-name = "8941_l7";
+ reg = <0x4600 0x100>;
+ compatible = "qcom,qpnp-regulator";
+ qcom,force-type = <0x04 0x10>;
+ status = "disabled";
+ };
+
+ regulator@4700 {
+ regulator-name = "8941_l8";
+ reg = <0x4700 0x100>;
+ compatible = "qcom,qpnp-regulator";
+ status = "disabled";
+ };
+
+ regulator@4800 {
+ regulator-name = "8941_l9";
+ reg = <0x4800 0x100>;
+ compatible = "qcom,qpnp-regulator";
+ status = "disabled";
+ };
+
+ regulator@4900 {
+ regulator-name = "8941_l10";
+ reg = <0x4900 0x100>;
+ compatible = "qcom,qpnp-regulator";
+ status = "disabled";
+ };
+
+ regulator@4a00 {
+ regulator-name = "8941_l11";
+ reg = <0x4a00 0x100>;
+ compatible = "qcom,qpnp-regulator";
+ status = "disabled";
+ };
+
+ regulator@4b00 {
+ regulator-name = "8941_l12";
+ reg = <0x4b00 0x100>;
+ compatible = "qcom,qpnp-regulator";
+ status = "disabled";
+ };
+
+ regulator@4c00 {
+ regulator-name = "8941_l13";
+ reg = <0x4c00 0x100>;
+ compatible = "qcom,qpnp-regulator";
+ status = "disabled";
+ };
+
+ regulator@4d00 {
+ regulator-name = "8941_l14";
+ reg = <0x4d00 0x100>;
+ compatible = "qcom,qpnp-regulator";
+ status = "disabled";
+ };
+
+ regulator@4e00 {
+ regulator-name = "8941_l15";
+ reg = <0x4e00 0x100>;
+ compatible = "qcom,qpnp-regulator";
+ status = "disabled";
+ };
+
+ regulator@4f00 {
+ regulator-name = "8941_l16";
+ reg = <0x4f00 0x100>;
+ compatible = "qcom,qpnp-regulator";
+ status = "disabled";
+ };
+
+ regulator@5000 {
+ regulator-name = "8941_l17";
+ reg = <0x5000 0x100>;
+ compatible = "qcom,qpnp-regulator";
+ status = "disabled";
+ };
+
+ regulator@5100 {
+ regulator-name = "8941_l18";
+ reg = <0x5100 0x100>;
+ compatible = "qcom,qpnp-regulator";
+ status = "disabled";
+ };
+
+ regulator@5200 {
+ regulator-name = "8941_l19";
+ reg = <0x5200 0x100>;
+ compatible = "qcom,qpnp-regulator";
+ status = "disabled";
+ };
+
+ regulator@5300 {
+ regulator-name = "8941_l20";
+ reg = <0x5300 0x100>;
+ compatible = "qcom,qpnp-regulator";
+ status = "disabled";
+ };
+
+ regulator@5400 {
+ regulator-name = "8941_l21";
+ reg = <0x5400 0x100>;
+ compatible = "qcom,qpnp-regulator";
+ status = "disabled";
+ };
+
+ regulator@5500 {
+ regulator-name = "8941_l22";
+ reg = <0x5500 0x100>;
+ compatible = "qcom,qpnp-regulator";
+ status = "disabled";
+ };
+
+ regulator@5600 {
+ regulator-name = "8941_l23";
+ reg = <0x5600 0x100>;
+ compatible = "qcom,qpnp-regulator";
+ status = "disabled";
+ };
+
+ regulator@5700 {
+ regulator-name = "8941_l24";
+ reg = <0x5700 0x100>;
+ compatible = "qcom,qpnp-regulator";
+ status = "disabled";
+ };
+
+ regulator@8000 {
+ regulator-name = "8941_lvs1";
+ reg = <0x8000 0x100>;
+ compatible = "qcom,qpnp-regulator";
+ status = "disabled";
+ };
+
+ regulator@8100 {
+ regulator-name = "8941_lvs2";
+ reg = <0x8100 0x100>;
+ compatible = "qcom,qpnp-regulator";
+ status = "disabled";
+ };
+
+ regulator@8200 {
+ regulator-name = "8941_lvs3";
+ reg = <0x8200 0x100>;
+ compatible = "qcom,qpnp-regulator";
+ status = "disabled";
+ };
+
+ regulator@8300 {
+ regulator-name = "8941_mvs1";
+ reg = <0x8300 0x100>;
+ compatible = "qcom,qpnp-regulator";
+ status = "disabled";
+ };
+
+ regulator@8400 {
+ regulator-name = "8941_mvs2";
+ reg = <0x8400 0x100>;
+ compatible = "qcom,qpnp-regulator";
+ status = "disabled";
+ };
+
+ qcom,vibrator@c000 {
+ compatible = "qcom,qpnp-vibrator";
+ reg = <0xc000 0x100>;
+ label = "vibrator";
+ status = "disabled";
+ };
+
+ qcom,leds@d000 {
+ compatible = "qcom,leds-qpnp";
+ reg = <0xd000 0x100>;
+ label = "rgb";
+ };
+
+ qcom,leds@d100 {
+ compatible = "qcom,leds-qpnp";
+ reg = <0xd100 0x100>;
+ label = "rgb";
+ };
+
+ qcom,leds@d200 {
+ compatible = "qcom,leds-qpnp";
+ reg = <0xd200 0x100>;
+ label = "rgb";
+ };
+
+ qcom,leds@d300 {
+ compatible = "qcom,leds-qpnp";
+ reg = <0xd300 0x100>;
+ label = "flash";
+ flash_boost-supply = <&pm8941_chg_boost>;
+ };
+
+ qcom,leds@d400 {
+ compatible = "qcom,leds-qpnp";
+ reg = <0xd400 0x100>;
+ label = "flash";
+ };
+
+ qcom,leds@d500 {
+ compatible = "qcom,leds-qpnp";
+ reg = <0xd500 0x100>;
+ label = "flash";
+ };
+
+ qcom,leds@d600 {
+ compatible = "qcom,leds-qpnp";
+ reg = <0xd600 0x100>;
+ label = "flash";
+ };
+
+ qcom,leds@d700 {
+ compatible = "qcom,leds-qpnp";
+ reg = <0xd700 0x100>;
+ label = "flash";
+ };
+
+ qcom,leds@d800 {
+ compatible = "qcom,leds-qpnp";
+ reg = <0xd800 0x100>;
+ label = "wled";
+ };
+
+ qcom,leds@d900 {
+ compatible = "qcom,leds-qpnp";
+ reg = <0xd900 0x100>;
+ label = "wled";
+ };
+
+ qcom,leds@da00 {
+ compatible = "qcom,leds-qpnp";
+ reg = <0xda00 0x100>;
+ label = "wled";
+ };
+
+ qcom,leds@db00 {
+ compatible = "qcom,leds-qpnp";
+ reg = <0xdb00 0x100>;
+ label = "wled";
+ };
+
+ qcom,leds@dc00 {
+ compatible = "qcom,leds-qpnp";
+ reg = <0xdc00 0x100>;
+ label = "wled";
+ };
+
+ qcom,leds@dd00 {
+ compatible = "qcom,leds-qpnp";
+ reg = <0xdd00 0x100>;
+ label = "wled";
+ };
+
+ qcom,leds@de00 {
+ compatible = "qcom,leds-qpnp";
+ reg = <0xde00 0x100>;
+ label = "wled";
+ };
+
+ qcom,leds@df00 {
+ compatible = "qcom,leds-qpnp";
+ reg = <0xdf00 0x100>;
+ label = "wled";
+ };
+
+ qcom,leds@e000 {
+ compatible = "qcom,leds-qpnp";
+ reg = <0xe000 0x100>;
+ label = "wled";
+ };
+
+ qcom,leds@e100 {
+ compatible = "qcom,leds-qpnp";
+ reg = <0xe100 0x100>;
+ label = "wled";
+ };
+
+ pwm@b100 {
+ compatible = "qcom,qpnp-pwm";
+ reg = <0xb100 0x100>,
+ <0xb042 0x7e>;
+ reg-names = "qpnp-lpg-channel-base", "qpnp-lpg-lut-base";
+ qcom,channel-id = <0>;
+ };
+
+ pwm@b200 {
+ compatible = "qcom,qpnp-pwm";
+ reg = <0xb200 0x100>,
+ <0xb042 0x7e>;
+ reg-names = "qpnp-lpg-channel-base", "qpnp-lpg-lut-base";
+ qcom,channel-id = <1>;
+ };
+
+ pwm@b300 {
+ compatible = "qcom,qpnp-pwm";
+ reg = <0xb300 0x100>,
+ <0xb042 0x7e>;
+ reg-names = "qpnp-lpg-channel-base", "qpnp-lpg-lut-base";
+ qcom,channel-id = <2>;
+ };
+
+ pwm@b400 {
+ compatible = "qcom,qpnp-pwm";
+ reg = <0xb400 0x100>,
+ <0xb042 0x7e>;
+ reg-names = "qpnp-lpg-channel-base", "qpnp-lpg-lut-base";
+ qcom,channel-id = <3>;
+ };
+
+ pwm@b500 {
+ compatible = "qcom,qpnp-pwm";
+ reg = <0xb500 0x100>,
+ <0xb042 0x7e>;
+ reg-names = "qpnp-lpg-channel-base", "qpnp-lpg-lut-base";
+ qcom,channel-id = <4>;
+ };
+
+ pwm@b600 {
+ compatible = "qcom,qpnp-pwm";
+ reg = <0xb600 0x100>,
+ <0xb042 0x7e>;
+ reg-names = "qpnp-lpg-channel-base", "qpnp-lpg-lut-base";
+ qcom,channel-id = <5>;
+ };
+
+ pwm@b700 {
+ compatible = "qcom,qpnp-pwm";
+ reg = <0xb700 0x100>,
+ <0xb042 0x7e>;
+ reg-names = "qpnp-lpg-channel-base", "qpnp-lpg-lut-base";
+ qcom,channel-id = <6>;
+ };
+
+ pwm@b800 {
+ compatible = "qcom,qpnp-pwm";
+ reg = <0xb800 0x100>,
+ <0xb042 0x7e>;
+ reg-names = "qpnp-lpg-channel-base", "qpnp-lpg-lut-base";
+ qcom,channel-id = <7>;
};
};
diff --git a/arch/arm/boot/dts/msm-pma8084-rpm-regulator.dtsi b/arch/arm/boot/dts/msm-pma8084-rpm-regulator.dtsi
new file mode 100644
index 0000000..31796dd
--- /dev/null
+++ b/arch/arm/boot/dts/msm-pma8084-rpm-regulator.dtsi
@@ -0,0 +1,712 @@
+/* Copyright (c) 2013, 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.
+ */
+
+&rpm_bus {
+ rpm-regulator-smpa1 {
+ compatible = "qcom,rpm-regulator-smd-resource";
+ qcom,resource-name = "smpa";
+ qcom,resource-id = <1>;
+ qcom,regulator-type = <1>;
+ qcom,hpm-min-load = <100000>;
+ status = "disabled";
+
+ regulator-s1 {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8084_s1";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-smpa2 {
+ compatible = "qcom,rpm-regulator-smd-resource";
+ qcom,resource-name = "smpa";
+ qcom,resource-id = <2>;
+ qcom,regulator-type = <1>;
+ qcom,hpm-min-load = <100000>;
+ status = "disabled";
+
+ regulator-s2 {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8084_s2";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-smpa3 {
+ compatible = "qcom,rpm-regulator-smd-resource";
+ qcom,resource-name = "smpa";
+ qcom,resource-id = <3>;
+ qcom,regulator-type = <1>;
+ qcom,hpm-min-load = <100000>;
+ status = "disabled";
+
+ regulator-s3 {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8084_s3";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-smpa4 {
+ compatible = "qcom,rpm-regulator-smd-resource";
+ qcom,resource-name = "smpa";
+ qcom,resource-id = <4>;
+ qcom,regulator-type = <1>;
+ qcom,hpm-min-load = <100000>;
+ status = "disabled";
+
+ regulator-s4 {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8084_s4";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-smpa5 {
+ compatible = "qcom,rpm-regulator-smd-resource";
+ qcom,resource-name = "smpa";
+ qcom,resource-id = <5>;
+ qcom,regulator-type = <1>;
+ qcom,hpm-min-load = <100000>;
+ status = "disabled";
+
+ regulator-s5 {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8084_s5";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-smpa6 {
+ compatible = "qcom,rpm-regulator-smd-resource";
+ qcom,resource-name = "smpa";
+ qcom,resource-id = <6>;
+ qcom,regulator-type = <1>;
+ qcom,hpm-min-load = <100000>;
+ status = "disabled";
+
+ regulator-s6 {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8084_s6";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-smpa7 {
+ compatible = "qcom,rpm-regulator-smd-resource";
+ qcom,resource-name = "smpa";
+ qcom,resource-id = <7>;
+ qcom,regulator-type = <1>;
+ qcom,hpm-min-load = <100000>;
+ status = "disabled";
+
+ regulator-s7 {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8084_s7";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-smpa8 {
+ compatible = "qcom,rpm-regulator-smd-resource";
+ qcom,resource-name = "smpa";
+ qcom,resource-id = <8>;
+ qcom,regulator-type = <1>;
+ qcom,hpm-min-load = <100000>;
+ status = "disabled";
+
+ regulator-s8 {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8084_s8";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-smpa9 {
+ compatible = "qcom,rpm-regulator-smd-resource";
+ qcom,resource-name = "smpa";
+ qcom,resource-id = <9>;
+ qcom,regulator-type = <1>;
+ qcom,hpm-min-load = <100000>;
+ status = "disabled";
+
+ regulator-s9 {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8084_s9";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-smpa10 {
+ compatible = "qcom,rpm-regulator-smd-resource";
+ qcom,resource-name = "smpa";
+ qcom,resource-id = <10>;
+ qcom,regulator-type = <1>;
+ qcom,hpm-min-load = <100000>;
+ status = "disabled";
+
+ regulator-s10 {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8084_s10";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-smpa11 {
+ compatible = "qcom,rpm-regulator-smd-resource";
+ qcom,resource-name = "smpa";
+ qcom,resource-id = <11>;
+ qcom,regulator-type = <1>;
+ qcom,hpm-min-load = <100000>;
+ status = "disabled";
+
+ regulator-s11 {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8084_s11";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-smpa12 {
+ compatible = "qcom,rpm-regulator-smd-resource";
+ qcom,resource-name = "smpa";
+ qcom,resource-id = <12>;
+ qcom,regulator-type = <1>;
+ qcom,hpm-min-load = <100000>;
+ status = "disabled";
+
+ regulator-s12 {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8084_s12";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa1 {
+ compatible = "qcom,rpm-regulator-smd-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <1>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ status = "disabled";
+
+ regulator-l1 {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8084_l1";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa2 {
+ compatible = "qcom,rpm-regulator-smd-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <2>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ status = "disabled";
+
+ regulator-l2 {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8084_l2";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa3 {
+ compatible = "qcom,rpm-regulator-smd-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <3>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ status = "disabled";
+
+ regulator-l3 {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8084_l3";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa4 {
+ compatible = "qcom,rpm-regulator-smd-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <4>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ status = "disabled";
+
+ regulator-l4 {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8084_l4";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa5 {
+ compatible = "qcom,rpm-regulator-smd-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <5>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ status = "disabled";
+
+ regulator-l5 {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8084_l5";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa6 {
+ compatible = "qcom,rpm-regulator-smd-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <6>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ status = "disabled";
+
+ regulator-l6 {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8084_l6";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa7 {
+ compatible = "qcom,rpm-regulator-smd-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <7>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ status = "disabled";
+
+ regulator-l7 {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8084_l7";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa8 {
+ compatible = "qcom,rpm-regulator-smd-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <8>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ status = "disabled";
+
+ regulator-l8 {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8084_l8";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa9 {
+ compatible = "qcom,rpm-regulator-smd-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <9>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ status = "disabled";
+
+ regulator-l9 {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8084_l9";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa10 {
+ compatible = "qcom,rpm-regulator-smd-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <10>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ status = "disabled";
+
+ regulator-l10 {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8084_l10";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa11 {
+ compatible = "qcom,rpm-regulator-smd-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <11>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ status = "disabled";
+
+ regulator-l11 {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8084_l11";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa12 {
+ compatible = "qcom,rpm-regulator-smd-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <12>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ status = "disabled";
+
+ regulator-l12 {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8084_l12";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa13 {
+ compatible = "qcom,rpm-regulator-smd-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <13>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ status = "disabled";
+
+ regulator-l13 {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8084_l13";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa14 {
+ compatible = "qcom,rpm-regulator-smd-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <14>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ status = "disabled";
+
+ regulator-l14 {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8084_l14";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa15 {
+ compatible = "qcom,rpm-regulator-smd-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <15>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ status = "disabled";
+
+ regulator-l15 {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8084_l15";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa16 {
+ compatible = "qcom,rpm-regulator-smd-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <16>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ status = "disabled";
+
+ regulator-l16 {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8084_l16";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa17 {
+ compatible = "qcom,rpm-regulator-smd-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <17>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ status = "disabled";
+
+ regulator-l17 {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8084_l17";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa18 {
+ compatible = "qcom,rpm-regulator-smd-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <18>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ status = "disabled";
+
+ regulator-l18 {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8084_l18";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa19 {
+ compatible = "qcom,rpm-regulator-smd-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <19>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ status = "disabled";
+
+ regulator-l19 {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8084_l19";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa20 {
+ compatible = "qcom,rpm-regulator-smd-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <20>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ status = "disabled";
+
+ regulator-l20 {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8084_l20";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa21 {
+ compatible = "qcom,rpm-regulator-smd-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <21>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ status = "disabled";
+
+ regulator-l21 {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8084_l21";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa22 {
+ compatible = "qcom,rpm-regulator-smd-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <22>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ status = "disabled";
+
+ regulator-l22 {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8084_l22";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa23 {
+ compatible = "qcom,rpm-regulator-smd-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <23>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ status = "disabled";
+
+ regulator-l23 {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8084_l23";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa24 {
+ compatible = "qcom,rpm-regulator-smd-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <24>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ status = "disabled";
+
+ regulator-l24 {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8084_l24";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa25 {
+ compatible = "qcom,rpm-regulator-smd-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <25>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ status = "disabled";
+
+ regulator-l25 {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8084_l25";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa26 {
+ compatible = "qcom,rpm-regulator-smd-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <26>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ status = "disabled";
+
+ regulator-l26 {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8084_l26";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa27 {
+ compatible = "qcom,rpm-regulator-smd-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <27>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ status = "disabled";
+
+ regulator-l27 {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8084_l27";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-vsa1 {
+ compatible = "qcom,rpm-regulator-smd-resource";
+ qcom,resource-name = "vsa";
+ qcom,resource-id = <1>;
+ qcom,regulator-type = <2>;
+ status = "disabled";
+
+ regulator-lvs1 {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8084_lvs1";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-vsa2 {
+ compatible = "qcom,rpm-regulator-smd-resource";
+ qcom,resource-name = "vsa";
+ qcom,resource-id = <2>;
+ qcom,regulator-type = <2>;
+ status = "disabled";
+
+ regulator-lvs2 {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8084_lvs2";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-vsa3 {
+ compatible = "qcom,rpm-regulator-smd-resource";
+ qcom,resource-name = "vsa";
+ qcom,resource-id = <3>;
+ qcom,regulator-type = <2>;
+ status = "disabled";
+
+ regulator-lvs3 {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8084_lvs3";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-vsa4 {
+ compatible = "qcom,rpm-regulator-smd-resource";
+ qcom,resource-name = "vsa";
+ qcom,resource-id = <4>;
+ qcom,regulator-type = <2>;
+ status = "disabled";
+
+ regulator-lvs4 {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8084_lvs4";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-vsa5 {
+ compatible = "qcom,rpm-regulator-smd-resource";
+ qcom,resource-name = "vsa";
+ qcom,resource-id = <5>;
+ qcom,regulator-type = <2>;
+ status = "disabled";
+
+ regulator-mvs1 {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8084_mvs1";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/msm-pma8084.dtsi b/arch/arm/boot/dts/msm-pma8084.dtsi
index 42c48f8..ecbfc53 100644
--- a/arch/arm/boot/dts/msm-pma8084.dtsi
+++ b/arch/arm/boot/dts/msm-pma8084.dtsi
@@ -22,6 +22,68 @@
#address-cells = <1>;
#size-cells = <1>;
+ qcom,revid@100 {
+ compatible = "qcom,qpnp-revid";
+ reg = <0x100 0x100>;
+ };
+
+ qcom,power-on@800 {
+ compatible = "qcom,qpnp-power-on";
+ reg = <0x800 0x100>;
+ interrupts = <0x0 0x8 0x0>,
+ <0x0 0x8 0x1>,
+ <0x0 0x8 0x4>,
+ <0x0 0x8 0x5>;
+ interrupt-names = "kpdpwr", "resin",
+ "resin-bark", "kpdpwr-resin-bark";
+ qcom,pon-dbc-delay = <15625>;
+ qcom,system-reset;
+ qcom,s3-debounce = <32>;
+
+ qcom,pon_1 {
+ qcom,pon-type = <0>;
+ qcom,pull-up = <1>;
+ linux,code = <116>;
+ };
+
+ qcom,pon_2 {
+ qcom,pon-type = <1>;
+ qcom,support-reset = <1>;
+ qcom,pull-up = <1>;
+ qcom,s1-timer = <0>;
+ qcom,s2-timer = <2000>;
+ qcom,s2-type = <1>;
+ linux,code = <114>;
+ };
+
+ qcom,pon_3 {
+ qcom,pon-type = <3>;
+ qcom,support-reset = <1>;
+ qcom,s1-timer = <6720>;
+ qcom,s2-timer = <2000>;
+ qcom,s2-type = <7>;
+ qcom,pull-up = <1>;
+ };
+ };
+
+ pma8084_misc: qcom,misc@900 {
+ compatible = "qcom,qpnp-misc";
+ reg = <0x900 0x100>;
+ };
+
+ qcom,temp-alarm@2400 {
+ compatible = "qcom,qpnp-temp-alarm";
+ reg = <0x2400 0x100>;
+ interrupts = <0x0 0x24 0x0>;
+ label = "pma8084_tz";
+ qcom,threshold-set = <0>;
+ };
+
+ qcom,coincell@2800 {
+ compatible = "qcom,qpnp-coincell";
+ reg = <0x2800 0x100>;
+ };
+
pma8084_gpios: gpios {
spmi-dev-container;
compatible = "qcom,qpnp-pin";
@@ -261,6 +323,23 @@
qcom,adc-bit-resolution = <15>;
qcom,adc-vdd-reference = <1800>;
};
+
+ qcom,rtc {
+ compatible = "qcom,qpnp-rtc";
+ spmi-dev-container;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ qcom,qpnp-rtc-write = <0>;
+ qcom,qpnp-rtc-alarm-pwrup = <0>;
+
+ qcom,rtc_rw@6000 {
+ reg = <0x6000 0x100>;
+ };
+ qcom,rtc_alarm@6100 {
+ reg = <0x6100 0x100>;
+ interrupts = <0x0 0x61 0x1>;
+ };
+ };
};
qcom,pma8084@1 {
diff --git a/arch/arm/boot/dts/msm8226-cdp.dtsi b/arch/arm/boot/dts/msm8226-cdp.dtsi
index e5683fb..7acb1fe 100644
--- a/arch/arm/boot/dts/msm8226-cdp.dtsi
+++ b/arch/arm/boot/dts/msm8226-cdp.dtsi
@@ -114,8 +114,6 @@
&sdcc1 {
vdd-supply = <&pm8226_l17>;
- qcom,vdd-always-on;
- qcom,vdd-lpm-sup;
qcom,vdd-voltage-level = <2950000 2950000>;
qcom,vdd-current-level = <800 500000>;
@@ -140,8 +138,6 @@
&sdhc_1 {
vdd-supply = <&pm8226_l17>;
- qcom,vdd-always-on;
- qcom,vdd-lpm-sup;
qcom,vdd-voltage-level = <2950000 2950000>;
qcom,vdd-current-level = <800 500000>;
@@ -227,6 +223,16 @@
status = "ok";
};
+&sdcc3 {
+ qcom,sup-voltages = <1800 1800>;
+ status = "disabled";
+};
+
+&sdhc_3 {
+ qcom,sup-voltages = <1800 1800>;
+ status = "disabled";
+};
+
&spmi_bus {
qcom,pm8226@0 {
qcom,leds@a100 {
@@ -261,8 +267,12 @@
qcom,mode-ctrl = <0x60>;
qcom,pwm-channel = <0>;
qcom,start-idx = <1>;
- qcom,duty-pcts = [00 00 00 00 64
- 64 00 00 00 00];
+ qcom,ramp-step-ms = <120>;
+ qcom,duty-pcts = [00 00 00 00 00
+ 00 00 00 00 00
+ 50 00 00 00 00
+ 00 00 00 00 00
+ 00];
qcom,use-blink;
};
};
@@ -283,8 +293,12 @@
qcom,source-sel = <10>;
qcom,pwm-channel = <5>;
qcom,start-idx = <1>;
- qcom,duty-pcts = [00 00 00 00 64
- 64 00 00 00 00];
+ qcom,ramp-step-ms = <120>;
+ qcom,duty-pcts = [00 00 00 00 00
+ 00 00 00 00 00
+ 50 00 00 00 00
+ 00 00 00 00 00
+ 00];
qcom,use-blink;
};
};
diff --git a/arch/arm/boot/dts/msm8226-mdss.dtsi b/arch/arm/boot/dts/msm8226-mdss.dtsi
index f580897..b895c64 100644
--- a/arch/arm/boot/dts/msm8226-mdss.dtsi
+++ b/arch/arm/boot/dts/msm8226-mdss.dtsi
@@ -36,6 +36,7 @@
qcom,mdss-wb-off = <0x00011100 0x00013100>;
qcom,mdss-intf-off = <0x00000000 0x00021300>;
qcom,mdss-rot-block-size = <64>;
+ qcom,mdss-smp-mb-per-pipe = <2>;
qcom,vbif-settings = <0x004 0x00000001>,
<0x0D8 0x00000707>,
diff --git a/arch/arm/boot/dts/msm8226-mtp.dtsi b/arch/arm/boot/dts/msm8226-mtp.dtsi
index 0df3feb..ddb61bc 100644
--- a/arch/arm/boot/dts/msm8226-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8226-mtp.dtsi
@@ -131,8 +131,6 @@
&sdcc1 {
vdd-supply = <&pm8226_l17>;
- qcom,vdd-always-on;
- qcom,vdd-lpm-sup;
qcom,vdd-voltage-level = <2950000 2950000>;
qcom,vdd-current-level = <800 500000>;
@@ -157,8 +155,6 @@
&sdhc_1 {
vdd-supply = <&pm8226_l17>;
- qcom,vdd-always-on;
- qcom,vdd-lpm-sup;
qcom,vdd-voltage-level = <2950000 2950000>;
qcom,vdd-current-level = <800 500000>;
@@ -275,8 +271,12 @@
qcom,mode-ctrl = <0x60>;
qcom,pwm-channel = <0>;
qcom,start-idx = <1>;
- qcom,duty-pcts = [00 00 00 00 64
- 64 00 00 00 00];
+ qcom,ramp-step-ms = <120>;
+ qcom,duty-pcts = [00 00 00 00 00
+ 00 00 00 00 00
+ 50 00 00 00 00
+ 00 00 00 00 00
+ 00];
qcom,use-blink;
};
};
@@ -297,8 +297,12 @@
qcom,source-sel = <10>;
qcom,pwm-channel = <5>;
qcom,start-idx = <1>;
- qcom,duty-pcts = [00 00 00 00 64
- 64 00 00 00 00];
+ qcom,ramp-step-ms = <120>;
+ qcom,duty-pcts = [00 00 00 00 00
+ 00 00 00 00 00
+ 50 00 00 00 00
+ 00 00 00 00 00
+ 00];
qcom,use-blink;
};
};
diff --git a/arch/arm/boot/dts/msm8226-qrd.dtsi b/arch/arm/boot/dts/msm8226-qrd.dtsi
index db0620f..669f54a 100644
--- a/arch/arm/boot/dts/msm8226-qrd.dtsi
+++ b/arch/arm/boot/dts/msm8226-qrd.dtsi
@@ -129,8 +129,6 @@
&sdcc1 {
vdd-supply = <&pm8226_l17>;
- qcom,vdd-always-on;
- qcom,vdd-lpm-sup;
qcom,vdd-voltage-level = <2950000 2950000>;
qcom,vdd-current-level = <800 500000>;
@@ -155,8 +153,6 @@
&sdhc_1 {
vdd-supply = <&pm8226_l17>;
- qcom,vdd-always-on;
- qcom,vdd-lpm-sup;
qcom,vdd-voltage-level = <2950000 2950000>;
qcom,vdd-current-level = <800 500000>;
@@ -180,7 +176,7 @@
&sdcc2 {
vdd-supply = <&pm8226_l18>;
qcom,vdd-voltage-level = <2950000 2950000>;
- qcom,vdd-current-level = <9000 800000>;
+ qcom,vdd-current-level = <9000 400000>;
vdd-io-supply = <&pm8226_l21>;
qcom,vdd-io-voltage-level = <1800000 2950000>;
@@ -196,7 +192,7 @@
qcom,xpc;
qcom,bus-speed-mode = "SDR12", "SDR25", "SDR50", "DDR50", "SDR104";
- qcom,current-limit = <600>;
+ qcom,current-limit = <400>;
#address-cells = <0>;
interrupt-parent = <&sdcc2>;
@@ -215,7 +211,7 @@
&sdhc_2 {
vdd-supply = <&pm8226_l18>;
qcom,vdd-voltage-level = <2950000 2950000>;
- qcom,vdd-current-level = <9000 800000>;
+ qcom,vdd-current-level = <9000 400000>;
vdd-io-supply = <&pm8226_l21>;
qcom,vdd-io-voltage-level = <1800000 2950000>;
@@ -265,7 +261,7 @@
qcom,led_mpp_4 {
label = "mpp";
linux,name = "green";
- linux,default-trigger = "none";
+ linux,default-trigger = "battery-full";
qcom,default-state = "off";
qcom,max-current = <40>;
qcom,current-setting = <5>;
@@ -276,8 +272,12 @@
qcom,mode-ctrl = <0x60>;
qcom,pwm-channel = <0>;
qcom,start-idx = <1>;
- qcom,duty-pcts = [00 00 00 00 64
- 64 00 00 00 00];
+ qcom,ramp-step-ms = <120>;
+ qcom,duty-pcts = [00 00 00 00 00
+ 00 00 00 00 00
+ 50 00 00 00 00
+ 00 00 00 00 00
+ 00];
qcom,use-blink;
};
};
@@ -287,7 +287,7 @@
qcom,led_mpp_6 {
label = "mpp";
linux,name = "red";
- linux,default-trigger = "none";
+ linux,default-trigger = "battery-charging";
qcom,default-state = "off";
qcom,max-current = <40>;
qcom,current-setting = <5>;
@@ -298,8 +298,12 @@
qcom,source-sel = <10>;
qcom,pwm-channel = <5>;
qcom,start-idx = <1>;
- qcom,duty-pcts = [00 00 00 00 64
- 64 00 00 00 00];
+ qcom,ramp-step-ms = <120>;
+ qcom,duty-pcts = [00 00 00 00 00
+ 00 00 00 00 00
+ 50 00 00 00 00
+ 00 00 00 00 00
+ 00];
qcom,use-blink;
};
};
diff --git a/arch/arm/boot/dts/msm8226-regulator.dtsi b/arch/arm/boot/dts/msm8226-regulator.dtsi
index 8006da2..571ddc3 100644
--- a/arch/arm/boot/dts/msm8226-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8226-regulator.dtsi
@@ -30,19 +30,22 @@
apc_vreg_corner: regulator@f9018000 {
status = "okay";
compatible = "qcom,cpr-regulator";
- reg = <0xf9018000 0x1000>, <0xf9011064 4>, <0xfc4b80b0 8>,
- <0xfc4bc450 16>;
- reg-names = "rbcpr", "rbcpr_clk", "pvs_efuse", "cpr_efuse";
+ reg = <0xf9018000 0x1000>, <0xf9011064 4>, <0xfc4b8000 0x1000>;
+ reg-names = "rbcpr", "rbcpr_clk", "efuse_addr";
interrupts = <0 15 0>;
regulator-name = "apc_corner";
regulator-min-microvolt = <1>;
regulator-max-microvolt = <3>;
- qcom,num-efuse-bits = <5>;
+
+ qcom,pvs-fuse-redun-sel = <22 24 3 2>;
+ qcom,pvs-fuse = <22 6 5>;
+ qcom,pvs-fuse-redun = <22 27 5>;
+
qcom,pvs-bin-process = <0 0 0 0 0 1 1 1 1 1 2 2 2 2 2 2
2 2 2 2 3 3 3 3 3 3 3 3 0 0 0 0>;
qcom,pvs-corner-ceiling-slow = <1155000 1160000 1275000>;
- qcom,pvs-corner-ceiling-nom = <975000 1075000 1200000>;
- qcom,pvs-corner-ceiling-fast = <900000 1000000 1140000>;
+ qcom,pvs-corner-ceiling-nom = <1050000 1075000 1200000>;
+ qcom,pvs-corner-ceiling-fast = <1050000 1050000 1140000>;
vdd-apc-supply = <&pm8226_s2>;
vdd-mx-supply = <&pm8226_l3_ao>;
@@ -63,6 +66,16 @@
qcom,vdd-apc-step-down-limit = <1>;
qcom,cpr-apc-volt-step = <5000>;
+ qcom,cpr-fuse-redun-sel = <138 57 1 1>;
+ qcom,cpr-fuse-row = <138>;
+ qcom,cpr-fuse-bp-cpr-disable = <36>;
+ qcom,cpr-fuse-bp-scheme = <37>;
+ qcom,cpr-fuse-target-quot = <24 12 0>;
+ qcom,cpr-fuse-ro-sel = <54 38 41>;
+ qcom,cpr-fuse-redun-row = <139>;
+ qcom,cpr-fuse-redun-target-quot = <24 12 0>;
+ qcom,cpr-fuse-redun-ro-sel = <46 36 39>;
+
qcom,cpr-enable;
};
};
@@ -411,6 +424,17 @@
};
};
+ rpm-regulator-ldoa25 {
+ status = "okay";
+ pm8226_l25: regulator-l25 {
+ regulator-name = "8226_l25";
+ regulator-min-microvolt = <1775000>;
+ regulator-max-microvolt = <2125000>;
+ qcom,init-voltage = <1775000>;
+ status = "okay";
+ };
+ };
+
rpm-regulator-ldoa26 {
status = "okay";
pm8226_l26: regulator-l26 {
diff --git a/arch/arm/boot/dts/msm8226-v1-qrd-skuf.dts b/arch/arm/boot/dts/msm8226-v1-qrd-skuf.dts
index 8520ae3..cb5e299 100644
--- a/arch/arm/boot/dts/msm8226-v1-qrd-skuf.dts
+++ b/arch/arm/boot/dts/msm8226-v1-qrd-skuf.dts
@@ -30,4 +30,29 @@
status = "ok";
qcom,mdss-pan-bl-ctrl = "bl_ctrl_dcs";
};
+
+ sound {
+ qcom,model = "msm8226-tapan-skuf-snd-card";
+
+ qcom,audio-routing =
+ "RX_BIAS", "MCLK",
+ "LDO_H", "MCLK",
+ "SPK_OUT", "MCLK",
+ "SPK_OUT", "EXT_VDD_SPKR",
+ "Lineout_1 amp", "LINEOUT1",
+ "Lineout_2 amp", "LINEOUT2",
+ "AMIC1", "MIC BIAS1 External",
+ "MIC BIAS1 External", "Handset Mic",
+ "AMIC2", "MIC BIAS2 External",
+ "MIC BIAS2 External", "Headset Mic",
+ "AMIC3", "MIC BIAS1 External",
+ "MIC BIAS1 External", "ANCRight Headset Mic",
+ "AMIC4", "MIC BIAS2 External",
+ "MIC BIAS2 External", "ANCLeft Headset Mic";
+
+ qcom,cdc-mclk-gpios = <&pm8226_gpios 1 0>;
+ qcom,cdc-lineout-spkr-gpios = <&pm8226_gpios 2 0>;
+ qcom,cdc-vdd-spkr-gpios;
+ qcom,cdc-us-euro-gpios;
+ };
};
diff --git a/arch/arm/boot/dts/msm8226-v1.dtsi b/arch/arm/boot/dts/msm8226-v1.dtsi
index d471bec..1db1f12 100644
--- a/arch/arm/boot/dts/msm8226-v1.dtsi
+++ b/arch/arm/boot/dts/msm8226-v1.dtsi
@@ -17,3 +17,8 @@
*/
/include/ "msm8226.dtsi"
+
+&tsens {
+ qcom,sensors = <4>;
+ qcom,slope = <2901 2846 3038 2955>;
+};
diff --git a/arch/arm/boot/dts/msm8226-v2-qrd-skuf.dts b/arch/arm/boot/dts/msm8226-v2-qrd-skuf.dts
index 1c43589..ac8b437 100644
--- a/arch/arm/boot/dts/msm8226-v2-qrd-skuf.dts
+++ b/arch/arm/boot/dts/msm8226-v2-qrd-skuf.dts
@@ -31,4 +31,29 @@
status = "ok";
qcom,mdss-pan-bl-ctrl = "bl_ctrl_dcs";
};
+
+ sound {
+ qcom,model = "msm8226-tapan-skuf-snd-card";
+
+ qcom,audio-routing =
+ "RX_BIAS", "MCLK",
+ "LDO_H", "MCLK",
+ "SPK_OUT", "MCLK",
+ "SPK_OUT", "EXT_VDD_SPKR",
+ "Lineout_1 amp", "LINEOUT1",
+ "Lineout_2 amp", "LINEOUT2",
+ "AMIC1", "MIC BIAS1 External",
+ "MIC BIAS1 External", "Handset Mic",
+ "AMIC2", "MIC BIAS2 External",
+ "MIC BIAS2 External", "Headset Mic",
+ "AMIC3", "MIC BIAS1 External",
+ "MIC BIAS1 External", "ANCRight Headset Mic",
+ "AMIC4", "MIC BIAS2 External",
+ "MIC BIAS2 External", "ANCLeft Headset Mic";
+
+ qcom,cdc-mclk-gpios = <&pm8226_gpios 1 0>;
+ qcom,cdc-lineout-spkr-gpios = <&pm8226_gpios 2 0>;
+ qcom,cdc-vdd-spkr-gpios;
+ qcom,cdc-us-euro-gpios;
+ };
};
diff --git a/arch/arm/boot/dts/msm8226-v2.dtsi b/arch/arm/boot/dts/msm8226-v2.dtsi
index 2148e1d..b44cb681 100644
--- a/arch/arm/boot/dts/msm8226-v2.dtsi
+++ b/arch/arm/boot/dts/msm8226-v2.dtsi
@@ -43,8 +43,8 @@
qcom,pvs-bin-process = <1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2
2 2 2 2 2 3 3 3 3 3 3 3 3 3 3 3>;
qcom,pvs-corner-ceiling-slow = <1160000 1160000 1280000>;
- qcom,pvs-corner-ceiling-nom = <980000 1080000 1200000>;
- qcom,pvs-corner-ceiling-fast = <900000 1000000 1140000>;
+ qcom,pvs-corner-ceiling-nom = <1050000 1080000 1200000>;
+ qcom,pvs-corner-ceiling-fast = <1050000 1050000 1140000>;
qcom,cpr-step-quotient = <30>;
qcom,cpr-up-threshold = <0>;
qcom,cpr-down-threshold = <5>;
@@ -63,3 +63,8 @@
reg-names = "rcg_base", "pte_efuse";
};
};
+
+&tsens {
+ qcom,sensors = <6>;
+ qcom,slope = <2901 2846 3038 2955 2901 2846>;
+};
diff --git a/arch/arm/boot/dts/msm8226.dtsi b/arch/arm/boot/dts/msm8226.dtsi
index 42c1247..b836100 100644
--- a/arch/arm/boot/dts/msm8226.dtsi
+++ b/arch/arm/boot/dts/msm8226.dtsi
@@ -21,6 +21,7 @@
spi0 = &spi_0;
sdhc1 = &sdhc_1; /* SDC1 eMMC slot */
sdhc2 = &sdhc_2; /* SDC2 SD card slot */
+ sdhc3 = &sdhc_3; /* SDC3 SDIO slot */
};
memory {
@@ -762,6 +763,95 @@
status = "disabled";
};
+ sdcc3: qcom,sdcc@f9864000 {
+ cell-index = <3>;
+ compatible = "qcom,msm-sdcc";
+ reg = <0xf9864000 0x800>,
+ <0xf9864800 0x100>,
+ <0xf9844000 0x7000>;
+ reg-names = "core_mem", "dml_mem", "bam_mem";
+
+ qcom,bus-width = <4>;
+ gpios = <&msmgpio 44 0>, /* CLK */
+ <&msmgpio 43 0>, /* CMD */
+ <&msmgpio 42 0>, /* DATA0 */
+ <&msmgpio 41 0>, /* DATA1 */
+ <&msmgpio 40 0>, /* DATA2 */
+ <&msmgpio 39 0>; /* DATA3 */
+ qcom,gpio-names = "CLK", "CMD", "DAT0", "DAT1", "DAT2", "DAT3";
+
+ qcom,clk-rates = <400000 20000000 25000000 50000000 100000000>;
+
+ qcom,msm-bus,name = "sdcc3";
+ qcom,msm-bus,num-cases = <8>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,vectors-KBps = <79 512 0 0>, /* No vote */
+ <79 512 1600 3200>, /* 400 KB/s*/
+ <79 512 80000 160000>, /* 20 MB/s */
+ <79 512 100000 200000>, /* 25 MB/s */
+ <79 512 200000 400000>, /* 50 MB/s */
+ <79 512 400000 800000>, /* 100 MB/s */
+ <79 512 400000 800000>, /* 200 MB/s */
+ <79 512 2048000 4096000>; /* Max. bandwidth */
+ qcom,bus-bw-vectors-bps = <0 400000 20000000 25000000 50000000
+ 100000000 200000000 4294967295>;
+
+ #address-cells = <0>;
+ interrupt-parent = <&sdcc3>;
+ interrupts = <0 1 2>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0xffffffff>;
+ interrupt-map = <0 &intc 0 127 0
+ 1 &intc 0 223 0
+ 2 &msmgpio 41 0x8>;
+ interrupt-names = "core_irq", "bam_irq", "sdiowakeup_irq";
+
+ status = "disabled";
+ };
+
+ sdhc_3: sdhci@f9864900 {
+ compatible = "qcom,sdhci-msm";
+ reg = <0xf9864900 0x11c>, <0xf9864000 0x800>;
+ reg-names = "hc_mem", "core_mem";
+
+ qcom,bus-width = <4>;
+ gpios = <&msmgpio 44 0>, /* CLK */
+ <&msmgpio 43 0>, /* CMD */
+ <&msmgpio 42 0>, /* DATA0 */
+ <&msmgpio 41 0>, /* DATA1 */
+ <&msmgpio 40 0>, /* DATA2 */
+ <&msmgpio 39 0>; /* DATA3 */
+ qcom,gpio-names = "CLK", "CMD", "DAT0", "DAT1", "DAT2", "DAT3";
+
+ qcom,clk-rates = <400000 20000000 25000000 50000000 100000000>;
+
+ qcom,msm-bus,name = "sdhc3";
+ qcom,msm-bus,num-cases = <8>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,vectors-KBps = <79 512 0 0>, /* No vote */
+ <79 512 1600 3200>, /* 400 KB/s*/
+ <79 512 80000 160000>, /* 20 MB/s */
+ <79 512 100000 200000>, /* 25 MB/s */
+ <79 512 200000 400000>, /* 50 MB/s */
+ <79 512 400000 800000>, /* 100 MB/s */
+ <79 512 400000 800000>, /* 200 MB/s */
+ <79 512 2048000 4096000>; /* Max. bandwidth */
+ qcom,bus-bw-vectors-bps = <0 400000 20000000 25000000 50000000
+ 100000000 200000000 4294967295>;
+
+ #address-cells = <0>;
+ interrupt-parent = <&sdhc_3>;
+ interrupts = <0 1 2>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0xffffffff>;
+ interrupt-map = <0 &intc 0 127 0
+ 1 &intc 0 224 0
+ 2 &msmgpio 41 0x8>;
+ interrupt-names = "hc_irq", "pwr_irq", "sdiowakeup_irq";
+
+ status = "disabled";
+ };
+
spmi_bus: qcom,spmi@fc4c0000 {
cell-index = <0>;
compatible = "qcom,spmi-pmic-arb";
@@ -935,7 +1025,7 @@
tsens: tsens@fc4a8000 {
compatible = "qcom,msm-tsens";
reg = <0xfc4a8000 0x2000>,
- <0xfc4b8000 0x1000>;
+ <0xfc4bc000 0x1000>;
reg-names = "tsens_physical", "tsens_eeprom_physical";
interrupts = <0 184 0>;
qcom,sensors = <4>;
@@ -954,6 +1044,21 @@
qcom,core-limit-temp = <80>;
qcom,core-temp-hysteresis = <10>;
qcom,core-control-mask = <0xe>;
+ qcom,vdd-restriction-temp = <5>;
+ qcom,vdd-restriction-temp-hysteresis = <10>;
+ vdd-dig-supply = <&pm8226_s1_floor_corner>;
+
+ qcom,vdd-dig-rstr{
+ qcom,vdd-rstr-reg = "vdd-dig";
+ qcom,levels = <5 7 7>; /* Nominal, Super Turbo, Super Turbo */
+ qcom,min-level = <1>; /* No Request */
+ };
+
+ qcom,vdd-apps-rstr{
+ qcom,vdd-rstr-reg = "vdd-apps";
+ qcom,levels = <600000 787200 998400>;
+ qcom,freq-req;
+ };
};
spi_0: spi@f9923000 { /* BLSP1 QUP1 */
diff --git a/arch/arm/boot/dts/msm8610-cdp.dts b/arch/arm/boot/dts/msm8610-cdp.dts
index 6b61317..ce4ada5 100644
--- a/arch/arm/boot/dts/msm8610-cdp.dts
+++ b/arch/arm/boot/dts/msm8610-cdp.dts
@@ -222,9 +222,13 @@
qcom,default-state = "on";
qcom,max-current = <40>;
qcom,id = <6>;
- qcom,source-sel = <1>;
+ qcom,source-sel = <8>;
qcom,mode-ctrl = <0x10>;
- qcom,mode = "manual";
+ qcom,pwm-channel = <0>;
+ qcom,pwm-us = <14>;
+ qcom,vin-ctrl = <0x03>;
+ qcom,mode = "pwm";
+ qcom,min-brightness = <19>;
};
};
};
@@ -242,8 +246,6 @@
&sdhc_1 {
vdd-supply = <&pm8110_l17>;
- qcom,vdd-always-on;
- qcom,vdd-lpm-sup;
qcom,vdd-voltage-level = <2900000 2900000>;
qcom,vdd-current-level = <200 400000>;
diff --git a/arch/arm/boot/dts/msm8610-mtp.dts b/arch/arm/boot/dts/msm8610-mtp.dts
index 27381e2..221ace4 100644
--- a/arch/arm/boot/dts/msm8610-mtp.dts
+++ b/arch/arm/boot/dts/msm8610-mtp.dts
@@ -42,6 +42,7 @@
atmel,display-coords = <0 0 480 800>;
atmel,i2c-pull-up;
atmel,no-force-update;
+ atmel,no-lpm-support;
atmel,cfg_1 {
atmel,family-id = <0x81>;
atmel,variant-id = <0x15>;
@@ -90,6 +91,44 @@
};
};
+ i2c@f9925000 {
+ mpu3050@68 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "okay";
+ reg = <0x68>;
+ compatible = "invn,mpu3050";
+ interrupt-parent = <&msmgpio>;
+ interrupts = <84 0x2>;
+ vlogic-supply = <&pm8110_l14>;
+ vdd-supply = <&pm8110_l19>;
+ invn,gpio-int = <&msmgpio 84 0x2>;
+ invn,gpio-en = <&pm8110_gpios 2 0x2>;
+ invn,poll-interval = <200>;
+ };
+
+ bmp180@77 {
+ reg = <0x77>;
+ compatible = "bosch,bmp18x";
+ vdd-supply = <&pm8110_l19>;
+ vddio-supply = <&pm8110_l14>;
+ bosch,chip-id = <0x55>;
+ bosch,oversample = <3>;
+ bosch,period = <1000>;
+ };
+
+ mma8x5x@1d {
+ reg = <0x1d>;
+ compatible = "fsl,mma8x5x";
+ interrupt-parent = <&msmgpio>;
+ interrupts = <81 0x2>;
+ vdd-supply = <&pm8110_l19>;
+ vio-supply = <&pm8110_l14>;
+ fsl,irq-gpio = <&msmgpio 81 0x00>;
+ fsl,sensors-position = <5>;
+ };
+ };
+
gen-vkeys {
compatible = "qcom,gen-vkeys";
label = "atmel_mxt_ts";
@@ -154,7 +193,7 @@
cdc-vdda-h-supply = <&pm8110_l6>;
qcom,cdc-vdda-h-voltage = <1800000 1800000>;
- qcom,cdc-vdda-h-current = <250000>;
+ qcom,cdc-vdda-h-current = <25000>;
cdc-vdd-px-supply = <&pm8110_l6>;
qcom,cdc-vdd-px-voltage = <1800000 1800000>;
@@ -222,9 +261,13 @@
qcom,default-state = "on";
qcom,max-current = <40>;
qcom,id = <6>;
- qcom,source-sel = <1>;
+ qcom,source-sel = <8>;
qcom,mode-ctrl = <0x10>;
- qcom,mode = "manual";
+ qcom,pwm-channel = <0>;
+ qcom,pwm-us = <14>;
+ qcom,vin-ctrl = <0x03>;
+ qcom,mode = "pwm";
+ qcom,min-brightness = <19>;
};
};
};
@@ -242,8 +285,6 @@
&sdhc_1 {
vdd-supply = <&pm8110_l17>;
- qcom,vdd-always-on;
- qcom,vdd-lpm-sup;
qcom,vdd-voltage-level = <2900000 2900000>;
qcom,vdd-current-level = <200 400000>;
diff --git a/arch/arm/boot/dts/msm8610-qrd-skuaa.dts b/arch/arm/boot/dts/msm8610-qrd-skuaa.dts
new file mode 100644
index 0000000..220f642
--- /dev/null
+++ b/arch/arm/boot/dts/msm8610-qrd-skuaa.dts
@@ -0,0 +1,42 @@
+/* Copyright (c) 2013, 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.
+ */
+
+/dts-v1/;
+
+/include/ "msm8610-qrd.dtsi"
+/include/ "dsi-v2-panel-hx8379a-wvga-video.dtsi"
+/include/ "msm8610-qrd-camera-sensor.dtsi"
+
+/ {
+ model = "Qualcomm MSM 8610 QRD";
+ compatible = "qcom,msm8610-qrd", "qcom,msm8610", "qcom,qrd";
+ qcom,board-id = <11 1>, <11 0>;
+ qcom,msm-id = <147 0>, <165 0>, <161 0>, <162 0>,
+ <163 0>, <164 0>, <166 0>;
+};
+
+&soc {
+ sound {
+ qcom,model = "msm8x10-skuaa-snd-card";
+
+ qcom,audio-routing =
+ "RX_BIAS", "MCLK",
+ "INT_LDO_H", "MCLK",
+ "Lineout amp", "LINEOUT",
+ "MIC BIAS Internal1", "Handset Mic",
+ "MIC BIAS Internal2", "Headset Mic",
+ "AMIC1", "MIC BIAS Internal1",
+ "AMIC2", "MIC BIAS Internal2";
+
+ qcom,ext-spk-amp-gpio = <&msmgpio 92 0x0>;
+ };
+};
diff --git a/arch/arm/boot/dts/msm8610-qrd-skuab.dts b/arch/arm/boot/dts/msm8610-qrd-skuab.dts
new file mode 100644
index 0000000..24c2490
--- /dev/null
+++ b/arch/arm/boot/dts/msm8610-qrd-skuab.dts
@@ -0,0 +1,81 @@
+/* Copyright (c) 2013, 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.
+ */
+
+/dts-v1/;
+
+/include/ "msm8610-qrd.dtsi"
+/include/ "msm8612-qrd-camera-sensor.dtsi"
+
+/ {
+ model = "Qualcomm MSM 8610 QRD";
+ compatible = "qcom,msm8610-qrd", "qcom,msm8610", "qcom,qrd";
+ qcom,board-id = <11 3>;
+ qcom,msm-id = <147 0>, <165 0>, <161 0>, <162 0>,
+ <163 0>, <164 0>, <166 0>;
+};
+
+&soc {
+ sound {
+ qcom,model = "msm8x10-skuab-snd-card";
+
+ qcom,audio-routing =
+ "RX_BIAS", "MCLK",
+ "INT_LDO_H", "MCLK",
+ "Lineout amp", "LINEOUT",
+ "MIC BIAS Internal1", "Handset Mic",
+ "MIC BIAS Internal2", "Headset Mic",
+ "AMIC1", "MIC BIAS Internal1",
+ "AMIC2", "MIC BIAS Internal2";
+
+ qcom,ext-spk-amp-gpio = <&msmgpio 92 0x0>;
+ };
+ i2c@f9923000{
+ focaltech@38{
+ compatible = "focaltech,5x06";
+ reg = <0x38>;
+ interrupt-parent = <&msmgpio>;
+ interrupts = <1 0x2>;
+ vdd-supply = <&pm8110_l19>;
+ vcc_i2c-supply = <&pm8110_l14>;
+ focaltech,family-id = <0x06>;
+ focaltech,reset-gpio = <&msmgpio 0 0x00>;
+ focaltech,irq-gpio = <&msmgpio 1 0x00>;
+ focaltech,display-coords = <0 0 480 854>;
+ focaltech,panel-coords = <0 0 480 946>;
+ focaltech,button-map= <139 102 158>;
+ focaltech,no-force-update;
+ focaltech,i2c-pull-up;
+ };
+ };
+ gen-vkeys {
+ compatible = "qcom,gen-vkeys";
+ label = "ft5x06_ts";
+ qcom,disp-maxx = <480>;
+ qcom,disp-maxy = <854>;
+ qcom,panel-maxx = <481>;
+ qcom,panel-maxy = <946>;
+ qcom,key-codes = <139 102 158>;
+ qcom,y-offset = <0>;
+ };
+ i2c@f9925000 {
+ fsl@1c {
+ compatible = "fsl,mma8x5x";
+ reg = <0x1c>;
+ interrupt-parent = <&msmgpio>;
+ interrupts = <81 0x2>;
+ vdd-supply = <&pm8110_l19>;
+ vio-supply = <&pm8110_l14>;
+ fsl,irq-gpio = <&msmgpio 81 0x00>;
+ fsl,sensors-position = <5>;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/msm8610-qrd.dtsi b/arch/arm/boot/dts/msm8610-qrd.dtsi
index 7a93c49..ea47d45 100644
--- a/arch/arm/boot/dts/msm8610-qrd.dtsi
+++ b/arch/arm/boot/dts/msm8610-qrd.dtsi
@@ -124,51 +124,6 @@
};
};
- i2c@f9927000 {
- msm8x10_wcd_codec@0d{
- compatible = "qcom,msm8x10-wcd-i2c";
- reg = <0x0d>;
- cdc-vdda-cp-supply = <&pm8110_s4>;
- qcom,cdc-vdda-cp-voltage = <2150000 2150000>;
- qcom,cdc-vdda-cp-current = <650000>;
-
- cdc-vdda-h-supply = <&pm8110_l6>;
- qcom,cdc-vdda-h-voltage = <1800000 1800000>;
- qcom,cdc-vdda-h-current = <250000>;
-
- cdc-vdd-px-supply = <&pm8110_l6>;
- qcom,cdc-vdd-px-voltage = <1800000 1800000>;
- qcom,cdc-vdd-px-current = <10000>;
-
- cdc-vdd-1p2v-supply = <&pm8110_l4>;
- qcom,cdc-vdd-1p2v-voltage = <1200000 1200000>;
- qcom,cdc-vdd-1p2v-current = <5000>;
-
- cdc-vdd-mic-bias-supply = <&pm8110_l20>;
- qcom,cdc-vdd-mic-bias-voltage = <3075000 3075000>;
- qcom,cdc-vdd-mic-bias-current = <25000>;
-
- qcom,cdc-micbias-cfilt-sel = <0x0>;
- qcom,cdc-micbias-cfilt-mv = <1800000>;
- qcom,cdc-mclk-clk-rate = <12288000>;
- };
-
- msm8x10_wcd_codec@77{
- compatible = "qcom,msm8x10-wcd-i2c";
- reg = <0x77>;
- };
-
- msm8x10_wcd_codec@66{
- compatible = "qcom,msm8x10-wcd-i2c";
- reg = <0x66>;
- };
-
- msm8x10_wcd_codec@55{
- compatible = "qcom,msm8x10-wcd-i2c";
- reg = <0x55>;
- };
- };
-
sound {
qcom,audio-routing =
"RX_BIAS", "MCLK",
@@ -180,6 +135,58 @@
};
};
+&i2c_cdc {
+ msm8x10_wcd_codec@0d{
+ compatible = "qcom,msm8x10-wcd-i2c";
+ reg = <0x0d>;
+ cdc-vdda-cp-supply = <&pm8110_s4>;
+ qcom,cdc-vdda-cp-voltage = <1800000 2150000>;
+ qcom,cdc-vdda-cp-current = <650000>;
+
+ cdc-vdda-h-supply = <&pm8110_l6>;
+ qcom,cdc-vdda-h-voltage = <1800000 1800000>;
+ qcom,cdc-vdda-h-current = <25000>;
+
+ cdc-vdd-px-supply = <&pm8110_l6>;
+ qcom,cdc-vdd-px-voltage = <1800000 1800000>;
+ qcom,cdc-vdd-px-current = <10000>;
+
+ cdc-vdd-1p2v-supply = <&pm8110_l4>;
+ qcom,cdc-vdd-1p2v-voltage = <1200000 1200000>;
+ qcom,cdc-vdd-1p2v-current = <5000>;
+
+ cdc-vdd-mic-bias-supply = <&pm8110_l20>;
+ qcom,cdc-vdd-mic-bias-voltage = <3075000 3075000>;
+ qcom,cdc-vdd-mic-bias-current = <25000>;
+
+ qcom,cdc-micbias-cfilt-sel = <0x0>;
+ qcom,cdc-micbias-cfilt-mv = <1800000>;
+ qcom,cdc-mclk-clk-rate = <12288000>;
+
+ qcom,cdc-static-supplies = "cdc-vdda-h",
+ "cdc-vdd-px",
+ "cdc-vdd-1p2v";
+
+ qcom,cdc-on-demand-supplies = "cdc-vdda-cp",
+ "cdc-vdd-mic-bias";
+ };
+
+ msm8x10_wcd_codec@77{
+ compatible = "qcom,msm8x10-wcd-i2c";
+ reg = <0x77>;
+ };
+
+ msm8x10_wcd_codec@66{
+ compatible = "qcom,msm8x10-wcd-i2c";
+ reg = <0x66>;
+ };
+
+ msm8x10_wcd_codec@55{
+ compatible = "qcom,msm8x10-wcd-i2c";
+ reg = <0x55>;
+ };
+};
+
&spmi_bus {
qcom,pm8110@0 {
qcom,leds@a100 {
@@ -206,9 +213,13 @@
qcom,default-state = "on";
qcom,max-current = <40>;
qcom,id = <6>;
- qcom,source-sel = <1>;
+ qcom,source-sel = <8>;
qcom,mode-ctrl = <0x10>;
- qcom,mode = "manual";
+ qcom,pwm-channel = <0>;
+ qcom,pwm-us = <14>;
+ qcom,vin-ctrl = <0x03>;
+ qcom,mode = "pwm";
+ qcom,min-brightness = <19>;
};
};
};
@@ -226,8 +237,6 @@
&sdhc_1 {
vdd-supply = <&pm8110_l17>;
- qcom,vdd-always-on;
- qcom,vdd-lpm-sup;
qcom,vdd-voltage-level = <2900000 2900000>;
qcom,vdd-current-level = <200 400000>;
diff --git a/arch/arm/boot/dts/msm8610-regulator.dtsi b/arch/arm/boot/dts/msm8610-regulator.dtsi
index 0d47e5d..cf54098 100644
--- a/arch/arm/boot/dts/msm8610-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8610-regulator.dtsi
@@ -30,19 +30,22 @@
apc_vreg_corner: regulator@f9018000 {
status = "okay";
compatible = "qcom,cpr-regulator";
- reg = <0xf9018000 0x1000>, <0xf9011064 4>, <0xfc4b80b0 8>,
- <0xfc4bc450 16>;
- reg-names = "rbcpr", "rbcpr_clk", "pvs_efuse", "cpr_efuse";
+ reg = <0xf9018000 0x1000>, <0xf9011064 4>, <0xfc4b8000 0x1000>;
+ reg-names = "rbcpr", "rbcpr_clk", "efuse_addr";
interrupts = <0 15 0>;
regulator-name = "apc_corner";
regulator-min-microvolt = <1>;
regulator-max-microvolt = <3>;
- qcom,num-efuse-bits = <5>;
- qcom,pvs-bin-process = <0 0 0 0 0 1 1 1 1 1 2 2 2 2 2 2
- 2 2 2 2 3 3 3 3 3 3 3 3 0 0 0 0>;
+
+ qcom,pvs-fuse-redun-sel = <53 25 3 2>;
+ qcom,pvs-fuse = <23 6 5>;
+ qcom,pvs-fuse-redun = <61 47 5>;
+
+ qcom,pvs-bin-process = <1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
+ 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1>;
qcom,pvs-corner-ceiling-slow = <1150000 1150000 1275000>;
- qcom,pvs-corner-ceiling-nom = <975000 1075000 1200000>;
- qcom,pvs-corner-ceiling-fast = <900000 1000000 1140000>;
+ qcom,pvs-corner-ceiling-nom = <1075000 1075000 1200000>;
+ qcom,pvs-corner-ceiling-fast = <1000000 1000000 1140000>;
vdd-apc-supply = <&pm8110_s2>;
vdd-mx-supply = <&pm8110_l3_ao>;
@@ -62,6 +65,18 @@
qcom,vdd-apc-step-up-limit = <1>;
qcom,vdd-apc-step-down-limit = <1>;
qcom,cpr-apc-volt-step = <5000>;
+
+ qcom,cpr-fuse-redun-sel = <53 25 3 2>;
+ qcom,cpr-fuse-row = <61>;
+ qcom,cpr-fuse-bp-cpr-disable = <39>;
+ qcom,cpr-fuse-bp-scheme = <40>;
+ qcom,cpr-fuse-target-quot = <27 15 3>;
+ qcom,cpr-fuse-ro-sel = <47 41 44>;
+ qcom,cpr-fuse-redun-row = <52>;
+ qcom,cpr-fuse-redun-bp-cpr-disable = <24>;
+ qcom,cpr-fuse-redun-bp-scheme = <25>;
+ qcom,cpr-fuse-redun-target-quot = <32 12 0>;
+ qcom,cpr-fuse-redun-ro-sel = <44 26 29>;
};
};
@@ -182,6 +197,7 @@
regulator-min-microvolt = <1200000>;
regulator-max-microvolt = <1200000>;
qcom,init-voltage = <1200000>;
+ regulator-always-on;
status = "okay";
};
};
diff --git a/arch/arm/boot/dts/msm8610.dtsi b/arch/arm/boot/dts/msm8610.dtsi
index c9e88a8..ee444e3 100644
--- a/arch/arm/boot/dts/msm8610.dtsi
+++ b/arch/arm/boot/dts/msm8610.dtsi
@@ -253,8 +253,6 @@
interrupt-names = "core_irq", "bam_irq";
vdd-supply = <&pm8110_l17>;
- qcom,vdd-always-on;
- qcom,vdd-lpm-sup;
qcom,vdd-voltage-level = <2900000 2900000>;
qcom,vdd-current-level = <9000 400000>;
@@ -701,6 +699,7 @@
gpios = <&msmgpio 23 0>, <&msmgpio 24 0>, <&msmgpio 25 0>, <&msmgpio 26 0>, <&msmgpio 27 0>;
qcom,has-pronto-hw;
qcom,wlan-rx-buff-count = <256>;
+ qcom,has-autodetect-xo;
};
qcom,mss@fc880000 {
@@ -754,7 +753,7 @@
tsens: tsens@fc4a8000 {
compatible = "qcom,msm-tsens";
reg = <0xfc4a8000 0x2000>,
- <0xfc4b8000 0x1000>;
+ <0xfc4bc000 0x1000>;
reg-names = "tsens_physical", "tsens_eeprom_physical";
interrupts = <0 184 0>;
qcom,sensors = <2>;
@@ -776,16 +775,16 @@
qcom,core-control-mask = <0xe>;
qcom,vdd-restriction-temp = <5>;
qcom,vdd-restriction-temp-hysteresis = <10>;
- vdd_dig-supply = <&pm8110_s1_floor_corner>;
+ vdd-dig-supply = <&pm8110_s1_floor_corner>;
qcom,vdd-dig-rstr{
- qcom,vdd-rstr-reg = "vdd_dig";
+ qcom,vdd-rstr-reg = "vdd-dig";
qcom,levels = <5 7 7>; /* Nominal, Super Turbo, Super Turbo */
qcom,min-level = <1>; /* No Request */
};
qcom,vdd-apps-rstr{
- qcom,vdd-rstr-reg = "vdd_apps";
+ qcom,vdd-rstr-reg = "vdd-apps";
qcom,levels = <600000 787200 998400>;
qcom,freq-req;
};
@@ -914,6 +913,11 @@
<55 512 393600 3936000>;
};
+ cpu-pmu {
+ compatible = "arm,cortex-a7-pmu";
+ qcom,irq-is-percpu;
+ interrupts = <1 7 0xf00>;
+ };
};
&gdsc_vfe {
diff --git a/arch/arm/boot/dts/msm8612-qrd-camera-sensor.dtsi b/arch/arm/boot/dts/msm8612-qrd-camera-sensor.dtsi
new file mode 100644
index 0000000..25554eb
--- /dev/null
+++ b/arch/arm/boot/dts/msm8612-qrd-camera-sensor.dtsi
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2013, 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.
+ */
+
+&i2c {
+
+ qcom,camera@20 {
+ compatible = "shinetech,s5k4e1";
+ reg = <0x20>;
+ qcom,slave-id = <0x20 0x0000 0x4e10>;
+ qcom,csiphy-sd-index = <0>;
+ qcom,csid-sd-index = <0>;
+ qcom,mount-angle = <90>;
+ qcom,sensor-name = "SKUAB_ST_s5k4e1";
+ cam_vdig-supply = <&pm8110_l2>;
+ cam_vana-supply = <&pm8110_l19>;
+ cam_vio-supply = <&pm8110_l14>;
+ qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana";
+ qcom,cam-vreg-type = <0 0 0>;
+ qcom,cam-vreg-min-voltage = <1200000 1800000 2850000>;
+ qcom,cam-vreg-max-voltage = <1200000 1800000 2850000>;
+ qcom,cam-vreg-op-mode = <200000 8000 80000>;
+ qcom,gpio-no-mux = <0>;
+ gpios = <&msmgpio 13 0>,
+ <&msmgpio 21 0>,
+ <&msmgpio 20 0>;
+ qcom,gpio-reset = <1>;
+ qcom,gpio-standby = <2>;
+ qcom,gpio-req-tbl-num = <0 1 2>;
+ qcom,gpio-req-tbl-flags = <1 0 0>;
+ qcom,gpio-req-tbl-label = "CAMIF_MCLK",
+ "CAM_RESET1",
+ "CAM_STANDBY";
+ qcom,csi-lane-assign = <0xe4>;
+ qcom,csi-lane-mask = <0x3>;
+ qcom,sensor-position = <0>;
+ qcom,sensor-mode = <1>;
+ qcom,sensor-type = <0>;
+ qcom,cci-master = <0>;
+ };
+ qcom,camera@78 {
+ compatible = "shinetech,gc0339";
+ reg = <0x78>;
+ qcom,slave-id = <0x42 0x00 0xc8>;
+ qcom,csiphy-sd-index = <1>;
+ qcom,csid-sd-index = <1>;
+ qcom,mount-angle = <90>;
+ qcom,sensor-name = "skuab_shinetech_gc0339";
+ cam_vdig-supply = <&pm8110_l14>;
+ cam_vana-supply = <&pm8110_l19>;
+ cam_vio-supply = <&pm8110_l14>;
+ qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana";
+ qcom,cam-vreg-type = <0 1 0>;
+ qcom,cam-vreg-min-voltage = <1800000 1800000 2850000>;
+ qcom,cam-vreg-max-voltage = <1800000 1800000 2850000>;
+ qcom,cam-vreg-op-mode = <200000 0 80000>;
+ qcom,gpio-no-mux = <0>;
+ gpios = <&msmgpio 14 0>,
+ <&msmgpio 15 0>,
+ <&msmgpio 85 0>;
+ qcom,gpio-standby = <2>;
+ qcom,gpio-req-tbl-num = <0 1 2>;
+ qcom,gpio-req-tbl-flags = <1 0 0>;
+ qcom,gpio-req-tbl-label = "CAMIF_MCLK",
+ "CAM_RESET",
+ "CAM_STANDBY";
+ qcom,gpio-set-tbl-num = <1 1>;
+ qcom,gpio-set-tbl-flags = <0 2>;
+ qcom,gpio-set-tbl-delay = <1000 4000>;
+ qcom,csi-lane-assign = <0xe4>;
+ qcom,csi-lane-mask = <0x3>;
+ qcom,sensor-position = <1>;
+ qcom,sensor-mode = <1>;
+ qcom,cci-master = <0>;
+ status = "ok";
+ };
+};
diff --git a/arch/arm/boot/dts/msm8974-camera-sensor-dragonboard.dtsi b/arch/arm/boot/dts/msm8974-camera-sensor-dragonboard.dtsi
index b9f2125..2f8e558 100644
--- a/arch/arm/boot/dts/msm8974-camera-sensor-dragonboard.dtsi
+++ b/arch/arm/boot/dts/msm8974-camera-sensor-dragonboard.dtsi
@@ -50,12 +50,15 @@
qcom,cam-vreg-op-mode = <105000 0 80000 100000>;
qcom,gpio-no-mux = <0>;
gpios = <&msmgpio 15 0>,
- <&msmgpio 90 0>;
+ <&msmgpio 90 0>,
+ <&msmgpio 89 0>;
qcom,gpio-reset = <1>;
- qcom,gpio-req-tbl-num = <0 1>;
- qcom,gpio-req-tbl-flags = <1 0>;
+ qcom,gpio-standby = <2>;
+ qcom,gpio-req-tbl-num = <0 1 2>;
+ qcom,gpio-req-tbl-flags = <1 0 0>;
qcom,gpio-req-tbl-label = "CAMIF_MCLK",
- "CAM_RESET1";
+ "CAM_RESET1",
+ "CAM_STANDBY";
qcom,gpio-set-tbl-num = <1 1>;
qcom,gpio-set-tbl-flags = <0 2>;
qcom,gpio-set-tbl-delay = <1000 30000>;
@@ -90,12 +93,15 @@
qcom,cam-vreg-op-mode = <105000 0 80000 100000>;
qcom,gpio-no-mux = <0>;
gpios = <&msmgpio 15 0>,
- <&msmgpio 90 0>;
+ <&msmgpio 90 0>,
+ <&msmgpio 89 0>;
qcom,gpio-reset = <1>;
- qcom,gpio-req-tbl-num = <0 1>;
- qcom,gpio-req-tbl-flags = <1 0>;
+ qcom,gpio-standby = <2>;
+ qcom,gpio-req-tbl-num = <0 1 2>;
+ qcom,gpio-req-tbl-flags = <1 0 0>;
qcom,gpio-req-tbl-label = "CAMIF_MCLK",
- "CAM_RESET1";
+ "CAM_RESET1",
+ "CAM_STANDBY";
qcom,gpio-set-tbl-num = <1 1>;
qcom,gpio-set-tbl-flags = <0 2>;
qcom,gpio-set-tbl-delay = <1000 30000>;
diff --git a/arch/arm/boot/dts/msm8974-cdp.dtsi b/arch/arm/boot/dts/msm8974-cdp.dtsi
index bcdaf1b..8a3a77e 100644
--- a/arch/arm/boot/dts/msm8974-cdp.dtsi
+++ b/arch/arm/boot/dts/msm8974-cdp.dtsi
@@ -252,63 +252,61 @@
};
};
-&spmi_bus {
- qcom,pm8941@1 {
- qcom,leds@d800 {
- status = "okay";
- qcom,wled_0 {
- label = "wled";
- linux,name = "wled:backlight";
- linux,default-trigger = "bkl-trigger";
- qcom,cs-out-en;
- qcom,op-fdbck = <1>;
- qcom,default-state = "on";
- qcom,max-current = <25>;
- qcom,ctrl-delay-us = <0>;
- qcom,boost-curr-lim = <3>;
- qcom,cp-sel = <0>;
- qcom,switch-freq = <2>;
- qcom,ovp-val = <2>;
- qcom,num-strings = <1>;
- qcom,id = <0>;
- };
+&pm8941_lsid1 {
+ qcom,leds@d800 {
+ status = "okay";
+ qcom,wled_0 {
+ label = "wled";
+ linux,name = "wled:backlight";
+ linux,default-trigger = "bkl-trigger";
+ qcom,cs-out-en;
+ qcom,op-fdbck = <1>;
+ qcom,default-state = "on";
+ qcom,max-current = <25>;
+ qcom,ctrl-delay-us = <0>;
+ qcom,boost-curr-lim = <3>;
+ qcom,cp-sel = <0>;
+ qcom,switch-freq = <2>;
+ qcom,ovp-val = <2>;
+ qcom,num-strings = <1>;
+ qcom,id = <0>;
};
+ };
- qcom,leds@d900 {
- status = "disabled";
- };
+ qcom,leds@d900 {
+ status = "disabled";
+ };
- qcom,leds@da00 {
- status = "disabled";
- };
+ qcom,leds@da00 {
+ status = "disabled";
+ };
- qcom,leds@db00 {
- status = "disabled";
- };
+ qcom,leds@db00 {
+ status = "disabled";
+ };
- qcom,leds@dc00 {
- status = "disabled";
- };
+ qcom,leds@dc00 {
+ status = "disabled";
+ };
- qcom,leds@dd00 {
- status = "disabled";
- };
+ qcom,leds@dd00 {
+ status = "disabled";
+ };
- qcom,leds@de00 {
- status = "disabled";
- };
+ qcom,leds@de00 {
+ status = "disabled";
+ };
- qcom,leds@df00 {
- status = "disabled";
- };
+ qcom,leds@df00 {
+ status = "disabled";
+ };
- qcom,leds@e000 {
- status = "disabled";
- };
+ qcom,leds@e000 {
+ status = "disabled";
+ };
- qcom,leds@e100 {
- status = "disabled";
- };
+ qcom,leds@e100 {
+ status = "disabled";
};
};
diff --git a/arch/arm/boot/dts/msm8974-clock.dtsi b/arch/arm/boot/dts/msm8974-clock.dtsi
index bed5d70..8d90771 100644
--- a/arch/arm/boot/dts/msm8974-clock.dtsi
+++ b/arch/arm/boot/dts/msm8974-clock.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, 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
@@ -10,18 +10,14 @@
* GNU General Public License for more details.
*/
-&spmi_bus {
+&pm8941_lsid0 {
+ pm8941_clkdiv1: clkdiv@5b00 {
+ qcom,cxo-div = <2>;
+ };
- qcom,pm8941@0 {
+ pm8941_clkdiv2: clkdiv@5c00 {
+ };
- pm8941_clkdiv1: clkdiv@5b00 {
- qcom,cxo-div = <2>;
- };
-
- pm8941_clkdiv2: clkdiv@5c00 {
- };
-
- pm8941_clkdiv3: clkdiv@5d00 {
- };
+ pm8941_clkdiv3: clkdiv@5d00 {
};
};
diff --git a/arch/arm/boot/dts/msm8974-fluid.dtsi b/arch/arm/boot/dts/msm8974-fluid.dtsi
index 638e6dd..af21e43 100644
--- a/arch/arm/boot/dts/msm8974-fluid.dtsi
+++ b/arch/arm/boot/dts/msm8974-fluid.dtsi
@@ -251,63 +251,61 @@
};
};
-&spmi_bus {
- qcom,pm8941@1 {
- qcom,leds@d800 {
- status = "okay";
- qcom,wled_0 {
- label = "wled";
- linux,name = "wled:backlight";
- linux,default-trigger = "bkl-trigger";
- qcom,cs-out-en;
- qcom,op-fdbck = <1>;
- qcom,default-state = "on";
- qcom,max-current = <25>;
- qcom,ctrl-delay-us = <0>;
- qcom,boost-curr-lim = <3>;
- qcom,cp-sel = <0>;
- qcom,switch-freq = <2>;
- qcom,ovp-val = <2>;
- qcom,num-strings = <1>;
- qcom,id = <0>;
- };
+&pm8941_lsid1 {
+ qcom,leds@d800 {
+ status = "okay";
+ qcom,wled_0 {
+ label = "wled";
+ linux,name = "wled:backlight";
+ linux,default-trigger = "bkl-trigger";
+ qcom,cs-out-en;
+ qcom,op-fdbck = <1>;
+ qcom,default-state = "on";
+ qcom,max-current = <25>;
+ qcom,ctrl-delay-us = <0>;
+ qcom,boost-curr-lim = <3>;
+ qcom,cp-sel = <0>;
+ qcom,switch-freq = <2>;
+ qcom,ovp-val = <2>;
+ qcom,num-strings = <1>;
+ qcom,id = <0>;
};
+ };
- qcom,leds@d900 {
- status = "disabled";
- };
+ qcom,leds@d900 {
+ status = "disabled";
+ };
- qcom,leds@da00 {
- status = "disabled";
- };
+ qcom,leds@da00 {
+ status = "disabled";
+ };
- qcom,leds@db00 {
- status = "disabled";
- };
+ qcom,leds@db00 {
+ status = "disabled";
+ };
- qcom,leds@dc00 {
- status = "disabled";
- };
+ qcom,leds@dc00 {
+ status = "disabled";
+ };
- qcom,leds@dd00 {
- status = "disabled";
- };
+ qcom,leds@dd00 {
+ status = "disabled";
+ };
- qcom,leds@de00 {
- status = "disabled";
- };
+ qcom,leds@de00 {
+ status = "disabled";
+ };
- qcom,leds@df00 {
- status = "disabled";
- };
+ qcom,leds@df00 {
+ status = "disabled";
+ };
- qcom,leds@e000 {
- status = "disabled";
- };
+ qcom,leds@e000 {
+ status = "disabled";
+ };
- qcom,leds@e100 {
- status = "disabled";
- };
+ qcom,leds@e100 {
+ status = "disabled";
};
};
@@ -408,6 +406,7 @@
qcom,min-fcc-learning-soc = <20>;
qcom,min-fcc-ocv-pc = <30>;
qcom,min-fcc-learning-samples = <5>;
+ qcom,fcc-resolution = <10>;
status = "ok";
};
diff --git a/arch/arm/boot/dts/msm8974-leds.dtsi b/arch/arm/boot/dts/msm8974-leds.dtsi
index 5e91f45..ab57468 100644
--- a/arch/arm/boot/dts/msm8974-leds.dtsi
+++ b/arch/arm/boot/dts/msm8974-leds.dtsi
@@ -11,119 +11,116 @@
* GNU General Public License for more details.
*/
-&spmi_bus {
- qcom,pm8941@1 {
- qcom,leds@d000 {
- status = "okay";
- qcom,rgb_0 {
- label = "rgb";
- linux,name = "led:rgb_red";
- qcom,mode = "pwm";
- qcom,pwm-channel = <6>;
- qcom,pwm-us = <1000>;
- qcom,max-current = <12>;
- qcom,default-state = "off";
- qcom,id = <3>;
- linux,default-trigger =
- "battery-charging";
- };
-
- qcom,rgb_1 {
- label = "rgb";
- linux,name = "led:rgb_green";
- qcom,mode = "pwm";
- qcom,pwm-channel = <5>;
- qcom,pwm-us = <1000>;
- qcom,max-current = <12>;
- qcom,default-state = "off";
- qcom,id = <4>;
- linux,default-trigger = "battery-full";
- };
-
- qcom,rgb_2 {
- label = "rgb";
- linux,name = "led:rgb_blue";
- qcom,mode = "pwm";
- qcom,pwm-channel = <4>;
- qcom,pwm-us = <1000>;
- qcom,max-current = <12>;
- qcom,id = <5>;
- status = "disabled";
- };
+&pm8941_lsid1 {
+ qcom,leds@d000 {
+ status = "okay";
+ qcom,rgb_0 {
+ label = "rgb";
+ linux,name = "led:rgb_red";
+ qcom,mode = "pwm";
+ qcom,pwm-channel = <6>;
+ qcom,pwm-us = <1000>;
+ qcom,max-current = <12>;
+ qcom,default-state = "off";
+ qcom,id = <3>;
+ linux,default-trigger =
+ "battery-charging";
};
- qcom,leds@d100 {
- status = "disabled";
+ qcom,rgb_1 {
+ label = "rgb";
+ linux,name = "led:rgb_green";
+ qcom,mode = "pwm";
+ qcom,pwm-channel = <5>;
+ qcom,pwm-us = <1000>;
+ qcom,max-current = <12>;
+ qcom,default-state = "off";
+ qcom,id = <4>;
+ linux,default-trigger = "battery-full";
};
- qcom,leds@d200 {
- status = "disabled";
- };
-
- qcom,leds@d300 {
- status = "okay";
- pm8941_flash0: qcom,flash_0 {
- qcom,max-current = <1000>;
- qcom,default-state = "off";
- qcom,headroom = <3>;
- qcom,duration = <1280>;
- qcom,clamp-curr = <200>;
- qcom,startup-dly = <3>;
- qcom,safety-timer;
- label = "flash";
- linux,default-trigger =
- "flash0_trigger";
- qcom,id = <1>;
- linux,name = "led:flash_0";
- qcom,current = <625>;
- };
-
- pm8941_flash1: qcom,flash_1 {
- qcom,max-current = <1000>;
- qcom,default-state = "off";
- qcom,headroom = <3>;
- qcom,duration = <1280>;
- qcom,clamp-curr = <200>;
- qcom,startup-dly = <3>;
- qcom,safety-timer;
- linux,default-trigger =
- "flash1_trigger";
- label = "flash";
- qcom,id = <2>;
- linux,name = "led:flash_1";
- qcom,current = <625>;
- };
-
- pm8941_torch: qcom,flash_torch {
- qcom,max-current = <200>;
- qcom,default-state = "off";
- qcom,headroom = <0>;
- qcom,startup-dly = <1>;
- linux,default-trigger =
- "torch_trigger";
- label = "flash";
- qcom,id = <2>;
- linux,name = "led:flash_torch";
- qcom,current = <200>;
- qcom,torch-enable;
- };
- };
-
- qcom,leds@d400 {
- status = "disabled";
- };
-
- qcom,leds@d500 {
- status = "disabled";
- };
-
- qcom,leds@d600 {
- status = "disabled";
- };
-
- qcom,leds@d700 {
+ qcom,rgb_2 {
+ label = "rgb";
+ linux,name = "led:rgb_blue";
+ qcom,mode = "pwm";
+ qcom,pwm-channel = <4>;
+ qcom,pwm-us = <1000>;
+ qcom,max-current = <12>;
+ qcom,id = <5>;
status = "disabled";
};
};
-};
+ qcom,leds@d100 {
+ status = "disabled";
+ };
+
+ qcom,leds@d200 {
+ status = "disabled";
+ };
+
+ qcom,leds@d300 {
+ status = "okay";
+ pm8941_flash0: qcom,flash_0 {
+ qcom,max-current = <1000>;
+ qcom,default-state = "off";
+ qcom,headroom = <3>;
+ qcom,duration = <1280>;
+ qcom,clamp-curr = <200>;
+ qcom,startup-dly = <3>;
+ qcom,safety-timer;
+ label = "flash";
+ linux,default-trigger =
+ "flash0_trigger";
+ qcom,id = <1>;
+ linux,name = "led:flash_0";
+ qcom,current = <625>;
+ };
+
+ pm8941_flash1: qcom,flash_1 {
+ qcom,max-current = <1000>;
+ qcom,default-state = "off";
+ qcom,headroom = <3>;
+ qcom,duration = <1280>;
+ qcom,clamp-curr = <200>;
+ qcom,startup-dly = <3>;
+ qcom,safety-timer;
+ linux,default-trigger =
+ "flash1_trigger";
+ label = "flash";
+ qcom,id = <2>;
+ linux,name = "led:flash_1";
+ qcom,current = <625>;
+ };
+
+ pm8941_torch: qcom,flash_torch {
+ qcom,max-current = <200>;
+ qcom,default-state = "off";
+ qcom,headroom = <0>;
+ qcom,startup-dly = <1>;
+ linux,default-trigger =
+ "torch_trigger";
+ label = "flash";
+ qcom,id = <2>;
+ linux,name = "led:flash_torch";
+ qcom,current = <200>;
+ qcom,torch-enable;
+ };
+ };
+
+ qcom,leds@d400 {
+ status = "disabled";
+ };
+
+ qcom,leds@d500 {
+ status = "disabled";
+ };
+
+ qcom,leds@d600 {
+ status = "disabled";
+ };
+
+ qcom,leds@d700 {
+ status = "disabled";
+ };
+};
diff --git a/arch/arm/boot/dts/msm8974-liquid.dtsi b/arch/arm/boot/dts/msm8974-liquid.dtsi
index ddf5b60..82bb7dc 100644
--- a/arch/arm/boot/dts/msm8974-liquid.dtsi
+++ b/arch/arm/boot/dts/msm8974-liquid.dtsi
@@ -782,14 +782,12 @@
};
};
-&spmi_bus {
- qcom,pm8941@1 {
- qcom,leds@d000 {
- qcom,rgb_2 {
- status = "ok";
- qcom,default-state = "on";
- qcom,turn-off-delay-ms = <1000>;
- };
+&pm8941_lsid1 {
+ qcom,leds@d000 {
+ qcom,rgb_2 {
+ status = "ok";
+ qcom,default-state = "on";
+ qcom,turn-off-delay-ms = <1000>;
};
};
};
diff --git a/arch/arm/boot/dts/msm8974-mtp.dtsi b/arch/arm/boot/dts/msm8974-mtp.dtsi
index 4af48cc..8e3b7cc 100644
--- a/arch/arm/boot/dts/msm8974-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8974-mtp.dtsi
@@ -192,63 +192,61 @@
};
};
-&spmi_bus {
- qcom,pm8941@1 {
- qcom,leds@d800 {
- status = "okay";
- qcom,wled_0 {
- label = "wled";
- linux,name = "wled:backlight";
- linux,default-trigger = "bkl-trigger";
- qcom,cs-out-en;
- qcom,op-fdbck = <1>;
- qcom,default-state = "on";
- qcom,max-current = <25>;
- qcom,ctrl-delay-us = <0>;
- qcom,boost-curr-lim = <3>;
- qcom,cp-sel = <0>;
- qcom,switch-freq = <2>;
- qcom,ovp-val = <2>;
- qcom,num-strings = <1>;
- qcom,id = <0>;
- };
+&pm8941_lsid1 {
+ qcom,leds@d800 {
+ status = "okay";
+ qcom,wled_0 {
+ label = "wled";
+ linux,name = "wled:backlight";
+ linux,default-trigger = "bkl-trigger";
+ qcom,cs-out-en;
+ qcom,op-fdbck = <1>;
+ qcom,default-state = "on";
+ qcom,max-current = <25>;
+ qcom,ctrl-delay-us = <0>;
+ qcom,boost-curr-lim = <3>;
+ qcom,cp-sel = <0>;
+ qcom,switch-freq = <2>;
+ qcom,ovp-val = <2>;
+ qcom,num-strings = <1>;
+ qcom,id = <0>;
};
+ };
- qcom,leds@d900 {
- status = "disabled";
- };
+ qcom,leds@d900 {
+ status = "disabled";
+ };
- qcom,leds@da00 {
- status = "disabled";
- };
+ qcom,leds@da00 {
+ status = "disabled";
+ };
- qcom,leds@db00 {
- status = "disabled";
- };
+ qcom,leds@db00 {
+ status = "disabled";
+ };
- qcom,leds@dc00 {
- status = "disabled";
- };
+ qcom,leds@dc00 {
+ status = "disabled";
+ };
- qcom,leds@dd00 {
- status = "disabled";
- };
+ qcom,leds@dd00 {
+ status = "disabled";
+ };
- qcom,leds@de00 {
- status = "disabled";
- };
+ qcom,leds@de00 {
+ status = "disabled";
+ };
- qcom,leds@df00 {
- status = "disabled";
- };
+ qcom,leds@df00 {
+ status = "disabled";
+ };
- qcom,leds@e000 {
- status = "disabled";
- };
+ qcom,leds@e000 {
+ status = "disabled";
+ };
- qcom,leds@e100 {
- status = "disabled";
- };
+ qcom,leds@e100 {
+ status = "disabled";
};
};
@@ -357,6 +355,7 @@
qcom,min-fcc-learning-soc = <20>;
qcom,min-fcc-ocv-pc = <30>;
qcom,min-fcc-learning-samples = <5>;
+ qcom,fcc-resolution = <10>;
status = "ok";
};
@@ -667,21 +666,6 @@
};
};
-&pm8841_mpps {
-
- mpp@a000 { /* MPP 1 */
- };
-
- mpp@a100 { /* MPP 2 */
- };
-
- mpp@a200 { /* MPP 3 */
- };
-
- mpp@a300 { /* MPP 4 */
- };
-};
-
&slim_msm {
taiko_codec {
qcom,cdc-micbias1-ext-cap;
diff --git a/arch/arm/boot/dts/msm8974-regulator.dtsi b/arch/arm/boot/dts/msm8974-regulator.dtsi
index d9d5aaa..eae9032 100644
--- a/arch/arm/boot/dts/msm8974-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8974-regulator.dtsi
@@ -13,48 +13,44 @@
/* QPNP controlled regulators: */
-&spmi_bus {
+&pm8941_lsid1 {
+ pm8941_boost: regulator@a000 {
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ qcom,enable-time = <500>;
+ status = "okay";
+ };
- qcom,pm8941@1 {
+ pm8941_mvs1: regulator@8300 {
+ parent-supply = <&pm8941_chg_otg>;
+ qcom,enable-time = <1000>;
+ qcom,pull-down-enable = <1>;
+ interrupts = <0x1 0x83 0x2>;
+ interrupt-names = "ocp";
+ qcom,ocp-enable = <1>;
+ qcom,ocp-max-retries = <10>;
+ qcom,ocp-retry-delay = <30>;
+ qcom,soft-start-enable = <1>;
+ qcom,vs-soft-start-strength = <0>;
+ qcom,hpm-enable = <1>;
+ qcom,auto-mode-enable = <0>;
+ status = "okay";
+ };
- pm8941_boost: regulator@a000 {
- regulator-min-microvolt = <5000000>;
- regulator-max-microvolt = <5000000>;
- qcom,enable-time = <500>;
- status = "okay";
- };
-
- pm8941_mvs1: regulator@8300 {
- parent-supply = <&pm8941_chg_otg>;
- qcom,enable-time = <1000>;
- qcom,pull-down-enable = <1>;
- interrupts = <0x1 0x83 0x2>;
- interrupt-names = "ocp";
- qcom,ocp-enable = <1>;
- qcom,ocp-max-retries = <10>;
- qcom,ocp-retry-delay = <30>;
- qcom,soft-start-enable = <1>;
- qcom,vs-soft-start-strength = <0>;
- qcom,hpm-enable = <1>;
- qcom,auto-mode-enable = <0>;
- status = "okay";
- };
-
- pm8941_mvs2: regulator@8400 {
- parent-supply = <&pm8941_boost>;
- qcom,enable-time = <1000>;
- qcom,pull-down-enable = <1>;
- interrupts = <0x1 0x84 0x2>;
- interrupt-names = "ocp";
- qcom,ocp-enable = <1>;
- qcom,ocp-max-retries = <10>;
- qcom,ocp-retry-delay = <30>;
- qcom,soft-start-enable = <1>;
- qcom,vs-soft-start-strength = <0>;
- qcom,hpm-enable = <1>;
- qcom,auto-mode-enable = <0>;
- status = "okay";
- };
+ pm8941_mvs2: regulator@8400 {
+ parent-supply = <&pm8941_boost>;
+ qcom,enable-time = <1000>;
+ qcom,pull-down-enable = <1>;
+ interrupts = <0x1 0x84 0x2>;
+ interrupt-names = "ocp";
+ qcom,ocp-enable = <1>;
+ qcom,ocp-max-retries = <10>;
+ qcom,ocp-retry-delay = <30>;
+ qcom,soft-start-enable = <1>;
+ qcom,vs-soft-start-strength = <0>;
+ qcom,hpm-enable = <1>;
+ qcom,auto-mode-enable = <0>;
+ status = "okay";
};
};
diff --git a/arch/arm/boot/dts/msm8974-v1.dtsi b/arch/arm/boot/dts/msm8974-v1.dtsi
index caec2dc..cfacac6 100644
--- a/arch/arm/boot/dts/msm8974-v1.dtsi
+++ b/arch/arm/boot/dts/msm8974-v1.dtsi
@@ -17,6 +17,21 @@
*/
/include/ "msm8974.dtsi"
+
+/include/ "msm-pm8x41-rpm-regulator.dtsi"
+/include/ "msm-pm8841.dtsi"
+&spmi_bus {
+ pm8941_lsid0: qcom,pm8941@0 {
+ reg = <0x0>;
+ };
+ pm8941_lsid1: qcom,pm8941@1 {
+ reg = <0x1>;
+ };
+};
+/include/ "msm-pm8941.dtsi"
+/include/ "msm8974-regulator.dtsi"
+/include/ "msm8974-clock.dtsi"
+
/include/ "msm8974-v1-iommu.dtsi"
/include/ "msm8974-v1-iommu-domains.dtsi"
/include/ "msm8974-v1-pm.dtsi"
diff --git a/arch/arm/boot/dts/msm8610-qrd.dts b/arch/arm/boot/dts/msm8974-v2-2-cdp.dts
similarity index 62%
copy from arch/arm/boot/dts/msm8610-qrd.dts
copy to arch/arm/boot/dts/msm8974-v2-2-cdp.dts
index 86294df..cb8895f 100644
--- a/arch/arm/boot/dts/msm8610-qrd.dts
+++ b/arch/arm/boot/dts/msm8974-v2-2-cdp.dts
@@ -12,14 +12,13 @@
/dts-v1/;
-/include/ "msm8610-qrd.dtsi"
-/include/ "dsi-v2-panel-hx8379a-wvga-video.dtsi"
-/include/ "msm8610-qrd-camera-sensor.dtsi"
+/include/ "msm8974-v2-2.dtsi"
+/include/ "msm8974-cdp.dtsi"
/ {
- model = "Qualcomm MSM 8610 QRD";
- compatible = "qcom,msm8610-qrd", "qcom,msm8610", "qcom,qrd";
- qcom,msm-id = <147 11 0>, <165 11 0>, <161 11 0>, <162 11 0>,
- <163 11 0>, <164 11 0>, <166 11 0>;
+ model = "Qualcomm MSM 8974v2 CDP";
+ compatible = "qcom,msm8974-cdp", "qcom,msm8974", "qcom,cdp";
+ qcom,msm-id = <126 1 0x20002>,
+ <185 1 0x20002>,
+ <186 1 0x20002>;
};
-
diff --git a/arch/arm/boot/dts/msm8610-qrd.dts b/arch/arm/boot/dts/msm8974-v2-2-fluid.dts
similarity index 62%
copy from arch/arm/boot/dts/msm8610-qrd.dts
copy to arch/arm/boot/dts/msm8974-v2-2-fluid.dts
index 86294df..8e04c18 100644
--- a/arch/arm/boot/dts/msm8610-qrd.dts
+++ b/arch/arm/boot/dts/msm8974-v2-2-fluid.dts
@@ -12,14 +12,13 @@
/dts-v1/;
-/include/ "msm8610-qrd.dtsi"
-/include/ "dsi-v2-panel-hx8379a-wvga-video.dtsi"
-/include/ "msm8610-qrd-camera-sensor.dtsi"
+/include/ "msm8974-v2-2.dtsi"
+/include/ "msm8974-fluid.dtsi"
/ {
- model = "Qualcomm MSM 8610 QRD";
- compatible = "qcom,msm8610-qrd", "qcom,msm8610", "qcom,qrd";
- qcom,msm-id = <147 11 0>, <165 11 0>, <161 11 0>, <162 11 0>,
- <163 11 0>, <164 11 0>, <166 11 0>;
+ model = "Qualcomm MSM 8974v2 FLUID";
+ compatible = "qcom,msm8974-fluid", "qcom,msm8974", "qcom,fluid";
+ qcom,msm-id = <126 3 0x20002>,
+ <185 3 0x20002>,
+ <186 3 0x20002>;
};
-
diff --git a/arch/arm/boot/dts/msm8610-qrd.dts b/arch/arm/boot/dts/msm8974-v2-2-liquid.dts
similarity index 62%
rename from arch/arm/boot/dts/msm8610-qrd.dts
rename to arch/arm/boot/dts/msm8974-v2-2-liquid.dts
index 86294df..7128abe 100644
--- a/arch/arm/boot/dts/msm8610-qrd.dts
+++ b/arch/arm/boot/dts/msm8974-v2-2-liquid.dts
@@ -12,14 +12,13 @@
/dts-v1/;
-/include/ "msm8610-qrd.dtsi"
-/include/ "dsi-v2-panel-hx8379a-wvga-video.dtsi"
-/include/ "msm8610-qrd-camera-sensor.dtsi"
+/include/ "msm8974-v2-2.dtsi"
+/include/ "msm8974-liquid.dtsi"
/ {
- model = "Qualcomm MSM 8610 QRD";
- compatible = "qcom,msm8610-qrd", "qcom,msm8610", "qcom,qrd";
- qcom,msm-id = <147 11 0>, <165 11 0>, <161 11 0>, <162 11 0>,
- <163 11 0>, <164 11 0>, <166 11 0>;
+ model = "Qualcomm MSM 8974v2 LIQUID";
+ compatible = "qcom,msm8974-liquid", "qcom,msm8974", "qcom,liquid";
+ qcom,msm-id = <126 9 0x20002>,
+ <185 9 0x20002>,
+ <186 9 0x20002>;
};
-
diff --git a/arch/arm/boot/dts/msm8610-qrd.dts b/arch/arm/boot/dts/msm8974-v2-2-mtp.dts
similarity index 62%
copy from arch/arm/boot/dts/msm8610-qrd.dts
copy to arch/arm/boot/dts/msm8974-v2-2-mtp.dts
index 86294df..b7e35cf 100644
--- a/arch/arm/boot/dts/msm8610-qrd.dts
+++ b/arch/arm/boot/dts/msm8974-v2-2-mtp.dts
@@ -12,14 +12,17 @@
/dts-v1/;
-/include/ "msm8610-qrd.dtsi"
-/include/ "dsi-v2-panel-hx8379a-wvga-video.dtsi"
-/include/ "msm8610-qrd-camera-sensor.dtsi"
+/include/ "msm8974-v2-2.dtsi"
+/include/ "msm8974-mtp.dtsi"
/ {
- model = "Qualcomm MSM 8610 QRD";
- compatible = "qcom,msm8610-qrd", "qcom,msm8610", "qcom,qrd";
- qcom,msm-id = <147 11 0>, <165 11 0>, <161 11 0>, <162 11 0>,
- <163 11 0>, <164 11 0>, <166 11 0>;
+ model = "Qualcomm MSM 8974v2 MTP";
+ compatible = "qcom,msm8974-mtp", "qcom,msm8974", "qcom,mtp";
+ qcom,msm-id = <126 8 0x20002>,
+ <185 8 0x20002>,
+ <186 8 0x20002>;
};
+&pm8941_chg {
+ qcom,bpd-detection = "bpd_thm";
+};
diff --git a/arch/arm/boot/dts/msm8974-v2-2.dtsi b/arch/arm/boot/dts/msm8974-v2-2.dtsi
new file mode 100644
index 0000000..09455b1
--- /dev/null
+++ b/arch/arm/boot/dts/msm8974-v2-2.dtsi
@@ -0,0 +1,105 @@
+/* Copyright (c) 2013, 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.
+ */
+
+/*
+ * As a general rule, only version-specific property overrides should be placed
+ * inside this file. However, device definitions should be placed inside the
+ * msm8974.dtsi file.
+ */
+
+/include/ "msm8974-v2.dtsi"
+
+/* GPU overrides */
+&msm_gpu {
+ /* Updated chip ID */
+ qcom,chipid = <0x03030001>;
+
+ qcom,initial-pwrlevel = <4>;
+
+ /* Updated bus bandwidth requirements */
+ qcom,msm-bus,vectors-KBps =
+ /* Off */
+ <26 512 0 0>, <89 604 0 0>,
+ /* SVS */
+ <26 512 0 2400000>, <89 604 0 3000000>,
+ /* Nominal / SVS */
+ <26 512 0 4656000>, <89 604 0 3000000>,
+ /* Nominal */
+ <26 512 0 4656000>, <89 604 0 5120000>,
+ /* Turbo / Nominal */
+ <26 512 0 7464000>, <89 604 0 5120000>,
+ /* Turbo */
+ <26 512 0 7464000>, <89 604 0 6400000>;
+
+ qcom,gpu-pwrlevels {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ compatible = "qcom,gpu-pwrlevels";
+
+ qcom,gpu-pwrlevel@0 {
+ reg = <0>;
+ qcom,gpu-freq = <450000000>;
+ qcom,bus-freq = <5>;
+ qcom,io-fraction = <33>;
+ };
+
+ qcom,gpu-pwrlevel@1 {
+ reg = <1>;
+ qcom,gpu-freq = <389000000>;
+ qcom,bus-freq = <4>;
+ qcom,io-fraction = <33>;
+ };
+
+ qcom,gpu-pwrlevel@2 {
+ reg = <2>;
+ qcom,gpu-freq = <389000000>;
+ qcom,bus-freq = <3>;
+ qcom,io-fraction = <66>;
+ };
+
+ qcom,gpu-pwrlevel@3 {
+ reg = <3>;
+ qcom,gpu-freq = <320000000>;
+ qcom,bus-freq = <4>;
+ qcom,io-fraction = <66>;
+ };
+
+ qcom,gpu-pwrlevel@4 {
+ reg = <4>;
+ qcom,gpu-freq = <320000000>;
+ qcom,bus-freq = <3>;
+ qcom,io-fraction = <66>;
+ };
+
+ qcom,gpu-pwrlevel@5 {
+ reg = <5>;
+ qcom,gpu-freq = <200000000>;
+ qcom,bus-freq = <2>;
+ qcom,io-fraction = <100>;
+ };
+
+ qcom,gpu-pwrlevel@6 {
+ reg = <6>;
+ qcom,gpu-freq = <200000000>;
+ qcom,bus-freq = <1>;
+ qcom,io-fraction = <100>;
+ };
+
+ qcom,gpu-pwrlevel@7 {
+ reg = <7>;
+ qcom,gpu-freq = <27000000>;
+ qcom,bus-freq = <0>;
+ qcom,io-fraction = <0>;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/msm8974-v2.dtsi b/arch/arm/boot/dts/msm8974-v2.dtsi
index 0240039..0b3b60f 100644
--- a/arch/arm/boot/dts/msm8974-v2.dtsi
+++ b/arch/arm/boot/dts/msm8974-v2.dtsi
@@ -17,6 +17,21 @@
*/
/include/ "msm8974.dtsi"
+
+/include/ "msm-pm8x41-rpm-regulator.dtsi"
+/include/ "msm-pm8841.dtsi"
+&spmi_bus {
+ pm8941_lsid0: qcom,pm8941@0 {
+ reg = <0x0>;
+ };
+ pm8941_lsid1: qcom,pm8941@1 {
+ reg = <0x1>;
+ };
+};
+/include/ "msm-pm8941.dtsi"
+/include/ "msm8974-regulator.dtsi"
+/include/ "msm8974-clock.dtsi"
+
/include/ "msm8974-v2-iommu.dtsi"
/include/ "msm8974-v2-iommu-domains.dtsi"
/include/ "msm8974-v2-pm.dtsi"
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index 181eb9a..aaa5f3e 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -1364,7 +1364,7 @@
tsens: tsens@fc4a8000 {
compatible = "qcom,msm-tsens";
reg = <0xfc4a8000 0x2000>,
- <0xfc4b8000 0x1000>;
+ <0xfc4bc000 0x1000>;
reg-names = "tsens_physical", "tsens_eeprom_physical";
interrupts = <0 184 0>;
qcom,sensors = <11>;
@@ -1487,24 +1487,24 @@
qcom,vdd-restriction-temp-hysteresis = <10>;
qcom,pmic-sw-mode-temp = <85>;
qcom,pmic-sw-mode-temp-hysteresis = <75>;
- qcom,pmic-sw-mode-regs = "vdd_dig";
- vdd_dig-supply = <&pm8841_s2_floor_corner>;
- vdd_gfx-supply = <&pm8841_s4_floor_corner>;
+ qcom,pmic-sw-mode-regs = "vdd-dig";
+ vdd-dig-supply = <&pm8841_s2_floor_corner>;
+ vdd-gfx-supply = <&pm8841_s4_floor_corner>;
qcom,vdd-dig-rstr{
- qcom,vdd-rstr-reg = "vdd_dig";
+ qcom,vdd-rstr-reg = "vdd-dig";
qcom,levels = <5 7 7>; /* Nominal, Super Turbo, Super Turbo */
qcom,min-level = <1>; /* No Request */
};
qcom,vdd-gfx-rstr{
- qcom,vdd-rstr-reg = "vdd_gfx";
+ qcom,vdd-rstr-reg = "vdd-gfx";
qcom,levels = <5 7 7>; /* Nominal, Super Turbo, Super Turbo */
qcom,min-level = <1>; /* No Request */
};
qcom,vdd-apps-rstr{
- qcom,vdd-rstr-reg = "vdd_apps";
+ qcom,vdd-rstr-reg = "vdd-apps";
qcom,levels = <1881600 1958400 2265600>;
qcom,freq-req;
};
@@ -1690,9 +1690,3 @@
&gdsc_usb_hsic {
status = "ok";
};
-
-/include/ "msm-pm8x41-rpm-regulator.dtsi"
-/include/ "msm-pm8841.dtsi"
-/include/ "msm-pm8941.dtsi"
-/include/ "msm8974-regulator.dtsi"
-/include/ "msm8974-clock.dtsi"
diff --git a/arch/arm/boot/dts/msm8974pro-ab-mtp.dts b/arch/arm/boot/dts/msm8974pro-ab-mtp.dts
index 002baf7..d1566ae 100644
--- a/arch/arm/boot/dts/msm8974pro-ab-mtp.dts
+++ b/arch/arm/boot/dts/msm8974pro-ab-mtp.dts
@@ -26,3 +26,7 @@
<217 8 0x10000>,
<218 8 0x10000>;
};
+
+&sdhc_1 {
+ qcom,clk-rates = <400000 20000000 25000000 50000000 100000000>;
+};
diff --git a/arch/arm/boot/dts/msm8974pro-ab.dtsi b/arch/arm/boot/dts/msm8974pro-ab.dtsi
index 9240514..88687bd 100644
--- a/arch/arm/boot/dts/msm8974pro-ab.dtsi
+++ b/arch/arm/boot/dts/msm8974pro-ab.dtsi
@@ -17,3 +17,25 @@
*/
/include/ "msm8974pro.dtsi"
+
+/include/ "msm-pm8x41-rpm-regulator.dtsi"
+/include/ "msm-pm8841.dtsi"
+&spmi_bus {
+ pm8941_lsid0: qcom,pm8941@0 {
+ reg = <0x0>;
+ };
+ pm8941_lsid1: qcom,pm8941@1 {
+ reg = <0x1>;
+ };
+};
+/include/ "msm-pm8941.dtsi"
+/include/ "msm8974-regulator.dtsi"
+/include/ "msm8974-clock.dtsi"
+
+&krait_pdn {
+ qcom,use-phase-switching;
+};
+
+&tspp {
+ vdd_cx-supply = <&pm8841_s2_corner>;
+};
diff --git a/arch/arm/boot/dts/msm8974pro-ac-mtp.dts b/arch/arm/boot/dts/msm8974pro-ac-mtp.dts
index c5042b7..b8df576 100644
--- a/arch/arm/boot/dts/msm8974pro-ac-mtp.dts
+++ b/arch/arm/boot/dts/msm8974pro-ac-mtp.dts
@@ -12,8 +12,8 @@
/dts-v1/;
-/include/ "msm8974pro-ac.dtsi"
-/include/ "msm8974-mtp.dtsi"
+/include/ "msm8974pro-ac-pm8941.dtsi"
+/include/ "msm8974pro-ac-mtp.dtsi"
/ {
model = "Qualcomm MSM 8974Pro-AC MTP";
@@ -23,3 +23,7 @@
<213 8 0x10000>,
<216 8 0x10000>;
};
+
+&sdhc_1 {
+ qcom,clk-rates = <400000 20000000 25000000 50000000 100000000>;
+};
diff --git a/arch/arm/boot/dts/msm8974pro-ac-mtp.dtsi b/arch/arm/boot/dts/msm8974pro-ac-mtp.dtsi
new file mode 100644
index 0000000..250afd2
--- /dev/null
+++ b/arch/arm/boot/dts/msm8974pro-ac-mtp.dtsi
@@ -0,0 +1,302 @@
+/* Copyright (c) 2013, 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/ "msm8974-mtp.dtsi"
+
+&cci {
+ qcom,camera@6e {
+ qcom,vdd-cx-supply = <&pma8084_s2>;
+ cam_vdig-supply = <&pma8084_l3>;
+ cam_vana-supply = <&pma8084_l17>;
+ cam_vio-supply = <&pma8084_lvs4>;
+ cam_vaf-supply = <&pma8084_l23>;
+ };
+
+ qcom,camera@20 {
+ qcom,vdd-cx-supply = <&pma8084_s2>;
+ cam_vdig-supply = <&pma8084_l3>;
+ cam_vana-supply = <&pma8084_l17>;
+ cam_vio-supply = <&pma8084_lvs4>;
+ cam_vaf-supply = <&pma8084_l23>;
+ };
+
+ qcom,camera@6c {
+ qcom,vdd-cx-supply = <&pma8084_s2>;
+ cam_vdig-supply = <&pma8084_l3>;
+ cam_vana-supply = <&pma8084_l17>;
+ cam_vio-supply = <&pma8084_lvs4>;
+ };
+
+ qcom,camera@90 {
+ qcom,vdd-cx-supply = <&pma8084_s2>;
+ cam_vdig-supply = <&pma8084_l3>;
+ cam_vana-supply = <&pma8084_l17>;
+ cam_vio-supply = <&pma8084_lvs4>;
+ };
+};
+
+&soc {
+ i2c@f9924000 {
+ atmel_mxt_ts@4a {
+ vdd_ana-supply = <&pma8084_l18>;
+ vcc_i2c-supply = <&pma8084_lvs1>;
+ };
+ };
+
+ i2c@f9967000 {
+ isa1200@48 {
+ vcc_i2c-supply = <&pma8084_s4>;
+ };
+ };
+
+ qcom,ssusb@f9200000 {
+ vbus_dwc3-supply = <&pm8941_mvs1>;
+ };
+
+ qcom,mdss_dsi_toshiba_720p_video {
+ qcom,rst-gpio = <&pma8084_gpios 20 0>;
+ };
+
+ gpio_keys {
+ camera_snapshot {
+ gpios = <&pma8084_gpios 3 0x1>;
+ };
+
+ camera_focus {
+ gpios = <&pma8084_gpios 4 0x1>;
+ };
+
+ vol_up {
+ gpios = <&pma8084_gpios 5 0x1>;
+ };
+ };
+
+ spi@f9923000 {
+ ethernet-switch@2 {
+ rst-gpio = <&pma8084_mpps 6 0>;
+ };
+ };
+};
+
+&sdhc_1 {
+ vdd-supply = <&pma8084_l20>;
+ vdd-io-supply = <&pma8084_s4>;
+};
+
+&sdhc_2 {
+ vdd-supply = <&pma8084_l21>;
+ vdd-io-supply = <&pma8084_l13>;
+};
+
+&pma8084_gpios {
+ gpio@c000 { /* GPIO 1 */
+ /* Unused */
+ qcom,mode = <0>; /* Digital input */
+ qcom,pull = <0>; /* Pull up 30 uA */
+ qcom,master-en = <1>;
+ };
+
+ gpio@c100 { /* GPIO 2 */
+ /* Unused */
+ qcom,mode = <0>; /* Digital input */
+ qcom,pull = <0>; /* Pull up 30 uA */
+ qcom,master-en = <1>;
+ };
+
+ gpio@c200 { /* GPIO 3 */
+ /* Snapshot button */
+ qcom,mode = <0>; /* Digital input */
+ qcom,pull = <0>; /* Pull up 30 uA */
+ qcom,vin-sel = <2>; /* PMA8084 S4 = 1.8 V */
+ qcom,src-sel = <0>; /* Constant */
+ qcom,master-en = <1>;
+ };
+
+ gpio@c300 { /* GPIO 4 */
+ /* Focus button */
+ qcom,mode = <0>; /* Digital input */
+ qcom,pull = <0>; /* Pull up 30 uA */
+ qcom,vin-sel = <2>; /* PMA8084 S4 = 1.8 V */
+ qcom,src-sel = <0>; /* Constant */
+ qcom,master-en = <1>;
+ };
+
+ gpio@c400 { /* GPIO 5 */
+ /* Volume up button */
+ qcom,mode = <0>; /* Digital input */
+ qcom,pull = <0>; /* Pull up 30 uA */
+ qcom,vin-sel = <2>; /* PMA8084 S4 = 1.8 V */
+ qcom,src-sel = <0>; /* Constant */
+ qcom,master-en = <1>;
+ };
+
+ gpio@c500 { /* GPIO 6 */
+ /* Flash LED now */
+ qcom,mode = <0>; /* Digital input */
+ qcom,pull = <4>; /* Pull down */
+ qcom,master-en = <1>;
+ };
+
+ gpio@c600 { /* GPIO 7 */
+ /* GRFC_12 */
+ };
+
+ gpio@c700 { /* GPIO 8 */
+ /* Unused */
+ qcom,mode = <0>; /* Digital input */
+ qcom,pull = <0>; /* Pull up 30 uA */
+ qcom,master-en = <1>;
+ };
+
+ gpio@c800 { /* GPIO 9 */
+ /* Unused */
+ qcom,mode = <1>; /* Digital output */
+ qcom,out-strength = <1>; /* Low */
+ qcom,src-sel = <2>; /* Function 1 */
+ qcom,master-en = <1>;
+ };
+
+ gpio@c900 { /* GPIO 10 */
+ /* NFC clock request */
+ qcom,mode = <0>; /* Digital input */
+ qcom,pull = <4>; /* Pull down */
+ qcom,master-en = <1>;
+ };
+
+ gpio@ca00 { /* GPIO 11 */
+ /* Unused */
+ qcom,mode = <1>; /* Digital output */
+ qcom,out-strength = <1>; /* Low */
+ qcom,src-sel = <2>; /* Function 1 */
+ qcom,master-en = <1>;
+ };
+
+ gpio@cb00 { /* GPIO 12 */
+ /* Unused */
+ qcom,mode = <1>; /* Digital output */
+ qcom,out-strength = <1>; /* Low */
+ qcom,src-sel = <2>; /* Function 1 */
+ qcom,master-en = <1>;
+ };
+
+ gpio@cc00 { /* GPIO 13 */
+ /* TS_CHGR_IN */
+ qcom,mode = <0>; /* Digital input */
+ qcom,pull = <4>; /* Pull down */
+ qcom,master-en = <1>;
+ };
+
+ gpio@cd00 { /* GPIO 14 */
+ /* Unused */
+ qcom,mode = <1>; /* Digital output */
+ qcom,out-strength = <1>; /* Low */
+ qcom,src-sel = <2>; /* Function 1 */
+ qcom,master-en = <1>;
+ };
+
+ gpio@ce00 { /* GPIO 15 */
+ /* Codec clock */
+ qcom,mode = <1>; /* Digital output */
+ qcom,output-type = <0>; /* CMOS */
+ qcom,vin-sel = <2>; /* PMA8084 S4 = 1.8 V */
+ qcom,out-strength = <1>; /* Low */
+ qcom,src-sel = <2>; /* Function 1 - DIVCLK1 */
+ qcom,master-en = <1>;
+ };
+
+ gpio@cf00 { /* GPIO 16 */
+ /* Haptics clock */
+ qcom,mode = <1>; /* Digital output */
+ qcom,output-type = <0>; /* CMOS */
+ qcom,vin-sel = <2>; /* PMA8084 S4 = 1.8 V */
+ qcom,out-strength = <3>; /* High */
+ qcom,src-sel = <3>; /* Function 2 - SLEEPCLK3 */
+ qcom,master-en = <1>;
+ };
+
+ gpio@d000 { /* GPIO 17 */
+ /* QPA clock */
+ };
+
+ gpio@d100 { /* GPIO 18 */
+ /* Unused */
+ };
+
+ gpio@d200 { /* GPIO 19 */
+ /* BOOST_BYP */
+ };
+
+ gpio@d300 { /* GPIO 20 */
+ /* Display enable */
+ qcom,mode = <1>; /* Digital output */
+ qcom,output-type = <0>; /* CMOS */
+ qcom,vin-sel = <2>; /* PMA8084 S4 = 1.8 V */
+ qcom,out-strength = <1>; /* Low */
+ qcom,src-sel = <0>; /* Constant */
+ qcom,master-en = <1>;
+ };
+
+ gpio@d400 { /* GPIO 21 */
+ /* BATT_GONE */
+ };
+
+ gpio@d500 { /* GPIO 22 */
+ /* BATT_REM_ALARM */
+ };
+};
+
+&pma8084_mpps {
+ mpp@a000 { /* MPP 1 */
+ /* SDC_UIM_VBIAS */
+ status = "disabled";
+ };
+
+ mpp@a100 { /* MPP 2 */
+ /* PM8941_PON_1 */
+ };
+
+ mpp@a200 { /* MPP 3 */
+ /* VREF_DAC */
+ };
+
+ mpp@a300 { /* MPP 4 */
+ /* Unused */
+ };
+
+ mpp@a400 { /* MPP 5 */
+ /* Unused */
+ };
+
+ mpp@a500 { /* MPP 6 */
+ /* SPI ethernet enable */
+ qcom,mode = <1>; /* Digital output */
+ qcom,output-type = <0>; /* CMOS */
+ qcom,vin-sel = <2>; /* PMA8084 S4 = 1.8V > 1.6V */
+ qcom,src-sel = <0>; /* Constant */
+ qcom,out-strength = <1>; /* Low */
+ qcom,master-en = <1>;
+ };
+
+ mpp@a600 { /* MPP 7 */
+ /* NFC disable */
+ qcom,mode = <1>; /* Digital output */
+ qcom,out-strength = <1>; /* Low */
+ qcom,master-en = <1>;
+ };
+
+ mpp@a700 { /* MPP 8 */
+ /* Unused */
+ qcom,mode = <1>; /* Digital output */
+ qcom,out-strength = <1>; /* Low */
+ qcom,master-en = <1>;
+ };
+};
diff --git a/arch/arm/boot/dts/msm8974pro-ac-pm8941.dtsi b/arch/arm/boot/dts/msm8974pro-ac-pm8941.dtsi
new file mode 100644
index 0000000..4d10ded
--- /dev/null
+++ b/arch/arm/boot/dts/msm8974pro-ac-pm8941.dtsi
@@ -0,0 +1,250 @@
+/* Copyright (c) 2013, 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/ "msm8974pro-ac.dtsi"
+&spmi_bus {
+ pm8941_lsid0: qcom,pm8941@2 {
+ reg = <0x2>;
+ };
+ pm8941_lsid1: qcom,pm8941@3 {
+ reg = <0x3>;
+ };
+};
+/include/ "msm-pm8941.dtsi"
+
+&pma8084_vadc {
+ status = "disabled";
+};
+
+&pma8084_adc_tm {
+ status = "disabled";
+};
+
+&pm8941_lsid0 {
+ qcom,power-on@800 {
+ status = "disabled";
+ };
+
+ clkdiv@5b00 {
+ status = "disabled";
+ };
+
+ clkdiv@5c00 {
+ status = "disabled";
+ };
+
+ clkdiv@5d00 {
+ status = "disabled";
+ };
+
+ qcom,pm8941_rtc {
+ status = "disabled";
+ };
+
+ gpios {
+ status = "disabled";
+ };
+
+ mpps {
+ status = "disabled";
+ };
+};
+
+&pm8941_lsid1 {
+ pm8941_boost: regulator@a000 {
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ qcom,enable-time = <500>;
+ status = "okay";
+ };
+
+ pm8941_mvs1: regulator@8300 {
+ parent-supply = <&pm8941_chg_otg>;
+ qcom,enable-time = <1000>;
+ qcom,pull-down-enable = <1>;
+ interrupts = <0x3 0x83 0x2>;
+ interrupt-names = "ocp";
+ qcom,ocp-enable = <1>;
+ qcom,ocp-max-retries = <10>;
+ qcom,ocp-retry-delay = <30>;
+ qcom,soft-start-enable = <1>;
+ qcom,vs-soft-start-strength = <0>;
+ qcom,hpm-enable = <1>;
+ qcom,auto-mode-enable = <0>;
+ status = "okay";
+ };
+};
+
+&pma8084_mvs1 {
+ parent-supply = <&pm8941_boost>;
+};
+
+&pm8941_chg {
+ otg-parent-supply = <&pm8941_boost>;
+};
+
+&pm8941_chg_boost {
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ regulator-name = "8941_smbb_boost";
+};
+
+&pm8941_chg_otg {
+ regulator-name = "8941_smbb_otg";
+};
+
+/* Correct PM8941 local slave ID 0 to use global SID 4 for all interrupts. */
+&pm8941_lsid0 {
+ qcom,temp-alarm@2400 {
+ interrupts = <0x2 0x24 0x0>;
+ };
+
+ qcom,power-on@800 {
+ interrupts = <0x2 0x8 0x0>,
+ <0x2 0x8 0x1>,
+ <0x2 0x8 0x4>,
+ <0x2 0x8 0x5>;
+ interrupt-names = "kpdpwr", "resin",
+ "resin-bark", "kpdpwr-resin-bark";
+ };
+
+ qcom,bsi@1b00 {
+ interrupts = <0x2 0x1b 0x0>,
+ <0x2 0x1b 0x1>,
+ <0x2 0x1b 0x2>,
+ <0x2 0x12 0x0>;
+ interrupt-names = "err",
+ "rx",
+ "tx",
+ "batt-present";
+ };
+
+ qcom,bms {
+ qcom,bms-bms@4000 {
+ 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 = "cc_thr",
+ "ocv_for_r",
+ "good_ocv",
+ "charge_begin",
+ "ocv_thr",
+ "sw_cc_thr",
+ "vsense_avg",
+ "vsense_for_r";
+ };
+ };
+
+ qcom,charger {
+ qcom,chgr@1000 {
+ 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 = "vbat-det-lo",
+ "vbat-det-hi",
+ "chgwdog",
+ "state-change",
+ "trkl-chg-on",
+ "fast-chg-on",
+ "chg-failed",
+ "chg-done";
+ };
+
+ qcom,buck@1100 {
+ interrupts = <0x2 0x11 0x0>,
+ <0x2 0x11 0x1>,
+ <0x2 0x11 0x2>,
+ <0x2 0x11 0x3>,
+ <0x2 0x11 0x4>,
+ <0x2 0x11 0x5>,
+ <0x2 0x11 0x6>;
+ interrupt-names = "vbat-ov",
+ "vreg-ov",
+ "overtemp",
+ "vchg-loop",
+ "ichg-loop",
+ "ibat-loop",
+ "vdd-loop";
+ };
+
+ qcom,bat-if@1200 {
+ interrupts = <0x2 0x12 0x0>,
+ <0x2 0x12 0x1>,
+ <0x2 0x12 0x2>,
+ <0x2 0x12 0x3>,
+ <0x2 0x12 0x4>;
+ interrupt-names = "batt-pres",
+ "bat-temp-ok",
+ "bat-fet-on",
+ "vcp-on",
+ "psi";
+ };
+
+ qcom,usb-chgpth@1300 {
+ interrupts = <0x2 0x13 0x0>,
+ <0x2 0x13 0x1>,
+ <0x2 0x13 0x2>;
+ interrupt-names = "coarse-det-usb",
+ "usbin-valid",
+ "chg-gone";
+ };
+
+ qcom,dc-chgpth@1400 {
+ interrupts = <0x2 0x14 0x0>,
+ <0x2 0x14 0x1>;
+ interrupt-names = "coarse-det-dc",
+ "dcin-valid";
+ };
+
+ qcom,boost@1500 {
+ interrupts = <0x2 0x15 0x0>,
+ <0x2 0x15 0x1>;
+ interrupt-names = "boost-pwr-ok",
+ "limit-error";
+ };
+ };
+
+ qcom,pm8941_rtc {
+ qcom,pm8941_rtc_alarm@6100 {
+ interrupts = <0x2 0x61 0x1>;
+ };
+ };
+
+ vadc@3100 {
+ interrupts = <0x2 0x31 0x0>;
+ interrupt-names = "eoc-int-en-set";
+ };
+
+ iadc@3600 {
+ interrupts = <0x2 0x36 0x0>;
+ interrupt-names = "eoc-int-en-set";
+ };
+
+ qcom,vadc@3400 {
+ interrupts = <0x2 0x34 0x0>,
+ <0x2 0x34 0x3>,
+ <0x2 0x34 0x4>;
+ interrupt-names = "eoc-int-en-set",
+ "high-thr-en-set",
+ "low-thr-en-set";
+ };
+};
diff --git a/arch/arm/boot/dts/msm8974pro-ac-regulator.dtsi b/arch/arm/boot/dts/msm8974pro-ac-regulator.dtsi
new file mode 100644
index 0000000..9d7f316
--- /dev/null
+++ b/arch/arm/boot/dts/msm8974pro-ac-regulator.dtsi
@@ -0,0 +1,566 @@
+/* Copyright (c) 2013, 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.
+ */
+
+
+/* QPNP controlled regulators: */
+
+&spmi_bus {
+ qcom,pma8084@1 {
+ pma8084_mvs1: regulator@8400 {
+ qcom,enable-time = <1000>;
+ qcom,pull-down-enable = <1>;
+ interrupts = <0x1 0x84 0x2>;
+ interrupt-names = "ocp";
+ qcom,ocp-enable = <1>;
+ qcom,ocp-max-retries = <10>;
+ qcom,ocp-retry-delay = <30>;
+ qcom,soft-start-enable = <1>;
+ qcom,vs-soft-start-strength = <0>;
+ qcom,hpm-enable = <1>;
+ qcom,auto-mode-enable = <0>;
+ status = "okay";
+ };
+ };
+};
+
+/* RPM controlled regulators: */
+
+&rpm_bus {
+ rpm-regulator-smpa1 {
+ status = "okay";
+ pma8084_s1: regulator-s1 {
+ regulator-min-microvolt = <675000>;
+ regulator-max-microvolt = <1050000>;
+ status = "okay";
+ };
+ pma8084_s1_ao: regulator-s1-ao {
+ regulator-name = "8084_s1_ao";
+ qcom,set = <1>;
+ regulator-min-microvolt = <675000>;
+ regulator-max-microvolt = <1050000>;
+ status = "okay";
+ compatible = "qcom,rpm-regulator-smd";
+ };
+ pma8084_s1_so: regulator-s1-so {
+ regulator-name = "8084_s1_so";
+ qcom,set = <2>;
+ regulator-min-microvolt = <675000>;
+ regulator-max-microvolt = <1050000>;
+ qcom,init-voltage = <675000>;
+ status = "okay";
+ compatible = "qcom,rpm-regulator-smd";
+ };
+ };
+
+ rpm-regulator-smpa2 {
+ status = "okay";
+ pma8084_s2: regulator-s2 {
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <1050000>;
+ status = "okay";
+ };
+ pma8084_s2_corner: regulator-s2-corner {
+ regulator-name = "8084_s2_corner";
+ qcom,set = <3>;
+ regulator-min-microvolt = <1>;
+ regulator-max-microvolt = <7>;
+ qcom,use-voltage-corner;
+ compatible = "qcom,rpm-regulator-smd";
+ qcom,consumer-supplies = "vdd_dig", "";
+ };
+ pma8084_s2_corner_ao: regulator-s2-corner-ao {
+ regulator-name = "8084_s2_corner_ao";
+ qcom,set = <1>;
+ regulator-min-microvolt = <1>;
+ regulator-max-microvolt = <7>;
+ qcom,use-voltage-corner;
+ compatible = "qcom,rpm-regulator-smd";
+ };
+ pma8084_s2_floor_corner: regulator-s2-floor-corner {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8084_s2_floor_corner";
+ qcom,set = <3>;
+ regulator-min-microvolt = <1>;
+ regulator-max-microvolt = <7>;
+ qcom,use-voltage-floor-corner;
+ qcom,always-send-voltage;
+ };
+ };
+
+
+ rpm-regulator-smpa3 {
+ status = "okay";
+ pma8084_s3: regulator-s3 {
+ regulator-min-microvolt = <1300000>;
+ regulator-max-microvolt = <1300000>;
+ qcom,init-voltage = <1300000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-smpa4 {
+ status = "okay";
+ pma8084_s4: regulator-s4 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ qcom,init-voltage = <1800000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-smpa5 {
+ status = "okay";
+ pma8084_s5: regulator-s5 {
+ regulator-min-microvolt = <2150000>;
+ regulator-max-microvolt = <2150000>;
+ qcom,init-voltage = <2150000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-smpa6 {
+ status = "okay";
+ pma8084_s6: regulator-s6 {
+ regulator-min-microvolt = <1050000>;
+ regulator-max-microvolt = <1050000>;
+ qcom,init-voltage = <1050000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-smpa7 {
+ status = "okay";
+ pma8084_s7: regulator-s7 {
+ regulator-min-microvolt = <815000>;
+ regulator-max-microvolt = <900000>;
+ status = "okay";
+ };
+ pma8084_s7_corner: regulator-s7-corner {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8084_s7_corner";
+ qcom,set = <3>;
+ qcom,use-voltage-corner;
+ regulator-min-microvolt = <1>;
+ regulator-max-microvolt = <7>;
+ qcom,init-voltage-corner = <3>; /* SVS SOC */
+ };
+ pma8084_s7_floor_corner: regulator-s7-floor-corner {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8084_s7_floor_corner";
+ qcom,set = <3>;
+ regulator-min-microvolt = <1>;
+ regulator-max-microvolt = <7>;
+ qcom,use-voltage-floor-corner;
+ qcom,always-send-voltage;
+ };
+ };
+
+ rpm-regulator-ldoa1 {
+ status = "okay";
+ pma8084_l1: regulator-l1 {
+ regulator-min-microvolt = <1225000>;
+ regulator-max-microvolt = <1225000>;
+ qcom,init-voltage = <1225000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa2 {
+ status = "okay";
+ pma8084_l2: regulator-l2 {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ qcom,init-voltage = <1200000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa3 {
+ status = "okay";
+ pma8084_l3: regulator-l3 {
+ regulator-min-microvolt = <1225000>;
+ regulator-max-microvolt = <1225000>;
+ qcom,init-voltage = <1225000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa4 {
+ status = "okay";
+ pma8084_l4: regulator-l4 {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1225000>;
+ qcom,init-voltage = <1225000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa5 {
+ status = "okay";
+ pma8084_l5: regulator-l5 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ qcom,init-voltage = <1800000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa6 {
+ status = "okay";
+ pma8084_l6: regulator-l6 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ qcom,init-voltage = <1800000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa7 {
+ status = "okay";
+ pma8084_l7: regulator-l7 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ qcom,init-voltage = <1800000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa8 {
+ status = "okay";
+ pma8084_l8: regulator-l8 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ qcom,init-voltage = <1800000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa9 {
+ status = "okay";
+ pma8084_l9: regulator-l9 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2950000>;
+ qcom,init-voltage = <2950000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa10 {
+ status = "okay";
+ pma8084_l10: regulator-l10 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2950000>;
+ qcom,init-voltage = <2950000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa11 {
+ status = "okay";
+ pma8084_l11: regulator-l11 {
+ regulator-min-microvolt = <1300000>;
+ regulator-max-microvolt = <1300000>;
+ qcom,init-voltage = <1300000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa12 {
+ status = "okay";
+ pma8084_l12: regulator-l12 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ status = "okay";
+ };
+ pma8084_l12_ao: regulator-l12-ao {
+ regulator-name = "8084_l12_ao";
+ qcom,set = <1>;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ status = "okay";
+ compatible = "qcom,rpm-regulator-smd";
+ };
+ };
+
+ rpm-regulator-ldoa13 {
+ status = "okay";
+ pma8084_l13: regulator-l13 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2950000>;
+ qcom,init-voltage = <2950000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa14 {
+ status = "okay";
+ pma8084_l14: regulator-l14 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ qcom,init-voltage = <1800000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa15 {
+ status = "okay";
+ pma8084_l15: regulator-l15 {
+ regulator-min-microvolt = <2050000>;
+ regulator-max-microvolt = <2050000>;
+ qcom,init-voltage = <2050000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa16 {
+ status = "okay";
+ pma8084_l16: regulator-l16 {
+ regulator-min-microvolt = <2700000>;
+ regulator-max-microvolt = <2700000>;
+ qcom,init-voltage = <2700000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa17 {
+ status = "okay";
+ pma8084_l17: regulator-l17 {
+ regulator-min-microvolt = <2850000>;
+ regulator-max-microvolt = <2850000>;
+ qcom,init-voltage = <2850000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa18 {
+ status = "okay";
+ pma8084_l18: regulator-l18 {
+ regulator-min-microvolt = <2850000>;
+ regulator-max-microvolt = <2850000>;
+ qcom,init-voltage = <2850000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa19 {
+ status = "okay";
+ pma8084_l19: regulator-l19 {
+ regulator-min-microvolt = <2900000>;
+ regulator-max-microvolt = <3300000>;
+ qcom,init-voltage = <2900000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa20 {
+ status = "okay";
+ pma8084_l20: regulator-l20 {
+ regulator-min-microvolt = <2950000>;
+ regulator-max-microvolt = <2950000>;
+ qcom,init-voltage = <2950000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa21 {
+ status = "okay";
+ pma8084_l21: regulator-l21 {
+ regulator-min-microvolt = <2950000>;
+ regulator-max-microvolt = <2950000>;
+ qcom,init-voltage = <2950000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa22 {
+ status = "okay";
+ pma8084_l22: regulator-l22 {
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ qcom,init-voltage = <3000000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa23 {
+ status = "okay";
+ pma8084_l23: regulator-l23 {
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ qcom,init-voltage = <3000000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa24 {
+ status = "okay";
+ pma8084_l24: regulator-l24 {
+ regulator-min-microvolt = <3075000>;
+ regulator-max-microvolt = <3075000>;
+ qcom,init-voltage = <3075000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa25 {
+ status = "okay";
+ pma8084_l25: regulator-l25 {
+ regulator-min-microvolt = <2100000>;
+ regulator-max-microvolt = <2100000>;
+ qcom,init-voltage = <2100000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa26 {
+ status = "okay";
+ pma8084_l26: regulator-l26 {
+ regulator-min-microvolt = <2050000>;
+ regulator-max-microvolt = <2050000>;
+ qcom,init-voltage = <2050000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa27 {
+ status = "okay";
+ pma8084_l27: regulator-l27 {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1225000>;
+ qcom,init-voltage = <1200000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-vsa1 {
+ status = "okay";
+ pma8084_lvs1: regulator-lvs1 {
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-vsa2 {
+ status = "okay";
+ pma8084_lvs2: regulator-lvs2 {
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-vsa3 {
+ status = "okay";
+ pma8084_lvs3: regulator-lvs3 {
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-vsa4 {
+ status = "okay";
+ pma8084_lvs4: regulator-lvs4 {
+ status = "okay";
+ };
+ };
+};
+
+&soc {
+ krait_pdn: krait-pdn@f9011000 {
+ reg = <0xf9011000 0x1000>,
+ <0xfc4b80b0 8>;
+ reg-names = "apcs_gcc", "phase-scaling-efuse";
+ compatible = "qcom,krait-pdn";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+ qcom,pfm-threshold = <73>;
+
+ krait0_vreg: regulator@f9088000 {
+ compatible = "qcom,krait-regulator";
+ regulator-name = "krait0";
+ reg = <0xf9088000 0x1000>, /* APCS_ALIAS0_KPSS_ACS */
+ <0xf908a800 0x1000>; /* APCS_ALIAS0_KPSS_MDD */
+ reg-names = "acs", "mdd";
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <1100000>;
+ qcom,headroom-voltage = <150000>;
+ qcom,retention-voltage = <675000>;
+ qcom,ldo-default-voltage = <750000>;
+ qcom,ldo-threshold-voltage = <850000>;
+ qcom,ldo-delta-voltage = <50000>;
+ qcom,cpu-num = <0>;
+ };
+
+ krait1_vreg: regulator@f9098000 {
+ compatible = "qcom,krait-regulator";
+ regulator-name = "krait1";
+ reg = <0xf9098000 0x1000>, /* APCS_ALIAS1_KPSS_ACS */
+ <0xf909a800 0x1000>; /* APCS_ALIAS1_KPSS_MDD */
+ reg-names = "acs", "mdd";
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <1100000>;
+ qcom,headroom-voltage = <150000>;
+ qcom,retention-voltage = <675000>;
+ qcom,ldo-default-voltage = <750000>;
+ qcom,ldo-threshold-voltage = <850000>;
+ qcom,ldo-delta-voltage = <50000>;
+ qcom,cpu-num = <1>;
+ };
+
+ krait2_vreg: regulator@f90a8000 {
+ compatible = "qcom,krait-regulator";
+ regulator-name = "krait2";
+ reg = <0xf90a8000 0x1000>, /* APCS_ALIAS2_KPSS_ACS */
+ <0xf90aa800 0x1000>; /* APCS_ALIAS2_KPSS_MDD */
+ reg-names = "acs", "mdd";
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <1100000>;
+ qcom,headroom-voltage = <150000>;
+ qcom,retention-voltage = <675000>;
+ qcom,ldo-default-voltage = <750000>;
+ qcom,ldo-threshold-voltage = <850000>;
+ qcom,ldo-delta-voltage = <50000>;
+ qcom,cpu-num = <2>;
+ };
+
+ krait3_vreg: regulator@f90b8000 {
+ compatible = "qcom,krait-regulator";
+ regulator-name = "krait3";
+ reg = <0xf90b8000 0x1000>, /* APCS_ALIAS3_KPSS_ACS */
+ <0xf90ba800 0x1000>; /* APCS_ALIAS3_KPSS_MDD */
+ reg-names = "acs", "mdd";
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <1100000>;
+ qcom,headroom-voltage = <150000>;
+ qcom,retention-voltage = <675000>;
+ qcom,ldo-default-voltage = <750000>;
+ qcom,ldo-threshold-voltage = <850000>;
+ qcom,ldo-delta-voltage = <50000>;
+ qcom,cpu-num = <3>;
+ };
+ };
+
+ /* SPI expects a regulator device, but no hardware is present. */
+ spi_eth_vreg: spi_eth_phy_vreg {
+ compatible = "regulator-fixed";
+ regulator-name = "ethernet_phy";
+ regulator-always-on;
+ };
+
+ /*
+ * vph_pwr_vreg represents the unregulated battery voltage supply
+ * VPH_PWR that is present whenever the device is powered on.
+ */
+ vph_pwr_vreg: vph_pwr_vreg {
+ compatible = "regulator-fixed";
+ status = "disabled";
+ regulator-name = "vph_pwr";
+ regulator-always-on;
+ };
+};
diff --git a/arch/arm/boot/dts/msm8974pro-ac.dtsi b/arch/arm/boot/dts/msm8974pro-ac.dtsi
index 9240514..032c256 100644
--- a/arch/arm/boot/dts/msm8974pro-ac.dtsi
+++ b/arch/arm/boot/dts/msm8974pro-ac.dtsi
@@ -17,3 +17,174 @@
*/
/include/ "msm8974pro.dtsi"
+
+/include/ "msm-pma8084-rpm-regulator.dtsi"
+/include/ "msm-pma8084.dtsi"
+/include/ "msm8974pro-ac-regulator.dtsi"
+
+/*
+ * Override PM8841 and PM8941 resources with proper PMA8084 resources for
+ * MSM8974Pro AC.
+ */
+
+&soc {
+ qcom,csid@fda08000 {
+ qcom,mipi-csi-vdd-supply = <&pma8084_l12>;
+ };
+
+ qcom,csid@fda08400 {
+ qcom,mipi-csi-vdd-supply = <&pma8084_l12>;
+ };
+
+ qcom,csid@fda08800 {
+ qcom,mipi-csi-vdd-supply = <&pma8084_l12>;
+ };
+
+ qcom,csid@fda08C00 {
+ qcom,mipi-csi-vdd-supply = <&pma8084_l12>;
+ };
+
+ tpiu@fc318000 {
+ vdd-supply = <&pma8084_l21>;
+ };
+
+ qcom,mdss_dsi@fd922800 {
+ vdd-supply = <&pma8084_l22>;
+ vddio-supply = <&pma8084_l12>;
+ vdda-supply = <&pma8084_l2>;
+ };
+
+ qcom,mdss_dsi@fd922e00 {
+ vdd-supply = <&pma8084_l22>;
+ vddio-supply = <&pma8084_l12>;
+ vdda-supply = <&pma8084_l2>;
+ };
+
+ qcom,hdmi_tx@fd922100 {
+ hpd-5v-supply = <&pma8084_mvs1>;
+ core-vdda-supply = <&pma8084_l12>;
+ core-vcc-supply = <&pma8084_s4>;
+ };
+
+ qcom,mdss_edp@fd923400 {
+ vdda-supply = <&pma8084_l12>;
+ };
+
+ usb@f9a55000 {
+ HSUSB_VDDCX-supply = <&pma8084_s2_corner>;
+ HSUSB_1p8-supply = <&pma8084_l6>;
+ HSUSB_3p3-supply = <&pma8084_l24>;
+ };
+
+ qcom,sdcc@f9824000 {
+ vdd-supply = <&pma8084_l20>;
+ vdd-io-supply = <&pma8084_s4>;
+ };
+
+ qcom,sdcc@f98a4000 {
+ vdd-supply = <&pma8084_l21>;
+ vdd-io-supply = <&pma8084_l13>;
+ };
+
+ slim@fe12f000 {
+ taiko_codec {
+ cdc-vdd-buck-supply = <&pma8084_s5>;
+ cdc-vdd-tx-h-supply = <&pma8084_s4>;
+ cdc-vdd-rx-h-supply = <&pma8084_s4>;
+ cdc-vddpx-1-supply = <&pma8084_s4>;
+ cdc-vdd-a-1p2v-supply = <&pma8084_l1>;
+ cdc-vddcx-1-supply = <&pma8084_l1>;
+ cdc-vddcx-2-supply = <&pma8084_l1>;
+ };
+ };
+
+ qcom,acpuclk@f9000000 {
+ krait0_mem-supply = <&pma8084_s1_ao>;
+ krait1_mem-supply = <&pma8084_s1_ao>;
+ krait2_mem-supply = <&pma8084_s1_ao>;
+ krait3_mem-supply = <&pma8084_s1_ao>;
+ krait0_dig-supply = <&pma8084_s2_corner_ao>;
+ krait1_dig-supply = <&pma8084_s2_corner_ao>;
+ krait2_dig-supply = <&pma8084_s2_corner_ao>;
+ krait3_dig-supply = <&pma8084_s2_corner_ao>;
+ krait0_hfpll-supply = <&pma8084_l12_ao>;
+ krait1_hfpll-supply = <&pma8084_l12_ao>;
+ krait2_hfpll-supply = <&pma8084_l12_ao>;
+ krait3_hfpll-supply = <&pma8084_l12_ao>;
+ l2_hfpll-supply = <&pma8084_l12_ao>;
+ };
+
+ qcom,ssusb@f9200000 {
+ ssusb_vdd_dig-supply = <&pma8084_s2_corner>;
+ SSUSB_1p8-supply = <&pma8084_l6>;
+ hsusb_vdd_dig-supply = <&pma8084_s2_corner>;
+ HSUSB_1p8-supply = <&pma8084_l6>;
+ HSUSB_3p3-supply = <&pma8084_l24>;
+ };
+
+ qcom,ehci-host@f9a55000 {
+ HSUSB_VDDCX-supply = <&pma8084_s2>;
+ HSUSB_1p8-supply = <&pma8084_l6>;
+ HSUSB_3p3-supply = <&pma8084_l24>;
+ };
+
+ qcom,gdsc@fd8c4024 {
+ parent-supply = <&pma8084_s7_corner>;
+ };
+
+ qcom,lpass@fe200000 {
+ vdd_cx-supply = <&pma8084_s2_corner>;
+ };
+
+ qcom,mss@fc880000 {
+ vdd_mss-supply = <&pma8084_s6>;
+ vdd_cx-supply = <&pma8084_s2_corner>;
+ vdd_mx-supply = <&pma8084_s1>;
+ vdd_pll-supply = <&pma8084_l12>;
+ };
+
+ qcom,pronto@fb21b000 {
+ vdd_pronto_pll-supply = <&pma8084_l12>;
+ };
+
+ qcom,wcnss-wlan@fb000000 {
+ qcom,pronto-vddmx-supply = <&pma8084_s1>;
+ qcom,pronto-vddcx-supply = <&pma8084_s2>;
+ qcom,pronto-vddpx-supply = <&pma8084_s4>;
+ qcom,iris-vddxo-supply = <&pma8084_l6>;
+ qcom,iris-vddrfa-supply = <&pma8084_l11>;
+ qcom,iris-vddpa-supply = <&pma8084_l19>;
+ qcom,iris-vdddig-supply = <&pma8084_s4>;
+ };
+
+ qcom,msm-thermal {
+ vdd-dig-supply = <&pma8084_s2_floor_corner>;
+ vdd-gfx-supply = <&pma8084_s7_floor_corner>;
+ };
+
+ qcom,lpm-resources {
+ qcom,lpm-resources@0 {
+ qcom,name = "vdd-dig";
+ qcom,type = <0x61706d73>; /* "smpa" */
+ qcom,id = <2>;
+ };
+
+ qcom,lpm-resources@1 {
+ qcom,name = "vdd-mem";
+ qcom,type = <0x61706d73>; /* "smpa" */
+ qcom,id = <1>;
+ };
+ };
+
+ sound {
+ qcom,cdc-mclk-gpios = <&pma8084_gpios 15 0>;
+ };
+};
+
+&krait_pdn {
+ qcom,use-phase-switching;
+};
+
+&tspp {
+ vdd_cx-supply = <&pma8084_s2_corner>;
+};
diff --git a/arch/arm/boot/dts/msm8974pro.dtsi b/arch/arm/boot/dts/msm8974pro.dtsi
index 96e78ac..b80eb0f 100644
--- a/arch/arm/boot/dts/msm8974pro.dtsi
+++ b/arch/arm/boot/dts/msm8974pro.dtsi
@@ -37,7 +37,7 @@
/* GPU overrides */
&msm_gpu {
/* Updated chip ID */
- qcom,chipid = <0x03030001>;
+ qcom,chipid = <0x03030002>;
/* Updated bus bandwidth requirements */
qcom,msm-bus,vectors-KBps =
@@ -53,6 +53,55 @@
<26 512 0 7464000>, <89 604 0 5120000>,
/* Turbo */
<26 512 0 7464000>, <89 604 0 6400000>;
+
+ qcom,gpu-pwrlevels {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ compatible = "qcom,gpu-pwrlevels";
+
+ qcom,gpu-pwrlevel@0 {
+ reg = <0>;
+ qcom,gpu-freq = <550000000>;
+ qcom,bus-freq = <5>;
+ qcom,io-fraction = <33>;
+ };
+
+ qcom,gpu-pwrlevel@1 {
+ reg = <1>;
+ qcom,gpu-freq = <320000000>;
+ qcom,bus-freq = <4>;
+ qcom,io-fraction = <66>;
+ };
+
+ qcom,gpu-pwrlevel@2 {
+ reg = <2>;
+ qcom,gpu-freq = <320000000>;
+ qcom,bus-freq = <3>;
+ qcom,io-fraction = <66>;
+ };
+
+ qcom,gpu-pwrlevel@3 {
+ reg = <3>;
+ qcom,gpu-freq = <200000000>;
+ qcom,bus-freq = <2>;
+ qcom,io-fraction = <100>;
+ };
+
+ qcom,gpu-pwrlevel@4 {
+ reg = <4>;
+ qcom,gpu-freq = <200000000>;
+ qcom,bus-freq = <1>;
+ qcom,io-fraction = <100>;
+ };
+
+ qcom,gpu-pwrlevel@5 {
+ reg = <5>;
+ qcom,gpu-freq = <27000000>;
+ qcom,bus-freq = <0>;
+ qcom,io-fraction = <0>;
+ };
+ };
};
&mdss_mdp {
@@ -128,11 +177,3 @@
<0x42 0x2>,
<0x120 0x3>;
};
-
-&krait_pdn {
- qcom,use-phase-switching;
-};
-
-&tspp {
- vdd_cx-supply = <&pm8841_s2_corner>;
-};
diff --git a/arch/arm/boot/dts/msm9625-pm.dtsi b/arch/arm/boot/dts/msm9625-pm.dtsi
index 24c6143..e18e143 100644
--- a/arch/arm/boot/dts/msm9625-pm.dtsi
+++ b/arch/arm/boot/dts/msm9625-pm.dtsi
@@ -271,8 +271,9 @@
<37 71>;
};
- qcom,pm-8x60 {
+ qcom,pm-8x60@fe805664 {
compatible = "qcom,pm-8x60";
+ reg = <0xfe805664 0x40>;
qcom,pc-mode = "tz_l2_ext";
qcom,use-sync-timer;
};
diff --git a/arch/arm/boot/dts/msm9625.dtsi b/arch/arm/boot/dts/msm9625.dtsi
index 68f639f..5520401 100644
--- a/arch/arm/boot/dts/msm9625.dtsi
+++ b/arch/arm/boot/dts/msm9625.dtsi
@@ -173,7 +173,7 @@
qcom,msm-bus,vectors-KBps =
<87 512 0 0>,
<87 512 40000 640000>;
- qcom,hsusb-log2-itc = <5>;
+ qcom,hsusb-log2-itc = <4>;
};
hsic_host: hsic@f9a15000 {
@@ -511,7 +511,7 @@
tsens@fc4a8000 {
compatible = "qcom,msm-tsens";
reg = <0xfc4a8000 0x2000>,
- <0xfc4b8000 0x1000>;
+ <0xfc4bc000 0x1000>;
reg-names = "tsens_physical", "tsens_eeprom_physical";
interrupts = <0 184 0>;
qcom,sensors = <5>;
diff --git a/arch/arm/boot/dts/msmkrypton.dtsi b/arch/arm/boot/dts/msmkrypton.dtsi
index ba6377c..3743c54 100644
--- a/arch/arm/boot/dts/msmkrypton.dtsi
+++ b/arch/arm/boot/dts/msmkrypton.dtsi
@@ -50,6 +50,11 @@
reg = <0xfe807800 0x1000>; /* Address and size of IMEM */
};
+ qcom,msm-mem-hole {
+ compatible = "qcom,msm-mem-hole";
+ qcom,memblock-remove = <0x02000000 0x06000000>; /* Address and Size of Hole */
+ };
+
timer@f9020000 {
#address-cells = <1>;
#size-cells = <1>;
@@ -123,6 +128,15 @@
status = "disabled";
};
+ qcom,sps@f9980000 {
+ compatible = "qcom,msm_sps";
+ reg = <0xf9984000 0x15000>,
+ <0xf9999000 0xb000>,
+ <0xfe803000 0xd000>,
+ <0xfe805000 0x1000>;
+ interrupts = <0 94 0>;
+ };
+
spi_6: spi@f9928000 { /* BLSP1 QUP6 */
cell-index = <0>;
compatible = "qcom,spi-qup-v2";
diff --git a/arch/arm/boot/dts/msmsamarium-sim.dts b/arch/arm/boot/dts/msmsamarium-sim.dts
index 4acffae..d23bd89 100644
--- a/arch/arm/boot/dts/msmsamarium-sim.dts
+++ b/arch/arm/boot/dts/msmsamarium-sim.dts
@@ -53,3 +53,7 @@
status = "ok";
};
+
+&usb_otg {
+ status = "ok";
+};
diff --git a/arch/arm/boot/dts/msmsamarium.dtsi b/arch/arm/boot/dts/msmsamarium.dtsi
index e743989..fdf2680 100644
--- a/arch/arm/boot/dts/msmsamarium.dtsi
+++ b/arch/arm/boot/dts/msmsamarium.dtsi
@@ -177,6 +177,40 @@
};
};
+ android_usb@fe8050c8 {
+ compatible = "qcom,android-usb";
+ reg = <0xfe8050c8 0xc8>;
+ qcom,android-usb-swfi-latency = <1>;
+ };
+
+ usb_otg: usb@f9a55000 {
+ compatible = "qcom,hsusb-otg";
+ status = "disabled";
+
+ reg = <0xf9a55000 0x400>;
+ interrupts = <0 134 0>, <0 140 0>;
+ interrupt-names = "core_irq", "async_irq";
+ HSUSB_VDDCX-supply = "";
+ HSUSB_1p8-supply = "";
+ HSUSB_3p3-supply = "";
+ qcom,vdd-voltage-level = <1 5 7>;
+
+ qcom,hsusb-otg-phy-type = <2>;
+ qcom,hsusb-otg-phy-init-seq =
+ <0x44 0x80 0x68 0x81 0x24 0x82 0x13 0x83 0xffffffff>;
+ qcom,hsusb-otg-mode = <1>;
+ qcom,hsusb-otg-otg-control = <1>;
+ qcom,hsusb-otg-disable-reset;
+
+ qcom,msm-bus,name = "usb2";
+ qcom,msm-bus,num-cases = <3>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,vectors-KBps =
+ <87 512 0 0>,
+ <87 512 60000 960000>,
+ <87 512 6000 6000>;
+ };
+
qcom,bam_dmux@fc834000 {
compatible = "qcom,bam_dmux";
reg = <0xfc834000 0x7000>;
diff --git a/arch/arm/configs/mpq8092_defconfig b/arch/arm/configs/mpq8092_defconfig
index 5d05596..0ee406a 100644
--- a/arch/arm/configs/mpq8092_defconfig
+++ b/arch/arm/configs/mpq8092_defconfig
@@ -239,6 +239,7 @@
CONFIG_INPUT_UINPUT=y
CONFIG_SERIAL_MSM_HSL=y
CONFIG_SERIAL_MSM_HSL_CONSOLE=y
+CONFIG_DIAG_CHAR=y
CONFIG_HW_RANDOM=y
CONFIG_HW_RANDOM_MSM=y
CONFIG_I2C=y
@@ -274,6 +275,7 @@
CONFIG_ION_MSM=y
CONFIG_MSM_KGSL=y
CONFIG_FB=y
+CONFIG_FB_VIRTUAL=y
CONFIG_FB_MSM=y
# CONFIG_FB_MSM_BACKLIGHT is not set
CONFIG_FB_MSM_MDSS=y
@@ -284,6 +286,7 @@
# CONFIG_LCD_CLASS_DEVICE is not set
CONFIG_BACKLIGHT_CLASS_DEVICE=y
# CONFIG_BACKLIGHT_GENERIC is not set
+CONFIG_SOUND=y
CONFIG_USB=y
CONFIG_USB_SUSPEND=y
CONFIG_USB_EHCI_HCD=y
@@ -303,6 +306,11 @@
CONFIG_USB_STORAGE_KARMA=y
CONFIG_USB_STORAGE_CYPRESS_ATACB=y
CONFIG_USB_STORAGE_ENE_UB6250=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_DEBUG_FILES=y
+CONFIG_USB_GADGET_DEBUG_FS=y
+CONFIG_USB_CI13XXX_MSM=y
+CONFIG_USB_G_ANDROID=y
CONFIG_MMC=y
CONFIG_MMC_PERF_PROFILING=y
CONFIG_MMC_UNSAFE_RESUME=y
@@ -334,6 +342,7 @@
CONFIG_QPNP_CLKDIV=y
CONFIG_MSM_IOMMU_V1=y
CONFIG_IOMMU_PGTABLES_L2=y
+CONFIG_IOMMU_NON_SECURE=y
CONFIG_EXT2_FS=y
CONFIG_EXT2_FS_XATTR=y
CONFIG_EXT3_FS=y
diff --git a/arch/arm/configs/msm8226-perf_defconfig b/arch/arm/configs/msm8226-perf_defconfig
index 0a4936d..452cd8a 100644
--- a/arch/arm/configs/msm8226-perf_defconfig
+++ b/arch/arm/configs/msm8226-perf_defconfig
@@ -244,6 +244,8 @@
CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4=y
CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_RMI4_DEV=y
CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE=y
+CONFIG_TOUCHSCREEN_FT5X06=y
+CONFIG_TOUCHSCREEN_GEN_VKEYS=y
CONFIG_INPUT_MISC=y
CONFIG_INPUT_UINPUT=y
CONFIG_INPUT_GPIO=m
diff --git a/arch/arm/configs/msm8226_defconfig b/arch/arm/configs/msm8226_defconfig
index 1ae95da..6c59c38 100644
--- a/arch/arm/configs/msm8226_defconfig
+++ b/arch/arm/configs/msm8226_defconfig
@@ -71,6 +71,7 @@
CONFIG_MSM_RTB_SEPARATE_CPUS=y
CONFIG_MSM_ENABLE_WDOG_DEBUG_CONTROL=y
CONFIG_MSM_BOOT_STATS=y
+CONFIG_MSM_XPU_ERR_FATAL=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_SMP=y
@@ -245,6 +246,8 @@
CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4=y
CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_RMI4_DEV=y
CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE=y
+CONFIG_TOUCHSCREEN_FT5X06=y
+CONFIG_TOUCHSCREEN_GEN_VKEYS=y
CONFIG_INPUT_MISC=y
CONFIG_INPUT_UINPUT=y
CONFIG_INPUT_GPIO=m
diff --git a/arch/arm/configs/msm8610-perf_defconfig b/arch/arm/configs/msm8610-perf_defconfig
index 29ef385..f2d1e29 100644
--- a/arch/arm/configs/msm8610-perf_defconfig
+++ b/arch/arm/configs/msm8610-perf_defconfig
@@ -28,6 +28,7 @@
# CONFIG_SLUB_DEBUG is not set
CONFIG_PROFILING=y
CONFIG_OPROFILE=m
+CONFIG_KPROBES=y
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
CONFIG_MODULE_FORCE_UNLOAD=y
@@ -82,6 +83,7 @@
CONFIG_AEABI=y
CONFIG_HIGHMEM=y
CONFIG_COMPACTION=y
+CONFIG_CP_ACCESS=y
CONFIG_USE_OF=y
CONFIG_CPU_FREQ_GOV_POWERSAVE=y
CONFIG_CPU_FREQ_GOV_USERSPACE=y
@@ -241,6 +243,9 @@
CONFIG_I2C=y
CONFIG_I2C_CHARDEV=y
CONFIG_I2C_QUP=y
+CONFIG_INPUT_MPU3050=y
+CONFIG_BMP18X=y
+CONFIG_BMP18X_I2C=y
CONFIG_MSM_BUSPM_DEV=m
CONFIG_SPI=y
CONFIG_SPI_QUP=y
diff --git a/arch/arm/configs/msm8610_defconfig b/arch/arm/configs/msm8610_defconfig
index 1e1b35a..9ce4f5d 100644
--- a/arch/arm/configs/msm8610_defconfig
+++ b/arch/arm/configs/msm8610_defconfig
@@ -26,6 +26,7 @@
CONFIG_EMBEDDED=y
CONFIG_PROFILING=y
CONFIG_OPROFILE=m
+CONFIG_KPROBES=y
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
CONFIG_MODULE_FORCE_UNLOAD=y
@@ -80,6 +81,7 @@
CONFIG_AEABI=y
CONFIG_HIGHMEM=y
CONFIG_COMPACTION=y
+CONFIG_CP_ACCESS=y
CONFIG_USE_OF=y
CONFIG_CPU_FREQ_GOV_POWERSAVE=y
CONFIG_CPU_FREQ_GOV_USERSPACE=y
@@ -239,6 +241,9 @@
CONFIG_I2C=y
CONFIG_I2C_CHARDEV=y
CONFIG_I2C_QUP=y
+CONFIG_INPUT_MPU3050=y
+CONFIG_BMP18X=y
+CONFIG_BMP18X_I2C=y
CONFIG_MSM_BUSPM_DEV=m
CONFIG_SPI=y
CONFIG_SPI_QUP=y
diff --git a/arch/arm/configs/msmkrypton_defconfig b/arch/arm/configs/msmkrypton_defconfig
index f073d2b..6609c32 100644
--- a/arch/arm/configs/msmkrypton_defconfig
+++ b/arch/arm/configs/msmkrypton_defconfig
@@ -104,6 +104,9 @@
CONFIG_SPI_SPIDEV=m
CONFIG_DEBUG_GPIO=y
CONFIG_GPIO_SYSFS=y
+CONFIG_SPS=y
+CONFIG_SPS_SUPPORT_BAMDMA=y
+CONFIG_SPS_SUPPORT_NDP_BAM=y
CONFIG_MMC=y
CONFIG_MMC_PERF_PROFILING=y
CONFIG_MMC_UNSAFE_RESUME=y
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 174a576..a8eee29 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -429,6 +429,7 @@
select GPIO_MSM_V3
select MAY_HAVE_SPARSE_IRQ
select SPARSE_IRQ
+ select MEMORY_HOLE_CARVEOUT
config ARCH_MSM8610
bool "MSM8610"
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 68e9282..e5a2bb84f 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -295,6 +295,7 @@
obj-$(CONFIG_ARCH_MSM8226) += gdsc.o
obj-$(CONFIG_ARCH_MSM8610) += gdsc.o
obj-$(CONFIG_ARCH_MPQ8092) += gdsc.o
+obj-$(CONFIG_ARCH_APQ8084) += gdsc.o
obj-$(CONFIG_ARCH_MSM8974) += krait-regulator.o
obj-$(CONFIG_ARCH_MSMKRYPTON) += board-krypton.o board-krypton-gpiomux.o
obj-$(CONFIG_ARCH_MSMSAMARIUM) += board-samarium.o board-samarium-gpiomux.o
diff --git a/arch/arm/mach-msm/Makefile.boot b/arch/arm/mach-msm/Makefile.boot
index 1ec850f..8b0acc6 100644
--- a/arch/arm/mach-msm/Makefile.boot
+++ b/arch/arm/mach-msm/Makefile.boot
@@ -57,6 +57,7 @@
dtb-$(CONFIG_ARCH_MSM8974) += msm8974-v2-fluid.dtb
dtb-$(CONFIG_ARCH_MSM8974) += msm8974-v2-liquid.dtb
dtb-$(CONFIG_ARCH_MSM8974) += msm8974-v2-mtp.dtb
+ dtb-$(CONFIG_ARCH_MSM8974) += apq8074-v2-cdp.dtb
dtb-$(CONFIG_ARCH_MSM8974) += apq8074-v2-liquid.dtb
dtb-$(CONFIG_ARCH_MSM8974) += apq8074-v2-dragonboard.dtb
@@ -119,7 +120,8 @@
zreladdr-$(CONFIG_ARCH_MSM8610) := 0x00008000
dtb-$(CONFIG_ARCH_MSM8610) += msm8610-rumi.dtb
dtb-$(CONFIG_ARCH_MSM8610) += msm8610-sim.dtb
- dtb-$(CONFIG_ARCH_MSM8610) += msm8610-qrd.dtb
+ dtb-$(CONFIG_ARCH_MSM8610) += msm8610-qrd-skuaa.dtb
+ dtb-$(CONFIG_ARCH_MSM8610) += msm8610-qrd-skuab.dtb
# MSMSAMARIUM
zreladdr-$(CONFIG_ARCH_MSMSAMARIUM) := 0x00008000
diff --git a/arch/arm/mach-msm/acpuclock-8974.c b/arch/arm/mach-msm/acpuclock-8974.c
index 98ed2d8..6d848d2 100644
--- a/arch/arm/mach-msm/acpuclock-8974.c
+++ b/arch/arm/mach-msm/acpuclock-8974.c
@@ -270,7 +270,7 @@
[7] = { { 806400, HFPLL, 1, 42 }, LVL_NOM, 950000, 4 },
[8] = { { 883200, HFPLL, 1, 46 }, LVL_NOM, 950000, 5 },
[9] = { { 960000, HFPLL, 1, 50 }, LVL_NOM, 950000, 5 },
- [10] = { { 1036800, HFPLL, 1, 54 }, LVL_NOM, 950000, 6 },
+ [10] = { { 1036800, HFPLL, 1, 54 }, LVL_NOM, 950000, 5 },
[11] = { { 1113600, HFPLL, 1, 58 }, LVL_HIGH, 1050000, 6 },
[12] = { { 1190400, HFPLL, 1, 62 }, LVL_HIGH, 1050000, 6 },
[13] = { { 1267200, HFPLL, 1, 66 }, LVL_HIGH, 1050000, 7 },
@@ -899,7 +899,7 @@
{ 0, { 0 } }
};
-static struct acpu_level acpu_freq_tbl_v3_pvs0[] __initdata = {
+static struct acpu_level acpu_freq_tbl_pro_pvs0[] __initdata = {
{ 1, { 300000, PLL_0, 0, 0 }, L2(0), 800000, 999 },
{ 0, { 345600, HFPLL, 2, 36 }, L2(1), 800000, 999 },
{ 1, { 422400, HFPLL, 2, 44 }, L2(2), 800000, 999 },
@@ -971,17 +971,48 @@
[2][5] = { acpu_freq_tbl_2p2g_pvs5, sizeof(acpu_freq_tbl_2p2g_pvs5) },
[2][6] = { acpu_freq_tbl_2p2g_pvs6, sizeof(acpu_freq_tbl_2p2g_pvs6) },
[2][7] = { acpu_freq_tbl_2p2g_pvs6, sizeof(acpu_freq_tbl_2p2g_pvs6) },
+};
- /* 8974v3 Bringup */
- [3][0] = { acpu_freq_tbl_v3_pvs0, sizeof(acpu_freq_tbl_v3_pvs0) },
- [3][1] = { acpu_freq_tbl_v3_pvs0, sizeof(acpu_freq_tbl_v3_pvs0) },
- [3][2] = { acpu_freq_tbl_v3_pvs0, sizeof(acpu_freq_tbl_v3_pvs0) },
- [3][3] = { acpu_freq_tbl_v3_pvs0, sizeof(acpu_freq_tbl_v3_pvs0) },
- [3][4] = { acpu_freq_tbl_v3_pvs0, sizeof(acpu_freq_tbl_v3_pvs0) },
- [3][5] = { acpu_freq_tbl_v3_pvs0, sizeof(acpu_freq_tbl_v3_pvs0) },
- [3][6] = { acpu_freq_tbl_v3_pvs0, sizeof(acpu_freq_tbl_v3_pvs0) },
- [3][7] = { acpu_freq_tbl_v3_pvs0, sizeof(acpu_freq_tbl_v3_pvs0) },
+static struct pvs_table pvs_pro[NUM_SPEED_BINS][NUM_PVS] __initdata = {
+ /* Not used by 8974Pro */
+ [0][0] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [0][1] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [0][2] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [0][3] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [0][4] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [0][5] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [0][6] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [0][7] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ /* 8974Pro AB Bringup */
+ [1][0] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [1][1] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [1][2] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [1][3] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [1][4] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [1][5] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [1][6] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [1][7] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+
+ /* Not used by 8974Pro */
+ [2][0] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [2][1] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [2][2] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [2][3] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [2][4] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [2][5] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [2][6] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [2][7] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+
+ /* 8974Pro Bringup */
+ [3][0] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [3][1] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [3][2] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [3][3] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [3][4] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [3][5] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [3][6] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [3][7] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
};
static struct msm_bus_scale_pdata bus_scale_data __initdata = {
@@ -1004,6 +1035,11 @@
.stby_khz = 300000,
};
+static void __init apply_pro_bringup_workaround(void)
+{
+ acpuclk_8974_params.pvs_tables = pvs_pro;
+}
+
static void __init apply_v1_l2_workaround(void)
{
static struct l2_level resticted_l2_tbl[] __initdata = {
@@ -1023,9 +1059,13 @@
acpuclk_8974_params.l2_freq_tbl_size = sizeof(resticted_l2_tbl);
}
+#define cpu_is_msm8974pro() (cpu_is_msm8974pro_aa() || cpu_is_msm8974pro_ab() \
+ || cpu_is_msm8974pro_ac())
+
static int __init acpuclk_8974_probe(struct platform_device *pdev)
{
- if (SOCINFO_VERSION_MAJOR(socinfo_get_version()) == 1) {
+ if (SOCINFO_VERSION_MAJOR(socinfo_get_version()) == 1
+ && cpu_is_msm8974()) {
acpuclk_8974_params.pvs_tables = pvs_v1;
acpuclk_8974_params.l2_freq_tbl = l2_freq_tbl_v1;
bus_scale_data.usecase = bw_level_tbl_v1;
@@ -1043,6 +1083,9 @@
apply_v1_l2_workaround();
}
+ if (cpu_is_msm8974pro())
+ apply_pro_bringup_workaround();
+
return acpuclk_krait_init(&pdev->dev, &acpuclk_8974_params);
}
diff --git a/arch/arm/mach-msm/bam_dmux.c b/arch/arm/mach-msm/bam_dmux.c
index b5a7552..21a940d 100644
--- a/arch/arm/mach-msm/bam_dmux.c
+++ b/arch/arm/mach-msm/bam_dmux.c
@@ -232,6 +232,7 @@
/* A2 power collaspe */
#define UL_TIMEOUT_DELAY 1000 /* in ms */
#define ENABLE_DISCONNECT_ACK 0x1
+#define SHUTDOWN_TIMEOUT_MS 500
static void toggle_apps_ack(void);
static void reconnect_to_bam(void);
static void disconnect_to_bam(void);
@@ -272,6 +273,7 @@
static int power_management_only_mode;
static int in_ssr;
static int ssr_skipped_disconnect;
+static struct completion shutdown_completion;
struct outside_notify_func {
void (*notify)(void *, int, unsigned long);
@@ -1066,6 +1068,7 @@
goto fail;
}
polling_mode = 0;
+ complete_all(&shutdown_completion);
release_wakelock();
/* handle any rx packets before interrupt was enabled */
@@ -1266,6 +1269,7 @@
" not disabled\n", __func__, ret);
break;
}
+ INIT_COMPLETION(shutdown_completion);
grab_wakelock();
polling_mode = 1;
/*
@@ -1745,6 +1749,14 @@
struct list_head *node;
struct rx_pkt_info *info;
unsigned long flags;
+ unsigned long time_remaining;
+
+ time_remaining = wait_for_completion_timeout(&shutdown_completion,
+ msecs_to_jiffies(SHUTDOWN_TIMEOUT_MS));
+ if (time_remaining == 0) {
+ pr_err("%s: shutdown completion timed out\n", __func__);
+ ssrestart_check();
+ }
bam_connection_is_active = 0;
@@ -2365,6 +2377,8 @@
init_completion(&ul_wakeup_ack_completion);
init_completion(&bam_connection_completion);
init_completion(&dfab_unvote_completion);
+ init_completion(&shutdown_completion);
+ complete_all(&shutdown_completion);
INIT_DELAYED_WORK(&ul_timeout_work, ul_timeout);
INIT_DELAYED_WORK(&queue_rx_work, queue_rx_work_func);
wake_lock_init(&bam_wakelock, WAKE_LOCK_SUSPEND, "bam_dmux_wakelock");
diff --git a/arch/arm/mach-msm/board-8092.c b/arch/arm/mach-msm/board-8092.c
index 56826c7..500731c 100644
--- a/arch/arm/mach-msm/board-8092.c
+++ b/arch/arm/mach-msm/board-8092.c
@@ -73,6 +73,8 @@
}
static struct of_dev_auxdata mpq8092_auxdata_lookup[] __initdata = {
+ OF_DEV_AUXDATA("qcom,hsusb-otg", 0xF9A55000, \
+ "msm_otg", NULL),
OF_DEV_AUXDATA("qcom,msm-lsuart-v14", 0xF991F000, \
"msm_serial_hsl.0", NULL),
OF_DEV_AUXDATA("qcom,msm-lsuart-v14", 0xF9922000, \
diff --git a/arch/arm/mach-msm/board-8226-gpiomux.c b/arch/arm/mach-msm/board-8226-gpiomux.c
index a32031d..fd831fc 100644
--- a/arch/arm/mach-msm/board-8226-gpiomux.c
+++ b/arch/arm/mach-msm/board-8226-gpiomux.c
@@ -468,6 +468,91 @@
},
};
+#ifdef CONFIG_MMC_MSM_SDC3_SUPPORT
+static struct gpiomux_setting sdc3_clk_actv_cfg = {
+ .func = GPIOMUX_FUNC_2,
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_NONE,
+};
+
+static struct gpiomux_setting sdc3_cmd_data_0_3_actv_cfg = {
+ .func = GPIOMUX_FUNC_2,
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_UP,
+};
+
+static struct gpiomux_setting sdc3_suspend_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_DOWN,
+};
+
+static struct gpiomux_setting sdc3_data_1_suspend_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_UP,
+};
+
+static struct msm_gpiomux_config msm8226_sdc3_configs[] __initdata = {
+ {
+ /* DAT3 */
+ .gpio = 39,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &sdc3_cmd_data_0_3_actv_cfg,
+ [GPIOMUX_SUSPENDED] = &sdc3_suspend_cfg,
+ },
+ },
+ {
+ /* DAT2 */
+ .gpio = 40,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &sdc3_cmd_data_0_3_actv_cfg,
+ [GPIOMUX_SUSPENDED] = &sdc3_suspend_cfg,
+ },
+ },
+ {
+ /* DAT1 */
+ .gpio = 41,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &sdc3_cmd_data_0_3_actv_cfg,
+ [GPIOMUX_SUSPENDED] = &sdc3_data_1_suspend_cfg,
+ },
+ },
+ {
+ /* DAT0 */
+ .gpio = 42,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &sdc3_cmd_data_0_3_actv_cfg,
+ [GPIOMUX_SUSPENDED] = &sdc3_suspend_cfg,
+ },
+ },
+ {
+ /* CMD */
+ .gpio = 43,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &sdc3_cmd_data_0_3_actv_cfg,
+ [GPIOMUX_SUSPENDED] = &sdc3_suspend_cfg,
+ },
+ },
+ {
+ /* CLK */
+ .gpio = 44,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &sdc3_clk_actv_cfg,
+ [GPIOMUX_SUSPENDED] = &sdc3_suspend_cfg,
+ },
+ },
+};
+
+static void msm_gpiomux_sdc3_install(void)
+{
+ msm_gpiomux_install(msm8226_sdc3_configs,
+ ARRAY_SIZE(msm8226_sdc3_configs));
+}
+#else
+static void msm_gpiomux_sdc3_install(void) {}
+#endif /* CONFIG_MMC_MSM_SDC3_SUPPORT */
+
void __init msm8226_init_gpiomux(void)
{
int rc;
@@ -500,4 +585,6 @@
if (of_board_is_cdp() || of_board_is_mtp() || of_board_is_xpm())
msm_gpiomux_install(usb_otg_sw_configs,
ARRAY_SIZE(usb_otg_sw_configs));
+
+ msm_gpiomux_sdc3_install();
}
diff --git a/arch/arm/mach-msm/board-8226.c b/arch/arm/mach-msm/board-8226.c
index 5ad6175..0d62b7a 100644
--- a/arch/arm/mach-msm/board-8226.c
+++ b/arch/arm/mach-msm/board-8226.c
@@ -75,10 +75,14 @@
"msm_sdcc.1", NULL),
OF_DEV_AUXDATA("qcom,msm-sdcc", 0xF98A4000, \
"msm_sdcc.2", NULL),
+ OF_DEV_AUXDATA("qcom,msm-sdcc", 0xF9864000, \
+ "msm_sdcc.3", NULL),
OF_DEV_AUXDATA("qcom,sdhci-msm", 0xF9824900, \
"msm_sdcc.1", NULL),
OF_DEV_AUXDATA("qcom,sdhci-msm", 0xF98A4900, \
"msm_sdcc.2", NULL),
+ OF_DEV_AUXDATA("qcom,sdhci-msm", 0xF9864900, \
+ "msm_sdcc.3", NULL),
{}
};
diff --git a/arch/arm/mach-msm/board-8610-gpiomux.c b/arch/arm/mach-msm/board-8610-gpiomux.c
index b261ce4..f8ca143 100644
--- a/arch/arm/mach-msm/board-8610-gpiomux.c
+++ b/arch/arm/mach-msm/board-8610-gpiomux.c
@@ -16,6 +16,7 @@
#include <mach/board.h>
#include <mach/gpio.h>
#include <mach/gpiomux.h>
+#include <mach/socinfo.h>
static struct gpiomux_setting gpio_spi_config = {
.func = GPIOMUX_FUNC_1,
@@ -59,6 +60,30 @@
.pull = GPIOMUX_PULL_DOWN,
};
+static struct gpiomux_setting focaltech_int_act_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_UP,
+};
+
+static struct gpiomux_setting focaltech_int_sus_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_DOWN,
+};
+
+static struct gpiomux_setting focaltech_reset_act_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_6MA,
+ .pull = GPIOMUX_PULL_UP,
+};
+
+static struct gpiomux_setting focaltech_reset_sus_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_6MA,
+ .pull = GPIOMUX_PULL_UP,
+};
+
static struct gpiomux_setting wcnss_5wire_suspend_cfg = {
.func = GPIOMUX_FUNC_GPIO,
.drv = GPIOMUX_DRV_2MA,
@@ -110,6 +135,31 @@
.pull = GPIOMUX_PULL_NONE,
};
+/* define gpio used as interrupt input */
+static struct gpiomux_setting gpio_int_act_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_UP,
+ .dir = GPIOMUX_IN,
+};
+
+static struct gpiomux_setting gpio_int_sus_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_UP,
+ .dir = GPIOMUX_IN,
+};
+
+static struct msm_gpiomux_config msm_gpio_int_configs[] __initdata = {
+ {
+ .gpio = 84,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &gpio_int_act_cfg,
+ [GPIOMUX_SUSPENDED] = &gpio_int_sus_cfg,
+ },
+ },
+};
+
static struct msm_gpiomux_config msm_lcd_configs[] __initdata = {
{
.gpio = 41,
@@ -214,6 +264,48 @@
},
};
+static struct msm_gpiomux_config msm_focaltech_configs[] __initdata = {
+ {
+ .gpio = 0, /* TOUCH RESET */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &focaltech_reset_act_cfg,
+ [GPIOMUX_SUSPENDED] = &focaltech_reset_sus_cfg,
+ },
+ },
+ {
+ .gpio = 1, /* TOUCH INT */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &focaltech_int_act_cfg,
+ [GPIOMUX_SUSPENDED] = &focaltech_int_sus_cfg,
+ },
+ },
+ {
+ .gpio = 86, /* BLSP1 QUP4 SPI_DATA_MOSI */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gpio_spi_config,
+ },
+ },
+ {
+ .gpio = 87, /* BLSP1 QUP4 SPI_DATA_MISO */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gpio_spi_config,
+ },
+ },
+ {
+ .gpio = 89, /* BLSP1 QUP4 SPI_CLK */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gpio_spi_config,
+ },
+ },
+ {
+ .gpio = 88, /* BLSP1 QUP4 SPI_CS */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gpio_spi_config,
+ },
+ },
+};
+
+
static struct msm_gpiomux_config wcnss_5wire_interface[] = {
{
.gpio = 23,
@@ -430,8 +522,13 @@
}
msm_gpiomux_install(msm_blsp_configs, ARRAY_SIZE(msm_blsp_configs));
- msm_gpiomux_install(msm_atmel_configs,
+ if (of_board_is_qrd()) {
+ msm_gpiomux_install(msm_focaltech_configs,
+ ARRAY_SIZE(msm_focaltech_configs));
+ } else {
+ msm_gpiomux_install(msm_atmel_configs,
ARRAY_SIZE(msm_atmel_configs));
+ }
msm_gpiomux_install(wcnss_5wire_interface,
ARRAY_SIZE(wcnss_5wire_interface));
msm_gpiomux_install(msm_lcd_configs, ARRAY_SIZE(msm_lcd_configs));
@@ -439,4 +536,6 @@
ARRAY_SIZE(msm_keypad_configs));
msm_gpiomux_install(sd_card_det, ARRAY_SIZE(sd_card_det));
msm_gpiomux_install(msm_sensor_configs, ARRAY_SIZE(msm_sensor_configs));
+ msm_gpiomux_install(msm_gpio_int_configs,
+ ARRAY_SIZE(msm_gpio_int_configs));
}
diff --git a/arch/arm/mach-msm/board-8974-gpiomux.c b/arch/arm/mach-msm/board-8974-gpiomux.c
index 6432c93..66f2cd3 100644
--- a/arch/arm/mach-msm/board-8974-gpiomux.c
+++ b/arch/arm/mach-msm/board-8974-gpiomux.c
@@ -180,6 +180,12 @@
.pull = GPIOMUX_PULL_DOWN,
};
+static struct gpiomux_setting gpio_epm_marker_config = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_DOWN,
+};
+
static struct gpiomux_setting wcnss_5wire_suspend_cfg = {
.func = GPIOMUX_FUNC_GPIO,
.drv = GPIOMUX_DRV_2MA,
@@ -526,6 +532,18 @@
[GPIOMUX_SUSPENDED] = &gpio_epm_config,
},
},
+ {
+ .gpio = 85, /* EPM MARKER2 */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gpio_epm_marker_config,
+ },
+ },
+ {
+ .gpio = 96, /* EPM MARKER1 */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gpio_epm_marker_config,
+ },
+ },
};
static struct msm_gpiomux_config msm_blsp_configs[] __initdata = {
@@ -825,6 +843,135 @@
},
};
+static struct msm_gpiomux_config msm_sensor_configs_dragonboard[] __initdata = {
+ {
+ .gpio = 15, /* CAM_MCLK0 */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[0],
+ [GPIOMUX_SUSPENDED] = &cam_settings[1],
+ },
+ },
+ {
+ .gpio = 16, /* CAM_MCLK1 */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[0],
+ [GPIOMUX_SUSPENDED] = &cam_settings[1],
+ },
+ },
+ {
+ .gpio = 17, /* CAM_MCLK2 */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[0],
+ [GPIOMUX_SUSPENDED] = &cam_settings[1],
+ },
+ },
+ {
+ .gpio = 18, /* WEBCAM1_RESET_N / CAM_MCLK3 */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[3],
+ [GPIOMUX_SUSPENDED] = &cam_settings[4],
+ },
+ },
+ {
+ .gpio = 19, /* CCI_I2C_SDA0 */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[0],
+ [GPIOMUX_SUSPENDED] = &gpio_suspend_config[0],
+ },
+ },
+ {
+ .gpio = 20, /* CCI_I2C_SCL0 */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[0],
+ [GPIOMUX_SUSPENDED] = &gpio_suspend_config[0],
+ },
+ },
+ {
+ .gpio = 21, /* CCI_I2C_SDA1 */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[0],
+ [GPIOMUX_SUSPENDED] = &gpio_suspend_config[0],
+ },
+ },
+ {
+ .gpio = 22, /* CCI_I2C_SCL1 */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[0],
+ [GPIOMUX_SUSPENDED] = &gpio_suspend_config[0],
+ },
+ },
+ {
+ .gpio = 23, /* FLASH_LED_EN */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[0],
+ [GPIOMUX_SUSPENDED] = &gpio_suspend_config[1],
+ },
+ },
+ {
+ .gpio = 24, /* FLASH_LED_NOW */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[0],
+ [GPIOMUX_SUSPENDED] = &gpio_suspend_config[1],
+ },
+ },
+ {
+ .gpio = 25, /* WEBCAM2_RESET_N */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[3],
+ [GPIOMUX_SUSPENDED] = &gpio_suspend_config[1],
+ },
+ },
+ {
+ .gpio = 26, /* CAM_IRQ */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[0],
+ [GPIOMUX_SUSPENDED] = &cam_settings[1],
+ },
+ },
+ {
+ .gpio = 27, /* OIS_SYNC */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[0],
+ [GPIOMUX_SUSPENDED] = &gpio_suspend_config[1],
+ },
+ },
+ {
+ .gpio = 28, /* WEBCAM1_STANDBY */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[3],
+ [GPIOMUX_SUSPENDED] = &gpio_suspend_config[1],
+ },
+ },
+ {
+ .gpio = 89, /* CAM1_STANDBY_N */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[3],
+ [GPIOMUX_SUSPENDED] = &gpio_suspend_config[1],
+ },
+ },
+ {
+ .gpio = 90, /* CAM1_RST_N */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[3],
+ [GPIOMUX_SUSPENDED] = &gpio_suspend_config[1],
+ },
+ },
+ {
+ .gpio = 91, /* CAM2_STANDBY_N */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[3],
+ [GPIOMUX_SUSPENDED] = &gpio_suspend_config[1],
+ },
+ },
+ {
+ .gpio = 94, /* CAM2_RST_N */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[3],
+ [GPIOMUX_SUSPENDED] = &gpio_suspend_config[1],
+ },
+ },
+};
+
static struct gpiomux_setting auxpcm_act_cfg = {
.func = GPIOMUX_FUNC_1,
.drv = GPIOMUX_DRV_8MA,
@@ -1198,7 +1345,9 @@
}
#if defined(CONFIG_KS8851) || defined(CONFIG_KS8851_MODULE)
- msm_gpiomux_install(msm_eth_configs, ARRAY_SIZE(msm_eth_configs));
+ if (!(of_board_is_dragonboard() && machine_is_apq8074()))
+ msm_gpiomux_install(msm_eth_configs, \
+ ARRAY_SIZE(msm_eth_configs));
#endif
msm_gpiomux_install(msm_blsp_configs, ARRAY_SIZE(msm_blsp_configs));
msm_gpiomux_install(msm_blsp2_uart7_configs,
@@ -1215,7 +1364,12 @@
msm_gpiomux_install(hap_lvl_shft_config,
ARRAY_SIZE(hap_lvl_shft_config));
- msm_gpiomux_install(msm_sensor_configs, ARRAY_SIZE(msm_sensor_configs));
+ if (of_board_is_dragonboard() && machine_is_apq8074())
+ msm_gpiomux_install(msm_sensor_configs_dragonboard, \
+ ARRAY_SIZE(msm_sensor_configs_dragonboard));
+ else
+ msm_gpiomux_install(msm_sensor_configs, \
+ ARRAY_SIZE(msm_sensor_configs));
msm_gpiomux_install(&sd_card_det, 1);
@@ -1223,7 +1377,8 @@
of_board_is_dragonboard()))
msm_gpiomux_sdc3_install();
- msm_gpiomux_sdc4_install();
+ if (!(of_board_is_dragonboard() && machine_is_apq8074()))
+ msm_gpiomux_sdc4_install();
msm_gpiomux_install(msm_taiko_config, ARRAY_SIZE(msm_taiko_config));
diff --git a/arch/arm/mach-msm/board-9625.c b/arch/arm/mach-msm/board-9625.c
index fad2efc..36ad755 100644
--- a/arch/arm/mach-msm/board-9625.c
+++ b/arch/arm/mach-msm/board-9625.c
@@ -117,6 +117,10 @@
"usb_bam", NULL),
OF_DEV_AUXDATA("qcom,hsic-host", 0xF9A15000, \
"msm_hsic_host", NULL),
+ OF_DEV_AUXDATA("qcom,sdhci-msm", 0xF98A4900, \
+ "msm_sdcc.2", NULL),
+ OF_DEV_AUXDATA("qcom,sdhci-msm", 0xF9864900, \
+ "msm_sdcc.3", NULL),
{}
};
diff --git a/arch/arm/mach-msm/board-krypton.c b/arch/arm/mach-msm/board-krypton.c
index 0d06b83..e80244b 100644
--- a/arch/arm/mach-msm/board-krypton.c
+++ b/arch/arm/mach-msm/board-krypton.c
@@ -31,6 +31,22 @@
#include "clock.h"
#include "devices.h"
+static struct memtype_reserve msmkrypton_reserve_table[] __initdata = {
+ [MEMTYPE_EBI1] = {
+ .flags = MEMTYPE_FLAGS_1M_ALIGN,
+ },
+};
+
+static int msmkrypton_paddr_to_memtype(unsigned int paddr)
+{
+ return MEMTYPE_EBI1;
+}
+
+static struct reserve_info msmkrypton_reserve_info __initdata = {
+ .memtype_reserve_table = msmkrypton_reserve_table,
+ .paddr_to_memtype = msmkrypton_paddr_to_memtype,
+};
+
static struct of_dev_auxdata msmkrypton_auxdata_lookup[] __initdata = {
{}
};
@@ -47,6 +63,11 @@
msm_clock_init(&msmkrypton_clock_init_data);
}
+static void __init msmkrypton_early_memory(void)
+{
+ reserve_info = &msmkrypton_reserve_info;
+ of_scan_flat_dt(dt_scan_for_memory_hole, msmkrypton_reserve_table);
+}
static void __init msmkrypton_map_io(void)
{
msm_map_msmkrypton_io();
@@ -74,5 +95,6 @@
.handle_irq = gic_handle_irq,
.timer = &msm_dt_timer,
.dt_compat = msmkrypton_dt_match,
+ .init_very_early = msmkrypton_early_memory,
.restart = msm_restart,
MACHINE_END
diff --git a/arch/arm/mach-msm/clock-8084.c b/arch/arm/mach-msm/clock-8084.c
index 605a7ae..184338e 100644
--- a/arch/arm/mach-msm/clock-8084.c
+++ b/arch/arm/mach-msm/clock-8084.c
@@ -137,7 +137,8 @@
CLK_DUMMY("", gcc_lpass_mport_axi_clk.c, "", OFF),
CLK_DUMMY("", gcc_lpass_q6_axi_clk.c, "", OFF),
CLK_DUMMY("", gcc_lpass_sway_clk.c, "", OFF),
- CLK_DUMMY("", gcc_mmss_bimc_gfx_clk.c, "", OFF),
+ CLK_DUMMY("mem_iface_clk", gcc_mmss_bimc_gfx_clk.c,
+ "fdb00000.qcom,kgsl-3d0", OFF),
CLK_DUMMY("", gcc_mmss_vpu_maple_sys_noc_axi_clk.c, "", OFF),
CLK_DUMMY("", gcc_ocmem_noc_cfg_ahb_clk.c, "", OFF),
CLK_DUMMY("", gcc_msg_ram_ahb_clk.c, "", OFF),
@@ -310,20 +311,24 @@
CLK_DUMMY("iface_clk", mdss_ahb_clk.c, "fd900000.qcom,mdss_mdp", OFF),
CLK_DUMMY("bus_clk", mdss_axi_clk.c, "fd900000.qcom,mdss_mdp", OFF),
CLK_DUMMY("core_clk_src", mdp_clk_src.c, "fd900000.qcom,mdss_mdp", OFF),
- CLK_DUMMY("", mdss_byte0_clk.c, "", OFF),
- CLK_DUMMY("", mdss_byte1_clk.c, "", OFF),
CLK_DUMMY("", mdss_edpaux_clk.c, "", OFF),
CLK_DUMMY("", mdss_edplink_clk.c, "", OFF),
CLK_DUMMY("", mdss_edppixel_clk.c, "", OFF),
- CLK_DUMMY("", mdss_esc0_clk.c, "", OFF),
- CLK_DUMMY("", mdss_esc1_clk.c, "", OFF),
+ CLK_DUMMY("byte_clk", mdss_byte0_clk.c, "fd922800.qcom,mdss_dsi", OFF),
+ CLK_DUMMY("byte_clk", mdss_byte1_clk.c, "fd922e00.qcom,mdss_dsi", OFF),
+ CLK_DUMMY("core_clk", mdss_esc0_clk.c, "fd922800.qcom,mdss_dsi", OFF),
+ CLK_DUMMY("core_clk", mdss_esc1_clk.c, "fd922e00.qcom,mdss_dsi", OFF),
+ CLK_DUMMY("iface_clk", mdss_ahb_clk.c, "fd922800.qcom,mdss_dsi", OFF),
+ CLK_DUMMY("iface_clk", mdss_ahb_clk.c, "fd922e00.qcom,mdss_dsi", OFF),
+ CLK_DUMMY("bus_clk", mdss_axi_clk.c, "fd922800.qcom,mdss_dsi", OFF),
+ CLK_DUMMY("bus_clk", mdss_axi_clk.c, "fd922e00.qcom,mdss_dsi", OFF),
+ CLK_DUMMY("pixel_clk", mdss_pclk0_clk.c, "fd922800.qcom,mdss_dsi", OFF),
+ CLK_DUMMY("pixel_clk", mdss_pclk1_clk.c, "fd922e00.qcom,mdss_dsi", OFF),
CLK_DUMMY("", mdss_extpclk_clk.c, "", OFF),
CLK_DUMMY("", mdss_hdmi_ahb_clk.c, "", OFF),
CLK_DUMMY("", mdss_hdmi_clk.c, "", OFF),
CLK_DUMMY("core_clk", mdss_mdp_clk.c, "fd900000.qcom,mdss_mdp", OFF),
CLK_DUMMY("lut_clk", mdss_mdp_lut_clk.c, "fd900000.qcom,mdss_mdp", OFF),
- CLK_DUMMY("", mdss_pclk0_clk.c, "", OFF),
- CLK_DUMMY("", mdss_pclk1_clk.c, "", OFF),
CLK_DUMMY("vsync_clk", mdss_vsync_clk.c, "fd900000.qcom,mdss_mdp", OFF),
CLK_DUMMY("", mmss_misc_ahb_clk.c, "", OFF),
CLK_DUMMY("", mmss_mmssnoc_ahb_clk.c, "", OFF),
@@ -333,9 +338,11 @@
CLK_DUMMY("iface_clk", ocmemcx_ocmemnoc_clk.c,
"fdd00000.qcom,ocmem", OFF),
CLK_DUMMY("", oxili_ocmemgx_clk.c, "", OFF),
- CLK_DUMMY("", oxili_gfx3d_clk.c, "", OFF),
+ CLK_DUMMY("core_clk", oxili_gfx3d_clk.c,
+ "fdb00000.qcom,kgsl-3d0", OFF),
CLK_DUMMY("", oxili_rbbmtimer_clk.c, "", OFF),
- CLK_DUMMY("", oxilicx_ahb_clk.c, "", OFF),
+ CLK_DUMMY("iface_clk", oxilicx_ahb_clk.c,
+ "fdb00000.qcom,kgsl-3d0", OFF),
CLK_DUMMY("", venus0_ahb_clk.c, "", OFF),
CLK_DUMMY("", venus0_axi_clk.c, "", OFF),
CLK_DUMMY("", venus0_core0_vcodec_clk.c, "", OFF),
diff --git a/arch/arm/mach-msm/clock-8092.c b/arch/arm/mach-msm/clock-8092.c
index 9de97ea..bb46c4a 100644
--- a/arch/arm/mach-msm/clock-8092.c
+++ b/arch/arm/mach-msm/clock-8092.c
@@ -290,6 +290,16 @@
CLK_DUMMY("", vpu_sleep_clk.c, "", OFF),
CLK_DUMMY("", vpu_vdp_clk.c, "", OFF),
CLK_DUMMY("", vpu_vdp_xin_clk.c, "", OFF),
+ CLK_DUMMY("iface_clk", NULL, "fda64000.qcom,iommu", OFF),
+ CLK_DUMMY("core_clk", NULL, "fda64000.qcom,iommu", OFF),
+ CLK_DUMMY("alt_core_clk", NULL, "fda64000.qcom,iommu", OFF),
+ CLK_DUMMY("iface_clk", NULL, "fd928000.qcom,iommu", OFF),
+ CLK_DUMMY("core_clk", NULL, "fd928000.qcom,iommu", oFF),
+ CLK_DUMMY("core_clk", NULL, "fdb10000.qcom,iommu", OFF),
+ CLK_DUMMY("iface_clk", NULL, "fdb10000.qcom,iommu", OFF),
+ CLK_DUMMY("iface_clk", NULL, "fdc84000.qcom,iommu", OFF),
+ CLK_DUMMY("alt_core_clk", NULL, "fdc84000.qcom,iommu", OFF),
+ CLK_DUMMY("core_clk", NULL, "fdc84000.qcom,iommu", OFF),
/* BCSS broadcast */
CLK_DUMMY("", bcc_dem_core_b_clk_src.c, "", OFF),
CLK_DUMMY("", adc_01_clk_src.c, "", OFF),
@@ -319,6 +329,11 @@
CLK_DUMMY("", nidaq_out_clk.c, "", OFF),
CLK_DUMMY("", gcc_bcss_axi_clk.c, "", OFF),
CLK_DUMMY("", bcc_lnb_core_clk.c, "", OFF),
+
+ /* USB */
+ CLK_DUMMY("core_clk", NULL, "msm_otg", OFF),
+ CLK_DUMMY("iface_clk", NULL, "msm_otg", OFF),
+ CLK_DUMMY("xo", NULL, "msm_otg", OFF),
};
struct clock_init_data mpq8092_clock_init_data __initdata = {
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index 1e91d5b..1514bba 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -3047,7 +3047,7 @@
return branch_reset(&to_pix_rdi_clk(c)->b, action);
}
-static int pix_rdi_clk_list_rate(struct clk *c, unsigned n)
+static long pix_rdi_clk_list_rate(struct clk *c, unsigned n)
{
if (pix_rdi_mux_map[n])
return n;
diff --git a/arch/arm/mach-msm/clock-8974.c b/arch/arm/mach-msm/clock-8974.c
index 832e86f..11886a4 100644
--- a/arch/arm/mach-msm/clock-8974.c
+++ b/arch/arm/mach-msm/clock-8974.c
@@ -1401,7 +1401,7 @@
F_END
};
-static struct clk_freq_tbl ftbl_gcc_ce1_v3_clk[] = {
+static struct clk_freq_tbl ftbl_gcc_ce1_pro_clk[] = {
F( 50000000, gpll0, 12, 0, 0),
F( 75000000, gpll0, 8, 0, 0),
F(100000000, gpll0, 6, 0, 0),
@@ -1429,7 +1429,7 @@
F_END
};
-static struct clk_freq_tbl ftbl_gcc_ce2_v3_clk[] = {
+static struct clk_freq_tbl ftbl_gcc_ce2_pro_clk[] = {
F( 50000000, gpll0, 12, 0, 0),
F( 75000000, gpll0, 8, 0, 0),
F(100000000, gpll0, 6, 0, 0),
@@ -2945,12 +2945,12 @@
F_END
};
-static struct clk_freq_tbl ftbl_camss_mclk0_3_v3_clk[] = {
+static struct clk_freq_tbl ftbl_camss_mclk0_3_pro_clk[] = {
F_MM( 4800000, cxo, 4, 0, 0),
F_MM( 6000000, gpll0, 10, 1, 10),
F_MM( 8000000, gpll0, 15, 1, 5),
F_MM( 9600000, cxo, 2, 0, 0),
- F_MM(16000000, gpll0, 10, 1, 5),
+ F_MM(16000000, gpll0, 12.5, 1, 3),
F_MM(19200000, cxo, 1, 0, 0),
F_MM(24000000, gpll0, 5, 1, 5),
F_MM(32000000, mmpll0, 5, 1, 5),
@@ -4680,7 +4680,8 @@
clk->multiplier = 4;
clk_sel = 0x16A;
- if (SOCINFO_VERSION_MAJOR(socinfo_get_version()) == 1) {
+ if (SOCINFO_VERSION_MAJOR(socinfo_get_version()) == 1 &&
+ cpu_is_msm8974()) {
if (measure_mux[i].debug_mux == M_L2)
regval = BIT(7)|BIT(0);
else
@@ -5512,15 +5513,21 @@
.mn_ena_mask = BIT(24),
.main_output_val = BIT(0),
.main_output_mask = BIT(0),
+ .aux_output_val = BIT(1),
+ .aux_output_mask = BIT(1),
};
+#define cpu_is_msm8974pro() (cpu_is_msm8974pro_aa() || cpu_is_msm8974pro_ab() \
+ || cpu_is_msm8974pro_ac())
+
static void __init reg_init(void)
{
u32 regval;
configure_sr_hpm_lp_pll(&mmpll0_config, &mmpll0_regs, 1);
- if (SOCINFO_VERSION_MAJOR(socinfo_get_version()) == 2) {
+ if (SOCINFO_VERSION_MAJOR(socinfo_get_version()) == 2
+ || cpu_is_msm8974pro()) {
configure_sr_hpm_lp_pll(&mmpll1_v2_config, &mmpll1_regs, 1);
configure_sr_hpm_lp_pll(&mmpll3_v2_config, &mmpll3_regs, 0);
} else {
@@ -5537,7 +5544,8 @@
* V2 requires additional votes to allow the LPASS and MMSS
* controllers to use GPLL0.
*/
- if (SOCINFO_VERSION_MAJOR(socinfo_get_version()) == 2) {
+ if (SOCINFO_VERSION_MAJOR(socinfo_get_version()) == 2
+ || cpu_is_msm8974pro()) {
regval = readl_relaxed(
GCC_REG_BASE(APCS_CLOCK_BRANCH_ENA_VOTE));
writel_relaxed(regval | BIT(26) | BIT(25),
@@ -5547,7 +5555,8 @@
static void __init msm8974_clock_post_init(void)
{
- if (SOCINFO_VERSION_MAJOR(socinfo_get_version()) == 2) {
+ if (SOCINFO_VERSION_MAJOR(socinfo_get_version()) == 2
+ || cpu_is_msm8974pro()) {
clk_set_rate(&axi_clk_src.c, 291750000);
clk_set_rate(&ocmemnoc_clk_src.c, 291750000);
} else {
@@ -5661,35 +5670,44 @@
qup_i2c_clks[i][0]->parent = qup_i2c_clks[i][1];
}
-/* v2 to v3 clock changes */
-static void __init msm8974_v3_clock_override(void)
+/* v2 to pro clock changes */
+static void __init msm8974_pro_clock_override(void)
{
ce1_clk_src.c.fmax[VDD_DIG_LOW] = 75000000;
ce1_clk_src.c.fmax[VDD_DIG_NOMINAL] = 150000000;
- ce1_clk_src.freq_tbl = ftbl_gcc_ce1_v3_clk;
+ ce1_clk_src.freq_tbl = ftbl_gcc_ce1_pro_clk;
ce2_clk_src.c.fmax[VDD_DIG_LOW] = 75000000;
ce2_clk_src.c.fmax[VDD_DIG_NOMINAL] = 150000000;
- ce2_clk_src.freq_tbl = ftbl_gcc_ce2_v3_clk;
+ ce2_clk_src.freq_tbl = ftbl_gcc_ce2_pro_clk;
- sdcc1_apps_clk_src.c.fmax[VDD_DIG_LOW] = 200000000;
- sdcc1_apps_clk_src.c.fmax[VDD_DIG_NOMINAL] = 400000000;
+ if (cpu_is_msm8974pro_ac()) {
+ sdcc1_apps_clk_src.c.fmax[VDD_DIG_LOW] = 200000000;
+ sdcc1_apps_clk_src.c.fmax[VDD_DIG_NOMINAL] = 400000000;
+ }
vfe0_clk_src.c.fmax[VDD_DIG_LOW] = 150000000;
vfe0_clk_src.c.fmax[VDD_DIG_NOMINAL] = 320000000;
- vfe0_clk_src.c.fmax[VDD_DIG_HIGH] = 465000000;
vfe1_clk_src.c.fmax[VDD_DIG_LOW] = 150000000;
vfe1_clk_src.c.fmax[VDD_DIG_NOMINAL] = 320000000;
- vfe1_clk_src.c.fmax[VDD_DIG_HIGH] = 465000000;
cpp_clk_src.c.fmax[VDD_DIG_LOW] = 150000000;
cpp_clk_src.c.fmax[VDD_DIG_NOMINAL] = 320000000;
- cpp_clk_src.c.fmax[VDD_DIG_HIGH] = 465000000;
+
+ if (cpu_is_msm8974pro_ab() || cpu_is_msm8974pro_ac()) {
+ vfe0_clk_src.c.fmax[VDD_DIG_HIGH] = 465000000;
+ vfe1_clk_src.c.fmax[VDD_DIG_HIGH] = 465000000;
+ cpp_clk_src.c.fmax[VDD_DIG_HIGH] = 465000000;
+ } else if (cpu_is_msm8974pro_aa()) {
+ vfe0_clk_src.c.fmax[VDD_DIG_HIGH] = 320000000;
+ vfe1_clk_src.c.fmax[VDD_DIG_HIGH] = 320000000;
+ cpp_clk_src.c.fmax[VDD_DIG_HIGH] = 320000000;
+ }
mdp_clk_src.c.fmax[VDD_DIG_NOMINAL] = 266670000;
- mclk0_clk_src.freq_tbl = ftbl_camss_mclk0_3_v3_clk;
- mclk1_clk_src.freq_tbl = ftbl_camss_mclk0_3_v3_clk;
- mclk2_clk_src.freq_tbl = ftbl_camss_mclk0_3_v3_clk;
- mclk3_clk_src.freq_tbl = ftbl_camss_mclk0_3_v3_clk;
+ mclk0_clk_src.freq_tbl = ftbl_camss_mclk0_3_pro_clk;
+ mclk1_clk_src.freq_tbl = ftbl_camss_mclk0_3_pro_clk;
+ mclk2_clk_src.freq_tbl = ftbl_camss_mclk0_3_pro_clk;
+ mclk3_clk_src.freq_tbl = ftbl_camss_mclk0_3_pro_clk;
mclk0_clk_src.set_rate = set_rate_mnd;
mclk1_clk_src.set_rate = set_rate_mnd;
mclk2_clk_src.set_rate = set_rate_mnd;
@@ -5733,10 +5751,11 @@
msm8974_clock_init_data.size -= ARRAY_SIZE(msm_clocks_8974ac_only);
/* version specific changes */
- if (SOCINFO_VERSION_MAJOR(socinfo_get_version()) >= 2)
+ if (SOCINFO_VERSION_MAJOR(socinfo_get_version()) >= 2
+ || cpu_is_msm8974pro())
msm8974_v2_clock_override();
- if (SOCINFO_VERSION_MAJOR(socinfo_get_version()) == 3) {
- msm8974_v3_clock_override();
+ if (cpu_is_msm8974pro()) {
+ msm8974_pro_clock_override();
memcpy(msm_clocks_8974 + ARRAY_SIZE(msm_clocks_8974_common),
msm_clocks_8974ac_only, sizeof(msm_clocks_8974ac_only));
msm8974_clock_init_data.size +=
diff --git a/arch/arm/mach-msm/clock-debug.c b/arch/arm/mach-msm/clock-debug.c
index 8ec87d1..c91af54 100644
--- a/arch/arm/mach-msm/clock-debug.c
+++ b/arch/arm/mach-msm/clock-debug.c
@@ -198,11 +198,12 @@
static int list_rates_show(struct seq_file *m, void *unused)
{
struct clk *clock = m->private;
- int rate, level, fmax = 0, i = 0;
+ int level, i = 0;
+ unsigned long rate, fmax = 0;
/* Find max frequency supported within voltage constraints. */
if (!clock->vdd_class) {
- fmax = INT_MAX;
+ fmax = ULONG_MAX;
} else {
for (level = 0; level < clock->num_fmax; level++)
if (clock->fmax[level])
@@ -213,9 +214,9 @@
* List supported frequencies <= fmax. Higher frequencies may appear in
* the frequency table, but are not valid and should not be listed.
*/
- while ((rate = clock->ops->list_rate(clock, i++)) >= 0) {
+ while (!IS_ERR_VALUE(rate = clock->ops->list_rate(clock, i++))) {
if (rate <= fmax)
- seq_printf(m, "%u\n", rate);
+ seq_printf(m, "%lu\n", rate);
}
return 0;
diff --git a/arch/arm/mach-msm/clock-dsi-8610.c b/arch/arm/mach-msm/clock-dsi-8610.c
index 44b332e..73196fe 100644
--- a/arch/arm/mach-msm/clock-dsi-8610.c
+++ b/arch/arm/mach-msm/clock-dsi-8610.c
@@ -192,7 +192,7 @@
status = readl_relaxed(dsi_base + DSI_DSIPHY_PLL_CTRL_0);
if (!status & DSI_PLL_RDY_BIT) {
pr_err("DSI PLL not ready\n");
- clk_disable(dsi_ahb_clk);
+ clk_disable_unprepare(dsi_ahb_clk);
return HANDOFF_DISABLED_CLK;
}
@@ -370,35 +370,19 @@
return HANDOFF_ENABLED_CLK;
}
-int dsi_prepare(struct clk *clk)
-{
- return clk_prepare(dsi_ahb_clk);
-}
-
-void dsi_unprepare(struct clk *clk)
-{
- clk_unprepare(dsi_ahb_clk);
-}
-
struct clk_ops clk_ops_dsi_dsiclk = {
- .prepare = dsi_prepare,
- .unprepare = dsi_unprepare,
.set_rate = dsi_dsiclk_set_rate,
.round_rate = dsi_dsiclk_round_rate,
.handoff = dsi_dsiclk_handoff,
};
struct clk_ops clk_ops_dsi_byteclk = {
- .prepare = dsi_prepare,
- .unprepare = dsi_unprepare,
.set_rate = dsi_byteclk_set_rate,
.round_rate = dsi_byteclk_round_rate,
.handoff = dsi_byteclk_handoff,
};
struct clk_ops clk_ops_dsi_vco = {
- .prepare = dsi_prepare,
- .unprepare = dsi_unprepare,
.enable = dsi_pll_vco_enable,
.disable = dsi_pll_vco_disable,
.set_rate = dsi_pll_vco_set_rate,
diff --git a/arch/arm/mach-msm/clock-krypton.c b/arch/arm/mach-msm/clock-krypton.c
index aaee003..0b615cc 100644
--- a/arch/arm/mach-msm/clock-krypton.c
+++ b/arch/arm/mach-msm/clock-krypton.c
@@ -46,6 +46,8 @@
CLK_DUMMY("mem_clk", bimc_msmbus_clk.c, "msm_bimc", OFF),
CLK_DUMMY("mem_a_clk", bimc_msmbus_a_clk.c, "msm_bimc", OFF),
CLK_DUMMY("mem_clk", bimc_acpu_a_clk.c, "", OFF),
+ CLK_DUMMY("dfab_clk", DFAB_CLK, "msm_sps", OFF),
+ CLK_DUMMY("dma_bam_pclk", DMA_BAM_P_CLK, "msm_sps", OFF),
CLK_DUMMY("clktype", gcc_imem_axi_clk , "drivername", OFF),
CLK_DUMMY("clktype", gcc_imem_cfg_ahb_clk , "drivername", OFF),
diff --git a/arch/arm/mach-msm/clock-local.c b/arch/arm/mach-msm/clock-local.c
index 0b8240c..18ea514 100644
--- a/arch/arm/mach-msm/clock-local.c
+++ b/arch/arm/mach-msm/clock-local.c
@@ -579,7 +579,7 @@
}
/* Return the nth supported frequency for a given clock. */
-static int rcg_clk_list_rate(struct clk *c, unsigned n)
+static long rcg_clk_list_rate(struct clk *c, unsigned n)
{
struct rcg_clk *rcg = to_rcg_clk(c);
@@ -944,7 +944,7 @@
return rate > to_cdiv_clk(c)->max_div ? -EPERM : rate;
}
-static int cdiv_clk_list_rate(struct clk *c, unsigned n)
+static long cdiv_clk_list_rate(struct clk *c, unsigned n)
{
return n > to_cdiv_clk(c)->max_div ? -ENXIO : n;
}
diff --git a/arch/arm/mach-msm/clock-local2.c b/arch/arm/mach-msm/clock-local2.c
index fd790e2..b7852fe 100644
--- a/arch/arm/mach-msm/clock-local2.c
+++ b/arch/arm/mach-msm/clock-local2.c
@@ -210,7 +210,7 @@
}
/* Return the nth supported frequency for a given clock. */
-static int rcg_clk_list_rate(struct clk *c, unsigned n)
+static long rcg_clk_list_rate(struct clk *c, unsigned n)
{
struct rcg_clk *rcg = to_rcg_clk(c);
@@ -459,7 +459,7 @@
return clk_get_rate(c->parent);
}
-static int branch_clk_list_rate(struct clk *c, unsigned n)
+static long branch_clk_list_rate(struct clk *c, unsigned n)
{
int level, fmax = 0, rate;
struct branch_clk *branch = to_branch_clk(c);
@@ -934,7 +934,7 @@
return ERR_PTR(-EPERM);
}
-static int cam_mux_clk_list_rate(struct clk *c, unsigned n)
+static long cam_mux_clk_list_rate(struct clk *c, unsigned n)
{
struct cam_mux_clk *mux = to_cam_mux_clk(c);
int i;
diff --git a/arch/arm/mach-msm/clock-pll.c b/arch/arm/mach-msm/clock-pll.c
index 69c3751..a251784 100644
--- a/arch/arm/mach-msm/clock-pll.c
+++ b/arch/arm/mach-msm/clock-pll.c
@@ -694,6 +694,12 @@
regval |= config->main_output_val;
}
+ /* Enable the aux output */
+ if (config->aux_output_mask) {
+ regval &= ~config->aux_output_mask;
+ regval |= config->aux_output_val;
+ }
+
/* Set pre-divider and post-divider values */
regval &= ~config->pre_div_mask;
regval |= config->pre_div_val;
diff --git a/arch/arm/mach-msm/clock-pll.h b/arch/arm/mach-msm/clock-pll.h
index c4addb2..58c00b9 100644
--- a/arch/arm/mach-msm/clock-pll.h
+++ b/arch/arm/mach-msm/clock-pll.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2013, 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
@@ -184,6 +184,8 @@
u32 mn_ena_mask;
u32 main_output_val;
u32 main_output_mask;
+ u32 aux_output_val;
+ u32 aux_output_mask;
};
struct pll_config_regs {
diff --git a/arch/arm/mach-msm/clock-rpm.c b/arch/arm/mach-msm/clock-rpm.c
index 8356207..1d7a5e2 100644
--- a/arch/arm/mach-msm/clock-rpm.c
+++ b/arch/arm/mach-msm/clock-rpm.c
@@ -42,7 +42,7 @@
int rc;
struct msm_rpm_iv_pair iv = { .id = r->rpm_status_id, };
rc = msm_rpm_get_status(&iv, 1);
- return (rc < 0) ? rc : iv.value * r->factor;
+ return (rc < 0) ? rc : iv.value * 1000;
}
static int clk_rpmrs_handoff(struct rpm_clk *r)
@@ -54,7 +54,7 @@
return rc;
if (!r->branch)
- r->c.rate = iv.value * r->factor;
+ r->c.rate = iv.value * 1000;
return 0;
}
@@ -122,7 +122,7 @@
unsigned long *active_khz, unsigned long *sleep_khz)
{
/* Convert the rate (hz) to khz */
- *active_khz = DIV_ROUND_UP(rate, r->factor);
+ *active_khz = DIV_ROUND_UP(rate, 1000);
/*
* Active-only clocks don't care what the rate is during sleep. So,
diff --git a/arch/arm/mach-msm/clock-rpm.h b/arch/arm/mach-msm/clock-rpm.h
index b20c3d6..d283861 100644
--- a/arch/arm/mach-msm/clock-rpm.h
+++ b/arch/arm/mach-msm/clock-rpm.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2013, 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
@@ -39,9 +39,7 @@
const bool active_only;
bool enabled;
bool branch; /* true: RPM only accepts 1 for ON and 0 for OFF */
- unsigned factor;
struct clk_rpmrs_data *rpmrs_data;
-
struct rpm_clk *peer;
struct clk c;
};
@@ -69,7 +67,6 @@
.rpm_status_id = (stat_id), \
.rpm_key = (key), \
.peer = &active, \
- .factor = 1000, \
.rpmrs_data = (rpmrsdata),\
.c = { \
.ops = &clk_ops_rpm, \
@@ -85,7 +82,6 @@
.rpm_key = (key), \
.peer = &name, \
.active_only = true, \
- .factor = 1000, \
.rpmrs_data = (rpmrsdata),\
.c = { \
.ops = &clk_ops_rpm, \
@@ -104,7 +100,6 @@
.rpm_status_id = (stat_id), \
.rpm_key = (key), \
.peer = &active, \
- .factor = 1000, \
.branch = true, \
.rpmrs_data = (rpmrsdata),\
.c = { \
@@ -121,7 +116,6 @@
.rpm_key = (key), \
.peer = &name, \
.active_only = true, \
- .factor = 1000, \
.branch = true, \
.rpmrs_data = (rpmrsdata),\
.c = { \
@@ -132,46 +126,13 @@
}, \
};
-#define __DEFINE_CLK_RPM_QDSS(name, active, type, r_id, stat_id, \
- key, rpmrsdata) \
- static struct rpm_clk active; \
- static struct rpm_clk name = { \
- .rpm_res_type = (type), \
- .rpm_clk_id = (r_id), \
- .rpm_status_id = (stat_id), \
- .rpm_key = (key), \
- .peer = &active, \
- .factor = 1, \
- .rpmrs_data = (rpmrsdata),\
- .c = { \
- .ops = &clk_ops_rpm, \
- .dbg_name = #name, \
- CLK_INIT(name.c), \
- }, \
- }; \
- static struct rpm_clk active = { \
- .rpm_res_type = (type), \
- .rpm_clk_id = (r_id), \
- .rpm_status_id = (stat_id), \
- .rpm_key = (key), \
- .peer = &name, \
- .active_only = true, \
- .factor = 1, \
- .rpmrs_data = (rpmrsdata),\
- .c = { \
- .ops = &clk_ops_rpm, \
- .dbg_name = #active, \
- CLK_INIT(active.c), \
- }, \
- };
-
#define DEFINE_CLK_RPM(name, active, r_id, dep) \
__DEFINE_CLK_RPM(name, active, 0, MSM_RPM_ID_##r_id##_CLK, \
MSM_RPM_STATUS_ID_##r_id##_CLK, dep, 0, &clk_rpmrs_data)
#define DEFINE_CLK_RPM_QDSS(name, active) \
- __DEFINE_CLK_RPM_QDSS(name, active, 0, MSM_RPM_ID_QDSS_CLK, \
- MSM_RPM_STATUS_ID_QDSS_CLK, 0, &clk_rpmrs_data)
+ __DEFINE_CLK_RPM(name, active, 0, MSM_RPM_ID_QDSS_CLK, \
+ MSM_RPM_STATUS_ID_QDSS_CLK, 0, 0, &clk_rpmrs_data)
#define DEFINE_CLK_RPM_BRANCH(name, active, r_id, r) \
__DEFINE_CLK_RPM_BRANCH(name, active, 0, MSM_RPM_ID_##r_id##_CLK, \
@@ -186,8 +147,8 @@
RPM_SMD_KEY_ENABLE, &clk_rpmrs_data_smd)
#define DEFINE_CLK_RPM_SMD_QDSS(name, active, type, r_id) \
- __DEFINE_CLK_RPM_QDSS(name, active, type, r_id, \
- 0, RPM_SMD_KEY_STATE, &clk_rpmrs_data_smd)
+ __DEFINE_CLK_RPM(name, active, type, r_id, \
+ 0, 0, RPM_SMD_KEY_STATE, &clk_rpmrs_data_smd)
/*
* The RPM XO buffer clock management code aggregates votes for pin-control mode
* and software mode separately. Software-enable has higher priority over pin-
diff --git a/arch/arm/mach-msm/cpr-regulator.c b/arch/arm/mach-msm/cpr-regulator.c
index 5550282..a2936c2 100644
--- a/arch/arm/mach-msm/cpr-regulator.c
+++ b/arch/arm/mach-msm/cpr-regulator.c
@@ -125,21 +125,7 @@
#define CPR_FUSE_RO_SEL_BITS 3
#define CPR_FUSE_RO_SEL_BITS_MASK ((1<<CPR_FUSE_RO_SEL_BITS)-1)
-#define CPR_FUSE_TARGET_QUOT_TURBO_SHIFT 0
-#define CPR_FUSE_TARGET_QUOT_NOMINAL_SHIFT 12
-#define CPR_FUSE_TARGET_QUOT_SVS_SHIFT 24
-
-#define CPR_FUSE_DISABLE_CPR_SHIFT 36
-#define CPR_FUSE_LOCAL_APPROACH_SHIFT 37
-#define CPR_FUSE_REDUNDANT_SHIFT 57
-
-/* PVS eFuse parameters */
-#define PVS_FUSE_REDUNDANT_SHIFT 24
-#define PVS_FUSE_REDUNDANT_BITS 3
-#define PVS_FUSE_REDUNDANT_MASK ((1<<PVS_FUSE_REDUNDANT_BITS)-1)
-
-#define PVS_FUSE_BINS_SHIFT 6
-#define PVS_FUSE_BINS_REDUNDANT_SHIFT 27
+#define BYTES_PER_FUSE_ROW 8
enum voltage_change_dir {
NO_CHANGE,
@@ -154,9 +140,11 @@
int corner;
int ceiling_max;
+ /* eFuse parameters */
+ phys_addr_t efuse_addr;
+ void __iomem *efuse_base;
+
/* Process voltage parameters */
- phys_addr_t pvs_efuse;
- u32 num_efuse_bits;
u32 pvs_bin_process[CPR_PVS_EFUSE_BINS_MAX];
u32 pvs_corner_v[NUM_APC_PVS][CPR_CORNER_MAX];
/* Process voltage variables */
@@ -173,12 +161,9 @@
int vdd_mx_vmin;
/* CPR parameters */
- phys_addr_t cpr_fuse_addr;
u64 cpr_fuse_bits;
- u64 cpr_fuse_bits_2;
bool cpr_fuse_disable;
bool cpr_fuse_local;
- bool cpr_fuse_redundancy;
int cpr_fuse_target_quot[CPR_CORNER_MAX];
int cpr_fuse_ro_sel[CPR_CORNER_MAX];
int gcnt;
@@ -838,7 +823,7 @@
#define cpr_regulator_resume NULL
#endif
-static int cpr_config(struct cpr_regulator *cpr_vreg)
+static int __devinit cpr_config(struct cpr_regulator *cpr_vreg)
{
int i;
u32 val, gcnt, reg;
@@ -928,47 +913,80 @@
return 0;
}
-static int __init cpr_pvs_init(struct cpr_regulator *cpr_vreg)
+static int __devinit cpr_is_fuse_redundant(struct cpr_regulator *cpr_vreg,
+ u32 redun_sel[4])
{
- void __iomem *efuse_base;
- u32 efuse_bits, redundant, shift, mask;
- int i, process;
+ u32 fuse_bits;
+ int redundant;
- efuse_base = ioremap(cpr_vreg->pvs_efuse, 4);
- if (!efuse_base) {
- pr_err("Unable to map pvs_efuse 0x%08x\n",
- cpr_vreg->pvs_efuse);
- return -EINVAL;
+ fuse_bits = readl_relaxed(cpr_vreg->efuse_base
+ + redun_sel[0] * BYTES_PER_FUSE_ROW);
+ fuse_bits = (fuse_bits >> redun_sel[1]) & ((1 << redun_sel[2]) - 1);
+ if (fuse_bits == redun_sel[3])
+ redundant = 1;
+ else
+ redundant = 0;
+
+ pr_info("[row:%d] = 0x%x @%d:%d = %d?: redundant=%d\n",
+ redun_sel[0], fuse_bits,
+ redun_sel[1], redun_sel[2], redun_sel[3], redundant);
+ return redundant;
+}
+
+static int __devinit cpr_pvs_init(struct platform_device *pdev,
+ struct cpr_regulator *cpr_vreg)
+{
+ struct device_node *of_node = pdev->dev.of_node;
+ u32 efuse_bits;
+ int rc, process;
+ u32 pvs_fuse[3], pvs_fuse_redun_sel[4];
+ bool redundant;
+ size_t pvs_bins;
+
+ rc = of_property_read_u32_array(of_node, "qcom,pvs-fuse-redun-sel",
+ pvs_fuse_redun_sel, 4);
+ if (rc < 0) {
+ pr_err("pvs-fuse-redun-sel missing: rc=%d\n", rc);
+ return rc;
}
- efuse_bits = readl_relaxed(efuse_base);
+ redundant = cpr_is_fuse_redundant(cpr_vreg, pvs_fuse_redun_sel);
+
+ if (redundant) {
+ rc = of_property_read_u32_array(of_node, "qcom,pvs-fuse-redun",
+ pvs_fuse, 3);
+ if (rc < 0) {
+ pr_err("pvs-fuse-redun missing: rc=%d\n", rc);
+ return rc;
+ }
+ } else {
+ rc = of_property_read_u32_array(of_node, "qcom,pvs-fuse",
+ pvs_fuse, 3);
+ if (rc < 0) {
+ pr_err("pvs-fuse missing: rc=%d\n", rc);
+ return rc;
+ }
+ }
/* Construct PVS process # from the efuse bits */
- redundant = (efuse_bits >> PVS_FUSE_REDUNDANT_SHIFT)
- & PVS_FUSE_REDUNDANT_MASK;
- if (redundant == 2)
- shift = PVS_FUSE_BINS_REDUNDANT_SHIFT;
- else
- shift = PVS_FUSE_BINS_SHIFT;
- mask = (1 << cpr_vreg->num_efuse_bits) - 1;
- cpr_vreg->pvs_bin = (efuse_bits >> shift) & mask;
+ efuse_bits = readl_relaxed(cpr_vreg->efuse_base +
+ pvs_fuse[0] * BYTES_PER_FUSE_ROW);
+ cpr_vreg->pvs_bin = (efuse_bits >> pvs_fuse[1]) &
+ ((1 << pvs_fuse[2]) - 1);
- /* Set ceiling max and use it for APC_PVS_NO */
- cpr_vreg->ceiling_max =
- cpr_vreg->pvs_corner_v[APC_PVS_SLOW][CPR_CORNER_TURBO];
-
- iounmap(efuse_base);
+ pvs_bins = 1 << pvs_fuse[2];
+ rc = of_property_read_u32_array(of_node, "qcom,pvs-bin-process",
+ cpr_vreg->pvs_bin_process,
+ pvs_bins);
+ if (rc < 0) {
+ pr_err("pvs-bin-process missing: rc=%d\n", rc);
+ return rc;
+ }
process = cpr_vreg->pvs_bin_process[cpr_vreg->pvs_bin];
- pr_info("[0x%08X] = 0x%08X, n_bits=%d, bin=%d (%d) [redundant=%d]\n",
- cpr_vreg->pvs_efuse, efuse_bits, cpr_vreg->num_efuse_bits,
- cpr_vreg->pvs_bin, process, redundant);
- for (i = APC_PVS_SLOW; i < NUM_APC_PVS; i++) {
- pr_info("[%d] [%d %d %d] uV\n", i,
- cpr_vreg->pvs_corner_v[i][CPR_CORNER_SVS],
- cpr_vreg->pvs_corner_v[i][CPR_CORNER_NORMAL],
- cpr_vreg->pvs_corner_v[i][CPR_CORNER_TURBO]);
- }
+ pr_info("[row:%d] = 0x%08X, n_bits=%d, bin=%d (%d)\n",
+ pvs_fuse[0], efuse_bits, pvs_fuse[2],
+ cpr_vreg->pvs_bin, process);
if (process == APC_PVS_NO || process >= NUM_APC_PVS) {
pr_err("Bin=%d (%d) is out of spec. Assume SLOW.\n",
@@ -994,7 +1012,7 @@
} \
} while (0)
-static int __init cpr_apc_init(struct platform_device *pdev,
+static int __devinit cpr_apc_init(struct platform_device *pdev,
struct cpr_regulator *cpr_vreg)
{
struct device_node *of_node = pdev->dev.of_node;
@@ -1055,81 +1073,124 @@
}
}
-static int __init cpr_init_cpr_efuse(struct cpr_regulator *cpr_vreg)
+static int __devinit cpr_init_cpr_efuse(struct platform_device *pdev,
+ struct cpr_regulator *cpr_vreg)
{
- void __iomem *efuse_base;
+ struct device_node *of_node = pdev->dev.of_node;
+ int i, rc = 0;
+ bool redundant;
+ u32 cpr_fuse_redun_sel[4];
+ char *targ_quot_str, *ro_sel_str;
+ u32 cpr_fuse_row;
+ u32 bp_cpr_disable, bp_scheme;
+ int bp_target_quot[CPR_CORNER_MAX];
+ int bp_ro_sel[CPR_CORNER_MAX];
u32 ro_sel, val;
- u64 fuse_bits;
- int ro_sel_shift[CPR_CORNER_MAX];
+ u64 fuse_bits, fuse_bits_2;
- efuse_base = ioremap(cpr_vreg->cpr_fuse_addr, 16);
- if (!efuse_base) {
- pr_err("Unable to map cpr_fuse_addr 0x%08x\n",
- cpr_vreg->cpr_fuse_addr);
- return -EINVAL;
+ rc = of_property_read_u32_array(of_node, "qcom,cpr-fuse-redun-sel",
+ cpr_fuse_redun_sel, 4);
+ if (rc < 0) {
+ pr_err("cpr-fuse-redun-sel missing: rc=%d\n", rc);
+ return rc;
}
- cpr_vreg->cpr_fuse_bits = readll_relaxed(efuse_base);
- cpr_vreg->cpr_fuse_bits_2 = readll_relaxed(efuse_base + 8);
+ redundant = cpr_is_fuse_redundant(cpr_vreg, cpr_fuse_redun_sel);
- iounmap(efuse_base);
+ if (redundant) {
+ CPR_PROP_READ_U32(of_node, "cpr-fuse-redun-row",
+ &cpr_fuse_row, rc);
+ targ_quot_str = "qcom,cpr-fuse-redun-target-quot";
+ ro_sel_str = "qcom,cpr-fuse-redun-ro-sel";
+ } else {
+ CPR_PROP_READ_U32(of_node, "cpr-fuse-row",
+ &cpr_fuse_row, rc);
+ targ_quot_str = "qcom,cpr-fuse-target-quot";
+ ro_sel_str = "qcom,cpr-fuse-ro-sel";
+ }
+ if (rc)
+ return rc;
+
+ rc = of_property_read_u32_array(of_node,
+ targ_quot_str,
+ &bp_target_quot[CPR_CORNER_SVS],
+ CPR_CORNER_MAX - CPR_CORNER_SVS);
+ if (rc < 0) {
+ pr_err("missing %s: rc=%d\n", targ_quot_str, rc);
+ return rc;
+ }
+
+ rc = of_property_read_u32_array(of_node,
+ ro_sel_str,
+ &bp_ro_sel[CPR_CORNER_SVS],
+ CPR_CORNER_MAX - CPR_CORNER_SVS);
+ if (rc < 0) {
+ pr_err("missing %s: rc=%d\n", ro_sel_str, rc);
+ return rc;
+ }
/* Read the control bits of eFuse */
- cpr_vreg->cpr_fuse_disable = (cpr_vreg->cpr_fuse_bits >>
- CPR_FUSE_DISABLE_CPR_SHIFT) & 0x01;
- cpr_vreg->cpr_fuse_local = (cpr_vreg->cpr_fuse_bits >>
- CPR_FUSE_LOCAL_APPROACH_SHIFT) & 0x01;
- cpr_vreg->cpr_fuse_redundancy = (cpr_vreg->cpr_fuse_bits >>
- CPR_FUSE_REDUNDANT_SHIFT) & 0x01;
+ fuse_bits = readll_relaxed(cpr_vreg->efuse_base
+ + cpr_fuse_row * BYTES_PER_FUSE_ROW);
+ pr_info("[row:%d] = 0x%llx\n", cpr_fuse_row, fuse_bits);
- pr_info("[0x%08X] = 0x%llx\n", cpr_vreg->cpr_fuse_addr,
- cpr_vreg->cpr_fuse_bits);
- pr_info("disable = %d, local = %d, redundancy = %d\n",
- cpr_vreg->cpr_fuse_disable,
- cpr_vreg->cpr_fuse_local,
- cpr_vreg->cpr_fuse_redundancy);
- pr_info("[0x%08X] = 0x%llx\n", cpr_vreg->cpr_fuse_addr + 8,
- cpr_vreg->cpr_fuse_bits_2);
+ if (redundant) {
+ if (of_property_read_bool(of_node,
+ "qcom,cpr-fuse-redun-bp-cpr-disable")) {
+ CPR_PROP_READ_U32(of_node,
+ "cpr-fuse-redun-bp-cpr-disable",
+ &bp_cpr_disable, rc);
+ CPR_PROP_READ_U32(of_node,
+ "cpr-fuse-redun-bp-scheme",
+ &bp_scheme, rc);
+ if (rc)
+ return rc;
+ fuse_bits_2 = fuse_bits;
+ } else {
+ u32 temp_row;
- if (cpr_vreg->cpr_fuse_redundancy == 0) {
- fuse_bits = cpr_vreg->cpr_fuse_bits;
- ro_sel_shift[CPR_CORNER_SVS] = 54;
- ro_sel_shift[CPR_CORNER_NORMAL] = 38;
- ro_sel_shift[CPR_CORNER_TURBO] = 41;
+ /* Use original fuse if no optional property */
+ CPR_PROP_READ_U32(of_node, "cpr-fuse-bp-cpr-disable",
+ &bp_cpr_disable, rc);
+ CPR_PROP_READ_U32(of_node, "cpr-fuse-bp-scheme",
+ &bp_scheme, rc);
+ CPR_PROP_READ_U32(of_node, "cpr-fuse-row",
+ &temp_row, rc);
+ if (rc)
+ return rc;
+ fuse_bits_2 = readll_relaxed(cpr_vreg->efuse_base
+ + temp_row * BYTES_PER_FUSE_ROW);
+ pr_info("[original row:%d] = 0x%llx\n",
+ temp_row, fuse_bits_2);
+ }
} else {
- fuse_bits = cpr_vreg->cpr_fuse_bits_2;
- ro_sel_shift[CPR_CORNER_SVS] = 46;
- ro_sel_shift[CPR_CORNER_NORMAL] = 36;
- ro_sel_shift[CPR_CORNER_TURBO] = 39;
+ CPR_PROP_READ_U32(of_node, "cpr-fuse-bp-cpr-disable",
+ &bp_cpr_disable, rc);
+ CPR_PROP_READ_U32(of_node, "cpr-fuse-bp-scheme",
+ &bp_scheme, rc);
+ if (rc)
+ return rc;
+ fuse_bits_2 = fuse_bits;
}
- /* SVS */
- ro_sel = (fuse_bits >> ro_sel_shift[CPR_CORNER_SVS])
- & CPR_FUSE_RO_SEL_BITS_MASK;
- val = (fuse_bits >> CPR_FUSE_TARGET_QUOT_SVS_SHIFT)
- & CPR_FUSE_TARGET_QUOT_BITS_MASK;
- cpr_vreg->cpr_fuse_target_quot[CPR_CORNER_SVS] = val;
- cpr_vreg->cpr_fuse_ro_sel[CPR_CORNER_SVS] = ro_sel;
- pr_info("SVS: ro_sel = %d, target quot = 0x%04x\n", ro_sel, val);
+ cpr_vreg->cpr_fuse_disable = (fuse_bits_2 >> bp_cpr_disable) & 0x01;
+ cpr_vreg->cpr_fuse_local = (fuse_bits_2 >> bp_scheme) & 0x01;
- /* Nominal */
- ro_sel = (fuse_bits >> ro_sel_shift[CPR_CORNER_NORMAL])
- & CPR_FUSE_RO_SEL_BITS_MASK;
- val = (fuse_bits >> CPR_FUSE_TARGET_QUOT_NOMINAL_SHIFT)
- & CPR_FUSE_TARGET_QUOT_BITS_MASK;
- cpr_vreg->cpr_fuse_target_quot[CPR_CORNER_NORMAL] = val;
- cpr_vreg->cpr_fuse_ro_sel[CPR_CORNER_NORMAL] = ro_sel;
- pr_info("Nominal: ro_sel = %d, target quot = 0x%04x\n", ro_sel, val);
+ pr_info("disable = %d, local = %d\n",
+ cpr_vreg->cpr_fuse_disable, cpr_vreg->cpr_fuse_local);
- /* Turbo */
- ro_sel = (fuse_bits >> ro_sel_shift[CPR_CORNER_TURBO])
+ for (i = CPR_CORNER_SVS; i < CPR_CORNER_MAX; i++) {
+ ro_sel = (fuse_bits >> bp_ro_sel[i])
& CPR_FUSE_RO_SEL_BITS_MASK;
- val = (fuse_bits >> CPR_FUSE_TARGET_QUOT_TURBO_SHIFT)
+ val = (fuse_bits >> bp_target_quot[i])
& CPR_FUSE_TARGET_QUOT_BITS_MASK;
- cpr_vreg->cpr_fuse_target_quot[CPR_CORNER_TURBO] = val;
- cpr_vreg->cpr_fuse_ro_sel[CPR_CORNER_TURBO] = ro_sel;
- pr_info("Turbo: ro_sel = %d, target quot = 0x%04x\n", ro_sel, val);
+ cpr_vreg->cpr_fuse_target_quot[i] = val;
+ cpr_vreg->cpr_fuse_ro_sel[i] = ro_sel;
+ pr_info("Corner[%d]: ro_sel = %d, target quot = %d\n",
+ i, ro_sel, val);
+ }
+ cpr_vreg->cpr_fuse_bits = fuse_bits;
if (!cpr_vreg->cpr_fuse_bits) {
cpr_vreg->cpr_fuse_disable = 1;
pr_err("cpr_fuse_bits = 0: set cpr_fuse_disable = 1\n");
@@ -1138,7 +1199,7 @@
return 0;
}
-static int __init cpr_init_cpr_voltages(struct cpr_regulator *cpr_vreg)
+static int __devinit cpr_init_cpr_voltages(struct cpr_regulator *cpr_vreg)
{
int i;
@@ -1155,7 +1216,7 @@
return 0;
}
-static int __init cpr_init_cpr_parameters(struct platform_device *pdev,
+static int __devinit cpr_init_cpr_parameters(struct platform_device *pdev,
struct cpr_regulator *cpr_vreg)
{
struct device_node *of_node = pdev->dev.of_node;
@@ -1223,20 +1284,12 @@
return rc;
}
-static int __init cpr_init_cpr(struct platform_device *pdev,
+static int __devinit cpr_init_cpr(struct platform_device *pdev,
struct cpr_regulator *cpr_vreg)
{
struct resource *res;
int rc = 0;
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
- "cpr_efuse");
- if (!res || !res->start) {
- pr_err("cpr_efuse missing: res=%p\n", res);
- return -EINVAL;
- }
- cpr_vreg->cpr_fuse_addr = res->start;
-
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rbcpr_clk");
if (!res || !res->start) {
pr_err("missing rbcpr_clk address: res=%p\n", res);
@@ -1244,7 +1297,7 @@
}
cpr_vreg->rbcpr_clk_addr = res->start;
- rc = cpr_init_cpr_efuse(cpr_vreg);
+ rc = cpr_init_cpr_efuse(pdev, cpr_vreg);
if (rc)
return rc;
@@ -1287,44 +1340,41 @@
return 0;
}
-static int __init cpr_pvs_parse_dt(struct platform_device *pdev,
- struct cpr_regulator *cpr_vreg)
+static int __devinit cpr_efuse_init(struct platform_device *pdev,
+ struct cpr_regulator *cpr_vreg)
+{
+ struct resource *res;
+ int len;
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "efuse_addr");
+ if (!res || !res->start) {
+ pr_err("efuse_addr missing: res=%p\n", res);
+ return -EINVAL;
+ }
+ cpr_vreg->efuse_addr = res->start;
+ len = res->end - res->start + 1;
+
+ pr_info("efuse_addr = 0x%x (len=0x%x)\n", res->start, len);
+
+ cpr_vreg->efuse_base = ioremap(cpr_vreg->efuse_addr, len);
+ if (!cpr_vreg->efuse_base) {
+ pr_err("Unable to map efuse_addr 0x%08x\n",
+ cpr_vreg->efuse_addr);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static void cpr_efuse_free(struct cpr_regulator *cpr_vreg)
+{
+ iounmap(cpr_vreg->efuse_base);
+}
+
+static int __devinit cpr_voltage_plan_init(struct platform_device *pdev,
+ struct cpr_regulator *cpr_vreg)
{
struct device_node *of_node = pdev->dev.of_node;
- struct resource *res;
- int rc;
- size_t pvs_bins;
-
- /* Parse process voltage parameters */
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pvs_efuse");
- if (!res || !res->start) {
- pr_err("pvs_efuse missing: res=%p\n", res);
- return -EINVAL;
- }
- cpr_vreg->pvs_efuse = res->start;
-
- rc = of_property_read_u32(of_node, "qcom,num-efuse-bits",
- &cpr_vreg->num_efuse_bits);
- if (rc < 0) {
- pr_err("num-efuse-bits missing: rc=%d\n", rc);
- return rc;
- }
-
- if (cpr_vreg->num_efuse_bits == 0 ||
- cpr_vreg->num_efuse_bits > CPR_PVS_EFUSE_BITS_MAX) {
- pr_err("invalid num-efuse-bits : %d\n",
- cpr_vreg->num_efuse_bits);
- return -EINVAL;
- }
-
- pvs_bins = 1 << cpr_vreg->num_efuse_bits;
- rc = of_property_read_u32_array(of_node, "qcom,pvs-bin-process",
- cpr_vreg->pvs_bin_process,
- pvs_bins);
- if (rc < 0) {
- pr_err("pvs-bin-process missing: rc=%d\n", rc);
- return rc;
- }
+ int rc, i;
rc = of_property_read_u32_array(of_node,
"qcom,pvs-corner-ceiling-slow",
@@ -1353,6 +1403,17 @@
return rc;
}
+ /* Set ceiling max and use it for APC_PVS_NO */
+ cpr_vreg->ceiling_max =
+ cpr_vreg->pvs_corner_v[APC_PVS_SLOW][CPR_CORNER_TURBO];
+
+ for (i = APC_PVS_SLOW; i < NUM_APC_PVS; i++) {
+ pr_info("[%d] [%d %d %d] uV\n", i,
+ cpr_vreg->pvs_corner_v[i][CPR_CORNER_SVS],
+ cpr_vreg->pvs_corner_v[i][CPR_CORNER_NORMAL],
+ cpr_vreg->pvs_corner_v[i][CPR_CORNER_TURBO]);
+ }
+
return 0;
}
@@ -1386,31 +1447,39 @@
return -ENOMEM;
}
- rc = cpr_pvs_parse_dt(pdev, cpr_vreg);
+ rc = cpr_efuse_init(pdev, cpr_vreg);
if (rc) {
- pr_err("Wrong DT parameter specified: rc=%d\n", rc);
+ pr_err("Wrong eFuse address specified: rc=%d\n", rc);
return rc;
}
- rc = cpr_pvs_init(cpr_vreg);
+ rc = cpr_voltage_plan_init(pdev, cpr_vreg);
+ if (rc) {
+ pr_err("Wrong DT parameter specified: rc=%d\n", rc);
+ goto err_out;
+ }
+
+ rc = cpr_pvs_init(pdev, cpr_vreg);
if (rc) {
pr_err("Initialize PVS wrong: rc=%d\n", rc);
- return rc;
+ goto err_out;
}
rc = cpr_apc_init(pdev, cpr_vreg);
if (rc) {
if (rc != -EPROBE_DEFER)
pr_err("Initialize APC wrong: rc=%d\n", rc);
- return rc;
+ goto err_out;
}
rc = cpr_init_cpr(pdev, cpr_vreg);
if (rc) {
pr_err("Initialize CPR failed: rc=%d\n", rc);
- return rc;
+ goto err_out;
}
+ cpr_efuse_free(cpr_vreg);
+
mutex_init(&cpr_vreg->cpr_mutex);
rdesc = &cpr_vreg->rdesc;
@@ -1433,6 +1502,10 @@
the_cpr = cpr_vreg;
return 0;
+
+err_out:
+ cpr_efuse_free(cpr_vreg);
+ return rc;
}
static int __devexit cpr_regulator_remove(struct platform_device *pdev)
diff --git a/arch/arm/mach-msm/idle-v7.S b/arch/arm/mach-msm/idle-v7.S
index 5d25134..f8a32b4 100644
--- a/arch/arm/mach-msm/idle-v7.S
+++ b/arch/arm/mach-msm/idle-v7.S
@@ -25,6 +25,7 @@
#ifdef CONFIG_MSM_SCM
#define SCM_SVC_BOOT 0x1
#define SCM_CMD_TERMINATE_PC 0x2
+#define SCM_CMD_CORE_HOTPLUGGED 0x10
#endif
ENTRY(msm_arch_idle)
@@ -99,7 +100,7 @@
#ifdef CONFIG_MSM_SCM
ldr r0, =SCM_SVC_BOOT
ldr r1, =SCM_CMD_TERMINATE_PC
- mov r2, #0
+ ldr r2, =SCM_CMD_CORE_HOTPLUGGED
bl scm_call_atomic1
#else
mrc p15, 0, r3, c1, c0, 0 /* read current CR */
diff --git a/arch/arm/mach-msm/include/mach/board.h b/arch/arm/mach-msm/include/mach/board.h
index 7b26bd6..6370bd4 100644
--- a/arch/arm/mach-msm/include/mach/board.h
+++ b/arch/arm/mach-msm/include/mach/board.h
@@ -183,7 +183,7 @@
};
struct msm_camera_gpio_num_info {
- uint16_t gpio_num[2];
+ uint16_t gpio_num[7];
};
struct msm_camera_gpio_conf {
diff --git a/arch/arm/mach-msm/include/mach/clk-provider.h b/arch/arm/mach-msm/include/mach/clk-provider.h
index 1fad7f6..72b5cc1 100644
--- a/arch/arm/mach-msm/include/mach/clk-provider.h
+++ b/arch/arm/mach-msm/include/mach/clk-provider.h
@@ -114,7 +114,7 @@
int (*set_max_rate)(struct clk *clk, unsigned long rate);
int (*set_flags)(struct clk *clk, unsigned flags);
unsigned long (*get_rate)(struct clk *clk);
- int (*list_rate)(struct clk *clk, unsigned n);
+ long (*list_rate)(struct clk *clk, unsigned n);
int (*is_enabled)(struct clk *clk);
long (*round_rate)(struct clk *clk, unsigned long rate);
int (*set_parent)(struct clk *clk, struct clk *parent);
diff --git a/arch/arm/mach-msm/include/mach/iommu.h b/arch/arm/mach-msm/include/mach/iommu.h
index c979e0c..7cfbd93 100644
--- a/arch/arm/mach-msm/include/mach/iommu.h
+++ b/arch/arm/mach-msm/include/mach/iommu.h
@@ -327,30 +327,43 @@
static inline int msm_soc_version_supports_iommu_v0(void)
{
+ static int soc_supports_v0 = -1;
#ifdef CONFIG_OF
struct device_node *node;
+#endif
+ if (soc_supports_v0 != -1)
+ return soc_supports_v0;
+
+#ifdef CONFIG_OF
node = of_find_compatible_node(NULL, NULL, "qcom,msm-smmu-v1");
if (node) {
+ soc_supports_v0 = 0;
of_node_put(node);
return 0;
}
node = of_find_compatible_node(NULL, NULL, "qcom,msm-smmu-v0");
if (node) {
+ soc_supports_v0 = 1;
of_node_put(node);
return 1;
}
#endif
if (cpu_is_msm8960() &&
- SOCINFO_VERSION_MAJOR(socinfo_get_version()) < 2)
+ SOCINFO_VERSION_MAJOR(socinfo_get_version()) < 2) {
+ soc_supports_v0 = 0;
return 0;
+ }
if (cpu_is_msm8x60() &&
(SOCINFO_VERSION_MAJOR(socinfo_get_version()) != 2 ||
SOCINFO_VERSION_MINOR(socinfo_get_version()) < 1)) {
+ soc_supports_v0 = 0;
return 0;
}
+
+ soc_supports_v0 = 1;
return 1;
}
#endif
diff --git a/arch/arm/mach-msm/include/mach/msm_hdmi_audio_codec.h b/arch/arm/mach-msm/include/mach/msm_hdmi_audio_codec.h
index 95f33d5..ff3da11 100644
--- a/arch/arm/mach-msm/include/mach/msm_hdmi_audio_codec.h
+++ b/arch/arm/mach-msm/include/mach/msm_hdmi_audio_codec.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, 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
@@ -25,7 +25,8 @@
struct msm_hdmi_audio_codec_ops {
int (*audio_info_setup)(struct platform_device *pdev,
- u32 num_of_channels, u32 channel_allocation, u32 level_shift,
+ u32 sample_rate, u32 num_of_channels,
+ u32 channel_allocation, u32 level_shift,
bool down_mix);
int (*get_audio_edid_blk) (struct platform_device *pdev,
struct msm_hdmi_audio_edid_blk *blk);
diff --git a/arch/arm/mach-msm/include/mach/msm_tspp.h b/arch/arm/mach-msm/include/mach/msm_tspp.h
index ddc99f3..2c40d83 100644
--- a/arch/arm/mach-msm/include/mach/msm_tspp.h
+++ b/arch/arm/mach-msm/include/mach/msm_tspp.h
@@ -25,7 +25,7 @@
struct tspp_data_descriptor {
void *virt_base; /* logical address of the actual data */
- u32 phys_base; /* physical address of the actual data */
+ phys_addr_t phys_base; /* physical address of the actual data */
u32 size; /* size of buffer in bytes */
int id; /* unique identifier */
void *user; /* user-defined data */
@@ -33,9 +33,9 @@
typedef void (tspp_notifier)(int channel_id, void *user);
typedef void* (tspp_allocator)(int channel_id, u32 size,
- u32 *phys_base, void *user);
+ phys_addr_t *phys_base, void *user);
typedef void (tspp_memfree)(int channel_id, u32 size,
- void *virt_base, u32 phys_base, void *user);
+ void *virt_base, phys_addr_t phys_base, void *user);
/* Kernel API functions */
int tspp_open_stream(u32 dev, u32 channel_id,
diff --git a/arch/arm/mach-msm/include/mach/ocmem_priv.h b/arch/arm/mach-msm/include/mach/ocmem_priv.h
index 6f83c53..32d58d4 100644
--- a/arch/arm/mach-msm/include/mach/ocmem_priv.h
+++ b/arch/arm/mach-msm/include/mach/ocmem_priv.h
@@ -174,8 +174,8 @@
/* Request Power State */
unsigned power_state;
struct ocmem_eviction_data *edata;
- /* Request that triggered eviction */
- struct ocmem_req *e_handle;
+ /* Eviction data of the request being evicted */
+ struct ocmem_eviction_data *eviction_info;
};
struct ocmem_handle {
diff --git a/arch/arm/mach-msm/ipc_router.c b/arch/arm/mach-msm/ipc_router.c
index aba5fee..c0cca1d 100644
--- a/arch/arm/mach-msm/ipc_router.c
+++ b/arch/arm/mach-msm/ipc_router.c
@@ -2266,6 +2266,48 @@
}
/**
+ * msm_ipc_router_rx_data_wait() - Wait for new message destined to a local port.
+ * @port_ptr: Pointer to the local port
+ * @timeout: < 0 timeout indicates infinite wait till a message arrives.
+ * > 0 timeout indicates the wait time.
+ * 0 indicates that we do not wait.
+ * @return: 0 if there are pending messages to read,
+ * standard Linux error code otherwise.
+ *
+ * Checks for the availability of messages that are destined to a local port.
+ * If no messages are present then waits as per @timeout.
+ */
+int msm_ipc_router_rx_data_wait(struct msm_ipc_port *port_ptr, long timeout)
+{
+ int ret = 0;
+
+ mutex_lock(&port_ptr->port_rx_q_lock_lhb3);
+ while (list_empty(&port_ptr->port_rx_q)) {
+ mutex_unlock(&port_ptr->port_rx_q_lock_lhb3);
+ if (timeout < 0) {
+ ret = wait_event_interruptible(
+ port_ptr->port_rx_wait_q,
+ !list_empty(&port_ptr->port_rx_q));
+ if (ret)
+ return ret;
+ } else if (timeout > 0) {
+ timeout = wait_event_interruptible_timeout(
+ port_ptr->port_rx_wait_q,
+ !list_empty(&port_ptr->port_rx_q),
+ timeout);
+ if (timeout < 0)
+ return -EFAULT;
+ }
+ if (timeout == 0)
+ return -ENOMSG;
+ mutex_lock(&port_ptr->port_rx_q_lock_lhb3);
+ }
+ mutex_unlock(&port_ptr->port_rx_q_lock_lhb3);
+
+ return ret;
+}
+
+/**
* msm_ipc_router_recv_from() - Recieve messages destined to a local port.
* @port_ptr: Pointer to the local port
* @data : Pointer to the socket buffer head
@@ -2274,7 +2316,7 @@
* > 0 timeout indicates the wait time.
* 0 indicates that we do not wait.
* @return: = Number of bytes read(On successful read operation).
- * = 0 (If there are no pending messages and timeout is 0).
+ * = -ENOMSG (If there are no pending messages and timeout is 0).
* = -EINVAL (If either of the arguments, port_ptr or data is invalid)
* = -EFAULT (If there are no pending messages when timeout is > 0
* and the wait_event_interruptible_timeout has returned value > 0)
@@ -2303,28 +2345,10 @@
}
*data = NULL;
- mutex_lock(&port_ptr->port_rx_q_lock_lhb3);
- while (list_empty(&port_ptr->port_rx_q)) {
- mutex_unlock(&port_ptr->port_rx_q_lock_lhb3);
- if (timeout < 0) {
- ret = wait_event_interruptible(
- port_ptr->port_rx_wait_q,
- !list_empty(&port_ptr->port_rx_q));
- if (ret)
- return ret;
- } else if (timeout > 0) {
- timeout = wait_event_interruptible_timeout(
- port_ptr->port_rx_wait_q,
- !list_empty(&port_ptr->port_rx_q),
- timeout);
- if (timeout < 0)
- return -EFAULT;
- }
- if (timeout == 0)
- return 0;
- mutex_lock(&port_ptr->port_rx_q_lock_lhb3);
- }
- mutex_unlock(&port_ptr->port_rx_q_lock_lhb3);
+
+ ret = msm_ipc_router_rx_data_wait(port_ptr, timeout);
+ if (ret)
+ return ret;
ret = msm_ipc_router_read(port_ptr, data, 0);
if (ret <= 0 || !(*data))
@@ -2358,12 +2382,10 @@
ret = msm_ipc_router_recv_from(port_ptr, &in_skb_head, src, 0);
- if (ret == 0)
- return -ENOMSG;
-
if (ret < 0) {
- pr_err("%s: msm_ipc_router_recv_from failed - ret: %d\n",
- __func__, ret);
+ if (ret != -ENOMSG)
+ pr_err("%s: msm_ipc_router_recv_from failed - ret: %d\n",
+ __func__, ret);
return ret;
}
diff --git a/arch/arm/mach-msm/ipc_router.h b/arch/arm/mach-msm/ipc_router.h
index 55aeade..7bfc52b 100644
--- a/arch/arm/mach-msm/ipc_router.h
+++ b/arch/arm/mach-msm/ipc_router.h
@@ -160,6 +160,8 @@
void msm_ipc_sync_default_sec_rule(void *rule);
+int msm_ipc_router_rx_data_wait(struct msm_ipc_port *port_ptr, long timeout);
+
#if defined CONFIG_MSM_IPC_ROUTER_SMD_XPRT
extern void *msm_ipc_load_default_node(void);
diff --git a/arch/arm/mach-msm/ipc_socket.c b/arch/arm/mach-msm/ipc_socket.c
index 515dc92..ea27c71 100644
--- a/arch/arm/mach-msm/ipc_socket.c
+++ b/arch/arm/mach-msm/ipc_socket.c
@@ -411,33 +411,14 @@
lock_sock(sk);
timeout = sk->sk_rcvtimeo;
- mutex_lock(&port_ptr->port_rx_q_lock_lhb3);
- while (list_empty(&port_ptr->port_rx_q)) {
- mutex_unlock(&port_ptr->port_rx_q_lock_lhb3);
- release_sock(sk);
- if (timeout < 0) {
- ret = wait_event_interruptible(
- port_ptr->port_rx_wait_q,
- !list_empty(&port_ptr->port_rx_q));
- if (ret)
- return ret;
- } else if (timeout > 0) {
- timeout = wait_event_interruptible_timeout(
- port_ptr->port_rx_wait_q,
- !list_empty(&port_ptr->port_rx_q),
- timeout);
- if (timeout < 0)
- return -EFAULT;
- }
- if (timeout == 0) {
+ ret = msm_ipc_router_rx_data_wait(port_ptr, timeout);
+ if (ret) {
+ release_sock(sk);
+ if (ret == -ENOMSG)
m->msg_namelen = 0;
- return 0;
- }
- lock_sock(sk);
- mutex_lock(&port_ptr->port_rx_q_lock_lhb3);
+ return ret;
}
- mutex_unlock(&port_ptr->port_rx_q_lock_lhb3);
ret = msm_ipc_router_read(port_ptr, &msg, buf_len);
if (ret <= 0 || !msg) {
diff --git a/arch/arm/mach-msm/ocmem_sched.c b/arch/arm/mach-msm/ocmem_sched.c
index a3fd6b2..cbf7933 100644
--- a/arch/arm/mach-msm/ocmem_sched.c
+++ b/arch/arm/mach-msm/ocmem_sched.c
@@ -1192,19 +1192,23 @@
}
/* Remove the request from eviction lists */
-static void cancel_restore(struct ocmem_req *e_handle,
- struct ocmem_req *req)
+static void cancel_restore(struct ocmem_req *req)
{
- struct ocmem_eviction_data *edata = e_handle->edata;
+ struct ocmem_eviction_data *edata;
- if (!edata || !req)
+ if (!req)
+ return;
+
+ edata = req->eviction_info;
+
+ if (!edata)
return;
if (list_empty(&edata->req_list))
return;
list_del_init(&req->eviction_list);
- req->e_handle = NULL;
+ req->eviction_info = NULL;
return;
}
@@ -1499,8 +1503,8 @@
}
/* Remove the request from any restore lists */
- if (req->e_handle)
- cancel_restore(req->e_handle, req);
+ if (req->eviction_info)
+ cancel_restore(req);
/* Remove the request from any pending opreations */
if (TEST_STATE(req, R_ENQUEUED)) {
@@ -1747,12 +1751,7 @@
goto shrink_fail;
}
- if (!req->e_handle) {
- pr_err("Unable to find evicting request\n");
- goto shrink_fail;
- }
-
- edata = req->e_handle->edata;
+ edata = req->eviction_info;
if (!edata) {
pr_err("Unable to find eviction data\n");
@@ -1905,7 +1904,7 @@
&e_req->eviction_list,
&edata->req_list);
atomic_inc(&edata->pending);
- e_req->e_handle = req;
+ e_req->eviction_info = edata;
}
}
} else {
@@ -2037,7 +2036,7 @@
pr_debug("ocmem: restoring evicted request %p\n",
req);
req->edata = NULL;
- req->e_handle = NULL;
+ req->eviction_info = NULL;
req->op = SCHED_ALLOCATE;
inc_ocmem_stat(zone_of(req), NR_RESTORES);
sched_enqueue(req);
@@ -2076,8 +2075,11 @@
struct ocmem_eviction_data *edata = evictions[id];
int rc = 0;
- if (!edata)
+ if (!edata) {
+ pr_err("Client %s invoked restore without any eviction\n",
+ get_name(id));
return -EINVAL;
+ }
mutex_lock(&free_mutex);
rc = __restore_common(edata);
diff --git a/arch/arm/mach-msm/perf_debug.c b/arch/arm/mach-msm/perf_debug.c
index 643d945..0a799aa 100644
--- a/arch/arm/mach-msm/perf_debug.c
+++ b/arch/arm/mach-msm/perf_debug.c
@@ -33,6 +33,7 @@
"8 Perf: Add cortex A7 perf support\n"
"9 ARM: dts: msm: add perf-events support for msm8226\n"
"10 Perf: Fix counts across power collapse\n"
+ "11 ARM: dts: msm: add perf-events support for msm8x10, msm8x12\n"
;
static ssize_t desc_read(struct file *fp, char __user *buf,
diff --git a/arch/arm/mach-msm/peripheral-loader.c b/arch/arm/mach-msm/peripheral-loader.c
index c572291..ff1fd4f 100644
--- a/arch/arm/mach-msm/peripheral-loader.c
+++ b/arch/arm/mach-msm/peripheral-loader.c
@@ -771,7 +771,7 @@
ret = request_threaded_irq(desc->proxy_unvote_irq,
NULL,
proxy_unvote_intr_handler,
- IRQF_TRIGGER_RISING|IRQF_SHARED,
+ IRQF_TRIGGER_RISING,
desc->name, desc);
if (ret < 0) {
dev_err(desc->dev,
diff --git a/arch/arm/mach-msm/pil-dsps.c b/arch/arm/mach-msm/pil-dsps.c
index 73b58ab..f0a5ebf 100644
--- a/arch/arm/mach-msm/pil-dsps.c
+++ b/arch/arm/mach-msm/pil-dsps.c
@@ -23,6 +23,7 @@
#include <mach/msm_smsm.h>
#include <mach/ramdump.h>
#include <mach/msm_smem.h>
+#include <mach/msm_bus_board.h>
#include "peripheral-loader.h"
#include "scm-pas.h"
@@ -317,6 +318,8 @@
goto err_subsys;
}
+ scm_pas_init(MSM_BUS_MASTER_SPS);
+
ret = smsm_state_cb_register(SMSM_DSPS_STATE, SMSM_RESET,
dsps_smsm_state_cb, drv);
if (ret)
diff --git a/arch/arm/mach-msm/pil-gss.c b/arch/arm/mach-msm/pil-gss.c
index 840c90f..b209a25 100644
--- a/arch/arm/mach-msm/pil-gss.c
+++ b/arch/arm/mach-msm/pil-gss.c
@@ -571,6 +571,8 @@
goto err_smem;
}
+ scm_pas_init(MSM_BUS_MASTER_SPS);
+
ret = devm_request_irq(&pdev->dev, drv->irq, gss_wdog_bite_irq,
IRQF_TRIGGER_RISING, "gss_a5_wdog", drv);
if (ret < 0)
diff --git a/arch/arm/mach-msm/pil-modem.c b/arch/arm/mach-msm/pil-modem.c
index 8398206..f6a853e 100644
--- a/arch/arm/mach-msm/pil-modem.c
+++ b/arch/arm/mach-msm/pil-modem.c
@@ -25,6 +25,7 @@
#include <mach/subsystem_restart.h>
#include <mach/msm_smsm.h>
#include <mach/ramdump.h>
+#include <mach/msm_bus_board.h>
#include "modem_notifier.h"
#include "peripheral-loader.h"
@@ -490,6 +491,8 @@
goto err_ramdump;
}
+ scm_pas_init(MSM_BUS_MASTER_SPS);
+
ret = devm_request_irq(&pdev->dev, drv->irq, modem_wdog_bite_irq,
IRQF_TRIGGER_RISING, "modem_watchdog", drv);
if (ret)
diff --git a/arch/arm/mach-msm/pil-msa.c b/arch/arm/mach-msm/pil-msa.c
index a8f5b0e..3a26af9 100644
--- a/arch/arm/mach-msm/pil-msa.c
+++ b/arch/arm/mach-msm/pil-msa.c
@@ -292,25 +292,6 @@
.shutdown = pil_msa_pbl_shutdown,
};
-static int pil_msa_mba_make_proxy_votes(struct pil_desc *pil)
-{
- int ret;
- struct mba_data *drv = container_of(pil, struct mba_data, desc);
-
- ret = clk_prepare_enable(drv->xo);
- if (ret) {
- dev_err(pil->dev, "Failed to enable XO\n");
- return ret;
- }
- return 0;
-}
-
-static void pil_msa_mba_remove_proxy_votes(struct pil_desc *pil)
-{
- struct mba_data *drv = container_of(pil, struct mba_data, desc);
- clk_disable_unprepare(drv->xo);
-}
-
static int pil_msa_mba_init_image(struct pil_desc *pil,
const u8 *metadata, size_t size)
{
@@ -400,8 +381,6 @@
struct pil_reset_ops pil_msa_mba_ops = {
.init_image = pil_msa_mba_init_image,
- .proxy_vote = pil_msa_mba_make_proxy_votes,
- .proxy_unvote = pil_msa_mba_remove_proxy_votes,
.verify_blob = pil_msa_mba_verify_blob,
.auth_and_reset = pil_msa_mba_auth,
};
diff --git a/arch/arm/mach-msm/pil-pronto.c b/arch/arm/mach-msm/pil-pronto.c
index 80c0862..6e4aa02 100644
--- a/arch/arm/mach-msm/pil-pronto.c
+++ b/arch/arm/mach-msm/pil-pronto.c
@@ -31,6 +31,7 @@
#include <mach/msm_smsm.h>
#include <mach/ramdump.h>
#include <mach/msm_smem.h>
+#include <mach/msm_bus_board.h>
#include "peripheral-loader.h"
#include "scm-pas.h"
@@ -504,6 +505,8 @@
if (IS_ERR(drv->cxo))
return PTR_ERR(drv->cxo);
+ scm_pas_init(MSM_BUS_MASTER_CRYPTO_CORE0);
+
ret = pil_desc_init(desc);
if (ret)
return ret;
diff --git a/arch/arm/mach-msm/pil-q6v3.c b/arch/arm/mach-msm/pil-q6v3.c
index a369878..58d4301 100644
--- a/arch/arm/mach-msm/pil-q6v3.c
+++ b/arch/arm/mach-msm/pil-q6v3.c
@@ -24,6 +24,7 @@
#include <mach/subsystem_restart.h>
#include <mach/scm.h>
#include <mach/ramdump.h>
+#include <mach/msm_bus_board.h>
#include "peripheral-loader.h"
#include "scm-pas.h"
@@ -393,6 +394,8 @@
goto err_subsys;
}
+ scm_pas_init(MSM_BUS_MASTER_SPS);
+
ret = devm_request_irq(&pdev->dev, drv->irq, lpass_wdog_bite_irq,
IRQF_TRIGGER_RISING, "lpass_wdog", drv);
if (ret) {
diff --git a/arch/arm/mach-msm/pil-q6v4-lpass.c b/arch/arm/mach-msm/pil-q6v4-lpass.c
index 7acb599..6ec8430 100644
--- a/arch/arm/mach-msm/pil-q6v4-lpass.c
+++ b/arch/arm/mach-msm/pil-q6v4-lpass.c
@@ -26,6 +26,7 @@
#include <mach/subsystem_notif.h>
#include <mach/ramdump.h>
#include <mach/msm_smem.h>
+#include <mach/msm_bus_board.h>
#include "smd_private.h"
#include "sysmon.h"
@@ -356,6 +357,8 @@
goto err_notif_riva;
}
+ scm_pas_init(MSM_BUS_MASTER_SPS);
+
drv->modem_notif_hdle = subsys_notif_register_notifier("modem", &mnb);
if (IS_ERR(drv->modem_notif_hdle)) {
ret = PTR_ERR(drv->modem_notif_hdle);
diff --git a/arch/arm/mach-msm/pil-q6v4-mss.c b/arch/arm/mach-msm/pil-q6v4-mss.c
index c4b6038..6ee5965 100644
--- a/arch/arm/mach-msm/pil-q6v4-mss.c
+++ b/arch/arm/mach-msm/pil-q6v4-mss.c
@@ -24,6 +24,7 @@
#include <mach/msm_smsm.h>
#include <mach/ramdump.h>
#include <mach/msm_smem.h>
+#include <mach/msm_bus_board.h>
#include "smd_private.h"
#include "peripheral-loader.h"
@@ -462,6 +463,8 @@
if (ret)
goto err_irq;
+ scm_pas_init(MSM_BUS_MASTER_SPS);
+
ret = smsm_state_cb_register(SMSM_MODEM_STATE, SMSM_RESET,
smsm_state_cb, drv);
if (ret)
diff --git a/arch/arm/mach-msm/pil-q6v5-lpass.c b/arch/arm/mach-msm/pil-q6v5-lpass.c
index 6cd6ffe..3b88b10 100644
--- a/arch/arm/mach-msm/pil-q6v5-lpass.c
+++ b/arch/arm/mach-msm/pil-q6v5-lpass.c
@@ -30,6 +30,7 @@
#include <mach/scm.h>
#include <mach/ramdump.h>
#include <mach/msm_smem.h>
+#include <mach/msm_bus_board.h>
#include "peripheral-loader.h"
#include "pil-q6v5.h"
@@ -472,6 +473,8 @@
dev_info(&pdev->dev, "using non-secure boot\n");
}
+ scm_pas_init(MSM_BUS_MASTER_CRYPTO_CORE0);
+
ret = pil_desc_init(desc);
if (ret)
return ret;
diff --git a/arch/arm/mach-msm/pil-q6v5-mss.c b/arch/arm/mach-msm/pil-q6v5-mss.c
index 4d76c08..1f03fd32 100644
--- a/arch/arm/mach-msm/pil-q6v5-mss.c
+++ b/arch/arm/mach-msm/pil-q6v5-mss.c
@@ -429,8 +429,6 @@
mba_desc->dev = &pdev->dev;
mba_desc->ops = &pil_msa_mba_ops;
mba_desc->owner = THIS_MODULE;
- mba_desc->proxy_timeout = PROXY_TIMEOUT_MS;
- mba_desc->proxy_unvote_irq = clk_ready;
ret = pil_desc_init(mba_desc);
if (ret)
diff --git a/arch/arm/mach-msm/pil-riva.c b/arch/arm/mach-msm/pil-riva.c
index bf7438b..9a364b7 100644
--- a/arch/arm/mach-msm/pil-riva.c
+++ b/arch/arm/mach-msm/pil-riva.c
@@ -25,6 +25,7 @@
#include <mach/subsystem_restart.h>
#include <mach/ramdump.h>
#include <mach/msm_smem.h>
+#include <mach/msm_bus_board.h>
#include "peripheral-loader.h"
#include "scm-pas.h"
@@ -534,6 +535,8 @@
goto err_subsys;
}
+ scm_pas_init(MSM_BUS_MASTER_SPS);
+
ret = devm_request_irq(&pdev->dev, drv->irq, riva_wdog_bite_irq_hdlr,
IRQF_TRIGGER_RISING, "riva_wdog", drv);
if (ret < 0)
diff --git a/arch/arm/mach-msm/pil-tzapps.c b/arch/arm/mach-msm/pil-tzapps.c
index 1410117..d9f5700 100644
--- a/arch/arm/mach-msm/pil-tzapps.c
+++ b/arch/arm/mach-msm/pil-tzapps.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2013, 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
@@ -16,6 +16,7 @@
#include <linux/err.h>
#include <mach/subsystem_restart.h>
+#include <mach/msm_bus_board.h>
#include "peripheral-loader.h"
#include "scm-pas.h"
@@ -97,6 +98,9 @@
pil_desc_release(desc);
return PTR_ERR(drv->subsys);
}
+
+ scm_pas_init(MSM_BUS_MASTER_SPS);
+
return 0;
}
diff --git a/arch/arm/mach-msm/pil-venus.c b/arch/arm/mach-msm/pil-venus.c
index 4e9e54b..a7ebbf7 100644
--- a/arch/arm/mach-msm/pil-venus.c
+++ b/arch/arm/mach-msm/pil-venus.c
@@ -605,6 +605,8 @@
if (!drv->ramdump_dev)
return -ENOMEM;
+ scm_pas_init(MSM_BUS_MASTER_CRYPTO_CORE0);
+
rc = pil_desc_init(desc);
if (rc)
goto err_ramdump;
diff --git a/arch/arm/mach-msm/pil-vidc.c b/arch/arm/mach-msm/pil-vidc.c
index 629907f..3dbddae 100644
--- a/arch/arm/mach-msm/pil-vidc.c
+++ b/arch/arm/mach-msm/pil-vidc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, 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,6 +17,7 @@
#include <linux/clk.h>
#include <mach/subsystem_restart.h>
+#include <mach/msm_bus_board.h>
#include "peripheral-loader.h"
#include "scm-pas.h"
@@ -122,6 +123,9 @@
pil_desc_release(desc);
return PTR_ERR(drv->subsys);
}
+
+ scm_pas_init(MSM_BUS_MASTER_SPS);
+
return 0;
}
diff --git a/arch/arm/mach-msm/scm-pas.c b/arch/arm/mach-msm/scm-pas.c
index b244c6f..57acdc4 100644
--- a/arch/arm/mach-msm/scm-pas.c
+++ b/arch/arm/mach-msm/scm-pas.c
@@ -255,9 +255,14 @@
}
EXPORT_SYMBOL(pas_supported);
-static int __init scm_pas_init(void)
+void scm_pas_init(enum msm_bus_fabric_master_type id)
{
int i, rate;
+ static int is_inited;
+
+ if (is_inited)
+ return;
+
for (i = 0; i < NUM_CLKS; i++) {
scm_clocks[i] = clk_get_sys("scm", scm_clock_names[i]);
if (IS_ERR(scm_clocks[i]))
@@ -268,20 +273,14 @@
rate = clk_round_rate(scm_clocks[CORE_CLK_SRC], 1);
clk_set_rate(scm_clocks[CORE_CLK_SRC], rate);
- if (soc_class_is_msm8974() || cpu_is_msm8226() || cpu_is_msm8610()) {
- scm_pas_bw_tbl[0].vectors[0].src = MSM_BUS_MASTER_CRYPTO_CORE0;
- scm_pas_bw_tbl[1].vectors[0].src = MSM_BUS_MASTER_CRYPTO_CORE0;
- } else {
- if (!IS_ERR(scm_clocks[BUS_CLK]))
- clk_set_rate(scm_clocks[BUS_CLK], 64000000);
- else
- pr_warn("unable to get bus clock\n");
- }
+ scm_pas_bw_tbl[0].vectors[0].src = id;
+ scm_pas_bw_tbl[1].vectors[0].src = id;
+
+ clk_set_rate(scm_clocks[BUS_CLK], 64000000);
scm_perf_client = msm_bus_scale_register_client(&scm_pas_bus_pdata);
if (!scm_perf_client)
pr_warn("unable to register bus client\n");
- return 0;
+ is_inited = 1;
}
-module_init(scm_pas_init);
diff --git a/arch/arm/mach-msm/scm-pas.h b/arch/arm/mach-msm/scm-pas.h
index f13757c..48bc558 100644
--- a/arch/arm/mach-msm/scm-pas.h
+++ b/arch/arm/mach-msm/scm-pas.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2013, 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
@@ -9,6 +9,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
+
+#include <mach/msm_bus_board.h>
+
#ifndef __MSM_SCM_PAS_H
#define __MSM_SCM_PAS_H
@@ -31,6 +34,7 @@
extern int pas_auth_and_reset(enum pas_id id);
extern int pas_shutdown(enum pas_id id);
extern int pas_supported(enum pas_id id);
+extern void scm_pas_init(enum msm_bus_fabric_master_type id);
#else
static inline int pas_init_image(enum pas_id id, const u8 *metadata,
size_t size)
@@ -53,6 +57,9 @@
{
return 0;
}
+static inline void scm_pas_init(enum msm_bus_fabric_master_type id)
+{
+}
#endif
#endif
diff --git a/arch/arm/mach-msm/test_qmi_client.c b/arch/arm/mach-msm/test_qmi_client.c
index d070e37..b701be8 100644
--- a/arch/arm/mach-msm/test_qmi_client.c
+++ b/arch/arm/mach-msm/test_qmi_client.c
@@ -61,6 +61,25 @@
/* Variable to hold the test result */
static int test_res;
+static unsigned int callback_count;
+static void test_async_resp_cb(struct qmi_handle *handle,
+ unsigned int msg_id, void *msg,
+ void *resp_cb_data, int stat)
+{
+ callback_count++;
+ if (stat == 0)
+ D("%s invoked %d time(s): [RESP_LEN] = %d, [RESP_VALID] = %d",
+ __func__, callback_count,
+ ((struct test_data_resp_msg_v01 *)msg)->data_len,
+ ((struct test_data_resp_msg_v01 *)msg)->data_valid);
+ else if (stat < 0)
+ pr_err("%s: Request Failed [MSG_ID]: %d, [ERR_ID]: %d, [Callback_count]: %d",
+ __func__, msg_id, stat, callback_count);
+
+ kfree(msg);
+ kfree(resp_cb_data);
+}
+
static int test_qmi_ping_pong_send_sync_msg(void)
{
struct test_ping_req_msg_v01 req;
@@ -138,12 +157,68 @@
return rc;
}
+static int test_qmi_data_send_async_msg(unsigned int data_len)
+{
+ struct test_data_req_msg_v01 *req;
+ struct test_data_resp_msg_v01 *resp;
+ struct msg_desc req_desc, *resp_desc;
+ int rc, i;
+
+ req = kzalloc(sizeof(struct test_data_req_msg_v01), GFP_KERNEL);
+ if (!req) {
+ pr_err("%s: Data req msg alloc failed\n", __func__);
+ return -ENOMEM;
+ }
+
+ resp = kzalloc(sizeof(struct test_data_resp_msg_v01), GFP_KERNEL);
+ if (!resp) {
+ pr_err("%s: Data resp msg alloc failed\n", __func__);
+ kfree(req);
+ return -ENOMEM;
+ }
+
+ resp_desc = kzalloc(sizeof(struct msg_desc), GFP_KERNEL);
+ if (!resp_desc) {
+ pr_err("%s: Resp_desc msg alloc failed\n", __func__);
+ kfree(req);
+ kfree(resp);
+ return -ENOMEM;
+ }
+
+ req->data_len = data_len;
+ for (i = 0; i < data_len; i = i + sizeof(int))
+ memcpy(req->data + i, (uint8_t *)&i, sizeof(int));
+ req->client_name_valid = 0;
+
+ req_desc.max_msg_len = TEST_DATA_REQ_MAX_MSG_LEN_V01;
+ req_desc.msg_id = TEST_DATA_REQ_MSG_ID_V01;
+ req_desc.ei_array = test_data_req_msg_v01_ei;
+
+ resp_desc->max_msg_len = TEST_DATA_REQ_MAX_MSG_LEN_V01;
+ resp_desc->msg_id = TEST_DATA_REQ_MSG_ID_V01;
+ resp_desc->ei_array = test_data_resp_msg_v01_ei;
+
+ rc = qmi_send_req_nowait(test_clnt, &req_desc, req, sizeof(*req),
+ resp_desc, resp, sizeof(*resp),
+ test_async_resp_cb, (void *)resp_desc);
+ if (rc < 0) {
+ pr_err("%s: send req failed\n", __func__);
+ kfree(resp);
+ kfree(resp_desc);
+ }
+ kfree(req);
+ return rc;
+}
+
static void test_clnt_recv_msg(struct work_struct *work)
{
int rc;
- rc = qmi_recv_msg(test_clnt);
- if (rc < 0)
+ do {
+ D("%s: Notified about a Receive Event", __func__);
+ } while ((rc = qmi_recv_msg(test_clnt)) == 0);
+
+ if (rc != -ENOMSG)
pr_err("%s: Error receiving message\n", __func__);
}
@@ -280,6 +355,32 @@
} while (test_clnt_reset);
}
}
+ } else if (!strncmp(cmd, "data_async", sizeof(cmd))) {
+ int i;
+ callback_count = 0;
+ for (i = 0; i < test_rep_cnt; i++) {
+ test_res = test_qmi_data_send_async_msg(test_data_sz);
+ if (test_res == -ENETRESET || test_clnt_reset) {
+ --i;
+ do {
+ msleep(50);
+ } while (test_clnt_reset);
+ } else if (test_res < 0) {
+ --i;
+ pr_err("%s: Error sending txn, aborting now",
+ __func__);
+ break;
+ }
+ }
+ while (callback_count < i) {
+ if (test_clnt_reset) {
+ pr_err("%s: Service Exited", __func__);
+ break;
+ }
+ msleep(50);
+ }
+ D("%s complete\n", __func__);
+ callback_count = 0;
} else {
test_res = -EINVAL;
}
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index e65b5ba..c2efc34 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -360,9 +360,13 @@
PTE_SET_FN(nx, pte_mknexec)
SET_MEMORY_FN(ro, pte_set_ro)
+EXPORT_SYMBOL(set_memory_ro);
SET_MEMORY_FN(rw, pte_set_rw)
+EXPORT_SYMBOL(set_memory_rw);
SET_MEMORY_FN(x, pte_set_x)
+EXPORT_SYMBOL(set_memory_x);
SET_MEMORY_FN(nx, pte_set_nx)
+EXPORT_SYMBOL(set_memory_nx);
/*
* Adjust the PMD section entries according to the CPU in use.
diff --git a/block/blk-core.c b/block/blk-core.c
index 8e12c45..40d9b35 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -2058,10 +2058,8 @@
* not be passed by new incoming requests
*/
rq->cmd_flags |= REQ_STARTED;
- if (rq->cmd_flags & REQ_URGENT) {
- WARN_ON(q->dispatched_urgent);
+ if (rq->cmd_flags & REQ_URGENT)
q->dispatched_urgent = true;
- }
trace_block_rq_issue(q, rq);
}
@@ -3153,7 +3151,7 @@
q->rpm_status = RPM_ACTIVE;
__blk_run_queue(q);
pm_runtime_mark_last_busy(q->dev);
- pm_runtime_autosuspend(q->dev);
+ pm_request_autosuspend(q->dev);
} else {
q->rpm_status = RPM_SUSPENDED;
}
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index 32629e2..b4711cb 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -239,6 +239,9 @@
unsigned long workload_expires;
struct cfq_group *serving_group;
+ unsigned int nr_urgent_pending;
+ unsigned int nr_urgent_in_flight;
+
/*
* Each priority tree is sorted by next_request position. These
* trees are used when determining if two or more queues are
@@ -2091,6 +2094,14 @@
(RQ_CFQG(rq))->dispatched++;
elv_dispatch_sort(q, rq);
+ if (rq->cmd_flags & REQ_URGENT) {
+ if (!cfqd->nr_urgent_pending)
+ WARN_ON(1);
+ else
+ cfqd->nr_urgent_pending--;
+ cfqd->nr_urgent_in_flight++;
+ }
+
cfqd->rq_in_flight[cfq_cfqq_sync(cfqq)]++;
cfqq->nr_sectors += blk_rq_sectors(rq);
cfq_blkiocg_update_dispatch_stats(&cfqq->cfqg->blkg, blk_rq_bytes(rq),
@@ -3194,6 +3205,69 @@
}
}
+/*
+ * Called when a request (rq) is reinserted (to cfqq). Check if there's
+ * something we should do about it
+ */
+static void
+cfq_rq_requeued(struct cfq_data *cfqd, struct cfq_queue *cfqq,
+ struct request *rq)
+{
+ struct cfq_io_cq *cic = RQ_CIC(rq);
+
+ cfqd->rq_queued++;
+ if (rq->cmd_flags & REQ_PRIO)
+ cfqq->prio_pending++;
+
+ cfqq->dispatched--;
+ (RQ_CFQG(rq))->dispatched--;
+
+ cfqd->rq_in_flight[cfq_cfqq_sync(cfqq)]--;
+
+ cfq_update_io_thinktime(cfqd, cfqq, cic);
+ cfq_update_io_seektime(cfqd, cfqq, rq);
+ cfq_update_idle_window(cfqd, cfqq, cic);
+
+ cfqq->last_request_pos = blk_rq_pos(rq) + blk_rq_sectors(rq);
+
+ if (cfqq == cfqd->active_queue) {
+ if (cfq_cfqq_wait_request(cfqq)) {
+ if (blk_rq_bytes(rq) > PAGE_CACHE_SIZE ||
+ cfqd->busy_queues > 1) {
+ cfq_del_timer(cfqd, cfqq);
+ cfq_clear_cfqq_wait_request(cfqq);
+ } else {
+ cfq_blkiocg_update_idle_time_stats(
+ &cfqq->cfqg->blkg);
+ cfq_mark_cfqq_must_dispatch(cfqq);
+ }
+ }
+ } else if (cfq_should_preempt(cfqd, cfqq, rq)) {
+ cfq_preempt_queue(cfqd, cfqq);
+ }
+}
+
+static int cfq_reinsert_request(struct request_queue *q, struct request *rq)
+{
+ struct cfq_data *cfqd = q->elevator->elevator_data;
+ struct cfq_queue *cfqq = RQ_CFQQ(rq);
+
+ if (!cfqq || cfqq->cfqd != cfqd)
+ return -EIO;
+
+ cfq_log_cfqq(cfqd, cfqq, "re-insert_request");
+ list_add(&rq->queuelist, &cfqq->fifo);
+ cfq_add_rq_rb(rq);
+
+ cfq_rq_requeued(cfqd, cfqq, rq);
+ if (rq->cmd_flags & REQ_URGENT) {
+ if (cfqd->nr_urgent_in_flight)
+ cfqd->nr_urgent_in_flight--;
+ cfqd->nr_urgent_pending++;
+ }
+ return 0;
+}
+
static void cfq_insert_request(struct request_queue *q, struct request *rq)
{
struct cfq_data *cfqd = q->elevator->elevator_data;
@@ -3208,7 +3282,45 @@
cfq_blkiocg_update_io_add_stats(&(RQ_CFQG(rq))->blkg,
&cfqd->serving_group->blkg, rq_data_dir(rq),
rq_is_sync(rq));
+
cfq_rq_enqueued(cfqd, cfqq, rq);
+
+ if (rq->cmd_flags & REQ_URGENT) {
+ WARN_ON(1);
+ blk_dump_rq_flags(rq, "");
+ rq->cmd_flags &= ~REQ_URGENT;
+ }
+
+ /* Request is considered URGENT if:
+ * 1. The queue being served is of a lower IO priority then the new
+ * request
+ * OR:
+ * 2. The workload being performed is ASYNC
+ * Only READ requests may be considered as URGENT
+ */
+ if ((cfqd->active_queue &&
+ cfqq->ioprio_class < cfqd->active_queue->ioprio_class) ||
+ (cfqd->serving_type == ASYNC_WORKLOAD &&
+ rq_data_dir(rq) == READ)) {
+ rq->cmd_flags |= REQ_URGENT;
+ cfqd->nr_urgent_pending++;
+ }
+}
+
+
+/**
+ * cfq_urgent_pending() - Return TRUE if there is an urgent
+ * request on scheduler
+ * @q: requests queue
+ */
+static bool cfq_urgent_pending(struct request_queue *q)
+{
+ struct cfq_data *cfqd = q->elevator->elevator_data;
+
+ if (cfqd->nr_urgent_pending && !cfqd->nr_urgent_in_flight)
+ return true;
+
+ return false;
}
/*
@@ -3292,6 +3404,14 @@
const int sync = rq_is_sync(rq);
unsigned long now;
+ if (rq->cmd_flags & REQ_URGENT) {
+ if (!cfqd->nr_urgent_in_flight)
+ WARN_ON(1);
+ else
+ cfqd->nr_urgent_in_flight--;
+ rq->cmd_flags &= ~REQ_URGENT;
+ }
+
now = jiffies;
cfq_log_cfqq(cfqd, cfqq, "complete rqnoidle %d",
!!(rq->cmd_flags & REQ_NOIDLE));
@@ -3859,6 +3979,8 @@
.elevator_bio_merged_fn = cfq_bio_merged,
.elevator_dispatch_fn = cfq_dispatch_requests,
.elevator_add_req_fn = cfq_insert_request,
+ .elevator_reinsert_req_fn = cfq_reinsert_request,
+ .elevator_is_urgent_fn = cfq_urgent_pending,
.elevator_activate_req_fn = cfq_activate_request,
.elevator_deactivate_req_fn = cfq_deactivate_request,
.elevator_completed_req_fn = cfq_completed_request,
diff --git a/block/elevator.c b/block/elevator.c
index 44193a8..55f1f1e 100644
--- a/block/elevator.c
+++ b/block/elevator.c
@@ -842,7 +842,6 @@
if (rq->cmd_flags & REQ_URGENT) {
q->notified_urgent = false;
- WARN_ON(!q->dispatched_urgent);
q->dispatched_urgent = false;
}
/*
diff --git a/drivers/base/genlock.c b/drivers/base/genlock.c
index 0de37c9..58b0513 100644
--- a/drivers/base/genlock.c
+++ b/drivers/base/genlock.c
@@ -742,6 +742,16 @@
fd_install(ret, lock->file);
+ /*
+ * Taking a reference for lock file.
+ * This is required as now we have two file descriptor
+ * pointing to same file. If one FD is closed, lock file
+ * will be closed. Taking this reference will make sure
+ * that file doesn't get close. This refrence will go
+ * when client will call close on this FD.
+ */
+ fget(ret);
+
return ret;
}
EXPORT_SYMBOL(genlock_get_fd_handle);
diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c
index 83d94f1..7f7b4d7 100644
--- a/drivers/char/adsprpc.c
+++ b/drivers/char/adsprpc.c
@@ -395,21 +395,26 @@
static int get_args(uint32_t kernel, uint32_t sc, remote_arg_t *pra,
remote_arg_t *rpra, remote_arg_t *upra,
struct fastrpc_buf *ibuf, struct fastrpc_buf **abufs,
- int *nbufs)
+ int *nbufs, int *fds)
{
+ struct fastrpc_apps *me = &gfa;
struct smq_invoke_buf *list;
struct fastrpc_buf *pbuf = ibuf, *obufs = 0;
struct smq_phy_page *pages;
+ struct ion_handle **handles;
void *args;
int i, rlen, size, used, inh, bufs = 0, err = 0;
int inbufs = REMOTE_SCALARS_INBUFS(sc);
int outbufs = REMOTE_SCALARS_OUTBUFS(sc);
+ unsigned long iova, len;
list = smq_invoke_buf_start(rpra, sc);
pages = smq_phy_page_start(sc, list);
used = ALIGN(pbuf->used, BALIGN);
args = (void *)((char *)pbuf->virt + used);
rlen = pbuf->size - used;
+ if (fds)
+ handles = (struct ion_handle **)(fds + inbufs + outbufs);
for (i = 0; i < inbufs + outbufs; ++i) {
rpra[i].buf.len = pra[i].buf.len;
@@ -418,6 +423,22 @@
if (list[i].num) {
rpra[i].buf.pv = pra[i].buf.pv;
continue;
+ } else if (me->smmu.enabled && fds && (fds[i] >= 0)) {
+ len = buf_page_size(pra[i].buf.len);
+ handles[i] = ion_import_dma_buf(me->iclient, fds[i]);
+ VERIFY(err, 0 == IS_ERR_OR_NULL(handles[i]));
+ if (err)
+ goto bail;
+ VERIFY(err, 0 == ion_map_iommu(me->iclient, handles[i],
+ me->smmu.domain_id, 0, SZ_4K, 0,
+ &iova, &len, 0, 0));
+ if (err)
+ goto bail;
+ rpra[i].buf.pv = pra[i].buf.pv;
+ list[i].num = 1;
+ pages[list[i].pgidx].addr = iova;
+ pages[list[i].pgidx].size = len;
+ continue;
}
if (rlen < pra[i].buf.len) {
struct fastrpc_buf *b;
@@ -770,15 +791,17 @@
static int fastrpc_release_current_dsp_process(void);
static int fastrpc_internal_invoke(struct fastrpc_apps *me, uint32_t kernel,
- struct fastrpc_ioctl_invoke *invoke, remote_arg_t *pra)
+ struct fastrpc_ioctl_invoke *invoke, remote_arg_t *pra,
+ int *fds)
{
remote_arg_t *rpra = 0;
struct fastrpc_device *dev = 0;
struct smq_invoke_ctx *ctx = 0;
struct fastrpc_buf obuf, *abufs = 0, *b;
+ struct ion_handle **handles;
int interrupted = 0;
uint32_t sc;
- int i, nbufs = 0, err = 0;
+ int i, bufs, nbufs = 0, err = 0;
sc = invoke->sc;
obuf.handle = 0;
@@ -798,7 +821,7 @@
goto bail;
rpra = (remote_arg_t *)obuf.virt;
VERIFY(err, 0 == get_args(kernel, sc, pra, rpra, invoke->pra,
- &obuf, &abufs, &nbufs));
+ &obuf, &abufs, &nbufs, fds));
if (err)
goto bail;
}
@@ -828,8 +851,19 @@
}
context_free(ctx);
- if (me->smmu.enabled)
+ if (me->smmu.enabled) {
+ bufs = REMOTE_SCALARS_LENGTH(sc);
+ if (fds) {
+ handles = (struct ion_handle **)(fds + bufs);
+ for (i = 0; i < bufs; i++)
+ if (!IS_ERR_OR_NULL(handles[i])) {
+ ion_unmap_iommu(me->iclient, handles[i],
+ me->smmu.domain_id, 0);
+ ion_free(me->iclient, handles[i]);
+ }
+ }
iommu_detach_group(me->smmu.domain, me->smmu.group);
+ }
for (i = 0, b = abufs; i < nbufs; ++i, ++b)
free_mem(b);
@@ -856,7 +890,7 @@
ioctl.handle = 1;
ioctl.sc = REMOTE_SCALARS_MAKE(0, 1, 0);
ioctl.pra = ra;
- VERIFY(err, 0 == (err = fastrpc_internal_invoke(me, 1, &ioctl, ra)));
+ VERIFY(err, 0 == (err = fastrpc_internal_invoke(me, 1, &ioctl, ra, 0)));
return err;
}
@@ -874,7 +908,7 @@
ioctl.handle = 1;
ioctl.sc = REMOTE_SCALARS_MAKE(1, 1, 0);
ioctl.pra = ra;
- VERIFY(err, 0 == (err = fastrpc_internal_invoke(me, 1, &ioctl, ra)));
+ VERIFY(err, 0 == (err = fastrpc_internal_invoke(me, 1, &ioctl, ra, 0)));
return err;
}
@@ -912,7 +946,7 @@
ioctl.handle = 1;
ioctl.sc = REMOTE_SCALARS_MAKE(2, 2, 1);
ioctl.pra = ra;
- VERIFY(err, 0 == (err = fastrpc_internal_invoke(me, 1, &ioctl, ra)));
+ VERIFY(err, 0 == (err = fastrpc_internal_invoke(me, 1, &ioctl, ra, 0)));
mmap->vaddrout = routargs.vaddrout;
if (err)
goto bail;
@@ -941,7 +975,7 @@
ioctl.handle = 1;
ioctl.sc = REMOTE_SCALARS_MAKE(3, 1, 0);
ioctl.pra = ra;
- VERIFY(err, 0 == (err = fastrpc_internal_invoke(me, 1, &ioctl, ra)));
+ VERIFY(err, 0 == (err = fastrpc_internal_invoke(me, 1, &ioctl, ra, 0)));
return err;
}
@@ -1107,33 +1141,49 @@
unsigned long ioctl_param)
{
struct fastrpc_apps *me = &gfa;
- struct fastrpc_ioctl_invoke invoke;
+ struct fastrpc_ioctl_invoke_fd invokefd;
+ struct fastrpc_ioctl_invoke *invoke = &invokefd.inv;
struct fastrpc_ioctl_mmap mmap;
struct fastrpc_ioctl_munmap munmap;
remote_arg_t *pra = 0;
void *param = (char *)ioctl_param;
struct file_data *fdata = (struct file_data *)file->private_data;
- int bufs, err = 0;
+ int *fds = 0;
+ int bufs, size = 0, err = 0;
switch (ioctl_num) {
+ case FASTRPC_IOCTL_INVOKE_FD:
case FASTRPC_IOCTL_INVOKE:
- VERIFY(err, 0 == copy_from_user(&invoke, param,
- sizeof(invoke)));
+ invokefd.fds = 0;
+ size = (ioctl_num == FASTRPC_IOCTL_INVOKE) ?
+ sizeof(*invoke) : sizeof(invokefd);
+ VERIFY(err, 0 == copy_from_user(&invokefd, param, size));
if (err)
goto bail;
- bufs = REMOTE_SCALARS_INBUFS(invoke.sc) +
- REMOTE_SCALARS_OUTBUFS(invoke.sc);
+ bufs = REMOTE_SCALARS_INBUFS(invoke->sc) +
+ REMOTE_SCALARS_OUTBUFS(invoke->sc);
if (bufs) {
- bufs = bufs * sizeof(*pra);
- VERIFY(err, 0 != (pra = kmalloc(bufs, GFP_KERNEL)));
+ size = bufs * sizeof(*pra);
+ if (invokefd.fds)
+ size = size + bufs * sizeof(*fds) +
+ bufs * sizeof(struct ion_handle *);
+ VERIFY(err, 0 != (pra = kzalloc(size, GFP_KERNEL)));
if (err)
goto bail;
}
- VERIFY(err, 0 == copy_from_user(pra, invoke.pra, bufs));
+ VERIFY(err, 0 == copy_from_user(pra, invoke->pra,
+ bufs * sizeof(*pra)));
if (err)
goto bail;
- VERIFY(err, 0 == (err = fastrpc_internal_invoke(me, 0, &invoke,
- pra)));
+ if (invokefd.fds) {
+ fds = (int *)(pra + bufs);
+ VERIFY(err, 0 == copy_from_user(fds, invokefd.fds,
+ bufs * sizeof(*fds)));
+ if (err)
+ goto bail;
+ }
+ VERIFY(err, 0 == (err = fastrpc_internal_invoke(me, 0, invoke,
+ pra, fds)));
if (err)
goto bail;
break;
diff --git a/drivers/char/adsprpc_shared.h b/drivers/char/adsprpc_shared.h
index f2804ad..da70eb5 100644
--- a/drivers/char/adsprpc_shared.h
+++ b/drivers/char/adsprpc_shared.h
@@ -19,6 +19,7 @@
#define FASTRPC_IOCTL_INVOKE _IOWR('R', 1, struct fastrpc_ioctl_invoke)
#define FASTRPC_IOCTL_MMAP _IOWR('R', 2, struct fastrpc_ioctl_mmap)
#define FASTRPC_IOCTL_MUNMAP _IOWR('R', 3, struct fastrpc_ioctl_munmap)
+#define FASTRPC_IOCTL_INVOKE_FD _IOWR('R', 4, struct fastrpc_ioctl_invoke_fd)
#define FASTRPC_SMD_GUID "fastrpcsmd-apps-dsp"
#define DEVICE_NAME "adsprpc-smd"
@@ -94,6 +95,11 @@
remote_arg_t *pra; /* remote arguments list */
};
+struct fastrpc_ioctl_invoke_fd {
+ struct fastrpc_ioctl_invoke inv;
+ int *fds; /* fd list */
+};
+
struct fastrpc_ioctl_munmap {
uint32_t vaddrout; /* address to unmap */
int size; /* size */
diff --git a/drivers/char/diag/diag_dci.c b/drivers/char/diag/diag_dci.c
index d01496e..0c67ed8 100644
--- a/drivers/char/diag/diag_dci.c
+++ b/drivers/char/diag/diag_dci.c
@@ -20,6 +20,8 @@
#include <linux/workqueue.h>
#include <linux/pm_runtime.h>
#include <linux/platform_device.h>
+#include <linux/pm_wakeup.h>
+#include <linux/spinlock.h>
#include <asm/current.h>
#ifdef CONFIG_DIAG_OVER_USB
#include <mach/usbdiag.h>
@@ -39,6 +41,12 @@
struct mutex dci_event_mask_mutex;
struct mutex dci_health_mutex;
+spinlock_t ws_lock;
+unsigned long ws_lock_flags;
+
+/* Number of milliseconds anticipated to process the DCI data */
+#define DCI_WAKEUP_TIMEOUT 1
+
#define DCI_CHK_CAPACITY(entry, new_data_len) \
((entry->data_len + new_data_len > entry->total_capacity) ? 1 : 0) \
@@ -96,6 +104,11 @@
read_bytes += 5 + dci_pkt_len;
buf += 5 + dci_pkt_len; /* advance to next DCI pkt */
}
+ /* Release wakeup source when there are no more clients to
+ process DCI data */
+ if (driver->num_dci_client == 0)
+ diag_dci_try_deactivate_wakeup_source(smd_info->ch);
+
/* wake up all sleeping DCI clients which have some data */
for (i = 0; i < MAX_DCI_CLIENTS; i++) {
if (driver->dci_client_tbl[i].client &&
@@ -1101,6 +1114,9 @@
diag_smd_notify);
driver->smd_dci[index].ch_save =
driver->smd_dci[index].ch;
+ driver->dci_device = &pdev->dev;
+ driver->dci_device->power.wakeup = wakeup_source_register
+ ("DIAG_DCI_WS");
if (err)
pr_err("diag: In %s, cannot open DCI port, Id = %d, err: %d\n",
__func__, pdev->id, err);
@@ -1123,6 +1139,9 @@
diag_smd_notify);
driver->smd_dci_cmd[index].ch_save =
driver->smd_dci_cmd[index].ch;
+ driver->dci_cmd_device = &pdev->dev;
+ driver->dci_cmd_device->power.wakeup = wakeup_source_register
+ ("DIAG_DCI_CMD_WS");
if (err)
pr_err("diag: In %s, cannot open DCI port, Id = %d, err: %d\n",
__func__, pdev->id, err);
@@ -1174,10 +1193,13 @@
driver->dci_tag = 0;
driver->dci_client_id = 0;
driver->num_dci_client = 0;
+ driver->dci_device = NULL;
+ driver->dci_cmd_device = NULL;
mutex_init(&driver->dci_mutex);
mutex_init(&dci_log_mask_mutex);
mutex_init(&dci_event_mask_mutex);
mutex_init(&dci_health_mutex);
+ spin_lock_init(&ws_lock);
for (i = 0; i < NUM_SMD_DCI_CHANNELS; i++) {
success = diag_smd_constructor(&driver->smd_dci[i], i,
@@ -1408,3 +1430,26 @@
driver->dci_client_tbl[i].real_time = real_time;
return i;
}
+
+void diag_dci_try_activate_wakeup_source(smd_channel_t *channel)
+{
+ spin_lock_irqsave(&ws_lock, ws_lock_flags);
+ if (channel == driver->smd_dci[MODEM_DATA].ch) {
+ pm_wakeup_event(driver->dci_device, DCI_WAKEUP_TIMEOUT);
+ pm_stay_awake(driver->dci_device);
+ } else if (channel == driver->smd_dci_cmd[MODEM_DATA].ch) {
+ pm_wakeup_event(driver->dci_cmd_device, DCI_WAKEUP_TIMEOUT);
+ pm_stay_awake(driver->dci_cmd_device);
+ }
+ spin_unlock_irqrestore(&ws_lock, ws_lock_flags);
+}
+
+void diag_dci_try_deactivate_wakeup_source(smd_channel_t *channel)
+{
+ spin_lock_irqsave(&ws_lock, ws_lock_flags);
+ if (channel == driver->smd_dci[MODEM_DATA].ch)
+ pm_relax(driver->dci_device);
+ else if (channel == driver->smd_dci_cmd[MODEM_DATA].ch)
+ pm_relax(driver->dci_cmd_device);
+ spin_unlock_irqrestore(&ws_lock, ws_lock_flags);
+}
diff --git a/drivers/char/diag/diag_dci.h b/drivers/char/diag/diag_dci.h
index 2335d37..520995b 100644
--- a/drivers/char/diag/diag_dci.h
+++ b/drivers/char/diag/diag_dci.h
@@ -138,4 +138,7 @@
void diag_dci_smd_record_info(int read_bytes);
uint8_t diag_dci_get_cumulative_real_time(void);
int diag_dci_set_real_time(int client_id, uint8_t real_time);
+/* Functions related to DCI wakeup sources */
+void diag_dci_try_activate_wakeup_source(smd_channel_t *channel);
+void diag_dci_try_deactivate_wakeup_source(smd_channel_t *channel);
#endif
diff --git a/drivers/char/diag/diag_debugfs.c b/drivers/char/diag/diag_debugfs.c
index 0badda6..3d1a6cd 100644
--- a/drivers/char/diag/diag_debugfs.c
+++ b/drivers/char/diag/diag_debugfs.c
@@ -176,6 +176,26 @@
bytes_in_buf += bytes_written;
bytes_remaining -= bytes_written;
#endif
+ if (driver->dci_device) {
+ bytes_written = scnprintf(buf+bytes_in_buf,
+ bytes_remaining,
+ "dci power active, relax: %lu, %lu\n",
+ driver->dci_device->power.wakeup->active_count,
+ driver->dci_device->power.wakeup->relax_count);
+ bytes_in_buf += bytes_written;
+ bytes_remaining -= bytes_written;
+ }
+ if (driver->dci_cmd_device) {
+ bytes_written = scnprintf(buf+bytes_in_buf,
+ bytes_remaining,
+ "dci cmd power active, relax: %lu, %lu\n",
+ driver->dci_cmd_device->power.wakeup->
+ active_count,
+ driver->dci_cmd_device->power.wakeup->
+ relax_count);
+ bytes_in_buf += bytes_written;
+ bytes_remaining -= bytes_written;
+ }
}
temp_data += diag_dbgfs_dci_data_index;
for (i = diag_dbgfs_dci_data_index; i < DIAG_DCI_DEBUG_CNT; i++) {
diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h
index b7784b5..3ae56c5 100644
--- a/drivers/char/diag/diagchar.h
+++ b/drivers/char/diag/diagchar.h
@@ -333,6 +333,8 @@
unsigned hdlc_count;
unsigned hdlc_escape;
int in_busy_pktdata;
+ struct device *dci_device;
+ struct device *dci_cmd_device;
/* Variables for non real time mode */
int real_time_mode;
int real_time_update_busy;
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index 7513c7b..5e06f19 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -306,9 +306,10 @@
mutex_lock(&driver->diagchar_mutex);
driver->ref_count--;
- /* On Client exit, try to destroy all 3 pools */
+ /* On Client exit, try to destroy all 4 pools */
diagmem_exit(driver, POOL_TYPE_COPY);
diagmem_exit(driver, POOL_TYPE_HDLC);
+ diagmem_exit(driver, POOL_TYPE_USER);
diagmem_exit(driver, POOL_TYPE_WRITE_STRUCT);
for (i = 0; i < driver->num_clients; i++) {
if (NULL != diagpriv_data && diagpriv_data->pid ==
@@ -1452,19 +1453,25 @@
driver->data_ready[index] ^= DCI_DATA_TYPE;
for (i = 0; i < NUM_SMD_DCI_CHANNELS; i++) {
driver->smd_dci[i].in_busy_1 = 0;
- if (driver->smd_dci[i].ch)
+ if (driver->smd_dci[i].ch) {
+ diag_dci_try_deactivate_wakeup_source(
+ driver->smd_dci[i].ch);
queue_work(driver->diag_dci_wq,
&(driver->smd_dci[i].diag_read_smd_work));
+ }
}
if (driver->supports_separate_cmdrsp) {
for (i = 0; i < NUM_SMD_DCI_CMD_CHANNELS; i++) {
if (!driver->separate_cmdrsp[i])
continue;
driver->smd_dci_cmd[i].in_busy_1 = 0;
- if (driver->smd_dci_cmd[i].ch)
+ if (driver->smd_dci_cmd[i].ch) {
+ diag_dci_try_deactivate_wakeup_source(
+ driver->smd_dci_cmd[i].ch);
queue_work(driver->diag_dci_wq,
&(driver->smd_dci_cmd[i].
diag_read_smd_work));
+ }
}
}
goto exit;
@@ -1527,11 +1534,14 @@
err = copy_from_user(user_space_data, buf + 4, payload_size);
if (err) {
pr_alert("diag: copy failed for DCI data\n");
+ diagmem_free(driver, user_space_data, POOL_TYPE_USER);
+ user_space_data = NULL;
return DIAG_DCI_SEND_DATA_FAIL;
}
err = diag_process_dci_transaction(user_space_data,
payload_size);
diagmem_free(driver, user_space_data, POOL_TYPE_USER);
+ user_space_data = NULL;
return err;
}
if (pkt_type == CALLBACK_DATA_TYPE) {
@@ -1542,16 +1552,19 @@
return -EBADMSG;
}
+ mutex_lock(&driver->diagchar_mutex);
buf_copy = diagmem_alloc(driver, payload_size, POOL_TYPE_COPY);
if (!buf_copy) {
driver->dropped_count++;
+ mutex_unlock(&driver->diagchar_mutex);
return -ENOMEM;
}
err = copy_from_user(buf_copy, buf + 4, payload_size);
if (err) {
pr_err("diag: copy failed for user space data\n");
- return -EIO;
+ ret = -EIO;
+ goto fail_free_copy;
}
/* Check for proc_type */
remote_proc = diag_get_remote(*(int *)buf_copy);
@@ -1560,8 +1573,7 @@
wait_event_interruptible(driver->wait_q,
(driver->in_busy_pktdata == 0));
ret = diag_process_apps_pkt(buf_copy, payload_size);
- diagmem_free(driver, buf_copy, POOL_TYPE_COPY);
- return ret;
+ goto fail_free_copy;
}
/* The packet is for the remote processor */
token_offset = 4;
@@ -1574,20 +1586,20 @@
1 + payload_size);
send.terminate = 1;
- mutex_lock(&driver->diagchar_mutex);
+
if (!buf_hdlc)
buf_hdlc = diagmem_alloc(driver, HDLC_OUT_BUF_SIZE,
POOL_TYPE_HDLC);
if (!buf_hdlc) {
ret = -ENOMEM;
- goto fail_free_hdlc;
+ driver->used = 0;
+ goto fail_free_copy;
}
if (HDLC_OUT_BUF_SIZE < (2 * payload_size) + 3) {
pr_err("diag: Dropping packet, HDLC encoded packet payload size crosses buffer limit. Current payload size %d\n",
((2*payload_size) + 3));
driver->dropped_count++;
ret = -EBADMSG;
- diagmem_free(driver, buf_hdlc, POOL_TYPE_HDLC);
goto fail_free_hdlc;
}
enc.dest = buf_hdlc + driver->used;
@@ -1652,13 +1664,7 @@
}
}
#endif
- diagmem_free(driver, buf_copy, POOL_TYPE_COPY);
- diagmem_free(driver, buf_hdlc, POOL_TYPE_HDLC);
- buf_copy = NULL;
- buf_hdlc = NULL;
- driver->used = 0;
- mutex_unlock(&driver->diagchar_mutex);
- return ret;
+ goto fail_free_hdlc;
}
if (pkt_type == USER_SPACE_DATA_TYPE) {
user_space_data = diagmem_alloc(driver, payload_size,
@@ -1672,6 +1678,7 @@
if (err) {
pr_err("diag: copy failed for user space data\n");
diagmem_free(driver, user_space_data, POOL_TYPE_USER);
+ user_space_data = NULL;
return -EIO;
}
/* Check for proc_type */
@@ -1690,6 +1697,7 @@
pr_alert("diag: mask request Invalid\n");
diagmem_free(driver, user_space_data,
POOL_TYPE_USER);
+ user_space_data = NULL;
return -EFAULT;
}
}
@@ -1767,6 +1775,7 @@
err);
diagmem_free(driver, user_space_data,
POOL_TYPE_USER);
+ user_space_data = NULL;
return err;
}
}
@@ -1777,6 +1786,7 @@
diag_process_hdlc((void *)
(user_space_data + token_offset), payload_size);
diagmem_free(driver, user_space_data, POOL_TYPE_USER);
+ user_space_data = NULL;
return 0;
}
@@ -1788,9 +1798,11 @@
return -EBADMSG;
}
+ mutex_lock(&driver->diagchar_mutex);
buf_copy = diagmem_alloc(driver, payload_size, POOL_TYPE_COPY);
if (!buf_copy) {
driver->dropped_count++;
+ mutex_unlock(&driver->diagchar_mutex);
return -ENOMEM;
}
@@ -1834,13 +1846,13 @@
length++;
}
#endif
- mutex_lock(&driver->diagchar_mutex);
if (!buf_hdlc)
buf_hdlc = diagmem_alloc(driver, HDLC_OUT_BUF_SIZE,
POOL_TYPE_HDLC);
if (!buf_hdlc) {
ret = -ENOMEM;
- goto fail_free_hdlc;
+ driver->used = 0;
+ goto fail_free_copy;
}
if (HDLC_OUT_BUF_SIZE < (2*payload_size) + 3) {
pr_err("diag: Dropping packet, HDLC encoded packet payload size crosses buffer limit. Current payload size %d\n",
@@ -1853,7 +1865,6 @@
err = diag_device_write(buf_hdlc, APPS_DATA, NULL);
if (err) {
/*Free the buffer right away if write failed */
- diagmem_free(driver, buf_hdlc, POOL_TYPE_HDLC);
if (driver->logging_mode == USB_MODE)
diagmem_free(driver, (unsigned char *)driver->
write_ptr_svc, POOL_TYPE_WRITE_STRUCT);
@@ -1866,7 +1877,7 @@
POOL_TYPE_HDLC);
if (!buf_hdlc) {
ret = -ENOMEM;
- goto fail_free_hdlc;
+ goto fail_free_copy;
}
}
@@ -1882,7 +1893,6 @@
err = diag_device_write(buf_hdlc, APPS_DATA, NULL);
if (err) {
/*Free the buffer right away if write failed */
- diagmem_free(driver, buf_hdlc, POOL_TYPE_HDLC);
if (driver->logging_mode == USB_MODE)
diagmem_free(driver, (unsigned char *)driver->
write_ptr_svc, POOL_TYPE_WRITE_STRUCT);
@@ -1895,7 +1905,7 @@
POOL_TYPE_HDLC);
if (!buf_hdlc) {
ret = -ENOMEM;
- goto fail_free_hdlc;
+ goto fail_free_copy;
}
enc.dest = buf_hdlc + driver->used;
enc.dest_last = (void *)(buf_hdlc + driver->used +
@@ -1908,7 +1918,6 @@
err = diag_device_write(buf_hdlc, APPS_DATA, NULL);
if (err) {
/*Free the buffer right away if write failed */
- diagmem_free(driver, buf_hdlc, POOL_TYPE_HDLC);
if (driver->logging_mode == USB_MODE)
diagmem_free(driver, (unsigned char *)driver->
write_ptr_svc, POOL_TYPE_WRITE_STRUCT);
@@ -1920,6 +1929,7 @@
}
diagmem_free(driver, buf_copy, POOL_TYPE_COPY);
+ buf_copy = NULL;
mutex_unlock(&driver->diagchar_mutex);
if (!timer_in_progress) {
timer_in_progress = 1;
@@ -1928,14 +1938,18 @@
return 0;
fail_free_hdlc:
+ diagmem_free(driver, buf_hdlc, POOL_TYPE_HDLC);
buf_hdlc = NULL;
driver->used = 0;
diagmem_free(driver, buf_copy, POOL_TYPE_COPY);
+ buf_copy = NULL;
mutex_unlock(&driver->diagchar_mutex);
return ret;
fail_free_copy:
diagmem_free(driver, buf_copy, POOL_TYPE_COPY);
+ buf_copy = NULL;
+ mutex_unlock(&driver->diagchar_mutex);
return ret;
}
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index 6e7080e..de4433b 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -390,10 +390,18 @@
(smd_info->type == SMD_DATA_TYPE))
buf = smd_info->buf_in_2;
+ if (!buf && (smd_info->type == SMD_DCI_TYPE ||
+ smd_info->type == SMD_DCI_CMD_TYPE))
+ diag_dci_try_deactivate_wakeup_source(smd_info->ch);
+
if (smd_info->ch && buf) {
temp_buf = buf;
pkt_len = smd_cur_packet_size(smd_info->ch);
+ if (pkt_len == 0 && (smd_info->type == SMD_DCI_TYPE ||
+ smd_info->type == SMD_DCI_CMD_TYPE))
+ diag_dci_try_deactivate_wakeup_source(smd_info->ch);
+
while (pkt_len && (pkt_len != total_recd)) {
loop_count++;
r = smd_read_avail(smd_info->ch);
@@ -412,7 +420,7 @@
} else {
pr_debug("diag: In %s, return from wait_event ch closed\n",
__func__);
- return;
+ goto fail_return;
}
}
total_recd += r;
@@ -425,13 +433,13 @@
} else {
pr_err("diag: In %s, SMD sending in packets more than %d bytes\n",
__func__, MAX_IN_BUF_SIZE);
- return;
+ goto fail_return;
}
}
if (pkt_len < r) {
pr_err("diag: In %s, SMD sending incorrect pkt\n",
__func__);
- return;
+ goto fail_return;
}
if (pkt_len > r) {
pr_debug("diag: In %s, SMD sending partial pkt %d %d %d %d %d %d\n",
@@ -462,6 +470,13 @@
(driver->logging_mode == MEMORY_DEVICE_MODE)) {
chk_logging_wakeup();
}
+ return;
+
+fail_return:
+ if (smd_info->type == SMD_DCI_TYPE ||
+ smd_info->type == SMD_DCI_CMD_TYPE)
+ diag_dci_try_deactivate_wakeup_source(smd_info->ch);
+ return;
}
void diag_read_smd_work_fn(struct work_struct *work)
@@ -1705,10 +1720,12 @@
wake_up(&driver->smd_wait_q);
if (smd_info->type == SMD_DCI_TYPE ||
- smd_info->type == SMD_DCI_CMD_TYPE)
+ smd_info->type == SMD_DCI_CMD_TYPE) {
+ if (event == SMD_EVENT_DATA)
+ diag_dci_try_activate_wakeup_source(smd_info->ch);
queue_work(driver->diag_dci_wq,
&(smd_info->diag_read_smd_work));
- else
+ } else
queue_work(driver->diag_wq, &(smd_info->diag_read_smd_work));
}
diff --git a/drivers/crypto/msm/qcedev.c b/drivers/crypto/msm/qcedev.c
index d069f2e..0e4b309 100644
--- a/drivers/crypto/msm/qcedev.c
+++ b/drivers/crypto/msm/qcedev.c
@@ -1937,7 +1937,7 @@
rc = misc_register(&podev->miscdevice);
qce_hw_support(podev->qce, &podev->ce_support);
if (podev->ce_support.bam) {
- podev->platform_support.ce_shared = podev->ce_support.is_shared;
+ podev->platform_support.ce_shared = 0;
podev->platform_support.shared_ce_resource = 0;
podev->platform_support.hw_key_support =
podev->ce_support.hw_key;
diff --git a/drivers/gpio/qpnp-pin.c b/drivers/gpio/qpnp-pin.c
index 64341e9..ed001f0 100644
--- a/drivers/gpio/qpnp-pin.c
+++ b/drivers/gpio/qpnp-pin.c
@@ -589,6 +589,9 @@
}
mutex_unlock(&qpnp_pin_chips_lock);
+ if (!q_spec)
+ return -ENODEV;
+
rc = _qpnp_pin_config(q_chip, q_spec, param);
return rc;
@@ -1225,6 +1228,8 @@
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;
+ goto err_probe;
}
rc = of_property_read_u32(d_node->of_node,
diff --git a/drivers/gpu/ion/msm/msm_ion.c b/drivers/gpu/ion/msm/msm_ion.c
index f990ada..118c39a 100644
--- a/drivers/gpu/ion/msm/msm_ion.c
+++ b/drivers/gpu/ion/msm/msm_ion.c
@@ -264,6 +264,9 @@
}
}
+ if (!outer_cache_op)
+ return -EINVAL;
+
outer_cache_op(buff_phys_start + offset,
buff_phys_start + offset + length);
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index afb11c2..32a667f 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -109,6 +109,10 @@
.pm4_fw = NULL,
.wait_timeout = 0, /* in milliseconds, 0 means disabled */
.ib_check_level = 0,
+ .ft_policy = KGSL_FT_DEFAULT_POLICY,
+ .ft_pf_policy = KGSL_FT_PAGEFAULT_DEFAULT_POLICY,
+ .fast_hang_detect = 1,
+ .long_ib_detect = 1,
};
/* This set of registers are used for Hang detection
@@ -211,6 +215,8 @@
512, 0, 2, SZ_128K, 0x3FF037, 0x3FF016 },
};
+static unsigned int adreno_isidle(struct kgsl_device *device);
+
/**
* adreno_perfcounter_init: Reserve kernel performance counters
* @device: device to configure
@@ -818,6 +824,27 @@
return cmds - cmds_orig;
}
+/**
+ * adreno_use_default_setstate() - Use CPU instead of the GPU to manage the mmu?
+ * @adreno_dev: the device
+ *
+ * In many cases it is preferable to poke the iommu or gpummu directly rather
+ * than using the GPU command stream. If we are idle or trying to go to a low
+ * power state, using the command stream will be slower and asynchronous, which
+ * needlessly complicates the power state transitions. Additionally,
+ * the hardware simulators do not support command stream MMU operations so
+ * the command stream can never be used if we are capturing CFF data.
+ *
+ */
+static bool adreno_use_default_setstate(struct adreno_device *adreno_dev)
+{
+ return (adreno_isidle(&adreno_dev->dev) ||
+ adreno_dev->drawctxt_active == NULL ||
+ KGSL_STATE_ACTIVE != adreno_dev->dev.state ||
+ atomic_read(&adreno_dev->dev.active_cnt) == 0 ||
+ adreno_dev->dev.cff_dump_enable);
+}
+
static void adreno_iommu_setstate(struct kgsl_device *device,
unsigned int context_id,
uint32_t flags)
@@ -832,10 +859,7 @@
struct adreno_context *adreno_ctx = NULL;
struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
- if (!adreno_dev->drawctxt_active ||
- KGSL_STATE_ACTIVE != device->state ||
- !atomic_read(&device->active_cnt) ||
- device->cff_dump_enable) {
+ if (adreno_use_default_setstate(adreno_dev)) {
kgsl_mmu_device_setstate(&device->mmu, flags);
return;
}
@@ -845,7 +869,7 @@
if (context == NULL)
return;
- adreno_ctx = context->devctxt;
+ adreno_ctx = ADRENO_CONTEXT(context);
if (kgsl_mmu_enable_clk(&device->mmu,
KGSL_IOMMU_CONTEXT_USER))
@@ -886,8 +910,7 @@
adreno_ringbuffer_issuecmds(device, adreno_ctx, KGSL_CMD_FLAGS_PMODE,
&link[0], sizedwords);
- kgsl_mmu_disable_clk_on_ts(&device->mmu,
- rb->timestamp[KGSL_MEMSTORE_GLOBAL], true);
+ kgsl_mmu_disable_clk_on_ts(&device->mmu, rb->global_ts, true);
kgsl_context_put(context);
}
@@ -915,11 +938,11 @@
* writes For CFF dump we must idle and use the registers so that it is
* easier to filter out the mmu accesses from the dump
*/
- if (!device->cff_dump_enable && adreno_dev->drawctxt_active) {
+ if (!adreno_use_default_setstate(adreno_dev)) {
context = kgsl_context_get(device, context_id);
if (context == NULL)
return;
- adreno_ctx = context->devctxt;
+ adreno_ctx = ADRENO_CONTEXT(context);
if (flags & KGSL_MMUFLAGS_PTUPDATE) {
/* wait for graphics pipe to be idle */
@@ -1663,6 +1686,8 @@
adreno_debugfs_init(device);
+ adreno_ft_init_sysfs(device);
+
kgsl_pwrscale_init(device);
kgsl_pwrscale_attach_policy(device, ADRENO_DEFAULT_PWRSCALE_POLICY);
@@ -1703,7 +1728,6 @@
static int adreno_init(struct kgsl_device *device)
{
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
- struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
int i;
if (KGSL_STATE_DUMP_AND_FT != device->state)
@@ -1744,8 +1768,6 @@
adreno_gpulist[adreno_dev->gpulist_index].sync_lock_pfp_ver))
device->mmu.flags |= KGSL_MMU_FLAGS_IOMMU_SYNC;
- rb->timestamp[KGSL_MEMSTORE_GLOBAL] = 0;
-
/* Initialize ft detection register offsets */
ft_detect_regs[0] = adreno_getreg(adreno_dev,
ADRENO_REG_RBBM_STATUS);
@@ -1775,12 +1797,17 @@
int status = -EINVAL;
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
unsigned int state = device->state;
+ unsigned int regulator_left_on = 0;
kgsl_cffdump_open(device);
if (KGSL_STATE_DUMP_AND_FT != device->state)
kgsl_pwrctrl_set_state(device, KGSL_STATE_INIT);
+ regulator_left_on = (regulator_is_enabled(device->pwrctrl.gpu_reg) ||
+ (device->pwrctrl.gpu_cx &&
+ regulator_is_enabled(device->pwrctrl.gpu_cx)));
+
/* Power up the device */
kgsl_pwrctrl_enable(device);
@@ -1808,6 +1835,14 @@
goto error_mmu_off;
}
+ if (regulator_left_on && adreno_dev->gpudev->soft_reset) {
+ /*
+ * Reset the GPU for A3xx. A2xx does a soft reset in
+ * the start function.
+ */
+ adreno_dev->gpudev->soft_reset(adreno_dev);
+ }
+
/* Start the GPU */
adreno_dev->gpudev->start(adreno_dev);
@@ -1847,6 +1882,9 @@
{
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
+ if (adreno_dev->drawctxt_active)
+ kgsl_context_put(&adreno_dev->drawctxt_active->base);
+
adreno_dev->drawctxt_active = NULL;
adreno_ringbuffer_stop(&adreno_dev->ringbuffer);
@@ -1879,7 +1917,7 @@
{
unsigned int ft_status = *((unsigned int *) data);
struct kgsl_context *context = ptr;
- struct adreno_context *adreno_context = context->devctxt;
+ struct adreno_context *adreno_context = ADRENO_CONTEXT(context);
if (ft_status) {
context->reset_status =
@@ -1917,20 +1955,16 @@
static int _set_max_ts(int id, void *ptr, void *data)
{
struct kgsl_device *device = data;
- struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
- struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
struct kgsl_context *context = ptr;
- struct adreno_context *drawctxt = context->devctxt;
+ struct adreno_context *drawctxt = ADRENO_CONTEXT(context);
- if (drawctxt->flags & CTXT_FLAGS_GPU_HANG) {
+ if (drawctxt && drawctxt->flags & CTXT_FLAGS_GPU_HANG) {
kgsl_sharedmem_writel(device, &device->memstore,
KGSL_MEMSTORE_OFFSET(context->id,
- soptimestamp),
- rb->timestamp[context->id]);
+ soptimestamp), drawctxt->timestamp);
kgsl_sharedmem_writel(device, &device->memstore,
KGSL_MEMSTORE_OFFSET(context->id,
- eoptimestamp),
- rb->timestamp[context->id]);
+ eoptimestamp), drawctxt->timestamp);
}
return 0;
@@ -2186,7 +2220,7 @@
}
if (context) {
- adreno_context = context->devctxt;
+ adreno_context = ADRENO_CONTEXT(context);
if (adreno_context->flags & CTXT_FLAGS_PREAMBLE) {
if (ft_data->ib1) {
ret = _find_hanging_ib_sequence(rb,
@@ -2253,6 +2287,9 @@
return -EINVAL;
}
+ if (adreno_dev->drawctxt_active)
+ kgsl_context_put(&adreno_dev->drawctxt_active->base);
+
adreno_dev->drawctxt_active = NULL;
/* Stop the ringbuffer */
@@ -2315,11 +2352,9 @@
}
reset_done:
- if (context) {
- struct adreno_context *adreno_context = context->devctxt;
- kgsl_mmu_setstate(&device->mmu, adreno_context->pagetable,
- KGSL_MEMSTORE_GLOBAL);
- }
+ if (context)
+ kgsl_mmu_setstate(&device->mmu, context->pagetable,
+ KGSL_MEMSTORE_GLOBAL);
/* If iommu is used then we need to make sure that the iommu clocks
* are on since there could be commands in pipeline that touch iommu */
@@ -2438,7 +2473,7 @@
}
} else {
no_context_ft = 0;
- adreno_context = context->devctxt;
+ adreno_context = ADRENO_CONTEXT(context);
adreno_context->flags |= CTXT_FLAGS_GPU_HANG;
/*
* set the invalid ts flag to 0 for this context since we have
@@ -2494,16 +2529,16 @@
goto play_good_cmds;
}
- /* Do not try the reply if hang is due to a pagefault */
- if (adreno_context && adreno_context->pagefault) {
+ /* Do not try to replay if hang is due to a pagefault */
+ if (context && test_bit(KGSL_CONTEXT_PAGEFAULT, &context->priv)) {
/* Resume MMU */
mmu->mmu_ops->mmu_pagefault_resume(mmu);
- if ((ft_data->context_id == adreno_context->id) &&
- (ft_data->global_eop == adreno_context->pagefault_ts)) {
+ if ((ft_data->context_id == context->id) &&
+ (ft_data->global_eop == context->pagefault_ts)) {
ft_data->ft_policy &= ~KGSL_FT_REPLAY;
KGSL_FT_ERR(device, "MMU fault skipping replay\n");
}
- adreno_context->pagefault = 0;
+ clear_bit(KGSL_CONTEXT_PAGEFAULT, &context->priv);
}
if (ft_data->ft_policy & KGSL_FT_REPLAY) {
@@ -2591,6 +2626,10 @@
adreno_context->flags = (adreno_context->flags &
~CTXT_FLAGS_GPU_HANG) | CTXT_FLAGS_GPU_HANG_FT;
}
+
+ if (last_active_ctx)
+ _kgsl_context_get(&last_active_ctx->base);
+
adreno_dev->drawctxt_active = last_active_ctx;
}
@@ -2618,10 +2657,7 @@
struct kgsl_context *last_ctx = kgsl_context_get(device,
ft_data->last_valid_ctx_id);
- if (last_ctx)
- adreno_dev->drawctxt_active = last_ctx->devctxt;
-
- kgsl_context_put(last_ctx);
+ adreno_dev->drawctxt_active = ADRENO_CONTEXT(last_ctx);
}
done:
@@ -2640,7 +2676,6 @@
int ret = 0;
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
- unsigned int timestamp;
/*
* If GPU FT is turned off do not run FT.
@@ -2657,8 +2692,8 @@
"Bad context_id: %u, global_eop: 0x%x\n",
ft_data->ib1, ft_data->context_id, ft_data->global_eop);
- timestamp = rb->timestamp[KGSL_MEMSTORE_GLOBAL];
- KGSL_FT_INFO(device, "Last issued global timestamp: %x\n", timestamp);
+ KGSL_FT_INFO(device, "Last issued global timestamp: %x\n",
+ rb->global_ts);
/* We may need to replay commands multiple times based on whether
* multiple contexts hang the GPU */
@@ -2687,14 +2722,12 @@
/* Restore correct states after fault tolerance */
if (adreno_dev->drawctxt_active)
device->mmu.hwpagetable =
- adreno_dev->drawctxt_active->pagetable;
+ adreno_dev->drawctxt_active->base.pagetable;
else
device->mmu.hwpagetable = device->mmu.defaultpagetable;
- rb->timestamp[KGSL_MEMSTORE_GLOBAL] = timestamp;
kgsl_sharedmem_writel(device, &device->memstore,
KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
- eoptimestamp),
- rb->timestamp[KGSL_MEMSTORE_GLOBAL]);
+ eoptimestamp), rb->global_ts);
/* switch to NULL ctxt */
if (adreno_dev->drawctxt_active != NULL)
@@ -2785,6 +2818,264 @@
}
EXPORT_SYMBOL(adreno_dump_and_exec_ft);
+/**
+ * _ft_sysfs_store() - Common routine to write to FT sysfs files
+ * @buf: value to write
+ * @count: size of the value to write
+ * @sysfs_cfg: KGSL FT sysfs config to write
+ *
+ * This is a common routine to write to FT sysfs files.
+ */
+static int _ft_sysfs_store(const char *buf, size_t count, unsigned int *ptr)
+{
+ char temp[20];
+ unsigned long val;
+ int rc;
+
+ snprintf(temp, sizeof(temp), "%.*s",
+ (int)min(count, sizeof(temp) - 1), buf);
+ rc = kstrtoul(temp, 0, &val);
+ if (rc)
+ return rc;
+
+ *ptr = val;
+
+ return count;
+}
+
+/**
+ * _get_adreno_dev() - Routine to get a pointer to adreno dev
+ * @dev: device ptr
+ * @attr: Device attribute
+ * @buf: value to write
+ * @count: size of the value to write
+ */
+struct adreno_device *_get_adreno_dev(struct device *dev)
+{
+ struct kgsl_device *device = kgsl_device_from_dev(dev);
+ return device ? ADRENO_DEVICE(device) : NULL;
+}
+
+/**
+ * _ft_policy_store() - Routine to configure FT policy
+ * @dev: device ptr
+ * @attr: Device attribute
+ * @buf: value to write
+ * @count: size of the value to write
+ *
+ * FT policy can be set to any of the options below.
+ * KGSL_FT_DISABLE -> BIT(0) Set to disable FT
+ * KGSL_FT_REPLAY -> BIT(1) Set to enable replay
+ * KGSL_FT_SKIPIB -> BIT(2) Set to skip IB
+ * KGSL_FT_SKIPFRAME -> BIT(3) Set to skip frame
+ * by default set FT policy to KGSL_FT_DEFAULT_POLICY
+ */
+static int _ft_policy_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct adreno_device *adreno_dev = _get_adreno_dev(dev);
+ int ret;
+ if (adreno_dev == NULL)
+ return 0;
+
+ mutex_lock(&adreno_dev->dev.mutex);
+ ret = _ft_sysfs_store(buf, count, &adreno_dev->ft_policy);
+ mutex_unlock(&adreno_dev->dev.mutex);
+
+ return ret;
+}
+
+/**
+ * _ft_policy_show() - Routine to read FT policy
+ * @dev: device ptr
+ * @attr: Device attribute
+ * @buf: value read
+ *
+ * This is a routine to read current FT policy
+ */
+static int _ft_policy_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct adreno_device *adreno_dev = _get_adreno_dev(dev);
+ if (adreno_dev == NULL)
+ return 0;
+ return snprintf(buf, PAGE_SIZE, "0x%X\n", adreno_dev->ft_policy);
+}
+
+/**
+ * _ft_pagefault_policy_store() - Routine to configure FT
+ * pagefault policy
+ * @dev: device ptr
+ * @attr: Device attribute
+ * @buf: value to write
+ * @count: size of the value to write
+ *
+ * FT pagefault policy can be set to any of the options below.
+ * KGSL_FT_PAGEFAULT_INT_ENABLE -> BIT(0) set to enable pagefault INT
+ * KGSL_FT_PAGEFAULT_GPUHALT_ENABLE -> BIT(1) Set to enable GPU HALT on
+ * pagefaults. This stalls the GPU on a pagefault on IOMMU v1 HW.
+ * KGSL_FT_PAGEFAULT_LOG_ONE_PER_PAGE -> BIT(2) Set to log only one
+ * pagefault per page.
+ * KGSL_FT_PAGEFAULT_LOG_ONE_PER_INT -> BIT(3) Set to log only one
+ * pagefault per INT.
+ */
+static int _ft_pagefault_policy_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct adreno_device *adreno_dev = _get_adreno_dev(dev);
+ int ret;
+ if (adreno_dev == NULL)
+ return 0;
+
+ mutex_lock(&adreno_dev->dev.mutex);
+ ret = _ft_sysfs_store(buf, count, &adreno_dev->ft_pf_policy);
+ mutex_unlock(&adreno_dev->dev.mutex);
+
+ return ret;
+}
+
+/**
+ * _ft_pagefault_policy_show() - Routine to read FT pagefault
+ * policy
+ * @dev: device ptr
+ * @attr: Device attribute
+ * @buf: value read
+ *
+ * This is a routine to read current FT pagefault policy
+ */
+static int _ft_pagefault_policy_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct adreno_device *adreno_dev = _get_adreno_dev(dev);
+ if (adreno_dev == NULL)
+ return 0;
+ return snprintf(buf, PAGE_SIZE, "0x%X\n", adreno_dev->ft_pf_policy);
+}
+
+/**
+ * _ft_fast_hang_detect_store() - Routine to configure FT fast
+ * hang detect policy
+ * @dev: device ptr
+ * @attr: Device attribute
+ * @buf: value to write
+ * @count: size of the value to write
+ *
+ * 0x1 - Enable fast hang detection
+ * 0x0 - Disable fast hang detection
+ */
+static int _ft_fast_hang_detect_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct adreno_device *adreno_dev = _get_adreno_dev(dev);
+ int ret;
+ if (adreno_dev == NULL)
+ return 0;
+
+ mutex_lock(&adreno_dev->dev.mutex);
+ ret = _ft_sysfs_store(buf, count, &adreno_dev->fast_hang_detect);
+ mutex_unlock(&adreno_dev->dev.mutex);
+
+ return ret;
+
+}
+
+/**
+ * _ft_fast_hang_detect_show() - Routine to read FT fast
+ * hang detect policy
+ * @dev: device ptr
+ * @attr: Device attribute
+ * @buf: value read
+ */
+static int _ft_fast_hang_detect_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct adreno_device *adreno_dev = _get_adreno_dev(dev);
+ if (adreno_dev == NULL)
+ return 0;
+ return snprintf(buf, PAGE_SIZE, "%d\n",
+ (adreno_dev->fast_hang_detect ? 1 : 0));
+}
+
+/**
+ * _ft_long_ib_detect_store() - Routine to configure FT long IB
+ * detect policy
+ * @dev: device ptr
+ * @attr: Device attribute
+ * @buf: value to write
+ * @count: size of the value to write
+ *
+ * 0x0 - Enable long IB detection
+ * 0x1 - Disable long IB detection
+ */
+static int _ft_long_ib_detect_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct adreno_device *adreno_dev = _get_adreno_dev(dev);
+ int ret;
+ if (adreno_dev == NULL)
+ return 0;
+
+ mutex_lock(&adreno_dev->dev.mutex);
+ ret = _ft_sysfs_store(buf, count, &adreno_dev->long_ib_detect);
+ mutex_unlock(&adreno_dev->dev.mutex);
+
+ return ret;
+
+}
+
+/**
+ * _ft_long_ib_detect_show() - Routine to read FT long IB
+ * detect policy
+ * @dev: device ptr
+ * @attr: Device attribute
+ * @buf: value read
+ */
+static int _ft_long_ib_detect_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct adreno_device *adreno_dev = _get_adreno_dev(dev);
+ if (adreno_dev == NULL)
+ return 0;
+ return snprintf(buf, PAGE_SIZE, "%d\n",
+ (adreno_dev->long_ib_detect ? 1 : 0));
+}
+
+
+#define FT_DEVICE_ATTR(name) \
+ DEVICE_ATTR(name, 0644, _ ## name ## _show, _ ## name ## _store);
+
+FT_DEVICE_ATTR(ft_policy);
+FT_DEVICE_ATTR(ft_pagefault_policy);
+FT_DEVICE_ATTR(ft_fast_hang_detect);
+FT_DEVICE_ATTR(ft_long_ib_detect);
+
+
+const struct device_attribute *ft_attr_list[] = {
+ &dev_attr_ft_policy,
+ &dev_attr_ft_pagefault_policy,
+ &dev_attr_ft_fast_hang_detect,
+ &dev_attr_ft_long_ib_detect,
+ NULL,
+};
+
+int adreno_ft_init_sysfs(struct kgsl_device *device)
+{
+ return kgsl_create_device_sysfs_files(device->dev, ft_attr_list);
+}
+
+void adreno_ft_uninit_sysfs(struct kgsl_device *device)
+{
+ kgsl_remove_device_sysfs_files(device->dev, ft_attr_list);
+}
+
static int adreno_getproperty(struct kgsl_device *device,
enum kgsl_property_type type,
void *value,
@@ -2929,20 +3220,15 @@
{
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
- unsigned long wait;
+ unsigned long wait = jiffies;
unsigned long timeout = jiffies + msecs_to_jiffies(ADRENO_IDLE_TIMEOUT);
unsigned int rptr;
- /*
- * The first time into the loop, wait for 100 msecs and kick wptr again
- * to ensure that the hardware has updated correctly. After that, kick
- * it periodically every KGSL_TIMEOUT_PART msecs until the timeout
- * expires
- */
-
- wait = jiffies + msecs_to_jiffies(100);
-
do {
+ /*
+ * Wait is "jiffies" first time in the loop to start
+ * GPU stall detection immediately.
+ */
if (time_after(jiffies, wait)) {
/* Check to see if the core is hung */
if (adreno_ft_detect(device, regs))
@@ -2964,11 +3250,10 @@
/* Caller must hold the device mutex. */
int adreno_idle(struct kgsl_device *device)
{
- struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
- unsigned int rbbm_status;
unsigned long wait_time;
unsigned long wait_time_part;
unsigned int prev_reg_val[FT_DETECT_REGS_COUNT];
+ struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
memset(prev_reg_val, 0, sizeof(prev_reg_val));
@@ -2986,23 +3271,15 @@
wait_time_part = jiffies + msecs_to_jiffies(KGSL_TIMEOUT_PART);
while (time_before(jiffies, wait_time)) {
- adreno_readreg(adreno_dev, ADRENO_REG_RBBM_STATUS,
- &rbbm_status);
- if (adreno_is_a2xx(adreno_dev)) {
- if (rbbm_status == 0x110)
- return 0;
- } else {
- if (!(rbbm_status & 0x80000000))
- return 0;
- }
+ if (adreno_isidle(device))
+ return 0;
- /* Dont wait for timeout, detect hang faster.
- */
+ /* Dont wait for timeout, detect hang faster. */
if (time_after(jiffies, wait_time_part)) {
- wait_time_part = jiffies +
- msecs_to_jiffies(KGSL_TIMEOUT_PART);
- if ((adreno_ft_detect(device, prev_reg_val)))
- goto err;
+ wait_time_part = jiffies +
+ msecs_to_jiffies(KGSL_TIMEOUT_PART);
+ if ((adreno_ft_detect(device, prev_reg_val)))
+ goto err;
}
}
@@ -3051,9 +3328,8 @@
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
- WARN_ON(device->state == KGSL_STATE_INIT);
/* If the device isn't active, don't force it on. */
- if (device->state == KGSL_STATE_ACTIVE) {
+ if (kgsl_pwrctrl_isenabled(device)) {
/* Is the ring buffer is empty? */
unsigned int rptr = adreno_get_rptr(rb);
if (rptr == rb->wptr) {
@@ -3096,21 +3372,20 @@
phys_addr_t pt_base, unsigned int gpuaddr, unsigned int size)
{
struct kgsl_context *context;
- struct adreno_context *adreno_context = NULL;
int next = 0;
struct kgsl_memdesc *desc = NULL;
-
read_lock(&device->context_lock);
while (1) {
context = idr_get_next(&device->context_idr, &next);
if (context == NULL)
break;
- adreno_context = (struct adreno_context *)context->devctxt;
-
- if (kgsl_mmu_pt_equal(&device->mmu, adreno_context->pagetable,
+ if (kgsl_mmu_pt_equal(&device->mmu, context->pagetable,
pt_base)) {
+ struct adreno_context *adreno_context;
+
+ adreno_context = ADRENO_CONTEXT(context);
desc = &adreno_context->gpustate;
if (kgsl_gpuaddr_in_memdesc(desc, gpuaddr, size))
break;
@@ -3244,9 +3519,10 @@
static unsigned int _get_context_id(struct kgsl_context *k_ctxt)
{
unsigned int context_id = KGSL_MEMSTORE_GLOBAL;
+
if (k_ctxt != NULL) {
- struct adreno_context *a_ctxt = k_ctxt->devctxt;
- if (k_ctxt->id == KGSL_CONTEXT_INVALID || a_ctxt == NULL)
+ struct adreno_context *a_ctxt = ADRENO_CONTEXT(k_ctxt);
+ if (kgsl_context_detached(k_ctxt))
context_id = KGSL_CONTEXT_INVALID;
else if (a_ctxt->flags & CTXT_FLAGS_PER_CONTEXT_TS)
context_id = k_ctxt->id;
@@ -3317,7 +3593,8 @@
*/
if (context && device->state != KGSL_STATE_SLUMBER) {
- adreno_ringbuffer_issuecmds(device, context->devctxt,
+ adreno_ringbuffer_issuecmds(device,
+ ADRENO_CONTEXT(context),
KGSL_CMD_FLAGS_GET_INT, NULL, 0);
}
}
@@ -3377,6 +3654,7 @@
unsigned int curr_context_id = 0;
static struct adreno_context *curr_context;
static struct kgsl_context *context;
+ static char pid_name[TASK_COMM_LEN] = "unknown";
if (!adreno_dev->fast_hang_detect)
fast_hang_detected = 0;
@@ -3389,7 +3667,7 @@
if (is_adreno_rbbm_status_idle(device) &&
(kgsl_readtimestamp(device, NULL, KGSL_TIMESTAMP_RETIRED)
- == rb->timestamp[KGSL_MEMSTORE_GLOBAL])) {
+ == rb->global_ts)) {
/*
* On A2XX if the RPTR != WPTR and the device is idle, then
@@ -3440,8 +3718,13 @@
if (curr_global_ts == prev_global_ts) {
- /* Get the current context here */
- if (context == NULL) {
+ /* If we don't already have a good context, get it. */
+ if (kgsl_context_detached(context)) {
+ kgsl_context_put(context);
+ context = NULL;
+ curr_context = NULL;
+ strlcpy(pid_name, "unknown", sizeof(pid_name));
+
kgsl_sharedmem_readl(&device->memstore,
&curr_context_id,
KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
@@ -3451,8 +3734,12 @@
context = kgsl_context_get(device, curr_context_id);
if (context != NULL) {
- curr_context = context->devctxt;
+ struct task_struct *task;
+ curr_context = ADRENO_CONTEXT(context);
curr_context->ib_gpu_time_used = 0;
+ task = find_task_by_vpid(context->pid);
+ if (task)
+ get_task_comm(pid_name, task);
} else {
KGSL_DRV_ERR(device,
"Fault tolerance no context found\n");
@@ -3476,8 +3763,7 @@
KGSL_FT_ERR(device,
"Proc %s, ctxt_id %d ts %d triggered fault tolerance"
" on global ts %d\n",
- curr_context ? curr_context->pid_name : "",
- curr_context ? curr_context->id : 0,
+ pid_name, context ? context->id : 0,
(kgsl_readtimestamp(device, context,
KGSL_TIMESTAMP_RETIRED) + 1),
curr_global_ts + 1);
@@ -3489,7 +3775,7 @@
curr_context->ib_gpu_time_used += KGSL_TIMEOUT_PART;
KGSL_FT_INFO(device,
"Proc %s used GPU Time %d ms on timestamp 0x%X\n",
- curr_context->pid_name, curr_context->ib_gpu_time_used,
+ pid_name, curr_context->ib_gpu_time_used,
curr_global_ts+1);
if ((long_ib_detected) &&
@@ -3505,8 +3791,7 @@
"Proc %s, ctxt_id %d ts %d"
"used GPU for %d ms long ib "
"detected on global ts %d\n",
- curr_context->pid_name,
- curr_context->id,
+ pid_name, context->id,
(kgsl_readtimestamp(device,
context,
KGSL_TIMESTAMP_RETIRED)+1),
@@ -3528,6 +3813,7 @@
kgsl_context_put(context);
context = NULL;
curr_context = NULL;
+ strlcpy(pid_name, "unknown", sizeof(pid_name));
adreno_dev->long_ib = 0;
adreno_dev->long_ib_ts = 0;
}
@@ -3550,7 +3836,7 @@
if (context_id == KGSL_CONTEXT_INVALID)
return -EINVAL;
- ts_issued = adreno_dev->ringbuffer.timestamp[context_id];
+ ts_issued = adreno_context_timestamp(context, &adreno_dev->ringbuffer);
if (timestamp_cmp(timestamp, ts_issued) <= 0)
return 0;
@@ -3585,7 +3871,8 @@
unsigned int msecs)
{
static unsigned int io_cnt;
- struct adreno_context *adreno_ctx = context ? context->devctxt : NULL;
+ struct adreno_context *adreno_ctx = context ? ADRENO_CONTEXT(context) :
+ NULL;
struct kgsl_pwrctrl *pwr = &device->pwrctrl;
unsigned int context_id = _get_context_id(context);
unsigned int time_elapsed = 0;
@@ -3593,8 +3880,6 @@
int ts_compare = 1;
int io, ret = -ETIMEDOUT;
- /* Get out early if the context has already been destroyed */
-
if (context_id == KGSL_CONTEXT_INVALID) {
KGSL_DRV_WARN(device, "context was detached");
return -EINVAL;
@@ -3732,9 +4017,9 @@
switch (type) {
case KGSL_TIMESTAMP_QUEUED: {
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
- struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
- timestamp = rb->timestamp[context_id];
+ timestamp = adreno_context_timestamp(context,
+ &adreno_dev->ringbuffer);
break;
}
case KGSL_TIMESTAMP_CONSUMED:
@@ -3906,6 +4191,7 @@
/* Optional functions */
.setstate = adreno_setstate,
.drawctxt_create = adreno_drawctxt_create,
+ .drawctxt_detach = adreno_drawctxt_detach,
.drawctxt_destroy = adreno_drawctxt_destroy,
.setproperty = adreno_setproperty,
.postmortem_dump = adreno_dump,
diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h
index b53d16f..cb75b34 100644
--- a/drivers/gpu/msm/adreno.h
+++ b/drivers/gpu/msm/adreno.h
@@ -25,6 +25,9 @@
#define ADRENO_DEVICE(device) \
KGSL_CONTAINER_OF(device, struct adreno_device, dev)
+#define ADRENO_CONTEXT(device) \
+ KGSL_CONTAINER_OF(device, struct adreno_context, base)
+
#define ADRENO_CHIPID_CORE(_id) (((_id) >> 24) & 0xFF)
#define ADRENO_CHIPID_MAJOR(_id) (((_id) >> 16) & 0xFF)
#define ADRENO_CHIPID_MINOR(_id) (((_id) >> 8) & 0xFF)
@@ -337,10 +340,10 @@
#define KGSL_FT_DEFAULT_POLICY (KGSL_FT_REPLAY + KGSL_FT_SKIPIB)
/* Pagefault policy flags */
-#define KGSL_FT_PAGEFAULT_INT_ENABLE 0x00000001
-#define KGSL_FT_PAGEFAULT_GPUHALT_ENABLE 0x00000002
-#define KGSL_FT_PAGEFAULT_LOG_ONE_PER_PAGE 0x00000004
-#define KGSL_FT_PAGEFAULT_LOG_ONE_PER_INT 0x00000008
+#define KGSL_FT_PAGEFAULT_INT_ENABLE BIT(0)
+#define KGSL_FT_PAGEFAULT_GPUHALT_ENABLE BIT(1)
+#define KGSL_FT_PAGEFAULT_LOG_ONE_PER_PAGE BIT(2)
+#define KGSL_FT_PAGEFAULT_LOG_ONE_PER_INT BIT(3)
#define KGSL_FT_PAGEFAULT_DEFAULT_POLICY (KGSL_FT_PAGEFAULT_INT_ENABLE + \
KGSL_FT_PAGEFAULT_GPUHALT_ENABLE)
@@ -407,6 +410,9 @@
unsigned int adreno_ft_detect(struct kgsl_device *device,
unsigned int *prev_reg_val);
+int adreno_ft_init_sysfs(struct kgsl_device *device);
+void adreno_ft_uninit_sysfs(struct kgsl_device *device);
+
int adreno_perfcounter_get(struct adreno_device *adreno_dev,
unsigned int groupid, unsigned int countable, unsigned int *offset,
unsigned int flags);
@@ -501,6 +507,26 @@
}
/**
+ * adreno_context_timestamp() - Return the last queued timestamp for the context
+ * @k_ctxt: Pointer to the KGSL context to query
+ * @rb: Pointer to the ringbuffer structure for the GPU
+ *
+ * Return the last queued context for the given context. This is used to verify
+ * that incoming requests are not using an invalid (unsubmitted) timestamp
+ */
+static inline int adreno_context_timestamp(struct kgsl_context *k_ctxt,
+ struct adreno_ringbuffer *rb)
+{
+ if (k_ctxt) {
+ struct adreno_context *a_ctxt = ADRENO_CONTEXT(k_ctxt);
+
+ if (a_ctxt->flags & CTXT_FLAGS_PER_CONTEXT_TS)
+ return a_ctxt->timestamp;
+ }
+ return rb->global_ts;
+}
+
+/**
* adreno_encode_istore_size - encode istore size in CP format
* @adreno_dev - The 3D device.
*
diff --git a/drivers/gpu/msm/adreno_a2xx.c b/drivers/gpu/msm/adreno_a2xx.c
index 42137fe..3d72c5c 100644
--- a/drivers/gpu/msm/adreno_a2xx.c
+++ b/drivers/gpu/msm/adreno_a2xx.c
@@ -1355,7 +1355,7 @@
tmp_ctx.gmem_base = adreno_dev->gmem_base;
result = kgsl_allocate(&drawctxt->context_gmem_shadow.gmemshadow,
- drawctxt->pagetable, drawctxt->context_gmem_shadow.size);
+ drawctxt->base.pagetable, drawctxt->context_gmem_shadow.size);
if (result)
return result;
@@ -1364,7 +1364,7 @@
drawctxt->flags |= CTXT_FLAGS_GMEM_SHADOW;
/* blank out gmem shadow. */
- kgsl_sharedmem_set(drawctxt->dev_priv->device,
+ kgsl_sharedmem_set(drawctxt->base.device,
&drawctxt->context_gmem_shadow.gmemshadow, 0, 0,
drawctxt->context_gmem_shadow.size);
@@ -1389,7 +1389,7 @@
kgsl_cache_range_op(&drawctxt->context_gmem_shadow.gmemshadow,
KGSL_CACHE_OP_FLUSH);
- kgsl_cffdump_syncmem(drawctxt->dev_priv,
+ kgsl_cffdump_syncmem(drawctxt->base.device,
&drawctxt->context_gmem_shadow.gmemshadow,
drawctxt->context_gmem_shadow.gmemshadow.gpuaddr,
drawctxt->context_gmem_shadow.gmemshadow.size, false);
@@ -1410,13 +1410,13 @@
*/
ret = kgsl_allocate(&drawctxt->gpustate,
- drawctxt->pagetable, _context_size(adreno_dev));
+ drawctxt->base.pagetable, _context_size(adreno_dev));
if (ret)
return ret;
- kgsl_sharedmem_set(drawctxt->dev_priv->device, &drawctxt->gpustate, 0,
- 0, _context_size(adreno_dev));
+ kgsl_sharedmem_set(drawctxt->base.device, &drawctxt->gpustate,
+ 0, 0, _context_size(adreno_dev));
tmp_ctx.cmd = tmp_ctx.start
= (unsigned int *)((char *)drawctxt->gpustate.hostptr + CMD_OFFSET);
@@ -1440,8 +1440,8 @@
kgsl_cache_range_op(&drawctxt->gpustate,
KGSL_CACHE_OP_FLUSH);
- kgsl_cffdump_syncmem(drawctxt->dev_priv, &drawctxt->gpustate,
- drawctxt->gpustate.gpuaddr,
+ kgsl_cffdump_syncmem(drawctxt->base.device,
+ &drawctxt->gpustate, drawctxt->gpustate.gpuaddr,
drawctxt->gpustate.size, false);
done:
@@ -1516,7 +1516,7 @@
"Current active context has caused gpu hang\n");
if (!(context->flags & CTXT_FLAGS_PREAMBLE)) {
- kgsl_cffdump_syncmem(context->dev_priv, &context->gpustate,
+ kgsl_cffdump_syncmem(context->base.device, &context->gpustate,
context->reg_save[1],
context->reg_save[2] << 2, true);
/* save registers and constants. */
@@ -1525,7 +1525,7 @@
context->reg_save, 3);
if (context->flags & CTXT_FLAGS_SHADER_SAVE) {
- kgsl_cffdump_syncmem(context->dev_priv,
+ kgsl_cffdump_syncmem(context->base.device,
&context->gpustate,
context->shader_save[1],
context->shader_save[2] << 2, true);
@@ -1534,7 +1534,7 @@
KGSL_CMD_FLAGS_PMODE,
context->shader_save, 3);
- kgsl_cffdump_syncmem(context->dev_priv,
+ kgsl_cffdump_syncmem(context->base.device,
&context->gpustate,
context->shader_fixup[1],
context->shader_fixup[2] << 2, true);
@@ -1552,7 +1552,7 @@
if ((context->flags & CTXT_FLAGS_GMEM_SAVE) &&
(context->flags & CTXT_FLAGS_GMEM_SHADOW)) {
- kgsl_cffdump_syncmem(context->dev_priv, &context->gpustate,
+ kgsl_cffdump_syncmem(context->base.device, &context->gpustate,
context->context_gmem_shadow.gmem_save[1],
context->context_gmem_shadow.gmem_save[2] << 2, true);
/* save gmem.
@@ -1562,7 +1562,7 @@
KGSL_CMD_FLAGS_PMODE,
context->context_gmem_shadow.gmem_save, 3);
- kgsl_cffdump_syncmem(context->dev_priv, &context->gpustate,
+ kgsl_cffdump_syncmem(context->base.device, &context->gpustate,
context->chicken_restore[1],
context->chicken_restore[2] << 2, true);
@@ -1586,9 +1586,18 @@
unsigned int cmds[5];
if (context == NULL) {
- /* No context - set the default apgetable and thats it */
+ /* No context - set the default pagetable and thats it */
+ unsigned int id;
+ /*
+ * If there isn't a current context, the kgsl_mmu_setstate
+ * will use the CPU path so we don't need to give
+ * it a valid context id.
+ */
+ id = (adreno_dev->drawctxt_active != NULL)
+ ? adreno_dev->drawctxt_active->base.id
+ : KGSL_CONTEXT_INVALID;
kgsl_mmu_setstate(&device->mmu, device->mmu.defaultpagetable,
- adreno_dev->drawctxt_active->id);
+ id);
return;
}
@@ -1597,16 +1606,17 @@
cmds[2] = cp_type3_packet(CP_MEM_WRITE, 2);
cmds[3] = device->memstore.gpuaddr +
KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL, current_context);
- cmds[4] = context->id;
+ cmds[4] = context->base.id;
adreno_ringbuffer_issuecmds(device, context, KGSL_CMD_FLAGS_NONE,
cmds, 5);
- kgsl_mmu_setstate(&device->mmu, context->pagetable, context->id);
+ kgsl_mmu_setstate(&device->mmu, context->base.pagetable,
+ context->base.id);
/* restore gmem.
* (note: changes shader. shader must not already be restored.)
*/
if (context->flags & CTXT_FLAGS_GMEM_RESTORE) {
- kgsl_cffdump_syncmem(context->dev_priv, &context->gpustate,
+ kgsl_cffdump_syncmem(context->base.device, &context->gpustate,
context->context_gmem_shadow.gmem_restore[1],
context->context_gmem_shadow.gmem_restore[2] << 2,
true);
@@ -1616,7 +1626,7 @@
context->context_gmem_shadow.gmem_restore, 3);
if (!(context->flags & CTXT_FLAGS_PREAMBLE)) {
- kgsl_cffdump_syncmem(context->dev_priv,
+ kgsl_cffdump_syncmem(context->base.device,
&context->gpustate,
context->chicken_restore[1],
context->chicken_restore[2] << 2, true);
@@ -1631,7 +1641,7 @@
}
if (!(context->flags & CTXT_FLAGS_PREAMBLE)) {
- kgsl_cffdump_syncmem(context->dev_priv, &context->gpustate,
+ kgsl_cffdump_syncmem(context->base.device, &context->gpustate,
context->reg_restore[1],
context->reg_restore[2] << 2, true);
@@ -1641,7 +1651,7 @@
/* restore shader instructions & partitioning. */
if (context->flags & CTXT_FLAGS_SHADER_RESTORE) {
- kgsl_cffdump_syncmem(context->dev_priv,
+ kgsl_cffdump_syncmem(context->base.device,
&context->gpustate,
context->shader_restore[1],
context->shader_restore[2] << 2, true);
diff --git a/drivers/gpu/msm/adreno_a3xx.c b/drivers/gpu/msm/adreno_a3xx.c
index 7e5638c..670f0cf 100644
--- a/drivers/gpu/msm/adreno_a3xx.c
+++ b/drivers/gpu/msm/adreno_a3xx.c
@@ -2321,7 +2321,7 @@
tmp_ctx.gmem_base = adreno_dev->gmem_base;
result = kgsl_allocate(&drawctxt->context_gmem_shadow.gmemshadow,
- drawctxt->pagetable, drawctxt->context_gmem_shadow.size);
+ drawctxt->base.pagetable, drawctxt->context_gmem_shadow.size);
if (result)
return result;
@@ -2355,7 +2355,7 @@
*/
ret = kgsl_allocate(&drawctxt->gpustate,
- drawctxt->pagetable, CONTEXT_SIZE);
+ drawctxt->base.pagetable, CONTEXT_SIZE);
if (ret)
return ret;
@@ -2420,7 +2420,7 @@
* already be saved.)
*/
- kgsl_cffdump_syncmem(context->dev_priv,
+ kgsl_cffdump_syncmem(context->base.device,
&context->gpustate,
context->context_gmem_shadow.gmem_save[1],
context->context_gmem_shadow.gmem_save[2] << 2, true);
@@ -2441,8 +2441,17 @@
if (context == NULL) {
/* No context - set the default pagetable and thats it */
+ unsigned int id;
+ /*
+ * If there isn't a current context, the kgsl_mmu_setstate
+ * will use the CPU path so we don't need to give
+ * it a valid context id.
+ */
+ id = (adreno_dev->drawctxt_active != NULL)
+ ? adreno_dev->drawctxt_active->base.id
+ : KGSL_CONTEXT_INVALID;
kgsl_mmu_setstate(&device->mmu, device->mmu.defaultpagetable,
- adreno_dev->drawctxt_active->id);
+ id);
return;
}
@@ -2451,10 +2460,11 @@
cmds[2] = cp_type3_packet(CP_MEM_WRITE, 2);
cmds[3] = device->memstore.gpuaddr +
KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL, current_context);
- cmds[4] = context->id;
+ cmds[4] = context->base.id;
adreno_ringbuffer_issuecmds(device, context, KGSL_CMD_FLAGS_NONE,
cmds, 5);
- kgsl_mmu_setstate(&device->mmu, context->pagetable, context->id);
+ kgsl_mmu_setstate(&device->mmu, context->base.pagetable,
+ context->base.id);
/*
* Restore GMEM. (note: changes shader.
@@ -2462,7 +2472,7 @@
*/
if (context->flags & CTXT_FLAGS_GMEM_RESTORE) {
- kgsl_cffdump_syncmem(context->dev_priv,
+ kgsl_cffdump_syncmem(context->base.device,
&context->gpustate,
context->context_gmem_shadow.gmem_restore[1],
context->context_gmem_shadow.gmem_restore[2] << 2,
diff --git a/drivers/gpu/msm/adreno_debugfs.c b/drivers/gpu/msm/adreno_debugfs.c
index 90bd017..fc98d86 100644
--- a/drivers/gpu/msm/adreno_debugfs.c
+++ b/drivers/gpu/msm/adreno_debugfs.c
@@ -56,41 +56,6 @@
&adreno_dev->wait_timeout);
debugfs_create_u32("ib_check", 0644, device->d_debugfs,
&adreno_dev->ib_check_level);
- /* By Default enable fast hang detection */
- adreno_dev->fast_hang_detect = 1;
- debugfs_create_u32("fast_hang_detect", 0644, device->d_debugfs,
- &adreno_dev->fast_hang_detect);
- /*
- * FT policy can be set to any of the options below.
- * KGSL_FT_OFF -> BIT(0) Set to turn off FT
- * KGSL_FT_REPLAY -> BIT(1) Set to enable replay
- * KGSL_FT_SKIPIB -> BIT(2) Set to skip IB
- * KGSL_FT_SKIPFRAME -> BIT(3) Set to skip frame
- * KGSL_FT_DISABLE -> BIT(4) Set to disable FT for faulting context
- * by default set FT policy to KGSL_FT_DEFAULT_POLICY
- */
- adreno_dev->ft_policy = KGSL_FT_DEFAULT_POLICY;
- debugfs_create_u32("ft_policy", 0644, device->d_debugfs,
- &adreno_dev->ft_policy);
- /* By default enable long IB detection */
- adreno_dev->long_ib_detect = 1;
- debugfs_create_u32("long_ib_detect", 0644, device->d_debugfs,
- &adreno_dev->long_ib_detect);
-
- /*
- * FT pagefault policy can be set to any of the options below.
- * KGSL_FT_PAGEFAULT_INT_ENABLE -> BIT(0) set to enable pagefault INT
- * KGSL_FT_PAGEFAULT_GPUHALT_ENABLE -> BIT(1) Set to enable GPU HALT on
- * pagefaults. This stalls the GPU on a pagefault on IOMMU v1 HW.
- * KGSL_FT_PAGEFAULT_LOG_ONE_PER_PAGE -> BIT(2) Set to log only one
- * pagefault per page.
- * KGSL_FT_PAGEFAULT_LOG_ONE_PER_INT -> BIT(3) Set to log only one
- * pagefault per INT.
- */
- adreno_dev->ft_pf_policy = KGSL_FT_PAGEFAULT_DEFAULT_POLICY;
- debugfs_create_u32("ft_pagefault_policy", 0644, device->d_debugfs,
- &adreno_dev->ft_pf_policy);
-
debugfs_create_file("active_cnt", 0444, device->d_debugfs, device,
&_active_count_fops);
}
diff --git a/drivers/gpu/msm/adreno_drawctxt.c b/drivers/gpu/msm/adreno_drawctxt.c
index b32cdae..bf173a7 100644
--- a/drivers/gpu/msm/adreno_drawctxt.c
+++ b/drivers/gpu/msm/adreno_drawctxt.c
@@ -134,34 +134,32 @@
/**
* adreno_drawctxt_create - create a new adreno draw context
- * @device - KGSL device to create the context on
- * @pagetable - Pagetable for the context
- * @context- Generic KGSL context structure
- * @flags - flags for the context (passed from user space)
+ * @dev_priv: the owner of the context
+ * @flags: flags for the context (passed from user space)
*
- * Create a new draw context for the 3D core. Return 0 on success,
- * or error code on failure.
+ * Create and return a new draw context for the 3D core.
*/
-int adreno_drawctxt_create(struct kgsl_device *device,
- struct kgsl_pagetable *pagetable,
- struct kgsl_context *context, uint32_t *flags)
+struct kgsl_context *
+adreno_drawctxt_create(struct kgsl_device_private *dev_priv,
+ uint32_t *flags)
{
struct adreno_context *drawctxt;
+ struct kgsl_device *device = dev_priv->device;
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
- struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
int ret;
drawctxt = kzalloc(sizeof(struct adreno_context), GFP_KERNEL);
-
if (drawctxt == NULL)
- return -ENOMEM;
+ return ERR_PTR(-ENOMEM);
- drawctxt->pid = task_pid_nr(current);
- strlcpy(drawctxt->pid_name, current->comm, TASK_COMM_LEN);
- drawctxt->pagetable = pagetable;
+ ret = kgsl_context_init(dev_priv, &drawctxt->base);
+ if (ret != 0) {
+ kfree(drawctxt);
+ return ERR_PTR(ret);
+ }
+
drawctxt->bin_base_offset = 0;
- drawctxt->id = context->id;
- rb->timestamp[context->id] = 0;
+ drawctxt->timestamp = 0;
*flags &= (KGSL_CONTEXT_PREAMBLE |
KGSL_CONTEXT_NO_GMEM_ALLOC |
@@ -192,50 +190,47 @@
drawctxt->type =
(*flags & KGSL_CONTEXT_TYPE_MASK) >> KGSL_CONTEXT_TYPE_SHIFT;
- drawctxt->dev_priv = context->dev_priv;
ret = adreno_dev->gpudev->ctxt_create(adreno_dev, drawctxt);
if (ret)
goto err;
kgsl_sharedmem_writel(device, &device->memstore,
- KGSL_MEMSTORE_OFFSET(drawctxt->id, ref_wait_ts),
+ KGSL_MEMSTORE_OFFSET(drawctxt->base.id, ref_wait_ts),
KGSL_INIT_REFTIMESTAMP);
kgsl_sharedmem_writel(device, &device->memstore,
- KGSL_MEMSTORE_OFFSET(drawctxt->id, ts_cmp_enable), 0);
+ KGSL_MEMSTORE_OFFSET(drawctxt->base.id, ts_cmp_enable),
+ 0);
kgsl_sharedmem_writel(device, &device->memstore,
- KGSL_MEMSTORE_OFFSET(drawctxt->id, soptimestamp), 0);
+ KGSL_MEMSTORE_OFFSET(drawctxt->base.id, soptimestamp),
+ 0);
kgsl_sharedmem_writel(device, &device->memstore,
- KGSL_MEMSTORE_OFFSET(drawctxt->id, eoptimestamp), 0);
+ KGSL_MEMSTORE_OFFSET(drawctxt->base.id, eoptimestamp),
+ 0);
- context->devctxt = drawctxt;
- return 0;
+ return &drawctxt->base;
err:
- kfree(drawctxt);
- return ret;
+ kgsl_context_put(&drawctxt->base);
+ return ERR_PTR(ret);
}
/**
- * adreno_drawctxt_destroy - destroy a draw context
- * @device - KGSL device that owns the context
- * @context- Generic KGSL context container for the context
+ * adreno_drawctxt_detach(): detach a context from the GPU
+ * @context: Generic KGSL context container for the context
*
- * Destroy an existing context. Return 0 on success or error
- * code on failure.
*/
-
-/* destroy a drawing context */
-
-void adreno_drawctxt_destroy(struct kgsl_device *device,
- struct kgsl_context *context)
+void adreno_drawctxt_detach(struct kgsl_context *context)
{
- struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
+ struct kgsl_device *device;
+ struct adreno_device *adreno_dev;
struct adreno_context *drawctxt;
- if (context == NULL || context->devctxt == NULL)
+ if (context == NULL)
return;
- drawctxt = context->devctxt;
+ device = context->device;
+ adreno_dev = ADRENO_DEVICE(device);
+ drawctxt = ADRENO_CONTEXT(context);
/* deactivate context */
if (adreno_dev->drawctxt_active == drawctxt) {
/* no need to save GMEM or shader, the context is
@@ -256,9 +251,17 @@
kgsl_sharedmem_free(&drawctxt->gpustate);
kgsl_sharedmem_free(&drawctxt->context_gmem_shadow.gmemshadow);
+}
+
+void adreno_drawctxt_destroy(struct kgsl_context *context)
+{
+ struct adreno_context *drawctxt;
+ if (context == NULL)
+ return;
+
+ drawctxt = ADRENO_CONTEXT(context);
kfree(drawctxt);
- context->devctxt = NULL;
}
/**
@@ -274,10 +277,12 @@
struct kgsl_context *context,
unsigned int offset)
{
- struct adreno_context *drawctxt = context->devctxt;
+ struct adreno_context *drawctxt;
- if (drawctxt)
- drawctxt->bin_base_offset = offset;
+ if (context == NULL)
+ return;
+ drawctxt = ADRENO_CONTEXT(context);
+ drawctxt->bin_base_offset = offset;
}
/**
@@ -316,12 +321,22 @@
KGSL_CTXT_INFO(device, "from %d to %d flags %d\n",
adreno_dev->drawctxt_active ?
- adreno_dev->drawctxt_active->id : 0,
- drawctxt ? drawctxt->id : 0, flags);
+ adreno_dev->drawctxt_active->base.id : 0,
+ drawctxt ? drawctxt->base.id : 0, flags);
/* Save the old context */
adreno_dev->gpudev->ctxt_save(adreno_dev, adreno_dev->drawctxt_active);
+ /* Put the old instance of the active drawctxt */
+ if (adreno_dev->drawctxt_active) {
+ kgsl_context_put(&adreno_dev->drawctxt_active->base);
+ adreno_dev->drawctxt_active = NULL;
+ }
+
+ /* Get a refcount to the new instance */
+ if (drawctxt)
+ _kgsl_context_get(&drawctxt->base);
+
/* Set the new context */
adreno_dev->gpudev->ctxt_restore(adreno_dev, drawctxt);
adreno_dev->drawctxt_active = drawctxt;
diff --git a/drivers/gpu/msm/adreno_drawctxt.h b/drivers/gpu/msm/adreno_drawctxt.h
index 2b8e600..88d1b8c 100644
--- a/drivers/gpu/msm/adreno_drawctxt.h
+++ b/drivers/gpu/msm/adreno_drawctxt.h
@@ -13,8 +13,6 @@
#ifndef __ADRENO_DRAWCTXT_H
#define __ADRENO_DRAWCTXT_H
-#include <linux/sched.h>
-
#include "adreno_pm4types.h"
#include "a2xx_reg.h"
@@ -96,15 +94,11 @@
};
struct adreno_context {
- pid_t pid;
- char pid_name[TASK_COMM_LEN];
- unsigned int id;
+ struct kgsl_context base;
unsigned int ib_gpu_time_used;
+ unsigned int timestamp;
uint32_t flags;
- uint32_t pagefault;
- unsigned long pagefault_ts;
unsigned int type;
- struct kgsl_pagetable *pagetable;
struct kgsl_memdesc gpustate;
unsigned int reg_restore[3];
unsigned int shader_save[3];
@@ -131,16 +125,15 @@
struct kgsl_memdesc constant_load_commands[3];
struct kgsl_memdesc cond_execs[4];
struct kgsl_memdesc hlsqcontrol_restore_commands[1];
- struct kgsl_device_private *dev_priv;
};
-int adreno_drawctxt_create(struct kgsl_device *device,
- struct kgsl_pagetable *pagetable,
- struct kgsl_context *context,
+
+struct kgsl_context *adreno_drawctxt_create(struct kgsl_device_private *,
uint32_t *flags);
-void adreno_drawctxt_destroy(struct kgsl_device *device,
- struct kgsl_context *context);
+void adreno_drawctxt_detach(struct kgsl_context *context);
+
+void adreno_drawctxt_destroy(struct kgsl_context *context);
void adreno_drawctxt_switch(struct adreno_device *adreno_dev,
struct adreno_context *drawctxt,
diff --git a/drivers/gpu/msm/adreno_ringbuffer.c b/drivers/gpu/msm/adreno_ringbuffer.c
index f6c05b5..999b782 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.c
+++ b/drivers/gpu/msm/adreno_ringbuffer.c
@@ -138,7 +138,7 @@
if (context && context->flags & CTXT_FLAGS_GPU_HANG) {
KGSL_CTXT_WARN(rb->device,
"Context %p caused a gpu hang. Will not accept commands for context %d\n",
- context, context->id);
+ context, context->base.id);
return -EDEADLK;
}
wait_time = jiffies + wait_timeout;
@@ -575,6 +575,8 @@
/* overlay structure on memptrs memory */
rb->memptrs = (struct kgsl_rbmemptrs *) rb->memptrs_desc.hostptr;
+ rb->global_ts = 0;
+
return 0;
}
@@ -594,11 +596,11 @@
memset(rb, 0, sizeof(struct adreno_ringbuffer));
}
-static uint32_t
+static int
adreno_ringbuffer_addcmds(struct adreno_ringbuffer *rb,
struct adreno_context *context,
unsigned int flags, unsigned int *cmds,
- int sizedwords, uint32_t timestamp)
+ int sizedwords)
{
struct adreno_device *adreno_dev = ADRENO_DEVICE(rb->device);
unsigned int *ringcmds;
@@ -607,6 +609,7 @@
unsigned int rcmd_gpu;
unsigned int context_id = KGSL_MEMSTORE_GLOBAL;
unsigned int gpuaddr = rb->device->memstore.gpuaddr;
+ unsigned int timestamp;
/*
* if the context was not created with per context timestamp
@@ -616,20 +619,7 @@
*/
if ((context && (context->flags & CTXT_FLAGS_PER_CONTEXT_TS)) &&
!(flags & KGSL_CMD_FLAGS_INTERNAL_ISSUE))
- context_id = context->id;
-
- if ((context && (context->flags & CTXT_FLAGS_USER_GENERATED_TS)) &&
- !(flags & KGSL_CMD_FLAGS_INTERNAL_ISSUE)) {
- if (timestamp_cmp(rb->timestamp[context_id],
- timestamp) >= 0) {
- KGSL_DRV_ERR(rb->device,
- "Invalid user generated ts <%d:0x%x>, "
- "less than last issued ts <%d:0x%x>\n",
- context_id, timestamp, context_id,
- rb->timestamp[context_id]);
- return -ERANGE;
- }
- }
+ context_id = context->base.id;
/* reserve space to temporarily turn off protected mode
* error checking if needed
@@ -669,13 +659,8 @@
total_sizedwords += 2;
ringcmds = adreno_ringbuffer_allocspace(rb, context, total_sizedwords);
- if (!ringcmds) {
- /*
- * We could not allocate space in ringbuffer, just return the
- * last timestamp
- */
- return rb->timestamp[context_id];
- }
+ if (!ringcmds)
+ return -ENOSPC;
rcmd_gpu = rb->buffer_desc.gpuaddr
+ sizeof(uint)*(rb->wptr-total_sizedwords);
@@ -690,26 +675,19 @@
}
/* always increment the global timestamp. once. */
- rb->timestamp[KGSL_MEMSTORE_GLOBAL]++;
+ rb->global_ts++;
- /*
- * If global timestamp then we are not using per context ts for
- * this submission
- */
- if (context_id != KGSL_MEMSTORE_GLOBAL) {
- if (context->flags & CTXT_FLAGS_USER_GENERATED_TS)
- rb->timestamp[context_id] = timestamp;
- else
- rb->timestamp[context_id]++;
- }
- timestamp = rb->timestamp[context_id];
+ if (KGSL_MEMSTORE_GLOBAL != context_id)
+ timestamp = context->timestamp;
+ else
+ timestamp = rb->global_ts;
/* scratchpad ts for fault tolerance */
GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu,
cp_type0_packet(adreno_getreg(adreno_dev,
ADRENO_REG_CP_TIMESTAMP), 1));
GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu,
- rb->timestamp[KGSL_MEMSTORE_GLOBAL]);
+ rb->global_ts);
/* start-of-pipeline timestamp */
GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu,
@@ -781,7 +759,7 @@
KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
eoptimestamp)));
GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu,
- rb->timestamp[KGSL_MEMSTORE_GLOBAL]);
+ rb->global_ts);
}
if (adreno_is_a20x(adreno_dev)) {
@@ -857,7 +835,7 @@
adreno_ringbuffer_submit(rb);
- return timestamp;
+ return 0;
}
unsigned int
@@ -877,7 +855,7 @@
flags |= KGSL_CMD_FLAGS_INTERNAL_ISSUE;
return adreno_ringbuffer_addcmds(rb, drawctxt, flags, cmds,
- sizedwords, 0);
+ sizedwords);
}
static bool _parse_ibs(struct kgsl_device_private *dev_priv, uint gpuaddr,
@@ -1097,12 +1075,9 @@
ret = -EINVAL;
goto done;
}
- drawctxt = context->devctxt;
+ drawctxt = ADRENO_CONTEXT(context);
if (drawctxt->flags & CTXT_FLAGS_GPU_HANG) {
- KGSL_CTXT_ERR(device, "proc %s failed fault tolerance"
- " will not accept commands for context %d\n",
- drawctxt->pid_name, drawctxt->id);
ret = -EDEADLK;
goto done;
}
@@ -1116,10 +1091,6 @@
start_index = 1;
if (drawctxt->flags & CTXT_FLAGS_SKIP_EOF) {
- KGSL_CTXT_ERR(device,
- "proc %s triggered fault tolerance"
- " skipping commands for context till EOF %d\n",
- drawctxt->pid_name, drawctxt->id);
if (flags & KGSL_CMD_FLAGS_EOF)
drawctxt->flags &= ~CTXT_FLAGS_SKIP_EOF;
if (start_index)
@@ -1172,10 +1143,30 @@
adreno_drawctxt_switch(adreno_dev, drawctxt, flags);
- *timestamp = adreno_ringbuffer_addcmds(&adreno_dev->ringbuffer,
+ if (drawctxt->flags & CTXT_FLAGS_USER_GENERATED_TS) {
+ if (timestamp_cmp(drawctxt->timestamp, *timestamp) >= 0) {
+ KGSL_DRV_ERR(device,
+ "Invalid user generated ts <%d:0x%x>, "
+ "less than last issued ts <%d:0x%x>\n",
+ context->id, *timestamp, context->id,
+ drawctxt->timestamp);
+ return -ERANGE;
+ }
+ drawctxt->timestamp = *timestamp;
+ } else
+ drawctxt->timestamp++;
+
+ ret = adreno_ringbuffer_addcmds(&adreno_dev->ringbuffer,
drawctxt,
(flags & KGSL_CMD_FLAGS_EOF),
- &link[0], (cmds - link), *timestamp);
+ &link[0], (cmds - link));
+ if (ret)
+ goto done;
+
+ if (drawctxt->flags & CTXT_FLAGS_PER_CONTEXT_TS)
+ *timestamp = drawctxt->timestamp;
+ else
+ *timestamp = adreno_dev->ringbuffer.global_ts;
#ifdef CONFIG_MSM_KGSL_CFF_DUMP
/*
@@ -1282,7 +1273,7 @@
k_ctxt = kgsl_context_get(device, ft_data->context_id);
if (k_ctxt) {
- a_ctxt = k_ctxt->devctxt;
+ a_ctxt = ADRENO_CONTEXT(k_ctxt);
if (a_ctxt->flags & CTXT_FLAGS_PREAMBLE)
_turn_preamble_on_for_ib_seq(rb, rb_rptr);
kgsl_context_put(k_ctxt);
@@ -1319,7 +1310,7 @@
k_ctxt = kgsl_context_get(rb->device, val2);
if (k_ctxt) {
- a_ctxt = k_ctxt->devctxt;
+ a_ctxt = ADRENO_CONTEXT(k_ctxt);
/* If we are changing to a good context and were not
* copying commands then copy over commands to the good
diff --git a/drivers/gpu/msm/adreno_ringbuffer.h b/drivers/gpu/msm/adreno_ringbuffer.h
index e9fb050..9634e32 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.h
+++ b/drivers/gpu/msm/adreno_ringbuffer.h
@@ -55,7 +55,7 @@
unsigned int wptr; /* write pointer offset in dwords from baseaddr */
- unsigned int timestamp[KGSL_MEMSTORE_MAX];
+ unsigned int global_ts;
};
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 4c1ef54..966e035 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -448,20 +448,24 @@
entry->priv = NULL;
}
-/* Allocate a new context id */
-
-static struct kgsl_context *
-kgsl_create_context(struct kgsl_device_private *dev_priv)
+/**
+ * kgsl_context_init() - helper to initialize kgsl_context members
+ * @dev_priv: the owner of the context
+ * @context: the newly created context struct, should be allocated by
+ * the device specific drawctxt_create function.
+ *
+ * This is a helper function for the device specific drawctxt_create
+ * function to initialize the common members of its context struct.
+ * If this function succeeds, reference counting is active in the context
+ * struct and the caller should kgsl_context_put() it on error.
+ * If it fails, the caller should just free the context structure
+ * it passed in.
+ */
+int kgsl_context_init(struct kgsl_device_private *dev_priv,
+ struct kgsl_context *context)
{
+ int ret = 0, id;
struct kgsl_device *device = dev_priv->device;
- struct kgsl_context *context;
- int ret, id = 0;
-
- context = kzalloc(sizeof(*context), GFP_KERNEL);
-
- if (context == NULL)
- return ERR_PTR(-ENOMEM);
-
while (1) {
if (idr_pre_get(&device->context_idr, GFP_KERNEL) == 0) {
@@ -480,30 +484,26 @@
}
if (ret)
- goto func_end;
+ goto fail;
/* MAX - 1, there is one memdesc in memstore for device info */
if (id >= KGSL_MEMSTORE_MAX) {
KGSL_DRV_INFO(device, "cannot have more than %d "
"ctxts due to memstore limitation\n",
KGSL_MEMSTORE_MAX);
- write_lock(&device->context_lock);
- idr_remove(&device->context_idr, id);
- write_unlock(&device->context_lock);
ret = -ENOSPC;
- goto func_end;
+ goto fail_free_id;
}
kref_init(&context->refcount);
- context->dev_priv = dev_priv;
+ context->device = dev_priv->device;
+ context->pagetable = dev_priv->process_priv->pagetable;
+
+ context->pid = dev_priv->process_priv->pid;
ret = kgsl_sync_timeline_create(context);
- if (ret) {
- write_lock(&device->context_lock);
- idr_remove(&dev_priv->device->context_idr, id);
- write_unlock(&device->context_lock);
- goto func_end;
- }
+ if (ret)
+ goto fail_free_id;
/* Initialize the pending event list */
INIT_LIST_HEAD(&context->events);
@@ -518,15 +518,15 @@
*/
INIT_LIST_HEAD(&context->events_list);
-
-func_end:
- if (ret) {
- kfree(context);
- return ERR_PTR(ret);
- }
-
- return context;
+ return 0;
+fail_free_id:
+ write_lock(&device->context_lock);
+ idr_remove(&dev_priv->device->context_idr, id);
+ write_unlock(&device->context_lock);
+fail:
+ return ret;
}
+EXPORT_SYMBOL(kgsl_context_init);
/**
* kgsl_context_detach - Release the "master" context reference
@@ -536,37 +536,36 @@
* has requested for it to be destroyed. The context itself may
* exist a bit longer until its reference count goes to zero.
* Other code referencing the context can detect that it has been
- * detached because the context id will be set to KGSL_CONTEXT_INVALID.
+ * detached by checking the KGSL_CONTEXT_DETACHED bit in
+ * context->priv.
*/
void
kgsl_context_detach(struct kgsl_context *context)
{
- int id;
struct kgsl_device *device;
if (context == NULL)
return;
- device = context->dev_priv->device;
- trace_kgsl_context_detach(device, context);
- id = context->id;
- if (device->ftbl->drawctxt_destroy)
- device->ftbl->drawctxt_destroy(device, context);
- /*device specific drawctxt_destroy MUST clean up devctxt */
- BUG_ON(context->devctxt);
+ device = context->device;
+
+ /*
+ * Mark the context as detached to keep others from using
+ * the context before it gets fully removed, and to make sure
+ * we don't try to detach twice.
+ */
+ if (test_and_set_bit(KGSL_CONTEXT_DETACHED, &context->priv))
+ return;
+
+ trace_kgsl_context_detach(device, context);
+
+ device->ftbl->drawctxt_detach(context);
/*
* Cancel events after the device-specific context is
- * destroyed, to avoid possibly freeing memory while
+ * detached, to avoid possibly freeing memory while
* it is still in use by the GPU.
*/
kgsl_cancel_events_ctxt(device, context);
- write_lock(&device->context_lock);
- context->id = KGSL_CONTEXT_INVALID;
- idr_remove(&device->context_idr, id);
- write_unlock(&device->context_lock);
-
- context->dev_priv = NULL;
-
kgsl_context_put(context);
}
@@ -575,8 +574,19 @@
{
struct kgsl_context *context = container_of(kref, struct kgsl_context,
refcount);
+ struct kgsl_device *device = context->device;
+
+ trace_kgsl_context_destroy(device, context);
+
+ write_lock(&device->context_lock);
+ if (context->id != KGSL_CONTEXT_INVALID) {
+ idr_remove(&device->context_idr, context->id);
+ context->id = KGSL_CONTEXT_INVALID;
+ }
+ write_unlock(&device->context_lock);
kgsl_sync_timeline_destroy(context);
- kfree(context);
+
+ device->ftbl->drawctxt_destroy(context);
}
struct kgsl_device *kgsl_get_device(int dev_idx)
@@ -975,7 +985,7 @@
if (context == NULL)
break;
- if (context->dev_priv == dev_priv)
+ if (context->pid == private->pid)
kgsl_context_detach(context);
next = next + 1;
@@ -1623,27 +1633,16 @@
int result = 0;
struct kgsl_drawctxt_create *param = data;
struct kgsl_context *context = NULL;
+ struct kgsl_device *device = dev_priv->device;
- context = kgsl_create_context(dev_priv);
-
+ context = device->ftbl->drawctxt_create(dev_priv, ¶m->flags);
if (IS_ERR(context)) {
result = PTR_ERR(context);
goto done;
}
-
- if (dev_priv->device->ftbl->drawctxt_create) {
- result = dev_priv->device->ftbl->drawctxt_create(
- dev_priv->device, dev_priv->process_priv->pagetable,
- context, ¶m->flags);
- if (result)
- goto done;
- }
trace_kgsl_context_create(dev_priv->device, context, param->flags);
param->drawctxt_id = context->id;
done:
- if (result && !IS_ERR(context))
- kgsl_context_detach(context);
-
return result;
}
@@ -2600,7 +2599,7 @@
if (!entry)
return -EINVAL;
- kgsl_cffdump_syncmem(dev_priv, &entry->memdesc, param->gpuaddr,
+ kgsl_cffdump_syncmem(dev_priv->device, &entry->memdesc, param->gpuaddr,
param->len, true);
kgsl_mem_entry_put(entry);
diff --git a/drivers/gpu/msm/kgsl_cffdump.c b/drivers/gpu/msm/kgsl_cffdump.c
index b07a1cad..43bcc30 100644
--- a/drivers/gpu/msm/kgsl_cffdump.c
+++ b/drivers/gpu/msm/kgsl_cffdump.c
@@ -410,29 +410,19 @@
cffdump_printline(-1, cff_opcode, op1, op2, op3, op4, op5);
}
-void kgsl_cffdump_syncmem(struct kgsl_device_private *dev_priv,
- struct kgsl_memdesc *memdesc, uint gpuaddr, uint sizebytes,
- bool clean_cache)
+void kgsl_cffdump_syncmem(struct kgsl_device *device,
+ struct kgsl_memdesc *memdesc, uint gpuaddr,
+ uint sizebytes, bool clean_cache)
{
- struct kgsl_device *device = dev_priv->device;
const void *src;
if (!device->cff_dump_enable)
return;
+ BUG_ON(memdesc == NULL);
+
total_syncmem += sizebytes;
- if (memdesc == NULL) {
- struct kgsl_mem_entry *entry;
- entry = kgsl_sharedmem_find_region(dev_priv->process_priv,
- gpuaddr, sizebytes);
- if (entry == NULL) {
- KGSL_CORE_ERR("did not find mapping "
- "for gpuaddr: 0x%08x\n", gpuaddr);
- return;
- }
- memdesc = &entry->memdesc;
- }
src = (uint *)kgsl_gpuaddr_to_vaddr(memdesc, gpuaddr);
if (memdesc->hostptr == NULL) {
KGSL_CORE_ERR(
diff --git a/drivers/gpu/msm/kgsl_cffdump.h b/drivers/gpu/msm/kgsl_cffdump.h
index ab5a345..2852e0f 100644
--- a/drivers/gpu/msm/kgsl_cffdump.h
+++ b/drivers/gpu/msm/kgsl_cffdump.h
@@ -28,7 +28,7 @@
void kgsl_cffdump_destroy(void);
void kgsl_cffdump_open(struct kgsl_device *device);
void kgsl_cffdump_close(struct kgsl_device *device);
-void kgsl_cffdump_syncmem(struct kgsl_device_private *dev_priv,
+void kgsl_cffdump_syncmem(struct kgsl_device *,
struct kgsl_memdesc *memdesc, uint physaddr, uint sizebytes,
bool clean_cache);
void kgsl_cffdump_setmem(struct kgsl_device *device, uint addr,
@@ -74,7 +74,7 @@
return;
}
-static inline void kgsl_cffdump_syncmem(struct kgsl_device_private *dev_priv,
+static inline void kgsl_cffdump_syncmem(struct kgsl_device *device,
struct kgsl_memdesc *memdesc, uint physaddr, uint sizebytes,
bool clean_cache)
{
diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h
index d0e40db..1f8bcbe 100644
--- a/drivers/gpu/msm/kgsl_device.h
+++ b/drivers/gpu/msm/kgsl_device.h
@@ -15,6 +15,7 @@
#include <linux/idr.h>
#include <linux/pm_qos.h>
+#include <linux/sched.h>
#include "kgsl.h"
#include "kgsl_mmu.h"
@@ -103,11 +104,10 @@
calling the hook */
void (*setstate) (struct kgsl_device *device, unsigned int context_id,
uint32_t flags);
- int (*drawctxt_create) (struct kgsl_device *device,
- struct kgsl_pagetable *pagetable, struct kgsl_context *context,
- uint32_t *flags);
- void (*drawctxt_destroy) (struct kgsl_device *device,
- struct kgsl_context *context);
+ struct kgsl_context *(*drawctxt_create) (struct kgsl_device_private *,
+ uint32_t *flags);
+ void (*drawctxt_detach) (struct kgsl_context *context);
+ void (*drawctxt_destroy) (struct kgsl_context *context);
long (*ioctl) (struct kgsl_device_private *dev_priv,
unsigned int cmd, void *data);
int (*setproperty) (struct kgsl_device *device,
@@ -254,31 +254,44 @@
.ver_minor = DRIVER_VERSION_MINOR
+/* bits for struct kgsl_context.priv */
+/* the context has been destroyed by userspace and is no longer using the gpu */
+#define KGSL_CONTEXT_DETACHED 0
+/* the context has caused a pagefault */
+#define KGSL_CONTEXT_PAGEFAULT 1
+
/**
* struct kgsl_context - Master structure for a KGSL context object
- * @refcount - kref object for reference counting the context
- * @id - integer identifier for the context
- * @dev_priv - pointer to the owning device instance
- * @devctxt - pointer to the device specific context information
- * @reset_status - status indication whether a gpu reset occured and whether
+ * @refcount: kref object for reference counting the context
+ * @id: integer identifier for the context
+ * @priv: in-kernel context flags, use KGSL_CONTEXT_* values
+ * @dev_priv: pointer to the owning device instance
+ * @reset_status: status indication whether a gpu reset occured and whether
* this context was responsible for causing it
- * @wait_on_invalid_ts - flag indicating if this context has tried to wait on a
+ * @wait_on_invalid_ts: flag indicating if this context has tried to wait on a
* bad timestamp
- * @timeline - sync timeline used to create fences that can be signaled when a
+ * @timeline: sync timeline used to create fences that can be signaled when a
* sync_pt timestamp expires
- * @events - list head of pending events for this context
- * @events_list - list node for the list of all contexts that have pending events
+ * @events: list head of pending events for this context
+ * @events_list: list node for the list of all contexts that have pending events
+ * @pid: process that owns this context.
+ * @pagefault: flag set if this context caused a pagefault.
+ * @pagefault_ts: global timestamp of the pagefault, if KGSL_CONTEXT_PAGEFAULT
+ * is set.
*/
struct kgsl_context {
struct kref refcount;
uint32_t id;
- struct kgsl_device_private *dev_priv;
- void *devctxt;
+ pid_t pid;
+ unsigned long priv;
+ struct kgsl_device *device;
+ struct kgsl_pagetable *pagetable;
unsigned int reset_status;
bool wait_on_invalid_ts;
struct sync_timeline *timeline;
struct list_head events;
struct list_head events_list;
+ unsigned int pagefault_ts;
};
struct kgsl_process_private {
@@ -429,6 +442,9 @@
void kgsl_context_destroy(struct kref *kref);
+int kgsl_context_init(struct kgsl_device_private *, struct kgsl_context
+ *context);
+
/**
* kgsl_context_put() - Release context reference count
* @context: Pointer to the KGSL context to be released
@@ -442,6 +458,22 @@
if (context)
kref_put(&context->refcount, kgsl_context_destroy);
}
+
+/**
+ * kgsl_context_detached() - check if a context is detached
+ * @context: the context
+ *
+ * Check if a context has been destroyed by userspace and is only waiting
+ * for reference counts to go away. This check is used to weed out
+ * contexts that shouldn't use the gpu so NULL is considered detached.
+ */
+static inline bool kgsl_context_detached(struct kgsl_context *context)
+{
+ return (context == NULL || test_bit(KGSL_CONTEXT_DETACHED,
+ &context->priv));
+}
+
+
/**
* kgsl_context_get() - get a pointer to a KGSL context
* @device: Pointer to the KGSL device that owns the context
@@ -462,7 +494,10 @@
context = idr_find(&device->context_idr, id);
- if (context)
+ /* Don't return a context that has been detached */
+ if (kgsl_context_detached(context))
+ context = NULL;
+ else
kref_get(&context->refcount);
read_unlock(&device->context_lock);
@@ -471,6 +506,20 @@
}
/**
+* _kgsl_context_get() - lightweight function to just increment the ref count
+* @context: Pointer to the KGSL context
+*
+* Get a reference to the specified KGSL context structure. This is a
+* lightweight way to just increase the refcount on a known context rather than
+* walking through kgsl_context_get and searching the iterator
+*/
+static inline void _kgsl_context_get(struct kgsl_context *context)
+{
+ if (context)
+ kref_get(&context->refcount);
+}
+
+/**
* kgsl_context_get_owner() - get a pointer to a KGSL context in a specific
* process
* @dev_priv: Pointer to the process struct
@@ -489,8 +538,8 @@
context = kgsl_context_get(dev_priv->device, id);
- /* Verify that the context belongs to the dev_priv instance */
- if (context && context->dev_priv != dev_priv) {
+ /* Verify that the context belongs to current calling process. */
+ if (context != NULL && context->pid != dev_priv->process_priv->pid) {
kgsl_context_put(context);
return NULL;
}
diff --git a/drivers/gpu/msm/kgsl_events.c b/drivers/gpu/msm/kgsl_events.c
index 0b75175..40974b0 100644
--- a/drivers/gpu/msm/kgsl_events.c
+++ b/drivers/gpu/msm/kgsl_events.c
@@ -147,7 +147,7 @@
* Increment the refcount to avoid freeing the context while
* cancelling its events
*/
- kref_get(&context->refcount);
+ _kgsl_context_get(context);
/* Remove ourselves from the master pending list */
list_del_init(&context->events_list);
@@ -324,7 +324,7 @@
* Increment the refcount to make sure that the list_del_init
* is called with a valid context's list
*/
- kref_get(&context->refcount);
+ _kgsl_context_get(context);
/*
* If kgsl_timestamp_expired_context returns 0 then it no longer
* has any pending events and can be removed from the list
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
index ace6121..14aae9f 100644
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.c
@@ -38,6 +38,7 @@
static struct kgsl_iommu_register_list kgsl_iommuv0_reg[KGSL_IOMMU_REG_MAX] = {
{ 0, 0 }, /* GLOBAL_BASE */
+ { 0x0, 1 }, /* SCTLR */
{ 0x10, 1 }, /* TTBR0 */
{ 0x14, 1 }, /* TTBR1 */
{ 0x20, 1 }, /* FSR */
@@ -54,6 +55,7 @@
static struct kgsl_iommu_register_list kgsl_iommuv1_reg[KGSL_IOMMU_REG_MAX] = {
{ 0, 0 }, /* GLOBAL_BASE */
+ { 0x0, 1 }, /* SCTLR */
{ 0x20, 1 }, /* TTBR0 */
{ 0x28, 1 }, /* TTBR1 */
{ 0x58, 1 }, /* FSR */
@@ -325,7 +327,7 @@
unsigned int no_page_fault_log = 0;
unsigned int curr_context_id = 0;
unsigned int curr_global_ts = 0;
- static struct kgsl_context *context;
+ struct kgsl_context *context;
ret = get_iommu_unit(dev, &mmu, &iommu_unit);
if (ret)
@@ -399,23 +401,16 @@
context = kgsl_context_get(device, curr_context_id);
if (context != NULL) {
- struct adreno_context *drawctxt = context->devctxt;
-
kgsl_sharedmem_readl(&device->memstore, &curr_global_ts,
KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
eoptimestamp));
- /*
- * Store pagefault's timestamp in adreno context,
- * this information will be used in GFT
- */
-
- if (drawctxt != NULL) {
- drawctxt->pagefault = 1;
- drawctxt->pagefault_ts = curr_global_ts;
- }
+ /* save pagefault timestamp for GFT */
+ set_bit(KGSL_CONTEXT_PAGEFAULT, &context->priv);
+ context->pagefault_ts = curr_global_ts;
kgsl_context_put(context);
+ context = NULL;
}
trace_kgsl_mmu_pagefault(iommu_dev->kgsldev, addr,
@@ -1581,6 +1576,8 @@
int status;
struct kgsl_iommu *iommu = mmu->priv;
int i, j;
+ int sctlr_val = 0;
+ struct adreno_device *adreno_dev = ADRENO_DEVICE(mmu->device);
if (mmu->flags & KGSL_FLAGS_STARTED)
return 0;
@@ -1632,6 +1629,25 @@
for (i = 0; i < iommu->unit_count; i++) {
struct kgsl_iommu_unit *iommu_unit = &iommu->iommu_units[i];
for (j = 0; j < iommu_unit->dev_count; j++) {
+
+ /*
+ * For IOMMU V1 do not halt IOMMU on pagefault if
+ * FT pagefault policy is set accordingly
+ */
+ if ((!msm_soc_version_supports_iommu_v0()) &&
+ (!(adreno_dev->ft_pf_policy &
+ KGSL_FT_PAGEFAULT_GPUHALT_ENABLE))) {
+ sctlr_val = KGSL_IOMMU_GET_CTX_REG(iommu,
+ iommu_unit,
+ iommu_unit->dev[j].ctx_id,
+ SCTLR);
+ sctlr_val |= (0x1 <<
+ KGSL_IOMMU_SCTLR_HUPCF_SHIFT);
+ KGSL_IOMMU_SET_CTX_REG(iommu,
+ iommu_unit,
+ iommu_unit->dev[j].ctx_id,
+ SCTLR, sctlr_val);
+ }
if (sizeof(phys_addr_t) > sizeof(unsigned long)) {
iommu_unit->dev[j].default_ttbr0 =
KGSL_IOMMU_GET_CTX_REG_LL(iommu,
diff --git a/drivers/gpu/msm/kgsl_iommu.h b/drivers/gpu/msm/kgsl_iommu.h
index 5c4b17e..7dca40e 100644
--- a/drivers/gpu/msm/kgsl_iommu.h
+++ b/drivers/gpu/msm/kgsl_iommu.h
@@ -61,8 +61,12 @@
#define KGSL_IOMMU_IMPLDEF_MICRO_MMU_CTRL_HALT BIT(2)
#define KGSL_IOMMU_IMPLDEF_MICRO_MMU_CTRL_IDLE BIT(3)
+/* SCTLR fields */
+#define KGSL_IOMMU_SCTLR_HUPCF_SHIFT 8
+
enum kgsl_iommu_reg_map {
KGSL_IOMMU_GLOBAL_BASE = 0,
+ KGSL_IOMMU_CTX_SCTLR,
KGSL_IOMMU_CTX_TTBR0,
KGSL_IOMMU_CTX_TTBR1,
KGSL_IOMMU_CTX_FSR,
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c
index 5e6d24b..20391be 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.c
+++ b/drivers/gpu/msm/kgsl_pwrctrl.c
@@ -1214,6 +1214,11 @@
}
}
+bool kgsl_pwrctrl_isenabled(struct kgsl_device *device)
+{
+ struct kgsl_pwrctrl *pwr = &device->pwrctrl;
+ return (test_bit(KGSL_PWRFLAGS_CLK_ON, &pwr->power_flags) != 0);
+}
/**
* kgsl_pre_hwaccess - Enforce preconditions for touching registers
@@ -1230,7 +1235,7 @@
/* In order to touch a register you must hold the device mutex...*/
BUG_ON(!mutex_is_locked(&device->mutex));
/* and have the clock on! */
- BUG_ON(!test_bit(KGSL_PWRFLAGS_CLK_ON, &device->pwrctrl.power_flags));
+ BUG_ON(!kgsl_pwrctrl_isenabled(device));
}
EXPORT_SYMBOL(kgsl_pre_hwaccess);
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.h b/drivers/gpu/msm/kgsl_pwrctrl.h
index 3bf65ee..b7d9226 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.h
+++ b/drivers/gpu/msm/kgsl_pwrctrl.h
@@ -110,6 +110,8 @@
void kgsl_pwrctrl_uninit_sysfs(struct kgsl_device *device);
void kgsl_pwrctrl_enable(struct kgsl_device *device);
void kgsl_pwrctrl_disable(struct kgsl_device *device);
+bool kgsl_pwrctrl_isenabled(struct kgsl_device *device);
+
static inline unsigned long kgsl_get_clkrate(struct clk *clk)
{
return (clk != NULL) ? clk_get_rate(clk) : 0;
diff --git a/drivers/gpu/msm/kgsl_snapshot.c b/drivers/gpu/msm/kgsl_snapshot.c
index 35f24d9..6094e04 100644
--- a/drivers/gpu/msm/kgsl_snapshot.c
+++ b/drivers/gpu/msm/kgsl_snapshot.c
@@ -109,7 +109,7 @@
struct kgsl_device *device;
if (context)
- device = context->dev_priv->device;
+ device = context->device;
else
device = (struct kgsl_device *)data;
diff --git a/drivers/gpu/msm/kgsl_sync.c b/drivers/gpu/msm/kgsl_sync.c
index 1853996c..62ecdeb 100644
--- a/drivers/gpu/msm/kgsl_sync.c
+++ b/drivers/gpu/msm/kgsl_sync.c
@@ -239,7 +239,7 @@
char ktimeline_name[sizeof(context->timeline->name)] = {};
snprintf(ktimeline_name, sizeof(ktimeline_name),
"%s_%.15s(%d)-%.15s(%d)-%d",
- context->dev_priv->device->name,
+ context->device->name,
current->group_leader->comm, current->group_leader->pid,
current->comm, current->pid, context->id);
@@ -250,7 +250,7 @@
ktimeline = (struct kgsl_sync_timeline *) context->timeline;
ktimeline->last_timestamp = 0;
- ktimeline->device = context->dev_priv->device;
+ ktimeline->device = context->device;
ktimeline->context_id = context->id;
return 0;
diff --git a/drivers/gpu/msm/kgsl_trace.h b/drivers/gpu/msm/kgsl_trace.h
index abb7c35..5981163 100644
--- a/drivers/gpu/msm/kgsl_trace.h
+++ b/drivers/gpu/msm/kgsl_trace.h
@@ -678,6 +678,28 @@
)
);
+TRACE_EVENT(kgsl_context_destroy,
+
+ TP_PROTO(struct kgsl_device *device, struct kgsl_context *context),
+
+ TP_ARGS(device, context),
+
+ TP_STRUCT__entry(
+ __string(device_name, device->name)
+ __field(unsigned int, id)
+ ),
+
+ TP_fast_assign(
+ __assign_str(device_name, device->name);
+ __entry->id = context->id;
+ ),
+
+ TP_printk(
+ "d_name=%s ctx=%u",
+ __get_str(device_name), __entry->id
+ )
+);
+
TRACE_EVENT(kgsl_mmu_pagefault,
TP_PROTO(struct kgsl_device *device, unsigned int page,
diff --git a/drivers/gpu/msm/z180.c b/drivers/gpu/msm/z180.c
index cc1819d..883417f 100644
--- a/drivers/gpu/msm/z180.c
+++ b/drivers/gpu/msm/z180.c
@@ -859,11 +859,30 @@
return status;
}
-static void
-z180_drawctxt_destroy(struct kgsl_device *device,
- struct kgsl_context *context)
+struct kgsl_context *
+z180_drawctxt_create(struct kgsl_device_private *dev_priv,
+ uint32_t *flags)
{
- struct z180_device *z180_dev = Z180_DEVICE(device);
+ int ret;
+ struct kgsl_context *context = kzalloc(sizeof(*context), GFP_KERNEL);
+ if (context == NULL)
+ return ERR_PTR(-ENOMEM);
+ ret = kgsl_context_init(dev_priv, context);
+ if (ret != 0) {
+ kfree(context);
+ return ERR_PTR(ret);
+ }
+ return context;
+}
+
+static void
+z180_drawctxt_detach(struct kgsl_context *context)
+{
+ struct kgsl_device *device;
+ struct z180_device *z180_dev;
+
+ device = context->device;
+ z180_dev = Z180_DEVICE(device);
z180_idle(device);
@@ -875,6 +894,12 @@
}
}
+static void
+z180_drawctxt_destroy(struct kgsl_context *context)
+{
+ kfree(context);
+}
+
static void z180_power_stats(struct kgsl_device *device,
struct kgsl_power_stats *stats)
{
@@ -941,7 +966,8 @@
.gpuid = z180_gpuid,
.irq_handler = z180_irq_handler,
/* Optional functions */
- .drawctxt_create = NULL,
+ .drawctxt_create = z180_drawctxt_create,
+ .drawctxt_detach = z180_drawctxt_detach,
.drawctxt_destroy = z180_drawctxt_destroy,
.ioctl = NULL,
.postmortem_dump = z180_dump,
diff --git a/drivers/hwmon/epm_adc.c b/drivers/hwmon/epm_adc.c
index a587ed2..a309ceb 100644
--- a/drivers/hwmon/epm_adc.c
+++ b/drivers/hwmon/epm_adc.c
@@ -65,6 +65,8 @@
#define EPM_ADC_MILLI_VOLTS_SOURCE 4750
#define EPM_ADC_SCALE_FACTOR 64
#define GPIO_EPM_GLOBAL_ENABLE 86
+#define GPIO_EPM_MARKER1 85
+#define GPIO_EPM_MARKER2 96
#define EPM_ADC_CONVERSION_TIME_MIN 50000
#define EPM_ADC_CONVERSION_TIME_MAX 51000
/* PSoc Commands */
@@ -715,6 +717,56 @@
return 0;
}
+static int epm_set_marker1(struct epm_marker_level *marker_init)
+{
+ int rc = 0;
+
+ rc = gpio_request(GPIO_EPM_MARKER1, "EPM_MARKER1");
+ if (!rc) {
+ gpio_direction_output(GPIO_EPM_MARKER1, 1);
+ } else {
+ pr_err("%s: Configure MARKER1 GPIO Failed\n",
+ __func__);
+ return rc;
+ }
+
+ gpio_set_value(GPIO_EPM_MARKER1, marker_init->level);
+
+ return 0;
+}
+
+static int epm_set_marker2(struct epm_marker_level *marker_init)
+{
+ int rc = 0;
+
+ rc = gpio_request(GPIO_EPM_MARKER2, "EPM_MARKER2");
+ if (!rc) {
+ gpio_direction_output(GPIO_EPM_MARKER2, 1);
+ } else {
+ pr_err("%s: Configure MARKER2 GPIO Failed\n",
+ __func__);
+ return rc;
+ }
+
+ gpio_set_value(GPIO_EPM_MARKER2, marker_init->level);
+
+ return 0;
+}
+
+static int epm_marker1_release(void)
+{
+ gpio_free(GPIO_EPM_MARKER1);
+
+ return 0;
+}
+
+static int epm_marker2_release(void)
+{
+ gpio_free(GPIO_EPM_MARKER2);
+
+ return 0;
+}
+
static int epm_psoc_init(struct epm_adc_drv *epm_adc,
struct epm_psoc_init_resp *init_resp)
{
@@ -1296,6 +1348,58 @@
return -EFAULT;
break;
}
+ case EPM_MARKER1_REQUEST:
+ {
+ struct epm_marker_level marker_init;
+ uint32_t result;
+
+ if (copy_from_user(&marker_init, (void __user *)arg,
+ sizeof(struct epm_marker_level)))
+ return -EFAULT;
+
+ result = epm_set_marker1(&marker_init);
+
+ if (copy_to_user((void __user *)arg, &result,
+ sizeof(uint32_t)))
+ return -EFAULT;
+ break;
+ }
+ case EPM_MARKER2_REQUEST:
+ {
+ struct epm_marker_level marker_init;
+ uint32_t result;
+
+ if (copy_from_user(&marker_init, (void __user *)arg,
+ sizeof(struct epm_marker_level)))
+ return -EFAULT;
+
+ result = epm_set_marker2(&marker_init);
+
+ if (copy_to_user((void __user *)arg, &result,
+ sizeof(uint32_t)))
+ return -EFAULT;
+ break;
+ }
+ case EPM_MARKER1_RELEASE:
+ {
+ uint32_t result;
+ result = epm_marker1_release();
+
+ if (copy_to_user((void __user *)arg, &result,
+ sizeof(uint32_t)))
+ return -EFAULT;
+ break;
+ }
+ case EPM_MARKER2_RELEASE:
+ {
+ uint32_t result;
+ result = epm_marker2_release();
+
+ if (copy_to_user((void __user *)arg, &result,
+ sizeof(uint32_t)))
+ return -EFAULT;
+ break;
+ }
case EPM_PSOC_ADC_INIT:
{
struct epm_psoc_init_resp psoc_init;
@@ -1312,11 +1416,29 @@
return -EINVAL;
}
+ if (!rc) {
+ rc = epm_adc_psoc_gpio_init(true);
+ if (rc) {
+ pr_err("GPIO init failed\n");
+ return -EINVAL;
+ }
+ }
+
if (copy_to_user((void __user *)arg, &psoc_init,
sizeof(struct epm_psoc_init_resp)))
return -EFAULT;
break;
}
+ case EPM_PSOC_ADC_DEINIT:
+ {
+ uint32_t result;
+ result = epm_adc_psoc_gpio_init(false);
+
+ if (copy_to_user((void __user *)arg, &result,
+ sizeof(uint32_t)))
+ return -EFAULT;
+ break;
+ }
case EPM_PSOC_ADC_CHANNEL_ENABLE:
case EPM_PSOC_ADC_CHANNEL_DISABLE:
{
diff --git a/drivers/hwmon/qpnp-adc-common.c b/drivers/hwmon/qpnp-adc-common.c
index 8e350f0..4e77ca2 100644
--- a/drivers/hwmon/qpnp-adc-common.c
+++ b/drivers/hwmon/qpnp-adc-common.c
@@ -923,8 +923,12 @@
pr_err("Invalid channel fast average setup\n");
return -EINVAL;
}
- calibration_param = of_get_property(child,
- "qcom,calibration-type", NULL);
+ rc = of_property_read_string(child, "qcom,calibration-type",
+ &calibration_param);
+ if (rc) {
+ pr_err("Invalid calibration type\n");
+ return -EINVAL;
+ }
if (!strncmp(calibration_param, "absolute", 8))
calib_type = CALIB_ABSOLUTE;
else if (!strncmp(calibration_param, "ratiometric", 11))
diff --git a/drivers/hwmon/qpnp-adc-current.c b/drivers/hwmon/qpnp-adc-current.c
index 9570327..27818b4 100644
--- a/drivers/hwmon/qpnp-adc-current.c
+++ b/drivers/hwmon/qpnp-adc-current.c
@@ -530,6 +530,9 @@
uint16_t raw_data;
uint32_t mode_sel = 0;
+ if (!iadc || !iadc->iadc_initialized)
+ return -EPROBE_DEFER;
+
mutex_lock(&iadc->adc->adc_lock);
rc = qpnp_iadc_configure(GAIN_CALIBRATION_17P857MV,
@@ -541,11 +544,22 @@
iadc->adc->calib.gain_raw = raw_data;
- rc = qpnp_iadc_configure(OFFSET_CALIBRATION_CSP2_CSN2,
+ if (iadc->external_rsense) {
+ /* external offset calculation */
+ rc = qpnp_iadc_configure(OFFSET_CALIBRATION_CSP_CSN,
&raw_data, mode_sel);
- if (rc < 0) {
- pr_err("qpnp adc result read failed with %d\n", rc);
- goto fail;
+ if (rc < 0) {
+ pr_err("qpnp adc result read failed with %d\n", rc);
+ goto fail;
+ }
+ } else {
+ /* internal offset calculation */
+ rc = qpnp_iadc_configure(OFFSET_CALIBRATION_CSP2_CSN2,
+ &raw_data, mode_sel);
+ if (rc < 0) {
+ pr_err("qpnp adc result read failed with %d\n", rc);
+ goto fail;
+ }
}
iadc->adc->calib.offset_raw = raw_data;
diff --git a/drivers/hwmon/qpnp-adc-voltage.c b/drivers/hwmon/qpnp-adc-voltage.c
index 309944e..53e43d1 100644
--- a/drivers/hwmon/qpnp-adc-voltage.c
+++ b/drivers/hwmon/qpnp-adc-voltage.c
@@ -866,6 +866,11 @@
amux_prescaling =
vadc->adc->adc_channels[dt_index].chan_path_prescaling;
+ if (amux_prescaling >= PATH_SCALING_NONE) {
+ rc = -EINVAL;
+ goto fail_unlock;
+ }
+
vadc->adc->amux_prop->chan_prop->offset_gain_numerator =
qpnp_vadc_amux_scaling_ratio[amux_prescaling].num;
vadc->adc->amux_prop->chan_prop->offset_gain_denominator =
@@ -1016,6 +1021,11 @@
amux_prescaling =
vadc->adc->adc_channels[dt_index].chan_path_prescaling;
+ if (amux_prescaling >= PATH_SCALING_NONE) {
+ rc = -EINVAL;
+ goto fail;
+ }
+
vadc->adc->amux_prop->chan_prop->offset_gain_numerator =
qpnp_vadc_amux_scaling_ratio[amux_prescaling].num;
vadc->adc->amux_prop->chan_prop->offset_gain_denominator =
diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index b96349e..74a252f 100644
--- a/drivers/i2c/busses/i2c-qup.c
+++ b/drivers/i2c/busses/i2c-qup.c
@@ -1385,7 +1385,8 @@
qup_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM,
"qup_phys_addr");
if (!qup_mem) {
- dev_err(&pdev->dev, "no qup mem resource?\n");
+ dev_err(&pdev->dev,
+ "platform_get_resource_byname(qup_phys_addr) failed\n");
ret = -ENODEV;
goto get_res_failed;
}
@@ -1655,11 +1656,22 @@
return ret;
}
+static void qup_i2c_mem_release(struct platform_device *pdev, const char *name)
+{
+ struct resource *res =
+ platform_get_resource_byname(pdev, IORESOURCE_MEM, name);
+
+ if (res)
+ release_mem_region(res->start, resource_size(res));
+ else
+ dev_dbg(&pdev->dev,
+ "platform_get_resource_byname(%s) failed\n", name);
+}
+
static int __devexit
qup_i2c_remove(struct platform_device *pdev)
{
- struct qup_i2c_dev *dev = platform_get_drvdata(pdev);
- struct resource *qup_mem, *gsbi_mem;
+ struct qup_i2c_dev *dev = platform_get_drvdata(pdev);
/* Grab mutex to ensure ongoing transaction is over */
mutex_lock(&dev->mlock);
@@ -1693,14 +1705,11 @@
pm_runtime_disable(&pdev->dev);
pm_runtime_set_suspended(&pdev->dev);
- if (!(dev->pdata->use_gsbi_shared_mode)) {
- gsbi_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM,
- "gsbi_qup_i2c_addr");
- release_mem_region(gsbi_mem->start, resource_size(gsbi_mem));
- }
- qup_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM,
- "qup_phys_addr");
- release_mem_region(qup_mem->start, resource_size(qup_mem));
+ if (!(dev->pdata->use_gsbi_shared_mode))
+ qup_i2c_mem_release(pdev, "gsbi_qup_i2c_addr");
+
+ qup_i2c_mem_release(pdev, "qup_phys_addr");
+
if (dev->dev->of_node)
kfree(dev->pdata);
kfree(dev);
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index 1464dab..a052bd3 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -654,4 +654,42 @@
If you say yes here you get support for STMicroelectronics's
acceleration sensors LIS3DH.
+config BMP18X
+ tristate "BMP18X digital pressure sensor"
+ depends on (I2C ) && SYSFS
+ help
+ If you say yes here you get support for Bosch Sensortec
+ digital pressure sensors BMP085, BMP180.
+
+ To compile this driver as a module, choose M here: the
+ module will be called bmp18x-core.
+
+config BMP18X_I2C
+ tristate "support I2C bus connection"
+ depends on BMP18X && I2C
+ help
+ Say Y here if you want to support Bosch Sensortec digital pressure
+ sensor hooked to an I2C bus.
+
+ To compile this driver as a module, choose M here: the
+ module will be called bmp18x-i2c.
+
+config SENSORS_MMA8X5X
+ tristate "MMA8451/MMA8452/MMA8453/MMA8652/MMA8653 device driver"
+ depends on I2C && SYSFS
+ select INPUT_POLLDEV
+ default n
+ help
+ If you say yes here you get support for the Freescale MMA8451/
+ MMA8452/MMA8453/MMA8652/MMA8653 sensors.
+
+ To compile this driver as a module, choose M here: the
+ module will be called mma8x5x.
+
+config SENSORS_MMA_POSITION
+ int "MMA8x5x Accelerate Sensor Position Setting"
+ depends on SENSORS_MMA8X5X
+ default "0"
+ help
+ this provide the sensor position setting , value is between 0~7
endif
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index 96c9288..4f29e05 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -61,3 +61,6 @@
obj-$(CONFIG_INPUT_PMIC8058_VIBRA_MEMLESS) += pmic8058-vib-memless.o
obj-$(CONFIG_BOSCH_BMA150) += bma150.o
obj-$(CONFIG_STM_LIS3DH) += lis3dh_acc.o
+obj-$(CONFIG_BMP18X) += bmp18x-core.o
+obj-$(CONFIG_BMP18X_I2C) += bmp18x-i2c.o
+obj-$(CONFIG_SENSORS_MMA8X5X) += mma8x5x.o
diff --git a/drivers/input/misc/bmp18x-core.c b/drivers/input/misc/bmp18x-core.c
new file mode 100644
index 0000000..4b5b710
--- /dev/null
+++ b/drivers/input/misc/bmp18x-core.c
@@ -0,0 +1,705 @@
+/* Copyright (c) 2011 Bosch Sensortec GmbH
+ Copyright (c) 2011 Unixphere
+
+ Based on:
+ BMP085 driver, bmp085.c
+ Copyright (c) 2010 Christoph Mair <christoph.mair@gmail.com>
+
+ This driver supports the bmp18x digital barometric pressure
+ and temperature sensors from Bosch Sensortec.
+
+ A pressure measurement is issued by reading from pressure0_input.
+ The return value ranges from 30000 to 110000 pascal with a resulution
+ of 1 pascal (0.01 millibar) which enables measurements from 9000m above
+ to 500m below sea level.
+
+ The temperature can be read from temp0_input. Values range from
+ -400 to 850 representing the ambient temperature in degree celsius
+ multiplied by 10.The resolution is 0.1 celsius.
+
+ Because ambient pressure is temperature dependent, a temperature
+ measurement will be executed automatically even if the user is reading
+ from pressure0_input. This happens if the last temperature measurement
+ has been executed more then one second ago.
+
+ To decrease RMS noise from pressure measurements, the bmp18x can
+ autonomously calculate the average of up to eight samples. This is
+ set up by writing to the oversampling sysfs file. Accepted values
+ are 0, 1, 2 and 3. 2^x when x is the value written to this file
+ specifies the number of samples used to calculate the ambient pressure.
+ RMS noise is specified with six pascal (without averaging) and decreases
+ down to 3 pascal when using an oversampling setting of 3.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/input.h>
+#include <linux/workqueue.h>
+#include <linux/module.h>
+#ifdef CONFIG_HAS_EARLYSUSPEND
+#include <linux/earlysuspend.h>
+#endif
+#include "bmp18x.h"
+
+#define BMP18X_CHIP_ID 0x55
+
+#define BMP18X_CALIBRATION_DATA_START 0xAA
+#define BMP18X_CALIBRATION_DATA_LENGTH 11 /* 16 bit values */
+#define BMP18X_CHIP_ID_REG 0xD0
+#define BMP18X_CTRL_REG 0xF4
+#define BMP18X_TEMP_MEASUREMENT 0x2E
+#define BMP18X_PRESSURE_MEASUREMENT 0x34
+#define BMP18X_CONVERSION_REGISTER_MSB 0xF6
+#define BMP18X_CONVERSION_REGISTER_LSB 0xF7
+#define BMP18X_CONVERSION_REGISTER_XLSB 0xF8
+#define BMP18X_TEMP_CONVERSION_TIME 5
+
+#define ABS_MIN_PRESSURE 30000
+#define ABS_MAX_PRESSURE 120000
+#define BMP_DELAY_DEFAULT 200
+
+struct bmp18x_calibration_data {
+ s16 AC1, AC2, AC3;
+ u16 AC4, AC5, AC6;
+ s16 B1, B2;
+ s16 MB, MC, MD;
+};
+
+/* Each client has this additional data */
+struct bmp18x_data {
+ struct bmp18x_data_bus data_bus;
+ struct device *dev;
+ struct mutex lock;
+ struct bmp18x_calibration_data calibration;
+ u8 oversampling_setting;
+ u8 sw_oversampling_setting;
+ u32 raw_temperature;
+ u32 raw_pressure;
+ u32 temp_measurement_period;
+ u32 last_temp_measurement;
+ s32 b6; /* calculated temperature correction coefficient */
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ struct early_suspend early_suspend;
+#endif
+ struct input_dev *input;
+ struct delayed_work work;
+ u32 delay;
+ u32 enable;
+};
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void bmp18x_early_suspend(struct early_suspend *h);
+static void bmp18x_late_resume(struct early_suspend *h);
+#endif
+
+static s32 bmp18x_read_calibration_data(struct bmp18x_data *data)
+{
+ u16 tmp[BMP18X_CALIBRATION_DATA_LENGTH];
+ struct bmp18x_calibration_data *cali = &(data->calibration);
+ s32 status = data->data_bus.bops->read_block(data->data_bus.client,
+ BMP18X_CALIBRATION_DATA_START,
+ BMP18X_CALIBRATION_DATA_LENGTH*sizeof(u16),
+ (u8 *)tmp);
+ if (status < 0)
+ return status;
+
+ if (status != BMP18X_CALIBRATION_DATA_LENGTH*sizeof(u16))
+ return -EIO;
+
+ cali->AC1 = be16_to_cpu(tmp[0]);
+ cali->AC2 = be16_to_cpu(tmp[1]);
+ cali->AC3 = be16_to_cpu(tmp[2]);
+ cali->AC4 = be16_to_cpu(tmp[3]);
+ cali->AC5 = be16_to_cpu(tmp[4]);
+ cali->AC6 = be16_to_cpu(tmp[5]);
+ cali->B1 = be16_to_cpu(tmp[6]);
+ cali->B2 = be16_to_cpu(tmp[7]);
+ cali->MB = be16_to_cpu(tmp[8]);
+ cali->MC = be16_to_cpu(tmp[9]);
+ cali->MD = be16_to_cpu(tmp[10]);
+ return 0;
+}
+
+
+static s32 bmp18x_update_raw_temperature(struct bmp18x_data *data)
+{
+ u16 tmp;
+ s32 status;
+
+ mutex_lock(&data->lock);
+ status = data->data_bus.bops->write_byte(data->data_bus.client,
+ BMP18X_CTRL_REG, BMP18X_TEMP_MEASUREMENT);
+ if (status != 0) {
+ dev_err(data->dev,
+ "Error while requesting temperature measurement.\n");
+ goto exit;
+ }
+ msleep(BMP18X_TEMP_CONVERSION_TIME);
+
+ status = data->data_bus.bops->read_block(data->data_bus.client,
+ BMP18X_CONVERSION_REGISTER_MSB, sizeof(tmp), (u8 *)&tmp);
+ if (status < 0)
+ goto exit;
+ if (status != sizeof(tmp)) {
+ dev_err(data->dev,
+ "Error while reading temperature measurement result\n");
+ status = -EIO;
+ goto exit;
+ }
+ data->raw_temperature = be16_to_cpu(tmp);
+ data->last_temp_measurement = jiffies;
+ status = 0; /* everything ok, return 0 */
+
+exit:
+ mutex_unlock(&data->lock);
+ return status;
+}
+
+static s32 bmp18x_update_raw_pressure(struct bmp18x_data *data)
+{
+ u32 tmp = 0;
+ s32 status;
+
+ mutex_lock(&data->lock);
+ status = data->data_bus.bops->write_byte(data->data_bus.client,
+ BMP18X_CTRL_REG, BMP18X_PRESSURE_MEASUREMENT +
+ (data->oversampling_setting<<6));
+ if (status != 0) {
+ dev_err(data->dev,
+ "Error while requesting pressure measurement.\n");
+ goto exit;
+ }
+
+ /* wait for the end of conversion */
+ msleep(2+(3 << data->oversampling_setting));
+
+ /* copy data into a u32 (4 bytes), but skip the first byte. */
+ status = data->data_bus.bops->read_block(data->data_bus.client,
+ BMP18X_CONVERSION_REGISTER_MSB, 3, ((u8 *)&tmp)+1);
+ if (status < 0)
+ goto exit;
+ if (status != 3) {
+ dev_err(data->dev,
+ "Error while reading pressure measurement results\n");
+ status = -EIO;
+ goto exit;
+ }
+ data->raw_pressure = be32_to_cpu((tmp));
+ data->raw_pressure >>= (8-data->oversampling_setting);
+ status = 0; /* everything ok, return 0 */
+
+exit:
+ mutex_unlock(&data->lock);
+ return status;
+}
+
+
+/*
+ * This function starts the temperature measurement and returns the value
+ * in tenth of a degree celsius.
+ */
+static s32 bmp18x_get_temperature(struct bmp18x_data *data, int *temperature)
+{
+ struct bmp18x_calibration_data *cali = &data->calibration;
+ long x1, x2;
+ int status;
+
+ status = bmp18x_update_raw_temperature(data);
+ if (status != 0)
+ goto exit;
+
+ x1 = ((data->raw_temperature - cali->AC6) * cali->AC5) >> 15;
+ x2 = (cali->MC << 11) / (x1 + cali->MD);
+ data->b6 = x1 + x2 - 4000;
+ /* if NULL just update b6. Used for pressure only measurements */
+ if (temperature != NULL)
+ *temperature = (x1+x2+8) >> 4;
+
+exit:
+ return status;
+}
+
+/*
+ * This function starts the pressure measurement and returns the value
+ * in millibar. Since the pressure depends on the ambient temperature,
+ * a temperature measurement is executed according to the given temperature
+ * measurememt period (default is 1 sec boundary). This period could vary
+ * and needs to be adjusted accoring to the sensor environment, i.e. if big
+ * temperature variations then the temperature needs to be read out often.
+ */
+static s32 bmp18x_get_pressure(struct bmp18x_data *data, int *pressure)
+{
+ struct bmp18x_calibration_data *cali = &data->calibration;
+ s32 x1, x2, x3, b3;
+ u32 b4, b7;
+ s32 p;
+ int status;
+ int i_loop, i;
+ u32 p_tmp;
+
+ /* update the ambient temperature according to the given meas. period */
+ if (data->last_temp_measurement +
+ data->temp_measurement_period < jiffies) {
+ status = bmp18x_get_temperature(data, NULL);
+ if (status != 0)
+ goto exit;
+ }
+
+ if ((data->oversampling_setting == 3)
+ && (data->sw_oversampling_setting == 1)) {
+ i_loop = 3;
+ } else {
+ i_loop = 1;
+ }
+
+ p_tmp = 0;
+ for (i = 0; i < i_loop; i++) {
+ status = bmp18x_update_raw_pressure(data);
+ if (status != 0)
+ goto exit;
+ p_tmp += data->raw_pressure;
+ }
+
+ data->raw_pressure = (p_tmp + (i_loop >> 1)) / i_loop;
+
+ x1 = (data->b6 * data->b6) >> 12;
+ x1 *= cali->B2;
+ x1 >>= 11;
+
+ x2 = cali->AC2 * data->b6;
+ x2 >>= 11;
+
+ x3 = x1 + x2;
+
+ b3 = (((((s32)cali->AC1) * 4 + x3) << data->oversampling_setting) + 2);
+ b3 >>= 2;
+
+ x1 = (cali->AC3 * data->b6) >> 13;
+ x2 = (cali->B1 * ((data->b6 * data->b6) >> 12)) >> 16;
+ x3 = (x1 + x2 + 2) >> 2;
+ b4 = (cali->AC4 * (u32)(x3 + 32768)) >> 15;
+
+ b7 = ((u32)data->raw_pressure - b3) *
+ (50000 >> data->oversampling_setting);
+ p = ((b7 < 0x80000000) ? ((b7 << 1) / b4) : ((b7 / b4) * 2));
+
+ x1 = p >> 8;
+ x1 *= x1;
+ x1 = (x1 * 3038) >> 16;
+ x2 = (-7357 * p) >> 16;
+ p += (x1 + x2 + 3791) >> 4;
+
+ *pressure = p;
+
+exit:
+ return status;
+}
+
+/*
+ * This function sets the chip-internal oversampling. Valid values are 0..3.
+ * The chip will use 2^oversampling samples for internal averaging.
+ * This influences the measurement time and the accuracy; larger values
+ * increase both. The datasheet gives on overview on how measurement time,
+ * accuracy and noise correlate.
+ */
+static void bmp18x_set_oversampling(struct bmp18x_data *data,
+ unsigned char oversampling)
+{
+ if (oversampling > 3)
+ oversampling = 3;
+ data->oversampling_setting = oversampling;
+}
+
+/*
+ * Returns the currently selected oversampling. Range: 0..3
+ */
+static unsigned char bmp18x_get_oversampling(struct bmp18x_data *data)
+{
+ return data->oversampling_setting;
+}
+
+/* sysfs callbacks */
+static ssize_t set_oversampling(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct bmp18x_data *data = dev_get_drvdata(dev);
+ unsigned long oversampling;
+ int success = kstrtoul(buf, 10, &oversampling);
+ if (success == 0) {
+ mutex_lock(&data->lock);
+ bmp18x_set_oversampling(data, oversampling);
+ if (oversampling != 3)
+ data->sw_oversampling_setting = 0;
+ mutex_unlock(&data->lock);
+ return count;
+ }
+ return success;
+}
+
+static ssize_t show_oversampling(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct bmp18x_data *data = dev_get_drvdata(dev);
+ return snprintf(buf, PAGE_SIZE,
+ "%u\n", bmp18x_get_oversampling(data));
+}
+static DEVICE_ATTR(oversampling, S_IWUSR | S_IRUGO,
+ show_oversampling, set_oversampling);
+
+static ssize_t set_sw_oversampling(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct bmp18x_data *data = dev_get_drvdata(dev);
+ unsigned long sw_oversampling;
+ int success = kstrtoul(buf, 10, &sw_oversampling);
+ if (success == 0) {
+ mutex_lock(&data->lock);
+ data->sw_oversampling_setting = sw_oversampling ? 1 : 0;
+ mutex_unlock(&data->lock);
+ }
+ return success;
+}
+
+static ssize_t show_sw_oversampling(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct bmp18x_data *data = dev_get_drvdata(dev);
+ return snprintf(buf, PAGE_SIZE,
+ "%u\n", data->sw_oversampling_setting);
+}
+static DEVICE_ATTR(sw_oversampling, S_IWUSR | S_IRUGO,
+ show_sw_oversampling, set_sw_oversampling);
+
+static ssize_t show_delay(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct bmp18x_data *data = dev_get_drvdata(dev);
+ return snprintf(buf, PAGE_SIZE, "%u\n", data->delay);
+}
+
+static ssize_t set_delay(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct bmp18x_data *data = dev_get_drvdata(dev);
+ unsigned long delay;
+ int success = kstrtoul(buf, 10, &delay);
+ if (success == 0) {
+ mutex_lock(&data->lock);
+ data->delay = delay;
+ mutex_unlock(&data->lock);
+ }
+ return success;
+}
+static DEVICE_ATTR(delay, S_IWUSR | S_IRUGO,
+ show_delay, set_delay);
+
+static ssize_t show_enable(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct bmp18x_data *data = dev_get_drvdata(dev);
+ return snprintf(buf, PAGE_SIZE, "%u\n", data->enable);
+}
+
+static ssize_t set_enable(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct bmp18x_data *data = dev_get_drvdata(dev);
+ unsigned long enable;
+ int success = kstrtoul(buf, 10, &enable);
+ if (success == 0) {
+ mutex_lock(&data->lock);
+ data->enable = enable ? 1 : 0;
+
+ if (data->enable) {
+ bmp18x_enable(dev);
+ schedule_delayed_work(&data->work,
+ msecs_to_jiffies(data->delay));
+ } else {
+ cancel_delayed_work_sync(&data->work);
+ bmp18x_disable(dev);
+ }
+ mutex_unlock(&data->lock);
+
+ }
+ return count;
+}
+static DEVICE_ATTR(enable, S_IWUSR | S_IRUGO,
+ show_enable, set_enable);
+
+static ssize_t show_temperature(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int temperature;
+ int status;
+ struct bmp18x_data *data = dev_get_drvdata(dev);
+
+ status = bmp18x_get_temperature(data, &temperature);
+ if (status != 0)
+ return status;
+ else
+ return snprintf(buf, PAGE_SIZE,
+ "%d\n", temperature);
+}
+static DEVICE_ATTR(temp0_input, S_IRUGO, show_temperature, NULL);
+
+
+static ssize_t show_pressure(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int pressure;
+ int status;
+ struct bmp18x_data *data = dev_get_drvdata(dev);
+
+ status = bmp18x_get_pressure(data, &pressure);
+ if (status != 0)
+ return status;
+ else
+ return snprintf(buf, PAGE_SIZE, "%d\n", pressure);
+}
+static DEVICE_ATTR(pressure0_input, S_IRUGO, show_pressure, NULL);
+
+
+static struct attribute *bmp18x_attributes[] = {
+ &dev_attr_temp0_input.attr,
+ &dev_attr_pressure0_input.attr,
+ &dev_attr_oversampling.attr,
+ &dev_attr_sw_oversampling.attr,
+ &dev_attr_delay.attr,
+ &dev_attr_enable.attr,
+ NULL
+};
+
+static const struct attribute_group bmp18x_attr_group = {
+ .attrs = bmp18x_attributes,
+};
+
+static void bmp18x_work_func(struct work_struct *work)
+{
+ struct bmp18x_data *client_data =
+ container_of((struct delayed_work *)work,
+ struct bmp18x_data, work);
+ unsigned long delay = msecs_to_jiffies(client_data->delay);
+ unsigned long j1 = jiffies;
+ int pressure;
+ int status;
+
+ status = bmp18x_get_pressure(client_data, &pressure);
+
+ if (status == 0) {
+ input_report_abs(client_data->input, ABS_PRESSURE, pressure);
+ input_sync(client_data->input);
+ }
+
+ schedule_delayed_work(&client_data->work, delay-(jiffies-j1));
+}
+
+static int bmp18x_input_init(struct bmp18x_data *data)
+{
+ struct input_dev *dev;
+ int err;
+
+ dev = input_allocate_device();
+ if (!dev)
+ return -ENOMEM;
+ dev->name = BMP18X_NAME;
+ dev->id.bustype = BUS_I2C;
+
+ input_set_capability(dev, EV_ABS, ABS_MISC);
+ input_set_abs_params(dev, ABS_PRESSURE,
+ ABS_MIN_PRESSURE, ABS_MAX_PRESSURE, 0, 0);
+ input_set_drvdata(dev, data);
+
+ err = input_register_device(dev);
+ if (err < 0) {
+ input_free_device(dev);
+ return err;
+ }
+ data->input = dev;
+
+ return 0;
+}
+
+static void bmp18x_input_delete(struct bmp18x_data *data)
+{
+ struct input_dev *dev = data->input;
+
+ input_unregister_device(dev);
+ input_free_device(dev);
+}
+
+static int bmp18x_init_client(struct bmp18x_data *data,
+ struct bmp18x_platform_data *pdata)
+{
+ int status = bmp18x_read_calibration_data(data);
+ if (status != 0)
+ goto exit;
+ data->last_temp_measurement = 0;
+ data->temp_measurement_period =
+ pdata ? (pdata->temp_measurement_period/1000)*HZ : 1*HZ;
+ data->oversampling_setting = pdata ? pdata->default_oversampling : 3;
+ if (data->oversampling_setting == 3)
+ data->sw_oversampling_setting
+ = pdata ? pdata->default_sw_oversampling : 0;
+ mutex_init(&data->lock);
+exit:
+ return status;
+}
+
+__devinit int bmp18x_probe(struct device *dev, struct bmp18x_data_bus *data_bus)
+{
+ struct bmp18x_data *data;
+ struct bmp18x_platform_data *pdata = dev->platform_data;
+ u8 chip_id = pdata && pdata->chip_id ? pdata->chip_id : BMP18X_CHIP_ID;
+ int err = 0;
+
+ if (pdata && pdata->init_hw) {
+ err = pdata->init_hw(data_bus);
+ if (err) {
+ printk(KERN_ERR "%s: init_hw failed!\n",
+ BMP18X_NAME);
+ goto exit;
+ }
+ }
+
+ if (data_bus->bops->read_byte(data_bus->client,
+ BMP18X_CHIP_ID_REG) != chip_id) {
+ printk(KERN_ERR "%s: chip_id failed!\n", BMP18X_NAME);
+ err = -ENODEV;
+ goto exit;
+ }
+
+ data = kzalloc(sizeof(struct bmp18x_data), GFP_KERNEL);
+ if (!data) {
+ err = -ENOMEM;
+ goto exit;
+ }
+
+ dev_set_drvdata(dev, data);
+ data->data_bus = *data_bus;
+ data->dev = dev;
+
+ /* Initialize the BMP18X chip */
+ err = bmp18x_init_client(data, pdata);
+ if (err != 0)
+ goto exit_free;
+
+ /* Initialize the BMP18X input device */
+ err = bmp18x_input_init(data);
+ if (err != 0)
+ goto exit_free;
+
+ /* Register sysfs hooks */
+ err = sysfs_create_group(&data->input->dev.kobj, &bmp18x_attr_group);
+ if (err)
+ goto error_sysfs;
+ /* workqueue init */
+ INIT_DELAYED_WORK(&data->work, bmp18x_work_func);
+ data->delay = BMP_DELAY_DEFAULT;
+ data->enable = 0;
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ data->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
+ data->early_suspend.suspend = bmp18x_early_suspend;
+ data->early_suspend.resume = bmp18x_late_resume;
+ register_early_suspend(&data->early_suspend);
+#endif
+
+ dev_info(dev, "Succesfully initialized bmp18x!\n");
+ return 0;
+
+error_sysfs:
+ bmp18x_input_delete(data);
+exit_free:
+ kfree(data);
+exit:
+ if (pdata && pdata->deinit_hw)
+ pdata->deinit_hw(data_bus);
+ return err;
+}
+EXPORT_SYMBOL(bmp18x_probe);
+
+int bmp18x_remove(struct device *dev)
+{
+ struct bmp18x_data *data = dev_get_drvdata(dev);
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ unregister_early_suspend(&data->early_suspend);
+#endif
+ sysfs_remove_group(&data->input->dev.kobj, &bmp18x_attr_group);
+ kfree(data);
+
+ return 0;
+}
+EXPORT_SYMBOL(bmp18x_remove);
+
+#ifdef CONFIG_PM
+int bmp18x_disable(struct device *dev)
+{
+ struct bmp18x_platform_data *pdata = dev->platform_data;
+ struct bmp18x_data *data = dev_get_drvdata(dev);
+ if (pdata && pdata->deinit_hw)
+ pdata->deinit_hw(&data->data_bus);
+
+ return 0;
+}
+EXPORT_SYMBOL(bmp18x_disable);
+
+int bmp18x_enable(struct device *dev)
+{
+ struct bmp18x_platform_data *pdata = dev->platform_data;
+ struct bmp18x_data *data = dev_get_drvdata(dev);
+ if (pdata && pdata->init_hw)
+ return pdata->init_hw(&data->data_bus);
+
+ return 0;
+}
+EXPORT_SYMBOL(bmp18x_enable);
+#endif
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void bmp18x_early_suspend(struct early_suspend *h)
+{
+ struct bmp18x_data *data =
+ container_of(h, struct bmp18x_data, early_suspend);
+ if (data->enable) {
+ cancel_delayed_work_sync(&data->work);
+ (void) bmp18x_disable(data->dev);
+ }
+}
+
+static void bmp18x_late_resume(struct early_suspend *h)
+{
+ struct bmp18x_data *data =
+ container_of(h, struct bmp18x_data, early_suspend);
+
+ if (data->enable) {
+ (void) bmp18x_enable(data->dev);
+ schedule_delayed_work(&data->work,
+ msecs_to_jiffies(data->delay));
+ }
+
+}
+#endif
+
+MODULE_AUTHOR("Eric Andersson <eric.andersson@unixphere.com>");
+MODULE_DESCRIPTION("BMP18X driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/misc/bmp18x-i2c.c b/drivers/input/misc/bmp18x-i2c.c
new file mode 100644
index 0000000..abbe6e5
--- /dev/null
+++ b/drivers/input/misc/bmp18x-i2c.c
@@ -0,0 +1,275 @@
+/* Copyright (c) 2011 Bosch Sensortec GmbH
+ Copyright (c) 2011 Unixphere
+
+ Based on:
+ BMP085 driver, bmp085.c
+ Copyright (c) 2010 Christoph Mair <christoph.mair@gmail.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/err.h>
+#include <linux/regulator/consumer.h>
+#include "bmp18x.h"
+
+struct sensor_regulator {
+ struct regulator *vreg;
+ const char *name;
+ u32 min_uV;
+ u32 max_uV;
+};
+
+struct sensor_regulator bmp_vreg[] = {
+ {NULL, "vdd", 2850000, 2850000},
+ {NULL, "vddio", 1800000, 1800000},
+};
+
+
+static int bmp18x_config_regulator(struct i2c_client *client, bool on)
+{
+ int rc = 0, i;
+ int num_vreg = ARRAY_SIZE(bmp_vreg);
+
+ if (on) {
+ for (i = 0; i < num_vreg; i++) {
+ bmp_vreg[i].vreg = regulator_get(&client->dev,
+ bmp_vreg[i].name);
+ if (IS_ERR(bmp_vreg[i].vreg)) {
+ rc = PTR_ERR(bmp_vreg[i].vreg);
+ dev_err(&client->dev, "%s:regulator get failed rc=%d\n",
+ __func__, rc);
+ bmp_vreg[i].vreg = NULL;
+ goto error_vdd;
+ }
+ if (regulator_count_voltages(bmp_vreg[i].vreg) > 0) {
+ rc = regulator_set_voltage(bmp_vreg[i].vreg,
+ bmp_vreg[i].min_uV, bmp_vreg[i].max_uV);
+ if (rc) {
+ dev_err(&client->dev, "%s:set_voltage failed rc=%d\n",
+ __func__, rc);
+ regulator_put(bmp_vreg[i].vreg);
+ bmp_vreg[i].vreg = NULL;
+ goto error_vdd;
+ }
+ }
+ rc = regulator_enable(bmp_vreg[i].vreg);
+ if (rc) {
+ dev_err(&client->dev, "%s: regulator_enable failed rc =%d\n",
+ __func__, rc);
+ if (regulator_count_voltages(bmp_vreg[i].vreg)
+ > 0) {
+ regulator_set_voltage(bmp_vreg[i].vreg,
+ 0, bmp_vreg[i].max_uV);
+ }
+ regulator_put(bmp_vreg[i].vreg);
+ bmp_vreg[i].vreg = NULL;
+ goto error_vdd;
+ }
+ }
+ return rc;
+ } else {
+ i = num_vreg;
+ }
+error_vdd:
+ while (--i >= 0) {
+ if (!IS_ERR_OR_NULL(bmp_vreg[i].vreg)) {
+ if (regulator_count_voltages(
+ bmp_vreg[i].vreg) > 0) {
+ regulator_set_voltage(bmp_vreg[i].vreg, 0,
+ bmp_vreg[i].max_uV);
+ }
+ regulator_disable(bmp_vreg[i].vreg);
+ regulator_put(bmp_vreg[i].vreg);
+ bmp_vreg[i].vreg = NULL;
+ }
+ }
+ return rc;
+}
+
+static int bmp18x_init_hw(struct bmp18x_data_bus *data_bus)
+{
+ if (data_bus->client)
+ return bmp18x_config_regulator(data_bus->client, 1);
+ return 0;
+}
+
+static void bmp18x_deinit_hw(struct bmp18x_data_bus *data_bus)
+{
+ if (data_bus->client)
+ bmp18x_config_regulator(data_bus->client, 0);
+}
+
+#ifdef CONFIG_OF
+static int bmp18x_parse_dt(struct device *dev,
+ struct bmp18x_platform_data *pdata)
+{
+ int ret = 0;
+ u32 val;
+
+ ret = of_property_read_u32(dev->of_node, "bosch,chip-id", &val);
+ if (ret) {
+ dev_err(dev, "no chip_id from dt\n");
+ return ret;
+ }
+ pdata->chip_id = (u8)val;
+
+ ret = of_property_read_u32(dev->of_node, "bosch,oversample", &val);
+ if (ret) {
+ dev_err(dev, "no default_oversampling from dt\n");
+ return ret;
+ }
+ pdata->default_oversampling = (u8)val;
+
+ ret = of_property_read_u32(dev->of_node, "bosch,period",
+ &pdata->temp_measurement_period);
+ if (ret) {
+ dev_err(dev, "no temp_measurement_period from dt\n");
+ return ret;
+ }
+
+ pdata->default_sw_oversampling = of_property_read_bool(dev->of_node,
+ "bosch,sw-oversample");
+ return 0;
+}
+#else
+static int bmp18x_parse_dt(struct device *dev,
+ struct bmp18x_platform_data *pdata)
+{
+ return -EINVAL;
+}
+#endif
+
+static int bmp18x_i2c_read_block(void *client, u8 reg, int len, char *buf)
+{
+ return i2c_smbus_read_i2c_block_data(client, reg, len, buf);
+}
+
+static int bmp18x_i2c_read_byte(void *client, u8 reg)
+{
+ return i2c_smbus_read_byte_data(client, reg);
+}
+
+static int bmp18x_i2c_write_byte(void *client, u8 reg, u8 value)
+{
+ return i2c_smbus_write_byte_data(client, reg, value);
+}
+
+static const struct bmp18x_bus_ops bmp18x_i2c_bus_ops = {
+ .read_block = bmp18x_i2c_read_block,
+ .read_byte = bmp18x_i2c_read_byte,
+ .write_byte = bmp18x_i2c_write_byte
+};
+
+static int __devinit bmp18x_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct bmp18x_data_bus data_bus = {
+ .bops = &bmp18x_i2c_bus_ops,
+ .client = client
+ };
+ struct bmp18x_platform_data *pdata;
+ int ret;
+
+ if (client->dev.of_node) {
+ pdata = devm_kzalloc(&client->dev,
+ sizeof(struct bmp18x_platform_data), GFP_KERNEL);
+ if (!pdata) {
+ dev_err(&client->dev, "Failed to allocate memory\n");
+ return -ENOMEM;
+ }
+ ret = bmp18x_parse_dt(&client->dev, pdata);
+ if (ret) {
+ dev_err(&client->dev, "Failed to parse device tree\n");
+ return ret;
+ }
+ pdata->init_hw = bmp18x_init_hw;
+ pdata->deinit_hw = bmp18x_deinit_hw;
+ client->dev.platform_data = pdata;
+ }
+ return bmp18x_probe(&client->dev, &data_bus);
+}
+
+static void bmp18x_i2c_shutdown(struct i2c_client *client)
+{
+ bmp18x_disable(&client->dev);
+}
+
+static int bmp18x_i2c_remove(struct i2c_client *client)
+{
+ return bmp18x_remove(&client->dev);
+}
+
+#ifdef CONFIG_PM
+static int bmp18x_i2c_suspend(struct device *dev)
+{
+ return bmp18x_disable(dev);
+}
+
+static int bmp18x_i2c_resume(struct device *dev)
+{
+ return bmp18x_enable(dev);
+}
+
+static const struct dev_pm_ops bmp18x_i2c_pm_ops = {
+ .suspend = bmp18x_i2c_suspend,
+ .resume = bmp18x_i2c_resume
+};
+#endif
+
+static const struct i2c_device_id bmp18x_id[] = {
+ { BMP18X_NAME, 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, bmp18x_id);
+
+static const struct of_device_id bmp18x_of_match[] = {
+ { .compatible = "bosch,bmp180", },
+ { },
+};
+
+static struct i2c_driver bmp18x_i2c_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = BMP18X_NAME,
+#ifdef CONFIG_PM
+ .pm = &bmp18x_i2c_pm_ops,
+#endif
+ .of_match_table = bmp18x_of_match,
+ },
+ .id_table = bmp18x_id,
+ .probe = bmp18x_i2c_probe,
+ .shutdown = bmp18x_i2c_shutdown,
+ .remove = __devexit_p(bmp18x_i2c_remove)
+};
+
+static int __init bmp18x_i2c_init(void)
+{
+ return i2c_add_driver(&bmp18x_i2c_driver);
+}
+
+static void __exit bmp18x_i2c_exit(void)
+{
+ i2c_del_driver(&bmp18x_i2c_driver);
+}
+
+
+MODULE_AUTHOR("Eric Andersson <eric.andersson@unixphere.com>");
+MODULE_DESCRIPTION("BMP18X I2C bus driver");
+MODULE_LICENSE("GPL");
+
+module_init(bmp18x_i2c_init);
+module_exit(bmp18x_i2c_exit);
diff --git a/drivers/input/misc/bmp18x.h b/drivers/input/misc/bmp18x.h
new file mode 100644
index 0000000..d1b1ee7
--- /dev/null
+++ b/drivers/input/misc/bmp18x.h
@@ -0,0 +1,65 @@
+/* Copyright (c) 2010 Christoph Mair <christoph.mair@gmail.com>
+ Copyright (c) 2011 Bosch Sensortec GmbH
+ Copyright (c) 2011 Unixphere AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#ifndef _BMP18X_H
+#define _BMP18X_H
+
+#define BMP18X_NAME "bmp18x"
+
+/**
+ * struct bmp18x_platform_data - represents platform data for the bmp18x driver
+ * @chip_id: Configurable chip id for non-default chip revisions
+ * @default_oversampling: Default oversampling value to be used at startup,
+ * value range is 0-3 with rising sensitivity.
+ * @default_sw_oversampling: Default software oversampling value to be used
+ * at startup,value range is 0(Disabled) or 1(Enabled). Only take effect
+ * when default_oversampling is 3.
+ * @temp_measurement_period: Temperature measurement period (milliseconds), set
+ * to zero if unsure.
+ * @init_hw: Callback for hw specific startup
+ * @deinit_hw: Callback for hw specific shutdown
+ */
+
+struct bmp18x_bus_ops {
+ int (*read_block)(void *client, u8 reg, int len, char *buf);
+ int (*read_byte)(void *client, u8 reg);
+ int (*write_byte)(void *client, u8 reg, u8 value);
+};
+
+struct bmp18x_data_bus {
+ const struct bmp18x_bus_ops *bops;
+ void *client;
+};
+
+struct bmp18x_platform_data {
+ u8 chip_id;
+ u8 default_oversampling;
+ u8 default_sw_oversampling;
+ u32 temp_measurement_period;
+ int (*init_hw)(struct bmp18x_data_bus *);
+ void (*deinit_hw)(struct bmp18x_data_bus *);
+};
+
+int bmp18x_probe(struct device *dev, struct bmp18x_data_bus *data_bus);
+int bmp18x_remove(struct device *dev);
+#ifdef CONFIG_PM
+int bmp18x_enable(struct device *dev);
+int bmp18x_disable(struct device *dev);
+#endif
+
+#endif
diff --git a/drivers/input/misc/kxtj9.c b/drivers/input/misc/kxtj9.c
index dd2e5d8..f879d78 100644
--- a/drivers/input/misc/kxtj9.c
+++ b/drivers/input/misc/kxtj9.c
@@ -756,7 +756,10 @@
kxtj9_pdata->negate_z = of_property_read_bool(np, "kionix,negate-z");
- kxtj9_pdata->res_12bit = of_property_read_bool(np, "kionix,res-12bit");
+ if (of_property_read_bool(np, "kionix,res-12bit"))
+ kxtj9_pdata->res_ctl = RES_12BIT;
+ else
+ kxtj9_pdata->res_ctl = RES_8BIT;
return 0;
}
@@ -834,7 +837,7 @@
i2c_set_clientdata(client, tj9);
- tj9->ctrl_reg1 = tj9->pdata.res_12bit | tj9->pdata.g_range;
+ tj9->ctrl_reg1 = tj9->pdata.res_ctl | tj9->pdata.g_range;
tj9->last_poll_interval = tj9->pdata.init_interval;
if (client->irq) {
diff --git a/drivers/input/misc/mma8x5x.c b/drivers/input/misc/mma8x5x.c
new file mode 100644
index 0000000..f1ea705
--- /dev/null
+++ b/drivers/input/misc/mma8x5x.c
@@ -0,0 +1,684 @@
+/*
+ * mma8x5x.c - Linux kernel modules for 3-Axis Orientation/Motion
+ * Detection Sensor MMA8451/MMA8452/MMA8453
+ *
+ * Copyright (c) 2013, The Linux Foundation. All Rights Reserved.
+ * Linux Foundation chooses to take subject only to the GPLv2 license
+ * terms, and distributes only under these terms.
+ * Copyright (C) 2010-2011 Freescale Semiconductor, Inc. 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 as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/input-polldev.h>
+#include <linux/regulator/consumer.h>
+#include <linux/of_gpio.h>
+
+#define ACCEL_INPUT_DEV_NAME "accelerometer"
+#define MMA8451_ID 0x1A
+#define MMA8452_ID 0x2A
+#define MMA8453_ID 0x3A
+#define MMA8652_ID 0x4A
+#define MMA8653_ID 0x5A
+
+
+#define POLL_INTERVAL_MIN 1
+#define POLL_INTERVAL_MAX 500
+#define POLL_INTERVAL 100 /* msecs */
+
+/* if sensor is standby ,set POLL_STOP_TIME to slow down the poll */
+#define POLL_STOP_TIME 200
+#define INPUT_FUZZ 32
+#define INPUT_FLAT 32
+#define MODE_CHANGE_DELAY_MS 100
+
+#define MMA8X5X_STATUS_ZYXDR 0x08
+#define MMA8X5X_BUF_SIZE 7
+
+struct sensor_regulator {
+ struct regulator *vreg;
+ const char *name;
+ u32 min_uV;
+ u32 max_uV;
+};
+
+static struct sensor_regulator mma_vreg[] = {
+ {NULL, "vdd", 2850000, 2850000},
+ {NULL, "vio", 1800000, 1800000},
+};
+
+/* register enum for mma8x5x registers */
+enum {
+ MMA8X5X_STATUS = 0x00,
+ MMA8X5X_OUT_X_MSB,
+ MMA8X5X_OUT_X_LSB,
+ MMA8X5X_OUT_Y_MSB,
+ MMA8X5X_OUT_Y_LSB,
+ MMA8X5X_OUT_Z_MSB,
+ MMA8X5X_OUT_Z_LSB,
+
+ MMA8X5X_F_SETUP = 0x09,
+ MMA8X5X_TRIG_CFG,
+ MMA8X5X_SYSMOD,
+ MMA8X5X_INT_SOURCE,
+ MMA8X5X_WHO_AM_I,
+ MMA8X5X_XYZ_DATA_CFG,
+ MMA8X5X_HP_FILTER_CUTOFF,
+
+ MMA8X5X_PL_STATUS,
+ MMA8X5X_PL_CFG,
+ MMA8X5X_PL_COUNT,
+ MMA8X5X_PL_BF_ZCOMP,
+ MMA8X5X_P_L_THS_REG,
+
+ MMA8X5X_FF_MT_CFG,
+ MMA8X5X_FF_MT_SRC,
+ MMA8X5X_FF_MT_THS,
+ MMA8X5X_FF_MT_COUNT,
+
+ MMA8X5X_TRANSIENT_CFG = 0x1D,
+ MMA8X5X_TRANSIENT_SRC,
+ MMA8X5X_TRANSIENT_THS,
+ MMA8X5X_TRANSIENT_COUNT,
+
+ MMA8X5X_PULSE_CFG,
+ MMA8X5X_PULSE_SRC,
+ MMA8X5X_PULSE_THSX,
+ MMA8X5X_PULSE_THSY,
+ MMA8X5X_PULSE_THSZ,
+ MMA8X5X_PULSE_TMLT,
+ MMA8X5X_PULSE_LTCY,
+ MMA8X5X_PULSE_WIND,
+
+ MMA8X5X_ASLP_COUNT,
+ MMA8X5X_CTRL_REG1,
+ MMA8X5X_CTRL_REG2,
+ MMA8X5X_CTRL_REG3,
+ MMA8X5X_CTRL_REG4,
+ MMA8X5X_CTRL_REG5,
+
+ MMA8X5X_OFF_X,
+ MMA8X5X_OFF_Y,
+ MMA8X5X_OFF_Z,
+
+ MMA8X5X_REG_END,
+};
+
+/* The sensitivity is represented in counts/g. In 2g mode the
+sensitivity is 1024 counts/g. In 4g mode the sensitivity is 512
+counts/g and in 8g mode the sensitivity is 256 counts/g.
+ */
+enum {
+ MODE_2G = 0,
+ MODE_4G,
+ MODE_8G,
+};
+
+enum {
+ MMA_STANDBY = 0,
+ MMA_ACTIVED,
+};
+struct mma8x5x_data_axis {
+ short x;
+ short y;
+ short z;
+};
+struct mma8x5x_data {
+ struct i2c_client *client;
+ struct input_polled_dev *poll_dev;
+ struct mutex data_lock;
+ int active;
+ int position;
+ u8 chip_id;
+ int mode;
+ int int_pin;
+ u32 int_flags;
+};
+/* Addresses scanned */
+static const unsigned short normal_i2c[] = {0x1c, 0x1d, I2C_CLIENT_END};
+
+static int mma8x5x_chip_id[] = {
+ MMA8451_ID,
+ MMA8452_ID,
+ MMA8453_ID,
+ MMA8652_ID,
+ MMA8653_ID,
+};
+static char *mma8x5x_names[] = {
+ "mma8451",
+ "mma8452",
+ "mma8453",
+ "mma8652",
+ "mma8653",
+};
+static int mma8x5x_position_setting[8][3][3] = {
+ {{ 0, -1, 0}, { 1, 0, 0}, {0, 0, 1} },
+ {{-1, 0, 0}, { 0, -1, 0}, {0, 0, 1} },
+ {{ 0, 1, 0}, {-1, 0, 0}, {0, 0, 1} },
+ {{ 1, 0, 0}, { 0, 1, 0}, {0, 0, 1} },
+ {{ 0, -1, 0}, {-1, 0, 0}, {0, 0, -1} },
+ {{-1, 0, 0}, { 0, 1, 0}, {0, 0, -1} },
+ {{ 0, 1, 0}, { 1, 0, 0}, {0, 0, -1} },
+ {{ 1, 0, 0}, { 0, -1, 0}, {0, 0, -1} },
+};
+
+static int mma8x5x_config_regulator(struct i2c_client *client, bool on)
+{
+ int rc = 0, i;
+ int num_vreg = sizeof(mma_vreg)/sizeof(struct sensor_regulator);
+
+ if (on) {
+ for (i = 0; i < num_vreg; i++) {
+ mma_vreg[i].vreg = regulator_get(&client->dev,
+ mma_vreg[i].name);
+ if (IS_ERR(mma_vreg[i].vreg)) {
+ rc = PTR_ERR(mma_vreg[i].vreg);
+ dev_err(&client->dev, "%s:regulator get failed rc=%d\n",
+ __func__, rc);
+ mma_vreg[i].vreg = NULL;
+ goto error_vdd;
+ }
+ if (regulator_count_voltages(mma_vreg[i].vreg) > 0) {
+ rc = regulator_set_voltage(mma_vreg[i].vreg,
+ mma_vreg[i].min_uV, mma_vreg[i].max_uV);
+ if (rc) {
+ dev_err(&client->dev, "%s:set_voltage failed rc=%d\n",
+ __func__, rc);
+ regulator_put(mma_vreg[i].vreg);
+ mma_vreg[i].vreg = NULL;
+ goto error_vdd;
+ }
+ }
+ rc = regulator_enable(mma_vreg[i].vreg);
+ if (rc) {
+ dev_err(&client->dev, "%s: regulator_enable failed rc =%d\n",
+ __func__, rc);
+ if (regulator_count_voltages(mma_vreg[i].vreg)
+ > 0) {
+ regulator_set_voltage(mma_vreg[i].vreg,
+ 0, mma_vreg[i].max_uV);
+ }
+ regulator_put(mma_vreg[i].vreg);
+ mma_vreg[i].vreg = NULL;
+ goto error_vdd;
+ }
+ }
+ return rc;
+ } else {
+ i = num_vreg;
+ }
+error_vdd:
+ while (--i >= 0) {
+ if (!IS_ERR_OR_NULL(mma_vreg[i].vreg)) {
+ if (regulator_count_voltages(
+ mma_vreg[i].vreg) > 0) {
+ regulator_set_voltage(mma_vreg[i].vreg, 0,
+ mma_vreg[i].max_uV);
+ }
+ regulator_disable(mma_vreg[i].vreg);
+ regulator_put(mma_vreg[i].vreg);
+ mma_vreg[i].vreg = NULL;
+ }
+ }
+ return rc;
+}
+
+static int mma8x5x_data_convert(struct mma8x5x_data *pdata,
+ struct mma8x5x_data_axis *axis_data)
+{
+ short rawdata[3], data[3];
+ int i, j;
+ int position = pdata->position ;
+ if (position < 0 || position > 7)
+ position = 0;
+ rawdata[0] = axis_data->x;
+ rawdata[1] = axis_data->y;
+ rawdata[2] = axis_data->z;
+ for (i = 0; i < 3 ; i++) {
+ data[i] = 0;
+ for (j = 0; j < 3; j++)
+ data[i] += rawdata[j] *
+ mma8x5x_position_setting[position][i][j];
+ }
+ axis_data->x = data[0];
+ axis_data->y = data[1];
+ axis_data->z = data[2];
+ return 0;
+}
+static int mma8x5x_check_id(int id)
+{
+ int i = 0;
+ for (i = 0; i < sizeof(mma8x5x_chip_id)/sizeof(mma8x5x_chip_id[0]);
+ i++)
+ if (id == mma8x5x_chip_id[i])
+ return 1;
+ return 0;
+}
+static char *mma8x5x_id2name(u8 id)
+{
+ return mma8x5x_names[(id >> 4)-1];
+}
+static int mma8x5x_device_init(struct i2c_client *client)
+{
+ int result;
+ struct mma8x5x_data *pdata = i2c_get_clientdata(client);
+ result = i2c_smbus_write_byte_data(client, MMA8X5X_CTRL_REG1, 0);
+ if (result < 0)
+ goto out;
+
+ result = i2c_smbus_write_byte_data(client, MMA8X5X_XYZ_DATA_CFG,
+ pdata->mode);
+ if (result < 0)
+ goto out;
+ pdata->active = MMA_STANDBY;
+ msleep(MODE_CHANGE_DELAY_MS);
+ return 0;
+out:
+ dev_err(&client->dev, "error when init mma8x5x:(%d)", result);
+ return result;
+}
+static int mma8x5x_device_stop(struct i2c_client *client)
+{
+ u8 val;
+ val = i2c_smbus_read_byte_data(client, MMA8X5X_CTRL_REG1);
+ i2c_smbus_write_byte_data(client, MMA8X5X_CTRL_REG1, val & 0xfe);
+ return 0;
+}
+
+static int mma8x5x_read_data(struct i2c_client *client,
+ struct mma8x5x_data_axis *data)
+{
+ u8 tmp_data[MMA8X5X_BUF_SIZE];
+ int ret;
+
+ ret = i2c_smbus_read_i2c_block_data(client,
+ MMA8X5X_OUT_X_MSB, 7, tmp_data);
+ if (ret < MMA8X5X_BUF_SIZE) {
+ dev_err(&client->dev, "i2c block read failed\n");
+ return -EIO;
+ }
+ data->x = ((tmp_data[0] << 8) & 0xff00) | tmp_data[1];
+ data->y = ((tmp_data[2] << 8) & 0xff00) | tmp_data[3];
+ data->z = ((tmp_data[4] << 8) & 0xff00) | tmp_data[5];
+ return 0;
+}
+
+static void mma8x5x_report_data(struct mma8x5x_data *pdata)
+{
+ struct input_polled_dev *poll_dev = pdata->poll_dev;
+ struct mma8x5x_data_axis data;
+ mutex_lock(&pdata->data_lock);
+ if (pdata->active == MMA_STANDBY) {
+ poll_dev->poll_interval = POLL_STOP_TIME;
+ /* if standby ,set as 10s to slow the poll. */
+ goto out;
+ } else {
+ if (poll_dev->poll_interval == POLL_STOP_TIME)
+ poll_dev->poll_interval = POLL_INTERVAL;
+ }
+ if (mma8x5x_read_data(pdata->client, &data) != 0)
+ goto out;
+ mma8x5x_data_convert(pdata, &data);
+ input_report_abs(poll_dev->input, ABS_X, data.x);
+ input_report_abs(poll_dev->input, ABS_Y, data.y);
+ input_report_abs(poll_dev->input, ABS_Z, data.z);
+ input_sync(poll_dev->input);
+out:
+ mutex_unlock(&pdata->data_lock);
+}
+
+static void mma8x5x_dev_poll(struct input_polled_dev *dev)
+{
+ struct mma8x5x_data *pdata = (struct mma8x5x_data *)dev->private;
+ mma8x5x_report_data(pdata);
+}
+
+static ssize_t mma8x5x_enable_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct input_polled_dev *poll_dev = dev_get_drvdata(dev);
+ struct mma8x5x_data *pdata = (struct mma8x5x_data *)(poll_dev->private);
+ struct i2c_client *client = pdata->client;
+ u8 val;
+ int enable;
+
+ mutex_lock(&pdata->data_lock);
+ val = i2c_smbus_read_byte_data(client, MMA8X5X_CTRL_REG1);
+ if ((val & 0x01) && pdata->active == MMA_ACTIVED)
+ enable = 1;
+ else
+ enable = 0;
+ mutex_unlock(&pdata->data_lock);
+ return snprintf(buf, PAGE_SIZE, "%d\n", enable);
+}
+
+static ssize_t mma8x5x_enable_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct input_polled_dev *poll_dev = dev_get_drvdata(dev);
+ struct mma8x5x_data *pdata = (struct mma8x5x_data *)(poll_dev->private);
+ struct i2c_client *client = pdata->client;
+ int ret;
+ unsigned long enable;
+ u8 val = 0;
+ ret = kstrtoul(buf, 10, &enable);
+ if (ret)
+ return ret;
+ mutex_lock(&pdata->data_lock);
+ enable = (enable > 0) ? 1 : 0;
+ if (enable && pdata->active == MMA_STANDBY) {
+ val = i2c_smbus_read_byte_data(client, MMA8X5X_CTRL_REG1);
+ ret = i2c_smbus_write_byte_data(client,
+ MMA8X5X_CTRL_REG1, val|0x01);
+ if (!ret) {
+ pdata->active = MMA_ACTIVED;
+ dev_dbg(dev,
+ "%s:mma enable setting active.\n", __func__);
+ }
+ } else if (enable == 0 && pdata->active == MMA_ACTIVED) {
+ val = i2c_smbus_read_byte_data(client, MMA8X5X_CTRL_REG1);
+ ret = i2c_smbus_write_byte_data(client,
+ MMA8X5X_CTRL_REG1, val & 0xFE);
+ if (!ret) {
+ pdata->active = MMA_STANDBY;
+ dev_dbg(dev,
+ "%s:mma enable setting inactive.\n", __func__);
+ }
+ }
+ mutex_unlock(&pdata->data_lock);
+ return count;
+}
+static ssize_t mma8x5x_position_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct input_polled_dev *poll_dev = dev_get_drvdata(dev);
+ struct mma8x5x_data *pdata = (struct mma8x5x_data *)(poll_dev->private);
+ int position = 0;
+ mutex_lock(&pdata->data_lock);
+ position = pdata->position ;
+ mutex_unlock(&pdata->data_lock);
+ return snprintf(buf, PAGE_SIZE, "%d\n", position);
+}
+
+static ssize_t mma8x5x_position_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct input_polled_dev *poll_dev = dev_get_drvdata(dev);
+ struct mma8x5x_data *pdata = (struct mma8x5x_data *)(poll_dev->private);
+ int position;
+ int ret;
+ ret = kstrtoint(buf, 10, &position);
+ if (ret)
+ return ret;
+ mutex_lock(&pdata->data_lock);
+ pdata->position = position;
+ mutex_unlock(&pdata->data_lock);
+ return count;
+}
+
+static DEVICE_ATTR(enable, S_IWUSR | S_IRUGO,
+ mma8x5x_enable_show, mma8x5x_enable_store);
+static DEVICE_ATTR(position, S_IWUSR | S_IRUGO,
+ mma8x5x_position_show, mma8x5x_position_store);
+
+static struct attribute *mma8x5x_attributes[] = {
+ &dev_attr_enable.attr,
+ &dev_attr_position.attr,
+ NULL
+};
+
+static const struct attribute_group mma8x5x_attr_group = {
+ .attrs = mma8x5x_attributes,
+};
+static int mma8x5x_detect(struct i2c_client *client,
+ struct i2c_board_info *info)
+{
+ struct i2c_adapter *adapter = client->adapter;
+ int chip_id;
+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_WORD_DATA))
+ return -ENODEV;
+ chip_id = i2c_smbus_read_byte_data(client, MMA8X5X_WHO_AM_I);
+ if (!mma8x5x_check_id(chip_id))
+ return -ENODEV;
+ dev_dbg(&client->dev, "%s,check %s i2c address 0x%x.\n",
+ __func__, mma8x5x_id2name(chip_id), client->addr);
+ strlcpy(info->type, "mma8x5x", I2C_NAME_SIZE);
+ return 0;
+}
+
+static int mma8x5x_parse_dt(struct device *dev, struct mma8x5x_data *data)
+{
+ int rc;
+ struct device_node *np = dev->of_node;
+ u32 temp_val;
+
+ data->int_pin = of_get_named_gpio_flags(np, "fsl,irq-gpio",
+ 0, &data->int_flags);
+ if (data->int_pin < 0) {
+ dev_err(dev, "Unable to read irq-gpio\n");
+ return data->int_pin;
+ }
+
+ rc = of_property_read_u32(np, "fsl,sensors-position", &temp_val);
+ if (!rc)
+ data->position = temp_val;
+ else {
+ dev_err(dev, "Unable to read sensors-position\n");
+ return rc;
+ }
+
+ return 0;
+}
+
+static int __devinit mma8x5x_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ int result, chip_id;
+ struct input_dev *idev;
+ struct mma8x5x_data *pdata;
+ struct i2c_adapter *adapter;
+ struct input_polled_dev *poll_dev;
+ adapter = to_i2c_adapter(client->dev.parent);
+ /* power on the device */
+ result = mma8x5x_config_regulator(client, 1);
+ if (result)
+ goto err_power_on;
+
+ result = i2c_check_functionality(adapter,
+ I2C_FUNC_SMBUS_BYTE |
+ I2C_FUNC_SMBUS_BYTE_DATA);
+ if (!result)
+ goto err_out;
+
+ chip_id = i2c_smbus_read_byte_data(client, MMA8X5X_WHO_AM_I);
+
+ if (!mma8x5x_check_id(chip_id)) {
+ dev_err(&client->dev,
+ "read chip ID 0x%x is not equal to 0x%x,0x%x,0x%x,0x%x,0x%x!\n",
+ chip_id, MMA8451_ID, MMA8452_ID, MMA8453_ID,
+ MMA8652_ID, MMA8653_ID);
+ result = -EINVAL;
+ goto err_out;
+ }
+ /* set the private data */
+ pdata = kzalloc(sizeof(struct mma8x5x_data), GFP_KERNEL);
+ if (!pdata) {
+ result = -ENOMEM;
+ dev_err(&client->dev, "alloc data memory error!\n");
+ goto err_out;
+ }
+
+ if (client->dev.of_node) {
+ result = mma8x5x_parse_dt(&client->dev, pdata);
+ if (result)
+ return result;
+ } else {
+ pdata->position = CONFIG_SENSORS_MMA_POSITION;
+ pdata->int_pin = -1;
+ pdata->int_flags = 0;
+ }
+
+ /* Initialize the MMA8X5X chip */
+ pdata->client = client;
+ pdata->chip_id = chip_id;
+ pdata->mode = MODE_2G;
+
+ mutex_init(&pdata->data_lock);
+ i2c_set_clientdata(client, pdata);
+ /* Initialize the MMA8X5X chip */
+ mma8x5x_device_init(client);
+ /* create the input poll device */
+ poll_dev = input_allocate_polled_device();
+ if (!poll_dev) {
+ result = -ENOMEM;
+ dev_err(&client->dev, "alloc poll device failed!\n");
+ goto err_alloc_poll_device;
+ }
+ poll_dev->poll = mma8x5x_dev_poll;
+ poll_dev->poll_interval = POLL_STOP_TIME;
+ poll_dev->poll_interval_min = POLL_INTERVAL_MIN;
+ poll_dev->poll_interval_max = POLL_INTERVAL_MAX;
+ poll_dev->private = pdata;
+ idev = poll_dev->input;
+ idev->name = ACCEL_INPUT_DEV_NAME;
+ idev->uniq = mma8x5x_id2name(pdata->chip_id);
+ idev->id.bustype = BUS_I2C;
+ idev->evbit[0] = BIT_MASK(EV_ABS);
+ input_set_abs_params(idev, ABS_X, -0x7fff, 0x7fff, 0, 0);
+ input_set_abs_params(idev, ABS_Y, -0x7fff, 0x7fff, 0, 0);
+ input_set_abs_params(idev, ABS_Z, -0x7fff, 0x7fff, 0, 0);
+ pdata->poll_dev = poll_dev;
+ result = input_register_polled_device(pdata->poll_dev);
+ if (result) {
+ dev_err(&client->dev, "register poll device failed!\n");
+ goto err_register_polled_device;
+ }
+ result = sysfs_create_group(&idev->dev.kobj, &mma8x5x_attr_group);
+ if (result) {
+ dev_err(&client->dev, "create device file failed!\n");
+ result = -EINVAL;
+ goto err_create_sysfs;
+ }
+ dev_info(&client->dev,
+ "%s:mma8x5x device driver probe successfully, position =%d\n",
+ __func__, pdata->position);
+
+ return 0;
+err_create_sysfs:
+ input_unregister_polled_device(pdata->poll_dev);
+err_register_polled_device:
+ input_free_polled_device(poll_dev);
+err_alloc_poll_device:
+ kfree(pdata);
+err_out:
+ mma8x5x_config_regulator(client, 0);
+err_power_on:
+ return result;
+}
+static int __devexit mma8x5x_remove(struct i2c_client *client)
+{
+ struct mma8x5x_data *pdata = i2c_get_clientdata(client);
+ struct input_polled_dev *poll_dev;
+ mma8x5x_device_stop(client);
+ if (pdata) {
+ poll_dev = pdata->poll_dev;
+ input_unregister_polled_device(poll_dev);
+ input_free_polled_device(poll_dev);
+ kfree(pdata);
+ }
+ return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int mma8x5x_suspend(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct mma8x5x_data *pdata = i2c_get_clientdata(client);
+ if (pdata->active == MMA_ACTIVED)
+ mma8x5x_device_stop(client);
+ return 0;
+}
+
+static int mma8x5x_resume(struct device *dev)
+{
+ int val = 0;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct mma8x5x_data *pdata = i2c_get_clientdata(client);
+ if (pdata->active == MMA_ACTIVED) {
+ val = i2c_smbus_read_byte_data(client, MMA8X5X_CTRL_REG1);
+ i2c_smbus_write_byte_data(client, MMA8X5X_CTRL_REG1, val|0x01);
+ }
+ return 0;
+
+}
+#endif
+
+static const struct i2c_device_id mma8x5x_id[] = {
+ {"mma8x5x", 0},
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, mma8x5x_id);
+
+static const struct of_device_id mma8x5x_of_match[] = {
+ { .compatible = "fsl,mma8x5x", },
+ { },
+};
+
+static SIMPLE_DEV_PM_OPS(mma8x5x_pm_ops, mma8x5x_suspend, mma8x5x_resume);
+static struct i2c_driver mma8x5x_driver = {
+ .class = I2C_CLASS_HWMON,
+ .driver = {
+ .name = "mma8x5x",
+ .owner = THIS_MODULE,
+ .pm = &mma8x5x_pm_ops,
+ .of_match_table = mma8x5x_of_match,
+ },
+ .probe = mma8x5x_probe,
+ .remove = __devexit_p(mma8x5x_remove),
+ .id_table = mma8x5x_id,
+ .detect = mma8x5x_detect,
+ .address_list = normal_i2c,
+};
+
+static int __init mma8x5x_init(void)
+{
+ /* register driver */
+ int res;
+
+ res = i2c_add_driver(&mma8x5x_driver);
+ if (res < 0) {
+ pr_info("%s:add mma8x5x i2c driver failed\n", __func__);
+ return -ENODEV;
+ }
+ return res;
+}
+
+static void __exit mma8x5x_exit(void)
+{
+ i2c_del_driver(&mma8x5x_driver);
+}
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("MMA8X5X 3-Axis Orientation/Motion Detection Sensor driver");
+MODULE_LICENSE("GPL");
+
+module_init(mma8x5x_init);
+module_exit(mma8x5x_exit);
diff --git a/drivers/input/misc/mpu3050.c b/drivers/input/misc/mpu3050.c
index 6c64a57..519b7e4 100644
--- a/drivers/input/misc/mpu3050.c
+++ b/drivers/input/misc/mpu3050.c
@@ -43,8 +43,8 @@
#include <linux/gpio.h>
#include <linux/input/mpu3050.h>
#include <linux/regulator/consumer.h>
-
-#define MPU3050_CHIP_ID 0x69
+#include <linux/of_gpio.h>
+#include <mach/gpiomux.h>
#define MPU3050_AUTO_DELAY 1000
@@ -124,6 +124,8 @@
u32 use_poll;
u32 poll_interval;
u32 dlpf_index;
+ u32 enable_gpio;
+ u32 enable;
};
struct sensor_regulator {
@@ -138,6 +140,11 @@
{NULL, "vlogic", 1800000, 1800000},
};
+static const int mpu3050_chip_ids[] = {
+ 0x68,
+ 0x69,
+};
+
struct dlpf_cfg_tb {
u8 cfg; /* cfg index */
u32 lpf_bw; /* low pass filter bandwidth in Hz */
@@ -293,11 +300,42 @@
return size;
}
-static struct device_attribute attributes[] = {
+/**
+ * Set/get enable function is just needed by sensor HAL.
+ * Normally, the open function does all the initialization
+ * and power work. And close undo that open does.
+ * Just keeping the function simple.
+ */
+static ssize_t mpu3050_attr_set_enable(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct mpu3050_sensor *sensor = dev_get_drvdata(dev);
+ unsigned long val;
+
+ if (kstrtoul(buf, 10, &val))
+ return -EINVAL;
+ sensor->enable = (u32)val;
+
+ return count;
+}
+
+static ssize_t mpu3050_attr_get_enable(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct mpu3050_sensor *sensor = dev_get_drvdata(dev);
+
+ return snprintf(buf, 4, "%d\n", sensor->enable);
+}
+
+static struct device_attribute attributes[] = {
__ATTR(pollrate_ms, 0664,
mpu3050_attr_get_polling_rate,
mpu3050_attr_set_polling_rate),
+ __ATTR(enable, 0644,
+ mpu3050_attr_get_enable,
+ mpu3050_attr_set_enable),
};
static int create_sysfs_interfaces(struct device *dev)
@@ -390,10 +428,12 @@
static void mpu3050_set_power_mode(struct i2c_client *client, u8 val)
{
u8 value;
+ struct mpu3050_sensor *sensor = i2c_get_clientdata(client);
if (val) {
mpu3050_config_regulator(client, 1);
udelay(10);
+ gpio_set_value(sensor->enable_gpio, 1);
}
value = i2c_smbus_read_byte_data(client, MPU3050_PWR_MGM);
@@ -404,6 +444,8 @@
if (!val) {
udelay(10);
+ gpio_set_value(sensor->enable_gpio, 0);
+ udelay(10);
mpu3050_config_regulator(client, 0);
}
}
@@ -550,6 +592,37 @@
return 0;
}
+#ifdef CONFIG_OF
+static int mpu3050_parse_dt(struct device *dev,
+ struct mpu3050_gyro_platform_data *pdata)
+{
+ int rc = 0;
+
+ rc = of_property_read_u32(dev->of_node, "invn,poll-interval",
+ &pdata->poll_interval);
+ if (rc) {
+ dev_err(dev, "Failed to read poll-interval\n");
+ return rc;
+ }
+
+ /* check gpio_int later, if it is invalid, just use poll */
+ pdata->gpio_int = of_get_named_gpio_flags(dev->of_node,
+ "invn,gpio-int", 0, NULL);
+
+ pdata->gpio_en = of_get_named_gpio_flags(dev->of_node,
+ "invn,gpio-en", 0, NULL);
+ if (!gpio_is_valid(pdata->gpio_en))
+ return -EINVAL;
+
+ return 0;
+}
+#else
+static int mpu3050_parse_dt(struct device *dev,
+ struct mpu3050_gyro_platform_data *pdata)
+{
+ return -EINVAL;
+}
+#endif
/**
* mpu3050_probe - device detection callback
@@ -566,8 +639,10 @@
{
struct mpu3050_sensor *sensor;
struct input_dev *idev;
+ struct mpu3050_gyro_platform_data *pdata;
int ret;
int error;
+ u32 i;
sensor = kzalloc(sizeof(struct mpu3050_sensor), GFP_KERNEL);
idev = input_allocate_device();
@@ -580,10 +655,29 @@
sensor->client = client;
sensor->dev = &client->dev;
sensor->idev = idev;
- sensor->platform_data = client->dev.platform_data;
i2c_set_clientdata(client, sensor);
+
+ if (client->dev.of_node) {
+ pdata = devm_kzalloc(&client->dev,
+ sizeof(struct mpu3050_gyro_platform_data), GFP_KERNEL);
+ if (!pdata) {
+ dev_err(&client->dev, "Failed to allcated memory\n");
+ error = -ENOMEM;
+ goto err_free_mem;
+ }
+ ret = mpu3050_parse_dt(&client->dev, pdata);
+ if (ret) {
+ dev_err(&client->dev, "Failed to parse device tree\n");
+ error = ret;
+ goto err_free_mem;
+ }
+ } else
+ pdata = client->dev.platform_data;
+ sensor->platform_data = pdata;
+
if (sensor->platform_data) {
u32 interval = sensor->platform_data->poll_interval;
+ sensor->enable_gpio = sensor->platform_data->gpio_en;
if ((interval < MPU3050_MIN_POLL_INTERVAL) ||
(interval > MPU3050_MAX_POLL_INTERVAL))
@@ -592,6 +686,12 @@
sensor->poll_interval = interval;
} else {
sensor->poll_interval = MPU3050_DEFAULT_POLL_INTERVAL;
+ sensor->enable_gpio = -EINVAL;
+ }
+
+ if (gpio_is_valid(sensor->enable_gpio)) {
+ ret = gpio_request(sensor->enable_gpio, "GYRO_EN_PM");
+ gpio_direction_output(sensor->enable_gpio, 1);
}
mpu3050_set_power_mode(client, 1);
@@ -604,7 +704,11 @@
goto err_free_mem;
}
- if (ret != MPU3050_CHIP_ID) {
+ for (i = 0; i < ARRAY_SIZE(mpu3050_chip_ids); i++)
+ if (ret == mpu3050_chip_ids[i])
+ break;
+
+ if (i == ARRAY_SIZE(mpu3050_chip_ids)) {
dev_err(&client->dev, "unsupported chip id\n");
error = -ENXIO;
goto err_free_mem;
@@ -617,7 +721,7 @@
idev->open = mpu3050_input_open;
idev->close = mpu3050_input_close;
- __set_bit(EV_ABS, idev->evbit);
+ input_set_capability(idev, EV_ABS, ABS_MISC);
input_set_abs_params(idev, ABS_X,
MPU3050_MIN_VALUE, MPU3050_MAX_VALUE, 0, 0);
input_set_abs_params(idev, ABS_Y,
@@ -657,6 +761,11 @@
__func__, sensor->platform_data->gpio_int);
goto err_free_gpio;
}
+ client->irq = gpio_to_irq(
+ sensor->platform_data->gpio_int);
+ } else {
+ ret = -EINVAL;
+ goto err_pm_set_suspended;
}
error = request_threaded_irq(client->irq,
@@ -677,14 +786,20 @@
goto err_free_irq;
}
- error = create_sysfs_interfaces(&client->dev);
+ error = create_sysfs_interfaces(&idev->dev);
if (error < 0) {
dev_err(&client->dev, "failed to create sysfs\n");
goto err_input_cleanup;
}
- pm_runtime_enable(&client->dev);
- pm_runtime_set_autosuspend_delay(&client->dev, MPU3050_AUTO_DELAY);
+ if (sensor->use_poll)
+ schedule_delayed_work(&sensor->input_work,
+ msecs_to_jiffies(sensor->poll_interval));
+ else
+ i2c_smbus_write_byte_data(sensor->client, MPU3050_INT_CFG,
+ MPU3050_ACTIVE_LOW |
+ MPU3050_OPEN_DRAIN |
+ MPU3050_RAW_RDY_EN);
return 0;
@@ -722,6 +837,8 @@
free_irq(client->irq, sensor);
remove_sysfs_interfaces(&client->dev);
+ if (gpio_is_valid(sensor->enable_gpio))
+ gpio_free(sensor->enable_gpio);
input_unregister_device(sensor->idev);
kfree(sensor);
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index 479b788..5415f4e 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -393,6 +393,9 @@
bool update_cfg;
const char *fw_name;
bool no_force_update;
+ bool lpm_support;
+ bool regs_enabled;
+
#if defined(CONFIG_SECURE_TOUCH)
atomic_t st_enabled;
atomic_t st_pending_irqs;
@@ -2158,6 +2161,11 @@
if (on == false)
goto power_off;
+ if (data->regs_enabled) {
+ dev_dbg(&data->client->dev, "regs are already enabled\n");
+ return 0;
+ }
+
rc = reg_set_optimum_mode_check(data->vcc_ana, MXT_ACTIVE_LOAD_UA);
if (rc < 0) {
dev_err(&data->client->dev,
@@ -2206,6 +2214,8 @@
}
}
+ data->regs_enabled = true;
+
msleep(130);
return 0;
@@ -2226,6 +2236,12 @@
return rc;
power_off:
+
+ if (!data->regs_enabled) {
+ dev_dbg(&data->client->dev, "regs are already disabled\n");
+ return 0;
+ }
+
reg_set_optimum_mode_check(data->vcc_ana, 0);
regulator_disable(data->vcc_ana);
if (data->pdata->digital_pwr_regulator) {
@@ -2236,6 +2252,9 @@
reg_set_optimum_mode_check(data->vcc_i2c, 0);
regulator_disable(data->vcc_i2c);
}
+
+ data->regs_enabled = false;
+
msleep(50);
return 0;
}
@@ -2435,8 +2454,9 @@
struct input_dev *input_dev = data->input_dev;
int error;
- mutex_lock(&input_dev->mutex);
+ disable_irq(data->irq);
+ mutex_lock(&input_dev->mutex);
if (input_dev->users) {
error = mxt_stop(data);
if (error < 0) {
@@ -2444,16 +2464,24 @@
mutex_unlock(&input_dev->mutex);
return error;
}
-
}
mutex_unlock(&input_dev->mutex);
+ mxt_release_all(data);
/* put regulators in low power mode */
- error = mxt_regulator_lpm(data, true);
- if (error < 0) {
- dev_err(dev, "failed to enter low power mode\n");
- return error;
+ if (data->lpm_support) {
+ error = mxt_regulator_lpm(data, true);
+ if (error < 0) {
+ dev_err(dev, "failed to enter low power mode\n");
+ return error;
+ }
+ } else {
+ error = mxt_power_on(data, false);
+ if (error < 0) {
+ dev_err(dev, "failed to disable regulators\n");
+ return error;
+ }
}
return 0;
@@ -2466,13 +2494,25 @@
struct input_dev *input_dev = data->input_dev;
int error;
- /* put regulators in high power mode */
- error = mxt_regulator_lpm(data, false);
- if (error < 0) {
- dev_err(dev, "failed to enter high power mode\n");
- return error;
+ /* put regulators back in active power mode */
+ if (data->lpm_support) {
+ error = mxt_regulator_lpm(data, false);
+ if (error < 0) {
+ dev_err(dev, "failed to enter high power mode\n");
+ return error;
+ }
+ } else {
+ error = mxt_power_on(data, true);
+ if (error < 0) {
+ dev_err(dev, "failed to enable regulators\n");
+ return error;
+ }
+ mxt_power_on_delay(data);
}
+ mxt_write_object(data, MXT_GEN_COMMAND_T6, MXT_COMMAND_RESET, 1);
+ mxt_reset_delay(data);
+
mutex_lock(&input_dev->mutex);
if (input_dev->users) {
@@ -2495,6 +2535,8 @@
mutex_unlock(&input_dev->mutex);
+ enable_irq(data->irq);
+
return 0;
}
@@ -2672,6 +2714,9 @@
pdata->no_force_update = of_property_read_bool(np,
"atmel,no-force-update");
+ pdata->no_lpm_support = of_property_read_bool(np,
+ "atmel,no-lpm-support");
+
/* reset, irq gpio info */
pdata->reset_gpio = of_get_named_gpio_flags(np, "atmel,reset-gpio",
0, &pdata->reset_gpio_flags);
@@ -2877,6 +2922,7 @@
data->input_dev = input_dev;
data->pdata = pdata;
data->no_force_update = pdata->no_force_update;
+ data->lpm_support = !pdata->no_lpm_support;
__set_bit(EV_ABS, input_dev->evbit);
__set_bit(EV_KEY, input_dev->evbit);
diff --git a/drivers/input/touchscreen/ft5x06_ts.c b/drivers/input/touchscreen/ft5x06_ts.c
index 8dbac64..8de6b1e 100644
--- a/drivers/input/touchscreen/ft5x06_ts.c
+++ b/drivers/input/touchscreen/ft5x06_ts.c
@@ -308,7 +308,7 @@
event->pressure = 0;
}
- input_mt_slot(data->input_dev, i);
+ input_mt_slot(data->input_dev, event->finger_id[i]);
input_mt_report_slot_state(data->input_dev, MT_TOOL_FINGER,
!!event->pressure);
@@ -317,10 +317,6 @@
event->x[i]);
input_report_abs(data->input_dev, ABS_MT_POSITION_Y,
event->y[i]);
- input_report_abs(data->input_dev, ABS_MT_PRESSURE,
- event->pressure);
- input_report_abs(data->input_dev, ABS_MT_TRACKING_ID,
- event->finger_id[i]);
input_report_abs(data->input_dev, ABS_MT_TOUCH_MAJOR,
event->pressure);
}
@@ -493,7 +489,7 @@
static int ft5x06_ts_suspend(struct device *dev)
{
struct ft5x06_ts_data *data = dev_get_drvdata(dev);
- char txbuf[2];
+ char txbuf[2], i;
if (data->loading_fw) {
dev_info(dev, "Firmware loading in process...\n");
@@ -507,6 +503,14 @@
disable_irq(data->client->irq);
+ /* release all touches */
+ for (i = 0; i < CFG_MAX_TOUCH_POINTS; i++) {
+ input_mt_slot(data->input_dev, i);
+ input_mt_report_slot_state(data->input_dev, MT_TOOL_FINGER, 0);
+ }
+ input_report_key(data->input_dev, BTN_TOUCH, 0);
+ input_sync(data->input_dev);
+
if (gpio_is_valid(data->pdata->reset_gpio)) {
txbuf[0] = FT_REG_PMODE;
txbuf[1] = FT_PMODE_HIBERNATE;
@@ -1231,7 +1235,6 @@
input_set_abs_params(input_dev, ABS_MT_POSITION_Y, pdata->y_min,
pdata->y_max, 0, 0);
input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, FT_PRESS, 0, 0);
- input_set_abs_params(input_dev, ABS_MT_PRESSURE, 0, FT_PRESS, 0, 0);
err = input_register_device(input_dev);
if (err) {
@@ -1306,7 +1309,7 @@
err = ft5x06_i2c_read(client, ®_addr, 1, ®_value, 1);
if (err < 0) {
dev_err(&client->dev, "version read failed");
- return err;
+ goto free_reset_gpio;
}
dev_info(&client->dev, "Device ID = 0x%x\n", reg_value);
diff --git a/drivers/input/touchscreen/synaptics_fw_update.c b/drivers/input/touchscreen/synaptics_fw_update.c
index c01ab0e..2a5fea7 100644
--- a/drivers/input/touchscreen/synaptics_fw_update.c
+++ b/drivers/input/touchscreen/synaptics_fw_update.c
@@ -1722,7 +1722,7 @@
static struct bin_attribute dev_attr_data = {
.attr = {
.name = "data",
- .mode = (S_IRUGO | S_IWUGO),
+ .mode = (S_IRUGO | S_IWUSR | S_IWGRP),
},
.size = 0,
.read = fwu_sysfs_show_image,
@@ -1730,25 +1730,25 @@
};
static struct device_attribute attrs[] = {
- __ATTR(fw_name, S_IWUGO | S_IRUGO,
+ __ATTR(fw_name, S_IRUGO | S_IWUSR | S_IWGRP,
fwu_sysfs_fw_name_show,
fwu_sysfs_fw_name_store),
- __ATTR(force_update_fw, S_IWUGO,
+ __ATTR(force_update_fw, S_IRUGO | S_IWUSR | S_IWGRP,
synaptics_rmi4_show_error,
fwu_sysfs_force_reflash_store),
- __ATTR(update_fw, S_IWUGO,
+ __ATTR(update_fw, S_IRUGO | S_IWUSR | S_IWGRP,
synaptics_rmi4_show_error,
fwu_sysfs_do_reflash_store),
- __ATTR(writeconfig, S_IWUGO,
+ __ATTR(writeconfig, S_IRUGO | S_IWUSR | S_IWGRP,
synaptics_rmi4_show_error,
fwu_sysfs_write_config_store),
- __ATTR(readconfig, S_IWUGO,
+ __ATTR(readconfig, S_IRUGO | S_IWUSR | S_IWGRP,
synaptics_rmi4_show_error,
fwu_sysfs_read_config_store),
- __ATTR(configarea, S_IWUGO,
+ __ATTR(configarea, S_IRUGO | S_IWUSR | S_IWGRP,
synaptics_rmi4_show_error,
fwu_sysfs_config_area_store),
- __ATTR(imagesize, S_IWUGO,
+ __ATTR(imagesize, S_IRUGO | S_IWUSR | S_IWGRP,
synaptics_rmi4_show_error,
fwu_sysfs_image_size_store),
__ATTR(blocksize, S_IRUGO,
diff --git a/drivers/input/touchscreen/synaptics_i2c_rmi4.c b/drivers/input/touchscreen/synaptics_i2c_rmi4.c
index 9da095a..ba0be2b 100644
--- a/drivers/input/touchscreen/synaptics_i2c_rmi4.c
+++ b/drivers/input/touchscreen/synaptics_i2c_rmi4.c
@@ -235,11 +235,11 @@
static struct device_attribute attrs[] = {
#ifdef CONFIG_PM
- __ATTR(full_pm_cycle, (S_IRUGO | S_IWUGO),
+ __ATTR(full_pm_cycle, (S_IRUGO | S_IWUSR | S_IWGRP),
synaptics_rmi4_full_pm_cycle_show,
synaptics_rmi4_full_pm_cycle_store),
#endif
- __ATTR(reset, S_IWUGO,
+ __ATTR(reset, S_IRUGO | S_IWUSR | S_IWGRP,
synaptics_rmi4_show_error,
synaptics_rmi4_f01_reset_store),
__ATTR(productinfo, S_IRUGO,
@@ -251,13 +251,13 @@
__ATTR(flashprog, S_IRUGO,
synaptics_rmi4_f01_flashprog_show,
synaptics_rmi4_store_error),
- __ATTR(0dbutton, (S_IRUGO | S_IWUGO),
+ __ATTR(0dbutton, (S_IRUGO | S_IWUSR | S_IWGRP),
synaptics_rmi4_0dbutton_show,
synaptics_rmi4_0dbutton_store),
- __ATTR(flipx, (S_IRUGO | S_IWUGO),
+ __ATTR(flipx, (S_IRUGO | S_IWUSR | S_IWGRP),
synaptics_rmi4_flipx_show,
synaptics_rmi4_flipx_store),
- __ATTR(flipy, (S_IRUGO | S_IWUGO),
+ __ATTR(flipy, (S_IRUGO | S_IWUSR | S_IWGRP),
synaptics_rmi4_flipy_show,
synaptics_rmi4_flipy_store),
};
diff --git a/drivers/input/touchscreen/synaptics_rmi_dev.c b/drivers/input/touchscreen/synaptics_rmi_dev.c
index c6b8a1c..c60ca23 100644
--- a/drivers/input/touchscreen/synaptics_rmi_dev.c
+++ b/drivers/input/touchscreen/synaptics_rmi_dev.c
@@ -73,19 +73,19 @@
};
static struct device_attribute attrs[] = {
- __ATTR(open, S_IWUGO,
+ __ATTR(open, S_IRUGO | S_IWUSR | S_IWGRP,
synaptics_rmi4_show_error,
rmidev_sysfs_open_store),
- __ATTR(release, S_IWUGO,
+ __ATTR(release, S_IRUGO | S_IWUSR | S_IWGRP,
synaptics_rmi4_show_error,
rmidev_sysfs_release_store),
- __ATTR(address, S_IWUGO,
+ __ATTR(address, S_IRUGO | S_IWUSR | S_IWGRP,
synaptics_rmi4_show_error,
rmidev_sysfs_address_store),
- __ATTR(length, S_IWUGO,
+ __ATTR(length, S_IRUGO | S_IWUSR | S_IWGRP,
synaptics_rmi4_show_error,
rmidev_sysfs_length_store),
- __ATTR(data, (S_IRUGO | S_IWUGO),
+ __ATTR(data, (S_IRUGO | S_IWUSR | S_IWGRP),
rmidev_sysfs_data_show,
rmidev_sysfs_data_store),
};
diff --git a/drivers/leds/leds-qpnp.c b/drivers/leds/leds-qpnp.c
index fbcc243..e84b477 100644
--- a/drivers/leds/leds-qpnp.c
+++ b/drivers/leds/leds-qpnp.c
@@ -170,11 +170,13 @@
#define LED_MPP_SINK_CTRL(base) (base + 0x4C)
#define LED_MPP_CURRENT_DEFAULT 5
+#define LED_MPP_VIN_CTRL_DEFAULT 0
#define LED_MPP_CURRENT_PER_SETTING 5
#define LED_MPP_SOURCE_SEL_DEFAULT LED_MPP_MODE_ENABLE
#define LED_MPP_SINK_MASK 0x07
#define LED_MPP_MODE_MASK 0x7F
+#define LED_MPP_VIN_MASK 0x03
#define LED_MPP_EN_MASK 0x80
#define LED_MPP_SRC_MASK 0x0F
#define LED_MPP_MODE_CTRL_MASK 0x70
@@ -348,6 +350,8 @@
* @current_setting - current setting, 5ma-40ma in 5ma increments
* @source_sel - source selection
* @mode_ctrl - mode control
+ * @vin_ctrl - input control
+ * @min_brightness - minimum brightness supported
* @pwm_mode - pwm mode in use
*/
struct mpp_config_data {
@@ -355,6 +359,8 @@
u8 current_setting;
u8 source_sel;
u8 mode_ctrl;
+ u8 vin_ctrl;
+ u8 min_brightness;
u8 pwm_mode;
};
@@ -576,6 +582,13 @@
int duty_us;
if (led->cdev.brightness) {
+ if (led->cdev.brightness < led->mpp_cfg->min_brightness) {
+ dev_warn(&led->spmi_dev->dev,
+ "brightness is less than supported..." \
+ "set to minimum supported\n");
+ led->cdev.brightness = led->mpp_cfg->min_brightness;
+ }
+
if (led->mpp_cfg->pwm_mode != MANUAL_MODE) {
if (!led->mpp_cfg->pwm_cfg->blinking) {
led->mpp_cfg->pwm_cfg->mode =
@@ -2093,6 +2106,14 @@
if (val < 0)
val = 0;
+ 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,
+ "Failed to write led vin control reg\n");
+ return rc;
+ }
+
rc = qpnp_led_masked_write(led, LED_MPP_SINK_CTRL(led->base),
LED_MPP_SINK_MASK, val);
if (rc) {
@@ -2677,6 +2698,20 @@
else if (rc != -EINVAL)
return rc;
+ led->mpp_cfg->vin_ctrl = LED_MPP_VIN_CTRL_DEFAULT;
+ rc = of_property_read_u32(node, "qcom,vin-ctrl", &val);
+ if (!rc)
+ led->mpp_cfg->vin_ctrl = (u8) val;
+ else if (rc != -EINVAL)
+ return rc;
+
+ led->mpp_cfg->min_brightness = 0;
+ rc = of_property_read_u32(node, "qcom,min-brightness", &val);
+ if (!rc)
+ led->mpp_cfg->min_brightness = (u8) val;
+ else if (rc != -EINVAL)
+ return rc;
+
rc = of_property_read_string(node, "qcom,mode", &mode);
if (!rc) {
led_mode = qpnp_led_get_mode(mode);
diff --git a/drivers/media/platform/msm/camera_v2/msm.c b/drivers/media/platform/msm/camera_v2/msm.c
index 8d53e35..07f3b40 100644
--- a/drivers/media/platform/msm/camera_v2/msm.c
+++ b/drivers/media/platform/msm/camera_v2/msm.c
@@ -519,6 +519,7 @@
struct msm_session *session;
unsigned int session_id;
unsigned int stream_id;
+ unsigned long spin_flags = 0;
event_data = (struct msm_v4l2_event_data *)
((struct v4l2_event *)arg)->u.data;
@@ -564,9 +565,13 @@
break;
}
+ spin_lock_irqsave(&(session->command_ack_q.lock),
+ spin_flags);
ret_cmd->event = *(struct v4l2_event *)arg;
msm_enqueue(&cmd_ack->command_q, &ret_cmd->list);
wake_up(&cmd_ack->wait);
+ spin_unlock_irqrestore(&(session->command_ack_q.lock),
+ spin_flags);
}
break;
diff --git a/drivers/media/platform/msm/camera_v2/sensor/hi256.c b/drivers/media/platform/msm/camera_v2/sensor/hi256.c
index f1df703..de651df 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/hi256.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/hi256.c
@@ -1000,15 +1000,25 @@
{0x30, 0x06},
{0x31, 0x40},
{0x03, 0x20},
- {0x88, 0x05},
- {0x89, 0x7e},
- {0x8a, 0x40},
+ {0x88, 0x01},
+ {0x89, 0x5f},
+ {0x8a, 0x90},
{0x03, 0x20},
{0x10, 0x9c},
{0x03, 0x22},
{0x10, 0xe9},
};
+static struct msm_camera_i2c_reg_conf hi256_sleep_settings[] = {
+ {0x03, 0x00},
+ {0x01, 0xf1},
+ {0x03, 0x02},
+ {0x55, 0x10},
+ {0x01, 0xf1},
+ {0x01, 0xf3},
+ {0x01, 0xf1},
+};
+
static const struct i2c_device_id hi256_i2c_id[] = {
{HI256_SENSOR_NAME, (kernel_ulong_t)&hi256_s_ctrl},
@@ -1073,6 +1083,13 @@
}
+static int32_t hi256_sensor_power_down(struct msm_sensor_ctrl_t *s_ctrl)
+{
+ hi256_i2c_write_table(s_ctrl, &hi256_sleep_settings[0],
+ ARRAY_SIZE(hi256_sleep_settings));
+ return msm_sensor_power_down(s_ctrl);
+}
+
static int32_t hi256_platform_probe(struct platform_device *pdev)
{
int32_t rc;
@@ -1393,7 +1410,7 @@
static struct msm_sensor_fn_t hi256_sensor_func_tbl = {
.sensor_config = hi256_sensor_config,
.sensor_power_up = msm_sensor_power_up,
- .sensor_power_down = msm_sensor_power_down,
+ .sensor_power_down = hi256_sensor_power_down,
.sensor_match_id = hi256_sensor_match_id,
};
diff --git a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_cci_i2c.c b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_cci_i2c.c
index 40d1155..3792247 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_cci_i2c.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_cci_i2c.c
@@ -338,17 +338,11 @@
enum msm_camera_i2c_data_type data_type)
{
int32_t rc;
- int i;
S_I2C_DBG("%s: addr: 0x%x data: 0x%x dt: %d\n",
__func__, addr, data, data_type);
- for (i = 0; i < I2C_POLL_MAX_ITERATION; i++) {
- rc = msm_camera_cci_i2c_compare(client,
- addr, data, data_type);
- if (rc == 0 || rc < 0)
- break;
- usleep_range(10000, 11000);
- }
+ rc = msm_camera_cci_i2c_compare(client,
+ addr, data, data_type);
return rc;
}
diff --git a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c
index 7f474bb..adbfbe7 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c
@@ -569,7 +569,92 @@
CDBG("%s qcom,gpio-reset %d\n", __func__,
gconf->gpio_num_info->gpio_num[SENSOR_GPIO_STANDBY]);
}
- return rc;
+
+ rc = of_property_read_u32(of_node, "qcom,gpio-vio", &val);
+ if (!rc) {
+ if (val >= gpio_array_size) {
+ pr_err("%s:%d qcom,gpio-vio invalid %d\n",
+ __func__, __LINE__, val);
+ goto ERROR;
+ }
+ gconf->gpio_num_info->gpio_num[SENSOR_GPIO_VIO] =
+ gpio_array[val];
+ CDBG("%s qcom,gpio-vio %d\n", __func__,
+ gconf->gpio_num_info->gpio_num[SENSOR_GPIO_VIO]);
+ } else if (rc != -EINVAL) {
+ pr_err("%s:%d read qcom,gpio-vio failed rc %d\n",
+ __func__, __LINE__, rc);
+ goto ERROR;
+ }
+
+ rc = of_property_read_u32(of_node, "qcom,gpio-vana", &val);
+ if (!rc) {
+ if (val >= gpio_array_size) {
+ pr_err("%s:%d qcom,gpio-vana invalid %d\n",
+ __func__, __LINE__, val);
+ goto ERROR;
+ }
+ gconf->gpio_num_info->gpio_num[SENSOR_GPIO_VANA] =
+ gpio_array[val];
+ CDBG("%s qcom,gpio-vana %d\n", __func__,
+ gconf->gpio_num_info->gpio_num[SENSOR_GPIO_VANA]);
+ } else if (rc != -EINVAL) {
+ pr_err("%s:%d read qcom,gpio-vana failed rc %d\n",
+ __func__, __LINE__, rc);
+ goto ERROR;
+ }
+
+ rc = of_property_read_u32(of_node, "qcom,gpio-vdig", &val);
+ if (!rc) {
+ if (val >= gpio_array_size) {
+ pr_err("%s:%d qcom,gpio-vdig invalid %d\n",
+ __func__, __LINE__, val);
+ goto ERROR;
+ }
+ gconf->gpio_num_info->gpio_num[SENSOR_GPIO_VDIG] =
+ gpio_array[val];
+ CDBG("%s qcom,gpio-vdig %d\n", __func__,
+ gconf->gpio_num_info->gpio_num[SENSOR_GPIO_VDIG]);
+ } else if (rc != -EINVAL) {
+ pr_err("%s:%d read qcom,gpio-vdig failed rc %d\n",
+ __func__, __LINE__, rc);
+ goto ERROR;
+ }
+
+ rc = of_property_read_u32(of_node, "qcom,gpio-vaf", &val);
+ if (!rc) {
+ if (val >= gpio_array_size) {
+ pr_err("%s:%d qcom,gpio-vaf invalid %d\n",
+ __func__, __LINE__, val);
+ goto ERROR;
+ }
+ gconf->gpio_num_info->gpio_num[SENSOR_GPIO_VAF] =
+ gpio_array[val];
+ CDBG("%s qcom,gpio-vaf %d\n", __func__,
+ gconf->gpio_num_info->gpio_num[SENSOR_GPIO_VAF]);
+ } else if (rc != -EINVAL) {
+ pr_err("%s:%d read qcom,gpio-vaf failed rc %d\n",
+ __func__, __LINE__, rc);
+ goto ERROR;
+ }
+
+ rc = of_property_read_u32(of_node, "qcom,gpio-af-pwdm", &val);
+ if (!rc) {
+ if (val >= gpio_array_size) {
+ pr_err("%s:%d qcom,gpio-af-pwdm invalid %d\n",
+ __func__, __LINE__, val);
+ goto ERROR;
+ }
+ gconf->gpio_num_info->gpio_num[SENSOR_GPIO_AF_PWDM] =
+ gpio_array[val];
+ CDBG("%s qcom,gpio-af-pwdm %d\n", __func__,
+ gconf->gpio_num_info->gpio_num[SENSOR_GPIO_AF_PWDM]);
+ } else if (rc != -EINVAL) {
+ pr_err("%s:%d read qcom,gpio-af-pwdm failed rc %d\n",
+ __func__, __LINE__, rc);
+ goto ERROR;
+ }
+ return 0;
ERROR:
kfree(gconf->gpio_num_info);
@@ -1162,6 +1247,15 @@
return;
}
+static int msm_sensor_get_af_status(struct msm_sensor_ctrl_t *s_ctrl,
+ void __user *argp)
+{
+ /* TO-DO: Need to set AF status register address and expected value
+ We need to check the AF status in the sensor register and
+ set the status in the *status variable accordingly*/
+ return 0;
+}
+
static long msm_sensor_subdev_ioctl(struct v4l2_subdev *sd,
unsigned int cmd, void *arg)
{
@@ -1174,6 +1268,8 @@
switch (cmd) {
case VIDIOC_MSM_SENSOR_CFG:
return s_ctrl->func_tbl->sensor_config(s_ctrl, argp);
+ case VIDIOC_MSM_SENSOR_GET_AF_STATUS:
+ return msm_sensor_get_af_status(s_ctrl, argp);
case VIDIOC_MSM_SENSOR_RELEASE:
msm_sensor_stop_stream(s_ctrl);
return 0;
diff --git a/drivers/media/platform/msm/camera_v2/sensor/mt9m114.c b/drivers/media/platform/msm/camera_v2/sensor/mt9m114.c
index c1cf862..de4fcd0 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/mt9m114.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/mt9m114.c
@@ -1424,8 +1424,51 @@
break;
}
break;
- }
- default:
+ }
+ case CFG_SET_SATURATION: {
+ int32_t sat_lev;
+ if (copy_from_user(&sat_lev, (void *)cdata->cfg.setting,
+ sizeof(int32_t))) {
+ pr_err("%s:%d failed\n", __func__, __LINE__);
+ rc = -EFAULT;
+ break;
+ }
+ pr_debug("%s: Saturation Value is %d", __func__, sat_lev);
+ break;
+ }
+ case CFG_SET_CONTRAST: {
+ int32_t con_lev;
+ if (copy_from_user(&con_lev, (void *)cdata->cfg.setting,
+ sizeof(int32_t))) {
+ pr_err("%s:%d failed\n", __func__, __LINE__);
+ rc = -EFAULT;
+ break;
+ }
+ pr_debug("%s: Contrast Value is %d", __func__, con_lev);
+ break;
+ }
+ case CFG_SET_SHARPNESS: {
+ int32_t shp_lev;
+ if (copy_from_user(&shp_lev, (void *)cdata->cfg.setting,
+ sizeof(int32_t))) {
+ pr_err("%s:%d failed\n", __func__, __LINE__);
+ rc = -EFAULT;
+ break;
+ }
+ pr_debug("%s: Sharpness Value is %d", __func__, shp_lev);
+ break;
+ }
+ case CFG_SET_AUTOFOCUS: {
+ /* TO-DO: set the Auto Focus */
+ pr_debug("%s: Setting Auto Focus", __func__);
+ break;
+ }
+ case CFG_CANCEL_AUTOFOCUS: {
+ /* TO-DO: Cancel the Auto Focus */
+ pr_debug("%s: Cancelling Auto Focus", __func__);
+ break;
+ }
+ default:
rc = -EFAULT;
break;
}
diff --git a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c
index 75b75ea..a3d6dd8 100644
--- a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c
+++ b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c
@@ -1635,7 +1635,17 @@
__func__, ret);
goto failed_unmap_metadata_buf;
}
- metadata_buff_desc->base_addr = (void *)temp;
+
+ /*
+ * NOTE: the following casting to u32 must be done
+ * as long as TZ does not support LPAE. Once TZ supports
+ * LPAE SDMX interface needs to be updated accordingly.
+ */
+ if (temp > 0xFFFFFFFF)
+ MPQ_DVB_ERR_PRINT(
+ "%s: WARNNING - physical address %pa is larger than 32bits!\n",
+ __func__, &temp);
+ metadata_buff_desc->base_addr = (void *)(u32)temp;
dvb_ringbuffer_init(&feed->metadata_buf, metadata_buff_base,
SDMX_METADATA_BUFFER_SIZE);
@@ -2273,7 +2283,16 @@
return ret;
}
- buf_desc->base_addr = (void *)phys_addr;
+ /*
+ * NOTE: the following casting to u32 must be done
+ * as long as TZ does not support LPAE. Once TZ supports
+ * LPAE SDMX interface needs to be updated accordingly.
+ */
+ if (phys_addr > 0xFFFFFFFF)
+ MPQ_DVB_ERR_PRINT(
+ "%s: WARNNING - physical address %pa is larger than 32bits!\n",
+ __func__, &phys_addr);
+ buf_desc->base_addr = (void *)(u32)phys_addr;
buf_desc->size = rbuf->size;
return 0;
@@ -3405,8 +3424,19 @@
sg = sg_ptr->sgl;
for (i = 0; i < sg_ptr->nents; i++) {
+ /*
+ * NOTE: the following casting to u32 must be done
+ * as long as TZ does not support LPAE. Once TZ supports
+ * LPAE SDMX interface needs to be updated accordingly.
+ */
+ if (sg_dma_address(sg) > 0xFFFFFFFF)
+ MPQ_DVB_ERR_PRINT(
+ "%s: WARNNING - physical address %pa is larger than 32bits!\n",
+ __func__, &sg_dma_address(sg));
+
buff_chunks[i].base_addr =
- (void *)sg_dma_address(sg);
+ (void *)(u32)sg_dma_address(sg);
+
if (sg->length > actual_buff_size)
chunk_size = actual_buff_size;
else
diff --git a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v1.c b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v1.c
index 940a4bc..8179061 100644
--- a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v1.c
+++ b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v1.c
@@ -195,7 +195,7 @@
} mpq_dmx_tspp_info;
static void *tspp_mem_allocator(int channel_id, u32 size,
- u32 *phys_base, void *user)
+ phys_addr_t *phys_base, void *user)
{
void *virt_addr = NULL;
int i = TSPP_GET_TSIF_NUM(channel_id);
@@ -218,7 +218,7 @@
}
static void tspp_mem_free(int channel_id, u32 size,
- void *virt_base, u32 phys_base, void *user)
+ void *virt_base, phys_addr_t phys_base, void *user)
{
int i = TSPP_GET_TSIF_NUM(channel_id);
@@ -372,7 +372,18 @@
buff_start_addr_phys =
mpq_dmx_tspp_info.tsif[tsif].ch_mem_heap_phys_base;
- input.base_addr = (void *)buff_start_addr_phys;
+
+ /*
+ * NOTE: the following casting to u32 must be done
+ * as long as TZ does not support LPAE. Once TZ supports
+ * LPAE SDMX interface needs to be updated accordingly.
+ */
+ if (buff_start_addr_phys > 0xFFFFFFFF)
+ MPQ_DVB_ERR_PRINT(
+ "%s: WARNNING - physical address %pa is larger than 32bits!\n",
+ __func__, &buff_start_addr_phys);
+
+ input.base_addr = (void *)(u32)buff_start_addr_phys;
input.size = mpq_dmx_tspp_info.tsif[tsif].buffer_count *
TSPP_DESCRIPTOR_SIZE;
@@ -381,7 +392,7 @@
"%s: SDMX Processing %d descriptors: %d bytes at start address 0x%x, read offset %d\n",
__func__, aggregate_count, aggregate_len,
(unsigned int)input.base_addr,
- buff_current_addr_phys - buff_start_addr_phys);
+ (int)(buff_current_addr_phys - buff_start_addr_phys));
mpq_sdmx_process(mpq_demux, &input, aggregate_len,
buff_current_addr_phys - buff_start_addr_phys,
diff --git a/drivers/media/platform/msm/vidc/hfi_packetization.c b/drivers/media/platform/msm/vidc/hfi_packetization.c
index 6e8c809..d92a9c1 100644
--- a/drivers/media/platform/msm/vidc/hfi_packetization.c
+++ b/drivers/media/platform/msm/vidc/hfi_packetization.c
@@ -360,6 +360,25 @@
return ret;
}
+static u32 get_hfi_buf_mode(enum buffer_mode_type hal_buf_mode)
+{
+ u32 buf_mode;
+ switch (hal_buf_mode) {
+ case HAL_BUFFER_MODE_STATIC:
+ buf_mode = HFI_BUFFER_MODE_STATIC;
+ break;
+ case HAL_BUFFER_MODE_RING:
+ buf_mode = HFI_BUFFER_MODE_RING;
+ break;
+ default:
+ dprintk(VIDC_ERR, "Invalid buffer mode :0x%x\n",
+ hal_buf_mode);
+ buf_mode = 0;
+ break;
+ }
+ return buf_mode;
+}
+
int create_pkt_cmd_session_set_buffers(
struct hfi_cmd_session_set_buffers_packet *pkt,
u32 session_id,
@@ -1277,6 +1296,39 @@
pkt->size += sizeof(u32) + sizeof(struct hfi_enable);
break;
}
+ case HAL_PARAM_BUFFER_ALLOC_MODE:
+ {
+ u32 buffer_type;
+ u32 buffer_mode;
+ struct hfi_buffer_alloc_mode *hfi;
+ struct hal_buffer_alloc_mode *alloc_info = pdata;
+ pkt->rg_property_data[0] =
+ HFI_PROPERTY_PARAM_BUFFER_ALLOC_MODE;
+ hfi = (struct hfi_buffer_alloc_mode *)
+ &pkt->rg_property_data[1];
+ buffer_type = get_hfi_buffer(alloc_info->buffer_type);
+ if (buffer_type)
+ hfi->buffer_type = buffer_type;
+ else
+ return -EINVAL;
+ buffer_mode = get_hfi_buf_mode(alloc_info->buffer_mode);
+ if (buffer_mode)
+ hfi->buffer_mode = buffer_mode;
+ else
+ return -EINVAL;
+ pkt->size += sizeof(u32) + sizeof(struct hfi_buffer_alloc_mode);
+ break;
+ }
+ case HAL_PARAM_VDEC_FRAME_ASSEMBLY:
+ {
+ struct hfi_enable *hfi;
+ pkt->rg_property_data[0] =
+ HFI_PROPERTY_PARAM_VDEC_FRAME_ASSEMBLY;
+ hfi = (struct hfi_enable *) &pkt->rg_property_data[1];
+ hfi->enable = ((struct hfi_enable *) pdata)->enable;
+ pkt->size += sizeof(u32) + sizeof(struct hfi_enable);
+ break;
+ }
/* FOLLOWING PROPERTIES ARE NOT IMPLEMENTED IN CORE YET */
case HAL_CONFIG_BUFFER_REQUIREMENTS:
case HAL_CONFIG_PRIORITY:
@@ -1343,3 +1395,17 @@
pkt->trigger_type = get_hfi_ssr_type(type);
return 0;
}
+
+int create_pkt_cmd_sys_image_version(
+ struct hfi_cmd_sys_get_property_packet *pkt)
+{
+ if (!pkt) {
+ dprintk(VIDC_ERR, "%s invalid param :%p\n", __func__, pkt);
+ return -EINVAL;
+ }
+ pkt->size = sizeof(struct hfi_cmd_sys_get_property_packet);
+ pkt->packet_type = HFI_CMD_SYS_GET_PROPERTY;
+ pkt->num_properties = 1;
+ pkt->rg_property_data[0] = HFI_PROPERTY_SYS_IMAGE_VERSION;
+ return 0;
+}
diff --git a/drivers/media/platform/msm/vidc/hfi_packetization.h b/drivers/media/platform/msm/vidc/hfi_packetization.h
index df93906..20619c0 100644
--- a/drivers/media/platform/msm/vidc/hfi_packetization.h
+++ b/drivers/media/platform/msm/vidc/hfi_packetization.h
@@ -89,4 +89,7 @@
int create_pkt_ssr_cmd(enum hal_ssr_trigger_type type,
struct hfi_cmd_sys_test_ssr_packet *pkt);
+
+int create_pkt_cmd_sys_image_version(
+ struct hfi_cmd_sys_get_property_packet *pkt);
#endif
diff --git a/drivers/media/platform/msm/vidc/hfi_response_handler.c b/drivers/media/platform/msm/vidc/hfi_response_handler.c
index 859345f..44105ad 100644
--- a/drivers/media/platform/msm/vidc/hfi_response_handler.c
+++ b/drivers/media/platform/msm/vidc/hfi_response_handler.c
@@ -14,6 +14,7 @@
#include <linux/slab.h>
#include <linux/list.h>
#include <linux/interrupt.h>
+#include <mach/msm_smem.h>
#include "vidc_hfi_helper.h"
#include "vidc_hfi_io.h"
#include "msm_vidc_debug.h"
@@ -1089,6 +1090,44 @@
callback(SESSION_GET_SEQ_HDR_DONE, &data_done);
}
+void hfi_process_sys_property_info(
+ struct hfi_property_sys_image_version_info_type *pkt)
+{
+ int i = 0;
+ u32 smem_block_size = 0;
+ u8 *smem_table_ptr;
+ char version[256];
+ const u32 smem_image_index_venus = 14 * 128;
+
+ if (!pkt || !pkt->string_size) {
+ dprintk(VIDC_ERR, "%s: invalid param\n", __func__);
+ return;
+ }
+
+ if (pkt->string_size < sizeof(version)) {
+ /*
+ * The version string returned by firmware includes null
+ * characters at the start and in between. Replace the null
+ * characters with space, to print the version info.
+ */
+ for (i = 0; i < pkt->string_size; i++) {
+ if (pkt->str_image_version[i] != '\0')
+ version[i] = pkt->str_image_version[i];
+ else
+ version[i] = ' ';
+ }
+ version[i] = '\0';
+ dprintk(VIDC_INFO, "F/W version: %s\n", version);
+ }
+
+ smem_table_ptr = smem_get_entry(SMEM_IMAGE_VERSION_TABLE,
+ &smem_block_size);
+ if (smem_table_ptr &&
+ ((smem_image_index_venus + 128) <= smem_block_size))
+ memcpy(smem_table_ptr + smem_image_index_venus,
+ (u8 *)pkt->str_image_version, 128);
+}
+
u32 hfi_process_msg_packet(
msm_vidc_callback callback, u32 device_id,
struct vidc_hal_msg_pkt_hdr *msg_hdr)
@@ -1121,6 +1160,11 @@
(struct hfi_msg_sys_session_init_done_packet *)
msg_hdr);
break;
+ case HFI_MSG_SYS_PROPERTY_INFO:
+ hfi_process_sys_property_info(
+ (struct hfi_property_sys_image_version_info_type *)
+ msg_hdr);
+ break;
case HFI_MSG_SYS_SESSION_END_DONE:
hfi_process_session_end_done(callback, device_id,
(struct hfi_msg_sys_session_end_done_packet *)
diff --git a/drivers/media/platform/msm/vidc/msm_vdec.c b/drivers/media/platform/msm/vidc/msm_vdec.c
index 7547464..96bf9f4 100644
--- a/drivers/media/platform/msm/vidc/msm_vdec.c
+++ b/drivers/media/platform/msm/vidc/msm_vdec.c
@@ -68,6 +68,10 @@
"Extradata aspect ratio",
"Extradata mpeg2 seqdisp",
};
+static const char *const mpeg_vidc_video_alloc_mode_type[] = {
+ "Buffer Allocation Static",
+ "Buffer Allocation Ring Buffer",
+};
static const char *const perf_level[] = {
"Nominal",
@@ -249,6 +253,33 @@
.qmenu = perf_level,
.step = 0,
},
+ {
+ .id = V4L2_CID_MPEG_VIDC_VIDEO_ALLOC_MODE,
+ .name = "Buffer allocation mode",
+ .type = V4L2_CTRL_TYPE_MENU,
+ .minimum = V4L2_MPEG_VIDC_VIDEO_STATIC,
+ .maximum = V4L2_MPEG_VIDC_VIDEO_RING,
+ .default_value = V4L2_MPEG_VIDC_VIDEO_STATIC,
+ .menu_skip_mask = ~(
+ (1 << V4L2_MPEG_VIDC_VIDEO_STATIC) |
+ (1 << V4L2_MPEG_VIDC_VIDEO_RING)
+ ),
+ .qmenu = mpeg_vidc_video_alloc_mode_type,
+ .step = 0,
+ .cluster = 0,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDC_VIDEO_FRAME_ASSEMBLY,
+ .name = "Video frame assembly",
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .minimum = V4L2_MPEG_VIDC_FRAME_ASSEMBLY_DISABLE,
+ .maximum = V4L2_MPEG_VIDC_FRAME_ASSEMBLY_ENABLE,
+ .default_value = V4L2_MPEG_VIDC_FRAME_ASSEMBLY_DISABLE,
+ .step = 1,
+ .menu_skip_mask = 0,
+ .qmenu = NULL,
+ .cluster = 0,
+ },
};
#define NUM_CTRLS ARRAY_SIZE(msm_vdec_ctrls)
@@ -934,6 +965,8 @@
struct hal_buffer_requirements *bufreq;
int extra_idx = 0;
struct hfi_device *hdev;
+ struct hal_buffer_count_actual new_buf_count;
+ enum hal_property property_id;
if (!q || !num_buffers || !num_planes
|| !sizes || !q->drv_priv) {
dprintk(VIDC_ERR, "Invalid input, q = %p, %p, %p\n",
@@ -960,6 +993,16 @@
i, inst->capability.height.max,
inst->capability.width.max);
}
+ property_id = HAL_PARAM_BUFFER_COUNT_ACTUAL;
+ new_buf_count.buffer_type = HAL_BUFFER_INPUT;
+ new_buf_count.buffer_count_actual = *num_buffers;
+ rc = call_hfi_op(hdev, session_set_property,
+ inst->session, property_id, &new_buf_count);
+ if (rc) {
+ dprintk(VIDC_WARN,
+ "Failed to set new buffer count(%d) on FW, err: %d\n",
+ new_buf_count.buffer_count_actual, rc);
+ }
break;
case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
dprintk(VIDC_DBG, "Getting bufreqs on capture plane\n");
@@ -987,15 +1030,11 @@
}
if (*num_buffers && *num_buffers >
bufreq->buffer_count_actual) {
- struct hal_buffer_count_actual new_buf_count;
- enum hal_property property_id =
- HAL_PARAM_BUFFER_COUNT_ACTUAL;
-
+ property_id = HAL_PARAM_BUFFER_COUNT_ACTUAL;
new_buf_count.buffer_type = HAL_BUFFER_OUTPUT;
new_buf_count.buffer_count_actual = *num_buffers;
rc = call_hfi_op(hdev, session_set_property,
inst->session, property_id, &new_buf_count);
-
}
if (bufreq->buffer_count_actual > *num_buffers)
*num_buffers = bufreq->buffer_count_actual;
@@ -1349,13 +1388,29 @@
}
break;
+ case V4L2_CID_MPEG_VIDC_VIDEO_ALLOC_MODE:
+ {
+ struct hal_buffer_alloc_mode mode;
+ property_id = HAL_PARAM_BUFFER_ALLOC_MODE;
+ mode.buffer_mode = ctrl->val;
+ mode.buffer_type = HAL_BUFFER_INPUT;
+ pdata = &mode;
+ break;
+ }
+ case V4L2_CID_MPEG_VIDC_VIDEO_FRAME_ASSEMBLY:
+ {
+ property_id = HAL_PARAM_VDEC_FRAME_ASSEMBLY;
+ hal_property.enable = ctrl->val;
+ pdata = &hal_property;
+ break;
+ }
default:
break;
}
if (!rc && property_id) {
dprintk(VIDC_DBG,
- "Control: HAL property = %d, ctrl_id = 0x%x, ctrl_value = %d\n",
+ "Control: HAL property=0x%x,ctrl: id=0x%x,value=0x%x\n",
property_id, ctrl->id, ctrl->val);
rc = call_hfi_op(hdev, session_set_property, (void *)
inst->session, property_id, pdata);
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c
index 77f838c..5f0ec4e 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c
@@ -69,6 +69,20 @@
return false;
}
+static bool is_thumbnail_session(struct msm_vidc_inst *inst)
+{
+ if (inst->session_type == MSM_VIDC_DECODER) {
+ int rc = 0;
+ struct v4l2_control ctrl = {
+ .id = V4L2_CID_MPEG_VIDC_VIDEO_SYNC_FRAME_DECODE
+ };
+ rc = v4l2_g_ctrl(&inst->ctrl_handler, &ctrl);
+ if (!rc && ctrl.value)
+ return true;
+ }
+ return false;
+}
+
static int msm_comm_get_load(struct msm_vidc_core *core,
enum session_type type)
{
@@ -83,7 +97,9 @@
if (inst->session_type == type &&
inst->state >= MSM_VIDC_OPEN_DONE &&
inst->state < MSM_VIDC_STOP_DONE) {
- num_mbs_per_sec += NUM_MBS_PER_SEC(inst->prop.height,
+ if (!is_thumbnail_session(inst))
+ num_mbs_per_sec += NUM_MBS_PER_SEC(
+ inst->prop.height,
inst->prop.width, inst->prop.fps);
}
mutex_unlock(&inst->lock);
@@ -728,6 +744,15 @@
vb = response->clnt_data;
inst = (struct msm_vidc_inst *)response->session_id;
if (vb) {
+ vb->v4l2_planes[0].bytesused = response->input_done.filled_len;
+ vb->v4l2_planes[0].data_offset = response->input_done.offset;
+ if (vb->v4l2_planes[0].data_offset > vb->v4l2_planes[0].length)
+ dprintk(VIDC_ERR, "Error: data_offset overflow\n");
+ if (vb->v4l2_planes[0].bytesused > vb->v4l2_planes[0].length)
+ dprintk(VIDC_ERR, "Error: buffer overflow\n");
+ if ((u8 *)vb->v4l2_planes[0].m.userptr !=
+ response->input_done.packet_buffer)
+ dprintk(VIDC_ERR, "Error: unexpected buffer address\n");
mutex_lock(&inst->bufq[OUTPUT_PORT].lock);
vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
mutex_unlock(&inst->bufq[OUTPUT_PORT].lock);
@@ -1889,10 +1914,19 @@
memset(&frame_data, 0 , sizeof(struct vidc_frame_data));
frame_data.alloc_len = vb->v4l2_planes[0].length;
frame_data.filled_len = vb->v4l2_planes[0].bytesused;
+ frame_data.offset = vb->v4l2_planes[0].data_offset;
frame_data.device_addr = vb->v4l2_planes[0].m.userptr;
frame_data.timestamp = time_usec;
frame_data.flags = 0;
frame_data.clnt_data = (u32)vb;
+ if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE &&
+ (frame_data.filled_len > frame_data.alloc_len ||
+ frame_data.offset > frame_data.alloc_len)) {
+ dprintk(VIDC_ERR,
+ "Buffer will overflow, not queueing it\n");
+ rc = -EINVAL;
+ goto err_bad_input;
+ }
if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
frame_data.buffer_type = HAL_BUFFER_INPUT;
if (vb->v4l2_buf.flags & V4L2_BUF_FLAG_EOS) {
@@ -1911,8 +1945,11 @@
V4L2_QCOM_BUF_TIMESTAMP_INVALID)
frame_data.timestamp = LLONG_MAX;
dprintk(VIDC_DBG,
- "Sending etb to hal: Alloc: %d :filled: %d\n",
- frame_data.alloc_len, frame_data.filled_len);
+ "Sending etb to hal: device_addr: 0x%x"
+ "Alloc: %d, filled: %d, offset: %d\n",
+ frame_data.device_addr,
+ frame_data.alloc_len, frame_data.filled_len,
+ frame_data.offset);
rc = call_hfi_op(hdev, session_etb, (void *)
inst->session, &frame_data);
if (!rc)
@@ -1965,6 +2002,7 @@
rc = -EINVAL;
}
}
+err_bad_input:
if (rc)
dprintk(VIDC_ERR, "Failed to queue buffer\n");
err_no_mem:
diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c
index 28ea41a..47b88db 100644
--- a/drivers/media/platform/msm/vidc/venus_hfi.c
+++ b/drivers/media/platform/msm/vidc/venus_hfi.c
@@ -1030,6 +1030,7 @@
static int venus_hfi_core_init(void *device)
{
struct hfi_cmd_sys_init_packet pkt;
+ struct hfi_cmd_sys_get_property_packet version_pkt;
int rc = 0;
struct venus_hfi_device *dev;
@@ -1088,6 +1089,10 @@
rc = -ENOTEMPTY;
goto err_core_init;
}
+ rc = create_pkt_cmd_sys_image_version(&version_pkt);
+ if (rc || venus_hfi_iface_cmdq_write(dev, &version_pkt))
+ dprintk(VIDC_WARN, "Failed to send image version pkt to f/w");
+
return rc;
err_core_init:
disable_irq_nosync(dev->hal_data->irq);
@@ -1418,6 +1423,10 @@
break;
case HAL_SYS_DEBUG_CONFIG:
break;
+ case HAL_PARAM_BUFFER_ALLOC_MODE:
+ break;
+ case HAL_PARAM_VDEC_FRAME_ASSEMBLY:
+ break;
/*FOLLOWING PROPERTIES ARE NOT IMPLEMENTED IN CORE YET*/
case HAL_CONFIG_BUFFER_REQUIREMENTS:
case HAL_CONFIG_PRIORITY:
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi.h b/drivers/media/platform/msm/vidc/vidc_hfi.h
index bb72da7..ac6cb02 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi.h
@@ -335,7 +335,6 @@
#define HFI_MSG_SYS_OX_START \
(HFI_DOMAIN_BASE_COMMON + HFI_ARCH_OX_OFFSET + HFI_MSG_START_OFFSET + 0x0000)
#define HFI_MSG_SYS_PING_ACK (HFI_MSG_SYS_OX_START + 0x2)
-#define HFI_MSG_SYS_PROPERTY_INFO (HFI_MSG_SYS_OX_START + 0x3)
#define HFI_MSG_SYS_SESSION_ABORT_DONE (HFI_MSG_SYS_OX_START + 0x4)
#define HFI_MSG_SESSION_OX_START \
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_api.h b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
index 389c13f..288b386 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_api.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
@@ -172,6 +172,8 @@
HAL_PARAM_VENC_H264_VUI_TIMING_INFO,
HAL_PARAM_VENC_H264_GENERATE_AUDNAL,
HAL_PARAM_VENC_MAX_NUM_B_FRAMES,
+ HAL_PARAM_BUFFER_ALLOC_MODE,
+ HAL_PARAM_VDEC_FRAME_ASSEMBLY,
};
enum hal_domain {
@@ -860,6 +862,16 @@
HAL_UNUSED_SEQCHG = 0x10000000,
};
+enum buffer_mode_type {
+ HAL_BUFFER_MODE_STATIC = 0x00000000,
+ HAL_BUFFER_MODE_RING,
+};
+
+struct hal_buffer_alloc_mode {
+ enum hal_buffer buffer_type;
+ enum buffer_mode_type buffer_mode;
+};
+
/* HAL Response */
enum command_response {
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_helper.h b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
index 2b6d6bb..0f1e896 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
@@ -197,6 +197,10 @@
(HFI_PROPERTY_SYS_COMMON_START + 0x003)
#define HFI_PROPERTY_SYS_IDLE_INDICATOR \
(HFI_PROPERTY_SYS_COMMON_START + 0x004)
+#define HFI_PROPERTY_SYS_CODEC_POWER_PLANE_CTRL \
+ (HFI_PROPERTY_SYS_COMMON_START + 0x005)
+#define HFI_PROPERTY_SYS_IMAGE_VERSION \
+ (HFI_PROPERTY_SYS_COMMON_START + 0x006)
#define HFI_PROPERTY_PARAM_COMMON_START \
(HFI_DOMAIN_BASE_COMMON + HFI_ARCH_COMMON_OFFSET + 0x1000)
@@ -615,6 +619,11 @@
struct hfi_resource_ocmem_requirement rg_requirements[1];
};
+struct hfi_property_sys_image_version_info_type {
+ u32 string_size;
+ u8 str_image_version[1];
+};
+
struct hfi_venc_config_advanced {
u8 pipe2d;
u8 hw_mode;
@@ -703,6 +712,7 @@
#define HFI_MSG_SYS_SESSION_INIT_DONE (HFI_MSG_SYS_COMMON_START + 0x6)
#define HFI_MSG_SYS_SESSION_END_DONE (HFI_MSG_SYS_COMMON_START + 0x7)
#define HFI_MSG_SYS_IDLE (HFI_MSG_SYS_COMMON_START + 0x8)
+#define HFI_MSG_SYS_PROPERTY_INFO (HFI_MSG_SYS_COMMON_START + 0xA)
#define HFI_MSG_SESSION_COMMON_START \
(HFI_DOMAIN_BASE_COMMON + HFI_ARCH_COMMON_OFFSET + \
diff --git a/drivers/media/platform/msm/wfd/wfd-ioctl.c b/drivers/media/platform/msm/wfd/wfd-ioctl.c
index 30a666d..6554947 100644
--- a/drivers/media/platform/msm/wfd/wfd-ioctl.c
+++ b/drivers/media/platform/msm/wfd/wfd-ioctl.c
@@ -715,6 +715,11 @@
if (rc)
WFD_MSG_ERR("Failed to stop MDP\n");
+ rc = v4l2_subdev_call(&wfd_dev->enc_sdev, core, ioctl,
+ ENCODE_FLUSH, (void *)inst->venc_inst);
+ if (rc)
+ WFD_MSG_ERR("Failed to flush encoder\n");
+
WFD_MSG_DBG("vsg stop\n");
rc = v4l2_subdev_call(&wfd_dev->vsg_sdev, core, ioctl,
VSG_STOP, NULL);
@@ -723,10 +728,6 @@
complete(&inst->stop_mdp_thread);
kthread_stop(inst->mdp_task);
- rc = v4l2_subdev_call(&wfd_dev->enc_sdev, core, ioctl,
- ENCODE_FLUSH, (void *)inst->venc_inst);
- if (rc)
- WFD_MSG_ERR("Failed to flush encoder\n");
WFD_MSG_DBG("enc stop\n");
rc = v4l2_subdev_call(&wfd_dev->enc_sdev, core, ioctl,
ENCODE_STOP, (void *)inst->venc_inst);
diff --git a/drivers/mfd/pm8xxx-pwm.c b/drivers/mfd/pm8xxx-pwm.c
index eb8320f..24fd5c1 100644
--- a/drivers/mfd/pm8xxx-pwm.c
+++ b/drivers/mfd/pm8xxx-pwm.c
@@ -35,7 +35,7 @@
*/
#define PM8XXX_LPG_V0_PWM_CHANNELS 8
#define PM8XXX_LPG_V1_PWM_CHANNELS 6
-#define PM8XXX_LPG_CTL_REGS 7
+#define PM8XXX_LPG_CTL_REGS 8
/* PM8XXX PWM */
#define SSBI_REG_ADDR_PWM1_CTRL1 0x88
@@ -66,6 +66,7 @@
#define SSBI_REG_ADDR_LPG_LUT_CFG0 0x145
#define SSBI_REG_ADDR_LPG_LUT_CFG1 0x146
#define SSBI_REG_ADDR_LPG_TEST 0x147
+#define SSBI_REG_ADDR_LPG_CTL_7 0x14D
/* LPG Control 0 */
#define PM8XXX_PWM_1KHZ_COUNT_MASK 0xF0
@@ -126,6 +127,7 @@
#define PM8XXX_PWM_PAUSE_ENABLE_HIGH 0x02
#define PM8XXX_PWM_SIZE_9_BIT 0x01
+#define PM8XXX_PWM_SIZE_7_BIT 0x04
/* LPG Control 6 */
#define PM8XXX_PWM_PAUSE_COUNT_LO_MASK 0xFC
@@ -369,17 +371,22 @@
}
static void pm8xxx_pwm_calc_period(unsigned int period_us,
- struct pm8xxx_pwm_period *period)
+ struct pwm_device *pwm)
{
int n, m, clk, div;
int best_m, best_div, best_clk;
unsigned int last_err, cur_err, min_err;
unsigned int tmp_p, period_n;
+ struct pm8xxx_pwm_period *period = &pwm->period;
+
+ if (pwm->banks == PM_PWM_BANK_LO)
+ n = 7;
+ else
+ n = 6;
/* PWM Period / N */
if (period_us < ((unsigned)(-1) / NSEC_PER_USEC)) {
- period_n = (period_us * NSEC_PER_USEC) >> 6;
- n = 6;
+ period_n = (period_us * NSEC_PER_USEC) >> n;
} else {
period_n = (period_us >> 9) * NSEC_PER_USEC;
n = 9;
@@ -458,6 +465,9 @@
int rc = 0;
pwm_size = (pwm->pwm_lpg_ctl[5] & PM8XXX_PWM_SIZE_9_BIT) ? 9 : 6;
+ if (pwm->period.pwm_size == 7)
+ pwm_size = 7;
+
max_pwm_value = (1 << pwm_size) - 1;
for (i = 0; i < len; i++) {
if (raw_value)
@@ -512,9 +522,16 @@
PM8XXX_LPG_PWM_PREDIVIDE_MASK | PM8XXX_LPG_PWM_M_MASK;
pm8xxx_pwm_save(&pwm->pwm_lpg_ctl[4], mask, val);
- val = (pwm->period.pwm_size > 6) ? PM8XXX_PWM_SIZE_9_BIT : 0;
- mask = PM8XXX_PWM_SIZE_9_BIT;
- pm8xxx_pwm_save(&pwm->pwm_lpg_ctl[5], mask, val);
+ if (pwm->period.pwm_size == 7) {
+ val = PM8XXX_PWM_SIZE_7_BIT;
+ mask = PM8XXX_PWM_SIZE_7_BIT;
+ pm8xxx_pwm_save(&pwm->pwm_lpg_ctl[7], mask, val);
+ } else {
+ val = (pwm->period.pwm_size > 6) ?
+ PM8XXX_PWM_SIZE_9_BIT : 0;
+ mask = PM8XXX_PWM_SIZE_9_BIT;
+ pm8xxx_pwm_save(&pwm->pwm_lpg_ctl[5], mask, val);
+ }
} else {
val = ((pwm->period.clk + 1) << PM8XXX_PWM_CLK_SEL_SHIFT)
& PM8XXX_PWM_CLK_SEL_MASK;
@@ -639,8 +656,18 @@
{
int i, rc;
+ if (end == 7) {
+ rc = pm8xxx_writeb(pwm->chip->dev->parent,
+ SSBI_REG_ADDR_LPG_CTL_7,
+ pwm->pwm_lpg_ctl[end]);
+ if (rc) {
+ pr_err("pm8xxx_writeb(): rc=%d (PWM Ctl[7])\n", rc);
+ return rc;
+ }
+ }
+
/* Write in reverse way so 0 would be the last */
- for (i = end - 1; i >= start; i--) {
+ for (i = end - 2; i >= start; i--) {
rc = pm8xxx_writeb(pwm->chip->dev->parent,
SSBI_REG_ADDR_LPG_CTL(i),
pwm->pwm_lpg_ctl[i]);
@@ -788,7 +815,7 @@
}
if (pwm->pwm_period != period_us) {
- pm8xxx_pwm_calc_period(period_us, period);
+ pm8xxx_pwm_calc_period(period_us, pwm);
pm8xxx_pwm_save_period(pwm);
pwm->pwm_period = period_us;
}
@@ -801,7 +828,7 @@
PM8XXX_PWM_BYPASS_LUT, PM8XXX_PWM_BYPASS_LUT);
pm8xxx_pwm_bank_sel(pwm);
- rc = pm8xxx_lpg_pwm_write(pwm, 1, 6);
+ rc = pm8xxx_lpg_pwm_write(pwm, 1, 7);
} else {
rc = pm8xxx_pwm_write(pwm);
}
@@ -851,7 +878,7 @@
* PWM mode.
*/
if (pwm->chip->is_pwm_enable_sync_workaround_needed)
- rc = pm8xxx_lpg_pwm_write(pwm, 3, 4);
+ rc = pm8xxx_lpg_pwm_write(pwm, 3, 5);
} else {
pm8xxx_pwm_enable(pwm);
@@ -921,7 +948,7 @@
if (pwm_chip->is_lpg_supported) {
pm8xxx_pwm_bank_sel(pwm);
- rc = pm8xxx_lpg_pwm_write(pwm, 4, 6);
+ rc = pm8xxx_lpg_pwm_write(pwm, 4, 7);
} else {
rc = pm8xxx_pwm_write(pwm);
}
@@ -965,7 +992,7 @@
pm8xxx_pwm_save(&pwm->pwm_lpg_ctl[1],
PM8XXX_PWM_BYPASS_LUT, PM8XXX_PWM_BYPASS_LUT);
pm8xxx_pwm_bank_sel(pwm);
- rc = pm8xxx_lpg_pwm_write(pwm, 1, 6);
+ rc = pm8xxx_lpg_pwm_write(pwm, 1, 7);
} else {
rc = pm8xxx_pwm_write(pwm);
}
@@ -996,7 +1023,6 @@
int idx_len, int pause_lo, int pause_hi, int flags)
{
struct pm8xxx_pwm_lut lut;
- struct pm8xxx_pwm_period *period;
int len;
int rc;
@@ -1032,7 +1058,6 @@
return -EINVAL;
}
- period = &pwm->period;
mutex_lock(&pwm->chip->pwm_mutex);
if (flags & PM_PWM_BANK_HI)
@@ -1052,7 +1077,7 @@
}
if (pwm->pwm_period != period_us) {
- pm8xxx_pwm_calc_period(period_us, period);
+ pm8xxx_pwm_calc_period(period_us, pwm);
pm8xxx_pwm_save_period(pwm);
pwm->pwm_period = period_us;
}
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index 6ea2346..9d0bc61 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -605,11 +605,12 @@
memcpy(req.app_name, load_img_req.img_name, MAX_APP_NAME_SIZE);
ret = __qseecom_check_app_exists(req);
- if (ret < 0)
+ if (ret < 0) {
+ qsee_disable_clock_vote(data, CLK_SFPB);
return ret;
- else
- app_id = ret;
+ }
+ app_id = ret;
if (app_id) {
pr_debug("App id %d (%s) already exists\n", app_id,
(char *)(req.app_name));
@@ -2008,14 +2009,15 @@
pr_err("set_cpus_allowed_ptr failed : ret %d\n",
set_cpu_ret);
ret = -EFAULT;
- goto qseecom_load_external_elf_set_cpu_err;
+ goto exit_ion_free;
}
+
/* Vote for the SFPB clock */
ret = qsee_vote_for_clock(data, CLK_SFPB);
if (ret) {
pr_err("Unable to vote for SFPB clock: ret = %d", ret);
ret = -EIO;
- goto qseecom_load_external_elf_set_cpu_err;
+ goto exit_cpu_restore;
}
msm_ion_do_cache_op(qseecom.ion_clnt, ihandle, NULL, len,
ION_IOC_CLEAN_INV_CACHES);
@@ -2027,23 +2029,32 @@
pr_err("scm_call to load failed : ret %d\n",
ret);
ret = -EFAULT;
- goto qseecom_load_external_elf_scm_err;
+ goto exit_disable_clock;
}
- if (resp.result == QSEOS_RESULT_INCOMPLETE) {
+ switch (resp.result) {
+ case QSEOS_RESULT_SUCCESS:
+ break;
+ case QSEOS_RESULT_INCOMPLETE:
+ pr_err("%s: qseos result incomplete\n", __func__);
ret = __qseecom_process_incomplete_cmd(data, &resp);
if (ret)
- pr_err("process_incomplete_cmd failed err: %d\n",
- ret);
- } else {
- if (resp.result != QSEOS_RESULT_SUCCESS) {
- pr_err("scm_call to load image failed resp.result =%d\n",
- resp.result);
- ret = -EFAULT;
- }
+ pr_err("process_incomplete_cmd failed: err: %d\n", ret);
+ break;
+ case QSEOS_RESULT_FAILURE:
+ pr_err("scm_call rsp.result is QSEOS_RESULT_FAILURE\n");
+ ret = -EFAULT;
+ break;
+ default:
+ pr_err("scm_call response result %d not supported\n",
+ resp.result);
+ ret = -EFAULT;
+ break;
}
-qseecom_load_external_elf_scm_err:
+exit_disable_clock:
+ qsee_disable_clock_vote(data, CLK_SFPB);
+exit_cpu_restore:
/* Restore the CPU mask */
mask = CPU_MASK_ALL;
set_cpu_ret = set_cpus_allowed_ptr(current, &mask);
@@ -2052,12 +2063,10 @@
set_cpu_ret);
ret = -EFAULT;
}
-
-qseecom_load_external_elf_set_cpu_err:
+exit_ion_free:
/* Deallocate the handle */
if (!IS_ERR_OR_NULL(ihandle))
ion_free(qseecom.ion_clnt, ihandle);
- qsee_disable_clock_vote(data, CLK_SFPB);
return ret;
}
diff --git a/drivers/misc/tspp.c b/drivers/misc/tspp.c
index aa71b74..36bdf45 100644
--- a/drivers/misc/tspp.c
+++ b/drivers/misc/tspp.c
@@ -617,8 +617,8 @@
break;
if (iovec.addr != channel->waiting->sps.phys_base)
- pr_err("tspp: buffer mismatch 0x%08x",
- channel->waiting->sps.phys_base);
+ pr_err("tspp: buffer mismatch %pa",
+ &channel->waiting->sps.phys_base);
complete = 1;
channel->waiting->state = TSPP_BUF_STATE_DATA;
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index d975543..da07947 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -1363,7 +1363,7 @@
pr_debug("%s: %s - SANITIZE IN PROGRESS...\n",
mmc_hostname(card->host), __func__);
- err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+ err = mmc_switch_ignore_timeout(card, EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_SANITIZE_START, 1,
MMC_SANITIZE_REQ_TIMEOUT);
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 04687fa..064d5ec 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -59,6 +59,9 @@
*/
#define MMC_BKOPS_MAX_TIMEOUT (30 * 1000) /* max time to wait in ms */
+/* Flushing a large amount of cached data may take a long time. */
+#define MMC_FLUSH_REQ_TIMEOUT_MS 30000 /* msec */
+
static struct workqueue_struct *workqueue;
/*
@@ -785,21 +788,13 @@
cmd = mrq->cmd;
/*
- * If host has timed out waiting for the blocking BKOPs
- * to complete, card might be still in programming state
- * so let's try to bring the card out of programming state.
+ * If host has timed out waiting for the commands which can be
+ * HPIed then let the caller handle the timeout error as it may
+ * want to send the HPI command to bring the card out of
+ * programming state.
*/
- if (cmd->bkops_busy && cmd->error == -ETIMEDOUT) {
- if (!mmc_interrupt_hpi(host->card)) {
- pr_warning("%s: %s: Interrupted blocking bkops\n",
- mmc_hostname(host), __func__);
- cmd->error = 0;
- break;
- } else {
- pr_err("%s: %s: Failed to interrupt blocking bkops\n",
- mmc_hostname(host), __func__);
- }
- }
+ if (cmd->ignore_timeout && cmd->error == -ETIMEDOUT)
+ break;
if (!cmd->error || !cmd->retries ||
mmc_card_removed(host->card))
@@ -1064,8 +1059,6 @@
}
err = mmc_send_hpi_cmd(card, &status);
- if (err)
- goto out;
prg_wait = jiffies + msecs_to_jiffies(card->ext_csd.out_of_int_time);
do {
@@ -2594,7 +2587,7 @@
if (mmc_card_sdio(card))
return 0;
- if (mmc_card_mmc(card)) {
+ if (mmc_card_mmc(card) && (card->host->caps & MMC_CAP_HW_RESET)) {
rst_n_function = card->ext_csd.rst_n_function;
if ((rst_n_function & EXT_CSD_RST_N_EN_MASK) !=
EXT_CSD_RST_N_ENABLED)
@@ -2611,9 +2604,6 @@
if (!host->bus_ops->power_restore)
return -EOPNOTSUPP;
- if (!(host->caps & MMC_CAP_HW_RESET))
- return -EOPNOTSUPP;
-
if (!card)
return -EINVAL;
@@ -2623,10 +2613,10 @@
mmc_host_clk_hold(host);
mmc_set_clock(host, host->f_init);
- if (mmc_card_sd(card))
- mmc_power_cycle(host);
- else if (host->ops->hw_reset)
+ if (mmc_card_mmc(card) && host->ops->hw_reset)
host->ops->hw_reset(host);
+ else
+ mmc_power_cycle(host);
/* If the reset has happened, then a status command will fail */
if (check) {
@@ -3336,7 +3326,7 @@
int mmc_flush_cache(struct mmc_card *card)
{
struct mmc_host *host = card->host;
- int err = 0;
+ int err = 0, rc;
if (!(host->caps2 & MMC_CAP2_CACHE_CTRL))
return err;
@@ -3344,11 +3334,20 @@
if (mmc_card_mmc(card) &&
(card->ext_csd.cache_size > 0) &&
(card->ext_csd.cache_ctrl & 1)) {
- err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
- EXT_CSD_FLUSH_CACHE, 1, 0);
- if (err)
+ err = mmc_switch_ignore_timeout(card, EXT_CSD_CMD_SET_NORMAL,
+ EXT_CSD_FLUSH_CACHE, 1,
+ MMC_FLUSH_REQ_TIMEOUT_MS);
+ if (err == -ETIMEDOUT) {
+ pr_debug("%s: cache flush timeout\n",
+ mmc_hostname(card->host));
+ rc = mmc_interrupt_hpi(card);
+ if (rc)
+ pr_err("%s: mmc_interrupt_hpi() failed (%d)\n",
+ mmc_hostname(host), rc);
+ } else if (err) {
pr_err("%s: cache flush error %d\n",
mmc_hostname(card->host), err);
+ }
}
return err;
@@ -3364,8 +3363,8 @@
int mmc_cache_ctrl(struct mmc_host *host, u8 enable)
{
struct mmc_card *card = host->card;
- unsigned int timeout;
- int err = 0;
+ unsigned int timeout = card->ext_csd.generic_cmd6_time;
+ int err = 0, rc;
if (!(host->caps2 & MMC_CAP2_CACHE_CTRL) ||
mmc_card_is_removable(host))
@@ -3376,16 +3375,28 @@
enable = !!enable;
if (card->ext_csd.cache_ctrl ^ enable) {
- timeout = enable ? card->ext_csd.generic_cmd6_time : 0;
- err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+ if (!enable)
+ timeout = MMC_FLUSH_REQ_TIMEOUT_MS;
+
+ err = mmc_switch_ignore_timeout(card,
+ EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_CACHE_CTRL, enable, timeout);
- if (err)
+
+ if (err == -ETIMEDOUT && !enable) {
+ pr_debug("%s:cache disable operation timeout\n",
+ mmc_hostname(card->host));
+ rc = mmc_interrupt_hpi(card);
+ if (rc)
+ pr_err("%s: mmc_interrupt_hpi() failed (%d)\n",
+ mmc_hostname(host), rc);
+ } else if (err) {
pr_err("%s: cache %s error %d\n",
mmc_hostname(card->host),
enable ? "on" : "off",
err);
- else
+ } else {
card->ext_csd.cache_ctrl = enable;
+ }
}
}
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 9b9c1ed..90d9826 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -892,9 +892,12 @@
MMC_SEND_TUNING_BLOCK_HS200);
mmc_host_clk_release(card->host);
- if (err)
- pr_warn("%s: %s: tuning execution failed %d\n",
- mmc_hostname(card->host), __func__, err);
+ if (err) {
+ pr_warn("%s: %s: tuning execution failed %d. Restoring to previous clock %lu\n",
+ mmc_hostname(card->host), __func__, err,
+ host->clk_scaling.curr_freq);
+ mmc_set_clock(host, host->clk_scaling.curr_freq);
+ }
}
out:
mmc_release_host(host);
@@ -1576,9 +1579,7 @@
if (err)
goto out;
- if (mmc_can_poweroff_notify(host->card))
- err = mmc_poweroff_notify(host->card, EXT_CSD_POWER_OFF_SHORT);
- else if (mmc_card_can_sleep(host))
+ if (mmc_card_can_sleep(host))
err = mmc_card_sleep(host);
else if (!mmc_host_is_spi(host))
mmc_deselect_cards(host);
diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
index 8087ea6..164c418 100644
--- a/drivers/mmc/core/mmc_ops.c
+++ b/drivers/mmc/core/mmc_ops.c
@@ -378,13 +378,13 @@
* @timeout_ms: timeout (ms) for operation performed by register write,
* timeout of zero implies maximum possible timeout
* @use_busy_signal: use the busy signal as response type
- * @bkops_busy: set this to indicate that we are starting blocking bkops
+ * @ignore_timeout: set this flag only for commands which can be HPIed
*
* Modifies the EXT_CSD register for selected card.
*/
int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
unsigned int timeout_ms, bool use_busy_signal,
- bool bkops_busy)
+ bool ignore_timeout)
{
int err;
struct mmc_command cmd = {0};
@@ -407,7 +407,7 @@
cmd.cmd_timeout_ms = timeout_ms;
- cmd.bkops_busy = bkops_busy;
+ cmd.ignore_timeout = ignore_timeout;
err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES);
if (err)
@@ -458,6 +458,13 @@
}
EXPORT_SYMBOL_GPL(mmc_switch);
+int mmc_switch_ignore_timeout(struct mmc_card *card, u8 set, u8 index, u8 value,
+ unsigned int timeout_ms)
+{
+ return __mmc_switch(card, set, index, value, timeout_ms, true, true);
+}
+EXPORT_SYMBOL(mmc_switch_ignore_timeout);
+
int mmc_send_status(struct mmc_card *card, u32 *status)
{
int err;
@@ -608,7 +615,7 @@
err = mmc_wait_for_cmd(card->host, &cmd, 0);
if (err) {
- pr_warn("%s: error %d interrupting operation. "
+ pr_debug("%s: error %d interrupting operation. "
"HPI command response %#x\n", mmc_hostname(card->host),
err, cmd.resp[0]);
return err;
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index ddf9a87..a4498d2 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -666,9 +666,12 @@
MMC_SEND_TUNING_BLOCK);
mmc_host_clk_release(card->host);
- if (err)
- pr_warn("%s: %s: tuning execution failed %d\n",
- mmc_hostname(card->host), __func__, err);
+ if (err) {
+ pr_warn("%s: %s: tuning execution failed %d. Restoring to previous clock %lu\n",
+ mmc_hostname(card->host), __func__, err,
+ host->clk_scaling.curr_freq);
+ mmc_set_clock(host, host->clk_scaling.curr_freq);
+ }
}
out:
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index 476e75c..89e3472 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -4319,56 +4319,6 @@
return rc;
}
-/*
- * Work around of the unavailability of a power_reset functionality in SD cards
- * by turning the OFF & back ON the regulators supplying the SD card.
- */
-void msmsdcc_hw_reset(struct mmc_host *mmc)
-{
- struct mmc_card *card = mmc->card;
- struct msmsdcc_host *host = mmc_priv(mmc);
- int rc;
-
- /* Write-protection bits would be lost on a hardware reset in emmc */
- if (!card || !mmc_card_sd(card))
- return;
-
- pr_debug("%s: Starting h/w reset\n", mmc_hostname(host->mmc));
-
- if (host->plat->translate_vdd || host->plat->vreg_data) {
-
- /* Disable the regulators */
- if (host->plat->translate_vdd)
- rc = host->plat->translate_vdd(mmc_dev(mmc), 0);
- else if (host->plat->vreg_data)
- rc = msmsdcc_setup_vreg(host, false, false);
-
- if (rc) {
- pr_err("%s: Failed to disable voltage regulator\n",
- mmc_hostname(host->mmc));
- BUG_ON(rc);
- }
-
- /* 10ms delay for supply to reach the desired voltage level */
- usleep_range(10000, 12000);
-
- /* Enable the regulators */
- if (host->plat->translate_vdd)
- rc = host->plat->translate_vdd(mmc_dev(mmc), 1);
- else if (host->plat->vreg_data)
- rc = msmsdcc_setup_vreg(host, true, false);
-
- if (rc) {
- pr_err("%s: Failed to enable voltage regulator\n",
- mmc_hostname(host->mmc));
- BUG_ON(rc);
- }
-
- /* 10ms delay for supply to reach the desired voltage level */
- usleep_range(10000, 12000);
- }
-}
-
/**
* msmsdcc_stop_request - stops ongoing request
* @mmc: MMC host, running the request
@@ -4476,7 +4426,6 @@
.enable_sdio_irq = msmsdcc_enable_sdio_irq,
.start_signal_voltage_switch = msmsdcc_switch_io_voltage,
.execute_tuning = msmsdcc_execute_tuning,
- .hw_reset = msmsdcc_hw_reset,
.stop_request = msmsdcc_stop_request,
.get_xfer_remain = msmsdcc_get_xfer_remain,
.notify_load = msmsdcc_notify_load,
@@ -5364,7 +5313,7 @@
mrq = host->curr.mrq;
if (mrq && mrq->cmd) {
- if (!mrq->cmd->bkops_busy) {
+ if (!mrq->cmd->ignore_timeout) {
pr_info("%s: CMD%d: Request timeout\n",
mmc_hostname(host->mmc), mrq->cmd->opcode);
msmsdcc_dump_sdcc_state(host);
@@ -6116,6 +6065,10 @@
msmsdcc_msm_bus_cancel_work_and_set_vote(host, &mmc->ios);
+ /* Disable SDHCi mode if supported */
+ if (is_sdhci_supported(host))
+ writel_relaxed(0, (host->base + MCI_CORE_HC_MODE));
+
/* Apply Hard reset to SDCC to put it in power on default state */
msmsdcc_hard_reset(host);
@@ -6161,7 +6114,6 @@
mmc->caps |= plat->mmc_bus_width;
mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED;
mmc->caps |= MMC_CAP_WAIT_WHILE_BUSY | MMC_CAP_ERASE;
- mmc->caps |= MMC_CAP_HW_RESET;
/*
* If we send the CMD23 before multi block write/read command
* then we need not to send CMD12 at the end of the transfer.
diff --git a/drivers/mmc/host/msm_sdcc.h b/drivers/mmc/host/msm_sdcc.h
index bcfde57..3668d75 100644
--- a/drivers/mmc/host/msm_sdcc.h
+++ b/drivers/mmc/host/msm_sdcc.h
@@ -197,6 +197,8 @@
#define MAX_TESTBUS 8
#define MCI_TESTBUS_ENA (1 << 3)
+#define MCI_CORE_HC_MODE 0x78
+
#define MCI_SDCC_DEBUG_REG 0x124
#define MCI_IRQENABLE \
@@ -456,6 +458,7 @@
#define MSMSDCC_SW_RST_CFG_BROKEN (1 << 11)
#define MSMSDCC_DATA_PEND_FOR_CMD53 (1 << 12)
#define MSMSDCC_TESTBUS_DEBUG (1 << 13)
+#define MSMSDCC_SDHCI_MODE_SUPPORTED (1 << 14)
#define set_hw_caps(h, val) ((h)->hw_caps |= val)
#define is_sps_mode(h) ((h)->hw_caps & MSMSDCC_SPS_BAM_SUP)
@@ -473,6 +476,7 @@
((h)->hw_caps & MSMSDCC_SW_RST_CFG_BROKEN)
#define is_data_pend_for_cmd53(h) ((h)->hw_caps & MSMSDCC_DATA_PEND_FOR_CMD53)
#define is_testbus_debug(h) ((h)->hw_caps & MSMSDCC_TESTBUS_DEBUG)
+#define is_sdhci_supported(h) ((h)->hw_caps & MSMSDCC_SDHCI_MODE_SUPPORTED)
/* Set controller capabilities based on version */
static inline void set_default_hw_caps(struct msmsdcc_host *host)
@@ -511,7 +515,8 @@
MSMSDCC_AUTO_CMD21 |
MSMSDCC_DATA_PEND_FOR_CMD53 |
MSMSDCC_TESTBUS_DEBUG |
- MSMSDCC_SW_RST_CFG_BROKEN;
+ MSMSDCC_SW_RST_CFG_BROKEN |
+ MSMSDCC_SDHCI_MODE_SUPPORTED;
}
int msmsdcc_set_pwrsave(struct mmc_host *mmc, int pwrsave);
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 4ff8fea..3495f4d 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -89,6 +89,9 @@
#define CORE_TESTBUS_ENA (1 << 3)
#define CORE_TESTBUS_SEL2 (1 << 4)
+#define CORE_MCI_VERSION 0x050
+#define CORE_VERSION_310 0x10000011
+
/*
* Waiting until end of potential AHB access for data:
* 16 AHB cycles (160ns for 100MHz and 320ns for 50MHz) +
@@ -264,6 +267,7 @@
u32 curr_io_level;
struct completion pwr_irq_completion;
struct sdhci_msm_bus_vote msm_bus_vote;
+ struct device_attribute polling;
u32 clk_rate; /* Keeps track of current clock rate that is set */
};
@@ -593,6 +597,7 @@
int sdhci_msm_execute_tuning(struct sdhci_host *host, u32 opcode)
{
unsigned long flags;
+ int tuning_seq_cnt = 3;
u8 phase, *data_buf, tuned_phases[16], tuned_phase_cnt = 0;
const u32 *tuning_block_pattern = tuning_block_64;
int size = sizeof(tuning_block_64); /* Tuning pattern size in bytes */
@@ -619,17 +624,18 @@
}
spin_unlock_irqrestore(&host->lock, flags);
- /* first of all reset the tuning block */
- rc = msm_init_cm_dll(host);
- if (rc)
- goto out;
-
data_buf = kmalloc(size, GFP_KERNEL);
if (!data_buf) {
rc = -ENOMEM;
goto out;
}
+retry:
+ /* first of all reset the tuning block */
+ rc = msm_init_cm_dll(host);
+ if (rc)
+ goto kfree;
+
phase = 0;
do {
struct mmc_command cmd = {0};
@@ -686,10 +692,12 @@
pr_debug("%s: %s: finally setting the tuning phase to %d\n",
mmc_hostname(mmc), __func__, phase);
} else {
+ if (--tuning_seq_cnt)
+ goto retry;
/* tuning failed */
pr_err("%s: %s: no tuning point found\n",
mmc_hostname(mmc), __func__);
- rc = -EAGAIN;
+ rc = -EIO;
}
kfree:
@@ -1838,6 +1846,42 @@
else
return 0;
}
+
+static ssize_t
+show_polling(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct sdhci_host *host = dev_get_drvdata(dev);
+ int poll;
+ unsigned long flags;
+
+ spin_lock_irqsave(&host->lock, flags);
+ poll = !!(host->mmc->caps & MMC_CAP_NEEDS_POLL);
+ spin_unlock_irqrestore(&host->lock, flags);
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", poll);
+}
+
+static ssize_t
+store_polling(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct sdhci_host *host = dev_get_drvdata(dev);
+ int value;
+ unsigned long flags;
+
+ if (!kstrtou32(buf, 0, &value)) {
+ spin_lock_irqsave(&host->lock, flags);
+ if (value) {
+ host->mmc->caps |= MMC_CAP_NEEDS_POLL;
+ mmc_detect_change(host->mmc, 0);
+ } else {
+ host->mmc->caps &= ~MMC_CAP_NEEDS_POLL;
+ }
+ spin_unlock_irqrestore(&host->lock, flags);
+ }
+ return count;
+}
+
static ssize_t
show_sdhci_max_bus_bw(struct device *dev, struct device_attribute *attr,
char *buf)
@@ -2129,6 +2173,12 @@
struct sdhci_msm_host *msm_host = pltfm_host->priv;
u32 value;
int ret;
+ u32 version;
+
+ version = readl_relaxed(msm_host->core_mem + CORE_MCI_VERSION);
+ /* Core version 3.1.0 doesn't need this workaround */
+ if (version == CORE_VERSION_310)
+ return;
value = readl_relaxed(msm_host->core_mem + CORE_MCI_DATA_CTRL);
value &= ~(u32)CORE_MCI_DPSM_ENABLE;
@@ -2410,7 +2460,6 @@
MMC_CAP_SET_XPC_300|
MMC_CAP_SET_XPC_330;
- msm_host->mmc->caps |= MMC_CAP_HW_RESET;
msm_host->mmc->caps2 |= msm_host->pdata->caps2;
msm_host->mmc->caps2 |= MMC_CAP2_CORE_RUNTIME_PM;
msm_host->mmc->caps2 |= MMC_CAP2_PACKED_WR;
@@ -2464,6 +2513,16 @@
if (ret)
goto remove_host;
+ if (!gpio_is_valid(msm_host->pdata->status_gpio)) {
+ msm_host->polling.show = show_polling;
+ msm_host->polling.store = store_polling;
+ sysfs_attr_init(&msm_host->polling.attr);
+ msm_host->polling.attr.name = "polling";
+ msm_host->polling.attr.mode = S_IRUGO | S_IWUSR;
+ ret = device_create_file(&pdev->dev, &msm_host->polling);
+ if (ret)
+ goto remove_max_bus_bw_file;
+ }
ret = pm_runtime_set_active(&pdev->dev);
if (ret)
pr_err("%s: %s: pm_runtime_set_active failed: err: %d\n",
@@ -2474,6 +2533,8 @@
/* Successful initialization */
goto out;
+remove_max_bus_bw_file:
+ device_remove_file(&pdev->dev, &msm_host->msm_bus_vote.max_bus_bw);
remove_host:
dead = (readl_relaxed(host->ioaddr + SDHCI_INT_STATUS) == 0xffffffff);
sdhci_remove_host(host, dead);
@@ -2512,6 +2573,8 @@
0xffffffff);
pr_debug("%s: %s\n", dev_name(&pdev->dev), __func__);
+ if (!gpio_is_valid(msm_host->pdata->status_gpio))
+ device_remove_file(&pdev->dev, &msm_host->polling);
device_remove_file(&pdev->dev, &msm_host->msm_bus_vote.max_bus_bw);
sdhci_remove_host(host, dead);
pm_runtime_disable(&pdev->dev);
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index ce1c536..9527249 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -1932,7 +1932,7 @@
if (host->ops->execute_tuning) {
spin_unlock(&host->lock);
enable_irq(host->irq);
- host->ops->execute_tuning(host, opcode);
+ err = host->ops->execute_tuning(host, opcode);
disable_irq(host->irq);
spin_lock(&host->lock);
goto out;
@@ -2312,9 +2312,11 @@
spin_lock_irqsave(&host->lock, flags);
if (host->mrq) {
- pr_err("%s: Timeout waiting for hardware "
- "interrupt.\n", mmc_hostname(host->mmc));
- sdhci_dumpregs(host);
+ if (!host->mrq->cmd->ignore_timeout) {
+ pr_err("%s: Timeout waiting for hardware interrupt.\n",
+ mmc_hostname(host->mmc));
+ sdhci_dumpregs(host);
+ }
if (host->data) {
pr_info("%s: bytes to transfer: %d transferred: %d\n",
diff --git a/drivers/mtd/devices/msm_qpic_nand.c b/drivers/mtd/devices/msm_qpic_nand.c
index 16012bd..7f02187 100644
--- a/drivers/mtd/devices/msm_qpic_nand.c
+++ b/drivers/mtd/devices/msm_qpic_nand.c
@@ -2229,7 +2229,8 @@
return err;
}
-#define BAM_APPS_PIPE_LOCK_GRP 0
+#define BAM_APPS_PIPE_LOCK_GRP0 0
+#define BAM_APPS_PIPE_LOCK_GRP1 1
/*
* This function allocates, configures, connects an end point and
* also registers event notification for an end point. It also allocates
@@ -2273,7 +2274,13 @@
}
sps_config->options = SPS_O_AUTO_ENABLE | SPS_O_DESC_DONE;
- sps_config->lock_group = BAM_APPS_PIPE_LOCK_GRP;
+
+ if (pipe_index == SPS_DATA_PROD_PIPE_INDEX ||
+ pipe_index == SPS_DATA_CONS_PIPE_INDEX)
+ sps_config->lock_group = BAM_APPS_PIPE_LOCK_GRP0;
+ else if (pipe_index == SPS_CMD_CONS_PIPE_INDEX)
+ sps_config->lock_group = BAM_APPS_PIPE_LOCK_GRP1;
+
/*
* Descriptor FIFO is a cyclic FIFO. If SPS_MAX_DESC_NUM descriptors
* are allowed to be submitted before we get any ack for any of them,
diff --git a/drivers/net/usb/rmnet_usb_ctrl.c b/drivers/net/usb/rmnet_usb_ctrl.c
index 0772592..d1f3748 100644
--- a/drivers/net/usb/rmnet_usb_ctrl.c
+++ b/drivers/net/usb/rmnet_usb_ctrl.c
@@ -200,8 +200,10 @@
dev->get_encap_failure_cnt++;
usb_unanchor_urb(dev->rcvurb);
usb_autopm_put_interface(dev->intf);
- dev_err(dev->devicep,
- "%s: Error submitting Read URB %d\n", __func__, status);
+ if (status != -ENODEV)
+ dev_err(dev->devicep,
+ "%s: Error submitting Read URB %d\n",
+ __func__, status);
goto resubmit_int_urb;
}
@@ -214,7 +216,9 @@
status = usb_submit_urb(dev->inturb, GFP_KERNEL);
if (status) {
usb_unanchor_urb(dev->inturb);
- dev_err(dev->devicep, "%s: Error re-submitting Int URB %d\n",
+ if (status != -ENODEV)
+ dev_err(dev->devicep,
+ "%s: Error re-submitting Int URB %d\n",
__func__, status);
}
}
@@ -286,8 +290,10 @@
status = usb_submit_urb(urb, GFP_ATOMIC);
if (status) {
usb_unanchor_urb(urb);
- dev_err(dev->devicep, "%s: Error re-submitting Int URB %d\n",
- __func__, status);
+ if (status != -ENODEV)
+ dev_err(dev->devicep,
+ "%s: Error re-submitting Int URB %d\n",
+ __func__, status);
}
return;
@@ -383,7 +389,9 @@
status = usb_submit_urb(dev->inturb, GFP_ATOMIC);
if (status) {
usb_unanchor_urb(dev->inturb);
- dev_err(dev->devicep, "%s: Error re-submitting Int URB %d\n",
+ if (status != -ENODEV)
+ dev_err(dev->devicep,
+ "%s: Error re-submitting Int URB %d\n",
__func__, status);
}
}
@@ -397,8 +405,9 @@
retval = usb_submit_urb(dev->inturb, GFP_KERNEL);
if (retval < 0) {
usb_unanchor_urb(dev->inturb);
- dev_err(dev->devicep, "%s Intr submit %d\n", __func__,
- retval);
+ if (retval != -ENODEV)
+ dev_err(dev->devicep,
+ "%s Intr submit %d\n", __func__, retval);
}
return retval;
@@ -527,7 +536,9 @@
dev->snd_encap_cmd_cnt++;
result = usb_submit_urb(sndurb, GFP_KERNEL);
if (result < 0) {
- dev_err(dev->devicep, "%s: Submit URB error %d\n",
+ if (result != -ENODEV)
+ dev_err(dev->devicep,
+ "%s: Submit URB error %d\n",
__func__, result);
dev->snd_encap_cmd_cnt--;
usb_autopm_put_interface(dev->intf);
diff --git a/drivers/net/wireless/wcnss/wcnss_wlan.c b/drivers/net/wireless/wcnss/wcnss_wlan.c
index 5e22c35..657fc2f 100644
--- a/drivers/net/wireless/wcnss/wcnss_wlan.c
+++ b/drivers/net/wireless/wcnss/wcnss_wlan.c
@@ -115,6 +115,9 @@
#define MSM_PRONTO_SAW2_BASE 0xfb219000
#define PRONTO_SAW2_SPM_STS_OFFSET 0x0c
+#define MSM_PRONTO_PLL_BASE 0xfb21b1c0
+#define PRONTO_PLL_STATUS_OFFSET 0x1c
+
#define WCNSS_DEF_WLAN_RX_BUFF_COUNT 1024
#define WCNSS_CTRL_CHANNEL "WCNSS_CTRL"
@@ -292,6 +295,7 @@
void __iomem *pronto_a2xb_base;
void __iomem *pronto_ccpu_base;
void __iomem *pronto_saw2_base;
+ void __iomem *pronto_pll_base;
void __iomem *fiq_reg;
int ssr_boot;
int nv_downloaded;
@@ -487,6 +491,10 @@
reg = readl_relaxed(reg_addr);
pr_info_ratelimited("%s: PRONTO_SAW2_SPM_STS %08x\n", __func__, reg);
+ reg_addr = penv->pronto_pll_base + PRONTO_PLL_STATUS_OFFSET;
+ reg = readl_relaxed(reg_addr);
+ pr_info_ratelimited("%s: PRONTO_PLL_STATUS %08x\n", __func__, reg);
+
tst_addr = penv->pronto_a2xb_base + A2XB_TSTBUS_OFFSET;
tst_ctrl_addr = penv->pronto_a2xb_base + A2XB_TSTBUS_CTRL_OFFSET;
@@ -1699,6 +1707,15 @@
ret = -ENOMEM;
goto fail_ioremap5;
}
+ penv->pronto_pll_base = ioremap_nocache(MSM_PRONTO_PLL_BASE,
+ SZ_64);
+ if (!penv->pronto_pll_base) {
+ pr_err("%s: ioremap wcnss physical(pll) failed\n",
+ __func__);
+ ret = -ENOMEM;
+ goto fail_ioremap6;
+ }
+
}
/* trigger initialization of the WCNSS */
@@ -1715,6 +1732,9 @@
fail_pil:
if (penv->riva_ccu_base)
iounmap(penv->riva_ccu_base);
+ if (penv->pronto_pll_base)
+ iounmap(penv->pronto_pll_base);
+fail_ioremap6:
if (penv->pronto_saw2_base)
iounmap(penv->pronto_saw2_base);
fail_ioremap5:
diff --git a/drivers/pinctrl/pinconf-generic.c b/drivers/pinctrl/pinconf-generic.c
index 06c304a..180b856 100644
--- a/drivers/pinctrl/pinconf-generic.c
+++ b/drivers/pinctrl/pinconf-generic.c
@@ -20,6 +20,7 @@
#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinconf.h>
#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/of.h>
#include "core.h"
#include "pinconf.h"
@@ -36,11 +37,15 @@
struct pin_config_item conf_items[] = {
PCONFDUMP(PIN_CONFIG_BIAS_DISABLE, "input bias disabled", NULL),
PCONFDUMP(PIN_CONFIG_BIAS_HIGH_IMPEDANCE, "input bias high impedance", NULL),
+ PCONFDUMP(PIN_CONFIG_BIAS_BUS_HOLD, "input bias bus hold", NULL),
PCONFDUMP(PIN_CONFIG_BIAS_PULL_UP, "input bias pull up", NULL),
PCONFDUMP(PIN_CONFIG_BIAS_PULL_DOWN, "input bias pull down", NULL),
+ PCONFDUMP(PIN_CONFIG_BIAS_PULL_PIN_DEFAULT,
+ "input bias pull to pin specific state", NULL),
PCONFDUMP(PIN_CONFIG_DRIVE_PUSH_PULL, "output drive push pull", NULL),
PCONFDUMP(PIN_CONFIG_DRIVE_OPEN_DRAIN, "output drive open drain", NULL),
PCONFDUMP(PIN_CONFIG_DRIVE_OPEN_SOURCE, "output drive open source", NULL),
+ PCONFDUMP(PIN_CONFIG_DRIVE_STRENGTH, "output drive strength", "mA"),
PCONFDUMP(PIN_CONFIG_INPUT_SCHMITT_ENABLE, "input schmitt enabled", NULL),
PCONFDUMP(PIN_CONFIG_INPUT_SCHMITT, "input schmitt trigger", NULL),
PCONFDUMP(PIN_CONFIG_INPUT_DEBOUNCE, "input debounce", "time units"),
@@ -121,3 +126,103 @@
}
#endif
+
+#ifdef CONFIG_OF
+struct pinconf_generic_dt_params {
+ const char * const property;
+ enum pin_config_param param;
+ u32 default_value;
+};
+
+static struct pinconf_generic_dt_params dt_params[] = {
+ { "bias-disable", PIN_CONFIG_BIAS_DISABLE, 0 },
+ { "bias-high-impedance", PIN_CONFIG_BIAS_HIGH_IMPEDANCE, 0 },
+ { "bias-bus-hold", PIN_CONFIG_BIAS_BUS_HOLD, 0 },
+ { "bias-pull-up", PIN_CONFIG_BIAS_PULL_UP, 1 },
+ { "bias-pull-down", PIN_CONFIG_BIAS_PULL_DOWN, 1 },
+ { "bias-pull-pin-default", PIN_CONFIG_BIAS_PULL_PIN_DEFAULT, 1 },
+ { "drive-push-pull", PIN_CONFIG_DRIVE_PUSH_PULL, 0 },
+ { "drive-open-drain", PIN_CONFIG_DRIVE_OPEN_DRAIN, 0 },
+ { "drive-open-source", PIN_CONFIG_DRIVE_OPEN_SOURCE, 0 },
+ { "drive-strength", PIN_CONFIG_DRIVE_STRENGTH, 0 },
+ { "input-schmitt-enable", PIN_CONFIG_INPUT_SCHMITT_ENABLE, 1 },
+ { "input-schmitt-disable", PIN_CONFIG_INPUT_SCHMITT_ENABLE, 0 },
+ { "input-schmitt", PIN_CONFIG_INPUT_SCHMITT, 0 },
+ { "input-debounce", PIN_CONFIG_INPUT_DEBOUNCE, 0 },
+ { "power-source", PIN_CONFIG_POWER_SOURCE, 0 },
+ { "slew-rate", PIN_CONFIG_SLEW_RATE, 0 },
+ { "low-power-enable", PIN_CONFIG_LOW_POWER_MODE, 1 },
+ { "low-power-disable", PIN_CONFIG_LOW_POWER_MODE, 0 },
+ { "output-low", PIN_CONFIG_OUTPUT, 0, },
+ { "output-high", PIN_CONFIG_OUTPUT, 1, },
+};
+
+/**
+ * pinconf_generic_parse_dt_config()
+ * parse the config properties into generic pinconfig values.
+ * @np: node containing the pinconfig properties
+ * @configs: array with nconfigs entries containing the generic pinconf values
+ * @nconfigs: umber of configurations
+ */
+int pinconf_generic_parse_dt_config(struct device_node *np,
+ unsigned long **configs,
+ unsigned int *nconfigs)
+{
+ unsigned long *cfg;
+ unsigned int ncfg = 0;
+ int ret;
+ int i;
+ u32 val;
+
+ if (!np)
+ return -EINVAL;
+
+ /* allocate a temporary array big enough to hold one of each option */
+ cfg = kzalloc(sizeof(*cfg) * ARRAY_SIZE(dt_params), GFP_KERNEL);
+ if (!cfg)
+ return -ENOMEM;
+
+ for (i = 0; i < ARRAY_SIZE(dt_params); i++) {
+ struct pinconf_generic_dt_params *par = &dt_params[i];
+ ret = of_property_read_u32(np, par->property, &val);
+
+ /* property not found */
+ if (ret == -EINVAL)
+ continue;
+
+ /* use default value, when no value is specified */
+ if (ret)
+ val = par->default_value;
+
+ pr_debug("found %s with value %u\n", par->property, val);
+ cfg[ncfg] = pinconf_to_config_packed(par->param, val);
+ ncfg++;
+ }
+
+ ret = 0;
+
+ /* no configs found at all */
+ if (ncfg == 0) {
+ *configs = NULL;
+ *nconfigs = 0;
+ goto out;
+ }
+
+ /*
+ * Now limit the number of configs to the real number of
+ * found properties.
+ */
+ *configs = kzalloc(ncfg * sizeof(unsigned long), GFP_KERNEL);
+ if (!*configs) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ memcpy(*configs, cfg, ncfg * sizeof(unsigned long));
+ *nconfigs = ncfg;
+
+out:
+ kfree(cfg);
+ return ret;
+}
+#endif
diff --git a/drivers/pinctrl/pinconf.h b/drivers/pinctrl/pinconf.h
index bfda73d..bf21525 100644
--- a/drivers/pinctrl/pinconf.h
+++ b/drivers/pinctrl/pinconf.h
@@ -115,3 +115,9 @@
}
#endif
+
+#if defined(CONFIG_GENERIC_PINCONF) && defined(CONFIG_OF)
+int pinconf_generic_parse_dt_config(struct device_node *np,
+ unsigned long **configs,
+ unsigned int *nconfigs);
+#endif
diff --git a/drivers/platform/msm/ipa/ipa_client.c b/drivers/platform/msm/ipa/ipa_client.c
index f20f37f..3aaec07 100644
--- a/drivers/platform/msm/ipa/ipa_client.c
+++ b/drivers/platform/msm/ipa/ipa_client.c
@@ -45,7 +45,7 @@
if (ipa_ctx->ipa_hw_type == IPA_HW_v1_1) {
ipa_write_reg(ipa_ctx->mmio,
IPA_ENDP_INIT_CTRL_n_OFST(clnt_hdl), 1);
- usleep(IPA_PKT_FLUSH_TO_US);
+ udelay(IPA_PKT_FLUSH_TO_US);
if (IPA_CLIENT_IS_CONS(ep->client) &&
ep->cfg.aggr.aggr_en == IPA_ENABLE_AGGR &&
ep->cfg.aggr.aggr_time_limit)
diff --git a/drivers/platform/msm/ipa/ipa_rm_resource.c b/drivers/platform/msm/ipa/ipa_rm_resource.c
index dba4430..986892b 100644
--- a/drivers/platform/msm/ipa/ipa_rm_resource.c
+++ b/drivers/platform/msm/ipa/ipa_rm_resource.c
@@ -787,15 +787,11 @@
&producer->resource.state_lock, flags);
consumer_result = ipa_rm_resource_consumer_release(
(struct ipa_rm_resource_cons *)consumer);
- if (consumer_result == -EINPROGRESS) {
- result = -EINPROGRESS;
- } else {
- spin_lock_irqsave(
- &producer->resource.state_lock, flags);
- producer->pending_release--;
- spin_unlock_irqrestore(
- &producer->resource.state_lock, flags);
- }
+ spin_lock_irqsave(
+ &producer->resource.state_lock, flags);
+ producer->pending_release--;
+ spin_unlock_irqrestore(
+ &producer->resource.state_lock, flags);
}
}
spin_lock_irqsave(&producer->resource.state_lock, flags);
diff --git a/drivers/platform/msm/ipa/ipa_utils.c b/drivers/platform/msm/ipa/ipa_utils.c
index e38b796..4a5fa4d 100644
--- a/drivers/platform/msm/ipa/ipa_utils.c
+++ b/drivers/platform/msm/ipa/ipa_utils.c
@@ -1396,12 +1396,8 @@
if (__ratelimit(&_rs)) {
ipa_inc_client_enable_clks();
pr_err("IPA BAM START\n");
- sps_get_bam_debug_info(ipa_ctx->bam_handle, 5, 1048575, 0, 0);
+ sps_get_bam_debug_info(ipa_ctx->bam_handle, 5, 479182, 0, 0);
sps_get_bam_debug_info(ipa_ctx->bam_handle, 93, 0, 0, 0);
- pr_err("BAM-DMA BAM START\n");
- sps_get_bam_debug_info(sps_dma_get_bam_handle(), 5, 1044480,
- 0, 0);
- sps_get_bam_debug_info(sps_dma_get_bam_handle(), 93, 0, 0, 0);
ipa_dec_client_disable_clks();
}
}
diff --git a/drivers/power/pm8921-bms.c b/drivers/power/pm8921-bms.c
index 1fd4434..a9af974 100644
--- a/drivers/power/pm8921-bms.c
+++ b/drivers/power/pm8921-bms.c
@@ -2118,6 +2118,10 @@
if (the_chip->start_percent == -EINVAL)
return prev_soc;
+ /* do not scale at 100 */
+ if (new_soc == 100)
+ return new_soc;
+
chg_time_sec = DIV_ROUND_UP(the_chip->charge_time_us, USEC_PER_SEC);
catch_up_sec = DIV_ROUND_UP(the_chip->catch_up_time_us, USEC_PER_SEC);
if (catch_up_sec == 0)
@@ -2501,7 +2505,7 @@
}
/* last_soc < soc ... scale and catch up */
- if (last_soc != -EINVAL && last_soc < soc && soc != 100)
+ if (last_soc != -EINVAL && last_soc < soc)
soc = scale_soc_while_chg(chip, delta_time_us, soc, last_soc);
if (last_soc != -EINVAL) {
diff --git a/drivers/power/qpnp-bms.c b/drivers/power/qpnp-bms.c
index 14d5b6a..08995cc 100644
--- a/drivers/power/qpnp-bms.c
+++ b/drivers/power/qpnp-bms.c
@@ -64,11 +64,10 @@
/* Extra bms registers */
#define SOC_STORAGE_REG 0xB0
#define IAVG_STORAGE_REG 0xB1
-#define BMS_BATT_REMOVED_REG 0xB2
-#define BMS1_BMS_DATA_REG_3 0xB3
-#define CHARGE_INCREASE_STORAGE 0xB4
-#define FCC_BATT_TEMP_STORAGE 0xB5
-#define FCC_STORAGE_LSB 0xBC /* LSB=0xBC, MSB=0xBD */
+#define BMS_FCC_COUNT 0xB2
+#define BMS_FCC_BASE_REG 0xB3 /* FCC updates - 0xB3 to 0xB7 */
+#define BMS_CHGCYL_BASE_REG 0xB8 /* FCC chgcyl - 0xB8 to 0xBC */
+#define CHARGE_INCREASE_STORAGE 0xBD
#define CHARGE_CYCLE_STORAGE_LSB 0xBE /* LSB=0xBE, MSB=0xBF */
/* IADC Channel Select */
@@ -84,8 +83,11 @@
#define IAVG_SAMPLES 16
/* FCC learning constants */
+#define MAX_FCC_CYCLES 5
#define DELTA_FCC_PERCENT 5
#define VALID_FCC_CHGCYL_RANGE 50
+#define CHGCYL_RESOLUTION 20
+#define FCC_DEFAULT_TEMP 250
#define QPNP_BMS_DEV_NAME "qcom,qpnp-bms"
@@ -116,9 +118,8 @@
int last_good_ocv_uv;
};
-struct fcc_data {
+struct fcc_sample {
int fcc_new;
- int batt_temp;
int chargecycles;
};
@@ -244,7 +245,8 @@
int ocv_low_threshold_uv;
unsigned long last_recalc_time;
- struct fcc_data *fcc_table;
+ struct fcc_sample *fcc_learning_samples;
+ u8 fcc_sample_count;
int enable_fcc_learning;
int min_fcc_learning_soc;
int min_fcc_ocv_pc;
@@ -259,8 +261,8 @@
int fcc_new_batt_temp;
uint16_t charge_cycles;
u8 charge_increase;
- int fcc_new_sysfs;
- int fcc_update_complete;
+ int fcc_resolution;
+ bool battery_removed;
struct bms_irq sw_cc_thr_irq;
struct bms_irq ocv_thr_irq;
};
@@ -285,45 +287,10 @@
POWER_SUPPLY_PROP_CYCLE_COUNT,
};
+static int discard_backup_fcc_data(struct qpnp_bms_chip *chip);
+static void backup_charge_cycle(struct qpnp_bms_chip *chip);
+
static bool bms_reset;
-static int min_fcc_cycles = -EINVAL;
-static int last_fcc_update_count;
-static int battery_removed;
-
-static int
-bms_ro_ops_set(const char *val, const struct kernel_param *kp)
-{
- return -EINVAL;
-}
-
-static int
-bms_last_fcc_count_set(const char *val, const struct kernel_param *kp)
-{
- int rc;
-
- if (battery_removed) {
- last_fcc_update_count = 0;
- return 0;
- }
- rc = param_set_int(val, kp);
- if (rc)
- pr_err("Failed to set last_fcc_update_count rc=%d\n", rc);
-
- return rc;
-}
-
-static struct kernel_param_ops bms_ro_param_ops = {
- .set = bms_ro_ops_set,
- .get = param_get_int,
-};
-static struct kernel_param_ops bms_last_fcc_count_param_ops = {
- .set = bms_last_fcc_count_set,
- .get = param_get_int,
-};
-module_param_cb(min_fcc_cycles, &bms_ro_param_ops, &min_fcc_cycles, 0644);
-module_param_cb(battery_removed, &bms_ro_param_ops, &battery_removed, 0644);
-module_param_cb(last_fcc_update_count, &bms_last_fcc_count_param_ops,
- &last_fcc_update_count, 0644);
static int qpnp_read_wrapper(struct qpnp_bms_chip *chip, u8 *val,
u16 base, int count)
@@ -871,6 +838,19 @@
chip->last_cc_uah = INT_MIN;
chip->last_ocv_temp = batt_temp;
chip->prev_batt_terminal_uv = 0;
+ if (chip->enable_fcc_learning) {
+ chip->adjusted_fcc_temp_lut = NULL;
+ chip->fcc_new_mah = -EINVAL;
+ /* reset the charge-cycle and charge-increase registers */
+ chip->charge_increase = 0;
+ chip->charge_cycles = 0;
+ backup_charge_cycle(chip);
+ /* discard all the FCC learnt data and reset the local table */
+ discard_backup_fcc_data(chip);
+ memset(chip->fcc_learning_samples, 0,
+ chip->min_fcc_learning_samples *
+ sizeof(struct fcc_sample));
+ }
}
#define OCV_RAW_UNINITIALIZED 0xFFFF
@@ -2624,26 +2604,85 @@
kfree(old);
}
-
-static void backup_fcc_new(struct qpnp_bms_chip *chip)
+static int read_fcc_data_from_backup(struct qpnp_bms_chip *chip)
{
- int rc = 0;
- u8 temp = 0;
+ int rc, i;
+ u8 fcc = 0, chgcyl = 0;
- if (chip->fcc_new_mah > 0) {
- rc = qpnp_write_wrapper(chip, (u8 *)&chip->fcc_new_mah,
- chip->base + FCC_STORAGE_LSB, 2);
- if (rc)
- pr_err("Unable to backup new_fcc\n");
-
- temp = chip->fcc_new_batt_temp / 10;
- rc = qpnp_write_wrapper(chip, &temp,
- chip->base + FCC_BATT_TEMP_STORAGE, 1);
- if (rc)
- pr_err("Unable to backup fcc temp.\n");
+ for (i = 0; i < chip->min_fcc_learning_samples; i++) {
+ rc = qpnp_read_wrapper(chip, &fcc,
+ chip->base + BMS_FCC_BASE_REG + i, 1);
+ rc |= qpnp_read_wrapper(chip, &chgcyl,
+ chip->base + BMS_CHGCYL_BASE_REG + i, 1);
+ if (rc) {
+ pr_err("Unable to read FCC data\n");
+ return rc;
+ }
+ if (fcc == 0 || (fcc == 0xFF && chgcyl == 0xFF)) {
+ /* FCC invalid/not present */
+ chip->fcc_learning_samples[i].fcc_new = 0;
+ chip->fcc_learning_samples[i].chargecycles = 0;
+ } else {
+ /* valid FCC data */
+ chip->fcc_sample_count++;
+ chip->fcc_learning_samples[i].fcc_new =
+ fcc * chip->fcc_resolution;
+ chip->fcc_learning_samples[i].chargecycles =
+ chgcyl * CHGCYL_RESOLUTION;
+ }
}
+
+ return 0;
}
+static int discard_backup_fcc_data(struct qpnp_bms_chip *chip)
+{
+ int rc = 0, i;
+ u8 temp_u8 = 0;
+
+ chip->fcc_sample_count = 0;
+ for (i = 0; i < chip->min_fcc_learning_samples; i++) {
+ rc = qpnp_write_wrapper(chip, &temp_u8,
+ chip->base + BMS_FCC_BASE_REG + i, 1);
+ rc |= qpnp_write_wrapper(chip, &temp_u8,
+ chip->base + BMS_CHGCYL_BASE_REG + i, 1);
+ if (rc) {
+ pr_err("Unable to clear FCC data\n");
+ return rc;
+ }
+ }
+
+ return 0;
+}
+
+static void
+average_fcc_samples_and_readjust_fcc_table(struct qpnp_bms_chip *chip)
+{
+ int i, temp_fcc_avg = 0, temp_fcc_delta = 0, new_fcc_avg = 0;
+ struct fcc_sample *ft;
+
+ for (i = 0; i < chip->min_fcc_learning_samples; i++)
+ temp_fcc_avg += chip->fcc_learning_samples[i].fcc_new;
+
+ temp_fcc_avg /= chip->min_fcc_learning_samples;
+ temp_fcc_delta = div_u64(temp_fcc_avg * DELTA_FCC_PERCENT, 100);
+
+ /* fix the fcc if its an outlier i.e. > 5% of the average */
+ for (i = 0; i < chip->min_fcc_learning_samples; i++) {
+ ft = &chip->fcc_learning_samples[i];
+ if (abs(ft->fcc_new - temp_fcc_avg) > temp_fcc_delta)
+ new_fcc_avg += temp_fcc_avg;
+ else
+ new_fcc_avg += ft->fcc_new;
+ }
+ new_fcc_avg /= chip->min_fcc_learning_samples;
+
+ chip->fcc_new_mah = new_fcc_avg;
+ chip->fcc_new_batt_temp = FCC_DEFAULT_TEMP;
+ pr_info("FCC update: New fcc_mah=%d, fcc_batt_temp=%d\n",
+ new_fcc_avg, FCC_DEFAULT_TEMP);
+ readjust_fcc_table(chip);
+}
static void backup_charge_cycle(struct qpnp_bms_chip *chip)
{
@@ -2651,7 +2690,7 @@
if (chip->charge_increase >= 0) {
rc = qpnp_write_wrapper(chip, &chip->charge_increase,
- chip->base + CHARGE_INCREASE_STORAGE, 1);
+ chip->base + CHARGE_INCREASE_STORAGE, 1);
if (rc)
pr_err("Unable to backup charge_increase\n");
}
@@ -2664,9 +2703,31 @@
}
}
-static void restore_fcc_data(struct qpnp_bms_chip *chip)
+static bool chargecycles_in_range(struct qpnp_bms_chip *chip)
{
- int rc = 0;
+ int i, min_cycle, max_cycle, valid_range;
+
+ /* find the smallest and largest charge cycle */
+ max_cycle = min_cycle = chip->fcc_learning_samples[0].chargecycles;
+ for (i = 1; i < chip->min_fcc_learning_samples; i++) {
+ if (min_cycle > chip->fcc_learning_samples[i].chargecycles)
+ min_cycle = chip->fcc_learning_samples[i].chargecycles;
+ if (max_cycle < chip->fcc_learning_samples[i].chargecycles)
+ max_cycle = chip->fcc_learning_samples[i].chargecycles;
+ }
+
+ /* check if chargecyles are in range to continue with FCC update */
+ valid_range = DIV_ROUND_UP(VALID_FCC_CHGCYL_RANGE,
+ CHGCYL_RESOLUTION) * CHGCYL_RESOLUTION;
+ if (abs(max_cycle - min_cycle) > valid_range)
+ return false;
+
+ return true;
+}
+
+static int read_chgcycle_data_from_backup(struct qpnp_bms_chip *chip)
+{
+ int rc;
uint16_t temp_u16 = 0;
u8 temp_u8 = 0;
@@ -2680,25 +2741,18 @@
if (!rc && temp_u16 != 0xFFFF)
chip->charge_cycles = temp_u16;
- rc = qpnp_read_wrapper(chip, (u8 *)&temp_u16,
- chip->base + FCC_STORAGE_LSB, 2);
- if (!rc && temp_u16 != 0xFFFF) {
- chip->fcc_new_mah = temp_u16;
- } else {
- pr_debug("Backed-up FCC not initialized, FCC not updated\n");
- return;
- }
+ return rc;
+}
- rc = qpnp_read_wrapper(chip, &temp_u8,
- chip->base + FCC_BATT_TEMP_STORAGE, 1);
- if (!rc && temp_u8 != 0xFF) {
- chip->fcc_new_batt_temp = (s8)temp_u8 * 10;
- } else {
- pr_debug("Backed-up temp. not initialized, FCC not updated\n");
- return;
- }
- /* readjust the FCC table if fcc and temp are valid */
- readjust_fcc_table(chip);
+static void
+attempt_learning_new_fcc(struct qpnp_bms_chip *chip)
+{
+ pr_debug("Total FCC sample count=%d\n", chip->fcc_sample_count);
+
+ /* update FCC if we have the required samples */
+ if ((chip->fcc_sample_count == chip->min_fcc_learning_samples) &&
+ chargecycles_in_range(chip))
+ average_fcc_samples_and_readjust_fcc_table(chip);
}
static int calculate_real_soc(struct qpnp_bms_chip *chip,
@@ -2712,82 +2766,80 @@
return ((rc_uah - cc_uah) * 100) / fcc_uah;
}
-static void update_fcc_table_for_temp(struct qpnp_bms_chip *chip,
- int batt_temp_final)
-{
- int i, fcc_t1, fcc_t2, fcc_final;
- struct fcc_data *ft;
+#define MAX_U8_VALUE ((u8)(~0U))
- /* Interpolate all the FCC entries to the same temperature */
- for (i = 0; i < chip->min_fcc_learning_samples; i++) {
- ft = &chip->fcc_table[i];
- if (ft->batt_temp == batt_temp_final)
- continue;
- fcc_t1 = interpolate_fcc(chip->fcc_temp_lut, ft->batt_temp);
- fcc_t2 = interpolate_fcc(chip->fcc_temp_lut, batt_temp_final);
- fcc_final = (ft->fcc_new / fcc_t1) * fcc_t2;
- ft->fcc_new = fcc_final;
- ft->batt_temp = batt_temp_final;
+static int backup_new_fcc(struct qpnp_bms_chip *chip, int fcc_mah,
+ int chargecycles)
+{
+ int rc, min_cycle, i;
+ u8 fcc_new, chgcyl, pos = 0;
+ struct fcc_sample *ft;
+
+ if ((fcc_mah > (chip->fcc_resolution * MAX_U8_VALUE)) ||
+ (chargecycles > (CHGCYL_RESOLUTION * MAX_U8_VALUE))) {
+ pr_warn("FCC/Chgcyl beyond storage limit. FCC=%d, chgcyl=%d\n",
+ fcc_mah, chargecycles);
+ return -EINVAL;
}
+
+ if (chip->fcc_sample_count == chip->min_fcc_learning_samples) {
+ /* search best location - oldest entry */
+ min_cycle = chip->fcc_learning_samples[0].chargecycles;
+ for (i = 1; i < chip->min_fcc_learning_samples; i++) {
+ if (min_cycle >
+ chip->fcc_learning_samples[i].chargecycles)
+ pos = i;
+ }
+ } else {
+ /* find an empty location */
+ for (i = 0; i < chip->min_fcc_learning_samples; i++) {
+ ft = &chip->fcc_learning_samples[i];
+ if (ft->fcc_new == 0 || (ft->fcc_new == 0xFF &&
+ ft->chargecycles == 0xFF)) {
+ pos = i;
+ break;
+ }
+ }
+ chip->fcc_sample_count++;
+ }
+ chip->fcc_learning_samples[pos].fcc_new = fcc_mah;
+ chip->fcc_learning_samples[pos].chargecycles = chargecycles;
+
+ fcc_new = DIV_ROUND_UP(fcc_mah, chip->fcc_resolution);
+ rc = qpnp_write_wrapper(chip, (u8 *)&fcc_new,
+ chip->base + BMS_FCC_BASE_REG + pos, 1);
+ if (rc)
+ return rc;
+
+ chgcyl = DIV_ROUND_UP(chargecycles, CHGCYL_RESOLUTION);
+ rc = qpnp_write_wrapper(chip, (u8 *)&chgcyl,
+ chip->base + BMS_CHGCYL_BASE_REG + pos, 1);
+ if (rc)
+ return rc;
+
+ pr_debug("Backup new FCC: fcc_new=%d, chargecycle=%d, pos=%d\n",
+ fcc_new, chgcyl, pos);
+
+ return rc;
}
static void update_fcc_learning_table(struct qpnp_bms_chip *chip,
- int fcc_uah, int new_fcc_uah, int chargecycles, int batt_temp)
+ int new_fcc_uah, int chargecycles, int batt_temp)
{
- int i, count, new_fcc_avg = 0, temp_fcc_avg = 0, temp_fcc_delta = 0;
- struct fcc_data *ft;
+ int rc, fcc_default, fcc_temp;
- count = last_fcc_update_count % chip->min_fcc_learning_samples;
- ft = &chip->fcc_table[count];
- ft->fcc_new = chip->fcc_new_sysfs = new_fcc_uah;
- ft->batt_temp = batt_temp;
- ft->chargecycles = chargecycles;
- last_fcc_update_count++;
- /* update userspace */
- sysfs_notify(&chip->dev->kobj, NULL, "fcc_data");
+ /* convert the fcc at batt_temp to new fcc at FCC_DEFAULT_TEMP */
+ fcc_default = calculate_fcc(chip, FCC_DEFAULT_TEMP) / 1000;
+ fcc_temp = calculate_fcc(chip, batt_temp) / 1000;
+ new_fcc_uah = (new_fcc_uah / fcc_temp) * fcc_default;
- pr_debug("Updated fcc table. new_fcc=%d, chargecycle=%d, temp=%d fcc_update_count=%d\n",
- new_fcc_uah, chargecycles, batt_temp, last_fcc_update_count);
-
- if (last_fcc_update_count < chip->min_fcc_learning_samples) {
- pr_debug("Not enough FCC samples. Current count = %d\n",
- last_fcc_update_count);
- return; /* Not enough samples to update fcc */
+ rc = backup_new_fcc(chip, new_fcc_uah / 1000, chargecycles);
+ if (rc) {
+ pr_err("Unable to backup new FCC\n");
+ return;
}
-
- /* reject entries if they are > 50 chargecycles apart */
- for (i = 0; i < chip->min_fcc_learning_samples; i++) {
- if ((chip->fcc_table[i].chargecycles + VALID_FCC_CHGCYL_RANGE)
- < chargecycles) {
- pr_debug("Charge cycle too old (> %d cycles apart)\n",
- VALID_FCC_CHGCYL_RANGE);
- return; /* Samples old, > 50 cycles apart*/
- }
- }
- /* update the fcc table for temperature difference*/
- update_fcc_table_for_temp(chip, batt_temp);
-
- for (i = 0; i < chip->min_fcc_learning_samples; i++)
- temp_fcc_avg += chip->fcc_table[i].fcc_new;
-
- temp_fcc_avg /= chip->min_fcc_learning_samples;
- temp_fcc_delta = div_u64(temp_fcc_avg * DELTA_FCC_PERCENT, 100);
-
- /* fix the fcc if its an outlier i.e. > 5% of the average */
- for (i = 0; i < chip->min_fcc_learning_samples; i++) {
- ft = &chip->fcc_table[i];
- if (abs(ft->fcc_new - temp_fcc_avg) > temp_fcc_delta)
- ft->fcc_new = temp_fcc_avg;
- new_fcc_avg += ft->fcc_new;
- }
- new_fcc_avg /= chip->min_fcc_learning_samples;
-
- chip->fcc_new_mah = new_fcc_avg / 1000;
- chip->fcc_new_batt_temp = batt_temp;
- pr_info("FCC update: New fcc_mah=%d, fcc_batt_temp=%d\n",
- new_fcc_avg, batt_temp);
- readjust_fcc_table(chip);
- backup_fcc_new(chip);
+ /* check if FCC can be updated */
+ attempt_learning_new_fcc(chip);
}
static bool is_new_fcc_valid(int new_fcc_uah, int fcc_uah)
@@ -2841,8 +2893,8 @@
chip->start_cc_uah, chip->end_cc_uah, new_fcc_uah);
if (is_new_fcc_valid(new_fcc_uah, fcc_uah))
- update_fcc_learning_table(chip, fcc_uah,
- new_fcc_uah, chip->charge_cycles, batt_temp);
+ update_fcc_learning_table(chip, new_fcc_uah,
+ chip->charge_cycles, batt_temp);
}
}
@@ -3013,123 +3065,6 @@
return 0;
}
-static ssize_t fcc_data_set(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct qpnp_bms_chip *chip = dev_get_drvdata(dev);
- static int i;
- int fcc_new = 0, rc;
-
- if (chip->fcc_update_complete) {
- pr_debug("Invalid FCC update\n");
- return count;
- }
-
- i %= chip->min_fcc_learning_samples;
- rc = sscanf(buf, "%d", &fcc_new);
- if (rc != 1)
- return -EINVAL;
- chip->fcc_table[i].fcc_new = fcc_new;
- pr_debug("Rcvd: [%d] fcc_new=%d\n", i, fcc_new);
- i++;
-
- return count;
-}
-
-static ssize_t fcc_data_get(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- int count = 0;
- struct qpnp_bms_chip *chip = dev_get_drvdata(dev);
-
- count = snprintf(buf, PAGE_SIZE, "%d", chip->fcc_new_sysfs);
- pr_debug("Sent: fcc_new=%d\n", chip->fcc_new_sysfs);
- chip->fcc_update_complete = 1;
-
- return count;
-}
-
-static ssize_t fcc_temp_set(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- static int i;
- int batt_temp = 0, rc;
- struct qpnp_bms_chip *chip = dev_get_drvdata(dev);
-
- if (chip->fcc_update_complete)
- return count;
-
- i %= chip->min_fcc_learning_samples;
- rc = sscanf(buf, "%d", &batt_temp);
- if (rc != 1)
- return -EINVAL;
- chip->fcc_table[i].batt_temp = batt_temp;
- pr_debug("Rcvd: [%d] batt_temp=%d\n", i, batt_temp);
- i++;
-
- return count;
-}
-
-static ssize_t fcc_chgcyl_set(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- static int i;
- int chargecycle = 0, rc;
- struct qpnp_bms_chip *chip = dev_get_drvdata(dev);
-
- if (chip->fcc_update_complete)
- return count;
-
- i %= chip->min_fcc_learning_samples;
- rc = sscanf(buf, "%d", &chargecycle);
- if (rc != 1)
- return -EINVAL;
- chip->fcc_table[i].chargecycles = chargecycle;
- pr_debug("Rcvd: [%d] chargecycle=%d\n", i, chargecycle);
- i++;
-
- return count;
-}
-
-static ssize_t fcc_list_get(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- struct qpnp_bms_chip *chip = dev_get_drvdata(dev);
- struct fcc_data *ft;
- int i = 0, j, count = 0;
-
- if (last_fcc_update_count < chip->min_fcc_learning_samples)
- i = last_fcc_update_count;
- else
- i = chip->min_fcc_learning_samples;
-
- for (j = 0; j < i; j++) {
- ft = &chip->fcc_table[j];
- count += snprintf(buf + count, PAGE_SIZE - count,
- "%d %d %d\n", ft->fcc_new, ft->chargecycles,
- ft->batt_temp);
- }
-
- return count;
-}
-
-static DEVICE_ATTR(fcc_data, 0664, fcc_data_get, fcc_data_set);
-static DEVICE_ATTR(fcc_temp, 0664, NULL, fcc_temp_set);
-static DEVICE_ATTR(fcc_chgcyl, 0664, NULL, fcc_chgcyl_set);
-static DEVICE_ATTR(fcc_list, 0664, fcc_list_get, NULL);
-
-static struct attribute *fcc_attrs[] = {
- &dev_attr_fcc_data.attr,
- &dev_attr_fcc_temp.attr,
- &dev_attr_fcc_chgcyl.attr,
- &dev_attr_fcc_list.attr,
- NULL
-};
-
-static const struct attribute_group fcc_attr_group = {
- .attrs = fcc_attrs,
-};
-
#define OCV_USE_LIMIT_EN BIT(7)
static int set_ocv_voltage_thresholds(struct qpnp_bms_chip *chip,
int low_voltage_threshold,
@@ -3213,10 +3148,19 @@
}
}
- pr_debug("shutdown_soc = %d shutdown_iavg = %d shutdown_soc_invalid = %d\n",
+ /* read the SOC storage to determine if there was a battery removal */
+ rc = qpnp_read_wrapper(chip, &temp, chip->base + SOC_STORAGE_REG, 1);
+ if (!rc) {
+ if (temp == SOC_INVALID)
+ chip->battery_removed = true;
+ }
+
+
+ pr_debug("shutdown_soc = %d shutdown_iavg = %d shutdown_soc_invalid = %d, battery_removed = %d\n",
chip->shutdown_soc,
chip->shutdown_iavg_ma,
- chip->shutdown_soc_invalid);
+ chip->shutdown_soc_invalid,
+ chip->battery_removed);
}
static irqreturn_t bms_ocv_thr_irq_handler(int irq, void *_chip)
@@ -3325,6 +3269,12 @@
} \
} while (0)
+#define SPMI_PROP_READ_BOOL(chip_prop, qpnp_spmi_property) \
+do { \
+ chip->chip_prop = of_property_read_bool(chip->spmi->dev.of_node,\
+ "qcom," qpnp_spmi_property); \
+} while (0)
+
static inline int bms_read_properties(struct qpnp_bms_chip *chip)
{
int rc;
@@ -3371,8 +3321,7 @@
if (chip->adjust_soc_low_threshold >= 45)
chip->adjust_soc_low_threshold = 45;
- chip->enable_fcc_learning = of_property_read_bool(
- chip->spmi->dev.of_node, "qcom,enable-fcc-learning");
+ SPMI_PROP_READ_BOOL(enable_fcc_learning, "enable-fcc-learning");
if (chip->enable_fcc_learning) {
SPMI_PROP_READ(min_fcc_learning_soc,
"min-fcc-learning-soc", rc);
@@ -3380,12 +3329,16 @@
"min-fcc-ocv-pc", rc);
SPMI_PROP_READ(min_fcc_learning_samples,
"min-fcc-learning-samples", rc);
- chip->fcc_table = kzalloc((sizeof(struct fcc_data) *
- chip->min_fcc_learning_samples), GFP_KERNEL);
+ SPMI_PROP_READ(fcc_resolution,
+ "fcc-resolution", rc);
+ if (chip->min_fcc_learning_samples > MAX_FCC_CYCLES)
+ chip->min_fcc_learning_samples = MAX_FCC_CYCLES;
+ chip->fcc_learning_samples = devm_kzalloc(&chip->spmi->dev,
+ (sizeof(struct fcc_sample) *
+ chip->min_fcc_learning_samples), GFP_KERNEL);
pr_debug("min-fcc-soc=%d, min-fcc-pc=%d, min-fcc-cycles=%d\n",
chip->min_fcc_learning_soc, chip->min_fcc_ocv_pc,
chip->min_fcc_learning_samples);
- min_fcc_cycles = chip->min_fcc_learning_samples;
}
pr_debug("dts data: r_sense_uohm:%d, v_cutoff_uv:%d, max_v:%d\n",
@@ -3662,28 +3615,6 @@
return 0;
}
-static void check_battery_removal(struct qpnp_bms_chip *chip)
-{
- int rc;
- u8 temp = 0;
-
- /* check if battery was removed at PON */
- rc = qpnp_read_wrapper(chip, &temp,
- chip->base + BMS_BATT_REMOVED_REG, 1);
- if (temp == 0xFF) {
- pr_debug("New battery inserted at PON\n");
- temp = battery_removed = 1;
- rc = qpnp_write_wrapper(chip, &temp,
- chip->base + BMS_BATT_REMOVED_REG, 1);
- if (rc)
- pr_err("Unable to set BMS_BATT_REMOVED_REG\n");
- } else {
- if (rc)
- pr_err("Unable to read BMS_BATT_REMOVED_REG\n");
- battery_removed = 0;
- }
-}
-
static int __devinit qpnp_bms_probe(struct spmi_device *spmi)
{
struct qpnp_bms_chip *chip;
@@ -3711,6 +3642,12 @@
goto error_read;
}
+ mutex_init(&chip->bms_output_lock);
+ mutex_init(&chip->last_ocv_uv_mutex);
+ mutex_init(&chip->vbat_monitor_mutex);
+ mutex_init(&chip->soc_invalidation_mutex);
+ mutex_init(&chip->last_soc_mutex);
+
warm_reset = qpnp_pon_is_warm_reset();
rc = warm_reset;
if (rc < 0)
@@ -3768,12 +3705,6 @@
bms_initialize_constants(chip);
- mutex_init(&chip->bms_output_lock);
- mutex_init(&chip->last_ocv_uv_mutex);
- mutex_init(&chip->vbat_monitor_mutex);
- mutex_init(&chip->soc_invalidation_mutex);
- mutex_init(&chip->last_soc_mutex);
-
wakeup_source_init(&chip->soc_wake_source.source, "qpnp_soc_wake");
wake_lock_init(&chip->low_voltage_wake_lock, WAKE_LOCK_SUSPEND,
"qpnp_low_voltage_lock");
@@ -3786,20 +3717,26 @@
read_shutdown_soc_and_iavg(chip);
if (chip->enable_fcc_learning) {
- restore_fcc_data(chip);
- rc = sysfs_create_group(&spmi->dev.kobj, &fcc_attr_group);
- if (rc) {
- pr_err("Unable to create sysfs entries\n");
- goto error_setup;
+ if (chip->battery_removed) {
+ rc = discard_backup_fcc_data(chip);
+ if (rc)
+ pr_err("Could not discard backed-up FCC data\n");
+ } else {
+ rc = read_chgcycle_data_from_backup(chip);
+ if (rc)
+ pr_err("Unable to restore charge-cycle data\n");
+
+ rc = read_fcc_data_from_backup(chip);
+ if (rc)
+ pr_err("Unable to restore FCC-learning data\n");
+ else
+ attempt_learning_new_fcc(chip);
}
}
dev_set_drvdata(&spmi->dev, chip);
device_init_wakeup(&spmi->dev, 1);
- check_battery_removal(chip);
-
-
rc = setup_vbat_monitoring(chip);
if (rc < 0) {
pr_err("failed to set up voltage notifications: %d\n", rc);
diff --git a/drivers/power/qpnp-charger.c b/drivers/power/qpnp-charger.c
index e05c866..3679aa9 100644
--- a/drivers/power/qpnp-charger.c
+++ b/drivers/power/qpnp-charger.c
@@ -296,6 +296,8 @@
unsigned int cool_bat_mv;
unsigned int resume_delta_mv;
int term_current;
+ int soc_resume_limit;
+ bool resuming_charging;
unsigned int maxinput_usb_ma;
unsigned int maxinput_dc_ma;
unsigned int hot_batt_p;
@@ -757,6 +759,23 @@
}
static void
+qpnp_chg_set_appropriate_vbatdet(struct qpnp_chg_chip *chip)
+{
+ if (chip->bat_is_cool)
+ qpnp_chg_vbatdet_set(chip, chip->cool_bat_mv
+ - chip->resume_delta_mv);
+ else if (chip->bat_is_warm)
+ qpnp_chg_vbatdet_set(chip, chip->warm_bat_mv
+ - chip->resume_delta_mv);
+ else if (chip->resuming_charging)
+ qpnp_chg_vbatdet_set(chip, chip->max_voltage_mv
+ + chip->resume_delta_mv);
+ else
+ qpnp_chg_vbatdet_set(chip, chip->max_voltage_mv
+ - chip->resume_delta_mv);
+}
+
+static void
qpnp_arb_stop_work(struct work_struct *work)
{
struct delayed_work *dwork = to_delayed_work(work);
@@ -955,6 +974,10 @@
power_supply_changed(chip->usb_psy);
if (chip->dc_chgpth_base)
power_supply_changed(&chip->dc_psy);
+ if (chip->resuming_charging) {
+ chip->resuming_charging = false;
+ qpnp_chg_set_appropriate_vbatdet(chip);
+ }
qpnp_chg_enable_irq(&chip->chg_vbatdet_lo);
return IRQ_HANDLED;
@@ -1120,7 +1143,7 @@
val->intval = qpnp_chg_is_dc_chg_plugged_in(chip);
break;
case POWER_SUPPLY_PROP_CURRENT_MAX:
- val->intval = chip->maxinput_dc_ma;
+ val->intval = chip->maxinput_dc_ma * 1000;
break;
default:
return -EINVAL;
@@ -1295,6 +1318,16 @@
if (chip->bms_psy) {
chip->bms_psy->get_property(chip->bms_psy,
POWER_SUPPLY_PROP_CAPACITY, &ret);
+ if (get_prop_batt_status(chip) == POWER_SUPPLY_STATUS_FULL
+ && !chip->resuming_charging
+ && !chip->charging_disabled
+ && chip->soc_resume_limit
+ && ret.intval <= chip->soc_resume_limit) {
+ pr_debug("resuming charging at %d%% soc\n", ret.intval);
+ chip->resuming_charging = true;
+ qpnp_chg_set_appropriate_vbatdet(chip);
+ qpnp_chg_charge_en(chip, !chip->charging_disabled);
+ }
if (ret.intval == 0) {
if (!qpnp_chg_is_usb_chg_plugged_in(chip)
&& !qpnp_chg_is_usb_chg_plugged_in(chip))
@@ -1674,20 +1707,6 @@
}
static void
-qpnp_chg_set_appropriate_vbatdet(struct qpnp_chg_chip *chip)
-{
- if (chip->bat_is_cool)
- qpnp_chg_vbatdet_set(chip, chip->cool_bat_mv
- - chip->resume_delta_mv);
- else if (chip->bat_is_warm)
- qpnp_chg_vbatdet_set(chip, chip->warm_bat_mv
- - chip->resume_delta_mv);
- else
- qpnp_chg_vbatdet_set(chip, chip->max_voltage_mv
- - chip->resume_delta_mv);
-}
-
-static void
qpnp_chg_set_appropriate_battery_current(struct qpnp_chg_chip *chip)
{
unsigned int chg_current = chip->max_bat_chg_current;
@@ -2129,7 +2148,16 @@
chip->bat_is_cool = bat_cool;
chip->bat_is_warm = bat_warm;
- /* set appropriate voltages and currents */
+ if (bat_cool || bat_warm)
+ chip->resuming_charging = false;
+
+ /**
+ * set appropriate voltages and currents.
+ *
+ * Note that when the battery is hot or cold, the charger
+ * driver will not resume with SoC. Only vbatdet is used to
+ * determine resume of charging.
+ */
qpnp_chg_set_appropriate_vddmax(chip);
qpnp_chg_set_appropriate_battery_current(chip);
qpnp_chg_set_appropriate_vbatdet(chip);
@@ -2324,7 +2352,8 @@
}
rc = devm_request_irq(chip->dev, chip->batt_pres.irq,
qpnp_chg_bat_if_batt_pres_irq_handler,
- IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING
+ | IRQF_SHARED | IRQF_ONESHOT,
"batt-pres", chip);
if (rc < 0) {
pr_err("Can't request %d batt-pres irq: %d\n",
@@ -2692,6 +2721,8 @@
OF_PROP_READ(chip, tchg_mins, "tchg-mins", rc, 1);
OF_PROP_READ(chip, hot_batt_p, "batt-hot-percentage", rc, 1);
OF_PROP_READ(chip, cold_batt_p, "batt-cold-percentage", rc, 1);
+ OF_PROP_READ(chip, soc_resume_limit, "resume-soc", rc, 1);
+
if (rc)
return rc;
@@ -2736,13 +2767,6 @@
chip->duty_cycle_100p = of_property_read_bool(
chip->spmi->dev.of_node,
"qcom,duty-cycle-100p");
- if (chip->duty_cycle_100p) {
- rc = qpnp_buck_set_100_duty_cycle_enable(chip, 1);
- if (rc) {
- pr_err("failed to enable duty cycle %d\n", rc);
- return rc;
- }
- }
/* Get the fake-batt-values property */
chip->use_default_batt_values =
@@ -2908,6 +2932,16 @@
0xFF,
0x80, 1);
+ if (chip->duty_cycle_100p) {
+ rc = qpnp_buck_set_100_duty_cycle_enable(chip,
+ 1);
+ if (rc) {
+ pr_err("failed to set duty cycle %d\n",
+ rc);
+ goto fail_chg_enable;
+ }
+ }
+
break;
case SMBB_BAT_IF_SUBTYPE:
case SMBBP_BAT_IF_SUBTYPE:
diff --git a/drivers/spi/spi_qsd.c b/drivers/spi/spi_qsd.c
index c7db832..863339b 100644
--- a/drivers/spi/spi_qsd.c
+++ b/drivers/spi/spi_qsd.c
@@ -1426,9 +1426,10 @@
dma_coherent_post_ops();
memcpy(dd->read_buf + offset, dd->rx_padding,
dd->rx_unaligned_len);
- memcpy(dd->cur_transfer->rx_buf,
- dd->read_buf + prev_xfr->len,
- dd->cur_transfer->len);
+ if (dd->cur_transfer->rx_buf)
+ memcpy(dd->cur_transfer->rx_buf,
+ dd->read_buf + prev_xfr->len,
+ dd->cur_transfer->len);
}
}
kfree(dd->temp_buf);
@@ -3121,7 +3122,7 @@
msm_spi_disable_irqs(dd);
clk_disable_unprepare(dd->clk);
clk_disable_unprepare(dd->pclk);
- if (!dd->pdata->active_only)
+ if (dd->pdata && !dd->pdata->active_only)
msm_spi_clk_path_unvote(dd);
/* Free the spi clk, miso, mosi, cs gpio */
diff --git a/drivers/spmi/qpnp-int.c b/drivers/spmi/qpnp-int.c
index 082c9ff..eedb1e5 100644
--- a/drivers/spmi/qpnp-int.c
+++ b/drivers/spmi/qpnp-int.c
@@ -578,11 +578,14 @@
unsigned long hwirq, busno;
int irq;
+ if (!spec || !spmi_ctrl)
+ return -EINVAL;
+
pr_debug("spec slave = %u per = %u irq = %u\n",
spec->slave, spec->per, spec->irq);
busno = spmi_ctrl->nr;
- if (!spec || !spmi_ctrl || busno >= QPNPINT_MAX_BUSSES)
+ if (busno >= QPNPINT_MAX_BUSSES)
return -EINVAL;
hwirq = qpnpint_encode_hwirq(spec);
diff --git a/drivers/thermal/msm8974-tsens.c b/drivers/thermal/msm8974-tsens.c
index 52608af..6933163 100644
--- a/drivers/thermal/msm8974-tsens.c
+++ b/drivers/thermal/msm8974-tsens.c
@@ -77,6 +77,9 @@
#define TSENS_EEPROM_8X10_1(n) ((n) + 0x1a4)
#define TSENS_EEPROM_8X10_1_OFFSET 8
+#define TSENS_EEPROM_8X10_2(n) ((n) + 0x1a8)
+#define TSENS_EEPROM_8X10_SPARE_1(n) ((n) + 0xd8)
+#define TSENS_EEPROM_8X10_SPARE_2(n) ((n) + 0xdc)
/* TSENS calibration Mask data */
#define TSENS_BASE1_MASK 0xff
@@ -207,6 +210,8 @@
#define TSENS_8X10_TSENS_CAL_SEL 0x70000000
#define TSENS1_8X10_POINT1_MASK 0x3f
#define TSENS1_8X10_POINT2_MASK 0xfc0
+#define TSENS_8X10_REDUN_SEL_MASK 0x6000000
+#define TSENS_8X10_REDUN_SEL_SHIFT 25
#define TSENS_BIT_APPEND 0x3
#define TSENS_CAL_DEGC_POINT1 30
@@ -559,6 +564,9 @@
unsigned int reg_cntl;
int code, hi_code, lo_code, code_err_chk, sensor_sw_id = 0, rc = 0;
+ if (!tm_sensor || trip < 0 || !temp)
+ return -EINVAL;
+
rc = tsens_get_sw_id_mapping(tm_sensor->sensor_hw_num, &sensor_sw_id);
if (rc < 0) {
pr_err("tsens mapping index not found\n");
@@ -721,17 +729,30 @@
int i, tsens_base0_data = 0, tsens0_point1 = 0, tsens1_point1 = 0;
int tsens0_point2 = 0, tsens1_point2 = 0;
int tsens_base1_data = 0, tsens_calibration_mode = 0;
- uint32_t calib_data[2];
+ uint32_t calib_data[2], calib_redun_sel;
uint32_t calib_tsens_point1_data[2], calib_tsens_point2_data[2];
if (tmdev->calibration_less_mode)
goto calibration_less_mode;
- calib_data[0] = readl_relaxed(
+ calib_redun_sel = readl_relaxed(
+ TSENS_EEPROM_8X10_2(tmdev->tsens_calib_addr));
+ calib_redun_sel = calib_redun_sel & TSENS_8X10_REDUN_SEL_MASK;
+ calib_redun_sel >>= TSENS_8X10_REDUN_SEL_SHIFT;
+ pr_debug("calib_redun_sel:%x\n", calib_redun_sel);
+
+ if (calib_redun_sel == TSENS_QFPROM_BACKUP_SEL) {
+ calib_data[0] = readl_relaxed(
+ TSENS_EEPROM_8X10_SPARE_1(tmdev->tsens_calib_addr));
+ calib_data[1] = readl_relaxed(
+ TSENS_EEPROM_8X10_SPARE_2(tmdev->tsens_calib_addr));
+ } else {
+ calib_data[0] = readl_relaxed(
TSENS_EEPROM_8X10_1(tmdev->tsens_calib_addr));
- calib_data[1] = readl_relaxed(
- (TSENS_EEPROM_8X10_1(tmdev->tsens_calib_addr) +
+ calib_data[1] = readl_relaxed(
+ (TSENS_EEPROM_8X10_1(tmdev->tsens_calib_addr) +
TSENS_EEPROM_8X10_1_OFFSET));
+ }
tsens_calibration_mode = (calib_data[0] & TSENS_8X10_TSENS_CAL_SEL)
>> TSENS_8X10_CAL_SEL_SHIFT;
@@ -1325,7 +1346,7 @@
static int get_device_tree_data(struct platform_device *pdev)
{
- const struct device_node *of_node = pdev->dev.of_node;
+ struct device_node *of_node = pdev->dev.of_node;
struct resource *res_mem = NULL;
u32 *tsens_slope_data;
u32 *sensor_id;
@@ -1353,8 +1374,13 @@
return rc;
};
- tsens_calib_mode = of_get_property(of_node,
- "qcom,calib-mode", NULL);
+ rc = of_property_read_string(of_node,
+ "qcom,calib-mode", &tsens_calib_mode);
+ if (rc) {
+ dev_err(&pdev->dev, "missing calib-mode\n");
+ return -ENODEV;
+ }
+
if (!strncmp(tsens_calib_mode, "fuse_map1", 9))
calib_type = TSENS_CALIB_FUSE_MAP_8974;
else if (!strncmp(tsens_calib_mode, "fuse_map2", 9))
diff --git a/drivers/tty/n_smux.c b/drivers/tty/n_smux.c
index d1545dc..c8e5163 100644
--- a/drivers/tty/n_smux.c
+++ b/drivers/tty/n_smux.c
@@ -297,6 +297,8 @@
[SMUX_HIGH_WM_HIT] = "HIGH_WM_HIT",
[SMUX_RX_RETRY_HIGH_WM_HIT] = "RX_RETRY_HIGH_WM_HIT",
[SMUX_RX_RETRY_LOW_WM_HIT] = "RX_RETRY_LOW_WM_HIT",
+ [SMUX_LOCAL_CLOSED] = "LOCAL_CLOSED",
+ [SMUX_REMOTE_CLOSED] = "REMOTE_CLOSED",
};
static const char * const smux_local_state[] = {
@@ -553,6 +555,8 @@
/* Close all ports */
for (i = 0 ; i < SMUX_NUM_LOGICAL_CHANNELS; i++) {
+ union notifier_metadata meta;
+ int send_disconnect = 0;
ch = &smux_lch[i];
SMUX_DBG("smux: %s: cleaning up lcid %d\n", __func__, i);
@@ -563,14 +567,19 @@
smux_purge_ch_tx_queue(ch, 1);
spin_unlock(&ch->tx_lock_lhb2);
+ meta.disconnected.is_ssr = smux.in_reset;
/* Notify user of disconnect and reset channel state */
if (ch->local_state == SMUX_LCH_LOCAL_OPENED ||
ch->local_state == SMUX_LCH_LOCAL_CLOSING) {
- union notifier_metadata meta;
-
- meta.disconnected.is_ssr = smux.in_reset;
- schedule_notify(ch->lcid, SMUX_DISCONNECTED, &meta);
+ schedule_notify(ch->lcid, SMUX_LOCAL_CLOSED, &meta);
+ send_disconnect = 1;
}
+ if (ch->remote_state != SMUX_LCH_REMOTE_CLOSED) {
+ schedule_notify(ch->lcid, SMUX_REMOTE_CLOSED, &meta);
+ send_disconnect = 1;
+ }
+ if (send_disconnect)
+ schedule_notify(ch->lcid, SMUX_DISCONNECTED, &meta);
ch->local_state = SMUX_LCH_LOCAL_CLOSED;
ch->remote_state = SMUX_LCH_REMOTE_CLOSED;
@@ -857,6 +866,10 @@
IPC_LOG_STR("smux: %s ch:%d\n", event_to_str(event), lcid);
ch = &smux_lch[lcid];
+ if (!ch->notify) {
+ SMUX_DBG("%s: [%d]lcid notify fn is NULL\n", __func__, lcid);
+ return ret;
+ }
notify_handle = kzalloc(sizeof(struct smux_notify_handle),
GFP_ATOMIC);
if (!notify_handle) {
@@ -1187,8 +1200,11 @@
enable_powerdown = 1;
ch->local_state = SMUX_LCH_LOCAL_OPENED;
- if (ch->remote_state == SMUX_LCH_REMOTE_OPENED)
+ if (ch->remote_state == SMUX_LCH_REMOTE_OPENED) {
schedule_notify(lcid, SMUX_CONNECTED, NULL);
+ if (!(list_empty(&ch->tx_queue)))
+ list_channel(ch);
+ }
ret = 0;
} else if (ch->remote_mode == SMUX_LCH_MODE_REMOTE_LOOPBACK) {
SMUX_DBG("smux: Remote loopback OPEN ACK received\n");
@@ -1232,6 +1248,7 @@
SMUX_LCH_LOCAL_CLOSING,
SMUX_LCH_LOCAL_CLOSED);
ch->local_state = SMUX_LCH_LOCAL_CLOSED;
+ schedule_notify(lcid, SMUX_LOCAL_CLOSED, &meta_disconnected);
if (ch->remote_state == SMUX_LCH_REMOTE_CLOSED)
schedule_notify(lcid, SMUX_DISCONNECTED,
&meta_disconnected);
@@ -1419,6 +1436,7 @@
}
}
+ schedule_notify(lcid, SMUX_REMOTE_CLOSED, &meta_disconnected);
if (ch->local_state == SMUX_LCH_LOCAL_CLOSED)
schedule_notify(lcid, SMUX_DISCONNECTED,
&meta_disconnected);
@@ -2357,8 +2375,11 @@
union notifier_metadata meta_disconnected;
meta_disconnected.disconnected.is_ssr = smux.in_reset;
- schedule_notify(ch->lcid, SMUX_DISCONNECTED,
+ schedule_notify(ch->lcid, SMUX_LOCAL_CLOSED,
&meta_disconnected);
+ if (ch->remote_state == SMUX_LCH_REMOTE_CLOSED)
+ schedule_notify(ch->lcid, SMUX_DISCONNECTED,
+ &meta_disconnected);
}
}
@@ -3086,11 +3107,15 @@
*
* @returns 0 for success, <0 otherwise
*
- * A channel must be fully closed (either not previously opened or
- * msm_smux_close() has been called and the SMUX_DISCONNECTED has been
- * received.
+ * The local channel state must be closed (either not previously
+ * opened or msm_smux_close() has been called and the SMUX_LOCAL_CLOSED
+ * notification has been received).
*
- * One the remote side is opened, the client will receive a SMUX_CONNECTED
+ * If open is called before the SMUX_LOCAL_CLOSED has been received,
+ * then the function will return -EAGAIN and the client will need to
+ * retry the open later.
+ *
+ * Once the remote side is opened, the client will receive a SMUX_CONNECTED
* event.
*/
int msm_smux_open(uint8_t lcid, void *priv,
@@ -3167,7 +3192,8 @@
* @returns 0 for success, <0 otherwise
*
* Once the close event has been acknowledge by the remote side, the client
- * will receive a SMUX_DISCONNECTED notification.
+ * will receive an SMUX_LOCAL_CLOSED notification. If the remote side is also
+ * closed, then an SMUX_DISCONNECTED notification will also be sent.
*/
int msm_smux_close(uint8_t lcid)
{
diff --git a/drivers/tty/serial/msm_serial_hs.c b/drivers/tty/serial/msm_serial_hs.c
index cab7c12..9e22afd 100644
--- a/drivers/tty/serial/msm_serial_hs.c
+++ b/drivers/tty/serial/msm_serial_hs.c
@@ -192,7 +192,7 @@
ktime_t clk_off_delay;
enum msm_hs_clk_states_e clk_state;
enum msm_hs_clk_req_off_state_e clk_req_off_state;
-
+ atomic_t clk_count;
struct msm_hs_wakeup wakeup;
struct wake_lock dma_wake_lock; /* held while any DMA active */
@@ -241,6 +241,7 @@
static void msm_hs_start_rx_locked(struct uart_port *uport);
static void msm_serial_hs_rx_tlet(unsigned long tlet_ptr);
static void flip_insert_work(struct work_struct *work);
+static void msm_hs_bus_voting(struct msm_hs_port *msm_uport, unsigned int vote);
#define UARTDM_TO_MSM(uart_port) \
container_of((uart_port), struct msm_hs_port, uport)
@@ -287,6 +288,61 @@
return ret;
}
+static int msm_hs_clock_vote(struct msm_hs_port *msm_uport)
+{
+ int rc = 0;
+
+ if (1 == atomic_inc_return(&msm_uport->clk_count)) {
+ msm_hs_bus_voting(msm_uport, BUS_SCALING);
+ /* Turn on core clk and iface clk */
+ rc = clk_prepare_enable(msm_uport->clk);
+ if (rc) {
+ dev_err(msm_uport->uport.dev,
+ "%s: Could not turn on core clk [%d]\n",
+ __func__, rc);
+ return rc;
+ }
+
+ if (msm_uport->pclk) {
+ rc = clk_prepare_enable(msm_uport->pclk);
+ if (rc) {
+ clk_disable_unprepare(msm_uport->clk);
+ dev_err(msm_uport->uport.dev,
+ "%s: Could not turn on pclk [%d]\n",
+ __func__, rc);
+ return rc;
+ }
+ }
+ msm_uport->clk_state = MSM_HS_CLK_ON;
+ }
+
+
+ return rc;
+}
+
+static void msm_hs_clock_unvote(struct msm_hs_port *msm_uport)
+{
+ int rc = atomic_dec_return(&msm_uport->clk_count);
+
+ if (rc < 0) {
+ msm_hs_bus_voting(msm_uport, BUS_RESET);
+ WARN(rc, "msm_uport->clk_count < 0!");
+ dev_err(msm_uport->uport.dev,
+ "%s: Clocks count invalid [%d]\n", __func__,
+ atomic_read(&msm_uport->clk_count));
+ return;
+ }
+
+ if (0 == rc) {
+ msm_hs_bus_voting(msm_uport, BUS_RESET);
+ /* Turn off the core clk and iface clk*/
+ clk_disable_unprepare(msm_uport->clk);
+ if (msm_uport->pclk)
+ clk_disable_unprepare(msm_uport->pclk);
+ msm_uport->clk_state = MSM_HS_CLK_OFF;
+ }
+}
+
static ssize_t show_clock(struct device *dev, struct device_attribute *attr,
char *buf)
{
@@ -432,11 +488,7 @@
unsigned long flags;
int ret = 0;
- msm_hs_bus_voting(msm_uport, BUS_SCALING);
-
- clk_prepare_enable(msm_uport->clk);
- if (msm_uport->pclk)
- clk_prepare_enable(msm_uport->pclk);
+ msm_hs_clock_vote(msm_uport);
if (val) {
spin_lock_irqsave(&uport->lock, flags);
@@ -461,11 +513,8 @@
}
/* Calling CLOCK API. Hence mb() requires here. */
mb();
- clk_disable_unprepare(msm_uport->clk);
- if (msm_uport->pclk)
- clk_disable_unprepare(msm_uport->pclk);
- msm_hs_bus_voting(msm_uport, BUS_RESET);
+ msm_hs_clock_unvote(msm_uport);
return 0;
}
@@ -476,23 +525,16 @@
unsigned long flags;
int ret = 0;
- msm_hs_bus_voting(msm_uport, BUS_SCALING);
-
- clk_prepare_enable(msm_uport->clk);
- if (msm_uport->pclk)
- clk_prepare_enable(msm_uport->pclk);
+ msm_hs_clock_vote(msm_uport);
spin_lock_irqsave(&uport->lock, flags);
ret = msm_hs_read(&msm_uport->uport, UARTDM_MR2_ADDR);
spin_unlock_irqrestore(&uport->lock, flags);
- clk_disable_unprepare(msm_uport->clk);
- if (msm_uport->pclk)
- clk_disable_unprepare(msm_uport->pclk);
+ msm_hs_clock_unvote(msm_uport);
*val = (ret & UARTDM_MR2_LOOP_MODE_BMSK) ? 1 : 0;
- msm_hs_bus_voting(msm_uport, BUS_RESET);
return 0;
}
DEFINE_SIMPLE_ATTRIBUTE(loopback_enable_fops, msm_serial_loopback_enable_get,
@@ -585,22 +627,12 @@
return ret;
}
- ret = clk_prepare_enable(msm_uport->clk);
+ ret = msm_hs_clock_vote(msm_uport);
if (ret) {
printk(KERN_ERR "Error could not turn on UART clk\n");
return ret;
}
- if (msm_uport->pclk) {
- ret = clk_prepare_enable(msm_uport->pclk);
- if (ret) {
- clk_disable_unprepare(msm_uport->clk);
- dev_err(uport->dev,
- "Error could not turn on UART pclk\n");
- return ret;
- }
- }
- msm_uport->clk_state = MSM_HS_CLK_ON;
return 0;
}
@@ -1040,8 +1072,12 @@
{
unsigned int data;
unsigned int ret = 0;
+ struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
+ msm_hs_clock_vote(msm_uport);
data = msm_hs_read(uport, UARTDM_SR_ADDR);
+ msm_hs_clock_unvote(msm_uport);
+
if (data & UARTDM_SR_TXEMT_BMSK)
ret = TIOCSER_TEMT;
@@ -1658,10 +1694,13 @@
unsigned int mctrl)
{
unsigned long flags;
+ struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
+ msm_hs_clock_vote(msm_uport);
spin_lock_irqsave(&uport->lock, flags);
msm_hs_set_mctrl_locked(uport, mctrl);
spin_unlock_irqrestore(&uport->lock, flags);
+ msm_hs_clock_unvote(msm_uport);
}
EXPORT_SYMBOL(msm_hs_set_mctrl);
@@ -1825,11 +1864,7 @@
spin_unlock_irqrestore(&uport->lock, flags);
/* we really want to clock off */
- clk_disable_unprepare(msm_uport->clk);
- if (msm_uport->pclk)
- clk_disable_unprepare(msm_uport->pclk);
-
- msm_uport->clk_state = MSM_HS_CLK_OFF;
+ msm_hs_clock_unvote(msm_uport);
spin_lock_irqsave(&uport->lock, flags);
if (use_low_power_wakeup(msm_uport)) {
@@ -2020,25 +2055,13 @@
disable_irq_nosync(msm_uport->wakeup.irq);
spin_unlock_irqrestore(&uport->lock, flags);
- /* Vote for PNOC BUS Scaling */
- msm_hs_bus_voting(msm_uport, BUS_SCALING);
-
- ret = clk_prepare_enable(msm_uport->clk);
+ ret = msm_hs_clock_vote(msm_uport);
if (ret) {
dev_err(uport->dev, "Clock ON Failure"
"For UART CLK Stalling HSUART\n");
break;
}
- if (msm_uport->pclk) {
- ret = clk_prepare_enable(msm_uport->pclk);
- if (unlikely(ret)) {
- clk_disable_unprepare(msm_uport->clk);
- dev_err(uport->dev, "Clock ON Failure"
- "For UART Pclk Stalling HSUART\n");
- break;
- }
- }
spin_lock_irqsave(&uport->lock, flags);
/* else fall-through */
case MSM_HS_CLK_REQUEST_OFF:
@@ -2375,8 +2398,7 @@
disable_irq(msm_uport->wakeup.irq);
}
- /* Vote for PNOC BUS Scaling */
- msm_hs_bus_voting(msm_uport, BUS_SCALING);
+ msm_hs_clock_vote(msm_uport);
spin_lock_irqsave(&uport->lock, flags);
@@ -2384,6 +2406,8 @@
spin_unlock_irqrestore(&uport->lock, flags);
+ msm_hs_clock_unvote(msm_uport);
+
pm_runtime_enable(uport->dev);
return 0;
@@ -2403,9 +2427,7 @@
if (is_blsp_uart(msm_uport))
msm_hs_unconfig_uart_gpios(uport);
deinit_uart_clk:
- clk_disable_unprepare(msm_uport->clk);
- if (msm_uport->pclk)
- clk_disable_unprepare(msm_uport->pclk);
+ msm_hs_clock_unvote(msm_uport);
wake_unlock(&msm_uport->dma_wake_lock);
return ret;
@@ -3057,6 +3079,8 @@
INIT_WORK(&msm_uport->disconnect_rx_endpoint,
hsuart_disconnect_rx_endpoint_work);
mutex_init(&msm_uport->clk_mutex);
+ atomic_set(&msm_uport->clk_count, 0);
+
/* Initialize SPS HW connected with UART core */
if (is_blsp_uart(msm_uport)) {
@@ -3067,11 +3091,7 @@
}
}
- msm_hs_bus_voting(msm_uport, BUS_SCALING);
-
- clk_prepare_enable(msm_uport->clk);
- if (msm_uport->pclk)
- clk_prepare_enable(msm_uport->pclk);
+ msm_hs_clock_vote(msm_uport);
ret = uartdm_init_port(uport);
if (unlikely(ret)) {
@@ -3106,19 +3126,12 @@
uport->line = pdata->userid;
ret = uart_add_one_port(&msm_hs_driver, uport);
if (!ret) {
- msm_hs_bus_voting(msm_uport, BUS_RESET);
- clk_disable_unprepare(msm_uport->clk);
- if (msm_uport->pclk)
- clk_disable_unprepare(msm_uport->pclk);
+ msm_hs_clock_unvote(msm_uport);
return ret;
}
err_clock:
-
- msm_hs_bus_voting(msm_uport, BUS_RESET);
- clk_disable_unprepare(msm_uport->clk);
- if (msm_uport->pclk)
- clk_disable_unprepare(msm_uport->pclk);
+ msm_hs_clock_unvote(msm_uport);
destroy_mutex:
mutex_destroy(&msm_uport->clk_mutex);
@@ -3189,6 +3202,7 @@
struct msm_hs_tx *tx = &msm_uport->tx;
struct sps_pipe *sps_pipe_handle = tx->cons.pipe_handle;
+ msm_hs_clock_vote(msm_uport);
if (msm_uport->tx.dma_in_flight) {
if (!is_blsp_uart(msm_uport)) {
spin_lock_irqsave(&uport->lock, flags);
@@ -3240,16 +3254,12 @@
*/
mb();
- /* Reset PNOC Bus Scaling */
- msm_hs_bus_voting(msm_uport, BUS_RESET);
-
if (msm_uport->clk_state != MSM_HS_CLK_OFF) {
/* to balance clk_state */
- clk_disable_unprepare(msm_uport->clk);
- if (msm_uport->pclk)
- clk_disable_unprepare(msm_uport->pclk);
+ msm_hs_clock_unvote(msm_uport);
wake_unlock(&msm_uport->dma_wake_lock);
}
+ msm_hs_clock_unvote(msm_uport);
msm_uport->clk_state = MSM_HS_CLK_PORT_OFF;
dma_unmap_single(uport->dev, msm_uport->tx.dma_base,
diff --git a/drivers/tty/smux_test.c b/drivers/tty/smux_test.c
index 8d17674..130b65e 100644
--- a/drivers/tty/smux_test.c
+++ b/drivers/tty/smux_test.c
@@ -194,6 +194,8 @@
int event_high_wm;
int event_rx_retry_high_wm;
int event_rx_retry_low_wm;
+ int event_local_closed;
+ int event_remote_closed;
/* TIOCM changes */
int event_tiocm;
@@ -249,6 +251,8 @@
cb->event_high_wm = 0;
cb->event_rx_retry_high_wm = 0;
cb->event_rx_retry_low_wm = 0;
+ cb->event_local_closed = 0;
+ cb->event_remote_closed = 0;
cb->event_tiocm = 0;
cb->tiocm_meta.tiocm_old = 0;
cb->tiocm_meta.tiocm_new = 0;
@@ -311,6 +315,8 @@
"\tevent_high_wm=%d\n"
"\tevent_rx_retry_high_wm=%d\n"
"\tevent_rx_retry_low_wm=%d\n"
+ "\tevent_local_closed=%d\n"
+ "\tevent_remote_closed=%d\n"
"\tevent_tiocm=%d\n"
"\tevent_read_done=%d\n"
"\tevent_read_failed=%d\n"
@@ -329,6 +335,8 @@
cb->event_high_wm,
cb->event_rx_retry_high_wm,
cb->event_rx_retry_low_wm,
+ cb->event_local_closed,
+ cb->event_remote_closed,
cb->event_tiocm,
cb->event_read_done,
cb->event_read_failed,
@@ -467,6 +475,22 @@
spin_unlock_irqrestore(&cb_data_ptr->lock, flags);
break;
+ case SMUX_LOCAL_CLOSED:
+ spin_lock_irqsave(&cb_data_ptr->lock, flags);
+ ++cb_data_ptr->event_local_closed;
+ cb_data_ptr->event_disconnected_ssr =
+ ((struct smux_meta_disconnected *)metadata)->is_ssr;
+ spin_unlock_irqrestore(&cb_data_ptr->lock, flags);
+ break;
+
+ case SMUX_REMOTE_CLOSED:
+ spin_lock_irqsave(&cb_data_ptr->lock, flags);
+ ++cb_data_ptr->event_remote_closed;
+ cb_data_ptr->event_disconnected_ssr =
+ ((struct smux_meta_disconnected *)metadata)->is_ssr;
+ spin_unlock_irqrestore(&cb_data_ptr->lock, flags);
+ break;
+
default:
pr_err("%s: unknown event %d\n", __func__, event);
};
@@ -609,13 +633,18 @@
/* close port */
ret = msm_smux_close(SMUX_TEST_LCID);
UT_ASSERT_INT(ret, ==, 0);
- UT_ASSERT_INT(
- (int)wait_for_completion_timeout(
- &cb_data.cb_completion, HZ),
- >, 0);
- UT_ASSERT_INT(cb_data.cb_count, ==, 1);
+ while (cb_data.cb_count < 3) {
+ UT_ASSERT_INT(
+ (int)wait_for_completion_timeout(
+ &cb_data.cb_completion, HZ),
+ >, 0);
+ INIT_COMPLETION(cb_data.cb_completion);
+ }
+ UT_ASSERT_INT(cb_data.cb_count, ==, 3);
UT_ASSERT_INT(cb_data.event_disconnected, ==, 1);
UT_ASSERT_INT(cb_data.event_disconnected_ssr, ==, 0);
+ UT_ASSERT_INT(cb_data.event_local_closed, ==, 1);
+ UT_ASSERT_INT(cb_data.event_remote_closed, ==, 1);
break;
}
@@ -783,13 +812,18 @@
/* verify SSR events */
UT_ASSERT_INT(ret, ==, 0);
- UT_ASSERT_INT(
- (int)wait_for_completion_timeout(
- &cb_data.cb_completion, 5*HZ),
- >, 0);
- UT_ASSERT_INT(cb_data.cb_count, ==, 1);
+ while (cb_data.cb_count < 3) {
+ UT_ASSERT_INT(
+ (int)wait_for_completion_timeout(
+ &cb_data.cb_completion, 10*HZ),
+ >, 0);
+ INIT_COMPLETION(cb_data.cb_completion);
+ }
+ UT_ASSERT_INT(cb_data.cb_count, ==, 3);
UT_ASSERT_INT(cb_data.event_disconnected, ==, 1);
UT_ASSERT_INT(cb_data.event_disconnected_ssr, ==, 1);
+ UT_ASSERT_INT(cb_data.event_local_closed, ==, 1);
+ UT_ASSERT_INT(cb_data.event_remote_closed, ==, 1);
mock_cb_data_reset(&cb_data);
/* close port */
@@ -894,6 +928,8 @@
break;
UT_ASSERT_INT(cb_data.event_disconnected, ==, 1);
UT_ASSERT_INT(cb_data.event_disconnected_ssr, ==, 1);
+ UT_ASSERT_INT(cb_data.event_local_closed, ==, 1);
+ UT_ASSERT_INT(cb_data.event_remote_closed, ==, 1);
mock_cb_data_reset(&cb_data);
/* close port */
@@ -1272,13 +1308,18 @@
/* close port */
ret = msm_smux_close(SMUX_TEST_LCID);
UT_ASSERT_INT(ret, ==, 0);
- UT_ASSERT_INT(
- (int)wait_for_completion_timeout(
- &cb_data.cb_completion, HZ),
- >, 0);
- UT_ASSERT_INT(cb_data.cb_count, ==, 1);
+ while (cb_data.cb_count < 3) {
+ UT_ASSERT_INT(
+ (int)wait_for_completion_timeout(
+ &cb_data.cb_completion, HZ),
+ >, 0);
+ INIT_COMPLETION(cb_data.cb_completion);
+ }
+ UT_ASSERT_INT(cb_data.cb_count, ==, 3);
UT_ASSERT_INT(cb_data.event_disconnected, ==, 1);
UT_ASSERT_INT(cb_data.event_disconnected_ssr, ==, 0);
+ UT_ASSERT_INT(cb_data.event_local_closed, ==, 1);
+ UT_ASSERT_INT(cb_data.event_remote_closed, ==, 1);
break;
}
@@ -1442,13 +1483,18 @@
/* close port */
ret = msm_smux_close(SMUX_TEST_LCID);
UT_ASSERT_INT(ret, ==, 0);
- UT_ASSERT_INT(
- (int)wait_for_completion_timeout(
- &cb_data.cb_completion, HZ),
- >, 0);
- UT_ASSERT_INT(cb_data.cb_count, ==, 1);
+ while (cb_data.cb_count < 3) {
+ UT_ASSERT_INT(
+ (int)wait_for_completion_timeout(
+ &cb_data.cb_completion, HZ),
+ >, 0);
+ INIT_COMPLETION(cb_data.cb_completion);
+ }
+ UT_ASSERT_INT(cb_data.cb_count, ==, 3);
UT_ASSERT_INT(cb_data.event_disconnected, ==, 1);
UT_ASSERT_INT(cb_data.event_disconnected_ssr, ==, 0);
+ UT_ASSERT_INT(cb_data.event_local_closed, ==, 1);
+ UT_ASSERT_INT(cb_data.event_remote_closed, ==, 1);
break;
}
@@ -1552,13 +1598,18 @@
/* close port */
ret = msm_smux_close(SMUX_TEST_LCID);
UT_ASSERT_INT(ret, ==, 0);
- UT_ASSERT_INT(
- (int)wait_for_completion_timeout(
- &cb_data.cb_completion, HZ),
- >, 0);
- UT_ASSERT_INT(cb_data.cb_count, ==, 1);
+ while (cb_data.cb_count < 3) {
+ UT_ASSERT_INT(
+ (int)wait_for_completion_timeout(
+ &cb_data.cb_completion, HZ),
+ >, 0);
+ INIT_COMPLETION(cb_data.cb_completion);
+ }
+ UT_ASSERT_INT(cb_data.cb_count, ==, 3);
UT_ASSERT_INT(cb_data.event_disconnected, ==, 1);
UT_ASSERT_INT(cb_data.event_disconnected_ssr, ==, 0);
+ UT_ASSERT_INT(cb_data.event_local_closed, ==, 1);
+ UT_ASSERT_INT(cb_data.event_remote_closed, ==, 1);
break;
}
@@ -1884,13 +1935,18 @@
/* close port */
ret = msm_smux_close(SMUX_TEST_LCID);
UT_ASSERT_INT(ret, ==, 0);
- UT_ASSERT_INT(
- (int)wait_for_completion_timeout(
- &cb_data.cb_completion, HZ),
- >, 0);
- UT_ASSERT_INT(cb_data.cb_count, ==, 1);
+ while (cb_data.cb_count < 3) {
+ UT_ASSERT_INT(
+ (int)wait_for_completion_timeout(
+ &cb_data.cb_completion, HZ),
+ >, 0);
+ INIT_COMPLETION(cb_data.cb_completion);
+ }
+ UT_ASSERT_INT(cb_data.cb_count, ==, 3);
UT_ASSERT_INT(cb_data.event_disconnected, ==, 1);
UT_ASSERT_INT(cb_data.event_disconnected_ssr, ==, 0);
+ UT_ASSERT_INT(cb_data.event_local_closed, ==, 1);
+ UT_ASSERT_INT(cb_data.event_remote_closed, ==, 1);
break;
}
@@ -2010,13 +2066,18 @@
/* close port */
ret = msm_smux_close(SMUX_TEST_LCID);
UT_ASSERT_INT(ret, ==, 0);
- UT_ASSERT_INT(
- (int)wait_for_completion_timeout(
- &cb_data.cb_completion, HZ),
- >, 0);
- UT_ASSERT_INT(cb_data.cb_count, ==, 1);
+ while (cb_data.cb_count < 3) {
+ UT_ASSERT_INT(
+ (int)wait_for_completion_timeout(
+ &cb_data.cb_completion, HZ),
+ >, 0);
+ INIT_COMPLETION(cb_data.cb_completion);
+ }
+ UT_ASSERT_INT(cb_data.cb_count, ==, 3);
UT_ASSERT_INT(cb_data.event_disconnected, ==, 1);
UT_ASSERT_INT(cb_data.event_disconnected_ssr, ==, 0);
+ UT_ASSERT_INT(cb_data.event_local_closed, ==, 1);
+ UT_ASSERT_INT(cb_data.event_remote_closed, ==, 1);
break;
}
@@ -2139,13 +2200,18 @@
/* close port */
ret = msm_smux_close(SMUX_TEST_LCID);
UT_ASSERT_INT(ret, ==, 0);
- UT_ASSERT_INT(
- (int)wait_for_completion_timeout(
- &cb_data.cb_completion, HZ),
- >, 0);
- UT_ASSERT_INT(cb_data.cb_count, ==, 1);
+ while (cb_data.cb_count < 3) {
+ UT_ASSERT_INT(
+ (int)wait_for_completion_timeout(
+ &cb_data.cb_completion, HZ),
+ >, 0);
+ INIT_COMPLETION(cb_data.cb_completion);
+ }
+ UT_ASSERT_INT(cb_data.cb_count, ==, 3);
UT_ASSERT_INT(cb_data.event_disconnected, ==, 1);
UT_ASSERT_INT(cb_data.event_disconnected_ssr, ==, 0);
+ UT_ASSERT_INT(cb_data.event_local_closed, ==, 1);
+ UT_ASSERT_INT(cb_data.event_remote_closed, ==, 1);
break;
}
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index 9446ddf..0f8a7f0 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -34,7 +34,9 @@
#include <linux/usb/gadget.h>
#include <linux/qpnp-misc.h>
#include <linux/usb/msm_hsusb.h>
+#include <linux/usb/msm_ext_chg.h>
#include <linux/regulator/consumer.h>
+#include <linux/pm_wakeup.h>
#include <linux/power_supply.h>
#include <linux/qpnp/qpnp-adc.h>
#include <linux/cdev.h>
@@ -165,7 +167,7 @@
struct dwc3_msm {
struct device *dev;
void __iomem *base;
- u32 resource_size;
+ struct resource *io_res;
int dbm_num_eps;
u8 ep_num_mapping[DBM_MAX_EPS];
const struct usb_ep_ops *original_ep_ops[DWC3_ENDPOINTS_NUM];
@@ -195,7 +197,6 @@
bool lpm_irq_seen;
struct delayed_work resume_work;
struct work_struct restart_usb_work;
- struct wake_lock wlock;
struct dwc3_charger charger;
struct usb_phy *otg_xceiv;
struct delayed_work chg_work;
@@ -245,8 +246,6 @@
#define USB_SSPHY_1P8_VOL_MAX 1800000 /* uV */
#define USB_SSPHY_1P8_HPM_LOAD 23000 /* uA */
-static struct dwc3_msm *context;
-
static struct usb_ext_notification *usb_ext;
/**
@@ -342,8 +341,8 @@
tmp &= mask; /* clear other bits */
if (tmp != val)
- dev_err(context->dev, "%s: write: %x to QSCRATCH: %x FAILED\n",
- __func__, val, offset);
+ pr_err("%s: write: %x to QSCRATCH: %x FAILED\n",
+ __func__, val, offset);
}
/**
@@ -412,12 +411,12 @@
* Return DBM EP number according to usb endpoint number.
*
*/
-static int dwc3_msm_find_matching_dbm_ep(u8 usb_ep)
+static int dwc3_msm_find_matching_dbm_ep(struct dwc3_msm *mdwc, u8 usb_ep)
{
int i;
- for (i = 0; i < context->dbm_num_eps; i++)
- if (context->ep_num_mapping[i] == usb_ep)
+ for (i = 0; i < mdwc->dbm_num_eps; i++)
+ if (mdwc->ep_num_mapping[i] == usb_ep)
return i;
return -ENODEV; /* Not found */
@@ -427,13 +426,13 @@
* Return number of configured DBM endpoints.
*
*/
-static int dwc3_msm_configured_dbm_ep_num(void)
+static int dwc3_msm_configured_dbm_ep_num(struct dwc3_msm *mdwc)
{
int i;
int count = 0;
- for (i = 0; i < context->dbm_num_eps; i++)
- if (context->ep_num_mapping[i])
+ for (i = 0; i < mdwc->dbm_num_eps; i++)
+ if (mdwc->ep_num_mapping[i])
count++;
return count;
@@ -447,12 +446,13 @@
* @size - size of the event buffer.
*
*/
-static int dwc3_msm_event_buffer_config(u32 addr, u16 size)
+static int dwc3_msm_event_buffer_config(struct dwc3_msm *mdwc,
+ u32 addr, u16 size)
{
- dev_dbg(context->dev, "%s\n", __func__);
+ dev_dbg(mdwc->dev, "%s\n", __func__);
- dwc3_msm_write_reg(context->base, DBM_GEVNTADR, addr);
- dwc3_msm_write_reg_field(context->base, DBM_GEVNTSIZ,
+ dwc3_msm_write_reg(mdwc->base, DBM_GEVNTADR, addr);
+ dwc3_msm_write_reg_field(mdwc->base, DBM_GEVNTSIZ,
DBM_GEVNTSIZ_MASK, size);
return 0;
@@ -462,19 +462,19 @@
* Reset the DBM registers upon initialization.
*
*/
-static int dwc3_msm_dbm_soft_reset(int enter_reset)
+static int dwc3_msm_dbm_soft_reset(struct dwc3_msm *mdwc, int enter_reset)
{
- dev_dbg(context->dev, "%s\n", __func__);
+ dev_dbg(mdwc->dev, "%s\n", __func__);
if (enter_reset) {
- dev_dbg(context->dev, "enter DBM reset\n");
- dwc3_msm_write_reg_field(context->base, DBM_SOFT_RESET,
+ dev_dbg(mdwc->dev, "enter DBM reset\n");
+ dwc3_msm_write_reg_field(mdwc->base, DBM_SOFT_RESET,
DBM_SFT_RST_MASK, 1);
} else {
- dev_dbg(context->dev, "exit DBM reset\n");
- dwc3_msm_write_reg_field(context->base, DBM_SOFT_RESET,
+ dev_dbg(mdwc->dev, "exit DBM reset\n");
+ dwc3_msm_write_reg_field(mdwc->base, DBM_SOFT_RESET,
DBM_SFT_RST_MASK, 0);
/*enable DBM*/
- dwc3_msm_write_reg_field(context->base, QSCRATCH_GENERAL_CFG,
+ dwc3_msm_write_reg_field(mdwc->base, QSCRATCH_GENERAL_CFG,
DBM_EN_MASK, 0x1);
}
@@ -491,21 +491,21 @@
* @enter_reset - should we enter a reset state or get out of it.
*
*/
-static int dwc3_msm_dbm_ep_soft_reset(u8 dbm_ep, bool enter_reset)
+static int dwc3_msm_dbm_ep_soft_reset(struct dwc3_msm *mdwc,
+ u8 dbm_ep, bool enter_reset)
{
- dev_dbg(context->dev, "%s\n", __func__);
+ dev_dbg(mdwc->dev, "%s\n", __func__);
- if (dbm_ep >= context->dbm_num_eps) {
- dev_err(context->dev,
- "%s: Invalid DBM ep index\n", __func__);
+ if (dbm_ep >= mdwc->dbm_num_eps) {
+ dev_err(mdwc->dev, "%s: Invalid DBM ep index\n", __func__);
return -ENODEV;
}
if (enter_reset) {
- dwc3_msm_write_reg_field(context->base, DBM_SOFT_RESET,
+ dwc3_msm_write_reg_field(mdwc->base, DBM_SOFT_RESET,
DBM_SFT_RST_EPS_MASK & 1 << dbm_ep, 1);
} else {
- dwc3_msm_write_reg_field(context->base, DBM_SOFT_RESET,
+ dwc3_msm_write_reg_field(mdwc->base, DBM_SOFT_RESET,
DBM_SFT_RST_EPS_MASK & 1 << dbm_ep, 0);
}
@@ -524,43 +524,43 @@
*
* @return int - DBM ep number.
*/
-static int dwc3_msm_dbm_ep_config(u8 usb_ep, u8 bam_pipe,
+static int dwc3_msm_dbm_ep_config(struct dwc3_msm *mdwc, u8 usb_ep, u8 bam_pipe,
bool producer, bool disable_wb,
bool internal_mem, bool ioc)
{
u8 dbm_ep;
u32 ep_cfg;
- dev_dbg(context->dev, "%s\n", __func__);
+ dev_dbg(mdwc->dev, "%s\n", __func__);
- dbm_ep = dwc3_msm_find_matching_dbm_ep(usb_ep);
+ dbm_ep = dwc3_msm_find_matching_dbm_ep(mdwc, usb_ep);
if (dbm_ep < 0) {
- dev_err(context->dev,
+ dev_err(mdwc->dev,
"%s: Invalid usb ep index\n", __func__);
return -ENODEV;
}
/* First, reset the dbm endpoint */
- dwc3_msm_dbm_ep_soft_reset(dbm_ep, 0);
+ dwc3_msm_dbm_ep_soft_reset(mdwc, dbm_ep, 0);
/* Set ioc bit for dbm_ep if needed */
- dwc3_msm_write_reg_field(context->base, DBM_DBG_CNFG,
+ dwc3_msm_write_reg_field(mdwc->base, DBM_DBG_CNFG,
DBM_ENABLE_IOC_MASK & 1 << dbm_ep, ioc ? 1 : 0);
ep_cfg = (producer ? DBM_PRODUCER : 0) |
(disable_wb ? DBM_DISABLE_WB : 0) |
(internal_mem ? DBM_INT_RAM_ACC : 0);
- dwc3_msm_write_reg_field(context->base, DBM_EP_CFG(dbm_ep),
+ dwc3_msm_write_reg_field(mdwc->base, DBM_EP_CFG(dbm_ep),
DBM_PRODUCER | DBM_DISABLE_WB | DBM_INT_RAM_ACC, ep_cfg >> 8);
- dwc3_msm_write_reg_field(context->base, DBM_EP_CFG(dbm_ep), USB3_EPNUM,
+ dwc3_msm_write_reg_field(mdwc->base, DBM_EP_CFG(dbm_ep), USB3_EPNUM,
usb_ep);
- dwc3_msm_write_reg_field(context->base, DBM_EP_CFG(dbm_ep),
+ dwc3_msm_write_reg_field(mdwc->base, DBM_EP_CFG(dbm_ep),
DBM_BAM_PIPE_NUM, bam_pipe);
- dwc3_msm_write_reg_field(context->base, DBM_PIPE_CFG, 0x000000ff,
+ dwc3_msm_write_reg_field(mdwc->base, DBM_PIPE_CFG, 0x000000ff,
0xe4);
- dwc3_msm_write_reg_field(context->base, DBM_EP_CFG(dbm_ep), DBM_EN_EP,
+ dwc3_msm_write_reg_field(mdwc->base, DBM_EP_CFG(dbm_ep), DBM_EN_EP,
1);
return dbm_ep;
@@ -572,35 +572,34 @@
* @usb_ep - USB ep number.
*
*/
-static int dwc3_msm_dbm_ep_unconfig(u8 usb_ep)
+static int dwc3_msm_dbm_ep_unconfig(struct dwc3_msm *mdwc, u8 usb_ep)
{
u8 dbm_ep;
u32 data;
- dev_dbg(context->dev, "%s\n", __func__);
+ dev_dbg(mdwc->dev, "%s\n", __func__);
- dbm_ep = dwc3_msm_find_matching_dbm_ep(usb_ep);
+ dbm_ep = dwc3_msm_find_matching_dbm_ep(mdwc, usb_ep);
if (dbm_ep < 0) {
- dev_err(context->dev,
- "%s: Invalid usb ep index\n", __func__);
+ dev_err(mdwc->dev, "%s: Invalid usb ep index\n", __func__);
return -ENODEV;
}
- context->ep_num_mapping[dbm_ep] = 0;
+ mdwc->ep_num_mapping[dbm_ep] = 0;
- data = dwc3_msm_read_reg(context->base, DBM_EP_CFG(dbm_ep));
+ data = dwc3_msm_read_reg(mdwc->base, DBM_EP_CFG(dbm_ep));
data &= (~0x1);
- dwc3_msm_write_reg(context->base, DBM_EP_CFG(dbm_ep), data);
+ dwc3_msm_write_reg(mdwc->base, DBM_EP_CFG(dbm_ep), data);
/* Reset the dbm endpoint */
- dwc3_msm_dbm_ep_soft_reset(dbm_ep, true);
+ dwc3_msm_dbm_ep_soft_reset(mdwc, dbm_ep, true);
/*
* 10 usec delay is required before deasserting DBM endpoint reset
* according to hardware programming guide.
*/
udelay(10);
- dwc3_msm_dbm_ep_soft_reset(dbm_ep, false);
+ dwc3_msm_dbm_ep_soft_reset(mdwc, dbm_ep, false);
return 0;
}
@@ -619,15 +618,17 @@
{
u8 dbm_ep;
struct dwc3_ep *dep = to_dwc3_ep(ep);
+ struct dwc3 *dwc = dep->dwc;
+ struct dwc3_msm *mdwc = dev_get_drvdata(dwc->dev->parent);
u8 bam_pipe = dst_pipe_idx;
- dev_dbg(context->dev, "%s\n", __func__);
+ dev_dbg(mdwc->dev, "%s\n", __func__);
dbm_ep = bam_pipe;
- context->ep_num_mapping[dbm_ep] = dep->number;
+ mdwc->ep_num_mapping[dbm_ep] = dep->number;
- dwc3_msm_write_reg(context->base, DBM_DATA_FIFO(dbm_ep), addr);
- dwc3_msm_write_reg_field(context->base, DBM_DATA_FIFO_SIZE(dbm_ep),
+ dwc3_msm_write_reg(mdwc->base, DBM_DATA_FIFO(dbm_ep), addr);
+ dwc3_msm_write_reg_field(mdwc->base, DBM_DATA_FIFO_SIZE(dbm_ep),
DBM_DATA_FIFO_SIZE_MASK, size);
return 0;
@@ -647,12 +648,12 @@
struct usb_request *request)
{
struct dwc3_ep *dep = to_dwc3_ep(ep);
+ struct dwc3 *dwc = dep->dwc;
+ struct dwc3_msm *mdwc = dev_get_drvdata(dwc->dev->parent);
struct dwc3_msm_req_complete *req_complete = NULL;
/* Find original request complete function and remove it from list */
- list_for_each_entry(req_complete,
- &context->req_complete_list,
- list_item) {
+ list_for_each_entry(req_complete, &mdwc->req_complete_list, list_item) {
if (req_complete->req == request)
break;
}
@@ -671,14 +672,14 @@
dep->busy_slot++;
/* Unconfigure dbm ep */
- dwc3_msm_dbm_ep_unconfig(dep->number);
+ dwc3_msm_dbm_ep_unconfig(mdwc, dep->number);
/*
* If this is the last endpoint we unconfigured, than reset also
* the event buffers.
*/
- if (0 == dwc3_msm_configured_dbm_ep_num())
- dwc3_msm_event_buffer_config(0, 0);
+ if (0 == dwc3_msm_configured_dbm_ep_num(mdwc))
+ dwc3_msm_event_buffer_config(mdwc, 0, 0);
/*
* Call original complete function, notice that dwc->lock is already
@@ -791,6 +792,7 @@
struct dwc3_request *req = to_dwc3_request(request);
struct dwc3_ep *dep = to_dwc3_ep(ep);
struct dwc3 *dwc = dep->dwc;
+ struct dwc3_msm *mdwc = dev_get_drvdata(dwc->dev->parent);
struct dwc3_msm_req_complete *req_complete;
unsigned long flags;
int ret = 0;
@@ -803,23 +805,23 @@
if (!(request->udc_priv & MSM_SPS_MODE)) {
/* Not SPS mode, call original queue */
- dev_vdbg(dwc->dev, "%s: not sps mode, use regular queue\n",
+ dev_vdbg(mdwc->dev, "%s: not sps mode, use regular queue\n",
__func__);
- return (context->original_ep_ops[dep->number])->queue(ep,
+ return (mdwc->original_ep_ops[dep->number])->queue(ep,
request,
gfp_flags);
}
if (!dep->endpoint.desc) {
- dev_err(dwc->dev,
+ dev_err(mdwc->dev,
"%s: trying to queue request %p to disabled ep %s\n",
__func__, request, ep->name);
return -EPERM;
}
if (dep->number == 0 || dep->number == 1) {
- dev_err(dwc->dev,
+ dev_err(mdwc->dev,
"%s: trying to queue dbm request %p to control ep %s\n",
__func__, request, ep->name);
return -EPERM;
@@ -828,7 +830,7 @@
if (dep->busy_slot != dep->free_slot || !list_empty(&dep->request_list)
|| !list_empty(&dep->req_queued)) {
- dev_err(dwc->dev,
+ dev_err(mdwc->dev,
"%s: trying to queue dbm request %p tp ep %s\n",
__func__, request, ep->name);
return -EPERM;
@@ -843,12 +845,12 @@
*/
req_complete = kzalloc(sizeof(*req_complete), GFP_KERNEL);
if (!req_complete) {
- dev_err(dep->dwc->dev, "%s: not enough memory\n", __func__);
+ dev_err(mdwc->dev, "%s: not enough memory\n", __func__);
return -ENOMEM;
}
req_complete->req = request;
req_complete->orig_complete = request->complete;
- list_add_tail(&req_complete->list_item, &context->req_complete_list);
+ list_add_tail(&req_complete->list_item, &mdwc->req_complete_list);
request->complete = dwc3_msm_req_complete_func;
/*
@@ -860,11 +862,11 @@
internal_mem = ((request->udc_priv & MSM_INTERNAL_MEM) ? true : false);
ioc = ((request->udc_priv & MSM_ETD_IOC) ? true : false);
- ret = dwc3_msm_dbm_ep_config(dep->number,
+ ret = dwc3_msm_dbm_ep_config(mdwc, dep->number,
bam_pipe, producer,
disable_wb, internal_mem, ioc);
if (ret < 0) {
- dev_err(context->dev,
+ dev_err(mdwc->dev,
"error %d after calling dwc3_msm_dbm_ep_config\n",
ret);
return ret;
@@ -884,13 +886,13 @@
ret = __dwc3_msm_ep_queue(dep, req);
spin_unlock_irqrestore(&dwc->lock, flags);
if (ret < 0) {
- dev_err(context->dev,
+ dev_err(mdwc->dev,
"error %d after calling __dwc3_msm_ep_queue\n", ret);
return ret;
}
speed = dwc3_readl(dwc->regs, DWC3_DSTS) & DWC3_DSTS_CONNECTSPD;
- dwc3_msm_write_reg(context->base, DBM_GEN_CFG, speed >> 2);
+ dwc3_msm_write_reg(mdwc->base, DBM_GEN_CFG, speed >> 2);
return 0;
}
@@ -912,25 +914,27 @@
int msm_ep_config(struct usb_ep *ep)
{
struct dwc3_ep *dep = to_dwc3_ep(ep);
+ struct dwc3 *dwc = dep->dwc;
+ struct dwc3_msm *mdwc = dev_get_drvdata(dwc->dev->parent);
struct usb_ep_ops *new_ep_ops;
- dwc3_msm_event_buffer_config(dwc3_msm_read_reg(context->base,
- DWC3_GEVNTADRLO(0)),
- dwc3_msm_read_reg(context->base, DWC3_GEVNTSIZ(0)));
+ dwc3_msm_event_buffer_config(mdwc,
+ dwc3_msm_read_reg(mdwc->base, DWC3_GEVNTADRLO(0)),
+ dwc3_msm_read_reg(mdwc->base, DWC3_GEVNTSIZ(0)));
/* Save original ep ops for future restore*/
- if (context->original_ep_ops[dep->number]) {
- dev_err(context->dev,
+ if (mdwc->original_ep_ops[dep->number]) {
+ dev_err(mdwc->dev,
"ep [%s,%d] already configured as msm endpoint\n",
ep->name, dep->number);
return -EPERM;
}
- context->original_ep_ops[dep->number] = ep->ops;
+ mdwc->original_ep_ops[dep->number] = ep->ops;
/* Set new usb ops as we like */
new_ep_ops = kzalloc(sizeof(struct usb_ep_ops), GFP_KERNEL);
if (!new_ep_ops) {
- dev_err(context->dev,
+ dev_err(mdwc->dev,
"%s: unable to allocate mem for new usb ep ops\n",
__func__);
return -ENOMEM;
@@ -962,18 +966,20 @@
int msm_ep_unconfig(struct usb_ep *ep)
{
struct dwc3_ep *dep = to_dwc3_ep(ep);
+ struct dwc3 *dwc = dep->dwc;
+ struct dwc3_msm *mdwc = dev_get_drvdata(dwc->dev->parent);
struct usb_ep_ops *old_ep_ops;
/* Restore original ep ops */
- if (!context->original_ep_ops[dep->number]) {
- dev_err(context->dev,
+ if (!mdwc->original_ep_ops[dep->number]) {
+ dev_err(mdwc->dev,
"ep [%s,%d] was not configured as msm endpoint\n",
ep->name, dep->number);
return -EINVAL;
}
old_ep_ops = (struct usb_ep_ops *)ep->ops;
- ep->ops = context->original_ep_ops[dep->number];
- context->original_ep_ops[dep->number] = NULL;
+ ep->ops = mdwc->original_ep_ops[dep->number];
+ mdwc->original_ep_ops[dep->number] = NULL;
kfree(old_ep_ops);
/*
@@ -1018,14 +1024,16 @@
* This performs full hardware reset and re-initialization which
* might be required by some DBM client driver during uninit/cleanup.
*/
-void msm_dwc3_restart_usb_session(void)
+void msm_dwc3_restart_usb_session(struct usb_gadget *gadget)
{
- struct dwc3_msm *mdwc = context;
+ struct dwc3 *dwc = container_of(gadget, struct dwc3, gadget);
+ struct dwc3_msm *mdwc = dev_get_drvdata(dwc->dev->parent);
+
+ if (mdwc)
+ return;
dev_dbg(mdwc->dev, "%s\n", __func__);
queue_work(system_nrt_wq, &mdwc->restart_usb_work);
-
- return;
}
EXPORT_SYMBOL(msm_dwc3_restart_usb_session);
@@ -1057,10 +1065,9 @@
EXPORT_SYMBOL(msm_register_usb_ext_notification);
/* HSPHY */
-static int dwc3_hsusb_config_vddcx(int high)
+static int dwc3_hsusb_config_vddcx(struct dwc3_msm *dwc, int high)
{
int min_vol, max_vol, ret;
- struct dwc3_msm *dwc = context;
max_vol = dwc->vdd_high_vol_level;
min_vol = high ? dwc->vdd_low_vol_level : dwc->vdd_no_vol_level;
@@ -1076,10 +1083,9 @@
return ret;
}
-static int dwc3_hsusb_ldo_init(int init)
+static int dwc3_hsusb_ldo_init(struct dwc3_msm *dwc, int init)
{
int rc = 0;
- struct dwc3_msm *dwc = context;
if (!init) {
regulator_set_voltage(dwc->hsusb_1p8, 0, USB_HSPHY_1P8_VOL_MAX);
@@ -1120,10 +1126,9 @@
return rc;
}
-static int dwc3_hsusb_ldo_enable(int on)
+static int dwc3_hsusb_ldo_enable(struct dwc3_msm *dwc, int on)
{
int rc = 0;
- struct dwc3_msm *dwc = context;
dev_dbg(dwc->dev, "reg (%s)\n", on ? "HPM" : "LPM");
@@ -1181,10 +1186,9 @@
}
/* SSPHY */
-static int dwc3_ssusb_config_vddcx(int high)
+static int dwc3_ssusb_config_vddcx(struct dwc3_msm *dwc, int high)
{
int min_vol, max_vol, ret;
- struct dwc3_msm *dwc = context;
max_vol = dwc->vdd_high_vol_level;
min_vol = high ? dwc->vdd_low_vol_level : dwc->vdd_no_vol_level;
@@ -1200,10 +1204,9 @@
}
/* 3.3v supply not needed for SS PHY */
-static int dwc3_ssusb_ldo_init(int init)
+static int dwc3_ssusb_ldo_init(struct dwc3_msm *dwc, int init)
{
int rc = 0;
- struct dwc3_msm *dwc = context;
if (!init) {
regulator_set_voltage(dwc->ssusb_1p8, 0, USB_SSPHY_1P8_VOL_MAX);
@@ -1223,12 +1226,11 @@
return rc;
}
-static int dwc3_ssusb_ldo_enable(int on)
+static int dwc3_ssusb_ldo_enable(struct dwc3_msm *dwc, int on)
{
int rc = 0;
- struct dwc3_msm *dwc = context;
- dev_dbg(context->dev, "reg (%s)\n", on ? "HPM" : "LPM");
+ dev_dbg(dwc->dev, "reg (%s)\n", on ? "HPM" : "LPM");
if (!on)
goto disable_regulators;
@@ -1265,37 +1267,36 @@
* Config Global Distributed Switch Controller (GDSC)
* to support controller power collapse
*/
-static int dwc3_msm_config_gdsc(struct dwc3_msm *msm, int on)
+static int dwc3_msm_config_gdsc(struct dwc3_msm *mdwc, int on)
{
int ret = 0;
- if (IS_ERR(msm->dwc3_gdsc))
+ if (IS_ERR(mdwc->dwc3_gdsc))
return 0;
- if (!msm->dwc3_gdsc) {
- msm->dwc3_gdsc = devm_regulator_get(msm->dev,
+ if (!mdwc->dwc3_gdsc) {
+ mdwc->dwc3_gdsc = devm_regulator_get(mdwc->dev,
"USB3_GDSC");
- if (IS_ERR(msm->dwc3_gdsc))
+ if (IS_ERR(mdwc->dwc3_gdsc))
return 0;
}
if (on) {
- ret = regulator_enable(msm->dwc3_gdsc);
+ ret = regulator_enable(mdwc->dwc3_gdsc);
if (ret) {
- dev_err(msm->dev, "unable to enable usb3 gdsc\n");
+ dev_err(mdwc->dev, "unable to enable usb3 gdsc\n");
return ret;
}
} else {
- regulator_disable(msm->dwc3_gdsc);
+ regulator_disable(mdwc->dwc3_gdsc);
}
return 0;
}
-static int dwc3_msm_link_clk_reset(bool assert)
+static int dwc3_msm_link_clk_reset(struct dwc3_msm *mdwc, bool assert)
{
int ret = 0;
- struct dwc3_msm *mdwc = context;
if (assert) {
/* Using asynchronous block reset to the hardware */
@@ -1321,7 +1322,7 @@
}
/* Reinitialize SSPHY parameters by overriding using QSCRATCH CR interface */
-static void dwc3_msm_ss_phy_reg_init(struct dwc3_msm *msm)
+static void dwc3_msm_ss_phy_reg_init(struct dwc3_msm *mdwc)
{
u32 data = 0;
@@ -1330,14 +1331,14 @@
* in HS mode instead of SS mode. Workaround it by asserting
* LANE0.TX_ALT_BLOCK.EN_ALT_BUS to enable TX to use alt bus mode
*/
- data = dwc3_msm_ssusb_read_phycreg(msm->base, 0x102D);
+ data = dwc3_msm_ssusb_read_phycreg(mdwc->base, 0x102D);
data |= (1 << 7);
- dwc3_msm_ssusb_write_phycreg(msm->base, 0x102D, data);
+ dwc3_msm_ssusb_write_phycreg(mdwc->base, 0x102D, data);
- data = dwc3_msm_ssusb_read_phycreg(msm->base, 0x1010);
+ data = dwc3_msm_ssusb_read_phycreg(mdwc->base, 0x1010);
data &= ~0xFF0;
data |= 0x20;
- dwc3_msm_ssusb_write_phycreg(msm->base, 0x1010, data);
+ dwc3_msm_ssusb_write_phycreg(mdwc->base, 0x1010, data);
/*
* Fix RX Equalization setting as follows
@@ -1346,13 +1347,13 @@
* LANE0.RX_OVRD_IN_HI.RX_EQ set to 3
* LANE0.RX_OVRD_IN_HI.RX_EQ_OVRD set to 1
*/
- data = dwc3_msm_ssusb_read_phycreg(msm->base, 0x1006);
+ data = dwc3_msm_ssusb_read_phycreg(mdwc->base, 0x1006);
data &= ~(1 << 6);
data |= (1 << 7);
data &= ~(0x7 << 8);
data |= (0x3 << 8);
data |= (0x1 << 11);
- dwc3_msm_ssusb_write_phycreg(msm->base, 0x1006, data);
+ dwc3_msm_ssusb_write_phycreg(mdwc->base, 0x1006, data);
/*
* Set EQ and TX launch amplitudes as follows
@@ -1360,12 +1361,12 @@
* LANE0.TX_OVRD_DRV_LO.AMPLITUDE set to 127
* LANE0.TX_OVRD_DRV_LO.EN set to 1.
*/
- data = dwc3_msm_ssusb_read_phycreg(msm->base, 0x1002);
+ data = dwc3_msm_ssusb_read_phycreg(mdwc->base, 0x1002);
data &= ~0x3F80;
data |= (0x16 << 7);
data &= ~0x7F;
data |= (0x7F | (1 << 14));
- dwc3_msm_ssusb_write_phycreg(msm->base, 0x1002, data);
+ dwc3_msm_ssusb_write_phycreg(mdwc->base, 0x1002, data);
/*
* Set the QSCRATCH SS_PHY_PARAM_CTRL1 parameters as follows
@@ -1373,73 +1374,73 @@
* TX_DEEMPH_3_5DB [13:8] to 22
* LOS_BIAS [2:0] to 0x5
*/
- dwc3_msm_write_readback(msm->base, SS_PHY_PARAM_CTRL_1,
+ dwc3_msm_write_readback(mdwc->base, SS_PHY_PARAM_CTRL_1,
0x07f03f07, 0x07f01605);
}
/* Initialize QSCRATCH registers for HSPHY and SSPHY operation */
-static void dwc3_msm_qscratch_reg_init(struct dwc3_msm *msm)
+static void dwc3_msm_qscratch_reg_init(struct dwc3_msm *mdwc)
{
/* SSPHY Initialization: Use ref_clk from pads and set its parameters */
- dwc3_msm_write_reg(msm->base, SS_PHY_CTRL_REG, 0x10210002);
+ dwc3_msm_write_reg(mdwc->base, SS_PHY_CTRL_REG, 0x10210002);
msleep(30);
/* Assert SSPHY reset */
- dwc3_msm_write_reg(msm->base, SS_PHY_CTRL_REG, 0x10210082);
+ dwc3_msm_write_reg(mdwc->base, SS_PHY_CTRL_REG, 0x10210082);
usleep_range(2000, 2200);
/* De-assert SSPHY reset - power and ref_clock must be ON */
- dwc3_msm_write_reg(msm->base, SS_PHY_CTRL_REG, 0x10210002);
+ dwc3_msm_write_reg(mdwc->base, SS_PHY_CTRL_REG, 0x10210002);
usleep_range(2000, 2200);
/* Ref clock must be stable now, enable ref clock for HS mode */
- dwc3_msm_write_reg(msm->base, SS_PHY_CTRL_REG, 0x10210102);
+ dwc3_msm_write_reg(mdwc->base, SS_PHY_CTRL_REG, 0x10210102);
usleep_range(2000, 2200);
/*
* HSPHY Initialization: Enable UTMI clock and clamp enable HVINTs,
* and disable RETENTION (power-on default is ENABLED)
*/
- dwc3_msm_write_reg(msm->base, HS_PHY_CTRL_REG, 0x5220bb2);
+ dwc3_msm_write_reg(mdwc->base, HS_PHY_CTRL_REG, 0x5220bb2);
usleep_range(2000, 2200);
/* Disable (bypass) VBUS and ID filters */
- dwc3_msm_write_reg(msm->base, QSCRATCH_GENERAL_CFG, 0x78);
+ dwc3_msm_write_reg(mdwc->base, QSCRATCH_GENERAL_CFG, 0x78);
/*
* write HSPHY init value to QSCRATCH reg to set HSPHY parameters like
* VBUS valid threshold, disconnect valid threshold, DC voltage level,
* preempasis and rise/fall time.
*/
if (override_phy_init)
- msm->hsphy_init_seq = override_phy_init;
- if (msm->hsphy_init_seq)
- dwc3_msm_write_readback(msm->base,
+ mdwc->hsphy_init_seq = override_phy_init;
+ if (mdwc->hsphy_init_seq)
+ dwc3_msm_write_readback(mdwc->base,
PARAMETER_OVERRIDE_X_REG, 0x03FFFFFF,
- msm->hsphy_init_seq & 0x03FFFFFF);
+ mdwc->hsphy_init_seq & 0x03FFFFFF);
/* Enable master clock for RAMs to allow BAM to access RAMs when
* RAM clock gating is enabled via DWC3's GCTL. Otherwise, issues
* are seen where RAM clocks get turned OFF in SS mode
*/
- dwc3_msm_write_reg(msm->base, CGCTL_REG,
- dwc3_msm_read_reg(msm->base, CGCTL_REG) | 0x18);
+ dwc3_msm_write_reg(mdwc->base, CGCTL_REG,
+ dwc3_msm_read_reg(mdwc->base, CGCTL_REG) | 0x18);
- dwc3_msm_ss_phy_reg_init(msm);
+ dwc3_msm_ss_phy_reg_init(mdwc);
/*
* This is required to restore the POR value after userspace
* is done with charger detection.
*/
- msm->qscratch_ctl_val = dwc3_msm_read_reg(msm->base, QSCRATCH_CTRL_REG);
+ mdwc->qscratch_ctl_val =
+ dwc3_msm_read_reg(mdwc->base, QSCRATCH_CTRL_REG);
}
-static void dwc3_msm_block_reset(bool core_reset)
+static void dwc3_msm_block_reset(struct dwc3_ext_xceiv *xceiv, bool core_reset)
{
-
- struct dwc3_msm *mdwc = context;
+ struct dwc3_msm *mdwc = container_of(xceiv, struct dwc3_msm, ext_xceiv);
int ret = 0;
if (core_reset) {
- ret = dwc3_msm_link_clk_reset(1);
+ ret = dwc3_msm_link_clk_reset(mdwc, 1);
if (ret)
return;
usleep_range(1000, 1200);
- ret = dwc3_msm_link_clk_reset(0);
+ ret = dwc3_msm_link_clk_reset(mdwc, 0);
if (ret)
return;
@@ -1450,9 +1451,9 @@
}
/* Reset the DBM */
- dwc3_msm_dbm_soft_reset(1);
+ dwc3_msm_dbm_soft_reset(mdwc, 1);
usleep_range(1000, 1200);
- dwc3_msm_dbm_soft_reset(0);
+ dwc3_msm_dbm_soft_reset(mdwc, 0);
}
static void dwc3_chg_enable_secondary_det(struct dwc3_msm *mdwc)
@@ -1663,7 +1664,7 @@
static void dwc3_start_chg_det(struct dwc3_charger *charger, bool start)
{
- struct dwc3_msm *mdwc = context;
+ struct dwc3_msm *mdwc = container_of(charger, struct dwc3_msm, charger);
if (start == false) {
dev_dbg(mdwc->dev, "canceling charging detection work\n");
@@ -1795,13 +1796,13 @@
if (mdwc->otg_xceiv && mdwc->ext_xceiv.otg_capability && !dcp &&
!host_bus_suspend)
- dwc3_hsusb_ldo_enable(0);
+ dwc3_hsusb_ldo_enable(mdwc, 0);
- dwc3_ssusb_ldo_enable(0);
- dwc3_ssusb_config_vddcx(0);
+ dwc3_ssusb_ldo_enable(mdwc, 0);
+ dwc3_ssusb_config_vddcx(mdwc, 0);
if (!host_bus_suspend && !dcp)
- dwc3_hsusb_config_vddcx(0);
- wake_unlock(&mdwc->wlock);
+ dwc3_hsusb_config_vddcx(mdwc, 0);
+ pm_relax(mdwc->dev);
atomic_set(&mdwc->in_lpm, 1);
dev_info(mdwc->dev, "DWC3 in low power mode\n");
@@ -1829,7 +1830,7 @@
return 0;
}
- wake_lock(&mdwc->wlock);
+ pm_stay_awake(mdwc->dev);
if (mdwc->bus_perf_client) {
ret = msm_bus_scale_client_update_request(
@@ -1860,13 +1861,13 @@
if (mdwc->otg_xceiv && mdwc->ext_xceiv.otg_capability && !dcp &&
!host_bus_suspend)
- dwc3_hsusb_ldo_enable(1);
+ dwc3_hsusb_ldo_enable(mdwc, 1);
- dwc3_ssusb_ldo_enable(1);
- dwc3_ssusb_config_vddcx(1);
+ dwc3_ssusb_ldo_enable(mdwc, 1);
+ dwc3_ssusb_config_vddcx(mdwc, 1);
if (!host_bus_suspend && !dcp)
- dwc3_hsusb_config_vddcx(1);
+ dwc3_hsusb_config_vddcx(mdwc, 1);
clk_prepare_enable(mdwc->ref_clk);
usleep_range(1000, 1200);
@@ -2220,9 +2221,9 @@
static void dwc3_init_adc_work(struct work_struct *w);
-static void dwc3_ext_notify_online(int on)
+static void dwc3_ext_notify_online(void *ctx, int on)
{
- struct dwc3_msm *mdwc = context;
+ struct dwc3_msm *mdwc = ctx;
bool notify_otg = false;
if (!mdwc) {
@@ -2270,7 +2271,7 @@
disable_irq(mdwc->pmic_id_irq);
ret = usb_ext->notify(usb_ext->ctxt, mdwc->id_state,
- dwc3_ext_notify_online);
+ dwc3_ext_notify_online, mdwc);
dev_dbg(mdwc->dev, "%s: external handler returned %d\n",
__func__, ret);
@@ -2366,7 +2367,12 @@
static ssize_t adc_enable_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- return snprintf(buf, PAGE_SIZE, "%s\n", context->id_adc_detect ?
+ struct dwc3_msm *mdwc = dev_get_drvdata(dev);
+
+ if (!mdwc)
+ return -EINVAL;
+
+ return snprintf(buf, PAGE_SIZE, "%s\n", mdwc->id_adc_detect ?
"enabled" : "disabled");
}
@@ -2374,13 +2380,18 @@
struct device_attribute *attr, const char
*buf, size_t size)
{
+ struct dwc3_msm *mdwc = dev_get_drvdata(dev);
+
+ if (!mdwc)
+ return -EINVAL;
+
if (!strnicmp(buf, "enable", 6)) {
- if (!context->id_adc_detect)
- dwc3_init_adc_work(&context->init_adc_work.work);
+ if (!mdwc->id_adc_detect)
+ dwc3_init_adc_work(&mdwc->init_adc_work.work);
return size;
} else if (!strnicmp(buf, "disable", 7)) {
qpnp_adc_tm_usbid_end();
- context->id_adc_detect = false;
+ mdwc->id_adc_detect = false;
return size;
}
@@ -2392,55 +2403,78 @@
static int dwc3_msm_ext_chg_open(struct inode *inode, struct file *file)
{
- struct dwc3_msm *mdwc = context;
+ struct dwc3_msm *mdwc =
+ container_of(inode->i_cdev, struct dwc3_msm, ext_chg_cdev);
pr_debug("dwc3-msm ext chg open\n");
-
+ file->private_data = mdwc;
mdwc->ext_chg_opened = true;
+
return 0;
}
-static ssize_t
-dwc3_msm_ext_chg_write(struct file *file, const char __user *ubuf,
- size_t size, loff_t *pos)
+static long
+dwc3_msm_ext_chg_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
- struct dwc3_msm *mdwc = context;
- char kbuf[16];
+ struct dwc3_msm *mdwc = file->private_data;
+ struct msm_usb_chg_info info = {0};
+ int ret = 0, val;
- memset(kbuf, 0x00, sizeof(kbuf));
- if (copy_from_user(&kbuf, ubuf, min_t(size_t, sizeof(kbuf) - 1, size)))
- return -EFAULT;
+ switch (cmd) {
+ case MSM_USB_EXT_CHG_INFO:
+ info.chg_block_type = USB_CHG_BLOCK_QSCRATCH;
+ info.page_offset = (mdwc->io_res->start +
+ QSCRATCH_REG_OFFSET) & ~PAGE_MASK;
+ /*
+ * The charger block register address space is only
+ * 512 bytes. But mmap() works on PAGE granularity.
+ */
+ info.length = PAGE_SIZE;
- pr_debug("%s: buf = %s\n", __func__, kbuf);
-
- if (!strncmp(kbuf, "enable", 6)) {
- pr_info("%s: on\n", __func__);
- if (mdwc->charger.chg_type == DWC3_DCP_CHARGER) {
- pm_runtime_get_sync(mdwc->dev);
+ if (copy_to_user((void __user *)arg, &info, sizeof(info))) {
+ pr_err("%s: copy to user failed\n\n", __func__);
+ ret = -EFAULT;
+ }
+ break;
+ case MSM_USB_EXT_CHG_BLOCK_LPM:
+ if (get_user(val, (int __user *)arg)) {
+ pr_err("%s: get_user failed\n\n", __func__);
+ ret = -EFAULT;
+ break;
+ }
+ pr_debug("%s: LPM block request %d\n", __func__, val);
+ if (val) { /* block LPM */
+ if (mdwc->charger.chg_type == DWC3_DCP_CHARGER) {
+ pm_runtime_get_sync(mdwc->dev);
+ } else {
+ mdwc->ext_chg_active = false;
+ complete(&mdwc->ext_chg_wait);
+ ret = -ENODEV;
+ }
} else {
mdwc->ext_chg_active = false;
complete(&mdwc->ext_chg_wait);
- return -ENODEV;
+ pm_runtime_put(mdwc->dev);
}
- } else if (!strncmp(kbuf, "disable", 7)) {
- pr_info("%s: off\n", __func__);
- mdwc->ext_chg_active = false;
- complete(&mdwc->ext_chg_wait);
- pm_runtime_put(mdwc->dev);
- } else {
- return -EINVAL;
+ break;
+ default:
+ ret = -EINVAL;
}
- return size;
+ return ret;
}
static int dwc3_msm_ext_chg_mmap(struct file *file, struct vm_area_struct *vma)
{
+ struct dwc3_msm *mdwc = file->private_data;
unsigned long vsize = vma->vm_end - vma->vm_start;
int ret;
- pr_debug("%s: size = %lu %x\n", __func__, vsize, (int) vma->vm_pgoff);
+ if (vma->vm_pgoff != 0 || vsize > PAGE_SIZE)
+ return -EINVAL;
+ vma->vm_pgoff = __phys_to_pfn(mdwc->io_res->start +
+ QSCRATCH_REG_OFFSET);
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
ret = io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
@@ -2453,7 +2487,7 @@
static int dwc3_msm_ext_chg_release(struct inode *inode, struct file *file)
{
- struct dwc3_msm *mdwc = context;
+ struct dwc3_msm *mdwc = file->private_data;
pr_debug("dwc3-msm ext chg release\n");
@@ -2465,7 +2499,7 @@
static const struct file_operations dwc3_msm_ext_chg_fops = {
.owner = THIS_MODULE,
.open = dwc3_msm_ext_chg_open,
- .write = dwc3_msm_ext_chg_write,
+ .unlocked_ioctl = dwc3_msm_ext_chg_ioctl,
.mmap = dwc3_msm_ext_chg_mmap,
.release = dwc3_msm_ext_chg_release,
};
@@ -2518,7 +2552,7 @@
static int __devinit dwc3_msm_probe(struct platform_device *pdev)
{
struct device_node *node = pdev->dev.of_node;
- struct dwc3_msm *msm;
+ struct dwc3_msm *mdwc;
struct resource *res;
void __iomem *tcsr;
unsigned long flags;
@@ -2526,39 +2560,38 @@
int len = 0;
u32 tmp[3];
- msm = devm_kzalloc(&pdev->dev, sizeof(*msm), GFP_KERNEL);
- if (!msm) {
+ mdwc = devm_kzalloc(&pdev->dev, sizeof(*mdwc), GFP_KERNEL);
+ if (!mdwc) {
dev_err(&pdev->dev, "not enough memory\n");
return -ENOMEM;
}
- platform_set_drvdata(pdev, msm);
- context = msm;
- msm->dev = &pdev->dev;
+ platform_set_drvdata(pdev, mdwc);
+ mdwc->dev = &pdev->dev;
- INIT_LIST_HEAD(&msm->req_complete_list);
- INIT_DELAYED_WORK(&msm->chg_work, dwc3_chg_detect_work);
- INIT_DELAYED_WORK(&msm->resume_work, dwc3_resume_work);
- INIT_WORK(&msm->restart_usb_work, dwc3_restart_usb_work);
- INIT_WORK(&msm->id_work, dwc3_id_work);
- INIT_DELAYED_WORK(&msm->init_adc_work, dwc3_init_adc_work);
- init_completion(&msm->ext_chg_wait);
+ INIT_LIST_HEAD(&mdwc->req_complete_list);
+ INIT_DELAYED_WORK(&mdwc->chg_work, dwc3_chg_detect_work);
+ INIT_DELAYED_WORK(&mdwc->resume_work, dwc3_resume_work);
+ INIT_WORK(&mdwc->restart_usb_work, dwc3_restart_usb_work);
+ INIT_WORK(&mdwc->id_work, dwc3_id_work);
+ INIT_DELAYED_WORK(&mdwc->init_adc_work, dwc3_init_adc_work);
+ init_completion(&mdwc->ext_chg_wait);
- ret = dwc3_msm_config_gdsc(msm, 1);
+ ret = dwc3_msm_config_gdsc(mdwc, 1);
if (ret) {
dev_err(&pdev->dev, "unable to configure usb3 gdsc\n");
return ret;
}
- msm->xo_clk = clk_get(&pdev->dev, "xo");
- if (IS_ERR(msm->xo_clk)) {
+ mdwc->xo_clk = clk_get(&pdev->dev, "xo");
+ if (IS_ERR(mdwc->xo_clk)) {
dev_err(&pdev->dev, "%s unable to get TCXO buffer handle\n",
__func__);
- ret = PTR_ERR(msm->xo_clk);
+ ret = PTR_ERR(mdwc->xo_clk);
goto disable_dwc3_gdsc;
}
- ret = clk_prepare_enable(msm->xo_clk);
+ ret = clk_prepare_enable(mdwc->xo_clk);
if (ret) {
dev_err(&pdev->dev, "%s failed to vote for TCXO buffer%d\n",
__func__, ret);
@@ -2569,62 +2602,62 @@
* DWC3 Core requires its CORE CLK (aka master / bus clk) to
* run at 125Mhz in SSUSB mode and >60MHZ for HSUSB mode.
*/
- msm->core_clk = devm_clk_get(&pdev->dev, "core_clk");
- if (IS_ERR(msm->core_clk)) {
+ mdwc->core_clk = devm_clk_get(&pdev->dev, "core_clk");
+ if (IS_ERR(mdwc->core_clk)) {
dev_err(&pdev->dev, "failed to get core_clk\n");
- ret = PTR_ERR(msm->core_clk);
+ ret = PTR_ERR(mdwc->core_clk);
goto disable_xo;
}
- clk_set_rate(msm->core_clk, 125000000);
- clk_prepare_enable(msm->core_clk);
+ clk_set_rate(mdwc->core_clk, 125000000);
+ clk_prepare_enable(mdwc->core_clk);
- msm->iface_clk = devm_clk_get(&pdev->dev, "iface_clk");
- if (IS_ERR(msm->iface_clk)) {
+ mdwc->iface_clk = devm_clk_get(&pdev->dev, "iface_clk");
+ if (IS_ERR(mdwc->iface_clk)) {
dev_err(&pdev->dev, "failed to get iface_clk\n");
- ret = PTR_ERR(msm->iface_clk);
+ ret = PTR_ERR(mdwc->iface_clk);
goto disable_core_clk;
}
- clk_prepare_enable(msm->iface_clk);
+ clk_prepare_enable(mdwc->iface_clk);
- msm->sleep_clk = devm_clk_get(&pdev->dev, "sleep_clk");
- if (IS_ERR(msm->sleep_clk)) {
+ mdwc->sleep_clk = devm_clk_get(&pdev->dev, "sleep_clk");
+ if (IS_ERR(mdwc->sleep_clk)) {
dev_err(&pdev->dev, "failed to get sleep_clk\n");
- ret = PTR_ERR(msm->sleep_clk);
+ ret = PTR_ERR(mdwc->sleep_clk);
goto disable_iface_clk;
}
- clk_prepare_enable(msm->sleep_clk);
+ clk_prepare_enable(mdwc->sleep_clk);
- msm->hsphy_sleep_clk = devm_clk_get(&pdev->dev, "sleep_a_clk");
- if (IS_ERR(msm->hsphy_sleep_clk)) {
+ mdwc->hsphy_sleep_clk = devm_clk_get(&pdev->dev, "sleep_a_clk");
+ if (IS_ERR(mdwc->hsphy_sleep_clk)) {
dev_err(&pdev->dev, "failed to get sleep_a_clk\n");
- ret = PTR_ERR(msm->hsphy_sleep_clk);
+ ret = PTR_ERR(mdwc->hsphy_sleep_clk);
goto disable_sleep_clk;
}
- clk_prepare_enable(msm->hsphy_sleep_clk);
+ clk_prepare_enable(mdwc->hsphy_sleep_clk);
- msm->utmi_clk = devm_clk_get(&pdev->dev, "utmi_clk");
- if (IS_ERR(msm->utmi_clk)) {
+ mdwc->utmi_clk = devm_clk_get(&pdev->dev, "utmi_clk");
+ if (IS_ERR(mdwc->utmi_clk)) {
dev_err(&pdev->dev, "failed to get utmi_clk\n");
- ret = PTR_ERR(msm->utmi_clk);
+ ret = PTR_ERR(mdwc->utmi_clk);
goto disable_sleep_a_clk;
}
- clk_prepare_enable(msm->utmi_clk);
+ clk_prepare_enable(mdwc->utmi_clk);
- msm->ref_clk = devm_clk_get(&pdev->dev, "ref_clk");
- if (IS_ERR(msm->ref_clk)) {
+ mdwc->ref_clk = devm_clk_get(&pdev->dev, "ref_clk");
+ if (IS_ERR(mdwc->ref_clk)) {
dev_err(&pdev->dev, "failed to get ref_clk\n");
- ret = PTR_ERR(msm->ref_clk);
+ ret = PTR_ERR(mdwc->ref_clk);
goto disable_utmi_clk;
}
- clk_prepare_enable(msm->ref_clk);
+ clk_prepare_enable(mdwc->ref_clk);
of_get_property(node, "qcom,vdd-voltage-level", &len);
if (len == sizeof(tmp)) {
of_property_read_u32_array(node, "qcom,vdd-voltage-level",
tmp, len/sizeof(*tmp));
- msm->vdd_no_vol_level = tmp[0];
- msm->vdd_low_vol_level = tmp[1];
- msm->vdd_high_vol_level = tmp[2];
+ mdwc->vdd_no_vol_level = tmp[0];
+ mdwc->vdd_low_vol_level = tmp[1];
+ mdwc->vdd_high_vol_level = tmp[2];
} else {
dev_err(&pdev->dev, "no qcom,vdd-voltage-level property\n");
ret = -EINVAL;
@@ -2632,99 +2665,100 @@
}
/* SS PHY */
- msm->ssusb_vddcx = devm_regulator_get(&pdev->dev, "ssusb_vdd_dig");
- if (IS_ERR(msm->ssusb_vddcx)) {
+ mdwc->ssusb_vddcx = devm_regulator_get(&pdev->dev, "ssusb_vdd_dig");
+ if (IS_ERR(mdwc->ssusb_vddcx)) {
dev_err(&pdev->dev, "unable to get ssusb vddcx\n");
- ret = PTR_ERR(msm->ssusb_vddcx);
+ ret = PTR_ERR(mdwc->ssusb_vddcx);
goto disable_ref_clk;
}
- ret = dwc3_ssusb_config_vddcx(1);
+ ret = dwc3_ssusb_config_vddcx(mdwc, 1);
if (ret) {
dev_err(&pdev->dev, "ssusb vddcx configuration failed\n");
goto disable_ref_clk;
}
- ret = regulator_enable(context->ssusb_vddcx);
+ ret = regulator_enable(mdwc->ssusb_vddcx);
if (ret) {
dev_err(&pdev->dev, "unable to enable the ssusb vddcx\n");
goto unconfig_ss_vddcx;
}
- ret = dwc3_ssusb_ldo_init(1);
+ ret = dwc3_ssusb_ldo_init(mdwc, 1);
if (ret) {
dev_err(&pdev->dev, "ssusb vreg configuration failed\n");
goto disable_ss_vddcx;
}
- ret = dwc3_ssusb_ldo_enable(1);
+ ret = dwc3_ssusb_ldo_enable(mdwc, 1);
if (ret) {
dev_err(&pdev->dev, "ssusb vreg enable failed\n");
goto free_ss_ldo_init;
}
/* HS PHY */
- msm->hsusb_vddcx = devm_regulator_get(&pdev->dev, "hsusb_vdd_dig");
- if (IS_ERR(msm->hsusb_vddcx)) {
+ mdwc->hsusb_vddcx = devm_regulator_get(&pdev->dev, "hsusb_vdd_dig");
+ if (IS_ERR(mdwc->hsusb_vddcx)) {
dev_err(&pdev->dev, "unable to get hsusb vddcx\n");
- ret = PTR_ERR(msm->hsusb_vddcx);
+ ret = PTR_ERR(mdwc->hsusb_vddcx);
goto disable_ss_ldo;
}
- ret = dwc3_hsusb_config_vddcx(1);
+ ret = dwc3_hsusb_config_vddcx(mdwc, 1);
if (ret) {
dev_err(&pdev->dev, "hsusb vddcx configuration failed\n");
goto disable_ss_ldo;
}
- ret = regulator_enable(context->hsusb_vddcx);
+ ret = regulator_enable(mdwc->hsusb_vddcx);
if (ret) {
dev_err(&pdev->dev, "unable to enable the hsusb vddcx\n");
goto unconfig_hs_vddcx;
}
- ret = dwc3_hsusb_ldo_init(1);
+ ret = dwc3_hsusb_ldo_init(mdwc, 1);
if (ret) {
dev_err(&pdev->dev, "hsusb vreg configuration failed\n");
goto disable_hs_vddcx;
}
- ret = dwc3_hsusb_ldo_enable(1);
+ ret = dwc3_hsusb_ldo_enable(mdwc, 1);
if (ret) {
dev_err(&pdev->dev, "hsusb vreg enable failed\n");
goto free_hs_ldo_init;
}
- msm->id_state = msm->ext_xceiv.id = DWC3_ID_FLOAT;
- msm->ext_xceiv.otg_capability = of_property_read_bool(node,
+ mdwc->id_state = mdwc->ext_xceiv.id = DWC3_ID_FLOAT;
+ mdwc->ext_xceiv.otg_capability = of_property_read_bool(node,
"qcom,otg-capability");
- msm->charger.charging_disabled = of_property_read_bool(node,
+ mdwc->charger.charging_disabled = of_property_read_bool(node,
"qcom,charging-disabled");
- msm->charger.skip_chg_detect = of_property_read_bool(node,
+ mdwc->charger.skip_chg_detect = of_property_read_bool(node,
"qcom,skip-charger-detection");
/*
* DWC3 has separate IRQ line for OTG events (ID/BSV) and for
* DP and DM linestate transitions during low power mode.
*/
- msm->hs_phy_irq = platform_get_irq_byname(pdev, "hs_phy_irq");
- if (msm->hs_phy_irq < 0) {
+ mdwc->hs_phy_irq = platform_get_irq_byname(pdev, "hs_phy_irq");
+ if (mdwc->hs_phy_irq < 0) {
dev_dbg(&pdev->dev, "pget_irq for hs_phy_irq failed\n");
- msm->hs_phy_irq = 0;
+ mdwc->hs_phy_irq = 0;
} else {
- ret = devm_request_irq(&pdev->dev, msm->hs_phy_irq,
+ ret = devm_request_irq(&pdev->dev, mdwc->hs_phy_irq,
msm_dwc3_irq, IRQF_TRIGGER_RISING,
- "msm_dwc3", msm);
+ "msm_dwc3", mdwc);
if (ret) {
dev_err(&pdev->dev, "irqreq HSPHYINT failed\n");
goto disable_hs_ldo;
}
- enable_irq_wake(msm->hs_phy_irq);
+ enable_irq_wake(mdwc->hs_phy_irq);
}
- if (msm->ext_xceiv.otg_capability) {
- msm->pmic_id_irq = platform_get_irq_byname(pdev, "pmic_id_irq");
- if (msm->pmic_id_irq > 0) {
+ if (mdwc->ext_xceiv.otg_capability) {
+ mdwc->pmic_id_irq =
+ platform_get_irq_byname(pdev, "pmic_id_irq");
+ if (mdwc->pmic_id_irq > 0) {
/* check if PMIC ID IRQ is supported */
ret = qpnp_misc_irqs_available(&pdev->dev);
@@ -2732,14 +2766,15 @@
/* qpnp hasn't probed yet; defer dwc probe */
goto disable_hs_ldo;
} else if (ret == 0) {
- msm->pmic_id_irq = 0;
+ mdwc->pmic_id_irq = 0;
} else {
ret = devm_request_irq(&pdev->dev,
- msm->pmic_id_irq,
+ mdwc->pmic_id_irq,
dwc3_pmic_id_irq,
IRQF_TRIGGER_RISING |
IRQF_TRIGGER_FALLING,
- "dwc3_msm_pmic_id", msm);
+ "dwc3_msm_pmic_id",
+ mdwc);
if (ret) {
dev_err(&pdev->dev, "irqreq IDINT failed\n");
goto disable_hs_ldo;
@@ -2747,21 +2782,21 @@
local_irq_save(flags);
/* Update initial ID state */
- msm->id_state =
- !!irq_read_line(msm->pmic_id_irq);
- if (msm->id_state == DWC3_ID_GROUND)
+ mdwc->id_state =
+ !!irq_read_line(mdwc->pmic_id_irq);
+ if (mdwc->id_state == DWC3_ID_GROUND)
queue_work(system_nrt_wq,
- &msm->id_work);
+ &mdwc->id_work);
local_irq_restore(flags);
- enable_irq_wake(msm->pmic_id_irq);
+ enable_irq_wake(mdwc->pmic_id_irq);
}
}
- if (msm->pmic_id_irq <= 0) {
+ if (mdwc->pmic_id_irq <= 0) {
/* If no PMIC ID IRQ, use ADC for ID pin detection */
- queue_work(system_nrt_wq, &msm->init_adc_work.work);
+ queue_work(system_nrt_wq, &mdwc->init_adc_work.work);
device_create_file(&pdev->dev, &dev_attr_adc_enable);
- msm->pmic_id_irq = 0;
+ mdwc->pmic_id_irq = 0;
}
}
@@ -2791,59 +2826,60 @@
goto disable_hs_ldo;
}
- msm->base = devm_ioremap_nocache(&pdev->dev, res->start,
+ mdwc->base = devm_ioremap_nocache(&pdev->dev, res->start,
resource_size(res));
- if (!msm->base) {
+ if (!mdwc->base) {
dev_err(&pdev->dev, "ioremap failed\n");
ret = -ENODEV;
goto disable_hs_ldo;
}
- msm->resource_size = resource_size(res);
+ mdwc->io_res = res; /* used to calculate chg block offset */
if (of_property_read_u32(node, "qcom,dwc-hsphy-init",
- &msm->hsphy_init_seq))
+ &mdwc->hsphy_init_seq))
dev_dbg(&pdev->dev, "unable to read hsphy init seq\n");
- else if (!msm->hsphy_init_seq)
+ else if (!mdwc->hsphy_init_seq)
dev_warn(&pdev->dev, "incorrect hsphyinitseq.Using PORvalue\n");
- dwc3_msm_qscratch_reg_init(msm);
+ dwc3_msm_qscratch_reg_init(mdwc);
- pm_runtime_set_active(msm->dev);
- pm_runtime_enable(msm->dev);
+ pm_runtime_set_active(mdwc->dev);
+ pm_runtime_enable(mdwc->dev);
if (of_property_read_u32(node, "qcom,dwc-usb3-msm-dbm-eps",
- &msm->dbm_num_eps)) {
+ &mdwc->dbm_num_eps)) {
dev_err(&pdev->dev,
"unable to read platform data num of dbm eps\n");
- msm->dbm_num_eps = DBM_MAX_EPS;
+ mdwc->dbm_num_eps = DBM_MAX_EPS;
}
- if (msm->dbm_num_eps > DBM_MAX_EPS) {
+ if (mdwc->dbm_num_eps > DBM_MAX_EPS) {
dev_err(&pdev->dev,
"Driver doesn't support number of DBM EPs. "
"max: %d, dbm_num_eps: %d\n",
- DBM_MAX_EPS, msm->dbm_num_eps);
+ DBM_MAX_EPS, mdwc->dbm_num_eps);
ret = -ENODEV;
goto disable_hs_ldo;
}
/* usb_psy required only for vbus_notifications or charging support */
- if (msm->ext_xceiv.otg_capability || !msm->charger.charging_disabled) {
- msm->usb_psy.name = "usb";
- msm->usb_psy.type = POWER_SUPPLY_TYPE_USB;
- msm->usb_psy.supplied_to = dwc3_msm_pm_power_supplied_to;
- msm->usb_psy.num_supplicants = ARRAY_SIZE(
+ if (mdwc->ext_xceiv.otg_capability ||
+ !mdwc->charger.charging_disabled) {
+ mdwc->usb_psy.name = "usb";
+ mdwc->usb_psy.type = POWER_SUPPLY_TYPE_USB;
+ mdwc->usb_psy.supplied_to = dwc3_msm_pm_power_supplied_to;
+ mdwc->usb_psy.num_supplicants = ARRAY_SIZE(
dwc3_msm_pm_power_supplied_to);
- msm->usb_psy.properties = dwc3_msm_pm_power_props_usb;
- msm->usb_psy.num_properties =
+ mdwc->usb_psy.properties = dwc3_msm_pm_power_props_usb;
+ mdwc->usb_psy.num_properties =
ARRAY_SIZE(dwc3_msm_pm_power_props_usb);
- msm->usb_psy.get_property = dwc3_msm_power_get_property_usb;
- msm->usb_psy.set_property = dwc3_msm_power_set_property_usb;
- msm->usb_psy.external_power_changed =
+ mdwc->usb_psy.get_property = dwc3_msm_power_get_property_usb;
+ mdwc->usb_psy.set_property = dwc3_msm_power_set_property_usb;
+ mdwc->usb_psy.external_power_changed =
dwc3_msm_external_power_changed;
- ret = power_supply_register(&pdev->dev, &msm->usb_psy);
+ ret = power_supply_register(&pdev->dev, &mdwc->usb_psy);
if (ret < 0) {
dev_err(&pdev->dev,
"%s:power_supply_register usb failed\n",
@@ -2861,27 +2897,28 @@
}
}
- msm->bus_scale_table = msm_bus_cl_get_pdata(pdev);
- if (!msm->bus_scale_table) {
+ mdwc->bus_scale_table = msm_bus_cl_get_pdata(pdev);
+ if (!mdwc->bus_scale_table) {
dev_err(&pdev->dev, "bus scaling is disabled\n");
} else {
- msm->bus_perf_client =
- msm_bus_scale_register_client(msm->bus_scale_table);
+ mdwc->bus_perf_client =
+ msm_bus_scale_register_client(mdwc->bus_scale_table);
ret = msm_bus_scale_client_update_request(
- msm->bus_perf_client, 1);
+ mdwc->bus_perf_client, 1);
if (ret)
dev_err(&pdev->dev, "Failed to vote for bus scaling\n");
}
- msm->otg_xceiv = usb_get_transceiver();
+ mdwc->otg_xceiv = usb_get_transceiver();
/* Register with OTG if present, ignore USB2 OTG using other PHY */
- if (msm->otg_xceiv && !(msm->otg_xceiv->flags & ENABLE_SECONDARY_PHY)) {
+ if (mdwc->otg_xceiv &&
+ !(mdwc->otg_xceiv->flags & ENABLE_SECONDARY_PHY)) {
/* Skip charger detection for simulator targets */
- if (!msm->charger.skip_chg_detect) {
- msm->charger.start_detection = dwc3_start_chg_det;
- ret = dwc3_set_charger(msm->otg_xceiv->otg,
- &msm->charger);
- if (ret || !msm->charger.notify_detection_complete) {
+ if (!mdwc->charger.skip_chg_detect) {
+ mdwc->charger.start_detection = dwc3_start_chg_det;
+ ret = dwc3_set_charger(mdwc->otg_xceiv->otg,
+ &mdwc->charger);
+ if (ret || !mdwc->charger.notify_detection_complete) {
dev_err(&pdev->dev,
"failed to register charger: %d\n",
ret);
@@ -2889,129 +2926,130 @@
}
}
- if (msm->ext_xceiv.otg_capability)
- msm->ext_xceiv.ext_block_reset = dwc3_msm_block_reset;
- ret = dwc3_set_ext_xceiv(msm->otg_xceiv->otg, &msm->ext_xceiv);
- if (ret || !msm->ext_xceiv.notify_ext_events) {
+ if (mdwc->ext_xceiv.otg_capability)
+ mdwc->ext_xceiv.ext_block_reset = dwc3_msm_block_reset;
+ ret = dwc3_set_ext_xceiv(mdwc->otg_xceiv->otg,
+ &mdwc->ext_xceiv);
+ if (ret || !mdwc->ext_xceiv.notify_ext_events) {
dev_err(&pdev->dev, "failed to register xceiver: %d\n",
ret);
goto put_xcvr;
}
} else {
dev_dbg(&pdev->dev, "No OTG, DWC3 running in host only mode\n");
- msm->host_mode = 1;
- msm->vbus_otg = devm_regulator_get(&pdev->dev, "vbus_dwc3");
- if (IS_ERR(msm->vbus_otg)) {
+ mdwc->host_mode = 1;
+ mdwc->vbus_otg = devm_regulator_get(&pdev->dev, "vbus_dwc3");
+ if (IS_ERR(mdwc->vbus_otg)) {
dev_dbg(&pdev->dev, "Failed to get vbus regulator\n");
- msm->vbus_otg = 0;
+ mdwc->vbus_otg = 0;
} else {
- ret = regulator_enable(msm->vbus_otg);
+ ret = regulator_enable(mdwc->vbus_otg);
if (ret) {
- msm->vbus_otg = 0;
+ mdwc->vbus_otg = 0;
dev_err(&pdev->dev, "Failed to enable vbus_otg\n");
}
}
- msm->otg_xceiv = NULL;
+ mdwc->otg_xceiv = NULL;
}
- if (msm->ext_xceiv.otg_capability && msm->charger.start_detection) {
- ret = dwc3_msm_setup_cdev(msm);
+ if (mdwc->ext_xceiv.otg_capability && mdwc->charger.start_detection) {
+ ret = dwc3_msm_setup_cdev(mdwc);
if (ret)
dev_err(&pdev->dev, "Fail to setup dwc3 setup cdev\n");
}
- wake_lock_init(&msm->wlock, WAKE_LOCK_SUSPEND, "msm_dwc3");
- wake_lock(&msm->wlock);
- dwc3_debugfs_init(msm);
+ device_init_wakeup(mdwc->dev, 1);
+ pm_stay_awake(mdwc->dev);
+ dwc3_debugfs_init(mdwc);
return 0;
put_xcvr:
- usb_put_transceiver(msm->otg_xceiv);
+ usb_put_transceiver(mdwc->otg_xceiv);
put_psupply:
- if (msm->usb_psy.dev)
- power_supply_unregister(&msm->usb_psy);
+ if (mdwc->usb_psy.dev)
+ power_supply_unregister(&mdwc->usb_psy);
disable_hs_ldo:
- dwc3_hsusb_ldo_enable(0);
+ dwc3_hsusb_ldo_enable(mdwc, 0);
free_hs_ldo_init:
- dwc3_hsusb_ldo_init(0);
+ dwc3_hsusb_ldo_init(mdwc, 0);
disable_hs_vddcx:
- regulator_disable(context->hsusb_vddcx);
+ regulator_disable(mdwc->hsusb_vddcx);
unconfig_hs_vddcx:
- dwc3_hsusb_config_vddcx(0);
+ dwc3_hsusb_config_vddcx(mdwc, 0);
disable_ss_ldo:
- dwc3_ssusb_ldo_enable(0);
+ dwc3_ssusb_ldo_enable(mdwc, 0);
free_ss_ldo_init:
- dwc3_ssusb_ldo_init(0);
+ dwc3_ssusb_ldo_init(mdwc, 0);
disable_ss_vddcx:
- regulator_disable(context->ssusb_vddcx);
+ regulator_disable(mdwc->ssusb_vddcx);
unconfig_ss_vddcx:
- dwc3_ssusb_config_vddcx(0);
+ dwc3_ssusb_config_vddcx(mdwc, 0);
disable_ref_clk:
- clk_disable_unprepare(msm->ref_clk);
+ clk_disable_unprepare(mdwc->ref_clk);
disable_utmi_clk:
- clk_disable_unprepare(msm->utmi_clk);
+ clk_disable_unprepare(mdwc->utmi_clk);
disable_sleep_a_clk:
- clk_disable_unprepare(msm->hsphy_sleep_clk);
+ clk_disable_unprepare(mdwc->hsphy_sleep_clk);
disable_sleep_clk:
- clk_disable_unprepare(msm->sleep_clk);
+ clk_disable_unprepare(mdwc->sleep_clk);
disable_iface_clk:
- clk_disable_unprepare(msm->iface_clk);
+ clk_disable_unprepare(mdwc->iface_clk);
disable_core_clk:
- clk_disable_unprepare(msm->core_clk);
+ clk_disable_unprepare(mdwc->core_clk);
disable_xo:
- clk_disable_unprepare(msm->xo_clk);
+ clk_disable_unprepare(mdwc->xo_clk);
put_xo:
- clk_put(msm->xo_clk);
+ clk_put(mdwc->xo_clk);
disable_dwc3_gdsc:
- dwc3_msm_config_gdsc(msm, 0);
+ dwc3_msm_config_gdsc(mdwc, 0);
return ret;
}
static int __devexit dwc3_msm_remove(struct platform_device *pdev)
{
- struct dwc3_msm *msm = platform_get_drvdata(pdev);
+ struct dwc3_msm *mdwc = platform_get_drvdata(pdev);
- if (!msm->ext_chg_device) {
- device_destroy(msm->ext_chg_class, msm->ext_chg_dev);
- cdev_del(&msm->ext_chg_cdev);
- class_destroy(msm->ext_chg_class);
- unregister_chrdev_region(msm->ext_chg_dev, 1);
+ if (!mdwc->ext_chg_device) {
+ device_destroy(mdwc->ext_chg_class, mdwc->ext_chg_dev);
+ cdev_del(&mdwc->ext_chg_cdev);
+ class_destroy(mdwc->ext_chg_class);
+ unregister_chrdev_region(mdwc->ext_chg_dev, 1);
}
- if (msm->id_adc_detect)
+ if (mdwc->id_adc_detect)
qpnp_adc_tm_usbid_end();
if (dwc3_debugfs_root)
debugfs_remove_recursive(dwc3_debugfs_root);
- if (msm->otg_xceiv) {
- dwc3_start_chg_det(&msm->charger, false);
- usb_put_transceiver(msm->otg_xceiv);
+ if (mdwc->otg_xceiv) {
+ dwc3_start_chg_det(&mdwc->charger, false);
+ usb_put_transceiver(mdwc->otg_xceiv);
}
- if (msm->usb_psy.dev)
- power_supply_unregister(&msm->usb_psy);
- if (msm->vbus_otg)
- regulator_disable(msm->vbus_otg);
+ if (mdwc->usb_psy.dev)
+ power_supply_unregister(&mdwc->usb_psy);
+ if (mdwc->vbus_otg)
+ regulator_disable(mdwc->vbus_otg);
- pm_runtime_disable(msm->dev);
- wake_lock_destroy(&msm->wlock);
+ pm_runtime_disable(mdwc->dev);
+ device_init_wakeup(mdwc->dev, 0);
- dwc3_hsusb_ldo_enable(0);
- dwc3_hsusb_ldo_init(0);
- regulator_disable(msm->hsusb_vddcx);
- dwc3_hsusb_config_vddcx(0);
- dwc3_ssusb_ldo_enable(0);
- dwc3_ssusb_ldo_init(0);
- regulator_disable(msm->ssusb_vddcx);
- dwc3_ssusb_config_vddcx(0);
- clk_disable_unprepare(msm->core_clk);
- clk_disable_unprepare(msm->iface_clk);
- clk_disable_unprepare(msm->sleep_clk);
- clk_disable_unprepare(msm->hsphy_sleep_clk);
- clk_disable_unprepare(msm->ref_clk);
- clk_disable_unprepare(msm->xo_clk);
- clk_put(msm->xo_clk);
+ dwc3_hsusb_ldo_enable(mdwc, 0);
+ dwc3_hsusb_ldo_init(mdwc, 0);
+ regulator_disable(mdwc->hsusb_vddcx);
+ dwc3_hsusb_config_vddcx(mdwc, 0);
+ dwc3_ssusb_ldo_enable(mdwc, 0);
+ dwc3_ssusb_ldo_init(mdwc, 0);
+ regulator_disable(mdwc->ssusb_vddcx);
+ dwc3_ssusb_config_vddcx(mdwc, 0);
+ clk_disable_unprepare(mdwc->core_clk);
+ clk_disable_unprepare(mdwc->iface_clk);
+ clk_disable_unprepare(mdwc->sleep_clk);
+ clk_disable_unprepare(mdwc->hsphy_sleep_clk);
+ clk_disable_unprepare(mdwc->ref_clk);
+ clk_disable_unprepare(mdwc->xo_clk);
+ clk_put(mdwc->xo_clk);
- dwc3_msm_config_gdsc(msm, 0);
+ dwc3_msm_config_gdsc(mdwc, 0);
return 0;
}
diff --git a/drivers/usb/dwc3/dwc3_otg.c b/drivers/usb/dwc3/dwc3_otg.c
index 1bc7757..a7bea63 100644
--- a/drivers/usb/dwc3/dwc3_otg.c
+++ b/drivers/usb/dwc3/dwc3_otg.c
@@ -218,7 +218,7 @@
*/
if (ext_xceiv && ext_xceiv->otg_capability &&
ext_xceiv->ext_block_reset)
- ext_xceiv->ext_block_reset(true);
+ ext_xceiv->ext_block_reset(ext_xceiv, true);
dwc3_otg_set_peripheral_regs(dotg);
@@ -285,7 +285,7 @@
* DBM reset is required, hence perform only DBM reset here */
if (ext_xceiv && ext_xceiv->otg_capability &&
ext_xceiv->ext_block_reset)
- ext_xceiv->ext_block_reset(false);
+ ext_xceiv->ext_block_reset(ext_xceiv, false);
dwc3_otg_set_peripheral_regs(dotg);
usb_gadget_vbus_connect(otg->gadget);
diff --git a/drivers/usb/dwc3/dwc3_otg.h b/drivers/usb/dwc3/dwc3_otg.h
index 28573a1..7adf874 100644
--- a/drivers/usb/dwc3/dwc3_otg.h
+++ b/drivers/usb/dwc3/dwc3_otg.h
@@ -114,7 +114,8 @@
void (*notify_ext_events)(struct usb_otg *otg,
enum dwc3_ext_events ext_event);
/* for block reset USB core */
- void (*ext_block_reset)(bool core_reset);
+ void (*ext_block_reset)(struct dwc3_ext_xceiv *ext_xceiv,
+ bool core_reset);
};
/* for external transceiver driver */
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index e7074a2..3f8d924 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -1853,6 +1853,14 @@
spin_lock_irqsave(mep->lock, flags);
+
+ if (_udc && (!_udc->vbus_active || _udc->suspended)) {
+ pr_debug("ep%d%s prime timer when vbus_active=%d,suspend=%d\n",
+ mep->num, mep->dir ? "IN" : "OUT",
+ _udc->vbus_active, _udc->suspended);
+ goto out;
+ }
+
if (!hw_cread(CAP_ENDPTPRIME, BIT(n)))
goto out;
@@ -2197,6 +2205,9 @@
if (mEp == NULL)
return -EINVAL;
+ del_timer(&mEp->prime_timer);
+ mEp->prime_timer_count = 0;
+
hw_ep_flush(mEp->num, mEp->dir);
while (!list_empty(&mEp->qh.queue)) {
@@ -2926,8 +2937,6 @@
/* only internal SW should disable ctrl endpts */
- del_timer(&mEp->prime_timer);
- mEp->prime_timer_count = 0;
direction = mEp->dir;
do {
dbg_event(_usb_addr(mEp), "DISABLE", 0);
@@ -3282,8 +3291,6 @@
spin_lock_irqsave(mEp->lock, flags);
- del_timer(&mEp->prime_timer);
- mEp->prime_timer_count = 0;
dbg_event(_usb_addr(mEp), "FFLUSH", 0);
/*
* _ep_nuke() takes care of flushing the endpoint.
diff --git a/drivers/usb/gadget/f_diag.c b/drivers/usb/gadget/f_diag.c
index 3355e19..d1b911a 100644
--- a/drivers/usb/gadget/f_diag.c
+++ b/drivers/usb/gadget/f_diag.c
@@ -642,6 +642,8 @@
if (ctxt->ch && ctxt->ch->priv_usb == ctxt)
ctxt->ch->priv_usb = NULL;
list_del(&ctxt->list_item);
+ /* Free any pending USB requests from last session */
+ free_reqs(ctxt);
kfree(ctxt);
}
diff --git a/drivers/usb/gadget/f_qdss.c b/drivers/usb/gadget/f_qdss.c
index cece500..f90967f 100644
--- a/drivers/usb/gadget/f_qdss.c
+++ b/drivers/usb/gadget/f_qdss.c
@@ -790,6 +790,7 @@
void usb_qdss_close(struct usb_qdss_ch *ch)
{
struct f_qdss *qdss = ch->priv_usb;
+ struct usb_gadget *gadget = qdss->cdev->gadget;
unsigned long flags;
pr_debug("usb_qdss_close\n");
@@ -801,7 +802,7 @@
ch->app_conn = 0;
spin_unlock_irqrestore(&d_lock, flags);
- msm_dwc3_restart_usb_session();
+ msm_dwc3_restart_usb_session(gadget);
}
EXPORT_SYMBOL(usb_qdss_close);
diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c
index 823229b..8b1f3a8 100644
--- a/drivers/usb/host/ehci-msm.c
+++ b/drivers/usb/host/ehci-msm.c
@@ -48,7 +48,7 @@
return retval;
/* bursts of unspecified length. */
- writel(0, USB_AHBBURST);
+ writel_relaxed(0, USB_AHBBURST);
/* Use the AHB transactor */
writel_relaxed(0x08, USB_AHBMODE);
/* Disable streaming mode and select host mode */
@@ -60,6 +60,10 @@
USB_PHY_CTRL2);
}
+ /* Disable ULPI_TX_PKT_EN_CLR_FIX which is valid only for HSIC */
+ writel_relaxed(readl_relaxed(USB_GENCONFIG2) & ~(1<<19),
+ USB_GENCONFIG2);
+
ehci_port_power(ehci, 1);
return 0;
}
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index eb65509..fa1932b 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -36,6 +36,7 @@
#include <linux/usb/quirks.h>
#include <linux/usb/msm_hsusb.h>
#include <linux/usb/msm_hsusb_hw.h>
+#include <linux/usb/msm_ext_chg.h>
#include <linux/regulator/consumer.h>
#include <linux/mfd/pm8xxx/pm8921-charger.h>
#include <linux/mfd/pm8xxx/misc.h>
@@ -888,7 +889,7 @@
bool floated_charger;
u32 phy_ctrl_val = 0, cmd_val;
unsigned ret;
- u32 portsc;
+ u32 portsc, config2;
if (atomic_read(&motg->in_lpm))
return 0;
@@ -906,6 +907,17 @@
prop_charger = motg->chg_type == USB_PROPRIETARY_CHARGER;
floated_charger = motg->chg_type == USB_FLOATED_CHARGER;
+ /* Enable line state difference wakeup fix for only device and host
+ * bus suspend scenarios. Otherwise PHY can not be suspended when
+ * a charger that pulls DP/DM high is connected.
+ */
+ config2 = readl_relaxed(USB_GENCONFIG2);
+ if (device_bus_suspend)
+ config2 |= GENCFG2_LINESTATE_DIFF_WAKEUP_EN;
+ else
+ config2 &= ~GENCFG2_LINESTATE_DIFF_WAKEUP_EN;
+ writel_relaxed(config2, USB_GENCONFIG2);
+
/*
* Abort suspend when,
* 1. charging detection in progress due to cable plug-in
@@ -2207,6 +2219,8 @@
/* Clear alt interrupt latch and enable bits */
ulpi_write(phy, 0x1F, 0x92);
ulpi_write(phy, 0x1F, 0x95);
+ /* re-enable DP and DM pull down resistors */
+ ulpi_write(phy, 0x6, 0xB);
break;
default:
break;
@@ -2448,11 +2462,46 @@
}
}
+static void msm_otg_wait_for_ext_chg_done(struct msm_otg *motg)
+{
+ struct usb_phy *phy = &motg->phy;
+ unsigned long t;
+
+ /*
+ * Defer next cable connect event till external charger
+ * detection is completed.
+ */
+
+ if (motg->ext_chg_active) {
+
+ pr_debug("before msm_otg ext chg wait\n");
+
+ t = wait_for_completion_timeout(&motg->ext_chg_wait,
+ msecs_to_jiffies(3000));
+ if (!t)
+ pr_err("msm_otg ext chg wait timeout\n");
+ else
+ pr_debug("msm_otg ext chg wait done\n");
+ }
+
+ if (motg->ext_chg_opened) {
+ if (phy->flags & ENABLE_DP_MANUAL_PULLUP) {
+ ulpi_write(phy, ULPI_MISC_A_VBUSVLDEXT |
+ ULPI_MISC_A_VBUSVLDEXTSEL,
+ ULPI_CLR(ULPI_MISC_A));
+ }
+ /* clear charging register bits */
+ ulpi_write(phy, 0x3F, 0x86);
+ /* re-enable DP and DM pull-down resistors*/
+ ulpi_write(phy, 0x6, 0xB);
+ }
+}
+
static void msm_otg_sm_work(struct work_struct *w)
{
struct msm_otg *motg = container_of(w, struct msm_otg, sm_work);
struct usb_otg *otg = motg->phy.otg;
- bool work = 0, srp_reqd;
+ bool work = 0, srp_reqd, dcp;
pm_runtime_resume(otg->phy->dev);
pr_debug("%s work\n", otg_state_string(otg->phy->state));
@@ -2502,12 +2551,16 @@
case USB_DCP_CHARGER:
/* Enable VDP_SRC */
ulpi_write(otg->phy, 0x2, 0x85);
+ if (motg->ext_chg_opened) {
+ init_completion(
+ &motg->ext_chg_wait);
+ motg->ext_chg_active = true;
+ }
/* fall through */
case USB_PROPRIETARY_CHARGER:
msm_otg_notify_charger(motg,
IDEV_CHG_MAX);
- pm_runtime_put_noidle(otg->phy->dev);
- pm_runtime_suspend(otg->phy->dev);
+ pm_runtime_put_sync(otg->phy->dev);
break;
case USB_FLOATED_CHARGER:
msm_otg_notify_charger(motg,
@@ -2567,9 +2620,12 @@
clear_bit(B_FALSE_SDP, &motg->inputs);
clear_bit(A_BUS_REQ, &motg->inputs);
cancel_delayed_work_sync(&motg->chg_work);
+ dcp = (motg->chg_type == USB_DCP_CHARGER);
motg->chg_state = USB_CHG_STATE_UNDEFINED;
motg->chg_type = USB_INVALID_CHARGER;
msm_otg_notify_charger(motg, 0);
+ if (dcp)
+ msm_otg_wait_for_ext_chg_done(motg);
msm_otg_reset(otg->phy);
/*
* There is a small window where ID interrupt
@@ -3552,6 +3608,9 @@
case POWER_SUPPLY_PROP_ONLINE:
val->intval = motg->online;
break;
+ case POWER_SUPPLY_PROP_TYPE:
+ val->intval = psy->type;
+ break;
default:
return -EINVAL;
}
@@ -3576,6 +3635,9 @@
case POWER_SUPPLY_PROP_CURRENT_MAX:
motg->current_max = val->intval;
break;
+ case POWER_SUPPLY_PROP_TYPE:
+ psy->type = val->intval;
+ break;
default:
return -EINVAL;
}
@@ -3608,6 +3670,7 @@
POWER_SUPPLY_PROP_ONLINE,
POWER_SUPPLY_PROP_CURRENT_MAX,
POWER_SUPPLY_PROP_SCOPE,
+ POWER_SUPPLY_PROP_TYPE,
};
const struct file_operations msm_otg_bus_fops = {
@@ -3828,6 +3891,168 @@
return 0;
}
+static int msm_otg_ext_chg_open(struct inode *inode, struct file *file)
+{
+ struct msm_otg *motg = the_msm_otg;
+
+ pr_debug("msm_otg ext chg open\n");
+
+ motg->ext_chg_opened = true;
+ file->private_data = (void *)motg;
+ return 0;
+}
+
+static long
+msm_otg_ext_chg_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ struct msm_otg *motg = file->private_data;
+ struct msm_usb_chg_info info = {0};
+ int ret = 0, val;
+
+ switch (cmd) {
+ case MSM_USB_EXT_CHG_INFO:
+ info.chg_block_type = USB_CHG_BLOCK_ULPI;
+ info.page_offset = motg->io_res->start & ~PAGE_MASK;
+ /* mmap() works on PAGE granularity */
+ info.length = PAGE_SIZE;
+
+ if (copy_to_user((void __user *)arg, &info, sizeof(info))) {
+ pr_err("%s: copy to user failed\n\n", __func__);
+ ret = -EFAULT;
+ }
+ break;
+ case MSM_USB_EXT_CHG_BLOCK_LPM:
+ if (get_user(val, (int __user *)arg)) {
+ pr_err("%s: get_user failed\n\n", __func__);
+ ret = -EFAULT;
+ break;
+ }
+ pr_debug("%s: LPM block request %d\n", __func__, val);
+ if (val) { /* block LPM */
+ if (motg->chg_type == USB_DCP_CHARGER) {
+ /*
+ * If device is already suspended, resume it.
+ * The PM usage counter is incremented in
+ * runtime resume method. if device is not
+ * suspended, cancel the scheduled suspend
+ * and increment the PM usage counter.
+ */
+ if (pm_runtime_suspended(motg->phy.dev))
+ pm_runtime_resume(motg->phy.dev);
+ else
+ pm_runtime_get_sync(motg->phy.dev);
+ } else {
+ motg->ext_chg_active = false;
+ complete(&motg->ext_chg_wait);
+ ret = -ENODEV;
+ }
+ } else {
+ motg->ext_chg_active = false;
+ complete(&motg->ext_chg_wait);
+ pm_runtime_put(motg->phy.dev);
+ }
+ break;
+ default:
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+static int msm_otg_ext_chg_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ struct msm_otg *motg = file->private_data;
+ unsigned long vsize = vma->vm_end - vma->vm_start;
+ int ret;
+
+ if (vma->vm_pgoff || vsize > PAGE_SIZE)
+ return -EINVAL;
+
+ vma->vm_pgoff = __phys_to_pfn(motg->io_res->start);
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+
+ ret = io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
+ vsize, vma->vm_page_prot);
+ if (ret < 0) {
+ pr_err("%s: failed with return val %d\n", __func__, ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int msm_otg_ext_chg_release(struct inode *inode, struct file *file)
+{
+ struct msm_otg *motg = file->private_data;
+
+ pr_debug("msm_otg ext chg release\n");
+
+ motg->ext_chg_opened = false;
+
+ return 0;
+}
+
+static const struct file_operations msm_otg_ext_chg_fops = {
+ .owner = THIS_MODULE,
+ .open = msm_otg_ext_chg_open,
+ .unlocked_ioctl = msm_otg_ext_chg_ioctl,
+ .mmap = msm_otg_ext_chg_mmap,
+ .release = msm_otg_ext_chg_release,
+};
+
+static int msm_otg_setup_ext_chg_cdev(struct msm_otg *motg)
+{
+ int ret;
+
+ if (motg->pdata->enable_sec_phy || motg->pdata->mode == USB_HOST ||
+ motg->pdata->otg_control != OTG_PMIC_CONTROL ||
+ psy != &motg->usb_psy) {
+ pr_debug("usb ext chg is not supported by msm otg\n");
+ return -ENODEV;
+ }
+
+ ret = alloc_chrdev_region(&motg->ext_chg_dev, 0, 1, "usb_ext_chg");
+ if (ret < 0) {
+ pr_err("Fail to allocate usb ext char dev region\n");
+ return ret;
+ }
+ motg->ext_chg_class = class_create(THIS_MODULE, "msm_ext_chg");
+ if (ret < 0) {
+ pr_err("Fail to create usb ext chg class\n");
+ goto unreg_chrdev;
+ }
+ cdev_init(&motg->ext_chg_cdev, &msm_otg_ext_chg_fops);
+ motg->ext_chg_cdev.owner = THIS_MODULE;
+
+ ret = cdev_add(&motg->ext_chg_cdev, motg->ext_chg_dev, 1);
+ if (ret < 0) {
+ pr_err("Fail to add usb ext chg cdev\n");
+ goto destroy_class;
+ }
+ motg->ext_chg_device = device_create(motg->ext_chg_class,
+ NULL, motg->ext_chg_dev, NULL,
+ "usb_ext_chg");
+ if (IS_ERR(motg->ext_chg_device)) {
+ pr_err("Fail to create usb ext chg device\n");
+ ret = PTR_ERR(motg->ext_chg_device);
+ motg->ext_chg_device = NULL;
+ goto del_cdev;
+ }
+
+ init_completion(&motg->ext_chg_wait);
+ pr_debug("msm otg ext chg cdev setup success\n");
+ return 0;
+
+del_cdev:
+ cdev_del(&motg->ext_chg_cdev);
+destroy_class:
+ class_destroy(motg->ext_chg_class);
+unreg_chrdev:
+ unregister_chrdev_region(motg->ext_chg_dev, 1);
+
+ return ret;
+}
+
struct msm_otg_platform_data *msm_otg_dt_to_pdata(struct platform_device *pdev)
{
struct device_node *node = pdev->dev.of_node;
@@ -4029,6 +4254,7 @@
goto put_pclk;
}
+ motg->io_res = res;
motg->regs = ioremap(res->start, resource_size(res));
if (!motg->regs) {
dev_err(&pdev->dev, "ioremap failed\n");
@@ -4292,6 +4518,10 @@
if (legacy_power_supply && pdata->otg_control == OTG_PMIC_CONTROL)
pm8921_charger_register_vbus_sn(&msm_otg_set_vbus_state);
+ ret = msm_otg_setup_ext_chg_cdev(motg);
+ if (ret)
+ dev_dbg(&pdev->dev, "fail to setup cdev\n");
+
return 0;
remove_phy:
@@ -4353,6 +4583,13 @@
if (phy->otg->host || phy->otg->gadget)
return -EBUSY;
+ if (!motg->ext_chg_device) {
+ device_destroy(motg->ext_chg_class, motg->ext_chg_dev);
+ cdev_del(&motg->ext_chg_cdev);
+ class_destroy(motg->ext_chg_class);
+ unregister_chrdev_region(motg->ext_chg_dev, 1);
+ }
+
if (pdev->dev.of_node)
msm_otg_setup_devices(pdev, motg->pdata->mode, false);
if (motg->pdata->otg_control == OTG_PMIC_CONTROL)
@@ -4444,8 +4681,25 @@
if (phy->state == OTG_STATE_UNDEFINED)
return -EAGAIN;
- else
- return 0;
+
+ if (motg->ext_chg_active) {
+ dev_dbg(dev, "Deferring LPM\n");
+ /*
+ * Charger detection may happen in user space.
+ * Delay entering LPM by 3 sec. Otherwise we
+ * have to exit LPM when user space begins
+ * charger detection.
+ *
+ * This timer will be canceled when user space
+ * votes against LPM by incrementing PM usage
+ * counter. We enter low power mode when
+ * PM usage counter is decremented.
+ */
+ pm_schedule_suspend(dev, 3000);
+ return -EAGAIN;
+ }
+
+ return 0;
}
static int msm_otg_runtime_suspend(struct device *dev)
diff --git a/drivers/video/msm/mdss/dsi_io_v2.c b/drivers/video/msm/mdss/dsi_io_v2.c
index 273fb54..f0ad511 100644
--- a/drivers/video/msm/mdss/dsi_io_v2.c
+++ b/drivers/video/msm/mdss/dsi_io_v2.c
@@ -320,7 +320,7 @@
static void msm_dsi_phy_regulator_init(unsigned char *ctrl_base,
struct mdss_dsi_phy_ctrl *pd)
{
- MIPI_OUTP(ctrl_base + DSI_DSIPHY_LDO_CNTRL, 0x04);
+ MIPI_OUTP(ctrl_base + DSI_DSIPHY_LDO_CNTRL, 0x25);
MIPI_OUTP(ctrl_base + DSI_DSIPHY_REGULATOR_CTRL_0, pd->regulator[0]);
MIPI_OUTP(ctrl_base + DSI_DSIPHY_REGULATOR_CTRL_1, pd->regulator[1]);
MIPI_OUTP(ctrl_base + DSI_DSIPHY_REGULATOR_CTRL_2, pd->regulator[2]);
diff --git a/drivers/video/msm/mdss/dsi_v2.c b/drivers/video/msm/mdss/dsi_v2.c
index 5833796..1a9059c 100644
--- a/drivers/video/msm/mdss/dsi_v2.c
+++ b/drivers/video/msm/mdss/dsi_v2.c
@@ -26,15 +26,6 @@
static int dsi_off(struct mdss_panel_data *pdata)
{
int rc = 0;
- if (!panel_common_data || !pdata)
- return -ENODEV;
-
- if (dsi_intf.op_mode_config)
- dsi_intf.op_mode_config(DSI_CMD_MODE, pdata);
-
- pr_debug("panel off commands\n");
- if (panel_common_data->off)
- panel_common_data->off(pdata);
pr_debug("turn off dsi controller\n");
if (dsi_intf.off)
@@ -44,11 +35,6 @@
pr_err("mdss_dsi_off DSI failed %d\n", rc);
return rc;
}
-
- pr_debug("turn off panel power\n");
- if (panel_common_data->reset)
- panel_common_data->reset(pdata, 0);
-
return rc;
}
@@ -56,13 +42,7 @@
{
int rc = 0;
- pr_debug("dsi_on\n");
-
- if (!panel_common_data || !pdata)
- return -ENODEV;
-
-
- pr_debug("dsi_on DSI controller ont\n");
+ pr_debug("dsi_on DSI controller on\n");
if (dsi_intf.on)
rc = dsi_intf.on(pdata);
@@ -70,17 +50,34 @@
pr_err("mdss_dsi_on DSI failed %d\n", rc);
return rc;
}
- pr_debug("dsi_on power on panel\n");
- if (panel_common_data->reset)
- panel_common_data->reset(pdata, 1);
+ return rc;
+}
+static int dsi_panel_handler(struct mdss_panel_data *pdata, int enable)
+{
+ int rc = 0;
- pr_debug("dsi_on DSI panel ont\n");
- if (panel_common_data->on)
- rc = panel_common_data->on(pdata);
+ pr_debug("dsi_panel_handler enable=%d\n", enable);
+ if (!panel_common_data || !pdata)
+ return -ENODEV;
- if (rc) {
- pr_err("mdss_dsi_on panel failed %d\n", rc);
- return rc;
+ if (enable) {
+ if (panel_common_data->reset)
+ panel_common_data->reset(pdata, 1);
+
+ if (panel_common_data->on)
+ rc = panel_common_data->on(pdata);
+
+ if (rc)
+ pr_err("dsi_panel_handler panel on failed %d\n", rc);
+ } else {
+ if (dsi_intf.op_mode_config)
+ dsi_intf.op_mode_config(DSI_CMD_MODE, pdata);
+
+ if (panel_common_data->off)
+ panel_common_data->off(pdata);
+
+ if (panel_common_data->reset)
+ panel_common_data->reset(pdata, 0);
}
return rc;
}
@@ -96,12 +93,18 @@
}
switch (event) {
- case MDSS_EVENT_PANEL_ON:
+ case MDSS_EVENT_UNBLANK:
rc = dsi_on(pdata);
break;
- case MDSS_EVENT_PANEL_OFF:
+ case MDSS_EVENT_BLANK:
rc = dsi_off(pdata);
break;
+ case MDSS_EVENT_PANEL_ON:
+ rc = dsi_panel_handler(pdata, 1);
+ break;
+ case MDSS_EVENT_PANEL_OFF:
+ rc = dsi_panel_handler(pdata, 0);
+ break;
default:
pr_debug("%s: unhandled event=%d\n", __func__, event);
break;
diff --git a/drivers/video/msm/mdss/mdp3.c b/drivers/video/msm/mdss/mdp3.c
index 91e70a7..66418db 100644
--- a/drivers/video/msm/mdss/mdp3.c
+++ b/drivers/video/msm/mdss/mdp3.c
@@ -161,12 +161,19 @@
{
int i = 0;
struct mdp3_hw_resource *mdata = (struct mdp3_hw_resource *)ptr;
- u32 mdp_interrupt = MDP3_REG_READ(MDP3_REG_INTR_STATUS);
+ u32 mdp_interrupt = 0;
+ spin_lock(&mdata->irq_lock);
+ if (!mdata->irq_mask) {
+ pr_err("spurious interrupt\n");
+ spin_unlock(&mdata->irq_lock);
+ return IRQ_HANDLED;
+ }
+
+ mdp_interrupt = MDP3_REG_READ(MDP3_REG_INTR_STATUS);
MDP3_REG_WRITE(MDP3_REG_INTR_CLEAR, mdp_interrupt);
pr_debug("mdp3_irq_handler irq=%d\n", mdp_interrupt);
- spin_lock(&mdata->irq_lock);
mdp_interrupt &= mdata->irq_mask;
while (mdp_interrupt && i < MDP3_MAX_INTR) {
@@ -183,7 +190,6 @@
void mdp3_irq_enable(int type)
{
unsigned long flag;
- int irqEnabled = 0;
pr_debug("mdp3_irq_enable type=%d\n", type);
spin_lock_irqsave(&mdp3_res->irq_lock, flag);
@@ -193,11 +199,10 @@
spin_unlock_irqrestore(&mdp3_res->irq_lock, flag);
return;
}
- irqEnabled = mdp3_res->irq_mask;
+
mdp3_res->irq_mask |= BIT(type);
MDP3_REG_WRITE(MDP3_REG_INTR_ENABLE, mdp3_res->irq_mask);
- if (!irqEnabled)
- enable_irq(mdp3_res->irq);
+
spin_unlock_irqrestore(&mdp3_res->irq_lock, flag);
}
@@ -220,8 +225,6 @@
if (mdp3_res->irq_ref_count[type] == 0) {
mdp3_res->irq_mask &= ~BIT(type);
MDP3_REG_WRITE(MDP3_REG_INTR_ENABLE, mdp3_res->irq_mask);
- if (!mdp3_res->irq_mask)
- disable_irq_nosync(mdp3_res->irq);
}
}
@@ -229,7 +232,7 @@
{
unsigned long flag;
- pr_debug("interrupt %d callback n", type);
+ pr_debug("interrupt %d callback\n", type);
spin_lock_irqsave(&mdp3_res->irq_lock, flag);
if (cb)
mdp3_res->callbacks[type] = *cb;
@@ -240,6 +243,30 @@
return 0;
}
+void mdp3_irq_register(void)
+{
+ unsigned long flag;
+
+ pr_debug("mdp3_irq_register\n");
+ spin_lock_irqsave(&mdp3_res->irq_lock, flag);
+ enable_irq(mdp3_res->irq);
+ spin_unlock_irqrestore(&mdp3_res->irq_lock, flag);
+}
+
+void mdp3_irq_deregister(void)
+{
+ unsigned long flag;
+
+ pr_debug("mdp3_irq_deregister\n");
+ spin_lock_irqsave(&mdp3_res->irq_lock, flag);
+ memset(mdp3_res->irq_ref_count, 0, sizeof(u32) * MDP3_MAX_INTR);
+ mdp3_res->irq_mask = 0;
+ MDP3_REG_WRITE(MDP3_REG_INTR_ENABLE, 0);
+ MDP3_REG_WRITE(MDP3_REG_INTR_CLEAR, 0xfffffff);
+ disable_irq_nosync(mdp3_res->irq);
+ spin_unlock_irqrestore(&mdp3_res->irq_lock, flag);
+}
+
static int mdp3_bus_scale_register(void)
{
int i;
@@ -955,6 +982,92 @@
return xres * bpp;
}
+static int mdp3_fbmem_alloc(struct msm_fb_data_type *mfd)
+{
+ int ret = -ENOMEM, dom;
+ void *virt = NULL;
+ unsigned long phys = 0;
+ size_t size;
+ u32 yres = mfd->fbi->var.yres_virtual;
+
+ size = PAGE_ALIGN(mfd->fbi->fix.line_length * yres);
+
+ if (mfd->index != 0) {
+ mfd->fbi->screen_base = virt;
+ mfd->fbi->fix.smem_start = phys;
+ mfd->fbi->fix.smem_len = 0;
+ return 0;
+ }
+
+ mdp3_res->ion_handle = ion_alloc(mdp3_res->ion_client, size,
+ SZ_1M,
+ ION_HEAP(ION_QSECOM_HEAP_ID), 0);
+
+ if (!IS_ERR_OR_NULL(mdp3_res->ion_handle)) {
+ virt = ion_map_kernel(mdp3_res->ion_client,
+ mdp3_res->ion_handle);
+ if (IS_ERR(virt)) {
+ pr_err("%s map kernel error\n", __func__);
+ goto ion_map_kernel_err;
+ }
+
+ ret = ion_phys(mdp3_res->ion_client, mdp3_res->ion_handle,
+ &phys, &size);
+ if (ret) {
+ pr_err("%s ion_phys error\n", __func__);
+ goto ion_map_phys_err;
+ }
+ } else {
+ pr_err("%s ion alloc fail\n", __func__);
+ mdp3_res->ion_handle = NULL;
+ return -ENOMEM;
+ }
+
+ dom = (mdp3_res->domains + MDP3_IOMMU_DOMAIN)->domain_idx;
+
+ ret = ion_map_iommu(mdp3_res->ion_client, mdp3_res->ion_handle,
+ dom, 0, SZ_4K, 0, &mfd->iova,
+ (unsigned long *)&size, 0, 0);
+
+ if (ret) {
+ pr_err("%s map IOMMU error\n", __func__);
+ goto ion_map_phys_err;
+ }
+
+ pr_info("allocating %u bytes at %p (%lx phys) for fb %d\n",
+ size, virt, phys, mfd->index);
+
+ mfd->fbi->screen_base = virt;
+ mfd->fbi->fix.smem_start = phys;
+ mfd->fbi->fix.smem_len = size;
+ return 0;
+
+ion_map_phys_err:
+ ion_unmap_kernel(mdp3_res->ion_client, mdp3_res->ion_handle);
+ion_map_kernel_err:
+ ion_free(mdp3_res->ion_client, mdp3_res->ion_handle);
+ mdp3_res->ion_handle = NULL;
+ return -ENOMEM;
+}
+
+void mdp3_fbmem_free(struct msm_fb_data_type *mfd)
+{
+ pr_info("mdp3_fbmem_free\n");
+ if (mdp3_res->ion_handle) {
+ int dom = (mdp3_res->domains + MDP3_IOMMU_DOMAIN)->domain_idx;
+
+ ion_unmap_kernel(mdp3_res->ion_client, mdp3_res->ion_handle);
+ ion_unmap_iommu(mdp3_res->ion_client, mdp3_res->ion_handle,
+ dom, 0);
+ ion_free(mdp3_res->ion_client, mdp3_res->ion_handle);
+ mdp3_res->ion_handle = NULL;
+ mfd->fbi->screen_base = 0;
+ mfd->fbi->fix.smem_start = 0;
+ mfd->fbi->fix.smem_len = 0;
+ mfd->iova = 0;
+ }
+}
+
struct mdp3_dma *mdp3_get_dma_pipe(int capability)
{
int i;
@@ -996,6 +1109,7 @@
static struct msm_mdp_interface mdp3_interface = {
.init_fnc = mdp3_init,
.fb_mem_get_iommu_domain = mdp3_fb_mem_get_iommu_domain,
+ .fb_mem_alloc_fnc = mdp3_fbmem_alloc,
.fb_stride = mdp3_fb_stride,
};
diff --git a/drivers/video/msm/mdss/mdp3.h b/drivers/video/msm/mdss/mdp3.h
index 1afae01..d29e5b6 100644
--- a/drivers/video/msm/mdss/mdp3.h
+++ b/drivers/video/msm/mdss/mdp3.h
@@ -110,6 +110,7 @@
struct ion_client *ion_client;
struct mdp3_iommu_domain_map *domains;
struct mdp3_iommu_ctx_map *iommu_contexts;
+ struct ion_handle *ion_handle;
struct mdp3_dma dma[MDP3_DMA_MAX];
struct mdp3_intf intf[MDP3_DMA_OUTPUT_SEL_MAX];
@@ -141,6 +142,8 @@
void mdp3_irq_disable(int type);
void mdp3_irq_disable_nosync(int type);
int mdp3_set_intr_callback(u32 type, struct mdp3_intr_cb *cb);
+void mdp3_irq_register(void);
+void mdp3_irq_deregister(void);
int mdp3_clk_set_rate(int clk_type, unsigned long clk_rate, int client);
int mdp3_clk_enable(int enable);
int mdp3_bus_scale_set_quota(int client, u64 ab_quota, u64 ib_quota);
@@ -148,6 +151,7 @@
int mdp3_get_img(struct msmfb_data *img, struct mdp3_img_data *data);
int mdp3_iommu_enable(int client);
int mdp3_iommu_disable(int client);
+void mdp3_fbmem_free(struct msm_fb_data_type *mfd);
#define MDP3_REG_WRITE(addr, val) writel_relaxed(val, mdp3_res->mdp_base + addr)
#define MDP3_REG_READ(addr) readl_relaxed(mdp3_res->mdp_base + addr)
diff --git a/drivers/video/msm/mdss/mdp3_ctrl.c b/drivers/video/msm/mdss/mdp3_ctrl.c
index f43d1ed..7edf3d2 100644
--- a/drivers/video/msm/mdss/mdp3_ctrl.c
+++ b/drivers/video/msm/mdss/mdp3_ctrl.c
@@ -427,8 +427,10 @@
}
panel = mdp3_session->panel;
- if (panel->event_handler)
- rc = panel->event_handler(panel, MDSS_EVENT_PANEL_ON, NULL);
+ if (panel->event_handler) {
+ rc = panel->event_handler(panel, MDSS_EVENT_UNBLANK, NULL);
+ rc |= panel->event_handler(panel, MDSS_EVENT_PANEL_ON, NULL);
+ }
if (rc) {
pr_err("fail to turn on the panel\n");
goto on_error;
@@ -439,6 +441,8 @@
goto on_error;
}
+ mdp3_irq_register();
+
rc = mdp3_ctrl_dma_init(mfd, mdp3_session->dma);
if (rc) {
pr_err("dma init failed\n");
@@ -457,6 +461,10 @@
goto on_error;
}
+ if (panel->set_backlight)
+ panel->set_backlight(panel, panel->panel_info.bl_max);
+
+ pr_debug("mdp3_ctrl_on dma start\n");
if (mfd->fbi->screen_base) {
rc = mdp3_session->dma->start(mdp3_session->dma,
mdp3_session->intf);
@@ -488,6 +496,7 @@
return -ENODEV;
}
+ panel = mdp3_session->panel;
mutex_lock(&mdp3_session->lock);
if (!mdp3_session->status) {
@@ -495,30 +504,39 @@
goto off_error;
}
- pr_debug("mdp3_ctrl_off stop mdp3 dma engine\n");
-
mdp3_histogram_stop(mdp3_session, MDP_BLOCK_DMA_P);
- rc = mdp3_session->dma->stop(mdp3_session->dma, mdp3_session->intf);
+ pr_debug("mdp3_ctrl_off turn panel off\n");
+ if (panel->set_backlight)
+ panel->set_backlight(panel, 0);
- if (rc)
- pr_err("fail to stop the MDP3 dma\n");
-
- pr_debug("mdp3_ctrl_off stop dsi panel and controller\n");
- panel = mdp3_session->panel;
if (panel->event_handler)
rc = panel->event_handler(panel, MDSS_EVENT_PANEL_OFF, NULL);
if (rc)
pr_err("fail to turn off the panel\n");
- pr_debug("mdp3_ctrl_off release bus and clock\n");
- rc = mdp3_ctrl_res_req_bus(mfd, 0);
+ rc = mdp3_session->dma->stop(mdp3_session->dma, mdp3_session->intf);
if (rc)
- pr_err("mdp bus resource release failed\n");
+ pr_err("fail to stop the MDP3 dma\n");
+
+ mdp3_irq_deregister();
+
+ pr_debug("mdp3_ctrl_off stop clock\n");
rc = mdp3_ctrl_res_req_clk(mfd, 0);
if (rc)
pr_err("mdp clock resource release failed\n");
+ pr_debug("mdp3_ctrl_off stop dsi controller\n");
+ if (panel->event_handler)
+ rc = panel->event_handler(panel, MDSS_EVENT_BLANK, NULL);
+ if (rc)
+ pr_err("fail to turn off the panel\n");
+
+ pr_debug("mdp3_ctrl_off release bus\n");
+ rc = mdp3_ctrl_res_req_bus(mfd, 0);
+ if (rc)
+ pr_err("mdp bus resource release failed\n");
+
rc = mdp3_iommu_disable(MDP3_CLIENT_DMA_P);
if (rc)
pr_err("fail to dettach MDP DMA SMMU\n");
@@ -666,6 +684,9 @@
if (mdp3_bufq_count(&mdp3_session->bufq_out) > 2) {
data = mdp3_bufq_pop(&mdp3_session->bufq_out);
mdp3_put_img(data);
+
+ if (mfd->fbi->screen_base)
+ mdp3_fbmem_free(mfd);
}
mutex_unlock(&mdp3_session->lock);
@@ -850,7 +871,7 @@
ret = session->dma->get_histo(session->dma);
if (ret) {
- pr_err("mdp3_histogram_collect error = %d\n", ret);
+ pr_debug("mdp3_histogram_collect error = %d\n", ret);
return ret;
}
@@ -899,11 +920,53 @@
return ret;
}
+static int mdp3_csc_config(struct mdp3_session_data *session,
+ struct mdp_csc_cfg_data *data)
+{
+ struct mdp3_dma_color_correct_config config;
+ struct mdp3_dma_ccs ccs;
+ int ret = -EINVAL;
+
+ if (!data->csc_data.csc_mv || !data->csc_data.csc_pre_bv ||
+ !data->csc_data.csc_post_bv || !data->csc_data.csc_pre_lv ||
+ !data->csc_data.csc_post_lv) {
+ pr_err("%s : Invalid csc vectors", __func__);
+ return -EINVAL;
+ }
+
+ session->cc_vect_sel = (session->cc_vect_sel + 1) % 2;
+
+ config.ccs_enable = 1;
+ config.ccs_sel = session->cc_vect_sel;
+ config.pre_limit_sel = session->cc_vect_sel;
+ config.post_limit_sel = session->cc_vect_sel;
+ config.pre_bias_sel = session->cc_vect_sel;
+ config.post_bias_sel = session->cc_vect_sel;
+ config.ccs_dirty = true;
+
+ ccs.mv = data->csc_data.csc_mv;
+ ccs.pre_bv = data->csc_data.csc_pre_bv;
+ ccs.post_bv = data->csc_data.csc_post_bv;
+ ccs.pre_lv = data->csc_data.csc_pre_lv;
+ ccs.post_lv = data->csc_data.csc_post_lv;
+
+ mutex_lock(&session->lock);
+ ret = session->dma->config_ccs(session->dma, &config, &ccs);
+ mutex_unlock(&session->lock);
+ return ret;
+}
+
static int mdp3_pp_ioctl(struct msm_fb_data_type *mfd,
void __user *argp)
{
int ret = -EINVAL;
struct msmfb_mdp_pp mdp_pp;
+ struct mdp3_session_data *mdp3_session;
+
+ if (!mfd || !mfd->mdp.private1)
+ return -EINVAL;
+
+ mdp3_session = mfd->mdp.private1;
ret = copy_from_user(&mdp_pp, argp, sizeof(mdp_pp));
if (ret)
@@ -914,6 +977,11 @@
ret = mdp3_bl_scale_config(mfd, (struct mdp_bl_scale_data *)
&mdp_pp.data.bl_scale_data);
break;
+ case mdp_op_csc_cfg:
+ ret = mdp3_csc_config(mdp3_session,
+ &(mdp_pp.data.csc_cfg_data));
+ break;
+
default:
pr_err("Unsupported request to MDP_PP IOCTL.\n");
ret = -EINVAL;
@@ -1001,6 +1069,7 @@
lut_config.lut_enable = 7;
lut_config.lut_sel = mdp3_session->lut_sel;
lut_config.lut_position = 0;
+ lut_config.lut_dirty = true;
lut.color0_lut = r;
lut.color1_lut = g;
lut.color2_lut = b;
diff --git a/drivers/video/msm/mdss/mdp3_ctrl.h b/drivers/video/msm/mdss/mdp3_ctrl.h
index 0bbc2ac..9ea1c91 100644
--- a/drivers/video/msm/mdss/mdp3_ctrl.h
+++ b/drivers/video/msm/mdss/mdp3_ctrl.h
@@ -50,6 +50,7 @@
int histo_status;
struct mutex histo_lock;
int lut_sel;
+ int cc_vect_sel;
};
int mdp3_ctrl_init(struct msm_fb_data_type *mfd);
diff --git a/drivers/video/msm/mdss/mdp3_dma.c b/drivers/video/msm/mdss/mdp3_dma.c
index 3b65405..2e9c787 100644
--- a/drivers/video/msm/mdss/mdp3_dma.c
+++ b/drivers/video/msm/mdss/mdp3_dma.c
@@ -219,6 +219,25 @@
}
}
+static void mdp3_dma_clk_auto_gating(struct mdp3_dma *dma, int enable)
+{
+ u32 cgc;
+ int clock_bit = 10;
+
+ clock_bit += dma->dma_sel;
+
+ if (enable) {
+ cgc = MDP3_REG_READ(MDP3_REG_CGC_EN);
+ cgc |= BIT(clock_bit);
+ MDP3_REG_WRITE(MDP3_REG_CGC_EN, cgc);
+
+ } else {
+ cgc = MDP3_REG_READ(MDP3_REG_CGC_EN);
+ cgc &= ~BIT(clock_bit);
+ MDP3_REG_WRITE(MDP3_REG_CGC_EN, cgc);
+ }
+}
+
static int mdp3_dma_sync_config(struct mdp3_dma *dma,
struct mdp3_dma_source *source_config)
{
@@ -347,11 +366,109 @@
return 0;
}
+static void mdp3_ccs_update(struct mdp3_dma *dma)
+{
+ u32 cc_config;
+ int updated = 0;
+
+ cc_config = MDP3_REG_READ(MDP3_REG_DMA_P_COLOR_CORRECT_CONFIG);
+
+ if (dma->ccs_config.ccs_dirty) {
+ cc_config &= DMA_CCS_CONFIG_MASK;
+ if (dma->ccs_config.ccs_enable)
+ cc_config |= BIT(3);
+ else
+ cc_config &= ~BIT(3);
+ cc_config |= dma->ccs_config.ccs_sel << 5;
+ cc_config |= dma->ccs_config.pre_bias_sel << 6;
+ cc_config |= dma->ccs_config.post_bias_sel << 7;
+ cc_config |= dma->ccs_config.pre_limit_sel << 8;
+ cc_config |= dma->ccs_config.post_limit_sel << 9;
+ dma->ccs_config.ccs_dirty = false;
+ updated = 1;
+ }
+
+ if (dma->lut_config.lut_dirty) {
+ cc_config &= DMA_LUT_CONFIG_MASK;
+ cc_config |= dma->lut_config.lut_enable;
+ cc_config |= dma->lut_config.lut_position << 4;
+ cc_config |= dma->lut_config.lut_sel << 10;
+ dma->lut_config.lut_dirty = false;
+ updated = 1;
+ }
+ if (updated) {
+ MDP3_REG_WRITE(MDP3_REG_DMA_P_COLOR_CORRECT_CONFIG, cc_config);
+
+ /* Make sure ccs configuration update is done before continuing
+ with the DMA transfer */
+ wmb();
+ }
+}
+
+static int mdp3_dmap_ccs_config(struct mdp3_dma *dma,
+ struct mdp3_dma_color_correct_config *config,
+ struct mdp3_dma_ccs *ccs)
+{
+ int i;
+ u32 addr;
+
+ if (!ccs)
+ return -EINVAL;
+
+ if (config->ccs_enable) {
+ addr = MDP3_REG_DMA_P_CSC_MV1;
+ if (config->ccs_sel)
+ addr = MDP3_REG_DMA_P_CSC_MV2;
+ for (i = 0; i < 9; i++) {
+ MDP3_REG_WRITE(addr, ccs->mv[i]);
+ addr += 4;
+ }
+
+ addr = MDP3_REG_DMA_P_CSC_PRE_BV1;
+ if (config->pre_bias_sel)
+ addr = MDP3_REG_DMA_P_CSC_PRE_BV2;
+ for (i = 0; i < 3; i++) {
+ MDP3_REG_WRITE(addr, ccs->pre_bv[i]);
+ addr += 4;
+ }
+
+ addr = MDP3_REG_DMA_P_CSC_POST_BV1;
+ if (config->post_bias_sel)
+ addr = MDP3_REG_DMA_P_CSC_POST_BV2;
+ for (i = 0; i < 3; i++) {
+ MDP3_REG_WRITE(addr, ccs->post_bv[i]);
+ addr += 4;
+ }
+
+ addr = MDP3_REG_DMA_P_CSC_PRE_LV1;
+ if (config->pre_limit_sel)
+ addr = MDP3_REG_DMA_P_CSC_PRE_LV2;
+ for (i = 0; i < 6; i++) {
+ MDP3_REG_WRITE(addr, ccs->pre_lv[i]);
+ addr += 4;
+ }
+
+ addr = MDP3_REG_DMA_P_CSC_POST_LV1;
+ if (config->post_limit_sel)
+ addr = MDP3_REG_DMA_P_CSC_POST_LV2;
+ for (i = 0; i < 6; i++) {
+ MDP3_REG_WRITE(addr, ccs->post_lv[i]);
+ addr += 4;
+ }
+ }
+ dma->ccs_config = *config;
+
+ if (dma->output_config.out_sel != MDP3_DMA_OUTPUT_SEL_DSI_CMD)
+ mdp3_ccs_update(dma);
+
+ return 0;
+}
+
static int mdp3_dmap_lut_config(struct mdp3_dma *dma,
struct mdp3_dma_lut_config *config,
struct mdp3_dma_lut *lut)
{
- u32 cc_config, addr, color;
+ u32 addr, color;
int i;
if (config->lut_enable && lut) {
@@ -368,119 +485,11 @@
}
}
- cc_config = MDP3_REG_READ(MDP3_REG_DMA_P_COLOR_CORRECT_CONFIG);
- cc_config &= DMA_LUT_CONFIG_MASK;
- cc_config |= config->lut_enable;
- cc_config |= config->lut_position << 4;
- cc_config |= config->lut_sel << 10;
- MDP3_REG_WRITE(MDP3_REG_DMA_P_COLOR_CORRECT_CONFIG, cc_config);
- wmb();
-
dma->lut_config = *config;
- return 0;
-}
-static int mdp3_dmap_ccs_config(struct mdp3_dma *dma,
- struct mdp3_dma_color_correct_config *config,
- struct mdp3_dma_ccs *ccs)
-{
- int i;
- u32 cc_config, addr;
+ if (dma->output_config.out_sel != MDP3_DMA_OUTPUT_SEL_DSI_CMD)
+ mdp3_ccs_update(dma);
- cc_config = MDP3_REG_READ(MDP3_REG_DMA_P_COLOR_CORRECT_CONFIG);
- cc_config &= DMA_CCS_CONFIG_MASK;
- cc_config |= BIT(3);
- cc_config |= config->ccs_sel << 5;
- cc_config |= config->pre_bias_sel << 6;
- cc_config |= config->post_bias_sel << 7;
- cc_config |= config->pre_limit_sel << 8;
- cc_config |= config->post_limit_sel << 9;
-
- MDP3_REG_WRITE(MDP3_REG_DMA_P_COLOR_CORRECT_CONFIG, cc_config);
-
- if (config->ccs_enable && ccs) {
- if (ccs->mv1) {
- addr = MDP3_REG_DMA_P_CSC_MV1;
- for (i = 0; i < 9; i++) {
- MDP3_REG_WRITE(addr, ccs->mv1[i]);
- addr += 4;
- }
- }
-
- if (ccs->mv2) {
- addr = MDP3_REG_DMA_P_CSC_MV2;
- for (i = 0; i < 9; i++) {
- MDP3_REG_WRITE(addr, ccs->mv2[i]);
- addr += 4;
- }
- }
-
- if (ccs->pre_bv1) {
- addr = MDP3_REG_DMA_P_CSC_PRE_BV1;
- for (i = 0; i < 3; i++) {
- MDP3_REG_WRITE(addr, ccs->pre_bv1[i]);
- addr += 4;
- }
- }
-
- if (ccs->pre_bv2) {
- addr = MDP3_REG_DMA_P_CSC_PRE_BV2;
- for (i = 0; i < 3; i++) {
- MDP3_REG_WRITE(addr, ccs->pre_bv2[i]);
- addr += 4;
- }
- }
-
- if (ccs->post_bv1) {
- addr = MDP3_REG_DMA_P_CSC_POST_BV1;
- for (i = 0; i < 3; i++) {
- MDP3_REG_WRITE(addr, ccs->post_bv1[i]);
- addr += 4;
- }
- }
-
- if (ccs->post_bv2) {
- addr = MDP3_REG_DMA_P_CSC_POST_BV2;
- for (i = 0; i < 3; i++) {
- MDP3_REG_WRITE(addr, ccs->post_bv2[i]);
- addr += 4;
- }
- }
-
- if (ccs->pre_lv1) {
- addr = MDP3_REG_DMA_P_CSC_PRE_LV1;
- for (i = 0; i < 6; i++) {
- MDP3_REG_WRITE(addr, ccs->pre_lv1[i]);
- addr += 4;
- }
- }
-
- if (ccs->pre_lv2) {
- addr = MDP3_REG_DMA_P_CSC_PRE_LV2;
- for (i = 0; i < 6; i++) {
- MDP3_REG_WRITE(addr, ccs->pre_lv2[i]);
- addr += 4;
- }
- }
-
- if (ccs->post_lv1) {
- addr = MDP3_REG_DMA_P_CSC_POST_LV1;
- for (i = 0; i < 6; i++) {
- MDP3_REG_WRITE(addr, ccs->post_lv1[i]);
- addr += 4;
- }
- }
-
- if (ccs->post_lv2) {
- addr = MDP3_REG_DMA_P_CSC_POST_LV2;
- for (i = 0; i < 6; i++) {
- MDP3_REG_WRITE(addr, ccs->post_lv2[i]);
- addr += 4;
- }
- }
- }
-
- dma->ccs_config = *config;
return 0;
}
@@ -528,8 +537,10 @@
spin_lock_irqsave(&dma->dma_lock, flag);
MDP3_REG_WRITE(MDP3_REG_DMA_P_IBUF_ADDR, (u32)buf);
dma->source_config.buf = buf;
- if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_CMD)
+ if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_CMD) {
+ mdp3_ccs_update(dma);
MDP3_REG_WRITE(MDP3_REG_DMA_P_START, 1);
+ }
if (!intf->active) {
pr_debug("mdp3_dmap_update start interface\n");
@@ -610,7 +621,7 @@
ret = wait_for_completion_killable_timeout(&dma->histo_comp, timeout);
if (ret == 0) {
- pr_err("mdp3_dmap_histo_get time out\n");
+ pr_debug("mdp3_dmap_histo_get time out\n");
ret = -ETIMEDOUT;
} else if (ret < 0) {
pr_err("mdp3_dmap_histo_get interrupted\n");
@@ -682,7 +693,6 @@
{
unsigned long flag;
int ret;
- u32 cgc;
if (dma->histo_state == MDP3_DMA_HISTO_STATE_START)
return -EINVAL;
@@ -690,9 +700,8 @@
spin_lock_irqsave(&dma->histo_lock, flag);
init_completion(&dma->histo_comp);
- cgc = MDP3_REG_READ(MDP3_REG_CGC_EN);
- cgc &= ~BIT(10);
- MDP3_REG_WRITE(MDP3_REG_CGC_EN, cgc);
+
+ mdp3_dma_clk_auto_gating(dma, 0);
MDP3_REG_WRITE(MDP3_REG_DMA_P_HIST_INTR_ENABLE, BIT(0)|BIT(1));
MDP3_REG_WRITE(MDP3_REG_DMA_P_HIST_RESET_SEQ_START, 1);
@@ -714,8 +723,7 @@
ret = 0;
}
mdp3_dma_callback_disable(dma, MDP3_DMA_CALLBACK_TYPE_HIST_RESET_DONE);
- cgc |= BIT(10);
- MDP3_REG_WRITE(MDP3_REG_CGC_EN, cgc);
+ mdp3_dma_clk_auto_gating(dma, 1);
return ret;
}
@@ -732,6 +740,7 @@
MDP3_REG_WRITE(MDP3_REG_DMA_P_HIST_INTR_ENABLE, 0);
wmb();
dma->histo_state = MDP3_DMA_HISTO_STATE_IDLE;
+ complete(&dma->histo_comp);
spin_unlock_irqrestore(&dma->histo_lock, flag);
diff --git a/drivers/video/msm/mdss/mdp3_dma.h b/drivers/video/msm/mdss/mdp3_dma.h
index 518bd58..c652818 100644
--- a/drivers/video/msm/mdss/mdp3_dma.h
+++ b/drivers/video/msm/mdss/mdp3_dma.h
@@ -176,16 +176,11 @@
};
struct mdp3_dma_ccs {
- u32 *mv1; /*set1 matrix vector, 3x3 */
- u32 *mv2;
- u32 *pre_bv1; /*pre-bias vector for set1, 1x3*/
- u32 *pre_bv2;
- u32 *post_bv1; /*post-bias vecotr for set1, */
- u32 *post_bv2;
- u32 *pre_lv1; /*pre-limit vector for set 1, 1x6*/
- u32 *pre_lv2;
- u32 *post_lv1;
- u32 *post_lv2;
+ u32 *mv; /*set1 matrix vector, 3x3 */
+ u32 *pre_bv; /*pre-bias vector for set1, 1x3*/
+ u32 *post_bv; /*post-bias vecotr for set1, */
+ u32 *pre_lv; /*pre-limit vector for set 1, 1x6*/
+ u32 *post_lv;
};
struct mdp3_dma_lut {
@@ -198,6 +193,7 @@
int lut_enable;
u32 lut_sel;
u32 lut_position;
+ bool lut_dirty;
};
struct mdp3_dma_color_correct_config {
@@ -207,6 +203,7 @@
u32 post_bias_sel;
u32 pre_bias_sel;
u32 ccs_sel;
+ bool ccs_dirty;
};
struct mdp3_dma_histogram_config {
diff --git a/drivers/video/msm/mdss/mdp3_ppp.c b/drivers/video/msm/mdss/mdp3_ppp.c
index 48ffb72..afb2eb4 100644
--- a/drivers/video/msm/mdss/mdp3_ppp.c
+++ b/drivers/video/msm/mdss/mdp3_ppp.c
@@ -898,8 +898,8 @@
struct blit_req_list *req;
int i, rc;
- req = mdp3_ppp_next_req(&ppp_stat->req_q);
mutex_lock(&ppp_stat->config_ppp_mutex);
+ req = mdp3_ppp_next_req(&ppp_stat->req_q);
mdp3_iommu_enable(MDP3_CLIENT_PPP);
mdp3_ppp_turnon(mfd, 1);
diff --git a/drivers/video/msm/mdss/mdp3_ppp_hwio.c b/drivers/video/msm/mdss/mdp3_ppp_hwio.c
index 309effc..8dd3d55 100644
--- a/drivers/video/msm/mdss/mdp3_ppp_hwio.c
+++ b/drivers/video/msm/mdss/mdp3_ppp_hwio.c
@@ -57,6 +57,8 @@
int64_t Od;
int64_t Odprime;
int64_t Oreq;
+ int64_t init_phase_temp;
+ int64_t delta;
uint32_t mult;
/*
@@ -149,7 +151,24 @@
Oreq = (Osprime & int_mask) - one;
/* calculate initial phase */
- init_phase = (int)((Osprime - Oreq) >> 4);
+ init_phase_temp = Osprime - Oreq;
+ delta = ((int64_t) (org) << PQF_PLUS_4) - Oreq;
+ init_phase_temp -= delta;
+
+ /* limit to valid range before the left shift */
+ delta = (init_phase_temp & (1LL << 63)) ?
+ 4 : -4;
+ delta <<= PQF_PLUS_4;
+ while (abs((int)(init_phase_temp >>
+ PQF_PLUS_4)) > 4)
+ init_phase_temp += delta;
+
+ /*
+ * right shift to account for extra bits of
+ * precision
+ */
+ init_phase = (int)(init_phase_temp >> 4);
+
}
} else {
/*
@@ -181,7 +200,18 @@
Oreq = (Osprime & int_mask) - one;
/* calculate initial phase */
- init_phase = (int)((Osprime - Oreq) >> 4);
+ init_phase_temp = Osprime - Oreq;
+ delta = ((int64_t) (org) << PQF_PLUS_4) - Oreq;
+ init_phase_temp -= delta;
+
+ /* limit to valid range before the left shift */
+ delta = (init_phase_temp & (1LL << 63)) ? 4 : -4;
+ delta <<= PQF_PLUS_4;
+ while (abs((int)(init_phase_temp >> PQF_PLUS_4)) > 4)
+ init_phase_temp += delta;
+
+ /* right shift to account for extra bits of precision */
+ init_phase = (int)(init_phase_temp >> 4);
}
}
@@ -331,13 +361,43 @@
return rgb;
}
-static uint8_t *mdp_adjust_rot_addr(struct ppp_blit_op *iBuf,
+uint8_t *mdp_bg_adjust_rot_addr(struct ppp_blit_op *iBuf,
+ uint8_t *addr, uint32_t bpp, uint32_t uv)
+{
+ uint32_t dest_ystride = iBuf->bg.prop.width * bpp;
+ uint32_t h_slice = 1, min_val;
+
+ if (uv && ((iBuf->bg.color_fmt == MDP_Y_CBCR_H2V2) ||
+ (iBuf->bg.color_fmt == MDP_Y_CRCB_H2V2)))
+ h_slice = 2;
+
+ if (((iBuf->mdp_op & MDPOP_ROT90) == MDPOP_ROT90) ^
+ ((iBuf->mdp_op & MDPOP_LR) == MDPOP_LR)) {
+ min_val = (iBuf->bg.roi.width + iBuf->bg.roi.x) % 16;
+ if (!min_val)
+ min_val = 16;
+ addr +=
+ (iBuf->bg.roi.width -
+ MIN(min_val, iBuf->bg.roi.width)) * bpp;
+ }
+ if ((iBuf->mdp_op & MDPOP_UD) == MDPOP_UD) {
+ min_val = (iBuf->bg.roi.height + iBuf->bg.roi.y) % 16;
+ if (!min_val)
+ min_val = 16;
+ addr +=
+ ((iBuf->bg.roi.height -
+ MIN(min_val, iBuf->bg.roi.height))/h_slice) *
+ dest_ystride;
+ }
+
+ return addr;
+}
+
+uint8_t *mdp_dst_adjust_rot_addr(struct ppp_blit_op *iBuf,
uint8_t *addr, uint32_t bpp, uint32_t uv)
{
uint32_t dest_ystride = iBuf->dst.prop.width * bpp;
uint32_t h_slice = 1;
- if (0)
- return 0;
if (uv && ((iBuf->dst.color_fmt == MDP_Y_CBCR_H2V2) ||
(iBuf->dst.color_fmt == MDP_Y_CRCB_H2V2)))
@@ -350,16 +410,10 @@
MIN(16, iBuf->dst.roi.width)) * bpp;
}
if ((iBuf->mdp_op & MDPOP_UD) == MDPOP_UD) {
- if (1) {
- addr +=
- ((iBuf->dst.roi.height -
- MIN(16, iBuf->dst.roi.height))/h_slice) *
- dest_ystride;
- } else {
- addr +=
- (iBuf->dst.roi.width -
- MIN(16, iBuf->dst.roi.width)) * bpp;
- }
+ addr +=
+ ((iBuf->dst.roi.height -
+ MIN(16, iBuf->dst.roi.height))/h_slice) *
+ dest_ystride;
}
return addr;
@@ -378,8 +432,10 @@
img->p0 += (x + y * ALIGN(width, 32)) * bpp;
else
img->p0 += (x + y * width) * bpp;
- if (layer != 0)
- img->p0 = mdp_adjust_rot_addr(blit_op, img->p0, bpp, 0);
+ if (layer == 1)
+ img->p0 = mdp_bg_adjust_rot_addr(blit_op, img->p0, bpp, 0);
+ else if (layer == 2)
+ img->p0 = mdp_dst_adjust_rot_addr(blit_op, img->p0, bpp, 0);
if (img->p1) {
/*
@@ -394,8 +450,14 @@
else
img->p1 += ((x / h_slice) * h_slice +
((y == 0) ? 0 : ((y + 1) / v_slice - 1) * width)) * bpp;
- if (layer != 0)
- img->p1 = mdp_adjust_rot_addr(blit_op, img->p1, bpp, 1);
+
+ if (layer == 1) {
+ img->p0 = mdp_bg_adjust_rot_addr(blit_op,
+ img->p0, bpp, 0);
+ } else if (layer == 2) {
+ img->p0 = mdp_dst_adjust_rot_addr(blit_op,
+ img->p0, bpp, 0);
+ }
}
}
@@ -1044,7 +1106,6 @@
}
if (*pppop_reg_ptr & PPP_OP_BLEND_ON) {
- blit_op->bg = blit_op->dst;
config_ppp_background(&blit_op->bg);
if (blit_op->dst.color_fmt == MDP_YCRYCB_H2V1) {
@@ -1152,9 +1213,11 @@
blit_op->dst.p1 = NULL;
}
+ blit_op->bg = blit_op->dst;
/* Jumping from Y-Plane to Chroma Plane */
/* first pixel addr calculation */
mdp_adjust_start_addr(blit_op, &blit_op->src, sv_slice, sh_slice, 0);
+ mdp_adjust_start_addr(blit_op, &blit_op->bg, dv_slice, dh_slice, 1);
mdp_adjust_start_addr(blit_op, &blit_op->dst, dv_slice, dh_slice, 2);
config_ppp_scale(blit_op, &ppp_operation_reg);
diff --git a/drivers/video/msm/mdss/mdss.h b/drivers/video/msm/mdss/mdss.h
index 078960b..840af17 100644
--- a/drivers/video/msm/mdss/mdss.h
+++ b/drivers/video/msm/mdss/mdss.h
@@ -89,6 +89,7 @@
u32 smp_mb_cnt;
u32 smp_mb_size;
+ u32 smp_mb_per_pipe;
u32 rot_block_size;
diff --git a/drivers/video/msm/mdss/mdss_dsi.c b/drivers/video/msm/mdss/mdss_dsi.c
index fb0e8ba..44a5e62 100644
--- a/drivers/video/msm/mdss/mdss_dsi.c
+++ b/drivers/video/msm/mdss/mdss_dsi.c
@@ -360,13 +360,13 @@
__func__, rc);
goto error;
}
- mp->vreg_config[i].peak_current = val_array[i];
+ mp->vreg_config[i].enable_load = val_array[i];
pr_debug("%s: %s min=%d, max=%d, pc=%d\n", __func__,
mp->vreg_config[i].vreg_name,
mp->vreg_config[i].min_voltage,
mp->vreg_config[i].max_voltage,
- mp->vreg_config[i].peak_current);
+ mp->vreg_config[i].enable_load);
}
devm_kfree(dev, val_array);
diff --git a/drivers/video/msm/mdss/mdss_dsi_host.c b/drivers/video/msm/mdss/mdss_dsi_host.c
index 2f29b3d..e682e69 100644
--- a/drivers/video/msm/mdss/mdss_dsi_host.c
+++ b/drivers/video/msm/mdss/mdss_dsi_host.c
@@ -1209,6 +1209,8 @@
{
u32 dsi_ctrl, data;
int video_mode;
+ u32 left_dsi_ctrl = 0;
+ bool left_ctrl_restore = false;
if (ctrl->shared_pdata.broadcast_enable) {
if (ctrl->ndx == DSI_CTRL_0) {
@@ -1221,13 +1223,15 @@
if (ctrl->shared_pdata.broadcast_enable) {
if ((ctrl->ndx == DSI_CTRL_1)
&& (left_ctrl_pdata != NULL)) {
- dsi_ctrl = MIPI_INP(left_ctrl_pdata->ctrl_base
+ left_dsi_ctrl = MIPI_INP(left_ctrl_pdata->ctrl_base
+ 0x0004);
- video_mode = dsi_ctrl & 0x02; /* VIDEO_MODE_EN */
+ video_mode =
+ left_dsi_ctrl & 0x02; /* VIDEO_MODE_EN */
if (video_mode) {
- data = dsi_ctrl | 0x04; /* CMD_MODE_EN */
+ data = left_dsi_ctrl | 0x04; /* CMD_MODE_EN */
MIPI_OUTP(left_ctrl_pdata->ctrl_base + 0x0004,
data);
+ left_ctrl_restore = true;
}
}
}
@@ -1246,6 +1250,10 @@
mdss_dsi_cmds2buf_tx(ctrl, cmds, cnt);
+ if (left_ctrl_restore)
+ MIPI_OUTP(left_ctrl_pdata->ctrl_base + 0x0004,
+ left_dsi_ctrl); /*restore */
+
if (video_mode)
MIPI_OUTP((ctrl->ctrl_base) + 0x0004,
dsi_ctrl); /* restore */
@@ -1280,6 +1288,45 @@
struct dsi_buf *tp, *rp;
int no_max_pkt_size;
char cmd;
+ u32 dsi_ctrl, data;
+ int video_mode;
+ u32 left_dsi_ctrl = 0;
+ bool left_ctrl_restore = false;
+
+ if (ctrl->shared_pdata.broadcast_enable) {
+ if (ctrl->ndx == DSI_CTRL_0) {
+ pr_debug("%s: Broadcast mode. 1st ctrl\n",
+ __func__);
+ return 0;
+ }
+ }
+
+ if (ctrl->shared_pdata.broadcast_enable) {
+ if ((ctrl->ndx == DSI_CTRL_1)
+ && (left_ctrl_pdata != NULL)) {
+ left_dsi_ctrl = MIPI_INP(left_ctrl_pdata->ctrl_base
+ + 0x0004);
+ video_mode = left_dsi_ctrl & 0x02; /* VIDEO_MODE_EN */
+ if (video_mode) {
+ data = left_dsi_ctrl | 0x04; /* CMD_MODE_EN */
+ MIPI_OUTP(left_ctrl_pdata->ctrl_base + 0x0004,
+ data);
+ left_ctrl_restore = true;
+ }
+ }
+ }
+
+ /* turn on cmd mode
+ * for video mode, do not send cmds more than
+ * one pixel line, since it only transmit it
+ * during BLLP.
+ */
+ dsi_ctrl = MIPI_INP((ctrl->ctrl_base) + 0x0004);
+ video_mode = dsi_ctrl & 0x02; /* VIDEO_MODE_EN */
+ if (video_mode) {
+ data = dsi_ctrl | 0x04; /* CMD_MODE_EN */
+ MIPI_OUTP((ctrl->ctrl_base) + 0x0004, data);
+ }
no_max_pkt_size = rx_flags & CMD_REQ_NO_MAX_PKT_SIZE;
if (no_max_pkt_size)
@@ -1378,6 +1425,13 @@
break;
}
+ if (left_ctrl_restore)
+ MIPI_OUTP(left_ctrl_pdata->ctrl_base + 0x0004,
+ left_dsi_ctrl); /*restore */
+ if (video_mode)
+ MIPI_OUTP((ctrl->ctrl_base) + 0x0004,
+ dsi_ctrl); /* restore */
+
return rp->len;
}
diff --git a/drivers/video/msm/mdss/mdss_hdmi_tx.c b/drivers/video/msm/mdss/mdss_hdmi_tx.c
index 91e5660..e4a6b86 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_tx.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_tx.c
@@ -87,6 +87,9 @@
static void hdmi_tx_hpd_off(struct hdmi_tx_ctrl *hdmi_ctrl);
static int hdmi_tx_enable_power(struct hdmi_tx_ctrl *hdmi_ctrl,
enum hdmi_tx_power_module_type module, int enable);
+static void hdmi_tx_audio_off(struct hdmi_tx_ctrl *hdmi_ctrl,
+ bool wait_audio_tx);
+static int hdmi_tx_audio_setup(struct hdmi_tx_ctrl *hdmi_ctrl);
struct mdss_hw hdmi_tx_hw = {
.hw_ndx = MDSS_HW_HDMI,
@@ -1676,10 +1679,11 @@
} /* hdmi_tx_powerdown_phy */
static int hdmi_tx_audio_acr_setup(struct hdmi_tx_ctrl *hdmi_ctrl,
- bool enabled, int num_of_channels)
+ bool enabled)
{
/* Read first before writing */
u32 acr_pck_ctrl_reg;
+ u32 sample_rate;
struct dss_io_data *io = NULL;
if (!hdmi_ctrl) {
@@ -1687,6 +1691,8 @@
return -EINVAL;
}
+ sample_rate = hdmi_ctrl->audio_data.sample_rate;
+
io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
if (!io->base) {
DEV_ERR("%s: core io not inititalized\n", __func__);
@@ -1721,18 +1727,19 @@
return -EPERM;
}
- n = audio_acr->lut[hdmi_ctrl->audio_sample_rate].n;
- cts = audio_acr->lut[hdmi_ctrl->audio_sample_rate].cts;
- layout = (MSM_HDMI_AUDIO_CHANNEL_2 == num_of_channels) ? 0 : 1;
+ n = audio_acr->lut[sample_rate].n;
+ cts = audio_acr->lut[sample_rate].cts;
+ layout = (MSM_HDMI_AUDIO_CHANNEL_2 ==
+ hdmi_ctrl->audio_data.channel_num) ? 0 : 1;
if (
- (AUDIO_SAMPLE_RATE_192KHZ == hdmi_ctrl->audio_sample_rate) ||
- (AUDIO_SAMPLE_RATE_176_4KHZ == hdmi_ctrl->audio_sample_rate)) {
+ (AUDIO_SAMPLE_RATE_192KHZ == sample_rate) ||
+ (AUDIO_SAMPLE_RATE_176_4KHZ == sample_rate)) {
multiplier = 4;
n >>= 2; /* divide N by 4 and use multiplier */
} else if (
- (AUDIO_SAMPLE_RATE_96KHZ == hdmi_ctrl->audio_sample_rate) ||
- (AUDIO_SAMPLE_RATE_88_2KHZ == hdmi_ctrl->audio_sample_rate)) {
+ (AUDIO_SAMPLE_RATE_96KHZ == sample_rate) ||
+ (AUDIO_SAMPLE_RATE_88_2KHZ == sample_rate)) {
multiplier = 2;
n >>= 1; /* divide N by 2 and use multiplier */
} else {
@@ -1743,12 +1750,16 @@
/* AUDIO_PRIORITY | SOURCE */
acr_pck_ctrl_reg |= 0x80000100;
+
+ /* Reset multiplier bits */
+ acr_pck_ctrl_reg &= ~(7 << 16);
+
/* N_MULTIPLE(multiplier) */
acr_pck_ctrl_reg |= (multiplier & 7) << 16;
- if ((AUDIO_SAMPLE_RATE_48KHZ == hdmi_ctrl->audio_sample_rate) ||
- (AUDIO_SAMPLE_RATE_96KHZ == hdmi_ctrl->audio_sample_rate) ||
- (AUDIO_SAMPLE_RATE_192KHZ == hdmi_ctrl->audio_sample_rate)) {
+ if ((AUDIO_SAMPLE_RATE_48KHZ == sample_rate) ||
+ (AUDIO_SAMPLE_RATE_96KHZ == sample_rate) ||
+ (AUDIO_SAMPLE_RATE_192KHZ == sample_rate)) {
/* SELECT(3) */
acr_pck_ctrl_reg |= 3 << 4;
/* CTS_48 */
@@ -1759,9 +1770,9 @@
/* N */
DSS_REG_W(io, HDMI_ACR_48_1, n);
} else if (
- (AUDIO_SAMPLE_RATE_44_1KHZ == hdmi_ctrl->audio_sample_rate) ||
- (AUDIO_SAMPLE_RATE_88_2KHZ == hdmi_ctrl->audio_sample_rate) ||
- (AUDIO_SAMPLE_RATE_176_4KHZ == hdmi_ctrl->audio_sample_rate)) {
+ (AUDIO_SAMPLE_RATE_44_1KHZ == sample_rate) ||
+ (AUDIO_SAMPLE_RATE_88_2KHZ == sample_rate) ||
+ (AUDIO_SAMPLE_RATE_176_4KHZ == sample_rate)) {
/* SELECT(2) */
acr_pck_ctrl_reg |= 2 << 4;
/* CTS_44 */
@@ -1800,12 +1811,15 @@
} /* hdmi_tx_audio_acr_setup */
static int hdmi_tx_audio_iframe_setup(struct hdmi_tx_ctrl *hdmi_ctrl,
- bool enabled, u32 num_of_channels, u32 channel_allocation,
- u32 level_shift, bool down_mix)
+ bool enabled)
{
struct dss_io_data *io = NULL;
u32 channel_count = 1; /* Def to 2 channels -> Table 17 in CEA-D */
+ u32 num_of_channels;
+ u32 channel_allocation;
+ u32 level_shift;
+ u32 down_mix;
u32 check_sum, audio_info_0_reg, audio_info_1_reg;
u32 audio_info_ctrl_reg;
u32 aud_pck_ctrl_2_reg;
@@ -1816,6 +1830,11 @@
return -EINVAL;
}
+ num_of_channels = hdmi_ctrl->audio_data.channel_num;
+ channel_allocation = hdmi_ctrl->audio_data.spkr_alloc;
+ level_shift = hdmi_ctrl->audio_data.level_shift;
+ down_mix = hdmi_ctrl->audio_data.down_mix;
+
io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
if (!io->base) {
DEV_ERR("%s: core io not inititalized\n", __func__);
@@ -1926,8 +1945,8 @@
} /* hdmi_tx_audio_iframe_setup */
static int hdmi_tx_audio_info_setup(struct platform_device *pdev,
- u32 num_of_channels, u32 channel_allocation, u32 level_shift,
- bool down_mix)
+ u32 sample_rate, u32 num_of_channels, u32 channel_allocation,
+ u32 level_shift, bool down_mix)
{
int rc = 0;
struct hdmi_tx_ctrl *hdmi_ctrl = platform_get_drvdata(pdev);
@@ -1937,10 +1956,31 @@
return -ENODEV;
}
- if (hdmi_ctrl->panel_power_on) {
- rc = hdmi_tx_audio_iframe_setup(hdmi_ctrl, true,
- num_of_channels, channel_allocation, level_shift,
- down_mix);
+ if (!hdmi_tx_is_dvi_mode(hdmi_ctrl) && hdmi_ctrl->panel_power_on) {
+
+ /* Map given sample rate to Enum */
+ if (sample_rate == 32000)
+ sample_rate = AUDIO_SAMPLE_RATE_32KHZ;
+ else if (sample_rate == 44100)
+ sample_rate = AUDIO_SAMPLE_RATE_44_1KHZ;
+ else if (sample_rate == 48000)
+ sample_rate = AUDIO_SAMPLE_RATE_48KHZ;
+ else if (sample_rate == 88200)
+ sample_rate = AUDIO_SAMPLE_RATE_88_2KHZ;
+ else if (sample_rate == 96000)
+ sample_rate = AUDIO_SAMPLE_RATE_96KHZ;
+ else if (sample_rate == 176400)
+ sample_rate = AUDIO_SAMPLE_RATE_176_4KHZ;
+ else if (sample_rate == 192000)
+ sample_rate = AUDIO_SAMPLE_RATE_192KHZ;
+
+ hdmi_ctrl->audio_data.sample_rate = sample_rate;
+ hdmi_ctrl->audio_data.channel_num = num_of_channels;
+ hdmi_ctrl->audio_data.spkr_alloc = channel_allocation;
+ hdmi_ctrl->audio_data.level_shift = level_shift;
+ hdmi_ctrl->audio_data.down_mix = down_mix;
+
+ rc = hdmi_tx_audio_setup(hdmi_ctrl);
if (rc)
DEV_ERR("%s: hdmi_tx_audio_iframe_setup failed.rc=%d\n",
__func__, rc);
@@ -2047,7 +2087,6 @@
static int hdmi_tx_audio_setup(struct hdmi_tx_ctrl *hdmi_ctrl)
{
int rc = 0;
- const int channels = MSM_HDMI_AUDIO_CHANNEL_2;
struct dss_io_data *io = NULL;
if (!hdmi_ctrl) {
@@ -2061,14 +2100,14 @@
return -EINVAL;
}
- rc = hdmi_tx_audio_acr_setup(hdmi_ctrl, true, channels);
+ rc = hdmi_tx_audio_acr_setup(hdmi_ctrl, true);
if (rc) {
DEV_ERR("%s: hdmi_tx_audio_acr_setup failed. rc=%d\n",
__func__, rc);
return rc;
}
- rc = hdmi_tx_audio_iframe_setup(hdmi_ctrl, true, channels, 0, 0, false);
+ rc = hdmi_tx_audio_iframe_setup(hdmi_ctrl, true);
if (rc) {
DEV_ERR("%s: hdmi_tx_audio_iframe_setup failed. rc=%d\n",
__func__, rc);
@@ -2080,9 +2119,10 @@
return 0;
} /* hdmi_tx_audio_setup */
-static void hdmi_tx_audio_off(struct hdmi_tx_ctrl *hdmi_ctrl)
+static void hdmi_tx_audio_off(struct hdmi_tx_ctrl *hdmi_ctrl,
+ bool wait_audio_tx)
{
- u32 i, status, sleep_us, timeout_us, timeout_sec = 15;
+ u32 i = 0, status, sleep_us, timeout_us, timeout_sec = 15;
struct dss_io_data *io = NULL;
if (!hdmi_ctrl) {
@@ -2096,33 +2136,43 @@
return;
}
- /* Check if audio engine is turned off by QDSP or not */
- /* send off notification after every 1 sec for 15 seconds */
- for (i = 0; i < timeout_sec; i++) {
- sleep_us = 5000; /* Maximum time to sleep between two reads */
- timeout_us = 1000 * 1000; /* Total time for condition to meet */
+ if (wait_audio_tx) {
+ /* Check if audio engine is turned off by QDSP or not */
+ /* send off notification after every 1 sec for 15 seconds */
+ for (i = 0; i < timeout_sec; i++) {
+ /* Maximum time to sleep between two reads */
+ sleep_us = 5000;
+ /* Total time for condition to meet */
+ timeout_us = 1000 * 1000;
- if (readl_poll_timeout((io->base + HDMI_AUDIO_CFG),
- status, ((status & BIT(0)) == 0),
- sleep_us, timeout_us)) {
+ if (readl_poll_timeout((io->base + HDMI_AUDIO_CFG),
+ status, ((status & BIT(0)) == 0),
+ sleep_us, timeout_us)) {
- DEV_ERR("%s: audio still on after %d sec. try again\n",
+ DEV_ERR(
+ "%s: audio still on after %d sec. try again\n",
__func__, i+1);
- hdmi_tx_set_audio_switch_node(hdmi_ctrl, 0, true);
- continue;
+ hdmi_tx_set_audio_switch_node(hdmi_ctrl, 0,
+ true);
+ continue;
+ }
+ break;
}
- break;
}
+
if (i == timeout_sec)
DEV_ERR("%s: Error: cannot turn off audio engine\n", __func__);
- if (hdmi_tx_audio_iframe_setup(hdmi_ctrl, false, 0, 0, 0, false))
+ if (hdmi_tx_audio_iframe_setup(hdmi_ctrl, false))
DEV_ERR("%s: hdmi_tx_audio_iframe_setup failed.\n", __func__);
- if (hdmi_tx_audio_acr_setup(hdmi_ctrl, false, 0))
+ if (hdmi_tx_audio_acr_setup(hdmi_ctrl, false))
DEV_ERR("%s: hdmi_tx_audio_acr_setup failed.\n", __func__);
+ hdmi_ctrl->audio_data.sample_rate = AUDIO_SAMPLE_RATE_48KHZ;
+ hdmi_ctrl->audio_data.channel_num = MSM_HDMI_AUDIO_CHANNEL_2;
+
DEV_INFO("HDMI Audio: Disabled\n");
} /* hdmi_tx_audio_off */
@@ -2239,7 +2289,7 @@
if (!hdmi_tx_is_dvi_mode(hdmi_ctrl)) {
hdmi_tx_set_audio_switch_node(hdmi_ctrl, 0, false);
- hdmi_tx_audio_off(hdmi_ctrl);
+ hdmi_tx_audio_off(hdmi_ctrl, true);
}
hdmi_tx_powerdown_phy(hdmi_ctrl);
@@ -2656,7 +2706,8 @@
INIT_WORK(&hdmi_ctrl->power_off_work, hdmi_tx_power_off_work);
- hdmi_ctrl->audio_sample_rate = AUDIO_SAMPLE_RATE_48KHZ;
+ hdmi_ctrl->audio_data.sample_rate = AUDIO_SAMPLE_RATE_48KHZ;
+ hdmi_ctrl->audio_data.channel_num = MSM_HDMI_AUDIO_CHANNEL_2;
hdmi_ctrl->sdev.name = "hdmi";
if (switch_dev_register(&hdmi_ctrl->sdev) < 0) {
@@ -3216,13 +3267,13 @@
__func__, hdmi_tx_pm_name(module_type), rc);
goto error;
}
- mp->vreg_config[j].peak_current = val_array[i];
+ mp->vreg_config[j].enable_load = val_array[i];
DEV_DBG("%s: %s min=%d, max=%d, pc=%d\n", __func__,
mp->vreg_config[j].vreg_name,
mp->vreg_config[j].min_voltage,
mp->vreg_config[j].max_voltage,
- mp->vreg_config[j].peak_current);
+ mp->vreg_config[j].enable_load);
ndx_mask >>= 1;
j++;
diff --git a/drivers/video/msm/mdss/mdss_hdmi_tx.h b/drivers/video/msm/mdss/mdss_hdmi_tx.h
index d4f8e67..18ee782 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_tx.h
+++ b/drivers/video/msm/mdss/mdss_hdmi_tx.h
@@ -38,12 +38,20 @@
struct dss_module_power power_data[HDMI_TX_MAX_PM];
};
+struct hdmi_audio {
+ int sample_rate;
+ int channel_num;
+ int spkr_alloc;
+ int level_shift;
+ int down_mix;
+};
+
struct hdmi_tx_ctrl {
struct platform_device *pdev;
struct hdmi_tx_platform_data pdata;
struct mdss_panel_data panel_data;
- int audio_sample_rate;
+ struct hdmi_audio audio_data;
struct mutex mutex;
struct kobject *kobj;
diff --git a/drivers/video/msm/mdss/mdss_io_util.c b/drivers/video/msm/mdss/mdss_io_util.c
index 31058f8..c862e78 100644
--- a/drivers/video/msm/mdss/mdss_io_util.c
+++ b/drivers/video/msm/mdss/mdss_io_util.c
@@ -213,7 +213,7 @@
}
msleep(in_vreg[i].pre_on_sleep);
rc = regulator_set_optimum_mode(in_vreg[i].vreg,
- in_vreg[i].peak_current);
+ in_vreg[i].enable_load);
if (rc < 0) {
DEV_ERR("%pS->%s: %s set opt m fail\n",
__builtin_return_address(0), __func__,
@@ -233,7 +233,8 @@
for (i = num_vreg-1; i >= 0; i--)
if (regulator_is_enabled(in_vreg[i].vreg)) {
msleep(in_vreg[i].pre_off_sleep);
- regulator_set_optimum_mode(in_vreg[i].vreg, 0);
+ regulator_set_optimum_mode(in_vreg[i].vreg,
+ in_vreg[i].disable_load);
regulator_disable(in_vreg[i].vreg);
msleep(in_vreg[i].post_off_sleep);
}
@@ -241,12 +242,13 @@
return rc;
disable_vreg:
- regulator_set_optimum_mode(in_vreg[i].vreg, 0);
+ regulator_set_optimum_mode(in_vreg[i].vreg, in_vreg[i].disable_load);
vreg_set_opt_mode_fail:
for (i--; i >= 0; i--) {
msleep(in_vreg[i].pre_off_sleep);
- regulator_set_optimum_mode(in_vreg[i].vreg, 0);
+ regulator_set_optimum_mode(in_vreg[i].vreg,
+ in_vreg[i].disable_load);
regulator_disable(in_vreg[i].vreg);
msleep(in_vreg[i].post_off_sleep);
}
diff --git a/drivers/video/msm/mdss/mdss_io_util.h b/drivers/video/msm/mdss/mdss_io_util.h
index cb0fb70..6ad21e8 100644
--- a/drivers/video/msm/mdss/mdss_io_util.h
+++ b/drivers/video/msm/mdss/mdss_io_util.h
@@ -52,7 +52,8 @@
char vreg_name[32];
int min_voltage;
int max_voltage;
- int peak_current;
+ int enable_load;
+ int disable_load;
int pre_on_sleep;
int post_on_sleep;
int pre_off_sleep;
diff --git a/drivers/video/msm/mdss/mdss_mdp.c b/drivers/video/msm/mdss/mdss_mdp.c
index 56a4ac4..0a41ef8 100644
--- a/drivers/video/msm/mdss/mdss_mdp.c
+++ b/drivers/video/msm/mdss/mdss_mdp.c
@@ -1511,10 +1511,16 @@
rc = mdss_mdp_smp_setup(mdata, data[0], data[1]);
- if (rc)
+ if (rc) {
pr_err("unable to setup smp data\n");
+ return rc;
+ }
- return rc;
+ rc = of_property_read_u32(pdev->dev.of_node,
+ "qcom,mdss-smp-mb-per-pipe", data);
+ mdata->smp_mb_per_pipe = (!rc ? data[0] : 0);
+
+ return 0;
}
static int mdss_mdp_parse_dt_misc(struct platform_device *pdev)
diff --git a/drivers/video/msm/mdss/mdss_mdp.h b/drivers/video/msm/mdss/mdss_mdp.h
index 8ecc861..950fd27 100644
--- a/drivers/video/msm/mdss/mdss_mdp.h
+++ b/drivers/video/msm/mdss/mdss_mdp.h
@@ -301,6 +301,11 @@
struct pp_sts_type pp_sts;
};
+struct mdss_mdp_pipe_smp_map {
+ DECLARE_BITMAP(reserved, MDSS_MDP_SMP_MMB_BLOCKS);
+ DECLARE_BITMAP(allocated, MDSS_MDP_SMP_MMB_BLOCKS);
+};
+
struct mdss_mdp_pipe {
u32 num;
u32 type;
@@ -337,8 +342,7 @@
struct mdp_overlay req_data;
u32 params_changed;
- unsigned long smp[MAX_PLANES];
- unsigned long smp_reserved[MAX_PLANES];
+ struct mdss_mdp_pipe_smp_map smp_map[MAX_PLANES];
struct mdss_mdp_data back_buf;
struct mdss_mdp_data front_buf;
diff --git a/drivers/video/msm/mdss/mdss_mdp_ctl.c b/drivers/video/msm/mdss/mdss_mdp_ctl.c
index e656131..f6225ab 100644
--- a/drivers/video/msm/mdss/mdss_mdp_ctl.c
+++ b/drivers/video/msm/mdss/mdss_mdp_ctl.c
@@ -1722,9 +1722,13 @@
static inline int __mdss_mdp_ctl_get_mixer_off(struct mdss_mdp_mixer *mixer)
{
- if (mixer->type == MDSS_MDP_MIXER_TYPE_INTF)
- return MDSS_MDP_REG_CTL_LAYER(mixer->num);
- else
+ if (mixer->type == MDSS_MDP_MIXER_TYPE_INTF) {
+ if (mixer->num == MDSS_MDP_INTF_LAYERMIXER3)
+ return MDSS_MDP_CTL_X_LAYER_5;
+ else
+ return MDSS_MDP_REG_CTL_LAYER(mixer->num);
+ } else {
return MDSS_MDP_REG_CTL_LAYER(mixer->num +
- MDSS_MDP_INTF_MAX_LAYERMIXER);
+ MDSS_MDP_INTF_LAYERMIXER3);
+ }
}
diff --git a/drivers/video/msm/mdss/mdss_mdp_hwio.h b/drivers/video/msm/mdss/mdss_mdp_hwio.h
index 8e5534d..ccd6e56 100644
--- a/drivers/video/msm/mdss/mdss_mdp_hwio.h
+++ b/drivers/video/msm/mdss/mdss_mdp_hwio.h
@@ -235,6 +235,7 @@
#define MDSS_MDP_NUM_REG_MIXERS 3
#define MDSS_MDP_NUM_WB_MIXERS 2
+#define MDSS_MDP_CTL_X_LAYER_5 0x24
enum mdss_mdp_mixer_intf_index {
MDSS_MDP_INTF_LAYERMIXER0,
@@ -496,7 +497,7 @@
#define MDSS_MDP_REG_SMP_ALLOC_W0 0x00180
#define MDSS_MDP_REG_SMP_ALLOC_R0 0x00230
-#define MDSS_MDP_SMP_MMB_BLOCKS 22
+#define MDSS_MDP_SMP_MMB_BLOCKS 44
#define MDSS_MDP_LP_MISR_SEL 0x450
#define MDSS_MDP_LP_MISR_CTRL_MDP 0x454
diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_video.c b/drivers/video/msm/mdss/mdss_mdp_intf_video.c
index ab028e4..9b81633 100644
--- a/drivers/video/msm/mdss/mdss_mdp_intf_video.c
+++ b/drivers/video/msm/mdss/mdss_mdp_intf_video.c
@@ -573,7 +573,7 @@
mdss_mdp_ctl_write(ctl, 0, MDSS_MDP_LM_BORDER_COLOR);
off = MDSS_MDP_REG_INTF_OFFSET(ctl->intf_num);
- if (mdss_mdp_rev == MDSS_MDP_HW_REV_102)
+ if (mdss_mdp_rev >= MDSS_MDP_HW_REV_102)
mdss_v2_intf_off = 0xEC00;
MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_INTF_TIMING_ENGINE_EN -
diff --git a/drivers/video/msm/mdss/mdss_mdp_pipe.c b/drivers/video/msm/mdss/mdss_mdp_pipe.c
index 137da66..eaef12b 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pipe.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pipe.c
@@ -30,6 +30,7 @@
static DECLARE_BITMAP(mdss_mdp_smp_mmb_pool, MDSS_MDP_SMP_MMB_BLOCKS);
static int mdss_mdp_pipe_free(struct mdss_mdp_pipe *pipe);
+static int __mdss_mdp_pipe_smp_mmb_is_empty(unsigned long *smp);
static inline void mdss_mdp_pipe_write(struct mdss_mdp_pipe *pipe,
u32 reg, u32 val)
@@ -94,6 +95,11 @@
}
}
+static int __mdss_mdp_pipe_smp_mmb_is_empty(unsigned long *smp)
+{
+ return bitmap_weight(smp, SMP_MB_CNT) == 0;
+}
+
static void mdss_mdp_smp_set_wm_levels(struct mdss_mdp_pipe *pipe, int mb_cnt)
{
u32 fetch_size, val, wm[3];
@@ -132,8 +138,8 @@
mutex_lock(&mdss_mdp_smp_lock);
for (i = 0; i < MAX_PLANES; i++) {
- mdss_mdp_smp_mmb_free(&pipe->smp_reserved[i], false);
- mdss_mdp_smp_mmb_free(&pipe->smp[i], true);
+ mdss_mdp_smp_mmb_free(pipe->smp_map[i].reserved, false);
+ mdss_mdp_smp_mmb_free(pipe->smp_map[i].allocated, true);
}
mutex_unlock(&mdss_mdp_smp_lock);
}
@@ -144,7 +150,7 @@
mutex_lock(&mdss_mdp_smp_lock);
for (i = 0; i < MAX_PLANES; i++)
- mdss_mdp_smp_mmb_free(&pipe->smp_reserved[i], false);
+ mdss_mdp_smp_mmb_free(pipe->smp_map[i].reserved, false);
mutex_unlock(&mdss_mdp_smp_lock);
}
@@ -193,13 +199,17 @@
if (mdata->mdp_rev == MDSS_MDP_HW_REV_100)
num_blks = roundup_pow_of_two(num_blks);
+
+ if (mdata->smp_mb_per_pipe &&
+ (num_blks > mdata->smp_mb_per_pipe) &&
+ !(pipe->flags & MDP_FLIP_LR))
+ num_blks = mdata->smp_mb_per_pipe;
}
pr_debug("reserving %d mmb for pnum=%d plane=%d\n",
num_blks, pipe->num, i);
- reserved = mdss_mdp_smp_mmb_reserve(&pipe->smp[i],
- &pipe->smp_reserved[i], num_blks);
-
+ reserved = mdss_mdp_smp_mmb_reserve(pipe->smp_map[i].allocated,
+ pipe->smp_map[i].reserved, num_blks);
if (reserved < num_blks)
break;
}
@@ -207,7 +217,8 @@
if (reserved < num_blks) {
pr_debug("insufficient MMB blocks\n");
for (; i >= 0; i--)
- mdss_mdp_smp_mmb_free(&pipe->smp_reserved[i], false);
+ mdss_mdp_smp_mmb_free(pipe->smp_map[i].reserved,
+ false);
rc = -ENOMEM;
}
mutex_unlock(&mdss_mdp_smp_lock);
@@ -222,8 +233,12 @@
mutex_lock(&mdss_mdp_smp_lock);
for (i = 0; i < MAX_PLANES; i++) {
- mdss_mdp_smp_mmb_amend(&pipe->smp[i], &pipe->smp_reserved[i]);
- cnt += mdss_mdp_smp_mmb_set(pipe->ftch_id + i, &pipe->smp[i]);
+ if (__mdss_mdp_pipe_smp_mmb_is_empty(pipe->smp_map[i].reserved))
+ continue;
+ mdss_mdp_smp_mmb_amend(pipe->smp_map[i].allocated,
+ pipe->smp_map[i].reserved);
+ cnt += mdss_mdp_smp_mmb_set(pipe->ftch_id + i,
+ pipe->smp_map[i].allocated);
}
mdss_mdp_smp_set_wm_levels(pipe, cnt);
mutex_unlock(&mdss_mdp_smp_lock);
@@ -701,10 +716,9 @@
if (pipe->type == MDSS_MDP_PIPE_TYPE_VIG)
mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_VIG_OP_MODE,
opmode);
-
- mdss_mdp_smp_alloc(pipe);
}
+ mdss_mdp_smp_alloc(pipe);
ret = mdss_mdp_src_addr_setup(pipe, src_data);
if (ret) {
pr_err("addr setup error for pnum=%d\n", pipe->num);
diff --git a/drivers/video/msm/mdss/mhl_sii8334.c b/drivers/video/msm/mdss/mhl_sii8334.c
index 3f03725..82b56e3 100644
--- a/drivers/video/msm/mdss/mhl_sii8334.c
+++ b/drivers/video/msm/mdss/mhl_sii8334.c
@@ -373,7 +373,7 @@
/* USB_HANDSHAKING FUNCTIONS */
static int mhl_sii_device_discovery(void *data, int id,
- void (*usb_notify_cb)(int online))
+ void (*usb_notify_cb)(void *, int), void *ctx)
{
int rc;
struct mhl_tx_ctrl *mhl_ctrl = data;
@@ -398,8 +398,10 @@
return -EINVAL;
}
- if (!mhl_ctrl->notify_usb_online)
+ if (!mhl_ctrl->notify_usb_online) {
mhl_ctrl->notify_usb_online = usb_notify_cb;
+ mhl_ctrl->notify_ctx = ctx;
+ }
if (!mhl_ctrl->disc_enabled) {
spin_lock_irqsave(&mhl_ctrl->lock, flags);
@@ -904,7 +906,7 @@
mhl_ctrl->mhl_mode = 1;
power_supply_changed(&mhl_ctrl->mhl_psy);
if (mhl_ctrl->notify_usb_online)
- mhl_ctrl->notify_usb_online(1);
+ mhl_ctrl->notify_usb_online(mhl_ctrl->notify_ctx, 1);
} else {
pr_debug("%s: non-mhl sink\n", __func__);
mhl_ctrl->mhl_mode = 0;
@@ -1004,7 +1006,7 @@
mhl_msm_disconnection(mhl_ctrl);
power_supply_changed(&mhl_ctrl->mhl_psy);
if (mhl_ctrl->notify_usb_online)
- mhl_ctrl->notify_usb_online(0);
+ mhl_ctrl->notify_usb_online(mhl_ctrl->notify_ctx, 0);
return 0;
}
@@ -1019,7 +1021,7 @@
mhl_msm_disconnection(mhl_ctrl);
power_supply_changed(&mhl_ctrl->mhl_psy);
if (mhl_ctrl->notify_usb_online)
- mhl_ctrl->notify_usb_online(0);
+ mhl_ctrl->notify_usb_online(mhl_ctrl->notify_ctx, 0);
return 0;
}
diff --git a/include/linux/coresight.h b/include/linux/coresight.h
index cfc690e..5b69884 100644
--- a/include/linux/coresight.h
+++ b/include/linux/coresight.h
@@ -39,8 +39,8 @@
enum coresight_clk_rate {
CORESIGHT_CLK_RATE_OFF,
- CORESIGHT_CLK_RATE_TRACE,
- CORESIGHT_CLK_RATE_HSTRACE,
+ CORESIGHT_CLK_RATE_TRACE = 1000,
+ CORESIGHT_CLK_RATE_HSTRACE = 2000,
};
enum coresight_dev_type {
diff --git a/include/linux/epm_adc.h b/include/linux/epm_adc.h
index 4fa41b5..6f00df7 100644
--- a/include/linux/epm_adc.h
+++ b/include/linux/epm_adc.h
@@ -97,6 +97,23 @@
uint32_t gain;
};
+struct epm_marker_level {
+ uint8_t level;
+};
+
+struct epm_gpio_buffer_request {
+ uint8_t cmd;
+ uint8_t bitmask_monitor_pin;
+ uint8_t status;
+};
+
+struct epm_get_gpio_buffer_resp {
+ uint8_t cmd;
+ uint8_t status;
+ uint8_t bitmask_monitor_pin;
+ uint32_t timestamp;
+};
+
#ifdef __KERNEL__
struct epm_adc_platform_data {
struct epm_chan_properties *channel;
@@ -121,7 +138,19 @@
#define EPM_ADC_DEINIT _IOR(EPM_ADC_IOCTL_CODE, 3, \
uint32_t)
-#define EPM_PSOC_ADC_INIT _IOR(EPM_ADC_IOCTL_CODE, 4, \
+#define EPM_MARKER1_REQUEST _IOWR(EPM_ADC_IOCTL_CODE, 90, \
+ uint32_t)
+
+#define EPM_MARKER1_RELEASE _IOWR(EPM_ADC_IOCTL_CODE, 91, \
+ uint32_t)
+
+#define EPM_MARKER2_REQUEST _IOWR(EPM_ADC_IOCTL_CODE, 95, \
+ uint32_t)
+
+#define EPM_MARKER2_RELEASE _IOWR(EPM_ADC_IOCTL_CODE, 92, \
+ uint32_t)
+
+#define EPM_PSOC_ADC_INIT _IOWR(EPM_ADC_IOCTL_CODE, 4, \
struct epm_psoc_init_resp)
#define EPM_PSOC_ADC_CHANNEL_ENABLE _IOWR(EPM_ADC_IOCTL_CODE, 5, \
@@ -157,4 +186,13 @@
#define EPM_PSOC_ADC_SET_VADC_REFERENCE _IOWR(EPM_ADC_IOCTL_CODE, 15, \
struct epm_psoc_set_vadc)
+#define EPM_PSOC_ADC_DEINIT _IOWR(EPM_ADC_IOCTL_CODE, 16, \
+ uint32_t)
+
+#define EPM_PSOC_GPIO_BUFFER_REQUEST _IOWR(EPM_ADC_IOCTL_CODE, 17, \
+ uint32_t)
+
+#define EPM_PSOC_GET_GPIO_BUFFER_DATA _IOWR(EPM_ADC_IOCTL_CODE, 18, \
+ uint32_t)
+
#endif /* __EPM_ADC_H */
diff --git a/include/linux/i2c/atmel_mxt_ts.h b/include/linux/i2c/atmel_mxt_ts.h
index b903dfb..e9fbf90 100644
--- a/include/linux/i2c/atmel_mxt_ts.h
+++ b/include/linux/i2c/atmel_mxt_ts.h
@@ -77,6 +77,7 @@
int *key_codes;
bool need_calibration;
bool no_force_update;
+ bool no_lpm_support;
u8 bl_addr;
u8(*read_chg) (void);
diff --git a/include/linux/input/kxtj9.h b/include/linux/input/kxtj9.h
index d415579..65378c0 100644
--- a/include/linux/input/kxtj9.h
+++ b/include/linux/input/kxtj9.h
@@ -46,7 +46,7 @@
/* Output resolution: 8-bit valid or 12-bit valid */
#define RES_8BIT 0
#define RES_12BIT (1 << 6)
- u8 res_12bit;
+ u8 res_ctl;
/* Output g-range: +/-2g, 4g, or 8g */
#define KXTJ9_G_2G 0
#define KXTJ9_G_4G (1 << 3)
diff --git a/include/linux/input/mpu3050.h b/include/linux/input/mpu3050.h
index 61a2920..f87dfe3 100644
--- a/include/linux/input/mpu3050.h
+++ b/include/linux/input/mpu3050.h
@@ -25,6 +25,7 @@
int (*power_off)(void);
int gpio_int;
+ int gpio_en;
int gpio_fsync;
};
diff --git a/include/linux/mhl_8334.h b/include/linux/mhl_8334.h
index 7297ff3..560f75b 100644
--- a/include/linux/mhl_8334.h
+++ b/include/linux/mhl_8334.h
@@ -137,7 +137,8 @@
uint8_t chip_rev_id;
int mhl_mode;
struct completion rgnd_done;
- void (*notify_usb_online)(int online);
+ void (*notify_usb_online)(void *ctx, int online);
+ void *notify_ctx;
struct usb_ext_notification *mhl_info;
bool disc_enabled;
struct power_supply mhl_psy;
diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h
index f548721..e3ff5db 100644
--- a/include/linux/mmc/core.h
+++ b/include/linux/mmc/core.h
@@ -99,8 +99,8 @@
*/
unsigned int cmd_timeout_ms; /* in milliseconds */
- /* Set this flag only for blocking bkops request */
- bool bkops_busy;
+ /* Set this flag only for commands which can be HPIed */
+ bool ignore_timeout;
struct mmc_data *data; /* data segment associated with cmd */
struct mmc_request *mrq; /* associated request */
@@ -162,6 +162,8 @@
extern int __mmc_switch(struct mmc_card *, u8, u8, u8, unsigned int, bool,
bool);
extern int mmc_switch(struct mmc_card *, u8, u8, u8, unsigned int);
+extern int mmc_switch_ignore_timeout(struct mmc_card *, u8, u8, u8,
+ unsigned int);
extern int mmc_send_ext_csd(struct mmc_card *card, u8 *ext_csd);
#define MMC_ERASE_ARG 0x00000000
diff --git a/include/linux/msm_audio_acdb.h b/include/linux/msm_audio_acdb.h
index a741107..e8ca1cd 100644
--- a/include/linux/msm_audio_acdb.h
+++ b/include/linux/msm_audio_acdb.h
@@ -54,12 +54,16 @@
#define AUDIO_SET_ASM_CUSTOM_TOPOLOGY _IOW(AUDIO_IOCTL_MAGIC, \
(AUDIO_MAX_COMMON_IOCTL_NUM+24), unsigned)
#define AUDIO_SET_SPEAKER_PROT _IOW(AUDIO_IOCTL_MAGIC, 25, \
- struct msm_spk_prot_cfg)
+ struct msm_spk_prot_cfg)
#define AUDIO_GET_SPEAKER_PROT _IOR(AUDIO_IOCTL_MAGIC, 26, \
- struct msm_spk_prot_status)
+ struct msm_spk_prot_status)
#define AUDIO_SET_AANC_CAL _IOW(AUDIO_IOCTL_MAGIC, \
(AUDIO_MAX_COMMON_IOCTL_NUM+27), unsigned)
-#define AUDIO_MAX_ACDB_IOCTL (AUDIO_MAX_COMMON_IOCTL_NUM+30)
+#define AUDIO_REGISTER_VOCPROC_VOL_TABLE _IOW(AUDIO_IOCTL_MAGIC, \
+ (AUDIO_MAX_COMMON_IOCTL_NUM+28), unsigned)
+#define AUDIO_DEREGISTER_VOCPROC_VOL_TABLE _IOW(AUDIO_IOCTL_MAGIC, \
+ (AUDIO_MAX_COMMON_IOCTL_NUM+29), unsigned)
+#define AUDIO_MAX_ACDB_IOCTL (AUDIO_MAX_COMMON_IOCTL_NUM+40)
/* ACDB structures */
struct cal_block {
diff --git a/include/linux/pinctrl/pinconf-generic.h b/include/linux/pinctrl/pinconf-generic.h
index 72474e1..9fd5ec5 100644
--- a/include/linux/pinctrl/pinconf-generic.h
+++ b/include/linux/pinctrl/pinconf-generic.h
@@ -29,12 +29,21 @@
* if for example some other pin is going to drive the signal connected
* to it for a while. Pins used for input are usually always high
* impedance.
+ * @PIN_CONFIG_BIAS_BUS_HOLD: the pin will be set to weakly latch so that it
+ * weakly drives the last value on a tristate bus, also known as a "bus
+ * holder", "bus keeper" or "repeater". This allows another device on the
+ * bus to change the value by driving the bus high or low and switching to
+ * tristate. The argument is ignored.
* @PIN_CONFIG_BIAS_PULL_UP: the pin will be pulled up (usually with high
* impedance to VDD). If the argument is != 0 pull-up is enabled,
* if it is 0, pull-up is disabled.
* @PIN_CONFIG_BIAS_PULL_DOWN: the pin will be pulled down (usually with high
* impedance to GROUND). If the argument is != 0 pull-down is enabled,
* if it is 0, pull-down is disabled.
+ * @PIN_CONFIG_BIAS_PULL_PIN_DEFAULT: the pin will be pulled up or down based
+ * on embedded knowledge of the controller, like current mux function.
+ * If the argument is != 0 pull up/down is enabled, if it is 0,
+ * the pull is disabled.
* @PIN_CONFIG_DRIVE_PUSH_PULL: the pin will be driven actively high and
* low, this is the most typical case and is typically achieved with two
* active transistors on the output. Sending this config will enabale
@@ -78,8 +87,10 @@
enum pin_config_param {
PIN_CONFIG_BIAS_DISABLE,
PIN_CONFIG_BIAS_HIGH_IMPEDANCE,
+ PIN_CONFIG_BIAS_BUS_HOLD,
PIN_CONFIG_BIAS_PULL_UP,
PIN_CONFIG_BIAS_PULL_DOWN,
+ PIN_CONFIG_BIAS_PULL_PIN_DEFAULT,
PIN_CONFIG_DRIVE_PUSH_PULL,
PIN_CONFIG_DRIVE_OPEN_DRAIN,
PIN_CONFIG_DRIVE_OPEN_SOURCE,
diff --git a/include/linux/smux.h b/include/linux/smux.h
index 56b18fa..1157cef 100644
--- a/include/linux/smux.h
+++ b/include/linux/smux.h
@@ -1,6 +1,6 @@
/* include/linux/smux.h
*
- * Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -79,6 +79,8 @@
SMUX_HIGH_WM_HIT, /* @metadata is NULL */
SMUX_RX_RETRY_HIGH_WM_HIT, /* @metadata is NULL */
SMUX_RX_RETRY_LOW_WM_HIT, /* @metadata is NULL */
+ SMUX_LOCAL_CLOSED,
+ SMUX_REMOTE_CLOSED,
};
/**
diff --git a/include/linux/usb/Kbuild b/include/linux/usb/Kbuild
index b607f35..087d163 100644
--- a/include/linux/usb/Kbuild
+++ b/include/linux/usb/Kbuild
@@ -5,6 +5,7 @@
header-y += functionfs.h
header-y += gadgetfs.h
header-y += midi.h
+header-y += msm_ext_chg.h
header-y += g_printer.h
header-y += tmc.h
header-y += video.h
diff --git a/include/linux/usb/msm_ext_chg.h b/include/linux/usb/msm_ext_chg.h
new file mode 100644
index 0000000..dcc786d
--- /dev/null
+++ b/include/linux/usb/msm_ext_chg.h
@@ -0,0 +1,31 @@
+#ifndef __LINUX_USB_MSM_EXT_CHG_H
+#define __LINUX_USB_MSM_EXT_CHG_H
+
+#include <linux/ioctl.h>
+
+#define USB_CHG_BLOCK_ULPI 1
+#define USB_CHG_BLOCK_QSCRATCH 2
+
+/**
+ * struct msm_usb_chg_info - MSM USB charger block details.
+ * @chg_block_type: The type of charger block. QSCRATCH/ULPI.
+ * @page_offset: USB charger register base may not be aligned to
+ * PAGE_SIZE. The kernel driver aligns the base
+ * address and use it for memory mapping. This
+ * page_offset is used by user space to calaculate
+ * the corret charger register base address.
+ * @length: The length of the charger register address space.
+ */
+struct msm_usb_chg_info {
+ uint32_t chg_block_type;
+ off_t page_offset;
+ size_t length;
+};
+
+/* Get the MSM USB charger block information */
+#define MSM_USB_EXT_CHG_INFO _IOW('M', 0, struct msm_usb_chg_info)
+
+/* Vote against USB hardware low power mode */
+#define MSM_USB_EXT_CHG_BLOCK_LPM _IOW('M', 1, int)
+
+#endif /* __LINUX_USB_MSM_EXT_CHG_H */
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index 1c9884c..f04d2bf 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -26,6 +26,7 @@
#include <linux/pm_qos.h>
#include <linux/hrtimer.h>
#include <linux/power_supply.h>
+#include <linux/cdev.h>
/*
* The following are bit fields describing the usb_request.udc_priv word.
* These bit fields are set by function drivers that wish to queue
@@ -347,6 +348,7 @@
struct clk *phy_reset_clk;
struct clk *core_clk;
long core_clk_rate;
+ struct resource *io_res;
void __iomem *regs;
#define ID 0
#define B_SESS_VLD 1
@@ -434,6 +436,14 @@
unsigned int online;
unsigned int host_mode;
unsigned int current_max;
+
+ dev_t ext_chg_dev;
+ struct cdev ext_chg_cdev;
+ struct class *ext_chg_class;
+ struct device *ext_chg_device;
+ bool ext_chg_opened;
+ bool ext_chg_active;
+ struct completion ext_chg_wait;
};
struct ci13xxx_platform_data {
@@ -496,7 +506,7 @@
/**
* struct usb_ext_notification: event notification structure
* @notify: pointer to client function to call when ID event is detected.
- * The last parameter is provided by driver to be called back when
+ * The function parameter is provided by driver to be called back when
* external client indicates it is done using the USB. This function
* should return 0 if handled successfully, otherise an error code.
* @ctxt: client-specific context pointer
@@ -510,7 +520,7 @@
* called with the online parameter set to false.
*/
struct usb_ext_notification {
- int (*notify)(void *, int, void (*)(int online));
+ int (*notify)(void *, int, void (*)(void *, int online), void *);
void *ctxt;
};
#ifdef CONFIG_USB_BAM
@@ -540,7 +550,7 @@
int msm_data_fifo_config(struct usb_ep *ep, u32 addr, u32 size,
u8 dst_pipe_idx);
-void msm_dwc3_restart_usb_session(void);
+void msm_dwc3_restart_usb_session(struct usb_gadget *gadget);
int msm_register_usb_ext_notification(struct usb_ext_notification *info);
#else
@@ -560,7 +570,7 @@
return -ENODEV;
}
-static inline void msm_dwc3_restart_usb_session(void)
+static inline void msm_dwc3_restart_usb_session(struct usb_gadget *gadget)
{
return;
}
diff --git a/include/linux/usb/msm_hsusb_hw.h b/include/linux/usb/msm_hsusb_hw.h
index ba75cb9..064d210 100644
--- a/include/linux/usb/msm_hsusb_hw.h
+++ b/include/linux/usb/msm_hsusb_hw.h
@@ -24,6 +24,7 @@
#define USB_HS_GPTIMER_BASE (MSM_USB_BASE + 0x80)
#define GENCFG2_SESS_VLD_CTRL_EN BIT(7)
+#define GENCFG2_LINESTATE_DIFF_WAKEUP_EN BIT(12)
#define USB_USBCMD (MSM_USB_BASE + 0x0140)
#define USB_USBSTS (MSM_USB_BASE + 0x0144)
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index 81187aa..7ad0c16 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -1856,6 +1856,21 @@
V4L2_MPEG_VIDC_VIDEO_H264_VUI_TIMING_INFO_DISABLED = 0,
V4L2_MPEG_VIDC_VIDEO_H264_VUI_TIMING_INFO_ENABLED = 1
};
+
+#define V4L2_CID_MPEG_VIDC_VIDEO_ALLOC_MODE \
+ (V4L2_CID_MPEG_MSM_VIDC_BASE+30)
+enum v4l2_mpeg_vidc_video_alloc_mode_type {
+ V4L2_MPEG_VIDC_VIDEO_STATIC = 0,
+ V4L2_MPEG_VIDC_VIDEO_RING = 1,
+};
+
+#define V4L2_CID_MPEG_VIDC_VIDEO_FRAME_ASSEMBLY \
+ (V4L2_CID_MPEG_MSM_VIDC_BASE+31)
+enum v4l2_mpeg_vidc_video_assembly {
+ V4L2_MPEG_VIDC_FRAME_ASSEMBLY_DISABLE = 0,
+ V4L2_MPEG_VIDC_FRAME_ASSEMBLY_ENABLE = 1,
+};
+
/* Camera class control IDs */
#define V4L2_CID_CAMERA_CLASS_BASE (V4L2_CTRL_CLASS_CAMERA | 0x900)
#define V4L2_CID_CAMERA_CLASS (V4L2_CTRL_CLASS_CAMERA | 1)
diff --git a/include/media/msm_cam_sensor.h b/include/media/msm_cam_sensor.h
index 6358f8a..2805401 100644
--- a/include/media/msm_cam_sensor.h
+++ b/include/media/msm_cam_sensor.h
@@ -46,6 +46,8 @@
#define MAX_EEPROM_NAME 32
+#define MAX_AF_ITERATIONS 3
+
enum msm_camera_i2c_reg_addr_type {
MSM_CAMERA_I2C_BYTE_ADDR = 1,
MSM_CAMERA_I2C_WORD_ADDR,
@@ -78,6 +80,11 @@
enum msm_sensor_power_seq_gpio_t {
SENSOR_GPIO_RESET,
SENSOR_GPIO_STANDBY,
+ SENSOR_GPIO_AF_PWDM,
+ SENSOR_GPIO_VIO,
+ SENSOR_GPIO_VANA,
+ SENSOR_GPIO_VDIG,
+ SENSOR_GPIO_VAF,
SENSOR_GPIO_MAX,
};
@@ -133,6 +140,11 @@
REG_GPIO,
};
+enum sensor_af_t {
+ SENSOR_AF_FOCUSSED,
+ SENSOR_AF_NOT_FOCUSSED,
+};
+
struct msm_sensor_power_setting {
enum msm_sensor_power_seq_type_t seq_type;
uint16_t seq_val;
@@ -346,6 +358,11 @@
CFG_SET_RESOLUTION,
CFG_SET_STOP_STREAM,
CFG_SET_START_STREAM,
+ CFG_SET_SATURATION,
+ CFG_SET_CONTRAST,
+ CFG_SET_SHARPNESS,
+ CFG_SET_AUTOFOCUS,
+ CFG_CANCEL_AUTOFOCUS,
};
enum msm_actuator_cfg_type_t {
@@ -509,6 +526,9 @@
#define VIDIOC_MSM_EEPROM_CFG \
_IOWR('V', BASE_VIDIOC_PRIVATE + 8, struct msm_eeprom_cfg_data)
+#define VIDIOC_MSM_SENSOR_GET_AF_STATUS \
+ _IOWR('V', BASE_VIDIOC_PRIVATE + 9, uint32_t)
+
#define MSM_V4L2_PIX_FMT_META v4l2_fourcc('M', 'E', 'T', 'A') /* META */
#endif /* __LINUX_MSM_CAM_SENSOR_H */
diff --git a/include/trace/events/sched.h b/include/trace/events/sched.h
index ea7a203..41f8607 100644
--- a/include/trace/events/sched.h
+++ b/include/trace/events/sched.h
@@ -51,6 +51,44 @@
);
/*
+ * Tracepoint for task enqueue/dequeue:
+ */
+TRACE_EVENT(sched_enq_deq_task,
+
+ TP_PROTO(struct task_struct *p, int enqueue),
+
+ TP_ARGS(p, enqueue),
+
+ TP_STRUCT__entry(
+ __array( char, comm, TASK_COMM_LEN )
+ __field( pid_t, pid )
+ __field( int, prio )
+ __field( int, cpu )
+ __field( int, enqueue )
+ __field(unsigned int, nr_running )
+ __field(unsigned long, cpu_load )
+ __field(unsigned int, rt_nr_running )
+ ),
+
+ TP_fast_assign(
+ memcpy(__entry->comm, p->comm, TASK_COMM_LEN);
+ __entry->pid = p->pid;
+ __entry->prio = p->prio;
+ __entry->cpu = task_cpu(p);
+ __entry->enqueue = enqueue;
+ __entry->nr_running = task_rq(p)->nr_running;
+ __entry->cpu_load = task_rq(p)->cpu_load[0];
+ __entry->rt_nr_running = task_rq(p)->rt.rt_nr_running;
+ ),
+
+ TP_printk("cpu=%d %s comm=%s pid=%d prio=%d nr_running=%u cpu_load=%lu rt_nr_running=%u",
+ __entry->cpu, __entry->enqueue ? "enqueue" : "dequeue",
+ __entry->comm, __entry->pid,
+ __entry->prio, __entry->nr_running,
+ __entry->cpu_load, __entry->rt_nr_running)
+);
+
+/*
* Tracepoint for waking up a task:
*/
DECLARE_EVENT_CLASS(sched_wakeup_template,
@@ -179,6 +217,31 @@
__entry->orig_cpu, __entry->dest_cpu)
);
+/*
+ * Tracepoint for a CPU going offline/online:
+ */
+TRACE_EVENT(sched_cpu_hotplug,
+
+ TP_PROTO(int affected_cpu, int error, int status),
+
+ TP_ARGS(affected_cpu, error, status),
+
+ TP_STRUCT__entry(
+ __field( int, affected_cpu )
+ __field( int, error )
+ __field( int, status )
+ ),
+
+ TP_fast_assign(
+ __entry->affected_cpu = affected_cpu;
+ __entry->error = error;
+ __entry->status = status;
+ ),
+
+ TP_printk("cpu %d %s error=%d", __entry->affected_cpu,
+ __entry->status ? "online" : "offline", __entry->error)
+);
+
DECLARE_EVENT_CLASS(sched_process_template,
TP_PROTO(struct task_struct *p),
diff --git a/kernel/cpu.c b/kernel/cpu.c
index fb4a5ac..d5ab2e6 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -17,6 +17,8 @@
#include <linux/gfp.h>
#include <linux/suspend.h>
+#include <trace/events/sched.h>
+
#ifdef CONFIG_SMP
/* Serializes the updates to cpu_online_mask, cpu_present_mask */
static DEFINE_MUTEX(cpu_add_remove_lock);
@@ -264,6 +266,7 @@
out_release:
cpu_hotplug_done();
+ trace_sched_cpu_hotplug(cpu, err, 0);
if (!err)
cpu_notify_nofail(CPU_POST_DEAD | mod, hcpu);
return err;
@@ -321,6 +324,7 @@
if (ret != 0)
__cpu_notify(CPU_UP_CANCELED | mod, hcpu, nr_calls, NULL);
cpu_hotplug_done();
+ trace_sched_cpu_hotplug(cpu, ret, 1);
return ret;
}
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 3513fef..d9c4b64 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -727,6 +727,7 @@
update_rq_clock(rq);
sched_info_queued(p);
p->sched_class->enqueue_task(rq, p, flags);
+ trace_sched_enq_deq_task(p, 1);
}
static void dequeue_task(struct rq *rq, struct task_struct *p, int flags)
@@ -734,6 +735,7 @@
update_rq_clock(rq);
sched_info_dequeued(p);
p->sched_class->dequeue_task(rq, p, flags);
+ trace_sched_enq_deq_task(p, 0);
}
void activate_task(struct rq *rq, struct task_struct *p, int flags)
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 68fd9d7..1dee449 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -3031,10 +3031,10 @@
params.listen_interval =
nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]);
- if (info->attrs[NL80211_ATTR_STA_AID])
- params.aid = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]);
- else
+ if (info->attrs[NL80211_ATTR_PEER_AID])
params.aid = nla_get_u16(info->attrs[NL80211_ATTR_PEER_AID]);
+ else
+ params.aid = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]);
if (!params.aid || params.aid > IEEE80211_MAX_AID)
return -EINVAL;
@@ -3104,7 +3104,8 @@
params.sta_modify_mask |= STATION_PARAM_APPLY_UAPSD;
}
/* TDLS peers cannot be added */
- if (params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))
+ if ((params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) ||
+ info->attrs[NL80211_ATTR_PEER_AID])
return -EINVAL;
/* but don't bother the driver with it */
params.sta_flags_mask &= ~BIT(NL80211_STA_FLAG_TDLS_PEER);
@@ -3116,7 +3117,8 @@
break;
case NL80211_IFTYPE_MESH_POINT:
/* TDLS peers cannot be added */
- if (params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))
+ if ((params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) ||
+ info->attrs[NL80211_ATTR_PEER_AID])
return -EINVAL;
break;
case NL80211_IFTYPE_STATION:
diff --git a/sound/soc/codecs/msm8x10-wcd.c b/sound/soc/codecs/msm8x10-wcd.c
index 53cfb3e..de0b4da 100644
--- a/sound/soc/codecs/msm8x10-wcd.c
+++ b/sound/soc/codecs/msm8x10-wcd.c
@@ -35,9 +35,11 @@
#include <sound/soc-dapm.h>
#include <sound/tlv.h>
#include <mach/qdsp6v2/apr.h>
+#include <mach/subsystem_notif.h>
#include "msm8x10-wcd.h"
#include "wcd9xxx-resmgr.h"
#include "msm8x10_wcd_registers.h"
+#include "../msm/qdsp6v2/q6core.h"
#define MSM8X10_WCD_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\
SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000)
@@ -186,6 +188,11 @@
struct msm8x10_wcd_i2c msm8x10_wcd_modules[MAX_MSM8X10_WCD_DEVICE];
+static void *adsp_state_notifier;
+
+static struct snd_soc_codec *registered_codec;
+#define ADSP_STATE_READY_TIMEOUT_MS 2000
+
static int get_i2c_msm8x10_wcd_device_info(u16 reg,
struct msm8x10_wcd_i2c **msm8x10_wcd)
@@ -2549,6 +2556,53 @@
return NULL;
}
+static int msm8x10_wcd_device_up(struct snd_soc_codec *codec)
+{
+ pr_debug("%s: device up!\n", __func__);
+
+ mutex_lock(&codec->mutex);
+
+ msm8x10_wcd_bringup(codec);
+ msm8x10_wcd_codec_init_reg(codec);
+ msm8x10_wcd_update_reg_defaults(codec);
+
+ mutex_unlock(&codec->mutex);
+
+ return 0;
+}
+
+static int adsp_state_callback(struct notifier_block *nb, unsigned long value,
+ void *priv)
+{
+ bool timedout;
+ unsigned long timeout;
+
+ if (value == SUBSYS_AFTER_POWERUP) {
+ pr_debug("%s: ADSP is about to power up. bring up codec\n",
+ __func__);
+
+ timeout = jiffies +
+ msecs_to_jiffies(ADSP_STATE_READY_TIMEOUT_MS);
+ while (!(timedout = time_after(jiffies, timeout))) {
+ if (!q6core_is_adsp_ready()) {
+ pr_debug("%s: ADSP isn't ready\n", __func__);
+ } else {
+ pr_debug("%s: ADSP is ready\n", __func__);
+ msm8x10_wcd_device_up(registered_codec);
+ break;
+ }
+ }
+ }
+
+ return NOTIFY_OK;
+}
+
+static struct notifier_block adsp_state_notifier_block = {
+ .notifier_call = adsp_state_callback,
+ .priority = -INT_MAX,
+};
+
+
static int msm8x10_wcd_codec_probe(struct snd_soc_codec *codec)
{
struct msm8x10_wcd_priv *msm8x10_wcd;
@@ -2591,6 +2645,16 @@
msm8x10_wcd->mbhc_polling_active = false;
mutex_init(&msm8x10_wcd->codec_resource_lock);
+ registered_codec = codec;
+ adsp_state_notifier =
+ subsys_notif_register_notifier("adsp",
+ &adsp_state_notifier_block);
+ if (!adsp_state_notifier) {
+ pr_err("%s: Failed to register adsp state notifier\n",
+ __func__);
+ registered_codec = NULL;
+ return -ENOMEM;
+ }
return 0;
}
diff --git a/sound/soc/codecs/msm_hdmi_codec_rx.c b/sound/soc/codecs/msm_hdmi_codec_rx.c
index 46bce9e..e5d5c32 100644
--- a/sound/soc/codecs/msm_hdmi_codec_rx.c
+++ b/sound/soc/codecs/msm_hdmi_codec_rx.c
@@ -113,7 +113,7 @@
channel_allocation);
codec_data->hdmi_ops.audio_info_setup(codec_data->hdmi_core_pdev,
- num_channels, channel_allocation,
+ params_rate(params), num_channels, channel_allocation,
level_shift, down_mix);
return 0;
diff --git a/sound/soc/codecs/wcd9310.c b/sound/soc/codecs/wcd9310.c
index 69e4cca..212924fd 100644
--- a/sound/soc/codecs/wcd9310.c
+++ b/sound/soc/codecs/wcd9310.c
@@ -2639,17 +2639,31 @@
case SND_SOC_DAPM_PRE_PMU:
(*dmic_clk_cnt)++;
- if (*dmic_clk_cnt == 1)
+ if (*dmic_clk_cnt == 1) {
+ snd_soc_update_bits(codec,
+ TABLA_A_CDC_DMIC_CLK0_MODE, 0x7, 0x0);
+ snd_soc_update_bits(codec,
+ TABLA_A_CDC_DMIC_CLK1_MODE, 0x7, 0x0);
+ snd_soc_update_bits(codec,
+ TABLA_A_CDC_DMIC_CLK2_MODE, 0x7, 0x0);
snd_soc_update_bits(codec, TABLA_A_CDC_CLK_DMIC_CTL,
dmic_clk_en, dmic_clk_en);
+ }
break;
case SND_SOC_DAPM_POST_PMD:
(*dmic_clk_cnt)--;
- if (*dmic_clk_cnt == 0)
+ if (*dmic_clk_cnt == 0) {
snd_soc_update_bits(codec, TABLA_A_CDC_CLK_DMIC_CTL,
dmic_clk_en, 0);
+ snd_soc_update_bits(codec,
+ TABLA_A_CDC_DMIC_CLK0_MODE, 0x7, 0x4);
+ snd_soc_update_bits(codec,
+ TABLA_A_CDC_DMIC_CLK1_MODE, 0x7, 0x4);
+ snd_soc_update_bits(codec,
+ TABLA_A_CDC_DMIC_CLK2_MODE, 0x7, 0x4);
+ }
break;
}
return 0;
@@ -8772,6 +8786,13 @@
tabla_2_higher_codec_reg_init_val[i].mask,
tabla_2_higher_codec_reg_init_val[i].val);
}
+ snd_soc_update_bits(codec, TABLA_A_CDC_DMIC_CLK0_MODE, 0x7, 0x4);
+ snd_soc_update_bits(codec, TABLA_A_CDC_DMIC_CLK1_MODE, 0x7, 0x4);
+ snd_soc_update_bits(codec, TABLA_A_CDC_DMIC_CLK2_MODE, 0x7, 0x4);
+ snd_soc_update_bits(codec, TABLA_A_PIN_CTL_OE0, 0x90, 0x90);
+ snd_soc_update_bits(codec, TABLA_A_PIN_CTL_OE1, 0x8, 0x8);
+ snd_soc_update_bits(codec, TABLA_A_PIN_CTL_DATA0, 0x90, 0x0);
+ snd_soc_update_bits(codec, TABLA_A_PIN_CTL_DATA1, 0x8, 0x0);
}
static void tabla_update_reg_address(struct tabla_priv *priv)
diff --git a/sound/soc/codecs/wcd9320.c b/sound/soc/codecs/wcd9320.c
index 03de4e0..59354a3 100644
--- a/sound/soc/codecs/wcd9320.c
+++ b/sound/soc/codecs/wcd9320.c
@@ -3096,6 +3096,8 @@
{
struct snd_soc_codec *codec = w->codec;
struct taiko_priv *taiko_p = snd_soc_codec_get_drvdata(codec);
+ uint32_t impedl, impedr;
+ int ret = 0;
pr_debug("%s %s %d\n", __func__, w->name, event);
@@ -3107,6 +3109,13 @@
WCD9XXX_CLSH_STATE_HPHL,
WCD9XXX_CLSH_REQ_ENABLE,
WCD9XXX_CLSH_EVENT_PRE_DAC);
+ ret = wcd9xxx_mbhc_get_impedance(&taiko_p->mbhc,
+ &impedl, &impedr);
+ if (!ret)
+ wcd9xxx_clsh_imped_config(codec, impedl);
+ else
+ dev_err(codec->dev, "Failed to get mbhc impedance %d\n",
+ ret);
break;
case SND_SOC_DAPM_POST_PMD:
snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_RDAC_CLK_EN_CTL,
diff --git a/sound/soc/codecs/wcd9xxx-common.c b/sound/soc/codecs/wcd9xxx-common.c
index bfd66ea..d00b843 100644
--- a/sound/soc/codecs/wcd9xxx-common.c
+++ b/sound/soc/codecs/wcd9xxx-common.c
@@ -30,6 +30,387 @@
#define BUCK_SETTLE_TIME_US 50
#define NCP_SETTLE_TIME_US 50
+#define MAX_IMPED_PARAMS 13
+
+struct wcd9xxx_imped_val {
+ u32 imped_val;
+ u8 index;
+};
+
+static const struct wcd9xxx_reg_mask_val imped_table[][MAX_IMPED_PARAMS] = {
+ {
+ {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x46},
+ {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x04},
+ {WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x11},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x02},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x9B},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x02},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x15},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1C},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+ {WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x04},
+ {WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x0C},
+ },
+ {
+ {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x47},
+ {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x05},
+ {WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x11},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x02},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x9B},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x02},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x15},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1C},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+ {WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x05},
+ {WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x0C},
+ },
+ {
+ {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x49},
+ {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x07},
+ {WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x02},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x12},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x35},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x4E},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+ {WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x06},
+ {WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x0E},
+ },
+ {
+ {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x49},
+ {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x16},
+ {WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xAC},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x02},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x17},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x5F},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xCF},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+ {WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x06},
+ {WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x0F},
+ },
+ {
+ {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x59},
+ {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x15},
+ {WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x9C},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x02},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1B},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xCE},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xBD},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+ {WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x07},
+ {WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x10},
+ },
+ {
+ {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x66},
+ {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x04},
+ {WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x9A},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x02},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x2E},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xBD},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xA6},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+ {WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x07},
+ {WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x11},
+ },
+ {
+ {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x79},
+ {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x04},
+ {WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x11},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x37},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xA6},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xAD},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+ {WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x08},
+ {WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x12},
+ },
+ {
+ {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x76},
+ {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x04},
+ {WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x11},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x4E},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xAD},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xAC},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+ {WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x09},
+ {WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x12},
+ },
+ {
+ {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x78},
+ {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x05},
+ {WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x12},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xD0},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xAC},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x13},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+ {WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x0A},
+ {WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x13},
+ },
+ {
+ {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x7A},
+ {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x06},
+ {WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x14},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xB7},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x13},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x14},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+ {WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x0B},
+ {WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x14},
+ },
+ {
+ {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x60},
+ {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x09},
+ {WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1C},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xA4},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x14},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1F},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+ {WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x0C},
+ {WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x14},
+ },
+ {
+ {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x79},
+ {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x17},
+ {WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x25},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xAE},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1F},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1D},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+ {WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x0D},
+ {WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x15},
+ },
+ {
+ {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x78},
+ {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x16},
+ {WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x2C},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xAC},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1D},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1C},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+ {WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x0E},
+ {WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x16},
+ },
+ {
+ {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x89},
+ {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x05},
+ {WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x40},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x13},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1C},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1B},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+ {WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x10},
+ {WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x16},
+ },
+ {
+ {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x97},
+ {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x05},
+ {WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xD0},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x14},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1B},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1B},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+ {WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x12},
+ {WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x17},
+ },
+ {
+ {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x8A},
+ {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x06},
+ {WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xB7},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x10},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1B},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x24},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+ {WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x13},
+ {WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x17},
+ },
+ {
+ {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x8A},
+ {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x07},
+ {WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xA4},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1D},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x24},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x25},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+ {WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x15},
+ {WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x18},
+ },
+ {
+ {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x9A},
+ {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x08},
+ {WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xAE},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1C},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x25},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x27},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+ {WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x18},
+ {WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x19},
+ },
+ {
+ {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x8B},
+ {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x18},
+ {WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xAC},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1B},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x20},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x2E},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+ {WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x1A},
+ {WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x19},
+ },
+ {
+ {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x9A},
+ {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x17},
+ {WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x13},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1B},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x2E},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x2D},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+ {WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x1D},
+ {WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x1A},
+ },
+ {
+ {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0xA9},
+ {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x06},
+ {WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x14},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x24},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x2D},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x2C},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+ {WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x1F},
+ {WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x19},
+ },
+ {
+ {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0xB9},
+ {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x06},
+ {WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x10},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x25},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x2C},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x2C},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+ {WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x23},
+ {WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x18},
+ },
+ {
+ {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0xA9},
+ {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x07},
+ {WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1D},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x27},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x2C},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x35},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+ {WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x26},
+ {WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x16},
+ },
+};
+
+static const struct wcd9xxx_imped_val imped_index[] = {
+ {4000, 0},
+ {4500, 1},
+ {5000, 2},
+ {5500, 3},
+ {6000, 4},
+ {6500, 5},
+ {7000, 6},
+ {7700, 7},
+ {8470, 8},
+ {9317, 9},
+ {10248, 10},
+ {11273, 11},
+ {12400, 12},
+ {13641, 13},
+ {15005, 14},
+ {16505, 15},
+ {18156, 16},
+ {19971, 17},
+ {21969, 18},
+ {24165, 19},
+ {26582, 20},
+ {29240, 21},
+ {32164, 22},
+};
+
static inline void wcd9xxx_enable_clsh_block(
struct snd_soc_codec *codec,
bool on)
@@ -165,6 +546,40 @@
}
}
+static int get_impedance_index(u32 imped)
+{
+ int i = 0;
+ if (imped < imped_index[i].imped_val) {
+ pr_debug("%s, detected impedance is less than 4 Ohm\n",
+ __func__);
+ goto ret;
+ }
+ for (i = 0; i < ARRAY_SIZE(imped_index); i++) {
+ if (imped >= imped_index[i].imped_val &&
+ imped < imped_index[i + 1].imped_val)
+ break;
+ }
+ret:
+ pr_debug("%s: selected impedance index = %d\n",
+ __func__, imped_index[i].index);
+ return imped_index[i].index;
+}
+
+void wcd9xxx_clsh_imped_config(struct snd_soc_codec *codec,
+ int imped)
+{
+ int i = 0;
+ int index = 0;
+ index = get_impedance_index(imped);
+ if (index > ARRAY_SIZE(imped_index)) {
+ pr_err("%s, invalid imped = %d\n", __func__, imped);
+ return;
+ }
+ for (i = 0; i < MAX_IMPED_PARAMS; i++)
+ snd_soc_write(codec, imped_table[index][i].reg,
+ imped_table[index][i].val);
+}
+
static void wcd9xxx_clsh_comp_req(struct snd_soc_codec *codec,
struct wcd9xxx_clsh_cdc_data *clsh_d,
int compute_pa, bool on)
diff --git a/sound/soc/codecs/wcd9xxx-common.h b/sound/soc/codecs/wcd9xxx-common.h
index 50381c9..654964e 100644
--- a/sound/soc/codecs/wcd9xxx-common.h
+++ b/sound/soc/codecs/wcd9xxx-common.h
@@ -74,6 +74,9 @@
extern void wcd9xxx_clsh_init(struct wcd9xxx_clsh_cdc_data *clsh,
struct wcd9xxx_resmgr *resmgr);
+extern void wcd9xxx_clsh_imped_config(struct snd_soc_codec *codec,
+ int imped);
+
enum wcd9xxx_codec_event {
WCD9XXX_CODEC_EVENT_CODEC_UP = 0,
};
diff --git a/sound/soc/codecs/wcd9xxx-mbhc.c b/sound/soc/codecs/wcd9xxx-mbhc.c
index e34dec1..d0c00a7 100644
--- a/sound/soc/codecs/wcd9xxx-mbhc.c
+++ b/sound/soc/codecs/wcd9xxx-mbhc.c
@@ -220,11 +220,15 @@
pr_debug("%s: leave\n", __func__);
}
-/* called under codec_resource_lock acquisition */
-static void __wcd9xxx_switch_micbias(struct wcd9xxx_mbhc *mbhc,
+/*
+ * called under codec_resource_lock acquisition
+ * return old status
+ */
+static bool __wcd9xxx_switch_micbias(struct wcd9xxx_mbhc *mbhc,
int vddio_switch, bool restartpolling,
bool checkpolling)
{
+ bool ret;
int cfilt_k_val;
bool override;
struct snd_soc_codec *codec;
@@ -234,9 +238,11 @@
if (mbhc->micbias_enable) {
pr_debug("%s: micbias is already on\n", __func__);
- return;
+ ret = mbhc->mbhc_micbias_switched;
+ return ret;
}
+ ret = mbhc->mbhc_micbias_switched;
if (vddio_switch && !mbhc->mbhc_micbias_switched &&
(!checkpolling || mbhc->polling_active)) {
if (restartpolling)
@@ -343,11 +349,13 @@
mbhc->mbhc_micbias_switched = false;
pr_debug("%s: VDDIO switch disabled\n", __func__);
}
+
+ return ret;
}
static void wcd9xxx_switch_micbias(struct wcd9xxx_mbhc *mbhc, int vddio_switch)
{
- return __wcd9xxx_switch_micbias(mbhc, vddio_switch, true, true);
+ __wcd9xxx_switch_micbias(mbhc, vddio_switch, true, true);
}
static s16 wcd9xxx_get_current_v(struct wcd9xxx_mbhc *mbhc,
@@ -1124,10 +1132,15 @@
/*
* wcd9xxx_find_plug_type : Find out and return the best plug type with given
* list of wcd9xxx_mbhc_detect structure.
+ * param mbhc wcd9xxx_mbhc structure
+ * param dt collected measurements
+ * param size array size of dt
+ * param event_state mbhc->event_state when dt is collected
*/
static enum wcd9xxx_mbhc_plug_type
wcd9xxx_find_plug_type(struct wcd9xxx_mbhc *mbhc,
- struct wcd9xxx_mbhc_detect *dt, const int size)
+ struct wcd9xxx_mbhc_detect *dt, const int size,
+ unsigned long event_state)
{
int i;
int ch;
@@ -1140,6 +1153,8 @@
const s16 hs_max = plug_type->v_hs_max;
const s16 no_mic = plug_type->v_no_mic;
+ pr_debug("%s: event_state 0x%lx\n", __func__, event_state);
+
for (i = 0, d = dt, ch = 0; i < size; i++, d++) {
vdce = wcd9xxx_codec_sta_dce_v(mbhc, true, d->dce);
if (d->vddio)
@@ -1181,7 +1196,10 @@
goto exit;
}
}
- if (ch != size && ch > 0) {
+
+ if (event_state & (1 << MBHC_EVENT_PA_HPHL)) {
+ pr_debug("%s: HPHL PA was ON\n", __func__);
+ } else if (ch != size && ch > 0) {
pr_debug("%s: Invalid, inconsistent HPHL\n", __func__);
type = PLUG_TYPE_INVALID;
goto exit;
@@ -1221,12 +1239,18 @@
maxv))
type = PLUG_TYPE_GND_MIC_SWAP;
}
- if (((type == PLUG_TYPE_HEADSET || type == PLUG_TYPE_HEADPHONE) &&
- ch != size) || (type == PLUG_TYPE_GND_MIC_SWAP && ch)) {
- pr_debug("%s: Invalid, not fully inserted, TYPE %d\n",
- __func__, type);
- type = PLUG_TYPE_INVALID;
+
+ /* if HPHL PA was on, we cannot use hphl status */
+ if (!(event_state & (1UL << MBHC_EVENT_PA_HPHL))) {
+ if (((type == PLUG_TYPE_HEADSET ||
+ type == PLUG_TYPE_HEADPHONE) && ch != size) ||
+ (type == PLUG_TYPE_GND_MIC_SWAP && ch)) {
+ pr_debug("%s: Invalid, not fully inserted, TYPE %d\n",
+ __func__, type);
+ type = PLUG_TYPE_INVALID;
+ }
}
+
if (type == PLUG_TYPE_HEADSET && dvddio) {
if ((dvddio->_vdces > hs_max) ||
(dvddio->_vdces > minv + WCD9XXX_THRESHOLD_MIC_THRESHOLD)) {
@@ -1294,6 +1318,7 @@
wcd9xxx_codec_get_plug_type(struct wcd9xxx_mbhc *mbhc, bool highhph)
{
int i;
+ bool vddioon;
struct wcd9xxx_mbhc_plug_type_cfg *plug_type_ptr;
struct wcd9xxx_mbhc_detect rt[NUM_DCE_PLUG_INS_DETECT];
enum wcd9xxx_mbhc_plug_type type = PLUG_TYPE_INVALID;
@@ -1308,6 +1333,13 @@
/* GND and MIC swap detection requires at least 2 rounds of DCE */
BUG_ON(NUM_DCE_PLUG_INS_DETECT < 2);
+ /*
+ * There are chances vddio switch is on and cfilt voltage is adjusted
+ * to vddio voltage even after plug type removal reported.
+ */
+ vddioon = __wcd9xxx_switch_micbias(mbhc, 0, false, false);
+ pr_debug("%s: vddio switch was %s\n", __func__, vddioon ? "on" : "off");
+
plug_type_ptr =
WCD9XXX_MBHC_CAL_PLUG_TYPE_PTR(mbhc->mbhc_cfg->calibration);
@@ -1350,7 +1382,11 @@
wcd9xxx_codec_hphr_gnd_switch(codec, false);
}
- type = wcd9xxx_find_plug_type(mbhc, rt, ARRAY_SIZE(rt));
+ if (vddioon)
+ __wcd9xxx_switch_micbias(mbhc, 1, false, false);
+
+ type = wcd9xxx_find_plug_type(mbhc, rt, ARRAY_SIZE(rt),
+ mbhc->event_state);
pr_debug("%s: leave\n", __func__);
return type;
@@ -2134,6 +2170,7 @@
unsigned long timeout;
int retry = 0, pt_gnd_mic_swap_cnt = 0;
bool correction = false;
+ bool wrk_complete = true;
pr_debug("%s: enter\n", __func__);
@@ -2159,12 +2196,14 @@
++retry;
rmb();
if (mbhc->hs_detect_work_stop) {
+ wrk_complete = false;
pr_debug("%s: stop requested\n", __func__);
break;
}
msleep(HS_DETECT_PLUG_INERVAL_MS);
if (wcd9xxx_swch_level_remove(mbhc)) {
+ wrk_complete = false;
pr_debug("%s: Switch level is low\n", __func__);
break;
}
@@ -2238,7 +2277,9 @@
if (plug_type == PLUG_TYPE_HIGH_HPH) {
pr_debug("%s: polling is done, still HPH, so enabling MIC trigger\n",
__func__);
+ WCD9XXX_BCL_LOCK(mbhc->resmgr);
wcd9xxx_find_plug_and_report(mbhc, plug_type);
+ WCD9XXX_BCL_UNLOCK(mbhc->resmgr);
}
/* Turn off override */
if (!correction)
@@ -2248,10 +2289,11 @@
if (mbhc->mbhc_cfg->detect_extn_cable) {
WCD9XXX_BCL_LOCK(mbhc->resmgr);
- if (mbhc->current_plug == PLUG_TYPE_HEADPHONE ||
+ if ((mbhc->current_plug == PLUG_TYPE_HEADPHONE &&
+ wrk_complete) ||
mbhc->current_plug == PLUG_TYPE_GND_MIC_SWAP ||
mbhc->current_plug == PLUG_TYPE_INVALID ||
- plug_type == PLUG_TYPE_INVALID) {
+ (plug_type == PLUG_TYPE_INVALID && wrk_complete)) {
/* Enable removal detection */
wcd9xxx_cleanup_hs_polling(mbhc);
wcd9xxx_enable_hs_detect(mbhc, 0, 0, false);
diff --git a/sound/soc/msm/msm8226.c b/sound/soc/msm/msm8226.c
index 043a998..d3ba3d5 100644
--- a/sound/soc/msm/msm8226.c
+++ b/sound/soc/msm/msm8226.c
@@ -36,12 +36,20 @@
#define BTSCO_RATE_8KHZ 8000
#define BTSCO_RATE_16KHZ 16000
+/* It takes about 13ms for Class-D PAs to ramp-up */
+#define EXT_CLASS_D_EN_DELAY 13000
+#define EXT_CLASS_D_DIS_DELAY 3000
+#define EXT_CLASS_D_DELAY_DELTA 2000
+
#define WCD9XXX_MBHC_DEF_BUTTONS 8
#define WCD9XXX_MBHC_DEF_RLOADS 5
#define TAPAN_EXT_CLK_RATE 9600000
#define NUM_OF_AUXPCM_GPIOS 4
+#define LO_1_SPK_AMP 0x1
+#define LO_2_SPK_AMP 0x2
+
static int msm8226_auxpcm_rate = 8000;
static atomic_t auxpcm_rsc_ref;
static const char *const auxpcm_rate_text[] = {"rate_8000", "rate_16000"};
@@ -116,6 +124,7 @@
SLIM_4_TX_1 = 150, /* In-call musid delivery TX */
};
+static int msm8226_ext_spk_pamp;
static int msm_slim_0_rx_ch = 1;
static int msm_slim_0_tx_ch = 1;
@@ -125,6 +134,7 @@
static struct mutex cdc_mclk_mutex;
static struct clk *codec_clk;
static int clk_users;
+static int ext_spk_amp_gpio = -1;
static int vdd_spkr_gpio = -1;
static int msm_proxy_rx_ch = 2;
@@ -189,6 +199,99 @@
return 0;
}
+static void msm8226_ext_spk_power_amp_enable(u32 enable)
+{
+ if (enable) {
+ gpio_direction_output(ext_spk_amp_gpio, enable);
+ /* time takes enable the external power amplifier */
+ usleep_range(EXT_CLASS_D_EN_DELAY,
+ EXT_CLASS_D_EN_DELAY + EXT_CLASS_D_DELAY_DELTA);
+ } else {
+ gpio_direction_output(ext_spk_amp_gpio, enable);
+ /* time takes disable the external power amplifier */
+ usleep_range(EXT_CLASS_D_DIS_DELAY,
+ EXT_CLASS_D_DIS_DELAY + EXT_CLASS_D_DELAY_DELTA);
+ }
+
+ pr_debug("%s: %s external speaker PAs.\n", __func__,
+ enable ? "Enable" : "Disable");
+}
+
+static void msm8226_ext_spk_power_amp_on(u32 spk)
+{
+ if (gpio_is_valid(ext_spk_amp_gpio)) {
+ if (spk & (LO_1_SPK_AMP | LO_2_SPK_AMP)) {
+ pr_debug("%s:Enable left and right speakers case spk = 0x%x\n",
+ __func__, spk);
+
+ msm8226_ext_spk_pamp |= spk;
+
+ if ((msm8226_ext_spk_pamp & LO_1_SPK_AMP) &&
+ (msm8226_ext_spk_pamp & LO_2_SPK_AMP))
+ if (ext_spk_amp_gpio >= 0) {
+ pr_debug("%s enable power", __func__);
+ msm8226_ext_spk_power_amp_enable(1);
+ }
+ } else {
+ pr_err("%s: Invalid external speaker ampl. spk = 0x%x\n",
+ __func__, spk);
+ }
+ }
+}
+
+static void msm8226_ext_spk_power_amp_off(u32 spk)
+{
+ if (gpio_is_valid(ext_spk_amp_gpio)) {
+ if (spk & (LO_1_SPK_AMP | LO_2_SPK_AMP)) {
+ pr_debug("%s Disable left and right speakers case spk = 0x%08x",
+ __func__, spk);
+
+ msm8226_ext_spk_pamp &= ~spk;
+
+ if (!msm8226_ext_spk_pamp) {
+ if (ext_spk_amp_gpio >= 0) {
+ pr_debug("%s disable power", __func__);
+ msm8226_ext_spk_power_amp_enable(0);
+ }
+ msm8226_ext_spk_pamp = 0;
+ }
+ } else {
+ pr_err("%s: ERROR : Invalid Ext Spk Ampl. spk = 0x%08x\n",
+ __func__, spk);
+ }
+ }
+}
+
+static int msm8226_ext_spkramp_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *k, int event)
+{
+ pr_debug("%s()\n", __func__);
+
+ if (SND_SOC_DAPM_EVENT_ON(event)) {
+ if (!strncmp(w->name, "Lineout_1 amp", 14))
+ msm8226_ext_spk_power_amp_on(LO_1_SPK_AMP);
+ else if (!strncmp(w->name, "Lineout_2 amp", 14))
+ msm8226_ext_spk_power_amp_on(LO_2_SPK_AMP);
+ else {
+ pr_err("%s() Invalid Speaker Widget = %s\n",
+ __func__, w->name);
+ return -EINVAL;
+ }
+ } else {
+ if (!strncmp(w->name, "Lineout_1 amp", 14))
+ msm8226_ext_spk_power_amp_off(LO_1_SPK_AMP);
+ else if (!strncmp(w->name, "Lineout_2 amp", 14))
+ msm8226_ext_spk_power_amp_off(LO_2_SPK_AMP);
+ else {
+ pr_err("%s() Invalid Speaker Widget = %s\n",
+ __func__, w->name);
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
static int msm8226_vdd_spkr_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
@@ -230,6 +333,9 @@
SND_SOC_DAPM_MIC("Digital Mic5", NULL),
SND_SOC_DAPM_MIC("Digital Mic6", NULL),
+ SND_SOC_DAPM_SPK("Lineout_1 amp", msm8226_ext_spkramp_event),
+ SND_SOC_DAPM_SPK("Lineout_2 amp", msm8226_ext_spkramp_event),
+
SND_SOC_DAPM_SUPPLY("EXT_VDD_SPKR", SND_SOC_NOPM, 0, 0,
msm8226_vdd_spkr_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
};
@@ -1437,7 +1543,7 @@
pdata->us_euro_gpio = of_get_named_gpio(pdev->dev.of_node,
"qcom,cdc-us-euro-gpios", 0);
if (pdata->us_euro_gpio < 0) {
- dev_info(&pdev->dev,
+ dev_dbg(&pdev->dev,
"property %s in node %s not found %d\n",
"qcom,cdc-us-euro-gpios", pdev->dev.of_node->full_name,
pdata->us_euro_gpio);
@@ -1527,7 +1633,7 @@
vdd_spkr_gpio = of_get_named_gpio(pdev->dev.of_node,
"qcom,cdc-vdd-spkr-gpios", 0);
if (vdd_spkr_gpio < 0) {
- dev_err(&pdev->dev,
+ dev_dbg(&pdev->dev,
"Looking up %s property in node %s failed %d\n",
"qcom, cdc-vdd-spkr-gpios",
pdev->dev.of_node->full_name, vdd_spkr_gpio);
@@ -1542,19 +1648,38 @@
}
}
+ ext_spk_amp_gpio = of_get_named_gpio(pdev->dev.of_node,
+ "qcom,cdc-lineout-spkr-gpios", 0);
+ if (ext_spk_amp_gpio < 0) {
+ dev_err(&pdev->dev,
+ "Looking up %s property in node %s failed %d\n",
+ "qcom, cdc-lineout-spkr-gpios",
+ pdev->dev.of_node->full_name, ext_spk_amp_gpio);
+ } else {
+ ret = gpio_request(ext_spk_amp_gpio,
+ "TAPAN_CODEC_LINEOUT_SPKR");
+ if (ret) {
+ /* GPIO to enable EXT AMP exists, but failed request */
+ dev_err(card->dev,
+ "%s: Failed to request tapan amp spkr gpio %d\n",
+ __func__, ext_spk_amp_gpio);
+ goto err_vdd_spkr;
+ }
+ }
+
mbhc_cfg.gpio_level_insert = of_property_read_bool(pdev->dev.of_node,
"qcom,headset-jack-type-NO");
msm8226_setup_hs_jack(pdev, pdata);
ret = msm8226_prepare_codec_mclk(card);
if (ret)
- goto err_vdd_spkr;
+ goto err_lineout_spkr;
ret = snd_soc_register_card(card);
if (ret) {
dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
ret);
- goto err_vdd_spkr;
+ goto err_lineout_spkr;
}
mutex_init(&cdc_mclk_mutex);
@@ -1564,7 +1689,7 @@
dev_err(&pdev->dev, "Looking up %s property in node %s failed",
"qcom,prim-auxpcm-gpio-set",
pdev->dev.of_node->full_name);
- goto err_vdd_spkr;
+ goto err_lineout_spkr;
}
if (!strcmp(auxpcm_pri_gpio_set, "prim-gpio-prim")) {
lpaif_pri_muxsel_virt_addr = ioremap(LPAIF_PRI_MODE_MUXSEL, 4);
@@ -1574,16 +1699,22 @@
dev_err(&pdev->dev, "Invalid value %s for AUXPCM GPIO set\n",
auxpcm_pri_gpio_set);
ret = -EINVAL;
- goto err_vdd_spkr;
+ goto err_lineout_spkr;
}
if (lpaif_pri_muxsel_virt_addr == NULL) {
pr_err("%s Pri muxsel virt addr is null\n", __func__);
ret = -EINVAL;
- goto err_vdd_spkr;
+ goto err_lineout_spkr;
}
return 0;
+err_lineout_spkr:
+ if (ext_spk_amp_gpio >= 0) {
+ gpio_free(ext_spk_amp_gpio);
+ ext_spk_amp_gpio = -1;
+ }
+
err_vdd_spkr:
if (vdd_spkr_gpio >= 0) {
gpio_free(vdd_spkr_gpio);
@@ -1607,11 +1738,15 @@
struct msm8226_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
gpio_free(pdata->mclk_gpio);
- gpio_free(vdd_spkr_gpio);
+ if (vdd_spkr_gpio >= 0)
+ gpio_free(vdd_spkr_gpio);
+ if (ext_spk_amp_gpio >= 0)
+ gpio_free(ext_spk_amp_gpio);
if (pdata->us_euro_gpio > 0)
gpio_free(pdata->us_euro_gpio);
vdd_spkr_gpio = -1;
+ ext_spk_amp_gpio = -1;
snd_soc_unregister_card(card);
return 0;
diff --git a/sound/soc/msm/qdsp6v2/audio_acdb.c b/sound/soc/msm/qdsp6v2/audio_acdb.c
index d6090cf..2836b87 100644
--- a/sound/soc/msm/qdsp6v2/audio_acdb.c
+++ b/sound/soc/msm/qdsp6v2/audio_acdb.c
@@ -20,6 +20,7 @@
#include <linux/mm.h>
#include <linux/msm_audio_ion.h>
#include "audio_acdb.h"
+#include "q6voice.h"
#define MAX_NETWORKS 15
@@ -949,6 +950,36 @@
return result;
}
+static int register_vocvol_table(void)
+{
+ int result = 0;
+ pr_debug("%s\n", __func__);
+
+ result = voc_register_vocproc_vol_table();
+ if (result < 0) {
+ pr_err("%s: Register vocproc vol failed!\n", __func__);
+ goto done;
+ }
+
+done:
+ return result;
+}
+
+static int deregister_vocvol_table(void)
+{
+ int result = 0;
+ pr_debug("%s\n", __func__);
+
+ result = voc_deregister_vocproc_vol_table();
+ if (result < 0) {
+ pr_err("%s: Deregister vocproc vol failed!\n", __func__);
+ goto done;
+ }
+
+done:
+ return result;
+}
+
static int acdb_open(struct inode *inode, struct file *f)
{
s32 result = 0;
@@ -1139,10 +1170,16 @@
}
if (copy_to_user((void *)arg, &prot_status,
sizeof(prot_status))) {
- pr_err("%s Failed to update prot_status\n", __func__);
+ pr_err("%s: Failed to update prot_status\n", __func__);
}
mutex_unlock(&acdb_data.acdb_mutex);
goto done;
+ case AUDIO_REGISTER_VOCPROC_VOL_TABLE:
+ result = register_vocvol_table();
+ goto done;
+ case AUDIO_DEREGISTER_VOCPROC_VOL_TABLE:
+ result = deregister_vocvol_table();
+ goto done;
}
if (copy_from_user(&size, (void *) arg, sizeof(size))) {
diff --git a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
index 9f4e189..aa6ef6b 100644
--- a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
@@ -127,6 +127,7 @@
int i = 0;
int time_stamp_flag = 0;
int buffer_length = 0;
+ int stop_playback = 0;
pr_debug("%s opcode =%08x\n", __func__, opcode);
switch (opcode) {
@@ -151,9 +152,15 @@
/*
* check for underrun
*/
+ snd_pcm_stream_lock_irq(substream);
if (runtime->status->hw_ptr >= runtime->control->appl_ptr) {
- pr_info("render stopped");
runtime->render_flag |= SNDRV_RENDER_STOPPED;
+ stop_playback = 1;
+ }
+ snd_pcm_stream_unlock_irq(substream);
+
+ if (stop_playback) {
+ pr_err("underrun! render stopped\n");
break;
}
diff --git a/sound/soc/msm/qdsp6v2/q6voice.c b/sound/soc/msm/qdsp6v2/q6voice.c
index f268171..be62727 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.c
+++ b/sound/soc/msm/qdsp6v2/q6voice.c
@@ -95,7 +95,6 @@
static int voice_alloc_and_map_oob_mem(struct voice_data *v);
static struct voice_data *voice_get_session_by_idx(int idx);
-static int voice_get_idx_for_session(u32 session_id);
static u16 voice_get_mvm_handle(struct voice_data *v)
{
@@ -240,7 +239,7 @@
return v;
}
-static int voice_get_idx_for_session(u32 session_id)
+int voice_get_idx_for_session(u32 session_id)
{
int idx = 0;
@@ -300,6 +299,16 @@
return (session_id == common.voice[VOC_PATH_VOICE2_PASSIVE].session_id);
}
+static bool is_voc_state_active(int voc_state)
+{
+ if ((voc_state == VOC_RUN) ||
+ (voc_state == VOC_CHANGE) ||
+ (voc_state == VOC_STANDBY))
+ return true;
+
+ return false;
+}
+
static bool is_other_session_active(u32 session_id)
{
int i;
@@ -310,9 +319,7 @@
if (common.voice[i].session_id == session_id)
continue;
- if ((common.voice[i].voc_state == VOC_RUN) ||
- (common.voice[i].voc_state == VOC_CHANGE) ||
- (common.voice[i].voc_state == VOC_STANDBY)) {
+ if (is_voc_state_active(common.voice[i].voc_state)) {
ret = true;
break;
}
@@ -1213,9 +1220,8 @@
for (i = 0; i < MAX_VOC_SESSIONS; i++) {
v = &common.voice[i];
if ((v->dtmf_rx_detect_en) &&
- ((v->voc_state == VOC_RUN) ||
- (v->voc_state == VOC_CHANGE) ||
- (v->voc_state == VOC_STANDBY))) {
+ is_voc_state_active(v->voc_state)) {
+
pr_debug("disable dtmf det on ses_id=%d\n",
v->session_id);
voice_send_dtmf_rx_detection_cmd(v, 0);
@@ -1236,9 +1242,7 @@
mutex_lock(&v->lock);
v->dtmf_rx_detect_en = enable;
- if ((v->voc_state == VOC_RUN) ||
- (v->voc_state == VOC_CHANGE) ||
- (v->voc_state == VOC_STANDBY))
+ if (is_voc_state_active(v->voc_state))
ret = voice_send_dtmf_rx_detection_cmd(v,
v->dtmf_rx_detect_en);
@@ -2327,6 +2331,62 @@
return ret;
}
+int voc_register_vocproc_vol_table(void)
+{
+ int result = 0;
+ int i;
+ struct voice_data *v = NULL;
+ pr_debug("%s\n", __func__);
+
+ mutex_lock(&common.common_lock);
+ for (i = 0; i < MAX_VOC_SESSIONS; i++) {
+ v = &common.voice[i];
+
+ mutex_lock(&v->lock);
+ if (is_voc_state_active(v->voc_state)) {
+ result = voice_send_cvp_register_vol_cal_cmd(v);
+ if (result) {
+ pr_err("%s: Failed to register vocvol table for session 0x%x!\n",
+ __func__, v->session_id);
+ mutex_unlock(&v->lock);
+ goto done;
+ }
+ }
+ mutex_unlock(&v->lock);
+ }
+done:
+ mutex_unlock(&common.common_lock);
+ return result;
+}
+
+int voc_deregister_vocproc_vol_table(void)
+{
+ int result = 0;
+ int i;
+ struct voice_data *v = NULL;
+ pr_debug("%s\n", __func__);
+
+ mutex_lock(&common.common_lock);
+ for (i = 0; i < MAX_VOC_SESSIONS; i++) {
+ v = &common.voice[i];
+
+ mutex_lock(&v->lock);
+ if (is_voc_state_active(v->voc_state)) {
+ result = voice_send_cvp_deregister_vol_cal_cmd(v);
+ if (result) {
+ pr_err("%s: Failed to deregister vocvol table for session 0x%x!\n",
+ __func__, v->session_id);
+ mutex_unlock(&v->lock);
+ goto done;
+ }
+ }
+ mutex_unlock(&v->lock);
+ }
+done:
+ mutex_unlock(&common.common_lock);
+ return result;
+}
+
static int voice_map_memory_physical_cmd(struct voice_data *v,
struct mem_map_table *table_info,
dma_addr_t phys,
@@ -3870,9 +3930,7 @@
v->stream_tx.stream_mute = mute;
- if ((v->voc_state == VOC_RUN) ||
- (v->voc_state == VOC_CHANGE) ||
- (v->voc_state == VOC_STANDBY))
+ if (is_voc_state_active(v->voc_state))
ret = voice_send_stream_mute_cmd(v);
mutex_unlock(&v->lock);
@@ -4026,9 +4084,7 @@
v->dev_rx.volume = vol_idx;
- if ((v->voc_state == VOC_RUN) ||
- (v->voc_state == VOC_CHANGE) ||
- (v->voc_state == VOC_STANDBY))
+ if (is_voc_state_active(v->voc_state))
ret = voice_send_vol_index_cmd(v);
mutex_unlock(&v->lock);
diff --git a/sound/soc/msm/qdsp6v2/q6voice.h b/sound/soc/msm/qdsp6v2/q6voice.h
index b8f7008..42b1800 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.h
+++ b/sound/soc/msm/qdsp6v2/q6voice.h
@@ -1377,9 +1377,13 @@
int voc_alloc_cal_shared_memory(void);
int voc_alloc_voip_shared_memory(void);
int is_voc_initialized(void);
+int voc_register_vocproc_vol_table(void);
+int voc_deregister_vocproc_vol_table(void);
uint32_t voc_get_session_id(char *name);
int voc_start_playback(uint32_t set, uint16_t port_id);
int voc_start_record(uint32_t port_id, uint32_t set);
+int voice_get_idx_for_session(u32 session_id);
+
#endif
diff --git a/sound/soc/msm/qdsp6v2/rtac.c b/sound/soc/msm/qdsp6v2/rtac.c
index 1f2a487..a4983d3 100644
--- a/sound/soc/msm/qdsp6v2/rtac.c
+++ b/sound/soc/msm/qdsp6v2/rtac.c
@@ -24,7 +24,7 @@
#include <sound/q6asm-v2.h>
#include <sound/q6afe-v2.h>
#include <sound/apr_audio-v2.h>
-
+#include <q6voice.h>
#include "audio_acdb.h"
@@ -352,13 +352,13 @@
return;
}
-static int get_voice_index_cvs(u32 cvs_handle)
+static u32 get_voice_session_id_cvs(u32 cvs_handle)
{
u32 i;
for (i = 0; i < rtac_voice_data.num_of_voice_combos; i++) {
if (rtac_voice_data.voice[i].cvs_handle == cvs_handle)
- return i;
+ return voice_session_id[i];
}
pr_err("%s: No voice index for CVS handle %d found returning 0\n",
@@ -366,13 +366,13 @@
return 0;
}
-static int get_voice_index_cvp(u32 cvp_handle)
+static u32 get_voice_session_id_cvp(u32 cvp_handle)
{
u32 i;
for (i = 0; i < rtac_voice_data.num_of_voice_combos; i++) {
if (rtac_voice_data.voice[i].cvp_handle == cvp_handle)
- return i;
+ return voice_session_id[i];
}
pr_err("%s: No voice index for CVP handle %d found returning 0\n",
@@ -383,9 +383,11 @@
static int get_voice_index(u32 mode, u32 handle)
{
if (mode == RTAC_CVP)
- return get_voice_index_cvp(handle);
+ return voice_get_idx_for_session(
+ get_voice_session_id_cvp(handle));
if (mode == RTAC_CVS)
- return get_voice_index_cvs(handle);
+ return voice_get_idx_for_session(
+ get_voice_session_id_cvs(handle));
pr_err("%s: Invalid mode %d, returning 0\n",
__func__, mode);
@@ -847,8 +849,7 @@
payload_size);
voice_params.src_svc = 0;
voice_params.src_domain = APR_DOMAIN_APPS;
- voice_params.src_port = voice_session_id[
- get_voice_index(mode, dest_port)];
+ voice_params.src_port = get_voice_index(mode, dest_port);
voice_params.dest_svc = 0;
voice_params.dest_domain = APR_DOMAIN_MODEM;
voice_params.dest_port = (u16)dest_port;