summaryrefslogtreecommitdiff
path: root/drivers/soc/qcom
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2021-09-01 15:25:28 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2021-09-01 15:25:28 -0700
commit866147b8fa59530812fc769027a94468d89401e7 (patch)
tree1d97cf66b7db6765570ba824c51bd3dc84b561fc /drivers/soc/qcom
parent634135a07b887a8ad8904da8c147407650747a38 (diff)
parent06779631d18ff2901af604eadea0d7b2193db7a1 (diff)
Merge tag 'drivers-5.15' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc
Pull ARM SoC driver updates from Arnd Bergmann: "These are updates for drivers that are tied to a particular SoC, including the correspondig device tree bindings: - A couple of reset controller changes for unisoc, uniphier, renesas and zte platforms - memory controller driver fixes for omap and tegra - Rockchip io domain driver updates - Lots of updates for qualcomm platforms, mostly touching their firmware and power management drivers - Tegra FUSE and firmware driver updateѕ - Support for virtio transports in the SCMI firmware framework - cleanup of ixp4xx drivers, towards enabling multiplatform support and bringing it up to date with modern platforms - Minor updates for keystone, mediatek, omap, renesas" * tag 'drivers-5.15' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc: (96 commits) reset: simple: remove ZTE details in Kconfig help soc: rockchip: io-domain: Remove unneeded semicolon soc: rockchip: io-domain: add rk3568 support dt-bindings: power: add rk3568-pmu-io-domain support bus: ixp4xx: return on error in ixp4xx_exp_probe() soc: renesas: Prefer memcpy() over strcpy() firmware: tegra: Stop using seq_get_buf() soc/tegra: fuse: Enable fuse clock on suspend for Tegra124 soc/tegra: fuse: Add runtime PM support soc/tegra: fuse: Clear fuse->clk on driver probe failure soc/tegra: pmc: Prevent racing with cpuilde driver soc/tegra: bpmp: Remove unused including <linux/version.h> dt-bindings: soc: ti: pruss: Add dma-coherent property soc: ti: Remove pm_runtime_irq_safe() usage for smartreflex soc: ti: pruss: Enable support for ICSSG subsystems on K3 AM64x SoCs dt-bindings: soc: ti: pruss: Update bindings for K3 AM64x SoCs firmware: arm_scmi: Use WARN_ON() to check configured transports firmware: arm_scmi: Fix boolconv.cocci warnings soc: mediatek: mmsys: Fix missing UFOE component in mt8173 table routing soc: mediatek: mmsys: add MT8365 support ...
Diffstat (limited to 'drivers/soc/qcom')
-rw-r--r--drivers/soc/qcom/cpr.c43
-rw-r--r--drivers/soc/qcom/mdt_loader.c18
-rw-r--r--drivers/soc/qcom/qcom-geni-se.c30
-rw-r--r--drivers/soc/qcom/qcom_aoss.c9
-rw-r--r--drivers/soc/qcom/rpmhpd.c5
-rw-r--r--drivers/soc/qcom/rpmpd.c28
-rw-r--r--drivers/soc/qcom/smd-rpm.c1
-rw-r--r--drivers/soc/qcom/smsm.c28
-rw-r--r--drivers/soc/qcom/socinfo.c4
9 files changed, 110 insertions, 56 deletions
diff --git a/drivers/soc/qcom/cpr.c b/drivers/soc/qcom/cpr.c
index b24cc77d1889..4ce8e816154f 100644
--- a/drivers/soc/qcom/cpr.c
+++ b/drivers/soc/qcom/cpr.c
@@ -801,38 +801,6 @@ unlock:
return ret;
}
-static int cpr_read_efuse(struct device *dev, const char *cname, u32 *data)
-{
- struct nvmem_cell *cell;
- ssize_t len;
- char *ret;
- int i;
-
- *data = 0;
-
- cell = nvmem_cell_get(dev, cname);
- if (IS_ERR(cell)) {
- if (PTR_ERR(cell) != -EPROBE_DEFER)
- dev_err(dev, "undefined cell %s\n", cname);
- return PTR_ERR(cell);
- }
-
- ret = nvmem_cell_read(cell, &len);
- nvmem_cell_put(cell);
- if (IS_ERR(ret)) {
- dev_err(dev, "can't read cell %s\n", cname);
- return PTR_ERR(ret);
- }
-
- for (i = 0; i < len; i++)
- *data |= ret[i] << (8 * i);
-
- kfree(ret);
- dev_dbg(dev, "efuse read(%s) = %x, bytes %zd\n", cname, *data, len);
-
- return 0;
-}
-
static int
cpr_populate_ring_osc_idx(struct cpr_drv *drv)
{
@@ -843,8 +811,7 @@ cpr_populate_ring_osc_idx(struct cpr_drv *drv)
int ret;
for (; fuse < end; fuse++, fuses++) {
- ret = cpr_read_efuse(drv->dev, fuses->ring_osc,
- &data);
+ ret = nvmem_cell_read_variable_le_u32(drv->dev, fuses->ring_osc, &data);
if (ret)
return ret;
fuse->ring_osc_idx = data;
@@ -863,7 +830,7 @@ static int cpr_read_fuse_uV(const struct cpr_desc *desc,
u32 bits = 0;
int ret;
- ret = cpr_read_efuse(drv->dev, init_v_efuse, &bits);
+ ret = nvmem_cell_read_variable_le_u32(drv->dev, init_v_efuse, &bits);
if (ret)
return ret;
@@ -932,7 +899,7 @@ static int cpr_fuse_corner_init(struct cpr_drv *drv)
}
/* Populate target quotient by scaling */
- ret = cpr_read_efuse(drv->dev, fuses->quotient, &fuse->quot);
+ ret = nvmem_cell_read_variable_le_u32(drv->dev, fuses->quotient, &fuse->quot);
if (ret)
return ret;
@@ -1001,7 +968,7 @@ static int cpr_calculate_scaling(const char *quot_offset,
prev_fuse = fuse - 1;
if (quot_offset) {
- ret = cpr_read_efuse(drv->dev, quot_offset, &quot_diff);
+ ret = nvmem_cell_read_variable_le_u32(drv->dev, quot_offset, &quot_diff);
if (ret)
return ret;
@@ -1701,7 +1668,7 @@ static int cpr_probe(struct platform_device *pdev)
* initialized after attaching to the power domain,
* since it depends on the CPU's OPP table.
*/
- ret = cpr_read_efuse(dev, "cpr_fuse_revision", &cpr_rev);
+ ret = nvmem_cell_read_variable_le_u32(dev, "cpr_fuse_revision", &cpr_rev);
if (ret)
return ret;
diff --git a/drivers/soc/qcom/mdt_loader.c b/drivers/soc/qcom/mdt_loader.c
index eba7f76f9d61..bda170d7b4a2 100644
--- a/drivers/soc/qcom/mdt_loader.c
+++ b/drivers/soc/qcom/mdt_loader.c
@@ -166,6 +166,8 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw,
metadata = qcom_mdt_read_metadata(fw, &metadata_len);
if (IS_ERR(metadata)) {
ret = PTR_ERR(metadata);
+ dev_err(dev, "error %d reading firmware %s metadata\n",
+ ret, fw_name);
goto out;
}
@@ -173,7 +175,9 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw,
kfree(metadata);
if (ret) {
- dev_err(dev, "invalid firmware metadata\n");
+ /* Invalid firmware metadata */
+ dev_err(dev, "error %d initializing firmware %s\n",
+ ret, fw_name);
goto out;
}
}
@@ -199,7 +203,9 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw,
ret = qcom_scm_pas_mem_setup(pas_id, mem_phys,
max_addr - min_addr);
if (ret) {
- dev_err(dev, "unable to setup relocation\n");
+ /* Unable to set up relocation */
+ dev_err(dev, "error %d setting up firmware %s\n",
+ ret, fw_name);
goto out;
}
}
@@ -243,9 +249,8 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw,
if (phdr->p_filesz && phdr->p_offset < fw->size) {
/* Firmware is large enough to be non-split */
if (phdr->p_offset + phdr->p_filesz > fw->size) {
- dev_err(dev,
- "failed to load segment %d from truncated file %s\n",
- i, firmware);
+ dev_err(dev, "file %s segment %d would be truncated\n",
+ fw_name, i);
ret = -EINVAL;
break;
}
@@ -257,7 +262,8 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw,
ret = request_firmware_into_buf(&seg_fw, fw_name, dev,
ptr, phdr->p_filesz);
if (ret) {
- dev_err(dev, "failed to load %s\n", fw_name);
+ dev_err(dev, "error %d loading %s\n",
+ ret, fw_name);
break;
}
diff --git a/drivers/soc/qcom/qcom-geni-se.c b/drivers/soc/qcom/qcom-geni-se.c
index 5bdfb1565c14..7d649d2cf31e 100644
--- a/drivers/soc/qcom/qcom-geni-se.c
+++ b/drivers/soc/qcom/qcom-geni-se.c
@@ -104,7 +104,6 @@ static const char * const icc_path_names[] = {"qup-core", "qup-config",
#define GENI_OUTPUT_CTRL 0x24
#define GENI_CGC_CTRL 0x28
#define GENI_CLK_CTRL_RO 0x60
-#define GENI_IF_DISABLE_RO 0x64
#define GENI_FW_S_REVISION_RO 0x6c
#define SE_GENI_BYTE_GRAN 0x254
#define SE_GENI_TX_PACKING_CFG0 0x260
@@ -322,6 +321,30 @@ static void geni_se_select_dma_mode(struct geni_se *se)
writel_relaxed(val, se->base + SE_GENI_DMA_MODE_EN);
}
+static void geni_se_select_gpi_mode(struct geni_se *se)
+{
+ u32 val;
+
+ geni_se_irq_clear(se);
+
+ writel(0, se->base + SE_IRQ_EN);
+
+ val = readl(se->base + SE_GENI_S_IRQ_EN);
+ val &= ~S_CMD_DONE_EN;
+ writel(val, se->base + SE_GENI_S_IRQ_EN);
+
+ val = readl(se->base + SE_GENI_M_IRQ_EN);
+ val &= ~(M_CMD_DONE_EN | M_TX_FIFO_WATERMARK_EN |
+ M_RX_FIFO_WATERMARK_EN | M_RX_FIFO_LAST_EN);
+ writel(val, se->base + SE_GENI_M_IRQ_EN);
+
+ writel(GENI_DMA_MODE_EN, se->base + SE_GENI_DMA_MODE_EN);
+
+ val = readl(se->base + SE_GSI_EVENT_EN);
+ val |= (DMA_RX_EVENT_EN | DMA_TX_EVENT_EN | GENI_M_EVENT_EN | GENI_S_EVENT_EN);
+ writel(val, se->base + SE_GSI_EVENT_EN);
+}
+
/**
* geni_se_select_mode() - Select the serial engine transfer mode
* @se: Pointer to the concerned serial engine.
@@ -329,7 +352,7 @@ static void geni_se_select_dma_mode(struct geni_se *se)
*/
void geni_se_select_mode(struct geni_se *se, enum geni_se_xfer_mode mode)
{
- WARN_ON(mode != GENI_SE_FIFO && mode != GENI_SE_DMA);
+ WARN_ON(mode != GENI_SE_FIFO && mode != GENI_SE_DMA && mode != GENI_GPI_DMA);
switch (mode) {
case GENI_SE_FIFO:
@@ -338,6 +361,9 @@ void geni_se_select_mode(struct geni_se *se, enum geni_se_xfer_mode mode)
case GENI_SE_DMA:
geni_se_select_dma_mode(se);
break;
+ case GENI_GPI_DMA:
+ geni_se_select_gpi_mode(se);
+ break;
case GENI_SE_INVALID:
default:
break;
diff --git a/drivers/soc/qcom/qcom_aoss.c b/drivers/soc/qcom/qcom_aoss.c
index 934fcc4d2b05..536c3e4114fb 100644
--- a/drivers/soc/qcom/qcom_aoss.c
+++ b/drivers/soc/qcom/qcom_aoss.c
@@ -476,12 +476,12 @@ static int qmp_cooling_device_add(struct qmp *qmp,
static int qmp_cooling_devices_register(struct qmp *qmp)
{
struct device_node *np, *child;
- int count = QMP_NUM_COOLING_RESOURCES;
+ int count = 0;
int ret;
np = qmp->dev->of_node;
- qmp->cooling_devs = devm_kcalloc(qmp->dev, count,
+ qmp->cooling_devs = devm_kcalloc(qmp->dev, QMP_NUM_COOLING_RESOURCES,
sizeof(*qmp->cooling_devs),
GFP_KERNEL);
@@ -497,12 +497,16 @@ static int qmp_cooling_devices_register(struct qmp *qmp)
goto unroll;
}
+ if (!count)
+ devm_kfree(qmp->dev, qmp->cooling_devs);
+
return 0;
unroll:
while (--count >= 0)
thermal_cooling_device_unregister
(qmp->cooling_devs[count].cdev);
+ devm_kfree(qmp->dev, qmp->cooling_devs);
return ret;
}
@@ -602,6 +606,7 @@ static const struct of_device_id qmp_dt_match[] = {
{ .compatible = "qcom,sm8150-aoss-qmp", },
{ .compatible = "qcom,sm8250-aoss-qmp", },
{ .compatible = "qcom,sm8350-aoss-qmp", },
+ { .compatible = "qcom,aoss-qmp", },
{}
};
MODULE_DEVICE_TABLE(of, qmp_dt_match);
diff --git a/drivers/soc/qcom/rpmhpd.c b/drivers/soc/qcom/rpmhpd.c
index 2daa17ba54a3..fa209b479ab3 100644
--- a/drivers/soc/qcom/rpmhpd.c
+++ b/drivers/soc/qcom/rpmhpd.c
@@ -403,12 +403,11 @@ static int rpmhpd_power_on(struct generic_pm_domain *domain)
static int rpmhpd_power_off(struct generic_pm_domain *domain)
{
struct rpmhpd *pd = domain_to_rpmhpd(domain);
- int ret = 0;
+ int ret;
mutex_lock(&rpmhpd_lock);
- ret = rpmhpd_aggregate_corner(pd, pd->level[0]);
-
+ ret = rpmhpd_aggregate_corner(pd, 0);
if (!ret)
pd->enabled = false;
diff --git a/drivers/soc/qcom/rpmpd.c b/drivers/soc/qcom/rpmpd.c
index 0b532a892d60..dbf494e92574 100644
--- a/drivers/soc/qcom/rpmpd.c
+++ b/drivers/soc/qcom/rpmpd.c
@@ -346,6 +346,33 @@ static const struct rpmpd_desc sdm660_desc = {
.max_state = RPM_SMD_LEVEL_TURBO,
};
+/* sm4250/6115 RPM Power domains */
+DEFINE_RPMPD_PAIR(sm6115, vddcx, vddcx_ao, RWCX, LEVEL, 0);
+DEFINE_RPMPD_VFL(sm6115, vddcx_vfl, RWCX, 0);
+
+DEFINE_RPMPD_PAIR(sm6115, vddmx, vddmx_ao, RWMX, LEVEL, 0);
+DEFINE_RPMPD_VFL(sm6115, vddmx_vfl, RWMX, 0);
+
+DEFINE_RPMPD_LEVEL(sm6115, vdd_lpi_cx, RWLC, 0);
+DEFINE_RPMPD_LEVEL(sm6115, vdd_lpi_mx, RWLM, 0);
+
+static struct rpmpd *sm6115_rpmpds[] = {
+ [SM6115_VDDCX] = &sm6115_vddcx,
+ [SM6115_VDDCX_AO] = &sm6115_vddcx_ao,
+ [SM6115_VDDCX_VFL] = &sm6115_vddcx_vfl,
+ [SM6115_VDDMX] = &sm6115_vddmx,
+ [SM6115_VDDMX_AO] = &sm6115_vddmx_ao,
+ [SM6115_VDDMX_VFL] = &sm6115_vddmx_vfl,
+ [SM6115_VDD_LPI_CX] = &sm6115_vdd_lpi_cx,
+ [SM6115_VDD_LPI_MX] = &sm6115_vdd_lpi_mx,
+};
+
+static const struct rpmpd_desc sm6115_desc = {
+ .rpmpds = sm6115_rpmpds,
+ .num_pds = ARRAY_SIZE(sm6115_rpmpds),
+ .max_state = RPM_SMD_LEVEL_TURBO_NO_CPR,
+};
+
static const struct of_device_id rpmpd_match_table[] = {
{ .compatible = "qcom,mdm9607-rpmpd", .data = &mdm9607_desc },
{ .compatible = "qcom,msm8916-rpmpd", .data = &msm8916_desc },
@@ -356,6 +383,7 @@ static const struct of_device_id rpmpd_match_table[] = {
{ .compatible = "qcom,msm8998-rpmpd", .data = &msm8998_desc },
{ .compatible = "qcom,qcs404-rpmpd", .data = &qcs404_desc },
{ .compatible = "qcom,sdm660-rpmpd", .data = &sdm660_desc },
+ { .compatible = "qcom,sm6115-rpmpd", .data = &sm6115_desc },
{ }
};
MODULE_DEVICE_TABLE(of, rpmpd_match_table);
diff --git a/drivers/soc/qcom/smd-rpm.c b/drivers/soc/qcom/smd-rpm.c
index bc0be1d4be5f..dfdd4f20f5fd 100644
--- a/drivers/soc/qcom/smd-rpm.c
+++ b/drivers/soc/qcom/smd-rpm.c
@@ -242,6 +242,7 @@ static const struct of_device_id qcom_smd_rpm_of_match[] = {
{ .compatible = "qcom,rpm-msm8996" },
{ .compatible = "qcom,rpm-msm8998" },
{ .compatible = "qcom,rpm-sdm660" },
+ { .compatible = "qcom,rpm-sm6115" },
{ .compatible = "qcom,rpm-sm6125" },
{ .compatible = "qcom,rpm-qcs404" },
{}
diff --git a/drivers/soc/qcom/smsm.c b/drivers/soc/qcom/smsm.c
index 1d3d5e3ec2b0..ef15d014c03a 100644
--- a/drivers/soc/qcom/smsm.c
+++ b/drivers/soc/qcom/smsm.c
@@ -109,7 +109,7 @@ struct smsm_entry {
DECLARE_BITMAP(irq_enabled, 32);
DECLARE_BITMAP(irq_rising, 32);
DECLARE_BITMAP(irq_falling, 32);
- u32 last_value;
+ unsigned long last_value;
u32 *remote_state;
u32 *subscription;
@@ -204,8 +204,7 @@ static irqreturn_t smsm_intr(int irq, void *data)
u32 val;
val = readl(entry->remote_state);
- changed = val ^ entry->last_value;
- entry->last_value = val;
+ changed = val ^ xchg(&entry->last_value, val);
for_each_set_bit(i, entry->irq_enabled, 32) {
if (!(changed & BIT(i)))
@@ -264,6 +263,12 @@ static void smsm_unmask_irq(struct irq_data *irqd)
struct qcom_smsm *smsm = entry->smsm;
u32 val;
+ /* Make sure our last cached state is up-to-date */
+ if (readl(entry->remote_state) & BIT(irq))
+ set_bit(irq, &entry->last_value);
+ else
+ clear_bit(irq, &entry->last_value);
+
set_bit(irq, entry->irq_enabled);
if (entry->subscription) {
@@ -299,11 +304,28 @@ static int smsm_set_irq_type(struct irq_data *irqd, unsigned int type)
return 0;
}
+static int smsm_get_irqchip_state(struct irq_data *irqd,
+ enum irqchip_irq_state which, bool *state)
+{
+ struct smsm_entry *entry = irq_data_get_irq_chip_data(irqd);
+ irq_hw_number_t irq = irqd_to_hwirq(irqd);
+ u32 val;
+
+ if (which != IRQCHIP_STATE_LINE_LEVEL)
+ return -EINVAL;
+
+ val = readl(entry->remote_state);
+ *state = !!(val & BIT(irq));
+
+ return 0;
+}
+
static struct irq_chip smsm_irq_chip = {
.name = "smsm",
.irq_mask = smsm_mask_irq,
.irq_unmask = smsm_unmask_irq,
.irq_set_type = smsm_set_irq_type,
+ .irq_get_irqchip_state = smsm_get_irqchip_state,
};
/**
diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c
index b2f049faa3df..9faf48302f4b 100644
--- a/drivers/soc/qcom/socinfo.c
+++ b/drivers/soc/qcom/socinfo.c
@@ -417,8 +417,8 @@ QCOM_OPEN(chip_id, qcom_show_chip_id);
static int show_image_##type(struct seq_file *seq, void *p) \
{ \
struct smem_image_version *image_version = seq->private; \
- seq_puts(seq, image_version->type); \
- seq_putc(seq, '\n'); \
+ if (image_version->type[0] != '\0') \
+ seq_printf(seq, "%s\n", image_version->type); \
return 0; \
} \
static int open_image_##type(struct inode *inode, struct file *file) \