Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d832a023 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "soc: qcom: Add generic irq handler for secure processor"

parents 6d911f05 2c848e14
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -61,6 +61,9 @@ Optional properties:
- qcom,sysmon-id:	platform device id that sysmon is probed with for the subsystem.
- qcom,pil-force-shutdown: Boolean. If set, the SSR framework will not trigger graceful shutdown
                           on behalf of the subsystem driver.
- qcom,pil-generic-irq-handler: generic interrupt handler used for communication with subsytem
				based on bit values in scsr registers.
- qcom,spss-scsr-bits: array of bit positions into the scsr registers used in generic handler.

Example:
	qcom,venus@fdce0000 {
+86 −4
Original line number Diff line number Diff line
@@ -40,6 +40,15 @@
#define STOP_ACK_TIMEOUT_MS	1000
#define CRASH_STOP_ACK_TO_MS	200

#define COLD_BOOT_DONE	0
#define GDSC_DONE	1
#define RAM_WIPE_DONE	2
#define CPU_BOOT_DONE	3
#define WDOG_BITE	4
#define CLR_WDOG_BITE	5
#define ERR_READY	6
#define PBL_DONE	7

#define desc_to_data(d) container_of(d, struct pil_tz_data, desc)
#define subsys_to_data(d) container_of(d, struct pil_tz_data, subsys_desc)

@@ -80,6 +89,7 @@ struct reg_info {
 * @desc: PIL descriptor
 * @subsys: subsystem device pointer
 * @subsys_desc: subsystem descriptor
 * @u32 bits_arr[8]: array of bit positions in SCSR registers
 */
struct pil_tz_data {
	struct reg_info *regs;
@@ -100,6 +110,11 @@ struct pil_tz_data {
	struct pil_desc desc;
	struct subsys_device *subsys;
	struct subsys_desc subsys_desc;
	void __iomem *irq_status;
	void __iomem *irq_clear;
	void __iomem *irq_mask;
	void __iomem *err_status;
	u32 bits_arr[8];
};

enum scm_cmd {
@@ -896,9 +911,54 @@ static irqreturn_t subsys_stop_ack_intr_handler(int irq, void *dev_id)
	return IRQ_HANDLED;
}

static irqreturn_t subsys_generic_handler(int irq, void *dev_id)
{
	struct pil_tz_data *d = subsys_to_data(dev_id);
	uint32_t status_val, clear_val, err_value;

	if (subsys_get_crash_status(d->subsys))
		return IRQ_HANDLED;

	/* Masking interrupts not handled by HLOS */
	clear_val = __raw_readl(d->irq_mask);
	__raw_writel(clear_val | BIT(d->bits_arr[COLD_BOOT_DONE]) |
		BIT(d->bits_arr[GDSC_DONE]) | BIT(d->bits_arr[RAM_WIPE_DONE]) |
		BIT(d->bits_arr[CPU_BOOT_DONE]), d->irq_mask);
	status_val = __raw_readl(d->irq_status);

	if (status_val & BIT(d->bits_arr[WDOG_BITE])) {
		pr_err("wdog bite received from %s!\n", d->subsys_desc.name);
		clear_val = __raw_readl(d->irq_clear);
		__raw_writel(clear_val | BIT(d->bits_arr[CLR_WDOG_BITE]),
							d->irq_clear);
		subsys_set_crash_status(d->subsys, true);
		log_failure_reason(d);
		subsystem_restart_dev(d->subsys);
	} else if (status_val & BIT(d->bits_arr[ERR_READY])) {
		pr_debug("Subsystem error services up received from %s!\n",
							d->subsys_desc.name);
		clear_val = __raw_readl(d->irq_clear);
		__raw_writel(clear_val | BIT(d->bits_arr[ERR_READY]),
							d->irq_clear);
		complete_err_ready(d->subsys);
	} else if (status_val & BIT(d->bits_arr[PBL_DONE])) {
		err_value =  __raw_readl(d->err_status);
		pr_debug("PBL_DONE received from %s!\n",
							d->subsys_desc.name);
		if (!err_value) {
			clear_val = __raw_readl(d->irq_clear);
			__raw_writel(clear_val | BIT(d->bits_arr[PBL_DONE]),
							d->irq_clear);
		} else
			pr_err("SP-PBL rmb error status: 0x%08x\n", err_value);
	}
	return IRQ_HANDLED;
}

static int pil_tz_driver_probe(struct platform_device *pdev)
{
	struct pil_tz_data *d;
	struct resource *res;
	u32 proxy_timeout;
	int len, rc;

@@ -969,10 +1029,32 @@ static int pil_tz_driver_probe(struct platform_device *pdev)
	d->subsys_desc.ramdump = subsys_ramdump;
	d->subsys_desc.free_memory = subsys_free_memory;
	d->subsys_desc.crash_shutdown = subsys_crash_shutdown;
	d->subsys_desc.err_fatal_handler = subsys_err_fatal_intr_handler;
	if (of_property_read_bool(pdev->dev.of_node,
					"qcom,pil-generic-irq-handler")) {
		d->subsys_desc.generic_handler = subsys_generic_handler;
		res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
						"sp2soc_irq_status");
		d->irq_status = devm_ioremap_resource(&pdev->dev, res);
		res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
						"sp2soc_irq_clr");
		d->irq_clear = devm_ioremap_resource(&pdev->dev, res);
		res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
						"sp2soc_irq_mask");
		d->irq_mask = devm_ioremap_resource(&pdev->dev, res);
		res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
						"rmb_err");
		d->err_status = devm_ioremap_resource(&pdev->dev, res);
		rc = of_property_read_u32_array(pdev->dev.of_node,
		       "qcom,spss-scsr-bits", d->bits_arr, sizeof(d->bits_arr)/
							sizeof(d->bits_arr[0]));
		if (rc)
			dev_err(&pdev->dev, "Failed to read qcom,spss-scsr-bits");
	} else {
		d->subsys_desc.err_fatal_handler =
						subsys_err_fatal_intr_handler;
		d->subsys_desc.wdog_bite_handler = subsys_wdog_bite_irq_handler;
		d->subsys_desc.stop_ack_handler = subsys_stop_ack_intr_handler;

	}
	d->ramdump_dev = create_ramdump_device(d->subsys_desc.name,
								&pdev->dev);
	if (!d->ramdump_dev) {
+38 −1
Original line number Diff line number Diff line
@@ -184,6 +184,11 @@ static struct subsys_device *to_subsys(struct device *d)
	return container_of(d, struct subsys_device, dev);
}

void complete_err_ready(struct subsys_device *subsys)
{
	complete(&subsys->err_ready);
}

static struct subsys_tracking *subsys_get_track(struct subsys_device *subsys)
{
	struct subsys_soc_restart_order *order = subsys->restart_order;
@@ -538,6 +543,10 @@ static void enable_all_irqs(struct subsys_device *dev)
		enable_irq(dev->desc->err_fatal_irq);
	if (dev->desc->stop_ack_irq && dev->desc->stop_ack_handler)
		enable_irq(dev->desc->stop_ack_irq);
	if (dev->desc->generic_irq && dev->desc->generic_handler) {
		enable_irq(dev->desc->generic_irq);
		irq_set_irq_wake(dev->desc->generic_irq, 1);
	}
}

static void disable_all_irqs(struct subsys_device *dev)
@@ -552,6 +561,10 @@ static void disable_all_irqs(struct subsys_device *dev)
		disable_irq(dev->desc->err_fatal_irq);
	if (dev->desc->stop_ack_irq && dev->desc->stop_ack_handler)
		disable_irq(dev->desc->stop_ack_irq);
	if (dev->desc->generic_irq && dev->desc->generic_handler) {
		disable_irq(dev->desc->generic_irq);
		irq_set_irq_wake(dev->desc->generic_irq, 0);
	}
}

int wait_for_shutdown_ack(struct subsys_desc *desc)
@@ -577,7 +590,12 @@ static int wait_for_err_ready(struct subsys_device *subsys)
{
	int ret;

	if (!subsys->desc->err_ready_irq || enable_debug == 1)
	/*
	 * If subsys is using generic_irq in which case err_ready_irq will be 0,
	 * don't return.
	 */
	if ((subsys->desc->generic_irq <= 0 && !subsys->desc->err_ready_irq)
							|| enable_debug == 1)
		return 0;

	ret = wait_for_completion_timeout(&subsys->err_ready,
@@ -1475,6 +1493,13 @@ static int subsys_parse_devicetree(struct subsys_desc *desc)
	if (ret > 0)
		desc->wdog_bite_irq = ret;

	if (of_property_read_bool(pdev->dev.of_node,
					"qcom,pil-generic-irq-handler")) {
		ret = platform_get_irq(pdev, 0);
		if (ret > 0)
			desc->generic_irq = ret;
	}

	order = ssr_parse_restart_orders(desc);
	if (IS_ERR(order)) {
		pr_err("Could not initialize SSR restart order, err = %ld\n",
@@ -1526,6 +1551,18 @@ static int subsys_setup_irqs(struct subsys_device *subsys)
		disable_irq(desc->wdog_bite_irq);
	}

	if (desc->generic_irq && desc->generic_handler) {
		ret = devm_request_irq(desc->dev, desc->generic_irq,
			desc->generic_handler,
			IRQF_TRIGGER_HIGH, desc->name, desc);
		if (ret < 0) {
			dev_err(desc->dev, "[%s]: Unable to register generic irq handler!: %d\n",
				desc->name, ret);
			return ret;
		}
		disable_irq(desc->generic_irq);
	}

	if (desc->err_ready_irq) {
		ret = devm_request_irq(desc->dev,
					desc->err_ready_irq,
+3 −0
Original line number Diff line number Diff line
@@ -66,12 +66,14 @@ struct subsys_desc {
	irqreturn_t (*err_fatal_handler) (int irq, void *dev_id);
	irqreturn_t (*stop_ack_handler) (int irq, void *dev_id);
	irqreturn_t (*wdog_bite_handler) (int irq, void *dev_id);
	irqreturn_t (*generic_handler)(int irq, void *dev_id);
	int is_not_loadable;
	int err_fatal_gpio;
	unsigned int err_fatal_irq;
	unsigned int err_ready_irq;
	unsigned int stop_ack_irq;
	unsigned int wdog_bite_irq;
	unsigned int generic_irq;
	int force_stop_gpio;
	int ramdump_disable_gpio;
	int shutdown_ack_gpio;
@@ -120,6 +122,7 @@ extern void subsys_set_crash_status(struct subsys_device *dev, bool crashed);
extern bool subsys_get_crash_status(struct subsys_device *dev);
void notify_proxy_vote(struct device *device);
void notify_proxy_unvote(struct device *device);
void complete_err_ready(struct subsys_device *subsys);
extern int wait_for_shutdown_ack(struct subsys_desc *desc);
#else