From patchwork Fri Sep 21 00:57:11 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Tivy, Robert" X-Patchwork-Id: 1571641 Return-Path: X-Original-To: patchwork-davinci@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from arroyo.ext.ti.com (arroyo.ext.ti.com [192.94.94.40]) by patchwork2.kernel.org (Postfix) with ESMTP id 07125E0004 for ; Tue, 9 Oct 2012 21:29:09 +0000 (UTC) Received: from dlelxv30.itg.ti.com ([172.17.2.17]) by arroyo.ext.ti.com (8.13.7/8.13.7) with ESMTP id q99LRM1n021706; Tue, 9 Oct 2012 16:27:22 -0500 Received: from DLEE74.ent.ti.com (dlee74.ent.ti.com [157.170.170.8]) by dlelxv30.itg.ti.com (8.13.8/8.13.8) with ESMTP id q99LRMRa019072; Tue, 9 Oct 2012 16:27:22 -0500 Received: from dlelxv24.itg.ti.com (172.17.1.199) by DLEE74.ent.ti.com (157.170.170.8) with Microsoft SMTP Server id 14.1.323.3; Tue, 9 Oct 2012 16:27:21 -0500 Received: from linux.omap.com (dlelxs01.itg.ti.com [157.170.227.31]) by dlelxv24.itg.ti.com (8.13.8/8.13.8) with ESMTP id q99LRMlV018712; Tue, 9 Oct 2012 16:27:22 -0500 Received: from linux.omap.com (localhost [127.0.0.1]) by linux.omap.com (Postfix) with ESMTP id 4CCA280627; Tue, 9 Oct 2012 16:27:21 -0500 (CDT) X-Original-To: davinci-linux-open-source@linux.davincidsp.com Delivered-To: davinci-linux-open-source@linux.davincidsp.com Received: from dlelxv30.itg.ti.com (dlelxv30.itg.ti.com [172.17.2.17]) by linux.omap.com (Postfix) with ESMTP id D033980626 for ; Tue, 9 Oct 2012 16:27:20 -0500 (CDT) Received: from DFLE73.ent.ti.com (dfle73.ent.ti.com [128.247.5.110]) by dlelxv30.itg.ti.com (8.13.8/8.13.8) with ESMTP id q99LRKFg019008 for ; Tue, 9 Oct 2012 16:27:20 -0500 Received: from dlelxv23.itg.ti.com (172.17.1.198) by dfle73.ent.ti.com (128.247.5.110) with Microsoft SMTP Server id 14.1.323.3; Tue, 9 Oct 2012 16:27:20 -0500 Received: from legion.dal.design.ti.com (legion.dal.design.ti.com [128.247.22.53]) by dlelxv23.itg.ti.com (8.13.8/8.13.8) with ESMTP id q99LRK5Z030130; Tue, 9 Oct 2012 16:27:20 -0500 Received: from sanblnx02.sanb.design.ti.com (sanblnx02.sanb.design.ti.com [146.252.160.81]) by legion.dal.design.ti.com (8.11.7p1+Sun/8.11.7) with ESMTP id q99LRJw10900; Tue, 9 Oct 2012 16:27:20 -0500 (CDT) Received: from sanblnx02.sanb.design.ti.com (localhost [127.0.0.1]) by sanblnx02.sanb.design.ti.com (8.13.6/8.13.6/SuSE Linux 0.8) with ESMTP id q99LRJve016680; Tue, 9 Oct 2012 14:27:19 -0700 Received: (from a0783933@localhost) by sanblnx02.sanb.design.ti.com (8.13.6/8.13.6/Submit) id q99LRJQh016676; Tue, 9 Oct 2012 14:27:19 -0700 Message-ID: <201210092127.q99LRJQh016676@sanblnx02.sanb.design.ti.com> From: Robert Tivy To: Sekhar Nori Date: Thu, 20 Sep 2012 17:57:11 -0700 Subject: [PATCH 2/2] ARM: davinci: remoteproc support for OMAP-L138 DSP MIME-Version: 1.0 CC: X-BeenThere: davinci-linux-open-source@linux.davincidsp.com X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: Errors-To: davinci-linux-open-source-bounces@linux.davincidsp.com From: Robert Tivy Still using the "old" way of reserving some contiguous physical memory during kernel boot, need to switch to new CMA framework. Signed-off-by: Robert Tivy --- arch/arm/mach-davinci/board-da850-evm.c | 8 +- arch/arm/mach-davinci/board-omapl138-hawk.c | 8 +- arch/arm/mach-davinci/clock.h | 3 +- arch/arm/mach-davinci/da850.c | 19 +- arch/arm/mach-davinci/devices-da8xx.c | 53 +++++ arch/arm/mach-davinci/include/mach/da8xx.h | 2 + arch/arm/mach-davinci/include/mach/psc.h | 3 +- arch/arm/mach-davinci/include/mach/remoteproc.h | 37 +++ arch/arm/mach-davinci/psc.c | 9 +- drivers/remoteproc/Kconfig | 19 ++ drivers/remoteproc/Makefile | 1 + drivers/remoteproc/davinci_remoteproc.c | 273 +++++++++++++++++++++++ 12 files changed, 429 insertions(+), 6 deletions(-) create mode 100644 arch/arm/mach-davinci/include/mach/remoteproc.h create mode 100644 drivers/remoteproc/davinci_remoteproc.c diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c index 44f6bb0..482d95b 100644 --- a/arch/arm/mach-davinci/board-da850-evm.c +++ b/arch/arm/mach-davinci/board-da850-evm.c @@ -1,7 +1,7 @@ /* * TI DA850/OMAP-L138 EVM board * - * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/ + * Copyright (C) 2009-2012 Texas Instruments Incorporated - http://www.ti.com/ * * Derived from: arch/arm/mach-davinci/board-da830-evm.c * Original Copyrights follow: @@ -44,6 +44,7 @@ #include #include #include +#include #define DA850_EVM_PHY_ID "davinci_mdio-0:00" #define DA850_LCD_PWR_PIN GPIO_TO_PIN(2, 8) @@ -1387,6 +1388,10 @@ static __init void da850_evm_init(void) ret); da850_evm_setup_mac_addr(); + + ret = da8xx_register_rproc(); + if (ret) + pr_warn("dsp/rproc registration failed: %d\n", ret); } #ifdef CONFIG_SERIAL_8250_CONSOLE @@ -1414,4 +1419,5 @@ MACHINE_START(DAVINCI_DA850_EVM, "DaVinci DA850/OMAP-L138/AM18x EVM") .init_late = davinci_init_late, .dma_zone_size = SZ_128M, .restart = da8xx_restart, + .reserve = da8xx_rproc_reserve_contig, MACHINE_END diff --git a/arch/arm/mach-davinci/board-omapl138-hawk.c b/arch/arm/mach-davinci/board-omapl138-hawk.c index e5ce9c4..3c9e7ee 100644 --- a/arch/arm/mach-davinci/board-omapl138-hawk.c +++ b/arch/arm/mach-davinci/board-omapl138-hawk.c @@ -3,7 +3,7 @@ * * Initial code: Syed Mohammed Khasim * - * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com + * Copyright (C) 2009-2012 Texas Instruments Incorporated - http://www.ti.com * * This file is licensed under the terms of the GNU General Public License * version 2. This program is licensed "as is" without any warranty of @@ -20,6 +20,7 @@ #include #include #include +#include #define HAWKBOARD_PHY_ID "davinci_mdio-0:07" #define DA850_HAWK_MMCSD_CD_PIN GPIO_TO_PIN(3, 12) @@ -319,6 +320,10 @@ static __init void omapl138_hawk_init(void) pr_warn("omapl138_hawk_init: " "watchdog registration failed: %d\n", ret); + + ret = da8xx_register_rproc(); + if (ret) + pr_warn("dsp/rproc registration failed: %d\n", ret); } #ifdef CONFIG_SERIAL_8250_CONSOLE @@ -346,4 +351,5 @@ MACHINE_START(OMAPL138_HAWKBOARD, "AM18x/OMAP-L138 Hawkboard") .init_late = davinci_init_late, .dma_zone_size = SZ_128M, .restart = da8xx_restart, + .reserve = da8xx_rproc_reserve_contig, MACHINE_END diff --git a/arch/arm/mach-davinci/clock.h b/arch/arm/mach-davinci/clock.h index 46f0f1b..8481638 100644 --- a/arch/arm/mach-davinci/clock.h +++ b/arch/arm/mach-davinci/clock.h @@ -1,7 +1,7 @@ /* * TI DaVinci clock definitions * - * Copyright (C) 2006-2007 Texas Instruments. + * Copyright (C) 2006-2012 Texas Instruments. * Copyright (C) 2008-2009 Deep Root Systems, LLC * * This program is free software; you can redistribute it and/or modify @@ -112,6 +112,7 @@ struct clk { #define PRE_PLL BIT(4) /* source is before PLL mult/div */ #define PSC_SWRSTDISABLE BIT(5) /* Disable state is SwRstDisable */ #define PSC_FORCE BIT(6) /* Force module state transtition */ +#define PSC_LRST BIT(8) /* Use local reset on enable/disable */ #define CLK(dev, con, ck) \ { \ diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c index b44dc84..539f5a8 100644 --- a/arch/arm/mach-davinci/da850.c +++ b/arch/arm/mach-davinci/da850.c @@ -1,7 +1,7 @@ /* * TI DA850/OMAP-L138 chip specific setup * - * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/ + * Copyright (C) 2009-2012 Texas Instruments Incorporated - http://www.ti.com/ * * Derived from: arch/arm/mach-davinci/da830.c * Original Copyrights follow: @@ -76,6 +76,13 @@ static struct clk pll0_aux_clk = { .flags = CLK_PLL | PRE_PLL, }; +static struct clk pll0_sysclk1 = { + .name = "pll0_sysclk1", + .parent = &pll0_clk, + .flags = CLK_PLL, + .div_reg = PLLDIV1, +}; + static struct clk pll0_sysclk2 = { .name = "pll0_sysclk2", .parent = &pll0_clk, @@ -355,10 +362,19 @@ static struct clk sata_clk = { .flags = PSC_FORCE, }; +static struct clk dsp_clk = { + .name = "dsp", + .parent = &pll0_sysclk1, + .domain = DAVINCI_GPSC_DSPDOMAIN, + .lpsc = DA8XX_LPSC0_GEM, + .flags = PSC_LRST, +}; + static struct clk_lookup da850_clks[] = { CLK(NULL, "ref", &ref_clk), CLK(NULL, "pll0", &pll0_clk), CLK(NULL, "pll0_aux", &pll0_aux_clk), + CLK(NULL, "pll0_sysclk1", &pll0_sysclk1), CLK(NULL, "pll0_sysclk2", &pll0_sysclk2), CLK(NULL, "pll0_sysclk3", &pll0_sysclk3), CLK(NULL, "pll0_sysclk4", &pll0_sysclk4), @@ -398,6 +414,7 @@ static struct clk_lookup da850_clks[] = { CLK("spi_davinci.0", NULL, &spi0_clk), CLK("spi_davinci.1", NULL, &spi1_clk), CLK("ahci", NULL, &sata_clk), + CLK(NULL, "dsp", &dsp_clk), CLK(NULL, NULL, NULL), }; diff --git a/arch/arm/mach-davinci/devices-da8xx.c b/arch/arm/mach-davinci/devices-da8xx.c index fa5ea17..f2367be 100644 --- a/arch/arm/mach-davinci/devices-da8xx.c +++ b/arch/arm/mach-davinci/devices-da8xx.c @@ -1,6 +1,7 @@ /* * DA8XX/OMAP L1XX platform device data * + * Copyright (C) 2012 Texas Instruments, Inc. * Copyright (c) 2007-2009, MontaVista Software, Inc. * Derived from code that was: * Copyright (C) 2006 Komal Shah @@ -16,12 +17,14 @@ #include #include #include +#include #include #include #include #include #include +#include #include "clock.h" @@ -660,6 +663,56 @@ int __init da850_register_mmcsd1(struct davinci_mmc_config *config) } #endif +/* + * The following address range was chosen because the XDC Platform for + * OMAP-L138 has this range as its default code/data placement. + * + * System integrators must ensure that Linux does not own this range. + */ +#define DA_CONTIG_BASE (0xc3000000) +#define DA_CONTIG_SIZE (0x02000000) + +void __init da8xx_rproc_reserve_contig(void) +{ + pr_info("reserving contig memory\n"); + + if (memblock_is_region_reserved(DA_CONTIG_BASE, DA_CONTIG_SIZE) || + memblock_reserve(DA_CONTIG_BASE, DA_CONTIG_SIZE) < 0) { + pr_err("memory already reserved\n"); + return; + } +} + +static struct platform_device *da8xx_dsp; + +int __init da8xx_register_rproc(void) +{ + struct da8xx_rproc_pdata rproc_pdata = { + .name = "dsp", + .firmware = "da8xx-dsp.xe674", + .clk_name = "dsp", + }; + int ret; + + da8xx_dsp = platform_device_register_data(NULL, "davinci-rproc", 0, + &rproc_pdata, sizeof(rproc_pdata)); + + ret = dma_declare_coherent_memory(&da8xx_dsp->dev, + DA_CONTIG_BASE, DA_CONTIG_BASE, + DA_CONTIG_SIZE, + DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE); + + if (!(ret & DMA_MEMORY_MAP)) { + pr_err("dma_declare_coherent failure\n"); + + platform_device_unregister(da8xx_dsp); + + return -ENOMEM; + } + + return 0; +}; + static struct resource da8xx_rtc_resources[] = { { .start = DA8XX_RTC_BASE, diff --git a/arch/arm/mach-davinci/include/mach/da8xx.h b/arch/arm/mach-davinci/include/mach/da8xx.h index a2f1f27..12bcc12 100644 --- a/arch/arm/mach-davinci/include/mach/da8xx.h +++ b/arch/arm/mach-davinci/include/mach/da8xx.h @@ -3,6 +3,7 @@ * * Author: Mark A. Greer * + * Copyright (C) 2011-2012 Texas Instruments, Inc. * 2007, 2009-2010 (c) MontaVista Software, Inc. This file is licensed under * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express @@ -91,6 +92,7 @@ int da850_register_cpufreq(char *async_clk); int da8xx_register_cpuidle(void); void __iomem * __init da8xx_get_mem_ctlr(void); int da850_register_pm(struct platform_device *pdev); +int da8xx_register_rproc(void); int __init da850_register_sata(unsigned long refclkpn); void da8xx_restart(char mode, const char *cmd); diff --git a/arch/arm/mach-davinci/include/mach/psc.h b/arch/arm/mach-davinci/include/mach/psc.h index 405318e..b119411 100644 --- a/arch/arm/mach-davinci/include/mach/psc.h +++ b/arch/arm/mach-davinci/include/mach/psc.h @@ -1,7 +1,7 @@ /* * DaVinci Power & Sleep Controller (PSC) defines * - * Copyright (C) 2006 Texas Instruments. + * Copyright (C) 2006-2012 Texas Instruments. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -245,6 +245,7 @@ #define MDSTAT_STATE_MASK 0x3f #define PDSTAT_STATE_MASK 0x1f +#define MDCTL_LRST BIT(8) #define MDCTL_FORCE BIT(31) #define PDCTL_NEXT BIT(0) #define PDCTL_EPCGOOD BIT(8) diff --git a/arch/arm/mach-davinci/include/mach/remoteproc.h b/arch/arm/mach-davinci/include/mach/remoteproc.h new file mode 100644 index 0000000..0f56688 --- /dev/null +++ b/arch/arm/mach-davinci/include/mach/remoteproc.h @@ -0,0 +1,37 @@ +/* + * Remote Processor + * + * Copyright (C) 2011-2012 Texas Instruments, Inc. + * + * 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. + */ + +#ifndef _MACH_REMOTEPROC_H +#define _MACH_REMOTEPROC_H + +#include + +/* + * struct da8xx_rproc_pdata - da8xx remoteproc's platform data + * @name: the remoteproc's name + * @clk_name: the remoteproc's clock + * @firmware: name of firmware file to load + * @ops: start/stop rproc handlers + */ +struct da8xx_rproc_pdata { + const char *name; + const char *clk_name; + const char *firmware; + const struct rproc_ops *ops; +}; + +void __init da8xx_rproc_reserve_contig(void); + +#endif /* _MACH_REMOTEPROC_H */ diff --git a/arch/arm/mach-davinci/psc.c b/arch/arm/mach-davinci/psc.c index bddaba9..c6e9d9f 100644 --- a/arch/arm/mach-davinci/psc.c +++ b/arch/arm/mach-davinci/psc.c @@ -1,7 +1,7 @@ /* * TI DaVinci Power and Sleep Controller (PSC) * - * Copyright (C) 2006 Texas Instruments. + * Copyright (C) 2006-2012 Texas Instruments. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -77,6 +77,8 @@ void davinci_psc_config(unsigned int domain, unsigned int ctlr, mdctl |= next_state; if (flags & PSC_FORCE) mdctl |= MDCTL_FORCE; + if ((flags & PSC_LRST) && !enable) + mdctl &= ~MDCTL_LRST; __raw_writel(mdctl, psc_base + MDCTL + 4 * id); pdstat = __raw_readl(psc_base + PDSTAT + 4 * domain); @@ -108,5 +110,10 @@ void davinci_psc_config(unsigned int domain, unsigned int ctlr, mdstat = __raw_readl(psc_base + MDSTAT + 4 * id); } while (!((mdstat & MDSTAT_STATE_MASK) == next_state)); + if ((flags & PSC_LRST) && enable) { + mdctl |= MDCTL_LRST; + __raw_writel(mdctl, psc_base + MDCTL + 4 * id); + } + iounmap(psc_base); } diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig index f8d818a..ceccfa1 100644 --- a/drivers/remoteproc/Kconfig +++ b/drivers/remoteproc/Kconfig @@ -3,6 +3,7 @@ menu "Remoteproc drivers (EXPERIMENTAL)" # REMOTEPROC gets selected by whoever wants it config REMOTEPROC tristate + select FW_LOADER depends on EXPERIMENTAL select FW_CONFIG @@ -27,4 +28,22 @@ config OMAP_REMOTEPROC It's safe to say n here if you're not interested in multimedia offloading or just want a bare minimum kernel. +config DAVINCI_REMOTEPROC + tristate "DaVinci DA850/OMAPL138 remoteproc support" + depends on EXPERIMENTAL + depends on ARCH_DAVINCI_DA850 + select REMOTEPROC + select RPMSG + default y + help + Say y here to support DaVinci DA850/OMAPL138 remote processors + via the remote processor framework. + + Usually you want to say y here, in order to enable AMP + use-cases to run on your platform (multimedia codecs are + offloaded to remote DSP processors using this framework). + + It's safe to say n here if you're not interested in multimedia + offloading or just want a bare minimum kernel. + endmenu diff --git a/drivers/remoteproc/Makefile b/drivers/remoteproc/Makefile index 5445d9b..10d5a81 100644 --- a/drivers/remoteproc/Makefile +++ b/drivers/remoteproc/Makefile @@ -7,3 +7,4 @@ remoteproc-y := remoteproc_core.o remoteproc-y += remoteproc_debugfs.o remoteproc-y += remoteproc_virtio.o obj-$(CONFIG_OMAP_REMOTEPROC) += omap_remoteproc.o +obj-$(CONFIG_DAVINCI_REMOTEPROC) += davinci_remoteproc.o diff --git a/drivers/remoteproc/davinci_remoteproc.c b/drivers/remoteproc/davinci_remoteproc.c new file mode 100644 index 0000000..df5a948 --- /dev/null +++ b/drivers/remoteproc/davinci_remoteproc.c @@ -0,0 +1,273 @@ +/* + * Remote processor machine-specific module for Davinci + * + * Copyright (C) 2011-2012 Texas Instruments, Inc. + * + * 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. + */ + +#define pr_fmt(fmt) "%s: " fmt, __func__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "remoteproc_internal.h" + +/* + * OMAP-L138 Technical References: + * http://www.ti.com/product/omap-l138 + */ + +/* next state bits in MDCTL15 register (section 9.6.18) */ +#define NEXT_ENABLED 0x3 + +/* register for DSP boot address in SYSCFG0 module (section 11.5.6) */ +#define HOST1CFG 0x44 + +#define SYSCFG_CHIPINT0_IRQ 28 + +#define SYSCFG_CHIPSIG_OFFSET 0x174 +#define SYSCFG_CHIPSIG_CLR_OFFSET 0x178 +#define SYSCFG_CHIPINT0 (1 << 0) +#define SYSCFG_CHIPINT1 (1 << 1) +#define SYSCFG_CHIPINT2 (1 << 2) +#define SYSCFG_CHIPINT3 (1 << 3) + +/** + * struct davinci_rproc - davinci remote processor state + * @rproc: rproc handle + */ +struct davinci_rproc { + struct rproc *rproc; + struct clk *dsp_clk; +}; + +static void __iomem *syscfg0_base; +static struct platform_device *remoteprocdev; +static struct work_struct workqueue; +static struct irq_data *irq_data; +static void (*ack_fxn)(struct irq_data *data); + +/** + * handle_event() - inbound virtqueue message workqueue function + * + * This funciton is registered with 'workqueue' and is scheduled by the + * ISR handler. + */ +static void handle_event(struct work_struct *work) +{ + struct rproc *rproc = platform_get_drvdata(remoteprocdev); + + /* Process incoming buffers on our vring */ + while (IRQ_HANDLED == rproc_vq_interrupt(rproc, 0)) + ; + + /* Must allow wakeup of potenitally blocking senders: */ + rproc_vq_interrupt(rproc, 1); +} + +/** + * davinci_rproc_callback() - inbound virtqueue message handler + * + * This handler is invoked directly by the kernel whenever the remote + * core (DSP) has modified the state of a virtqueue. There is no + * "payload" message indicating the virtqueue index as is the case with + * mailbox-based implementations on OMAP4. As such, this handler "polls" + * each known virtqueue index for every invocation. + */ +static irqreturn_t davinci_rproc_callback(int irq, void *p) +{ + if (__raw_readl(syscfg0_base + SYSCFG_CHIPSIG_OFFSET) & + SYSCFG_CHIPINT0) { + /* + * Following can fail if work is pending; but it's OK since the + * work function will loop to process all incoming messages. + * schedule_work() calls handle_event with pending bit off. + */ + (void)schedule_work(&workqueue); + + /* Clear interrupt level source */ + __raw_writel(SYSCFG_CHIPINT0, + syscfg0_base + SYSCFG_CHIPSIG_CLR_OFFSET); + + /* + * ACK intr to AINTC. + * + * It has already been ack'ed by the kernel before calling + * this function, but since the ARM<->DSP interrupts in the + * CHIPSIG register are "level" instead of "pulse" variety, + * we need to ack it after taking down the level else we'll + * be called again immediately after returning. + */ + ack_fxn(irq_data); + } + + return IRQ_HANDLED; +} + +static int davinci_rproc_start(struct rproc *rproc) +{ + struct platform_device *pdev = to_platform_device(rproc->dev); + struct device *dev = rproc->dev; + struct da8xx_rproc_pdata *pdata = dev->platform_data; + struct davinci_rproc *drproc = rproc->priv; + struct clk *dsp_clk; + int ret; + + /* hw requires the start (boot) address be on 1KB boundary */ + if (rproc->bootaddr & 0x3ff) { + dev_err(dev, "invalid boot address: must be aligned to 1KB\n"); + return -EINVAL; + } + + irq_data = irq_get_irq_data(SYSCFG_CHIPINT0_IRQ); + if (IS_ERR_OR_NULL(irq_data)) { + dev_err(dev, + "irq_get_irq_data(SYSCFG_CHIPINT0_IRQ) error: %ld\n", + PTR_ERR(irq_data)); + + return PTR_ERR(irq_data); + } + ack_fxn = irq_data->chip->irq_ack; + + INIT_WORK(&workqueue, handle_event); + remoteprocdev = pdev; + + dsp_clk = clk_get(dev, pdata->clk_name); + if (IS_ERR_OR_NULL(dsp_clk)) { + dev_err(dev, "clk_get error: %ld\n", PTR_ERR(dsp_clk)); + return PTR_ERR(dsp_clk); + } + + ret = request_irq(SYSCFG_CHIPINT0_IRQ, davinci_rproc_callback, + IRQF_SHARED, "davinci-remoteproc", drproc); + if (ret) { + dev_err(dev, "request_irq error: %d\n", ret); + goto fail; + } + + syscfg0_base = ioremap(DA8XX_SYSCFG0_BASE, SZ_4K); + __raw_writel(rproc->bootaddr, syscfg0_base + HOST1CFG); + + clk_enable(dsp_clk); + drproc->dsp_clk = dsp_clk; + + return 0; +fail: + clk_put(dsp_clk); + + return ret; +} + +static int davinci_rproc_stop(struct rproc *rproc) +{ + struct davinci_rproc *drproc = rproc->priv; + struct clk *dsp_clk = drproc->dsp_clk; + + clk_disable(dsp_clk); + clk_put(dsp_clk); + + iounmap(syscfg0_base); + + free_irq(SYSCFG_CHIPINT0_IRQ, drproc); + + /* Flush any pending work: */ + (void)flush_work_sync(&workqueue); + + return 0; +} + +/* kick a virtqueue */ +static void davinci_rproc_kick(struct rproc *rproc, int vqid) +{ + /* Poll for ack from other side first */ + while (__raw_readl(syscfg0_base + SYSCFG_CHIPSIG_OFFSET) & + SYSCFG_CHIPINT2) + ; + + /* Interupt remote proc */ + __raw_writel(SYSCFG_CHIPINT2, syscfg0_base + SYSCFG_CHIPSIG_OFFSET); +} + +static struct rproc_ops davinci_rproc_ops = { + .start = davinci_rproc_start, + .stop = davinci_rproc_stop, + .kick = davinci_rproc_kick, +}; + +static int davinci_rproc_probe(struct platform_device *pdev) +{ + struct davinci_soc_info *soc_info = &davinci_soc_info; + struct da8xx_rproc_pdata *pdata = pdev->dev.platform_data; + struct davinci_rproc *drproc; + struct rproc *rproc; + void __iomem *psc_base; + int ret; + + ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); + if (ret) { + dev_err(&pdev->dev, "dma_set_coherent_mask: %d\n", ret); + return ret; + } + + rproc = rproc_alloc(&pdev->dev, pdata->name, &davinci_rproc_ops, + pdata->firmware, sizeof(*drproc)); + if (!rproc) + return -ENOMEM; + + drproc = rproc->priv; + drproc->rproc = rproc; + + platform_set_drvdata(pdev, rproc); + + ret = rproc_register(rproc); + if (ret) + goto free_rproc; + + /* insure the dsp is halted by asserting local reset (LRST=0) */ + psc_base = ioremap(soc_info->psc_bases[0], SZ_4K); + __raw_writel(NEXT_ENABLED, psc_base + MDCTL + 4 * DA8XX_LPSC0_GEM); + iounmap(psc_base); + + return 0; + +free_rproc: + rproc_free(rproc); + return ret; +} + +static int __devexit davinci_rproc_remove(struct platform_device *pdev) +{ + struct rproc *rproc = platform_get_drvdata(pdev); + + return rproc_unregister(rproc); +} + +static struct platform_driver davinci_rproc_driver = { + .probe = davinci_rproc_probe, + .remove = __devexit_p(davinci_rproc_remove), + .driver = { + .name = "davinci-rproc", + .owner = THIS_MODULE, + }, +}; + +module_platform_driver(davinci_rproc_driver); + +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("Davinci DA850 Remote Processor control driver");