diff options
58 files changed, 2319 insertions, 547 deletions
diff --git a/Documentation/devicetree/bindings/cnss/icnss.txt b/Documentation/devicetree/bindings/cnss/icnss.txt index da5159006a98..505966fb9226 100644 --- a/Documentation/devicetree/bindings/cnss/icnss.txt +++ b/Documentation/devicetree/bindings/cnss/icnss.txt @@ -25,6 +25,8 @@ Required properties: uS. Optional properties: + - qcom,icnss-vadc: VADC handle for vph_pwr read APIs. + - qcom,icnss-adc_tm: VADC handle for vph_pwr notification APIs. Example: diff --git a/Documentation/devicetree/bindings/input/touchscreen/gt9xx/gt9xx.txt b/Documentation/devicetree/bindings/input/touchscreen/gt9xx/gt9xx.txt new file mode 100644 index 000000000000..af09840bb053 --- /dev/null +++ b/Documentation/devicetree/bindings/input/touchscreen/gt9xx/gt9xx.txt @@ -0,0 +1,79 @@ +Goodix GT9xx series touch controller + +The Goodix GT9xx series touch controller is connected to the host processor via +I2C. The controller generates interrupts when the user touches the panel. The +host controller is expected to read the touch coordinates over I2C and pass +the coordinates to the rest of the system. + +Required properties: + + - compatible : Should be "goodix,gt9xx" + - reg : I2C slave address of the device. + - interrupt-parent : Parent of interrupt. + - interrupts : Configuration of touch panel controller interrupt + GPIO. + - goodix,family-id : Family identification of the controller. + - interrupt-gpios : Interrupt gpio which is to provide interrupts to + host, same as "interrupts" node. + - reset-gpios : Reset gpio to control the reset of chip. + - goodix,display-coords : Display coordinates in pixels. It is a four + tuple consisting of min x, min y, max x and + max y values. + +Optional properties: + + - avdd-supply : Power supply needed to power up the device, this is + for fixed voltage external regulator. + - vdd-supply : Power supply needed to power up the device, when use + external regulator, do not add this property. + - vcc-i2c-supply : Power source required to power up i2c bus. + GT9xx series can provide 1.8V from internal + LDO, add this properties base on hardware + design. + - goodix,panel-coords : Panel coordinates for the chip in pixels. + It is a four tuple consisting of min x, + min y, max x and max y values. + - goodix,i2c-pull-up : To specify pull up is required. + - goodix,no-force-update : To specify force update is allowed. + - goodix,button-map : Button map of key codes. The number of key codes + depend on panel. + - goodix,cfg-data : Touchpanel controller configuration data, ask vendor + to provide that. Default configuration will be + used if this property is not present. + +Example: +i2c@f9927000 { + goodix@5d { + compatible = "goodix,gt9xx"; + reg = <0x5d>; + interrupt-parent = <&msmgpio>; + interrupts = <17 0x2008>; + reset-gpios = <&msmgpio 16 0x00>; + interrupt-gpios = <&msmgpio 17 0x00>; + avdd-supply = <&tp_power>; + goodix,panel-coords = <0 0 720 1200>; + goodix,display-coords = <0 0 720 1080>; + goodix,button-map= <158 102 139>; + goodix,family-id = <0x0>; + goodix,cfg-data = [ + 41 D0 02 00 05 0A 05 01 01 08 + 12 58 50 41 03 05 00 00 00 00 + 00 00 00 00 00 00 00 8C 2E 0E + 28 24 73 13 00 00 00 83 03 1D + 40 02 00 00 00 03 64 32 00 00 + 00 1A 38 94 C0 02 00 00 00 04 + 9E 1C 00 8D 20 00 7A 26 00 6D + 2C 00 60 34 00 60 10 38 68 00 + F0 50 35 FF FF 27 00 00 00 00 + 00 01 1B 14 0C 14 00 00 01 00 + 00 00 00 00 00 00 00 00 00 00 + 00 00 02 04 06 08 0A 0C 0E 10 + 12 14 16 18 1A 1C FF FF FF FF + FF FF FF FF FF FF FF FF FF FF + FF FF 00 02 04 06 08 0A 0C 0F + 10 12 13 14 16 18 1C 1D 1E 1F + 20 21 22 24 26 28 29 2A FF FF + FF FF FF FF FF FF FF 22 22 22 + 22 22 22 FF 07 01]; + }; +}; diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt index aca2dd3e4ccb..1d7e54f68ee4 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt @@ -87,6 +87,7 @@ firefly Firefly focaltech FocalTech Systems Co.,Ltd fsl Freescale Semiconductor GEFanuc GE Fanuc Intelligent Platforms Embedded Systems, Inc. +goodix Goodix. Ltd. gef GE Fanuc Intelligent Platforms Embedded Systems, Inc. geniatech Geniatech, Inc. giantplus Giantplus Technology Co., Ltd. diff --git a/arch/arm/boot/dts/qcom/msmcobalt-coresight.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-coresight.dtsi index 4afaa3aa51be..aeb6bf6141d8 100644 --- a/arch/arm/boot/dts/qcom/msmcobalt-coresight.dtsi +++ b/arch/arm/boot/dts/qcom/msmcobalt-coresight.dtsi @@ -39,10 +39,18 @@ }; replicator: replicator@6046000 { - compatible = "arm,coresight-replicator"; + compatible = "arm,primecell"; + arm,primecell-periphid = <0x0003b909>; + + reg = <0x6046000 0x1000>; + reg-names = "replicator-base"; coresight-name = "coresight-replicator"; + clocks = <&clock_gcc clk_qdss_clk>, + <&clock_gcc clk_qdss_a_clk>; + clock-names = "apb_pclk", "core_a_clk"; + ports{ #address-cells = <1>; #size-cells = <0>; diff --git a/arch/arm/boot/dts/qcom/msmcobalt.dtsi b/arch/arm/boot/dts/qcom/msmcobalt.dtsi index 0a3eb6f70644..cd01d5158fc4 100644 --- a/arch/arm/boot/dts/qcom/msmcobalt.dtsi +++ b/arch/arm/boot/dts/qcom/msmcobalt.dtsi @@ -745,6 +745,7 @@ reg = <0xc8c0000 0x40000>; reg-names = "cc_base"; vdd_dig-supply = <&pmcobalt_s1_level>; + vdd_mmsscc_mx-supply = <&pmcobalt_s9_level>; clock-names = "xo", "gpll0", "gpll0_div", "pclk0_src", "pclk1_src", "byte0_src", "byte1_src", @@ -1731,7 +1732,7 @@ "rx_lane0_sync_clk"; clocks = <&clock_gcc clk_gcc_ufs_axi_hw_ctl_clk>, - <&clock_gcc clk_gcc_aggre1_ufs_axi_clk>, + <&clock_gcc clk_gcc_aggre1_ufs_axi_hw_ctl_clk>, <&clock_gcc clk_gcc_ufs_ahb_clk>, <&clock_gcc clk_gcc_ufs_unipro_core_hw_ctl_clk>, <&clock_gcc clk_gcc_ufs_ice_core_hw_ctl_clk>, @@ -2866,6 +2867,8 @@ qcom,msm-bus,num-paths = <1>; qcom,msm-bus,vectors-KBps = <81 10065 0 0>, <81 10065 0 16000>; + qcom,icnss-vadc = <&pmcobalt_vadc>; + qcom,icnss-adc_tm = <&pmcobalt_adc_tm>; }; wil6210: qcom,wil6210 { diff --git a/arch/arm/boot/dts/qcom/msmfalcon-coresight.dtsi b/arch/arm/boot/dts/qcom/msmfalcon-coresight.dtsi new file mode 100644 index 000000000000..352856965373 --- /dev/null +++ b/arch/arm/boot/dts/qcom/msmfalcon-coresight.dtsi @@ -0,0 +1,194 @@ +/* Copyright (c) 2016, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <dt-bindings/clock/qcom,gcc-msmfalcon.h> +#include <dt-bindings/clock/qcom,gpu-msmfalcon.h> +#include <dt-bindings/clock/qcom,mmcc-msmfalcon.h> + +&soc { + tmc_etr: tmc@6048000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x0003b961>; + + reg = <0x6048000 0x1000>, + <0x6064000 0x15000>; + reg-names = "tmc-base", "bam-base"; + + arm,buffer-size = <0x400000>; + arm,sg-enable; + + coresight-name = "coresight-tmc-etr"; + + clocks = <&clock_gcc RPM_QDSS_CLK>, + <&clock_gcc RPM_QDSS_A_CLK>; + clock-names = "apb_pclk", "core_a_clk"; + + port{ + tmc_etr_in_replicator: endpoint { + slave-mode; + remote-endpoint = <&replicator_out_tmc_etr>; + }; + }; + }; + + replicator: replicator@6046000 { + compatible = "arm,coresight-replicator"; + + coresight-name = "coresight-replicator"; + + ports{ + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + replicator_out_tmc_etr:endpoint { + remote-endpoint = + <&tmc_etr_in_replicator>; + }; + }; + port@1 { + reg = <0>; + replicator_in_tmc_etf:endpoint { + slave-mode; + remote-endpoint = + <&tmc_etf_out_replicator>; + }; + }; + }; + }; + + tmc_etf: tmc@6047000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x0003b961>; + + reg = <0x6047000 0x1000>; + reg-names = "tmc-base"; + + coresight-name = "coresight-tmc-etf"; + + clocks = <&clock_gcc RPM_QDSS_CLK>, + <&clock_gcc RPM_QDSS_A_CLK>; + clock-names = "apb_pclk", "core_a_clk"; + + ports{ + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + tmc_etf_out_replicator:endpoint { + remote-endpoint = + <&replicator_in_tmc_etf>; + }; + }; + port@1 { + reg = <0>; + tmc_etf_in_funnel_merg:endpoint { + slave-mode; + remote-endpoint = + <&funnel_merg_out_tmc_etf>; + }; + }; + }; + }; + + funnel_merg: funnel@6045000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x0003b908>; + + reg = <0x6045000 0x1000>; + reg-names = "funnel-base"; + + coresight-name = "coresight-funnel-merg"; + + clocks = <&clock_gcc RPM_QDSS_CLK>, + <&clock_gcc RPM_QDSS_A_CLK>; + clock-names = "apb_pclk", "core_a_clk"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + funnel_merg_out_tmc_etf:endpoint { + remote-endpoint = + <&tmc_etf_in_funnel_merg>; + }; + }; + port@1 { + reg = <0>; + funnel_merg_in_funnel_in0:endpoint { + slave-mode; + remote-endpoint = + <&funnel_in0_out_funnel_merg>; + }; + }; + }; + }; + + funnel_in0: funnel@6041000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x0003b908>; + + reg = <0x6041000 0x1000>; + reg-names = "funnel-base"; + + coresight-name = "coresight-funnel-in0"; + + clocks = <&clock_gcc RPM_QDSS_CLK>, + <&clock_gcc RPM_QDSS_A_CLK>; + clock-names = "apb_pclk", "core_a_clk"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + funnel_in0_out_funnel_merg: endpoint { + remote-endpoint = + <&funnel_merg_in_funnel_in0>; + }; + }; + port@4 { + reg = <7>; + funnel_in0_in_stm: endpoint { + slave-mode; + remote-endpoint = <&stm_out_funnel_in0>; + }; + }; + }; + }; + + stm: stm@6002000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x0003b962>; + + reg = <0x6002000 0x1000>, + <0x16280000 0x180000>; + reg-names = "stm-base", "stm-data-base"; + + coresight-name = "coresight-stm"; + + clocks = <&clock_gcc RPM_QDSS_CLK>, + <&clock_gcc RPM_QDSS_A_CLK>; + clock-names = "apb_pclk", "core_a_clk"; + + port{ + stm_out_funnel_in0: endpoint { + remote-endpoint = <&funnel_in0_in_stm>; + }; + }; + }; +}; diff --git a/arch/arm/boot/dts/qcom/msmfalcon.dtsi b/arch/arm/boot/dts/qcom/msmfalcon.dtsi index 7c4e7f0ee55a..fb97074f35a3 100644 --- a/arch/arm/boot/dts/qcom/msmfalcon.dtsi +++ b/arch/arm/boot/dts/qcom/msmfalcon.dtsi @@ -201,6 +201,7 @@ }; #include "msmfalcon-smp2p.dtsi" +#include "msmfalcon-coresight.dtsi" &soc { #address-cells = <1>; #size-cells = <1>; diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c index 9ed43cdc3845..39be6ef3735e 100644 --- a/drivers/char/diag/diagchar_core.c +++ b/drivers/char/diag/diagchar_core.c @@ -999,7 +999,7 @@ static int diag_send_raw_data_remote(int proc, void *buf, int len, (void *)driver->hdlc_encode_buf); send_data: - err = diagfwd_bridge_write(proc, driver->hdlc_encode_buf, + err = diagfwd_bridge_write(bridge_index, driver->hdlc_encode_buf, driver->hdlc_encode_buf_len); if (err) { pr_err_ratelimited("diag: Error writing Callback packet to proc: %d, err: %d\n", @@ -2570,7 +2570,7 @@ static int diag_user_process_raw_data(const char __user *buf, int len) } } if (remote_proc) { - ret = diag_send_raw_data_remote(remote_proc - 1, + ret = diag_send_raw_data_remote(remote_proc, (void *)(user_space_data + token_offset), len, USER_SPACE_RAW_DATA); if (ret) { @@ -3424,13 +3424,13 @@ static int __init diagchar_init(void) ret = diag_masks_init(); if (ret) goto fail; - ret = diag_mux_init(); + ret = diag_remote_init(); if (ret) goto fail; - ret = diagfwd_init(); + ret = diag_mux_init(); if (ret) goto fail; - ret = diag_remote_init(); + ret = diagfwd_init(); if (ret) goto fail; ret = diagfwd_bridge_init(); diff --git a/drivers/char/diag/diagfwd_bridge.c b/drivers/char/diag/diagfwd_bridge.c index 701677b30a71..0462a64614f3 100644 --- a/drivers/char/diag/diagfwd_bridge.c +++ b/drivers/char/diag/diagfwd_bridge.c @@ -107,7 +107,7 @@ static int diagfwd_bridge_mux_write_done(unsigned char *buf, int len, if (id < 0 || id >= NUM_REMOTE_DEV) return -EINVAL; - ch = &bridge_info[id]; + ch = &bridge_info[buf_ctx]; if (ch->dev_ops && ch->dev_ops->fwd_complete) ch->dev_ops->fwd_complete(ch->ctxt, buf, len, 0); return 0; diff --git a/drivers/clk/msm/clock-gcc-cobalt.c b/drivers/clk/msm/clock-gcc-cobalt.c index 71c5541d0c0d..05272118af16 100644 --- a/drivers/clk/msm/clock-gcc-cobalt.c +++ b/drivers/clk/msm/clock-gcc-cobalt.c @@ -241,8 +241,8 @@ DEFINE_EXT_CLK(gpll4_out_main, &gpll4.c); static struct clk_freq_tbl ftbl_hmss_ahb_clk_src[] = { F( 19200000, cxo_clk_src_ao, 1, 0, 0), - F( 37500000, gpll0_out_main, 16, 0, 0), - F( 75000000, gpll0_out_main, 8, 0, 0), + F( 50000000, gpll0_out_main, 12, 0, 0), + F( 100000000, gpll0_out_main, 6, 0, 0), F_END }; @@ -1200,6 +1200,17 @@ static struct branch_clk gcc_aggre1_ufs_axi_clk = { }, }; +static struct hw_ctl_clk gcc_aggre1_ufs_axi_hw_ctl_clk = { + .cbcr_reg = GCC_AGGRE1_UFS_AXI_CBCR, + .base = &virt_base, + .c = { + .dbg_name = "gcc_aggre1_ufs_axi_hw_ctl_clk", + .parent = &gcc_aggre1_ufs_axi_clk.c, + .ops = &clk_ops_branch_hw_ctl, + CLK_INIT(gcc_aggre1_ufs_axi_hw_ctl_clk.c), + }, +}; + static struct branch_clk gcc_aggre1_usb3_axi_clk = { .cbcr_reg = GCC_AGGRE1_USB3_AXI_CBCR, .has_sibling = 1, @@ -2597,6 +2608,7 @@ static struct clk_lookup msm_clocks_gcc_cobalt[] = { CLK_LIST(gcc_qusb2phy_sec_reset), CLK_LIST(gpll0_out_msscc), CLK_LIST(gcc_aggre1_ufs_axi_clk), + CLK_LIST(gcc_aggre1_ufs_axi_hw_ctl_clk), CLK_LIST(gcc_aggre1_usb3_axi_clk), CLK_LIST(gcc_bimc_mss_q6_axi_clk), CLK_LIST(gcc_blsp1_ahb_clk), diff --git a/drivers/clk/msm/clock-mmss-cobalt.c b/drivers/clk/msm/clock-mmss-cobalt.c index fbd83a02aa02..220a8ba377ba 100644 --- a/drivers/clk/msm/clock-mmss-cobalt.c +++ b/drivers/clk/msm/clock-mmss-cobalt.c @@ -83,6 +83,7 @@ DEFINE_EXT_CLK(ext_dp_phy_pll_vco, NULL); DEFINE_EXT_CLK(ext_dp_phy_pll_link, NULL); static DEFINE_VDD_REGULATORS(vdd_dig, VDD_DIG_NUM, 1, vdd_corner, NULL); +static DEFINE_VDD_REGULATORS(vdd_mmsscc_mx, VDD_DIG_NUM, 1, vdd_corner, NULL); static struct alpha_pll_masks pll_masks_p = { .lock_mask = BIT(31), @@ -102,7 +103,7 @@ static struct pll_vote_clk mmpll0_pll = { .parent = &mmsscc_xo.c, .dbg_name = "mmpll0", .ops = &clk_ops_pll_vote, - VDD_DIG_FMAX_MAP2(LOWER, 404000000, NOMINAL, 808000000), + VDD_MM_PLL_FMAX_MAP2(LOWER, 404000000, NOMINAL, 808000000), CLK_INIT(mmpll0_pll.c), }, }; @@ -119,7 +120,7 @@ static struct pll_vote_clk mmpll1_pll = { .parent = &mmsscc_xo.c, .dbg_name = "mmpll1_pll", .ops = &clk_ops_pll_vote, - VDD_DIG_FMAX_MAP2(LOWER, 406000000, NOMINAL, 812000000), + VDD_MM_PLL_FMAX_MAP2(LOWER, 406000000, NOMINAL, 812000000), CLK_INIT(mmpll1_pll.c), }, }; @@ -136,7 +137,7 @@ static struct alpha_pll_clk mmpll3_pll = { .parent = &mmsscc_xo.c, .dbg_name = "mmpll3_pll", .ops = &clk_ops_fixed_fabia_alpha_pll, - VDD_DIG_FMAX_MAP2(LOWER, 465000000, LOW, 930000000), + VDD_MM_PLL_FMAX_MAP2(LOWER, 465000000, LOW, 930000000), CLK_INIT(mmpll3_pll.c), }, }; @@ -153,7 +154,7 @@ static struct alpha_pll_clk mmpll4_pll = { .parent = &mmsscc_xo.c, .dbg_name = "mmpll4_pll", .ops = &clk_ops_fixed_fabia_alpha_pll, - VDD_DIG_FMAX_MAP2(LOWER, 384000000, LOW, 768000000), + VDD_MM_PLL_FMAX_MAP2(LOWER, 384000000, LOW, 768000000), CLK_INIT(mmpll4_pll.c), }, }; @@ -170,7 +171,7 @@ static struct alpha_pll_clk mmpll5_pll = { .parent = &mmsscc_xo.c, .dbg_name = "mmpll5_pll", .ops = &clk_ops_fixed_fabia_alpha_pll, - VDD_DIG_FMAX_MAP2(LOWER, 412500000, LOW, 825000000), + VDD_MM_PLL_FMAX_MAP2(LOWER, 412500000, LOW, 825000000), CLK_INIT(mmpll5_pll.c), }, }; @@ -187,7 +188,7 @@ static struct alpha_pll_clk mmpll6_pll = { .parent = &mmsscc_xo.c, .dbg_name = "mmpll6_pll", .ops = &clk_ops_fixed_fabia_alpha_pll, - VDD_DIG_FMAX_MAP2(LOWER, 360000000, NOMINAL, 720000000), + VDD_MM_PLL_FMAX_MAP2(LOWER, 360000000, NOMINAL, 720000000), CLK_INIT(mmpll6_pll.c), }, }; @@ -204,7 +205,7 @@ static struct alpha_pll_clk mmpll7_pll = { .parent = &mmsscc_xo.c, .dbg_name = "mmpll7_pll", .ops = &clk_ops_fixed_fabia_alpha_pll, - VDD_DIG_FMAX_MAP2(LOWER, 480000000, NOMINAL, 960000000), + VDD_MM_PLL_FMAX_MAP1(LOW, 960000000), CLK_INIT(mmpll7_pll.c), }, }; @@ -221,7 +222,7 @@ static struct alpha_pll_clk mmpll10_pll = { .parent = &mmsscc_xo.c, .dbg_name = "mmpll10_pll", .ops = &clk_ops_fixed_fabia_alpha_pll, - VDD_DIG_FMAX_MAP2(LOWER, 288000000, NOMINAL, 576000000), + VDD_MM_PLL_FMAX_MAP2(LOWER, 288000000, NOMINAL, 576000000), CLK_INIT(mmpll10_pll.c), }, }; @@ -2626,7 +2627,6 @@ static struct clk_lookup msm_clocks_mmss_cobalt[] = { CLK_LIST(mmss_misc_ahb_clk), CLK_LIST(mmss_misc_cxo_clk), CLK_LIST(mmss_mnoc_ahb_clk), - CLK_LIST(mmss_mnoc_maxi_clk), CLK_LIST(mmss_video_subcore0_clk), CLK_LIST(mmss_video_subcore1_clk), CLK_LIST(mmss_video_ahb_clk), @@ -2635,6 +2635,7 @@ static struct clk_lookup msm_clocks_mmss_cobalt[] = { CLK_LIST(mmss_video_maxi_clk), CLK_LIST(mmss_vmem_ahb_clk), CLK_LIST(mmss_vmem_maxi_clk), + CLK_LIST(mmss_mnoc_maxi_clk), CLK_LIST(mmss_debug_mux), }; @@ -2745,10 +2746,6 @@ static void msm_mmsscc_v2_fixup(void) csiphy_clk_src.c.fmax[VDD_DIG_LOW] = 256000000; dp_pixel_clk_src.c.fmax[VDD_DIG_LOWER] = 148380000; - - video_subcore0_clk_src.c.fmax[VDD_DIG_LOW_L1] = 355200000; - video_subcore1_clk_src.c.fmax[VDD_DIG_LOW_L1] = 355200000; - video_core_clk_src.c.fmax[VDD_DIG_LOW_L1] = 355200000; } int msm_mmsscc_cobalt_probe(struct platform_device *pdev) @@ -2783,6 +2780,14 @@ int msm_mmsscc_cobalt_probe(struct platform_device *pdev) return PTR_ERR(reg); } + reg = vdd_mmsscc_mx.regulator[0] = devm_regulator_get(&pdev->dev, + "vdd_mmsscc_mx"); + if (IS_ERR(reg)) { + if (PTR_ERR(reg) != -EPROBE_DEFER) + dev_err(&pdev->dev, "Unable to get vdd_mmsscc_mx regulator!"); + return PTR_ERR(reg); + } + tmp = mmsscc_xo.c.parent = devm_clk_get(&pdev->dev, "xo"); if (IS_ERR(tmp)) { if (PTR_ERR(tmp) != -EPROBE_DEFER) diff --git a/drivers/clk/msm/vdd-level-cobalt.h b/drivers/clk/msm/vdd-level-cobalt.h index f847a4104d4d..c1897b7da7f7 100644 --- a/drivers/clk/msm/vdd-level-cobalt.h +++ b/drivers/clk/msm/vdd-level-cobalt.h @@ -24,6 +24,7 @@ [VDD_DIG_##l1] = (f1), \ }, \ .num_fmax = VDD_DIG_NUM + #define VDD_DIG_FMAX_MAP2(l1, f1, l2, f2) \ .vdd_class = &vdd_dig, \ .fmax = (unsigned long[VDD_DIG_NUM]) { \ @@ -40,6 +41,7 @@ [VDD_DIG_##l3] = (f3), \ }, \ .num_fmax = VDD_DIG_NUM + #define VDD_DIG_FMAX_MAP4(l1, f1, l2, f2, l3, f3, l4, f4) \ .vdd_class = &vdd_dig, \ .fmax = (unsigned long[VDD_DIG_NUM]) { \ @@ -66,6 +68,22 @@ }, \ .num_fmax = VDD_DIG_NUM +#define VDD_MM_PLL_FMAX_MAP1(l1, f1) \ + .vdd_class = &vdd_mmsscc_mx, \ + .fmax = (unsigned long[VDD_DIG_NUM]) { \ + [VDD_DIG_##l1] = (f1), \ + }, \ + .num_fmax = VDD_DIG_NUM + +#define VDD_MM_PLL_FMAX_MAP2(l1, f1, l2, f2) \ + .vdd_class = &vdd_mmsscc_mx, \ + .fmax = (unsigned long[VDD_DIG_NUM]) { \ + [VDD_DIG_##l1] = (f1), \ + [VDD_DIG_##l2] = (f2), \ + }, \ + .num_fmax = VDD_DIG_NUM + + #define VDD_GPU_PLL_FMAX_MAP1(l1, f1) \ .vdd_class = &vdd_gpucc_mx, \ .fmax = (unsigned long[VDD_DIG_NUM]) { \ diff --git a/drivers/clk/qcom/gcc-msm8996.c b/drivers/clk/qcom/gcc-msm8996.c index a63680290219..a7b8ac07e73a 100644 --- a/drivers/clk/qcom/gcc-msm8996.c +++ b/drivers/clk/qcom/gcc-msm8996.c @@ -21,6 +21,7 @@ #include <linux/clk-provider.h> #include <linux/regmap.h> #include <linux/reset-controller.h> +#include <linux/clk.h> #include <dt-bindings/clock/qcom,gcc-msm8996.h> @@ -30,7 +31,6 @@ #include "clk-rcg.h" #include "clk-branch.h" #include "reset.h" -#include "gdsc.h" #define F(f, s, h, m, n) { (f), (s), (2 * (h) - 1), (m), (n) } @@ -48,14 +48,6 @@ enum { P_GPLL1_EARLY_DIV }; -static const struct parent_map gcc_sleep_clk_map[] = { - { P_SLEEP_CLK, 5 } -}; - -static const char * const gcc_sleep_clk[] = { - "sleep_clk" -}; - static const struct parent_map gcc_xo_gpll0_map[] = { { P_XO, 0 }, { P_GPLL0, 1 } @@ -284,71 +276,6 @@ static struct clk_alpha_pll_postdiv gpll4 = { }, }; -static const struct freq_tbl ftbl_system_noc_clk_src[] = { - F(19200000, P_XO, 1, 0, 0), - F(50000000, P_GPLL0_EARLY_DIV, 6, 0, 0), - F(100000000, P_GPLL0, 6, 0, 0), - F(150000000, P_GPLL0, 4, 0, 0), - F(200000000, P_GPLL0, 3, 0, 0), - F(240000000, P_GPLL0, 2.5, 0, 0), - { } -}; - -static struct clk_rcg2 system_noc_clk_src = { - .cmd_rcgr = 0x0401c, - .hid_width = 5, - .parent_map = gcc_xo_gpll0_gpll2_gpll3_gpll1_gpll2_early_gpll0_early_div_map, - .freq_tbl = ftbl_system_noc_clk_src, - .clkr.hw.init = &(struct clk_init_data){ - .name = "system_noc_clk_src", - .parent_names = gcc_xo_gpll0_gpll2_gpll3_gpll1_gpll2_early_gpll0_early_div, - .num_parents = 7, - .ops = &clk_rcg2_ops, - }, -}; - -static const struct freq_tbl ftbl_config_noc_clk_src[] = { - F(19200000, P_XO, 1, 0, 0), - F(37500000, P_GPLL0, 16, 0, 0), - F(75000000, P_GPLL0, 8, 0, 0), - { } -}; - -static struct clk_rcg2 config_noc_clk_src = { - .cmd_rcgr = 0x0500c, - .hid_width = 5, - .parent_map = gcc_xo_gpll0_map, - .freq_tbl = ftbl_config_noc_clk_src, - .clkr.hw.init = &(struct clk_init_data){ - .name = "config_noc_clk_src", - .parent_names = gcc_xo_gpll0, - .num_parents = 2, - .ops = &clk_rcg2_ops, - }, -}; - -static const struct freq_tbl ftbl_periph_noc_clk_src[] = { - F(19200000, P_XO, 1, 0, 0), - F(37500000, P_GPLL0, 16, 0, 0), - F(50000000, P_GPLL0, 12, 0, 0), - F(75000000, P_GPLL0, 8, 0, 0), - F(100000000, P_GPLL0, 6, 0, 0), - { } -}; - -static struct clk_rcg2 periph_noc_clk_src = { - .cmd_rcgr = 0x06014, - .hid_width = 5, - .parent_map = gcc_xo_gpll0_map, - .freq_tbl = ftbl_periph_noc_clk_src, - .clkr.hw.init = &(struct clk_init_data){ - .name = "periph_noc_clk_src", - .parent_names = gcc_xo_gpll0, - .num_parents = 2, - .ops = &clk_rcg2_ops, - }, -}; - static const struct freq_tbl ftbl_usb30_master_clk_src[] = { F(19200000, P_XO, 1, 0, 0), F(120000000, P_GPLL0, 5, 0, 0), @@ -464,10 +391,18 @@ static struct clk_rcg2 sdcc1_apps_clk_src = { }, }; +static struct freq_tbl ftbl_sdcc1_ice_core_clk_src[] = { + F(19200000, P_XO, 1, 0, 0), + F(150000000, P_GPLL0, 4, 0, 0), + F(300000000, P_GPLL0, 2, 0, 0), + { } +}; + static struct clk_rcg2 sdcc1_ice_core_clk_src = { .cmd_rcgr = 0x13024, .hid_width = 5, .parent_map = gcc_xo_gpll0_gpll4_gpll0_early_div_map, + .freq_tbl = ftbl_sdcc1_ice_core_clk_src, .clkr.hw.init = &(struct clk_init_data){ .name = "sdcc1_ice_core_clk_src", .parent_names = gcc_xo_gpll0_gpll4_gpll0_early_div, @@ -1104,18 +1039,6 @@ static struct clk_rcg2 tsif_ref_clk_src = { }, }; -static struct clk_rcg2 gcc_sleep_clk_src = { - .cmd_rcgr = 0x43014, - .hid_width = 5, - .parent_map = gcc_sleep_clk_map, - .clkr.hw.init = &(struct clk_init_data){ - .name = "gcc_sleep_clk_src", - .parent_names = gcc_sleep_clk, - .num_parents = 1, - .ops = &clk_rcg2_ops, - }, -}; - static struct clk_rcg2 hmss_rbcpr_clk_src = { .cmd_rcgr = 0x48040, .hid_width = 5, @@ -1230,10 +1153,18 @@ static struct clk_rcg2 ufs_axi_clk_src = { }, }; +static const struct freq_tbl ftbl_ufs_ice_core_clk_src[] = { + F(19200000, P_XO, 1, 0, 0), + F(150000000, P_GPLL0, 4, 0, 0), + F(300000000, P_GPLL0, 2, 0, 0), + { } +}; + static struct clk_rcg2 ufs_ice_core_clk_src = { .cmd_rcgr = 0x76014, .hid_width = 5, .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_ufs_ice_core_clk_src, .clkr.hw.init = &(struct clk_init_data){ .name = "ufs_ice_core_clk_src", .parent_names = gcc_xo_gpll0, @@ -1242,10 +1173,19 @@ static struct clk_rcg2 ufs_ice_core_clk_src = { }, }; +static const struct freq_tbl ftbl_qspi_ser_clk_src[] = { + F(75000000, P_GPLL0, 8, 0, 0), + F(150000000, P_GPLL0, 4, 0, 0), + F(256000000, P_GPLL4, 1.5, 0, 0), + F(300000000, P_GPLL0, 2, 0, 0), + { } +}; + static struct clk_rcg2 qspi_ser_clk_src = { .cmd_rcgr = 0x8b00c, .hid_width = 5, .parent_map = gcc_xo_gpll0_gpll1_early_div_gpll1_gpll4_gpll0_early_div_map, + .freq_tbl = ftbl_qspi_ser_clk_src, .clkr.hw.init = &(struct clk_init_data){ .name = "qspi_ser_clk_src", .parent_names = gcc_xo_gpll0_gpll1_early_div_gpll1_gpll4_gpll0_early_div, @@ -1306,9 +1246,6 @@ static struct clk_branch gcc_mmss_noc_cfg_ahb_clk = { .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_mmss_noc_cfg_ahb_clk", - .parent_names = (const char *[]){ "config_noc_clk_src" }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, .ops = &clk_branch2_ops, }, }, @@ -1316,12 +1253,12 @@ static struct clk_branch gcc_mmss_noc_cfg_ahb_clk = { static struct clk_branch gcc_mmss_bimc_gfx_clk = { .halt_reg = 0x9010, + .halt_check = BRANCH_HALT_NO_CHECK_ON_DISABLE, .clkr = { .enable_reg = 0x9010, .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_mmss_bimc_gfx_clk", - .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -1349,9 +1286,6 @@ static struct clk_branch gcc_usb30_sleep_clk = { .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_usb30_sleep_clk", - .parent_names = (const char *[]){ "gcc_sleep_clk_src" }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -1387,17 +1321,26 @@ static struct clk_branch gcc_usb3_phy_aux_clk = { }, }; -static struct clk_branch gcc_usb3_phy_pipe_clk = { - .halt_reg = 0x50004, +static struct clk_gate2 gcc_usb3_phy_pipe_clk = { + .udelay = 50, .clkr = { .enable_reg = 0x50004, .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_usb3_phy_pipe_clk", - .parent_names = (const char *[]){ "usb3_phy_pipe_clk_src" }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, - .ops = &clk_branch2_ops, + .ops = &clk_gate2_ops, + }, + }, +}; + +static struct clk_gate2 gpll0_out_msscc = { + .udelay = 1, + .clkr = { + .enable_reg = 0x5200c, + .enable_mask = BIT(2), + .hw.init = &(struct clk_init_data){ + .name = "gpll0_out_msscc", + .ops = &clk_gate2_ops, }, }, }; @@ -1424,9 +1367,6 @@ static struct clk_branch gcc_usb20_sleep_clk = { .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_usb20_sleep_clk", - .parent_names = (const char *[]){ "gcc_sleep_clk_src" }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -1454,9 +1394,6 @@ static struct clk_branch gcc_usb_phy_cfg_ahb2phy_clk = { .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_usb_phy_cfg_ahb2phy_clk", - .parent_names = (const char *[]){ "periph_noc_clk_src" }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -1484,9 +1421,6 @@ static struct clk_branch gcc_sdcc1_ahb_clk = { .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_sdcc1_ahb_clk", - .parent_names = (const char *[]){ "periph_noc_clk_src" }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -1529,9 +1463,6 @@ static struct clk_branch gcc_sdcc2_ahb_clk = { .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_sdcc2_ahb_clk", - .parent_names = (const char *[]){ "periph_noc_clk_src" }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -1559,9 +1490,6 @@ static struct clk_branch gcc_sdcc3_ahb_clk = { .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_sdcc3_ahb_clk", - .parent_names = (const char *[]){ "periph_noc_clk_src" }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -1589,9 +1517,6 @@ static struct clk_branch gcc_sdcc4_ahb_clk = { .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_sdcc4_ahb_clk", - .parent_names = (const char *[]){ "periph_noc_clk_src" }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -1605,9 +1530,6 @@ static struct clk_branch gcc_blsp1_ahb_clk = { .enable_mask = BIT(17), .hw.init = &(struct clk_init_data){ .name = "gcc_blsp1_ahb_clk", - .parent_names = (const char *[]){ "periph_noc_clk_src" }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -1621,9 +1543,6 @@ static struct clk_branch gcc_blsp1_sleep_clk = { .enable_mask = BIT(16), .hw.init = &(struct clk_init_data){ .name = "gcc_blsp1_sleep_clk", - .parent_names = (const char *[]){ "gcc_sleep_clk_src" }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -1907,9 +1826,6 @@ static struct clk_branch gcc_blsp2_ahb_clk = { .enable_mask = BIT(15), .hw.init = &(struct clk_init_data){ .name = "gcc_blsp2_ahb_clk", - .parent_names = (const char *[]){ "periph_noc_clk_src" }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -1923,9 +1839,6 @@ static struct clk_branch gcc_blsp2_sleep_clk = { .enable_mask = BIT(14), .hw.init = &(struct clk_init_data){ .name = "gcc_blsp2_sleep_clk", - .parent_names = (const char *[]){ "gcc_sleep_clk_src" }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -2208,9 +2121,6 @@ static struct clk_branch gcc_pdm_ahb_clk = { .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_pdm_ahb_clk", - .parent_names = (const char *[]){ "periph_noc_clk_src" }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -2239,9 +2149,6 @@ static struct clk_branch gcc_prng_ahb_clk = { .enable_mask = BIT(13), .hw.init = &(struct clk_init_data){ .name = "gcc_prng_ahb_clk", - .parent_names = (const char *[]){ "config_noc_clk_src" }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -2254,9 +2161,6 @@ static struct clk_branch gcc_tsif_ahb_clk = { .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_tsif_ahb_clk", - .parent_names = (const char *[]){ "periph_noc_clk_src" }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -2277,21 +2181,6 @@ static struct clk_branch gcc_tsif_ref_clk = { }, }; -static struct clk_branch gcc_tsif_inactivity_timers_clk = { - .halt_reg = 0x3600c, - .clkr = { - .enable_reg = 0x3600c, - .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data){ - .name = "gcc_tsif_inactivity_timers_clk", - .parent_names = (const char *[]){ "gcc_sleep_clk_src" }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, - .ops = &clk_branch2_ops, - }, - }, -}; - static struct clk_branch gcc_boot_rom_ahb_clk = { .halt_reg = 0x38004, .halt_check = BRANCH_HALT_VOTED, @@ -2300,9 +2189,6 @@ static struct clk_branch gcc_boot_rom_ahb_clk = { .enable_mask = BIT(10), .hw.init = &(struct clk_init_data){ .name = "gcc_boot_rom_ahb_clk", - .parent_names = (const char *[]){ "config_noc_clk_src" }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -2315,7 +2201,6 @@ static struct clk_branch gcc_bimc_gfx_clk = { .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_bimc_gfx_clk", - .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -2388,9 +2273,6 @@ static struct clk_branch gcc_pcie_0_slv_axi_clk = { .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_pcie_0_slv_axi_clk", - .parent_names = (const char *[]){ "system_noc_clk_src" }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -2403,9 +2285,6 @@ static struct clk_branch gcc_pcie_0_mstr_axi_clk = { .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_pcie_0_mstr_axi_clk", - .parent_names = (const char *[]){ "system_noc_clk_src" }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -2418,9 +2297,6 @@ static struct clk_branch gcc_pcie_0_cfg_ahb_clk = { .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_pcie_0_cfg_ahb_clk", - .parent_names = (const char *[]){ "config_noc_clk_src" }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -2441,17 +2317,14 @@ static struct clk_branch gcc_pcie_0_aux_clk = { }, }; -static struct clk_branch gcc_pcie_0_pipe_clk = { - .halt_reg = 0x6b018, +static struct clk_gate2 gcc_pcie_0_pipe_clk = { + .udelay = 500, .clkr = { .enable_reg = 0x6b018, .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_pcie_0_pipe_clk", - .parent_names = (const char *[]){ "pcie_0_pipe_clk_src" }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, - .ops = &clk_branch2_ops, + .ops = &clk_gate2_ops, }, }, }; @@ -2463,9 +2336,6 @@ static struct clk_branch gcc_pcie_1_slv_axi_clk = { .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_pcie_1_slv_axi_clk", - .parent_names = (const char *[]){ "system_noc_clk_src" }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -2478,9 +2348,6 @@ static struct clk_branch gcc_pcie_1_mstr_axi_clk = { .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_pcie_1_mstr_axi_clk", - .parent_names = (const char *[]){ "system_noc_clk_src" }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -2493,9 +2360,6 @@ static struct clk_branch gcc_pcie_1_cfg_ahb_clk = { .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_pcie_1_cfg_ahb_clk", - .parent_names = (const char *[]){ "config_noc_clk_src" }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -2516,17 +2380,14 @@ static struct clk_branch gcc_pcie_1_aux_clk = { }, }; -static struct clk_branch gcc_pcie_1_pipe_clk = { - .halt_reg = 0x6d018, +static struct clk_gate2 gcc_pcie_1_pipe_clk = { + .udelay = 500, .clkr = { .enable_reg = 0x6d018, .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_pcie_1_pipe_clk", - .parent_names = (const char *[]){ "pcie_1_pipe_clk_src" }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, - .ops = &clk_branch2_ops, + .ops = &clk_gate2_ops, }, }, }; @@ -2538,9 +2399,6 @@ static struct clk_branch gcc_pcie_2_slv_axi_clk = { .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_pcie_2_slv_axi_clk", - .parent_names = (const char *[]){ "system_noc_clk_src" }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -2553,9 +2411,6 @@ static struct clk_branch gcc_pcie_2_mstr_axi_clk = { .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_pcie_2_mstr_axi_clk", - .parent_names = (const char *[]){ "system_noc_clk_src" }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -2568,9 +2423,6 @@ static struct clk_branch gcc_pcie_2_cfg_ahb_clk = { .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_pcie_2_cfg_ahb_clk", - .parent_names = (const char *[]){ "config_noc_clk_src" }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -2591,17 +2443,14 @@ static struct clk_branch gcc_pcie_2_aux_clk = { }, }; -static struct clk_branch gcc_pcie_2_pipe_clk = { - .halt_reg = 0x6e108, +static struct clk_gate2 gcc_pcie_2_pipe_clk = { + .udelay = 500, .clkr = { - .enable_reg = 0x6e108, + .enable_reg = 0x6e018, .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_pcie_2_pipe_clk", - .parent_names = (const char *[]){ "pcie_2_pipe_clk_src" }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, - .ops = &clk_branch2_ops, + .ops = &clk_gate2_ops, }, }, }; @@ -2613,9 +2462,6 @@ static struct clk_branch gcc_pcie_phy_cfg_ahb_clk = { .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_pcie_phy_cfg_ahb_clk", - .parent_names = (const char *[]){ "config_noc_clk_src" }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -2658,9 +2504,6 @@ static struct clk_branch gcc_ufs_ahb_clk = { .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_ufs_ahb_clk", - .parent_names = (const char *[]){ "config_noc_clk_src" }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -2720,47 +2563,39 @@ static struct clk_branch gcc_ufs_rx_cfg_clk = { }, }; -static struct clk_branch gcc_ufs_tx_symbol_0_clk = { - .halt_reg = 0x75018, +static struct clk_gate2 gcc_ufs_tx_symbol_0_clk = { + .udelay = 500, .clkr = { .enable_reg = 0x75018, .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_ufs_tx_symbol_0_clk", - .parent_names = (const char *[]){ "ufs_tx_symbol_0_clk_src" }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, - .ops = &clk_branch2_ops, + .ops = &clk_gate2_ops, }, }, }; -static struct clk_branch gcc_ufs_rx_symbol_0_clk = { - .halt_reg = 0x7501c, +static struct clk_gate2 gcc_ufs_rx_symbol_0_clk = { + .udelay = 500, .clkr = { .enable_reg = 0x7501c, .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_ufs_rx_symbol_0_clk", - .parent_names = (const char *[]){ "ufs_rx_symbol_0_clk_src" }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, - .ops = &clk_branch2_ops, + .ops = &clk_gate2_ops, }, }, }; -static struct clk_branch gcc_ufs_rx_symbol_1_clk = { - .halt_reg = 0x75020, +static struct clk_gate2 gcc_ufs_rx_symbol_1_clk = { + .udelay = 500, .clkr = { .enable_reg = 0x75020, .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_ufs_rx_symbol_1_clk", - .parent_names = (const char *[]){ "ufs_rx_symbol_1_clk_src" }, - .num_parents = 1, .flags = CLK_SET_RATE_PARENT, - .ops = &clk_branch2_ops, + .ops = &clk_gate2_ops, }, }, }; @@ -2807,26 +2642,26 @@ static struct clk_branch gcc_ufs_ice_core_clk = { }, }; -static struct clk_branch gcc_ufs_sys_clk_core_clk = { - .halt_check = BRANCH_HALT_DELAY, +static struct clk_gate2 gcc_ufs_sys_clk_core_clk = { + .udelay = 500, .clkr = { .enable_reg = 0x76030, .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_ufs_sys_clk_core_clk", - .ops = &clk_branch2_ops, + .ops = &clk_gate2_ops, }, }, }; -static struct clk_branch gcc_ufs_tx_symbol_clk_core_clk = { - .halt_check = BRANCH_HALT_DELAY, +static struct clk_gate2 gcc_ufs_tx_symbol_clk_core_clk = { + .udelay = 500, .clkr = { .enable_reg = 0x76034, .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_ufs_tx_symbol_clk_core_clk", - .ops = &clk_branch2_ops, + .ops = &clk_gate2_ops, }, }, }; @@ -2838,9 +2673,6 @@ static struct clk_branch gcc_aggre0_snoc_axi_clk = { .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_aggre0_snoc_axi_clk", - .parent_names = (const char *[]){ "system_noc_clk_src" }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -2853,9 +2685,6 @@ static struct clk_branch gcc_aggre0_cnoc_ahb_clk = { .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_aggre0_cnoc_ahb_clk", - .parent_names = (const char *[]){ "config_noc_clk_src" }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -2863,29 +2692,37 @@ static struct clk_branch gcc_aggre0_cnoc_ahb_clk = { static struct clk_branch gcc_smmu_aggre0_axi_clk = { .halt_reg = 0x81014, + .halt_check = BRANCH_HALT_NO_CHECK_ON_DISABLE, .clkr = { .enable_reg = 0x81014, .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_smmu_aggre0_axi_clk", - .parent_names = (const char *[]){ "system_noc_clk_src" }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, }; +static struct clk_gate2 gcc_aggre0_noc_qosgen_extref_clk = { + .udelay = 500, + .clkr = { + .enable_reg = 0x8101c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_aggre0_noc_qosgen_extref_clk", + .ops = &clk_gate2_ops, + }, + }, +}; + static struct clk_branch gcc_smmu_aggre0_ahb_clk = { .halt_reg = 0x81018, + .halt_check = BRANCH_HALT_NO_CHECK_ON_DISABLE, .clkr = { .enable_reg = 0x81018, .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_smmu_aggre0_ahb_clk", - .parent_names = (const char *[]){ "config_noc_clk_src" }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -2898,9 +2735,6 @@ static struct clk_branch gcc_aggre1_pnoc_ahb_clk = { .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_aggre1_pnoc_ahb_clk", - .parent_names = (const char *[]){ "periph_noc_clk_src" }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -2943,9 +2777,6 @@ static struct clk_branch gcc_qspi_ahb_clk = { .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_qspi_ahb_clk", - .parent_names = (const char *[]){ "periph_noc_clk_src" }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -2973,8 +2804,6 @@ static struct clk_branch gcc_usb3_clkref_clk = { .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_usb3_clkref_clk", - .parent_names = (const char *[]){ "xo" }, - .num_parents = 1, .ops = &clk_branch2_ops, }, }, @@ -2987,8 +2816,6 @@ static struct clk_branch gcc_hdmi_clkref_clk = { .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_hdmi_clkref_clk", - .parent_names = (const char *[]){ "xo" }, - .num_parents = 1, .ops = &clk_branch2_ops, }, }, @@ -3001,8 +2828,6 @@ static struct clk_branch gcc_ufs_clkref_clk = { .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_ufs_clkref_clk", - .parent_names = (const char *[]){ "xo" }, - .num_parents = 1, .ops = &clk_branch2_ops, }, }, @@ -3015,8 +2840,6 @@ static struct clk_branch gcc_pcie_clkref_clk = { .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_pcie_clkref_clk", - .parent_names = (const char *[]){ "xo" }, - .num_parents = 1, .ops = &clk_branch2_ops, }, }, @@ -3029,8 +2852,6 @@ static struct clk_branch gcc_rx2_usb2_clkref_clk = { .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_rx2_usb2_clkref_clk", - .parent_names = (const char *[]){ "xo" }, - .num_parents = 1, .ops = &clk_branch2_ops, }, }, @@ -3043,96 +2864,142 @@ static struct clk_branch gcc_rx1_usb2_clkref_clk = { .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_rx1_usb2_clkref_clk", - .parent_names = (const char *[]){ "xo" }, - .num_parents = 1, .ops = &clk_branch2_ops, }, }, }; -static struct clk_hw *gcc_msm8996_hws[] = { - &xo.hw, - &gpll0_early_div.hw, - &ufs_tx_cfg_clk_src.hw, - &ufs_rx_cfg_clk_src.hw, - &ufs_ice_core_postdiv_clk_src.hw, +static struct clk_branch hlos1_vote_lpass_core_smmu_clk = { + .halt_reg = 0x7d010, + .halt_check = BRANCH_HALT_NO_CHECK_ON_DISABLE, + .clkr = { + .enable_reg = 0x7d010, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "hlos1_vote_lpass_core_smmu_clk", + .ops = &clk_branch2_ops, + }, + }, }; -static struct gdsc aggre0_noc_gdsc = { - .gdscr = 0x81004, - .gds_hw_ctrl = 0x81028, - .pd = { - .name = "aggre0_noc", +static struct clk_branch hlos1_vote_lpass_adsp_smmu_clk = { + .halt_reg = 0x7d014, + .halt_check = BRANCH_HALT_NO_CHECK_ON_DISABLE, + .clkr = { + .enable_reg = 0x7d014, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "hlos1_vote_lpass_adsp_smmu_clk", + .ops = &clk_branch2_ops, + }, }, - .pwrsts = PWRSTS_OFF_ON, - .flags = VOTABLE, }; -static struct gdsc hlos1_vote_aggre0_noc_gdsc = { - .gdscr = 0x7d024, - .pd = { - .name = "hlos1_vote_aggre0_noc", +static struct clk_branch gcc_edp_clkref_clk = { + .halt_reg = 0x88004, + .clkr = { + .enable_reg = 0x88004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_edp_clkref_clk", + .ops = &clk_branch2_ops, + }, }, - .pwrsts = PWRSTS_OFF_ON, - .flags = VOTABLE, }; -static struct gdsc hlos1_vote_lpass_adsp_gdsc = { - .gdscr = 0x7d034, - .pd = { - .name = "hlos1_vote_lpass_adsp", +static struct clk_branch gcc_mss_cfg_ahb_clk = { + .halt_reg = 0x8a000, + .clkr = { + .enable_reg = 0x8a000, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_mss_cfg_ahb_clk", + .ops = &clk_branch2_ops, + }, }, - .pwrsts = PWRSTS_OFF_ON, - .flags = VOTABLE, }; -static struct gdsc hlos1_vote_lpass_core_gdsc = { - .gdscr = 0x7d038, - .pd = { - .name = "hlos1_vote_lpass_core", +static struct clk_branch gcc_mss_q6_bimc_axi_clk = { + .halt_reg = 0x8a028, + .clkr = { + .enable_reg = 0x8a028, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_mss_q6_bimc_axi_clk", + .ops = &clk_branch2_ops, + }, }, - .pwrsts = PWRSTS_OFF_ON, - .flags = VOTABLE, }; -static struct gdsc usb30_gdsc = { - .gdscr = 0xf004, - .pd = { - .name = "usb30", +static struct clk_branch gcc_mss_snoc_axi_clk = { + .halt_reg = 0x8a024, + .clkr = { + .enable_reg = 0x8a024, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_mss_snoc_axi_clk", + .ops = &clk_branch2_ops, + }, }, - .pwrsts = PWRSTS_OFF_ON, }; -static struct gdsc pcie0_gdsc = { - .gdscr = 0x6b004, - .pd = { - .name = "pcie0", +static struct clk_branch gcc_mss_mnoc_bimc_axi_clk = { + .halt_reg = 0x8a004, + .clkr = { + .enable_reg = 0x8a004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_mss_mnoc_bimc_axi_clk", + .ops = &clk_branch2_ops, + }, }, - .pwrsts = PWRSTS_OFF_ON, }; -static struct gdsc pcie1_gdsc = { - .gdscr = 0x6d004, - .pd = { - .name = "pcie1", +static struct clk_branch gcc_dcc_ahb_clk = { + .halt_reg = 0x84004, + .clkr = { + .enable_reg = 0x84004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_dcc_ahb_clk", + .ops = &clk_branch2_ops, + }, }, - .pwrsts = PWRSTS_OFF_ON, }; -static struct gdsc pcie2_gdsc = { - .gdscr = 0x6e004, - .pd = { - .name = "pcie2", +static struct clk_branch gcc_aggre0_noc_mpu_cfg_ahb_clk = { + .halt_reg = 0x85000, + .clkr = { + .enable_reg = 0x85000, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_aggre0_noc_mpu_cfg_ahb_clk", + .ops = &clk_branch2_ops, + }, }, - .pwrsts = PWRSTS_OFF_ON, }; -static struct gdsc ufs_gdsc = { - .gdscr = 0x75004, - .pd = { - .name = "ufs", +static struct clk_branch gcc_mmss_gpll0_div_clk = { + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x5200c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_mmss_gpll0_div_clk", + .parent_names = (const char *[]){ "gpll0" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, }, - .pwrsts = PWRSTS_OFF_ON, +}; + +static struct clk_hw *gcc_msm8996_hws[] = { + &xo.hw, + &gpll0_early_div.hw, + &ufs_tx_cfg_clk_src.hw, + &ufs_rx_cfg_clk_src.hw, + &ufs_ice_core_postdiv_clk_src.hw, }; static struct clk_regmap *gcc_msm8996_clocks[] = { @@ -3140,9 +3007,6 @@ static struct clk_regmap *gcc_msm8996_clocks[] = { [GPLL0] = &gpll0.clkr, [GPLL4_EARLY] = &gpll4_early.clkr, [GPLL4] = &gpll4.clkr, - [SYSTEM_NOC_CLK_SRC] = &system_noc_clk_src.clkr, - [CONFIG_NOC_CLK_SRC] = &config_noc_clk_src.clkr, - [PERIPH_NOC_CLK_SRC] = &periph_noc_clk_src.clkr, [USB30_MASTER_CLK_SRC] = &usb30_master_clk_src.clkr, [USB30_MOCK_UTMI_CLK_SRC] = &usb30_mock_utmi_clk_src.clkr, [USB3_PHY_AUX_CLK_SRC] = &usb3_phy_aux_clk_src.clkr, @@ -3191,7 +3055,6 @@ static struct clk_regmap *gcc_msm8996_clocks[] = { [BLSP2_UART6_APPS_CLK_SRC] = &blsp2_uart6_apps_clk_src.clkr, [PDM2_CLK_SRC] = &pdm2_clk_src.clkr, [TSIF_REF_CLK_SRC] = &tsif_ref_clk_src.clkr, - [GCC_SLEEP_CLK_SRC] = &gcc_sleep_clk_src.clkr, [HMSS_RBCPR_CLK_SRC] = &hmss_rbcpr_clk_src.clkr, [HMSS_GPLL0_CLK_SRC] = &hmss_gpll0_clk_src.clkr, [GP1_CLK_SRC] = &gp1_clk_src.clkr, @@ -3269,7 +3132,6 @@ static struct clk_regmap *gcc_msm8996_clocks[] = { [GCC_PRNG_AHB_CLK] = &gcc_prng_ahb_clk.clkr, [GCC_TSIF_AHB_CLK] = &gcc_tsif_ahb_clk.clkr, [GCC_TSIF_REF_CLK] = &gcc_tsif_ref_clk.clkr, - [GCC_TSIF_INACTIVITY_TIMERS_CLK] = &gcc_tsif_inactivity_timers_clk.clkr, [GCC_BOOT_ROM_AHB_CLK] = &gcc_boot_rom_ahb_clk.clkr, [GCC_BIMC_GFX_CLK] = &gcc_bimc_gfx_clk.clkr, [GCC_HMSS_RBCPR_CLK] = &gcc_hmss_rbcpr_clk.clkr, @@ -3319,18 +3181,21 @@ static struct clk_regmap *gcc_msm8996_clocks[] = { [GCC_PCIE_CLKREF_CLK] = &gcc_pcie_clkref_clk.clkr, [GCC_RX2_USB2_CLKREF_CLK] = &gcc_rx2_usb2_clkref_clk.clkr, [GCC_RX1_USB2_CLKREF_CLK] = &gcc_rx1_usb2_clkref_clk.clkr, -}; - -static struct gdsc *gcc_msm8996_gdscs[] = { - [AGGRE0_NOC_GDSC] = &aggre0_noc_gdsc, - [HLOS1_VOTE_AGGRE0_NOC_GDSC] = &hlos1_vote_aggre0_noc_gdsc, - [HLOS1_VOTE_LPASS_ADSP_GDSC] = &hlos1_vote_lpass_adsp_gdsc, - [HLOS1_VOTE_LPASS_CORE_GDSC] = &hlos1_vote_lpass_core_gdsc, - [USB30_GDSC] = &usb30_gdsc, - [PCIE0_GDSC] = &pcie0_gdsc, - [PCIE1_GDSC] = &pcie1_gdsc, - [PCIE2_GDSC] = &pcie2_gdsc, - [UFS_GDSC] = &ufs_gdsc, + [GCC_AGGRE0_NOC_QOSGEN_EXTREF_CLK] = + &gcc_aggre0_noc_qosgen_extref_clk.clkr, + [GCC_HLOS1_VOTE_LPASS_CORE_SMMU_CLK] = + &hlos1_vote_lpass_core_smmu_clk.clkr, + [GCC_HLOS1_VOTE_LPASS_ADSP_SMMU_CLK] = + &hlos1_vote_lpass_adsp_smmu_clk.clkr, + [GCC_EDP_CLKREF_CLK] = &gcc_edp_clkref_clk.clkr, + [GCC_MSS_CFG_AHB_CLK] = &gcc_mss_cfg_ahb_clk.clkr, + [GCC_MSS_Q6_BIMC_AXI_CLK] = &gcc_mss_q6_bimc_axi_clk.clkr, + [GCC_MSS_SNOC_AXI_CLK] = &gcc_mss_snoc_axi_clk.clkr, + [GCC_MSS_MNOC_BIMC_AXI_CLK] = &gcc_mss_mnoc_bimc_axi_clk.clkr, + [GCC_DCC_AHB_ALK] = &gcc_dcc_ahb_clk.clkr, + [GCC_AGGRE0_NOC_MPU_CFG_AHB_CLK] = &gcc_aggre0_noc_mpu_cfg_ahb_clk.clkr, + [GCC_MMSS_GPLL0_DIV_CLK] = &gcc_mmss_gpll0_div_clk.clkr, + [GPLL0_OUT_MSSCC] = &gpll0_out_msscc.clkr, }; static const struct qcom_reset_map gcc_msm8996_resets[] = { @@ -3455,8 +3320,6 @@ static const struct qcom_cc_desc gcc_msm8996_desc = { .num_clks = ARRAY_SIZE(gcc_msm8996_clocks), .resets = gcc_msm8996_resets, .num_resets = ARRAY_SIZE(gcc_msm8996_resets), - .gdscs = gcc_msm8996_gdscs, - .num_gdscs = ARRAY_SIZE(gcc_msm8996_gdscs), }; static const struct of_device_id gcc_msm8996_match_table[] = { @@ -3469,18 +3332,15 @@ static int gcc_msm8996_probe(struct platform_device *pdev) { struct clk *clk; struct device *dev = &pdev->dev; - int i; + int i, ret = 0; struct regmap *regmap; regmap = qcom_cc_map(pdev, &gcc_msm8996_desc); if (IS_ERR(regmap)) return PTR_ERR(regmap); - /* - * Set the HMSS_AHB_CLK_SLEEP_ENA bit to allow the hmss_ahb_clk to be - * turned off by hardware during certain apps low power modes. - */ - regmap_update_bits(regmap, 0x52008, BIT(21), BIT(21)); + /* Set the HMSS_AHB_CLK_ENA bit to enable the hmss_ahb_clk */ + regmap_update_bits(regmap, 0x52004, BIT(21), BIT(21)); for (i = 0; i < ARRAY_SIZE(gcc_msm8996_hws); i++) { clk = devm_clk_register(dev, gcc_msm8996_hws[i]); @@ -3488,7 +3348,19 @@ static int gcc_msm8996_probe(struct platform_device *pdev) return PTR_ERR(clk); } - return qcom_cc_really_probe(pdev, &gcc_msm8996_desc, regmap); + ret = qcom_cc_really_probe(pdev, &gcc_msm8996_desc, regmap); + + if (ret) { + dev_err(&pdev->dev, "Failed to register GCC clocks\n"); + return ret; + } + + /* This clock is used for all MMSS register access */ + clk_prepare_enable(gcc_mmss_noc_cfg_ahb_clk.clkr.hw.clk); + + dev_info(&pdev->dev, "Registered GCC clocks\n"); + + return ret; } static struct platform_driver gcc_msm8996_driver = { diff --git a/drivers/crypto/msm/qce50.c b/drivers/crypto/msm/qce50.c index 61f99370863d..9b42e5ae129a 100644 --- a/drivers/crypto/msm/qce50.c +++ b/drivers/crypto/msm/qce50.c @@ -84,6 +84,8 @@ static LIST_HEAD(qce50_bam_list); /* Index to point the dummy request */ #define DUMMY_REQ_INDEX MAX_QCE_BAM_REQ +#define TOTAL_IOVEC_SPACE_PER_PIPE (QCE_MAX_NUM_DSCR * sizeof(struct sps_iovec)) + enum qce_owner { QCE_OWNER_NONE = 0, QCE_OWNER_CLIENT = 1, @@ -110,6 +112,8 @@ struct qce_device { unsigned char *coh_vmem; /* Allocated coherent virtual memory */ dma_addr_t coh_pmem; /* Allocated coherent physical memory */ int memsize; /* Memory allocated */ + unsigned char *iovec_vmem; /* Allocate iovec virtual memory */ + int iovec_memsize; /* Memory allocated */ uint32_t bam_mem; /* bam physical address, from DT */ uint32_t bam_mem_size; /* bam io size, from DT */ int is_shared; /* CE HW is shared */ @@ -4299,24 +4303,30 @@ static int qce_setup_ce_sps_data(struct qce_device *pce_dev) { unsigned char *vaddr; int i; + unsigned char *iovec_vaddr; + int iovec_memsize; vaddr = pce_dev->coh_vmem; vaddr = (unsigned char *)ALIGN(((uintptr_t)vaddr), pce_dev->ce_bam_info.ce_burst_size); + iovec_vaddr = pce_dev->iovec_vmem; + iovec_memsize = pce_dev->iovec_memsize; for (i = 0; i < MAX_QCE_ALLOC_BAM_REQ; i++) { /* Allow for 256 descriptor (cmd and data) entries per pipe */ pce_dev->ce_request_info[i].ce_sps.in_transfer.iovec = - (struct sps_iovec *)vaddr; + (struct sps_iovec *)iovec_vaddr; pce_dev->ce_request_info[i].ce_sps.in_transfer.iovec_phys = - (uintptr_t)GET_PHYS_ADDR(vaddr); - vaddr += QCE_MAX_NUM_DSCR * sizeof(struct sps_iovec); - + virt_to_phys(pce_dev->ce_request_info[i]. + ce_sps.in_transfer.iovec); + iovec_vaddr += TOTAL_IOVEC_SPACE_PER_PIPE; + iovec_memsize -= TOTAL_IOVEC_SPACE_PER_PIPE; pce_dev->ce_request_info[i].ce_sps.out_transfer.iovec = - (struct sps_iovec *)vaddr; + (struct sps_iovec *)iovec_vaddr; pce_dev->ce_request_info[i].ce_sps.out_transfer.iovec_phys = - (uintptr_t)GET_PHYS_ADDR(vaddr); - vaddr += QCE_MAX_NUM_DSCR * sizeof(struct sps_iovec); - + virt_to_phys(pce_dev->ce_request_info[i]. + ce_sps.out_transfer.iovec); + iovec_vaddr += TOTAL_IOVEC_SPACE_PER_PIPE; + iovec_memsize -= TOTAL_IOVEC_SPACE_PER_PIPE; if (pce_dev->support_cmd_dscr) qce_setup_cmdlistptrs(pce_dev, i, &vaddr); vaddr = (unsigned char *)ALIGN(((uintptr_t)vaddr), @@ -4343,7 +4353,8 @@ static int qce_setup_ce_sps_data(struct qce_device *pce_dev) } pce_dev->dummyreq.in_buf = (uint8_t *)vaddr; vaddr += DUMMY_REQ_DATA_LEN; - if ((vaddr - pce_dev->coh_vmem) > pce_dev->memsize) + if ((vaddr - pce_dev->coh_vmem) > pce_dev->memsize || + iovec_memsize < 0) panic("qce50: Not enough coherent memory. Allocate %x , need %lx\n", pce_dev->memsize, (uintptr_t)vaddr - (uintptr_t)pce_dev->coh_vmem); @@ -5933,12 +5944,19 @@ void *qce_open(struct platform_device *pdev, int *rc) pce_dev->memsize = 10 * PAGE_SIZE * MAX_QCE_ALLOC_BAM_REQ; pce_dev->coh_vmem = dma_alloc_coherent(pce_dev->pdev, pce_dev->memsize, &pce_dev->coh_pmem, GFP_KERNEL); + if (pce_dev->coh_vmem == NULL) { *rc = -ENOMEM; pr_err("Can not allocate coherent memory for sps data\n"); goto err_iobase; } + pce_dev->iovec_memsize = TOTAL_IOVEC_SPACE_PER_PIPE * + MAX_QCE_ALLOC_BAM_REQ * 2; + pce_dev->iovec_vmem = kzalloc(pce_dev->iovec_memsize, GFP_KERNEL); + if (pce_dev->iovec_vmem == NULL) + goto err_mem; + *rc = __qce_init_clk(pce_dev); if (*rc) goto err_mem; @@ -5978,6 +5996,7 @@ err_enable_clk: __qce_deinit_clk(pce_dev); err_mem: + kfree(pce_dev->iovec_vmem); if (pce_dev->coh_vmem) dma_free_coherent(pce_dev->pdev, pce_dev->memsize, pce_dev->coh_vmem, pce_dev->coh_pmem); @@ -6008,6 +6027,7 @@ int qce_close(void *handle) if (pce_dev->coh_vmem) dma_free_coherent(pce_dev->pdev, pce_dev->memsize, pce_dev->coh_vmem, pce_dev->coh_pmem); + kfree(pce_dev->iovec_vmem); qce_disable_clk(pce_dev); __qce_deinit_clk(pce_dev); diff --git a/drivers/gpu/msm/kgsl_pool.c b/drivers/gpu/msm/kgsl_pool.c index 7967b19779db..f5402fdc7e57 100644 --- a/drivers/gpu/msm/kgsl_pool.c +++ b/drivers/gpu/msm/kgsl_pool.c @@ -197,7 +197,7 @@ _kgsl_pool_shrink(struct kgsl_page_pool *pool, int num_pages) * starting from higher order pool. */ static unsigned long -kgsl_pool_reduce(unsigned int target_pages) +kgsl_pool_reduce(unsigned int target_pages, bool exit) { int total_pages = 0; int i; @@ -210,6 +210,14 @@ kgsl_pool_reduce(unsigned int target_pages) for (i = (KGSL_NUM_POOLS - 1); i >= 0; i--) { pool = &kgsl_pools[i]; + /* + * Only reduce the pool sizes for pools which are allowed to + * allocate memory unless we are at close, in which case the + * reserved memory for all pools needs to be freed + */ + if (!pool->allocation_allowed && !exit) + continue; + total_pages -= pcount; nr_removed = total_pages - target_pages; @@ -418,7 +426,7 @@ kgsl_pool_shrink_scan_objects(struct shrinker *shrinker, int target_pages = (nr > total_pages) ? 0 : (total_pages - nr); /* Reduce pool size to target_pages */ - return kgsl_pool_reduce(target_pages); + return kgsl_pool_reduce(target_pages, false); } static unsigned long @@ -449,7 +457,7 @@ void kgsl_init_page_pools(void) void kgsl_exit_page_pools(void) { /* Release all pages in pools, if any.*/ - kgsl_pool_reduce(0); + kgsl_pool_reduce(0, true); /* Unregister shrinker */ unregister_shrinker(&kgsl_pool_shrinker); diff --git a/drivers/hwtracing/coresight/coresight-tpda.c b/drivers/hwtracing/coresight/coresight-tpda.c index e4e188fc67fc..c43d8596a203 100644 --- a/drivers/hwtracing/coresight/coresight-tpda.c +++ b/drivers/hwtracing/coresight/coresight-tpda.c @@ -94,6 +94,10 @@ static void __tpda_enable_pre_port(struct tpda_drvdata *drvdata) val = val | BIT(2); else val = val & ~BIT(2); + + /* Force ASYNC-VERSION-FREQTS sequence */ + val = val | BIT(21); + tpda_writel(drvdata, val, TPDA_CR); /* @@ -154,8 +158,6 @@ static void __tpda_enable_post_port(struct tpda_drvdata *drvdata) if (drvdata->freq_req_val) tpda_writel(drvdata, drvdata->freq_req_val, TPDA_FREQREQ_VAL); - else - tpda_writel(drvdata, 0x0, TPDA_FREQREQ_VAL); val = tpda_readl(drvdata, TPDA_CR); if (drvdata->freq_req) diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index b02abfc58aea..b9956170b909 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -1205,4 +1205,16 @@ config FT_SECURE_TOUCH If unsure, say N. +config TOUCHSCREEN_IT7260_I2C + tristate "IT7260 Touchscreen Driver" + depends on I2C + help + Say Y here if you have a IT7260 Touchscreen Driver + connected to your system. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called it7258_ts_i2c. + endif diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index e1777f11d77b..f448df5b234c 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile @@ -45,6 +45,7 @@ obj-$(CONFIG_TOUCHSCREEN_ILI210X) += ili210x.o obj-$(CONFIG_TOUCHSCREEN_IMX6UL_TSC) += imx6ul_tsc.o obj-$(CONFIG_TOUCHSCREEN_INEXIO) += inexio.o obj-$(CONFIG_TOUCHSCREEN_INTEL_MID) += intel-mid-touch.o +obj-$(CONFIG_TOUCHSCREEN_IT7260_I2C) += it7258_ts_i2c.o obj-$(CONFIG_TOUCHSCREEN_IPROC) += bcm_iproc_tsc.o obj-$(CONFIG_TOUCHSCREEN_LPC32XX) += lpc32xx_ts.o obj-$(CONFIG_TOUCHSCREEN_MAX11801) += max11801_ts.o diff --git a/drivers/input/touchscreen/gt9xx/gt9xx.c b/drivers/input/touchscreen/gt9xx/gt9xx.c index 6615c3a039a0..ebb9ce7ba6a4 100644 --- a/drivers/input/touchscreen/gt9xx/gt9xx.c +++ b/drivers/input/touchscreen/gt9xx/gt9xx.c @@ -40,8 +40,11 @@ * By Meta, 2013/06/08 */ +#include <linux/regulator/consumer.h> #include "gt9xx.h" +#include <linux/of_gpio.h> + #if GTP_ICS_SLOT_REPORT #include <linux/input/mt.h> #endif @@ -55,6 +58,15 @@ #define GTP_I2C_ADDRESS_HIGH 0x14 #define GTP_I2C_ADDRESS_LOW 0x5D +#define GOODIX_VTG_MIN_UV 2600000 +#define GOODIX_VTG_MAX_UV 3300000 +#define GOODIX_I2C_VTG_MIN_UV 1800000 +#define GOODIX_I2C_VTG_MAX_UV 1800000 +#define GOODIX_VDD_LOAD_MIN_UA 0 +#define GOODIX_VDD_LOAD_MAX_UA 10000 +#define GOODIX_VIO_LOAD_MIN_UA 0 +#define GOODIX_VIO_LOAD_MAX_UA 10000 + #define RESET_DELAY_T3_US 200 /* T3: > 100us */ #define RESET_DELAY_T4 20 /* T4: > 5ms */ @@ -80,7 +92,10 @@ static void gtp_reset_guitar(struct goodix_ts_data *ts, int ms); static void gtp_int_sync(struct goodix_ts_data *ts, int ms); static int gtp_i2c_test(struct i2c_client *client); -#ifdef CONFIG_HAS_EARLYSUSPEND +#if defined(CONFIG_FB) +static int fb_notifier_callback(struct notifier_block *self, + unsigned long event, void *data); +#elif defined(CONFIG_HAS_EARLYSUSPEND) static void goodix_ts_early_suspend(struct early_suspend *h); static void goodix_ts_late_resume(struct early_suspend *h); #endif @@ -755,7 +770,7 @@ static void gtp_reset_guitar(struct goodix_ts_data *ts, int ms) #endif } -#ifdef CONFIG_HAS_EARLYSUSPEND +#if defined(CONFIG_HAS_EARLYSUSPEND) || defined(CONFIG_FB) #if GTP_SLIDE_WAKEUP /******************************************************* Function: @@ -860,16 +875,12 @@ static s8 gtp_wakeup_sleep(struct goodix_ts_data *ts) GTP_DEBUG_FUNC(); #if GTP_POWER_CTRL_SLEEP - while (retry++ < 5) { - gtp_reset_guitar(ts, 20); + gtp_reset_guitar(ts, 20); - ret = gtp_send_cfg(ts); - if (ret > 0) { - dev_dbg(&ts->client->dev, - "Wakeup sleep send config success."); - continue; - } - dev_dbg(&ts->client->dev, "GTP Wakeup!"); + ret = gtp_send_cfg(ts); + if (ret > 0) { + dev_dbg(&ts->client->dev, + "Wakeup sleep send config success."); return 1; } #else @@ -910,7 +921,7 @@ static s8 gtp_wakeup_sleep(struct goodix_ts_data *ts) dev_err(&ts->client->dev, "GTP wakeup sleep failed.\n"); return ret; } -#endif /* !CONFIG_HAS_EARLYSUSPEND */ +#endif /* !CONFIG_HAS_EARLYSUSPEND && !CONFIG_FB*/ /******************************************************* Function: @@ -1014,21 +1025,27 @@ static int gtp_init_panel(struct goodix_ts_data *ts) return -EINVAL; } - config_data = devm_kzalloc(&client->dev, + if (ts->pdata->gtp_cfg_len) { + config_data = ts->pdata->config_data; + ts->config_data = ts->pdata->config_data; + ts->gtp_cfg_len = ts->pdata->gtp_cfg_len; + } else { + config_data = devm_kzalloc(&client->dev, GTP_CONFIG_MAX_LENGTH + GTP_ADDR_LENGTH, - GFP_KERNEL); - if (!config_data) { - dev_err(&client->dev, - "Not enough memory for panel config data\n"); - return -ENOMEM; - } + GFP_KERNEL); + if (!config_data) { + dev_err(&client->dev, + "Not enough memory for panel config data\n"); + return -ENOMEM; + } - ts->config_data = config_data; - config_data[0] = GTP_REG_CONFIG_DATA >> 8; - config_data[1] = GTP_REG_CONFIG_DATA & 0xff; - memset(&config_data[GTP_ADDR_LENGTH], 0, GTP_CONFIG_MAX_LENGTH); - memcpy(&config_data[GTP_ADDR_LENGTH], send_cfg_buf[sensor_id], - ts->gtp_cfg_len); + ts->config_data = config_data; + config_data[0] = GTP_REG_CONFIG_DATA >> 8; + config_data[1] = GTP_REG_CONFIG_DATA & 0xff; + memset(&config_data[GTP_ADDR_LENGTH], 0, GTP_CONFIG_MAX_LENGTH); + memcpy(&config_data[GTP_ADDR_LENGTH], send_cfg_buf[sensor_id], + ts->gtp_cfg_len); + } #if GTP_CUSTOM_CFG config_data[RESOLUTION_LOC] = @@ -1345,6 +1362,318 @@ exit_free_inputdev: return ret; } +static int reg_set_optimum_mode_check(struct regulator *reg, int load_uA) +{ + return (regulator_count_voltages(reg) > 0) ? + regulator_set_optimum_mode(reg, load_uA) : 0; +} + +/** + * goodix_power_on - Turn device power ON + * @ts: driver private data + * + * Returns zero on success, else an error. + */ +static int goodix_power_on(struct goodix_ts_data *ts) +{ + int ret; + + if (!IS_ERR(ts->avdd)) { + ret = reg_set_optimum_mode_check(ts->avdd, + GOODIX_VDD_LOAD_MAX_UA); + if (ret < 0) { + dev_err(&ts->client->dev, + "Regulator avdd set_opt failed rc=%d\n", ret); + goto err_set_opt_avdd; + } + ret = regulator_enable(ts->avdd); + if (ret) { + dev_err(&ts->client->dev, + "Regulator avdd enable failed ret=%d\n", ret); + goto err_enable_avdd; + } + } + + if (!IS_ERR(ts->vdd)) { + ret = regulator_set_voltage(ts->vdd, GOODIX_VTG_MIN_UV, + GOODIX_VTG_MAX_UV); + if (ret) { + dev_err(&ts->client->dev, + "Regulator set_vtg failed vdd ret=%d\n", ret); + goto err_set_vtg_vdd; + } + ret = reg_set_optimum_mode_check(ts->vdd, + GOODIX_VDD_LOAD_MAX_UA); + if (ret < 0) { + dev_err(&ts->client->dev, + "Regulator vdd set_opt failed rc=%d\n", ret); + goto err_set_opt_vdd; + } + ret = regulator_enable(ts->vdd); + if (ret) { + dev_err(&ts->client->dev, + "Regulator vdd enable failed ret=%d\n", ret); + goto err_enable_vdd; + } + } + + if (!IS_ERR(ts->vcc_i2c)) { + ret = regulator_set_voltage(ts->vcc_i2c, GOODIX_I2C_VTG_MIN_UV, + GOODIX_I2C_VTG_MAX_UV); + if (ret) { + dev_err(&ts->client->dev, + "Regulator set_vtg failed vcc_i2c ret=%d\n", + ret); + goto err_set_vtg_vcc_i2c; + } + ret = reg_set_optimum_mode_check(ts->vcc_i2c, + GOODIX_VIO_LOAD_MAX_UA); + if (ret < 0) { + dev_err(&ts->client->dev, + "Regulator vcc_i2c set_opt failed rc=%d\n", + ret); + goto err_set_opt_vcc_i2c; + } + ret = regulator_enable(ts->vcc_i2c); + if (ret) { + dev_err(&ts->client->dev, + "Regulator vcc_i2c enable failed ret=%d\n", + ret); + regulator_disable(ts->vdd); + goto err_enable_vcc_i2c; + } + } + + return 0; + +err_enable_vcc_i2c: +err_set_opt_vcc_i2c: + if (!IS_ERR(ts->vcc_i2c)) + regulator_set_voltage(ts->vcc_i2c, 0, GOODIX_I2C_VTG_MAX_UV); +err_set_vtg_vcc_i2c: + if (!IS_ERR(ts->vdd)) + regulator_disable(ts->vdd); +err_enable_vdd: +err_set_opt_vdd: + if (!IS_ERR(ts->vdd)) + regulator_set_voltage(ts->vdd, 0, GOODIX_VTG_MAX_UV); +err_set_vtg_vdd: + if (!IS_ERR(ts->avdd)) + regulator_disable(ts->avdd); +err_enable_avdd: +err_set_opt_avdd: + return ret; +} + +/** + * goodix_power_off - Turn device power OFF + * @ts: driver private data + * + * Returns zero on success, else an error. + */ +static int goodix_power_off(struct goodix_ts_data *ts) +{ + int ret; + + if (!IS_ERR(ts->vcc_i2c)) { + ret = regulator_set_voltage(ts->vcc_i2c, 0, + GOODIX_I2C_VTG_MAX_UV); + if (ret < 0) + dev_err(&ts->client->dev, + "Regulator vcc_i2c set_vtg failed ret=%d\n", + ret); + ret = regulator_disable(ts->vcc_i2c); + if (ret) + dev_err(&ts->client->dev, + "Regulator vcc_i2c disable failed ret=%d\n", + ret); + } + + if (!IS_ERR(ts->vdd)) { + ret = regulator_set_voltage(ts->vdd, 0, GOODIX_VTG_MAX_UV); + if (ret < 0) + dev_err(&ts->client->dev, + "Regulator vdd set_vtg failed ret=%d\n", ret); + ret = regulator_disable(ts->vdd); + if (ret) + dev_err(&ts->client->dev, + "Regulator vdd disable failed ret=%d\n", ret); + } + + if (!IS_ERR(ts->avdd)) { + ret = regulator_disable(ts->avdd); + if (ret) + dev_err(&ts->client->dev, + "Regulator avdd disable failed ret=%d\n", ret); + } + + return 0; +} + +/** + * goodix_power_init - Initialize device power + * @ts: driver private data + * + * Returns zero on success, else an error. + */ +static int goodix_power_init(struct goodix_ts_data *ts) +{ + int ret; + + ts->avdd = regulator_get(&ts->client->dev, "avdd"); + if (IS_ERR(ts->avdd)) { + ret = PTR_ERR(ts->avdd); + dev_info(&ts->client->dev, + "Regulator get failed avdd ret=%d\n", ret); + } + + ts->vdd = regulator_get(&ts->client->dev, "vdd"); + if (IS_ERR(ts->vdd)) { + ret = PTR_ERR(ts->vdd); + dev_info(&ts->client->dev, + "Regulator get failed vdd ret=%d\n", ret); + } + + ts->vcc_i2c = regulator_get(&ts->client->dev, "vcc-i2c"); + if (IS_ERR(ts->vcc_i2c)) { + ret = PTR_ERR(ts->vcc_i2c); + dev_info(&ts->client->dev, + "Regulator get failed vcc_i2c ret=%d\n", ret); + } + + return 0; +} + +/** + * goodix_power_deinit - Deinitialize device power + * @ts: driver private data + * + * Returns zero on success, else an error. + */ +static int goodix_power_deinit(struct goodix_ts_data *ts) +{ + regulator_put(ts->vdd); + regulator_put(ts->vcc_i2c); + regulator_put(ts->avdd); + + return 0; +} + +static int goodix_ts_get_dt_coords(struct device *dev, char *name, + struct goodix_ts_platform_data *pdata) +{ + struct property *prop; + struct device_node *np = dev->of_node; + int rc; + u32 coords[GOODIX_COORDS_ARR_SIZE]; + + prop = of_find_property(np, name, NULL); + if (!prop) + return -EINVAL; + if (!prop->value) + return -ENODATA; + + rc = of_property_read_u32_array(np, name, coords, + GOODIX_COORDS_ARR_SIZE); + if (rc && (rc != -EINVAL)) { + dev_err(dev, "Unable to read %s\n", name); + return rc; + } + + if (!strcmp(name, "goodix,panel-coords")) { + pdata->panel_minx = coords[0]; + pdata->panel_miny = coords[1]; + pdata->panel_maxx = coords[2]; + pdata->panel_maxy = coords[3]; + } else if (!strcmp(name, "goodix,display-coords")) { + pdata->x_min = coords[0]; + pdata->y_min = coords[1]; + pdata->x_max = coords[2]; + pdata->y_max = coords[3]; + } else { + dev_err(dev, "unsupported property %s\n", name); + return -EINVAL; + } + + return 0; +} + +static int goodix_parse_dt(struct device *dev, + struct goodix_ts_platform_data *pdata) +{ + int rc; + struct device_node *np = dev->of_node; + struct property *prop; + u32 temp_val, num_buttons; + u32 button_map[MAX_BUTTONS]; + + rc = goodix_ts_get_dt_coords(dev, "goodix,panel-coords", pdata); + if (rc && (rc != -EINVAL)) + return rc; + + rc = goodix_ts_get_dt_coords(dev, "goodix,display-coords", pdata); + if (rc) + return rc; + + pdata->i2c_pull_up = of_property_read_bool(np, + "goodix,i2c-pull-up"); + + pdata->no_force_update = of_property_read_bool(np, + "goodix,no-force-update"); + /* reset, irq gpio info */ + pdata->reset_gpio = of_get_named_gpio_flags(np, "reset-gpios", + 0, &pdata->reset_gpio_flags); + if (pdata->reset_gpio < 0) + return pdata->reset_gpio; + + pdata->irq_gpio = of_get_named_gpio_flags(np, "interrupt-gpios", + 0, &pdata->irq_gpio_flags); + if (pdata->irq_gpio < 0) + return pdata->irq_gpio; + + rc = of_property_read_u32(np, "goodix,family-id", &temp_val); + if (!rc) + pdata->family_id = temp_val; + else + return rc; + + prop = of_find_property(np, "goodix,button-map", NULL); + if (prop) { + num_buttons = prop->length / sizeof(temp_val); + if (num_buttons > MAX_BUTTONS) + return -EINVAL; + + rc = of_property_read_u32_array(np, + "goodix,button-map", button_map, + num_buttons); + if (rc) { + dev_err(dev, "Unable to read key codes\n"); + return rc; + } + } + + prop = of_find_property(np, "goodix,cfg-data", &pdata->gtp_cfg_len); + if (prop && prop->value) { + pdata->config_data = devm_kzalloc(dev, + GTP_CONFIG_MAX_LENGTH + GTP_ADDR_LENGTH, GFP_KERNEL); + if (!pdata->config_data) + return -ENOMEM; + + pdata->config_data[0] = GTP_REG_CONFIG_DATA >> 8; + pdata->config_data[1] = GTP_REG_CONFIG_DATA & 0xff; + memset(&pdata->config_data[GTP_ADDR_LENGTH], 0, + GTP_CONFIG_MAX_LENGTH); + memcpy(&pdata->config_data[GTP_ADDR_LENGTH], + prop->value, pdata->gtp_cfg_len); + } else { + dev_err(dev, + "Unable to get configure data, default will be used.\n"); + pdata->gtp_cfg_len = 0; + } + + return 0; +} + /******************************************************* Function: I2c probe. @@ -1359,15 +1688,34 @@ Output: static int goodix_ts_probe(struct i2c_client *client, const struct i2c_device_id *id) { + struct goodix_ts_platform_data *pdata; struct goodix_ts_data *ts; u16 version_info; int ret; dev_dbg(&client->dev, "GTP I2C Address: 0x%02x\n", client->addr); + if (client->dev.of_node) { + pdata = devm_kzalloc(&client->dev, + sizeof(struct goodix_ts_platform_data), GFP_KERNEL); + if (!pdata) + return -ENOMEM; + + ret = goodix_parse_dt(&client->dev, pdata); + if (ret) + return ret; + } else { + pdata = client->dev.platform_data; + } + + if (!pdata) { + dev_err(&client->dev, "GTP invalid pdata\n"); + return -EINVAL; + } #if GTP_ESD_PROTECT i2c_connect_client = client; #endif + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { dev_err(&client->dev, "GTP I2C not supported\n"); return -ENODEV; @@ -1379,14 +1727,26 @@ static int goodix_ts_probe(struct i2c_client *client, memset(ts, 0, sizeof(*ts)); ts->client = client; - /* For kernel 2.6.39 later we spin_lock_init(&ts->irq_lock) + ts->pdata = pdata; + /* For 2.6.39 & later use spin_lock_init(&ts->irq_lock) * For 2.6.39 & before, use ts->irq_lock = SPIN_LOCK_UNLOCKED */ spin_lock_init(&ts->irq_lock); i2c_set_clientdata(client, ts); - ts->gtp_rawdiff_mode = 0; + ret = goodix_power_init(ts); + if (ret) { + dev_err(&client->dev, "GTP power init failed\n"); + goto exit_free_client_data; + } + + ret = goodix_power_on(ts); + if (ret) { + dev_err(&client->dev, "GTP power on failed\n"); + goto exit_deinit_power; + } + ret = gtp_request_io_port(ts); if (ret) { dev_err(&client->dev, "GTP request IO port failed.\n"); @@ -1424,6 +1784,20 @@ static int goodix_ts_probe(struct i2c_client *client, goto exit_free_inputdev; } +#if defined(CONFIG_FB) + ts->fb_notif.notifier_call = fb_notifier_callback; + ret = fb_register_client(&ts->fb_notif); + if (ret) + dev_err(&ts->client->dev, + "Unable to register fb_notifier: %d\n", + ret); +#elif defined(CONFIG_HAS_EARLYSUSPEND) + ts->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1; + ts->early_suspend.suspend = goodix_ts_early_suspend; + ts->early_suspend.resume = goodix_ts_late_resume; + register_early_suspend(&ts->early_suspend); +#endif + ts->goodix_wq = create_singlethread_workqueue("goodix_wq"); INIT_WORK(&ts->work, goodix_ts_work_func); @@ -1451,6 +1825,13 @@ static int goodix_ts_probe(struct i2c_client *client, init_done = true; return 0; exit_free_irq: +#if defined(CONFIG_FB) + if (fb_unregister_client(&ts->fb_notif)) + dev_err(&client->dev, + "Error occurred while unregistering fb_notifier.\n"); +#elif defined(CONFIG_HAS_EARLYSUSPEND) + unregister_early_suspend(&ts->early_suspend); +#endif if (ts->use_irq) free_irq(client->irq, ts); else @@ -1467,7 +1848,15 @@ exit_free_irq: exit_free_inputdev: kfree(ts->config_data); exit_free_io_port: + if (gpio_is_valid(pdata->reset_gpio)) + gpio_free(pdata->reset_gpio); + if (gpio_is_valid(pdata->irq_gpio)) + gpio_free(pdata->irq_gpio); exit_power_off: + goodix_power_off(ts); +exit_deinit_power: + goodix_power_deinit(ts); +exit_free_client_data: i2c_set_clientdata(client, NULL); kfree(ts); return ret; @@ -1486,7 +1875,11 @@ static int goodix_ts_remove(struct i2c_client *client) struct goodix_ts_data *ts = i2c_get_clientdata(client); GTP_DEBUG_FUNC(); -#ifdef CONFIG_HAS_EARLYSUSPEND +#if defined(CONFIG_FB) + if (fb_unregister_client(&ts->fb_notif)) + dev_err(&client->dev, + "Error occurred while unregistering fb_notifier.\n"); +#elif defined(CONFIG_HAS_EARLYSUSPEND) unregister_early_suspend(&ts->early_suspend); #endif @@ -1522,6 +1915,8 @@ static int goodix_ts_remove(struct i2c_client *client) if (gpio_is_valid(ts->pdata->irq_gpio)) gpio_free(ts->pdata->irq_gpio); + goodix_power_off(ts); + goodix_power_deinit(ts); i2c_set_clientdata(client, NULL); kfree(ts); } @@ -1529,7 +1924,7 @@ static int goodix_ts_remove(struct i2c_client *client) return 0; } -#ifdef CONFIG_HAS_EARLYSUSPEND +#if defined(CONFIG_HAS_EARLYSUSPEND) || defined(CONFIG_FB) /******************************************************* Function: Early suspend function. @@ -1538,12 +1933,9 @@ Input: Output: None. *******************************************************/ -static void goodix_ts_early_suspend(struct early_suspend *h) +static void goodix_ts_suspend(struct goodix_ts_data *ts) { - struct goodix_ts_data *ts; - s8 ret = -1; - - ts = container_of(h, struct goodix_ts_data, early_suspend); + int ret = -1; GTP_DEBUG_FUNC(); @@ -1577,12 +1969,9 @@ Input: Output: None. *******************************************************/ -static void goodix_ts_late_resume(struct early_suspend *h) +static void goodix_ts_resume(struct goodix_ts_data *ts) { - struct goodix_ts_data *ts; - s8 ret = -1; - - ts = container_of(h, struct goodix_ts_data, early_suspend); + int ret = -1; GTP_DEBUG_FUNC(); @@ -1593,7 +1982,7 @@ static void goodix_ts_late_resume(struct early_suspend *h) #endif if (ret < 0) - dev_err(&ts->client->dev, "GTP later resume failed.\n"); + dev_err(&ts->client->dev, "GTP resume failed.\n"); if (ts->use_irq) gtp_irq_enable(ts); @@ -1606,18 +1995,72 @@ static void goodix_ts_late_resume(struct early_suspend *h) gtp_esd_switch(ts->client, SWITCH_ON); #endif } + +#if defined(CONFIG_FB) +static int fb_notifier_callback(struct notifier_block *self, + unsigned long event, void *data) +{ + struct fb_event *evdata = data; + int *blank; + struct goodix_ts_data *ts = + container_of(self, struct goodix_ts_data, fb_notif); + + if (evdata && evdata->data && event == FB_EVENT_BLANK && + ts && ts->client) { + blank = evdata->data; + if (*blank == FB_BLANK_UNBLANK) + goodix_ts_resume(ts); + else if (*blank == FB_BLANK_POWERDOWN) + goodix_ts_suspend(ts); + } + + return 0; +} +#elif defined(CONFIG_HAS_EARLYSUSPEND) +/* + * Function: + * Early suspend function. + * Input: + * h: early_suspend struct. + * Output: + * None. + */ +static void goodix_ts_early_suspend(struct early_suspend *h) +{ + struct goodix_ts_data *ts; + + ts = container_of(h, struct goodix_ts_data, early_suspend); + goodix_ts_suspend(ts); +} + +/* + * Function: + * Late resume function. + * Input: + * h: early_suspend struct. + * Output: + * None. + */ +static void goodix_ts_late_resume(struct early_suspend *h) +{ + struct goodix_ts_data *ts; + + ts = container_of(h, struct goodix_ts_data, early_suspend); + goodix_ts_late_resume(ts); +} #endif +#endif /* !CONFIG_HAS_EARLYSUSPEND && !CONFIG_FB*/ #if GTP_ESD_PROTECT -/******************************************************* -Function: - switch on & off esd delayed work -Input: - client: i2c device - on: SWITCH_ON / SWITCH_OFF -Output: - void -*********************************************************/ +/* + * Function: + * switch on & off esd delayed work + * Input: + * client: i2c device + * on: SWITCH_ON / SWITCH_OFF + * Output: + * void + */ void gtp_esd_switch(struct i2c_client *client, int on) { struct goodix_ts_data *ts; @@ -1749,6 +2192,11 @@ static const struct i2c_device_id goodix_ts_id[] = { { } }; +static const struct of_device_id goodix_match_table[] = { + { .compatible = "goodix,gt9xx", }, + { }, +}; + static struct i2c_driver goodix_ts_driver = { .probe = goodix_ts_probe, .remove = goodix_ts_remove, @@ -1760,6 +2208,7 @@ static struct i2c_driver goodix_ts_driver = { .driver = { .name = GTP_I2C_NAME, .owner = THIS_MODULE, + .of_match_table = goodix_match_table, }, }; diff --git a/drivers/input/touchscreen/gt9xx/gt9xx.h b/drivers/input/touchscreen/gt9xx/gt9xx.h index 48fa2ad2faca..185927c6d2b5 100644 --- a/drivers/input/touchscreen/gt9xx/gt9xx.h +++ b/drivers/input/touchscreen/gt9xx/gt9xx.h @@ -33,7 +33,11 @@ #include <linux/regulator/consumer.h> #include <linux/firmware.h> #include <linux/debugfs.h> -#if defined(CONFIG_HAS_EARLYSUSPEND) + +#if defined(CONFIG_FB) +#include <linux/notifier.h> +#include <linux/fb.h> +#elif defined(CONFIG_HAS_EARLYSUSPEND) #include <linux/earlysuspend.h> #define GOODIX_SUSPEND_LEVEL 1 #endif @@ -43,8 +47,6 @@ struct goodix_ts_platform_data { u32 irq_gpio_flags; int reset_gpio; u32 reset_gpio_flags; - int ldo_en_gpio; - u32 ldo_en_gpio_flags; u32 family_id; u32 x_max; u32 y_max; @@ -56,6 +58,8 @@ struct goodix_ts_platform_data { u32 panel_maxy; bool no_force_update; bool i2c_pull_up; + int gtp_cfg_len; + u8 *config_data; }; struct goodix_ts_data { spinlock_t irq_lock; @@ -65,9 +69,6 @@ struct goodix_ts_data { struct hrtimer timer; struct workqueue_struct *goodix_wq; struct work_struct work; -#if defined(CONFIG_HAS_EARLYSUSPEND) - struct early_suspend early_suspend; -#endif s32 irq_is_disabled; s32 use_irq; u16 abs_x_max; @@ -84,6 +85,14 @@ struct goodix_ts_data { u8 fixed_cfg; u8 esd_running; u8 fw_error; + struct regulator *avdd; + struct regulator *vdd; + struct regulator *vcc_i2c; +#if defined(CONFIG_FB) + struct notifier_block fb_notif; +#elif defined(CONFIG_HAS_EARLYSUSPEND) + struct early_suspend early_suspend; +#endif }; extern u16 show_len; @@ -94,8 +103,8 @@ extern u16 total_len; #define GTP_CHANGE_X2Y 0 #define GTP_DRIVER_SEND_CFG 1 #define GTP_HAVE_TOUCH_KEY 1 -#define GTP_POWER_CTRL_SLEEP 1 -#define GTP_ICS_SLOT_REPORT 0 +#define GTP_POWER_CTRL_SLEEP 0 +#define GTP_ICS_SLOT_REPORT 1 /* auto updated by .bin file as default */ #define GTP_AUTO_UPDATE 0 diff --git a/drivers/misc/qcom/qdsp6v2/audio_utils.c b/drivers/misc/qcom/qdsp6v2/audio_utils.c index cad0220a4960..065b426ca6d0 100644 --- a/drivers/misc/qcom/qdsp6v2/audio_utils.c +++ b/drivers/misc/qcom/qdsp6v2/audio_utils.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2010-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2010-2016, 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 @@ -24,6 +24,15 @@ #include <asm/ioctls.h> #include "audio_utils.h" +/* + * Define maximum buffer size. Below values are chosen considering the higher + * values used among all native drivers. + */ +#define MAX_FRAME_SIZE 1536 +#define MAX_FRAMES 5 +#define META_SIZE (sizeof(struct meta_out_dsp)) +#define MAX_BUFFER_SIZE (1 + ((MAX_FRAME_SIZE + META_SIZE) * MAX_FRAMES)) + static int audio_in_pause(struct q6audio_in *audio) { int rc; @@ -329,6 +338,10 @@ long audio_in_ioctl(struct file *file, rc = -EINVAL; break; } + if (cfg.buffer_size > MAX_BUFFER_SIZE) { + rc = -EINVAL; + break; + } audio->str_cfg.buffer_size = cfg.buffer_size; audio->str_cfg.buffer_count = cfg.buffer_count; if (audio->opened) { diff --git a/drivers/phy/phy-qcom-ufs-i.h b/drivers/phy/phy-qcom-ufs-i.h index 35179c8be471..7acef104d5b7 100644 --- a/drivers/phy/phy-qcom-ufs-i.h +++ b/drivers/phy/phy-qcom-ufs-i.h @@ -152,6 +152,7 @@ struct ufs_qcom_phy { * and writes to QSERDES_RX_SIGDET_CNTRL attribute * @configure_lpm: pointer to a function that configures the phy * for low power mode. + * @dbg_register_dump: pointer to a function that dumps phy registers for debug. */ struct ufs_qcom_phy_specific_ops { int (*calibrate_phy)(struct ufs_qcom_phy *phy, bool is_rate_B); @@ -161,6 +162,7 @@ struct ufs_qcom_phy_specific_ops { void (*ctrl_rx_linecfg)(struct ufs_qcom_phy *phy, bool ctrl); void (*power_control)(struct ufs_qcom_phy *phy, bool val); int (*configure_lpm)(struct ufs_qcom_phy *phy, bool enable); + void (*dbg_register_dump)(struct ufs_qcom_phy *phy); }; struct ufs_qcom_phy *get_ufs_qcom_phy(struct phy *generic_phy); @@ -184,5 +186,6 @@ int ufs_qcom_phy_calibrate(struct ufs_qcom_phy *ufs_qcom_phy, void ufs_qcom_phy_write_tbl(struct ufs_qcom_phy *ufs_qcom_phy, struct ufs_qcom_phy_calibration *tbl, int tbl_size); - +void ufs_qcom_phy_dump_regs(struct ufs_qcom_phy *phy, + int offset, int len, char *prefix); #endif diff --git a/drivers/phy/phy-qcom-ufs-qmp-v3.c b/drivers/phy/phy-qcom-ufs-qmp-v3.c index 57c23f70eb63..a9ad3a6f87cc 100644 --- a/drivers/phy/phy-qcom-ufs-qmp-v3.c +++ b/drivers/phy/phy-qcom-ufs-qmp-v3.c @@ -194,6 +194,22 @@ out: return err; } +static void ufs_qcom_phy_qmp_v3_dbg_register_dump(struct ufs_qcom_phy *phy) +{ + ufs_qcom_phy_dump_regs(phy, COM_BASE, COM_SIZE, + "PHY QSERDES COM Registers "); + ufs_qcom_phy_dump_regs(phy, PHY_BASE, PHY_SIZE, + "PHY Registers "); + ufs_qcom_phy_dump_regs(phy, RX_BASE(0), RX_SIZE, + "PHY RX0 Registers "); + ufs_qcom_phy_dump_regs(phy, TX_BASE(0), TX_SIZE, + "PHY TX0 Registers "); + ufs_qcom_phy_dump_regs(phy, RX_BASE(1), RX_SIZE, + "PHY RX1 Registers "); + ufs_qcom_phy_dump_regs(phy, TX_BASE(1), TX_SIZE, + "PHY TX1 Registers "); +} + struct phy_ops ufs_qcom_phy_qmp_v3_phy_ops = { .init = ufs_qcom_phy_qmp_v3_init, .exit = ufs_qcom_phy_exit, @@ -210,6 +226,7 @@ struct ufs_qcom_phy_specific_ops phy_v3_ops = { .ctrl_rx_linecfg = ufs_qcom_phy_qmp_v3_ctrl_rx_linecfg, .power_control = ufs_qcom_phy_qmp_v3_power_control, .configure_lpm = ufs_qcom_phy_qmp_v3_configure_lpm, + .dbg_register_dump = ufs_qcom_phy_qmp_v3_dbg_register_dump, }; static int ufs_qcom_phy_qmp_v3_probe(struct platform_device *pdev) diff --git a/drivers/phy/phy-qcom-ufs-qmp-v3.h b/drivers/phy/phy-qcom-ufs-qmp-v3.h index cda57855acb5..8b1e03eab639 100644 --- a/drivers/phy/phy-qcom-ufs-qmp-v3.h +++ b/drivers/phy/phy-qcom-ufs-qmp-v3.h @@ -18,10 +18,18 @@ #include "phy-qcom-ufs-i.h" /* QCOM UFS PHY control registers */ -#define COM_OFF(x) (0x000 + x) -#define PHY_OFF(x) (0xC00 + x) -#define TX_OFF(n, x) (0x400 + (0x400 * n) + x) -#define RX_OFF(n, x) (0x600 + (0x400 * n) + x) +#define COM_BASE 0x000 +#define COM_SIZE 0x18C +#define PHY_BASE 0xC00 +#define PHY_SIZE 0x1DC +#define TX_BASE(n) (0x400 + (0x400 * n)) +#define TX_SIZE 0x128 +#define RX_BASE(n) (0x600 + (0x400 * n)) +#define RX_SIZE 0x1FC +#define COM_OFF(x) (COM_BASE + x) +#define PHY_OFF(x) (PHY_BASE + x) +#define TX_OFF(n, x) (TX_BASE(n) + x) +#define RX_OFF(n, x) (RX_BASE(n) + x) /* UFS PHY QSERDES COM registers */ #define QSERDES_COM_ATB_SEL1 COM_OFF(0x00) diff --git a/drivers/phy/phy-qcom-ufs.c b/drivers/phy/phy-qcom-ufs.c index de32b75f4f57..b2c58430785a 100644 --- a/drivers/phy/phy-qcom-ufs.c +++ b/drivers/phy/phy-qcom-ufs.c @@ -788,3 +788,21 @@ int ufs_qcom_phy_configure_lpm(struct phy *generic_phy, bool enable) return ret; } EXPORT_SYMBOL(ufs_qcom_phy_configure_lpm); + +void ufs_qcom_phy_dump_regs(struct ufs_qcom_phy *phy, int offset, + int len, char *prefix) +{ + print_hex_dump(KERN_ERR, prefix, + len > 4 ? DUMP_PREFIX_OFFSET : DUMP_PREFIX_NONE, + 16, 4, phy->mmio + offset, len, false); +} +EXPORT_SYMBOL(ufs_qcom_phy_dump_regs); + +void ufs_qcom_phy_dbg_register_dump(struct phy *generic_phy) +{ + struct ufs_qcom_phy *ufs_qcom_phy = get_ufs_qcom_phy(generic_phy); + + if (ufs_qcom_phy->phy_spec_ops->dbg_register_dump) + ufs_qcom_phy->phy_spec_ops->dbg_register_dump(ufs_qcom_phy); +} +EXPORT_SYMBOL(ufs_qcom_phy_dbg_register_dump); diff --git a/drivers/power/qcom-charger/qpnp-smb2.c b/drivers/power/qcom-charger/qpnp-smb2.c index 0be535194b49..f83b641bcc4f 100644 --- a/drivers/power/qcom-charger/qpnp-smb2.c +++ b/drivers/power/qcom-charger/qpnp-smb2.c @@ -588,6 +588,7 @@ static enum power_supply_property smb2_batt_props[] = { POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL, POWER_SUPPLY_PROP_CHARGER_TEMP, POWER_SUPPLY_PROP_CHARGER_TEMP_MAX, + POWER_SUPPLY_PROP_INPUT_CURRENT_LIMITED, }; static int smb2_batt_get_prop(struct power_supply *psy, @@ -625,6 +626,9 @@ static int smb2_batt_get_prop(struct power_supply *psy, case POWER_SUPPLY_PROP_CHARGER_TEMP_MAX: rc = smblib_get_prop_charger_temp_max(chg, val); break; + case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMITED: + rc = smblib_get_prop_input_current_limited(chg, val); + break; default: pr_err("batt power supply prop %d not supported\n", psp); return -EINVAL; @@ -1121,7 +1125,7 @@ static struct smb2_irq_info smb2_irqs[] = { { "wdog-bark", NULL }, { "aicl-fail", smblib_handle_debug }, { "aicl-done", smblib_handle_debug }, - { "high-duty-cycle", smblib_handle_debug }, + { "high-duty-cycle", smblib_handle_high_duty_cycle, true }, { "input-current-limiting", smblib_handle_debug }, { "temperature-change", smblib_handle_debug }, { "switcher-power-ok", smblib_handle_debug }, diff --git a/drivers/power/qcom-charger/smb-lib.c b/drivers/power/qcom-charger/smb-lib.c index ee4f65430d8b..21b330127369 100644 --- a/drivers/power/qcom-charger/smb-lib.c +++ b/drivers/power/qcom-charger/smb-lib.c @@ -988,6 +988,21 @@ int smblib_get_prop_system_temp_level(struct smb_charger *chg, return 0; } +int smblib_get_prop_input_current_limited(struct smb_charger *chg, + union power_supply_propval *val) +{ + u8 stat; + int rc; + + rc = smblib_read(chg, AICL_STATUS_REG, &stat); + if (rc < 0) { + dev_err(chg->dev, "Couldn't read AICL_STATUS rc=%d\n", rc); + return rc; + } + val->intval = (stat & SOFT_ILIMIT_BIT) || chg->is_hdc; + return 0; +} + /*********************** * BATTERY PSY SETTERS * ***********************/ @@ -1965,6 +1980,17 @@ irqreturn_t smblib_handle_usb_typec_change(int irq, void *data) return IRQ_HANDLED; } +irqreturn_t smblib_handle_high_duty_cycle(int irq, void *data) +{ + struct smb_irq_data *irq_data = data; + struct smb_charger *chg = irq_data->parent_data; + + chg->is_hdc = true; + schedule_delayed_work(&chg->clear_hdc_work, msecs_to_jiffies(60)); + + return IRQ_HANDLED; +} + /*************** * Work Queues * ***************/ @@ -2054,6 +2080,14 @@ done: vote(chg->awake_votable, PL_VOTER, false, 0); } +static void clear_hdc_work(struct work_struct *work) +{ + struct smb_charger *chg = container_of(work, struct smb_charger, + clear_hdc_work.work); + + chg->is_hdc = 0; +} + static int smblib_create_votables(struct smb_charger *chg) { int rc = 0; @@ -2194,6 +2228,7 @@ int smblib_init(struct smb_charger *chg) INIT_DELAYED_WORK(&chg->hvdcp_detect_work, smblib_hvdcp_detect_work); INIT_DELAYED_WORK(&chg->pl_taper_work, smblib_pl_taper_work); INIT_DELAYED_WORK(&chg->step_soc_req_work, step_soc_req_work); + INIT_DELAYED_WORK(&chg->clear_hdc_work, clear_hdc_work); chg->fake_capacity = -EINVAL; switch (chg->mode) { diff --git a/drivers/power/qcom-charger/smb-lib.h b/drivers/power/qcom-charger/smb-lib.h index 1b0c221b4764..aeb1eb2c454f 100644 --- a/drivers/power/qcom-charger/smb-lib.h +++ b/drivers/power/qcom-charger/smb-lib.h @@ -145,6 +145,7 @@ struct smb_charger { struct delayed_work ps_change_timeout_work; struct delayed_work pl_taper_work; struct delayed_work step_soc_req_work; + struct delayed_work clear_hdc_work; /* cached status */ int voltage_min_uv; @@ -159,6 +160,7 @@ struct smb_charger { int fake_capacity; bool step_chg_enabled; + bool is_hdc; }; int smblib_read(struct smb_charger *chg, u16 addr, u8 *val); @@ -202,6 +204,7 @@ irqreturn_t smblib_handle_usb_plugin(int irq, void *data); irqreturn_t smblib_handle_usb_source_change(int irq, void *data); irqreturn_t smblib_handle_icl_change(int irq, void *data); irqreturn_t smblib_handle_usb_typec_change(int irq, void *data); +irqreturn_t smblib_handle_high_duty_cycle(int irq, void *data); int smblib_get_prop_input_suspend(struct smb_charger *chg, union power_supply_propval *val); @@ -217,6 +220,8 @@ int smblib_get_prop_batt_health(struct smb_charger *chg, union power_supply_propval *val); int smblib_get_prop_system_temp_level(struct smb_charger *chg, union power_supply_propval *val); +int smblib_get_prop_input_current_limited(struct smb_charger *chg, + union power_supply_propval *val); int smblib_set_prop_input_suspend(struct smb_charger *chg, const union power_supply_propval *val); diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c index 23c32f2743c3..fde0d408d27e 100644 --- a/drivers/scsi/ufs/ufs-qcom.c +++ b/drivers/scsi/ufs/ufs-qcom.c @@ -2405,17 +2405,21 @@ void ufs_qcom_print_hw_debug_reg_all(struct ufs_hba *hba, void *priv, static void ufs_qcom_enable_test_bus(struct ufs_qcom_host *host) { - if (host->dbg_print_en & UFS_QCOM_DBG_PRINT_TEST_BUS_EN) + if (host->dbg_print_en & UFS_QCOM_DBG_PRINT_TEST_BUS_EN) { + ufshcd_rmwl(host->hba, UFS_REG_TEST_BUS_EN, + UFS_REG_TEST_BUS_EN, REG_UFS_CFG1); ufshcd_rmwl(host->hba, TEST_BUS_EN, TEST_BUS_EN, REG_UFS_CFG1); - else + } else { + ufshcd_rmwl(host->hba, UFS_REG_TEST_BUS_EN, 0, REG_UFS_CFG1); ufshcd_rmwl(host->hba, TEST_BUS_EN, 0, REG_UFS_CFG1); + } } static void ufs_qcom_get_default_testbus_cfg(struct ufs_qcom_host *host) { /* provide a legal default configuration */ - host->testbus.select_major = TSTBUS_UAWM; - host->testbus.select_minor = 1; + host->testbus.select_major = TSTBUS_UNIPRO; + host->testbus.select_minor = 37; } static bool ufs_qcom_testbus_cfg_is_ok(struct ufs_qcom_host *host) @@ -2432,7 +2436,7 @@ static bool ufs_qcom_testbus_cfg_is_ok(struct ufs_qcom_host *host) * mappings of select_minor, since there is no harm in * configuring a non-existent select_minor */ - if (host->testbus.select_minor > 0x1F) { + if (host->testbus.select_minor > 0xFF) { dev_err(host->hba->dev, "%s: 0x%05X is not a legal testbus option\n", __func__, host->testbus.select_minor); @@ -2501,7 +2505,8 @@ int ufs_qcom_testbus_config(struct ufs_qcom_host *host) break; case TSTBUS_UNIPRO: reg = UFS_UNIPRO_CFG; - offset = 1; + offset = 20; + mask = 0xFFF; break; /* * No need for a default case, since @@ -2520,6 +2525,11 @@ int ufs_qcom_testbus_config(struct ufs_qcom_host *host) (u32)host->testbus.select_minor << offset, reg); ufs_qcom_enable_test_bus(host); + /* + * Make sure the test bus configuration is + * committed before returning. + */ + mb(); ufshcd_release(host->hba, false); pm_runtime_put_sync(host->hba->dev); @@ -2531,15 +2541,44 @@ static void ufs_qcom_testbus_read(struct ufs_hba *hba) ufs_qcom_dump_regs(hba, UFS_TEST_BUS, 1, "UFS_TEST_BUS "); } +static void ufs_qcom_print_unipro_testbus(struct ufs_hba *hba) +{ + struct ufs_qcom_host *host = ufshcd_get_variant(hba); + u32 *testbus = NULL; + int i, nminor = 256, testbus_len = nminor * sizeof(u32); + + testbus = kmalloc(testbus_len, GFP_KERNEL); + if (!testbus) + return; + + host->testbus.select_major = TSTBUS_UNIPRO; + for (i = 0; i < nminor; i++) { + host->testbus.select_minor = i; + ufs_qcom_testbus_config(host); + testbus[i] = ufshcd_readl(hba, UFS_TEST_BUS); + } + print_hex_dump(KERN_ERR, "UNIPRO_TEST_BUS ", DUMP_PREFIX_OFFSET, + 16, 4, testbus, testbus_len, false); + kfree(testbus); +} + static void ufs_qcom_dump_dbg_regs(struct ufs_hba *hba) { struct ufs_qcom_host *host = ufshcd_get_variant(hba); + struct phy *phy = host->generic_phy; ufs_qcom_dump_regs(hba, REG_UFS_SYS1CLK_1US, 16, "HCI Vendor Specific Registers "); + /* sleep a bit intermittently as we are dumping too much data */ ufs_qcom_print_hw_debug_reg_all(hba, NULL, ufs_qcom_dump_regs_wrapper); + usleep_range(1000, 1100); ufs_qcom_testbus_read(hba); + usleep_range(1000, 1100); + ufs_qcom_print_unipro_testbus(hba); + usleep_range(1000, 1100); + ufs_qcom_phy_dbg_register_dump(phy); + usleep_range(1000, 1100); ufs_qcom_ice_print_regs(host); } diff --git a/drivers/scsi/ufs/ufs-qcom.h b/drivers/scsi/ufs/ufs-qcom.h index ba36d9883a0f..394de8302fd2 100644 --- a/drivers/scsi/ufs/ufs-qcom.h +++ b/drivers/scsi/ufs/ufs-qcom.h @@ -100,6 +100,7 @@ enum { #define QUNIPRO_SEL UFS_BIT(0) #define TEST_BUS_EN BIT(18) #define TEST_BUS_SEL GENMASK(22, 19) +#define UFS_REG_TEST_BUS_EN BIT(30) /* bit definitions for REG_UFS_CFG2 register */ #define UAWM_HW_CGC_EN (1 << 0) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index a49b3c7bc4ef..d478767ad3dd 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -3932,8 +3932,12 @@ static int ufshcd_uic_pwr_ctrl(struct ufs_hba *hba, struct uic_command *cmd) ret = (status != PWR_OK) ? status : -1; } out: - if (ret) + if (ret) { ufsdbg_set_err_state(hba); + ufshcd_print_host_state(hba); + ufshcd_print_pwr_info(hba); + ufshcd_print_host_regs(hba); + } ufshcd_save_tstamp_of_last_dme_cmd(hba); spin_lock_irqsave(hba->host->host_lock, flags); @@ -4644,8 +4648,12 @@ link_startup: ret = ufshcd_make_hba_operational(hba); out: - if (ret) + if (ret) { dev_err(hba->dev, "link startup failed %d\n", ret); + ufshcd_print_host_state(hba); + ufshcd_print_pwr_info(hba); + ufshcd_print_host_regs(hba); + } return ret; } diff --git a/drivers/slimbus/slim-msm-ngd.c b/drivers/slimbus/slim-msm-ngd.c index fbde0d318584..9af9ce323bc3 100644 --- a/drivers/slimbus/slim-msm-ngd.c +++ b/drivers/slimbus/slim-msm-ngd.c @@ -228,6 +228,16 @@ static int dsp_domr_notify_cb(struct notifier_block *n, unsigned long code, break; case LOCATOR_UP: reg = _cmd; + if (!reg || reg->total_domains != 1) { + SLIM_WARN(dev, "error locating audio-PD\n"); + if (reg) + SLIM_WARN(dev, "audio-PDs matched:%d\n", + reg->total_domains); + + /* Fall back to SSR */ + ngd_reg_ssr(dev); + return NOTIFY_DONE; + } dev->dsp.domr = service_notif_register_notifier( reg->domain_list->name, reg->domain_list->instance_id, @@ -1493,8 +1503,7 @@ static int ngd_slim_rx_msgq_thread(void *data) int retries = 0; u8 wbuf[8]; - set_current_state(TASK_INTERRUPTIBLE); - wait_for_completion(notify); + wait_for_completion_interruptible(notify); txn.dt = SLIM_MSG_DEST_LOGICALADDR; txn.ec = 0; @@ -1555,8 +1564,7 @@ static int ngd_notify_slaves(void *data) } while (!kthread_should_stop()) { - set_current_state(TASK_INTERRUPTIBLE); - wait_for_completion(&dev->qmi.slave_notify); + wait_for_completion_interruptible(&dev->qmi.slave_notify); /* Probe devices for first notification */ if (!i) { i++; diff --git a/drivers/soc/qcom/icnss.c b/drivers/soc/qcom/icnss.c index aaca82f87159..05a9ff4aeb1c 100644 --- a/drivers/soc/qcom/icnss.c +++ b/drivers/soc/qcom/icnss.c @@ -34,6 +34,8 @@ #include <linux/qmi_encdec.h> #include <linux/ipc_logging.h> #include <linux/msm-bus.h> +#include <linux/uaccess.h> +#include <linux/qpnp/qpnp-adc.h> #include <soc/qcom/memory_dump.h> #include <soc/qcom/icnss.h> #include <soc/qcom/msm_qmi_interface.h> @@ -49,6 +51,7 @@ #define MAX_PROP_SIZE 32 #define NUM_LOG_PAGES 10 #define NUM_REG_LOG_PAGES 4 +#define ICNSS_MAGIC 0x5abc5abc /* * Registers: MPM2_PSHOLD @@ -158,6 +161,10 @@ #define ICNSS_SERVICE_LOCATION_CLIENT_NAME "ICNSS-WLAN" #define ICNSS_WLAN_SERVICE_NAME "wlan/fw" +#define ICNSS_THRESHOLD_HIGH 3600000 +#define ICNSS_THRESHOLD_LOW 3450000 +#define ICNSS_THRESHOLD_GUARD 20000 + #define icnss_ipc_log_string(_x...) do { \ if (icnss_ipc_log_context) \ ipc_log_string(icnss_ipc_log_context, _x); \ @@ -269,6 +276,8 @@ enum icnss_driver_state { ICNSS_DRIVER_PROBED, ICNSS_FW_TEST_MODE, ICNSS_SUSPEND, + ICNSS_PM_SUSPEND, + ICNSS_PM_SUSPEND_NOIRQ, ICNSS_SSR_ENABLED, ICNSS_PDR_ENABLED, ICNSS_PD_RESTART, @@ -324,6 +333,15 @@ struct icnss_stats { uint32_t disable; } ce_irqs[ICNSS_MAX_IRQ_REGISTRATIONS]; + uint32_t pm_suspend; + uint32_t pm_suspend_err; + uint32_t pm_resume; + uint32_t pm_resume_err; + uint32_t pm_suspend_noirq; + uint32_t pm_suspend_noirq_err; + uint32_t pm_resume_noirq; + uint32_t pm_resume_noirq_err; + uint32_t ind_register_req; uint32_t ind_register_resp; uint32_t ind_register_err; @@ -347,9 +365,13 @@ struct icnss_stats { uint32_t ini_req; uint32_t ini_resp; uint32_t ini_req_err; + uint32_t vbatt_req; + uint32_t vbatt_resp; + uint32_t vbatt_req_err; }; static struct icnss_priv { + uint32_t magic; struct platform_device *pdev; struct icnss_driver_ops *ops; struct ce_irq_list ce_irq_list[ICNSS_MAX_IRQ_REGISTRATIONS]; @@ -397,6 +419,14 @@ static struct icnss_priv { void *modem_notify_handler; struct notifier_block modem_ssr_nb; struct wakeup_source ws; + uint32_t diag_reg_read_addr; + uint32_t diag_reg_read_mem_type; + uint32_t diag_reg_read_len; + uint8_t *diag_reg_read_buf; + struct qpnp_adc_tm_btm_param vph_monitor_params; + struct qpnp_adc_tm_chip *adc_tm_dev; + struct qpnp_vadc_chip *vadc_dev; + uint64_t vph_pwr; } *penv; static void icnss_hw_write_reg(void *base, u32 offset, u32 val) @@ -546,6 +576,189 @@ static int icnss_driver_event_post(enum icnss_driver_event_type type, return ret; } +static int wlfw_vbatt_send_sync_msg(struct icnss_priv *priv, + uint64_t voltage_uv) +{ + int ret; + struct wlfw_vbatt_req_msg_v01 req; + struct wlfw_vbatt_resp_msg_v01 resp; + struct msg_desc req_desc, resp_desc; + + if (!priv->wlfw_clnt) { + ret = -ENODEV; + goto out; + } + + icnss_pr_dbg("Sending Vbatt message, state: 0x%lx\n", + penv->state); + + memset(&req, 0, sizeof(req)); + memset(&resp, 0, sizeof(resp)); + + req.voltage_uv = voltage_uv; + + req_desc.max_msg_len = WLFW_VBATT_REQ_MSG_V01_MAX_MSG_LEN; + req_desc.msg_id = QMI_WLFW_VBATT_REQ_V01; + req_desc.ei_array = wlfw_vbatt_req_msg_v01_ei; + + resp_desc.max_msg_len = WLFW_VBATT_RESP_MSG_V01_MAX_MSG_LEN; + resp_desc.msg_id = QMI_WLFW_VBATT_RESP_V01; + resp_desc.ei_array = wlfw_vbatt_resp_msg_v01_ei; + + priv->stats.vbatt_req++; + + ret = qmi_send_req_wait(priv->wlfw_clnt, &req_desc, &req, sizeof(req), + &resp_desc, &resp, sizeof(resp), WLFW_TIMEOUT_MS); + if (ret < 0) { + icnss_pr_err("Send vbatt req failed %d\n", ret); + goto out; + } + + if (resp.resp.result != QMI_RESULT_SUCCESS_V01) { + icnss_pr_err("QMI vbatt request failed %d %d\n", + resp.resp.result, resp.resp.error); + ret = resp.resp.result; + goto out; + } + priv->stats.vbatt_resp++; + +out: + priv->stats.vbatt_req_err++; + return ret; +} + +static int icnss_get_phone_power(struct icnss_priv *priv, uint64_t *result_uv) +{ + int ret = 0; + struct qpnp_vadc_result adc_result; + + if (!priv->vadc_dev) { + icnss_pr_err("VADC dev doesn't exists\n"); + ret = -EINVAL; + goto out; + } + + ret = qpnp_vadc_read(penv->vadc_dev, VADC_VPH_PWR, &adc_result); + if (ret) { + icnss_pr_err("Error reading ADC channel %d, ret = %d\n", + VADC_VPH_PWR, ret); + goto out; + } + + icnss_pr_dbg("Phone power read phy=%lld meas=0x%llx\n", + adc_result.physical, adc_result.measurement); + + *result_uv = adc_result.physical; +out: + return ret; +} + +static void icnss_vph_notify(enum qpnp_tm_state state, void *ctx) +{ + struct icnss_priv *priv = ctx; + uint64_t vph_pwr = 0; + uint64_t vph_pwr_prev; + int ret = 0; + bool update = true; + + if (!priv) { + icnss_pr_err("Priv pointer is NULL\n"); + return; + } + + vph_pwr_prev = priv->vph_pwr; + + ret = icnss_get_phone_power(priv, &vph_pwr); + if (ret) + return; + + if (vph_pwr < ICNSS_THRESHOLD_LOW) { + if (vph_pwr_prev < ICNSS_THRESHOLD_LOW) + update = false; + priv->vph_monitor_params.state_request = + ADC_TM_HIGH_THR_ENABLE; + priv->vph_monitor_params.high_thr = ICNSS_THRESHOLD_LOW + + ICNSS_THRESHOLD_GUARD; + priv->vph_monitor_params.low_thr = 0; + } else if (vph_pwr > ICNSS_THRESHOLD_HIGH) { + if (vph_pwr_prev > ICNSS_THRESHOLD_HIGH) + update = false; + priv->vph_monitor_params.state_request = + ADC_TM_LOW_THR_ENABLE; + priv->vph_monitor_params.low_thr = ICNSS_THRESHOLD_HIGH - + ICNSS_THRESHOLD_GUARD; + priv->vph_monitor_params.high_thr = 0; + } else { + if (vph_pwr_prev > ICNSS_THRESHOLD_LOW && + vph_pwr_prev < ICNSS_THRESHOLD_HIGH) + update = false; + priv->vph_monitor_params.state_request = + ADC_TM_HIGH_LOW_THR_ENABLE; + priv->vph_monitor_params.low_thr = ICNSS_THRESHOLD_LOW; + priv->vph_monitor_params.high_thr = ICNSS_THRESHOLD_HIGH; + } + + priv->vph_pwr = vph_pwr; + + if (update) + wlfw_vbatt_send_sync_msg(priv, vph_pwr); + + icnss_pr_dbg("set low threshold to %d, high threshold to %d\n", + priv->vph_monitor_params.low_thr, + priv->vph_monitor_params.high_thr); + ret = qpnp_adc_tm_channel_measure(priv->adc_tm_dev, + &priv->vph_monitor_params); + if (ret) + icnss_pr_err("TM channel setup failed %d\n", ret); +} + +static int icnss_setup_vph_monitor(struct icnss_priv *priv) +{ + int ret = 0; + + if (!priv->adc_tm_dev) { + icnss_pr_err("ADC TM handler is NULL\n"); + ret = -EINVAL; + goto out; + } + + priv->vph_monitor_params.low_thr = ICNSS_THRESHOLD_LOW; + priv->vph_monitor_params.high_thr = ICNSS_THRESHOLD_HIGH; + priv->vph_monitor_params.state_request = ADC_TM_HIGH_LOW_THR_ENABLE; + priv->vph_monitor_params.channel = VADC_VPH_PWR; + priv->vph_monitor_params.btm_ctx = priv; + priv->vph_monitor_params.timer_interval = ADC_MEAS1_INTERVAL_1S; + priv->vph_monitor_params.threshold_notification = &icnss_vph_notify; + icnss_pr_dbg("Set low threshold to %d, high threshold to %d\n", + priv->vph_monitor_params.low_thr, + priv->vph_monitor_params.high_thr); + + ret = qpnp_adc_tm_channel_measure(priv->adc_tm_dev, + &priv->vph_monitor_params); + if (ret) + icnss_pr_err("TM channel setup failed %d\n", ret); +out: + return ret; +} + +static int icnss_init_vph_monitor(struct icnss_priv *priv) +{ + int ret = 0; + + ret = icnss_get_phone_power(priv, &priv->vph_pwr); + if (ret) + goto out; + + wlfw_vbatt_send_sync_msg(priv, priv->vph_pwr); + + ret = icnss_setup_vph_monitor(priv); + if (ret) + goto out; +out: + return ret; +} + + static int icnss_qmi_pin_connect_result_ind(void *msg, unsigned int msg_len) { struct msg_desc ind_desc; @@ -1777,6 +1990,127 @@ out: return ret; } +static int wlfw_athdiag_read_send_sync_msg(struct icnss_priv *priv, + uint32_t offset, uint32_t mem_type, + uint32_t data_len, uint8_t *data) +{ + int ret; + struct wlfw_athdiag_read_req_msg_v01 req; + struct wlfw_athdiag_read_resp_msg_v01 *resp = NULL; + struct msg_desc req_desc, resp_desc; + + if (!priv->wlfw_clnt) { + ret = -ENODEV; + goto out; + } + + icnss_pr_dbg("Diag read: state 0x%lx, offset %x, mem_type %x, data_len %u\n", + priv->state, offset, mem_type, data_len); + + resp = kzalloc(sizeof(*resp), GFP_KERNEL); + if (!resp) { + ret = -ENOMEM; + goto out; + } + memset(&req, 0, sizeof(req)); + + req.offset = offset; + req.mem_type = mem_type; + req.data_len = data_len; + + req_desc.max_msg_len = WLFW_ATHDIAG_READ_REQ_MSG_V01_MAX_MSG_LEN; + req_desc.msg_id = QMI_WLFW_ATHDIAG_READ_REQ_V01; + req_desc.ei_array = wlfw_athdiag_read_req_msg_v01_ei; + + resp_desc.max_msg_len = WLFW_ATHDIAG_READ_RESP_MSG_V01_MAX_MSG_LEN; + resp_desc.msg_id = QMI_WLFW_ATHDIAG_READ_RESP_V01; + resp_desc.ei_array = wlfw_athdiag_read_resp_msg_v01_ei; + + ret = qmi_send_req_wait(penv->wlfw_clnt, &req_desc, &req, sizeof(req), + &resp_desc, resp, sizeof(*resp), + WLFW_TIMEOUT_MS); + if (ret < 0) { + icnss_pr_err("send athdiag read req failed %d\n", ret); + goto out; + } + + if (resp->resp.result != QMI_RESULT_SUCCESS_V01) { + icnss_pr_err("QMI athdiag read request failed %d %d\n", + resp->resp.result, resp->resp.error); + ret = resp->resp.result; + goto out; + } + + if (!resp->data_valid || resp->data_len <= data_len) { + icnss_pr_err("Athdiag read data is invalid, data_valid = %u, data_len = %u\n", + resp->data_valid, resp->data_len); + ret = -EINVAL; + goto out; + } + + memcpy(data, resp->data, resp->data_len); + +out: + kfree(resp); + return ret; +} + +static int wlfw_athdiag_write_send_sync_msg(struct icnss_priv *priv, + uint32_t offset, uint32_t mem_type, + uint32_t data_len, uint8_t *data) +{ + int ret; + struct wlfw_athdiag_write_req_msg_v01 *req = NULL; + struct wlfw_athdiag_write_resp_msg_v01 resp; + struct msg_desc req_desc, resp_desc; + + if (!priv->wlfw_clnt) { + ret = -ENODEV; + goto out; + } + + icnss_pr_dbg("Diag write: state 0x%lx, offset %x, mem_type %x, data_len %u, data %p\n", + priv->state, offset, mem_type, data_len, data); + + req = kzalloc(sizeof(*req), GFP_KERNEL); + if (!req) { + ret = -ENOMEM; + goto out; + } + memset(&resp, 0, sizeof(resp)); + + req->offset = offset; + req->mem_type = mem_type; + req->data_len = data_len; + memcpy(req->data, data, data_len); + + req_desc.max_msg_len = WLFW_ATHDIAG_WRITE_REQ_MSG_V01_MAX_MSG_LEN; + req_desc.msg_id = QMI_WLFW_ATHDIAG_WRITE_REQ_V01; + req_desc.ei_array = wlfw_athdiag_write_req_msg_v01_ei; + + resp_desc.max_msg_len = WLFW_ATHDIAG_WRITE_RESP_MSG_V01_MAX_MSG_LEN; + resp_desc.msg_id = QMI_WLFW_ATHDIAG_WRITE_RESP_V01; + resp_desc.ei_array = wlfw_athdiag_write_resp_msg_v01_ei; + + ret = qmi_send_req_wait(penv->wlfw_clnt, &req_desc, req, sizeof(*req), + &resp_desc, &resp, sizeof(resp), + WLFW_TIMEOUT_MS); + if (ret < 0) { + icnss_pr_err("send athdiag write req failed %d\n", ret); + goto out; + } + + if (resp.resp.result != QMI_RESULT_SUCCESS_V01) { + icnss_pr_err("QMI athdiag write request failed %d %d\n", + resp.resp.result, resp.resp.error); + ret = resp.resp.result; + goto out; + } +out: + kfree(req); + return ret; +} + static void icnss_qmi_wlfw_clnt_notify_work(struct work_struct *work) { int ret; @@ -1907,6 +2241,8 @@ static int icnss_driver_event_server_arrive(void *data) if (ret < 0) goto err_setup_msa; + icnss_init_vph_monitor(penv); + return ret; err_setup_msa: @@ -1928,6 +2264,10 @@ static int icnss_driver_event_server_exit(void *data) icnss_pr_info("QMI Service Disconnected: 0x%lx\n", penv->state); + if (penv->adc_tm_dev) + qpnp_adc_tm_disable_chan_meas(penv->adc_tm_dev, + &penv->vph_monitor_params); + qmi_handle_destroy(penv->wlfw_clnt); clear_bit(ICNSS_WLFW_QMI_CONNECTED, &penv->state); @@ -2677,6 +3017,78 @@ int icnss_set_fw_debug_mode(bool enable_fw_log) } EXPORT_SYMBOL(icnss_set_fw_debug_mode); +int icnss_athdiag_read(struct device *dev, uint32_t offset, + uint32_t mem_type, uint32_t data_len, + uint8_t *output) +{ + int ret = 0; + struct icnss_priv *priv = dev_get_drvdata(dev); + + if (priv->magic != ICNSS_MAGIC) { + icnss_pr_err("Invalid drvdata for diag read: dev %p, data %p, magic 0x%x\n", + dev, priv, priv->magic); + return -EINVAL; + } + + if (!output || data_len == 0 + || data_len > QMI_WLFW_MAX_DATA_SIZE_V01) { + icnss_pr_err("Invalid parameters for diag read: output %p, data_len %u\n", + output, data_len); + ret = -EINVAL; + goto out; + } + + if (!test_bit(ICNSS_FW_READY, &priv->state) || + !test_bit(ICNSS_POWER_ON, &priv->state)) { + icnss_pr_err("Invalid state for diag read: 0x%lx\n", + priv->state); + ret = -EINVAL; + goto out; + } + + ret = wlfw_athdiag_read_send_sync_msg(priv, offset, mem_type, + data_len, output); +out: + return ret; +} +EXPORT_SYMBOL(icnss_athdiag_read); + +int icnss_athdiag_write(struct device *dev, uint32_t offset, + uint32_t mem_type, uint32_t data_len, + uint8_t *input) +{ + int ret = 0; + struct icnss_priv *priv = dev_get_drvdata(dev); + + if (priv->magic != ICNSS_MAGIC) { + icnss_pr_err("Invalid drvdata for diag write: dev %p, data %p, magic 0x%x\n", + dev, priv, priv->magic); + return -EINVAL; + } + + if (!input || data_len == 0 + || data_len > QMI_WLFW_MAX_DATA_SIZE_V01) { + icnss_pr_err("Invalid parameters for diag write: input %p, data_len %u\n", + input, data_len); + ret = -EINVAL; + goto out; + } + + if (!test_bit(ICNSS_FW_READY, &priv->state) || + !test_bit(ICNSS_POWER_ON, &priv->state)) { + icnss_pr_err("Invalid state for diag write: 0x%lx\n", + priv->state); + ret = -EINVAL; + goto out; + } + + ret = wlfw_athdiag_write_send_sync_msg(priv, offset, mem_type, + data_len, input); +out: + return ret; +} +EXPORT_SYMBOL(icnss_athdiag_write); + int icnss_wlan_enable(struct icnss_wlan_enable_cfg *config, enum icnss_driver_mode mode, const char *host_version) @@ -3302,6 +3714,12 @@ static int icnss_stats_show_state(struct seq_file *s, struct icnss_priv *priv) case ICNSS_FW_TEST_MODE: seq_puts(s, "FW TEST MODE"); continue; + case ICNSS_PM_SUSPEND: + seq_puts(s, "PM SUSPEND"); + continue; + case ICNSS_PM_SUSPEND_NOIRQ: + seq_puts(s, "PM SUSPEND_NOIRQ"); + continue; case ICNSS_SSR_ENABLED: seq_puts(s, "SSR ENABLED"); continue; @@ -3401,6 +3819,19 @@ static int icnss_stats_show(struct seq_file *s, void *data) ICNSS_STATS_DUMP(s, priv, ini_req); ICNSS_STATS_DUMP(s, priv, ini_resp); ICNSS_STATS_DUMP(s, priv, ini_req_err); + ICNSS_STATS_DUMP(s, priv, vbatt_req); + ICNSS_STATS_DUMP(s, priv, vbatt_resp); + ICNSS_STATS_DUMP(s, priv, vbatt_req_err); + + seq_puts(s, "\n<------------------ PM stats ------------------->\n"); + ICNSS_STATS_DUMP(s, priv, pm_suspend); + ICNSS_STATS_DUMP(s, priv, pm_suspend_err); + ICNSS_STATS_DUMP(s, priv, pm_resume); + ICNSS_STATS_DUMP(s, priv, pm_resume_err); + ICNSS_STATS_DUMP(s, priv, pm_suspend_noirq); + ICNSS_STATS_DUMP(s, priv, pm_suspend_noirq_err); + ICNSS_STATS_DUMP(s, priv, pm_resume_noirq); + ICNSS_STATS_DUMP(s, priv, pm_resume_noirq_err); icnss_stats_show_irqs(s, priv); @@ -3428,6 +3859,207 @@ static const struct file_operations icnss_stats_fops = { .llseek = seq_lseek, }; +static int icnss_regwrite_show(struct seq_file *s, void *data) +{ + struct icnss_priv *priv = s->private; + + seq_puts(s, "\nUsage: echo <mem_type> <offset> <reg_val> > <debugfs>/icnss/reg_write\n"); + + if (!test_bit(ICNSS_FW_READY, &priv->state)) + seq_puts(s, "Firmware is not ready yet!, wait for FW READY\n"); + + return 0; +} + +static ssize_t icnss_regwrite_write(struct file *fp, + const char __user *user_buf, + size_t count, loff_t *off) +{ + struct icnss_priv *priv = + ((struct seq_file *)fp->private_data)->private; + char buf[64]; + char *sptr, *token; + unsigned int len = 0; + uint32_t reg_offset, mem_type, reg_val; + const char *delim = " "; + int ret = 0; + + if (!test_bit(ICNSS_FW_READY, &priv->state) || + !test_bit(ICNSS_POWER_ON, &priv->state)) + return -EINVAL; + + len = min(count, sizeof(buf) - 1); + if (copy_from_user(buf, user_buf, len)) + return -EFAULT; + + buf[len] = '\0'; + sptr = buf; + + token = strsep(&sptr, delim); + if (!token) + return -EINVAL; + + if (!sptr) + return -EINVAL; + + if (kstrtou32(token, 0, &mem_type)) + return -EINVAL; + + token = strsep(&sptr, delim); + if (!token) + return -EINVAL; + + if (!sptr) + return -EINVAL; + + if (kstrtou32(token, 0, ®_offset)) + return -EINVAL; + + token = strsep(&sptr, delim); + if (!token) + return -EINVAL; + + if (kstrtou32(token, 0, ®_val)) + return -EINVAL; + + ret = wlfw_athdiag_write_send_sync_msg(priv, reg_offset, mem_type, + sizeof(uint32_t), + (uint8_t *)®_val); + if (ret) + return ret; + + return count; +} + +static int icnss_regwrite_open(struct inode *inode, struct file *file) +{ + return single_open(file, icnss_regwrite_show, inode->i_private); +} + +static const struct file_operations icnss_regwrite_fops = { + .read = seq_read, + .write = icnss_regwrite_write, + .open = icnss_regwrite_open, + .owner = THIS_MODULE, + .llseek = seq_lseek, +}; + +static int icnss_regread_show(struct seq_file *s, void *data) +{ + struct icnss_priv *priv = s->private; + + if (!priv->diag_reg_read_buf) { + seq_puts(s, "Usage: echo <mem_type> <offset> <data_len> > <debugfs>/icnss/reg_read\n"); + + if (!test_bit(ICNSS_FW_READY, &priv->state)) + seq_puts(s, "Firmware is not ready yet!, wait for FW READY\n"); + + return 0; + } + + seq_printf(s, "REGREAD: Addr 0x%x Type 0x%x Length 0x%x\n", + priv->diag_reg_read_addr, priv->diag_reg_read_mem_type, + priv->diag_reg_read_len); + + seq_hex_dump(s, "", DUMP_PREFIX_OFFSET, 32, 4, priv->diag_reg_read_buf, + priv->diag_reg_read_len, false); + + priv->diag_reg_read_len = 0; + kfree(priv->diag_reg_read_buf); + priv->diag_reg_read_buf = NULL; + + return 0; +} + +static ssize_t icnss_regread_write(struct file *fp, const char __user *user_buf, + size_t count, loff_t *off) +{ + struct icnss_priv *priv = + ((struct seq_file *)fp->private_data)->private; + char buf[64]; + char *sptr, *token; + unsigned int len = 0; + uint32_t reg_offset, mem_type; + uint32_t data_len = 0; + uint8_t *reg_buf = NULL; + const char *delim = " "; + int ret = 0; + + if (!test_bit(ICNSS_FW_READY, &priv->state) || + !test_bit(ICNSS_POWER_ON, &priv->state)) + return -EINVAL; + + len = min(count, sizeof(buf) - 1); + if (copy_from_user(buf, user_buf, len)) + return -EFAULT; + + buf[len] = '\0'; + sptr = buf; + + token = strsep(&sptr, delim); + if (!token) + return -EINVAL; + + if (!sptr) + return -EINVAL; + + if (kstrtou32(token, 0, &mem_type)) + return -EINVAL; + + token = strsep(&sptr, delim); + if (!token) + return -EINVAL; + + if (!sptr) + return -EINVAL; + + if (kstrtou32(token, 0, ®_offset)) + return -EINVAL; + + token = strsep(&sptr, delim); + if (!token) + return -EINVAL; + + if (kstrtou32(token, 0, &data_len)) + return -EINVAL; + + if (data_len == 0 || + data_len > QMI_WLFW_MAX_DATA_SIZE_V01) + return -EINVAL; + + reg_buf = kzalloc(data_len, GFP_KERNEL); + if (!reg_buf) + return -ENOMEM; + + ret = wlfw_athdiag_read_send_sync_msg(priv, reg_offset, + mem_type, data_len, + reg_buf); + if (ret) { + kfree(reg_buf); + return ret; + } + + priv->diag_reg_read_addr = reg_offset; + priv->diag_reg_read_mem_type = mem_type; + priv->diag_reg_read_len = data_len; + priv->diag_reg_read_buf = reg_buf; + + return count; +} + +static int icnss_regread_open(struct inode *inode, struct file *file) +{ + return single_open(file, icnss_regread_show, inode->i_private); +} + +static const struct file_operations icnss_regread_fops = { + .read = seq_read, + .write = icnss_regread_write, + .open = icnss_regread_open, + .owner = THIS_MODULE, + .llseek = seq_lseek, +}; + static int icnss_debugfs_create(struct icnss_priv *priv) { int ret = 0; @@ -3448,6 +4080,10 @@ static int icnss_debugfs_create(struct icnss_priv *priv) debugfs_create_file("stats", 0644, root_dentry, priv, &icnss_stats_fops); + debugfs_create_file("reg_read", 0600, root_dentry, priv, + &icnss_regread_fops); + debugfs_create_file("reg_write", 0644, root_dentry, priv, + &icnss_regwrite_fops); out: return ret; @@ -3458,6 +4094,44 @@ static void icnss_debugfs_destroy(struct icnss_priv *priv) debugfs_remove_recursive(priv->root_dentry); } +static int icnss_get_vbatt_info(struct icnss_priv *priv) +{ + struct qpnp_adc_tm_chip *adc_tm_dev = NULL; + struct qpnp_vadc_chip *vadc_dev = NULL; + int ret = 0; + + adc_tm_dev = qpnp_get_adc_tm(&priv->pdev->dev, "icnss"); + if (PTR_ERR(adc_tm_dev) == -EPROBE_DEFER) { + icnss_pr_err("adc_tm_dev probe defer\n"); + return -EPROBE_DEFER; + } + + if (IS_ERR(adc_tm_dev)) { + ret = PTR_ERR(adc_tm_dev); + icnss_pr_err("Not able to get ADC dev, VBATT monitoring is disabled: %d\n", + ret); + return ret; + } + + vadc_dev = qpnp_get_vadc(&priv->pdev->dev, "icnss"); + if (PTR_ERR(vadc_dev) == -EPROBE_DEFER) { + icnss_pr_err("vadc_dev probe defer\n"); + return -EPROBE_DEFER; + } + + if (IS_ERR(vadc_dev)) { + ret = PTR_ERR(vadc_dev); + icnss_pr_err("Not able to get VADC dev, VBATT monitoring is disabled: %d\n", + ret); + return ret; + } + + priv->adc_tm_dev = adc_tm_dev; + priv->vadc_dev = vadc_dev; + + return 0; +} + static int icnss_probe(struct platform_device *pdev) { int ret = 0; @@ -3477,10 +4151,15 @@ static int icnss_probe(struct platform_device *pdev) if (!priv) return -ENOMEM; + priv->magic = ICNSS_MAGIC; dev_set_drvdata(dev, priv); priv->pdev = pdev; + ret = icnss_get_vbatt_info(priv); + if (ret == -EPROBE_DEFER) + goto out; + memcpy(priv->vreg_info, icnss_vreg_info, sizeof(icnss_vreg_info)); for (i = 0; i < ICNSS_VREG_INFO_SIZE; i++) { ret = icnss_get_vreg_info(dev, &priv->vreg_info[i]); @@ -3725,6 +4404,131 @@ out: return ret; } +#ifdef CONFIG_PM_SLEEP +static int icnss_pm_suspend(struct device *dev) +{ + struct icnss_priv *priv = dev_get_drvdata(dev); + int ret = 0; + + if (priv->magic != ICNSS_MAGIC) { + icnss_pr_err("Invalid drvdata for pm suspend: dev %p, data %p, magic 0x%x\n", + dev, priv, priv->magic); + return -EINVAL; + } + + icnss_pr_dbg("PM Suspend, state: 0x%lx\n", priv->state); + + if (!priv->ops || !priv->ops->pm_suspend || + !test_bit(ICNSS_DRIVER_PROBED, &priv->state)) + goto out; + + ret = priv->ops->pm_suspend(dev); + +out: + if (ret == 0) { + priv->stats.pm_suspend++; + set_bit(ICNSS_PM_SUSPEND, &priv->state); + } else { + priv->stats.pm_suspend_err++; + } + return ret; +} + +static int icnss_pm_resume(struct device *dev) +{ + struct icnss_priv *priv = dev_get_drvdata(dev); + int ret = 0; + + if (priv->magic != ICNSS_MAGIC) { + icnss_pr_err("Invalid drvdata for pm resume: dev %p, data %p, magic 0x%x\n", + dev, priv, priv->magic); + return -EINVAL; + } + + icnss_pr_dbg("PM resume, state: 0x%lx\n", priv->state); + + if (!priv->ops || !priv->ops->pm_resume || + !test_bit(ICNSS_DRIVER_PROBED, &priv->state)) + goto out; + + ret = priv->ops->pm_resume(dev); + +out: + if (ret == 0) { + priv->stats.pm_resume++; + clear_bit(ICNSS_PM_SUSPEND, &priv->state); + } else { + priv->stats.pm_resume_err++; + } + return ret; +} + +static int icnss_pm_suspend_noirq(struct device *dev) +{ + struct icnss_priv *priv = dev_get_drvdata(dev); + int ret = 0; + + if (priv->magic != ICNSS_MAGIC) { + icnss_pr_err("Invalid drvdata for pm suspend_noirq: dev %p, data %p, magic 0x%x\n", + dev, priv, priv->magic); + return -EINVAL; + } + + icnss_pr_dbg("PM suspend_noirq, state: 0x%lx\n", priv->state); + + if (!priv->ops || !priv->ops->suspend_noirq || + !test_bit(ICNSS_DRIVER_PROBED, &priv->state)) + goto out; + + ret = priv->ops->suspend_noirq(dev); + +out: + if (ret == 0) { + priv->stats.pm_suspend_noirq++; + set_bit(ICNSS_PM_SUSPEND_NOIRQ, &priv->state); + } else { + priv->stats.pm_suspend_noirq_err++; + } + return ret; +} + +static int icnss_pm_resume_noirq(struct device *dev) +{ + struct icnss_priv *priv = dev_get_drvdata(dev); + int ret = 0; + + if (priv->magic != ICNSS_MAGIC) { + icnss_pr_err("Invalid drvdata for pm resume_noirq: dev %p, data %p, magic 0x%x\n", + dev, priv, priv->magic); + return -EINVAL; + } + + icnss_pr_dbg("PM resume_noirq, state: 0x%lx\n", priv->state); + + if (!priv->ops || !priv->ops->resume_noirq || + !test_bit(ICNSS_DRIVER_PROBED, &priv->state)) + goto out; + + ret = priv->ops->resume_noirq(dev); + +out: + if (ret == 0) { + priv->stats.pm_resume_noirq++; + clear_bit(ICNSS_PM_SUSPEND_NOIRQ, &priv->state); + } else { + priv->stats.pm_resume_noirq_err++; + } + return ret; +} +#endif + +static const struct dev_pm_ops icnss_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(icnss_pm_suspend, + icnss_pm_resume) + SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(icnss_pm_suspend_noirq, + icnss_pm_resume_noirq) +}; + static const struct of_device_id icnss_dt_match[] = { {.compatible = "qcom,icnss"}, {} @@ -3739,6 +4543,7 @@ static struct platform_driver icnss_driver = { .resume = icnss_resume, .driver = { .name = "icnss", + .pm = &icnss_pm_ops, .owner = THIS_MODULE, .of_match_table = icnss_dt_match, }, diff --git a/drivers/soc/qcom/memshare/msm_memshare.c b/drivers/soc/qcom/memshare/msm_memshare.c index f44f6f97ecdd..e1e91f56526d 100644 --- a/drivers/soc/qcom/memshare/msm_memshare.c +++ b/drivers/soc/qcom/memshare/msm_memshare.c @@ -203,6 +203,7 @@ static int modem_notifier_cb(struct notifier_block *this, unsigned long code, int dest_vmids[1] = {VMID_HLOS}; int dest_perms[1] = {PERM_READ|PERM_WRITE}; + mutex_lock(&memsh_drv->mem_share); switch (code) { case SUBSYS_BEFORE_SHUTDOWN: @@ -264,6 +265,7 @@ static int modem_notifier_cb(struct notifier_block *this, unsigned long code, break; } + mutex_unlock(&memsh_drv->mem_share); return NOTIFY_DONE; } diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 38ae877c46e3..3ffb01ff6549 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -1203,10 +1203,11 @@ static int proc_getdriver(struct usb_dev_state *ps, void __user *arg) static int proc_connectinfo(struct usb_dev_state *ps, void __user *arg) { - struct usbdevfs_connectinfo ci = { - .devnum = ps->dev->devnum, - .slow = ps->dev->speed == USB_SPEED_LOW - }; + struct usbdevfs_connectinfo ci; + + memset(&ci, 0, sizeof(ci)); + ci.devnum = ps->dev->devnum; + ci.slow = ps->dev->speed == USB_SPEED_LOW; if (copy_to_user(arg, &ci, sizeof(ci))) return -EFAULT; diff --git a/drivers/video/fbdev/msm/mdss.h b/drivers/video/fbdev/msm/mdss.h index 4724f4378e23..609a7aed4977 100644 --- a/drivers/video/fbdev/msm/mdss.h +++ b/drivers/video/fbdev/msm/mdss.h @@ -191,6 +191,7 @@ enum mdss_qos_settings { MDSS_QOS_TS_PREFILL, MDSS_QOS_REMAPPER, MDSS_QOS_IB_NOCR, + MDSS_QOS_WB2_WRITE_GATHER_EN, MDSS_QOS_MAX, }; diff --git a/drivers/video/fbdev/msm/mdss_mdp.c b/drivers/video/fbdev/msm/mdss_mdp.c index cd842cecc945..1b5c1b7d51e1 100644 --- a/drivers/video/fbdev/msm/mdss_mdp.c +++ b/drivers/video/fbdev/msm/mdss_mdp.c @@ -1984,6 +1984,7 @@ static void mdss_mdp_hw_rev_caps_init(struct mdss_data_type *mdata) set_bit(MDSS_QOS_SIMPLIFIED_PREFILL, mdata->mdss_qos_map); set_bit(MDSS_QOS_TS_PREFILL, mdata->mdss_qos_map); set_bit(MDSS_QOS_IB_NOCR, mdata->mdss_qos_map); + set_bit(MDSS_QOS_WB2_WRITE_GATHER_EN, mdata->mdss_qos_map); set_bit(MDSS_CAPS_YUV_CONFIG, mdata->mdss_caps_map); set_bit(MDSS_CAPS_SCM_RESTORE_NOT_REQUIRED, mdata->mdss_caps_map); diff --git a/drivers/video/fbdev/msm/mdss_mdp_hwio.h b/drivers/video/fbdev/msm/mdss_mdp_hwio.h index f54cbb575535..5d8c83126b1b 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_hwio.h +++ b/drivers/video/fbdev/msm/mdss_mdp_hwio.h @@ -829,6 +829,7 @@ enum mdss_mdp_pingpong_index { #define MMSS_VBIF_CLKON 0x4 #define MMSS_VBIF_RD_LIM_CONF 0x0B0 #define MMSS_VBIF_WR_LIM_CONF 0x0C0 +#define MDSS_VBIF_WRITE_GATHER_EN 0x0AC #define MMSS_VBIF_XIN_HALT_CTRL0 0x200 #define MMSS_VBIF_XIN_HALT_CTRL1 0x204 diff --git a/drivers/video/fbdev/msm/mdss_mdp_intf_writeback.c b/drivers/video/fbdev/msm/mdss_mdp_intf_writeback.c index 9026b99cd87a..40b10e368309 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_intf_writeback.c +++ b/drivers/video/fbdev/msm/mdss_mdp_intf_writeback.c @@ -488,6 +488,10 @@ int mdss_mdp_writeback_prepare_cwb(struct mdss_mdp_ctl *ctl, mdss_mdp_writeback_cwb_overflow, sctl); } + if (test_bit(MDSS_QOS_WB2_WRITE_GATHER_EN, ctl->mdata->mdss_qos_map)) + MDSS_VBIF_WRITE(ctl->mdata, MDSS_VBIF_WRITE_GATHER_EN, + BIT(6), false); + if (ctl->mdata->default_ot_wr_limit || ctl->mdata->default_ot_rd_limit) mdss_mdp_set_ot_limit_wb(ctx, false); @@ -907,6 +911,10 @@ static int mdss_mdp_writeback_display(struct mdss_mdp_ctl *ctl, void *arg) return ret; } + if (test_bit(MDSS_QOS_WB2_WRITE_GATHER_EN, ctl->mdata->mdss_qos_map)) + MDSS_VBIF_WRITE(ctl->mdata, MDSS_VBIF_WRITE_GATHER_EN, + BIT(6), false); + mdss_mdp_set_intr_callback(ctx->intr_type, ctx->intf_num, mdss_mdp_writeback_intr_done, ctl); diff --git a/fs/ext4/crypto.c b/fs/ext4/crypto.c index 1acac7fd21b2..032d0b9bb324 100644 --- a/fs/ext4/crypto.c +++ b/fs/ext4/crypto.c @@ -93,7 +93,8 @@ void ext4_release_crypto_ctx(struct ext4_crypto_ctx *ctx) * Return: An allocated and initialized encryption context on success; error * value or NULL otherwise. */ -struct ext4_crypto_ctx *ext4_get_crypto_ctx(struct inode *inode) +struct ext4_crypto_ctx *ext4_get_crypto_ctx(struct inode *inode, + gfp_t gfp_flags) { struct ext4_crypto_ctx *ctx = NULL; int res = 0; @@ -120,7 +121,7 @@ struct ext4_crypto_ctx *ext4_get_crypto_ctx(struct inode *inode) list_del(&ctx->free_list); spin_unlock_irqrestore(&ext4_crypto_ctx_lock, flags); if (!ctx) { - ctx = kmem_cache_zalloc(ext4_crypto_ctx_cachep, GFP_NOFS); + ctx = kmem_cache_zalloc(ext4_crypto_ctx_cachep, gfp_flags); if (!ctx) { res = -ENOMEM; goto out; @@ -257,7 +258,8 @@ static int ext4_page_crypto(struct inode *inode, ext4_direction_t rw, pgoff_t index, struct page *src_page, - struct page *dest_page) + struct page *dest_page, + gfp_t gfp_flags) { u8 xts_tweak[EXT4_XTS_TWEAK_SIZE]; @@ -309,9 +311,10 @@ static int ext4_page_crypto(struct inode *inode, return 0; } -static struct page *alloc_bounce_page(struct ext4_crypto_ctx *ctx) +static struct page *alloc_bounce_page(struct ext4_crypto_ctx *ctx, + gfp_t gfp_flags) { - ctx->w.bounce_page = mempool_alloc(ext4_bounce_page_pool, GFP_NOWAIT); + ctx->w.bounce_page = mempool_alloc(ext4_bounce_page_pool, gfp_flags); if (ctx->w.bounce_page == NULL) return ERR_PTR(-ENOMEM); ctx->flags |= EXT4_WRITE_PATH_FL; @@ -334,7 +337,8 @@ static struct page *alloc_bounce_page(struct ext4_crypto_ctx *ctx) * error value or NULL. */ struct page *ext4_encrypt(struct inode *inode, - struct page *plaintext_page) + struct page *plaintext_page, + gfp_t gfp_flags) { struct ext4_crypto_ctx *ctx; struct page *ciphertext_page = NULL; @@ -342,17 +346,17 @@ struct page *ext4_encrypt(struct inode *inode, BUG_ON(!PageLocked(plaintext_page)); - ctx = ext4_get_crypto_ctx(inode); + ctx = ext4_get_crypto_ctx(inode, gfp_flags); if (IS_ERR(ctx)) return (struct page *) ctx; /* The encryption operation will require a bounce page. */ - ciphertext_page = alloc_bounce_page(ctx); + ciphertext_page = alloc_bounce_page(ctx, gfp_flags); if (IS_ERR(ciphertext_page)) goto errout; ctx->w.control_page = plaintext_page; err = ext4_page_crypto(inode, EXT4_ENCRYPT, plaintext_page->index, - plaintext_page, ciphertext_page); + plaintext_page, ciphertext_page, gfp_flags); if (err) { ciphertext_page = ERR_PTR(err); errout: @@ -380,8 +384,8 @@ int ext4_decrypt(struct page *page) { BUG_ON(!PageLocked(page)); - return ext4_page_crypto(page->mapping->host, - EXT4_DECRYPT, page->index, page, page); + return ext4_page_crypto(page->mapping->host, EXT4_DECRYPT, + page->index, page, page, GFP_NOFS); } int ext4_encrypted_zeroout(struct inode *inode, struct ext4_extent *ex) @@ -402,11 +406,11 @@ int ext4_encrypted_zeroout(struct inode *inode, struct ext4_extent *ex) BUG_ON(inode->i_sb->s_blocksize != PAGE_CACHE_SIZE); - ctx = ext4_get_crypto_ctx(inode); + ctx = ext4_get_crypto_ctx(inode, GFP_NOFS); if (IS_ERR(ctx)) return PTR_ERR(ctx); - ciphertext_page = alloc_bounce_page(ctx); + ciphertext_page = alloc_bounce_page(ctx, GFP_NOWAIT); if (IS_ERR(ciphertext_page)) { err = PTR_ERR(ciphertext_page); goto errout; @@ -414,11 +418,12 @@ int ext4_encrypted_zeroout(struct inode *inode, struct ext4_extent *ex) while (len--) { err = ext4_page_crypto(inode, EXT4_ENCRYPT, lblk, - ZERO_PAGE(0), ciphertext_page); + ZERO_PAGE(0), ciphertext_page, + GFP_NOFS); if (err) goto errout; - bio = bio_alloc(GFP_KERNEL, 1); + bio = bio_alloc(GFP_NOWAIT, 1); if (!bio) { err = -ENOMEM; goto errout; @@ -477,13 +482,16 @@ uint32_t ext4_validate_encryption_key_size(uint32_t mode, uint32_t size) */ static int ext4_d_revalidate(struct dentry *dentry, unsigned int flags) { - struct inode *dir = d_inode(dentry->d_parent); - struct ext4_crypt_info *ci = EXT4_I(dir)->i_crypt_info; + struct dentry *dir; + struct ext4_crypt_info *ci; int dir_has_key, cached_with_key; - if (!ext4_encrypted_inode(dir)) + dir = dget_parent(dentry); + if (!ext4_encrypted_inode(d_inode(dir))) { + dput(dir); return 0; - + } + ci = EXT4_I(d_inode(dir))->i_crypt_info; if (ci && ci->ci_keyring_key && (ci->ci_keyring_key->flags & ((1 << KEY_FLAG_INVALIDATED) | (1 << KEY_FLAG_REVOKED) | @@ -493,6 +501,7 @@ static int ext4_d_revalidate(struct dentry *dentry, unsigned int flags) /* this should eventually be an flag in d_flags */ cached_with_key = dentry->d_fsdata != NULL; dir_has_key = (ci != NULL); + dput(dir); /* * If the dentry was cached without the key, and it is a diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index c1b4f6ab2148..785bc29e4f14 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -2251,11 +2251,13 @@ extern struct kmem_cache *ext4_crypt_info_cachep; bool ext4_valid_contents_enc_mode(uint32_t mode); uint32_t ext4_validate_encryption_key_size(uint32_t mode, uint32_t size); extern struct workqueue_struct *ext4_read_workqueue; -struct ext4_crypto_ctx *ext4_get_crypto_ctx(struct inode *inode); +struct ext4_crypto_ctx *ext4_get_crypto_ctx(struct inode *inode, + gfp_t gfp_flags); void ext4_release_crypto_ctx(struct ext4_crypto_ctx *ctx); void ext4_restore_control_page(struct page *data_page); struct page *ext4_encrypt(struct inode *inode, - struct page *plaintext_page); + struct page *plaintext_page, + gfp_t gfp_flags); int ext4_decrypt(struct page *page); int ext4_encrypted_zeroout(struct inode *inode, struct ext4_extent *ex); extern const struct dentry_operations ext4_encrypted_d_ops; diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c index 17fbe3882b8e..5c72ae5d62a6 100644 --- a/fs/ext4/page-io.c +++ b/fs/ext4/page-io.c @@ -23,6 +23,7 @@ #include <linux/kernel.h> #include <linux/slab.h> #include <linux/mm.h> +#include <linux/backing-dev.h> #include "ext4_jbd2.h" #include "xattr.h" @@ -485,9 +486,20 @@ int ext4_bio_write_page(struct ext4_io_submit *io, if (ext4_encrypted_inode(inode) && S_ISREG(inode->i_mode) && nr_to_submit) { - data_page = ext4_encrypt(inode, page); + gfp_t gfp_flags = GFP_NOFS; + + retry_encrypt: + data_page = ext4_encrypt(inode, page, gfp_flags); if (IS_ERR(data_page)) { ret = PTR_ERR(data_page); + if (ret == ENOMEM && wbc->sync_mode == WB_SYNC_ALL) { + if (io->io_bio) { + ext4_io_submit(io); + congestion_wait(BLK_RW_ASYNC, HZ/50); + } + gfp_flags |= __GFP_NOFAIL; + goto retry_encrypt; + } data_page = NULL; goto out; } diff --git a/fs/ext4/readpage.c b/fs/ext4/readpage.c index 5dc5e95063de..bc7642f57dc8 100644 --- a/fs/ext4/readpage.c +++ b/fs/ext4/readpage.c @@ -279,7 +279,7 @@ int ext4_mpage_readpages(struct address_space *mapping, if (ext4_encrypted_inode(inode) && S_ISREG(inode->i_mode)) { - ctx = ext4_get_crypto_ctx(inode); + ctx = ext4_get_crypto_ctx(inode, GFP_NOFS); if (IS_ERR(ctx)) goto set_error_page; } diff --git a/include/dt-bindings/clock/msm-clocks-cobalt.h b/include/dt-bindings/clock/msm-clocks-cobalt.h index 31c4537ea964..b80ea0c31597 100644 --- a/include/dt-bindings/clock/msm-clocks-cobalt.h +++ b/include/dt-bindings/clock/msm-clocks-cobalt.h @@ -157,6 +157,7 @@ #define clk_gcc_usb3_phy_reset 0x03d559f1 #define clk_gcc_usb3phy_phy_reset 0xb1a4f885 #define clk_gcc_aggre1_ufs_axi_clk 0x873459d8 +#define clk_gcc_aggre1_ufs_axi_hw_ctl_clk 0x117a6f39 #define clk_gcc_aggre1_usb3_axi_clk 0xc5c3fbe8 #define clk_gcc_bimc_mss_q6_axi_clk 0x7437988f #define clk_gcc_blsp1_ahb_clk 0x8caa5b4f diff --git a/include/dt-bindings/clock/qcom,gcc-msm8996.h b/include/dt-bindings/clock/qcom,gcc-msm8996.h index 3819485dead3..f66264a2beb4 100644 --- a/include/dt-bindings/clock/qcom,gcc-msm8996.h +++ b/include/dt-bindings/clock/qcom,gcc-msm8996.h @@ -233,6 +233,18 @@ #define GCC_PCIE_CLKREF_CLK 216 #define GCC_RX2_USB2_CLKREF_CLK 217 #define GCC_RX1_USB2_CLKREF_CLK 218 +#define GCC_AGGRE0_NOC_QOSGEN_EXTREF_CLK 219 +#define GCC_HLOS1_VOTE_LPASS_CORE_SMMU_CLK 220 +#define GCC_HLOS1_VOTE_LPASS_ADSP_SMMU_CLK 221 +#define GCC_EDP_CLKREF_CLK 222 +#define GCC_MSS_CFG_AHB_CLK 223 +#define GCC_MSS_Q6_BIMC_AXI_CLK 224 +#define GCC_MSS_SNOC_AXI_CLK 225 +#define GCC_MSS_MNOC_BIMC_AXI_CLK 226 +#define GCC_DCC_AHB_ALK 227 +#define GCC_AGGRE0_NOC_MPU_CFG_AHB_CLK 228 +#define GCC_MMSS_GPLL0_DIV_CLK 229 +#define GPLL0_OUT_MSSCC 230 #define GCC_SYSTEM_NOC_BCR 0 #define GCC_CONFIG_NOC_BCR 1 @@ -340,15 +352,4 @@ #define GCC_PCIE_PHY_NOCSR_COM_PHY_BCR 103 #define GCC_PCIE_PHY_COM_BCR 104 -/* Indexes for GDSCs */ -#define AGGRE0_NOC_GDSC 0 -#define HLOS1_VOTE_AGGRE0_NOC_GDSC 1 -#define HLOS1_VOTE_LPASS_ADSP_GDSC 2 -#define HLOS1_VOTE_LPASS_CORE_GDSC 3 -#define USB30_GDSC 4 -#define PCIE0_GDSC 5 -#define PCIE1_GDSC 6 -#define PCIE2_GDSC 7 -#define UFS_GDSC 8 - #endif diff --git a/include/linux/phy/phy-qcom-ufs.h b/include/linux/phy/phy-qcom-ufs.h index 7945fea14d77..25e7a5f183ec 100644 --- a/include/linux/phy/phy-qcom-ufs.h +++ b/include/linux/phy/phy-qcom-ufs.h @@ -58,5 +58,6 @@ void ufs_qcom_phy_save_controller_version(struct phy *phy, u8 major, u16 minor, u16 step); const char *ufs_qcom_phy_name(struct phy *phy); int ufs_qcom_phy_configure_lpm(struct phy *generic_phy, bool enable); +void ufs_qcom_phy_dbg_register_dump(struct phy *generic_phy); #endif /* PHY_QCOM_UFS_H_ */ diff --git a/include/net/rmnet_config.h b/include/net/rmnet_config.h new file mode 100644 index 000000000000..0e6282b05483 --- /dev/null +++ b/include/net/rmnet_config.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2016, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * RMNET Data config definition + * + */ + +#ifndef _RMNET_CONFIG_H_ +#define _RMNET_CONFIG_H_ + +#include <linux/skbuff.h> + +struct rmnet_phys_ep_conf_s { + void (*recycle)(struct sk_buff *); /* Destruct function */ + void *config; +}; + +#endif /* _RMNET_CONFIG_H_ */ diff --git a/include/soc/qcom/icnss.h b/include/soc/qcom/icnss.h index 8b64bf3b8de9..efc5425cf17d 100644 --- a/include/soc/qcom/icnss.h +++ b/include/soc/qcom/icnss.h @@ -26,6 +26,10 @@ struct icnss_driver_ops { void (*crash_shutdown)(void *pdev); int (*suspend)(struct device *dev, pm_message_t state); int (*resume)(struct device *dev); + int (*pm_suspend)(struct device *dev); + int (*pm_resume)(struct device *dev); + int (*suspend_noirq)(struct device *dev); + int (*resume_noirq)(struct device *dev); }; @@ -103,6 +107,12 @@ extern int icnss_ce_request_irq(unsigned int ce_id, unsigned long flags, const char *name, void *ctx); extern int icnss_get_ce_id(int irq); extern int icnss_set_fw_debug_mode(bool enable_fw_log); +extern int icnss_athdiag_read(struct device *dev, uint32_t offset, + uint32_t mem_type, uint32_t data_len, + uint8_t *output); +extern int icnss_athdiag_write(struct device *dev, uint32_t offset, + uint32_t mem_type, uint32_t data_len, + uint8_t *input); extern int icnss_get_irq(int ce_id); extern int icnss_power_on(struct device *dev); extern int icnss_power_off(struct device *dev); diff --git a/include/sound/q6asm-v2.h b/include/sound/q6asm-v2.h index dadc2f7a4eae..8525f2e7f738 100644 --- a/include/sound/q6asm-v2.h +++ b/include/sound/q6asm-v2.h @@ -226,7 +226,7 @@ struct audio_client *q6asm_get_audio_client(int session_id); int q6asm_audio_client_buf_alloc(unsigned int dir/* 1:Out,0:In */, struct audio_client *ac, unsigned int bufsz, - unsigned int bufcnt); + uint32_t bufcnt); int q6asm_audio_client_buf_alloc_contiguous(unsigned int dir /* 1:Out,0:In */, struct audio_client *ac, diff --git a/net/rmnet_data/rmnet_data_config.c b/net/rmnet_data/rmnet_data_config.c index c49393924e26..ebce455b645d 100644 --- a/net/rmnet_data/rmnet_data_config.c +++ b/net/rmnet_data/rmnet_data_config.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2016, 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 @@ -21,6 +21,7 @@ #include <linux/skbuff.h> #include <linux/spinlock.h> #include <linux/rmnet_data.h> +#include <net/rmnet_config.h> #include "rmnet_data_config.h" #include "rmnet_data_handlers.h" #include "rmnet_data_vnd.h" @@ -141,14 +142,22 @@ static inline int _rmnet_is_physical_endpoint_associated(struct net_device *dev) * - pointer to configuration if successful * - 0 (null) if device is not associated */ -static inline struct rmnet_phys_ep_conf_s *_rmnet_get_phys_ep_config - (struct net_device *dev) +struct rmnet_phys_ep_config *_rmnet_get_phys_ep_config + (struct net_device *dev) { - if (_rmnet_is_physical_endpoint_associated(dev)) - return (struct rmnet_phys_ep_conf_s *) - rcu_dereference(dev->rx_handler_data); - else + struct rmnet_phys_ep_conf_s *_rmnet_phys_ep_config; + + if (_rmnet_is_physical_endpoint_associated(dev)) { + _rmnet_phys_ep_config = (struct rmnet_phys_ep_conf_s *) + rcu_dereference(dev->rx_handler_data); + if (_rmnet_phys_ep_config && _rmnet_phys_ep_config->config) + return (struct rmnet_phys_ep_config *) + _rmnet_phys_ep_config->config; + else + return 0; + } else { return 0; + } } /** @@ -165,7 +174,7 @@ static inline struct rmnet_phys_ep_conf_s *_rmnet_get_phys_ep_config struct rmnet_logical_ep_conf_s *_rmnet_get_logical_ep(struct net_device *dev, int config_id) { - struct rmnet_phys_ep_conf_s *config; + struct rmnet_phys_ep_config *config; struct rmnet_logical_ep_conf_s *epconfig_l; if (rmnet_vnd_is_vnd(dev)) @@ -400,7 +409,7 @@ static void _rmnet_netlink_get_link_egress_data_format struct rmnet_nl_msg_s *resp_rmnet) { struct net_device *dev; - struct rmnet_phys_ep_conf_s *config; + struct rmnet_phys_ep_config *config; _RMNET_NETLINK_NULL_CHECKS(); resp_rmnet->crd = RMNET_NETLINK_MSG_RETURNCODE; @@ -432,7 +441,7 @@ static void _rmnet_netlink_get_link_ingress_data_format struct rmnet_nl_msg_s *resp_rmnet) { struct net_device *dev; - struct rmnet_phys_ep_conf_s *config; + struct rmnet_phys_ep_config *config; _RMNET_NETLINK_NULL_CHECKS(); resp_rmnet->crd = RMNET_NETLINK_MSG_RETURNCODE; @@ -725,7 +734,7 @@ int rmnet_set_ingress_data_format(struct net_device *dev, uint32_t ingress_data_format, uint8_t tail_spacing) { - struct rmnet_phys_ep_conf_s *config; + struct rmnet_phys_ep_config *config; ASSERT_RTNL(); LOGL("(%s,0x%08X);", dev->name, ingress_data_format); @@ -762,7 +771,7 @@ int rmnet_set_egress_data_format(struct net_device *dev, uint16_t agg_size, uint16_t agg_count) { - struct rmnet_phys_ep_conf_s *config; + struct rmnet_phys_ep_config *config; ASSERT_RTNL(); LOGL("(%s,0x%08X, %d, %d);", @@ -800,7 +809,9 @@ int rmnet_set_egress_data_format(struct net_device *dev, int rmnet_associate_network_device(struct net_device *dev) { struct rmnet_phys_ep_conf_s *config; + struct rmnet_phys_ep_config *conf; int rc; + ASSERT_RTNL(); LOGL("(%s);\n", dev->name); @@ -819,19 +830,25 @@ int rmnet_associate_network_device(struct net_device *dev) } config = kmalloc(sizeof(*config), GFP_ATOMIC); + conf = kmalloc(sizeof(*conf), GFP_ATOMIC); - if (!config) + if (!config || !conf) return RMNET_CONFIG_NOMEM; memset(config, 0, sizeof(struct rmnet_phys_ep_conf_s)); - config->dev = dev; - spin_lock_init(&config->agg_lock); + memset(conf, 0, sizeof(struct rmnet_phys_ep_config)); + + config->config = conf; + conf->dev = dev; + spin_lock_init(&conf->agg_lock); + config->recycle = kfree_skb; rc = netdev_rx_handler_register(dev, rmnet_rx_handler, config); if (rc) { LOGM("netdev_rx_handler_register returns %d", rc); kfree(config); + kfree(conf); return RMNET_CONFIG_DEVICE_IN_USE; } diff --git a/net/rmnet_data/rmnet_data_config.h b/net/rmnet_data/rmnet_data_config.h index a76bcef79e6a..78329c38b364 100644 --- a/net/rmnet_data/rmnet_data_config.h +++ b/net/rmnet_data/rmnet_data_config.h @@ -17,6 +17,7 @@ #include <linux/types.h> #include <linux/time.h> #include <linux/spinlock.h> +#include <net/rmnet_config.h> #ifndef _RMNET_DATA_CONFIG_H_ #define _RMNET_DATA_CONFIG_H_ @@ -62,7 +63,7 @@ struct rmnet_logical_ep_conf_s { * @agg_time: Wall clock time when aggregated frame was created * @agg_last: Last time the aggregation routing was invoked */ -struct rmnet_phys_ep_conf_s { +struct rmnet_phys_ep_config { struct net_device *dev; struct rmnet_logical_ep_conf_s local_ep; struct rmnet_logical_ep_conf_s muxed_ep[RMNET_DATA_MAX_LOGICAL_EP]; @@ -123,4 +124,7 @@ int rmnet_create_vnd(int id); int rmnet_create_vnd_prefix(int id, const char *name); int rmnet_free_vnd(int id); +struct rmnet_phys_ep_config *_rmnet_get_phys_ep_config + (struct net_device *dev); + #endif /* _RMNET_DATA_CONFIG_H_ */ diff --git a/net/rmnet_data/rmnet_data_handlers.c b/net/rmnet_data/rmnet_data_handlers.c index 9d04b2f8ddd9..185b609e637f 100644 --- a/net/rmnet_data/rmnet_data_handlers.c +++ b/net/rmnet_data/rmnet_data_handlers.c @@ -22,6 +22,7 @@ #include <linux/netdev_features.h> #include <linux/ip.h> #include <linux/ipv6.h> +#include <net/rmnet_config.h> #include "rmnet_data_private.h" #include "rmnet_data_config.h" #include "rmnet_data_vnd.h" @@ -321,7 +322,7 @@ static rx_handler_result_t __rmnet_deliver_skb(struct sk_buff *skb, * - RX_HANDLER_PASS if packet should be passed up the stack by caller */ static rx_handler_result_t rmnet_ingress_deliver_packet(struct sk_buff *skb, - struct rmnet_phys_ep_conf_s *config) + struct rmnet_phys_ep_config *config) { if (!config) { LOGD("%s", "NULL physical EP provided"); @@ -356,7 +357,7 @@ static rx_handler_result_t rmnet_ingress_deliver_packet(struct sk_buff *skb, * - result of __rmnet_deliver_skb() for all other cases */ static rx_handler_result_t _rmnet_map_ingress_handler(struct sk_buff *skb, - struct rmnet_phys_ep_conf_s *config) + struct rmnet_phys_ep_config *config) { struct rmnet_logical_ep_conf_s *ep; uint8_t mux_id; @@ -440,7 +441,7 @@ static rx_handler_result_t _rmnet_map_ingress_handler(struct sk_buff *skb, * - result of _rmnet_map_ingress_handler() for all other cases */ static rx_handler_result_t rmnet_map_ingress_handler(struct sk_buff *skb, - struct rmnet_phys_ep_conf_s *config) + struct rmnet_phys_ep_config *config) { struct sk_buff *skbn; int rc, co = 0; @@ -480,7 +481,7 @@ static rx_handler_result_t rmnet_map_ingress_handler(struct sk_buff *skb, * - 1 on failure */ static int rmnet_map_egress_handler(struct sk_buff *skb, - struct rmnet_phys_ep_conf_s *config, + struct rmnet_phys_ep_config *config, struct rmnet_logical_ep_conf_s *ep, struct net_device *orig_dev) { @@ -563,7 +564,7 @@ static int rmnet_map_egress_handler(struct sk_buff *skb, */ rx_handler_result_t rmnet_ingress_handler(struct sk_buff *skb) { - struct rmnet_phys_ep_conf_s *config; + struct rmnet_phys_ep_config *config; struct net_device *dev; int rc; @@ -574,8 +575,7 @@ rx_handler_result_t rmnet_ingress_handler(struct sk_buff *skb) trace_rmnet_ingress_handler(skb); rmnet_print_packet(skb, dev->name, 'r'); - config = (struct rmnet_phys_ep_conf_s *) - rcu_dereference(skb->dev->rx_handler_data); + config = _rmnet_get_phys_ep_config(skb->dev); if (!config) { LOGD("%s is not associated with rmnet_data", skb->dev->name); @@ -654,14 +654,13 @@ rx_handler_result_t rmnet_rx_handler(struct sk_buff **pskb) void rmnet_egress_handler(struct sk_buff *skb, struct rmnet_logical_ep_conf_s *ep) { - struct rmnet_phys_ep_conf_s *config; + struct rmnet_phys_ep_config *config; struct net_device *orig_dev; int rc; orig_dev = skb->dev; skb->dev = ep->egress_dev; - config = (struct rmnet_phys_ep_conf_s *) - rcu_dereference(skb->dev->rx_handler_data); + config = _rmnet_get_phys_ep_config(skb->dev); if (!config) { LOGD("%s is not associated with rmnet_data", skb->dev->name); diff --git a/net/rmnet_data/rmnet_data_stats.c b/net/rmnet_data/rmnet_data_stats.c index 5fefda55c72c..20f1628242c7 100644 --- a/net/rmnet_data/rmnet_data_stats.c +++ b/net/rmnet_data/rmnet_data_stats.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, The Linux Foundation. All rights reserved. + * Copyright (c) 2014, 2016 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 @@ -21,6 +21,7 @@ #include <linux/skbuff.h> #include <linux/spinlock.h> #include <linux/netdevice.h> +#include <net/rmnet_config.h> #include "rmnet_data_private.h" #include "rmnet_data_stats.h" #include "rmnet_data_config.h" @@ -73,8 +74,16 @@ void rmnet_kfree_skb(struct sk_buff *skb, unsigned int reason) skb_free[reason]++; spin_unlock_irqrestore(&rmnet_skb_free_lock, flags); - if (skb) - kfree_skb(skb); + if (likely(skb)) { + struct rmnet_phys_ep_conf_s *config; + + config = (struct rmnet_phys_ep_conf_s *)rcu_dereference + (skb->dev->rx_handler_data); + if (likely(config)) + config->recycle(skb); + else + kfree_skb(skb); + } } void rmnet_stats_queue_xmit(int rc, unsigned int reason) diff --git a/net/rmnet_data/rmnet_map.h b/net/rmnet_data/rmnet_map.h index 0a6ad908b827..71abca122dd6 100644 --- a/net/rmnet_data/rmnet_map.h +++ b/net/rmnet_data/rmnet_map.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -13,6 +13,7 @@ #include <linux/types.h> #include <linux/spinlock.h> +#include <net/rmnet_config.h> #ifndef _RMNET_MAP_H_ #define _RMNET_MAP_H_ @@ -133,14 +134,14 @@ enum rmnet_map_agg_state_e { uint8_t rmnet_map_demultiplex(struct sk_buff *skb); struct sk_buff *rmnet_map_deaggregate(struct sk_buff *skb, - struct rmnet_phys_ep_conf_s *config); + struct rmnet_phys_ep_config *config); struct rmnet_map_header_s *rmnet_map_add_map_header(struct sk_buff *skb, int hdrlen, int pad); rx_handler_result_t rmnet_map_command(struct sk_buff *skb, - struct rmnet_phys_ep_conf_s *config); + struct rmnet_phys_ep_config *config); void rmnet_map_aggregate(struct sk_buff *skb, - struct rmnet_phys_ep_conf_s *config); + struct rmnet_phys_ep_config *config); int rmnet_map_checksum_downlink_packet(struct sk_buff *skb); int rmnet_map_checksum_uplink_packet(struct sk_buff *skb, diff --git a/net/rmnet_data/rmnet_map_command.c b/net/rmnet_data/rmnet_map_command.c index 4bcfa10db486..055d5f402957 100644 --- a/net/rmnet_data/rmnet_map_command.c +++ b/net/rmnet_data/rmnet_map_command.c @@ -18,6 +18,7 @@ #include <linux/rmnet_data.h> #include <linux/net_map.h> #include <net/pkt_sched.h> +#include <net/rmnet_config.h> #include "rmnet_data_config.h" #include "rmnet_map.h" #include "rmnet_data_private.h" @@ -44,7 +45,7 @@ MODULE_PARM_DESC(rmnet_map_command_stats, "MAP command statistics"); * - RMNET_MAP_COMMAND_ACK on success */ static uint8_t rmnet_map_do_flow_control(struct sk_buff *skb, - struct rmnet_phys_ep_conf_s *config, + struct rmnet_phys_ep_config *config, int enable) { struct rmnet_map_control_command_s *cmd; @@ -116,7 +117,7 @@ static uint8_t rmnet_map_do_flow_control(struct sk_buff *skb, */ static void rmnet_map_send_ack(struct sk_buff *skb, unsigned char type, - struct rmnet_phys_ep_conf_s *config) + struct rmnet_phys_ep_config *config) { struct rmnet_map_control_command_s *cmd; int xmit_status; @@ -162,7 +163,7 @@ static void rmnet_map_send_ack(struct sk_buff *skb, * - RX_HANDLER_CONSUMED. Command frames are always consumed. */ rx_handler_result_t rmnet_map_command(struct sk_buff *skb, - struct rmnet_phys_ep_conf_s *config) + struct rmnet_phys_ep_config *config) { struct rmnet_map_control_command_s *cmd; unsigned char command_name; diff --git a/net/rmnet_data/rmnet_map_data.c b/net/rmnet_data/rmnet_map_data.c index 68caf44c1f92..beff8332c731 100644 --- a/net/rmnet_data/rmnet_map_data.c +++ b/net/rmnet_data/rmnet_map_data.c @@ -31,6 +31,7 @@ #include <net/ip.h> #include <net/checksum.h> #include <net/ip6_checksum.h> +#include <net/rmnet_config.h> #include "rmnet_data_config.h" #include "rmnet_map.h" #include "rmnet_data_private.h" @@ -52,7 +53,7 @@ MODULE_PARM_DESC(agg_bypass_time, "Skip agg when apart spaced more than this"); struct agg_work { struct delayed_work work; - struct rmnet_phys_ep_conf_s *config; + struct rmnet_phys_ep_config *config; }; #define RMNET_MAP_DEAGGR_SPACING 64 @@ -131,7 +132,7 @@ done: * - 0 (null) if no more aggregated packets */ struct sk_buff *rmnet_map_deaggregate(struct sk_buff *skb, - struct rmnet_phys_ep_conf_s *config) + struct rmnet_phys_ep_config *config) { struct sk_buff *skbn; struct rmnet_map_header_s *maph; @@ -185,7 +186,7 @@ struct sk_buff *rmnet_map_deaggregate(struct sk_buff *skb, static void rmnet_map_flush_packet_queue(struct work_struct *work) { struct agg_work *real_work; - struct rmnet_phys_ep_conf_s *config; + struct rmnet_phys_ep_config *config; unsigned long flags; struct sk_buff *skb; int rc, agg_count = 0; @@ -233,7 +234,7 @@ static void rmnet_map_flush_packet_queue(struct work_struct *work) * the argument SKB and should not be further processed by any other function. */ void rmnet_map_aggregate(struct sk_buff *skb, - struct rmnet_phys_ep_conf_s *config) { + struct rmnet_phys_ep_config *config) { uint8_t *dest_buff; struct agg_work *work; unsigned long flags; diff --git a/sound/soc/codecs/wcd9335.c b/sound/soc/codecs/wcd9335.c index 158b9ae08642..b5126351dda0 100644 --- a/sound/soc/codecs/wcd9335.c +++ b/sound/soc/codecs/wcd9335.c @@ -793,7 +793,7 @@ struct tasha_priv { struct wcd_swr_ctrl_platform_data swr_plat_data; /* Port values for Rx and Tx codec_dai */ - unsigned int rx_port_value; + unsigned int rx_port_value[TASHA_RX_MAX]; unsigned int tx_port_value; unsigned int vi_feed_value; @@ -2597,7 +2597,8 @@ static int slim_rx_mux_get(struct snd_kcontrol *kcontrol, struct snd_soc_codec *codec = snd_soc_dapm_to_codec(widget->dapm); struct tasha_priv *tasha_p = snd_soc_codec_get_drvdata(codec); - ucontrol->value.enumerated.item[0] = tasha_p->rx_port_value; + ucontrol->value.enumerated.item[0] = + tasha_p->rx_port_value[widget->shift]; return 0; } @@ -2616,25 +2617,27 @@ static int slim_rx_mux_put(struct snd_kcontrol *kcontrol, struct wcd9xxx *core = dev_get_drvdata(codec->dev->parent); struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; struct snd_soc_dapm_update *update = NULL; + unsigned int rx_port_value; u32 port_id = widget->shift; + tasha_p->rx_port_value[port_id] = ucontrol->value.enumerated.item[0]; + rx_port_value = tasha_p->rx_port_value[port_id]; + pr_debug("%s: wname %s cname %s value %u shift %d item %ld\n", __func__, - widget->name, ucontrol->id.name, tasha_p->rx_port_value, + widget->name, ucontrol->id.name, rx_port_value, widget->shift, ucontrol->value.integer.value[0]); - tasha_p->rx_port_value = ucontrol->value.enumerated.item[0]; - mutex_lock(&tasha_p->codec_mutex); if (tasha_p->intf_type != WCD9XXX_INTERFACE_TYPE_SLIMBUS) { - if (tasha_p->rx_port_value > 2) { + if (rx_port_value > 2) { dev_err(codec->dev, "%s: invalid AIF for I2C mode\n", __func__); goto err; } } /* value need to match the Virtual port and AIF number */ - switch (tasha_p->rx_port_value) { + switch (rx_port_value) { case 0: list_del_init(&core->rx_chs[port_id].list); break; @@ -2694,13 +2697,13 @@ static int slim_rx_mux_put(struct snd_kcontrol *kcontrol, &tasha_p->dai[AIF_MIX1_PB].wcd9xxx_ch_list); break; default: - pr_err("Unknown AIF %d\n", tasha_p->rx_port_value); + pr_err("Unknown AIF %d\n", rx_port_value); goto err; } rtn: mutex_unlock(&tasha_p->codec_mutex); snd_soc_dapm_mux_update_power(widget->dapm, kcontrol, - tasha_p->rx_port_value, e, update); + rx_port_value, e, update); return 0; err: diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c index 20d3f5212323..206fbec249fa 100644 --- a/sound/soc/msm/qdsp6v2/q6asm.c +++ b/sound/soc/msm/qdsp6v2/q6asm.c @@ -1195,7 +1195,7 @@ err: int q6asm_audio_client_buf_alloc(unsigned int dir, struct audio_client *ac, unsigned int bufsz, - unsigned int bufcnt) + uint32_t bufcnt) { int cnt = 0; int rc = 0; @@ -1222,7 +1222,7 @@ int q6asm_audio_client_buf_alloc(unsigned int dir, return 0; } mutex_lock(&ac->cmd_lock); - if (bufcnt > (LONG_MAX/sizeof(struct audio_buffer))) { + if (bufcnt > (U32_MAX/sizeof(struct audio_buffer))) { pr_err("%s: Buffer size overflows", __func__); mutex_unlock(&ac->cmd_lock); goto fail; |
