Merge tag 'armsoc-drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull ARM SoC driver updates from Arnd Bergmann: "The most noteworthy SoC driver changes this time include: - The TEE subsystem gains an in-kernel interface to access the TEE from device drivers. - The reset controller subsystem gains a driver for the Qualcomm Snapdragon 845 Power Domain Controller. - The Xilinx Zynq platform now has a firmware interface for its platform management unit. This contains a firmware "ioctl" interface that was a little controversial at first, but the version we merged solved that by not exposing arbitrary firmware calls to user space. - The Amlogic Meson platform gains a "canvas" driver that is used for video processing and shared between different high-level drivers. The rest is more of the usual, mostly related to SoC specific power management support and core drivers in drivers/soc: - Several Renesas SoCs (RZ/G1N, RZ/G2M, R-Car V3M, RZ/A2M) gain new features related to power and reset control. - The Mediatek mt8183 and mt6765 SoC platforms gain support for their respective power management chips. - A new driver for NXP i.MX8, which need a firmware interface for power management. - The SCPI firmware interface now contains support estimating power usage of performance states - The NVIDIA Tegra "pmc" driver gains a few new features, in particular a pinctrl interface for configuring the pads. - Lots of small changes for Qualcomm, in particular the "smem" device driver. - Some cleanups for the TI OMAP series related to their sysc controller. Additional cleanups and bugfixes in SoC specific drivers include the Meson, Keystone, NXP, AT91, Sunxi, Actions, and Tegra platforms" * tag 'armsoc-drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (129 commits) firmware: tegra: bpmp: Implement suspend/resume support drivers: clk: Add ZynqMP clock driver dt-bindings: clock: Add bindings for ZynqMP clock driver firmware: xilinx: Add zynqmp IOCTL API for device control Documentation: xilinx: Add documentation for eemi APIs MAINTAINERS: imx: include drivers/firmware/imx path firmware: imx: add misc svc support firmware: imx: add SCU firmware driver support reset: Fix potential use-after-free in __of_reset_control_get() dt-bindings: arm: fsl: add scu binding doc soc: fsl: qbman: add interrupt coalesce changing APIs soc: fsl: bman_portals: defer probe after bman's probe soc: fsl: qbman: Use last response to determine valid bit soc: fsl: qbman: Add 64 bit DMA addressing requirement to QBMan soc: fsl: qbman: replace CPU 0 with any online CPU in hotplug handlers soc: fsl: qbman: Check if CPU is offline when initializing portals reset: qcom: PDC Global (Power Domain Controller) reset controller dt-bindings: reset: Add PDC Global binding for SDM845 SoCs reset: Grammar s/more then once/more than once/ bus: ti-sysc: Just use SET_NOIRQ_SYSTEM_SLEEP_PM_OPS ...
This commit is contained in:
@@ -33,7 +33,7 @@ config QCOM_GLINK_SSR
|
||||
|
||||
config QCOM_GSBI
|
||||
tristate "QCOM General Serial Bus Interface"
|
||||
depends on ARCH_QCOM
|
||||
depends on ARCH_QCOM || COMPILE_TEST
|
||||
select MFD_SYSCON
|
||||
help
|
||||
Say y here to enable GSBI support. The GSBI provides control
|
||||
@@ -42,7 +42,7 @@ config QCOM_GSBI
|
||||
|
||||
config QCOM_LLCC
|
||||
tristate "Qualcomm Technologies, Inc. LLCC driver"
|
||||
depends on ARCH_QCOM
|
||||
depends on ARCH_QCOM || COMPILE_TEST
|
||||
help
|
||||
Qualcomm Technologies, Inc. platform specific
|
||||
Last Level Cache Controller(LLCC) driver. This provides interfaces
|
||||
@@ -73,7 +73,8 @@ config QCOM_PM
|
||||
|
||||
config QCOM_QMI_HELPERS
|
||||
tristate
|
||||
depends on (ARCH_QCOM || COMPILE_TEST) && NET
|
||||
depends on ARCH_QCOM || COMPILE_TEST
|
||||
depends on NET
|
||||
help
|
||||
Helper library for handling QMI encoded messages. QMI encoded
|
||||
messages are used in communication between the majority of QRTR
|
||||
@@ -94,7 +95,7 @@ config QCOM_RMTFS_MEM
|
||||
|
||||
config QCOM_RPMH
|
||||
bool "Qualcomm RPM-Hardened (RPMH) Communication"
|
||||
depends on ARCH_QCOM && ARM64 && OF || COMPILE_TEST
|
||||
depends on ARCH_QCOM && ARM64 || COMPILE_TEST
|
||||
help
|
||||
Support for communication with the hardened-RPM blocks in
|
||||
Qualcomm Technologies Inc (QTI) SoCs. RPMH communication uses an
|
||||
@@ -104,7 +105,7 @@ config QCOM_RPMH
|
||||
|
||||
config QCOM_SMEM
|
||||
tristate "Qualcomm Shared Memory Manager (SMEM)"
|
||||
depends on ARCH_QCOM
|
||||
depends on ARCH_QCOM || COMPILE_TEST
|
||||
depends on HWSPINLOCK
|
||||
help
|
||||
Say y here to enable support for the Qualcomm Shared Memory Manager.
|
||||
@@ -113,8 +114,8 @@ config QCOM_SMEM
|
||||
|
||||
config QCOM_SMD_RPM
|
||||
tristate "Qualcomm Resource Power Manager (RPM) over SMD"
|
||||
depends on ARCH_QCOM
|
||||
depends on RPMSG && OF
|
||||
depends on ARCH_QCOM || COMPILE_TEST
|
||||
depends on RPMSG
|
||||
help
|
||||
If you say yes to this option, support will be included for the
|
||||
Resource Power Manager system found in the Qualcomm 8974 based
|
||||
@@ -134,6 +135,7 @@ config QCOM_SMP2P
|
||||
depends on MAILBOX
|
||||
depends on QCOM_SMEM
|
||||
select QCOM_SMEM_STATE
|
||||
select IRQ_DOMAIN
|
||||
help
|
||||
Say yes here to support the Qualcomm Shared Memory Point to Point
|
||||
protocol.
|
||||
@@ -142,13 +144,14 @@ config QCOM_SMSM
|
||||
tristate "Qualcomm Shared Memory State Machine"
|
||||
depends on QCOM_SMEM
|
||||
select QCOM_SMEM_STATE
|
||||
select IRQ_DOMAIN
|
||||
help
|
||||
Say yes here to support the Qualcomm Shared Memory State Machine.
|
||||
The state machine is represented by bits in shared memory.
|
||||
|
||||
config QCOM_WCNSS_CTRL
|
||||
tristate "Qualcomm WCNSS control driver"
|
||||
depends on ARCH_QCOM
|
||||
depends on ARCH_QCOM || COMPILE_TEST
|
||||
depends on RPMSG
|
||||
help
|
||||
Client driver for the WCNSS_CTRL SMD channel, used to download nv
|
||||
@@ -156,7 +159,7 @@ config QCOM_WCNSS_CTRL
|
||||
|
||||
config QCOM_APR
|
||||
tristate "Qualcomm APR Bus (Asynchronous Packet Router)"
|
||||
depends on ARCH_QCOM
|
||||
depends on ARCH_QCOM || COMPILE_TEST
|
||||
depends on RPMSG
|
||||
help
|
||||
Enable APR IPC protocol support between
|
||||
|
@@ -87,7 +87,7 @@ static int apr_callback(struct rpmsg_device *rpdev, void *buf,
|
||||
}
|
||||
|
||||
if (hdr->pkt_size < APR_HDR_SIZE || hdr->pkt_size != len) {
|
||||
dev_err(apr->dev, "APR: Wrong paket size\n");
|
||||
dev_err(apr->dev, "APR: Wrong packet size\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -221,7 +221,7 @@ static int apr_add_device(struct device *dev, struct device_node *np,
|
||||
if (np)
|
||||
snprintf(adev->name, APR_NAME_SIZE, "%pOFn", np);
|
||||
else
|
||||
strncpy(adev->name, id->name, APR_NAME_SIZE);
|
||||
strscpy(adev->name, id->name, APR_NAME_SIZE);
|
||||
|
||||
dev_set_name(&adev->dev, "aprsvc:%s:%x:%x", adev->name,
|
||||
id->domain_id, id->svc_id);
|
||||
|
@@ -13,6 +13,7 @@
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/sizes.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/soc/qcom/llcc-qcom.h>
|
||||
|
||||
@@ -106,22 +107,24 @@ static int llcc_update_act_ctrl(u32 sid,
|
||||
u32 slice_status;
|
||||
int ret;
|
||||
|
||||
act_ctrl_reg = drv_data->bcast_off + LLCC_TRP_ACT_CTRLn(sid);
|
||||
status_reg = drv_data->bcast_off + LLCC_TRP_STATUSn(sid);
|
||||
act_ctrl_reg = LLCC_TRP_ACT_CTRLn(sid);
|
||||
status_reg = LLCC_TRP_STATUSn(sid);
|
||||
|
||||
/* Set the ACTIVE trigger */
|
||||
act_ctrl_reg_val |= ACT_CTRL_ACT_TRIG;
|
||||
ret = regmap_write(drv_data->regmap, act_ctrl_reg, act_ctrl_reg_val);
|
||||
ret = regmap_write(drv_data->bcast_regmap, act_ctrl_reg,
|
||||
act_ctrl_reg_val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Clear the ACTIVE trigger */
|
||||
act_ctrl_reg_val &= ~ACT_CTRL_ACT_TRIG;
|
||||
ret = regmap_write(drv_data->regmap, act_ctrl_reg, act_ctrl_reg_val);
|
||||
ret = regmap_write(drv_data->bcast_regmap, act_ctrl_reg,
|
||||
act_ctrl_reg_val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = regmap_read_poll_timeout(drv_data->regmap, status_reg,
|
||||
ret = regmap_read_poll_timeout(drv_data->bcast_regmap, status_reg,
|
||||
slice_status, !(slice_status & status),
|
||||
0, LLCC_STATUS_READ_DELAY);
|
||||
return ret;
|
||||
@@ -223,19 +226,16 @@ static int qcom_llcc_cfg_program(struct platform_device *pdev)
|
||||
u32 attr0_val;
|
||||
u32 max_cap_cacheline;
|
||||
u32 sz;
|
||||
int ret;
|
||||
int ret = 0;
|
||||
const struct llcc_slice_config *llcc_table;
|
||||
struct llcc_slice_desc desc;
|
||||
u32 bcast_off = drv_data->bcast_off;
|
||||
|
||||
sz = drv_data->cfg_size;
|
||||
llcc_table = drv_data->cfg;
|
||||
|
||||
for (i = 0; i < sz; i++) {
|
||||
attr1_cfg = bcast_off +
|
||||
LLCC_TRP_ATTR1_CFGn(llcc_table[i].slice_id);
|
||||
attr0_cfg = bcast_off +
|
||||
LLCC_TRP_ATTR0_CFGn(llcc_table[i].slice_id);
|
||||
attr1_cfg = LLCC_TRP_ATTR1_CFGn(llcc_table[i].slice_id);
|
||||
attr0_cfg = LLCC_TRP_ATTR0_CFGn(llcc_table[i].slice_id);
|
||||
|
||||
attr1_val = llcc_table[i].cache_mode;
|
||||
attr1_val |= llcc_table[i].probe_target_ways <<
|
||||
@@ -260,10 +260,12 @@ static int qcom_llcc_cfg_program(struct platform_device *pdev)
|
||||
attr0_val = llcc_table[i].res_ways & ATTR0_RES_WAYS_MASK;
|
||||
attr0_val |= llcc_table[i].bonus_ways << ATTR0_BONUS_WAYS_SHIFT;
|
||||
|
||||
ret = regmap_write(drv_data->regmap, attr1_cfg, attr1_val);
|
||||
ret = regmap_write(drv_data->bcast_regmap, attr1_cfg,
|
||||
attr1_val);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = regmap_write(drv_data->regmap, attr0_cfg, attr0_val);
|
||||
ret = regmap_write(drv_data->bcast_regmap, attr0_cfg,
|
||||
attr0_val);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (llcc_table[i].activate_on_init) {
|
||||
@@ -279,24 +281,37 @@ int qcom_llcc_probe(struct platform_device *pdev,
|
||||
{
|
||||
u32 num_banks;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct resource *res;
|
||||
void __iomem *base;
|
||||
struct resource *llcc_banks_res, *llcc_bcast_res;
|
||||
void __iomem *llcc_banks_base, *llcc_bcast_base;
|
||||
int ret, i;
|
||||
struct platform_device *llcc_edac;
|
||||
|
||||
drv_data = devm_kzalloc(dev, sizeof(*drv_data), GFP_KERNEL);
|
||||
if (!drv_data)
|
||||
return -ENOMEM;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
base = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(base))
|
||||
return PTR_ERR(base);
|
||||
llcc_banks_res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
|
||||
"llcc_base");
|
||||
llcc_banks_base = devm_ioremap_resource(&pdev->dev, llcc_banks_res);
|
||||
if (IS_ERR(llcc_banks_base))
|
||||
return PTR_ERR(llcc_banks_base);
|
||||
|
||||
drv_data->regmap = devm_regmap_init_mmio(dev, base,
|
||||
&llcc_regmap_config);
|
||||
drv_data->regmap = devm_regmap_init_mmio(dev, llcc_banks_base,
|
||||
&llcc_regmap_config);
|
||||
if (IS_ERR(drv_data->regmap))
|
||||
return PTR_ERR(drv_data->regmap);
|
||||
|
||||
llcc_bcast_res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
|
||||
"llcc_broadcast_base");
|
||||
llcc_bcast_base = devm_ioremap_resource(&pdev->dev, llcc_bcast_res);
|
||||
if (IS_ERR(llcc_bcast_base))
|
||||
return PTR_ERR(llcc_bcast_base);
|
||||
|
||||
drv_data->bcast_regmap = devm_regmap_init_mmio(dev, llcc_bcast_base,
|
||||
&llcc_regmap_config);
|
||||
if (IS_ERR(drv_data->bcast_regmap))
|
||||
return PTR_ERR(drv_data->bcast_regmap);
|
||||
|
||||
ret = regmap_read(drv_data->regmap, LLCC_COMMON_STATUS0,
|
||||
&num_banks);
|
||||
if (ret)
|
||||
@@ -318,8 +333,6 @@ int qcom_llcc_probe(struct platform_device *pdev,
|
||||
for (i = 0; i < num_banks; i++)
|
||||
drv_data->offsets[i] = i * BANK_OFFSET_STRIDE;
|
||||
|
||||
drv_data->bcast_off = num_banks * BANK_OFFSET_STRIDE;
|
||||
|
||||
drv_data->bitmap = devm_kcalloc(dev,
|
||||
BITS_TO_LONGS(drv_data->max_slices), sizeof(unsigned long),
|
||||
GFP_KERNEL);
|
||||
@@ -331,7 +344,20 @@ int qcom_llcc_probe(struct platform_device *pdev,
|
||||
mutex_init(&drv_data->lock);
|
||||
platform_set_drvdata(pdev, drv_data);
|
||||
|
||||
return qcom_llcc_cfg_program(pdev);
|
||||
ret = qcom_llcc_cfg_program(pdev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
drv_data->ecc_irq = platform_get_irq(pdev, 0);
|
||||
if (drv_data->ecc_irq >= 0) {
|
||||
llcc_edac = platform_device_register_data(&pdev->dev,
|
||||
"qcom_llcc_edac", -1, drv_data,
|
||||
sizeof(*drv_data));
|
||||
if (IS_ERR(llcc_edac))
|
||||
dev_err(dev, "Failed to register llcc edac driver\n");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(qcom_llcc_probe);
|
||||
|
||||
|
@@ -212,6 +212,11 @@ static int qcom_rmtfs_mem_probe(struct platform_device *pdev)
|
||||
dev_err(&pdev->dev, "failed to parse qcom,vmid\n");
|
||||
goto remove_cdev;
|
||||
} else if (!ret) {
|
||||
if (!qcom_scm_is_available()) {
|
||||
ret = -EPROBE_DEFER;
|
||||
goto remove_cdev;
|
||||
}
|
||||
|
||||
perms[0].vmid = QCOM_SCM_VMID_HLOS;
|
||||
perms[0].perm = QCOM_SCM_PERM_RW;
|
||||
perms[1].vmid = vmid;
|
||||
|
@@ -121,6 +121,7 @@ static int tcs_invalidate(struct rsc_drv *drv, int type)
|
||||
return -EAGAIN;
|
||||
}
|
||||
write_tcs_reg_sync(drv, RSC_DRV_CMD_ENABLE, m, 0);
|
||||
write_tcs_reg_sync(drv, RSC_DRV_CMD_WAIT_FOR_CMPL, m, 0);
|
||||
}
|
||||
bitmap_zero(tcs->slots, MAX_TCS_SLOTS);
|
||||
spin_unlock(&tcs->lock);
|
||||
@@ -239,6 +240,7 @@ static irqreturn_t tcs_tx_done(int irq, void *p)
|
||||
skip:
|
||||
/* Reclaim the TCS */
|
||||
write_tcs_reg(drv, RSC_DRV_CMD_ENABLE, i, 0);
|
||||
write_tcs_reg(drv, RSC_DRV_CMD_WAIT_FOR_CMPL, i, 0);
|
||||
write_tcs_reg(drv, RSC_DRV_IRQ_CLEAR, 0, BIT(i));
|
||||
spin_lock(&drv->lock);
|
||||
clear_bit(i, drv->tcs_in_use);
|
||||
|
@@ -18,6 +18,7 @@
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/sizes.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/soc/qcom/smem.h>
|
||||
|
||||
@@ -277,7 +278,7 @@ struct qcom_smem {
|
||||
u32 item_count;
|
||||
|
||||
unsigned num_regions;
|
||||
struct smem_region regions[0];
|
||||
struct smem_region regions[];
|
||||
};
|
||||
|
||||
static void *
|
||||
@@ -489,7 +490,7 @@ static void *qcom_smem_get_global(struct qcom_smem *smem,
|
||||
size_t *size)
|
||||
{
|
||||
struct smem_header *header;
|
||||
struct smem_region *area;
|
||||
struct smem_region *region;
|
||||
struct smem_global_entry *entry;
|
||||
u32 aux_base;
|
||||
unsigned i;
|
||||
@@ -502,12 +503,12 @@ static void *qcom_smem_get_global(struct qcom_smem *smem,
|
||||
aux_base = le32_to_cpu(entry->aux_base) & AUX_BASE_MASK;
|
||||
|
||||
for (i = 0; i < smem->num_regions; i++) {
|
||||
area = &smem->regions[i];
|
||||
region = &smem->regions[i];
|
||||
|
||||
if (area->aux_base == aux_base || !aux_base) {
|
||||
if (region->aux_base == aux_base || !aux_base) {
|
||||
if (size != NULL)
|
||||
*size = le32_to_cpu(entry->size);
|
||||
return area->virt_base + le32_to_cpu(entry->offset);
|
||||
return region->virt_base + le32_to_cpu(entry->offset);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -722,12 +723,59 @@ static u32 qcom_smem_get_item_count(struct qcom_smem *smem)
|
||||
return le16_to_cpu(info->num_items);
|
||||
}
|
||||
|
||||
/*
|
||||
* Validate the partition header for a partition whose partition
|
||||
* table entry is supplied. Returns a pointer to its header if
|
||||
* valid, or a null pointer otherwise.
|
||||
*/
|
||||
static struct smem_partition_header *
|
||||
qcom_smem_partition_header(struct qcom_smem *smem,
|
||||
struct smem_ptable_entry *entry, u16 host0, u16 host1)
|
||||
{
|
||||
struct smem_partition_header *header;
|
||||
u32 size;
|
||||
|
||||
header = smem->regions[0].virt_base + le32_to_cpu(entry->offset);
|
||||
|
||||
if (memcmp(header->magic, SMEM_PART_MAGIC, sizeof(header->magic))) {
|
||||
dev_err(smem->dev, "bad partition magic %02x %02x %02x %02x\n",
|
||||
header->magic[0], header->magic[1],
|
||||
header->magic[2], header->magic[3]);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (host0 != le16_to_cpu(header->host0)) {
|
||||
dev_err(smem->dev, "bad host0 (%hu != %hu)\n",
|
||||
host0, le16_to_cpu(header->host0));
|
||||
return NULL;
|
||||
}
|
||||
if (host1 != le16_to_cpu(header->host1)) {
|
||||
dev_err(smem->dev, "bad host1 (%hu != %hu)\n",
|
||||
host1, le16_to_cpu(header->host1));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size = le32_to_cpu(header->size);
|
||||
if (size != le32_to_cpu(entry->size)) {
|
||||
dev_err(smem->dev, "bad partition size (%u != %u)\n",
|
||||
size, le32_to_cpu(entry->size));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (le32_to_cpu(header->offset_free_uncached) > size) {
|
||||
dev_err(smem->dev, "bad partition free uncached (%u > %u)\n",
|
||||
le32_to_cpu(header->offset_free_uncached), size);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return header;
|
||||
}
|
||||
|
||||
static int qcom_smem_set_global_partition(struct qcom_smem *smem)
|
||||
{
|
||||
struct smem_partition_header *header;
|
||||
struct smem_ptable_entry *entry;
|
||||
struct smem_ptable *ptable;
|
||||
u32 host0, host1, size;
|
||||
bool found = false;
|
||||
int i;
|
||||
|
||||
@@ -742,10 +790,15 @@ static int qcom_smem_set_global_partition(struct qcom_smem *smem)
|
||||
|
||||
for (i = 0; i < le32_to_cpu(ptable->num_entries); i++) {
|
||||
entry = &ptable->entry[i];
|
||||
host0 = le16_to_cpu(entry->host0);
|
||||
host1 = le16_to_cpu(entry->host1);
|
||||
if (!le32_to_cpu(entry->offset))
|
||||
continue;
|
||||
if (!le32_to_cpu(entry->size))
|
||||
continue;
|
||||
|
||||
if (host0 == SMEM_GLOBAL_HOST && host0 == host1) {
|
||||
if (le16_to_cpu(entry->host0) != SMEM_GLOBAL_HOST)
|
||||
continue;
|
||||
|
||||
if (le16_to_cpu(entry->host1) == SMEM_GLOBAL_HOST) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
@@ -756,36 +809,10 @@ static int qcom_smem_set_global_partition(struct qcom_smem *smem)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!le32_to_cpu(entry->offset) || !le32_to_cpu(entry->size)) {
|
||||
dev_err(smem->dev, "Invalid entry for global partition\n");
|
||||
header = qcom_smem_partition_header(smem, entry,
|
||||
SMEM_GLOBAL_HOST, SMEM_GLOBAL_HOST);
|
||||
if (!header)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
header = smem->regions[0].virt_base + le32_to_cpu(entry->offset);
|
||||
host0 = le16_to_cpu(header->host0);
|
||||
host1 = le16_to_cpu(header->host1);
|
||||
|
||||
if (memcmp(header->magic, SMEM_PART_MAGIC, sizeof(header->magic))) {
|
||||
dev_err(smem->dev, "Global partition has invalid magic\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (host0 != SMEM_GLOBAL_HOST && host1 != SMEM_GLOBAL_HOST) {
|
||||
dev_err(smem->dev, "Global partition hosts are invalid\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (le32_to_cpu(header->size) != le32_to_cpu(entry->size)) {
|
||||
dev_err(smem->dev, "Global partition has invalid size\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
size = le32_to_cpu(header->offset_free_uncached);
|
||||
if (size > le32_to_cpu(header->size)) {
|
||||
dev_err(smem->dev,
|
||||
"Global partition has invalid free pointer\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
smem->global_partition = header;
|
||||
smem->global_cacheline = le32_to_cpu(entry->cacheline);
|
||||
@@ -793,14 +820,14 @@ static int qcom_smem_set_global_partition(struct qcom_smem *smem)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qcom_smem_enumerate_partitions(struct qcom_smem *smem,
|
||||
unsigned int local_host)
|
||||
static int
|
||||
qcom_smem_enumerate_partitions(struct qcom_smem *smem, u16 local_host)
|
||||
{
|
||||
struct smem_partition_header *header;
|
||||
struct smem_ptable_entry *entry;
|
||||
struct smem_ptable *ptable;
|
||||
unsigned int remote_host;
|
||||
u32 host0, host1;
|
||||
u16 host0, host1;
|
||||
int i;
|
||||
|
||||
ptable = qcom_smem_get_ptable(smem);
|
||||
@@ -809,71 +836,33 @@ static int qcom_smem_enumerate_partitions(struct qcom_smem *smem,
|
||||
|
||||
for (i = 0; i < le32_to_cpu(ptable->num_entries); i++) {
|
||||
entry = &ptable->entry[i];
|
||||
host0 = le16_to_cpu(entry->host0);
|
||||
host1 = le16_to_cpu(entry->host1);
|
||||
|
||||
if (host0 != local_host && host1 != local_host)
|
||||
continue;
|
||||
|
||||
if (!le32_to_cpu(entry->offset))
|
||||
continue;
|
||||
|
||||
if (!le32_to_cpu(entry->size))
|
||||
continue;
|
||||
|
||||
host0 = le16_to_cpu(entry->host0);
|
||||
host1 = le16_to_cpu(entry->host1);
|
||||
if (host0 == local_host)
|
||||
remote_host = host1;
|
||||
else
|
||||
else if (host1 == local_host)
|
||||
remote_host = host0;
|
||||
else
|
||||
continue;
|
||||
|
||||
if (remote_host >= SMEM_HOST_COUNT) {
|
||||
dev_err(smem->dev,
|
||||
"Invalid remote host %d\n",
|
||||
remote_host);
|
||||
dev_err(smem->dev, "bad host %hu\n", remote_host);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (smem->partitions[remote_host]) {
|
||||
dev_err(smem->dev,
|
||||
"Already found a partition for host %d\n",
|
||||
remote_host);
|
||||
dev_err(smem->dev, "duplicate host %hu\n", remote_host);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
header = smem->regions[0].virt_base + le32_to_cpu(entry->offset);
|
||||
host0 = le16_to_cpu(header->host0);
|
||||
host1 = le16_to_cpu(header->host1);
|
||||
|
||||
if (memcmp(header->magic, SMEM_PART_MAGIC,
|
||||
sizeof(header->magic))) {
|
||||
dev_err(smem->dev,
|
||||
"Partition %d has invalid magic\n", i);
|
||||
header = qcom_smem_partition_header(smem, entry, host0, host1);
|
||||
if (!header)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (host0 != local_host && host1 != local_host) {
|
||||
dev_err(smem->dev,
|
||||
"Partition %d hosts are invalid\n", i);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (host0 != remote_host && host1 != remote_host) {
|
||||
dev_err(smem->dev,
|
||||
"Partition %d hosts are invalid\n", i);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (le32_to_cpu(header->size) != le32_to_cpu(entry->size)) {
|
||||
dev_err(smem->dev,
|
||||
"Partition %d has invalid size\n", i);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (le32_to_cpu(header->offset_free_uncached) > le32_to_cpu(header->size)) {
|
||||
dev_err(smem->dev,
|
||||
"Partition %d has invalid free pointer\n", i);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
smem->partitions[remote_host] = header;
|
||||
smem->cacheline[remote_host] = le32_to_cpu(entry->cacheline);
|
||||
@@ -887,6 +876,7 @@ static int qcom_smem_map_memory(struct qcom_smem *smem, struct device *dev,
|
||||
{
|
||||
struct device_node *np;
|
||||
struct resource r;
|
||||
resource_size_t size;
|
||||
int ret;
|
||||
|
||||
np = of_parse_phandle(dev->of_node, name, 0);
|
||||
@@ -899,12 +889,13 @@ static int qcom_smem_map_memory(struct qcom_smem *smem, struct device *dev,
|
||||
of_node_put(np);
|
||||
if (ret)
|
||||
return ret;
|
||||
size = resource_size(&r);
|
||||
|
||||
smem->regions[i].aux_base = (u32)r.start;
|
||||
smem->regions[i].size = resource_size(&r);
|
||||
smem->regions[i].virt_base = devm_ioremap_wc(dev, r.start, resource_size(&r));
|
||||
smem->regions[i].virt_base = devm_ioremap_wc(dev, r.start, size);
|
||||
if (!smem->regions[i].virt_base)
|
||||
return -ENOMEM;
|
||||
smem->regions[i].aux_base = (u32)r.start;
|
||||
smem->regions[i].size = size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -962,6 +953,7 @@ static int qcom_smem_probe(struct platform_device *pdev)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
BUILD_BUG_ON(SMEM_HOST_APPS >= SMEM_HOST_COUNT);
|
||||
ret = qcom_smem_enumerate_partitions(smem, SMEM_HOST_APPS);
|
||||
if (ret < 0 && ret != -ENOENT)
|
||||
return ret;
|
||||
|
@@ -219,6 +219,9 @@ static int __init qcom_cpuidle_init(struct device_node *cpu_node, int cpu)
|
||||
cpumask_t mask;
|
||||
bool use_scm_power_down = false;
|
||||
|
||||
if (!qcom_scm_is_available())
|
||||
return -EPROBE_DEFER;
|
||||
|
||||
for (i = 0; ; i++) {
|
||||
state_node = of_parse_phandle(cpu_node, "cpu-idle-states", i);
|
||||
if (!state_node)
|
||||
|
@@ -281,7 +281,7 @@ struct rpmsg_endpoint *qcom_wcnss_open_channel(void *wcnss, const char *name, rp
|
||||
struct rpmsg_channel_info chinfo;
|
||||
struct wcnss_ctrl *_wcnss = wcnss;
|
||||
|
||||
strncpy(chinfo.name, name, sizeof(chinfo.name));
|
||||
strscpy(chinfo.name, name, sizeof(chinfo.name));
|
||||
chinfo.src = RPMSG_ADDR_ANY;
|
||||
chinfo.dst = RPMSG_ADDR_ANY;
|
||||
|
||||
|
Reference in New Issue
Block a user