diff options
91 files changed, 2814 insertions, 1799 deletions
diff --git a/Documentation/devicetree/bindings/leds/leds-qpnp.txt b/Documentation/devicetree/bindings/leds/leds-qpnp.txt index 4564bfff3996..85e097586466 100644 --- a/Documentation/devicetree/bindings/leds/leds-qpnp.txt +++ b/Documentation/devicetree/bindings/leds/leds-qpnp.txt @@ -1,10 +1,10 @@ -Qualcomm QPNP Leds +Qualcomm Technologies, Inc. QPNP LEDs -QPNP (Qualcomm Plug N Play) LEDs driver is used for -controlling LEDs that are part of PMIC on Qualcomm reference -platforms. The PMIC is connected to Host processor via -SPMI bus. This driver supports various LED modules such as -Keypad backlight, WLED (white LED), RGB LED and flash LED. +Qualcomm Technologies, Inc. Plug N Play (QPNP) LED modules +are used for controlling LEDs that are connected to a QPNP PMIC. +The PMIC is connected to a host processor via the SPMI bus. Various +LED modules are supported such as Keypad backlight, WLED (white LED), +RGB LED and flash LED. Each LED module is represented as a node of "leds-qpnp". This node will further contain the type of LED supported and its @@ -83,7 +83,7 @@ Optional properties for RGB led: - qcom,turn-off-delay-ms: delay in millisecond for turning off the led when its default-state is "on". Value is being ignored in case default-state is "off". - 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. -MPP LED is an LED controled through a Multi Purpose Pin. +MPP LED is an LED controlled through a Multi Purpose Pin. Optional properties for MPP LED: - linux,default-trigger: trigger the led from external modules such as display diff --git a/Documentation/devicetree/bindings/platform/msm/qpnp-coincell.txt b/Documentation/devicetree/bindings/platform/msm/qpnp-coincell.txt index 10c1bbf3c604..4d55f0cecefe 100644 --- a/Documentation/devicetree/bindings/platform/msm/qpnp-coincell.txt +++ b/Documentation/devicetree/bindings/platform/msm/qpnp-coincell.txt @@ -1,4 +1,4 @@ -Qualcomm QPNP Coincell - coincell battery charger devices +Qualcomm Technologies, Inc. QPNP Coincell - coincell battery charger devices Required properties: - compatible: Must be "qcom,qpnp-coincell". diff --git a/Documentation/devicetree/bindings/power/supply/qcom/smb138x-charger.txt b/Documentation/devicetree/bindings/power/supply/qcom/smb138x-charger.txt index 0244f910017a..c8f2a5a8e496 100644 --- a/Documentation/devicetree/bindings/power/supply/qcom/smb138x-charger.txt +++ b/Documentation/devicetree/bindings/power/supply/qcom/smb138x-charger.txt @@ -52,6 +52,18 @@ Charger specific properties: Value type: <u32> Definition: Specifies the DC input current limit in micro-amps. +- qcom,charger-temp-max-mdegc + Usage: optional + Value type: <u32> + Definition: Specifies the maximum charger temperature in milli-degrees + Celsius. If unspecified a default of 80000 will be used. + +- qcom,connector-temp-max-mdegc + Usage: optional + Value type: <u32> + Definition: Specifies the maximum connector temperature in milli-degrees + Celsius. If unspecified a default value of 105000 will be used. + - io-channels Usage: optional Value type: List of <phandle u32> diff --git a/Documentation/devicetree/bindings/regulator/mem-acc-regulator.txt b/Documentation/devicetree/bindings/regulator/mem-acc-regulator.txt index d217a4ea9fc8..55154579840a 100644 --- a/Documentation/devicetree/bindings/regulator/mem-acc-regulator.txt +++ b/Documentation/devicetree/bindings/regulator/mem-acc-regulator.txt @@ -1,4 +1,4 @@ -Qualcomm Technologies Memory Accelerator +Qualcomm Technologies, Inc. Memory Accelerator Memory accelerator configures the power-mode (corner) for the accelerator. diff --git a/Documentation/devicetree/bindings/regulator/qpnp-regulator.txt b/Documentation/devicetree/bindings/regulator/qpnp-regulator.txt index e1ebaf636ec3..601903bc60de 100644 --- a/Documentation/devicetree/bindings/regulator/qpnp-regulator.txt +++ b/Documentation/devicetree/bindings/regulator/qpnp-regulator.txt @@ -1,4 +1,4 @@ -Qualcomm QPNP Regulators +Qualcomm Technologies, Inc. QPNP Regulators qpnp-regulator is a regulator driver which supports regulators inside of PMICs that utilize the MSM SPMI implementation. diff --git a/Documentation/devicetree/bindings/thermal/qpnp-temp-alarm.txt b/Documentation/devicetree/bindings/thermal/qpnp-temp-alarm.txt index 545cdedeca4c..bb20644afde6 100644 --- a/Documentation/devicetree/bindings/thermal/qpnp-temp-alarm.txt +++ b/Documentation/devicetree/bindings/thermal/qpnp-temp-alarm.txt @@ -1,8 +1,9 @@ -Qualcomm QPNP Temperature Alarm +Qualcomm Technologies, Inc. QPNP Temperature Alarm -QPNP temperature alarm peripherals are found inside of Qualcomm PMIC chips that -utilize the MSM SPMI implementation. These peripherals provide an interrupt -signal and status register to identify high PMIC die temperature. +QPNP temperature alarm peripherals are found inside of Qualcomm Technologies, +Inc. PMIC chips that utilize the MSM SPMI implementation. These peripherals +provide an interrupt signal and status register to identify high PMIC die +temperature. Required properties: - compatible: Must be "qcom,qpnp-temp-alarm". diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 8d3d7a283eed..56961334bb7e 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -230,6 +230,9 @@ config NEED_RET_TO_USER config ARCH_MTD_XIP bool +config ARCH_WANT_KMAP_ATOMIC_FLUSH + bool + config VECTORS_BASE hex default 0xffff0000 if MMU || CPU_HIGH_VECTOR @@ -652,6 +655,7 @@ config ARCH_QCOM select SPARSE_IRQ select USE_OF select PINCTRL + select ARCH_WANT_KMAP_ATOMIC_FLUSH help Support for Qualcomm MSM/QSD based systems. This runs on the apps processor of the MSM/QSD and depends on a shared memory diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug index 815018770fb9..553b02b31847 100644 --- a/arch/arm/Kconfig.debug +++ b/arch/arm/Kconfig.debug @@ -86,6 +86,18 @@ config FORCE_PAGES If unsure say N. +config FREE_PAGES_RDONLY + bool "Set pages as read only while on the buddy list" + select FORCE_PAGES + select PAGE_POISONING + help + Pages are always mapped in the kernel. This means that anyone + can write to the page if they have the address. Enable this option + to mark pages as read only to trigger a fault if any code attempts + to write to a page on the buddy list. This may have a performance + impact. + + If unsure, say N. # These options are only for real kernel hackers who want to get their hands dirty. config DEBUG_LL diff --git a/arch/arm/boot/dts/qcom/dsi-panel-nt35597-truly-dsc-wqxga-cmd.dtsi b/arch/arm/boot/dts/qcom/dsi-panel-nt35597-truly-dsc-wqxga-cmd.dtsi index 89bf222231fb..39d3db3067e6 100644 --- a/arch/arm/boot/dts/qcom/dsi-panel-nt35597-truly-dsc-wqxga-cmd.dtsi +++ b/arch/arm/boot/dts/qcom/dsi-panel-nt35597-truly-dsc-wqxga-cmd.dtsi @@ -37,162 +37,162 @@ qcom,mdss-dsi-border-color = <0>; qcom,mdss-dsi-on-command = [ /* CMD2_P0 */ - 15 01 00 00 10 00 02 ff 20 - 15 01 00 00 10 00 02 fb 01 - 15 01 00 00 10 00 02 00 01 - 15 01 00 00 10 00 02 01 55 - 15 01 00 00 10 00 02 02 45 - 15 01 00 00 10 00 02 05 40 - 15 01 00 00 10 00 02 06 19 - 15 01 00 00 10 00 02 07 1e - 15 01 00 00 10 00 02 0b 73 - 15 01 00 00 10 00 02 0c 73 - 15 01 00 00 10 00 02 0e b0 - 15 01 00 00 10 00 02 0f ae - 15 01 00 00 10 00 02 11 b8 - 15 01 00 00 10 00 02 13 00 - 15 01 00 00 10 00 02 58 80 - 15 01 00 00 10 00 02 59 01 - 15 01 00 00 10 00 02 5a 00 - 15 01 00 00 10 00 02 5b 01 - 15 01 00 00 10 00 02 5c 80 - 15 01 00 00 10 00 02 5d 81 - 15 01 00 00 10 00 02 5e 00 - 15 01 00 00 10 00 02 5f 01 - 15 01 00 00 10 00 02 72 31 - 15 01 00 00 10 00 02 68 03 + 15 01 00 00 00 00 02 ff 20 + 15 01 00 00 00 00 02 fb 01 + 15 01 00 00 00 00 02 00 01 + 15 01 00 00 00 00 02 01 55 + 15 01 00 00 00 00 02 02 45 + 15 01 00 00 00 00 02 05 40 + 15 01 00 00 00 00 02 06 19 + 15 01 00 00 00 00 02 07 1e + 15 01 00 00 00 00 02 0b 73 + 15 01 00 00 00 00 02 0c 73 + 15 01 00 00 00 00 02 0e b0 + 15 01 00 00 00 00 02 0f ae + 15 01 00 00 00 00 02 11 b8 + 15 01 00 00 00 00 02 13 00 + 15 01 00 00 00 00 02 58 80 + 15 01 00 00 00 00 02 59 01 + 15 01 00 00 00 00 02 5a 00 + 15 01 00 00 00 00 02 5b 01 + 15 01 00 00 00 00 02 5c 80 + 15 01 00 00 00 00 02 5d 81 + 15 01 00 00 00 00 02 5e 00 + 15 01 00 00 00 00 02 5f 01 + 15 01 00 00 00 00 02 72 31 + 15 01 00 00 00 00 02 68 03 /* CMD2_P4 */ - 15 01 00 00 10 00 02 ff 24 - 15 01 00 00 10 00 02 fb 01 - 15 01 00 00 10 00 02 00 1c - 15 01 00 00 10 00 02 01 0b - 15 01 00 00 10 00 02 02 0c - 15 01 00 00 10 00 02 03 01 - 15 01 00 00 10 00 02 04 0f - 15 01 00 00 10 00 02 05 10 - 15 01 00 00 10 00 02 06 10 - 15 01 00 00 10 00 02 07 10 - 15 01 00 00 10 00 02 08 89 - 15 01 00 00 10 00 02 09 8a - 15 01 00 00 10 00 02 0a 13 - 15 01 00 00 10 00 02 0b 13 - 15 01 00 00 10 00 02 0c 15 - 15 01 00 00 10 00 02 0d 15 - 15 01 00 00 10 00 02 0e 17 - 15 01 00 00 10 00 02 0f 17 - 15 01 00 00 10 00 02 10 1c - 15 01 00 00 10 00 02 11 0b - 15 01 00 00 10 00 02 12 0c - 15 01 00 00 10 00 02 13 01 - 15 01 00 00 10 00 02 14 0f - 15 01 00 00 10 00 02 15 10 - 15 01 00 00 10 00 02 16 10 - 15 01 00 00 10 00 02 17 10 - 15 01 00 00 10 00 02 18 89 - 15 01 00 00 10 00 02 19 8a - 15 01 00 00 10 00 02 1a 13 - 15 01 00 00 10 00 02 1b 13 - 15 01 00 00 10 00 02 1c 15 - 15 01 00 00 10 00 02 1d 15 - 15 01 00 00 10 00 02 1e 17 - 15 01 00 00 10 00 02 1f 17 + 15 01 00 00 00 00 02 ff 24 + 15 01 00 00 00 00 02 fb 01 + 15 01 00 00 00 00 02 00 1c + 15 01 00 00 00 00 02 01 0b + 15 01 00 00 00 00 02 02 0c + 15 01 00 00 00 00 02 03 01 + 15 01 00 00 00 00 02 04 0f + 15 01 00 00 00 00 02 05 10 + 15 01 00 00 00 00 02 06 10 + 15 01 00 00 00 00 02 07 10 + 15 01 00 00 00 00 02 08 89 + 15 01 00 00 00 00 02 09 8a + 15 01 00 00 00 00 02 0a 13 + 15 01 00 00 00 00 02 0b 13 + 15 01 00 00 00 00 02 0c 15 + 15 01 00 00 00 00 02 0d 15 + 15 01 00 00 00 00 02 0e 17 + 15 01 00 00 00 00 02 0f 17 + 15 01 00 00 00 00 02 10 1c + 15 01 00 00 00 00 02 11 0b + 15 01 00 00 00 00 02 12 0c + 15 01 00 00 00 00 02 13 01 + 15 01 00 00 00 00 02 14 0f + 15 01 00 00 00 00 02 15 10 + 15 01 00 00 00 00 02 16 10 + 15 01 00 00 00 00 02 17 10 + 15 01 00 00 00 00 02 18 89 + 15 01 00 00 00 00 02 19 8a + 15 01 00 00 00 00 02 1a 13 + 15 01 00 00 00 00 02 1b 13 + 15 01 00 00 00 00 02 1c 15 + 15 01 00 00 00 00 02 1d 15 + 15 01 00 00 00 00 02 1e 17 + 15 01 00 00 00 00 02 1f 17 /* STV */ - 15 01 00 00 10 00 02 20 40 - 15 01 00 00 10 00 02 21 01 - 15 01 00 00 10 00 02 22 00 - 15 01 00 00 10 00 02 23 40 - 15 01 00 00 10 00 02 24 40 - 15 01 00 00 10 00 02 25 6d - 15 01 00 00 10 00 02 26 40 - 15 01 00 00 10 00 02 27 40 + 15 01 00 00 00 00 02 20 40 + 15 01 00 00 00 00 02 21 01 + 15 01 00 00 00 00 02 22 00 + 15 01 00 00 00 00 02 23 40 + 15 01 00 00 00 00 02 24 40 + 15 01 00 00 00 00 02 25 6d + 15 01 00 00 00 00 02 26 40 + 15 01 00 00 00 00 02 27 40 /* Vend */ - 15 01 00 00 10 00 02 e0 00 - 15 01 00 00 10 00 02 dc 21 - 15 01 00 00 10 00 02 dd 22 - 15 01 00 00 10 00 02 de 07 - 15 01 00 00 10 00 02 df 07 - 15 01 00 00 10 00 02 e3 6D - 15 01 00 00 10 00 02 e1 07 - 15 01 00 00 10 00 02 e2 07 + 15 01 00 00 00 00 02 e0 00 + 15 01 00 00 00 00 02 dc 21 + 15 01 00 00 00 00 02 dd 22 + 15 01 00 00 00 00 02 de 07 + 15 01 00 00 00 00 02 df 07 + 15 01 00 00 00 00 02 e3 6D + 15 01 00 00 00 00 02 e1 07 + 15 01 00 00 00 00 02 e2 07 /* UD */ - 15 01 00 00 10 00 02 29 d8 - 15 01 00 00 10 00 02 2a 2a + 15 01 00 00 00 00 02 29 d8 + 15 01 00 00 00 00 02 2a 2a /* CLK */ - 15 01 00 00 10 00 02 4b 03 - 15 01 00 00 10 00 02 4c 11 - 15 01 00 00 10 00 02 4d 10 - 15 01 00 00 10 00 02 4e 01 - 15 01 00 00 10 00 02 4f 01 - 15 01 00 00 10 00 02 50 10 - 15 01 00 00 10 00 02 51 00 - 15 01 00 00 10 00 02 52 80 - 15 01 00 00 10 00 02 53 00 - 15 01 00 00 10 00 02 56 00 - 15 01 00 00 10 00 02 54 07 - 15 01 00 00 10 00 02 58 07 - 15 01 00 00 10 00 02 55 25 + 15 01 00 00 00 00 02 4b 03 + 15 01 00 00 00 00 02 4c 11 + 15 01 00 00 00 00 02 4d 10 + 15 01 00 00 00 00 02 4e 01 + 15 01 00 00 00 00 02 4f 01 + 15 01 00 00 00 00 02 50 10 + 15 01 00 00 00 00 02 51 00 + 15 01 00 00 00 00 02 52 80 + 15 01 00 00 00 00 02 53 00 + 15 01 00 00 00 00 02 56 00 + 15 01 00 00 00 00 02 54 07 + 15 01 00 00 00 00 02 58 07 + 15 01 00 00 00 00 02 55 25 /* Reset XDONB */ - 15 01 00 00 10 00 02 5b 43 - 15 01 00 00 10 00 02 5c 00 - 15 01 00 00 10 00 02 5f 73 - 15 01 00 00 10 00 02 60 73 - 15 01 00 00 10 00 02 63 22 - 15 01 00 00 10 00 02 64 00 - 15 01 00 00 10 00 02 67 08 - 15 01 00 00 10 00 02 68 04 + 15 01 00 00 00 00 02 5b 43 + 15 01 00 00 00 00 02 5c 00 + 15 01 00 00 00 00 02 5f 73 + 15 01 00 00 00 00 02 60 73 + 15 01 00 00 00 00 02 63 22 + 15 01 00 00 00 00 02 64 00 + 15 01 00 00 00 00 02 67 08 + 15 01 00 00 00 00 02 68 04 /* Resolution:1440x2560*/ - 15 01 00 00 10 00 02 72 02 + 15 01 00 00 00 00 02 72 02 /* mux */ - 15 01 00 00 10 00 02 7a 80 - 15 01 00 00 10 00 02 7b 91 - 15 01 00 00 10 00 02 7c D8 - 15 01 00 00 10 00 02 7d 60 - 15 01 00 00 10 00 02 7f 15 - 15 01 00 00 10 00 02 75 15 + 15 01 00 00 00 00 02 7a 80 + 15 01 00 00 00 00 02 7b 91 + 15 01 00 00 00 00 02 7c D8 + 15 01 00 00 00 00 02 7d 60 + 15 01 00 00 00 00 02 7f 15 + 15 01 00 00 00 00 02 75 15 /* ABOFF */ - 15 01 00 00 10 00 02 b3 C0 - 15 01 00 00 10 00 02 b4 00 - 15 01 00 00 10 00 02 b5 00 + 15 01 00 00 00 00 02 b3 C0 + 15 01 00 00 00 00 02 b4 00 + 15 01 00 00 00 00 02 b5 00 /* Source EQ */ - 15 01 00 00 10 00 02 78 00 - 15 01 00 00 10 00 02 79 00 - 15 01 00 00 10 00 02 80 00 - 15 01 00 00 10 00 02 83 00 + 15 01 00 00 00 00 02 78 00 + 15 01 00 00 00 00 02 79 00 + 15 01 00 00 00 00 02 80 00 + 15 01 00 00 00 00 02 83 00 /* FP BP */ - 15 01 00 00 10 00 02 93 0a - 15 01 00 00 10 00 02 94 0a + 15 01 00 00 00 00 02 93 0a + 15 01 00 00 00 00 02 94 0a /* Inversion Type */ - 15 01 00 00 10 00 02 8a 00 - 15 01 00 00 10 00 02 9b ff + 15 01 00 00 00 00 02 8a 00 + 15 01 00 00 00 00 02 9b ff /* IMGSWAP =1 @PortSwap=1 */ - 15 01 00 00 10 00 02 9d b0 - 15 01 00 00 10 00 02 9f 63 - 15 01 00 00 10 00 02 98 10 + 15 01 00 00 00 00 02 9d b0 + 15 01 00 00 00 00 02 9f 63 + 15 01 00 00 00 00 02 98 10 /* FRM */ - 15 01 00 00 10 00 02 ec 00 + 15 01 00 00 00 00 02 ec 00 /* CMD1 */ - 15 01 00 00 10 00 02 ff 10 + 15 01 00 00 00 00 02 ff 10 /* VESA DSC PPS settings(1440x2560 slide 16H) */ - 39 01 00 00 10 00 11 c1 09 20 00 10 02 00 02 68 + 39 01 00 00 00 00 11 c1 09 20 00 10 02 00 02 68 01 bb 00 0a 06 67 04 c5 - 39 01 00 00 10 00 03 c2 10 f0 + 39 01 00 00 00 00 03 c2 10 f0 /* C0h = 0x0(2 Port SDC)0x01(1 PortA FBC) * 0x02(MTK) 0x03(1 PortA VESA) */ - 15 01 00 00 10 00 02 c0 03 + 15 01 00 00 00 00 02 c0 03 /* VBP+VSA=,VFP = 10H */ - 15 01 00 00 10 00 04 3b 03 0a 0a + 15 01 00 00 00 00 04 3b 03 0a 0a /* FTE on */ - 15 01 00 00 10 00 02 35 00 + 15 01 00 00 00 00 02 35 00 /* EN_BK =1(auto black) */ - 15 01 00 00 10 00 02 e5 01 + 15 01 00 00 00 00 02 e5 01 /* CMD mode(10) VDO mode(03) */ - 15 01 00 00 10 00 02 bb 10 + 15 01 00 00 00 00 02 bb 10 /* Non Reload MTP */ - 15 01 00 00 10 00 02 fb 01 + 15 01 00 00 00 00 02 fb 01 /* SlpOut + DispOn */ - 05 01 00 00 a0 00 02 11 00 - 05 01 00 00 a0 00 02 29 00 + 05 01 00 00 78 00 02 11 00 + 05 01 00 00 78 00 02 29 00 ]; qcom,mdss-dsi-off-command = [05 01 00 00 78 00 02 28 00 05 01 00 00 78 00 02 10 00]; diff --git a/arch/arm/boot/dts/qcom/dsi-panel-nt35597-truly-dsc-wqxga-video.dtsi b/arch/arm/boot/dts/qcom/dsi-panel-nt35597-truly-dsc-wqxga-video.dtsi index ca2ff6eb4924..353b3b2b09bd 100644 --- a/arch/arm/boot/dts/qcom/dsi-panel-nt35597-truly-dsc-wqxga-video.dtsi +++ b/arch/arm/boot/dts/qcom/dsi-panel-nt35597-truly-dsc-wqxga-video.dtsi @@ -1,4 +1,4 @@ -/* Copyright (c) 2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2017, 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 @@ -32,162 +32,162 @@ qcom,mdss-dsi-border-color = <0>; qcom,mdss-dsi-on-command = [ /* CMD2_P0 */ - 15 01 00 00 10 00 02 ff 20 - 15 01 00 00 10 00 02 fb 01 - 15 01 00 00 10 00 02 00 01 - 15 01 00 00 10 00 02 01 55 - 15 01 00 00 10 00 02 02 45 - 15 01 00 00 10 00 02 05 40 - 15 01 00 00 10 00 02 06 19 - 15 01 00 00 10 00 02 07 1e - 15 01 00 00 10 00 02 0b 73 - 15 01 00 00 10 00 02 0c 73 - 15 01 00 00 10 00 02 0e b0 - 15 01 00 00 10 00 02 0f aE - 15 01 00 00 10 00 02 11 b8 - 15 01 00 00 10 00 02 13 00 - 15 01 00 00 10 00 02 58 80 - 15 01 00 00 10 00 02 59 01 - 15 01 00 00 10 00 02 5a 00 - 15 01 00 00 10 00 02 5b 01 - 15 01 00 00 10 00 02 5c 80 - 15 01 00 00 10 00 02 5d 81 - 15 01 00 00 10 00 02 5e 00 - 15 01 00 00 10 00 02 5f 01 - 15 01 00 00 10 00 02 72 31 - 15 01 00 00 10 00 02 68 03 + 15 01 00 00 00 00 02 ff 20 + 15 01 00 00 00 00 02 fb 01 + 15 01 00 00 00 00 02 00 01 + 15 01 00 00 00 00 02 01 55 + 15 01 00 00 00 00 02 02 45 + 15 01 00 00 00 00 02 05 40 + 15 01 00 00 00 00 02 06 19 + 15 01 00 00 00 00 02 07 1e + 15 01 00 00 00 00 02 0b 73 + 15 01 00 00 00 00 02 0c 73 + 15 01 00 00 00 00 02 0e b0 + 15 01 00 00 00 00 02 0f aE + 15 01 00 00 00 00 02 11 b8 + 15 01 00 00 00 00 02 13 00 + 15 01 00 00 00 00 02 58 80 + 15 01 00 00 00 00 02 59 01 + 15 01 00 00 00 00 02 5a 00 + 15 01 00 00 00 00 02 5b 01 + 15 01 00 00 00 00 02 5c 80 + 15 01 00 00 00 00 02 5d 81 + 15 01 00 00 00 00 02 5e 00 + 15 01 00 00 00 00 02 5f 01 + 15 01 00 00 00 00 02 72 31 + 15 01 00 00 00 00 02 68 03 /* CMD2_P4 */ - 15 01 00 00 10 00 02 ff 24 - 15 01 00 00 10 00 02 fb 01 - 15 01 00 00 10 00 02 00 1c - 15 01 00 00 10 00 02 01 0b - 15 01 00 00 10 00 02 02 0c - 15 01 00 00 10 00 02 03 01 - 15 01 00 00 10 00 02 04 0f - 15 01 00 00 10 00 02 05 10 - 15 01 00 00 10 00 02 06 10 - 15 01 00 00 10 00 02 07 10 - 15 01 00 00 10 00 02 08 89 - 15 01 00 00 10 00 02 09 8a - 15 01 00 00 10 00 02 0a 13 - 15 01 00 00 10 00 02 0b 13 - 15 01 00 00 10 00 02 0c 15 - 15 01 00 00 10 00 02 0d 15 - 15 01 00 00 10 00 02 0e 17 - 15 01 00 00 10 00 02 0f 17 - 15 01 00 00 10 00 02 10 1c - 15 01 00 00 10 00 02 11 0b - 15 01 00 00 10 00 02 12 0c - 15 01 00 00 10 00 02 13 01 - 15 01 00 00 10 00 02 14 0f - 15 01 00 00 10 00 02 15 10 - 15 01 00 00 10 00 02 16 10 - 15 01 00 00 10 00 02 17 10 - 15 01 00 00 10 00 02 18 89 - 15 01 00 00 10 00 02 19 8a - 15 01 00 00 10 00 02 1a 13 - 15 01 00 00 10 00 02 1b 13 - 15 01 00 00 10 00 02 1c 15 - 15 01 00 00 10 00 02 1d 15 - 15 01 00 00 10 00 02 1e 17 - 15 01 00 00 10 00 02 1f 17 + 15 01 00 00 00 00 02 ff 24 + 15 01 00 00 00 00 02 fb 01 + 15 01 00 00 00 00 02 00 1c + 15 01 00 00 00 00 02 01 0b + 15 01 00 00 00 00 02 02 0c + 15 01 00 00 00 00 02 03 01 + 15 01 00 00 00 00 02 04 0f + 15 01 00 00 00 00 02 05 10 + 15 01 00 00 00 00 02 06 10 + 15 01 00 00 00 00 02 07 10 + 15 01 00 00 00 00 02 08 89 + 15 01 00 00 00 00 02 09 8a + 15 01 00 00 00 00 02 0a 13 + 15 01 00 00 00 00 02 0b 13 + 15 01 00 00 00 00 02 0c 15 + 15 01 00 00 00 00 02 0d 15 + 15 01 00 00 00 00 02 0e 17 + 15 01 00 00 00 00 02 0f 17 + 15 01 00 00 00 00 02 10 1c + 15 01 00 00 00 00 02 11 0b + 15 01 00 00 00 00 02 12 0c + 15 01 00 00 00 00 02 13 01 + 15 01 00 00 00 00 02 14 0f + 15 01 00 00 00 00 02 15 10 + 15 01 00 00 00 00 02 16 10 + 15 01 00 00 00 00 02 17 10 + 15 01 00 00 00 00 02 18 89 + 15 01 00 00 00 00 02 19 8a + 15 01 00 00 00 00 02 1a 13 + 15 01 00 00 00 00 02 1b 13 + 15 01 00 00 00 00 02 1c 15 + 15 01 00 00 00 00 02 1d 15 + 15 01 00 00 00 00 02 1e 17 + 15 01 00 00 00 00 02 1f 17 /* STV */ - 15 01 00 00 10 00 02 20 40 - 15 01 00 00 10 00 02 21 01 - 15 01 00 00 10 00 02 22 00 - 15 01 00 00 10 00 02 23 40 - 15 01 00 00 10 00 02 24 40 - 15 01 00 00 10 00 02 25 6d - 15 01 00 00 10 00 02 26 40 - 15 01 00 00 10 00 02 27 40 + 15 01 00 00 00 00 02 20 40 + 15 01 00 00 00 00 02 21 01 + 15 01 00 00 00 00 02 22 00 + 15 01 00 00 00 00 02 23 40 + 15 01 00 00 00 00 02 24 40 + 15 01 00 00 00 00 02 25 6d + 15 01 00 00 00 00 02 26 40 + 15 01 00 00 00 00 02 27 40 /* Vend */ - 15 01 00 00 10 00 02 e0 00 - 15 01 00 00 10 00 02 dc 21 - 15 01 00 00 10 00 02 dd 22 - 15 01 00 00 10 00 02 de 07 - 15 01 00 00 10 00 02 df 07 - 15 01 00 00 10 00 02 e3 6d - 15 01 00 00 10 00 02 e1 07 - 15 01 00 00 10 00 02 e2 07 + 15 01 00 00 00 00 02 e0 00 + 15 01 00 00 00 00 02 dc 21 + 15 01 00 00 00 00 02 dd 22 + 15 01 00 00 00 00 02 de 07 + 15 01 00 00 00 00 02 df 07 + 15 01 00 00 00 00 02 e3 6d + 15 01 00 00 00 00 02 e1 07 + 15 01 00 00 00 00 02 e2 07 /* UD */ - 15 01 00 00 10 00 02 29 d8 - 15 01 00 00 10 00 02 2a 2a + 15 01 00 00 00 00 02 29 d8 + 15 01 00 00 00 00 02 2a 2a /* CLK */ - 15 01 00 00 10 00 02 4b 03 - 15 01 00 00 10 00 02 4c 11 - 15 01 00 00 10 00 02 4d 10 - 15 01 00 00 10 00 02 4e 01 - 15 01 00 00 10 00 02 4f 01 - 15 01 00 00 10 00 02 50 10 - 15 01 00 00 10 00 02 51 00 - 15 01 00 00 10 00 02 52 80 - 15 01 00 00 10 00 02 53 00 - 15 01 00 00 10 00 02 56 00 - 15 01 00 00 10 00 02 54 07 - 15 01 00 00 10 00 02 58 07 - 15 01 00 00 10 00 02 55 25 + 15 01 00 00 00 00 02 4b 03 + 15 01 00 00 00 00 02 4c 11 + 15 01 00 00 00 00 02 4d 10 + 15 01 00 00 00 00 02 4e 01 + 15 01 00 00 00 00 02 4f 01 + 15 01 00 00 00 00 02 50 10 + 15 01 00 00 00 00 02 51 00 + 15 01 00 00 00 00 02 52 80 + 15 01 00 00 00 00 02 53 00 + 15 01 00 00 00 00 02 56 00 + 15 01 00 00 00 00 02 54 07 + 15 01 00 00 00 00 02 58 07 + 15 01 00 00 00 00 02 55 25 /* Reset XDONB */ - 15 01 00 00 10 00 02 5b 43 - 15 01 00 00 10 00 02 5c 00 - 15 01 00 00 10 00 02 5f 73 - 15 01 00 00 10 00 02 60 73 - 15 01 00 00 10 00 02 63 22 - 15 01 00 00 10 00 02 64 00 - 15 01 00 00 10 00 02 67 08 - 15 01 00 00 10 00 02 68 04 + 15 01 00 00 00 00 02 5b 43 + 15 01 00 00 00 00 02 5c 00 + 15 01 00 00 00 00 02 5f 73 + 15 01 00 00 00 00 02 60 73 + 15 01 00 00 00 00 02 63 22 + 15 01 00 00 00 00 02 64 00 + 15 01 00 00 00 00 02 67 08 + 15 01 00 00 00 00 02 68 04 /* Resolution:1440x2560*/ - 15 01 00 00 10 00 02 72 02 + 15 01 00 00 00 00 02 72 02 /* mux */ - 15 01 00 00 10 00 02 7a 80 - 15 01 00 00 10 00 02 7b 91 - 15 01 00 00 10 00 02 7c d8 - 15 01 00 00 10 00 02 7d 60 - 15 01 00 00 10 00 02 7f 15 - 15 01 00 00 10 00 02 75 15 + 15 01 00 00 00 00 02 7a 80 + 15 01 00 00 00 00 02 7b 91 + 15 01 00 00 00 00 02 7c d8 + 15 01 00 00 00 00 02 7d 60 + 15 01 00 00 00 00 02 7f 15 + 15 01 00 00 00 00 02 75 15 /* ABOFF */ - 15 01 00 00 10 00 02 b3 c0 - 15 01 00 00 10 00 02 b4 00 - 15 01 00 00 10 00 02 b5 00 + 15 01 00 00 00 00 02 b3 c0 + 15 01 00 00 00 00 02 b4 00 + 15 01 00 00 00 00 02 b5 00 /* Source EQ */ - 15 01 00 00 10 00 02 78 00 - 15 01 00 00 10 00 02 79 00 - 15 01 00 00 10 00 02 80 00 - 15 01 00 00 10 00 02 83 00 + 15 01 00 00 00 00 02 78 00 + 15 01 00 00 00 00 02 79 00 + 15 01 00 00 00 00 02 80 00 + 15 01 00 00 00 00 02 83 00 /* FP BP */ - 15 01 00 00 10 00 02 93 0a - 15 01 00 00 10 00 02 94 0a + 15 01 00 00 00 00 02 93 0a + 15 01 00 00 00 00 02 94 0a /* Inversion Type */ - 15 01 00 00 10 00 02 8a 00 - 15 01 00 00 10 00 02 9b ff + 15 01 00 00 00 00 02 8a 00 + 15 01 00 00 00 00 02 9b ff /* IMGSWAP =1 @PortSwap=1 */ - 15 01 00 00 10 00 02 9d b0 - 15 01 00 00 10 00 02 9f 63 - 15 01 00 00 10 00 02 98 10 + 15 01 00 00 00 00 02 9d b0 + 15 01 00 00 00 00 02 9f 63 + 15 01 00 00 00 00 02 98 10 /* FRM */ - 15 01 00 00 10 00 02 ec 00 + 15 01 00 00 00 00 02 ec 00 /* CMD1 */ - 15 01 00 00 10 00 02 ff 10 + 15 01 00 00 00 00 02 ff 10 /* VESA DSC PPS settings(1440x2560 slide 16H) */ - 39 01 00 00 10 00 11 c1 09 20 00 10 02 00 02 68 01 + 39 01 00 00 00 00 11 c1 09 20 00 10 02 00 02 68 01 bb 00 0a 06 67 04 c5 - 39 01 00 00 10 00 03 c2 10 f0 + 39 01 00 00 00 00 03 c2 10 f0 /* C0h = 0x00(2 Port SDC); 0x01(1 PortA FBC); * 0x02(MTK); 0x03(1 PortA VESA) */ - 15 01 00 00 10 00 02 c0 03 + 15 01 00 00 00 00 02 c0 03 /* VBP+VSA=,VFP = 10H */ - 39 01 00 00 10 00 04 3b 03 0a 0a + 39 01 00 00 00 00 04 3b 03 0a 0a /* FTE on */ - 15 01 00 00 10 00 02 35 00 + 15 01 00 00 00 00 02 35 00 /* EN_BK =1(auto black) */ - 15 01 00 00 10 00 02 e5 01 + 15 01 00 00 00 00 02 e5 01 /* CMD mode(10) VDO mode(03) */ - 15 01 00 00 10 00 02 bb 03 + 15 01 00 00 00 00 02 bb 03 /* Non Reload MTP */ - 15 01 00 00 10 00 02 fb 01 + 15 01 00 00 00 00 02 fb 01 /* SlpOut + DispOn */ - 05 01 00 00 a0 00 02 11 00 - 05 01 00 00 a0 00 02 29 00 + 05 01 00 00 78 00 02 11 00 + 05 01 00 00 78 00 02 29 00 ]; qcom,mdss-dsi-off-command = [05 01 00 00 78 00 02 28 00 05 01 00 00 78 00 02 10 00]; diff --git a/arch/arm/boot/dts/qcom/dsi-panel-nt35597-truly-dualmipi-wqxga-cmd.dtsi b/arch/arm/boot/dts/qcom/dsi-panel-nt35597-truly-dualmipi-wqxga-cmd.dtsi index 28b0d6d9cf14..6ff016676de7 100644 --- a/arch/arm/boot/dts/qcom/dsi-panel-nt35597-truly-dualmipi-wqxga-cmd.dtsi +++ b/arch/arm/boot/dts/qcom/dsi-panel-nt35597-truly-dualmipi-wqxga-cmd.dtsi @@ -1,4 +1,4 @@ -/* Copyright (c) 2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2017, 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 @@ -61,154 +61,154 @@ qcom,ulps-enabled; qcom,mdss-dsi-on-command = [ /* CMD2_P0 */ - 15 01 00 00 10 00 02 FF 20 - 15 01 00 00 10 00 02 fb 01 - 15 01 00 00 10 00 02 00 01 - 15 01 00 00 10 00 02 01 55 - 15 01 00 00 10 00 02 02 45 - 15 01 00 00 10 00 02 05 40 - 15 01 00 00 10 00 02 06 19 - 15 01 00 00 10 00 02 07 1E - 15 01 00 00 10 00 02 0B 73 - 15 01 00 00 10 00 02 0C 73 - 15 01 00 00 10 00 02 0E B0 - 15 01 00 00 10 00 02 0F AE - 15 01 00 00 10 00 02 11 B8 - 15 01 00 00 10 00 02 13 00 - 15 01 00 00 10 00 02 58 80 - 15 01 00 00 10 00 02 59 01 - 15 01 00 00 10 00 02 5A 00 - 15 01 00 00 10 00 02 5B 01 - 15 01 00 00 10 00 02 5C 80 - 15 01 00 00 10 00 02 5D 81 - 15 01 00 00 10 00 02 5E 00 - 15 01 00 00 10 00 02 5F 01 - 15 01 00 00 10 00 02 72 31 - 15 01 00 00 10 00 02 68 03 + 15 01 00 00 00 00 02 FF 20 + 15 01 00 00 00 00 02 fb 01 + 15 01 00 00 00 00 02 00 01 + 15 01 00 00 00 00 02 01 55 + 15 01 00 00 00 00 02 02 45 + 15 01 00 00 00 00 02 05 40 + 15 01 00 00 00 00 02 06 19 + 15 01 00 00 00 00 02 07 1E + 15 01 00 00 00 00 02 0B 73 + 15 01 00 00 00 00 02 0C 73 + 15 01 00 00 00 00 02 0E B0 + 15 01 00 00 00 00 02 0F AE + 15 01 00 00 00 00 02 11 B8 + 15 01 00 00 00 00 02 13 00 + 15 01 00 00 00 00 02 58 80 + 15 01 00 00 00 00 02 59 01 + 15 01 00 00 00 00 02 5A 00 + 15 01 00 00 00 00 02 5B 01 + 15 01 00 00 00 00 02 5C 80 + 15 01 00 00 00 00 02 5D 81 + 15 01 00 00 00 00 02 5E 00 + 15 01 00 00 00 00 02 5F 01 + 15 01 00 00 00 00 02 72 31 + 15 01 00 00 00 00 02 68 03 /* CMD2_P4 */ - 15 01 00 00 10 00 02 ff 24 - 15 01 00 00 10 00 02 fb 01 - 15 01 00 00 10 00 02 00 1C - 15 01 00 00 10 00 02 01 0B - 15 01 00 00 10 00 02 02 0C - 15 01 00 00 10 00 02 03 01 - 15 01 00 00 10 00 02 04 0F - 15 01 00 00 10 00 02 05 10 - 15 01 00 00 10 00 02 06 10 - 15 01 00 00 10 00 02 07 10 - 15 01 00 00 10 00 02 08 89 - 15 01 00 00 10 00 02 09 8A - 15 01 00 00 10 00 02 0A 13 - 15 01 00 00 10 00 02 0B 13 - 15 01 00 00 10 00 02 0C 15 - 15 01 00 00 10 00 02 0D 15 - 15 01 00 00 10 00 02 0E 17 - 15 01 00 00 10 00 02 0F 17 - 15 01 00 00 10 00 02 10 1C - 15 01 00 00 10 00 02 11 0B - 15 01 00 00 10 00 02 12 0C - 15 01 00 00 10 00 02 13 01 - 15 01 00 00 10 00 02 14 0F - 15 01 00 00 10 00 02 15 10 - 15 01 00 00 10 00 02 16 10 - 15 01 00 00 10 00 02 17 10 - 15 01 00 00 10 00 02 18 89 - 15 01 00 00 10 00 02 19 8A - 15 01 00 00 10 00 02 1A 13 - 15 01 00 00 10 00 02 1B 13 - 15 01 00 00 10 00 02 1C 15 - 15 01 00 00 10 00 02 1D 15 - 15 01 00 00 10 00 02 1E 17 - 15 01 00 00 10 00 02 1F 17 + 15 01 00 00 00 00 02 ff 24 + 15 01 00 00 00 00 02 fb 01 + 15 01 00 00 00 00 02 00 1C + 15 01 00 00 00 00 02 01 0B + 15 01 00 00 00 00 02 02 0C + 15 01 00 00 00 00 02 03 01 + 15 01 00 00 00 00 02 04 0F + 15 01 00 00 00 00 02 05 10 + 15 01 00 00 00 00 02 06 10 + 15 01 00 00 00 00 02 07 10 + 15 01 00 00 00 00 02 08 89 + 15 01 00 00 00 00 02 09 8A + 15 01 00 00 00 00 02 0A 13 + 15 01 00 00 00 00 02 0B 13 + 15 01 00 00 00 00 02 0C 15 + 15 01 00 00 00 00 02 0D 15 + 15 01 00 00 00 00 02 0E 17 + 15 01 00 00 00 00 02 0F 17 + 15 01 00 00 00 00 02 10 1C + 15 01 00 00 00 00 02 11 0B + 15 01 00 00 00 00 02 12 0C + 15 01 00 00 00 00 02 13 01 + 15 01 00 00 00 00 02 14 0F + 15 01 00 00 00 00 02 15 10 + 15 01 00 00 00 00 02 16 10 + 15 01 00 00 00 00 02 17 10 + 15 01 00 00 00 00 02 18 89 + 15 01 00 00 00 00 02 19 8A + 15 01 00 00 00 00 02 1A 13 + 15 01 00 00 00 00 02 1B 13 + 15 01 00 00 00 00 02 1C 15 + 15 01 00 00 00 00 02 1D 15 + 15 01 00 00 00 00 02 1E 17 + 15 01 00 00 00 00 02 1F 17 /* STV */ - 15 01 00 00 10 00 02 20 40 - 15 01 00 00 10 00 02 21 01 - 15 01 00 00 10 00 02 22 00 - 15 01 00 00 10 00 02 23 40 - 15 01 00 00 10 00 02 24 40 - 15 01 00 00 10 00 02 25 6D - 15 01 00 00 10 00 02 26 40 - 15 01 00 00 10 00 02 27 40 + 15 01 00 00 00 00 02 20 40 + 15 01 00 00 00 00 02 21 01 + 15 01 00 00 00 00 02 22 00 + 15 01 00 00 00 00 02 23 40 + 15 01 00 00 00 00 02 24 40 + 15 01 00 00 00 00 02 25 6D + 15 01 00 00 00 00 02 26 40 + 15 01 00 00 00 00 02 27 40 /* Vend */ - 15 01 00 00 10 00 02 E0 00 - 15 01 00 00 10 00 02 DC 21 - 15 01 00 00 10 00 02 DD 22 - 15 01 00 00 10 00 02 DE 07 - 15 01 00 00 10 00 02 DF 07 - 15 01 00 00 10 00 02 E3 6D - 15 01 00 00 10 00 02 E1 07 - 15 01 00 00 10 00 02 E2 07 + 15 01 00 00 00 00 02 E0 00 + 15 01 00 00 00 00 02 DC 21 + 15 01 00 00 00 00 02 DD 22 + 15 01 00 00 00 00 02 DE 07 + 15 01 00 00 00 00 02 DF 07 + 15 01 00 00 00 00 02 E3 6D + 15 01 00 00 00 00 02 E1 07 + 15 01 00 00 00 00 02 E2 07 /* UD */ - 15 01 00 00 10 00 02 29 D8 - 15 01 00 00 10 00 02 2A 2A + 15 01 00 00 00 00 02 29 D8 + 15 01 00 00 00 00 02 2A 2A /* CLK */ - 15 01 00 00 10 00 02 4B 03 - 15 01 00 00 10 00 02 4C 11 - 15 01 00 00 10 00 02 4D 10 - 15 01 00 00 10 00 02 4E 01 - 15 01 00 00 10 00 02 4F 01 - 15 01 00 00 10 00 02 50 10 - 15 01 00 00 10 00 02 51 00 - 15 01 00 00 10 00 02 52 80 - 15 01 00 00 10 00 02 53 00 - 15 01 00 00 10 00 02 56 00 - 15 01 00 00 10 00 02 54 07 - 15 01 00 00 10 00 02 58 07 - 15 01 00 00 10 00 02 55 25 + 15 01 00 00 00 00 02 4B 03 + 15 01 00 00 00 00 02 4C 11 + 15 01 00 00 00 00 02 4D 10 + 15 01 00 00 00 00 02 4E 01 + 15 01 00 00 00 00 02 4F 01 + 15 01 00 00 00 00 02 50 10 + 15 01 00 00 00 00 02 51 00 + 15 01 00 00 00 00 02 52 80 + 15 01 00 00 00 00 02 53 00 + 15 01 00 00 00 00 02 56 00 + 15 01 00 00 00 00 02 54 07 + 15 01 00 00 00 00 02 58 07 + 15 01 00 00 00 00 02 55 25 /* Reset XDONB */ - 15 01 00 00 10 00 02 5B 43 - 15 01 00 00 10 00 02 5C 00 - 15 01 00 00 10 00 02 5F 73 - 15 01 00 00 10 00 02 60 73 - 15 01 00 00 10 00 02 63 22 - 15 01 00 00 10 00 02 64 00 - 15 01 00 00 10 00 02 67 08 - 15 01 00 00 10 00 02 68 04 + 15 01 00 00 00 00 02 5B 43 + 15 01 00 00 00 00 02 5C 00 + 15 01 00 00 00 00 02 5F 73 + 15 01 00 00 00 00 02 60 73 + 15 01 00 00 00 00 02 63 22 + 15 01 00 00 00 00 02 64 00 + 15 01 00 00 00 00 02 67 08 + 15 01 00 00 00 00 02 68 04 /* Resolution:1440x2560*/ - 15 01 00 00 10 00 02 72 02 + 15 01 00 00 00 00 02 72 02 /* mux */ - 15 01 00 00 10 00 02 7A 80 - 15 01 00 00 10 00 02 7B 91 - 15 01 00 00 10 00 02 7C D8 - 15 01 00 00 10 00 02 7D 60 - 15 01 00 00 10 00 02 7F 15 - 15 01 00 00 10 00 02 75 15 + 15 01 00 00 00 00 02 7A 80 + 15 01 00 00 00 00 02 7B 91 + 15 01 00 00 00 00 02 7C D8 + 15 01 00 00 00 00 02 7D 60 + 15 01 00 00 00 00 02 7F 15 + 15 01 00 00 00 00 02 75 15 /* ABOFF */ - 15 01 00 00 10 00 02 B3 C0 - 15 01 00 00 10 00 02 B4 00 - 15 01 00 00 10 00 02 B5 00 + 15 01 00 00 00 00 02 B3 C0 + 15 01 00 00 00 00 02 B4 00 + 15 01 00 00 00 00 02 B5 00 /* Source EQ */ - 15 01 00 00 10 00 02 78 00 - 15 01 00 00 10 00 02 79 00 - 15 01 00 00 10 00 02 80 00 - 15 01 00 00 10 00 02 83 00 + 15 01 00 00 00 00 02 78 00 + 15 01 00 00 00 00 02 79 00 + 15 01 00 00 00 00 02 80 00 + 15 01 00 00 00 00 02 83 00 /* FP BP */ - 15 01 00 00 10 00 02 93 0A - 15 01 00 00 10 00 02 94 0A + 15 01 00 00 00 00 02 93 0A + 15 01 00 00 00 00 02 94 0A /* Inversion Type */ - 15 01 00 00 10 00 02 8A 00 - 15 01 00 00 10 00 02 9B FF + 15 01 00 00 00 00 02 8A 00 + 15 01 00 00 00 00 02 9B FF /* IMGSWAP =1 @PortSwap=1 */ - 15 01 00 00 10 00 02 9D B0 - 15 01 00 00 10 00 02 9F 63 - 15 01 00 00 10 00 02 98 10 + 15 01 00 00 00 00 02 9D B0 + 15 01 00 00 00 00 02 9F 63 + 15 01 00 00 00 00 02 98 10 /* FRM */ - 15 01 00 00 10 00 02 EC 00 + 15 01 00 00 00 00 02 EC 00 /* CMD1 */ - 15 01 00 00 10 00 02 ff 10 + 15 01 00 00 00 00 02 ff 10 /* VBP+VSA=,VFP = 10H */ - 15 01 00 00 10 00 04 3B 03 0A 0A + 15 01 00 00 00 00 04 3B 03 0A 0A /* FTE on */ - 15 01 00 00 10 00 02 35 00 + 15 01 00 00 00 00 02 35 00 /* EN_BK =1(auto black) */ - 15 01 00 00 10 00 02 E5 01 + 15 01 00 00 00 00 02 E5 01 /* CMD mode(10) VDO mode(03) */ - 15 01 00 00 10 00 02 BB 10 + 15 01 00 00 00 00 02 BB 10 /* Non Reload MTP */ - 15 01 00 00 10 00 02 FB 01 + 15 01 00 00 00 00 02 FB 01 /* SlpOut + DispOn */ - 05 01 00 00 a0 00 02 11 00 - 05 01 00 00 a0 00 02 29 00 + 05 01 00 00 78 00 02 11 00 + 05 01 00 00 78 00 02 29 00 ]; qcom,mdss-dsi-off-command = [05 01 00 00 78 00 02 28 00 05 01 00 00 78 00 02 10 00]; diff --git a/arch/arm/boot/dts/qcom/dsi-panel-nt35597-truly-dualmipi-wqxga-video.dtsi b/arch/arm/boot/dts/qcom/dsi-panel-nt35597-truly-dualmipi-wqxga-video.dtsi index 752345283819..d179acd043ed 100644 --- a/arch/arm/boot/dts/qcom/dsi-panel-nt35597-truly-dualmipi-wqxga-video.dtsi +++ b/arch/arm/boot/dts/qcom/dsi-panel-nt35597-truly-dualmipi-wqxga-video.dtsi @@ -32,154 +32,154 @@ qcom,mdss-dsi-border-color = <0>; qcom,mdss-dsi-on-command = [ /* CMD2_P0 */ - 15 01 00 00 10 00 02 FF 20 - 15 01 00 00 10 00 02 FB 01 - 15 01 00 00 10 00 02 00 01 - 15 01 00 00 10 00 02 01 55 - 15 01 00 00 10 00 02 02 45 - 15 01 00 00 10 00 02 05 40 - 15 01 00 00 10 00 02 06 19 - 15 01 00 00 10 00 02 07 1E - 15 01 00 00 10 00 02 0B 73 - 15 01 00 00 10 00 02 0C 73 - 15 01 00 00 10 00 02 0E B0 - 15 01 00 00 10 00 02 0F AE - 15 01 00 00 10 00 02 11 B8 - 15 01 00 00 10 00 02 13 00 - 15 01 00 00 10 00 02 58 80 - 15 01 00 00 10 00 02 59 01 - 15 01 00 00 10 00 02 5A 00 - 15 01 00 00 10 00 02 5B 01 - 15 01 00 00 10 00 02 5C 80 - 15 01 00 00 10 00 02 5D 81 - 15 01 00 00 10 00 02 5E 00 - 15 01 00 00 10 00 02 5F 01 - 15 01 00 00 10 00 02 72 31 - 15 01 00 00 10 00 02 68 03 + 15 01 00 00 00 00 02 FF 20 + 15 01 00 00 00 00 02 FB 01 + 15 01 00 00 00 00 02 00 01 + 15 01 00 00 00 00 02 01 55 + 15 01 00 00 00 00 02 02 45 + 15 01 00 00 00 00 02 05 40 + 15 01 00 00 00 00 02 06 19 + 15 01 00 00 00 00 02 07 1E + 15 01 00 00 00 00 02 0B 73 + 15 01 00 00 00 00 02 0C 73 + 15 01 00 00 00 00 02 0E B0 + 15 01 00 00 00 00 02 0F AE + 15 01 00 00 00 00 02 11 B8 + 15 01 00 00 00 00 02 13 00 + 15 01 00 00 00 00 02 58 80 + 15 01 00 00 00 00 02 59 01 + 15 01 00 00 00 00 02 5A 00 + 15 01 00 00 00 00 02 5B 01 + 15 01 00 00 00 00 02 5C 80 + 15 01 00 00 00 00 02 5D 81 + 15 01 00 00 00 00 02 5E 00 + 15 01 00 00 00 00 02 5F 01 + 15 01 00 00 00 00 02 72 31 + 15 01 00 00 00 00 02 68 03 /* CMD2_P4 */ - 15 01 00 00 10 00 02 FF 24 - 15 01 00 00 10 00 02 FB 01 - 15 01 00 00 10 00 02 00 1C - 15 01 00 00 10 00 02 01 0B - 15 01 00 00 10 00 02 02 0C - 15 01 00 00 10 00 02 03 01 - 15 01 00 00 10 00 02 04 0F - 15 01 00 00 10 00 02 05 10 - 15 01 00 00 10 00 02 06 10 - 15 01 00 00 10 00 02 07 10 - 15 01 00 00 10 00 02 08 89 - 15 01 00 00 10 00 02 09 8A - 15 01 00 00 10 00 02 0A 13 - 15 01 00 00 10 00 02 0B 13 - 15 01 00 00 10 00 02 0C 15 - 15 01 00 00 10 00 02 0D 15 - 15 01 00 00 10 00 02 0E 17 - 15 01 00 00 10 00 02 0F 17 - 15 01 00 00 10 00 02 10 1C - 15 01 00 00 10 00 02 11 0B - 15 01 00 00 10 00 02 12 0C - 15 01 00 00 10 00 02 13 01 - 15 01 00 00 10 00 02 14 0F - 15 01 00 00 10 00 02 15 10 - 15 01 00 00 10 00 02 16 10 - 15 01 00 00 10 00 02 17 10 - 15 01 00 00 10 00 02 18 89 - 15 01 00 00 10 00 02 19 8A - 15 01 00 00 10 00 02 1A 13 - 15 01 00 00 10 00 02 1B 13 - 15 01 00 00 10 00 02 1C 15 - 15 01 00 00 10 00 02 1D 15 - 15 01 00 00 10 00 02 1E 17 - 15 01 00 00 10 00 02 1F 17 + 15 01 00 00 00 00 02 FF 24 + 15 01 00 00 00 00 02 FB 01 + 15 01 00 00 00 00 02 00 1C + 15 01 00 00 00 00 02 01 0B + 15 01 00 00 00 00 02 02 0C + 15 01 00 00 00 00 02 03 01 + 15 01 00 00 00 00 02 04 0F + 15 01 00 00 00 00 02 05 10 + 15 01 00 00 00 00 02 06 10 + 15 01 00 00 00 00 02 07 10 + 15 01 00 00 00 00 02 08 89 + 15 01 00 00 00 00 02 09 8A + 15 01 00 00 00 00 02 0A 13 + 15 01 00 00 00 00 02 0B 13 + 15 01 00 00 00 00 02 0C 15 + 15 01 00 00 00 00 02 0D 15 + 15 01 00 00 00 00 02 0E 17 + 15 01 00 00 00 00 02 0F 17 + 15 01 00 00 00 00 02 10 1C + 15 01 00 00 00 00 02 11 0B + 15 01 00 00 00 00 02 12 0C + 15 01 00 00 00 00 02 13 01 + 15 01 00 00 00 00 02 14 0F + 15 01 00 00 00 00 02 15 10 + 15 01 00 00 00 00 02 16 10 + 15 01 00 00 00 00 02 17 10 + 15 01 00 00 00 00 02 18 89 + 15 01 00 00 00 00 02 19 8A + 15 01 00 00 00 00 02 1A 13 + 15 01 00 00 00 00 02 1B 13 + 15 01 00 00 00 00 02 1C 15 + 15 01 00 00 00 00 02 1D 15 + 15 01 00 00 00 00 02 1E 17 + 15 01 00 00 00 00 02 1F 17 /* STV */ - 15 01 00 00 10 00 02 20 40 - 15 01 00 00 10 00 02 21 01 - 15 01 00 00 10 00 02 22 00 - 15 01 00 00 10 00 02 23 40 - 15 01 00 00 10 00 02 24 40 - 15 01 00 00 10 00 02 25 6D - 15 01 00 00 10 00 02 26 40 - 15 01 00 00 10 00 02 27 40 + 15 01 00 00 00 00 02 20 40 + 15 01 00 00 00 00 02 21 01 + 15 01 00 00 00 00 02 22 00 + 15 01 00 00 00 00 02 23 40 + 15 01 00 00 00 00 02 24 40 + 15 01 00 00 00 00 02 25 6D + 15 01 00 00 00 00 02 26 40 + 15 01 00 00 00 00 02 27 40 /* Vend */ - 15 01 00 00 10 00 02 E0 00 - 15 01 00 00 10 00 02 DC 21 - 15 01 00 00 10 00 02 DD 22 - 15 01 00 00 10 00 02 DE 07 - 15 01 00 00 10 00 02 DF 07 - 15 01 00 00 10 00 02 E3 6D - 15 01 00 00 10 00 02 E1 07 - 15 01 00 00 10 00 02 E2 07 + 15 01 00 00 00 00 02 E0 00 + 15 01 00 00 00 00 02 DC 21 + 15 01 00 00 00 00 02 DD 22 + 15 01 00 00 00 00 02 DE 07 + 15 01 00 00 00 00 02 DF 07 + 15 01 00 00 00 00 02 E3 6D + 15 01 00 00 00 00 02 E1 07 + 15 01 00 00 00 00 02 E2 07 /* UD */ - 15 01 00 00 10 00 02 29 D8 - 15 01 00 00 10 00 02 2A 2A + 15 01 00 00 00 00 02 29 D8 + 15 01 00 00 00 00 02 2A 2A /* CLK */ - 15 01 00 00 10 00 02 4B 03 - 15 01 00 00 10 00 02 4C 11 - 15 01 00 00 10 00 02 4D 10 - 15 01 00 00 10 00 02 4E 01 - 15 01 00 00 10 00 02 4F 01 - 15 01 00 00 10 00 02 50 10 - 15 01 00 00 10 00 02 51 00 - 15 01 00 00 10 00 02 52 80 - 15 01 00 00 10 00 02 53 00 - 15 01 00 00 10 00 02 56 00 - 15 01 00 00 10 00 02 54 07 - 15 01 00 00 10 00 02 58 07 - 15 01 00 00 10 00 02 55 25 + 15 01 00 00 00 00 02 4B 03 + 15 01 00 00 00 00 02 4C 11 + 15 01 00 00 00 00 02 4D 10 + 15 01 00 00 00 00 02 4E 01 + 15 01 00 00 00 00 02 4F 01 + 15 01 00 00 00 00 02 50 10 + 15 01 00 00 00 00 02 51 00 + 15 01 00 00 00 00 02 52 80 + 15 01 00 00 00 00 02 53 00 + 15 01 00 00 00 00 02 56 00 + 15 01 00 00 00 00 02 54 07 + 15 01 00 00 00 00 02 58 07 + 15 01 00 00 00 00 02 55 25 /* Reset XDONB */ - 15 01 00 00 10 00 02 5B 43 - 15 01 00 00 10 00 02 5C 00 - 15 01 00 00 10 00 02 5F 73 - 15 01 00 00 10 00 02 60 73 - 15 01 00 00 10 00 02 63 22 - 15 01 00 00 10 00 02 64 00 - 15 01 00 00 10 00 02 67 08 - 15 01 00 00 10 00 02 68 04 + 15 01 00 00 00 00 02 5B 43 + 15 01 00 00 00 00 02 5C 00 + 15 01 00 00 00 00 02 5F 73 + 15 01 00 00 00 00 02 60 73 + 15 01 00 00 00 00 02 63 22 + 15 01 00 00 00 00 02 64 00 + 15 01 00 00 00 00 02 67 08 + 15 01 00 00 00 00 02 68 04 /* Resolution:1440x2560*/ - 15 01 00 00 10 00 02 72 02 + 15 01 00 00 00 00 02 72 02 /* mux */ - 15 01 00 00 10 00 02 7A 80 - 15 01 00 00 10 00 02 7B 91 - 15 01 00 00 10 00 02 7C D8 - 15 01 00 00 10 00 02 7D 60 - 15 01 00 00 10 00 02 7F 15 - 15 01 00 00 10 00 02 75 15 + 15 01 00 00 00 00 02 7A 80 + 15 01 00 00 00 00 02 7B 91 + 15 01 00 00 00 00 02 7C D8 + 15 01 00 00 00 00 02 7D 60 + 15 01 00 00 00 00 02 7F 15 + 15 01 00 00 00 00 02 75 15 /* ABOFF */ - 15 01 00 00 10 00 02 B3 C0 - 15 01 00 00 10 00 02 B4 00 - 15 01 00 00 10 00 02 B5 00 + 15 01 00 00 00 00 02 B3 C0 + 15 01 00 00 00 00 02 B4 00 + 15 01 00 00 00 00 02 B5 00 /* Source EQ */ - 15 01 00 00 10 00 02 78 00 - 15 01 00 00 10 00 02 79 00 - 15 01 00 00 10 00 02 80 00 - 15 01 00 00 10 00 02 83 00 + 15 01 00 00 00 00 02 78 00 + 15 01 00 00 00 00 02 79 00 + 15 01 00 00 00 00 02 80 00 + 15 01 00 00 00 00 02 83 00 /* FP BP */ - 15 01 00 00 10 00 02 93 0A - 15 01 00 00 10 00 02 94 0A + 15 01 00 00 00 00 02 93 0A + 15 01 00 00 00 00 02 94 0A /* Inversion Type */ - 15 01 00 00 10 00 02 8A 00 - 15 01 00 00 10 00 02 9B FF + 15 01 00 00 00 00 02 8A 00 + 15 01 00 00 00 00 02 9B FF /* IMGSWAP =1 @PortSwap=1 */ - 15 01 00 00 10 00 02 9D B0 - 15 01 00 00 10 00 02 9F 63 - 15 01 00 00 10 00 02 98 10 + 15 01 00 00 00 00 02 9D B0 + 15 01 00 00 00 00 02 9F 63 + 15 01 00 00 00 00 02 98 10 /* FRM */ - 15 01 00 00 10 00 02 EC 00 + 15 01 00 00 00 00 02 EC 00 /* CMD1 */ - 15 01 00 00 10 00 02 FF 10 + 15 01 00 00 00 00 02 FF 10 /* VBP+VSA=,VFP = 10H */ - 15 01 00 00 10 00 04 3B 03 0A 0A + 15 01 00 00 00 00 04 3B 03 0A 0A /* FTE on */ - 15 01 00 00 10 00 02 35 00 + 15 01 00 00 00 00 02 35 00 /* EN_BK =1(auto black) */ - 15 01 00 00 10 00 02 E5 01 + 15 01 00 00 00 00 02 E5 01 /* CMD mode(10) VDO mode(03) */ - 15 01 00 00 10 00 02 BB 03 + 15 01 00 00 00 00 02 BB 03 /* Non Reload MTP */ - 15 01 00 00 10 00 02 FB 01 + 15 01 00 00 00 00 02 FB 01 /* SlpOut + DispOn */ - 05 01 00 00 a0 00 02 11 00 - 05 01 00 00 a0 00 02 29 00 + 05 01 00 00 78 00 02 11 00 + 05 01 00 00 78 00 02 29 00 ]; qcom,mdss-dsi-off-command = [05 01 00 00 78 00 02 28 00 05 01 00 00 78 00 02 10 00]; diff --git a/arch/arm/boot/dts/qcom/dsi-panel-nt35695b-truly-fhd-cmd.dtsi b/arch/arm/boot/dts/qcom/dsi-panel-nt35695b-truly-fhd-cmd.dtsi index 3c0134b665fc..e3f60de3c3eb 100644 --- a/arch/arm/boot/dts/qcom/dsi-panel-nt35695b-truly-fhd-cmd.dtsi +++ b/arch/arm/boot/dts/qcom/dsi-panel-nt35695b-truly-fhd-cmd.dtsi @@ -20,13 +20,13 @@ qcom,mdss-dsi-stream = <0>; qcom,mdss-dsi-panel-width = <1080>; qcom,mdss-dsi-panel-height = <1920>; - qcom,mdss-dsi-h-front-porch = <96>; - qcom,mdss-dsi-h-back-porch = <64>; - qcom,mdss-dsi-h-pulse-width = <16>; + qcom,mdss-dsi-h-front-porch = <120>; + qcom,mdss-dsi-h-back-porch = <60>; + qcom,mdss-dsi-h-pulse-width = <12>; qcom,mdss-dsi-h-sync-skew = <0>; - qcom,mdss-dsi-v-back-porch = <16>; - qcom,mdss-dsi-v-front-porch = <4>; - qcom,mdss-dsi-v-pulse-width = <1>; + qcom,mdss-dsi-v-back-porch = <2>; + qcom,mdss-dsi-v-front-porch = <12>; + qcom,mdss-dsi-v-pulse-width = <2>; qcom,mdss-dsi-h-left-border = <0>; qcom,mdss-dsi-h-right-border = <0>; qcom,mdss-dsi-v-top-border = <0>; diff --git a/arch/arm/boot/dts/qcom/dsi-panel-nt35695b-truly-fhd-video.dtsi b/arch/arm/boot/dts/qcom/dsi-panel-nt35695b-truly-fhd-video.dtsi index d6b24f4e54d2..068459bf2504 100644 --- a/arch/arm/boot/dts/qcom/dsi-panel-nt35695b-truly-fhd-video.dtsi +++ b/arch/arm/boot/dts/qcom/dsi-panel-nt35695b-truly-fhd-video.dtsi @@ -20,13 +20,13 @@ qcom,mdss-dsi-stream = <0>; qcom,mdss-dsi-panel-width = <1080>; qcom,mdss-dsi-panel-height = <1920>; - qcom,mdss-dsi-h-front-porch = <96>; - qcom,mdss-dsi-h-back-porch = <64>; - qcom,mdss-dsi-h-pulse-width = <16>; + qcom,mdss-dsi-h-front-porch = <120>; + qcom,mdss-dsi-h-back-porch = <60>; + qcom,mdss-dsi-h-pulse-width = <12>; qcom,mdss-dsi-h-sync-skew = <0>; - qcom,mdss-dsi-v-back-porch = <16>; - qcom,mdss-dsi-v-front-porch = <4>; - qcom,mdss-dsi-v-pulse-width = <1>; + qcom,mdss-dsi-v-back-porch = <2>; + qcom,mdss-dsi-v-front-porch = <12>; + qcom,mdss-dsi-v-pulse-width = <2>; qcom,mdss-dsi-h-left-border = <0>; qcom,mdss-dsi-h-right-border = <0>; qcom,mdss-dsi-v-top-border = <0>; @@ -169,8 +169,7 @@ 15 01 00 00 00 00 02 e3 00 15 01 00 00 00 00 02 ec 00 15 01 00 00 00 00 02 ff 10 - 15 01 00 00 00 00 02 bb 10 - 15 01 00 00 00 00 02 35 02 + 15 01 00 00 00 00 02 bb 03 05 01 00 00 78 00 02 11 00 05 01 00 00 78 00 02 29 00]; qcom,mdss-dsi-off-command = [05 01 00 00 14 00 02 28 00 diff --git a/arch/arm/boot/dts/qcom/msm-smb138x.dtsi b/arch/arm/boot/dts/qcom/msm-smb138x.dtsi index 2aa730898f75..138fa2b57248 100644 --- a/arch/arm/boot/dts/qcom/msm-smb138x.dtsi +++ b/arch/arm/boot/dts/qcom/msm-smb138x.dtsi @@ -1,4 +1,4 @@ -/* Copyright (c) 2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2017, 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 @@ -96,16 +96,24 @@ #size-cells = <1>; interrupt-parent = <&smb138x>; io-channels = <&smb138x_tadc 2>, - <&smb138x_tadc 12>, - <&smb138x_tadc 3>; + <&smb138x_tadc 3>, + <&smb138x_tadc 14>, + <&smb138x_tadc 15>, + <&smb138x_tadc 16>, + <&smb138x_tadc 17>; io-channel-names = "charger_temp", - "charger_temp_max", - "batt_i"; + "batt_i", + "connector_temp_thr1", + "connector_temp_thr2", + "connector_temp_thr3", + "charger_temp_max"; qcom,chgr-misc@1600 { reg = <0x1600 0x100>; - interrupts = <0x16 0x1 IRQ_TYPE_EDGE_RISING>; - interrupt-names = "wdog-bark"; + interrupts = <0x16 0x1 IRQ_TYPE_EDGE_RISING>, + <0x16 0x6 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "wdog-bark", + "temperature-change"; }; }; }; diff --git a/arch/arm/boot/dts/qcom/msm8998-mtp.dtsi b/arch/arm/boot/dts/qcom/msm8998-mtp.dtsi index 4aadd4802b51..236020385e1c 100644 --- a/arch/arm/boot/dts/qcom/msm8998-mtp.dtsi +++ b/arch/arm/boot/dts/qcom/msm8998-mtp.dtsi @@ -171,6 +171,19 @@ }; }; +&pmi8998_gpios { + /* GPIO 6 for the internal QNOVO discharge FET control signal */ + gpio@c500 { + status = "okay"; + qcom,mode = <1>; + qcom,pull = <5>; + qcom,vin-sel = <0>; + qcom,src-sel = <2>; + qcom,out-strength = <1>; + qcom,master-en = <1>; + }; +}; + &i2c_5 { status = "okay"; synaptics@20 { diff --git a/arch/arm/boot/dts/qcom/msm8998-qrd-vr1.dtsi b/arch/arm/boot/dts/qcom/msm8998-qrd-vr1.dtsi index 25e381c2cb18..3c1c49edcc82 100644 --- a/arch/arm/boot/dts/qcom/msm8998-qrd-vr1.dtsi +++ b/arch/arm/boot/dts/qcom/msm8998-qrd-vr1.dtsi @@ -143,6 +143,19 @@ }; }; +&pmi8998_gpios { + /* GPIO 6 for the internal QNOVO discharge FET control signal */ + gpio@c500 { + status = "okay"; + qcom,mode = <1>; + qcom,pull = <5>; + qcom,vin-sel = <0>; + qcom,src-sel = <2>; + qcom,out-strength = <1>; + qcom,master-en = <1>; + }; +}; + &soc { gpio_keys { compatible = "gpio-keys"; diff --git a/arch/arm/boot/dts/qcom/msm8998-qrd.dtsi b/arch/arm/boot/dts/qcom/msm8998-qrd.dtsi index fb69a793a680..38072e447fba 100644 --- a/arch/arm/boot/dts/qcom/msm8998-qrd.dtsi +++ b/arch/arm/boot/dts/qcom/msm8998-qrd.dtsi @@ -159,6 +159,19 @@ }; }; +&pmi8998_gpios { + /* GPIO 6 for the internal QNOVO discharge FET control signal */ + gpio@c500 { + status = "okay"; + qcom,mode = <1>; + qcom,pull = <5>; + qcom,vin-sel = <0>; + qcom,src-sel = <2>; + qcom,out-strength = <1>; + qcom,master-en = <1>; + }; +}; + &i2c_5 { status = "okay"; synaptics@20 { diff --git a/arch/arm/boot/dts/qcom/sdm630.dtsi b/arch/arm/boot/dts/qcom/sdm630.dtsi index 38bb266bcf7d..ee8eaf48ad19 100644 --- a/arch/arm/boot/dts/qcom/sdm630.dtsi +++ b/arch/arm/boot/dts/qcom/sdm630.dtsi @@ -320,6 +320,36 @@ alignment = <0x0 0x400000>; size = <0x0 0x5c00000>; }; + + /* global autoconfigured region for contiguous allocations */ + linux,cma { + compatible = "shared-dma-pool"; + alloc-ranges = <0x0 0x00000000 0x0 0xffffffff>; + reusable; + alignment = <0x0 0x400000>; + size = <0x0 0x2000000>; + linux,cma-default; + }; + + }; + + bluetooth: bt_wcn3990 { + compatible = "qca,wcn3990"; + qca,bt-vdd-core-supply = <&pm660_l9_pin_ctrl>; + qca,bt-vdd-pa-supply = <&pm660_l6_pin_ctrl>; + qca,bt-vdd-ldo-supply = <&pm660_l19_pin_ctrl>; + qca,bt-chip-pwd-supply = <&pm660l_bob_pin1>; + clocks = <&clock_rpmcc RPM_RF_CLK1_PIN>; + clock-names = "rf_clk1"; + + qca,bt-vdd-core-voltage-level = <1800000 1900000>; + qca,bt-vdd-pa-voltage-level = <1304000 1370000>; + qca,bt-vdd-ldo-voltage-level = <3312000 3400000>; + qca,bt-chip-pwd-voltage-level = <3600000 3600000>; + + qca,bt-vdd-core-current-level = <1>; /* LPM/PFM */ + qca,bt-vdd-pa-current-level = <1>; /* LPM/PFM */ + qca,bt-vdd-ldo-current-level = <1>; /* LPM/PFM */ }; }; diff --git a/arch/arm/boot/dts/qcom/sdm660-cdp.dtsi b/arch/arm/boot/dts/qcom/sdm660-cdp.dtsi index 5bdca492fee2..1145bfa63cba 100644 --- a/arch/arm/boot/dts/qcom/sdm660-cdp.dtsi +++ b/arch/arm/boot/dts/qcom/sdm660-cdp.dtsi @@ -184,6 +184,15 @@ qcom,panel-roi-alignment = <2 2 4 2 1080 2>; }; +&mdss_dp_ctrl { + pinctrl-names = "mdss_dp_active", "mdss_dp_sleep"; + pinctrl-0 = <&mdss_dp_aux_active &mdss_dp_usbplug_cc_active>; + pinctrl-1 = <&mdss_dp_aux_suspend &mdss_dp_usbplug_cc_suspend>; + qcom,aux-en-gpio = <&tlmm 55 0>; + qcom,aux-sel-gpio = <&tlmm 56 0>; + qcom,usbplug-cc-gpio = <&tlmm 58 0>; +}; + &sdhc_1 { /* device core power supply */ vdd-supply = <&pm660l_l4>; diff --git a/arch/arm/boot/dts/qcom/sdm660-mdss-panels.dtsi b/arch/arm/boot/dts/qcom/sdm660-mdss-panels.dtsi index 51e88eb8dcf2..ce8273e4f1b8 100644 --- a/arch/arm/boot/dts/qcom/sdm660-mdss-panels.dtsi +++ b/arch/arm/boot/dts/qcom/sdm660-mdss-panels.dtsi @@ -196,19 +196,23 @@ }; &dsi_nt35695b_truly_fhd_video { - qcom,mdss-dsi-panel-timings-phy-v2 = [23 1e 07 08 05 03 04 a0 - 23 1e 07 08 05 03 04 a0 - 23 1e 07 08 05 03 04 a0 - 23 1e 07 08 05 03 04 a0 - 23 18 07 08 04 03 04 a0]; + qcom,mdss-dsi-panel-timings-phy-v2 = [24 1e 08 09 05 03 04 a0 + 24 1e 08 09 05 03 04 a0 + 24 1e 08 09 05 03 04 a0 + 24 1e 08 09 05 03 04 a0 + 24 1a 08 09 05 03 04 a0]; + qcom,mdss-dsi-min-refresh-rate = <48>; + qcom,mdss-dsi-max-refresh-rate = <60>; + qcom,mdss-dsi-pan-enable-dynamic-fps; + qcom,mdss-dsi-pan-fps-update = "dfps_immediate_porch_mode_vfp"; }; &dsi_nt35695b_truly_fhd_cmd { - qcom,mdss-dsi-panel-timings-phy-v2 = [23 1e 07 08 05 03 04 a0 - 23 1e 07 08 05 03 04 a0 - 23 1e 07 08 05 03 04 a0 - 23 1e 07 08 05 03 04 a0 - 23 18 07 08 04 03 04 a0]; + qcom,mdss-dsi-panel-timings-phy-v2 = [24 1e 08 09 05 03 04 a0 + 24 1e 08 09 05 03 04 a0 + 24 1e 08 09 05 03 04 a0 + 24 1e 08 09 05 03 04 a0 + 24 1a 08 09 05 03 04 a0]; }; &dsi_truly_1080_vid { diff --git a/arch/arm/boot/dts/qcom/sdm660-mdss-pll.dtsi b/arch/arm/boot/dts/qcom/sdm660-mdss-pll.dtsi index d2134c56541e..69d3736d4ba8 100644 --- a/arch/arm/boot/dts/qcom/sdm660-mdss-pll.dtsi +++ b/arch/arm/boot/dts/qcom/sdm660-mdss-pll.dtsi @@ -1,4 +1,4 @@ -/* Copyright (c) 2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2017, 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 @@ -79,4 +79,39 @@ }; }; }; + + mdss_dp_pll: qcom,mdss_dp_pll@c011000 { + compatible = "qcom,mdss_dp_pll_sdm660"; + status = "ok"; + label = "MDSS DP PLL"; + cell-index = <0>; + #clock-cells = <1>; + + reg = <0xc011c00 0x190>, + <0xc011000 0x910>, + <0x0c8c2300 0x8>; + reg-names = "pll_base", "phy_base", "gdsc_base"; + + gdsc-supply = <&gdsc_mdss>; + + clocks = <&clock_mmss MMSS_MDSS_AHB_CLK>, + <&clock_rpmcc RPM_LN_BB_CLK1>, + <&clock_gcc GCC_USB3_CLKREF_CLK>; + clock-names = "iface_clk", "ref_clk_src", "ref_clk"; + clock-rate = <0>; + + qcom,platform-supply-entries { + #address-cells = <1>; + #size-cells = <0>; + + qcom,platform-supply-entry@0 { + reg = <0>; + qcom,supply-name = "gdsc"; + qcom,supply-min-voltage = <0>; + qcom,supply-max-voltage = <0>; + qcom,supply-enable-load = <0>; + qcom,supply-disable-load = <0>; + }; + }; + }; }; diff --git a/arch/arm/boot/dts/qcom/sdm660-mdss.dtsi b/arch/arm/boot/dts/qcom/sdm660-mdss.dtsi index 32cf55a99ac0..b7329121ca49 100644 --- a/arch/arm/boot/dts/qcom/sdm660-mdss.dtsi +++ b/arch/arm/boot/dts/qcom/sdm660-mdss.dtsi @@ -437,7 +437,7 @@ }; msm_ext_disp: qcom,msm_ext_disp { - status = "disabled"; + status = "ok"; compatible = "qcom,msm-ext-disp"; ext_disp_audio_codec: qcom,msm-ext-disp-audio-codec-rx { @@ -447,16 +447,16 @@ }; mdss_dp_ctrl: qcom,dp_ctrl@c990000 { - status = "disabled"; + status = "ok"; cell-index = <0>; compatible = "qcom,mdss-dp"; qcom,mdss-fb-map = <&mdss_fb2>; gdsc-supply = <&gdsc_mdss>; - vdda-1p2-supply = <&pm660_l1>; + vdda-1p8-supply = <&pm660_l10>; vdda-0p9-supply = <&pm660l_l1>; - reg = <0xc990000 0xa84>, + reg = <0xc990000 0xa8c>, <0xc011000 0x910>, <0x1fcb200 0x050>, <0xc8c2200 0x1a0>, @@ -465,8 +465,37 @@ reg-names = "dp_ctrl", "dp_phy", "tcsr_regs", "dp_mmss_cc", "qfprom_physical","hdcp_physical"; + clocks = <&clock_mmss MMSS_MNOC_AHB_CLK>, + <&clock_mmss MMSS_MDSS_AHB_CLK>, + <&clock_mmss MMSS_MDSS_AXI_CLK>, + <&clock_mmss MMSS_MDSS_MDP_CLK>, + <&clock_mmss MMSS_MDSS_HDMI_DP_AHB_CLK>, + <&clock_mmss MMSS_MDSS_DP_AUX_CLK>, + <&clock_rpmcc RPM_LN_BB_CLK1>, + <&clock_gcc GCC_USB3_CLKREF_CLK>, + <&clock_gcc GCC_USB_PHY_CFG_AHB2PHY_CLK>, + <&clock_mmss MMSS_MDSS_DP_LINK_CLK>, + <&clock_mmss MMSS_MDSS_DP_LINK_INTF_CLK>, + <&clock_mmss MMSS_MDSS_DP_CRYPTO_CLK>, + <&clock_mmss MMSS_MDSS_DP_PIXEL_CLK>, + <&clock_mmss DP_PIXEL_CLK_SRC>, + <&mdss_dp_pll DP_VCO_DIVIDED_CLK_SRC_MUX>; + clock-names = "core_mnoc_clk", "core_iface_clk", "core_bus_clk", + "core_mdp_core_clk", "core_alt_iface_clk", + "core_aux_clk", "core_ref_clk_src", "core_ref_clk", + "core_ahb_phy_clk", "ctrl_link_clk", + "ctrl_link_iface_clk", "ctrl_crypto_clk", + "ctrl_pixel_clk", "pixel_clk_rcg", "pixel_parent"; + + qcom,dp-usbpd-detection = <&pm660_pdphy>; + qcom,msm_ext_disp = <&msm_ext_disp>; + qcom,aux-cfg-settings = [00 13 00 00 0a 28 0a 03 b7 03]; + qcom,logical2physical-lane-map = [00 01 02 03]; + qcom,phy-register-offset = <0x4>; + qcom,max-pclk-frequency-khz = <593470>; + qcom,core-supply-entries { #address-cells = <1>; #size-cells = <0>; @@ -487,9 +516,9 @@ qcom,ctrl-supply-entry@0 { reg = <0>; - qcom,supply-name = "vdda-1p2"; - qcom,supply-min-voltage = <1200000>; - qcom,supply-max-voltage = <1250000>; + qcom,supply-name = "vdda-1p8"; + qcom,supply-min-voltage = <1780000>; + qcom,supply-max-voltage = <1950000>; qcom,supply-enable-load = <12560>; qcom,supply-disable-load = <4>; }; diff --git a/arch/arm/boot/dts/qcom/sdm660-mtp.dtsi b/arch/arm/boot/dts/qcom/sdm660-mtp.dtsi index b666d846ca04..150b88c10646 100644 --- a/arch/arm/boot/dts/qcom/sdm660-mtp.dtsi +++ b/arch/arm/boot/dts/qcom/sdm660-mtp.dtsi @@ -106,6 +106,15 @@ qcom,platform-te-gpio = <&tlmm 59 0>; }; +&mdss_dp_ctrl { + pinctrl-names = "mdss_dp_active", "mdss_dp_sleep"; + pinctrl-0 = <&mdss_dp_aux_active &mdss_dp_usbplug_cc_active>; + pinctrl-1 = <&mdss_dp_aux_suspend &mdss_dp_usbplug_cc_suspend>; + qcom,aux-en-gpio = <&tlmm 55 0>; + qcom,aux-sel-gpio = <&tlmm 56 0>; + qcom,usbplug-cc-gpio = <&tlmm 58 0>; +}; + &pm660l_wled { qcom,led-strings-list = [01 02]; }; @@ -147,6 +156,20 @@ qcom,panel-supply-entries = <&dsi_panel_pwr_supply>; }; +&dsi_nt35695b_truly_fhd_video { + qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled"; + qcom,mdss-dsi-bl-min-level = <1>; + qcom,mdss-dsi-bl-max-level = <4095>; + qcom,panel-supply-entries = <&dsi_panel_pwr_supply>; +}; + +&dsi_nt35695b_truly_fhd_cmd { + qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled"; + qcom,mdss-dsi-bl-min-level = <1>; + qcom,mdss-dsi-bl-max-level = <4095>; + qcom,panel-supply-entries = <&dsi_panel_pwr_supply>; +}; + &sdhc_1 { /* device core power supply */ vdd-supply = <&pm660l_l4>; diff --git a/arch/arm/boot/dts/qcom/sdm660-pinctrl.dtsi b/arch/arm/boot/dts/qcom/sdm660-pinctrl.dtsi index dbc98a97fc8d..273f196364ce 100644 --- a/arch/arm/boot/dts/qcom/sdm660-pinctrl.dtsi +++ b/arch/arm/boot/dts/qcom/sdm660-pinctrl.dtsi @@ -1439,6 +1439,58 @@ }; }; + mdss_dp_aux_active: mdss_dp_aux_active { + mux { + pins = "gpio55", "gpio56"; + function = "gpio"; + }; + + config { + pins = "gpio55", "gpio56"; + bias-disable = <0>; /* no pull */ + drive-strength = <8>; + }; + }; + + mdss_dp_aux_suspend: mdss_dp_aux_suspend { + mux { + pins = "gpio55", "gpio56"; + function = "gpio"; + }; + + config { + pins = "gpio55", "gpio56"; + bias-pull-down; + drive-strength = <2>; + }; + }; + + mdss_dp_usbplug_cc_active: mdss_dp_usbplug_cc_active { + mux { + pins = "gpio58"; + function = "gpio"; + }; + + config { + pins = "gpio58"; + bias-disable; + drive-strength = <16>; + }; + }; + + mdss_dp_usbplug_cc_suspend: mdss_dp_usbplug_cc_suspend { + mux { + pins = "gpio58"; + function = "gpio"; + }; + + config { + pins = "gpio58"; + bias-pull-down; + drive-strength = <2>; + }; + }; + ts_mux { ts_active: ts_active { mux { diff --git a/arch/arm/boot/dts/qcom/sdm660.dtsi b/arch/arm/boot/dts/qcom/sdm660.dtsi index f35619d2a21e..ca787d38f9eb 100644 --- a/arch/arm/boot/dts/qcom/sdm660.dtsi +++ b/arch/arm/boot/dts/qcom/sdm660.dtsi @@ -1163,8 +1163,8 @@ < 902400000 0x0404002f 0x04260026 0x1 3 >, < 1113600000 0x0404003a 0x052e002e 0x2 4 >, < 1401600000 0x04040049 0x073a003a 0x2 5 >, - < 1536000000 0x04040050 0x08400040 0x3 6 >, - < 1747200000 0x0404005b 0x09480048 0x3 7 >, + < 1536000000 0x04040050 0x08400040 0x2 6 >, + < 1747200000 0x0404005b 0x09480048 0x2 7 >, < 1843200000 0x04040060 0x094c004c 0x3 8 >; qcom,perfcl-speedbin0-v0 = @@ -1172,8 +1172,8 @@ < 1113600000 0x0404003a 0x052e002e 0x1 2 >, < 1401600000 0x04040049 0x073a003a 0x2 3 >, < 1747200000 0x0404005b 0x09480048 0x2 4 >, - < 1958400000 0x04040066 0x0a510051 0x3 5 >, - < 2150400000 0x04040070 0x0b590059 0x3 6 >, + < 1958400000 0x04040066 0x0a510051 0x2 5 >, + < 2150400000 0x04040070 0x0b590059 0x2 6 >, < 2457600000 0x04040080 0x0c660066 0x3 7 >; qcom,perfcl-speedbin1-v0 = @@ -1181,8 +1181,8 @@ < 1113600000 0x0404003a 0x052e002e 0x1 2 >, < 1401600000 0x04040049 0x073a003a 0x2 3 >, < 1747200000 0x0404005b 0x09480048 0x2 4 >, - < 1958400000 0x04040066 0x0a510051 0x3 5 >, - < 2150400000 0x04040070 0x0b590059 0x3 6 >, + < 1958400000 0x04040066 0x0a510051 0x2 5 >, + < 2150400000 0x04040070 0x0b590059 0x2 6 >, < 2208000000 0x04040073 0x0b5c005c 0x3 7 >; qcom,up-timer = <1000 1000>; diff --git a/arch/arm/configs/sdm660-perf_defconfig b/arch/arm/configs/sdm660-perf_defconfig index d7eb67ff85c1..dcf4f6fa0031 100644 --- a/arch/arm/configs/sdm660-perf_defconfig +++ b/arch/arm/configs/sdm660-perf_defconfig @@ -35,6 +35,7 @@ CONFIG_EMBEDDED=y # CONFIG_COMPAT_BRK is not set CONFIG_PROFILING=y CONFIG_CC_STACKPROTECTOR_REGULAR=y +CONFIG_ARCH_MMAP_RND_BITS=16 CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_MODULE_FORCE_UNLOAD=y @@ -234,7 +235,6 @@ CONFIG_IPC_ROUTER=y CONFIG_IPC_ROUTER_SECURITY=y CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y CONFIG_DMA_CMA=y -CONFIG_CMA_SIZE_MBYTES=40 CONFIG_ZRAM=y CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_RAM=y @@ -497,6 +497,9 @@ CONFIG_CLOCK_CPU_OSM=y CONFIG_QCOM_MDSS_PLL=y CONFIG_REMOTE_SPINLOCK_MSM=y CONFIG_ARM_SMMU=y +CONFIG_IOMMU_DEBUG=y +CONFIG_IOMMU_DEBUG_TRACKING=y +CONFIG_IOMMU_TESTS=y CONFIG_QCOM_COMMON_LOG=y CONFIG_MSM_SMEM=y CONFIG_QPNP_HAPTIC=y diff --git a/arch/arm/configs/sdm660_defconfig b/arch/arm/configs/sdm660_defconfig index c2ceac22f15f..633b9ad305bc 100644 --- a/arch/arm/configs/sdm660_defconfig +++ b/arch/arm/configs/sdm660_defconfig @@ -7,7 +7,6 @@ CONFIG_RCU_EXPERT=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_CPU_MAX_BUF_SHIFT=17 -CONFIG_CGROUPS=y CONFIG_CGROUP_DEBUG=y CONFIG_CGROUP_FREEZER=y CONFIG_CPUSETS=y @@ -15,7 +14,6 @@ CONFIG_CGROUP_CPUACCT=y CONFIG_CGROUP_SCHEDTUNE=y CONFIG_MEMCG=y CONFIG_MEMCG_SWAP=y -CONFIG_CGROUP_SCHED=y CONFIG_RT_GROUP_SCHED=y CONFIG_SCHED_HMP=y CONFIG_SCHED_HMP_CSTATE_AWARE=y @@ -23,6 +21,7 @@ CONFIG_SCHED_CORE_CTL=y CONFIG_NAMESPACES=y # CONFIG_UTS_NS is not set # CONFIG_PID_NS is not set +CONFIG_SCHED_AUTOGROUP=y CONFIG_SCHED_TUNE=y CONFIG_BLK_DEV_INITRD=y # CONFIG_RD_XZ is not set @@ -35,6 +34,7 @@ CONFIG_EMBEDDED=y # CONFIG_COMPAT_BRK is not set CONFIG_PROFILING=y CONFIG_CC_STACKPROTECTOR_REGULAR=y +CONFIG_ARCH_MMAP_RND_BITS=16 CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_MODULE_FORCE_UNLOAD=y @@ -233,7 +233,6 @@ CONFIG_IPC_ROUTER=y CONFIG_IPC_ROUTER_SECURITY=y CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y CONFIG_DMA_CMA=y -CONFIG_CMA_SIZE_MBYTES=40 CONFIG_ZRAM=y CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_RAM=y @@ -643,6 +642,7 @@ CONFIG_BLK_DEV_IO_TRACE=y CONFIG_CPU_FREQ_SWITCH_PROFILER=y CONFIG_MEMTEST=y CONFIG_PANIC_ON_DATA_CORRUPTION=y +CONFIG_FREE_PAGES_RDONLY=y CONFIG_PID_IN_CONTEXTIDR=y CONFIG_DEBUG_SET_MODULE_RONX=y CONFIG_CORESIGHT=y diff --git a/arch/arm/include/asm/cacheflush.h b/arch/arm/include/asm/cacheflush.h index 2005a47b491e..2e2d1657e604 100644 --- a/arch/arm/include/asm/cacheflush.h +++ b/arch/arm/include/asm/cacheflush.h @@ -539,4 +539,13 @@ static inline void secure_flush_area(const void *addr, size_t size) outer_flush_range(phys, phys + size); } +#ifdef CONFIG_FREE_PAGES_RDONLY +#define mark_addr_rdonly(a) set_memory_ro((unsigned long)a, 1) +#define mark_addr_rdwrite(a) set_memory_rw((unsigned long)a, 1) +#else +#define mark_addr_rdonly(a) +#define mark_addr_rdwrite(a) +#endif + + #endif diff --git a/arch/arm/mm/highmem.c b/arch/arm/mm/highmem.c index d02f8187b1cc..5d73327f8491 100644 --- a/arch/arm/mm/highmem.c +++ b/arch/arm/mm/highmem.c @@ -10,6 +10,7 @@ * published by the Free Software Foundation. */ +#include <linux/cpu.h> #include <linux/module.h> #include <linux/highmem.h> #include <linux/interrupt.h> @@ -147,3 +148,58 @@ void *kmap_atomic_pfn(unsigned long pfn) return (void *)vaddr; } + +#ifdef CONFIG_ARCH_WANT_KMAP_ATOMIC_FLUSH +static void kmap_remove_unused_cpu(int cpu) +{ + int start_idx, idx, type; + + pagefault_disable(); + type = kmap_atomic_idx(); + start_idx = type + 1 + KM_TYPE_NR * cpu; + + for (idx = start_idx; idx < KM_TYPE_NR + KM_TYPE_NR * cpu; idx++) { + unsigned long vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); + pte_t ptep; + + ptep = get_top_pte(vaddr); + if (ptep) + set_top_pte(vaddr, __pte(0)); + } + pagefault_enable(); +} + +static void kmap_remove_unused(void *unused) +{ + kmap_remove_unused_cpu(smp_processor_id()); +} + +void kmap_atomic_flush_unused(void) +{ + on_each_cpu(kmap_remove_unused, NULL, 1); +} + +static int hotplug_kmap_atomic_callback(struct notifier_block *nfb, + unsigned long action, void *hcpu) +{ + switch (action & (~CPU_TASKS_FROZEN)) { + case CPU_DYING: + kmap_remove_unused_cpu((int)hcpu); + break; + default: + break; + } + + return NOTIFY_OK; +} + +static struct notifier_block hotplug_kmap_atomic_notifier = { + .notifier_call = hotplug_kmap_atomic_callback, +}; + +static int __init init_kmap_atomic(void) +{ + return register_hotcpu_notifier(&hotplug_kmap_atomic_notifier); +} +early_initcall(init_kmap_atomic); +#endif diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index 107b5f1b864b..d3d718772381 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c @@ -625,6 +625,9 @@ struct section_perm { pmdval_t mask; pmdval_t prot; pmdval_t clear; + pteval_t ptemask; + pteval_t pteprot; + pteval_t pteclear; }; static struct section_perm nx_perms[] = { @@ -634,6 +637,8 @@ static struct section_perm nx_perms[] = { .end = (unsigned long)_stext, .mask = ~PMD_SECT_XN, .prot = PMD_SECT_XN, + .ptemask = ~L_PTE_XN, + .pteprot = L_PTE_XN, }, /* Make init RW (set NX). */ { @@ -641,6 +646,8 @@ static struct section_perm nx_perms[] = { .end = (unsigned long)_sdata, .mask = ~PMD_SECT_XN, .prot = PMD_SECT_XN, + .ptemask = ~L_PTE_XN, + .pteprot = L_PTE_XN, }, #ifdef CONFIG_DEBUG_RODATA /* Make rodata NX (set RO in ro_perms below). */ @@ -649,6 +656,8 @@ static struct section_perm nx_perms[] = { .end = (unsigned long)__init_begin, .mask = ~PMD_SECT_XN, .prot = PMD_SECT_XN, + .ptemask = ~L_PTE_XN, + .pteprot = L_PTE_XN, }, #endif }; @@ -667,6 +676,8 @@ static struct section_perm ro_perms[] = { .prot = PMD_SECT_APX | PMD_SECT_AP_WRITE, .clear = PMD_SECT_AP_WRITE, #endif + .ptemask = ~L_PTE_RDONLY, + .pteprot = L_PTE_RDONLY, }, }; #endif @@ -676,6 +687,35 @@ static struct section_perm ro_perms[] = { * copied into each mm). During startup, this is the init_mm. Is only * safe to be called with preemption disabled, as under stop_machine(). */ +struct pte_data { + pteval_t mask; + pteval_t val; +}; + +static int __pte_update(pte_t *ptep, pgtable_t token, unsigned long addr, + void *d) +{ + struct pte_data *data = d; + pte_t pte = *ptep; + + pte = __pte((pte_val(*ptep) & data->mask) | data->val); + set_pte_ext(ptep, pte, 0); + + return 0; +} + +static inline void pte_update(unsigned long addr, pteval_t mask, + pteval_t prot, struct mm_struct *mm) +{ + struct pte_data data; + + data.mask = mask; + data.val = prot; + + apply_to_page_range(mm, addr, SECTION_SIZE, __pte_update, &data); + flush_tlb_kernel_range(addr, addr + SECTION_SIZE); +} + static inline void section_update(unsigned long addr, pmdval_t mask, pmdval_t prot, struct mm_struct *mm) { @@ -724,11 +764,21 @@ void set_section_perms(struct section_perm *perms, int n, bool set, for (addr = perms[i].start; addr < perms[i].end; - addr += SECTION_SIZE) - section_update(addr, perms[i].mask, - set ? perms[i].prot : perms[i].clear, mm); + addr += SECTION_SIZE) { + pmd_t *pmd; + + pmd = pmd_offset(pud_offset(pgd_offset(mm, addr), + addr), addr); + if (pmd_bad(*pmd)) + section_update(addr, perms[i].mask, + set ? perms[i].prot : perms[i].clear, + mm); + else + pte_update(addr, perms[i].ptemask, + set ? perms[i].pteprot : perms[i].pteclear, + mm); + } } - } static void update_sections_early(struct section_perm perms[], int n) diff --git a/arch/arm64/configs/sdm660-perf_defconfig b/arch/arm64/configs/sdm660-perf_defconfig index b24885a89bff..d00772c12626 100644 --- a/arch/arm64/configs/sdm660-perf_defconfig +++ b/arch/arm64/configs/sdm660-perf_defconfig @@ -37,6 +37,7 @@ CONFIG_EMBEDDED=y # CONFIG_COMPAT_BRK is not set CONFIG_PROFILING=y CONFIG_CC_STACKPROTECTOR_REGULAR=y +CONFIG_ARCH_MMAP_RND_COMPAT_BITS=16 CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_MODULE_FORCE_UNLOAD=y diff --git a/arch/arm64/configs/sdm660_defconfig b/arch/arm64/configs/sdm660_defconfig index bc633548bbc3..ef8bac8e2947 100644 --- a/arch/arm64/configs/sdm660_defconfig +++ b/arch/arm64/configs/sdm660_defconfig @@ -35,6 +35,7 @@ CONFIG_EMBEDDED=y # CONFIG_COMPAT_BRK is not set CONFIG_PROFILING=y CONFIG_CC_STACKPROTECTOR_REGULAR=y +CONFIG_ARCH_MMAP_RND_COMPAT_BITS=16 CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_MODULE_FORCE_UNLOAD=y diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c index fe3af13f0d38..9a7411a33127 100644 --- a/drivers/char/adsprpc.c +++ b/drivers/char/adsprpc.c @@ -815,9 +815,9 @@ static int overlap_ptr_cmp(const void *a, const void *b) return st == 0 ? ed : st; } -static void context_build_overlap(struct smq_invoke_ctx *ctx) +static int context_build_overlap(struct smq_invoke_ctx *ctx) { - int i; + int i, err = 0; remote_arg_t *lpra = ctx->lpra; int inbufs = REMOTE_SCALARS_INBUFS(ctx->sc); int outbufs = REMOTE_SCALARS_OUTBUFS(ctx->sc); @@ -826,6 +826,11 @@ static void context_build_overlap(struct smq_invoke_ctx *ctx) for (i = 0; i < nbufs; ++i) { ctx->overs[i].start = (uintptr_t)lpra[i].buf.pv; ctx->overs[i].end = ctx->overs[i].start + lpra[i].buf.len; + if (lpra[i].buf.len) { + VERIFY(err, ctx->overs[i].end > ctx->overs[i].start); + if (err) + goto bail; + } ctx->overs[i].raix = i; ctx->overps[i] = &ctx->overs[i]; } @@ -851,6 +856,8 @@ static void context_build_overlap(struct smq_invoke_ctx *ctx) max = *ctx->overps[i]; } } +bail: + return err; } #define K_COPY_FROM_USER(err, kernel, dst, src, size) \ @@ -923,8 +930,11 @@ static int context_alloc(struct fastrpc_file *fl, uint32_t kernel, } ctx->sc = invoke->sc; - if (bufs) - context_build_overlap(ctx); + if (bufs) { + VERIFY(err, 0 == context_build_overlap(ctx)); + if (err) + goto bail; + } ctx->retval = -1; ctx->pid = current->pid; ctx->tgid = current->tgid; diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 008b8babf31e..d4729fa59edb 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -339,22 +339,23 @@ config GPIO_PXA Say yes here to support the PXA GPIO device config GPIO_QPNP_PIN + tristate "Qualcomm Technologies, Inc. QPNP GPIO support" depends on SPMI - tristate "Qualcomm QPNP gpio support" help - Say 'y' here to include support for the Qualcomm QPNP gpio - driver. This driver supports Device Tree and allows a - device_node to be registered as a gpio-controller. It - does not handle gpio interrupts directly, they are handled - via the spmi arbiter interrupt driver. + Say 'y' here to include support for the Qualcomm Technologies, Inc. + QPNP GPIO driver. This driver supports Device Tree and allows a + device_node to be registered as a gpio-controller. It does not handle + GPIO interrupts directly; they are handled via the SPMI arbiter + interrupt driver. config GPIO_QPNP_PIN_DEBUG - depends on GPIO_QPNP_PIN - depends on DEBUG_FS - bool "Qualcomm QPNP GPIO debug support" + bool "Qualcomm Technologies, Inc. QPNP GPIO debug support" + depends on GPIO_QPNP_PIN && DEBUG_FS help - Say 'y' here to include debug support for the Qualcomm - QPNP gpio driver. + Say 'y' here to include debug support for the Qualcomm Technologies, + Inc. QPNP GPIO driver. This provides a userspace debug interface to + get and set all of the supported features of PMIC GPIO and MPP pins + including those which are managed by the gpio framework. config GPIO_RCAR tristate "Renesas R-Car GPIO" diff --git a/drivers/gpio/qpnp-pin.c b/drivers/gpio/qpnp-pin.c index de24d99ea34e..62cd78a95303 100644 --- a/drivers/gpio/qpnp-pin.c +++ b/drivers/gpio/qpnp-pin.c @@ -295,7 +295,7 @@ static int qpnp_pin_check_config(enum qpnp_pin_param_type idx, if (val >= QPNP_PIN_GPIO_LV_MV_MODE_INVALID) return -EINVAL; } else if (val >= QPNP_PIN_GPIO_MODE_INVALID) { - return -EINVAL; + return -EINVAL; } } else if (q_spec->type == Q_MPP_TYPE) { if (val >= QPNP_PIN_MPP_MODE_INVALID) @@ -753,16 +753,17 @@ int qpnp_pin_config(int gpio, struct qpnp_pin_cfg *param) } EXPORT_SYMBOL(qpnp_pin_config); -#define Q_MAX_CHIP_NAME 128 int qpnp_pin_map(const char *name, uint32_t pmic_pin) { struct qpnp_pin_chip *q_chip; struct qpnp_pin_spec *q_spec = NULL; + if (!name) + return -EINVAL; + mutex_lock(&qpnp_pin_chips_lock); list_for_each_entry(q_chip, &qpnp_pin_chips, chip_list) { - if (strncmp(q_chip->gpio_chip.label, name, - Q_MAX_CHIP_NAME) != 0) + if (strcmp(q_chip->gpio_chip.label, name) != 0) continue; if (q_chip->pmic_pin_lowest <= pmic_pin && q_chip->pmic_pin_highest >= pmic_pin) { @@ -778,7 +779,7 @@ int qpnp_pin_map(const char *name, uint32_t pmic_pin) } EXPORT_SYMBOL(qpnp_pin_map); -static int qpnp_pin_to_irq(struct gpio_chip *gpio_chip, unsigned offset) +static int qpnp_pin_to_irq(struct gpio_chip *gpio_chip, unsigned int offset) { struct qpnp_pin_chip *q_chip = dev_get_drvdata(gpio_chip->dev); struct qpnp_pin_spec *q_spec; @@ -811,14 +812,13 @@ static int qpnp_pin_to_irq(struct gpio_chip *gpio_chip, unsigned offset) return q_spec->irq; } -static int qpnp_pin_get(struct gpio_chip *gpio_chip, unsigned offset) +static int qpnp_pin_get(struct gpio_chip *gpio_chip, unsigned int offset) { - int rc, ret_val; struct qpnp_pin_chip *q_chip = dev_get_drvdata(gpio_chip->dev); struct qpnp_pin_spec *q_spec = NULL; - u8 buf[1], en_mask; - u8 shift, mask, reg; - int val; + u8 buf, en_mask, shift, mask, reg; + unsigned int val; + int rc; if (WARN_ON(!q_chip)) return -ENODEV; @@ -840,7 +840,9 @@ static int qpnp_pin_get(struct gpio_chip *gpio_chip, unsigned offset) == QPNP_PIN_MODE_DIG_IN) { rc = regmap_read(q_chip->regmap, Q_REG_ADDR(q_spec, Q_REG_STATUS1), &val); - buf[0] = (u8)val; + if (rc) + return rc; + buf = val; if (q_spec->type == Q_GPIO_TYPE && q_spec->dig_major_rev == 0) en_mask = Q_REG_STATUS1_GPIO_EN_REV0_MASK; @@ -850,26 +852,23 @@ static int qpnp_pin_get(struct gpio_chip *gpio_chip, unsigned offset) else /* MPP */ en_mask = Q_REG_STATUS1_MPP_EN_MASK; - if (!(buf[0] & en_mask)) + if (!(buf & en_mask)) return -EPERM; - return buf[0] & Q_REG_STATUS1_VAL_MASK; - } else { - if (is_gpio_lv_mv(q_spec)) { - shift = Q_REG_DIG_OUT_SRC_INVERT_SHIFT; - mask = Q_REG_DIG_OUT_SRC_INVERT_MASK; - reg = q_spec->regs[Q_REG_I_DIG_OUT_SRC_CTL]; - } else { - shift = Q_REG_OUT_INVERT_SHIFT; - mask = Q_REG_OUT_INVERT_MASK; - reg = q_spec->regs[Q_REG_I_MODE_CTL]; - } + return buf & Q_REG_STATUS1_VAL_MASK; + } - ret_val = (reg & mask) >> shift; - return ret_val; + if (is_gpio_lv_mv(q_spec)) { + shift = Q_REG_DIG_OUT_SRC_INVERT_SHIFT; + mask = Q_REG_DIG_OUT_SRC_INVERT_MASK; + reg = q_spec->regs[Q_REG_I_DIG_OUT_SRC_CTL]; + } else { + shift = Q_REG_OUT_INVERT_SHIFT; + mask = Q_REG_OUT_INVERT_MASK; + reg = q_spec->regs[Q_REG_I_MODE_CTL]; } - return 0; + return (reg & mask) >> shift; } static int __qpnp_pin_set(struct qpnp_pin_chip *q_chip, @@ -905,7 +904,7 @@ static int __qpnp_pin_set(struct qpnp_pin_chip *q_chip, static void qpnp_pin_set(struct gpio_chip *gpio_chip, - unsigned offset, int value) + unsigned int offset, int value) { struct qpnp_pin_chip *q_chip = dev_get_drvdata(gpio_chip->dev); struct qpnp_pin_spec *q_spec; @@ -950,7 +949,7 @@ static int qpnp_pin_set_mode(struct qpnp_pin_chip *q_chip, } static int qpnp_pin_direction_input(struct gpio_chip *gpio_chip, - unsigned offset) + unsigned int offset) { struct qpnp_pin_chip *q_chip = dev_get_drvdata(gpio_chip->dev); struct qpnp_pin_spec *q_spec; @@ -966,8 +965,7 @@ static int qpnp_pin_direction_input(struct gpio_chip *gpio_chip, } static int qpnp_pin_direction_output(struct gpio_chip *gpio_chip, - unsigned offset, - int val) + unsigned int offset, int val) { int rc; struct qpnp_pin_chip *q_chip = dev_get_drvdata(gpio_chip->dev); @@ -1343,7 +1341,7 @@ struct qpnp_pin_debugfs_args { const char *filename; }; -static struct qpnp_pin_debugfs_args dfs_args[] = { +static struct qpnp_pin_debugfs_args dfs_args[Q_NUM_PARAMS] = { { Q_PIN_CFG_MODE, "mode" }, { Q_PIN_CFG_OUTPUT_TYPE, "output_type" }, { Q_PIN_CFG_INVERT, "invert" }, @@ -1371,8 +1369,6 @@ static int qpnp_pin_debugfs_create(struct qpnp_pin_chip *q_chip) struct dentry *dfs, *dfs_io_dir; int i, j, rc; - BUG_ON(Q_NUM_PARAMS != ARRAY_SIZE(dfs_args)); - q_chip->dfs_dir = debugfs_create_dir(q_chip->gpio_chip.label, driver_dfs_dir); if (q_chip->dfs_dir == NULL) { @@ -1403,12 +1399,8 @@ static int qpnp_pin_debugfs_create(struct qpnp_pin_chip *q_chip) continue; params[type] = type; - dfs = debugfs_create_file( - filename, - S_IRUGO | S_IWUSR, - dfs_io_dir, - &q_spec->params[type], - &qpnp_pin_fops); + dfs = debugfs_create_file(filename, 0644, dfs_io_dir, + &q_spec->params[type], &qpnp_pin_fops); if (dfs == NULL) goto dfs_err; } @@ -1674,7 +1666,7 @@ static int qpnp_pin_remove(struct platform_device *pdev) return qpnp_pin_free_chip(q_chip); } -static struct of_device_id spmi_match_table[] = { +static const struct of_device_id spmi_match_table[] = { { .compatible = "qcom,qpnp-pin", }, {} diff --git a/drivers/iio/adc/qcom-tadc.c b/drivers/iio/adc/qcom-tadc.c index 4a56847a43e7..9241288c1d43 100644 --- a/drivers/iio/adc/qcom-tadc.c +++ b/drivers/iio/adc/qcom-tadc.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2017, 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,6 +10,8 @@ * GNU General Public License for more details. */ +#define pr_fmt(fmt) "TADC: %s: " fmt, __func__ + #include <linux/iio/iio.h> #include <linux/interrupt.h> #include <linux/module.h> @@ -101,8 +103,16 @@ enum tadc_chan_id { TADC_BATT_P, TADC_INPUT_P, TADC_THERM1_THR1, + TADC_THERM1_THR2, + TADC_THERM1_THR3, + TADC_THERM1_THR4, TADC_THERM2_THR1, + TADC_THERM2_THR2, + TADC_THERM2_THR3, TADC_DIE_TEMP_THR1, + TADC_DIE_TEMP_THR2, + TADC_DIE_TEMP_THR3, + TADC_CHAN_ID_MAX, }; #define TADC_CHAN(_name, _type, _channel, _info_mask) \ @@ -164,19 +174,39 @@ static const struct iio_chan_spec tadc_iio_chans[] = { [TADC_INPUT_P] = TADC_POWER_CHAN( "input", TADC_INPUT_P), [TADC_THERM1_THR1] = TADC_THERM_CHAN( - "batt_hot", TADC_THERM1_THR1), + "batt_warm", TADC_THERM1_THR1), + [TADC_THERM1_THR2] = TADC_THERM_CHAN( + "batt_cool", TADC_THERM1_THR2), + [TADC_THERM1_THR3] = TADC_THERM_CHAN( + "batt_cold", TADC_THERM1_THR3), + [TADC_THERM1_THR4] = TADC_THERM_CHAN( + "batt_hot", TADC_THERM1_THR4), [TADC_THERM2_THR1] = TADC_THERM_CHAN( - "skin_hot", TADC_THERM2_THR1), + "skin_lb", TADC_THERM2_THR1), + [TADC_THERM2_THR2] = TADC_THERM_CHAN( + "skin_ub", TADC_THERM2_THR2), + [TADC_THERM2_THR3] = TADC_THERM_CHAN( + "skin_rst", TADC_THERM2_THR3), [TADC_DIE_TEMP_THR1] = TADC_THERM_CHAN( - "die_hot", TADC_DIE_TEMP_THR1), + "die_lb", TADC_DIE_TEMP_THR1), + [TADC_DIE_TEMP_THR2] = TADC_THERM_CHAN( + "die_ub", TADC_DIE_TEMP_THR2), + [TADC_DIE_TEMP_THR3] = TADC_THERM_CHAN( + "die_rst", TADC_DIE_TEMP_THR3), +}; + +struct tadc_therm_thr { + int addr_lo; + int addr_hi; }; struct tadc_chan_data { - s32 scale; - s32 offset; - u32 rbias; - const struct tadc_pt *table; - size_t tablesize; + s32 scale; + s32 offset; + u32 rbias; + const struct tadc_pt *table; + size_t tablesize; + struct tadc_therm_thr thr[4]; }; struct tadc_chip { @@ -186,6 +216,7 @@ struct tadc_chip { u32 tadc_cmp_base; struct tadc_chan_data chans[TADC_NUM_CH]; struct completion eoc_complete; + struct mutex write_lock; }; struct tadc_pt { @@ -238,14 +269,24 @@ static const struct tadc_pt tadc_therm_3450b_68k[] = { { 1712127, -40000 }, }; -static int tadc_read(struct tadc_chip *chip, u16 reg, u8 *val, - size_t val_count) +static bool tadc_is_reg_locked(struct tadc_chip *chip, u16 reg) +{ + if ((reg & 0xFF00) == chip->tadc_cmp_base) + return true; + + if (reg == TADC_HWTRIG_CONV_CH_EN_REG(chip)) + return true; + + return false; +} + +static int tadc_read(struct tadc_chip *chip, u16 reg, u8 *val, size_t count) { int rc = 0; - rc = regmap_bulk_read(chip->regmap, reg, val, val_count); + rc = regmap_bulk_read(chip->regmap, reg, val, count); if (rc < 0) - pr_err("Couldn't read %04x rc=%d\n", reg, rc); + pr_err("Couldn't read 0x%04x rc=%d\n", reg, rc); return rc; } @@ -254,57 +295,108 @@ static int tadc_write(struct tadc_chip *chip, u16 reg, u8 data) { int rc = 0; + mutex_lock(&chip->write_lock); + if (tadc_is_reg_locked(chip, reg)) { + rc = regmap_write(chip->regmap, (reg & 0xFF00) | 0xD0, 0xA5); + if (rc < 0) { + pr_err("Couldn't unlock secure register rc=%d\n", rc); + goto unlock; + } + } + rc = regmap_write(chip->regmap, reg, data); - if (rc < 0) - pr_err("Couldn't write %02x to %04x rc=%d\n", - data, reg, rc); + if (rc < 0) { + pr_err("Couldn't write 0x%02x to 0x%04x rc=%d\n", + data, reg, rc); + goto unlock; + } + +unlock: + mutex_unlock(&chip->write_lock); + return rc; +} +static int tadc_bulk_write(struct tadc_chip *chip, u16 reg, u8 *data, + size_t count) +{ + int rc = 0, i; + + mutex_lock(&chip->write_lock); + for (i = 0; i < count; ++i, ++reg) { + if (tadc_is_reg_locked(chip, reg)) { + rc = regmap_write(chip->regmap, + (reg & 0xFF00) | 0xD0, 0xA5); + if (rc < 0) { + pr_err("Couldn't unlock secure register rc=%d\n", + rc); + goto unlock; + } + } + + rc = regmap_write(chip->regmap, reg, data[i]); + if (rc < 0) { + pr_err("Couldn't write 0x%02x to 0x%04x rc=%d\n", + data[i], reg, rc); + goto unlock; + } + } +unlock: + mutex_unlock(&chip->write_lock); return rc; } -static int tadc_lerp(const struct tadc_pt *pts, size_t tablesize, s32 input, - s32 *output) +static int tadc_lerp(const struct tadc_pt *pts, size_t size, bool inv, + s32 input, s32 *output) { int i; s64 temp; + bool ascending; if (pts == NULL) { pr_err("Table is NULL\n"); return -EINVAL; } - if (tablesize < 1) { + if (size < 1) { pr_err("Table has no entries\n"); return -ENOENT; } - if (tablesize == 1) { - *output = pts[0].y; + if (size == 1) { + *output = inv ? pts[0].x : pts[0].y; return 0; } - if (pts[0].x > pts[1].x) { - pr_err("Table is not in acending order\n"); - return -EINVAL; - } - - if (input <= pts[0].x) { - *output = pts[0].y; + ascending = inv ? (pts[0].y < pts[1].y) : (pts[0].x < pts[1].x); + if (ascending ? (input <= (inv ? pts[0].y : pts[0].x)) : + (input >= (inv ? pts[0].y : pts[0].x))) { + *output = inv ? pts[0].x : pts[0].y; return 0; } - if (input >= pts[tablesize - 1].x) { - *output = pts[tablesize - 1].y; + if (ascending ? (input >= (inv ? pts[size - 1].y : pts[size - 1].x)) : + (input <= (inv ? pts[size - 1].y : pts[size - 1].x))) { + *output = inv ? pts[size - 1].x : pts[size - 1].y; return 0; } - for (i = 1; i < tablesize; i++) - if (input <= pts[i].x) + for (i = 1; i < size; i++) + if (ascending ? (input <= (inv ? pts[i].y : pts[i].x)) : + (input >= (inv ? pts[i].y : pts[i].x))) break; - temp = (s64)(pts[i].y - pts[i - 1].y) * (s64)(input - pts[i - 1].x); - temp = div_s64(temp, pts[i].x - pts[i - 1].x); - *output = temp + pts[i - 1].y; + if (inv) { + temp = (s64)(pts[i].x - pts[i - 1].x) * + (s64)(input - pts[i - 1].y); + temp = div_s64(temp, pts[i].y - pts[i - 1].y); + *output = temp + pts[i - 1].x; + } else { + temp = (s64)(pts[i].y - pts[i - 1].y) * + (s64)(input - pts[i - 1].x); + temp = div_s64(temp, pts[i].x - pts[i - 1].x); + *output = temp + pts[i - 1].y; + } + return 0; } @@ -321,15 +413,32 @@ static int tadc_lerp(const struct tadc_pt *pts, size_t tablesize, s32 input, * Combine these equations and solve for Rtherm * Rtherm = (ADC * Rbias) / (1024 - ADC) */ -static int tadc_process_therm(const struct tadc_chan_data *chan_data, - s16 adc, s32 *result) +static int tadc_get_processed_therm(const struct tadc_chan_data *chan_data, + s16 adc, s32 *result) { - s64 rtherm; + s32 rtherm; - rtherm = (s64)adc * (s64)chan_data->rbias; - rtherm = div_s64(rtherm, TADC_RESOLUTION - adc); - return tadc_lerp(chan_data->table, chan_data->tablesize, rtherm, - result); + rtherm = div_s64((s64)adc * chan_data->rbias, TADC_RESOLUTION - adc); + return tadc_lerp(chan_data->table, chan_data->tablesize, false, rtherm, + result); +} + +static int tadc_get_raw_therm(const struct tadc_chan_data *chan_data, + int mdegc, int *result) +{ + int rc; + s32 rtherm; + + rc = tadc_lerp(chan_data->table, chan_data->tablesize, true, mdegc, + &rtherm); + if (rc < 0) { + pr_err("Couldn't interpolate %d\n rc=%d", mdegc, rc); + return rc; + } + + *result = div64_s64((s64)rtherm * TADC_RESOLUTION, + (s64)chan_data->rbias + rtherm); + return 0; } static int tadc_read_channel(struct tadc_chip *chip, u16 address, int *adc) @@ -339,12 +448,31 @@ static int tadc_read_channel(struct tadc_chip *chip, u16 address, int *adc) rc = tadc_read(chip, address, val, ARRAY_SIZE(val)); if (rc < 0) { - dev_err(chip->dev, "Couldn't read channel rc=%d\n", rc); + pr_err("Couldn't read channel rc=%d\n", rc); return rc; } - *adc = (s16)(val[0] | val[1] << BITS_PER_BYTE); - return 0; + /* the 10th bit is the sign bit for all channels */ + *adc = sign_extend32(val[0] | val[1] << BITS_PER_BYTE, 10); + return rc; +} + +static int tadc_write_channel(struct tadc_chip *chip, u16 address, int adc) +{ + u8 val[2]; + int rc; + + /* the 10th bit is the sign bit for all channels */ + adc = sign_extend32(adc, 10); + val[0] = (u8)adc; + val[1] = (u8)(adc >> BITS_PER_BYTE); + rc = tadc_bulk_write(chip, address, val, 2); + if (rc < 0) { + pr_err("Couldn't write to channel rc=%d\n", rc); + return rc; + } + + return rc; } #define CONVERSION_TIMEOUT_MS 100 @@ -356,8 +484,7 @@ static int tadc_do_conversion(struct tadc_chip *chip, u8 channels, s16 *adc) rc = tadc_read(chip, TADC_MBG_ERR_REG(chip), val, 1); if (rc < 0) { - dev_err(chip->dev, "Couldn't read mbg error status rc=%d\n", - rc); + pr_err("Couldn't read mbg error status rc=%d\n", rc); return rc; } @@ -368,8 +495,7 @@ static int tadc_do_conversion(struct tadc_chip *chip, u8 channels, s16 *adc) rc = tadc_write(chip, TADC_CONV_REQ_REG(chip), channels); if (rc < 0) { - dev_err(chip->dev, "Couldn't write conversion request rc=%d\n", - rc); + pr_err("Couldn't write conversion request rc=%d\n", rc); return rc; } @@ -379,21 +505,19 @@ static int tadc_do_conversion(struct tadc_chip *chip, u8 channels, s16 *adc) if (timeleft == 0) { rc = tadc_read(chip, TADC_SW_CH_CONV_REG(chip), val, 1); if (rc < 0) { - dev_err(chip->dev, "Couldn't read conversion status rc=%d\n", - rc); + pr_err("Couldn't read conversion status rc=%d\n", rc); return rc; } if (val[0] != channels) { - dev_err(chip->dev, "Conversion timed out\n"); + pr_err("Conversion timed out\n"); return -ETIMEDOUT; } } rc = tadc_read(chip, TADC_CH1_ADC_LO_REG(chip), val, ARRAY_SIZE(val)); if (rc < 0) { - dev_err(chip->dev, "Couldn't read adc channels rc=%d\n", - rc); + pr_err("Couldn't read adc channels rc=%d\n", rc); return rc; } @@ -404,84 +528,102 @@ static int tadc_do_conversion(struct tadc_chip *chip, u8 channels, s16 *adc) } static int tadc_read_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, int *val, int *val2, - long mask) + struct iio_chan_spec const *chan, int *val, int *val2, + long mask) { struct tadc_chip *chip = iio_priv(indio_dev); - const struct tadc_chan_data *chan_data = &chip->chans[chan->channel]; - int rc = 0, offset = 0, scale, scale2, scale_type; + struct tadc_chan_data *chan_data = NULL; + int rc, offset = 0, scale, scale2, scale_type; s16 adc[TADC_NUM_CH]; switch (chan->channel) { case TADC_THERM1_THR1: + case TADC_THERM1_THR2: + case TADC_THERM1_THR3: + case TADC_THERM1_THR4: chan_data = &chip->chans[TADC_THERM1]; break; case TADC_THERM2_THR1: + case TADC_THERM2_THR2: + case TADC_THERM2_THR3: chan_data = &chip->chans[TADC_THERM2]; break; case TADC_DIE_TEMP_THR1: + case TADC_DIE_TEMP_THR2: + case TADC_DIE_TEMP_THR3: chan_data = &chip->chans[TADC_DIE_TEMP]; break; default: + if (chan->channel >= ARRAY_SIZE(chip->chans)) { + pr_err("Channel %d is out of bounds\n", chan->channel); + return -EINVAL; + } + + chan_data = &chip->chans[chan->channel]; break; } + if (!chan_data) + return -EINVAL; + switch (mask) { case IIO_CHAN_INFO_RAW: switch (chan->channel) { case TADC_THERM1_THR1: + case TADC_THERM2_THR1: + case TADC_DIE_TEMP_THR1: rc = tadc_read_channel(chip, - TADC_CMP_THR1_CH1_CMP_LO_REG(chip), val); - if (rc < 0) { - dev_err(chip->dev, "Couldn't read THERM1 threshold rc=%d\n", - rc); - return rc; - } + chan_data->thr[0].addr_lo, val); break; - case TADC_THERM2_THR1: + case TADC_THERM1_THR2: + case TADC_THERM2_THR2: + case TADC_DIE_TEMP_THR2: rc = tadc_read_channel(chip, - TADC_CMP_THR1_CH2_CMP_LO_REG(chip), val); - if (rc < 0) { - dev_err(chip->dev, "Couldn't read THERM2 threshold rc=%d\n", - rc); - return rc; - } + chan_data->thr[1].addr_lo, val); break; - case TADC_DIE_TEMP_THR1: + case TADC_THERM1_THR3: + case TADC_THERM2_THR3: + case TADC_DIE_TEMP_THR3: rc = tadc_read_channel(chip, - TADC_CMP_THR1_CH3_CMP_LO_REG(chip), val); - if (rc < 0) { - dev_err(chip->dev, "Couldn't read DIE_TEMP threshold rc=%d\n", - rc); - return rc; - } + chan_data->thr[2].addr_lo, val); + break; + case TADC_THERM1_THR4: + rc = tadc_read_channel(chip, + chan_data->thr[3].addr_lo, val); break; default: rc = tadc_do_conversion(chip, BIT(chan->channel), adc); - if (rc < 0) { - dev_err(chip->dev, "Couldn't read channel %d\n", - chan->channel); - return rc; - } - *val = adc[chan->channel]; + if (rc >= 0) + *val = adc[chan->channel]; break; } + + if (rc < 0) { + pr_err("Couldn't read channel %d\n", chan->channel); + return rc; + } + return IIO_VAL_INT; case IIO_CHAN_INFO_PROCESSED: switch (chan->channel) { case TADC_THERM1: case TADC_THERM2: case TADC_THERM1_THR1: + case TADC_THERM1_THR2: + case TADC_THERM1_THR3: + case TADC_THERM1_THR4: case TADC_THERM2_THR1: + case TADC_THERM2_THR2: + case TADC_THERM2_THR3: rc = tadc_read_raw(indio_dev, chan, val, NULL, - IIO_CHAN_INFO_RAW); + IIO_CHAN_INFO_RAW); if (rc < 0) return rc; - rc = tadc_process_therm(chan_data, *val, val); + rc = tadc_get_processed_therm(chan_data, *val, val); if (rc < 0) { - dev_err(chip->dev, "Couldn't process 0x%04x from channel %d rc=%d\n", - *val, chan->channel, rc); + pr_err("Couldn't process 0x%04x from channel %d rc=%d\n", + *val, chan->channel, rc); return rc; } break; @@ -489,7 +631,8 @@ static int tadc_read_raw(struct iio_dev *indio_dev, rc = tadc_do_conversion(chip, BIT(TADC_BATT_I) | BIT(TADC_BATT_V), adc); if (rc < 0) { - dev_err(chip->dev, "Couldn't read battery current and voltage channels\n"); + pr_err("Couldn't read battery current and voltage channels rc=%d\n", + rc); return rc; } @@ -499,7 +642,8 @@ static int tadc_read_raw(struct iio_dev *indio_dev, rc = tadc_do_conversion(chip, BIT(TADC_INPUT_I) | BIT(TADC_INPUT_V), adc); if (rc < 0) { - dev_err(chip->dev, "Couldn't read input current and voltage channels\n"); + pr_err("Couldn't read input current and voltage channels rc=%d\n", + rc); return rc; } @@ -507,13 +651,13 @@ static int tadc_read_raw(struct iio_dev *indio_dev, break; default: rc = tadc_read_raw(indio_dev, chan, val, NULL, - IIO_CHAN_INFO_RAW); + IIO_CHAN_INFO_RAW); if (rc < 0) return rc; /* offset is optional */ rc = tadc_read_raw(indio_dev, chan, &offset, NULL, - IIO_CHAN_INFO_OFFSET); + IIO_CHAN_INFO_OFFSET); if (rc < 0) return rc; @@ -525,18 +669,20 @@ static int tadc_read_raw(struct iio_dev *indio_dev, break; case IIO_VAL_FRACTIONAL: *val = div_s64((s64)*val * scale + offset, - scale2); + scale2); break; default: return -EINVAL; } break; } + return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: switch (chan->channel) { case TADC_DIE_TEMP: case TADC_DIE_TEMP_THR1: + case TADC_DIE_TEMP_THR2: *val = chan_data->scale; return IIO_VAL_INT; case TADC_BATT_I: @@ -548,14 +694,134 @@ static int tadc_read_raw(struct iio_dev *indio_dev, *val2 = TADC_RESOLUTION; return IIO_VAL_FRACTIONAL; } + return -EINVAL; case IIO_CHAN_INFO_OFFSET: *val = chan_data->offset; return IIO_VAL_INT; } + return -EINVAL; } +static int tadc_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int val, int val2, + long mask) +{ + struct tadc_chip *chip = iio_priv(indio_dev); + const struct tadc_chan_data *chan_data; + int rc, raw; + s32 rem; + + switch (chan->channel) { + case TADC_THERM1_THR1: + case TADC_THERM1_THR2: + case TADC_THERM1_THR3: + case TADC_THERM1_THR4: + chan_data = &chip->chans[TADC_THERM1]; + break; + case TADC_THERM2_THR1: + case TADC_THERM2_THR2: + case TADC_THERM2_THR3: + chan_data = &chip->chans[TADC_THERM2]; + break; + case TADC_DIE_TEMP_THR1: + case TADC_DIE_TEMP_THR2: + case TADC_DIE_TEMP_THR3: + chan_data = &chip->chans[TADC_DIE_TEMP]; + break; + default: + if (chan->channel >= ARRAY_SIZE(chip->chans)) { + pr_err("Channel %d is out of bounds\n", chan->channel); + return -EINVAL; + } + + chan_data = &chip->chans[chan->channel]; + break; + } + + if (!chan_data) + return -EINVAL; + + switch (mask) { + case IIO_CHAN_INFO_PROCESSED: + switch (chan->channel) { + case TADC_THERM1_THR1: + case TADC_THERM1_THR2: + case TADC_THERM1_THR3: + case TADC_THERM1_THR4: + case TADC_THERM2_THR1: + case TADC_THERM2_THR2: + case TADC_THERM2_THR3: + rc = tadc_get_raw_therm(chan_data, val, &raw); + if (rc < 0) { + pr_err("Couldn't get raw value rc=%d\n", rc); + return rc; + } + break; + case TADC_DIE_TEMP_THR1: + case TADC_DIE_TEMP_THR2: + case TADC_DIE_TEMP_THR3: + /* DIV_ROUND_CLOSEST does not like negative numbers */ + raw = div_s64_rem(val - chan_data->offset, + chan_data->scale, &rem); + if (abs(rem) >= abs(chan_data->scale / 2)) + raw++; + break; + default: + return -EINVAL; + } + + rc = tadc_write_raw(indio_dev, chan, raw, 0, + IIO_CHAN_INFO_RAW); + if (rc < 0) { + pr_err("Couldn't write raw rc=%d\n", rc); + return rc; + } + + break; + case IIO_CHAN_INFO_RAW: + switch (chan->channel) { + case TADC_THERM1_THR1: + case TADC_THERM2_THR1: + case TADC_DIE_TEMP_THR1: + rc = tadc_write_channel(chip, + chan_data->thr[0].addr_lo, val); + break; + case TADC_THERM1_THR2: + case TADC_THERM2_THR2: + case TADC_DIE_TEMP_THR2: + rc = tadc_write_channel(chip, + chan_data->thr[1].addr_lo, val); + break; + case TADC_THERM1_THR3: + case TADC_THERM2_THR3: + case TADC_DIE_TEMP_THR3: + rc = tadc_write_channel(chip, + chan_data->thr[2].addr_lo, val); + break; + case TADC_THERM1_THR4: + rc = tadc_write_channel(chip, + chan_data->thr[3].addr_lo, val); + break; + default: + return -EINVAL; + } + + if (rc < 0) { + pr_err("Couldn't write channel %d\n", chan->channel); + return rc; + } + + break; + default: + return -EINVAL; + } + + return 0; +} + + static irqreturn_t handle_eoc(int irq, void *dev_id) { struct tadc_chip *chip = dev_id; @@ -587,72 +853,144 @@ static int tadc_parse_dt(struct tadc_chip *chip) for_each_available_child_of_node(node, child) { rc = of_property_read_u32(child, "reg", &chan_id); if (rc < 0) { - dev_err(chip->dev, "Couldn't find channel for %s rc=%d", - child->name, rc); + pr_err("Couldn't find channel for %s rc=%d", + child->name, rc); return rc; } if (chan_id > TADC_NUM_CH - 1) { - dev_err(chip->dev, "Channel %d is out of range [0, %d]\n", - chan_id, TADC_NUM_CH - 1); + pr_err("Channel %d is out of range [0, %d]\n", + chan_id, TADC_NUM_CH - 1); return -EINVAL; } chan_data = &chip->chans[chan_id]; - switch (chan_id) { - case TADC_THERM1: - case TADC_THERM2: + if (chan_id == TADC_THERM1 || chan_id == TADC_THERM2) { rc = of_property_read_u32(child, "qcom,rbias", &chan_data->rbias); if (rc < 0) { - dev_err(chip->dev, "Couldn't read qcom,rbias rc=%d\n", - rc); + pr_err("Couldn't read qcom,rbias rc=%d\n", rc); return rc; } rc = of_property_read_u32(child, "qcom,beta-coefficient", &beta); if (rc < 0) { - dev_err(chip->dev, "Couldn't read qcom,beta-coefficient rc=%d\n", - rc); + pr_err("Couldn't read qcom,beta-coefficient rc=%d\n", + rc); return rc; } rc = of_property_read_u32(child, "qcom,rtherm-at-25degc", &rtherm); if (rc < 0) { - dev_err(chip->dev, "Couldn't read qcom,rtherm-at-25degc rc=%d\n", + pr_err("Couldn't read qcom,rtherm-at-25degc rc=%d\n", rc); return rc; } rc = tadc_set_therm_table(chan_data, beta, rtherm); if (rc < 0) { - dev_err(chip->dev, "Couldn't set therm table rc=%d\n", - rc); + pr_err("Couldn't set therm table rc=%d\n", rc); return rc; } - break; - default: + } else { rc = of_property_read_s32(child, "qcom,scale", - &chan_data->scale); + &chan_data->scale); if (rc < 0) { - dev_err(chip->dev, "Couldn't read scale rc=%d\n", - rc); + pr_err("Couldn't read scale rc=%d\n", rc); return rc; } of_property_read_s32(child, "qcom,offset", - &chan_data->offset); - break; + &chan_data->offset); } } return rc; } +static int tadc_init_hw(struct tadc_chip *chip) +{ + int rc; + + chip->chans[TADC_THERM1].thr[0].addr_lo = + TADC_CMP_THR1_CH1_CMP_LO_REG(chip); + chip->chans[TADC_THERM1].thr[0].addr_hi = + TADC_CMP_THR1_CH1_CMP_HI_REG(chip); + chip->chans[TADC_THERM1].thr[1].addr_lo = + TADC_CMP_THR2_CH1_CMP_LO_REG(chip); + chip->chans[TADC_THERM1].thr[1].addr_hi = + TADC_CMP_THR2_CH1_CMP_HI_REG(chip); + chip->chans[TADC_THERM1].thr[2].addr_lo = + TADC_CMP_THR3_CH1_CMP_LO_REG(chip); + chip->chans[TADC_THERM1].thr[2].addr_hi = + TADC_CMP_THR3_CH1_CMP_HI_REG(chip); + chip->chans[TADC_THERM1].thr[3].addr_lo = + TADC_CMP_THR4_CH1_CMP_LO_REG(chip); + chip->chans[TADC_THERM1].thr[3].addr_hi = + TADC_CMP_THR4_CH1_CMP_HI_REG(chip); + + chip->chans[TADC_THERM2].thr[0].addr_lo = + TADC_CMP_THR1_CH2_CMP_LO_REG(chip); + chip->chans[TADC_THERM2].thr[0].addr_hi = + TADC_CMP_THR1_CH2_CMP_HI_REG(chip); + chip->chans[TADC_THERM2].thr[1].addr_lo = + TADC_CMP_THR2_CH2_CMP_LO_REG(chip); + chip->chans[TADC_THERM2].thr[1].addr_hi = + TADC_CMP_THR2_CH2_CMP_HI_REG(chip); + chip->chans[TADC_THERM2].thr[2].addr_lo = + TADC_CMP_THR3_CH2_CMP_LO_REG(chip); + chip->chans[TADC_THERM2].thr[2].addr_hi = + TADC_CMP_THR3_CH2_CMP_HI_REG(chip); + + chip->chans[TADC_DIE_TEMP].thr[0].addr_lo = + TADC_CMP_THR1_CH3_CMP_LO_REG(chip); + chip->chans[TADC_DIE_TEMP].thr[0].addr_hi = + TADC_CMP_THR1_CH3_CMP_HI_REG(chip); + chip->chans[TADC_DIE_TEMP].thr[1].addr_lo = + TADC_CMP_THR2_CH3_CMP_LO_REG(chip); + chip->chans[TADC_DIE_TEMP].thr[1].addr_hi = + TADC_CMP_THR2_CH3_CMP_HI_REG(chip); + chip->chans[TADC_DIE_TEMP].thr[2].addr_lo = + TADC_CMP_THR3_CH3_CMP_LO_REG(chip); + chip->chans[TADC_DIE_TEMP].thr[2].addr_hi = + TADC_CMP_THR3_CH3_CMP_HI_REG(chip); + + rc = tadc_write(chip, TADC_CMP_THR1_CMP_REG(chip), 0); + if (rc < 0) { + pr_err("Couldn't enable hardware triggers rc=%d\n", rc); + return rc; + } + + rc = tadc_write(chip, TADC_CMP_THR2_CMP_REG(chip), 0); + if (rc < 0) { + pr_err("Couldn't enable hardware triggers rc=%d\n", rc); + return rc; + } + + rc = tadc_write(chip, TADC_CMP_THR3_CMP_REG(chip), 0); + if (rc < 0) { + pr_err("Couldn't enable hardware triggers rc=%d\n", rc); + return rc; + } + + /* enable all temperature hardware triggers */ + rc = tadc_write(chip, TADC_HWTRIG_CONV_CH_EN_REG(chip), + BIT(TADC_THERM1) | + BIT(TADC_THERM2) | + BIT(TADC_DIE_TEMP)); + if (rc < 0) { + pr_err("Couldn't enable hardware triggers rc=%d\n", rc); + return rc; + } + + return 0; +} + static const struct iio_info tadc_info = { .read_raw = &tadc_read_raw, + .write_raw = &tadc_write_raw, .driver_module = THIS_MODULE, }; @@ -661,7 +999,7 @@ static int tadc_probe(struct platform_device *pdev) struct device_node *node = pdev->dev.of_node; struct iio_dev *indio_dev; struct tadc_chip *chip; - int rc = 0, irq; + int rc, irq; indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*chip)); if (!indio_dev) @@ -673,11 +1011,12 @@ static int tadc_probe(struct platform_device *pdev) rc = of_property_read_u32(node, "reg", &chip->tadc_base); if (rc < 0) { - dev_err(chip->dev, "Couldn't read base address rc=%d\n", rc); + pr_err("Couldn't read base address rc=%d\n", rc); return rc; } chip->tadc_cmp_base = chip->tadc_base + 0x100; + mutex_init(&chip->write_lock); chip->regmap = dev_get_regmap(chip->dev->parent, NULL); if (!chip->regmap) { pr_err("Couldn't get regmap\n"); @@ -690,6 +1029,12 @@ static int tadc_probe(struct platform_device *pdev) return rc; } + rc = tadc_init_hw(chip); + if (rc < 0) { + pr_err("Couldn't initialize hardware rc=%d\n", rc); + return rc; + } + irq = of_irq_get_byname(node, "eoc"); if (irq < 0) { pr_err("Couldn't get eoc irq rc=%d\n", irq); @@ -697,7 +1042,7 @@ static int tadc_probe(struct platform_device *pdev) } rc = devm_request_threaded_irq(chip->dev, irq, NULL, handle_eoc, - IRQF_ONESHOT, "eoc", chip); + IRQF_ONESHOT, "eoc", chip); if (rc < 0) { pr_err("Couldn't request irq %d rc=%d\n", irq, rc); return rc; @@ -711,10 +1056,12 @@ static int tadc_probe(struct platform_device *pdev) indio_dev->num_channels = ARRAY_SIZE(tadc_iio_chans); rc = devm_iio_device_register(chip->dev, indio_dev); - if (rc < 0) - dev_err(chip->dev, "Couldn't register IIO device rc=%d\n", rc); + if (rc < 0) { + pr_err("Couldn't register IIO device rc=%d\n", rc); + return rc; + } - return rc; + return 0; } static int tadc_remove(struct platform_device *pdev) diff --git a/drivers/iio/inkern.c b/drivers/iio/inkern.c index 217e9306aa0f..407b2ef4d2e9 100644 --- a/drivers/iio/inkern.c +++ b/drivers/iio/inkern.c @@ -664,3 +664,21 @@ err_unlock: return ret; } EXPORT_SYMBOL_GPL(iio_write_channel_raw); + +int iio_write_channel_processed(struct iio_channel *chan, int val) +{ + int ret; + + mutex_lock(&chan->indio_dev->info_exist_lock); + if (chan->indio_dev->info == NULL) { + ret = -ENODEV; + goto err_unlock; + } + + ret = iio_channel_write(chan, val, 0, IIO_CHAN_INFO_PROCESSED); +err_unlock: + mutex_unlock(&chan->indio_dev->info_exist_lock); + + return ret; +} +EXPORT_SYMBOL_GPL(iio_write_channel_processed); diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index 0fc18922801e..966227a3df1a 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -581,40 +581,6 @@ config LEDS_POWERNV depends on LEDS_CLASS depends on PPC_POWERNV depends on OF - -config LEDS_QPNP - tristate "Support for QPNP LEDs" - depends on LEDS_CLASS && SPMI - help - This driver supports the leds functionality of Qualcomm PNP PMIC. It - includes RGB Leds, WLED and Flash Led. - - To compile this driver as a module, choose M here: the module will - be called leds-qpnp. - -config LEDS_QPNP_FLASH - tristate "Support for QPNP Flash LEDs" - depends on LEDS_CLASS && SPMI - help - This driver supports the leds functionality of Qualcomm Technologies - PNP PMIC. It includes Flash Led. - - To compile this driver as a module, choose M here: the module will - be called leds-qpnp-flash. - -config LEDS_QPNP_FLASH_V2 - tristate "Support for QPNP V2 Flash LEDs" - depends on LEDS_CLASS && MFD_SPMI_PMIC - help - This driver supports the leds functionality of Qualcomm Technologies - PNP PMIC. It includes Flash Led. - - To compile this driver as a module, choose M here: the module will - be called leds-qpnp-flash-v2. - -config LEDS_QPNP_WLED - tristate "Support for QPNP WLED" - depends on LEDS_CLASS && SPMI help This option enables support for the system LEDs present on PowerNV platforms. Say 'y' to enable this support in kernel. @@ -625,31 +591,38 @@ config LEDS_QPNP tristate "Support for QPNP LEDs" depends on LEDS_CLASS && SPMI help - This driver supports the leds functionality of Qualcomm PNP PMIC. It - includes RGB Leds, WLED and Flash Led. - - To compile this driver as a module, choose M here: the module will - be called leds-qpnp. + This driver supports the LED functionality of Qualcomm Technologies, + Inc. QPNP PMICs. It primarily supports controlling tri-color RGB + LEDs in both PWM and light pattern generator (LPG) modes. For older + PMICs, it also supports WLEDs and flash LEDs. config LEDS_QPNP_FLASH tristate "Support for QPNP Flash LEDs" depends on LEDS_CLASS && SPMI help - This driver supports the leds functionality of Qualcomm Technologies - PNP PMIC. It includes Flash Led. + This driver supports the flash LED functionality of Qualcomm + Technologies, Inc. QPNP PMICs. This driver supports PMICs up through + PM8994. It can configure the flash LED target current for several + independent channels. - To compile this driver as a module, choose M here: the module will - be called leds-qpnp-flash. +config LEDS_QPNP_FLASH_V2 + tristate "Support for QPNP V2 Flash LEDs" + depends on LEDS_CLASS && MFD_SPMI_PMIC && !LEDS_QPNP_FLASH + help + This driver supports the flash V2 LED functionality of Qualcomm + Technologies, Inc. QPNP PMICs. This driver supports PMICs starting + from PMI8998. It can configure the flash LED target current for + several independent channels. It also supports various over current + and over temperature mitigation features. config LEDS_QPNP_WLED tristate "Support for QPNP WLED" depends on LEDS_CLASS && SPMI help - This driver supports the WLED (White LED) functionality of - Qualcomm Technologies PNP PMIC. WLED is used for display backlight. - - To compile this driver as a module, choose M here: the module will - be called leds-qpnp-wled. + This driver supports the WLED (White LED) functionality of Qualcomm + Technologies, Inc. QPNP PMICs. WLED is used for LCD backlight with + variable brightness. It also supports outputting the Avdd supply for + AMOLED displays. config LEDS_SYSCON bool "LED support for LEDs on system controllers" diff --git a/drivers/leds/leds-qpnp-flash-v2.c b/drivers/leds/leds-qpnp-flash-v2.c index b6aa4a87f31d..08809a93d4b2 100644 --- a/drivers/leds/leds-qpnp-flash-v2.c +++ b/drivers/leds/leds-qpnp-flash-v2.c @@ -1166,6 +1166,10 @@ static void qpnp_flash_led_brightness_set(struct led_classdev *led_cdev, struct qpnp_flash_led *led = NULL; int rc; + /* + * strncmp() must be used here since a prefix comparison is required + * in order to support names like led:switch_0 and led:flash_1. + */ if (!strncmp(led_cdev->name, "led:switch", strlen("led:switch"))) { snode = container_of(led_cdev, struct flash_switch_data, cdev); led = dev_get_drvdata(&snode->pdev->dev); @@ -1214,8 +1218,7 @@ static ssize_t qpnp_flash_led_max_current_show(struct device *dev, /* sysfs attributes exported by flash_led */ static struct device_attribute qpnp_flash_led_attrs[] = { - __ATTR(max_current, (S_IRUGO | S_IWUSR | S_IWGRP), - qpnp_flash_led_max_current_show, NULL), + __ATTR(max_current, 0664, qpnp_flash_led_max_current_show, NULL), }; static int flash_led_psy_notifier_call(struct notifier_block *nb, diff --git a/drivers/leds/leds-qpnp-flash.c b/drivers/leds/leds-qpnp-flash.c index 98dfa56add51..c27c0593cd10 100644 --- a/drivers/leds/leds-qpnp-flash.c +++ b/drivers/leds/leds-qpnp-flash.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2017, 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 @@ -608,10 +608,9 @@ qpnp_flash_led_get_max_avail_current(struct flash_node_data *flash_node, } /* - * When charging is enabled, enforce this new - * enabelment sequence to reduce fuel gauge - * resolution reading. - */ + * When charging is enabled, enforce this new enablement + * sequence to reduce fuel gauge reading resolution. + */ if (led->charging_enabled) { rc = qpnp_led_masked_write(led, FLASH_MODULE_ENABLE_CTRL(led->base), @@ -637,10 +636,10 @@ qpnp_flash_led_get_max_avail_current(struct flash_node_data *flash_node, max_curr_avail_ma = (prop.intval / FLASH_LED_UA_PER_MA); } - /* When thermal mitigation is available, this logic - * will execute, to derate current based on PMIC die - * temperature. - */ + /* + * When thermal mitigation is available, this logic will execute to + * derate current based upon the PMIC die temperature. + */ if (led->pdata->die_current_derate_en) { chg_temp_milidegc = qpnp_flash_led_get_die_temp(led); if (chg_temp_milidegc < 0) @@ -797,21 +796,14 @@ static ssize_t qpnp_flash_led_max_current_show(struct device *dev, } static struct device_attribute qpnp_flash_led_attrs[] = { - __ATTR(strobe, (S_IRUGO | S_IWUSR | S_IWGRP), - NULL, - qpnp_led_strobe_type_store), - __ATTR(reg_dump, (S_IRUGO | S_IWUSR | S_IWGRP), - qpnp_flash_led_dump_regs_show, - NULL), - __ATTR(enable_current_derate, (S_IRUGO | S_IWUSR | S_IWGRP), - NULL, - qpnp_flash_led_current_derate_store), - __ATTR(max_allowed_current, (S_IRUGO | S_IWUSR | S_IWGRP), - qpnp_flash_led_max_current_show, - NULL), - __ATTR(enable_die_temp_current_derate, (S_IRUGO | S_IWUSR | S_IWGRP), - NULL, - qpnp_flash_led_die_temp_store), + __ATTR(strobe, 0664, NULL, qpnp_led_strobe_type_store), + __ATTR(reg_dump, 0664, qpnp_flash_led_dump_regs_show, NULL), + __ATTR(enable_current_derate, 0664, NULL, + qpnp_flash_led_current_derate_store), + __ATTR(max_allowed_current, 0664, qpnp_flash_led_max_current_show, + NULL), + __ATTR(enable_die_temp_current_derate, 0664, NULL, + qpnp_flash_led_die_temp_store), }; static int qpnp_flash_led_get_thermal_derate_rate(const char *rate) @@ -1771,8 +1763,6 @@ error_enable_gpio: flash_node->flash_on = false; mutex_unlock(&led->flash_led_lock); - - return; } static void qpnp_flash_led_brightness_set(struct led_classdev *led_cdev, @@ -1823,8 +1813,6 @@ static void qpnp_flash_led_brightness_set(struct led_classdev *led_cdev, } queue_work(led->ordered_workq, &flash_node->work); - - return; } static int qpnp_flash_led_init_settings(struct qpnp_flash_led *led) @@ -2359,26 +2347,24 @@ static int qpnp_flash_led_parse_common_dt( dev_err(&led->pdev->dev, "Unable to acquire pinctrl\n"); led->pinctrl = NULL; return 0; - } else { - led->gpio_state_active = - pinctrl_lookup_state(led->pinctrl, "flash_led_enable"); - if (IS_ERR_OR_NULL(led->gpio_state_active)) { - dev_err(&led->pdev->dev, - "Can not lookup LED active state\n"); - devm_pinctrl_put(led->pinctrl); - led->pinctrl = NULL; - return PTR_ERR(led->gpio_state_active); - } - led->gpio_state_suspend = - pinctrl_lookup_state(led->pinctrl, + } + + led->gpio_state_active = pinctrl_lookup_state(led->pinctrl, + "flash_led_enable"); + if (IS_ERR_OR_NULL(led->gpio_state_active)) { + dev_err(&led->pdev->dev, "Cannot lookup LED active state\n"); + devm_pinctrl_put(led->pinctrl); + led->pinctrl = NULL; + return PTR_ERR(led->gpio_state_active); + } + + led->gpio_state_suspend = pinctrl_lookup_state(led->pinctrl, "flash_led_disable"); - if (IS_ERR_OR_NULL(led->gpio_state_suspend)) { - dev_err(&led->pdev->dev, - "Can not lookup LED disable state\n"); - devm_pinctrl_put(led->pinctrl); - led->pinctrl = NULL; - return PTR_ERR(led->gpio_state_suspend); - } + if (IS_ERR_OR_NULL(led->gpio_state_suspend)) { + dev_err(&led->pdev->dev, "Cannot lookup LED disable state\n"); + devm_pinctrl_put(led->pinctrl); + led->pinctrl = NULL; + return PTR_ERR(led->gpio_state_suspend); } return 0; @@ -2408,13 +2394,10 @@ static int qpnp_flash_led_probe(struct platform_device *pdev) return rc; } - led = devm_kzalloc(&pdev->dev, sizeof(struct qpnp_flash_led), - GFP_KERNEL); - if (!led) { - dev_err(&pdev->dev, - "Unable to allocate memory for flash LED\n"); + led = devm_kzalloc(&pdev->dev, sizeof(*led), GFP_KERNEL); + if (!led) return -ENOMEM; - } + led->regmap = dev_get_regmap(pdev->dev.parent, NULL); if (!led->regmap) { dev_err(&pdev->dev, "Couldn't get parent's regmap\n"); @@ -2426,13 +2409,9 @@ static int qpnp_flash_led_probe(struct platform_device *pdev) led->current_addr = FLASH_LED0_CURRENT(led->base); led->current2_addr = FLASH_LED1_CURRENT(led->base); - led->pdata = devm_kzalloc(&pdev->dev, - sizeof(struct flash_led_platform_data), GFP_KERNEL); - if (!led->pdata) { - dev_err(&pdev->dev, - "Unable to allocate memory for platform data\n"); + led->pdata = devm_kzalloc(&pdev->dev, sizeof(*led->pdata), GFP_KERNEL); + if (!led->pdata) return -ENOMEM; - } led->peripheral_type = (u8)qpnp_flash_led_get_peripheral_type(led); if (led->peripheral_type < 0) { @@ -2571,21 +2550,21 @@ static int qpnp_flash_led_probe(struct platform_device *pdev) } led->dbgfs_root = root; - file = debugfs_create_file("enable_debug", S_IRUSR | S_IWUSR, root, - led, &flash_led_dfs_dbg_feature_fops); + file = debugfs_create_file("enable_debug", 0600, root, led, + &flash_led_dfs_dbg_feature_fops); if (!file) { pr_err("error creating 'enable_debug' entry\n"); goto error_led_debugfs; } - file = debugfs_create_file("latched", S_IRUSR | S_IWUSR, root, led, + file = debugfs_create_file("latched", 0600, root, led, &flash_led_dfs_latched_reg_fops); if (!file) { pr_err("error creating 'latched' entry\n"); goto error_led_debugfs; } - file = debugfs_create_file("strobe", S_IRUSR | S_IWUSR, root, led, + file = debugfs_create_file("strobe", 0600, root, led, &flash_led_dfs_strobe_reg_fops); if (!file) { pr_err("error creating 'strobe' entry\n"); @@ -2639,7 +2618,7 @@ static int qpnp_flash_led_remove(struct platform_device *pdev) return 0; } -static struct of_device_id spmi_match_table[] = { +static const struct of_device_id spmi_match_table[] = { { .compatible = "qcom,qpnp-flash-led",}, { }, }; diff --git a/drivers/leds/leds-qpnp-wled.c b/drivers/leds/leds-qpnp-wled.c index 718badb16ea1..1e24c79c3f0a 100644 --- a/drivers/leds/leds-qpnp-wled.c +++ b/drivers/leds/leds-qpnp-wled.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2017, 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 @@ -721,10 +721,11 @@ static ssize_t qpnp_wled_ramp_ms_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct qpnp_wled *wled = dev_get_drvdata(dev); - int data; + int data, rc; - if (sscanf(buf, "%d", &data) != 1) - return -EINVAL; + rc = kstrtoint(buf, 10, &data); + if (rc) + return rc; wled->ramp_ms = data; return count; @@ -744,10 +745,11 @@ static ssize_t qpnp_wled_ramp_step_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct qpnp_wled *wled = dev_get_drvdata(dev); - int data; + int data, rc; - if (sscanf(buf, "%d", &data) != 1) - return -EINVAL; + rc = kstrtoint(buf, 10, &data); + if (rc) + return rc; wled->ramp_step = data; return count; @@ -832,8 +834,9 @@ static ssize_t qpnp_wled_fs_curr_ua_store(struct device *dev, int data, i, rc, temp; u8 reg; - if (sscanf(buf, "%d", &data) != 1) - return -EINVAL; + rc = kstrtoint(buf, 10, &data); + if (rc) + return rc; for (i = 0; i < wled->num_strings; i++) { if (data < QPNP_WLED_FS_CURR_MIN_UA) @@ -869,24 +872,15 @@ static ssize_t qpnp_wled_fs_curr_ua_store(struct device *dev, /* sysfs attributes exported by wled */ static struct device_attribute qpnp_wled_attrs[] = { - __ATTR(dump_regs, (S_IRUGO | S_IWUSR | S_IWGRP), - qpnp_wled_dump_regs_show, - NULL), - __ATTR(dim_mode, (S_IRUGO | S_IWUSR | S_IWGRP), - qpnp_wled_dim_mode_show, - qpnp_wled_dim_mode_store), - __ATTR(fs_curr_ua, (S_IRUGO | S_IWUSR | S_IWGRP), - qpnp_wled_fs_curr_ua_show, - qpnp_wled_fs_curr_ua_store), - __ATTR(start_ramp, (S_IRUGO | S_IWUSR | S_IWGRP), - NULL, - qpnp_wled_ramp_store), - __ATTR(ramp_ms, (S_IRUGO | S_IWUSR | S_IWGRP), - qpnp_wled_ramp_ms_show, - qpnp_wled_ramp_ms_store), - __ATTR(ramp_step, (S_IRUGO | S_IWUSR | S_IWGRP), - qpnp_wled_ramp_step_show, - qpnp_wled_ramp_step_store), + __ATTR(dump_regs, 0664, qpnp_wled_dump_regs_show, NULL), + __ATTR(dim_mode, 0664, qpnp_wled_dim_mode_show, + qpnp_wled_dim_mode_store), + __ATTR(fs_curr_ua, 0664, qpnp_wled_fs_curr_ua_show, + qpnp_wled_fs_curr_ua_store), + __ATTR(start_ramp, 0664, NULL, qpnp_wled_ramp_store), + __ATTR(ramp_ms, 0664, qpnp_wled_ramp_ms_show, qpnp_wled_ramp_ms_store), + __ATTR(ramp_step, 0664, qpnp_wled_ramp_step_show, + qpnp_wled_ramp_step_store), }; /* worker for setting wled brightness */ @@ -2196,7 +2190,7 @@ static int qpnp_wled_remove(struct platform_device *pdev) return 0; } -static struct of_device_id spmi_match_table[] = { +static const struct of_device_id spmi_match_table[] = { { .compatible = "qcom,qpnp-wled",}, { }, }; diff --git a/drivers/leds/leds-qpnp.c b/drivers/leds/leds-qpnp.c index d16fcc3c97ae..85a6be824485 100644 --- a/drivers/leds/leds-qpnp.c +++ b/drivers/leds/leds-qpnp.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2015, 2017, 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 @@ -666,7 +666,7 @@ static int qpnp_wled_set(struct qpnp_led_data *led) return rc; } - usleep_range(WLED_OVP_DELAY, WLED_OVP_DELAY); + usleep_range(WLED_OVP_DELAY, WLED_OVP_DELAY + 10); } else if (led->wled_cfg->pmic_version == PMIC_VER_8941) { if (led->wled_cfg->num_physical_strings <= WLED_THREE_STRINGS) { @@ -696,7 +696,8 @@ static int qpnp_wled_set(struct qpnp_led_data *led) "WLED write sink reg failed"); return rc; } - usleep_range(WLED_OVP_DELAY, WLED_OVP_DELAY); + usleep_range(WLED_OVP_DELAY, + WLED_OVP_DELAY + 10); } else { val = WLED_DISABLE_ALL_SINKS; rc = regmap_write(led->regmap, @@ -724,7 +725,8 @@ static int qpnp_wled_set(struct qpnp_led_data *led) msleep(WLED_OVP_DELAY_LOOP); tries++; } - usleep_range(WLED_OVP_DELAY, WLED_OVP_DELAY); + usleep_range(WLED_OVP_DELAY, + WLED_OVP_DELAY + 10); } } @@ -859,9 +861,7 @@ static int qpnp_mpp_set(struct qpnp_led_data *led) led->mpp_cfg->enable = true; if (led->cdev.brightness < led->mpp_cfg->min_brightness) { - dev_warn(&led->pdev->dev, - "brightness is less than supported..." \ - "set to minimum supported\n"); + dev_warn(&led->pdev->dev, "brightness is less than supported, set to minimum supported\n"); led->cdev.brightness = led->mpp_cfg->min_brightness; } @@ -940,9 +940,7 @@ static int qpnp_mpp_set(struct qpnp_led_data *led) LED_MPP_EN_CTRL(led->base), LED_MPP_EN_MASK, LED_MPP_EN_ENABLE); if (rc) { - dev_err(&led->pdev->dev, - "Failed to write led enable " \ - "reg\n"); + dev_err(&led->pdev->dev, "Failed to write led enable reg\n"); goto err_mpp_reg_write; } } else { @@ -1102,30 +1100,27 @@ static int qpnp_flash_regulator_operate(struct qpnp_led_data *led, bool on) led_array[i].flash_cfg-> flash_wa_reg); if (rc) { - dev_err(&led->pdev->dev, - "Flash wa regulator" - "enable failed(%d)\n", + dev_err(&led->pdev->dev, "Flash wa regulator enable failed(%d)\n", rc); return rc; } } rc = regulator_enable( - led_array[i].flash_cfg->\ - flash_boost_reg); + led_array[i].flash_cfg->flash_boost_reg); if (rc) { if (led_array[i].flash_cfg-> flash_wa_reg_get) - /* Disable flash wa regulator + /* + * Disable flash wa regulator * when flash boost regulator * enable fails */ regulator_disable( led_array[i].flash_cfg-> flash_wa_reg); - dev_err(&led->pdev->dev, - "Flash boost regulator enable" - "failed(%d)\n", rc); + dev_err(&led->pdev->dev, "Flash boost regulator enable failed(%d)\n", + rc); return rc; } led->flash_cfg->flash_on = true; @@ -1150,12 +1145,11 @@ regulator_turn_off: rc); } - rc = regulator_disable(led_array[i].flash_cfg->\ - flash_boost_reg); + rc = regulator_disable( + led_array[i].flash_cfg->flash_boost_reg); if (rc) { - dev_err(&led->pdev->dev, - "Flash boost regulator disable" - "failed(%d)\n", rc); + dev_err(&led->pdev->dev, "Flash boost regulator disable failed(%d)\n", + rc); return rc; } if (led_array[i].flash_cfg->flash_wa_reg_get) { @@ -1163,9 +1157,7 @@ regulator_turn_off: led_array[i].flash_cfg-> flash_wa_reg); if (rc) { - dev_err(&led->pdev->dev, - "Flash_wa regulator" - "disable failed(%d)\n", + dev_err(&led->pdev->dev, "Flash_wa regulator disable failed(%d)\n", rc); return rc; } @@ -1416,7 +1408,8 @@ static int qpnp_flash_set(struct qpnp_led_data *led) /* * Add 1ms delay for bharger enter stable state */ - usleep_range(FLASH_RAMP_UP_DELAY_US, FLASH_RAMP_UP_DELAY_US); + usleep_range(FLASH_RAMP_UP_DELAY_US, + FLASH_RAMP_UP_DELAY_US + 10); if (!led->flash_cfg->strobe_type) led->flash_cfg->trigger_flash &= @@ -1480,7 +1473,8 @@ static int qpnp_flash_set(struct qpnp_led_data *led) * Disable module after ramp down complete for stable * behavior */ - usleep_range(FLASH_RAMP_UP_DELAY_US, FLASH_RAMP_UP_DELAY_US); + usleep_range(FLASH_RAMP_UP_DELAY_US, + FLASH_RAMP_UP_DELAY_US + 10); rc = qpnp_led_masked_write(led, FLASH_ENABLE_CONTROL(led->base), @@ -1658,9 +1652,7 @@ static int qpnp_kpdbl_set(struct qpnp_led_data *led) KPDBL_MODULE_EN_MASK, KPDBL_MODULE_DIS); if (rc) { - dev_err(&led->pdev->dev, - "Failed to write led" - " enable reg\n"); + dev_err(&led->pdev->dev, "Failed to write led enable reg\n"); return rc; } } @@ -1854,8 +1846,6 @@ static void qpnp_led_work(struct work_struct *work) struct qpnp_led_data, work); __qpnp_led_work(led, led->cdev.brightness); - - return; } static int qpnp_led_set_max_brightness(struct qpnp_led_data *led) @@ -1942,7 +1932,7 @@ static int qpnp_wled_init(struct qpnp_led_data *led) return -EINVAL; } - if ((led->max_current > WLED_MAX_CURR)) { + if (led->max_current > WLED_MAX_CURR) { dev_err(&led->pdev->dev, "Invalid max current\n"); return -EINVAL; } @@ -3048,7 +3038,7 @@ static int qpnp_get_common_configs(struct qpnp_led_data *led, rc = of_property_read_string(node, "qcom,default-state", &temp_string); if (!rc) { - if (strncmp(temp_string, "on", sizeof("on")) == 0) + if (strcmp(temp_string, "on") == 0) led->default_on = true; } else if (rc != -EINVAL) return rc; @@ -3075,10 +3065,8 @@ static int qpnp_get_config_wled(struct qpnp_led_data *led, led->wled_cfg = devm_kzalloc(&led->pdev->dev, sizeof(struct wled_config_data), GFP_KERNEL); - if (!led->wled_cfg) { - dev_err(&led->pdev->dev, "Unable to allocate memory\n"); + if (!led->wled_cfg) return -ENOMEM; - } rc = regmap_read(led->regmap, PMIC_VERSION_REG, &tmp); if (rc) { @@ -3161,10 +3149,8 @@ static int qpnp_get_config_flash(struct qpnp_led_data *led, led->flash_cfg = devm_kzalloc(&led->pdev->dev, sizeof(struct flash_config_data), GFP_KERNEL); - if (!led->flash_cfg) { - dev_err(&led->pdev->dev, "Unable to allocate memory\n"); + if (!led->flash_cfg) return -ENOMEM; - } rc = regmap_read(led->regmap, FLASH_PERIPHERAL_SUBTYPE(led->base), &tmp); @@ -3297,23 +3283,23 @@ static int qpnp_get_config_flash(struct qpnp_led_data *led, } return 0; - } else { - rc = of_property_read_u32(node, "qcom,duration", &val); - if (!rc) - led->flash_cfg->duration = (u8)((val - 10) / 10); - else if (rc == -EINVAL) - led->flash_cfg->duration = FLASH_DURATION_200ms; - else - goto error_get_flash_reg; - - rc = of_property_read_u32(node, "qcom,current", &val); - if (!rc) - led->flash_cfg->current_prgm = (val * - FLASH_MAX_LEVEL / led->max_current); - else - goto error_get_flash_reg; } + rc = of_property_read_u32(node, "qcom,duration", &val); + if (!rc) + led->flash_cfg->duration = (u8)((val - 10) / 10); + else if (rc == -EINVAL) + led->flash_cfg->duration = FLASH_DURATION_200ms; + else + goto error_get_flash_reg; + + rc = of_property_read_u32(node, "qcom,current", &val); + if (!rc) + led->flash_cfg->current_prgm = val * FLASH_MAX_LEVEL + / led->max_current; + else + goto error_get_flash_reg; + rc = of_property_read_u32(node, "qcom,headroom", &val); if (!rc) led->flash_cfg->headroom = (u8) val; @@ -3512,11 +3498,11 @@ bad_lpg_params: static int qpnp_led_get_mode(const char *mode) { - if (strncmp(mode, "manual", strlen(mode)) == 0) + if (strcmp(mode, "manual") == 0) return MANUAL_MODE; - else if (strncmp(mode, "pwm", strlen(mode)) == 0) + else if (strcmp(mode, "pwm") == 0) return PWM_MODE; - else if (strncmp(mode, "lpg", strlen(mode)) == 0) + else if (strcmp(mode, "lpg") == 0) return LPG_MODE; else return -EINVAL; @@ -3532,10 +3518,8 @@ static int qpnp_get_config_kpdbl(struct qpnp_led_data *led, led->kpdbl_cfg = devm_kzalloc(&led->pdev->dev, sizeof(struct kpdbl_config_data), GFP_KERNEL); - if (!led->kpdbl_cfg) { - dev_err(&led->pdev->dev, "Unable to allocate memory\n"); + if (!led->kpdbl_cfg) return -ENOMEM; - } rc = of_property_read_string(node, "qcom,mode", &mode); if (!rc) { @@ -3547,11 +3531,9 @@ static int qpnp_get_config_kpdbl(struct qpnp_led_data *led, led->kpdbl_cfg->pwm_cfg = devm_kzalloc(&led->pdev->dev, sizeof(struct pwm_config_data), GFP_KERNEL); - if (!led->kpdbl_cfg->pwm_cfg) { - dev_err(&led->pdev->dev, - "Unable to allocate memory\n"); + if (!led->kpdbl_cfg->pwm_cfg) return -ENOMEM; - } + led->kpdbl_cfg->pwm_cfg->mode = led_mode; led->kpdbl_cfg->pwm_cfg->default_mode = led_mode; } else { @@ -3589,10 +3571,8 @@ static int qpnp_get_config_rgb(struct qpnp_led_data *led, led->rgb_cfg = devm_kzalloc(&led->pdev->dev, sizeof(struct rgb_config_data), GFP_KERNEL); - if (!led->rgb_cfg) { - dev_err(&led->pdev->dev, "Unable to allocate memory\n"); + if (!led->rgb_cfg) return -ENOMEM; - } if (led->id == QPNP_ID_RGB_RED) led->rgb_cfg->enable = RGB_LED_ENABLE_RED; @@ -3641,10 +3621,8 @@ static int qpnp_get_config_mpp(struct qpnp_led_data *led, led->mpp_cfg = devm_kzalloc(&led->pdev->dev, sizeof(struct mpp_config_data), GFP_KERNEL); - if (!led->mpp_cfg) { - dev_err(&led->pdev->dev, "Unable to allocate memory\n"); + if (!led->mpp_cfg) return -ENOMEM; - } if (of_find_property(of_get_parent(node), "mpp-power-supply", NULL)) { led->mpp_cfg->mpp_reg = @@ -3770,11 +3748,8 @@ static int qpnp_get_config_gpio(struct qpnp_led_data *led, led->gpio_cfg = devm_kzalloc(&led->pdev->dev, sizeof(struct gpio_config_data), GFP_KERNEL); - if (!led->gpio_cfg) { - dev_err(&led->pdev->dev, - "Unable to allocate memory gpio struct\n"); + if (!led->gpio_cfg) return -ENOMEM; - } led->gpio_cfg->source_sel = LED_GPIO_SOURCE_SEL_DEFAULT; rc = of_property_read_u32(node, "qcom,source-sel", &val); @@ -3823,12 +3798,10 @@ static int qpnp_leds_probe(struct platform_device *pdev) if (!num_leds) return -ECHILD; - led_array = devm_kzalloc(&pdev->dev, - (sizeof(struct qpnp_led_data) * num_leds), GFP_KERNEL); - if (!led_array) { - dev_err(&pdev->dev, "Unable to allocate memory\n"); + led_array = devm_kcalloc(&pdev->dev, num_leds, sizeof(*led_array), + GFP_KERNEL); + if (!led_array) return -ENOMEM; - } for_each_child_of_node(node, temp) { led = &led_array[parsed_leds]; @@ -3881,24 +3854,22 @@ static int qpnp_leds_probe(struct platform_device *pdev) rc = qpnp_get_common_configs(led, temp); if (rc) { - dev_err(&led->pdev->dev, - "Failure reading common led configuration," \ - " rc = %d\n", rc); + dev_err(&led->pdev->dev, "Failure reading common led configuration, rc = %d\n", + rc); goto fail_id_check; } led->cdev.brightness_set = qpnp_led_set; led->cdev.brightness_get = qpnp_led_get; - if (strncmp(led_label, "wled", sizeof("wled")) == 0) { + if (strcmp(led_label, "wled") == 0) { rc = qpnp_get_config_wled(led, temp); if (rc < 0) { dev_err(&led->pdev->dev, "Unable to read wled config data\n"); goto fail_id_check; } - } else if (strncmp(led_label, "flash", sizeof("flash")) - == 0) { + } else if (strcmp(led_label, "flash") == 0) { if (!of_find_property(node, "flash-boost-supply", NULL)) regulator_probe = true; rc = qpnp_get_config_flash(led, temp, ®ulator_probe); @@ -3907,14 +3878,14 @@ static int qpnp_leds_probe(struct platform_device *pdev) "Unable to read flash config data\n"); goto fail_id_check; } - } else if (strncmp(led_label, "rgb", sizeof("rgb")) == 0) { + } else if (strcmp(led_label, "rgb") == 0) { rc = qpnp_get_config_rgb(led, temp); if (rc < 0) { dev_err(&led->pdev->dev, "Unable to read rgb config data\n"); goto fail_id_check; } - } else if (strncmp(led_label, "mpp", sizeof("mpp")) == 0) { + } else if (strcmp(led_label, "mpp") == 0) { rc = qpnp_get_config_mpp(led, temp); if (rc < 0) { dev_err(&led->pdev->dev, @@ -3928,7 +3899,7 @@ static int qpnp_leds_probe(struct platform_device *pdev) "Unable to read gpio config data\n"); goto fail_id_check; } - } else if (strncmp(led_label, "kpdbl", sizeof("kpdbl")) == 0) { + } else if (strcmp(led_label, "kpdbl") == 0) { bitmap_zero(kpdbl_leds_in_use, NUM_KPDBL_LEDS); is_kpdbl_master_turn_on = false; rc = qpnp_get_config_kpdbl(led, temp); @@ -4113,8 +4084,8 @@ static int qpnp_leds_remove(struct platform_device *pdev) case QPNP_ID_FLASH1_LED0: case QPNP_ID_FLASH1_LED1: if (led_array[i].flash_cfg->flash_reg_get) - regulator_put(led_array[i].flash_cfg-> \ - flash_boost_reg); + regulator_put( + led_array[i].flash_cfg->flash_boost_reg); if (led_array[i].flash_cfg->torch_enable) if (!led_array[i].flash_cfg->no_smbb_support) regulator_put(led_array[i]. @@ -4126,49 +4097,49 @@ static int qpnp_leds_remove(struct platform_device *pdev) case QPNP_ID_RGB_GREEN: case QPNP_ID_RGB_BLUE: if (led_array[i].rgb_cfg->pwm_cfg->mode == PWM_MODE) - sysfs_remove_group(&led_array[i].cdev.dev->\ - kobj, &pwm_attr_group); + sysfs_remove_group(&led_array[i].cdev.dev->kobj, + &pwm_attr_group); if (led_array[i].rgb_cfg->pwm_cfg->use_blink) { - sysfs_remove_group(&led_array[i].cdev.dev->\ - kobj, &blink_attr_group); - sysfs_remove_group(&led_array[i].cdev.dev->\ - kobj, &lpg_attr_group); - } else if (led_array[i].rgb_cfg->pwm_cfg->mode\ - == LPG_MODE) - sysfs_remove_group(&led_array[i].cdev.dev->\ - kobj, &lpg_attr_group); + sysfs_remove_group(&led_array[i].cdev.dev->kobj, + &blink_attr_group); + sysfs_remove_group(&led_array[i].cdev.dev->kobj, + &lpg_attr_group); + } else if (led_array[i].rgb_cfg->pwm_cfg->mode + == LPG_MODE) + sysfs_remove_group(&led_array[i].cdev.dev->kobj, + &lpg_attr_group); break; case QPNP_ID_LED_MPP: if (!led_array[i].mpp_cfg->pwm_cfg) break; if (led_array[i].mpp_cfg->pwm_cfg->mode == PWM_MODE) - sysfs_remove_group(&led_array[i].cdev.dev->\ - kobj, &pwm_attr_group); + sysfs_remove_group(&led_array[i].cdev.dev->kobj, + &pwm_attr_group); if (led_array[i].mpp_cfg->pwm_cfg->use_blink) { - sysfs_remove_group(&led_array[i].cdev.dev->\ - kobj, &blink_attr_group); - sysfs_remove_group(&led_array[i].cdev.dev->\ - kobj, &lpg_attr_group); - } else if (led_array[i].mpp_cfg->pwm_cfg->mode\ - == LPG_MODE) - sysfs_remove_group(&led_array[i].cdev.dev->\ - kobj, &lpg_attr_group); + sysfs_remove_group(&led_array[i].cdev.dev->kobj, + &blink_attr_group); + sysfs_remove_group(&led_array[i].cdev.dev->kobj, + &lpg_attr_group); + } else if (led_array[i].mpp_cfg->pwm_cfg->mode + == LPG_MODE) + sysfs_remove_group(&led_array[i].cdev.dev->kobj, + &lpg_attr_group); if (led_array[i].mpp_cfg->mpp_reg) regulator_put(led_array[i].mpp_cfg->mpp_reg); break; case QPNP_ID_KPDBL: if (led_array[i].kpdbl_cfg->pwm_cfg->mode == PWM_MODE) - sysfs_remove_group(&led_array[i].cdev.dev-> - kobj, &pwm_attr_group); + sysfs_remove_group(&led_array[i].cdev.dev->kobj, + &pwm_attr_group); if (led_array[i].kpdbl_cfg->pwm_cfg->use_blink) { - sysfs_remove_group(&led_array[i].cdev.dev-> - kobj, &blink_attr_group); - sysfs_remove_group(&led_array[i].cdev.dev-> - kobj, &lpg_attr_group); + sysfs_remove_group(&led_array[i].cdev.dev->kobj, + &blink_attr_group); + sysfs_remove_group(&led_array[i].cdev.dev->kobj, + &lpg_attr_group); } else if (led_array[i].kpdbl_cfg->pwm_cfg->mode - == LPG_MODE) - sysfs_remove_group(&led_array[i].cdev.dev-> - kobj, &lpg_attr_group); + == LPG_MODE) + sysfs_remove_group(&led_array[i].cdev.dev->kobj, + &lpg_attr_group); break; default: dev_err(&led_array->pdev->dev, @@ -4182,7 +4153,7 @@ static int qpnp_leds_remove(struct platform_device *pdev) } #ifdef CONFIG_OF -static struct of_device_id spmi_match_table[] = { +static const struct of_device_id spmi_match_table[] = { { .compatible = "qcom,leds-qpnp",}, { }, }; diff --git a/drivers/platform/msm/Kconfig b/drivers/platform/msm/Kconfig index 9c2697dde76d..024c66ac8e57 100644 --- a/drivers/platform/msm/Kconfig +++ b/drivers/platform/msm/Kconfig @@ -5,20 +5,20 @@ config QPNP_REVID tristate "QPNP Revision ID Peripheral" depends on SPMI help - Say 'y' here to include support for the Qualcomm QPNP REVID - peripheral. REVID prints out the PMIC type and revision numbers - in the kernel log along with the PMIC option status. The PMIC - type is mapped to a Qualcomm chip part number and logged as well. + Say 'y' here to include support for the Qualcomm Technologies, Inc. + QPNP REVID peripheral. REVID prints out the PMIC type and revision + numbers in the kernel log along with the PMIC option status. The PMIC + type is mapped to a QTI chip part number and logged as well. config QPNP_COINCELL - tristate "Qualcomm QPNP coincell charger support" + tristate "QPNP coincell charger support" depends on SPMI help This driver supports the QPNP coincell peripheral found inside of - Qualcomm QPNP PMIC devices. The coincell charger provides a means to - charge a coincell battery or backup capacitor which is used to - maintain PMIC register state when the main battery is removed from the - mobile device. + Qualcomm Technologies, Inc. QPNP PMIC devices. The coincell charger + provides a means to charge a coincell battery or backup capacitor + which is used to maintain PMIC register state when the main battery is + removed from the mobile device. config SPS bool "SPS support" diff --git a/drivers/platform/msm/qpnp-coincell.c b/drivers/platform/msm/qpnp-coincell.c index 6aaa53526868..b427f43e76df 100644 --- a/drivers/platform/msm/qpnp-coincell.c +++ b/drivers/platform/msm/qpnp-coincell.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2015, 2017, 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 @@ -244,7 +244,7 @@ static int qpnp_coincell_remove(struct platform_device *pdev) return 0; } -static struct of_device_id qpnp_coincell_match_table[] = { +static const struct of_device_id qpnp_coincell_match_table[] = { { .compatible = QPNP_COINCELL_DRIVER_NAME, }, {} }; diff --git a/drivers/platform/msm/qpnp-revid.c b/drivers/platform/msm/qpnp-revid.c index 6b5db58f856a..9ea0b40304eb 100644 --- a/drivers/platform/msm/qpnp-revid.c +++ b/drivers/platform/msm/qpnp-revid.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2017, 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 @@ -70,7 +70,7 @@ struct revid_chip { static LIST_HEAD(revid_chips); static DEFINE_MUTEX(revid_chips_lock); -static struct of_device_id qpnp_revid_match_table[] = { +static const struct of_device_id qpnp_revid_match_table[] = { { .compatible = QPNP_REVID_DEV_NAME }, {} }; diff --git a/drivers/power/power_supply_sysfs.c b/drivers/power/power_supply_sysfs.c index 3b2ea6a6a5ed..55ab6177e6db 100644 --- a/drivers/power/power_supply_sysfs.c +++ b/drivers/power/power_supply_sysfs.c @@ -282,6 +282,7 @@ static struct device_attribute power_supply_attrs[] = { POWER_SUPPLY_ATTR(fcc_delta), POWER_SUPPLY_ATTR(icl_reduction), POWER_SUPPLY_ATTR(parallel_mode), + POWER_SUPPLY_ATTR(connector_therm_zone), /* Local extensions of type int64_t */ POWER_SUPPLY_ATTR(charge_counter_ext), /* Properties of type `const char *' */ diff --git a/drivers/power/supply/qcom/qpnp-qnovo.c b/drivers/power/supply/qcom/qpnp-qnovo.c index c4cc541a0a3e..078bbaaad5a2 100644 --- a/drivers/power/supply/qcom/qpnp-qnovo.c +++ b/drivers/power/supply/qcom/qpnp-qnovo.c @@ -110,8 +110,7 @@ struct qnovo_dt_props { }; enum { - QNOVO_ERASE_OFFSET_WA_BIT = BIT(0), - QNOVO_NO_ERR_STS_BIT = BIT(1), + QNOVO_NO_ERR_STS_BIT = BIT(0), }; struct chg_props { @@ -315,7 +314,6 @@ static int qnovo_check_chg_version(struct qnovo *chip) if ((chip->pmic_rev_id->pmic_subtype == PMI8998_SUBTYPE) && (chip->pmic_rev_id->rev4 < PMI8998_V2P0_REV4)) { - chip->wa_flags |= QNOVO_ERASE_OFFSET_WA_BIT; chip->wa_flags |= QNOVO_NO_ERR_STS_BIT; } @@ -447,6 +445,8 @@ static struct param_info params[] = { .num_regs = 1, .reg_to_unit_multiplier = 1, .reg_to_unit_divider = 1, + .min_val = 0, + .max_val = 255, .units_str = "pulses", }, [VLIM1] = { @@ -1187,7 +1187,7 @@ static int qnovo_hw_init(struct qnovo *chip) u8 iadc_offset_external, iadc_offset_internal; u8 iadc_gain_external, iadc_gain_internal; u8 vadc_offset, vadc_gain; - u8 buf[2] = {0, 0}; + u8 val; vote(chip->disable_votable, USER_VOTER, 1, 0); @@ -1241,13 +1241,39 @@ static int qnovo_hw_init(struct qnovo *chip) chip->v_gain_mega = 1000000000 + (s64)vadc_gain * GAIN_LSB_FACTOR; chip->v_gain_mega = div_s64(chip->v_gain_mega, 1000); - if (chip->wa_flags & QNOVO_ERASE_OFFSET_WA_BIT) { - rc = qnovo_write(chip, QNOVO_TR_IADC_OFFSET_0, buf, 2); - if (rc < 0) { - pr_err("Couldn't erase offset rc = %d\n", rc); - return rc; - } + val = 0; + rc = qnovo_write(chip, QNOVO_STRM_CTRL, &val, 1); + if (rc < 0) { + pr_err("Couldn't write iadc bitsteam control rc = %d\n", rc); + return rc; + } + + rc = qnovo_read(chip, QNOVO_TR_IADC_OFFSET_0, &val, 1); + if (rc < 0) { + pr_err("Couldn't read iadc offset rc = %d\n", rc); + return rc; + } + + val *= -1; + rc = qnovo_write(chip, QNOVO_TR_IADC_OFFSET_0, &val, 1); + if (rc < 0) { + pr_err("Couldn't write iadc offset rc = %d\n", rc); + return rc; + } + + rc = qnovo_read(chip, QNOVO_TR_IADC_OFFSET_1, &val, 1); + if (rc < 0) { + pr_err("Couldn't read iadc offset rc = %d\n", rc); + return rc; } + + val *= -1; + rc = qnovo_write(chip, QNOVO_TR_IADC_OFFSET_1, &val, 1); + if (rc < 0) { + pr_err("Couldn't write iadc offset rc = %d\n", rc); + return rc; + } + return 0; } diff --git a/drivers/power/supply/qcom/qpnp-smb2.c b/drivers/power/supply/qcom/qpnp-smb2.c index dea932ae37ad..f8171ecc47f3 100644 --- a/drivers/power/supply/qcom/qpnp-smb2.c +++ b/drivers/power/supply/qcom/qpnp-smb2.c @@ -620,7 +620,7 @@ static int smb2_usb_main_get_prop(struct power_supply *psy, rc = smblib_get_prop_fcc_delta(chg, val); break; default: - pr_err("get prop %d is not supported in usb-main\n", psp); + pr_debug("get prop %d is not supported in usb-main\n", psp); rc = -EINVAL; break; } @@ -1305,7 +1305,22 @@ static int smb2_init_hw(struct smb2 *chip) smblib_get_charge_param(chg, &chg->param.dc_icl, &chip->dt.dc_icl_ua); - chg->otg_cl_ua = chip->dt.otg_cl_ua; + /* set a slower soft start setting for OTG */ + rc = smblib_masked_write(chg, DC_ENG_SSUPPLY_CFG2_REG, + ENG_SSUPPLY_IVREF_OTG_SS_MASK, OTG_SS_SLOW); + if (rc < 0) { + pr_err("Couldn't set otg soft start rc=%d\n", rc); + return rc; + } + + /* set OTG current limit */ + rc = smblib_set_charge_param(chg, &chg->param.otg_cl, + chip->dt.otg_cl_ua); + if (rc < 0) { + pr_err("Couldn't set otg current limit rc=%d\n", rc); + return rc; + } + chg->dcp_icl_ua = chip->dt.usb_icl_ua; chg->boost_threshold_ua = chip->dt.boost_threshold_ua; diff --git a/drivers/power/supply/qcom/smb-lib.c b/drivers/power/supply/qcom/smb-lib.c index 3e939c5ffba1..ee5b5a51465b 100644 --- a/drivers/power/supply/qcom/smb-lib.c +++ b/drivers/power/supply/qcom/smb-lib.c @@ -762,20 +762,6 @@ out: return rc; } -#define MICRO_250MA 250000 -static int smblib_otg_cl_config(struct smb_charger *chg, int otg_cl_ua) -{ - int rc = 0; - - rc = smblib_set_charge_param(chg, &chg->param.otg_cl, otg_cl_ua); - if (rc < 0) { - smblib_err(chg, "Couldn't set otg current limit rc=%d\n", rc); - return rc; - } - - return rc; -} - static int smblib_dc_icl_vote_callback(struct votable *votable, void *data, int icl_ua, const char *client) { @@ -955,22 +941,33 @@ static int smblib_apsd_disable_vote_callback(struct votable *votable, * VCONN REGULATOR * * *****************/ +#define MAX_OTG_SS_TRIES 2 static int _smblib_vconn_regulator_enable(struct regulator_dev *rdev) { struct smb_charger *chg = rdev_get_drvdata(rdev); u8 otg_stat, stat4; - int rc = 0; + int rc = 0, i; if (!chg->external_vconn) { - rc = smblib_read(chg, OTG_STATUS_REG, &otg_stat); - if (rc < 0) { - smblib_err(chg, "Couldn't read OTG status rc=%d\n", rc); - return rc; + /* + * Hardware based OTG soft start should complete within 1ms, so + * wait for 2ms in the worst case. + */ + for (i = 0; i < MAX_OTG_SS_TRIES; ++i) { + usleep_range(1000, 1100); + rc = smblib_read(chg, OTG_STATUS_REG, &otg_stat); + if (rc < 0) { + smblib_err(chg, "Couldn't read OTG status rc=%d\n", + rc); + return rc; + } + + if (otg_stat & BOOST_SOFTSTART_DONE_BIT) + break; } - if ((otg_stat & OTG_STATE_MASK) != OTG_STATE_ENABLED) { - smblib_err(chg, "Couldn't enable VCONN; OTG is not ready otg_stat=0x%02x\n", - otg_stat); + if (!(otg_stat & BOOST_SOFTSTART_DONE_BIT)) { + smblib_err(chg, "Couldn't enable VCONN; OTG soft start failed\n"); return -EAGAIN; } } @@ -985,6 +982,7 @@ static int _smblib_vconn_regulator_enable(struct regulator_dev *rdev) return rc; } + smblib_dbg(chg, PR_OTG, "enabling VCONN\n"); stat4 = stat4 & CC_ORIENTATION_BIT ? 0 : VCONN_EN_ORIENTATION_BIT; rc = smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG, VCONN_EN_VALUE_BIT | VCONN_EN_ORIENTATION_BIT, @@ -1002,7 +1000,7 @@ int smblib_vconn_regulator_enable(struct regulator_dev *rdev) struct smb_charger *chg = rdev_get_drvdata(rdev); int rc = 0; - mutex_lock(&chg->otg_overcurrent_lock); + mutex_lock(&chg->otg_oc_lock); if (chg->vconn_en) goto unlock; @@ -1011,7 +1009,7 @@ int smblib_vconn_regulator_enable(struct regulator_dev *rdev) chg->vconn_en = true; unlock: - mutex_unlock(&chg->otg_overcurrent_lock); + mutex_unlock(&chg->otg_oc_lock); return rc; } @@ -1020,6 +1018,7 @@ static int _smblib_vconn_regulator_disable(struct regulator_dev *rdev) struct smb_charger *chg = rdev_get_drvdata(rdev); int rc = 0; + smblib_dbg(chg, PR_OTG, "disabling VCONN\n"); rc = smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG, VCONN_EN_VALUE_BIT, 0); if (rc < 0) @@ -1033,7 +1032,7 @@ int smblib_vconn_regulator_disable(struct regulator_dev *rdev) struct smb_charger *chg = rdev_get_drvdata(rdev); int rc = 0; - mutex_lock(&chg->otg_overcurrent_lock); + mutex_lock(&chg->otg_oc_lock); if (!chg->vconn_en) goto unlock; @@ -1042,7 +1041,7 @@ int smblib_vconn_regulator_disable(struct regulator_dev *rdev) chg->vconn_en = false; unlock: - mutex_unlock(&chg->otg_overcurrent_lock); + mutex_unlock(&chg->otg_oc_lock); return rc; } @@ -1051,9 +1050,9 @@ int smblib_vconn_regulator_is_enabled(struct regulator_dev *rdev) struct smb_charger *chg = rdev_get_drvdata(rdev); int ret; - mutex_lock(&chg->otg_overcurrent_lock); + mutex_lock(&chg->otg_oc_lock); ret = chg->vconn_en; - mutex_unlock(&chg->otg_overcurrent_lock); + mutex_unlock(&chg->otg_oc_lock); return ret; } @@ -1061,14 +1060,12 @@ int smblib_vconn_regulator_is_enabled(struct regulator_dev *rdev) * OTG REGULATOR * *****************/ -#define MAX_SOFTSTART_TRIES 2 static int _smblib_vbus_regulator_enable(struct regulator_dev *rdev) { struct smb_charger *chg = rdev_get_drvdata(rdev); - u8 stat; - int rc = 0; - int tries = MAX_SOFTSTART_TRIES; + int rc; + smblib_dbg(chg, PR_OTG, "halt 1 in 8 mode\n"); rc = smblib_masked_write(chg, OTG_ENG_OTG_CFG_REG, ENG_BUCKBOOST_HALT1_8_MODE_BIT, ENG_BUCKBOOST_HALT1_8_MODE_BIT); @@ -1078,34 +1075,13 @@ static int _smblib_vbus_regulator_enable(struct regulator_dev *rdev) return rc; } + smblib_dbg(chg, PR_OTG, "enabling OTG\n"); rc = smblib_write(chg, CMD_OTG_REG, OTG_EN_BIT); if (rc < 0) { smblib_err(chg, "Couldn't enable OTG regulator rc=%d\n", rc); return rc; } - /* waiting for boost readiness, usually ~1ms, 2ms in worst case */ - do { - usleep_range(1000, 1100); - - rc = smblib_read(chg, OTG_STATUS_REG, &stat); - if (rc < 0) { - smblib_err(chg, "Couldn't read OTG_STATUS_REG rc=%d\n", - rc); - return rc; - } - if (stat & BOOST_SOFTSTART_DONE_BIT) { - smblib_otg_cl_config(chg, chg->otg_cl_ua); - break; - } - } while (--tries); - - if (tries == 0) { - smblib_err(chg, "Timeout waiting for boost softstart rc=%d\n", - rc); - return -ETIMEDOUT; - } - return rc; } @@ -1114,7 +1090,7 @@ int smblib_vbus_regulator_enable(struct regulator_dev *rdev) struct smb_charger *chg = rdev_get_drvdata(rdev); int rc = 0; - mutex_lock(&chg->otg_overcurrent_lock); + mutex_lock(&chg->otg_oc_lock); if (chg->otg_en) goto unlock; @@ -1123,7 +1099,7 @@ int smblib_vbus_regulator_enable(struct regulator_dev *rdev) chg->otg_en = true; unlock: - mutex_unlock(&chg->otg_overcurrent_lock); + mutex_unlock(&chg->otg_oc_lock); return rc; } @@ -1131,32 +1107,23 @@ static int _smblib_vbus_regulator_disable(struct regulator_dev *rdev) { struct smb_charger *chg = rdev_get_drvdata(rdev); int rc; - u8 stat; - if (!chg->external_vconn) { - rc = smblib_read(chg, RID_CC_CONTROL_7_0_REG, &stat); + if (!chg->external_vconn && chg->vconn_en) { + smblib_dbg(chg, PR_OTG, "Killing VCONN before disabling OTG\n"); + rc = _smblib_vconn_regulator_disable(rdev); if (rc < 0) - smblib_err(chg, "Couldn't read RID_CC_CONTROL_7_0 rc=%d\n", - rc); - - /* check if VCONN is enabled on either CC pin */ - if (stat & VCONN_EN_CC_MASK) { - smblib_dbg(chg, PR_MISC, "Killing VCONN before disabling OTG\n"); - rc = _smblib_vconn_regulator_disable(rdev); - if (rc < 0) - smblib_err(chg, "Couldn't disable VCONN rc=%d\n", - rc); - } + smblib_err(chg, "Couldn't disable VCONN rc=%d\n", rc); } + smblib_dbg(chg, PR_OTG, "disabling OTG\n"); rc = smblib_write(chg, CMD_OTG_REG, 0); if (rc < 0) { smblib_err(chg, "Couldn't disable OTG regulator rc=%d\n", rc); return rc; } - smblib_otg_cl_config(chg, MICRO_250MA); - + smblib_dbg(chg, PR_OTG, "start 1 in 8 mode\n"); + rc = smblib_write(chg, CMD_OTG_REG, 0); rc = smblib_masked_write(chg, OTG_ENG_OTG_CFG_REG, ENG_BUCKBOOST_HALT1_8_MODE_BIT, 0); if (rc < 0) { @@ -1172,7 +1139,7 @@ int smblib_vbus_regulator_disable(struct regulator_dev *rdev) struct smb_charger *chg = rdev_get_drvdata(rdev); int rc = 0; - mutex_lock(&chg->otg_overcurrent_lock); + mutex_lock(&chg->otg_oc_lock); if (!chg->otg_en) goto unlock; @@ -1181,7 +1148,7 @@ int smblib_vbus_regulator_disable(struct regulator_dev *rdev) chg->otg_en = false; unlock: - mutex_unlock(&chg->otg_overcurrent_lock); + mutex_unlock(&chg->otg_oc_lock); return rc; } @@ -1190,9 +1157,9 @@ int smblib_vbus_regulator_is_enabled(struct regulator_dev *rdev) struct smb_charger *chg = rdev_get_drvdata(rdev); int ret; - mutex_lock(&chg->otg_overcurrent_lock); + mutex_lock(&chg->otg_oc_lock); ret = chg->otg_en; - mutex_unlock(&chg->otg_overcurrent_lock); + mutex_unlock(&chg->otg_oc_lock); return ret; } @@ -1955,6 +1922,29 @@ int smblib_get_pe_start(struct smb_charger *chg, return 0; } +int smblib_get_prop_connector_therm_zone(struct smb_charger *chg, + union power_supply_propval *val) +{ + int rc, i; + u8 stat; + + rc = smblib_read(chg, TEMP_RANGE_STATUS_REG, &stat); + if (rc < 0) { + smblib_err(chg, "Couldn't read TEMP_RANGE_STATUS_REG rc=%d\n", + rc); + return rc; + } + + i = fls((stat & TEMP_RANGE_MASK) >> TEMP_RANGE_SHIFT) - 1; + if (i < 0) { + smblib_err(chg, "TEMP_RANGE is invalid\n"); + return -EINVAL; + } + + val->intval = i; + return 0; +} + /******************* * USB PSY SETTERS * * *****************/ @@ -2467,50 +2457,9 @@ irqreturn_t smblib_handle_otg_overcurrent(int irq, void *data) return IRQ_HANDLED; } - if (!(stat & OTG_OVERCURRENT_RT_STS_BIT)) - return IRQ_HANDLED; + if (stat & OTG_OVERCURRENT_RT_STS_BIT) + schedule_work(&chg->otg_oc_work); - smblib_err(chg, "over-current detected on VBUS\n"); - if (!chg->vbus_vreg || !chg->vbus_vreg->rdev) - return IRQ_HANDLED; - - mutex_lock(&chg->otg_overcurrent_lock); - if (!chg->external_vconn && chg->vconn_en) { - rc = _smblib_vconn_regulator_disable(chg->vconn_vreg->rdev); - if (rc < 0) - smblib_err(chg, "Couldn't disable VCONN rc=%d\n", rc); - } - - rc = _smblib_vbus_regulator_disable(chg->vbus_vreg->rdev); - if (rc < 0) - smblib_err(chg, "Couldn't disable VBUS rc=%d\n", rc); - - /* - * VBUS must be disabled after OC to be ready for the next insertion. - * If the maximum number of attempts have been reached then don't try - * to re-enable. - */ - if (++chg->otg_attempts > OTG_MAX_ATTEMPTS) { - smblib_err(chg, "OTG failed to enable after %d attempts\n", - chg->otg_attempts - 1); - goto unlock; - } - - /* allow the attached device to discharge */ - msleep(250); - - rc = _smblib_vbus_regulator_enable(chg->vbus_vreg->rdev); - if (rc < 0) - smblib_err(chg, "Couldn't enable VBUS rc=%d\n", rc); - - if (!chg->external_vconn && chg->vconn_en) { - rc = _smblib_vconn_regulator_enable(chg->vconn_vreg->rdev); - if (rc < 0) - smblib_err(chg, "Couldn't enable VCONN rc=%d\n", rc); - } - -unlock: - mutex_unlock(&chg->otg_overcurrent_lock); return IRQ_HANDLED; } @@ -3094,41 +3043,6 @@ irqreturn_t smblib_handle_usb_typec_change_for_uusb(struct smb_charger *chg) return IRQ_HANDLED; } -static void smblib_handle_vconn_overcurrent(struct smb_charger *chg) -{ - int rc; - - smblib_err(chg, "over-current detected on VCONN\n"); - if (!chg->vconn_vreg || !chg->vconn_vreg->rdev) - return; - - mutex_lock(&chg->otg_overcurrent_lock); - rc = _smblib_vconn_regulator_disable(chg->vconn_vreg->rdev); - if (rc < 0) - smblib_err(chg, "Couldn't disable VCONN rc=%d\n", rc); - - /* - * VCONN must be disabled after OC to be ready for the next insertion. - * If the maximum number of attempts have been reached then don't try - * to re-enable. - */ - if (++chg->vconn_attempts > VCONN_MAX_ATTEMPTS) { - smblib_err(chg, "VCONN failed to enable after %d attempts\n", - chg->vconn_attempts - 1); - goto unlock; - } - - /* allow the attached device to discharge */ - msleep(250); - - rc = _smblib_vconn_regulator_enable(chg->vconn_vreg->rdev); - if (rc < 0) - smblib_err(chg, "Couldn't enable VCONN rc=%d\n", rc); - -unlock: - mutex_unlock(&chg->otg_overcurrent_lock); -} - irqreturn_t smblib_handle_usb_typec_change(int irq, void *data) { struct smb_irq_data *irq_data = data; @@ -3168,7 +3082,7 @@ irqreturn_t smblib_handle_usb_typec_change(int irq, void *data) irq_data->name); if (stat4 & TYPEC_VCONN_OVERCURR_STATUS_BIT) - smblib_handle_vconn_overcurrent(chg); + schedule_work(&chg->vconn_oc_work); power_supply_changed(chg->usb_psy); smblib_dbg(chg, PR_REGISTER, "TYPE_C_STATUS_4 = 0x%02x\n", stat4); @@ -3362,6 +3276,190 @@ rerun: schedule_work(&chg->rdstd_cc2_detach_work); } +static void smblib_otg_oc_exit(struct smb_charger *chg, bool success) +{ + int rc; + + chg->otg_attempts = 0; + if (!success) { + smblib_err(chg, "OTG soft start failed\n"); + chg->otg_en = false; + } + + smblib_dbg(chg, PR_OTG, "enabling VBUS < 1V check\n"); + rc = smblib_masked_write(chg, OTG_CFG_REG, + QUICKSTART_OTG_FASTROLESWAP_BIT, 0); + if (rc < 0) + smblib_err(chg, "Couldn't enable VBUS < 1V check rc=%d\n", rc); + + if (!chg->external_vconn && chg->vconn_en) { + chg->vconn_attempts = 0; + if (success) { + rc = _smblib_vconn_regulator_enable( + chg->vconn_vreg->rdev); + if (rc < 0) + smblib_err(chg, "Couldn't enable VCONN rc=%d\n", + rc); + } else { + chg->vconn_en = false; + } + } +} + +#define MAX_OC_FALLING_TRIES 10 +static void smblib_otg_oc_work(struct work_struct *work) +{ + struct smb_charger *chg = container_of(work, struct smb_charger, + otg_oc_work); + int rc, i; + u8 stat; + + if (!chg->vbus_vreg || !chg->vbus_vreg->rdev) + return; + + smblib_err(chg, "over-current detected on VBUS\n"); + mutex_lock(&chg->otg_oc_lock); + if (!chg->otg_en) + goto unlock; + + smblib_dbg(chg, PR_OTG, "disabling VBUS < 1V check\n"); + smblib_masked_write(chg, OTG_CFG_REG, + QUICKSTART_OTG_FASTROLESWAP_BIT, + QUICKSTART_OTG_FASTROLESWAP_BIT); + + /* + * If 500ms has passed and another over-current interrupt has not + * triggered then it is likely that the software based soft start was + * successful and the VBUS < 1V restriction should be re-enabled. + */ + schedule_delayed_work(&chg->otg_ss_done_work, msecs_to_jiffies(500)); + + rc = _smblib_vbus_regulator_disable(chg->vbus_vreg->rdev); + if (rc < 0) { + smblib_err(chg, "Couldn't disable VBUS rc=%d\n", rc); + goto unlock; + } + + if (++chg->otg_attempts > OTG_MAX_ATTEMPTS) { + cancel_delayed_work_sync(&chg->otg_ss_done_work); + smblib_err(chg, "OTG failed to enable after %d attempts\n", + chg->otg_attempts - 1); + smblib_otg_oc_exit(chg, false); + goto unlock; + } + + /* + * The real time status should go low within 10ms. Poll every 1-2ms to + * minimize the delay when re-enabling OTG. + */ + for (i = 0; i < MAX_OC_FALLING_TRIES; ++i) { + usleep_range(1000, 2000); + rc = smblib_read(chg, OTG_BASE + INT_RT_STS_OFFSET, &stat); + if (rc >= 0 && !(stat & OTG_OVERCURRENT_RT_STS_BIT)) + break; + } + + if (i >= MAX_OC_FALLING_TRIES) { + cancel_delayed_work_sync(&chg->otg_ss_done_work); + smblib_err(chg, "OTG OC did not fall after %dms\n", + 2 * MAX_OC_FALLING_TRIES); + smblib_otg_oc_exit(chg, false); + goto unlock; + } + + smblib_dbg(chg, PR_OTG, "OTG OC fell after %dms\n", 2 * i + 1); + rc = _smblib_vbus_regulator_enable(chg->vbus_vreg->rdev); + if (rc < 0) { + smblib_err(chg, "Couldn't enable VBUS rc=%d\n", rc); + goto unlock; + } + +unlock: + mutex_unlock(&chg->otg_oc_lock); +} + +static void smblib_vconn_oc_work(struct work_struct *work) +{ + struct smb_charger *chg = container_of(work, struct smb_charger, + vconn_oc_work); + int rc, i; + u8 stat; + + smblib_err(chg, "over-current detected on VCONN\n"); + if (!chg->vconn_vreg || !chg->vconn_vreg->rdev) + return; + + mutex_lock(&chg->otg_oc_lock); + rc = _smblib_vconn_regulator_disable(chg->vconn_vreg->rdev); + if (rc < 0) { + smblib_err(chg, "Couldn't disable VCONN rc=%d\n", rc); + goto unlock; + } + + if (++chg->vconn_attempts > VCONN_MAX_ATTEMPTS) { + smblib_err(chg, "VCONN failed to enable after %d attempts\n", + chg->otg_attempts - 1); + chg->vconn_en = false; + chg->vconn_attempts = 0; + goto unlock; + } + + /* + * The real time status should go low within 10ms. Poll every 1-2ms to + * minimize the delay when re-enabling OTG. + */ + for (i = 0; i < MAX_OC_FALLING_TRIES; ++i) { + usleep_range(1000, 2000); + rc = smblib_read(chg, TYPE_C_STATUS_4_REG, &stat); + if (rc >= 0 && !(stat & TYPEC_VCONN_OVERCURR_STATUS_BIT)) + break; + } + + if (i >= MAX_OC_FALLING_TRIES) { + smblib_err(chg, "VCONN OC did not fall after %dms\n", + 2 * MAX_OC_FALLING_TRIES); + chg->vconn_en = false; + chg->vconn_attempts = 0; + goto unlock; + } + + smblib_dbg(chg, PR_OTG, "VCONN OC fell after %dms\n", 2 * i + 1); + if (++chg->vconn_attempts > VCONN_MAX_ATTEMPTS) { + smblib_err(chg, "VCONN failed to enable after %d attempts\n", + chg->vconn_attempts - 1); + chg->vconn_en = false; + goto unlock; + } + + rc = _smblib_vconn_regulator_enable(chg->vconn_vreg->rdev); + if (rc < 0) { + smblib_err(chg, "Couldn't enable VCONN rc=%d\n", rc); + goto unlock; + } + +unlock: + mutex_unlock(&chg->otg_oc_lock); +} + +static void smblib_otg_ss_done_work(struct work_struct *work) +{ + struct smb_charger *chg = container_of(work, struct smb_charger, + otg_ss_done_work.work); + int rc; + bool success = false; + u8 stat; + + mutex_lock(&chg->otg_oc_lock); + rc = smblib_read(chg, OTG_STATUS_REG, &stat); + if (rc < 0) + smblib_err(chg, "Couldn't read OTG status rc=%d\n", rc); + else if (stat & BOOST_SOFTSTART_DONE_BIT) + success = true; + + smblib_otg_oc_exit(chg, success); + mutex_unlock(&chg->otg_oc_lock); +} + static int smblib_create_votables(struct smb_charger *chg) { int rc = 0; @@ -3541,12 +3639,15 @@ int smblib_init(struct smb_charger *chg) int rc = 0; mutex_init(&chg->write_lock); - mutex_init(&chg->otg_overcurrent_lock); + mutex_init(&chg->otg_oc_lock); INIT_WORK(&chg->bms_update_work, bms_update_work); INIT_WORK(&chg->rdstd_cc2_detach_work, rdstd_cc2_detach_work); INIT_DELAYED_WORK(&chg->hvdcp_detect_work, smblib_hvdcp_detect_work); INIT_DELAYED_WORK(&chg->step_soc_req_work, step_soc_req_work); INIT_DELAYED_WORK(&chg->clear_hdc_work, clear_hdc_work); + INIT_WORK(&chg->otg_oc_work, smblib_otg_oc_work); + INIT_WORK(&chg->vconn_oc_work, smblib_vconn_oc_work); + INIT_DELAYED_WORK(&chg->otg_ss_done_work, smblib_otg_ss_done_work); chg->fake_capacity = -EINVAL; switch (chg->mode) { diff --git a/drivers/power/supply/qcom/smb-lib.h b/drivers/power/supply/qcom/smb-lib.h index b3fce23c6508..cda4b80939ec 100644 --- a/drivers/power/supply/qcom/smb-lib.h +++ b/drivers/power/supply/qcom/smb-lib.h @@ -24,6 +24,7 @@ enum print_reason { PR_REGISTER = BIT(1), PR_MISC = BIT(2), PR_PARALLEL = BIT(3), + PR_OTG = BIT(4), }; #define DEFAULT_VOTER "DEFAULT_VOTER" @@ -135,6 +136,9 @@ struct smb_iio { struct iio_channel *usbin_i_chan; struct iio_channel *usbin_v_chan; struct iio_channel *batt_i_chan; + struct iio_channel *connector_temp_thr1_chan; + struct iio_channel *connector_temp_thr2_chan; + struct iio_channel *connector_temp_thr3_chan; }; struct reg_info { @@ -158,7 +162,7 @@ struct smb_charger { /* locks */ struct mutex write_lock; struct mutex ps_change_lock; - struct mutex otg_overcurrent_lock; + struct mutex otg_oc_lock; /* power supplies */ struct power_supply *batt_psy; @@ -204,6 +208,9 @@ struct smb_charger { struct delayed_work ps_change_timeout_work; struct delayed_work step_soc_req_work; struct delayed_work clear_hdc_work; + struct work_struct otg_oc_work; + struct work_struct vconn_oc_work; + struct delayed_work otg_ss_done_work; /* cached status */ int voltage_min_uv; @@ -214,7 +221,6 @@ struct smb_charger { int system_temp_level; int thermal_levels; int *thermal_mitigation; - int otg_cl_ua; int dcp_icl_ua; int fake_capacity; bool step_chg_enabled; @@ -360,6 +366,8 @@ int smblib_get_prop_charger_temp(struct smb_charger *chg, union power_supply_propval *val); int smblib_get_prop_charger_temp_max(struct smb_charger *chg, union power_supply_propval *val); +int smblib_get_prop_connector_therm_zone(struct smb_charger *chg, + union power_supply_propval *val); int smblib_set_prop_pd_current_max(struct smb_charger *chg, const union power_supply_propval *val); int smblib_set_prop_usb_current_max(struct smb_charger *chg, diff --git a/drivers/power/supply/qcom/smb-reg.h b/drivers/power/supply/qcom/smb-reg.h index 5f74e27c7978..b5de39de995a 100644 --- a/drivers/power/supply/qcom/smb-reg.h +++ b/drivers/power/supply/qcom/smb-reg.h @@ -366,7 +366,9 @@ enum { #define OTG_CURRENT_LIMIT_MASK GENMASK(2, 0) #define OTG_CFG_REG (OTG_BASE + 0x53) -#define OTG_RESERVED_MASK GENMASK(7, 4) +#define OTG_RESERVED_MASK GENMASK(7, 6) +#define DIS_OTG_ON_TLIM_BIT BIT(5) +#define QUICKSTART_OTG_FASTROLESWAP_BIT BIT(4) #define INCREASE_DFP_TIME_BIT BIT(3) #define ENABLE_OTG_IN_DEBUG_MODE_BIT BIT(2) #define OTG_EN_SRC_CFG_BIT BIT(1) @@ -793,6 +795,10 @@ enum { ZIN_ICL_HV_MAX_MV = 11000, }; +#define DC_ENG_SSUPPLY_CFG2_REG (DCIN_BASE + 0xC1) +#define ENG_SSUPPLY_IVREF_OTG_SS_MASK GENMASK(2, 0) +#define OTG_SS_SLOW 0x3 + #define DC_ENG_SSUPPLY_CFG3_REG (DCIN_BASE + 0xC2) #define ENG_SSUPPLY_HI_CAP_BIT BIT(6) #define ENG_SSUPPLY_HI_RES_BIT BIT(5) @@ -817,6 +823,8 @@ enum { #define TEMP_RANGE_STATUS_7_BIT BIT(7) #define THERM_REG_ACTIVE_BIT BIT(6) #define TLIM_BIT BIT(5) +#define TEMP_RANGE_MASK GENMASK(4, 1) +#define TEMP_RANGE_SHIFT 1 #define ALERT_LEVEL_BIT BIT(4) #define TEMP_ABOVE_RANGE_BIT BIT(3) #define TEMP_WITHIN_RANGE_BIT BIT(2) diff --git a/drivers/power/supply/qcom/smb138x-charger.c b/drivers/power/supply/qcom/smb138x-charger.c index ae15fef6c3a6..9287b7c37b97 100644 --- a/drivers/power/supply/qcom/smb138x-charger.c +++ b/drivers/power/supply/qcom/smb138x-charger.c @@ -10,18 +10,21 @@ * GNU General Public License for more details. */ +#define pr_fmt(fmt) "SMB138X: %s: " fmt, __func__ + #include <linux/device.h> -#include <linux/module.h> -#include <linux/platform_device.h> -#include <linux/regmap.h> -#include <linux/power_supply.h> +#include <linux/iio/consumer.h> #include <linux/interrupt.h> +#include <linux/module.h> #include <linux/of.h> #include <linux/of_device.h> #include <linux/of_irq.h> +#include <linux/platform_device.h> +#include <linux/power_supply.h> +#include <linux/regmap.h> #include <linux/regulator/driver.h> -#include <linux/regulator/of_regulator.h> #include <linux/regulator/machine.h> +#include <linux/regulator/of_regulator.h> #include <linux/qpnp/qpnp-revid.h> #include "smb-reg.h" #include "smb-lib.h" @@ -89,6 +92,8 @@ struct smb_dt_props { int fcc_ua; int usb_icl_ua; int dc_icl_ua; + int chg_temp_max_mdegc; + int connector_temp_max_mdegc; }; struct smb138x { @@ -132,6 +137,18 @@ static int smb138x_parse_dt(struct smb138x *chip) if (rc < 0) chip->dt.dc_icl_ua = SMB138X_DEFAULT_ICL_UA; + rc = of_property_read_u32(node, + "qcom,charger-temp-max-mdegc", + &chip->dt.chg_temp_max_mdegc); + if (rc < 0) + chip->dt.chg_temp_max_mdegc = 80000; + + rc = of_property_read_u32(node, + "qcom,connector-temp-max-mdegc", + &chip->dt.chg_temp_max_mdegc); + if (rc < 0) + chip->dt.connector_temp_max_mdegc = 105000; + return 0; } @@ -415,6 +432,7 @@ static enum power_supply_property smb138x_parallel_props[] = { POWER_SUPPLY_PROP_CHARGER_TEMP_MAX, POWER_SUPPLY_PROP_MODEL_NAME, POWER_SUPPLY_PROP_PARALLEL_MODE, + POWER_SUPPLY_PROP_CONNECTOR_THERM_ZONE, }; static int smb138x_parallel_get_prop(struct power_supply *psy, @@ -467,6 +485,9 @@ static int smb138x_parallel_get_prop(struct power_supply *psy, case POWER_SUPPLY_PROP_PARALLEL_MODE: val->intval = POWER_SUPPLY_PARALLEL_MID_MID; break; + case POWER_SUPPLY_PROP_CONNECTOR_THERM_ZONE: + rc = smblib_get_prop_connector_therm_zone(chg, val); + break; default: pr_err("parallel power supply get prop %d not supported\n", prop); @@ -658,6 +679,138 @@ static int smb138x_init_vconn_regulator(struct smb138x *chip) * HARDWARE INITIALIZATION * ***************************/ +#define MDEGC_3 3000 +#define MDEGC_15 15000 +static int smb138x_init_slave_hw(struct smb138x *chip) +{ + struct smb_charger *chg = &chip->chg; + int rc; + + if (chip->wa_flags & OOB_COMP_WA_BIT) { + rc = smblib_masked_write(chg, SMB2CHG_MISC_ENG_SDCDC_CFG2, + ENG_SDCDC_SEL_OOB_VTH_BIT, + ENG_SDCDC_SEL_OOB_VTH_BIT); + if (rc < 0) { + pr_err("Couldn't configure the OOB comp threshold rc = %d\n", + rc); + return rc; + } + + rc = smblib_masked_write(chg, SMB2CHG_MISC_ENG_SDCDC_CFG6, + DEAD_TIME_MASK, HIGH_DEAD_TIME_MASK); + if (rc < 0) { + pr_err("Couldn't configure the sdcdc cfg 6 reg rc = %d\n", + rc); + return rc; + } + } + + /* enable watchdog bark and bite interrupts, and disable the watchdog */ + rc = smblib_masked_write(chg, WD_CFG_REG, WDOG_TIMER_EN_BIT + | WDOG_TIMER_EN_ON_PLUGIN_BIT | BITE_WDOG_INT_EN_BIT + | BARK_WDOG_INT_EN_BIT, + BITE_WDOG_INT_EN_BIT | BARK_WDOG_INT_EN_BIT); + if (rc < 0) { + pr_err("Couldn't configure the watchdog rc=%d\n", rc); + return rc; + } + + /* disable charging when watchdog bites */ + rc = smblib_masked_write(chg, SNARL_BARK_BITE_WD_CFG_REG, + BITE_WDOG_DISABLE_CHARGING_CFG_BIT, + BITE_WDOG_DISABLE_CHARGING_CFG_BIT); + if (rc < 0) { + pr_err("Couldn't configure the watchdog bite rc=%d\n", rc); + return rc; + } + + /* suspend parallel charging */ + rc = smb138x_set_parallel_suspend(chip, true); + if (rc < 0) { + pr_err("Couldn't suspend parallel charging rc=%d\n", rc); + return rc; + } + + /* initialize FCC to 0 */ + rc = smblib_set_charge_param(chg, &chg->param.fcc, 0); + if (rc < 0) { + pr_err("Couldn't set 0 FCC rc=%d\n", rc); + return rc; + } + + /* enable the charging path */ + rc = smblib_masked_write(chg, CHARGING_ENABLE_CMD_REG, + CHARGING_ENABLE_CMD_BIT, + CHARGING_ENABLE_CMD_BIT); + if (rc < 0) { + pr_err("Couldn't enable charging rc=%d\n", rc); + return rc; + } + + /* configure charge enable for software control; active high */ + rc = smblib_masked_write(chg, CHGR_CFG2_REG, + CHG_EN_POLARITY_BIT | CHG_EN_SRC_BIT, 0); + if (rc < 0) { + pr_err("Couldn't configure charge enable source rc=%d\n", + rc); + return rc; + } + + /* enable parallel current sensing */ + rc = smblib_masked_write(chg, CFG_REG, + VCHG_EN_CFG_BIT, VCHG_EN_CFG_BIT); + if (rc < 0) { + pr_err("Couldn't enable parallel current sensing rc=%d\n", + rc); + return rc; + } + + /* enable stacked diode */ + rc = smblib_write(chg, SMB2CHG_DC_TM_SREFGEN, STACKED_DIODE_EN_BIT); + if (rc < 0) { + pr_err("Couldn't enable stacked diode rc=%d\n", rc); + return rc; + } + + /* initialize charger temperature threshold */ + rc = iio_write_channel_processed(chg->iio.temp_max_chan, + chip->dt.chg_temp_max_mdegc); + if (rc < 0) { + pr_err("Couldn't set charger temp threshold rc=%d\n", rc); + return rc; + } + + rc = iio_write_channel_processed(chg->iio.connector_temp_thr1_chan, + chip->dt.connector_temp_max_mdegc); + if (rc < 0) { + pr_err("Couldn't set connector temp threshold1 rc=%d\n", rc); + return rc; + } + + rc = iio_write_channel_processed(chg->iio.connector_temp_thr2_chan, + chip->dt.connector_temp_max_mdegc + MDEGC_3); + if (rc < 0) { + pr_err("Couldn't set connector temp threshold2 rc=%d\n", rc); + return rc; + } + + rc = iio_write_channel_processed(chg->iio.connector_temp_thr3_chan, + chip->dt.connector_temp_max_mdegc + MDEGC_15); + if (rc < 0) { + pr_err("Couldn't set connector temp threshold3 rc=%d\n", rc); + return rc; + } + + rc = smblib_write(chg, THERMREG_SRC_CFG_REG, + THERMREG_SKIN_ADC_SRC_EN_BIT); + if (rc < 0) { + pr_err("Couldn't enable connector thermreg source rc=%d\n", rc); + return rc; + } + + return 0; +} + static int smb138x_init_hw(struct smb138x *chip) { struct smb_charger *chg = &chip->chg; @@ -681,15 +834,14 @@ static int smb138x_init_hw(struct smb138x *chip) rc = smblib_masked_write(chg, CHGR_CFG2_REG, CHG_EN_POLARITY_BIT | CHG_EN_SRC_BIT, 0); if (rc < 0) { - dev_err(chg->dev, - "Couldn't configure charge enable source rc=%d\n", rc); + pr_err("Couldn't configure charge enable source rc=%d\n", rc); return rc; } /* enable the charging path */ rc = vote(chg->chg_disable_votable, DEFAULT_VOTER, false, 0); if (rc < 0) { - dev_err(chg->dev, "Couldn't enable charging rc=%d\n", rc); + pr_err("Couldn't enable charging rc=%d\n", rc); return rc; } @@ -701,8 +853,7 @@ static int smb138x_init_hw(struct smb138x *chip) TYPEC_CCSTATE_CHANGE_INT_EN_BIT | TYPEC_VBUS_ERROR_INT_EN_BIT); if (rc < 0) { - dev_err(chg->dev, - "Couldn't configure Type-C interrupts rc=%d\n", rc); + pr_err("Couldn't configure Type-C interrupts rc=%d\n", rc); return rc; } @@ -711,16 +862,14 @@ static int smb138x_init_hw(struct smb138x *chip) VCONN_EN_SRC_BIT | VCONN_EN_VALUE_BIT, VCONN_EN_SRC_BIT); if (rc < 0) { - dev_err(chg->dev, - "Couldn't configure VCONN for SW control rc=%d\n", rc); + pr_err("Couldn't configure VCONN for SW control rc=%d\n", rc); return rc; } /* configure VBUS for software control */ rc = smblib_masked_write(chg, OTG_CFG_REG, OTG_EN_SRC_CFG_BIT, 0); if (rc < 0) { - dev_err(chg->dev, - "Couldn't configure VBUS for SW control rc=%d\n", rc); + pr_err("Couldn't configure VBUS for SW control rc=%d\n", rc); return rc; } @@ -728,8 +877,7 @@ static int smb138x_init_hw(struct smb138x *chip) rc = smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG, TYPEC_POWER_ROLE_CMD_MASK, 0); if (rc < 0) { - dev_err(chg->dev, - "Couldn't configure power role for DRP rc=%d\n", rc); + pr_err("Couldn't configure power role for DRP rc=%d\n", rc); return rc; } @@ -738,16 +886,16 @@ static int smb138x_init_hw(struct smb138x *chip) ENG_SDCDC_SEL_OOB_VTH_BIT, ENG_SDCDC_SEL_OOB_VTH_BIT); if (rc < 0) { - dev_err(chg->dev, - "Couldn't configure the oob comp threh rc = %d\n", rc); + pr_err("Couldn't configure the OOB comp threshold rc = %d\n", + rc); return rc; } rc = smblib_masked_write(chg, SMB2CHG_MISC_ENG_SDCDC_CFG6, DEAD_TIME_MASK, HIGH_DEAD_TIME_MASK); if (rc < 0) { - dev_err(chg->dev, - "Couldn't configure the sdcdc cfg 6 reg rc = %d\n", rc); + pr_err("Couldn't configure the sdcdc cfg 6 reg rc = %d\n", + rc); return rc; } } @@ -795,6 +943,23 @@ static int smb138x_setup_wa_flags(struct smb138x *chip) * DETERMINE INITIAL STATUS * ****************************/ +static irqreturn_t smb138x_handle_temperature_change(int irq, void *data) +{ + struct smb_irq_data *irq_data = data; + struct smb138x *chip = irq_data->parent_data; + + power_supply_changed(chip->parallel_psy); + return IRQ_HANDLED; +} + +static int smb138x_determine_initial_slave_status(struct smb138x *chip) +{ + struct smb_irq_data irq_data = {chip, "determine-initial-status"}; + + smb138x_handle_temperature_change(0, &irq_data); + return 0; +} + static int smb138x_determine_initial_status(struct smb138x *chip) { struct smb_irq_data irq_data = {chip, "determine-initial-status"}; @@ -802,7 +967,6 @@ static int smb138x_determine_initial_status(struct smb138x *chip) smblib_handle_usb_plugin(0, &irq_data); smblib_handle_usb_typec_change(0, &irq_data); smblib_handle_usb_source_change(0, &irq_data); - return 0; } @@ -971,7 +1135,7 @@ static const struct smb138x_irq_info smb138x_irqs[] = { }, { .name = "temperature-change", - .handler = smblib_handle_debug, + .handler = smb138x_handle_temperature_change, }, { .name = "switcher-power-ok", @@ -1144,95 +1308,54 @@ static int smb138x_slave_probe(struct smb138x *chip) goto cleanup; } - if (chip->wa_flags & OOB_COMP_WA_BIT) { - rc = smblib_masked_write(chg, SMB2CHG_MISC_ENG_SDCDC_CFG2, - ENG_SDCDC_SEL_OOB_VTH_BIT, - ENG_SDCDC_SEL_OOB_VTH_BIT); - if (rc < 0) { - dev_err(chg->dev, - "Couldn't configure the oob comp threh rc = %d\n", rc); - goto cleanup; - } - - rc = smblib_masked_write(chg, SMB2CHG_MISC_ENG_SDCDC_CFG6, - DEAD_TIME_MASK, HIGH_DEAD_TIME_MASK); - if (rc < 0) { - dev_err(chg->dev, - "Couldn't configure the sdcdc cfg 6 reg rc = %d\n", rc); - goto cleanup; - } - } - - /* enable watchdog bark and bite interrupts, and disable the watchdog */ - rc = smblib_masked_write(chg, WD_CFG_REG, WDOG_TIMER_EN_BIT - | WDOG_TIMER_EN_ON_PLUGIN_BIT | BITE_WDOG_INT_EN_BIT - | BARK_WDOG_INT_EN_BIT, - BITE_WDOG_INT_EN_BIT | BARK_WDOG_INT_EN_BIT); - if (rc < 0) { - pr_err("Couldn't configure the watchdog rc=%d\n", rc); + chg->iio.temp_max_chan = iio_channel_get(chg->dev, "charger_temp_max"); + if (IS_ERR(chg->iio.temp_max_chan)) { + rc = PTR_ERR(chg->iio.temp_max_chan); goto cleanup; } - /* disable charging when watchdog bites */ - rc = smblib_masked_write(chg, SNARL_BARK_BITE_WD_CFG_REG, - BITE_WDOG_DISABLE_CHARGING_CFG_BIT, - BITE_WDOG_DISABLE_CHARGING_CFG_BIT); - if (rc < 0) { - pr_err("Couldn't configure the watchdog bite rc=%d\n", rc); + chg->iio.connector_temp_thr1_chan = iio_channel_get(chg->dev, + "connector_temp_thr1"); + if (IS_ERR(chg->iio.connector_temp_thr1_chan)) { + rc = PTR_ERR(chg->iio.connector_temp_thr1_chan); goto cleanup; } - /* suspend parallel charging */ - rc = smb138x_set_parallel_suspend(chip, true); - if (rc < 0) { - pr_err("Couldn't suspend parallel charging rc=%d\n", rc); + chg->iio.connector_temp_thr2_chan = iio_channel_get(chg->dev, + "connector_temp_thr2"); + if (IS_ERR(chg->iio.connector_temp_thr2_chan)) { + rc = PTR_ERR(chg->iio.connector_temp_thr2_chan); goto cleanup; } - /* initialize FCC to 0 */ - rc = smblib_set_charge_param(chg, &chg->param.fcc, 0); - if (rc < 0) { - pr_err("Couldn't set 0 FCC rc=%d\n", rc); + chg->iio.connector_temp_thr3_chan = iio_channel_get(chg->dev, + "connector_temp_thr3"); + if (IS_ERR(chg->iio.connector_temp_thr3_chan)) { + rc = PTR_ERR(chg->iio.connector_temp_thr3_chan); goto cleanup; } - /* enable the charging path */ - rc = smblib_masked_write(chg, CHARGING_ENABLE_CMD_REG, - CHARGING_ENABLE_CMD_BIT, - CHARGING_ENABLE_CMD_BIT); + rc = smb138x_parse_dt(chip); if (rc < 0) { - dev_err(chg->dev, "Couldn't enable charging rc=%d\n", rc); + pr_err("Couldn't parse device tree rc=%d\n", rc); goto cleanup; } - /* configure charge enable for software control; active high */ - rc = smblib_masked_write(chg, CHGR_CFG2_REG, - CHG_EN_POLARITY_BIT | CHG_EN_SRC_BIT, 0); + rc = smb138x_init_slave_hw(chip); if (rc < 0) { - dev_err(chg->dev, "Couldn't configure charge enable source rc=%d\n", - rc); + pr_err("Couldn't initialize hardware rc=%d\n", rc); goto cleanup; } - /* enable parallel current sensing */ - rc = smblib_masked_write(chg, CFG_REG, - VCHG_EN_CFG_BIT, VCHG_EN_CFG_BIT); + rc = smb138x_init_parallel_psy(chip); if (rc < 0) { - dev_err(chg->dev, "Couldn't enable parallel current sensing rc=%d\n", - rc); + pr_err("Couldn't initialize parallel psy rc=%d\n", rc); goto cleanup; } - /* enable stacked diode */ - rc = smblib_write(chg, SMB2CHG_DC_TM_SREFGEN, STACKED_DIODE_EN_BIT); + rc = smb138x_determine_initial_slave_status(chip); if (rc < 0) { - pr_err("Couldn't enable stacked diode rc=%d\n", rc); - return rc; - } - - rc = smb138x_init_parallel_psy(chip); - if (rc < 0) { - pr_err("Couldn't initialize parallel psy rc=%d\n", rc); + pr_err("Couldn't determine initial status rc=%d\n", rc); goto cleanup; } @@ -1312,6 +1435,12 @@ static int smb138x_probe(struct platform_device *pdev) goto cleanup; } + if (rc < 0) { + if (rc != -EPROBE_DEFER) + pr_err("Couldn't probe SMB138X rc=%d\n", rc); + goto cleanup; + } + pr_info("SMB138X probed successfully mode=%d\n", chip->chg.mode); return rc; diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig index 40e1afdfc286..b5e44b237ed8 100644 --- a/drivers/pwm/Kconfig +++ b/drivers/pwm/Kconfig @@ -310,13 +310,14 @@ config PWM_RCAR will be called pwm-rcar. config PWM_QPNP + tristate "Qualcomm Technologies, Inc. QPNP LPG/PWM support" depends on SPMI - tristate "Qualcomm QPNP LPG/PWM support" - help - This driver supports PWM/LPG devices in Qualcomm PMIC chips which - comply with QPNP. QPNP is a SPMI based PMIC implementation. These - devices support Pulse Width Modulation output with user generated - patterns. They share a lookup table with size of 64 entries. + help + This driver supports PWM/LPG devices in Qualcomm Technologies, Inc. + PMIC chips which comply with QPNP. QPNP is an SPMI based PMIC + implementation. These devices support Pulse Width Modulation output + with user generated patterns. They share a lookup table with size of + 64 entries. config PWM_RENESAS_TPU tristate "Renesas TPU PWM support" diff --git a/drivers/pwm/pwm-qpnp.c b/drivers/pwm/pwm-qpnp.c index 6d0c1fbe566b..d57bf2f3b80c 100644 --- a/drivers/pwm/pwm-qpnp.c +++ b/drivers/pwm/pwm-qpnp.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2017, 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,7 +10,7 @@ * GNU General Public License for more details. */ /* - * Qualcomm QPNP Pulse Width Modulation (PWM) driver + * Qualcomm Technologies, Inc. QPNP Pulse Width Modulation (PWM) driver * * The HW module is also called LPG (Light Pattern Generator). */ @@ -382,6 +382,7 @@ static int qpnp_set_control(struct qpnp_pwm_chip *chip, bool pwm_hi, bool pwm_lo, bool pwm_out, bool pwm_src, bool ramp_gen) { int value; + value = (ramp_gen << QPNP_PWM_EN_RAMP_GEN_SHIFT) | (pwm_src << QPNP_PWM_SRC_SELECT_SHIFT) | (pwm_lo << QPNP_EN_PWM_LO_SHIFT) | @@ -476,7 +477,7 @@ static void qpnp_lpg_calc_period(enum time_level tm_lvl, n = 6; if (tm_lvl == LVL_USEC) { - if (period_value < ((unsigned)(-1) / NSEC_PER_USEC)) { + if (period_value < ((unsigned int)(-1) / NSEC_PER_USEC)) { period_n = (period_value * NSEC_PER_USEC) >> n; } else { if (supported_sizes == QPNP_PWM_SIZE_7_8_BIT) @@ -499,7 +500,7 @@ static void qpnp_lpg_calc_period(enum time_level tm_lvl, chip->channel_id, n); } - min_err = last_err = (unsigned)(-1); + min_err = last_err = (unsigned int)(-1); best_m = 0; best_clk = 0; best_div = 0; @@ -1233,7 +1234,7 @@ static int _pwm_config(struct qpnp_pwm_chip *chip, } pr_debug("duty/period=%u/%u %s: pwm_value=%d (of %d)\n", - (unsigned)duty_value, (unsigned)period_value, + (unsigned int)duty_value, (unsigned int)period_value, (tm_lvl == LVL_USEC) ? "usec" : "nsec", pwm_config->pwm_value, 1 << period->pwm_size); @@ -1290,7 +1291,7 @@ after_table_write: QPNP_SET_PAUSE_CNT(lut_config->lut_pause_hi_cnt, lut_params.lut_pause_hi, ramp_step_ms); if (lut_config->lut_pause_hi_cnt > PM_PWM_MAX_PAUSE_CNT) - lut_config->lut_pause_hi_cnt = PM_PWM_MAX_PAUSE_CNT; + lut_config->lut_pause_hi_cnt = PM_PWM_MAX_PAUSE_CNT; lut_config->ramp_step_ms = ramp_step_ms; @@ -1320,8 +1321,7 @@ static int _pwm_enable(struct qpnp_pwm_chip *chip) chip->flags & QPNP_PWM_LUT_NOT_SUPPORTED) { rc = qpnp_lpg_configure_pwm_state(chip, QPNP_PWM_ENABLE); } else if (!(chip->flags & QPNP_PWM_LUT_NOT_SUPPORTED)) { - rc = qpnp_lpg_configure_lut_state(chip, - QPNP_LUT_ENABLE); + rc = qpnp_lpg_configure_lut_state(chip, QPNP_LUT_ENABLE); } if (!rc) @@ -1368,7 +1368,7 @@ static int qpnp_pwm_config(struct pwm_chip *pwm_chip, struct qpnp_pwm_chip *chip = qpnp_pwm_from_pwm_chip(pwm_chip); int prev_period_us = chip->pwm_config.pwm_period; - if ((unsigned)period_ns < PM_PWM_PERIOD_MIN * NSEC_PER_USEC) { + if ((unsigned int)period_ns < PM_PWM_PERIOD_MIN * NSEC_PER_USEC) { pr_err("Invalid pwm handle or parameters\n"); return -EINVAL; } @@ -1403,6 +1403,7 @@ static int qpnp_pwm_enable(struct pwm_chip *pwm_chip, { int rc; struct qpnp_pwm_chip *chip = qpnp_pwm_from_pwm_chip(pwm_chip); + rc = _pwm_enable(chip); if (rc) pr_err("Failed to enable PWM channel: %d\n", chip->channel_id); @@ -1487,7 +1488,7 @@ int pwm_change_mode(struct pwm_device *pwm, enum pm_pwm_mode mode) return rc; } -EXPORT_SYMBOL_GPL(pwm_change_mode); +EXPORT_SYMBOL(pwm_change_mode); /** * pwm_config_period - change PWM period @@ -1592,7 +1593,7 @@ out_unlock: spin_unlock_irqrestore(&chip->lpg_lock, flags); return rc; } -EXPORT_SYMBOL_GPL(pwm_config_pwm_value); +EXPORT_SYMBOL(pwm_config_pwm_value); /** * pwm_config_us - change a PWM device configuration @@ -1608,8 +1609,8 @@ int pwm_config_us(struct pwm_device *pwm, int duty_us, int period_us) if (pwm == NULL || IS_ERR(pwm) || duty_us > period_us || - (unsigned)period_us > PM_PWM_PERIOD_MAX || - (unsigned)period_us < PM_PWM_PERIOD_MIN) { + (unsigned int)period_us > PM_PWM_PERIOD_MAX || + (unsigned int)period_us < PM_PWM_PERIOD_MIN) { pr_err("Invalid pwm handle or parameters\n"); return -EINVAL; } @@ -1622,10 +1623,11 @@ int pwm_config_us(struct pwm_device *pwm, int duty_us, int period_us) qpnp_lpg_calc_period(LVL_USEC, period_us, chip); qpnp_lpg_save_period(chip); chip->pwm_config.pwm_period = period_us; - if ((unsigned)period_us > (unsigned)(-1) / NSEC_PER_USEC) + if ((unsigned int)period_us > + (unsigned int)(-1) / NSEC_PER_USEC) pwm->period = 0; else - pwm->period = (unsigned)period_us * NSEC_PER_USEC; + pwm->period = (unsigned int)period_us * NSEC_PER_USEC; } rc = _pwm_config(chip, LVL_USEC, duty_us, period_us); @@ -1679,8 +1681,8 @@ int pwm_lut_config(struct pwm_device *pwm, int period_us, return -EINVAL; } - if ((unsigned)period_us > PM_PWM_PERIOD_MAX || - (unsigned)period_us < PM_PWM_PERIOD_MIN) { + if ((unsigned int)period_us > PM_PWM_PERIOD_MAX || + (unsigned int)period_us < PM_PWM_PERIOD_MIN) { pr_err("Period out of range\n"); return -EINVAL; } @@ -1702,7 +1704,7 @@ int pwm_lut_config(struct pwm_device *pwm, int period_us, return rc; } -EXPORT_SYMBOL_GPL(pwm_lut_config); +EXPORT_SYMBOL(pwm_lut_config); static int qpnp_parse_pwm_dt_config(struct device_node *of_pwm_node, struct device_node *of_parent, struct qpnp_pwm_chip *chip) @@ -1738,14 +1740,6 @@ static int qpnp_parse_pwm_dt_config(struct device_node *of_pwm_node, return rc; } -#define qpnp_check_optional_dt_bindings(func) \ -do { \ - rc = func; \ - if (rc && rc != -EINVAL) \ - goto out; \ - rc = 0; \ -} while (0) - static int qpnp_parse_lpg_dt_config(struct device_node *of_lpg_node, struct device_node *of_parent, struct qpnp_pwm_chip *chip) { @@ -1778,44 +1772,58 @@ static int qpnp_parse_lpg_dt_config(struct device_node *of_lpg_node, return -EINVAL; } - duty_pct_list = kzalloc(sizeof(u32) * list_size, GFP_KERNEL); - - if (!duty_pct_list) { - pr_err("kzalloc failed on duty_pct_list\n"); + duty_pct_list = kcalloc(list_size, sizeof(*duty_pct_list), GFP_KERNEL); + if (!duty_pct_list) return -ENOMEM; - } rc = of_property_read_u32_array(of_lpg_node, "qcom,duty-percents", duty_pct_list, list_size); if (rc) { - pr_err("invalid or missing property:\n"); - pr_err("qcom,duty-pcts-list\n"); - kfree(duty_pct_list); - return rc; + pr_err("invalid or missing property: qcom,duty-pcts-list\n"); + goto out; } /* Read optional properties */ - qpnp_check_optional_dt_bindings(of_property_read_u32(of_lpg_node, - "qcom,ramp-step-duration", &lut_config->ramp_step_ms)); - qpnp_check_optional_dt_bindings(of_property_read_u32(of_lpg_node, - "qcom,lpg-lut-pause-hi", &lut_config->lut_pause_hi_cnt)); - qpnp_check_optional_dt_bindings(of_property_read_u32(of_lpg_node, - "qcom,lpg-lut-pause-lo", &lut_config->lut_pause_lo_cnt)); - qpnp_check_optional_dt_bindings(of_property_read_u32(of_lpg_node, - "qcom,lpg-lut-ramp-direction", - (u32 *)&lut_config->ramp_direction)); - qpnp_check_optional_dt_bindings(of_property_read_u32(of_lpg_node, - "qcom,lpg-lut-pattern-repeat", - (u32 *)&lut_config->pattern_repeat)); - qpnp_check_optional_dt_bindings(of_property_read_u32(of_lpg_node, - "qcom,lpg-lut-ramp-toggle", - (u32 *)&lut_config->ramp_toggle)); - qpnp_check_optional_dt_bindings(of_property_read_u32(of_lpg_node, - "qcom,lpg-lut-enable-pause-hi", - (u32 *)&lut_config->enable_pause_hi)); - qpnp_check_optional_dt_bindings(of_property_read_u32(of_lpg_node, - "qcom,lpg-lut-enable-pause-lo", - (u32 *)&lut_config->enable_pause_lo)); + rc = of_property_read_u32(of_lpg_node, "qcom,ramp-step-duration", + &lut_config->ramp_step_ms); + if (rc && rc != -EINVAL) + goto out; + + rc = of_property_read_u32(of_lpg_node, "qcom,lpg-lut-pause-hi", + &lut_config->lut_pause_hi_cnt); + if (rc && rc != -EINVAL) + goto out; + + rc = of_property_read_u32(of_lpg_node, "qcom,lpg-lut-pause-lo", + &lut_config->lut_pause_lo_cnt); + if (rc && rc != -EINVAL) + goto out; + + rc = of_property_read_u32(of_lpg_node, "qcom,lpg-lut-ramp-direction", + (u32 *)&lut_config->ramp_direction); + if (rc && rc != -EINVAL) + goto out; + + rc = of_property_read_u32(of_lpg_node, "qcom,lpg-lut-pattern-repeat", + (u32 *)&lut_config->pattern_repeat); + if (rc && rc != -EINVAL) + goto out; + + rc = of_property_read_u32(of_lpg_node, "qcom,lpg-lut-ramp-toggle", + (u32 *)&lut_config->ramp_toggle); + if (rc && rc != -EINVAL) + goto out; + + rc = of_property_read_u32(of_lpg_node, "qcom,lpg-lut-enable-pause-hi", + (u32 *)&lut_config->enable_pause_hi); + if (rc && rc != -EINVAL) + goto out; + + rc = of_property_read_u32(of_lpg_node, "qcom,lpg-lut-enable-pause-lo", + (u32 *)&lut_config->enable_pause_lo); + if (rc && rc != -EINVAL) + goto out; + rc = 0; qpnp_set_lut_params(&lut_params, lut_config, start_idx, list_size); @@ -1877,7 +1885,7 @@ static int qpnp_parse_dt_config(struct platform_device *pdev, struct qpnp_pwm_chip *chip) { int rc, enable, lut_entry_size, list_size, i; - const char *lable; + const char *label; const __be32 *prop; u32 size; struct device_node *node; @@ -1992,12 +2000,10 @@ static int qpnp_parse_dt_config(struct platform_device *pdev, lut_entry_size = sizeof(u8); } - lut_config->duty_pct_list = kzalloc(lpg_config->lut_size * + lut_config->duty_pct_list = kcalloc(lpg_config->lut_size, lut_entry_size, GFP_KERNEL); - if (!lut_config->duty_pct_list) { - pr_err("can not allocate duty pct list\n"); + if (!lut_config->duty_pct_list) return -ENOMEM; - } rc = of_property_read_u32(of_node, "qcom,ramp-index", &lut_config->ramp_index); @@ -2038,18 +2044,18 @@ static int qpnp_parse_dt_config(struct platform_device *pdev, } for_each_child_of_node(of_node, node) { - rc = of_property_read_string(node, "label", &lable); + rc = of_property_read_string(node, "label", &label); if (rc) { - dev_err(&pdev->dev, "%s: Missing lable property\n", + dev_err(&pdev->dev, "%s: Missing label property\n", __func__); goto out; } - if (!strncmp(lable, "pwm", 3)) { + if (!strcmp(label, "pwm")) { rc = qpnp_parse_pwm_dt_config(node, of_node, chip); if (rc) goto out; found_pwm_subnode = 1; - } else if (!strncmp(lable, "lpg", 3) && + } else if (!strcmp(label, "lpg") && !(chip->flags & QPNP_PWM_LUT_NOT_SUPPORTED)) { rc = qpnp_parse_lpg_dt_config(node, of_node, chip); if (rc) @@ -2102,10 +2108,9 @@ static int qpnp_pwm_probe(struct platform_device *pdev) int rc; pwm_chip = kzalloc(sizeof(*pwm_chip), GFP_KERNEL); - if (pwm_chip == NULL) { - pr_err("kzalloc() failed.\n"); + if (pwm_chip == NULL) return -ENOMEM; - } + pwm_chip->regmap = dev_get_regmap(pdev->dev.parent, NULL); if (!pwm_chip->regmap) { dev_err(&pdev->dev, "Couldn't get parent's regmap\n"); @@ -2169,7 +2174,7 @@ static int qpnp_pwm_remove(struct platform_device *pdev) return 0; } -static struct of_device_id spmi_match_table[] = { +static const struct of_device_id spmi_match_table[] = { { .compatible = QPNP_LPG_DRIVER_NAME, }, {} }; diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 8d54ece776e2..e5ba63171eba 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -807,42 +807,43 @@ config REGULATOR_RPM_SMD application processor over SMD. config REGULATOR_QPNP + tristate "Qualcomm Technologies, Inc. QPNP regulator support" depends on SPMI - tristate "Qualcomm QPNP regulator support" help - This driver supports voltage regulators in Qualcomm PMIC chips which - comply with QPNP. QPNP is a SPMI based PMIC implementation. These - chips provide several different varieties of LDO and switching - regulators. They also provide voltage switches and boost regulators. + This driver supports voltage regulators in Qualcomm Technologies, Inc. + PMIC chips which comply with QPNP. QPNP is a SPMI based PMIC + implementation. These chips provide several different varieties of + LDO and switching regulators. They also provide voltage switches and + boost regulators. config REGULATOR_QPNP_LABIBB + tristate "Qualcomm Technologies, Inc. QPNP LAB/IBB regulator support" depends on SPMI - tristate "Qualcomm Technologies, Inc QPNP LAB/IBB regulator support" help - This driver supports voltage regulators in Qualcomm Technologies, Inc + This driver supports voltage regulators in Qualcomm Technologies, Inc. PMIC chips which comply with QPNP LAB/IBB regulators. QPNP LAB and IBB - are SPMI based PMIC implementation. LAB regulator can be used as a + are SPMI based PMIC implementations. LAB regulator can be used as a regular positive boost regulator. IBB can be used as a regular negative boost regulator. LAB/IBB regulators can also be used together for LCD or AMOLED. config REGULATOR_QPNP_LCDB + tristate "Qualcomm Technologies, Inc. QPNP LCDB support" depends on SPMI - tristate "Qualcomm Technologies, Inc QPNP LCDB support" help - Supports the LCDB module in the Qualcomm Technologies, Inc - QPNP PMIC. Exposes regulators to control the positive and + Supports the LCDB module in the Qualcomm Technologies, Inc. + QPNP PMICs. Exposes regulators to control the positive and negative voltage bias for the LCD display panel. It also allows configurability for the various bias-voltage parameters. config REGULATOR_QPNP_OLEDB + tristate "Qualcomm Technologies, Inc. QPNP OLEDB regulator support" depends on SPMI - tristate "Qualcomm Technologies, Inc QPNP OLEDB regulator support" help - This driver supports the OLEDB(AVDD bias) signal for AMOLED panel in Qualcomm - Technologies, Inc QPNP PMIC. It exposes the OLED voltage configuration - via the regulator framework. The configurable range of this bias is - 5V to 8.1V. + This driver supports the OLEDB (AVDD bias) signal for AMOLED panel in + Qualcomm Technologies, Inc. QPNP PMICs. It exposes the OLED voltage + configuration via the regulator framework. The configurable range of + this bias is 5 V to 8.1 V. config REGULATOR_SPM bool "SPM regulator driver" @@ -950,19 +951,18 @@ config REGULATOR_KRYO depends on OF help Some MSM designs have CPUs that can be directly powered from a common - voltage rail via a Block Head Switch (BHS) or an LDO whose output voltage - can be configured for use when certain power constraints are met. - Say yes to support management of LDO and BHS modes for the clusters in the - CPU subsystem. + voltage rail via a Block Head Switch (BHS) or an LDO whose output + voltage can be configured for use when certain power constraints are + met. Say yes to support management of LDO and BHS modes for the + clusters in the CPU subsystem. config REGULATOR_MEM_ACC - tristate "QTI Memory accelerator regulator driver" - help - Say y here to enable the memory accelerator driver for Qualcomm - Technologies (QTI) chips. The accelerator controls delays applied - for memory accesses. - This driver configures the power-mode (corner) for the memory - accelerator. + tristate "QTI Memory accelerator regulator driver" + help + Say y here to enable the memory accelerator driver for Qualcomm + Technologies, Inc. (QTI) chips. The accelerator controls delays + applied for memory accesses. This driver configures the power-mode + (corner) for the memory accelerator. config REGULATOR_PROXY_CONSUMER bool "Boot time regulator proxy consumer support" diff --git a/drivers/regulator/cpr3-hmss-regulator.c b/drivers/regulator/cpr3-hmss-regulator.c index 091780525207..77e8bf4b9895 100644 --- a/drivers/regulator/cpr3-hmss-regulator.c +++ b/drivers/regulator/cpr3-hmss-regulator.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2017, 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 @@ -1232,7 +1232,7 @@ static int cpr3_hmss_kvreg_init(struct cpr3_regulator *vreg) scnprintf(kvreg_name_buf, MAX_VREG_NAME_SIZE, "vdd-thread%d-ldo-supply", id); - if (!of_find_property(ctrl->dev->of_node, kvreg_name_buf , NULL)) + if (!of_find_property(ctrl->dev->of_node, kvreg_name_buf, NULL)) return 0; else if (!of_find_property(node, "qcom,ldo-min-headroom-voltage", NULL)) return 0; @@ -1675,7 +1675,7 @@ static int cpr3_hmss_regulator_resume(struct platform_device *pdev) } /* Data corresponds to the SoC revision */ -static struct of_device_id cpr_regulator_match_table[] = { +static const struct of_device_id cpr_regulator_match_table[] = { { .compatible = "qcom,cpr3-msm8996-v1-hmss-regulator", .data = (void *)(uintptr_t)1 diff --git a/drivers/regulator/cpr3-mmss-regulator.c b/drivers/regulator/cpr3-mmss-regulator.c index 1070a34073e4..41032dd3c15a 100644 --- a/drivers/regulator/cpr3-mmss-regulator.c +++ b/drivers/regulator/cpr3-mmss-regulator.c @@ -1088,7 +1088,7 @@ static int cpr3_mmss_regulator_resume(struct platform_device *pdev) } /* Data corresponds to the SoC revision */ -static struct of_device_id cpr_regulator_match_table[] = { +static const struct of_device_id cpr_regulator_match_table[] = { { .compatible = "qcom,cpr3-msm8996-v1-mmss-regulator", .data = (void *)(uintptr_t)1, diff --git a/drivers/regulator/cpr3-regulator.c b/drivers/regulator/cpr3-regulator.c index 6775152f2623..c51ed182ba96 100644 --- a/drivers/regulator/cpr3-regulator.c +++ b/drivers/regulator/cpr3-regulator.c @@ -1622,8 +1622,6 @@ static void cpr3_regulator_set_target_quot(struct cpr3_thread *thread) } thread->last_closed_loop_aggr_corner = thread->aggr_corner; - - return; } /** @@ -1647,8 +1645,8 @@ static void cpr3_update_vreg_closed_loop_volt(struct cpr3_regulator *vreg, if (vreg->last_closed_loop_corner == CPR3_REGULATOR_CORNER_INVALID) return; - else - corner = &vreg->corner[vreg->last_closed_loop_corner]; + + corner = &vreg->corner[vreg->last_closed_loop_corner]; if (vreg->thread->last_closed_loop_aggr_corner.ro_mask == CPR3_RO_MASK || !vreg->aggregated) { @@ -4195,7 +4193,7 @@ static int cpr3_regulator_update_ctrl_state(struct cpr3_controller *ctrl) * Return: 0 on success, errno on failure */ static int cpr3_regulator_set_voltage(struct regulator_dev *rdev, - int corner, int corner_max, unsigned *selector) + int corner, int corner_max, unsigned int *selector) { struct cpr3_regulator *vreg = rdev_get_drvdata(rdev); struct cpr3_controller *ctrl = vreg->thread->ctrl; @@ -4264,7 +4262,7 @@ static int cpr3_regulator_get_voltage(struct regulator_dev *rdev) * Return: voltage corner value offset by CPR3_CORNER_OFFSET */ static int cpr3_regulator_list_voltage(struct regulator_dev *rdev, - unsigned selector) + unsigned int selector) { struct cpr3_regulator *vreg = rdev_get_drvdata(rdev); @@ -4964,11 +4962,11 @@ static struct dentry *debugfs_create_int(const char *name, umode_t mode, struct dentry *parent, int *value) { /* if there are no write bits set, make read only */ - if (!(mode & S_IWUGO)) + if (!(mode & 0222)) return debugfs_create_file(name, mode, parent, value, &fops_int_ro); /* if there are no read bits set, make write only */ - if (!(mode & S_IRUGO)) + if (!(mode & 0444)) return debugfs_create_file(name, mode, parent, value, &fops_int_wo); @@ -5225,21 +5223,21 @@ static void cpr3_regulator_debugfs_corner_add(struct cpr3_regulator *vreg, struct cpr3_debug_corner_info *info; struct dentry *temp; - temp = cpr3_debugfs_create_corner_int(vreg, "floor_volt", S_IRUGO, + temp = cpr3_debugfs_create_corner_int(vreg, "floor_volt", 0444, corner_dir, index, offsetof(struct cpr3_corner, floor_volt)); if (IS_ERR_OR_NULL(temp)) { cpr3_err(vreg, "floor_volt debugfs file creation failed\n"); return; } - temp = cpr3_debugfs_create_corner_int(vreg, "ceiling_volt", S_IRUGO, + temp = cpr3_debugfs_create_corner_int(vreg, "ceiling_volt", 0444, corner_dir, index, offsetof(struct cpr3_corner, ceiling_volt)); if (IS_ERR_OR_NULL(temp)) { cpr3_err(vreg, "ceiling_volt debugfs file creation failed\n"); return; } - temp = cpr3_debugfs_create_corner_int(vreg, "open_loop_volt", S_IRUGO, + temp = cpr3_debugfs_create_corner_int(vreg, "open_loop_volt", 0444, corner_dir, index, offsetof(struct cpr3_corner, open_loop_volt)); if (IS_ERR_OR_NULL(temp)) { @@ -5247,7 +5245,7 @@ static void cpr3_regulator_debugfs_corner_add(struct cpr3_regulator *vreg, return; } - temp = cpr3_debugfs_create_corner_int(vreg, "last_volt", S_IRUGO, + temp = cpr3_debugfs_create_corner_int(vreg, "last_volt", 0444, corner_dir, index, offsetof(struct cpr3_corner, last_volt)); if (IS_ERR_OR_NULL(temp)) { cpr3_err(vreg, "last_volt debugfs file creation failed\n"); @@ -5262,8 +5260,8 @@ static void cpr3_regulator_debugfs_corner_add(struct cpr3_regulator *vreg, info->index = index; info->corner = vreg->corner; - temp = debugfs_create_file("target_quots", S_IRUGO, corner_dir, - info, &cpr3_debug_quot_fops); + temp = debugfs_create_file("target_quots", 0444, corner_dir, info, + &cpr3_debug_quot_fops); if (IS_ERR_OR_NULL(temp)) { cpr3_err(vreg, "target_quots debugfs file creation failed\n"); return; @@ -5361,21 +5359,21 @@ static void cpr3_regulator_debugfs_vreg_add(struct cpr3_regulator *vreg, return; } - temp = debugfs_create_int("speed_bin_fuse", S_IRUGO, vreg_dir, + temp = debugfs_create_int("speed_bin_fuse", 0444, vreg_dir, &vreg->speed_bin_fuse); if (IS_ERR_OR_NULL(temp)) { cpr3_err(vreg, "speed_bin_fuse debugfs file creation failed\n"); return; } - temp = debugfs_create_int("cpr_rev_fuse", S_IRUGO, vreg_dir, + temp = debugfs_create_int("cpr_rev_fuse", 0444, vreg_dir, &vreg->cpr_rev_fuse); if (IS_ERR_OR_NULL(temp)) { cpr3_err(vreg, "cpr_rev_fuse debugfs file creation failed\n"); return; } - temp = debugfs_create_int("fuse_combo", S_IRUGO, vreg_dir, + temp = debugfs_create_int("fuse_combo", 0444, vreg_dir, &vreg->fuse_combo); if (IS_ERR_OR_NULL(temp)) { cpr3_err(vreg, "fuse_combo debugfs file creation failed\n"); @@ -5383,15 +5381,15 @@ static void cpr3_regulator_debugfs_vreg_add(struct cpr3_regulator *vreg, } if (vreg->ldo_regulator) { - temp = debugfs_create_file("ldo_mode", S_IRUGO, vreg_dir, - vreg, &cpr3_debug_ldo_mode_fops); + temp = debugfs_create_file("ldo_mode", 0444, vreg_dir, vreg, + &cpr3_debug_ldo_mode_fops); if (IS_ERR_OR_NULL(temp)) { cpr3_err(vreg, "ldo_mode debugfs file creation failed\n"); return; } temp = debugfs_create_file("ldo_mode_allowed", - S_IRUGO | S_IWUSR, vreg_dir, vreg, + 0644, vreg_dir, vreg, &cpr3_debug_ldo_mode_allowed_fops); if (IS_ERR_OR_NULL(temp)) { cpr3_err(vreg, "ldo_mode_allowed debugfs file creation failed\n"); @@ -5399,7 +5397,7 @@ static void cpr3_regulator_debugfs_vreg_add(struct cpr3_regulator *vreg, } } - temp = debugfs_create_int("corner_count", S_IRUGO, vreg_dir, + temp = debugfs_create_int("corner_count", 0444, vreg_dir, &vreg->corner_count); if (IS_ERR_OR_NULL(temp)) { cpr3_err(vreg, "corner_count debugfs file creation failed\n"); @@ -5412,8 +5410,8 @@ static void cpr3_regulator_debugfs_vreg_add(struct cpr3_regulator *vreg, return; } - temp = debugfs_create_file("index", S_IRUGO | S_IWUSR, corner_dir, - vreg, &cpr3_debug_corner_index_fops); + temp = debugfs_create_file("index", 0644, corner_dir, vreg, + &cpr3_debug_corner_index_fops); if (IS_ERR_OR_NULL(temp)) { cpr3_err(vreg, "index debugfs file creation failed\n"); return; @@ -5428,8 +5426,8 @@ static void cpr3_regulator_debugfs_vreg_add(struct cpr3_regulator *vreg, return; } - temp = debugfs_create_file("index", S_IRUGO, corner_dir, - vreg, &cpr3_debug_current_corner_index_fops); + temp = debugfs_create_file("index", 0444, corner_dir, vreg, + &cpr3_debug_current_corner_index_fops); if (IS_ERR_OR_NULL(temp)) { cpr3_err(vreg, "index debugfs file creation failed\n"); return; @@ -5470,7 +5468,7 @@ static void cpr3_regulator_debugfs_thread_add(struct cpr3_thread *thread) return; } - temp = debugfs_create_int("floor_volt", S_IRUGO, aggr_dir, + temp = debugfs_create_int("floor_volt", 0444, aggr_dir, &thread->aggr_corner.floor_volt); if (IS_ERR_OR_NULL(temp)) { cpr3_err(ctrl, "thread %u aggr floor_volt debugfs file creation failed\n", @@ -5478,7 +5476,7 @@ static void cpr3_regulator_debugfs_thread_add(struct cpr3_thread *thread) return; } - temp = debugfs_create_int("ceiling_volt", S_IRUGO, aggr_dir, + temp = debugfs_create_int("ceiling_volt", 0444, aggr_dir, &thread->aggr_corner.ceiling_volt); if (IS_ERR_OR_NULL(temp)) { cpr3_err(ctrl, "thread %u aggr ceiling_volt debugfs file creation failed\n", @@ -5486,7 +5484,7 @@ static void cpr3_regulator_debugfs_thread_add(struct cpr3_thread *thread) return; } - temp = debugfs_create_int("open_loop_volt", S_IRUGO, aggr_dir, + temp = debugfs_create_int("open_loop_volt", 0444, aggr_dir, &thread->aggr_corner.open_loop_volt); if (IS_ERR_OR_NULL(temp)) { cpr3_err(ctrl, "thread %u aggr open_loop_volt debugfs file creation failed\n", @@ -5494,7 +5492,7 @@ static void cpr3_regulator_debugfs_thread_add(struct cpr3_thread *thread) return; } - temp = debugfs_create_int("last_volt", S_IRUGO, aggr_dir, + temp = debugfs_create_int("last_volt", 0444, aggr_dir, &thread->aggr_corner.last_volt); if (IS_ERR_OR_NULL(temp)) { cpr3_err(ctrl, "thread %u aggr last_volt debugfs file creation failed\n", @@ -5511,8 +5509,8 @@ static void cpr3_regulator_debugfs_thread_add(struct cpr3_thread *thread) info->index = index; info->corner = &thread->aggr_corner; - temp = debugfs_create_file("target_quots", S_IRUGO, aggr_dir, - info, &cpr3_debug_quot_fops); + temp = debugfs_create_file("target_quots", 0444, aggr_dir, info, + &cpr3_debug_quot_fops); if (IS_ERR_OR_NULL(temp)) { cpr3_err(ctrl, "thread %u target_quots debugfs file creation failed\n", thread->thread_id); @@ -5869,7 +5867,7 @@ static void cpr3_regulator_debugfs_ctrl_add(struct cpr3_controller *ctrl) return; } - temp = debugfs_create_file("cpr_closed_loop_enable", S_IRUGO | S_IWUSR, + temp = debugfs_create_file("cpr_closed_loop_enable", 0644, ctrl->debugfs, ctrl, &cpr3_debug_closed_loop_enable_fops); if (IS_ERR_OR_NULL(temp)) { @@ -5878,8 +5876,8 @@ static void cpr3_regulator_debugfs_ctrl_add(struct cpr3_controller *ctrl) } if (ctrl->supports_hw_closed_loop) { - temp = debugfs_create_file("use_hw_closed_loop", - S_IRUGO | S_IWUSR, ctrl->debugfs, ctrl, + temp = debugfs_create_file("use_hw_closed_loop", 0644, + ctrl->debugfs, ctrl, &cpr3_debug_hw_closed_loop_enable_fops); if (IS_ERR_OR_NULL(temp)) { cpr3_err(ctrl, "use_hw_closed_loop debugfs file creation failed\n"); @@ -5887,7 +5885,7 @@ static void cpr3_regulator_debugfs_ctrl_add(struct cpr3_controller *ctrl) } } - temp = debugfs_create_int("thread_count", S_IRUGO, ctrl->debugfs, + temp = debugfs_create_int("thread_count", 0444, ctrl->debugfs, &ctrl->thread_count); if (IS_ERR_OR_NULL(temp)) { cpr3_err(ctrl, "thread_count debugfs file creation failed\n"); @@ -5895,7 +5893,7 @@ static void cpr3_regulator_debugfs_ctrl_add(struct cpr3_controller *ctrl) } if (ctrl->apm) { - temp = debugfs_create_int("apm_threshold_volt", S_IRUGO, + temp = debugfs_create_int("apm_threshold_volt", 0444, ctrl->debugfs, &ctrl->apm_threshold_volt); if (IS_ERR_OR_NULL(temp)) { cpr3_err(ctrl, "apm_threshold_volt debugfs file creation failed\n"); @@ -5905,28 +5903,28 @@ static void cpr3_regulator_debugfs_ctrl_add(struct cpr3_controller *ctrl) if (ctrl->aging_required || ctrl->aging_succeeded || ctrl->aging_failed) { - temp = debugfs_create_int("aging_adj_volt", S_IRUGO, + temp = debugfs_create_int("aging_adj_volt", 0444, ctrl->debugfs, &ctrl->aging_ref_adjust_volt); if (IS_ERR_OR_NULL(temp)) { cpr3_err(ctrl, "aging_adj_volt debugfs file creation failed\n"); return; } - temp = debugfs_create_file("aging_succeeded", S_IRUGO, + temp = debugfs_create_file("aging_succeeded", 0444, ctrl->debugfs, &ctrl->aging_succeeded, &fops_bool_ro); if (IS_ERR_OR_NULL(temp)) { cpr3_err(ctrl, "aging_succeeded debugfs file creation failed\n"); return; } - temp = debugfs_create_file("aging_failed", S_IRUGO, + temp = debugfs_create_file("aging_failed", 0444, ctrl->debugfs, &ctrl->aging_failed, &fops_bool_ro); if (IS_ERR_OR_NULL(temp)) { cpr3_err(ctrl, "aging_failed debugfs file creation failed\n"); return; } - temp = debugfs_create_file("aging_trigger", S_IWUSR, + temp = debugfs_create_file("aging_trigger", 0200, ctrl->debugfs, ctrl, &cpr3_debug_trigger_aging_measurement_fops); if (IS_ERR_OR_NULL(temp)) { @@ -5941,28 +5939,28 @@ static void cpr3_regulator_debugfs_ctrl_add(struct cpr3_controller *ctrl) return; } - temp = debugfs_create_int("floor_volt", S_IRUGO, aggr_dir, + temp = debugfs_create_int("floor_volt", 0444, aggr_dir, &ctrl->aggr_corner.floor_volt); if (IS_ERR_OR_NULL(temp)) { cpr3_err(ctrl, "aggr floor_volt debugfs file creation failed\n"); return; } - temp = debugfs_create_int("ceiling_volt", S_IRUGO, aggr_dir, + temp = debugfs_create_int("ceiling_volt", 0444, aggr_dir, &ctrl->aggr_corner.ceiling_volt); if (IS_ERR_OR_NULL(temp)) { cpr3_err(ctrl, "aggr ceiling_volt debugfs file creation failed\n"); return; } - temp = debugfs_create_int("open_loop_volt", S_IRUGO, aggr_dir, + temp = debugfs_create_int("open_loop_volt", 0444, aggr_dir, &ctrl->aggr_corner.open_loop_volt); if (IS_ERR_OR_NULL(temp)) { cpr3_err(ctrl, "aggr open_loop_volt debugfs file creation failed\n"); return; } - temp = debugfs_create_int("last_volt", S_IRUGO, aggr_dir, + temp = debugfs_create_int("last_volt", 0444, aggr_dir, &ctrl->aggr_corner.last_volt); if (IS_ERR_OR_NULL(temp)) { cpr3_err(ctrl, "aggr last_volt debugfs file creation failed\n"); diff --git a/drivers/regulator/cpr3-regulator.h b/drivers/regulator/cpr3-regulator.h index f0230b8ae2e5..7dae23ca0e70 100644 --- a/drivers/regulator/cpr3-regulator.h +++ b/drivers/regulator/cpr3-regulator.h @@ -36,9 +36,9 @@ struct cpr3_thread; * from 0 to 63. bit_start must be less than or equal to bit_end. */ struct cpr3_fuse_param { - unsigned row; - unsigned bit_start; - unsigned bit_end; + unsigned int row; + unsigned int bit_start; + unsigned int bit_end; }; /* Each CPR3 sensor has 16 ring oscillators */ @@ -1021,7 +1021,6 @@ static inline int cpr3_limit_open_loop_voltages(struct cpr3_regulator *vreg) static inline void cpr3_open_loop_voltage_as_ceiling( struct cpr3_regulator *vreg) { - return; } static inline int cpr3_limit_floor_voltages(struct cpr3_regulator *vreg) @@ -1031,7 +1030,6 @@ static inline int cpr3_limit_floor_voltages(struct cpr3_regulator *vreg) static inline void cpr3_print_quots(struct cpr3_regulator *vreg) { - return; } static inline int cpr3_adjust_fused_open_loop_voltages( diff --git a/drivers/regulator/cpr4-apss-regulator.c b/drivers/regulator/cpr4-apss-regulator.c index 737511e250f1..cfc09ba9f8da 100644 --- a/drivers/regulator/cpr4-apss-regulator.c +++ b/drivers/regulator/cpr4-apss-regulator.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2017, 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 @@ -1402,7 +1402,7 @@ static int cpr4_apss_regulator_remove(struct platform_device *pdev) return cpr3_regulator_unregister(ctrl); } -static struct of_device_id cpr4_regulator_match_table[] = { +static const struct of_device_id cpr4_regulator_match_table[] = { { .compatible = "qcom,cpr4-msm8953-apss-regulator", }, {} }; diff --git a/drivers/regulator/cpr4-mmss-ldo-regulator.c b/drivers/regulator/cpr4-mmss-ldo-regulator.c index f8e3ea40ddac..c4aef84e26eb 100644 --- a/drivers/regulator/cpr4-mmss-ldo-regulator.c +++ b/drivers/regulator/cpr4-mmss-ldo-regulator.c @@ -737,6 +737,7 @@ static const struct of_device_id cpr4_mmss_regulator_match_table[] = { .compatible = "qcom,cpr4-sdm660-mmss-ldo-regulator", .data = (void *)NULL, }, + { }, }; static struct platform_driver cpr4_mmss_regulator_driver = { diff --git a/drivers/regulator/cprh-kbss-regulator.c b/drivers/regulator/cprh-kbss-regulator.c index 0472ce13197b..f21800e00d80 100644 --- a/drivers/regulator/cprh-kbss-regulator.c +++ b/drivers/regulator/cprh-kbss-regulator.c @@ -2007,7 +2007,7 @@ static int cprh_kbss_regulator_resume(struct platform_device *pdev) } /* Data corresponds to the SoC revision */ -static struct of_device_id cprh_regulator_match_table[] = { +static const struct of_device_id cprh_regulator_match_table[] = { { .compatible = "qcom,cprh-msm8998-v1-kbss-regulator", .data = (void *)(uintptr_t)MSM8998_V1_SOC_ID, diff --git a/drivers/regulator/kryo-regulator.c b/drivers/regulator/kryo-regulator.c index cf7830469db5..fd853e7323bb 100644 --- a/drivers/regulator/kryo-regulator.c +++ b/drivers/regulator/kryo-regulator.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2017, 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 @@ -333,7 +333,7 @@ static int kryo_regulator_is_enabled(struct regulator_dev *rdev) } static int kryo_regulator_set_voltage(struct regulator_dev *rdev, - int min_volt, int max_volt, unsigned *selector) + int min_volt, int max_volt, unsigned int *selector) { struct kryo_regulator *kvreg = rdev_get_drvdata(rdev); int rc; @@ -400,7 +400,7 @@ static int kryo_regulator_get_bypass(struct regulator_dev *rdev, } static int kryo_regulator_list_voltage(struct regulator_dev *rdev, - unsigned selector) + unsigned int selector) { struct kryo_regulator *kvreg = rdev_get_drvdata(rdev); @@ -411,7 +411,7 @@ static int kryo_regulator_list_voltage(struct regulator_dev *rdev, } static int kryo_regulator_retention_set_voltage(struct regulator_dev *rdev, - int min_volt, int max_volt, unsigned *selector) + int min_volt, int max_volt, unsigned int *selector) { struct kryo_regulator *kvreg = rdev_get_drvdata(rdev); int rc; @@ -499,7 +499,7 @@ static int kryo_regulator_retention_get_bypass(struct regulator_dev *rdev, } static int kryo_regulator_retention_list_voltage(struct regulator_dev *rdev, - unsigned selector) + unsigned int selector) { struct kryo_regulator *kvreg = rdev_get_drvdata(rdev); @@ -624,7 +624,7 @@ static void kryo_debugfs_init(struct kryo_regulator *kvreg) return; } - temp = debugfs_create_file("mode", S_IRUGO, kvreg->debugfs, + temp = debugfs_create_file("mode", 0444, kvreg->debugfs, kvreg, &kryo_dbg_mode_fops); if (IS_ERR_OR_NULL(temp)) { @@ -989,10 +989,8 @@ static int kryo_regulator_probe(struct platform_device *pdev) init_data->constraints.input_uV = init_data->constraints.max_uV; kvreg = devm_kzalloc(dev, sizeof(*kvreg), GFP_KERNEL); - if (!kvreg) { - dev_err(dev, "memory allocation failed\n"); + if (!kvreg) return -ENOMEM; - } rc = kryo_regulator_init_data(pdev, kvreg); if (rc) { @@ -1073,7 +1071,7 @@ static int kryo_regulator_remove(struct platform_device *pdev) return 0; } -static struct of_device_id kryo_regulator_match_table[] = { +static const struct of_device_id kryo_regulator_match_table[] = { { .compatible = "qcom,kryo-regulator", }, {} }; diff --git a/drivers/regulator/mem-acc-regulator.c b/drivers/regulator/mem-acc-regulator.c index c693969b19b6..4c03decda95a 100644 --- a/drivers/regulator/mem-acc-regulator.c +++ b/drivers/regulator/mem-acc-regulator.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2017, 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 @@ -269,7 +269,7 @@ static void update_acc_reg(struct mem_acc_regulator *mem_acc_vreg, int corner) } static int mem_acc_regulator_set_voltage(struct regulator_dev *rdev, - int corner, int corner_max, unsigned *selector) + int corner, int corner_max, unsigned int *selector) { struct mem_acc_regulator *mem_acc_vreg = rdev_get_drvdata(rdev); int i; @@ -333,10 +333,8 @@ static int __mem_acc_sel_init(struct mem_acc_regulator *mem_acc_vreg, mem_acc_vreg->acc_sel_mask[mem_type] = devm_kzalloc(mem_acc_vreg->dev, mem_acc_vreg->num_acc_sel[mem_type] * sizeof(u32), GFP_KERNEL); - if (!mem_acc_vreg->acc_sel_mask[mem_type]) { - pr_err("Unable to allocate memory for mem_type=%d\n", mem_type); + if (!mem_acc_vreg->acc_sel_mask[mem_type]) return -ENOMEM; - } for (i = 0; i < mem_acc_vreg->num_acc_sel[mem_type]; i++) { bit = mem_acc_vreg->acc_sel_bit_pos[mem_type][i]; @@ -355,8 +353,8 @@ static int mem_acc_sel_init(struct mem_acc_regulator *mem_acc_vreg) if (mem_acc_vreg->mem_acc_supported[i]) { rc = __mem_acc_sel_init(mem_acc_vreg, i); if (rc) { - pr_err("Unable to intialize mem_type=%d rc=%d\n", - i, rc); + pr_err("Unable to initialize mem_type=%d rc=%d\n", + i, rc); return rc; } } @@ -523,15 +521,15 @@ static int mem_acc_custom_data_init(struct platform_device *pdev, if (!res || !res->start) { pr_debug("%s resource missing\n", custom_apc_addr_str); return -EINVAL; - } else { - len = res->end - res->start + 1; - mem_acc_vreg->acc_custom_addr[mem_type] = - devm_ioremap(mem_acc_vreg->dev, res->start, len); - if (!mem_acc_vreg->acc_custom_addr[mem_type]) { - pr_err("Unable to map %s %pa\n", custom_apc_addr_str, - &res->start); - return -EINVAL; - } + } + + len = res->end - res->start + 1; + mem_acc_vreg->acc_custom_addr[mem_type] = + devm_ioremap(mem_acc_vreg->dev, res->start, len); + if (!mem_acc_vreg->acc_custom_addr[mem_type]) { + pr_err("Unable to map %s %pa\n", + custom_apc_addr_str, &res->start); + return -EINVAL; } rc = populate_acc_data(mem_acc_vreg, custom_apc_data_str, @@ -1190,7 +1188,7 @@ static int mem_acc_init(struct platform_device *pdev, rc = mem_acc_sel_init(mem_acc_vreg); if (rc) { - pr_err("Unable to intialize mem_acc_sel reg rc=%d\n", rc); + pr_err("Unable to initialize mem_acc_sel reg rc=%d\n", rc); return rc; } @@ -1307,19 +1305,16 @@ static int mem_acc_regulator_probe(struct platform_device *pdev) if (!init_data) { pr_err("regulator init data is missing\n"); return -EINVAL; - } else { - init_data->constraints.input_uV - = init_data->constraints.max_uV; - init_data->constraints.valid_ops_mask - |= REGULATOR_CHANGE_VOLTAGE; } + init_data->constraints.input_uV = init_data->constraints.max_uV; + init_data->constraints.valid_ops_mask |= REGULATOR_CHANGE_VOLTAGE; + mem_acc_vreg = devm_kzalloc(&pdev->dev, sizeof(*mem_acc_vreg), GFP_KERNEL); - if (!mem_acc_vreg) { - pr_err("Can't allocate mem_acc_vreg memory\n"); + if (!mem_acc_vreg) return -ENOMEM; - } + mem_acc_vreg->dev = &pdev->dev; rc = mem_acc_init(pdev, mem_acc_vreg); @@ -1361,7 +1356,7 @@ static int mem_acc_regulator_remove(struct platform_device *pdev) return 0; } -static struct of_device_id mem_acc_regulator_match_table[] = { +static const struct of_device_id mem_acc_regulator_match_table[] = { { .compatible = "qcom,mem-acc-regulator", }, {} }; diff --git a/drivers/regulator/msm_gfx_ldo.c b/drivers/regulator/msm_gfx_ldo.c index 265ca9ed5258..2800607b5b31 100644 --- a/drivers/regulator/msm_gfx_ldo.c +++ b/drivers/regulator/msm_gfx_ldo.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2017, 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 @@ -42,7 +42,7 @@ #define LDO_VREF_SET_REG 0x18 #define UPDATE_VREF_BIT BIT(31) #define SEL_RST_BIT BIT(16) -#define VREF_VAL_MASK GENMASK(6 , 0) +#define VREF_VAL_MASK GENMASK(6, 0) #define PWRSWITCH_CTRL_REG 0x1C #define LDO_CLAMP_IO_BIT BIT(31) @@ -95,9 +95,9 @@ enum voltage_handling { }; struct fuse_param { - unsigned row; - unsigned bit_start; - unsigned bit_end; + unsigned int row; + unsigned int bit_start; + unsigned int bit_end; }; struct ldo_config { @@ -665,7 +665,7 @@ static int switch_mode_to_bhs(struct msm_gfx_ldo *ldo_vreg) } static int msm_gfx_ldo_set_corner(struct regulator_dev *rdev, - int corner, int corner_max, unsigned *selector) + int corner, int corner_max, unsigned int *selector) { struct msm_gfx_ldo *ldo_vreg = rdev_get_drvdata(rdev); int rc = 0, mem_acc_corner, new_uv; @@ -860,7 +860,7 @@ fail: } static int msm_gfx_ldo_set_voltage(struct regulator_dev *rdev, - int new_uv, int max_uv, unsigned *selector) + int new_uv, int max_uv, unsigned int *selector) { struct msm_gfx_ldo *ldo_vreg = rdev_get_drvdata(rdev); int rc = 0; @@ -1444,22 +1444,22 @@ static void msm_gfx_ldo_debugfs_init(struct msm_gfx_ldo *ldo_vreg) return; } - temp = debugfs_create_file("debug_info", S_IRUGO, ldo_vreg->debugfs, + temp = debugfs_create_file("debug_info", 0444, ldo_vreg->debugfs, ldo_vreg, &msm_gfx_ldo_debug_info_fops); if (IS_ERR_OR_NULL(temp)) { pr_err("debug_info node creation failed\n"); return; } - temp = debugfs_create_file("ldo_voltage", S_IRUGO | S_IWUSR, - ldo_vreg->debugfs, ldo_vreg, &ldo_voltage_fops); + temp = debugfs_create_file("ldo_voltage", 0644, ldo_vreg->debugfs, + ldo_vreg, &ldo_voltage_fops); if (IS_ERR_OR_NULL(temp)) { pr_err("ldo_voltage node creation failed\n"); return; } - temp = debugfs_create_file("ldo_mode_disable", S_IRUGO | S_IWUSR, - ldo_vreg->debugfs, ldo_vreg, &ldo_mode_disable_fops); + temp = debugfs_create_file("ldo_mode_disable", 0644, ldo_vreg->debugfs, + ldo_vreg, &ldo_mode_disable_fops); if (IS_ERR_OR_NULL(temp)) { pr_err("ldo_mode_disable node creation failed\n"); return; diff --git a/drivers/regulator/qpnp-labibb-regulator.c b/drivers/regulator/qpnp-labibb-regulator.c index 40c62c355188..cf8f00085a0c 100644 --- a/drivers/regulator/qpnp-labibb-regulator.c +++ b/drivers/regulator/qpnp-labibb-regulator.c @@ -2365,7 +2365,7 @@ static int qpnp_lab_regulator_is_enabled(struct regulator_dev *rdev) } static int qpnp_lab_regulator_set_voltage(struct regulator_dev *rdev, - int min_uV, int max_uV, unsigned *selector) + int min_uV, int max_uV, unsigned int *selector) { int rc, new_uV; u8 val; @@ -3282,7 +3282,7 @@ static int qpnp_ibb_regulator_is_enabled(struct regulator_dev *rdev) } static int qpnp_ibb_regulator_set_voltage(struct regulator_dev *rdev, - int min_uV, int max_uV, unsigned *selector) + int min_uV, int max_uV, unsigned int *selector) { int rc = 0; @@ -3648,12 +3648,10 @@ static int qpnp_labibb_regulator_probe(struct platform_device *pdev) u8 type, revision; int rc = 0; - labibb = devm_kzalloc(&pdev->dev, - sizeof(struct qpnp_labibb), GFP_KERNEL); - if (labibb == NULL) { - pr_err("labibb allocation failed.\n"); + labibb = devm_kzalloc(&pdev->dev, sizeof(*labibb), GFP_KERNEL); + if (labibb == NULL) return -ENOMEM; - } + labibb->regmap = dev_get_regmap(pdev->dev.parent, NULL); if (!labibb->regmap) { dev_err(&pdev->dev, "Couldn't get parent's regmap\n"); @@ -3849,7 +3847,7 @@ static int qpnp_labibb_regulator_remove(struct platform_device *pdev) return 0; } -static struct of_device_id spmi_match_table[] = { +static const struct of_device_id spmi_match_table[] = { { .compatible = QPNP_LABIBB_REGULATOR_DRIVER_NAME, }, { }, }; diff --git a/drivers/regulator/qpnp-lcdb-regulator.c b/drivers/regulator/qpnp-lcdb-regulator.c index daa4e8e74d5b..a08ade61e057 100644 --- a/drivers/regulator/qpnp-lcdb-regulator.c +++ b/drivers/regulator/qpnp-lcdb-regulator.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2017, 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 @@ -863,7 +863,7 @@ static int qpnp_lcdb_ldo_regulator_is_enabled(struct regulator_dev *rdev) } static int qpnp_lcdb_ldo_regulator_set_voltage(struct regulator_dev *rdev, - int min_uV, int max_uV, unsigned *selector) + int min_uV, int max_uV, unsigned int *selector) { int rc = 0; struct qpnp_lcdb *lcdb = rdev_get_drvdata(rdev); @@ -934,7 +934,7 @@ static int qpnp_lcdb_ncp_regulator_is_enabled(struct regulator_dev *rdev) } static int qpnp_lcdb_ncp_regulator_set_voltage(struct regulator_dev *rdev, - int min_uV, int max_uV, unsigned *selector) + int min_uV, int max_uV, unsigned int *selector) { int rc = 0; struct qpnp_lcdb *lcdb = rdev_get_drvdata(rdev); diff --git a/drivers/regulator/qpnp-oledb-regulator.c b/drivers/regulator/qpnp-oledb-regulator.c index 587538cca474..8d017fb55a3f 100644 --- a/drivers/regulator/qpnp-oledb-regulator.c +++ b/drivers/regulator/qpnp-oledb-regulator.c @@ -327,7 +327,7 @@ static int qpnp_oledb_regulator_is_enabled(struct regulator_dev *rdev) } static int qpnp_oledb_regulator_set_voltage(struct regulator_dev *rdev, - int min_uV, int max_uV, unsigned *selector) + int min_uV, int max_uV, unsigned int *selector) { u8 val; int rc = 0; diff --git a/drivers/regulator/qpnp-regulator.c b/drivers/regulator/qpnp-regulator.c index 17865857df03..bd706658348d 100644 --- a/drivers/regulator/qpnp-regulator.c +++ b/drivers/regulator/qpnp-regulator.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2017, 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 @@ -45,7 +45,7 @@ enum { static int qpnp_vreg_debug_mask; module_param_named( - debug_mask, qpnp_vreg_debug_mask, int, S_IRUSR | S_IWUSR + debug_mask, qpnp_vreg_debug_mask, int, 0600 ); #define vreg_err(vreg, fmt, ...) \ @@ -302,7 +302,7 @@ struct qpnp_voltage_range { int step_uV; int set_point_min_uV; int set_point_max_uV; - unsigned n_voltages; + unsigned int n_voltages; u8 range_sel; }; @@ -313,7 +313,7 @@ struct qpnp_voltage_range { struct qpnp_voltage_set_points { struct qpnp_voltage_range *range; int count; - unsigned n_voltages; + unsigned int n_voltages; }; struct qpnp_regulator_mapping { @@ -381,7 +381,7 @@ struct qpnp_regulator { { \ .range = _ranges, \ .count = ARRAY_SIZE(_ranges), \ -}; +} /* * These tables contain the physically available PMIC regulator voltage setpoint @@ -730,7 +730,7 @@ static int qpnp_regulator_common_disable(struct regulator_dev *rdev) */ static int qpnp_regulator_select_voltage_same_range(struct qpnp_regulator *vreg, int min_uV, int max_uV, int *range_sel, int *voltage_sel, - unsigned *selector) + unsigned int *selector) { struct qpnp_voltage_range *range = NULL; int uV = min_uV; @@ -781,9 +781,9 @@ static int qpnp_regulator_select_voltage_same_range(struct qpnp_regulator *vreg, (uV - vreg->set_points->range[i].set_point_min_uV) / vreg->set_points->range[i].step_uV; break; - } else { - *selector += vreg->set_points->range[i].n_voltages; } + + *selector += vreg->set_points->range[i].n_voltages; } if (*selector >= vreg->set_points->n_voltages) @@ -794,7 +794,7 @@ static int qpnp_regulator_select_voltage_same_range(struct qpnp_regulator *vreg, static int qpnp_regulator_select_voltage(struct qpnp_regulator *vreg, int min_uV, int max_uV, int *range_sel, int *voltage_sel, - unsigned *selector) + unsigned int *selector) { struct qpnp_voltage_range *range; int uV = min_uV; @@ -872,7 +872,7 @@ static int qpnp_regulator_delay_for_slewing(struct qpnp_regulator *vreg, } static int qpnp_regulator_common_set_voltage(struct regulator_dev *rdev, - int min_uV, int max_uV, unsigned *selector) + int min_uV, int max_uV, unsigned int *selector) { struct qpnp_regulator *vreg = rdev_get_drvdata(rdev); int rc, range_sel, voltage_sel, voltage_old = 0; @@ -958,7 +958,7 @@ static int qpnp_regulator_common_get_voltage(struct regulator_dev *rdev) } static int qpnp_regulator_single_range_set_voltage(struct regulator_dev *rdev, - int min_uV, int max_uV, unsigned *selector) + int min_uV, int max_uV, unsigned int *selector) { struct qpnp_regulator *vreg = rdev_get_drvdata(rdev); int rc, range_sel, voltage_sel; @@ -995,7 +995,7 @@ static int qpnp_regulator_single_range_get_voltage(struct regulator_dev *rdev) } static int qpnp_regulator_ult_lo_smps_set_voltage(struct regulator_dev *rdev, - int min_uV, int max_uV, unsigned *selector) + int min_uV, int max_uV, unsigned int *selector) { struct qpnp_regulator *vreg = rdev_get_drvdata(rdev); int rc, range_sel, voltage_sel; @@ -1065,7 +1065,7 @@ static int qpnp_regulator_ult_lo_smps_get_voltage(struct regulator_dev *rdev) } static int qpnp_regulator_common_list_voltage(struct regulator_dev *rdev, - unsigned selector) + unsigned int selector) { struct qpnp_regulator *vreg = rdev_get_drvdata(rdev); int uV = 0; @@ -1079,16 +1079,16 @@ static int qpnp_regulator_common_list_voltage(struct regulator_dev *rdev, uV = selector * vreg->set_points->range[i].step_uV + vreg->set_points->range[i].set_point_min_uV; break; - } else { - selector -= vreg->set_points->range[i].n_voltages; } + + selector -= vreg->set_points->range[i].n_voltages; } return uV; } static int qpnp_regulator_common2_set_voltage(struct regulator_dev *rdev, - int min_uV, int max_uV, unsigned *selector) + int min_uV, int max_uV, unsigned int *selector) { struct qpnp_regulator *vreg = rdev_get_drvdata(rdev); int rc, range_sel, voltage_sel, voltage_old = 0; @@ -1280,8 +1280,6 @@ static void qpnp_regulator_vs_ocp_work(struct work_struct *work) = container_of(dwork, struct qpnp_regulator, ocp_work); qpnp_regulator_vs_clear_ocp(vreg); - - return; } static irqreturn_t qpnp_regulator_vs_ocp_isr(int irq, void *data) @@ -1418,8 +1416,7 @@ static void qpnp_vreg_show_state(struct regulator_dev *rdev, pc_mode_label[5] = mode_reg & QPNP_COMMON_MODE_FOLLOW_HW_EN0_MASK ? '0' : '_'; - pr_info("%s %-11s: %s, v=%7d uV, mode=%s, pc_en=%s, " - "alt_mode=%s\n", + pr_info("%s %-11s: %s, v=%7d uV, mode=%s, pc_en=%s, alt_mode=%s\n", action_label, vreg->rdesc.name, enable_label, uV, mode_label, pc_enable_label, pc_mode_label); break; @@ -1440,8 +1437,7 @@ static void qpnp_vreg_show_state(struct regulator_dev *rdev, pc_mode_label[6] = mode_reg & QPNP_COMMON_MODE_FOLLOW_HW_EN0_MASK ? '0' : '_'; - pr_info("%s %-11s: %s, v=%7d uV, mode=%s, pc_en=%s, " - "alt_mode=%s\n", + pr_info("%s %-11s: %s, v=%7d uV, mode=%s, pc_en=%s, alt_mode=%s\n", action_label, vreg->rdesc.name, enable_label, uV, mode_label, pc_enable_label, pc_mode_label); break; @@ -2165,7 +2161,7 @@ static int qpnp_regulator_get_dt_config(struct platform_device *pdev, return rc; } -static struct of_device_id spmi_match_table[]; +static const struct of_device_id spmi_match_table[]; #define MAX_NAME_LEN 127 @@ -2256,8 +2252,6 @@ static int qpnp_regulator_probe(struct platform_device *pdev) reg_name = kzalloc(strnlen(pdata->init_data.constraints.name, MAX_NAME_LEN) + 1, GFP_KERNEL); if (!reg_name) { - dev_err(&pdev->dev, "%s: Can't allocate regulator name\n", - __func__); kfree(vreg); return -ENOMEM; } @@ -2362,7 +2356,7 @@ static int qpnp_regulator_remove(struct platform_device *pdev) return 0; } -static struct of_device_id spmi_match_table[] = { +static const struct of_device_id spmi_match_table[] = { { .compatible = QPNP_REGULATOR_DRIVER_NAME, }, {} }; @@ -2422,8 +2416,7 @@ int __init qpnp_regulator_init(void) if (has_registered) return 0; - else - has_registered = true; + has_registered = true; qpnp_regulator_set_point_init(); diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index ef3ff5e16e86..50ca3c33f942 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -1592,13 +1592,13 @@ config RTC_DRV_MOXART will be called rtc-moxart config RTC_DRV_QPNP - tristate "Qualcomm QPNP PMIC RTC" - depends on SPMI && OF_SPMI && MSM_QPNP_INT + tristate "Qualcomm Technologies, Inc. QPNP PMIC RTC" + depends on SPMI help - Say Y here if you want to support the Qualcomm QPNP PMIC RTC. - - To compile this driver as a module, choose M here: the - module will be called qpnp-rtc. + This enables support for the RTC found on Qualcomm Technologies, Inc. + QPNP PMIC chips. This driver supports using the PMIC RTC peripheral + to wake a mobile device up from suspend or to wake it up from power- + off. config RTC_DRV_MT6397 tristate "Mediatek Real Time Clock driver" @@ -1610,15 +1610,6 @@ config RTC_DRV_MT6397 If you want to use Mediatek(R) RTC interface, select Y or M here. -config RTC_DRV_QPNP - tristate "Qualcomm QPNP PMIC RTC" - depends on SPMI - help - Say Y here if you want to support the Qualcomm QPNP PMIC RTC. - - To compile this driver as a module, choose M here: the - module will be called qpnp-rtc. - config RTC_DRV_XGENE tristate "APM X-Gene RTC" depends on HAS_IOMEM diff --git a/drivers/rtc/qpnp-rtc.c b/drivers/rtc/qpnp-rtc.c index 1b74b94796ba..a2c004e0f7fd 100644 --- a/drivers/rtc/qpnp-rtc.c +++ b/drivers/rtc/qpnp-rtc.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2015, 2017, 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 @@ -50,9 +50,9 @@ /* Module parameter to control power-on-alarm */ bool poweron_alarm; +EXPORT_SYMBOL(poweron_alarm); module_param(poweron_alarm, bool, 0644); MODULE_PARM_DESC(poweron_alarm, "Enable/Disable power-on alarm"); -EXPORT_SYMBOL(poweron_alarm); /* rtc driver internal structure */ struct qpnp_rtc { @@ -138,7 +138,7 @@ qpnp_rtc_set_time(struct device *dev, struct rtc_time *tm) * | BYTE[3] | BYTE[2] | BYTE[1] | BYTE[0] | * ---------------------------------------------- * - * RTC has four 8 bit registers for writting time in seconds: + * RTC has four 8 bit registers for writing time in seconds: * WDATA[3], WDATA[2], WDATA[1], WDATA[0] * * Write to the RTC registers should be done in following order @@ -149,7 +149,7 @@ qpnp_rtc_set_time(struct device *dev, struct rtc_time *tm) * * Write BYTE[0] of time to RTC WDATA[0] register * - * Clearing BYTE[0] and writting in the end will prevent any + * Clearing BYTE[0] and writing in the end will prevent any * unintentional overflow from WDATA[0] to higher bytes during the * write operation */ @@ -162,9 +162,8 @@ qpnp_rtc_set_time(struct device *dev, struct rtc_time *tm) rc = qpnp_write_wrapper(rtc_dd, &rtc_ctrl_reg, rtc_dd->rtc_base + REG_OFFSET_RTC_CTRL, 1); if (rc) { - dev_err(dev, - "Disabling of RTC control reg failed" - " with error:%d\n", rc); + dev_err(dev, "Disabling of RTC control reg failed with error:%d\n", + rc); goto rtc_rw_fail; } rtc_dd->rtc_ctrl_reg = rtc_ctrl_reg; @@ -201,9 +200,8 @@ qpnp_rtc_set_time(struct device *dev, struct rtc_time *tm) rc = qpnp_write_wrapper(rtc_dd, &rtc_ctrl_reg, rtc_dd->rtc_base + REG_OFFSET_RTC_CTRL, 1); if (rc) { - dev_err(dev, - "Enabling of RTC control reg failed" - " with error:%d\n", rc); + dev_err(dev, "Enabling of RTC control reg failed with error:%d\n", + rc); goto rtc_rw_fail; } rtc_dd->rtc_ctrl_reg = rtc_ctrl_reg; @@ -417,11 +415,19 @@ rtc_rw_fail: return rc; } -static struct rtc_class_ops qpnp_rtc_ops = { +static const struct rtc_class_ops qpnp_rtc_ro_ops = { + .read_time = qpnp_rtc_read_time, + .set_alarm = qpnp_rtc_set_alarm, + .read_alarm = qpnp_rtc_read_alarm, + .alarm_irq_enable = qpnp_rtc_alarm_irq_enable, +}; + +static const struct rtc_class_ops qpnp_rtc_rw_ops = { .read_time = qpnp_rtc_read_time, .set_alarm = qpnp_rtc_set_alarm, .read_alarm = qpnp_rtc_read_alarm, .alarm_irq_enable = qpnp_rtc_alarm_irq_enable, + .set_time = qpnp_rtc_set_time, }; static irqreturn_t qpnp_alarm_trigger(int irq, void *dev_id) @@ -465,6 +471,7 @@ rtc_alarm_handled: static int qpnp_rtc_probe(struct platform_device *pdev) { + const struct rtc_class_ops *rtc_ops = &qpnp_rtc_ro_ops; int rc; u8 subtype; struct qpnp_rtc *rtc_dd; @@ -578,13 +585,13 @@ static int qpnp_rtc_probe(struct platform_device *pdev) } if (rtc_dd->rtc_write_enable == true) - qpnp_rtc_ops.set_time = qpnp_rtc_set_time; + rtc_ops = &qpnp_rtc_rw_ops; dev_set_drvdata(&pdev->dev, rtc_dd); /* Register the RTC device */ rtc_dd->rtc = rtc_device_register("qpnp_rtc", &pdev->dev, - &qpnp_rtc_ops, THIS_MODULE); + rtc_ops, THIS_MODULE); if (IS_ERR(rtc_dd->rtc)) { dev_err(&pdev->dev, "%s: RTC registration failed (%ld)\n", __func__, PTR_ERR(rtc_dd->rtc)); @@ -676,7 +683,7 @@ fail_alarm_disable: } } -static struct of_device_id spmi_match_table[] = { +static const struct of_device_id spmi_match_table[] = { { .compatible = "qcom,qpnp-rtc", }, @@ -707,4 +714,4 @@ static void __exit qpnp_rtc_exit(void) module_exit(qpnp_rtc_exit); MODULE_DESCRIPTION("SMPI PMIC RTC driver"); -MODULE_LICENSE("GPL V2"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig index 4a315d8f5534..1e5970b31404 100644 --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig @@ -37,12 +37,14 @@ config MSM_SMEM inter-processor communication. config QPNP_HAPTIC - tristate "Haptic support for QPNP PMIC" + tristate "Haptic support for QPNP PMIC" depends on ARCH_QCOM - help - This option enables device driver support for the Haptic - on the Qualcomm Technologies' QPNP PMICs. It uses the android - timed-output framework. + help + This option enables device driver support for the haptic peripheral + found on Qualcomm Technologies, Inc. QPNP PMICs. The haptic + peripheral is capable of driving both LRA and ERM vibrators. This + module provides haptic feedback for user actions such as a long press + on the touch screen. It uses the Android timed-output framework. config MSM_SMD depends on MSM_SMEM diff --git a/drivers/soc/qcom/icnss.c b/drivers/soc/qcom/icnss.c index 16ee98d8e4e0..7c08c28aeda8 100644 --- a/drivers/soc/qcom/icnss.c +++ b/drivers/soc/qcom/icnss.c @@ -1724,19 +1724,21 @@ static int icnss_call_driver_probe(struct icnss_priv *priv) out: icnss_hw_power_off(priv); - penv->ops = NULL; return ret; } -static int icnss_call_driver_reinit(struct icnss_priv *priv) +static int icnss_pd_restart_complete(struct icnss_priv *priv) { - int ret = 0; + int ret; + + clear_bit(ICNSS_PD_RESTART, &priv->state); + icnss_pm_relax(priv); if (!priv->ops || !priv->ops->reinit) goto out; if (!test_bit(ICNSS_DRIVER_PROBED, &penv->state)) - goto out; + goto call_probe; icnss_pr_dbg("Calling driver reinit state: 0x%lx\n", priv->state); @@ -1751,18 +1753,14 @@ static int icnss_call_driver_reinit(struct icnss_priv *priv) } out: - clear_bit(ICNSS_PD_RESTART, &priv->state); - - icnss_pm_relax(priv); - return 0; +call_probe: + return icnss_call_driver_probe(priv); + out_power_off: icnss_hw_power_off(priv); - clear_bit(ICNSS_PD_RESTART, &priv->state); - - icnss_pm_relax(priv); return ret; } @@ -1787,7 +1785,7 @@ static int icnss_driver_event_fw_ready_ind(void *data) } if (test_bit(ICNSS_PD_RESTART, &penv->state)) - ret = icnss_call_driver_reinit(penv); + ret = icnss_pd_restart_complete(penv); else ret = icnss_call_driver_probe(penv); diff --git a/drivers/soc/qcom/qpnp-haptic.c b/drivers/soc/qcom/qpnp-haptic.c index 21387568fe53..39070561d7e4 100644 --- a/drivers/soc/qcom/qpnp-haptic.c +++ b/drivers/soc/qcom/qpnp-haptic.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2015, 2017, 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 @@ -918,15 +918,16 @@ static ssize_t qpnp_hap_wf_samp_store(struct device *dev, struct timed_output_dev *timed_dev = dev_get_drvdata(dev); struct qpnp_hap *hap = container_of(timed_dev, struct qpnp_hap, timed_dev); - int data; + int data, rc; if (index < 0 || index >= QPNP_HAP_WAV_SAMP_LEN) { dev_err(dev, "Invalid sample index(%d)\n", index); return -EINVAL; } - if (sscanf(buf, "%x", &data) != 1) - return -EINVAL; + rc = kstrtoint(buf, 16, &data); + if (rc) + return rc; if (data < 0 || data > 0xff) { dev_err(dev, "Invalid sample wf_%d (%d)\n", index, data); @@ -1032,8 +1033,9 @@ static ssize_t qpnp_hap_wf_rep_store(struct device *dev, int data, rc, temp; u8 reg; - if (sscanf(buf, "%d", &data) != 1) - return -EINVAL; + rc = kstrtoint(buf, 10, &data); + if (rc) + return rc; if (data < QPNP_HAP_WAV_REP_MIN) data = QPNP_HAP_WAV_REP_MIN; @@ -1078,8 +1080,9 @@ static ssize_t qpnp_hap_wf_s_rep_store(struct device *dev, int data, rc, temp; u8 reg; - if (sscanf(buf, "%d", &data) != 1) - return -EINVAL; + rc = kstrtoint(buf, 10, &data); + if (rc) + return rc; if (data < QPNP_HAP_WAV_S_REP_MIN) data = QPNP_HAP_WAV_S_REP_MIN; @@ -1290,51 +1293,25 @@ static ssize_t qpnp_hap_ramp_test_data_show(struct device *dev, /* sysfs attributes */ static struct device_attribute qpnp_hap_attrs[] = { - __ATTR(wf_s0, (S_IRUGO | S_IWUSR | S_IWGRP), - qpnp_hap_wf_s0_show, - qpnp_hap_wf_s0_store), - __ATTR(wf_s1, (S_IRUGO | S_IWUSR | S_IWGRP), - qpnp_hap_wf_s1_show, - qpnp_hap_wf_s1_store), - __ATTR(wf_s2, (S_IRUGO | S_IWUSR | S_IWGRP), - qpnp_hap_wf_s2_show, - qpnp_hap_wf_s2_store), - __ATTR(wf_s3, (S_IRUGO | S_IWUSR | S_IWGRP), - qpnp_hap_wf_s3_show, - qpnp_hap_wf_s3_store), - __ATTR(wf_s4, (S_IRUGO | S_IWUSR | S_IWGRP), - qpnp_hap_wf_s4_show, - qpnp_hap_wf_s4_store), - __ATTR(wf_s5, (S_IRUGO | S_IWUSR | S_IWGRP), - qpnp_hap_wf_s5_show, - qpnp_hap_wf_s5_store), - __ATTR(wf_s6, (S_IRUGO | S_IWUSR | S_IWGRP), - qpnp_hap_wf_s6_show, - qpnp_hap_wf_s6_store), - __ATTR(wf_s7, (S_IRUGO | S_IWUSR | S_IWGRP), - qpnp_hap_wf_s7_show, - qpnp_hap_wf_s7_store), - __ATTR(wf_update, (S_IRUGO | S_IWUSR | S_IWGRP), - qpnp_hap_wf_update_show, - qpnp_hap_wf_update_store), - __ATTR(wf_rep, (S_IRUGO | S_IWUSR | S_IWGRP), - qpnp_hap_wf_rep_show, - qpnp_hap_wf_rep_store), - __ATTR(wf_s_rep, (S_IRUGO | S_IWUSR | S_IWGRP), - qpnp_hap_wf_s_rep_show, - qpnp_hap_wf_s_rep_store), - __ATTR(play_mode, (S_IRUGO | S_IWUSR | S_IWGRP), - qpnp_hap_play_mode_show, - qpnp_hap_play_mode_store), - __ATTR(dump_regs, (S_IRUGO | S_IWUSR | S_IWGRP), - qpnp_hap_dump_regs_show, - NULL), - __ATTR(ramp_test, (S_IRUGO | S_IWUSR | S_IWGRP), - qpnp_hap_ramp_test_data_show, - qpnp_hap_ramp_test_data_store), - __ATTR(min_max_test, (S_IRUGO | S_IWUSR | S_IWGRP), - qpnp_hap_min_max_test_data_show, - qpnp_hap_min_max_test_data_store), + __ATTR(wf_s0, 0664, qpnp_hap_wf_s0_show, qpnp_hap_wf_s0_store), + __ATTR(wf_s1, 0664, qpnp_hap_wf_s1_show, qpnp_hap_wf_s1_store), + __ATTR(wf_s2, 0664, qpnp_hap_wf_s2_show, qpnp_hap_wf_s2_store), + __ATTR(wf_s3, 0664, qpnp_hap_wf_s3_show, qpnp_hap_wf_s3_store), + __ATTR(wf_s4, 0664, qpnp_hap_wf_s4_show, qpnp_hap_wf_s4_store), + __ATTR(wf_s5, 0664, qpnp_hap_wf_s5_show, qpnp_hap_wf_s5_store), + __ATTR(wf_s6, 0664, qpnp_hap_wf_s6_show, qpnp_hap_wf_s6_store), + __ATTR(wf_s7, 0664, qpnp_hap_wf_s7_show, qpnp_hap_wf_s7_store), + __ATTR(wf_update, 0664, qpnp_hap_wf_update_show, + qpnp_hap_wf_update_store), + __ATTR(wf_rep, 0664, qpnp_hap_wf_rep_show, qpnp_hap_wf_rep_store), + __ATTR(wf_s_rep, 0664, qpnp_hap_wf_s_rep_show, qpnp_hap_wf_s_rep_store), + __ATTR(play_mode, 0664, qpnp_hap_play_mode_show, + qpnp_hap_play_mode_store), + __ATTR(dump_regs, 0664, qpnp_hap_dump_regs_show, NULL), + __ATTR(ramp_test, 0664, qpnp_hap_ramp_test_data_show, + qpnp_hap_ramp_test_data_store), + __ATTR(min_max_test, 0664, qpnp_hap_min_max_test_data_show, + qpnp_hap_min_max_test_data_store), }; static void calculate_lra_code(struct qpnp_hap *hap) @@ -1420,13 +1397,13 @@ static enum hrtimer_restart detect_auto_res_error(struct hrtimer *timer) if (val & AUTO_RES_ERR_BIT) { schedule_work(&hap->auto_res_err_work); return HRTIMER_NORESTART; - } else { - update_lra_frequency(hap); - currtime = ktime_get(); - hrtimer_forward(&hap->auto_res_err_poll_timer, currtime, - ktime_set(0, POLL_TIME_AUTO_RES_ERR_NS)); - return HRTIMER_RESTART; } + + update_lra_frequency(hap); + currtime = ktime_get(); + hrtimer_forward(&hap->auto_res_err_poll_timer, currtime, + ktime_set(0, POLL_TIME_AUTO_RES_ERR_NS)); + return HRTIMER_RESTART; } static void correct_auto_res_error(struct work_struct *auto_res_err_work) @@ -1595,19 +1572,23 @@ int qpnp_hap_play_byte(u8 data, bool on) return rc; if (!on) { - /* set the pwm back to original duty for normal operations */ - /* this is not required if standard interface is not used */ + /* + * Set the pwm back to original duty for normal operations. + * This is not required if standard interface is not used. + */ rc = pwm_config(hap->pwm_info.pwm_dev, hap->pwm_info.duty_us * NSEC_PER_USEC, hap->pwm_info.period_us * NSEC_PER_USEC); return rc; } - /* pwm values range from 0x00 to 0xff. The range from 0x00 to 0x7f - provides a postive amplitude in the sin wave form for 0 to 100%. - The range from 0x80 to 0xff provides a negative amplitude in the - sin wave form for 0 to 100%. Here the duty percentage is calculated - based on the incoming data to accommodate this. */ + /* + * pwm values range from 0x00 to 0xff. The range from 0x00 to 0x7f + * provides a postive amplitude in the sin wave form for 0 to 100%. + * The range from 0x80 to 0xff provides a negative amplitude in the + * sin wave form for 0 to 100%. Here the duty percentage is calculated + * based on the incoming data to accommodate this. + */ if (data <= QPNP_HAP_EXT_PWM_PEAK_DATA) duty_percent = QPNP_HAP_EXT_PWM_HALF_DUTY + ((data * QPNP_HAP_EXT_PWM_DATA_FACTOR) / 100); @@ -1675,6 +1656,7 @@ static int qpnp_hap_get_time(struct timed_output_dev *dev) if (hrtimer_active(&hap->hap_timer)) { ktime_t r = hrtimer_get_remaining(&hap->hap_timer); + return (int)ktime_to_us(r); } else { return 0; @@ -1709,6 +1691,7 @@ static enum hrtimer_restart qpnp_hap_test_timer(struct hrtimer *timer) static int qpnp_haptic_suspend(struct device *dev) { struct qpnp_hap *hap = dev_get_drvdata(dev); + hrtimer_cancel(&hap->hap_timer); cancel_work_sync(&hap->work); /* turn-off haptic */ @@ -1845,9 +1828,11 @@ static int qpnp_hap_config(struct qpnp_hap *hap) if (rc) return rc; - /* Configure RATE_CFG1 and RATE_CFG2 registers */ - /* Note: For ERM these registers act as play rate and - for LRA these represent resonance period */ + /* + * Configure RATE_CFG1 and RATE_CFG2 registers. + * Note: For ERM these registers act as play rate and + * for LRA these represent resonance period + */ if (hap->wave_play_rate_us < QPNP_HAP_WAV_PLAY_RATE_US_MIN) hap->wave_play_rate_us = QPNP_HAP_WAV_PLAY_RATE_US_MIN; else if (hap->wave_play_rate_us > QPNP_HAP_WAV_PLAY_RATE_US_MAX) @@ -2314,7 +2299,7 @@ static int qpnp_haptic_remove(struct platform_device *pdev) return 0; } -static struct of_device_id spmi_match_table[] = { +static const struct of_device_id spmi_match_table[] = { { .compatible = "qcom,qpnp-haptic", }, { }, }; diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig index b8360383a6d2..aa122340c717 100644 --- a/drivers/thermal/Kconfig +++ b/drivers/thermal/Kconfig @@ -406,19 +406,18 @@ config INTEL_PCH_THERMAL programmable trip points and other information. config THERMAL_QPNP - tristate "Qualcomm Plug-and-Play PMIC Temperature Alarm" - depends on THERMAL - depends on OF - depends on SPMI - help - This enables a thermal Sysfs driver for Qualcomm plug-and-play (QPNP) - PMIC devices. It shows up in Sysfs as a thermal zone with multiple - trip points. The temperature reported by the thermal zone reflects the - real time die temperature if an ADC is present or an estimate of the - temperature based upon the over temperature stage value if no ADC is - available. If allowed via compile time configuration; enabling the - thermal zone device via the mode file results in shifting PMIC over - temperature shutdown control from hardware to software. + tristate "Qualcomm Technologies, Inc. QPNP PMIC Temperature Alarm" + depends on OF && SPMI + help + This enables a thermal Sysfs driver for Qualcomm Technologies, Inc. + QPNP PMIC devices. It shows up in Sysfs as a thermal zone with + multiple trip points. The temperature reported by the thermal zone + reflects the real time die temperature if an ADC is present or an + estimate of the temperature based upon the over temperature stage + value if no ADC is available. If allowed via compile time + configuration; enabling the thermal zone device via the mode file + results in shifting PMIC over temperature shutdown control from + hardware to software. config THERMAL_QPNP_ADC_TM tristate "Qualcomm 8974 Thermal Monitor ADC Driver" diff --git a/drivers/thermal/qpnp-temp-alarm.c b/drivers/thermal/qpnp-temp-alarm.c index 691c6c16532d..8c516da1d9ab 100644 --- a/drivers/thermal/qpnp-temp-alarm.c +++ b/drivers/thermal/qpnp-temp-alarm.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2017, 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 @@ -773,7 +773,7 @@ static const struct dev_pm_ops qpnp_tm_pm_ops = { #define QPNP_TM_PM_OPS NULL #endif -static struct of_device_id qpnp_tm_match_table[] = { +static const struct of_device_id qpnp_tm_match_table[] = { { .compatible = QPNP_TM_DRIVER_NAME, }, {} }; diff --git a/drivers/usb/gadget/function/u_data_ipa.c b/drivers/usb/gadget/function/u_data_ipa.c index 6c18a04f6c1c..83a98f1196f8 100644 --- a/drivers/usb/gadget/function/u_data_ipa.c +++ b/drivers/usb/gadget/function/u_data_ipa.c @@ -402,6 +402,7 @@ static void ipa_data_connect_work(struct work_struct *w) if (!port->port_usb) { spin_unlock_irqrestore(&port->port_lock, flags); + usb_gadget_autopm_put_async(port->gadget); pr_err("%s(): port_usb is NULL.\n", __func__); return; } diff --git a/drivers/video/fbdev/msm/mdss_dsi.c b/drivers/video/fbdev/msm/mdss_dsi.c index 51745a9a59ac..c66d9f3b3a65 100644 --- a/drivers/video/fbdev/msm/mdss_dsi.c +++ b/drivers/video/fbdev/msm/mdss_dsi.c @@ -2183,6 +2183,21 @@ static int mdss_dsi_check_params(struct mdss_dsi_ctrl_pdata *ctrl, void *arg) return rc; } +static void mdss_dsi_avr_config(struct mdss_dsi_ctrl_pdata *ctrl_pdata, + int enabled) +{ + u32 data = MIPI_INP((ctrl_pdata->ctrl_base) + 0x10); + + /* DSI_VIDEO_MODE_CTRL */ + if (enabled) + data |= BIT(29); /* AVR_SUPPORT_ENABLED */ + else + data &= ~BIT(29); + + MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x10, data); + MDSS_XLOG(ctrl_pdata->ndx, enabled, data); +} + static int mdss_dsi_dfps_config(struct mdss_panel_data *pdata, int new_fps) { int rc = 0; @@ -2700,6 +2715,9 @@ static int mdss_dsi_event_handler(struct mdss_panel_data *pdata, case MDSS_EVENT_DSI_TIMING_DB_CTRL: mdss_dsi_timing_db_ctrl(ctrl_pdata, (int)(unsigned long)arg); break; + case MDSS_EVENT_AVR_MODE: + mdss_dsi_avr_config(ctrl_pdata, (int)(unsigned long) arg); + break; default: pr_debug("%s: unhandled event=%d\n", __func__, event); break; diff --git a/drivers/video/fbdev/msm/mdss_hdmi_tx.c b/drivers/video/fbdev/msm/mdss_hdmi_tx.c index abc56f5f352d..5804d88e5af5 100644 --- a/drivers/video/fbdev/msm/mdss_hdmi_tx.c +++ b/drivers/video/fbdev/msm/mdss_hdmi_tx.c @@ -22,6 +22,7 @@ #include <linux/types.h> #include <linux/hdcp_qseecom.h> #include <linux/msm_mdp.h> +#include <linux/msm_ext_display.h> #define REG_DUMP 0 @@ -414,7 +415,6 @@ static inline void hdmi_tx_cec_device_suspend(struct hdmi_tx_ctrl *hdmi_ctrl) hdmi_cec_device_suspend(fd, hdmi_ctrl->panel_suspend); } - static inline void hdmi_tx_send_cable_notification( struct hdmi_tx_ctrl *hdmi_ctrl, int val) { @@ -431,7 +431,7 @@ static inline void hdmi_tx_send_cable_notification( } } -static inline void hdmi_tx_set_audio_switch_node( +static inline void hdmi_tx_ack_state( struct hdmi_tx_ctrl *hdmi_ctrl, int val) { if (hdmi_ctrl && hdmi_ctrl->ext_audio_data.intf_ops.notify && @@ -440,47 +440,6 @@ static inline void hdmi_tx_set_audio_switch_node( val); } -static void hdmi_tx_wait_for_audio_engine(struct hdmi_tx_ctrl *hdmi_ctrl) -{ - u64 status = 0; - u32 wait_for_vote = 50; - struct dss_io_data *io = NULL; - - if (!hdmi_ctrl) { - DEV_ERR("%s: invalid input\n", __func__); - return; - } - - io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO]; - if (!io->base) { - DEV_ERR("%s: core io not inititalized\n", __func__); - return; - } - - /* - * wait for 5 sec max for audio engine to acknowledge if hdmi tx core - * can be safely turned off. Sleep for a reasonable time to make sure - * vote_hdmi_core_on variable is updated properly by audio. - */ - while (hdmi_ctrl->vote_hdmi_core_on && --wait_for_vote) - msleep(100); - - - if (!wait_for_vote) - DEV_ERR("%s: HDMI core still voted for power on\n", __func__); - - if (readl_poll_timeout(io->base + HDMI_AUDIO_PKT_CTRL, status, - (status & BIT(0)) == 0, AUDIO_POLL_SLEEP_US, - AUDIO_POLL_TIMEOUT_US)) - DEV_ERR("%s: Error turning off audio packet transmission.\n", - __func__); - - if (readl_poll_timeout(io->base + HDMI_AUDIO_CFG, status, - (status & BIT(0)) == 0, AUDIO_POLL_SLEEP_US, - AUDIO_POLL_TIMEOUT_US)) - DEV_ERR("%s: Error turning off audio engine.\n", __func__); -} - static struct hdmi_tx_ctrl *hdmi_tx_get_drvdata_from_panel_data( struct mdss_panel_data *mpd) { @@ -900,8 +859,7 @@ static ssize_t hdmi_tx_sysfs_wta_hpd(struct device *dev, hdmi_tx_config_5v(hdmi_ctrl, false); } else { hdmi_tx_hpd_off(hdmi_ctrl); - - hdmi_tx_set_audio_switch_node(hdmi_ctrl, 0); + hdmi_tx_send_cable_notification(hdmi_ctrl, 0); } break; @@ -1589,7 +1547,6 @@ static void hdmi_tx_hdcp_cb_work(struct work_struct *work) if (hdmi_tx_is_panel_on(hdmi_ctrl) && hdmi_tx_is_stream_shareable(hdmi_ctrl)) { rc = hdmi_tx_config_avmute(hdmi_ctrl, false); - hdmi_tx_set_audio_switch_node(hdmi_ctrl, 1); } if (hdmi_ctrl->hdcp1_use_sw_keys && hdmi_ctrl->hdcp14_present) @@ -1605,7 +1562,6 @@ static void hdmi_tx_hdcp_cb_work(struct work_struct *work) if (hdmi_tx_is_encryption_set(hdmi_ctrl) || !hdmi_tx_is_stream_shareable(hdmi_ctrl)) { - hdmi_tx_set_audio_switch_node(hdmi_ctrl, 0); rc = hdmi_tx_config_avmute(hdmi_ctrl, true); } @@ -1631,7 +1587,6 @@ static void hdmi_tx_hdcp_cb_work(struct work_struct *work) if (hdmi_tx_is_panel_on(hdmi_ctrl)) { rc = hdmi_tx_config_avmute(hdmi_ctrl, false); - hdmi_tx_set_audio_switch_node(hdmi_ctrl, 1); } break; case HDCP_STATE_AUTH_ENC_1X: @@ -1641,9 +1596,7 @@ static void hdmi_tx_hdcp_cb_work(struct work_struct *work) if (hdmi_tx_is_panel_on(hdmi_ctrl) && hdmi_tx_is_stream_shareable(hdmi_ctrl)) { rc = hdmi_tx_config_avmute(hdmi_ctrl, false); - hdmi_tx_set_audio_switch_node(hdmi_ctrl, 1); } else { - hdmi_tx_set_audio_switch_node(hdmi_ctrl, 0); rc = hdmi_tx_config_avmute(hdmi_ctrl, true); } break; @@ -2373,7 +2326,8 @@ static void hdmi_tx_hpd_int_work(struct work_struct *work) if (!hdmi_ctrl->hpd_initialized) { DEV_DBG("hpd not initialized\n"); - goto end; + mutex_unlock(&hdmi_ctrl->tx_lock); + return; } DEV_DBG("%s: %s\n", __func__, @@ -2386,16 +2340,11 @@ static void hdmi_tx_hpd_int_work(struct work_struct *work) pr_warn_ratelimited("%s: EDID read failed\n", __func__); hdmi_tx_update_deep_color(hdmi_ctrl); hdmi_tx_update_hdr_info(hdmi_ctrl); - - hdmi_tx_send_cable_notification(hdmi_ctrl, true); - } else { - hdmi_tx_set_audio_switch_node(hdmi_ctrl, 0); - hdmi_tx_wait_for_audio_engine(hdmi_ctrl); - - hdmi_tx_send_cable_notification(hdmi_ctrl, false); } -end: + mutex_unlock(&hdmi_ctrl->tx_lock); + + hdmi_tx_send_cable_notification(hdmi_ctrl, hdmi_ctrl->hpd_state); } /* hdmi_tx_hpd_int_work */ static int hdmi_tx_check_capability(struct hdmi_tx_ctrl *hdmi_ctrl) @@ -3239,7 +3188,6 @@ static int hdmi_tx_power_on(struct hdmi_tx_ctrl *hdmi_ctrl) if (hdmi_ctrl->panel.infoframe && !hdmi_tx_is_encryption_set(hdmi_ctrl) && hdmi_tx_is_stream_shareable(hdmi_ctrl)) { - hdmi_tx_set_audio_switch_node(hdmi_ctrl, 1); hdmi_tx_config_avmute(hdmi_ctrl, false); } @@ -3845,20 +3793,6 @@ static int hdmi_tx_evt_handle_resume(struct hdmi_tx_ctrl *hdmi_ctrl) goto end; } - if (hdmi_ctrl->sdev.state && - !hdmi_tx_hw_is_cable_connected(hdmi_ctrl)) { - u32 timeout; - - reinit_completion(&hdmi_ctrl->hpd_int_done); - timeout = wait_for_completion_timeout( - &hdmi_ctrl->hpd_int_done, HZ/10); - if (!timeout && !hdmi_ctrl->hpd_state) { - DEV_DBG("%s: cable removed during suspend\n", __func__); - hdmi_tx_set_audio_switch_node(hdmi_ctrl, 0); - hdmi_tx_wait_for_audio_engine(hdmi_ctrl); - hdmi_tx_send_cable_notification(hdmi_ctrl, 0); - } - } end: return rc; } @@ -3906,14 +3840,6 @@ static int hdmi_tx_evt_handle_panel_on(struct hdmi_tx_ctrl *hdmi_ctrl) hdmi_ctrl->timing_gen_on = true; - if (hdmi_ctrl->panel_suspend) { - DEV_DBG("%s: panel suspend has triggered\n", __func__); - - hdmi_tx_set_audio_switch_node(hdmi_ctrl, 0); - hdmi_tx_wait_for_audio_engine(hdmi_ctrl); - hdmi_tx_send_cable_notification(hdmi_ctrl, 0); - } - return rc; } @@ -4003,6 +3929,55 @@ static int hdmi_tx_evt_handle_hdmi_ppm(struct hdmi_tx_ctrl *hdmi_ctrl) return hdmi_tx_update_ppm(hdmi_ctrl, ppm); } +static int hdmi_tx_pre_evt_handle_panel_off(struct hdmi_tx_ctrl *hdmi_ctrl) +{ + hdmi_tx_ack_state(hdmi_ctrl, false); + return 0; +} + +static int hdmi_tx_pre_evt_handle_update_fps(struct hdmi_tx_ctrl *hdmi_ctrl) +{ + hdmi_ctrl->dynamic_fps = (u32) (unsigned long)hdmi_ctrl->evt_arg; + queue_work(hdmi_ctrl->workq, &hdmi_ctrl->fps_work); + return 0; +} + +static int hdmi_tx_post_evt_handle_unblank(struct hdmi_tx_ctrl *hdmi_ctrl) +{ + hdmi_tx_ack_state(hdmi_ctrl, true); + return 0; +} + +static int hdmi_tx_post_evt_handle_resume(struct hdmi_tx_ctrl *hdmi_ctrl) +{ + if (!hdmi_ctrl->hpd_feature_on) + return 0; + + if (!hdmi_tx_hw_is_cable_connected(hdmi_ctrl)) { + u32 timeout; + + reinit_completion(&hdmi_ctrl->hpd_int_done); + timeout = wait_for_completion_timeout( + &hdmi_ctrl->hpd_int_done, HZ/10); + if (!timeout) { + pr_debug("cable removed during suspend\n"); + hdmi_tx_send_cable_notification(hdmi_ctrl, 0); + } + } + + return 0; +} + +static int hdmi_tx_post_evt_handle_panel_on(struct hdmi_tx_ctrl *hdmi_ctrl) +{ + if (hdmi_ctrl->panel_suspend) { + pr_debug("panel suspend has triggered\n"); + hdmi_tx_send_cable_notification(hdmi_ctrl, 0); + } + + return 0; +} + static int hdmi_tx_event_handler(struct mdss_panel_data *panel_data, int event, void *arg) { @@ -4012,33 +3987,52 @@ static int hdmi_tx_event_handler(struct mdss_panel_data *panel_data, hdmi_tx_get_drvdata_from_panel_data(panel_data); if (!hdmi_ctrl) { - DEV_ERR("%s: invalid input\n", __func__); - rc = -EINVAL; - goto end; - } - - /* UPDATE FPS is called from atomic context */ - if (event == MDSS_EVENT_PANEL_UPDATE_FPS) { - hdmi_ctrl->dynamic_fps = (u32) (unsigned long)arg; - queue_work(hdmi_ctrl->workq, &hdmi_ctrl->fps_work); - return rc; + pr_err("%s: invalid input\n", __func__); + return -EINVAL; } - mutex_lock(&hdmi_ctrl->tx_lock); - hdmi_ctrl->evt_arg = arg; - DEV_DBG("%s: event = %s suspend=%d, hpd_feature=%d\n", __func__, + pr_debug("event = %s suspend=%d, hpd_feature=%d\n", mdss_panel_intf_event_to_string(event), hdmi_ctrl->panel_suspend, hdmi_ctrl->hpd_feature_on); + /* event handlers prior to tx_lock */ + handler = hdmi_ctrl->pre_evt_handler[event]; + if (handler) { + rc = handler(hdmi_ctrl); + if (rc) { + pr_err("pre handler failed: event = %s, rc = %d\n", + mdss_panel_intf_event_to_string(event), rc); + return rc; + } + } + + mutex_lock(&hdmi_ctrl->tx_lock); + handler = hdmi_ctrl->evt_handler[event]; - if (handler) + if (handler) { rc = handler(hdmi_ctrl); + if (rc) { + pr_err("handler failed: event = %s, rc = %d\n", + mdss_panel_intf_event_to_string(event), rc); + mutex_unlock(&hdmi_ctrl->tx_lock); + return rc; + } + } mutex_unlock(&hdmi_ctrl->tx_lock); -end: + + /* event handlers post to tx_lock */ + handler = hdmi_ctrl->post_evt_handler[event]; + if (handler) { + rc = handler(hdmi_ctrl); + if (rc) + pr_err("post handler failed: event = %s, rc = %d\n", + mdss_panel_intf_event_to_string(event), rc); + } + return rc; } @@ -4692,7 +4686,6 @@ static int hdmi_tx_init_event_handler(struct hdmi_tx_ctrl *hdmi_ctrl) return -EINVAL; handler = hdmi_ctrl->evt_handler; - handler[MDSS_EVENT_FB_REGISTERED] = hdmi_tx_evt_handle_register; handler[MDSS_EVENT_CHECK_PARAMS] = hdmi_tx_evt_handle_check_param; handler[MDSS_EVENT_RESUME] = hdmi_tx_evt_handle_resume; @@ -4704,7 +4697,17 @@ static int hdmi_tx_init_event_handler(struct hdmi_tx_ctrl *hdmi_ctrl) handler[MDSS_EVENT_PANEL_OFF] = hdmi_tx_evt_handle_panel_off; handler[MDSS_EVENT_CLOSE] = hdmi_tx_evt_handle_close; handler[MDSS_EVENT_DEEP_COLOR] = hdmi_tx_evt_handle_deep_color; - handler[MDSS_EVENT_UPDATE_PANEL_PPM] = hdmi_tx_evt_handle_hdmi_ppm; + handler[MDSS_EVENT_UPDATE_PANEL_PPM] = hdmi_tx_evt_handle_hdmi_ppm; + + handler = hdmi_ctrl->pre_evt_handler; + handler[MDSS_EVENT_PANEL_UPDATE_FPS] = + hdmi_tx_pre_evt_handle_update_fps; + handler[MDSS_EVENT_PANEL_OFF] = hdmi_tx_pre_evt_handle_panel_off; + + handler = hdmi_ctrl->post_evt_handler; + handler[MDSS_EVENT_UNBLANK] = hdmi_tx_post_evt_handle_unblank; + handler[MDSS_EVENT_RESUME] = hdmi_tx_post_evt_handle_resume; + handler[MDSS_EVENT_PANEL_ON] = hdmi_tx_post_evt_handle_panel_on; return 0; } diff --git a/drivers/video/fbdev/msm/mdss_hdmi_tx.h b/drivers/video/fbdev/msm/mdss_hdmi_tx.h index 2a6a48a4e473..ca316a350238 100644 --- a/drivers/video/fbdev/msm/mdss_hdmi_tx.h +++ b/drivers/video/fbdev/msm/mdss_hdmi_tx.h @@ -98,7 +98,6 @@ struct hdmi_tx_ctrl { struct mutex tx_lock; struct list_head cable_notify_handlers; struct kobject *kobj; - struct switch_dev sdev; struct workqueue_struct *workq; struct hdmi_util_ds_data ds_data; struct completion hpd_int_done; @@ -166,7 +165,10 @@ struct hdmi_tx_ctrl { char disp_switch_name[MAX_SWITCH_NAME_SIZE]; + /* pre/post is done in the context without tx_lock */ + hdmi_tx_evt_handler pre_evt_handler[MDSS_EVENT_MAX - 1]; hdmi_tx_evt_handler evt_handler[MDSS_EVENT_MAX - 1]; + hdmi_tx_evt_handler post_evt_handler[MDSS_EVENT_MAX - 1]; }; #endif /* __MDSS_HDMI_TX_H__ */ diff --git a/drivers/video/fbdev/msm/mdss_mdp.c b/drivers/video/fbdev/msm/mdss_mdp.c index 37a3876d3570..b65582f8e042 100644 --- a/drivers/video/fbdev/msm/mdss_mdp.c +++ b/drivers/video/fbdev/msm/mdss_mdp.c @@ -4159,6 +4159,7 @@ static int mdss_mdp_parse_dt_prefill(struct platform_device *pdev) static void mdss_mdp_parse_vbif_qos(struct platform_device *pdev) { struct mdss_data_type *mdata = platform_get_drvdata(pdev); + u32 npriority_lvl_nrt; int rc; mdata->npriority_lvl = mdss_mdp_parse_dt_prop_len(pdev, @@ -4184,8 +4185,20 @@ static void mdss_mdp_parse_vbif_qos(struct platform_device *pdev) return; } - mdata->npriority_lvl = mdss_mdp_parse_dt_prop_len(pdev, + npriority_lvl_nrt = mdss_mdp_parse_dt_prop_len(pdev, "qcom,mdss-vbif-qos-nrt-setting"); + + if (!npriority_lvl_nrt) { + pr_debug("no vbif nrt priorities found rt:%d\n", + mdata->npriority_lvl); + return; + } else if (npriority_lvl_nrt != mdata->npriority_lvl) { + /* driver expects same number for both nrt and rt */ + pr_err("invalid nrt settings nrt(%d) != rt(%d)\n", + npriority_lvl_nrt, mdata->npriority_lvl); + return; + } + if (mdata->npriority_lvl == MDSS_VBIF_QOS_REMAP_ENTRIES) { mdata->vbif_nrt_qos = kzalloc(sizeof(u32) * mdata->npriority_lvl, GFP_KERNEL); @@ -4203,7 +4216,7 @@ static void mdss_mdp_parse_vbif_qos(struct platform_device *pdev) } } else { mdata->npriority_lvl = 0; - pr_debug("Invalid or no vbif qos nrt seting\n"); + pr_debug("Invalid or no vbif qos nrt setting\n"); } } diff --git a/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c b/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c index b7f27b818eda..2a62ae5881b3 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c +++ b/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c @@ -2031,6 +2031,19 @@ static int __mdss_mdp_wait4pingpong(struct mdss_mdp_cmd_ctx *ctx) return rc; } +static void __clear_ping_pong_callback(struct mdss_mdp_ctl *ctl, + struct mdss_mdp_cmd_ctx *ctx) +{ + mdss_mdp_irq_disable_nosync(MDSS_MDP_IRQ_TYPE_PING_PONG_COMP, + ctx->current_pp_num); + mdss_mdp_set_intr_callback_nosync( + MDSS_MDP_IRQ_TYPE_PING_PONG_COMP, + ctx->current_pp_num, NULL, NULL); + if (atomic_add_unless(&ctx->koff_cnt, -1, 0) + && mdss_mdp_cmd_do_notifier(ctx)) + mdss_mdp_ctl_notify(ctl, MDP_NOTIFY_FRAME_TIMEOUT); +} + static int mdss_mdp_cmd_wait4pingpong(struct mdss_mdp_ctl *ctl, void *arg) { struct mdss_mdp_cmd_ctx *ctx; @@ -2047,7 +2060,7 @@ static int mdss_mdp_cmd_wait4pingpong(struct mdss_mdp_ctl *ctl, void *arg) pdata = ctl->panel_data; MDSS_XLOG(ctl->num, atomic_read(&ctx->koff_cnt), ctl->roi_bkup.w, - ctl->roi_bkup.h); + ctl->roi_bkup.h, pdata->panel_info.panel_dead); pr_debug("%s: intf_num=%d ctx=%pK koff_cnt=%d\n", __func__, ctl->intf_num, ctx, atomic_read(&ctx->koff_cnt)); @@ -2073,6 +2086,13 @@ static int mdss_mdp_cmd_wait4pingpong(struct mdss_mdp_ctl *ctl, void *arg) mdss_mdp_cmd_pingpong_done(ctl); local_irq_restore(flags); rc = 1; + } else if (pdata->panel_info.panel_dead) { + /* + * if panel is reported dead, no need to wait for + * pingpong done, and don't report timeout + */ + MDSS_XLOG(0xdead); + __clear_ping_pong_callback(ctl, ctx); } rc = atomic_read(&ctx->koff_cnt) == 0; @@ -2098,15 +2118,7 @@ static int mdss_mdp_cmd_wait4pingpong(struct mdss_mdp_ctl *ctl, void *arg) ctx->pp_timeout_report_cnt++; rc = -EPERM; - mdss_mdp_irq_disable_nosync(MDSS_MDP_IRQ_TYPE_PING_PONG_COMP, - ctx->current_pp_num); - mdss_mdp_set_intr_callback_nosync( - MDSS_MDP_IRQ_TYPE_PING_PONG_COMP, - ctx->current_pp_num, NULL, NULL); - if (atomic_add_unless(&ctx->koff_cnt, -1, 0) - && mdss_mdp_cmd_do_notifier(ctx)) - mdss_mdp_ctl_notify(ctl, MDP_NOTIFY_FRAME_TIMEOUT); - + __clear_ping_pong_callback(ctl, ctx); } else { rc = 0; ctx->pp_timeout_report_cnt = 0; diff --git a/drivers/video/fbdev/msm/mdss_mdp_intf_video.c b/drivers/video/fbdev/msm/mdss_mdp_intf_video.c index 4efa38093557..663d63092ebf 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_intf_video.c +++ b/drivers/video/fbdev/msm/mdss_mdp_intf_video.c @@ -106,6 +106,9 @@ static void mdss_mdp_fetch_start_config(struct mdss_mdp_video_ctx *ctx, static void mdss_mdp_fetch_end_config(struct mdss_mdp_video_ctx *ctx, struct mdss_mdp_ctl *ctl); +static void mdss_mdp_video_timegen_flush(struct mdss_mdp_ctl *ctl, + struct mdss_mdp_video_ctx *sctx); + static void early_wakeup_dfps_update_work(struct work_struct *work); static int mdss_mdp_video_avr_ctrl(struct mdss_mdp_ctl *ctl, bool enable); @@ -411,6 +414,8 @@ static void mdss_mdp_video_avr_vtotal_setup(struct mdss_mdp_ctl *ctl, struct mdss_mdp_video_ctx *ctx) { struct mdss_data_type *mdata = ctl->mdata; + struct mdss_mdp_ctl *sctl = NULL; + struct mdss_mdp_video_ctx *sctx = NULL; if (test_bit(MDSS_CAPS_AVR_SUPPORTED, mdata->mdss_caps_map)) { struct mdss_panel_data *pdata = ctl->panel_data; @@ -435,6 +440,17 @@ static void mdss_mdp_video_avr_vtotal_setup(struct mdss_mdp_ctl *ctl, mdp_video_write(ctx, MDSS_MDP_REG_INTF_AVR_VTOTAL, avr_vtotal); + /* + * Make sure config goes through + */ + wmb(); + + sctl = mdss_mdp_get_split_ctl(ctl); + if (sctl) + sctx = (struct mdss_mdp_video_ctx *) + sctl->intf_ctx[MASTER_CTX]; + mdss_mdp_video_timegen_flush(ctl, ctx); + MDSS_XLOG(pinfo->min_fps, pinfo->default_fps, avr_vtotal); } } @@ -461,8 +477,9 @@ static int mdss_mdp_video_avr_trigger_setup(struct mdss_mdp_ctl *ctl) } static void mdss_mdp_video_avr_ctrl_setup(struct mdss_mdp_video_ctx *ctx, - struct mdss_mdp_avr_info *avr_info, bool is_master, bool enable) + struct mdss_mdp_ctl *ctl, bool is_master, bool enable) { + struct mdss_mdp_avr_info *avr_info = &ctl->avr_info; u32 avr_ctrl = 0; u32 avr_mode = 0; @@ -475,9 +492,18 @@ static void mdss_mdp_video_avr_ctrl_setup(struct mdss_mdp_video_ctx *ctx, if (avr_mode == MDSS_MDP_AVR_ONE_SHOT) avr_mode |= (1 << 8); - if (is_master) + if (is_master) { mdp_video_write(ctx, MDSS_MDP_REG_INTF_AVR_CONTROL, avr_ctrl); + /* + * When AVR is enabled, need to setup DSI Video mode control + */ + mdss_mdp_ctl_intf_event(ctl, + MDSS_EVENT_AVR_MODE, + (void *)(unsigned long) avr_ctrl, + CTL_INTF_EVENT_FLAG_DEFAULT); + } + mdp_video_write(ctx, MDSS_MDP_REG_INTF_AVR_MODE, avr_mode); pr_debug("intf:%d avr_mode:%x avr_ctrl:%x\n", @@ -1435,7 +1461,6 @@ static int mdss_mdp_video_config_fps(struct mdss_mdp_ctl *ctl, int new_fps) } mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON); - /* * Need to disable AVR during DFPS update period. * Next commit will restore the AVR settings. @@ -1844,6 +1869,7 @@ static void mdss_mdp_handoff_programmable_fetch(struct mdss_mdp_ctl *ctl, struct mdss_mdp_video_ctx *ctx) { struct mdss_panel_info *pinfo = &ctl->panel_data->panel_info; + u32 fetch_start_handoff, v_total_handoff, h_total_handoff; pinfo->prg_fet = 0; if (mdp_video_read(ctx, MDSS_MDP_REG_INTF_CONFIG) & BIT(31)) { @@ -2269,7 +2295,7 @@ static int mdss_mdp_video_avr_ctrl(struct mdss_mdp_ctl *ctl, bool enable) pr_err("invalid master ctx\n"); return -EINVAL; } - mdss_mdp_video_avr_ctrl_setup(ctx, &ctl->avr_info, ctl->is_master, + mdss_mdp_video_avr_ctrl_setup(ctx, ctl, ctl->is_master, enable); if (is_pingpong_split(ctl->mfd)) { @@ -2278,7 +2304,7 @@ static int mdss_mdp_video_avr_ctrl(struct mdss_mdp_ctl *ctl, bool enable) pr_err("invalid slave ctx\n"); return -EINVAL; } - mdss_mdp_video_avr_ctrl_setup(sctx, &ctl->avr_info, false, + mdss_mdp_video_avr_ctrl_setup(sctx, ctl, false, enable); } diff --git a/drivers/video/fbdev/msm/mdss_mdp_pipe.c b/drivers/video/fbdev/msm/mdss_mdp_pipe.c index 563cb8be1a04..bd41cb9e025c 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_pipe.c +++ b/drivers/video/fbdev/msm/mdss_mdp_pipe.c @@ -1011,8 +1011,10 @@ static void mdss_mdp_qos_vbif_remapper_setup(struct mdss_data_type *mdata, u32 mask, reg_val, reg_val_lvl, i, vbif_qos; u32 reg_high; bool is_nrt_vbif = mdss_mdp_is_nrt_vbif_client(mdata, pipe); + u32 *vbif_qos_ptr = is_realtime ? mdata->vbif_rt_qos : + mdata->vbif_nrt_qos; - if (mdata->npriority_lvl == 0) + if ((mdata->npriority_lvl == 0) || !vbif_qos_ptr) return; if (test_bit(MDSS_QOS_REMAPPER, mdata->mdss_qos_map)) { @@ -1028,8 +1030,7 @@ static void mdss_mdp_qos_vbif_remapper_setup(struct mdss_data_type *mdata, is_nrt_vbif); mask = 0x3 << (pipe->xin_id * 4); - vbif_qos = is_realtime ? - mdata->vbif_rt_qos[i] : mdata->vbif_nrt_qos[i]; + vbif_qos = vbif_qos_ptr[i]; reg_val &= ~(mask); reg_val |= vbif_qos << (pipe->xin_id * 4); @@ -1053,8 +1054,7 @@ static void mdss_mdp_qos_vbif_remapper_setup(struct mdss_data_type *mdata, mask = 0x3 << (pipe->xin_id * 2); reg_val &= ~(mask); - vbif_qos = is_realtime ? - mdata->vbif_rt_qos[i] : mdata->vbif_nrt_qos[i]; + vbif_qos = vbif_qos_ptr[i]; reg_val |= vbif_qos << (pipe->xin_id * 2); MDSS_VBIF_WRITE(mdata, MDSS_VBIF_QOS_REMAP_BASE + i*4, reg_val, is_nrt_vbif); diff --git a/drivers/video/fbdev/msm/mdss_panel.h b/drivers/video/fbdev/msm/mdss_panel.h index 3fc5b2226b3e..d73416e311b5 100644 --- a/drivers/video/fbdev/msm/mdss_panel.h +++ b/drivers/video/fbdev/msm/mdss_panel.h @@ -265,6 +265,10 @@ struct mdss_intf_recovery { * Argument provided is bits per pixel (8/10/12) * @MDSS_EVENT_UPDATE_PANEL_PPM: update pixel clock by input PPM. * Argument provided is parts per million. + * @MDSS_EVENT_AVR_MODE: Setup DSI Video mode to support AVR based on the + * avr mode passed as argument + * 0 - disable AVR support + * 1 - enable AVR support */ enum mdss_intf_events { MDSS_EVENT_RESET = 1, @@ -299,6 +303,7 @@ enum mdss_intf_events { MDSS_EVENT_DISABLE_PANEL, MDSS_EVENT_UPDATE_PANEL_PPM, MDSS_EVENT_DSI_TIMING_DB_CTRL, + MDSS_EVENT_AVR_MODE, MDSS_EVENT_MAX, }; diff --git a/include/linux/iio/consumer.h b/include/linux/iio/consumer.h index fad58671c49e..62acf17a894b 100644 --- a/include/linux/iio/consumer.h +++ b/include/linux/iio/consumer.h @@ -161,6 +161,16 @@ int iio_read_channel_processed(struct iio_channel *chan, int *val); int iio_write_channel_raw(struct iio_channel *chan, int val); /** + * iio_write_channel_processed() - write to a given channel + * @chan: The channel being queried. + * @val: Value being written. + * + * Note processed writes to iio channels are converted to raw + * values before being written. + */ +int iio_write_channel_processed(struct iio_channel *chan, int val); + +/** * iio_get_channel_type() - get the type of a channel * @channel: The channel being queried. * @type: The type of the channel. diff --git a/include/linux/msm_ext_display.h b/include/linux/msm_ext_display.h index 44a04b5c2fcd..4378080da0d9 100644 --- a/include/linux/msm_ext_display.h +++ b/include/linux/msm_ext_display.h @@ -91,7 +91,7 @@ enum msm_ext_disp_power_state { /** * struct msm_ext_disp_intf_ops - operations exposed to display interface * @hpd: updates external display interface state - * @notify: updates audio framework with interface state + * @notify: acknowledgment to power on or off */ struct msm_ext_disp_intf_ops { int (*hpd)(struct platform_device *pdev, @@ -100,8 +100,7 @@ struct msm_ext_disp_intf_ops { u32 flags); int (*notify)(struct platform_device *pdev, enum msm_ext_disp_cable_state state); - int (*ack)(struct platform_device *pdev, - u32 ack); + int (*ack)(struct platform_device *pdev, u32 ack); }; /** diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h index 8f95c91c059a..64f5c4ca09d5 100644 --- a/include/linux/power_supply.h +++ b/include/linux/power_supply.h @@ -237,6 +237,7 @@ enum power_supply_property { POWER_SUPPLY_PROP_FCC_DELTA, POWER_SUPPLY_PROP_ICL_REDUCTION, POWER_SUPPLY_PROP_PARALLEL_MODE, + POWER_SUPPLY_PROP_CONNECTOR_THERM_ZONE, /* Local extensions of type int64_t */ POWER_SUPPLY_PROP_CHARGE_COUNTER_EXT, /* Properties of type `const char *' */ diff --git a/include/linux/regulator/qpnp-regulator.h b/include/linux/regulator/qpnp-regulator.h index c7afeb50f244..36288c068ac3 100644 --- a/include/linux/regulator/qpnp-regulator.h +++ b/include/linux/regulator/qpnp-regulator.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2013, 2017, 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 @@ -158,8 +158,8 @@ enum qpnp_boost_current_limit { struct qpnp_regulator_platform_data { struct regulator_init_data init_data; int pull_down_enable; - unsigned pin_ctrl_enable; - unsigned pin_ctrl_hpm; + unsigned int pin_ctrl_enable; + unsigned int pin_ctrl_hpm; int system_load; int enable_time; int ocp_enable; diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 46e60923221f..6f7985e6f129 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -208,6 +208,9 @@ struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask, u8 *data; bool pfmemalloc; + if (IS_ENABLED(CONFIG_FORCE_ALLOC_FROM_DMA_ZONE)) + gfp_mask |= GFP_DMA; + cache = (flags & SKB_ALLOC_FCLONE) ? skbuff_fclone_cache : skbuff_head_cache; |
