Commit abfbb292 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'rproc-v5.8' of git://git.kernel.org/pub/scm/linux/kernel/git/andersson/remoteproc

Pull remoteproc updates from Bjorn Andersson:
 "This introduces device managed versions of functions used to register
  remoteproc devices, add support for remoteproc driver specific
  resource control, enables remoteproc drivers to specify ELF class and
  machine for coredumps. It integrates pm_runtime in the core for
  keeping resources active while the remote is booted and holds a wake
  source while recoverying a remote processor after a firmware crash.

  It refactors the remoteproc device's allocation path to simplify the
  logic, fix a few cleanup bugs and to not clone const strings onto the
  heap. Debugfs code is simplifies using the DEFINE_SHOW_ATTRIBUTE and a
  zero-length array is replaced with flexible-array.

  A new remoteproc driver for the JZ47xx VPU is introduced, the Qualcomm
  SM8250 gains support for audio, compute and sensor remoteprocs and the
  Qualcomm SC7180 modem support is cleaned up and improved.

  The Qualcomm glink subsystem-restart driver is merged into the main
  glink driver, the Qualcomm sysmon driver is extended to properly
  notify remote processors about all other remote processors' state
  transitions"

* tag 'rproc-v5.8' of git://git.kernel.org/pub/scm/linux/kernel/git/andersson/remoteproc: (43 commits)
  remoteproc: Fix an error code in devm_rproc_alloc()
  MAINTAINERS: Add myself as reviewer for Ingenic rproc driver
  remoteproc: ingenic: Added remoteproc driver
  remoteproc: Add support for runtime PM
  dt-bindings: Document JZ47xx VPU auxiliary processor
  remoteproc: wcss: Fix arguments passed to qcom_add_glink_subdev()
  remoteproc: Fix and restore the parenting hierarchy for vdev
  remoteproc: Fall back to using parent memory pool if no dedicated available
  remoteproc: Replace zero-length array with flexible-array
  remoteproc: wcss: add support for rpmsg communication
  remoteproc: core: Prevent system suspend during remoteproc recovery
  remoteproc: qcom_q6v5_mss: Remove unused q6v5_da_to_va function
  remoteproc: qcom_q6v5_mss: map/unmap mpss segments before/after use
  remoteproc: qcom_q6v5_mss: Drop accesses to MPSS PERPH register space
  dt-bindings: remoteproc: qcom: Replace halt-nav with spare-regs
  remoteproc: qcom: pas: Add SM8250 PAS remoteprocs
  dt-bindings: remoteproc: qcom: pas: Add SM8250 remoteprocs
  remoteproc: qcom_q6v5_mss: Extract mba/mpss from memory-region
  dt-bindings: remoteproc: qcom: Use memory-region to reference memory
  remoteproc: qcom: pas: Add SC7180 Modem support
  ...
parents d26a42a9 7dcef398
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: "http://devicetree.org/schemas/remoteproc/ingenic,vpu.yaml#"
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
title: Ingenic Video Processing Unit bindings
description:
Inside the Video Processing Unit (VPU) of the recent JZ47xx SoCs from
Ingenic is a second Xburst MIPS CPU very similar to the main core.
This document describes the devicetree bindings for this auxiliary
processor.
maintainers:
- Paul Cercueil <paul@crapouillou.net>
properties:
compatible:
const: ingenic,jz4770-vpu-rproc
reg:
items:
- description: aux registers
- description: tcsm0 registers
- description: tcsm1 registers
- description: sram registers
reg-names:
items:
- const: aux
- const: tcsm0
- const: tcsm1
- const: sram
clocks:
items:
- description: aux clock
- description: vpu clock
clock-names:
items:
- const: aux
- const: vpu
interrupts:
description: VPU hardware interrupt
required:
- compatible
- reg
- reg-names
- clocks
- clock-names
- interrupts
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/jz4770-cgu.h>
vpu: video-decoder@132a0000 {
compatible = "ingenic,jz4770-vpu-rproc";
reg = <0x132a0000 0x20>, /* AUX */
<0x132b0000 0x4000>, /* TCSM0 */
<0x132c0000 0xc000>, /* TCSM1 */
<0x132f0000 0x7000>; /* SRAM */
reg-names = "aux", "tcsm0", "tcsm1", "sram";
clocks = <&cgu JZ4770_CLK_AUX>, <&cgu JZ4770_CLK_VPU>;
clock-names = "aux", "vpu";
interrupt-parent = <&cpuintc>;
interrupts = <3>;
};
...@@ -15,12 +15,16 @@ on the Qualcomm ADSP Hexagon core. ...@@ -15,12 +15,16 @@ on the Qualcomm ADSP Hexagon core.
"qcom,qcs404-adsp-pas" "qcom,qcs404-adsp-pas"
"qcom,qcs404-cdsp-pas" "qcom,qcs404-cdsp-pas"
"qcom,qcs404-wcss-pas" "qcom,qcs404-wcss-pas"
"qcom,sc7180-mpss-pas"
"qcom,sdm845-adsp-pas" "qcom,sdm845-adsp-pas"
"qcom,sdm845-cdsp-pas" "qcom,sdm845-cdsp-pas"
"qcom,sm8150-adsp-pas" "qcom,sm8150-adsp-pas"
"qcom,sm8150-cdsp-pas" "qcom,sm8150-cdsp-pas"
"qcom,sm8150-mpss-pas" "qcom,sm8150-mpss-pas"
"qcom,sm8150-slpi-pas" "qcom,sm8150-slpi-pas"
"qcom,sm8250-adsp-pas"
"qcom,sm8250-cdsp-pas"
"qcom,sm8250-slpi-pas"
- interrupts-extended: - interrupts-extended:
Usage: required Usage: required
...@@ -44,8 +48,12 @@ on the Qualcomm ADSP Hexagon core. ...@@ -44,8 +48,12 @@ on the Qualcomm ADSP Hexagon core.
qcom,sm8150-adsp-pas: qcom,sm8150-adsp-pas:
qcom,sm8150-cdsp-pas: qcom,sm8150-cdsp-pas:
qcom,sm8150-slpi-pas: qcom,sm8150-slpi-pas:
qcom,sm8250-adsp-pas:
qcom,sm8250-cdsp-pas:
qcom,sm8250-slpi-pas:
must be "wdog", "fatal", "ready", "handover", "stop-ack" must be "wdog", "fatal", "ready", "handover", "stop-ack"
qcom,qcs404-wcss-pas: qcom,qcs404-wcss-pas:
qcom,sc7180-mpss-pas:
qcom,sm8150-mpss-pas: qcom,sm8150-mpss-pas:
must be "wdog", "fatal", "ready", "handover", "stop-ack", must be "wdog", "fatal", "ready", "handover", "stop-ack",
"shutdown-ack" "shutdown-ack"
...@@ -105,10 +113,14 @@ on the Qualcomm ADSP Hexagon core. ...@@ -105,10 +113,14 @@ on the Qualcomm ADSP Hexagon core.
qcom,sdm845-cdsp-pas: qcom,sdm845-cdsp-pas:
qcom,sm8150-adsp-pas: qcom,sm8150-adsp-pas:
qcom,sm8150-cdsp-pas: qcom,sm8150-cdsp-pas:
qcom,sm8250-cdsp-pas:
must be "cx", "load_state" must be "cx", "load_state"
qcom,sc7180-mpss-pas:
qcom,sm8150-mpss-pas: qcom,sm8150-mpss-pas:
must be "cx", "load_state", "mss" must be "cx", "load_state", "mss"
qcom,sm8250-adsp-pas:
qcom,sm8150-slpi-pas: qcom,sm8150-slpi-pas:
qcom,sm8250-slpi-pas:
must be "lcx", "lmx", "load_state" must be "lcx", "lmx", "load_state"
- memory-region: - memory-region:
......
...@@ -79,7 +79,7 @@ on the Qualcomm Hexagon core. ...@@ -79,7 +79,7 @@ on the Qualcomm Hexagon core.
"snoc_axi", "mnoc_axi", "qdss" "snoc_axi", "mnoc_axi", "qdss"
qcom,sc7180-mss-pil: qcom,sc7180-mss-pil:
must be "iface", "bus", "xo", "snoc_axi", "mnoc_axi", must be "iface", "bus", "xo", "snoc_axi", "mnoc_axi",
"mss_crypto", "mss_nav", "nav" "nav"
qcom,sdm845-mss-pil: qcom,sdm845-mss-pil:
must be "iface", "bus", "mem", "xo", "gpll0_mss", must be "iface", "bus", "mem", "xo", "gpll0_mss",
"snoc_axi", "mnoc_axi", "prng" "snoc_axi", "mnoc_axi", "prng"
...@@ -102,6 +102,14 @@ on the Qualcomm Hexagon core. ...@@ -102,6 +102,14 @@ on the Qualcomm Hexagon core.
must be "mss_restart", "pdc_reset" for the modem must be "mss_restart", "pdc_reset" for the modem
sub-system on SC7180, SDM845 SoCs sub-system on SC7180, SDM845 SoCs
For devices where the mba and mpss sub-nodes are not specified, mba/mpss region
should be referenced as follows:
- memory-region:
Usage: required
Value type: <phandle>
Definition: reference to the reserved-memory for the mba region followed
by the mpss region
For the compatible strings below the following supplies are required: For the compatible strings below the following supplies are required:
"qcom,q6v5-pil" "qcom,q6v5-pil"
"qcom,msm8916-mss-pil", "qcom,msm8916-mss-pil",
...@@ -173,16 +181,12 @@ For the compatible string below the following supplies are required: ...@@ -173,16 +181,12 @@ For the compatible string below the following supplies are required:
For the compatible strings below the following phandle references are required: For the compatible strings below the following phandle references are required:
"qcom,sc7180-mss-pil" "qcom,sc7180-mss-pil"
- qcom,halt-nav-regs: - qcom,spare-regs:
Usage: required Usage: required
Value type: <prop-encoded-array> Value type: <prop-encoded-array>
Definition: reference to a list of 2 phandles with one offset each for Definition: a phandle reference to a syscon representing TCSR followed
the modem sub-system running on SC7180 SoC. The first by the offset within syscon for conn_box_spare0 register
phandle reference is to the mss clock node followed by the used by the modem sub-system running on SC7180 SoC.
offset within register space for nav halt register. The
second phandle reference is to a syscon representing TCSR
followed by the offset within syscon for conn_box_spare0
register.
The Hexagon node must contain iommus property as described in ../iommu/iommu.txt The Hexagon node must contain iommus property as described in ../iommu/iommu.txt
on platforms which do not have TrustZone. on platforms which do not have TrustZone.
......
...@@ -8502,6 +8502,7 @@ F: drivers/mtd/nand/raw/ingenic/ ...@@ -8502,6 +8502,7 @@ F: drivers/mtd/nand/raw/ingenic/
F: drivers/pinctrl/pinctrl-ingenic.c F: drivers/pinctrl/pinctrl-ingenic.c
F: drivers/power/supply/ingenic-battery.c F: drivers/power/supply/ingenic-battery.c
F: drivers/pwm/pwm-jz4740.c F: drivers/pwm/pwm-jz4740.c
F: drivers/remoteproc/ingenic_rproc.c
F: drivers/rtc/rtc-jz4740.c F: drivers/rtc/rtc-jz4740.c
F: drivers/tty/serial/8250/8250_ingenic.c F: drivers/tty/serial/8250/8250_ingenic.c
F: drivers/usb/musb/jz4740.c F: drivers/usb/musb/jz4740.c
......
...@@ -23,6 +23,15 @@ config IMX_REMOTEPROC ...@@ -23,6 +23,15 @@ config IMX_REMOTEPROC
It's safe to say N here. It's safe to say N here.
config INGENIC_VPU_RPROC
tristate "Ingenic JZ47xx VPU remoteproc support"
depends on MIPS || COMPILE_TEST
help
Say y or m here to support the VPU in the JZ47xx SoCs from Ingenic.
This can be either built-in or a loadable module.
If unsure say N.
config MTK_SCP config MTK_SCP
tristate "Mediatek SCP support" tristate "Mediatek SCP support"
depends on ARCH_MEDIATEK depends on ARCH_MEDIATEK
......
...@@ -10,6 +10,7 @@ remoteproc-y += remoteproc_sysfs.o ...@@ -10,6 +10,7 @@ remoteproc-y += remoteproc_sysfs.o
remoteproc-y += remoteproc_virtio.o remoteproc-y += remoteproc_virtio.o
remoteproc-y += remoteproc_elf_loader.o remoteproc-y += remoteproc_elf_loader.o
obj-$(CONFIG_IMX_REMOTEPROC) += imx_rproc.o obj-$(CONFIG_IMX_REMOTEPROC) += imx_rproc.o
obj-$(CONFIG_INGENIC_VPU_RPROC) += ingenic_rproc.o
obj-$(CONFIG_MTK_SCP) += mtk_scp.o mtk_scp_ipi.o obj-$(CONFIG_MTK_SCP) += mtk_scp.o mtk_scp_ipi.o
obj-$(CONFIG_OMAP_REMOTEPROC) += omap_remoteproc.o obj-$(CONFIG_OMAP_REMOTEPROC) += omap_remoteproc.o
obj-$(CONFIG_WKUP_M3_RPROC) += wkup_m3_rproc.o obj-$(CONFIG_WKUP_M3_RPROC) += wkup_m3_rproc.o
......
// SPDX-License-Identifier: GPL-2.0+
/*
* Ingenic JZ47xx remoteproc driver
* Copyright 2019, Paul Cercueil <paul@crapouillou.net>
*/
#include <linux/bitops.h>
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/remoteproc.h>
#include "remoteproc_internal.h"
#define REG_AUX_CTRL 0x0
#define REG_AUX_MSG_ACK 0x10
#define REG_AUX_MSG 0x14
#define REG_CORE_MSG_ACK 0x18
#define REG_CORE_MSG 0x1C
#define AUX_CTRL_SLEEP BIT(31)
#define AUX_CTRL_MSG_IRQ_EN BIT(3)
#define AUX_CTRL_NMI_RESETS BIT(2)
#define AUX_CTRL_NMI BIT(1)
#define AUX_CTRL_SW_RESET BIT(0)
struct vpu_mem_map {
const char *name;
unsigned int da;
};
struct vpu_mem_info {
const struct vpu_mem_map *map;
unsigned long len;
void __iomem *base;
};
static const struct vpu_mem_map vpu_mem_map[] = {
{ "tcsm0", 0x132b0000 },
{ "tcsm1", 0xf4000000 },
{ "sram", 0x132f0000 },
};
/**
* struct vpu - Ingenic VPU remoteproc private structure
* @irq: interrupt number
* @clks: pointers to the VPU and AUX clocks
* @aux_base: raw pointer to the AUX interface registers
* @mem_info: array of struct vpu_mem_info, which contain the mapping info of
* each of the external memories
* @dev: private pointer to the device
*/
struct vpu {
int irq;
struct clk_bulk_data clks[2];
void __iomem *aux_base;
struct vpu_mem_info mem_info[ARRAY_SIZE(vpu_mem_map)];
struct device *dev;
};
static int ingenic_rproc_start(struct rproc *rproc)
{
struct vpu *vpu = rproc->priv;
u32 ctrl;
enable_irq(vpu->irq);
/* Reset the AUX and enable message IRQ */
ctrl = AUX_CTRL_NMI_RESETS | AUX_CTRL_NMI | AUX_CTRL_MSG_IRQ_EN;
writel(ctrl, vpu->aux_base + REG_AUX_CTRL);
return 0;
}
static int ingenic_rproc_stop(struct rproc *rproc)
{
struct vpu *vpu = rproc->priv;
disable_irq(vpu->irq);
/* Keep AUX in reset mode */
writel(AUX_CTRL_SW_RESET, vpu->aux_base + REG_AUX_CTRL);
return 0;
}
static void ingenic_rproc_kick(struct rproc *rproc, int vqid)
{
struct vpu *vpu = rproc->priv;
writel(vqid, vpu->aux_base + REG_CORE_MSG);
}
static void *ingenic_rproc_da_to_va(struct rproc *rproc, u64 da, size_t len)
{
struct vpu *vpu = rproc->priv;
void __iomem *va = NULL;
unsigned int i;
for (i = 0; i < ARRAY_SIZE(vpu_mem_map); i++) {
const struct vpu_mem_info *info = &vpu->mem_info[i];
const struct vpu_mem_map *map = info->map;
if (da >= map->da && (da + len) < (map->da + info->len)) {
va = info->base + (da - map->da);
break;
}
}
return (__force void *)va;
}
static struct rproc_ops ingenic_rproc_ops = {
.start = ingenic_rproc_start,
.stop = ingenic_rproc_stop,
.kick = ingenic_rproc_kick,
.da_to_va = ingenic_rproc_da_to_va,
};
static irqreturn_t vpu_interrupt(int irq, void *data)
{
struct rproc *rproc = data;
struct vpu *vpu = rproc->priv;
u32 vring;
vring = readl(vpu->aux_base + REG_AUX_MSG);
/* Ack the interrupt */
writel(0, vpu->aux_base + REG_AUX_MSG_ACK);
return rproc_vq_interrupt(rproc, vring);
}
static void ingenic_rproc_disable_clks(void *data)
{
struct vpu *vpu = data;
pm_runtime_resume(vpu->dev);
pm_runtime_disable(vpu->dev);
clk_bulk_disable_unprepare(ARRAY_SIZE(vpu->clks), vpu->clks);
}
static int ingenic_rproc_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct resource *mem;
struct rproc *rproc;
struct vpu *vpu;
unsigned int i;
int ret;
rproc = devm_rproc_alloc(dev, "ingenic-vpu",
&ingenic_rproc_ops, NULL, sizeof(*vpu));
if (!rproc)
return -ENOMEM;
vpu = rproc->priv;
vpu->dev = &pdev->dev;
platform_set_drvdata(pdev, vpu);
mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, "aux");
vpu->aux_base = devm_ioremap_resource(dev, mem);
if (IS_ERR(vpu->aux_base)) {
dev_err(dev, "Failed to ioremap\n");
return PTR_ERR(vpu->aux_base);
}
for (i = 0; i < ARRAY_SIZE(vpu_mem_map); i++) {
mem = platform_get_resource_byname(pdev, IORESOURCE_MEM,
vpu_mem_map[i].name);
vpu->mem_info[i].base = devm_ioremap_resource(dev, mem);
if (IS_ERR(vpu->mem_info[i].base)) {
ret = PTR_ERR(vpu->mem_info[i].base);
dev_err(dev, "Failed to ioremap\n");
return ret;
}
vpu->mem_info[i].len = resource_size(mem);
vpu->mem_info[i].map = &vpu_mem_map[i];
}
vpu->clks[0].id = "vpu";
vpu->clks[1].id = "aux";
ret = devm_clk_bulk_get(dev, ARRAY_SIZE(vpu->clks), vpu->clks);
if (ret) {
dev_err(dev, "Failed to get clocks\n");
return ret;
}
vpu->irq = platform_get_irq(pdev, 0);
if (vpu->irq < 0)
return vpu->irq;
ret = devm_request_irq(dev, vpu->irq, vpu_interrupt, 0, "VPU", rproc);
if (ret < 0) {
dev_err(dev, "Failed to request IRQ\n");
return ret;
}
disable_irq(vpu->irq);
/* The clocks must be enabled for the firmware to be loaded in TCSM */
ret = clk_bulk_prepare_enable(ARRAY_SIZE(vpu->clks), vpu->clks);
if (ret) {
dev_err(dev, "Unable to start clocks\n");
return ret;
}
pm_runtime_irq_safe(dev);
pm_runtime_set_active(dev);
pm_runtime_enable(dev);
pm_runtime_get_sync(dev);
pm_runtime_use_autosuspend(dev);
ret = devm_add_action_or_reset(dev, ingenic_rproc_disable_clks, vpu);
if (ret) {
dev_err(dev, "Unable to register action\n");
goto out_pm_put;
}
ret = devm_rproc_add(dev, rproc);
if (ret) {
dev_err(dev, "Failed to register remote processor\n");
goto out_pm_put;
}
out_pm_put:
pm_runtime_put_autosuspend(dev);
return ret;
}
static const struct of_device_id ingenic_rproc_of_matches[] = {
{ .compatible = "ingenic,jz4770-vpu-rproc", },
{}
};
MODULE_DEVICE_TABLE(of, ingenic_rproc_of_matches);
static int __maybe_unused ingenic_rproc_suspend(struct device *dev)
{
struct vpu *vpu = dev_get_drvdata(dev);
clk_bulk_disable(ARRAY_SIZE(vpu->clks), vpu->clks);
return 0;
}
static int __maybe_unused ingenic_rproc_resume(struct device *dev)
{
struct vpu *vpu = dev_get_drvdata(dev);
return clk_bulk_enable(ARRAY_SIZE(vpu->clks), vpu->clks);
}
static const struct dev_pm_ops __maybe_unused ingenic_rproc_pm = {
SET_RUNTIME_PM_OPS(ingenic_rproc_suspend, ingenic_rproc_resume, NULL)
};
static struct platform_driver ingenic_rproc_driver = {
.probe = ingenic_rproc_probe,
.driver = {
.name = "ingenic-vpu",
#ifdef CONFIG_PM
.pm = &ingenic_rproc_pm,
#endif
.of_match_table = ingenic_rproc_of_matches,
},
};
module_platform_driver(ingenic_rproc_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Paul Cercueil <paul@crapouillou.net>");
MODULE_DESCRIPTION("Ingenic JZ47xx Remote Processor control driver");
...@@ -132,8 +132,8 @@ static int scp_ipi_init(struct mtk_scp *scp) ...@@ -132,8 +132,8 @@ static int scp_ipi_init(struct mtk_scp *scp)
(struct mtk_share_obj __iomem *)(scp->sram_base + recv_offset); (struct mtk_share_obj __iomem *)(scp->sram_base + recv_offset);
scp->send_buf = scp->send_buf =
(struct mtk_share_obj __iomem *)(scp->sram_base + send_offset); (struct mtk_share_obj __iomem *)(scp->sram_base + send_offset);
memset_io(scp->recv_buf, 0, sizeof(scp->recv_buf)); memset_io(scp->recv_buf, 0, sizeof(*scp->recv_buf));
memset_io(scp->send_buf, 0, sizeof(scp->send_buf)); memset_io(scp->send_buf, 0, sizeof(*scp->send_buf));
return 0; return 0;
} }
......
...@@ -42,12 +42,21 @@ static void glink_subdev_stop(struct rproc_subdev *subdev, bool crashed) ...@@ -42,12 +42,21 @@ static void glink_subdev_stop(struct rproc_subdev *subdev, bool crashed)
glink->edge = NULL; glink->edge = NULL;
} }
static void glink_subdev_unprepare(struct rproc_subdev *subdev)
{
struct qcom_rproc_glink *glink = to_glink_subdev(subdev);
qcom_glink_ssr_notify(glink->ssr_name);
}
/** /**
* qcom_add_glink_subdev() - try to add a GLINK subdevice to rproc * qcom_add_glink_subdev() - try to add a GLINK subdevice to rproc
* @rproc: rproc handle to parent the subdevice * @rproc: rproc handle to parent the subdevice
* @glink: reference to a GLINK subdev context * @glink: reference to a GLINK subdev context
* @ssr_name: identifier of the associated remoteproc for ssr notifications
*/ */
void qcom_add_glink_subdev(struct rproc *rproc, struct qcom_rproc_glink *glink) void qcom_add_glink_subdev(struct rproc *rproc, struct qcom_rproc_glink *glink,
const char *ssr_name)
{ {
struct device *dev = &rproc->dev; struct device *dev = &rproc->dev;
...@@ -55,9 +64,14 @@ void qcom_add_glink_subdev(struct rproc *rproc, struct qcom_rproc_glink *glink) ...@@ -55,9 +64,14 @@ void qcom_add_glink_subdev(struct rproc *rproc, struct qcom_rproc_glink *glink)
if (!glink->node) if (!glink->node)
return; return;
glink->ssr_name = kstrdup_const(ssr_name, GFP_KERNEL);
if (!glink->ssr_name)
return;
glink->dev = dev; glink->dev = dev;
glink->subdev.start = glink_subdev_start; glink->subdev.start = glink_subdev_start;
glink->subdev.stop = glink_subdev_stop; glink->subdev.stop = glink_subdev_stop;
glink->subdev.unprepare = glink_subdev_unprepare;
rproc_add_subdev(rproc, &glink->subdev); rproc_add_subdev(rproc, &glink->subdev);
} }
...@@ -74,6 +88,7 @@ void qcom_remove_glink_subdev(struct rproc *rproc, struct qcom_rproc_glink *glin ...@@ -74,6 +88,7 @@ void qcom_remove_glink_subdev(struct rproc *rproc, struct qcom_rproc_glink *glin
return; return;
rproc_remove_subdev(rproc, &glink->subdev); rproc_remove_subdev(rproc, &glink->subdev);
kfree_const(glink->ssr_name);
of_node_put(glink->node); of_node_put(glink->node);
} }
EXPORT_SYMBOL_GPL(qcom_remove_glink_subdev); EXPORT_SYMBOL_GPL(qcom_remove_glink_subdev);
......
...@@ -11,6 +11,8 @@ struct qcom_sysmon; ...@@ -11,6 +11,8 @@ struct qcom_sysmon;
struct qcom_rproc_glink { struct qcom_rproc_glink {
struct rproc_subdev subdev; struct rproc_subdev subdev;
const char *ssr_name;
struct device *dev; struct device *dev;
struct device_node *node; struct device_node *node;
struct qcom_glink *edge; struct qcom_glink *edge;
...@@ -30,7 +32,8 @@ struct qcom_rproc_ssr { ...@@ -30,7 +32,8 @@ struct qcom_rproc_ssr {
const char *name; const char *name;
}; };
void qcom_add_glink_subdev(struct rproc *rproc, struct qcom_rproc_glink *glink); void qcom_add_glink_subdev(struct rproc *rproc, struct qcom_rproc_glink *glink,
const char *ssr_name);
void qcom_remove_glink_subdev(struct rproc *rproc, struct qcom_rproc_glink *glink); void qcom_remove_glink_subdev(struct rproc *rproc, struct qcom_rproc_glink *glink);
int qcom_register_dump_segments(struct rproc *rproc, const struct firmware *fw); int qcom_register_dump_segments(struct rproc *rproc, const struct firmware *fw);
......
...@@ -431,6 +431,7 @@ static int adsp_probe(struct platform_device *pdev) ...@@ -431,6 +431,7 @@ static int adsp_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "unable to allocate remoteproc\n"); dev_err(&pdev->dev, "unable to allocate remoteproc\n");
return -ENOMEM; return -ENOMEM;
} }
rproc_coredump_set_elf_info(rproc, ELFCLASS32, EM_NONE);
adsp = (struct qcom_adsp *)rproc->priv; adsp = (struct qcom_adsp *)rproc->priv;
adsp->dev = &pdev->dev; adsp->dev = &pdev->dev;
...@@ -460,7 +461,7 @@ static int adsp_probe(struct platform_device *pdev) ...@@ -460,7 +461,7 @@ static int adsp_probe(struct platform_device *pdev)
if (ret) if (ret)
goto disable_pm; goto disable_pm;
qcom_add_glink_subdev(rproc, &adsp->glink_subdev); qcom_add_glink_subdev(rproc, &adsp->glink_subdev, desc->ssr_name);
qcom_add_ssr_subdev(rproc, &adsp->ssr_subdev, desc->ssr_name); qcom_add_ssr_subdev(rproc, &adsp->ssr_subdev, desc->ssr_name);
adsp->sysmon = qcom_add_sysmon_subdev(rproc, adsp->sysmon = qcom_add_sysmon_subdev(rproc,
desc->sysmon_name, desc->sysmon_name,
......
This diff is collapsed.
...@@ -398,6 +398,7 @@ static int adsp_probe(struct platform_device *pdev) ...@@ -398,6 +398,7 @@ static int adsp_probe(struct platform_device *pdev)
} }
rproc->auto_boot = desc->auto_boot; rproc->auto_boot = desc->auto_boot;
rproc_coredump_set_elf_info(rproc, ELFCLASS32, EM_NONE);
adsp = (struct qcom_adsp *)rproc->priv; adsp = (struct qcom_adsp *)rproc->priv;
adsp->dev = &pdev->dev; adsp->dev = &pdev->dev;
...@@ -406,6 +407,8 @@ static int adsp_probe(struct platform_device *pdev) ...@@ -406,6 +407,8 @@ static int adsp_probe(struct platform_device *pdev)
adsp->has_aggre2_clk = desc->has_aggre2_clk; adsp->has_aggre2_clk = desc->has_aggre2_clk;
platform_set_drvdata(pdev, adsp); platform_set_drvdata(pdev, adsp);
device_wakeup_enable(adsp->dev);
ret = adsp_alloc_memory_region(adsp); ret = adsp_alloc_memory_region(adsp);
if (ret) if (ret)
goto free_rproc; goto free_rproc;
...@@ -435,7 +438,7 @@ static int adsp_probe(struct platform_device *pdev) ...@@ -435,7 +438,7 @@ static int adsp_probe(struct platform_device *pdev)
if (ret) if (ret)
goto detach_proxy_pds; goto detach_proxy_pds;
qcom_add_glink_subdev(rproc, &adsp->glink_subdev); qcom_add_glink_subdev(rproc, &adsp->glink_subdev, desc->ssr_name);
qcom_add_smd_subdev(rproc, &adsp->smd_subdev); qcom_add_smd_subdev(rproc, &adsp->smd_subdev);
qcom_add_ssr_subdev(rproc, &adsp->ssr_subdev, desc->ssr_name); qcom_add_ssr_subdev(rproc, &adsp->ssr_subdev, desc->ssr_name);
adsp->sysmon = qcom_add_sysmon_subdev(rproc, adsp->sysmon = qcom_add_sysmon_subdev(rproc,
...@@ -507,6 +510,26 @@ static const struct adsp_data sm8150_adsp_resource = { ...@@ -507,6 +510,26 @@ static const struct adsp_data sm8150_adsp_resource = {
.ssctl_id = 0x14, .ssctl_id = 0x14,
}; };
static const struct adsp_data sm8250_adsp_resource = {
.crash_reason_smem = 423,
.firmware_name = "adsp.mdt",
.pas_id = 1,
.has_aggre2_clk = false,
.auto_boot = true,
.active_pd_names = (char*[]){
"load_state",
NULL
},
.proxy_pd_names = (char*[]){
"lcx",
"lmx",
NULL
},
.ssr_name = "lpass",
.sysmon_name = "adsp",
.ssctl_id = 0x14,
};
static const struct adsp_data msm8998_adsp_resource = { static const struct adsp_data msm8998_adsp_resource = {
.crash_reason_smem = 423, .crash_reason_smem = 423,
.firmware_name = "adsp.mdt", .firmware_name = "adsp.mdt",
...@@ -552,6 +575,25 @@ static const struct adsp_data sm8150_cdsp_resource = { ...@@ -552,6 +575,25 @@ static const struct adsp_data sm8150_cdsp_resource = {
.ssctl_id = 0x17, .ssctl_id = 0x17,
}; };
static const struct adsp_data sm8250_cdsp_resource = {
.crash_reason_smem = 601,
.firmware_name = "cdsp.mdt",
.pas_id = 18,
.has_aggre2_clk = false,
.auto_boot = true,
.active_pd_names = (char*[]){
"load_state",
NULL
},
.proxy_pd_names = (char*[]){
"cx",
NULL
},
.ssr_name = "cdsp",
.sysmon_name = "cdsp",
.ssctl_id = 0x17,
};
static const struct adsp_data mpss_resource_init = { static const struct adsp_data mpss_resource_init = {
.crash_reason_smem = 421, .crash_reason_smem = 421,
.firmware_name = "modem.mdt", .firmware_name = "modem.mdt",
...@@ -603,6 +645,26 @@ static const struct adsp_data sm8150_slpi_resource = { ...@@ -603,6 +645,26 @@ static const struct adsp_data sm8150_slpi_resource = {
.ssctl_id = 0x16, .ssctl_id = 0x16,
}; };
static const struct adsp_data sm8250_slpi_resource = {
.crash_reason_smem = 424,
.firmware_name = "slpi.mdt",
.pas_id = 12,
.has_aggre2_clk = false,
.auto_boot = true,
.active_pd_names = (char*[]){
"load_state",
NULL
},
.proxy_pd_names = (char*[]){
"lcx",
"lmx",
NULL
},
.ssr_name = "dsps",
.sysmon_name = "slpi",
.ssctl_id = 0x16,
};
static const struct adsp_data msm8998_slpi_resource = { static const struct adsp_data msm8998_slpi_resource = {
.crash_reason_smem = 424, .crash_reason_smem = 424,
.firmware_name = "slpi.mdt", .firmware_name = "slpi.mdt",
...@@ -637,12 +699,16 @@ static const struct of_device_id adsp_of_match[] = { ...@@ -637,12 +699,16 @@ static const struct of_device_id adsp_of_match[] = {
{ .compatible = "qcom,qcs404-adsp-pas", .data = &adsp_resource_init }, { .compatible = "qcom,qcs404-adsp-pas", .data = &adsp_resource_init },
{ .compatible = "qcom,qcs404-cdsp-pas", .data = &cdsp_resource_init }, { .compatible = "qcom,qcs404-cdsp-pas", .data = &cdsp_resource_init },
{ .compatible = "qcom,qcs404-wcss-pas", .data = &wcss_resource_init }, { .compatible = "qcom,qcs404-wcss-pas", .data = &wcss_resource_init },
{ .compatible = "qcom,sc7180-mpss-pas", .data = &mpss_resource_init},
{ .compatible = "qcom,sdm845-adsp-pas", .data = &adsp_resource_init}, { .compatible = "qcom,sdm845-adsp-pas", .data = &adsp_resource_init},
{ .compatible = "qcom,sdm845-cdsp-pas", .data = &cdsp_resource_init}, { .compatible = "qcom,sdm845-cdsp-pas", .data = &cdsp_resource_init},
{ .compatible = "qcom,sm8150-adsp-pas", .data = &sm8150_adsp_resource}, { .compatible = "qcom,sm8150-adsp-pas", .data = &sm8150_adsp_resource},
{ .compatible = "qcom,sm8150-cdsp-pas", .data = &sm8150_cdsp_resource}, { .compatible = "qcom,sm8150-cdsp-pas", .data = &sm8150_cdsp_resource},
{ .compatible = "qcom,sm8150-mpss-pas", .data = &mpss_resource_init}, { .compatible = "qcom,sm8150-mpss-pas", .data = &mpss_resource_init},
{ .compatible = "qcom,sm8150-slpi-pas", .data = &sm8150_slpi_resource}, { .compatible = "qcom,sm8150-slpi-pas", .data = &sm8150_slpi_resource},
{ .compatible = "qcom,sm8250-adsp-pas", .data = &sm8250_adsp_resource},
{ .compatible = "qcom,sm8250-cdsp-pas", .data = &sm8250_cdsp_resource},
{ .compatible = "qcom,sm8250-slpi-pas", .data = &sm8250_slpi_resource},
{ }, { },
}; };
MODULE_DEVICE_TABLE(of, adsp_of_match); MODULE_DEVICE_TABLE(of, adsp_of_match);
......
...@@ -91,6 +91,9 @@ struct q6v5_wcss { ...@@ -91,6 +91,9 @@ struct q6v5_wcss {
phys_addr_t mem_reloc; phys_addr_t mem_reloc;
void *mem_region; void *mem_region;
size_t mem_size; size_t mem_size;
struct qcom_rproc_glink glink_subdev;
struct qcom_rproc_ssr ssr_subdev;
}; };
static int q6v5_wcss_reset(struct q6v5_wcss *wcss) static int q6v5_wcss_reset(struct q6v5_wcss *wcss)
...@@ -557,6 +560,9 @@ static int q6v5_wcss_probe(struct platform_device *pdev) ...@@ -557,6 +560,9 @@ static int q6v5_wcss_probe(struct platform_device *pdev)
if (ret) if (ret)
goto free_rproc; goto free_rproc;
qcom_add_glink_subdev(rproc, &wcss->glink_subdev, "q6wcss");
qcom_add_ssr_subdev(rproc, &wcss->ssr_subdev, "q6wcss");
ret = rproc_add(rproc); ret = rproc_add(rproc);
if (ret) if (ret)
goto free_rproc; goto free_rproc;
......
...@@ -46,6 +46,25 @@ struct qcom_sysmon { ...@@ -46,6 +46,25 @@ struct qcom_sysmon {
struct sockaddr_qrtr ssctl; struct sockaddr_qrtr ssctl;
}; };
enum {
SSCTL_SSR_EVENT_BEFORE_POWERUP,
SSCTL_SSR_EVENT_AFTER_POWERUP,
SSCTL_SSR_EVENT_BEFORE_SHUTDOWN,
SSCTL_SSR_EVENT_AFTER_SHUTDOWN,
};
static const char * const sysmon_state_string[] = {
[SSCTL_SSR_EVENT_BEFORE_POWERUP] = "before_powerup",
[SSCTL_SSR_EVENT_AFTER_POWERUP] = "after_powerup",
[SSCTL_SSR_EVENT_BEFORE_SHUTDOWN] = "before_shutdown",
[SSCTL_SSR_EVENT_AFTER_SHUTDOWN] = "after_shutdown",
};
struct sysmon_event {
const char *subsys_name;
u32 ssr_event;
};
static DEFINE_MUTEX(sysmon_lock); static DEFINE_MUTEX(sysmon_lock);
static LIST_HEAD(sysmon_list); static LIST_HEAD(sysmon_list);
...@@ -54,13 +73,15 @@ static LIST_HEAD(sysmon_list); ...@@ -54,13 +73,15 @@ static LIST_HEAD(sysmon_list);
* @sysmon: sysmon context * @sysmon: sysmon context
* @name: other remote's name * @name: other remote's name
*/ */
static void sysmon_send_event(struct qcom_sysmon *sysmon, const char *name) static void sysmon_send_event(struct qcom_sysmon *sysmon,
const struct sysmon_event *event)
{ {
char req[50]; char req[50];
int len; int len;
int ret; int ret;
len = snprintf(req, sizeof(req), "ssr:%s:before_shutdown", name); len = snprintf(req, sizeof(req), "ssr:%s:%s", event->subsys_name,
sysmon_state_string[event->ssr_event]);
if (len >= sizeof(req)) if (len >= sizeof(req))
return; return;
...@@ -148,13 +169,6 @@ static int sysmon_callback(struct rpmsg_device *rpdev, void *data, int count, ...@@ -148,13 +169,6 @@ static int sysmon_callback(struct rpmsg_device *rpdev, void *data, int count,
#define SSCTL_SUBSYS_NAME_LENGTH 15 #define SSCTL_SUBSYS_NAME_LENGTH 15
enum {
SSCTL_SSR_EVENT_BEFORE_POWERUP,
SSCTL_SSR_EVENT_AFTER_POWERUP,
SSCTL_SSR_EVENT_BEFORE_SHUTDOWN,
SSCTL_SSR_EVENT_AFTER_SHUTDOWN,
};
enum { enum {
SSCTL_SSR_EVENT_FORCED, SSCTL_SSR_EVENT_FORCED,
SSCTL_SSR_EVENT_GRACEFUL, SSCTL_SSR_EVENT_GRACEFUL,
...@@ -331,7 +345,8 @@ static void ssctl_request_shutdown(struct qcom_sysmon *sysmon) ...@@ -331,7 +345,8 @@ static void ssctl_request_shutdown(struct qcom_sysmon *sysmon)
* @sysmon: sysmon context * @sysmon: sysmon context
* @name: other remote's name * @name: other remote's name
*/ */
static void ssctl_send_event(struct qcom_sysmon *sysmon, const char *name) static void ssctl_send_event(struct qcom_sysmon *sysmon,
const struct sysmon_event *event)
{ {
struct ssctl_subsys_event_resp resp; struct ssctl_subsys_event_resp resp;
struct ssctl_subsys_event_req req; struct ssctl_subsys_event_req req;
...@@ -346,9 +361,9 @@ static void ssctl_send_event(struct qcom_sysmon *sysmon, const char *name) ...@@ -346,9 +361,9 @@ static void ssctl_send_event(struct qcom_sysmon *sysmon, const char *name)
} }
memset(&req, 0, sizeof(req)); memset(&req, 0, sizeof(req));
strlcpy(req.subsys_name, name, sizeof(req.subsys_name)); strlcpy(req.subsys_name, event->subsys_name, sizeof(req.subsys_name));
req.subsys_name_len = strlen(req.subsys_name); req.subsys_name_len = strlen(req.subsys_name);
req.event = SSCTL_SSR_EVENT_BEFORE_SHUTDOWN; req.event = event->ssr_event;
req.evt_driven_valid = true; req.evt_driven_valid = true;
req.evt_driven = SSCTL_SSR_EVENT_FORCED; req.evt_driven = SSCTL_SSR_EVENT_FORCED;
...@@ -424,16 +439,68 @@ static const struct qmi_ops ssctl_ops = { ...@@ -424,16 +439,68 @@ static const struct qmi_ops ssctl_ops = {
.del_server = ssctl_del_server, .del_server = ssctl_del_server,
}; };
static int sysmon_prepare(struct rproc_subdev *subdev)
{
struct qcom_sysmon *sysmon = container_of(subdev, struct qcom_sysmon,
subdev);
struct sysmon_event event = {
.subsys_name = sysmon->name,
.ssr_event = SSCTL_SSR_EVENT_BEFORE_POWERUP
};
blocking_notifier_call_chain(&sysmon_notifiers, 0, (void *)&event);
return 0;
}
/**
* sysmon_start() - start callback for the sysmon remoteproc subdevice
* @subdev: instance of the sysmon subdevice
*
* Inform all the listners of sysmon notifications that the rproc associated
* to @subdev has booted up. The rproc that booted up also needs to know
* which rprocs are already up and running, so send start notifications
* on behalf of all the online rprocs.
*/
static int sysmon_start(struct rproc_subdev *subdev) static int sysmon_start(struct rproc_subdev *subdev)
{ {
struct qcom_sysmon *sysmon = container_of(subdev, struct qcom_sysmon,
subdev);
struct qcom_sysmon *target;
struct sysmon_event event = {
.subsys_name = sysmon->name,
.ssr_event = SSCTL_SSR_EVENT_AFTER_POWERUP
};
blocking_notifier_call_chain(&sysmon_notifiers, 0, (void *)&event);
mutex_lock(&sysmon_lock);
list_for_each_entry(target, &sysmon_list, node) {
if (target == sysmon ||
target->rproc->state != RPROC_RUNNING)
continue;
event.subsys_name = target->name;
if (sysmon->ssctl_version == 2)
ssctl_send_event(sysmon, &event);
else if (sysmon->ept)
sysmon_send_event(sysmon, &event);
}
mutex_unlock(&sysmon_lock);
return 0; return 0;
} }
static void sysmon_stop(struct rproc_subdev *subdev, bool crashed) static void sysmon_stop(struct rproc_subdev *subdev, bool crashed)
{ {
struct qcom_sysmon *sysmon = container_of(subdev, struct qcom_sysmon, subdev); struct qcom_sysmon *sysmon = container_of(subdev, struct qcom_sysmon, subdev);
struct sysmon_event event = {
.subsys_name = sysmon->name,
.ssr_event = SSCTL_SSR_EVENT_BEFORE_SHUTDOWN
};
blocking_notifier_call_chain(&sysmon_notifiers, 0, (void *)sysmon->name); blocking_notifier_call_chain(&sysmon_notifiers, 0, (void *)&event);
/* Don't request graceful shutdown if we've crashed */ /* Don't request graceful shutdown if we've crashed */
if (crashed) if (crashed)
...@@ -445,6 +512,18 @@ static void sysmon_stop(struct rproc_subdev *subdev, bool crashed) ...@@ -445,6 +512,18 @@ static void sysmon_stop(struct rproc_subdev *subdev, bool crashed)
sysmon_request_shutdown(sysmon); sysmon_request_shutdown(sysmon);
} }
static void sysmon_unprepare(struct rproc_subdev *subdev)
{
struct qcom_sysmon *sysmon = container_of(subdev, struct qcom_sysmon,
subdev);
struct sysmon_event event = {
.subsys_name = sysmon->name,
.ssr_event = SSCTL_SSR_EVENT_AFTER_SHUTDOWN
};
blocking_notifier_call_chain(&sysmon_notifiers, 0, (void *)&event);
}
/** /**
* sysmon_notify() - notify sysmon target of another's SSR * sysmon_notify() - notify sysmon target of another's SSR
* @nb: notifier_block associated with sysmon instance * @nb: notifier_block associated with sysmon instance
...@@ -456,19 +535,20 @@ static int sysmon_notify(struct notifier_block *nb, unsigned long event, ...@@ -456,19 +535,20 @@ static int sysmon_notify(struct notifier_block *nb, unsigned long event,
{ {
struct qcom_sysmon *sysmon = container_of(nb, struct qcom_sysmon, nb); struct qcom_sysmon *sysmon = container_of(nb, struct qcom_sysmon, nb);
struct rproc *rproc = sysmon->rproc; struct rproc *rproc = sysmon->rproc;
const char *ssr_name = data; struct sysmon_event *sysmon_event = data;
/* Skip non-running rprocs and the originating instance */ /* Skip non-running rprocs and the originating instance */
if (rproc->state != RPROC_RUNNING || !strcmp(data, sysmon->name)) { if (rproc->state != RPROC_RUNNING ||
!strcmp(sysmon_event->subsys_name, sysmon->name)) {
dev_dbg(sysmon->dev, "not notifying %s\n", sysmon->name); dev_dbg(sysmon->dev, "not notifying %s\n", sysmon->name);
return NOTIFY_DONE; return NOTIFY_DONE;
} }
/* Only SSCTL version 2 supports SSR events */ /* Only SSCTL version 2 supports SSR events */
if (sysmon->ssctl_version == 2) if (sysmon->ssctl_version == 2)
ssctl_send_event(sysmon, ssr_name); ssctl_send_event(sysmon, sysmon_event);
else if (sysmon->ept) else if (sysmon->ept)
sysmon_send_event(sysmon, ssr_name); sysmon_send_event(sysmon, sysmon_event);
return NOTIFY_DONE; return NOTIFY_DONE;
} }
...@@ -543,8 +623,10 @@ struct qcom_sysmon *qcom_add_sysmon_subdev(struct rproc *rproc, ...@@ -543,8 +623,10 @@ struct qcom_sysmon *qcom_add_sysmon_subdev(struct rproc *rproc,
qmi_add_lookup(&sysmon->qmi, 43, 0, 0); qmi_add_lookup(&sysmon->qmi, 43, 0, 0);
sysmon->subdev.prepare = sysmon_prepare;
sysmon->subdev.start = sysmon_start; sysmon->subdev.start = sysmon_start;
sysmon->subdev.stop = sysmon_stop; sysmon->subdev.stop = sysmon_stop;
sysmon->subdev.unprepare = sysmon_unprepare;
rproc_add_subdev(rproc, &sysmon->subdev); rproc_add_subdev(rproc, &sysmon->subdev);
......
...@@ -480,6 +480,7 @@ static int wcnss_probe(struct platform_device *pdev) ...@@ -480,6 +480,7 @@ static int wcnss_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "unable to allocate remoteproc\n"); dev_err(&pdev->dev, "unable to allocate remoteproc\n");
return -ENOMEM; return -ENOMEM;
} }
rproc_coredump_set_elf_info(rproc, ELFCLASS32, EM_NONE);
wcnss = (struct qcom_wcnss *)rproc->priv; wcnss = (struct qcom_wcnss *)rproc->priv;
wcnss->dev = &pdev->dev; wcnss->dev = &pdev->dev;
......
This diff is collapsed.
...@@ -269,17 +269,7 @@ static int rproc_rsc_table_show(struct seq_file *seq, void *p) ...@@ -269,17 +269,7 @@ static int rproc_rsc_table_show(struct seq_file *seq, void *p)
return 0; return 0;
} }
static int rproc_rsc_table_open(struct inode *inode, struct file *file) DEFINE_SHOW_ATTRIBUTE(rproc_rsc_table);
{
return single_open(file, rproc_rsc_table_show, inode->i_private);
}
static const struct file_operations rproc_rsc_table_ops = {
.open = rproc_rsc_table_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
/* Expose carveout content via debugfs */ /* Expose carveout content via debugfs */
static int rproc_carveouts_show(struct seq_file *seq, void *p) static int rproc_carveouts_show(struct seq_file *seq, void *p)
...@@ -299,17 +289,7 @@ static int rproc_carveouts_show(struct seq_file *seq, void *p) ...@@ -299,17 +289,7 @@ static int rproc_carveouts_show(struct seq_file *seq, void *p)
return 0; return 0;
} }
static int rproc_carveouts_open(struct inode *inode, struct file *file) DEFINE_SHOW_ATTRIBUTE(rproc_carveouts);
{
return single_open(file, rproc_carveouts_show, inode->i_private);
}
static const struct file_operations rproc_carveouts_ops = {
.open = rproc_carveouts_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
void rproc_remove_trace_file(struct dentry *tfile) void rproc_remove_trace_file(struct dentry *tfile)
{ {
...@@ -354,9 +334,9 @@ void rproc_create_debug_dir(struct rproc *rproc) ...@@ -354,9 +334,9 @@ void rproc_create_debug_dir(struct rproc *rproc)
debugfs_create_file("crash", 0200, rproc->dbg_dir, debugfs_create_file("crash", 0200, rproc->dbg_dir,
rproc, &rproc_crash_ops); rproc, &rproc_crash_ops);
debugfs_create_file("resource_table", 0400, rproc->dbg_dir, debugfs_create_file("resource_table", 0400, rproc->dbg_dir,
rproc, &rproc_rsc_table_ops); rproc, &rproc_rsc_table_fops);
debugfs_create_file("carveout_memories", 0400, rproc->dbg_dir, debugfs_create_file("carveout_memories", 0400, rproc->dbg_dir,
rproc, &rproc_carveouts_ops); rproc, &rproc_carveouts_fops);
} }
void __init rproc_init_debugfs(void) void __init rproc_init_debugfs(void)
......
...@@ -112,27 +112,6 @@ int rproc_elf_sanity_check(struct rproc *rproc, const struct firmware *fw) ...@@ -112,27 +112,6 @@ int rproc_elf_sanity_check(struct rproc *rproc, const struct firmware *fw)
} }
EXPORT_SYMBOL(rproc_elf_sanity_check); EXPORT_SYMBOL(rproc_elf_sanity_check);
/**
* rproc_elf_sanity_check() - Sanity Check ELF32 firmware image
* @rproc: the remote processor handle
* @fw: the ELF32 firmware image
*
* Make sure this fw image is sane.
*/
int rproc_elf32_sanity_check(struct rproc *rproc, const struct firmware *fw)
{
int ret = rproc_elf_sanity_check(rproc, fw);
if (ret)
return ret;
if (fw_elf_get_class(fw) == ELFCLASS32)
return 0;
return -EINVAL;
}
EXPORT_SYMBOL(rproc_elf32_sanity_check);
/** /**
* rproc_elf_get_boot_addr() - Get rproc's boot address. * rproc_elf_get_boot_addr() - Get rproc's boot address.
* @rproc: the remote processor handle * @rproc: the remote processor handle
...@@ -248,9 +227,6 @@ int rproc_elf_load_segments(struct rproc *rproc, const struct firmware *fw) ...@@ -248,9 +227,6 @@ int rproc_elf_load_segments(struct rproc *rproc, const struct firmware *fw)
memset(ptr + filesz, 0, memsz - filesz); memset(ptr + filesz, 0, memsz - filesz);
} }
if (ret == 0)
rproc->elf_class = class;
return ret; return ret;
} }
EXPORT_SYMBOL(rproc_elf_load_segments); EXPORT_SYMBOL(rproc_elf_load_segments);
......
...@@ -54,7 +54,6 @@ void *rproc_da_to_va(struct rproc *rproc, u64 da, size_t len); ...@@ -54,7 +54,6 @@ void *rproc_da_to_va(struct rproc *rproc, u64 da, size_t len);
phys_addr_t rproc_va_to_pa(void *cpu_addr); phys_addr_t rproc_va_to_pa(void *cpu_addr);
int rproc_trigger_recovery(struct rproc *rproc); int rproc_trigger_recovery(struct rproc *rproc);
int rproc_elf32_sanity_check(struct rproc *rproc, const struct firmware *fw);
int rproc_elf_sanity_check(struct rproc *rproc, const struct firmware *fw); int rproc_elf_sanity_check(struct rproc *rproc, const struct firmware *fw);
u64 rproc_elf_get_boot_addr(struct rproc *rproc, const struct firmware *fw); u64 rproc_elf_get_boot_addr(struct rproc *rproc, const struct firmware *fw);
int rproc_elf_load_segments(struct rproc *rproc, const struct firmware *fw); int rproc_elf_load_segments(struct rproc *rproc, const struct firmware *fw);
...@@ -64,6 +63,22 @@ struct resource_table *rproc_elf_find_loaded_rsc_table(struct rproc *rproc, ...@@ -64,6 +63,22 @@ struct resource_table *rproc_elf_find_loaded_rsc_table(struct rproc *rproc,
struct rproc_mem_entry * struct rproc_mem_entry *
rproc_find_carveout_by_name(struct rproc *rproc, const char *name, ...); rproc_find_carveout_by_name(struct rproc *rproc, const char *name, ...);
static inline int rproc_prepare_device(struct rproc *rproc)
{
if (rproc->ops->prepare)
return rproc->ops->prepare(rproc);
return 0;
}
static inline int rproc_unprepare_device(struct rproc *rproc)
{
if (rproc->ops->unprepare)
return rproc->ops->unprepare(rproc);
return 0;
}
static inline static inline
int rproc_fw_sanity_check(struct rproc *rproc, const struct firmware *fw) int rproc_fw_sanity_check(struct rproc *rproc, const struct firmware *fw)
{ {
......
...@@ -337,8 +337,7 @@ int rproc_add_virtio_dev(struct rproc_vdev *rvdev, int id) ...@@ -337,8 +337,7 @@ int rproc_add_virtio_dev(struct rproc_vdev *rvdev, int id)
if (rproc->ops->kick == NULL) { if (rproc->ops->kick == NULL) {
ret = -EINVAL; ret = -EINVAL;
dev_err(dev, ".kick method not defined for %s", dev_err(dev, ".kick method not defined for %s\n", rproc->name);
rproc->name);
goto out; goto out;
} }
...@@ -376,6 +375,18 @@ int rproc_add_virtio_dev(struct rproc_vdev *rvdev, int id) ...@@ -376,6 +375,18 @@ int rproc_add_virtio_dev(struct rproc_vdev *rvdev, int id)
goto out; goto out;
} }
} }
} else {
struct device_node *np = rproc->dev.parent->of_node;
/*
* If we don't have dedicated buffer, just attempt to re-assign
* the reserved memory from our parent. A default memory-region
* at index 0 from the parent's memory-regions is assigned for
* the rvdev dev to allocate from. Failure is non-critical and
* the allocations will fall back to global pools, so don't
* check return value either.
*/
of_reserved_mem_device_init_by_idx(dev, np, 0);
} }
/* Allocate virtio device */ /* Allocate virtio device */
......
...@@ -233,7 +233,7 @@ static const struct rproc_ops st_rproc_ops = { ...@@ -233,7 +233,7 @@ static const struct rproc_ops st_rproc_ops = {
.parse_fw = st_rproc_parse_fw, .parse_fw = st_rproc_parse_fw,
.load = rproc_elf_load_segments, .load = rproc_elf_load_segments,
.find_loaded_rsc_table = rproc_elf_find_loaded_rsc_table, .find_loaded_rsc_table = rproc_elf_find_loaded_rsc_table,
.sanity_check = rproc_elf32_sanity_check, .sanity_check = rproc_elf_sanity_check,
.get_boot_addr = rproc_elf_get_boot_addr, .get_boot_addr = rproc_elf_get_boot_addr,
}; };
......
...@@ -203,7 +203,7 @@ static const struct rproc_ops slim_rproc_ops = { ...@@ -203,7 +203,7 @@ static const struct rproc_ops slim_rproc_ops = {
.da_to_va = slim_rproc_da_to_va, .da_to_va = slim_rproc_da_to_va,
.get_boot_addr = rproc_elf_get_boot_addr, .get_boot_addr = rproc_elf_get_boot_addr,
.load = rproc_elf_load_segments, .load = rproc_elf_load_segments,
.sanity_check = rproc_elf32_sanity_check, .sanity_check = rproc_elf_sanity_check,
}; };
/** /**
......
...@@ -506,7 +506,7 @@ static struct rproc_ops st_rproc_ops = { ...@@ -506,7 +506,7 @@ static struct rproc_ops st_rproc_ops = {
.load = rproc_elf_load_segments, .load = rproc_elf_load_segments,
.parse_fw = stm32_rproc_parse_fw, .parse_fw = stm32_rproc_parse_fw,
.find_loaded_rsc_table = rproc_elf_find_loaded_rsc_table, .find_loaded_rsc_table = rproc_elf_find_loaded_rsc_table,
.sanity_check = rproc_elf32_sanity_check, .sanity_check = rproc_elf_sanity_check,
.get_boot_addr = rproc_elf_get_boot_addr, .get_boot_addr = rproc_elf_get_boot_addr,
}; };
...@@ -626,6 +626,7 @@ static int stm32_rproc_probe(struct platform_device *pdev) ...@@ -626,6 +626,7 @@ static int stm32_rproc_probe(struct platform_device *pdev)
if (!rproc) if (!rproc)
return -ENOMEM; return -ENOMEM;
rproc_coredump_set_elf_info(rproc, ELFCLASS32, EM_NONE);
rproc->has_iommu = false; rproc->has_iommu = false;
ddata = rproc->priv; ddata = rproc->priv;
ddata->workqueue = create_workqueue(dev_name(dev)); ddata->workqueue = create_workqueue(dev_name(dev));
......
...@@ -24,13 +24,13 @@ config RPMSG_MTK_SCP ...@@ -24,13 +24,13 @@ config RPMSG_MTK_SCP
remote processors in MediaTek platforms. remote processors in MediaTek platforms.
This use IPI and IPC to communicate with remote processors. This use IPI and IPC to communicate with remote processors.
config RPMSG_QCOM_GLINK_NATIVE config RPMSG_QCOM_GLINK
tristate tristate
select RPMSG select RPMSG
config RPMSG_QCOM_GLINK_RPM config RPMSG_QCOM_GLINK_RPM
tristate "Qualcomm RPM Glink driver" tristate "Qualcomm RPM Glink driver"
select RPMSG_QCOM_GLINK_NATIVE select RPMSG_QCOM_GLINK
depends on HAS_IOMEM depends on HAS_IOMEM
depends on MAILBOX depends on MAILBOX
help help
...@@ -40,7 +40,7 @@ config RPMSG_QCOM_GLINK_RPM ...@@ -40,7 +40,7 @@ config RPMSG_QCOM_GLINK_RPM
config RPMSG_QCOM_GLINK_SMEM config RPMSG_QCOM_GLINK_SMEM
tristate "Qualcomm SMEM Glink driver" tristate "Qualcomm SMEM Glink driver"
select RPMSG_QCOM_GLINK_NATIVE select RPMSG_QCOM_GLINK
depends on MAILBOX depends on MAILBOX
depends on QCOM_SMEM depends on QCOM_SMEM
help help
......
...@@ -2,8 +2,9 @@ ...@@ -2,8 +2,9 @@
obj-$(CONFIG_RPMSG) += rpmsg_core.o obj-$(CONFIG_RPMSG) += rpmsg_core.o
obj-$(CONFIG_RPMSG_CHAR) += rpmsg_char.o obj-$(CONFIG_RPMSG_CHAR) += rpmsg_char.o
obj-$(CONFIG_RPMSG_MTK_SCP) += mtk_rpmsg.o obj-$(CONFIG_RPMSG_MTK_SCP) += mtk_rpmsg.o
qcom_glink-objs := qcom_glink_native.o qcom_glink_ssr.o
obj-$(CONFIG_RPMSG_QCOM_GLINK) += qcom_glink.o
obj-$(CONFIG_RPMSG_QCOM_GLINK_RPM) += qcom_glink_rpm.o obj-$(CONFIG_RPMSG_QCOM_GLINK_RPM) += qcom_glink_rpm.o
obj-$(CONFIG_RPMSG_QCOM_GLINK_NATIVE) += qcom_glink_native.o
obj-$(CONFIG_RPMSG_QCOM_GLINK_SMEM) += qcom_glink_smem.o obj-$(CONFIG_RPMSG_QCOM_GLINK_SMEM) += qcom_glink_smem.o
obj-$(CONFIG_RPMSG_QCOM_SMD) += qcom_smd.o obj-$(CONFIG_RPMSG_QCOM_SMD) += qcom_smd.o
obj-$(CONFIG_RPMSG_VIRTIO) += virtio_rpmsg_bus.o obj-$(CONFIG_RPMSG_VIRTIO) += virtio_rpmsg_bus.o
...@@ -54,6 +54,19 @@ struct glink_ssr { ...@@ -54,6 +54,19 @@ struct glink_ssr {
struct completion completion; struct completion completion;
}; };
/* Notifier list for all registered glink_ssr instances */
static BLOCKING_NOTIFIER_HEAD(ssr_notifiers);
/**
* qcom_glink_ssr_notify() - notify GLINK SSR about stopped remoteproc
* @ssr_name: name of the remoteproc that has been stopped
*/
void qcom_glink_ssr_notify(const char *ssr_name)
{
blocking_notifier_call_chain(&ssr_notifiers, 0, (void *)ssr_name);
}
EXPORT_SYMBOL_GPL(qcom_glink_ssr_notify);
static int qcom_glink_ssr_callback(struct rpmsg_device *rpdev, static int qcom_glink_ssr_callback(struct rpmsg_device *rpdev,
void *data, int len, void *priv, u32 addr) void *data, int len, void *priv, u32 addr)
{ {
...@@ -81,7 +94,8 @@ static int qcom_glink_ssr_callback(struct rpmsg_device *rpdev, ...@@ -81,7 +94,8 @@ static int qcom_glink_ssr_callback(struct rpmsg_device *rpdev,
return 0; return 0;
} }
static int qcom_glink_ssr_notify(struct notifier_block *nb, unsigned long event, static int qcom_glink_ssr_notifier_call(struct notifier_block *nb,
unsigned long event,
void *data) void *data)
{ {
struct glink_ssr *ssr = container_of(nb, struct glink_ssr, nb); struct glink_ssr *ssr = container_of(nb, struct glink_ssr, nb);
...@@ -121,18 +135,18 @@ static int qcom_glink_ssr_probe(struct rpmsg_device *rpdev) ...@@ -121,18 +135,18 @@ static int qcom_glink_ssr_probe(struct rpmsg_device *rpdev)
ssr->dev = &rpdev->dev; ssr->dev = &rpdev->dev;
ssr->ept = rpdev->ept; ssr->ept = rpdev->ept;
ssr->nb.notifier_call = qcom_glink_ssr_notify; ssr->nb.notifier_call = qcom_glink_ssr_notifier_call;
dev_set_drvdata(&rpdev->dev, ssr); dev_set_drvdata(&rpdev->dev, ssr);
return qcom_register_ssr_notifier(&ssr->nb); return blocking_notifier_chain_register(&ssr_notifiers, &ssr->nb);
} }
static void qcom_glink_ssr_remove(struct rpmsg_device *rpdev) static void qcom_glink_ssr_remove(struct rpmsg_device *rpdev)
{ {
struct glink_ssr *ssr = dev_get_drvdata(&rpdev->dev); struct glink_ssr *ssr = dev_get_drvdata(&rpdev->dev);
qcom_unregister_ssr_notifier(&ssr->nb); blocking_notifier_chain_unregister(&ssr_notifiers, &ssr->nb);
} }
static const struct rpmsg_device_id qcom_glink_ssr_match[] = { static const struct rpmsg_device_id qcom_glink_ssr_match[] = {
...@@ -150,7 +164,3 @@ static struct rpmsg_driver qcom_glink_ssr_driver = { ...@@ -150,7 +164,3 @@ static struct rpmsg_driver qcom_glink_ssr_driver = {
}, },
}; };
module_rpmsg_driver(qcom_glink_ssr_driver); module_rpmsg_driver(qcom_glink_ssr_driver);
MODULE_ALIAS("rpmsg:glink_ssr");
MODULE_DESCRIPTION("Qualcomm GLINK SSR notifier");
MODULE_LICENSE("GPL v2");
...@@ -35,15 +35,6 @@ config QCOM_GENI_SE ...@@ -35,15 +35,6 @@ config QCOM_GENI_SE
driver is also used to manage the common aspects of multiple Serial driver is also used to manage the common aspects of multiple Serial
Engines present in the QUP. Engines present in the QUP.
config QCOM_GLINK_SSR
tristate "Qualcomm Glink SSR driver"
depends on RPMSG
depends on QCOM_RPROC_COMMON
help
Say y here to enable GLINK SSR support. The GLINK SSR driver
implements the SSR protocol for notifying the remote processor about
neighboring subsystems going up or down.
config QCOM_GSBI config QCOM_GSBI
tristate "QCOM General Serial Bus Interface" tristate "QCOM General Serial Bus Interface"
depends on ARCH_QCOM || COMPILE_TEST depends on ARCH_QCOM || COMPILE_TEST
......
...@@ -3,7 +3,6 @@ CFLAGS_rpmh-rsc.o := -I$(src) ...@@ -3,7 +3,6 @@ CFLAGS_rpmh-rsc.o := -I$(src)
obj-$(CONFIG_QCOM_AOSS_QMP) += qcom_aoss.o obj-$(CONFIG_QCOM_AOSS_QMP) += qcom_aoss.o
obj-$(CONFIG_QCOM_GENI_SE) += qcom-geni-se.o obj-$(CONFIG_QCOM_GENI_SE) += qcom-geni-se.o
obj-$(CONFIG_QCOM_COMMAND_DB) += cmd-db.o obj-$(CONFIG_QCOM_COMMAND_DB) += cmd-db.o
obj-$(CONFIG_QCOM_GLINK_SSR) += glink_ssr.o
obj-$(CONFIG_QCOM_GSBI) += qcom_gsbi.o obj-$(CONFIG_QCOM_GSBI) += qcom_gsbi.o
obj-$(CONFIG_QCOM_MDT_LOADER) += mdt_loader.o obj-$(CONFIG_QCOM_MDT_LOADER) += mdt_loader.o
obj-$(CONFIG_QCOM_OCMEM) += ocmem.o obj-$(CONFIG_QCOM_OCMEM) += ocmem.o
......
...@@ -73,7 +73,7 @@ struct resource_table { ...@@ -73,7 +73,7 @@ struct resource_table {
u32 ver; u32 ver;
u32 num; u32 num;
u32 reserved[2]; u32 reserved[2];
u32 offset[0]; u32 offset[];
} __packed; } __packed;
/** /**
...@@ -87,7 +87,7 @@ struct resource_table { ...@@ -87,7 +87,7 @@ struct resource_table {
*/ */
struct fw_rsc_hdr { struct fw_rsc_hdr {
u32 type; u32 type;
u8 data[0]; u8 data[];
} __packed; } __packed;
/** /**
...@@ -306,7 +306,7 @@ struct fw_rsc_vdev { ...@@ -306,7 +306,7 @@ struct fw_rsc_vdev {
u8 status; u8 status;
u8 num_of_vrings; u8 num_of_vrings;
u8 reserved[2]; u8 reserved[2];
struct fw_rsc_vdev_vring vring[0]; struct fw_rsc_vdev_vring vring[];
} __packed; } __packed;
struct rproc; struct rproc;
...@@ -355,6 +355,8 @@ enum rsc_handling_status { ...@@ -355,6 +355,8 @@ enum rsc_handling_status {
/** /**
* struct rproc_ops - platform-specific device handlers * struct rproc_ops - platform-specific device handlers
* @prepare: prepare device for code loading
* @unprepare: unprepare device after stop
* @start: power on the device and boot it * @start: power on the device and boot it
* @stop: power off the device * @stop: power off the device
* @kick: kick a virtqueue (virtqueue id given as a parameter) * @kick: kick a virtqueue (virtqueue id given as a parameter)
...@@ -373,6 +375,8 @@ enum rsc_handling_status { ...@@ -373,6 +375,8 @@ enum rsc_handling_status {
* panic at least the returned number of milliseconds * panic at least the returned number of milliseconds
*/ */
struct rproc_ops { struct rproc_ops {
int (*prepare)(struct rproc *rproc);
int (*unprepare)(struct rproc *rproc);
int (*start)(struct rproc *rproc); int (*start)(struct rproc *rproc);
int (*stop)(struct rproc *rproc); int (*stop)(struct rproc *rproc);
void (*kick)(struct rproc *rproc, int vqid); void (*kick)(struct rproc *rproc, int vqid);
...@@ -489,7 +493,7 @@ struct rproc { ...@@ -489,7 +493,7 @@ struct rproc {
struct list_head node; struct list_head node;
struct iommu_domain *domain; struct iommu_domain *domain;
const char *name; const char *name;
char *firmware; const char *firmware;
void *priv; void *priv;
struct rproc_ops *ops; struct rproc_ops *ops;
struct device dev; struct device dev;
...@@ -518,6 +522,7 @@ struct rproc { ...@@ -518,6 +522,7 @@ struct rproc {
struct list_head dump_segments; struct list_head dump_segments;
int nb_vdev; int nb_vdev;
u8 elf_class; u8 elf_class;
u16 elf_machine;
}; };
/** /**
...@@ -599,6 +604,11 @@ int rproc_add(struct rproc *rproc); ...@@ -599,6 +604,11 @@ int rproc_add(struct rproc *rproc);
int rproc_del(struct rproc *rproc); int rproc_del(struct rproc *rproc);
void rproc_free(struct rproc *rproc); void rproc_free(struct rproc *rproc);
struct rproc *devm_rproc_alloc(struct device *dev, const char *name,
const struct rproc_ops *ops,
const char *firmware, int len);
int devm_rproc_add(struct device *dev, struct rproc *rproc);
void rproc_add_carveout(struct rproc *rproc, struct rproc_mem_entry *mem); void rproc_add_carveout(struct rproc *rproc, struct rproc_mem_entry *mem);
struct rproc_mem_entry * struct rproc_mem_entry *
...@@ -622,6 +632,7 @@ int rproc_coredump_add_custom_segment(struct rproc *rproc, ...@@ -622,6 +632,7 @@ int rproc_coredump_add_custom_segment(struct rproc *rproc,
struct rproc_dump_segment *segment, struct rproc_dump_segment *segment,
void *dest), void *dest),
void *priv); void *priv);
int rproc_coredump_set_elf_info(struct rproc *rproc, u8 class, u16 machine);
static inline struct rproc_vdev *vdev_to_rvdev(struct virtio_device *vdev) static inline struct rproc_vdev *vdev_to_rvdev(struct virtio_device *vdev)
{ {
......
...@@ -12,6 +12,7 @@ struct qcom_glink; ...@@ -12,6 +12,7 @@ struct qcom_glink;
struct qcom_glink *qcom_glink_smem_register(struct device *parent, struct qcom_glink *qcom_glink_smem_register(struct device *parent,
struct device_node *node); struct device_node *node);
void qcom_glink_smem_unregister(struct qcom_glink *glink); void qcom_glink_smem_unregister(struct qcom_glink *glink);
void qcom_glink_ssr_notify(const char *ssr_name);
#else #else
...@@ -23,7 +24,7 @@ qcom_glink_smem_register(struct device *parent, ...@@ -23,7 +24,7 @@ qcom_glink_smem_register(struct device *parent,
} }
static inline void qcom_glink_smem_unregister(struct qcom_glink *glink) {} static inline void qcom_glink_smem_unregister(struct qcom_glink *glink) {}
static inline void qcom_glink_ssr_notify(const char *ssr_name) {}
#endif #endif
#endif #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment