diff options
-rw-r--r-- | drivers/remoteproc/Kconfig | 10 | ||||
-rw-r--r-- | drivers/remoteproc/Makefile | 1 | ||||
-rw-r--r-- | drivers/remoteproc/ti_power_proc.c | 180 |
3 files changed, 191 insertions, 0 deletions
diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig index 437224b..d0b76be 100644 --- a/drivers/remoteproc/Kconfig +++ b/drivers/remoteproc/Kconfig @@ -21,4 +21,14 @@ config REMOTEPROC_SANDBOX help Say 'y' here to add support for test processor which does dummy operations for sandbox platform. + +config REMOTEPROC_TI_POWER + bool "Support for TI Power processor" + select REMOTEPROC + depends on DM + depends on ARCH_KEYSTONE + depends on OF_CONTROL + help + Say 'y' here to add support for TI power processors such as those + found on certain TI keystone and OMAP generation SoCs. endmenu diff --git a/drivers/remoteproc/Makefile b/drivers/remoteproc/Makefile index 720aa6e..65fc061 100644 --- a/drivers/remoteproc/Makefile +++ b/drivers/remoteproc/Makefile @@ -8,3 +8,4 @@ obj-$(CONFIG_REMOTEPROC) += rproc-uclass.o # Remote proc drivers - Please keep this list alphabetically sorted. obj-$(CONFIG_REMOTEPROC_SANDBOX) += sandbox_testproc.o +obj-$(CONFIG_REMOTEPROC_TI_POWER) += ti_power_proc.o diff --git a/drivers/remoteproc/ti_power_proc.c b/drivers/remoteproc/ti_power_proc.c new file mode 100644 index 0000000..76ac3be --- /dev/null +++ b/drivers/remoteproc/ti_power_proc.c @@ -0,0 +1,180 @@ +/* + * (C) Copyright 2015-2016 + * Texas Instruments Incorporated - http://www.ti.com/ + * SPDX-License-Identifier: GPL-2.0+ + */ +#define pr_fmt(fmt) "%s: " fmt, __func__ +#include <common.h> +#include <dm.h> +#include <errno.h> +#include <fdtdec.h> +#include <remoteproc.h> +#include <mach/psc_defs.h> + +DECLARE_GLOBAL_DATA_PTR; + +/** + * struct ti_powerproc_privdata - power processor private data + * @loadaddr: base address for loading the power processor + * @psc_module: psc module address. + */ +struct ti_powerproc_privdata { + phys_addr_t loadaddr; + u32 psc_module; +}; + +/** + * ti_of_to_priv() - generate private data from device tree + * @dev: corresponding ti remote processor device + * @priv: pointer to driver specific private data + * + * Return: 0 if all went ok, else corresponding -ve error + */ +static int ti_of_to_priv(struct udevice *dev, + struct ti_powerproc_privdata *priv) +{ + int node = dev->of_offset; + const void *blob = gd->fdt_blob; + int tmp; + + if (!blob) { + debug("'%s' no dt?\n", dev->name); + return -EINVAL; + } + + priv->loadaddr = fdtdec_get_addr(blob, node, "reg"); + if (priv->loadaddr == FDT_ADDR_T_NONE) { + debug("'%s': no 'reg' property\n", dev->name); + return -EINVAL; + } + + tmp = fdtdec_get_int(blob, node, "ti,lpsc_module", -EINVAL); + if (tmp < 0) { + debug("'%s': no 'ti,lpsc_module' property\n", dev->name); + return tmp; + } + priv->psc_module = tmp; + + return 0; +} + +/** + * ti_powerproc_probe() - Basic probe + * @dev: corresponding ti remote processor device + * + * Return: 0 if all went ok, else corresponding -ve error + */ +static int ti_powerproc_probe(struct udevice *dev) +{ + struct dm_rproc_uclass_pdata *uc_pdata; + struct ti_powerproc_privdata *priv; + int ret; + + uc_pdata = dev_get_uclass_platdata(dev); + priv = dev_get_priv(dev); + + ret = ti_of_to_priv(dev, priv); + + debug("%s probed with slave_addr=0x%08lX module=%d(%d)\n", + uc_pdata->name, priv->loadaddr, priv->psc_module, ret); + + return ret; +} + +/** + * ti_powerproc_load() - Loadup the TI remote processor + * @dev: corresponding ti remote processor device + * @addr: Address in memory where image binary is stored + * @size: Size in bytes of the image binary + * + * Return: 0 if all went ok, else corresponding -ve error + */ +static int ti_powerproc_load(struct udevice *dev, ulong addr, ulong size) +{ + struct dm_rproc_uclass_pdata *uc_pdata; + struct ti_powerproc_privdata *priv; + int ret; + + uc_pdata = dev_get_uclass_platdata(dev); + if (!uc_pdata) { + debug("%s: no uc pdata!\n", dev->name); + return -EINVAL; + } + + priv = dev_get_priv(dev); + ret = psc_module_keep_in_reset_enabled(priv->psc_module, false); + if (ret) { + debug("%s Unable to disable module '%d'(ret=%d)\n", + uc_pdata->name, priv->psc_module, ret); + return ret; + } + + debug("%s: Loading binary from 0x%08lX, size 0x%08lX to 0x%08lX\n", + uc_pdata->name, addr, size, priv->loadaddr); + + memcpy((void *)priv->loadaddr, (void *)addr, size); + + debug("%s: Complete!\n", uc_pdata->name); + return 0; +} + +/** + * ti_powerproc_start() - (replace: short desc) + * @dev: corresponding ti remote processor device + * + * Return: 0 if all went ok, else corresponding -ve error + */ +static int ti_powerproc_start(struct udevice *dev) +{ + struct dm_rproc_uclass_pdata *uc_pdata; + struct ti_powerproc_privdata *priv; + int ret; + + uc_pdata = dev_get_uclass_platdata(dev); + if (!uc_pdata) { + debug("%s: no uc pdata!\n", dev->name); + return -EINVAL; + } + + priv = dev_get_priv(dev); + ret = psc_disable_module(priv->psc_module); + if (ret) { + debug("%s Unable to disable module '%d'(ret=%d)\n", + uc_pdata->name, priv->psc_module, ret); + return ret; + } + + ret = psc_module_release_from_reset(priv->psc_module); + if (ret) { + debug("%s Failed to wait for module '%d'(ret=%d)\n", + uc_pdata->name, priv->psc_module, ret); + return ret; + } + ret = psc_enable_module(priv->psc_module); + if (ret) { + debug("%s Unable to disable module '%d'(ret=%d)\n", + uc_pdata->name, priv->psc_module, ret); + return ret; + } + + return 0; +} + +static const struct dm_rproc_ops ti_powerproc_ops = { + .load = ti_powerproc_load, + .start = ti_powerproc_start, +}; + +static const struct udevice_id ti_powerproc_ids[] = { + {.compatible = "ti,power-processor"}, + {} +}; + +U_BOOT_DRIVER(ti_powerproc) = { + .name = "ti_power_proc", + .of_match = ti_powerproc_ids, + .id = UCLASS_REMOTEPROC, + .ops = &ti_powerproc_ops, + .probe = ti_powerproc_probe, + .priv_auto_alloc_size = sizeof(struct ti_powerproc_privdata), +}; |