From patchwork Tue Jun 13 23:45:12 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Suman Anna X-Patchwork-Id: 105450 Delivered-To: patch@linaro.org Received: by 10.140.91.77 with SMTP id y71csp42783qgd; Tue, 13 Jun 2017 16:46:20 -0700 (PDT) X-Received: by 10.99.123.27 with SMTP id w27mr1690584pgc.6.1497397580265; Tue, 13 Jun 2017 16:46:20 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1497397580; cv=none; d=google.com; s=arc-20160816; b=OOX8bZxseWt3eDQnPiO1frgwp5vVnUT/o1k3GQXX1rZLR7legKrmEzVQ2GQt0I9pkW JmGGxxM8dHfSoUdal9L8coBMCSzLw9rwUvu812Qo3JaUwMM8Aiso687sr5Z9VIrNIkYC bKqYC7dgdB9JjVeP4hrwny40z4se325ZOv8aZYgIXnB6eTNmytEEBG4sU4UlKcqhUFPt cO3VfsGgkD9XrKRHZWwvdEhV7QfFhK2GT/qQxMr6ltA7ybK5Bo6aQim5KLJWn7LMAv3I 62qWHQwlxX7B8cTCANtcUtesRAYb338Zj0WQNIFQbhAAE955jpan8q6+EiKjFo7HkiSl +00g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:dkim-signature :arc-authentication-results; bh=r9xkDfbICiyDnt8dW2V84sa04fzCjdVV/wXzV6JMNFI=; b=LyWzFwTpY1Kzp7nZ/4ywjch2seG+ECZoWkWFWpUAcLhwcpUrTbTxdzPCqF3nnReQfu SY25DufrRtLmybcFcw1RsYFhPPvKWCWfixK6WgNFmtIsB5quXu1o6FnAi+Lf/edQ17Hk UW5mMVEhXEyuHI365gVMrSXjELHziL4TLc4NNgk7YidgPEc1I2suQElsP3vZbdZyaXpu Z/+Nh/KkvaW59GlZb+SsqfkzFx9/PmrSv4+h9qLD3wImVmaS/PCMOgvVrSiyksbkiZtI 8GVX9E03XGUa7D0Fcvw0BXnSXPdrKVZnjN4uqhWxzJPIZL9isckkfBuvLvUJC/VosKey w6qA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@ti.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=QUARANTINE sp=NONE dis=NONE) header.from=ti.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id a25si919133pfe.264.2017.06.13.16.46.19; Tue, 13 Jun 2017 16:46:20 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@ti.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=QUARANTINE sp=NONE dis=NONE) header.from=ti.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754046AbdFMXqC (ORCPT + 25 others); Tue, 13 Jun 2017 19:46:02 -0400 Received: from lelnx193.ext.ti.com ([198.47.27.77]:45714 "EHLO lelnx193.ext.ti.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753870AbdFMXps (ORCPT ); Tue, 13 Jun 2017 19:45:48 -0400 Received: from dlelxv90.itg.ti.com ([172.17.2.17]) by lelnx193.ext.ti.com (8.15.1/8.15.1) with ESMTP id v5DNjFh0012836; Tue, 13 Jun 2017 18:45:15 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ti.com; s=ti-com-17Q1; t=1497397515; bh=fFn32UEg3jVF00unBapSaTZNIA6wjwQOP3YAmfupJw0=; h=From:To:CC:Subject:Date:In-Reply-To:References; b=BE150owTwbsSG+rHsi6nbdoHELRVH+b6KNv69a/kDyMT9dbSRCM3t+Y+LFc0FMJ+Z B85b6qf6Ih7kW43+vLIsNwJYwsTa3N9O/xA6pOQf+Btp/YiA1IftbsKCVqVe4x0ssE Mag7mZZSuKKQ+/J3xsSRG3oNL5mP7tOuzukl/8nQ= Received: from DLEE70.ent.ti.com (dlee70.ent.ti.com [157.170.170.113]) by dlelxv90.itg.ti.com (8.14.3/8.13.8) with ESMTP id v5DNjFDh021858; Tue, 13 Jun 2017 18:45:15 -0500 Received: from dflp32.itg.ti.com (10.64.6.15) by DLEE70.ent.ti.com (157.170.170.113) with Microsoft SMTP Server id 14.3.294.0; Tue, 13 Jun 2017 18:45:14 -0500 Received: from legion.dal.design.ti.com (legion.dal.design.ti.com [128.247.22.53]) by dflp32.itg.ti.com (8.14.3/8.13.8) with ESMTP id v5DNjEel001938; Tue, 13 Jun 2017 18:45:15 -0500 Received: from localhost (irmo.dhcp.ti.com [128.247.58.153]) by legion.dal.design.ti.com (8.11.7p1+Sun/8.11.7) with ESMTP id v5DNjE323325; Tue, 13 Jun 2017 18:45:14 -0500 (CDT) From: Suman Anna To: Bjorn Andersson , Ohad Ben-Cohen CC: Rob Herring , Santosh Shilimkar , Mark Rutland , , , , , Suman Anna , "Andrew F. Davis" , Sam Nelson Subject: [PATCH v3 2/3] remoteproc/keystone: Add a remoteproc driver for Keystone 2 DSPs Date: Tue, 13 Jun 2017 18:45:12 -0500 Message-ID: <20170613234513.7624-3-s-anna@ti.com> X-Mailer: git-send-email 2.13.1 In-Reply-To: <20170613234513.7624-1-s-anna@ti.com> References: <20170613234513.7624-1-s-anna@ti.com> MIME-Version: 1.0 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The Texas Instrument's Keystone 2 family of SoCs has 1 or more TMS320C66x DSP Core Subsystems (C66x CorePacs). Each subsystem has a C66x Fixed/Floating-Point DSP Core, with 32KB of L1P and L1D SRAMs, that can be configured and partitioned as either RAM and/or Cache, and 1 MB of L2 SRAM. The CorePac also includes an Internal DMA (IDMA), External Memory Controller (EMC), Extended Memory Controller (XMC) with a Memory Protection and Address Extension (MPAX) unit, a Bandwidth Management (BWM) unit, an Interrupt Controller (INTC) and a Powerdown Controller (PDC). A new remoteproc module is added to perform the device management of these DSP devices. The driver expects the firmware names to be of the form "keystone-dsp-fw", where X is the corresponding DSP number, and uses the standard remoteproc core ELF loader. The support is limited to images only using the DSP internal memories at the moment. This remoteproc driver is also designed to work with virtio, and uses the IPC Generation registers for performing the virtio signalling and getting notified of exceptions. The driver currently supports the 66AK2H/66AK2K, 66AK2L and 66AK2E SoCs. Signed-off-by: Suman Anna Signed-off-by: Sam Nelson Signed-off-by: Andrew F. Davis Acked-by: Santosh Shilimkar --- v3: No code changes, picked up Santosh's Ack v2: https://patchwork.kernel.org/patch/9773685/ drivers/remoteproc/Kconfig | 13 + drivers/remoteproc/Makefile | 1 + drivers/remoteproc/keystone_remoteproc.c | 515 +++++++++++++++++++++++++++++++ 3 files changed, 529 insertions(+) create mode 100644 drivers/remoteproc/keystone_remoteproc.c -- 2.13.1 diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig index faad69a1a597..9839b35b6ab3 100644 --- a/drivers/remoteproc/Kconfig +++ b/drivers/remoteproc/Kconfig @@ -71,6 +71,19 @@ config DA8XX_REMOTEPROC It's safe to say n here if you're not interested in multimedia offloading. +config KEYSTONE_REMOTEPROC + tristate "Keystone Remoteproc support" + depends on ARCH_KEYSTONE + depends on RESET_CONTROLLER + depends on REMOTEPROC + select RPMSG_VIRTIO + help + Say Y here here to support Keystone remote processors (DSP) + via the remote processor framework. + + It's safe to say N here if you're not interested in the Keystone + DSPs or just want to use a bare minimum kernel. + config QCOM_ADSP_PIL tristate "Qualcomm ADSP Peripheral Image Loader" depends on OF && ARCH_QCOM diff --git a/drivers/remoteproc/Makefile b/drivers/remoteproc/Makefile index ffc5e430df27..f1ce5fc8a2f3 100644 --- a/drivers/remoteproc/Makefile +++ b/drivers/remoteproc/Makefile @@ -11,6 +11,7 @@ remoteproc-y += remoteproc_elf_loader.o obj-$(CONFIG_OMAP_REMOTEPROC) += omap_remoteproc.o obj-$(CONFIG_WKUP_M3_RPROC) += wkup_m3_rproc.o obj-$(CONFIG_DA8XX_REMOTEPROC) += da8xx_remoteproc.o +obj-$(CONFIG_KEYSTONE_REMOTEPROC) += keystone_remoteproc.o obj-$(CONFIG_QCOM_ADSP_PIL) += qcom_adsp_pil.o obj-$(CONFIG_QCOM_RPROC_COMMON) += qcom_common.o obj-$(CONFIG_QCOM_Q6V5_PIL) += qcom_q6v5_pil.o diff --git a/drivers/remoteproc/keystone_remoteproc.c b/drivers/remoteproc/keystone_remoteproc.c new file mode 100644 index 000000000000..6e09ef76f7c7 --- /dev/null +++ b/drivers/remoteproc/keystone_remoteproc.c @@ -0,0 +1,515 @@ +/* + * TI Keystone DSP remoteproc driver + * + * Copyright (C) 2015-2017 Texas Instruments Incorporated - http://www.ti.com/ + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "remoteproc_internal.h" + +#define KEYSTONE_RPROC_LOCAL_ADDRESS_MASK (SZ_16M - 1) + +/** + * struct keystone_rproc_mem - internal memory structure + * @cpu_addr: MPU virtual address of the memory region + * @bus_addr: Bus address used to access the memory region + * @dev_addr: Device address of the memory region from DSP view + * @size: Size of the memory region + */ +struct keystone_rproc_mem { + void __iomem *cpu_addr; + phys_addr_t bus_addr; + u32 dev_addr; + size_t size; +}; + +/** + * struct keystone_rproc - keystone remote processor driver structure + * @dev: cached device pointer + * @rproc: remoteproc device handle + * @mem: internal memory regions data + * @num_mems: number of internal memory regions + * @dev_ctrl: device control regmap handle + * @reset: reset control handle + * @boot_offset: boot register offset in @dev_ctrl regmap + * @irq_ring: irq entry for vring + * @irq_fault: irq entry for exception + * @kick_gpio: gpio used for virtio kicks + * @workqueue: workqueue for processing virtio interrupts + */ +struct keystone_rproc { + struct device *dev; + struct rproc *rproc; + struct keystone_rproc_mem *mem; + int num_mems; + struct regmap *dev_ctrl; + struct reset_control *reset; + u32 boot_offset; + int irq_ring; + int irq_fault; + int kick_gpio; + struct work_struct workqueue; +}; + +/* Put the DSP processor into reset */ +static void keystone_rproc_dsp_reset(struct keystone_rproc *ksproc) +{ + reset_control_assert(ksproc->reset); +} + +/* Configure the boot address and boot the DSP processor */ +static int keystone_rproc_dsp_boot(struct keystone_rproc *ksproc, u32 boot_addr) +{ + int ret; + + if (boot_addr & (SZ_1K - 1)) { + dev_err(ksproc->dev, "invalid boot address 0x%x, must be aligned on a 1KB boundary\n", + boot_addr); + return -EINVAL; + } + + ret = regmap_write(ksproc->dev_ctrl, ksproc->boot_offset, boot_addr); + if (ret) { + dev_err(ksproc->dev, "regmap_write of boot address failed, status = %d\n", + ret); + return ret; + } + + reset_control_deassert(ksproc->reset); + + return 0; +} + +/* + * Process the remoteproc exceptions + * + * The exception reporting on Keystone DSP remote processors is very simple + * compared to the equivalent processors on the OMAP family, it is notified + * through a software-designed specific interrupt source in the IPC interrupt + * generation register. + * + * This function just invokes the rproc_report_crash to report the exception + * to the remoteproc driver core, to trigger a recovery. + */ +static irqreturn_t keystone_rproc_exception_interrupt(int irq, void *dev_id) +{ + struct keystone_rproc *ksproc = dev_id; + + rproc_report_crash(ksproc->rproc, RPROC_FATAL_ERROR); + + return IRQ_HANDLED; +} + +/* + * Main virtqueue message workqueue function + * + * This function is executed upon scheduling of the keystone remoteproc + * driver's workqueue. The workqueue is scheduled by the vring ISR handler. + * + * There is no payload message indicating the virtqueue index as is the + * case with mailbox-based implementations on OMAP family. As such, this + * handler processes both the Tx and Rx virtqueue indices on every invocation. + * The rproc_vq_interrupt function can detect if there are new unprocessed + * messages or not (returns IRQ_NONE vs IRQ_HANDLED), but there is no need + * to check for these return values. The index 0 triggering will process all + * pending Rx buffers, and the index 1 triggering will process all newly + * available Tx buffers and will wakeup any potentially blocked senders. + * + * NOTE: + * 1. A payload could be added by using some of the source bits in the + * IPC interrupt generation registers, but this would need additional + * changes to the overall IPC stack, and currently there are no benefits + * of adapting that approach. + * 2. The current logic is based on an inherent design assumption of supporting + * only 2 vrings, but this can be changed if needed. + */ +static void handle_event(struct work_struct *work) +{ + struct keystone_rproc *ksproc = + container_of(work, struct keystone_rproc, workqueue); + + rproc_vq_interrupt(ksproc->rproc, 0); + rproc_vq_interrupt(ksproc->rproc, 1); +} + +/* + * Interrupt handler for processing vring kicks from remote processor + */ +static irqreturn_t keystone_rproc_vring_interrupt(int irq, void *dev_id) +{ + struct keystone_rproc *ksproc = dev_id; + + schedule_work(&ksproc->workqueue); + + return IRQ_HANDLED; +} + +/* + * Power up the DSP remote processor. + * + * This function will be invoked only after the firmware for this rproc + * was loaded, parsed successfully, and all of its resource requirements + * were met. + */ +static int keystone_rproc_start(struct rproc *rproc) +{ + struct keystone_rproc *ksproc = rproc->priv; + int ret; + + INIT_WORK(&ksproc->workqueue, handle_event); + + ret = request_irq(ksproc->irq_ring, keystone_rproc_vring_interrupt, 0, + dev_name(ksproc->dev), ksproc); + if (ret) { + dev_err(ksproc->dev, "failed to enable vring interrupt, ret = %d\n", + ret); + goto out; + } + + ret = request_irq(ksproc->irq_fault, keystone_rproc_exception_interrupt, + 0, dev_name(ksproc->dev), ksproc); + if (ret) { + dev_err(ksproc->dev, "failed to enable exception interrupt, ret = %d\n", + ret); + goto free_vring_irq; + } + + ret = keystone_rproc_dsp_boot(ksproc, rproc->bootaddr); + if (ret) + goto free_exc_irq; + + return 0; + +free_exc_irq: + free_irq(ksproc->irq_fault, ksproc); +free_vring_irq: + free_irq(ksproc->irq_ring, ksproc); + flush_work(&ksproc->workqueue); +out: + return ret; +} + +/* + * Stop the DSP remote processor. + * + * This function puts the DSP processor into reset, and finishes processing + * of any pending messages. + */ +static int keystone_rproc_stop(struct rproc *rproc) +{ + struct keystone_rproc *ksproc = rproc->priv; + + keystone_rproc_dsp_reset(ksproc); + free_irq(ksproc->irq_fault, ksproc); + free_irq(ksproc->irq_ring, ksproc); + flush_work(&ksproc->workqueue); + + return 0; +} + +/* + * Kick the remote processor to notify about pending unprocessed messages. + * The vqid usage is not used and is inconsequential, as the kick is performed + * through a simulated GPIO (a bit in an IPC interrupt-triggering register), + * the remote processor is expected to process both its Tx and Rx virtqueues. + */ +static void keystone_rproc_kick(struct rproc *rproc, int vqid) +{ + struct keystone_rproc *ksproc = rproc->priv; + + if (WARN_ON(ksproc->kick_gpio < 0)) + return; + + gpio_set_value(ksproc->kick_gpio, 1); +} + +/* + * Custom function to translate a DSP device address (internal RAMs only) to a + * kernel virtual address. The DSPs can access their RAMs at either an internal + * address visible only from a DSP, or at the SoC-level bus address. Both these + * addresses need to be looked through for translation. The translated addresses + * can be used either by the remoteproc core for loading (when using kernel + * remoteproc loader), or by any rpmsg bus drivers. + */ +static void *keystone_rproc_da_to_va(struct rproc *rproc, u64 da, int len) +{ + struct keystone_rproc *ksproc = rproc->priv; + void __iomem *va = NULL; + phys_addr_t bus_addr; + u32 dev_addr, offset; + size_t size; + int i; + + if (len <= 0) + return NULL; + + for (i = 0; i < ksproc->num_mems; i++) { + bus_addr = ksproc->mem[i].bus_addr; + dev_addr = ksproc->mem[i].dev_addr; + size = ksproc->mem[i].size; + + if (da < KEYSTONE_RPROC_LOCAL_ADDRESS_MASK) { + /* handle DSP-view addresses */ + if ((da >= dev_addr) && + ((da + len) <= (dev_addr + size))) { + offset = da - dev_addr; + va = ksproc->mem[i].cpu_addr + offset; + break; + } + } else { + /* handle SoC-view addresses */ + if ((da >= bus_addr) && + (da + len) <= (bus_addr + size)) { + offset = da - bus_addr; + va = ksproc->mem[i].cpu_addr + offset; + break; + } + } + } + + return (__force void *)va; +} + +static const struct rproc_ops keystone_rproc_ops = { + .start = keystone_rproc_start, + .stop = keystone_rproc_stop, + .kick = keystone_rproc_kick, + .da_to_va = keystone_rproc_da_to_va, +}; + +static int keystone_rproc_of_get_memories(struct platform_device *pdev, + struct keystone_rproc *ksproc) +{ + static const char * const mem_names[] = {"l2sram", "l1pram", "l1dram"}; + struct device *dev = &pdev->dev; + struct resource *res; + int num_mems = 0; + int i; + + num_mems = ARRAY_SIZE(mem_names); + ksproc->mem = devm_kcalloc(ksproc->dev, num_mems, + sizeof(*ksproc->mem), GFP_KERNEL); + if (!ksproc->mem) + return -ENOMEM; + + for (i = 0; i < num_mems; i++) { + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, + mem_names[i]); + ksproc->mem[i].cpu_addr = devm_ioremap_resource(dev, res); + if (IS_ERR(ksproc->mem[i].cpu_addr)) { + dev_err(dev, "failed to parse and map %s memory\n", + mem_names[i]); + return PTR_ERR(ksproc->mem[i].cpu_addr); + } + ksproc->mem[i].bus_addr = res->start; + ksproc->mem[i].dev_addr = + res->start & KEYSTONE_RPROC_LOCAL_ADDRESS_MASK; + ksproc->mem[i].size = resource_size(res); + + /* zero out memories to start in a pristine state */ + memset((__force void *)ksproc->mem[i].cpu_addr, 0, + ksproc->mem[i].size); + } + ksproc->num_mems = num_mems; + + return 0; +} + +static int keystone_rproc_of_get_dev_syscon(struct platform_device *pdev, + struct keystone_rproc *ksproc) +{ + struct device_node *np = pdev->dev.of_node; + struct device *dev = &pdev->dev; + int ret; + + if (!of_property_read_bool(np, "ti,syscon-dev")) { + dev_err(dev, "ti,syscon-dev property is absent\n"); + return -EINVAL; + } + + ksproc->dev_ctrl = + syscon_regmap_lookup_by_phandle(np, "ti,syscon-dev"); + if (IS_ERR(ksproc->dev_ctrl)) { + ret = PTR_ERR(ksproc->dev_ctrl); + return ret; + } + + if (of_property_read_u32_index(np, "ti,syscon-dev", 1, + &ksproc->boot_offset)) { + dev_err(dev, "couldn't read the boot register offset\n"); + return -EINVAL; + } + + return 0; +} + +static int keystone_rproc_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + struct keystone_rproc *ksproc; + struct rproc *rproc; + int dsp_id; + char *fw_name = NULL; + char *template = "keystone-dsp%d-fw"; + int name_len = 0; + int ret = 0; + + if (!np) { + dev_err(dev, "only DT-based devices are supported\n"); + return -ENODEV; + } + + dsp_id = of_alias_get_id(np, "rproc"); + if (dsp_id < 0) { + dev_warn(dev, "device does not have an alias id\n"); + return dsp_id; + } + + /* construct a custom default fw name - subject to change in future */ + name_len = strlen(template); /* assuming a single digit alias */ + fw_name = devm_kzalloc(dev, name_len, GFP_KERNEL); + if (!fw_name) + return -ENOMEM; + snprintf(fw_name, name_len, template, dsp_id); + + rproc = rproc_alloc(dev, dev_name(dev), &keystone_rproc_ops, fw_name, + sizeof(*ksproc)); + if (!rproc) + return -ENOMEM; + + rproc->has_iommu = false; + ksproc = rproc->priv; + ksproc->rproc = rproc; + ksproc->dev = dev; + + ret = keystone_rproc_of_get_dev_syscon(pdev, ksproc); + if (ret) + goto free_rproc; + + ksproc->reset = devm_reset_control_get(dev, NULL); + if (IS_ERR(ksproc->reset)) { + ret = PTR_ERR(ksproc->reset); + goto free_rproc; + } + + /* enable clock for accessing DSP internal memories */ + pm_runtime_enable(dev); + ret = pm_runtime_get_sync(dev); + if (ret < 0) { + dev_err(dev, "failed to enable clock, status = %d\n", ret); + pm_runtime_put_noidle(dev); + goto disable_rpm; + } + + ret = keystone_rproc_of_get_memories(pdev, ksproc); + if (ret) + goto disable_clk; + + ksproc->irq_ring = platform_get_irq_byname(pdev, "vring"); + if (ksproc->irq_ring < 0) { + ret = ksproc->irq_ring; + dev_err(dev, "failed to get vring interrupt, status = %d\n", + ret); + goto disable_clk; + } + + ksproc->irq_fault = platform_get_irq_byname(pdev, "exception"); + if (ksproc->irq_fault < 0) { + ret = ksproc->irq_fault; + dev_err(dev, "failed to get exception interrupt, status = %d\n", + ret); + goto disable_clk; + } + + ksproc->kick_gpio = of_get_named_gpio_flags(np, "kick-gpios", 0, NULL); + if (ksproc->kick_gpio < 0) { + ret = ksproc->kick_gpio; + dev_err(dev, "failed to get gpio for virtio kicks, status = %d\n", + ret); + goto disable_clk; + } + + if (of_reserved_mem_device_init(dev)) + dev_warn(dev, "device does not have specific CMA pool\n"); + + ret = rproc_add(rproc); + if (ret) { + dev_err(dev, "failed to add register device with remoteproc core, status = %d\n", + ret); + goto release_mem; + } + + platform_set_drvdata(pdev, ksproc); + + return 0; + +release_mem: + of_reserved_mem_device_release(dev); +disable_clk: + pm_runtime_put_sync(dev); +disable_rpm: + pm_runtime_disable(dev); +free_rproc: + rproc_free(rproc); + return ret; +} + +static int keystone_rproc_remove(struct platform_device *pdev) +{ + struct keystone_rproc *ksproc = platform_get_drvdata(pdev); + + rproc_del(ksproc->rproc); + pm_runtime_put_sync(&pdev->dev); + pm_runtime_disable(&pdev->dev); + rproc_free(ksproc->rproc); + of_reserved_mem_device_release(&pdev->dev); + + return 0; +} + +static const struct of_device_id keystone_rproc_of_match[] = { + { .compatible = "ti,k2hk-dsp", }, + { .compatible = "ti,k2l-dsp", }, + { .compatible = "ti,k2e-dsp", }, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, keystone_rproc_of_match); + +static struct platform_driver keystone_rproc_driver = { + .probe = keystone_rproc_probe, + .remove = keystone_rproc_remove, + .driver = { + .name = "keystone-rproc", + .of_match_table = keystone_rproc_of_match, + }, +}; + +module_platform_driver(keystone_rproc_driver); + +MODULE_AUTHOR("Suman Anna "); +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("TI Keystone DSP Remoteproc driver"); From patchwork Tue Jun 13 23:45:13 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Suman Anna X-Patchwork-Id: 105451 Delivered-To: patch@linaro.org Received: by 10.140.91.77 with SMTP id y71csp42791qgd; Tue, 13 Jun 2017 16:46:21 -0700 (PDT) X-Received: by 10.84.229.70 with SMTP id d6mr1845753pln.263.1497397581549; Tue, 13 Jun 2017 16:46:21 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1497397581; cv=none; d=google.com; s=arc-20160816; b=LsHAaqMe4M62oF5N6ZFF+GFuiqwM+Bb+p4nS6ZMsczaVrEXYtpS5kyMkd1Az/m6Ajn NnApYgucSnSqaSUv7qZMsoEj2+1YFB2dLVy4k7yvpc9kRA5BtF72mkedNyaTRCWb6lvp Ufx3sBbBWGlhA4KkM4Zm1nHr4Nmw4YdDPJoEsUerce2a6rGvjQWoHcROZ91f9ZIIuddy 8UkGedqX6sGTtXw2zeQCr5CTNRu+3wD3RY6rpZJKekMIyFQey9L3ipbaGKCx/09L5ugk kbkCenZQPZJpNJOTaLaIF/32edrgODvi7a/CyPNO+yz+NNmjQCjv0PkTs3gFrdZ5kKL2 qaKQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:dkim-signature :arc-authentication-results; bh=fVQRqFsmMY6CFtXU7dHHR42EdTkmGElV1PZMvodqyeE=; b=HmHQ9bE9aP90DT2gyF33snUwatwnRMnsI96ciHr4kDJ49Yjj4XGLvlRCZYhnbpKPRz dUy1pv0vgMhV8por3Lf1RqKP3xaqWStzHngtiM0iUGdizjBeFcKCxLyA7ojEsugDbqqk C/OIY5NbYuoHja98/c+oqFMatTOL+OvuL/enjF0OHt89qnnBUBE8hBVdkF97dSdYNNfX fSKctnsnRnFiVrHXd936M+D3WsAJEiL4Us71kbUpCBGUuyR4Ab5EXe3+Y2NcyHcURoi6 dICbwGuVvt2o9D4M8oFlyXTZw3ItRksCccA8wb9HLXWGlgkV2bZvWkyBb2MiEGULjaJ6 nftQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@ti.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=QUARANTINE sp=NONE dis=NONE) header.from=ti.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id a25si919133pfe.264.2017.06.13.16.46.21; Tue, 13 Jun 2017 16:46:21 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@ti.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=QUARANTINE sp=NONE dis=NONE) header.from=ti.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753926AbdFMXps (ORCPT + 25 others); Tue, 13 Jun 2017 19:45:48 -0400 Received: from lelnx193.ext.ti.com ([198.47.27.77]:45709 "EHLO lelnx193.ext.ti.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752525AbdFMXpq (ORCPT ); Tue, 13 Jun 2017 19:45:46 -0400 Received: from dflxv15.itg.ti.com ([128.247.5.124]) by lelnx193.ext.ti.com (8.15.1/8.15.1) with ESMTP id v5DNjFcV012840; Tue, 13 Jun 2017 18:45:15 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ti.com; s=ti-com-17Q1; t=1497397515; bh=oqyxdka9PPiTRHQN0hNxm62PUe8jyGq+FqEOGcMZpB4=; h=From:To:CC:Subject:Date:In-Reply-To:References; b=MXHRQgdJGaqmD5WW/Umc/CDJlNyaVgecbpy+EA671gb4f6WLXBm0qzCPxzOKx8E9d hQbsKurm5+3BHAtC0qd/wwxS6PM7lA8SG9MuvxZxKV8sUWpkid9Wcj54uGJaTKpmsI 0QKwKNP/mrsYAHjmlGiYtb+caVTbMzTxGcxPX75Q= Received: from DLEE70.ent.ti.com (dlee70.ent.ti.com [157.170.170.113]) by dflxv15.itg.ti.com (8.14.3/8.13.8) with ESMTP id v5DNjFjI001201; Tue, 13 Jun 2017 18:45:15 -0500 Received: from dflp32.itg.ti.com (10.64.6.15) by DLEE70.ent.ti.com (157.170.170.113) with Microsoft SMTP Server id 14.3.294.0; Tue, 13 Jun 2017 18:45:15 -0500 Received: from legion.dal.design.ti.com (legion.dal.design.ti.com [128.247.22.53]) by dflp32.itg.ti.com (8.14.3/8.13.8) with ESMTP id v5DNjFx7001944; Tue, 13 Jun 2017 18:45:15 -0500 Received: from localhost (irmo.dhcp.ti.com [128.247.58.153]) by legion.dal.design.ti.com (8.11.7p1+Sun/8.11.7) with ESMTP id v5DNjF323329; Tue, 13 Jun 2017 18:45:15 -0500 (CDT) From: Suman Anna To: Bjorn Andersson , Ohad Ben-Cohen CC: Rob Herring , Santosh Shilimkar , Mark Rutland , , , , , Suman Anna , "Andrew F. Davis" , Sam Nelson Subject: [PATCH v3 3/3] remoteproc/keystone: Ensure the DSPs are in reset in probe Date: Tue, 13 Jun 2017 18:45:13 -0500 Message-ID: <20170613234513.7624-4-s-anna@ti.com> X-Mailer: git-send-email 2.13.1 In-Reply-To: <20170613234513.7624-1-s-anna@ti.com> References: <20170613234513.7624-1-s-anna@ti.com> MIME-Version: 1.0 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: "Andrew F. Davis" The DSPs are expected to be in reset when the driver probes a device. If the DSPs are out of reset in probe, the system may crash when the firmware is being loaded. So, add a check to make sure the DSP resets are asserted, and if not, throw a eye-catchy warning and assert the resets specifically. Signed-off-by: Andrew F. Davis [s-anna@ti.com: replace warning with a WARN] Signed-off-by: Suman Anna Acked-by: Santosh Shilimkar --- v3: No code changes, picked up Santosh's Ack v2: https://patchwork.kernel.org/patch/9773679/ drivers/remoteproc/keystone_remoteproc.c | 10 ++++++++++ 1 file changed, 10 insertions(+) -- 2.13.1 diff --git a/drivers/remoteproc/keystone_remoteproc.c b/drivers/remoteproc/keystone_remoteproc.c index 6e09ef76f7c7..5f776bfd674a 100644 --- a/drivers/remoteproc/keystone_remoteproc.c +++ b/drivers/remoteproc/keystone_remoteproc.c @@ -456,6 +456,16 @@ static int keystone_rproc_probe(struct platform_device *pdev) if (of_reserved_mem_device_init(dev)) dev_warn(dev, "device does not have specific CMA pool\n"); + /* ensure the DSP is in reset before loading firmware */ + ret = reset_control_status(ksproc->reset); + if (ret < 0) { + dev_err(dev, "failed to get reset status, status = %d\n", ret); + goto release_mem; + } else if (ret == 0) { + WARN(1, "device is not in reset\n"); + keystone_rproc_dsp_reset(ksproc); + } + ret = rproc_add(rproc); if (ret) { dev_err(dev, "failed to add register device with remoteproc core, status = %d\n",