diff options
| -rw-r--r-- | Documentation/devicetree/bindings/leds/leds-qpnp-wled.txt | 8 | ||||
| -rw-r--r-- | Documentation/devicetree/bindings/media/video/msm-cpp.txt | 4 | ||||
| -rw-r--r-- | arch/arm/boot/dts/qcom/msm-pm2falcon.dtsi | 2 | ||||
| -rw-r--r-- | arch/arm/boot/dts/qcom/msm-pmi8994.dtsi | 2 | ||||
| -rw-r--r-- | arch/arm/boot/dts/qcom/msm-pmicobalt.dtsi | 2 | ||||
| -rw-r--r-- | arch/arm/boot/dts/qcom/msmcobalt-camera.dtsi | 2 | ||||
| -rw-r--r-- | arch/arm/boot/dts/qcom/msmcobalt-v2-camera.dtsi | 71 | ||||
| -rw-r--r-- | drivers/leds/leds-qpnp-wled.c | 82 | ||||
| -rw-r--r-- | drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp_soc.c | 74 | ||||
| -rw-r--r-- | drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c | 3 | ||||
| -rw-r--r-- | drivers/media/platform/msm/sde/rotator/sde_rotator_r3_internal.h | 22 | ||||
| -rw-r--r-- | drivers/soc/qcom/icnss.c | 46 | ||||
| -rw-r--r-- | drivers/soc/qcom/wlan_firmware_service_v01.c | 62 | ||||
| -rw-r--r-- | drivers/soc/qcom/wlan_firmware_service_v01.h | 22 |
14 files changed, 343 insertions, 59 deletions
diff --git a/Documentation/devicetree/bindings/leds/leds-qpnp-wled.txt b/Documentation/devicetree/bindings/leds/leds-qpnp-wled.txt index ebbcfe5b2fd0..07f3fd274658 100644 --- a/Documentation/devicetree/bindings/leds/leds-qpnp-wled.txt +++ b/Documentation/devicetree/bindings/leds/leds-qpnp-wled.txt @@ -25,7 +25,11 @@ Optional properties for WLED: - linux,default-trigger : trigger for the backlight. default is NONE. - qcom,fdbk-output : string feedback current output for wled module. The accepted values are "wled1", "wled2", "wled3", "wled4" and "auto". default is "auto". -- qcom,vref-mv : maximum reference voltage in mv. default is 350. +- qcom,vref-uv : maximum reference voltage in uV. + For pmi8994/8952/8996, supported values are from 300000 to 675000 + with a step size of 25000, the default value is 350000. + For pmicobalt/pm2falcon, supported values are from 60000 to 397500 + with a step size of 22500, the default value is 127500. - qcom,switch-freq-khz : switch frequency in khz. default is 800. - qcom,ovp-mv : Over voltage protection threshold in mV. Default is 29500. Supported values are: @@ -94,7 +98,7 @@ Example: linux,name = "wled"; linux,default-trigger = "bkl-trigger"; qcom,fdbk-output = "auto"; - qcom,vref-mv = <350>; + qcom,vref-uv = <350000>; qcom,switch-freq-khz = <800>; qcom,ovp-mv = <29500>; qcom,ilim-ma = <980>; diff --git a/Documentation/devicetree/bindings/media/video/msm-cpp.txt b/Documentation/devicetree/bindings/media/video/msm-cpp.txt index 52abf409cb65..ade5fbe8cbd7 100644 --- a/Documentation/devicetree/bindings/media/video/msm-cpp.txt +++ b/Documentation/devicetree/bindings/media/video/msm-cpp.txt @@ -26,6 +26,8 @@ Required properties: and reset lines used by this controller. - reset-names: reset signal name strings sorted in the same order as the resets property. +- qcom,src-clock-rates = This is an array which holds clock rates for cpp src + clocks. The maximum size for the array is 10. Required properties of the child node: - qcom,stripe-base = Base offset of stripes in cpp payload. @@ -107,6 +109,8 @@ Example: <0x24 0x10000000>, <0x28 0x10000000>, <0x2C 0x10000000>; + qcom,src-clock-rates = <100000000 200000000 384000000 404000000 + 480000000 576000000 600000000>; qcom,cpp-fw-payload-info { qcom,stripe-base = <553>; qcom,plane-base = <481>; diff --git a/arch/arm/boot/dts/qcom/msm-pm2falcon.dtsi b/arch/arm/boot/dts/qcom/msm-pm2falcon.dtsi index 0e5a999e4642..33a4c1521e85 100644 --- a/arch/arm/boot/dts/qcom/msm-pm2falcon.dtsi +++ b/arch/arm/boot/dts/qcom/msm-pm2falcon.dtsi @@ -234,7 +234,7 @@ linux,name = "wled"; linux,default-trigger = "bkl-trigger"; qcom,fdbk-output = "auto"; - qcom,vref-mv = <350>; + qcom,vref-uv = <127500>; qcom,switch-freq-khz = <800>; qcom,ovp-mv = <29600>; qcom,ilim-ma = <970>; diff --git a/arch/arm/boot/dts/qcom/msm-pmi8994.dtsi b/arch/arm/boot/dts/qcom/msm-pmi8994.dtsi index c46c0963ff56..c820d213165b 100644 --- a/arch/arm/boot/dts/qcom/msm-pmi8994.dtsi +++ b/arch/arm/boot/dts/qcom/msm-pmi8994.dtsi @@ -523,7 +523,7 @@ linux,name = "wled"; linux,default-trigger = "bkl-trigger"; qcom,fdbk-output = "auto"; - qcom,vref-mv = <350>; + qcom,vref-uv = <350000>; qcom,switch-freq-khz = <800>; qcom,ovp-mv = <29500>; qcom,ilim-ma = <980>; diff --git a/arch/arm/boot/dts/qcom/msm-pmicobalt.dtsi b/arch/arm/boot/dts/qcom/msm-pmicobalt.dtsi index 640aa53364a5..a122e04a3f5c 100644 --- a/arch/arm/boot/dts/qcom/msm-pmicobalt.dtsi +++ b/arch/arm/boot/dts/qcom/msm-pmicobalt.dtsi @@ -598,7 +598,7 @@ linux,name = "wled"; linux,default-trigger = "bkl-trigger"; qcom,fdbk-output = "auto"; - qcom,vref-mv = <350>; + qcom,vref-uv = <127500>; qcom,switch-freq-khz = <800>; qcom,ovp-mv = <29600>; qcom,ilim-ma = <970>; diff --git a/arch/arm/boot/dts/qcom/msmcobalt-camera.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-camera.dtsi index 27e537c9c702..6a0061e206ca 100644 --- a/arch/arm/boot/dts/qcom/msmcobalt-camera.dtsi +++ b/arch/arm/boot/dts/qcom/msmcobalt-camera.dtsi @@ -422,6 +422,8 @@ qcom,msm-bus-vector-dyn-vote; resets = <&clock_mmss CAMSS_MICRO_BCR>; reset-names = "micro_iface_reset"; + qcom,src-clock-rates = <100000000 200000000 576000000 + 600000000>; qcom,cpp-fw-payload-info { qcom,stripe-base = <790>; qcom,plane-base = <715>; diff --git a/arch/arm/boot/dts/qcom/msmcobalt-v2-camera.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-v2-camera.dtsi index fcc4d6d8ee2d..a81287c36266 100644 --- a/arch/arm/boot/dts/qcom/msmcobalt-v2-camera.dtsi +++ b/arch/arm/boot/dts/qcom/msmcobalt-v2-camera.dtsi @@ -116,5 +116,76 @@ 0 256000000 0>; status = "ok"; }; + + qcom,cpp@ca04000 { + cell-index = <0>; + compatible = "qcom,cpp"; + reg = <0xca04000 0x100>, + <0xca80000 0x3000>, + <0xca18000 0x3000>, + <0xc8c36d4 0x4>; + reg-names = "cpp", "cpp_vbif", "cpp_hw", "camss_cpp"; + interrupts = <0 294 0>; + interrupt-names = "cpp"; + smmu-vdd-supply = <&gdsc_bimc_smmu>; + camss-vdd-supply = <&gdsc_camss_top>; + vdd-supply = <&gdsc_cpp>; + qcom,vdd-names = "smmu-vdd", "camss-vdd", "vdd"; + clocks = <&clock_gcc clk_mmssnoc_axi_clk>, + <&clock_mmss clk_mmss_mnoc_ahb_clk>, + <&clock_mmss clk_mmss_camss_ahb_clk>, + <&clock_mmss clk_mmss_camss_top_ahb_clk>, + <&clock_mmss clk_cpp_clk_src>, + <&clock_mmss clk_mmss_camss_cpp_clk>, + <&clock_mmss clk_mmss_camss_cpp_ahb_clk>, + <&clock_mmss clk_mmss_camss_cpp_axi_clk>, + <&clock_mmss clk_mmss_camss_micro_ahb_clk>, + <&clock_mmss clk_mmss_bimc_smmu_axi_clk>, + <&clock_mmss clk_mmss_camss_cpp_vbif_ahb_clk>; + clock-names = "mmssnoc_axi_clk", + "mnoc_ahb_clk", + "camss_ahb_clk", "camss_top_ahb_clk", + "cpp_src_clk", + "cpp_core_clk", "camss_cpp_ahb_clk", + "camss_cpp_axi_clk", "micro_iface_clk", + "mmss_smmu_axi_clk", "cpp_vbif_ahb_clk"; + qcom,clock-rates = <0 0 0 0 200000000 200000000 0 0 0 0 0>; + qcom,min-clock-rate = <200000000>; + qcom,bus-master = <1>; + qcom,vbif-qos-setting = <0x20 0x10000000>, + <0x24 0x10000000>, + <0x28 0x10000000>, + <0x2C 0x10000000>; + status = "ok"; + qcom,msm-bus,name = "msm_camera_cpp"; + qcom,msm-bus,num-cases = <2>; + qcom,msm-bus,num-paths = <1>; + qcom,msm-bus,vectors-KBps = + <106 512 0 0>, + <106 512 0 0>; + qcom,msm-bus-vector-dyn-vote; + resets = <&clock_mmss CAMSS_MICRO_BCR>; + reset-names = "micro_iface_reset"; + qcom,src-clock-rates = <100000000 200000000 384000000 404000000 + 480000000 576000000 600000000>; + qcom,cpp-fw-payload-info { + qcom,stripe-base = <790>; + qcom,plane-base = <715>; + qcom,stripe-size = <63>; + qcom,plane-size = <25>; + qcom,fe-ptr-off = <11>; + qcom,we-ptr-off = <23>; + qcom,ref-fe-ptr-off = <17>; + qcom,ref-we-ptr-off = <36>; + qcom,we-meta-ptr-off = <42>; + qcom,fe-mmu-pf-ptr-off = <7>; + qcom,ref-fe-mmu-pf-ptr-off = <10>; + qcom,we-mmu-pf-ptr-off = <13>; + qcom,dup-we-mmu-pf-ptr-off = <18>; + qcom,ref-we-mmu-pf-ptr-off = <23>; + qcom,set-group-buffer-len = <135>; + qcom,dup-frame-indicator-off = <70>; + }; + }; }; diff --git a/drivers/leds/leds-qpnp-wled.c b/drivers/leds/leds-qpnp-wled.c index 894c1d88b3ef..97cfa813f4ce 100644 --- a/drivers/leds/leds-qpnp-wled.c +++ b/drivers/leds/leds-qpnp-wled.c @@ -61,11 +61,7 @@ #define QPNP_WLED_EN_MASK 0x7F #define QPNP_WLED_EN_SHIFT 7 #define QPNP_WLED_FDBK_OP_MASK 0xF8 -#define QPNP_WLED_VREF_MASK 0xF0 -#define QPNP_WLED_VREF_STEP_MV 25 -#define QPNP_WLED_VREF_MIN_MV 300 -#define QPNP_WLED_VREF_MAX_MV 675 -#define QPNP_WLED_DFLT_VREF_MV 350 +#define QPNP_WLED_VREF_MASK GENMASK(3, 0) #define QPNP_WLED_VLOOP_COMP_RES_MASK 0xF0 #define QPNP_WLED_VLOOP_COMP_RES_OVERWRITE 0x80 @@ -275,6 +271,20 @@ static int qpnp_wled_ilim_settings_pmicobalt[NUM_SUPPORTED_ILIM_THRESHOLDS] = { 105, 280, 450, 620, 970, 1150, 1300, 1500, }; +struct wled_vref_setting { + u32 min_uv; + u32 max_uv; + u32 step_uv; + u32 default_uv; +}; + +static struct wled_vref_setting vref_setting_pmi8994 = { + 300000, 675000, 25000, 350000, +}; +static struct wled_vref_setting vref_setting_pmicobalt = { + 60000, 397500, 22500, 127500, +}; + /** * qpnp_wled - wed data structure * @ cdev - led class device @@ -294,7 +304,7 @@ static int qpnp_wled_ilim_settings_pmicobalt[NUM_SUPPORTED_ILIM_THRESHOLDS] = { * @ mod_freq_khz - modulator frequency in KHZ * @ hyb_thres - threshold for hybrid dimming * @ sync_dly_us - sync delay in us - * @ vref_mv - ref voltage in mv + * @ vref_uv - ref voltage in uv * @ vref_psm_mv - ref psm voltage in mv * @ loop_comp_res_kohm - control to select the compensation resistor * @ loop_ea_gm - control to select the gm for the gm stage in control loop @@ -337,7 +347,7 @@ struct qpnp_wled { u16 mod_freq_khz; u16 hyb_thres; u16 sync_dly_us; - u16 vref_mv; + u32 vref_uv; u16 vref_psm_mv; u16 loop_comp_res_kohm; u16 loop_ea_gm; @@ -1248,6 +1258,35 @@ static int qpnp_wled_ilim_config(struct qpnp_wled *wled) return rc; } +static int qpnp_wled_vref_config(struct qpnp_wled *wled) +{ + + struct wled_vref_setting vref_setting; + int rc; + u8 reg = 0; + + if (wled->pmic_rev_id->pmic_subtype == PMICOBALT_SUBTYPE || + wled->pmic_rev_id->pmic_subtype == PM2FALCON_SUBTYPE) + vref_setting = vref_setting_pmicobalt; + else + vref_setting = vref_setting_pmi8994; + + if (wled->vref_uv < vref_setting.min_uv) + wled->vref_uv = vref_setting.min_uv; + else if (wled->vref_uv > vref_setting.max_uv) + wled->vref_uv = vref_setting.max_uv; + + reg |= DIV_ROUND_CLOSEST(wled->vref_uv - vref_setting.min_uv, + vref_setting.step_uv); + + rc = qpnp_wled_masked_write_reg(wled, QPNP_WLED_VREF_MASK, + ®, QPNP_WLED_VREF_REG(wled->ctrl_base)); + if (rc) + pr_err("Write VREF_REG failed, rc=%d\n", rc); + + return rc; +} + /* Configure WLED registers */ static int qpnp_wled_config(struct qpnp_wled *wled) { @@ -1272,22 +1311,11 @@ static int qpnp_wled_config(struct qpnp_wled *wled) return rc; /* Configure the VREF register */ - if (wled->vref_mv < QPNP_WLED_VREF_MIN_MV) - wled->vref_mv = QPNP_WLED_VREF_MIN_MV; - else if (wled->vref_mv > QPNP_WLED_VREF_MAX_MV) - wled->vref_mv = QPNP_WLED_VREF_MAX_MV; - - rc = qpnp_wled_read_reg(wled, ®, - QPNP_WLED_VREF_REG(wled->ctrl_base)); - if (rc < 0) - return rc; - reg &= QPNP_WLED_VREF_MASK; - temp = wled->vref_mv - QPNP_WLED_VREF_MIN_MV; - reg |= (temp / QPNP_WLED_VREF_STEP_MV); - rc = qpnp_wled_write_reg(wled, reg, - QPNP_WLED_VREF_REG(wled->ctrl_base)); - if (rc) + rc = qpnp_wled_vref_config(wled); + if (rc < 0) { + pr_err("Error in configuring wled vref, rc=%d\n", rc); return rc; + } /* Configure the ILIM register */ rc = qpnp_wled_ilim_config(wled); @@ -1714,11 +1742,15 @@ static int qpnp_wled_parse_dt(struct qpnp_wled *wled) return rc; } - wled->vref_mv = QPNP_WLED_DFLT_VREF_MV; + if (wled->pmic_rev_id->pmic_subtype == PMICOBALT_SUBTYPE || + wled->pmic_rev_id->pmic_subtype == PM2FALCON_SUBTYPE) + wled->vref_uv = vref_setting_pmicobalt.default_uv; + else + wled->vref_uv = vref_setting_pmi8994.default_uv; rc = of_property_read_u32(pdev->dev.of_node, - "qcom,vref-mv", &temp_val); + "qcom,vref-uv", &temp_val); if (!rc) { - wled->vref_mv = temp_val; + wled->vref_uv = temp_val; } else if (rc != -EINVAL) { dev_err(&pdev->dev, "Unable to read vref\n"); return rc; diff --git a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp_soc.c b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp_soc.c index 2c313016bc90..8213f736205a 100644 --- a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp_soc.c +++ b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp_soc.c @@ -66,39 +66,72 @@ int msm_cpp_get_clock_index(struct cpp_device *cpp_dev, const char *clk_name) return -EINVAL; } -static int cpp_get_clk_freq_tbl(struct clk *clk, struct cpp_hw_info *hw_info, - uint32_t min_clk_rate) +static int cpp_get_clk_freq_tbl_dt(struct cpp_device *cpp_dev) { - uint32_t i; + uint32_t i, count, min_clk_rate; uint32_t idx = 0; - signed long freq_tbl_entry = 0; + struct device_node *of_node; + uint32_t *rates; + int32_t rc = 0; + struct cpp_hw_info *hw_info; - if ((clk == NULL) || (hw_info == NULL) || (clk->ops == NULL) || - (clk->ops->list_rate == NULL)) { + if (cpp_dev == NULL) { pr_err("Bad parameter\n"); - return -EINVAL; + rc = -EINVAL; + goto err; } - for (i = 0; i < MAX_FREQ_TBL; i++) { - freq_tbl_entry = clk->ops->list_rate(clk, i); - pr_debug("entry=%ld\n", freq_tbl_entry); - if (freq_tbl_entry >= 0) { - if (freq_tbl_entry >= min_clk_rate) { - hw_info->freq_tbl[idx++] = freq_tbl_entry; - pr_debug("tbl[%d]=%ld\n", idx-1, - freq_tbl_entry); + of_node = cpp_dev->pdev->dev.of_node; + min_clk_rate = cpp_dev->min_clk_rate; + hw_info = &cpp_dev->hw_info; + + if ((hw_info == NULL) || (of_node == NULL)) { + pr_err("Invalid hw_info %p or ofnode %p\n", hw_info, of_node); + rc = -EINVAL; + goto err; + + } + count = of_property_count_u32_elems(of_node, "qcom,src-clock-rates"); + if ((count == 0) || (count > MAX_FREQ_TBL)) { + pr_err("Clock count is invalid\n"); + rc = -EINVAL; + goto err; + } + + rates = devm_kcalloc(&cpp_dev->pdev->dev, count, sizeof(uint32_t), + GFP_KERNEL); + if (!rates) { + rc = -ENOMEM; + goto err; + } + + rc = of_property_read_u32_array(of_node, "qcom,src-clock-rates", + rates, count); + if (rc) { + rc = -EINVAL; + goto mem_free; + } + + for (i = 0; i < count; i++) { + pr_debug("entry=%d\n", rates[i]); + if (rates[i] >= 0) { + if (rates[i] >= min_clk_rate) { + hw_info->freq_tbl[idx++] = rates[i]; + pr_debug("tbl[%d]=%d\n", idx-1, rates[i]); } } else { - pr_debug("freq table returned invalid entry/end %ld\n", - freq_tbl_entry); + pr_debug("rate is invalid entry/end %d\n", rates[i]); break; } } - pr_debug("%s: idx %d", __func__, idx); + pr_debug("%s: idx %d\n", __func__, idx); hw_info->freq_tbl_count = idx; - return 0; +mem_free: + devm_kfree(&cpp_dev->pdev->dev, rates); +err: + return rc; } int msm_cpp_set_micro_clk(struct cpp_device *cpp_dev) @@ -147,8 +180,7 @@ int msm_update_freq_tbl(struct cpp_device *cpp_dev) rc = msm_cpp_core_clk_idx; return rc; } - rc = cpp_get_clk_freq_tbl(cpp_dev->cpp_clk[msm_cpp_core_clk_idx], - &cpp_dev->hw_info, cpp_dev->min_clk_rate); + rc = cpp_get_clk_freq_tbl_dt(cpp_dev); if (rc < 0) { pr_err("%s: fail to get frequency table\n", __func__); return rc; diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c index 925b8497273a..4e86a3ff820d 100644 --- a/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c +++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c @@ -1502,7 +1502,8 @@ static void sde_hw_rotator_free_rotctx(struct sde_hw_rotator *rot, ctx->q_id, ctx->timestamp, atomic_read(&ctx->hwres->num_active)); - rot->rotCtx[ctx->q_id][sde_hw_rotator_get_regdma_ctxidx(ctx)] = NULL; + /* Clear rotator context from lookup purpose */ + sde_hw_rotator_clr_ctx(ctx); devm_kfree(&rot->pdev->dev, ctx); } diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_r3_internal.h b/drivers/media/platform/msm/sde/rotator/sde_rotator_r3_internal.h index 91ac3d0371fa..7aecc3cee210 100644 --- a/drivers/media/platform/msm/sde/rotator/sde_rotator_r3_internal.h +++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_r3_internal.h @@ -345,10 +345,32 @@ static inline void sde_hw_rotator_put_ctx(struct sde_hw_rotator_context *ctx) { struct sde_hw_rotator *rot = ctx->rot; u32 idx = sde_hw_rotator_get_regdma_ctxidx(ctx); + unsigned long flags; + spin_lock_irqsave(&rot->rotisr_lock, flags); rot->rotCtx[ctx->q_id][idx] = ctx; + spin_unlock_irqrestore(&rot->rotisr_lock, flags); + SDEROT_DBG("rotCtx[%d][%d] <== ctx:%p | session-id:%d\n", ctx->q_id, idx, ctx, ctx->session_id); } +/** + * sde_hw_rotator_clr_ctx(): Clearing rotator context according to its + * timestamp. + */ +static inline void sde_hw_rotator_clr_ctx(struct sde_hw_rotator_context *ctx) +{ + struct sde_hw_rotator *rot = ctx->rot; + u32 idx = sde_hw_rotator_get_regdma_ctxidx(ctx); + unsigned long flags; + + spin_lock_irqsave(&rot->rotisr_lock, flags); + rot->rotCtx[ctx->q_id][idx] = NULL; + spin_unlock_irqrestore(&rot->rotisr_lock, flags); + + SDEROT_DBG("rotCtx[%d][%d] <== null | session-id:%d\n", + ctx->q_id, idx, ctx->session_id); +} + #endif /*_SDE_ROTATOR_R3_INTERNAL_H */ diff --git a/drivers/soc/qcom/icnss.c b/drivers/soc/qcom/icnss.c index feeed645fc47..6215636b0f46 100644 --- a/drivers/soc/qcom/icnss.c +++ b/drivers/soc/qcom/icnss.c @@ -45,6 +45,7 @@ #include <soc/qcom/service-locator.h> #include <soc/qcom/service-notifier.h> #include <soc/qcom/socinfo.h> +#include <soc/qcom/ramdump.h> #include "wlan_firmware_service_v01.h" @@ -439,6 +440,7 @@ static struct icnss_priv { struct wlfw_rf_board_info_s_v01 board_info; struct wlfw_soc_info_s_v01 soc_info; struct wlfw_fw_version_info_s_v01 fw_version_info; + char fw_build_id[QMI_WLFW_MAX_BUILD_ID_LEN_V01 + 1]; u32 pwr_pin_result; u32 phy_io_pin_result; u32 rf_pin_result; @@ -463,6 +465,7 @@ static struct icnss_priv { struct qpnp_vadc_chip *vadc_dev; uint64_t vph_pwr; atomic_t pm_count; + struct ramdump_device *msa0_dump_dev; } *penv; static void icnss_hw_write_reg(void *base, u32 offset, u32 val) @@ -1971,12 +1974,16 @@ static int wlfw_cap_send_sync_msg(void) penv->soc_info = resp.soc_info; if (resp.fw_version_info_valid) penv->fw_version_info = resp.fw_version_info; + if (resp.fw_build_id_valid) + strlcpy(penv->fw_build_id, resp.fw_build_id, + QMI_WLFW_MAX_BUILD_ID_LEN_V01 + 1); - icnss_pr_dbg("Capability, chip_id: 0x%x, chip_family: 0x%x, board_id: 0x%x, soc_id: 0x%x, fw_version: 0x%x, fw_build_timestamp: %s", + icnss_pr_dbg("Capability, chip_id: 0x%x, chip_family: 0x%x, board_id: 0x%x, soc_id: 0x%x, fw_version: 0x%x, fw_build_timestamp: %s, fw_build_id: %s", penv->chip_info.chip_id, penv->chip_info.chip_family, penv->board_info.board_id, penv->soc_info.soc_id, penv->fw_version_info.fw_version, - penv->fw_version_info.fw_build_timestamp); + penv->fw_version_info.fw_build_timestamp, + penv->fw_build_id); return 0; @@ -2657,8 +2664,6 @@ static int icnss_driver_event_pd_service_down(struct icnss_priv *priv, out: ret = icnss_hw_power_off(priv); - icnss_remove_msa_permissions(priv); - kfree(data); return ret; @@ -2763,6 +2768,16 @@ static int icnss_qmi_wlfw_clnt_svc_event_notify(struct notifier_block *this, return ret; } +static int icnss_msa0_ramdump(struct icnss_priv *priv) +{ + struct ramdump_segment segment; + + memset(&segment, 0, sizeof(segment)); + segment.v_address = priv->msa_va; + segment.size = priv->msa_mem_size; + return do_ramdump(priv->msa0_dump_dev, &segment, 1); +} + static struct notifier_block wlfw_clnt_nb = { .notifier_call = icnss_qmi_wlfw_clnt_svc_event_notify, }; @@ -2778,9 +2793,19 @@ static int icnss_modem_notifier_nb(struct notifier_block *nb, icnss_pr_dbg("Modem-Notify: event %lu\n", code); + if (code == SUBSYS_AFTER_SHUTDOWN) { + icnss_remove_msa_permissions(priv); + icnss_pr_info("Collecting msa0 segment dump\n"); + icnss_msa0_ramdump(priv); + return NOTIFY_OK; + } + if (code != SUBSYS_BEFORE_SHUTDOWN) return NOTIFY_OK; + if (test_bit(ICNSS_PDR_ENABLED, &priv->state)) + return NOTIFY_OK; + icnss_pr_info("Modem went down, state: %lx\n", priv->state); event_data = kzalloc(sizeof(*data), GFP_KERNEL); @@ -2936,8 +2961,6 @@ static int icnss_get_service_location_notify(struct notifier_block *nb, set_bit(ICNSS_PDR_ENABLED, &priv->state); - icnss_modem_ssr_unregister_notifier(priv); - icnss_pr_dbg("PD restart enabled, state: 0x%lx\n", priv->state); return NOTIFY_OK; @@ -3000,6 +3023,11 @@ static int icnss_enable_recovery(struct icnss_priv *priv) goto enable_pdr; } + priv->msa0_dump_dev = create_ramdump_device("wcss_msa0", + &priv->pdev->dev); + if (!priv->msa0_dump_dev) + return -ENOMEM; + icnss_modem_ssr_register_notifier(priv); if (test_bit(SSR_ONLY, &quirks)) { icnss_pr_dbg("PDR disabled through module parameter\n"); @@ -3929,6 +3957,8 @@ static int icnss_stats_show_capability(struct seq_file *s, priv->fw_version_info.fw_version); seq_printf(s, "Firmware Build Timestamp: %s\n", priv->fw_version_info.fw_build_timestamp); + seq_printf(s, "Firmware Build ID: %s\n", + priv->fw_build_id); } return 0; @@ -4511,6 +4541,8 @@ static int icnss_remove(struct platform_device *pdev) icnss_modem_ssr_unregister_notifier(penv); + destroy_ramdump_device(penv->msa0_dump_dev); + icnss_pdr_unregister_notifier(penv); qmi_svc_event_notifier_unregister(WLFW_SERVICE_ID_V01, @@ -4522,6 +4554,8 @@ static int icnss_remove(struct platform_device *pdev) icnss_hw_power_off(penv); + icnss_remove_msa_permissions(penv); + dev_set_drvdata(&pdev->dev, NULL); return 0; diff --git a/drivers/soc/qcom/wlan_firmware_service_v01.c b/drivers/soc/qcom/wlan_firmware_service_v01.c index f5f7ae8c9901..3e00d6c9d153 100644 --- a/drivers/soc/qcom/wlan_firmware_service_v01.c +++ b/drivers/soc/qcom/wlan_firmware_service_v01.c @@ -766,6 +766,24 @@ struct elem_info wlfw_cap_resp_msg_v01_ei[] = { .ei_array = wlfw_fw_version_info_s_v01_ei, }, { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(uint8_t), + .is_array = NO_ARRAY, + .tlv_type = 0x14, + .offset = offsetof(struct wlfw_cap_resp_msg_v01, + fw_build_id_valid), + }, + { + .data_type = QMI_STRING, + .elem_len = QMI_WLFW_MAX_BUILD_ID_LEN_V01 + 1, + .elem_size = sizeof(char), + .is_array = NO_ARRAY, + .tlv_type = 0x14, + .offset = offsetof(struct wlfw_cap_resp_msg_v01, + fw_build_id), + }, + { .data_type = QMI_EOTI, .is_array = NO_ARRAY, .is_array = QMI_COMMON_TLV_TYPE, @@ -1588,3 +1606,47 @@ struct elem_info wlfw_vbatt_resp_msg_v01_ei[] = { .is_array = QMI_COMMON_TLV_TYPE, }, }; + +struct elem_info wlfw_mac_addr_req_msg_v01_ei[] = { + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(uint8_t), + .is_array = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct wlfw_mac_addr_req_msg_v01, + mac_addr_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = QMI_WLFW_MAC_ADDR_SIZE_V01, + .elem_size = sizeof(uint8_t), + .is_array = STATIC_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct wlfw_mac_addr_req_msg_v01, + mac_addr), + }, + { + .data_type = QMI_EOTI, + .is_array = NO_ARRAY, + .is_array = QMI_COMMON_TLV_TYPE, + }, +}; + +struct elem_info wlfw_mac_addr_resp_msg_v01_ei[] = { + { + .data_type = QMI_STRUCT, + .elem_len = 1, + .elem_size = sizeof(struct qmi_response_type_v01), + .is_array = NO_ARRAY, + .tlv_type = 0x02, + .offset = offsetof(struct wlfw_mac_addr_resp_msg_v01, + resp), + .ei_array = get_qmi_response_type_v01_ei(), + }, + { + .data_type = QMI_EOTI, + .is_array = NO_ARRAY, + .is_array = QMI_COMMON_TLV_TYPE, + }, +}; diff --git a/drivers/soc/qcom/wlan_firmware_service_v01.h b/drivers/soc/qcom/wlan_firmware_service_v01.h index 29bdfb23480a..47b315fce94c 100644 --- a/drivers/soc/qcom/wlan_firmware_service_v01.h +++ b/drivers/soc/qcom/wlan_firmware_service_v01.h @@ -24,6 +24,7 @@ #define QMI_WLFW_CAL_DOWNLOAD_RESP_V01 0x0027 #define QMI_WLFW_INI_RESP_V01 0x002F #define QMI_WLFW_CAL_REPORT_RESP_V01 0x0026 +#define QMI_WLFW_MAC_ADDR_RESP_V01 0x0033 #define QMI_WLFW_INITIATE_CAL_DOWNLOAD_IND_V01 0x0028 #define QMI_WLFW_MSA_READY_IND_V01 0x002B #define QMI_WLFW_ATHDIAG_WRITE_RESP_V01 0x0031 @@ -43,6 +44,7 @@ #define QMI_WLFW_CAP_RESP_V01 0x0024 #define QMI_WLFW_ATHDIAG_READ_RESP_V01 0x0030 #define QMI_WLFW_VBATT_REQ_V01 0x0032 +#define QMI_WLFW_MAC_ADDR_REQ_V01 0x0033 #define QMI_WLFW_VBATT_RESP_V01 0x0032 #define QMI_WLFW_MSA_INFO_REQ_V01 0x002D #define QMI_WLFW_CAL_DOWNLOAD_REQ_V01 0x0027 @@ -57,6 +59,8 @@ #define QMI_WLFW_MAX_TIMESTAMP_LEN_V01 32 #define QMI_WLFW_MAX_STR_LEN_V01 16 #define QMI_WLFW_MAX_NUM_SHADOW_REG_V01 24 +#define QMI_WLFW_MAC_ADDR_SIZE_V01 6 +#define QMI_WLFW_MAX_BUILD_ID_LEN_V01 128 #define QMI_WLFW_MAX_NUM_SVC_V01 24 enum wlfw_driver_mode_enum_v01 { @@ -99,6 +103,7 @@ enum wlfw_pipedir_enum_v01 { #define QMI_WLFW_ALREADY_REGISTERED_V01 ((uint64_t)0x01ULL) #define QMI_WLFW_FW_READY_V01 ((uint64_t)0x02ULL) +#define QMI_WLFW_MSA_READY_V01 ((uint64_t)0x04ULL) struct wlfw_ce_tgt_pipe_cfg_s_v01 { uint32_t pipe_num; @@ -243,8 +248,10 @@ struct wlfw_cap_resp_msg_v01 { struct wlfw_soc_info_s_v01 soc_info; uint8_t fw_version_info_valid; struct wlfw_fw_version_info_s_v01 fw_version_info; + uint8_t fw_build_id_valid; + char fw_build_id[QMI_WLFW_MAX_BUILD_ID_LEN_V01 + 1]; }; -#define WLFW_CAP_RESP_MSG_V01_MAX_MSG_LEN 72 +#define WLFW_CAP_RESP_MSG_V01_MAX_MSG_LEN 203 extern struct elem_info wlfw_cap_resp_msg_v01_ei[]; struct wlfw_bdf_download_req_msg_v01 { @@ -428,4 +435,17 @@ struct wlfw_vbatt_resp_msg_v01 { #define WLFW_VBATT_RESP_MSG_V01_MAX_MSG_LEN 7 extern struct elem_info wlfw_vbatt_resp_msg_v01_ei[]; +struct wlfw_mac_addr_req_msg_v01 { + uint8_t mac_addr_valid; + uint8_t mac_addr[QMI_WLFW_MAC_ADDR_SIZE_V01]; +}; +#define WLFW_MAC_ADDR_REQ_MSG_V01_MAX_MSG_LEN 9 +extern struct elem_info wlfw_mac_addr_req_msg_v01_ei[]; + +struct wlfw_mac_addr_resp_msg_v01 { + struct qmi_response_type_v01 resp; +}; +#define WLFW_MAC_ADDR_RESP_MSG_V01_MAX_MSG_LEN 7 +extern struct elem_info wlfw_mac_addr_resp_msg_v01_ei[]; + #endif |
