Qualcomm driver updates for v7.1

Add ECS LIVA QC710, Glymur CRD, Mahua CRD, Purwa IoT EVK, and Asus
 Vivobook to the QSEECOM allow-list, to enable UEFI variable access
 through uefisecapp.
 
 Register the Gunyah watchdog device if the SCM driver finds itself
 running under Gunyah. Clean up some locking using guards.
 
 Handle possible cases where AOSS cooling state is given a non-boolean
 state.
 
 Replace LLCC per-slice activation bitmap with reference counting. Also
 add SDM670 support.
 
 Improve probe deferral handling in the OCMEM driver.
 
 Add Milos, QCS615, Eliza, Glymur, and Mahua support to the pd-mapper.
 
 Add support for SoCCP-based pmic-glink, as found in Glymur and
 Kaanapali.
 
 Add common QMI service ids to the main qmi headerfile, to avoid
 spreading these constants in various drivers.
 
 Add support for version 2 of SMP2P and implement the irqchip state
 reading support.
 
 Add CQ7790, SA8650P, SM7450, SM7450P, and IPQ5210 SoC and the PM7550BA
 PMIC identifiers to the socinfo driver.
 
 Add Eliza and Mahua support to the UBWC driver, introduce helpers for
 drivers to read out min_acc length and other programmable values, and
 disable bank swizzling for Glymur.
 
 Simplify the logic related to allocation of NV download request in the
 WCNSS control driver.
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEBd4DzF816k8JZtUlCx85Pw2ZrcUFAmnMQNQACgkQCx85Pw2Z
 rcWpmA//QDo8m9t4GgAdqJLSyH40Hcw0Uotv4DhzquUe1hYXTQb4NwNoJ+JZVPvO
 70BDuJTOQcnQCKeagW1Zq5ycJtA11khRL9ZWwzJB3fq3UTHI+n0EfHDmshAxz37Y
 h8x71dWKcI3NnEHWBFglRyYbv/eKFxcc2CFP0HrAB3UOxPClqsOVB5iNNM/JA3Jp
 eppYK6473VAF89q+q7+F3kEhz2p4sgyI9G2Sm/vFqXV3CLY0WV98FjQAHi1nXuNV
 pCz4oPkccBAcu7FQffMIydbtoIBPZDoI7pueJ4GlgewkkunuiJew/Rq0GEKnyzsN
 SqzfnBnbfsbQPOtZTBNY6tDgnSMQV2fMtgyBqkmgnSCs6A1AU6XVPFq4wWDpr6t/
 +y9QpA/Jfb1txeHp7xY/9bOAl2/vorZDLp9O8CR828z6Ptg/CGO8Gws/X0g4QWvZ
 6+UjRHTB5BnJENjzJGoxhrO59gyASUExoM02b6pQmz4ayw9q1PHGMVdSAPCygrDH
 r9+yMcTO8kfUAYtliJrygDTDlhwxMDfd2z82BOZGpSbAbR8zfFKKJmIaSQGNHCjl
 u3G9Kb5L7QlAVBGVcRYaArp1MQWD6oP+IU1W9YMra5cySwt/nXtSsQZRdhoP5Qp6
 YO8YMdldkf37DNar/+wrN012yaYSWj/k9x/f0phAn106oq1o8+0=
 =1zur
 -----END PGP SIGNATURE-----
gpgsig -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEo6/YBQwIrVS28WGKmmx57+YAGNkFAmnO3XkACgkQmmx57+YA
 GNlXDRAAkXYODhxU+T1AyT5OgDBzKgfVBte2vne+NOuirAX6+4U6v+0lCVx+fs4z
 kTfeveRoXtWlSSF3Vyv+rw1fZvpUOwZ9Y+u405fgveAxtDUkjzJGsnlrfMGIWD4a
 Q99WFz9L+kTcaf03uNLhrg9UAx0SpkfQQm2riY+ueHVY/0dOTsNzjv71A9sJrmvq
 oSEH3xquCOgd8diR3evE+2KhD4yQkzMmVeBuujDhWwIJmY8aSpZFIJIXYL5sRo+V
 l1bd5EwPH2Ku0bXaKh5mLDS/MvdKk7EPKru7ST0+IVfBXBnZf6KefAqljCvVuR66
 RRNDN2kcWU+aoih2vuVI+y3w1XGMX9AbFlviaGZWCY1mL2FTFvWfrQ4vLTz2bRlB
 8gFPmxMtVZQxu5hBOxAprnYrValRddYamh8cPQcpu9BGIG/ZIqx8cSOXZsQTiARk
 9DPRBQsQmaGXXl1YxbcYibQn1TL3ozmqQn0dhZ2Ojkxv0cyD3ymvdv68QKXPf7dm
 j2LU6BgNiK5IGZ2VUk5mk3hp5Kc+6qpmMqg7l/HIf1zUULCCFWu6l/IobuaX7ynj
 b5EU0feXMCJ9B17G1lgdFsZ0oI3RhkROjCi2huklNh1fA/xThwTsZsZQ9NmEKQHw
 TDCcavPXh64fSVtv4qePd9HV+KcHeBeA18m+6njdqByT36qMeC0=
 =nCjL
 -----END PGP SIGNATURE-----

Merge tag 'qcom-drivers-for-7.1' of https://git.kernel.org/pub/scm/linux/kernel/git/qcom/linux into soc/drivers

Qualcomm driver updates for v7.1

Add ECS LIVA QC710, Glymur CRD, Mahua CRD, Purwa IoT EVK, and Asus
Vivobook to the QSEECOM allow-list, to enable UEFI variable access
through uefisecapp.

Register the Gunyah watchdog device if the SCM driver finds itself
running under Gunyah. Clean up some locking using guards.

Handle possible cases where AOSS cooling state is given a non-boolean
state.

Replace LLCC per-slice activation bitmap with reference counting. Also
add SDM670 support.

Improve probe deferral handling in the OCMEM driver.

Add Milos, QCS615, Eliza, Glymur, and Mahua support to the pd-mapper.

Add support for SoCCP-based pmic-glink, as found in Glymur and
Kaanapali.

Add common QMI service ids to the main qmi headerfile, to avoid
spreading these constants in various drivers.

Add support for version 2 of SMP2P and implement the irqchip state
reading support.

Add CQ7790, SA8650P, SM7450, SM7450P, and IPQ5210 SoC and the PM7550BA
PMIC identifiers to the socinfo driver.

Add Eliza and Mahua support to the UBWC driver, introduce helpers for
drivers to read out min_acc length and other programmable values, and
disable bank swizzling for Glymur.

Simplify the logic related to allocation of NV download request in the
WCNSS control driver.

* tag 'qcom-drivers-for-7.1' of https://git.kernel.org/pub/scm/linux/kernel/git/qcom/linux: (51 commits)
  soc: qcom: ubwc: add helpers to get programmable values
  soc: qcom: ubwc: add helper to get min_acc length
  firmware: qcom: scm: Register gunyah watchdog device
  soc: qcom: socinfo: Add SoC ID for SA8650P
  dt-bindings: arm: qcom,ids: Add SoC ID for SA8650P
  firmware: qcom: scm: Allow QSEECOM on Mahua CRD
  soc: qcom: wcnss: simplify allocation of req
  soc: qcom: pd-mapper: Add support for Eliza
  soc: qcom: aoss: compare against normalized cooling state
  soc: qcom: llcc: fix v1 SB syndrome register offset
  dt-bindings: firmware: qcom,scm: Document ipq9650 SCM
  soc: qcom: ubwc: Add support for Mahua
  soc: qcom: pd-mapper: Add support for Glymur and Mahua
  soc: qcom: ubwc: Add configuration Eliza SoC
  soc: qcom: ubwc: Remove redundant x1e80100_data
  dt-bindings: firmware: qcom,scm: document Eliza SCM Firmware Interface
  soc: qcom: ocmem: return -EPROBE_DEFER is ocmem is not available
  soc: qcom: ocmem: register reasons for probe deferrals
  soc: qcom: ocmem: make the core clock optional
  soc: qcom: ubwc: disable bank swizzling for Glymur platform
  ...

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
This commit is contained in:
Arnd Bergmann 2026-04-02 23:19:51 +02:00
commit a66cc657ef
21 changed files with 480 additions and 139 deletions

View File

@ -33,6 +33,7 @@ properties:
- qcom,sc7280-llcc
- qcom,sc8180x-llcc
- qcom,sc8280xp-llcc
- qcom,sdm670-llcc
- qcom,sdm845-llcc
- qcom,sm6350-llcc
- qcom,sm7150-llcc
@ -204,6 +205,7 @@ allOf:
contains:
enum:
- qcom,sc7280-llcc
- qcom,sdm670-llcc
then:
properties:
reg:

View File

@ -23,15 +23,18 @@ properties:
- enum:
- qcom,scm-apq8064
- qcom,scm-apq8084
- qcom,scm-eliza
- qcom,scm-glymur
- qcom,scm-ipq4019
- qcom,scm-ipq5018
- qcom,scm-ipq5210
- qcom,scm-ipq5332
- qcom,scm-ipq5424
- qcom,scm-ipq6018
- qcom,scm-ipq806x
- qcom,scm-ipq8074
- qcom,scm-ipq9574
- qcom,scm-ipq9650
- qcom,scm-kaanapali
- qcom,scm-mdm9607
- qcom,scm-milos
@ -204,6 +207,7 @@ allOf:
compatible:
contains:
enum:
- qcom,scm-eliza
- qcom,scm-kaanapali
- qcom,scm-milos
- qcom,scm-sm8450

View File

@ -23,6 +23,8 @@ properties:
oneOf:
- items:
- enum:
- qcom,glymur-pmic-glink
- qcom,kaanapali-pmic-glink
- qcom,qcm6490-pmic-glink
- qcom,sc8180x-pmic-glink
- qcom,sc8280xp-pmic-glink

View File

@ -699,20 +699,18 @@ static DEFINE_MUTEX(__qcuefi_lock);
static int qcuefi_set_reference(struct qcuefi_client *qcuefi)
{
mutex_lock(&__qcuefi_lock);
guard(mutex)(&__qcuefi_lock);
if (qcuefi && __qcuefi) {
mutex_unlock(&__qcuefi_lock);
if (qcuefi && __qcuefi)
return -EEXIST;
}
__qcuefi = qcuefi;
mutex_unlock(&__qcuefi_lock);
return 0;
}
static struct qcuefi_client *qcuefi_acquire(void)
__acquires(__qcuefi_lock)
{
mutex_lock(&__qcuefi_lock);
if (!__qcuefi) {
@ -723,6 +721,7 @@ static struct qcuefi_client *qcuefi_acquire(void)
}
static void qcuefi_release(void)
__releases(__qcuefi_lock)
{
mutex_unlock(&__qcuefi_lock);
}

View File

@ -199,19 +199,18 @@ static int qcom_scm_bw_enable(void)
if (!__scm->path)
return 0;
mutex_lock(&__scm->scm_bw_lock);
guard(mutex)(&__scm->scm_bw_lock);
if (!__scm->scm_vote_count) {
ret = icc_set_bw(__scm->path, 0, UINT_MAX);
if (ret < 0) {
dev_err(__scm->dev, "failed to set bandwidth request\n");
goto err_bw;
return ret;
}
}
__scm->scm_vote_count++;
err_bw:
mutex_unlock(&__scm->scm_bw_lock);
return ret;
return 0;
}
static void qcom_scm_bw_disable(void)
@ -923,14 +922,13 @@ struct resource_table *qcom_scm_pas_get_rsc_table(struct qcom_scm_pas_context *c
goto free_input_rt;
}
tbl_ptr = kzalloc(size, GFP_KERNEL);
tbl_ptr = kmemdup(output_rt_tzm, size, GFP_KERNEL);
if (!tbl_ptr) {
qcom_tzmem_free(output_rt_tzm);
ret = -ENOMEM;
goto free_input_rt;
}
memcpy(tbl_ptr, output_rt_tzm, size);
*output_rt_size = size;
qcom_tzmem_free(output_rt_tzm);
@ -2290,11 +2288,13 @@ EXPORT_SYMBOL_GPL(qcom_scm_qseecom_app_send);
*/
static const struct of_device_id qcom_scm_qseecom_allowlist[] __maybe_unused = {
{ .compatible = "asus,vivobook-s15" },
{ .compatible = "asus,vivobook-s15-x1p4" },
{ .compatible = "asus,zenbook-a14-ux3407qa" },
{ .compatible = "asus,zenbook-a14-ux3407ra" },
{ .compatible = "dell,inspiron-14-plus-7441" },
{ .compatible = "dell,latitude-7455" },
{ .compatible = "dell,xps13-9345" },
{ .compatible = "ecs,liva-qc710" },
{ .compatible = "hp,elitebook-ultra-g1q" },
{ .compatible = "hp,omnibook-x14" },
{ .compatible = "huawei,gaokun3" },
@ -2309,7 +2309,10 @@ static const struct of_device_id qcom_scm_qseecom_allowlist[] __maybe_unused = {
{ .compatible = "microsoft,denali", },
{ .compatible = "microsoft,romulus13", },
{ .compatible = "microsoft,romulus15", },
{ .compatible = "qcom,glymur-crd" },
{ .compatible = "qcom,hamoa-iot-evk" },
{ .compatible = "qcom,mahua-crd" },
{ .compatible = "qcom,purwa-iot-evk" },
{ .compatible = "qcom,sc8180x-primus" },
{ .compatible = "qcom,x1e001de-devkit" },
{ .compatible = "qcom,x1e80100-crd" },
@ -2467,6 +2470,56 @@ int qcom_scm_qtee_callback_response(phys_addr_t buf, size_t buf_size,
}
EXPORT_SYMBOL(qcom_scm_qtee_callback_response);
static void qcom_scm_gunyah_wdt_free(void *data)
{
struct platform_device *gunyah_wdt_dev = data;
platform_device_unregister(gunyah_wdt_dev);
}
static void qcom_scm_gunyah_wdt_init(struct qcom_scm *scm)
{
struct platform_device *gunyah_wdt_dev;
struct device_node *np;
bool of_wdt_available;
int i;
static const uuid_t gunyah_uuid = UUID_INIT(0xc1d58fcd, 0xa453, 0x5fdb,
0x92, 0x65, 0xce, 0x36,
0x67, 0x3d, 0x5f, 0x14);
static const char * const of_wdt_compatible[] = {
"qcom,kpss-wdt",
"arm,sbsa-gwdt",
};
/* Bail out if we are not running under Gunyah */
if (!IS_ENABLED(CONFIG_HAVE_ARM_SMCCC_DISCOVERY) ||
!arm_smccc_hypervisor_has_uuid(&gunyah_uuid))
return;
/*
* Gunyah emulates either of Qualcomm watchdog or ARM SBSA watchdog on
* newer platforms. Bail out if we find them in the devicetree.
*/
for (i = 0; i < ARRAY_SIZE(of_wdt_compatible); i++) {
np = of_find_compatible_node(NULL, NULL, of_wdt_compatible[i]);
of_wdt_available = of_device_is_available(np);
of_node_put(np);
if (of_wdt_available)
return;
}
gunyah_wdt_dev = platform_device_register_simple("gunyah-wdt", -1,
NULL, 0);
if (IS_ERR(gunyah_wdt_dev)) {
dev_err(scm->dev, "Failed to register Gunyah watchdog device: %ld\n",
PTR_ERR(gunyah_wdt_dev));
return;
}
devm_add_action_or_reset(scm->dev, qcom_scm_gunyah_wdt_free,
gunyah_wdt_dev);
}
static void qcom_scm_qtee_free(void *data)
{
struct platform_device *qtee_dev = data;
@ -2811,6 +2864,9 @@ static int qcom_scm_probe(struct platform_device *pdev)
/* Initialize the QTEE object interface. */
qcom_scm_qtee_init(scm);
/* Initialize the Gunyah watchdog platform device. */
qcom_scm_gunyah_wdt_init(scm);
return 0;
}

View File

@ -5,7 +5,6 @@
*/
#include <linux/bitfield.h>
#include <linux/bitmap.h>
#include <linux/bitops.h>
#include <linux/cleanup.h>
#include <linux/device.h>
@ -1782,6 +1781,94 @@ static const struct llcc_slice_config sc8280xp_data[] = {
},
};
static const struct llcc_slice_config sdm670_data[] = {
{
.usecase_id = LLCC_CPUSS,
.slice_id = 1,
.max_cap = 512,
.priority = 1,
.bonus_ways = 0xf,
.res_ways = 0x0,
.cache_mode = 0,
.dis_cap_alloc = true,
.retain_on_pc = true,
.activate_on_init = true,
}, {
.usecase_id = LLCC_ROTATOR,
.slice_id = 4,
.max_cap = 384,
.priority = 2,
.fixed_size = true,
.bonus_ways = 0x0,
.res_ways = 0xe,
.cache_mode = 2,
.dis_cap_alloc = true,
.retain_on_pc = true,
}, {
.usecase_id = LLCC_VOICE,
.slice_id = 5,
.max_cap = 512,
.priority = 1,
.bonus_ways = 0xf,
.res_ways = 0x0,
.cache_mode = 0,
.dis_cap_alloc = true,
.retain_on_pc = true,
}, {
.usecase_id = LLCC_AUDIO,
.slice_id = 6,
.max_cap = 512,
.priority = 1,
.bonus_ways = 0xf,
.res_ways = 0x0,
.cache_mode = 0,
.dis_cap_alloc = true,
.retain_on_pc = true,
}, {
.usecase_id = LLCC_MDM,
.slice_id = 8,
.max_cap = 512,
.priority = 1,
.bonus_ways = 0xf,
.res_ways = 0x0,
.cache_mode = 0,
.dis_cap_alloc = true,
.retain_on_pc = true,
}, {
.usecase_id = LLCC_GPU,
.slice_id = 12,
.max_cap = 384,
.priority = 1,
.fixed_size = true,
.bonus_ways = 0x0,
.res_ways = 0x0,
.cache_mode = 0,
.dis_cap_alloc = true,
.retain_on_pc = true,
}, {
.usecase_id = LLCC_MMUHWT,
.slice_id = 13,
.max_cap = 512,
.priority = 1,
.bonus_ways = 0xf,
.res_ways = 0x0,
.cache_mode = 0,
.dis_cap_alloc = true,
.activate_on_init = true,
}, {
.usecase_id = LLCC_AUDHW,
.slice_id = 22,
.max_cap = 512,
.priority = 1,
.fixed_size = true,
.bonus_ways = 0xf,
.res_ways = 0x0,
.cache_mode = 0,
.dis_cap_alloc = true,
.retain_on_pc = true,
},
};
static const struct llcc_slice_config sdm845_data[] = {{
.usecase_id = LLCC_CPUSS,
.slice_id = 1,
@ -3943,7 +4030,7 @@ static const struct llcc_slice_config x1e80100_data[] = {
static const struct llcc_edac_reg_offset llcc_v1_edac_reg_offset = {
.trp_ecc_error_status0 = 0x20344,
.trp_ecc_error_status1 = 0x20348,
.trp_ecc_sb_err_syn0 = 0x2304c,
.trp_ecc_sb_err_syn0 = 0x2034c,
.trp_ecc_db_err_syn0 = 0x20370,
.trp_ecc_error_cntr_clear = 0x20440,
.trp_interrupt_0_status = 0x20480,
@ -4196,6 +4283,17 @@ static const struct qcom_llcc_config sc8280xp_cfg[] = {
},
};
static const struct qcom_llcc_config sdm670_cfg[] = {
{
.sct_data = sdm670_data,
.size = ARRAY_SIZE(sdm670_data),
.skip_llcc_cfg = true,
.reg_offset = llcc_v1_reg_offset,
.edac_reg_offset = &llcc_v1_edac_reg_offset,
.no_edac = true,
},
};
static const struct qcom_llcc_config sdm845_cfg[] = {
{
.sct_data = sdm845_data,
@ -4364,6 +4462,11 @@ static const struct qcom_sct_config sc8280xp_cfgs = {
.num_config = ARRAY_SIZE(sc8280xp_cfg),
};
static const struct qcom_sct_config sdm670_cfgs = {
.llcc_config = sdm670_cfg,
.num_config = ARRAY_SIZE(sdm670_cfg),
};
static const struct qcom_sct_config sdm845_cfgs = {
.llcc_config = sdm845_cfg,
.num_config = ARRAY_SIZE(sdm845_cfg),
@ -4431,8 +4534,7 @@ static struct llcc_drv_data *drv_data = (void *) -EPROBE_DEFER;
struct llcc_slice_desc *llcc_slice_getd(u32 uid)
{
const struct llcc_slice_config *cfg;
struct llcc_slice_desc *desc;
u32 sz, count;
u32 sz, i;
if (IS_ERR(drv_data))
return ERR_CAST(drv_data);
@ -4440,21 +4542,14 @@ struct llcc_slice_desc *llcc_slice_getd(u32 uid)
cfg = drv_data->cfg;
sz = drv_data->cfg_size;
for (count = 0; cfg && count < sz; count++, cfg++)
for (i = 0; cfg && i < sz; i++, cfg++)
if (cfg->usecase_id == uid)
break;
if (count == sz || !cfg)
if (i == sz)
return ERR_PTR(-ENODEV);
desc = kzalloc_obj(*desc);
if (!desc)
return ERR_PTR(-ENOMEM);
desc->slice_id = cfg->slice_id;
desc->slice_size = cfg->max_cap;
return desc;
return &drv_data->desc[i];
}
EXPORT_SYMBOL_GPL(llcc_slice_getd);
@ -4465,7 +4560,7 @@ EXPORT_SYMBOL_GPL(llcc_slice_getd);
void llcc_slice_putd(struct llcc_slice_desc *desc)
{
if (!IS_ERR_OR_NULL(desc))
kfree(desc);
return;
}
EXPORT_SYMBOL_GPL(llcc_slice_putd);
@ -4540,25 +4635,21 @@ int llcc_slice_activate(struct llcc_slice_desc *desc)
if (IS_ERR_OR_NULL(desc))
return -EINVAL;
mutex_lock(&drv_data->lock);
if (test_bit(desc->slice_id, drv_data->bitmap)) {
mutex_unlock(&drv_data->lock);
guard(mutex)(&drv_data->lock);
/* Already active; try to take another reference. */
if (refcount_inc_not_zero(&desc->refcount))
return 0;
}
act_ctrl_val = ACT_CTRL_OPCODE_ACTIVATE << ACT_CTRL_OPCODE_SHIFT;
ret = llcc_update_act_ctrl(desc->slice_id, act_ctrl_val,
DEACTIVATE);
if (ret) {
mutex_unlock(&drv_data->lock);
if (ret)
return ret;
}
__set_bit(desc->slice_id, drv_data->bitmap);
mutex_unlock(&drv_data->lock);
/* Set first reference */
refcount_set(&desc->refcount, 1);
return ret;
return 0;
}
EXPORT_SYMBOL_GPL(llcc_slice_activate);
@ -4580,24 +4671,21 @@ int llcc_slice_deactivate(struct llcc_slice_desc *desc)
if (IS_ERR_OR_NULL(desc))
return -EINVAL;
mutex_lock(&drv_data->lock);
if (!test_bit(desc->slice_id, drv_data->bitmap)) {
mutex_unlock(&drv_data->lock);
guard(mutex)(&drv_data->lock);
/* refcount > 1, drop one ref and were done. */
if (refcount_dec_not_one(&desc->refcount))
return 0;
}
act_ctrl_val = ACT_CTRL_OPCODE_DEACTIVATE << ACT_CTRL_OPCODE_SHIFT;
act_ctrl_val = ACT_CTRL_OPCODE_DEACTIVATE << ACT_CTRL_OPCODE_SHIFT;
ret = llcc_update_act_ctrl(desc->slice_id, act_ctrl_val,
ACTIVATE);
if (ret) {
mutex_unlock(&drv_data->lock);
if (ret)
return ret;
}
__clear_bit(desc->slice_id, drv_data->bitmap);
mutex_unlock(&drv_data->lock);
/* Finalize: atomically transition 1 -> 0 */
WARN_ON_ONCE(!refcount_dec_if_one(&desc->refcount));
return ret;
return 0;
}
EXPORT_SYMBOL_GPL(llcc_slice_deactivate);
@ -4638,7 +4726,7 @@ static int _qcom_llcc_cfg_program(const struct llcc_slice_config *config,
u32 attr1_val;
u32 attr0_val;
u32 max_cap_cacheline;
struct llcc_slice_desc desc;
struct llcc_slice_desc *desc;
attr1_val = config->cache_mode;
attr1_val |= config->probe_target_ways << ATTR1_PROBE_TARGET_WAYS_SHIFT;
@ -4787,8 +4875,11 @@ static int _qcom_llcc_cfg_program(const struct llcc_slice_config *config,
}
if (config->activate_on_init) {
desc.slice_id = config->slice_id;
ret = llcc_slice_activate(&desc);
desc = llcc_slice_getd(config->usecase_id);
if (IS_ERR(desc))
return PTR_ERR(desc);
ret = llcc_slice_activate(desc);
}
return ret;
@ -5101,18 +5192,18 @@ static int qcom_llcc_probe(struct platform_device *pdev)
llcc_cfg = cfg->sct_data;
sz = cfg->size;
for (i = 0; i < sz; i++)
if (llcc_cfg[i].slice_id > drv_data->max_slices)
drv_data->max_slices = llcc_cfg[i].slice_id;
drv_data->bitmap = devm_bitmap_zalloc(dev, drv_data->max_slices,
GFP_KERNEL);
if (!drv_data->bitmap) {
drv_data->desc = devm_kcalloc(dev, sz, sizeof(struct llcc_slice_desc), GFP_KERNEL);
if (!drv_data->desc) {
ret = -ENOMEM;
goto err;
}
for (i = 0; i < sz; i++) {
drv_data->desc[i].slice_id = llcc_cfg[i].slice_id;
drv_data->desc[i].slice_size = llcc_cfg[i].max_cap;
refcount_set(&drv_data->desc[i].refcount, 0);
}
drv_data->cfg = llcc_cfg;
drv_data->cfg_size = sz;
drv_data->edac_reg_offset = cfg->edac_reg_offset;
@ -5160,6 +5251,7 @@ static const struct of_device_id qcom_llcc_of_match[] = {
{ .compatible = "qcom,sc7280-llcc", .data = &sc7280_cfgs },
{ .compatible = "qcom,sc8180x-llcc", .data = &sc8180x_cfgs },
{ .compatible = "qcom,sc8280xp-llcc", .data = &sc8280xp_cfgs },
{ .compatible = "qcom,sdm670-llcc", .data = &sdm670_cfgs },
{ .compatible = "qcom,sdm845-llcc", .data = &sdm845_cfgs },
{ .compatible = "qcom,sm6350-llcc", .data = &sm6350_cfgs },
{ .compatible = "qcom,sm7150-llcc", .data = &sm7150_cfgs },

View File

@ -196,17 +196,16 @@ struct ocmem *of_get_ocmem(struct device *dev)
}
pdev = of_find_device_by_node(devnode->parent);
if (!pdev) {
dev_err(dev, "Cannot find device node %s\n", devnode->name);
return ERR_PTR(-EPROBE_DEFER);
}
if (!pdev)
return dev_err_ptr_probe(dev, -EPROBE_DEFER,
"Cannot find device node %s\n",
devnode->name);
ocmem = platform_get_drvdata(pdev);
put_device(&pdev->dev);
if (!ocmem) {
dev_err(dev, "Cannot get ocmem\n");
return ERR_PTR(-ENODEV);
}
if (!ocmem)
return dev_err_ptr_probe(dev, -EPROBE_DEFER, "Cannot get ocmem\n");
return ocmem;
}
EXPORT_SYMBOL_GPL(of_get_ocmem);
@ -308,7 +307,7 @@ static int ocmem_dev_probe(struct platform_device *pdev)
ocmem->dev = dev;
ocmem->config = device_get_match_data(dev);
ocmem->core_clk = devm_clk_get(dev, "core");
ocmem->core_clk = devm_clk_get_optional(dev, "core");
if (IS_ERR(ocmem->core_clk))
return dev_err_probe(dev, PTR_ERR(ocmem->core_clk),
"Unable to get core clock\n");

View File

@ -523,7 +523,7 @@ struct pdr_service *pdr_add_lookup(struct pdr_handle *pdr,
if (!pds)
return ERR_PTR(-ENOMEM);
pds->service = SERVREG_NOTIFIER_SERVICE;
pds->service = QMI_SERVICE_ID_SERVREG_NOTIF;
strscpy(pds->service_name, service_name, sizeof(pds->service_name));
strscpy(pds->service_path, service_path, sizeof(pds->service_path));
pds->need_locator_lookup = true;
@ -678,7 +678,7 @@ struct pdr_handle *pdr_handle_alloc(void (*status)(int state,
if (ret < 0)
goto destroy_indack;
ret = qmi_add_lookup(&pdr->locator_hdl, SERVREG_LOCATOR_SERVICE, 1, 1);
ret = qmi_add_lookup(&pdr->locator_hdl, QMI_SERVICE_ID_SERVREG_LOC, 1, 1);
if (ret < 0)
goto release_qmi_handle;

View File

@ -4,9 +4,6 @@
#include <linux/soc/qcom/pdr.h>
#define SERVREG_LOCATOR_SERVICE 0x40
#define SERVREG_NOTIFIER_SERVICE 0x42
#define SERVREG_REGISTER_LISTENER_REQ 0x20
#define SERVREG_GET_DOMAIN_LIST_REQ 0x21
#define SERVREG_STATE_UPDATED_IND_ID 0x22

View File

@ -23,13 +23,19 @@ enum {
PMIC_GLINK_CLIENT_UCSI,
};
struct pmic_glink_data {
unsigned long client_mask;
const char *charger_pdr_service_name;
const char *charger_pdr_service_path;
};
struct pmic_glink {
struct device *dev;
struct pdr_handle *pdr;
struct rpmsg_endpoint *ept;
unsigned long client_mask;
const struct pmic_glink_data *data;
struct auxiliary_device altmode_aux;
struct auxiliary_device ps_aux;
@ -292,7 +298,6 @@ static struct rpmsg_driver pmic_glink_rpmsg_driver = {
static int pmic_glink_probe(struct platform_device *pdev)
{
const unsigned long *match_data;
struct pdr_service *service;
struct pmic_glink *pg;
int ret;
@ -309,12 +314,10 @@ static int pmic_glink_probe(struct platform_device *pdev)
spin_lock_init(&pg->client_lock);
mutex_init(&pg->state_lock);
match_data = (unsigned long *)of_device_get_match_data(&pdev->dev);
if (!match_data)
pg->data = of_device_get_match_data(&pdev->dev);
if (!pg->data)
return -EINVAL;
pg->client_mask = *match_data;
pg->pdr = pdr_handle_alloc(pmic_glink_pdr_callback, pg);
if (IS_ERR(pg->pdr)) {
ret = dev_err_probe(&pdev->dev, PTR_ERR(pg->pdr),
@ -322,27 +325,30 @@ static int pmic_glink_probe(struct platform_device *pdev)
return ret;
}
if (pg->client_mask & BIT(PMIC_GLINK_CLIENT_UCSI)) {
if (pg->data->client_mask & BIT(PMIC_GLINK_CLIENT_UCSI)) {
ret = pmic_glink_add_aux_device(pg, &pg->ucsi_aux, "ucsi");
if (ret)
goto out_release_pdr_handle;
}
if (pg->client_mask & BIT(PMIC_GLINK_CLIENT_ALTMODE)) {
if (pg->data->client_mask & BIT(PMIC_GLINK_CLIENT_ALTMODE)) {
ret = pmic_glink_add_aux_device(pg, &pg->altmode_aux, "altmode");
if (ret)
goto out_release_ucsi_aux;
}
if (pg->client_mask & BIT(PMIC_GLINK_CLIENT_BATT)) {
if (pg->data->client_mask & BIT(PMIC_GLINK_CLIENT_BATT)) {
ret = pmic_glink_add_aux_device(pg, &pg->ps_aux, "power-supply");
if (ret)
goto out_release_altmode_aux;
}
service = pdr_add_lookup(pg->pdr, "tms/servreg", "msm/adsp/charger_pd");
if (IS_ERR(service)) {
ret = dev_err_probe(&pdev->dev, PTR_ERR(service),
"failed adding pdr lookup for charger_pd\n");
goto out_release_aux_devices;
if (pg->data->charger_pdr_service_name && pg->data->charger_pdr_service_path) {
service = pdr_add_lookup(pg->pdr, pg->data->charger_pdr_service_name,
pg->data->charger_pdr_service_path);
if (IS_ERR(service)) {
ret = dev_err_probe(&pdev->dev, PTR_ERR(service),
"failed adding pdr lookup for charger_pd\n");
goto out_release_aux_devices;
}
}
mutex_lock(&__pmic_glink_lock);
@ -352,13 +358,13 @@ static int pmic_glink_probe(struct platform_device *pdev)
return 0;
out_release_aux_devices:
if (pg->client_mask & BIT(PMIC_GLINK_CLIENT_BATT))
if (pg->data->client_mask & BIT(PMIC_GLINK_CLIENT_BATT))
pmic_glink_del_aux_device(pg, &pg->ps_aux);
out_release_altmode_aux:
if (pg->client_mask & BIT(PMIC_GLINK_CLIENT_ALTMODE))
if (pg->data->client_mask & BIT(PMIC_GLINK_CLIENT_ALTMODE))
pmic_glink_del_aux_device(pg, &pg->altmode_aux);
out_release_ucsi_aux:
if (pg->client_mask & BIT(PMIC_GLINK_CLIENT_UCSI))
if (pg->data->client_mask & BIT(PMIC_GLINK_CLIENT_UCSI))
pmic_glink_del_aux_device(pg, &pg->ucsi_aux);
out_release_pdr_handle:
pdr_handle_release(pg->pdr);
@ -372,23 +378,35 @@ static void pmic_glink_remove(struct platform_device *pdev)
pdr_handle_release(pg->pdr);
if (pg->client_mask & BIT(PMIC_GLINK_CLIENT_BATT))
if (pg->data->client_mask & BIT(PMIC_GLINK_CLIENT_BATT))
pmic_glink_del_aux_device(pg, &pg->ps_aux);
if (pg->client_mask & BIT(PMIC_GLINK_CLIENT_ALTMODE))
if (pg->data->client_mask & BIT(PMIC_GLINK_CLIENT_ALTMODE))
pmic_glink_del_aux_device(pg, &pg->altmode_aux);
if (pg->client_mask & BIT(PMIC_GLINK_CLIENT_UCSI))
if (pg->data->client_mask & BIT(PMIC_GLINK_CLIENT_UCSI))
pmic_glink_del_aux_device(pg, &pg->ucsi_aux);
guard(mutex)(&__pmic_glink_lock);
__pmic_glink = NULL;
}
static const unsigned long pmic_glink_sm8450_client_mask = BIT(PMIC_GLINK_CLIENT_BATT) |
BIT(PMIC_GLINK_CLIENT_ALTMODE) |
BIT(PMIC_GLINK_CLIENT_UCSI);
static const struct pmic_glink_data pmic_glink_adsp_data = {
.client_mask = BIT(PMIC_GLINK_CLIENT_BATT) |
BIT(PMIC_GLINK_CLIENT_ALTMODE) |
BIT(PMIC_GLINK_CLIENT_UCSI),
.charger_pdr_service_name = "tms/servreg",
.charger_pdr_service_path = "msm/adsp/charger_pd",
};
static const struct pmic_glink_data pmic_glink_soccp_data = {
.client_mask = BIT(PMIC_GLINK_CLIENT_BATT) |
BIT(PMIC_GLINK_CLIENT_ALTMODE) |
BIT(PMIC_GLINK_CLIENT_UCSI),
};
static const struct of_device_id pmic_glink_of_match[] = {
{ .compatible = "qcom,pmic-glink", .data = &pmic_glink_sm8450_client_mask },
{ .compatible = "qcom,glymur-pmic-glink", .data = &pmic_glink_soccp_data },
{ .compatible = "qcom,kaanapali-pmic-glink", .data = &pmic_glink_soccp_data },
{ .compatible = "qcom,pmic-glink", .data = &pmic_glink_adsp_data },
{}
};
MODULE_DEVICE_TABLE(of, pmic_glink_of_match);

View File

@ -355,7 +355,7 @@ static int qmp_cdev_set_cur_state(struct thermal_cooling_device *cdev,
/* Normalize state */
cdev_state = !!state;
if (qmp_cdev->state == state)
if (qmp_cdev->state == cdev_state)
return 0;
ret = qmp_send(qmp_cdev->qmp, "{class: volt_flr, event:zero_temp, res:%s, value:%s}",

View File

@ -360,6 +360,14 @@ static const struct qcom_pdm_domain_data mpss_wlan_pd = {
},
};
static const struct qcom_pdm_domain_data *glymur_domains[] = {
&adsp_audio_pd,
&adsp_root_pd,
&adsp_sensor_pd,
&cdsp_root_pd,
NULL,
};
static const struct qcom_pdm_domain_data *kaanapali_domains[] = {
&adsp_audio_pd,
&adsp_root_pd,
@ -401,6 +409,16 @@ static const struct qcom_pdm_domain_data *qcs404_domains[] = {
NULL,
};
static const struct qcom_pdm_domain_data *qcs615_domains[] = {
&adsp_audio_pd,
&adsp_root_pd,
&adsp_sensor_pd,
&cdsp_root_pd,
&mpss_root_pd,
&mpss_wlan_pd,
NULL,
};
static const struct qcom_pdm_domain_data *sc7180_domains[] = {
&adsp_audio_pd,
&adsp_root_pd_pdr,
@ -560,8 +578,12 @@ static const struct of_device_id qcom_pdm_domains[] __maybe_unused = {
{ .compatible = "qcom,apq8064", .data = NULL, },
{ .compatible = "qcom,apq8074", .data = NULL, },
{ .compatible = "qcom,apq8084", .data = NULL, },
{ .compatible = "qcom,eliza", .data = sm8550_domains, },
{ .compatible = "qcom,apq8096", .data = msm8996_domains, },
{ .compatible = "qcom,glymur", .data = glymur_domains, },
{ .compatible = "qcom,kaanapali", .data = kaanapali_domains, },
{ .compatible = "qcom,mahua", .data = glymur_domains, },
{ .compatible = "qcom,milos", .data = sm8550_domains, },
{ .compatible = "qcom,msm8226", .data = NULL, },
{ .compatible = "qcom,msm8909", .data = NULL, },
{ .compatible = "qcom,msm8916", .data = NULL, },
@ -572,6 +594,7 @@ static const struct of_device_id qcom_pdm_domains[] __maybe_unused = {
{ .compatible = "qcom,qcm2290", .data = qcm2290_domains, },
{ .compatible = "qcom,qcm6490", .data = sc7280_domains, },
{ .compatible = "qcom,qcs404", .data = qcs404_domains, },
{ .compatible = "qcom,qcs615", .data = qcs615_domains, },
{ .compatible = "qcom,sc7180", .data = sc7180_domains, },
{ .compatible = "qcom,sc7280", .data = sc7280_domains, },
{ .compatible = "qcom,sc8180x", .data = sc8180x_domains, },
@ -615,15 +638,9 @@ static struct qcom_pdm_data *qcom_pdm_start(void)
const struct qcom_pdm_domain_data * const *domains;
const struct of_device_id *match;
struct qcom_pdm_data *data;
struct device_node *root;
int ret, i;
root = of_find_node_by_path("/");
if (!root)
return ERR_PTR(-ENODEV);
match = of_match_node(qcom_pdm_domains, root);
of_node_put(root);
match = of_match_node(qcom_pdm_domains, of_root);
if (!match) {
pr_notice("PDM: no support for the platform, userspace daemon might be required.\n");
return ERR_PTR(-ENODEV);
@ -656,7 +673,7 @@ static struct qcom_pdm_data *qcom_pdm_start(void)
goto err_stop;
}
ret = qmi_add_server(&data->handle, SERVREG_LOCATOR_SERVICE,
ret = qmi_add_server(&data->handle, QMI_SERVICE_ID_SERVREG_LOC,
SERVREG_QMI_VERSION, SERVREG_QMI_INSTANCE);
if (ret) {
pr_err("PDM: error adding server %d\n", ret);

View File

@ -36,6 +36,10 @@
* The driver uses the Linux GPIO and interrupt framework to expose a virtual
* GPIO for each outbound entry and a virtual interrupt controller for each
* inbound entry.
*
* V2 of SMP2P allows remote processors to write to outbound smp2p items before
* the full smp2p connection is negotiated. This is important for processors
* started before linux runs.
*/
#define SMP2P_MAX_ENTRY 16
@ -47,11 +51,12 @@
#define SMP2P_MAGIC 0x504d5324
#define SMP2P_ALL_FEATURES SMP2P_FEATURE_SSR_ACK
#define MAX_VERSION 2
/**
* struct smp2p_smem_item - in memory communication structure
* @magic: magic number
* @version: version - must be 1
* @version: version
* @features: features flag - currently unused
* @local_pid: processor id of sending end
* @remote_pid: processor id of receiving end
@ -180,14 +185,22 @@ static void qcom_smp2p_kick(struct qcom_smp2p *smp2p)
static bool qcom_smp2p_check_ssr(struct qcom_smp2p *smp2p)
{
struct smp2p_smem_item *in = smp2p->in;
struct smp2p_entry *entry;
bool restart_done;
bool restart;
if (!smp2p->ssr_ack_enabled)
return false;
restart = in->flags & BIT(SMP2P_FLAGS_RESTART_DONE_BIT);
restart_done = in->flags & BIT(SMP2P_FLAGS_RESTART_DONE_BIT);
restart = restart_done != smp2p->ssr_ack;
list_for_each_entry(entry, &smp2p->inbound, node) {
if (!entry->value)
continue;
entry->last_value = 0;
}
return restart != smp2p->ssr_ack;
return restart;
}
static void qcom_smp2p_do_ssr_ack(struct qcom_smp2p *smp2p)
@ -219,9 +232,59 @@ static void qcom_smp2p_negotiate(struct qcom_smp2p *smp2p)
smp2p->negotiation_done = true;
trace_smp2p_negotiate(smp2p->dev, out->features);
} else if (in->version && in->version < out->version) {
out->version = in->version;
qcom_smp2p_kick(smp2p);
}
}
static int qcom_smp2p_in_version(struct qcom_smp2p *smp2p)
{
unsigned int smem_id = smp2p->smem_items[SMP2P_INBOUND];
unsigned int pid = smp2p->remote_pid;
struct smp2p_smem_item *in;
size_t size;
in = qcom_smem_get(pid, smem_id, &size);
if (IS_ERR(in))
return 0;
return in->version;
}
static void qcom_smp2p_start_in(struct qcom_smp2p *smp2p)
{
unsigned int smem_id = smp2p->smem_items[SMP2P_INBOUND];
unsigned int pid = smp2p->remote_pid;
char buf[SMP2P_MAX_ENTRY_NAME];
struct smp2p_smem_item *in;
struct smp2p_entry *entry;
size_t size;
int i;
in = qcom_smem_get(pid, smem_id, &size);
if (IS_ERR(in))
return;
smp2p->in = in;
/* Check if version is initialized by the remote. */
if (in->version == 0)
return;
for (i = smp2p->valid_entries; i < in->valid_entries; i++) {
list_for_each_entry(entry, &smp2p->inbound, node) {
memcpy(buf, in->entries[i].name, sizeof(buf));
if (!strcmp(buf, entry->name)) {
entry->value = &in->entries[i].value;
entry->last_value = readl(entry->value);
break;
}
}
}
smp2p->valid_entries = i;
}
static void qcom_smp2p_notify_in(struct qcom_smp2p *smp2p)
{
struct smp2p_smem_item *in;
@ -368,12 +431,31 @@ static void smp2p_irq_print_chip(struct irq_data *irqd, struct seq_file *p)
seq_printf(p, "%8s", dev_name(entry->smp2p->dev));
}
static int smp2p_irq_get_irqchip_state(struct irq_data *irqd, enum irqchip_irq_state which,
bool *state)
{
struct smp2p_entry *entry = irq_data_get_irq_chip_data(irqd);
u32 val;
if (which != IRQCHIP_STATE_LINE_LEVEL)
return -EINVAL;
if (!entry->value)
return -ENODEV;
val = readl(entry->value);
*state = !!(val & BIT(irqd_to_hwirq(irqd)));
return 0;
}
static struct irq_chip smp2p_irq_chip = {
.name = "smp2p",
.irq_mask = smp2p_mask_irq,
.irq_unmask = smp2p_unmask_irq,
.irq_set_type = smp2p_set_irq_type,
.irq_print_chip = smp2p_irq_print_chip,
.irq_get_irqchip_state = smp2p_irq_get_irqchip_state,
};
static int smp2p_irq_map(struct irq_domain *d,
@ -464,6 +546,7 @@ static int qcom_smp2p_alloc_outbound_item(struct qcom_smp2p *smp2p)
struct smp2p_smem_item *out;
unsigned smem_id = smp2p->smem_items[SMP2P_OUTBOUND];
unsigned pid = smp2p->remote_pid;
u8 in_version;
int ret;
ret = qcom_smem_alloc(pid, smem_id, sizeof(*out));
@ -485,12 +568,21 @@ static int qcom_smp2p_alloc_outbound_item(struct qcom_smp2p *smp2p)
out->valid_entries = 0;
out->features = SMP2P_ALL_FEATURES;
in_version = qcom_smp2p_in_version(smp2p);
if (in_version > MAX_VERSION) {
dev_err(smp2p->dev, "Unsupported smp2p version %d\n", in_version);
return -EINVAL;
}
/*
* Make sure the rest of the header is written before we validate the
* item by writing a valid version number.
*/
wmb();
out->version = 1;
if (in_version && in_version <= 2)
out->version = in_version;
else
out->version = 2;
qcom_smp2p_kick(smp2p);
@ -618,6 +710,9 @@ static int qcom_smp2p_probe(struct platform_device *pdev)
}
}
/* Check inbound entries in the case of early boot processor */
qcom_smp2p_start_in(smp2p);
/* Kick the outgoing edge after allocating entries */
qcom_smp2p_kick(smp2p);

View File

@ -182,6 +182,7 @@ static const char *const pmic_models[] = {
[72] = "PMR735D",
[73] = "PM8550",
[74] = "PMK8550",
[76] = "PM7550BA",
[78] = "PMM8650AU",
[79] = "PMM8650AU_PSAIL",
[80] = "PM7550",
@ -473,6 +474,7 @@ static const struct soc_id soc_id[] = {
{ qcom_board_id(IPQ5000) },
{ qcom_board_id(IPQ0509) },
{ qcom_board_id(IPQ0518) },
{ qcom_board_id(SM7450) },
{ qcom_board_id(SM6375) },
{ qcom_board_id(IPQ9514) },
{ qcom_board_id(IPQ9550) },
@ -488,10 +490,12 @@ static const struct soc_id soc_id[] = {
{ qcom_board_id(SM8475) },
{ qcom_board_id(SM8475P) },
{ qcom_board_id(SA8255P) },
{ qcom_board_id(SA8650P) },
{ qcom_board_id(SA8775P) },
{ qcom_board_id(QRU1000) },
{ qcom_board_id(SM8475_2) },
{ qcom_board_id(QDU1000) },
{ qcom_board_id(SM7450P) },
{ qcom_board_id(X1E80100) },
{ qcom_board_id(SM8650) },
{ qcom_board_id(SM4450) },
@ -522,6 +526,13 @@ static const struct soc_id soc_id[] = {
{ qcom_board_id(QCS8275) },
{ qcom_board_id(QCS9075) },
{ qcom_board_id(QCS615) },
{ qcom_board_id(CQ7790M) },
{ qcom_board_id(CQ7790S) },
{ qcom_board_id(IPQ5200) },
{ qcom_board_id(IPQ5210) },
{ qcom_board_id(QCF2200) },
{ qcom_board_id(QCF3200) },
{ qcom_board_id(QCF3210) },
};
static const char *socinfo_machine(struct device *dev, unsigned int id)

View File

@ -16,6 +16,17 @@ static const struct qcom_ubwc_cfg_data no_ubwc_data = {
/* no UBWC, no HBB */
};
static const struct qcom_ubwc_cfg_data eliza_data = {
.ubwc_enc_version = UBWC_5_0,
.ubwc_dec_version = UBWC_5_0,
.ubwc_swizzle = UBWC_SWIZZLE_ENABLE_LVL2 |
UBWC_SWIZZLE_ENABLE_LVL3,
.ubwc_bank_spread = true,
/* TODO: highest_bank_bit = 14 for LP_DDR4 */
.highest_bank_bit = 15,
.macrotile_mode = true,
};
static const struct qcom_ubwc_cfg_data kaanapali_data = {
.ubwc_enc_version = UBWC_6_0,
.ubwc_dec_version = UBWC_6_0,
@ -217,22 +228,10 @@ static const struct qcom_ubwc_cfg_data sm8750_data = {
.macrotile_mode = true,
};
static const struct qcom_ubwc_cfg_data x1e80100_data = {
.ubwc_enc_version = UBWC_4_0,
.ubwc_dec_version = UBWC_4_3,
.ubwc_swizzle = UBWC_SWIZZLE_ENABLE_LVL2 |
UBWC_SWIZZLE_ENABLE_LVL3,
.ubwc_bank_spread = true,
/* TODO: highest_bank_bit = 15 for LP_DDR4 */
.highest_bank_bit = 16,
.macrotile_mode = true,
};
static const struct qcom_ubwc_cfg_data glymur_data = {
.ubwc_enc_version = UBWC_5_0,
.ubwc_dec_version = UBWC_5_0,
.ubwc_swizzle = UBWC_SWIZZLE_ENABLE_LVL2 |
UBWC_SWIZZLE_ENABLE_LVL3,
.ubwc_swizzle = 0,
.ubwc_bank_spread = true,
/* TODO: highest_bank_bit = 15 for LP_DDR4 */
.highest_bank_bit = 16,
@ -244,8 +243,10 @@ static const struct of_device_id qcom_ubwc_configs[] __maybe_unused = {
{ .compatible = "qcom,apq8026", .data = &no_ubwc_data },
{ .compatible = "qcom,apq8074", .data = &no_ubwc_data },
{ .compatible = "qcom,apq8096", .data = &msm8998_data },
{ .compatible = "qcom,eliza", .data = &eliza_data, },
{ .compatible = "qcom,kaanapali", .data = &kaanapali_data, },
{ .compatible = "qcom,glymur", .data = &glymur_data},
{ .compatible = "qcom,mahua", .data = &glymur_data },
{ .compatible = "qcom,msm8226", .data = &no_ubwc_data },
{ .compatible = "qcom,msm8916", .data = &no_ubwc_data },
{ .compatible = "qcom,msm8917", .data = &no_ubwc_data },
@ -294,8 +295,8 @@ static const struct of_device_id qcom_ubwc_configs[] __maybe_unused = {
{ .compatible = "qcom,sm8550", .data = &sm8550_data, },
{ .compatible = "qcom,sm8650", .data = &sm8550_data, },
{ .compatible = "qcom,sm8750", .data = &sm8750_data, },
{ .compatible = "qcom,x1e80100", .data = &x1e80100_data, },
{ .compatible = "qcom,x1p42100", .data = &x1e80100_data, },
{ .compatible = "qcom,x1e80100", .data = &sm8550_data, },
{ .compatible = "qcom,x1p42100", .data = &sm8550_data, },
{ }
};

View File

@ -94,7 +94,7 @@ struct wcnss_download_nv_req {
u16 seq;
u16 last;
u32 frag_size;
u8 fragment[];
u8 fragment[] __counted_by(frag_size);
} __packed;
/**
@ -201,16 +201,12 @@ static int wcnss_download_nv(struct wcnss_ctrl *wcnss, bool *expect_cbc)
{
const struct firmware *fw;
struct device *dev = wcnss->dev;
struct wcnss_download_nv_req *req;
const char *nvbin = NVBIN_FILE;
const void *data;
ssize_t left;
int ret;
struct wcnss_download_nv_req *req __free(kfree) = kzalloc(sizeof(*req) + NV_FRAGMENT_SIZE,
GFP_KERNEL);
if (!req)
return -ENOMEM;
ret = of_property_read_string(dev->of_node, "firmware-name", &nvbin);
if (ret < 0 && ret != -EINVAL)
return ret;
@ -224,11 +220,15 @@ static int wcnss_download_nv(struct wcnss_ctrl *wcnss, bool *expect_cbc)
data = fw->data;
left = fw->size;
req = kzalloc_flex(*req, fragment, NV_FRAGMENT_SIZE);
if (!req)
return -ENOMEM;
req->frag_size = NV_FRAGMENT_SIZE;
req->hdr.type = WCNSS_DOWNLOAD_NV_REQ;
req->hdr.len = sizeof(*req) + NV_FRAGMENT_SIZE;
req->hdr.len = struct_size(req, fragment, NV_FRAGMENT_SIZE);
req->last = 0;
req->frag_size = NV_FRAGMENT_SIZE;
req->seq = 0;
do {
@ -264,6 +264,7 @@ static int wcnss_download_nv(struct wcnss_ctrl *wcnss, bool *expect_cbc)
release_fw:
release_firmware(fw);
kfree(req);
return ret;
}

View File

@ -245,6 +245,7 @@
#define QCOM_ID_IPQ5000 503
#define QCOM_ID_IPQ0509 504
#define QCOM_ID_IPQ0518 505
#define QCOM_ID_SM7450 506
#define QCOM_ID_SM6375 507
#define QCOM_ID_IPQ9514 510
#define QCOM_ID_IPQ9550 511
@ -260,10 +261,12 @@
#define QCOM_ID_SM8475 530
#define QCOM_ID_SM8475P 531
#define QCOM_ID_SA8255P 532
#define QCOM_ID_SA8650P 533
#define QCOM_ID_SA8775P 534
#define QCOM_ID_QRU1000 539
#define QCOM_ID_SM8475_2 540
#define QCOM_ID_QDU1000 545
#define QCOM_ID_SM7450P 547
#define QCOM_ID_X1E80100 555
#define QCOM_ID_SM8650 557
#define QCOM_ID_SM4450 568
@ -294,6 +297,13 @@
#define QCOM_ID_QCS8275 675
#define QCOM_ID_QCS9075 676
#define QCOM_ID_QCS615 680
#define QCOM_ID_CQ7790M 731
#define QCOM_ID_CQ7790S 732
#define QCOM_ID_IPQ5200 765
#define QCOM_ID_IPQ5210 766
#define QCOM_ID_QCF2200 767
#define QCOM_ID_QCF3200 768
#define QCOM_ID_QCF3210 769
/*
* The board type and revision information, used by Qualcomm bootloaders and

View File

@ -91,10 +91,12 @@
* struct llcc_slice_desc - Cache slice descriptor
* @slice_id: llcc slice id
* @slice_size: Size allocated for the llcc slice
* @refcount: Atomic counter to track activate/deactivate calls
*/
struct llcc_slice_desc {
u32 slice_id;
size_t slice_size;
refcount_t refcount;
};
/**
@ -152,11 +154,10 @@ struct llcc_edac_reg_offset {
* @edac_reg_offset: Offset of the LLCC EDAC registers
* @lock: mutex associated with each slice
* @cfg_size: size of the config data table
* @max_slices: max slices as read from device tree
* @num_banks: Number of llcc banks
* @bitmap: Bit map to track the active slice ids
* @ecc_irq: interrupt for llcc cache error detection and reporting
* @ecc_irq_configured: 'True' if firmware has already configured the irq propagation
* @desc: Array pointer of pre-allocated LLCC slice descriptors
* @version: Indicates the LLCC version
*/
struct llcc_drv_data {
@ -167,12 +168,11 @@ struct llcc_drv_data {
const struct llcc_edac_reg_offset *edac_reg_offset;
struct mutex lock;
u32 cfg_size;
u32 max_slices;
u32 num_banks;
unsigned long *bitmap;
int ecc_irq;
bool ecc_irq_configured;
u32 version;
struct llcc_slice_desc *desc;
};
#if IS_ENABLED(CONFIG_QCOM_LLCC)

View File

@ -92,6 +92,18 @@ struct qmi_elem_info {
#define QMI_ERR_INCOMPATIBLE_STATE_V01 90
#define QMI_ERR_NOT_SUPPORTED_V01 94
/*
* Enumerate the IDs of the QMI services
*/
#define QMI_SERVICE_ID_TEST 0x0f /* 15 */
#define QMI_SERVICE_ID_SSCTL 0x2b /* 43 */
#define QMI_SERVICE_ID_IPA 0x31 /* 49 */
#define QMI_SERVICE_ID_SERVREG_LOC 0x40 /* 64 */
#define QMI_SERVICE_ID_SERVREG_NOTIF 0x42 /* 66 */
#define QMI_SERVICE_ID_WLFW 0x45 /* 69 */
#define QMI_SERVICE_ID_SLIMBUS 0x301 /* 769 */
#define QMI_SERVICE_ID_USB_AUDIO_STREAM 0x41d /* 1053 */
/**
* struct qmi_response_type_v01 - common response header (decoded)
* @result: result of the transaction

View File

@ -74,4 +74,29 @@ static inline bool qcom_ubwc_get_ubwc_mode(const struct qcom_ubwc_cfg_data *cfg)
return ret;
}
/*
* This is the best guess, based on the MDSS driver, which worked so far.
*/
static inline bool qcom_ubwc_min_acc_length_64b(const struct qcom_ubwc_cfg_data *cfg)
{
return cfg->ubwc_enc_version == UBWC_1_0 &&
(cfg->ubwc_dec_version == UBWC_2_0 ||
cfg->ubwc_dec_version == UBWC_3_0);
}
static inline bool qcom_ubwc_macrotile_mode(const struct qcom_ubwc_cfg_data *cfg)
{
return cfg->macrotile_mode;
}
static inline bool qcom_ubwc_bank_spread(const struct qcom_ubwc_cfg_data *cfg)
{
return cfg->ubwc_bank_spread;
}
static inline u32 qcom_ubwc_swizzle(const struct qcom_ubwc_cfg_data *cfg)
{
return cfg->ubwc_swizzle;
}
#endif /* __QCOM_UBWC_H__ */

View File

@ -592,7 +592,7 @@ static int qmi_sample_init(void)
if (ret < 0)
goto err_unregister_driver;
qmi_add_lookup(&lookup_client, 15, 0, 0);
qmi_add_lookup(&lookup_client, QMI_SERVICE_ID_TEST, 0, 0);
return 0;