142392849SNishanth Menon /* 242392849SNishanth Menon * (C) Copyright 2015-2016 342392849SNishanth Menon * Texas Instruments Incorporated - http://www.ti.com/ 442392849SNishanth Menon * SPDX-License-Identifier: GPL-2.0+ 542392849SNishanth Menon */ 642392849SNishanth Menon #define pr_fmt(fmt) "%s: " fmt, __func__ 742392849SNishanth Menon #include <common.h> 842392849SNishanth Menon #include <dm.h> 942392849SNishanth Menon #include <errno.h> 1042392849SNishanth Menon #include <fdtdec.h> 1142392849SNishanth Menon #include <remoteproc.h> 1242392849SNishanth Menon #include <mach/psc_defs.h> 1342392849SNishanth Menon 1442392849SNishanth Menon DECLARE_GLOBAL_DATA_PTR; 1542392849SNishanth Menon 1642392849SNishanth Menon /** 1742392849SNishanth Menon * struct ti_powerproc_privdata - power processor private data 1842392849SNishanth Menon * @loadaddr: base address for loading the power processor 1942392849SNishanth Menon * @psc_module: psc module address. 2042392849SNishanth Menon */ 2142392849SNishanth Menon struct ti_powerproc_privdata { 2242392849SNishanth Menon phys_addr_t loadaddr; 2342392849SNishanth Menon u32 psc_module; 2442392849SNishanth Menon }; 2542392849SNishanth Menon 2642392849SNishanth Menon /** 2742392849SNishanth Menon * ti_of_to_priv() - generate private data from device tree 2842392849SNishanth Menon * @dev: corresponding ti remote processor device 2942392849SNishanth Menon * @priv: pointer to driver specific private data 3042392849SNishanth Menon * 3142392849SNishanth Menon * Return: 0 if all went ok, else corresponding -ve error 3242392849SNishanth Menon */ 3342392849SNishanth Menon static int ti_of_to_priv(struct udevice *dev, 3442392849SNishanth Menon struct ti_powerproc_privdata *priv) 3542392849SNishanth Menon { 36*e160f7d4SSimon Glass int node = dev_of_offset(dev); 3742392849SNishanth Menon const void *blob = gd->fdt_blob; 3842392849SNishanth Menon int tmp; 3942392849SNishanth Menon 4042392849SNishanth Menon if (!blob) { 4142392849SNishanth Menon debug("'%s' no dt?\n", dev->name); 4242392849SNishanth Menon return -EINVAL; 4342392849SNishanth Menon } 4442392849SNishanth Menon 4542392849SNishanth Menon priv->loadaddr = fdtdec_get_addr(blob, node, "reg"); 4642392849SNishanth Menon if (priv->loadaddr == FDT_ADDR_T_NONE) { 4742392849SNishanth Menon debug("'%s': no 'reg' property\n", dev->name); 4842392849SNishanth Menon return -EINVAL; 4942392849SNishanth Menon } 5042392849SNishanth Menon 5142392849SNishanth Menon tmp = fdtdec_get_int(blob, node, "ti,lpsc_module", -EINVAL); 5242392849SNishanth Menon if (tmp < 0) { 5342392849SNishanth Menon debug("'%s': no 'ti,lpsc_module' property\n", dev->name); 5442392849SNishanth Menon return tmp; 5542392849SNishanth Menon } 5642392849SNishanth Menon priv->psc_module = tmp; 5742392849SNishanth Menon 5842392849SNishanth Menon return 0; 5942392849SNishanth Menon } 6042392849SNishanth Menon 6142392849SNishanth Menon /** 6242392849SNishanth Menon * ti_powerproc_probe() - Basic probe 6342392849SNishanth Menon * @dev: corresponding ti remote processor device 6442392849SNishanth Menon * 6542392849SNishanth Menon * Return: 0 if all went ok, else corresponding -ve error 6642392849SNishanth Menon */ 6742392849SNishanth Menon static int ti_powerproc_probe(struct udevice *dev) 6842392849SNishanth Menon { 6942392849SNishanth Menon struct dm_rproc_uclass_pdata *uc_pdata; 7042392849SNishanth Menon struct ti_powerproc_privdata *priv; 7142392849SNishanth Menon int ret; 7242392849SNishanth Menon 7342392849SNishanth Menon uc_pdata = dev_get_uclass_platdata(dev); 7442392849SNishanth Menon priv = dev_get_priv(dev); 7542392849SNishanth Menon 7642392849SNishanth Menon ret = ti_of_to_priv(dev, priv); 7742392849SNishanth Menon 7842392849SNishanth Menon debug("%s probed with slave_addr=0x%08lX module=%d(%d)\n", 7942392849SNishanth Menon uc_pdata->name, priv->loadaddr, priv->psc_module, ret); 8042392849SNishanth Menon 8142392849SNishanth Menon return ret; 8242392849SNishanth Menon } 8342392849SNishanth Menon 8442392849SNishanth Menon /** 8542392849SNishanth Menon * ti_powerproc_load() - Loadup the TI remote processor 8642392849SNishanth Menon * @dev: corresponding ti remote processor device 8742392849SNishanth Menon * @addr: Address in memory where image binary is stored 8842392849SNishanth Menon * @size: Size in bytes of the image binary 8942392849SNishanth Menon * 9042392849SNishanth Menon * Return: 0 if all went ok, else corresponding -ve error 9142392849SNishanth Menon */ 9242392849SNishanth Menon static int ti_powerproc_load(struct udevice *dev, ulong addr, ulong size) 9342392849SNishanth Menon { 9442392849SNishanth Menon struct dm_rproc_uclass_pdata *uc_pdata; 9542392849SNishanth Menon struct ti_powerproc_privdata *priv; 9642392849SNishanth Menon int ret; 9742392849SNishanth Menon 9842392849SNishanth Menon uc_pdata = dev_get_uclass_platdata(dev); 9942392849SNishanth Menon if (!uc_pdata) { 10042392849SNishanth Menon debug("%s: no uc pdata!\n", dev->name); 10142392849SNishanth Menon return -EINVAL; 10242392849SNishanth Menon } 10342392849SNishanth Menon 10442392849SNishanth Menon priv = dev_get_priv(dev); 10542392849SNishanth Menon ret = psc_module_keep_in_reset_enabled(priv->psc_module, false); 10642392849SNishanth Menon if (ret) { 10742392849SNishanth Menon debug("%s Unable to disable module '%d'(ret=%d)\n", 10842392849SNishanth Menon uc_pdata->name, priv->psc_module, ret); 10942392849SNishanth Menon return ret; 11042392849SNishanth Menon } 11142392849SNishanth Menon 11242392849SNishanth Menon debug("%s: Loading binary from 0x%08lX, size 0x%08lX to 0x%08lX\n", 11342392849SNishanth Menon uc_pdata->name, addr, size, priv->loadaddr); 11442392849SNishanth Menon 11542392849SNishanth Menon memcpy((void *)priv->loadaddr, (void *)addr, size); 11642392849SNishanth Menon 11742392849SNishanth Menon debug("%s: Complete!\n", uc_pdata->name); 11842392849SNishanth Menon return 0; 11942392849SNishanth Menon } 12042392849SNishanth Menon 12142392849SNishanth Menon /** 12242392849SNishanth Menon * ti_powerproc_start() - (replace: short desc) 12342392849SNishanth Menon * @dev: corresponding ti remote processor device 12442392849SNishanth Menon * 12542392849SNishanth Menon * Return: 0 if all went ok, else corresponding -ve error 12642392849SNishanth Menon */ 12742392849SNishanth Menon static int ti_powerproc_start(struct udevice *dev) 12842392849SNishanth Menon { 12942392849SNishanth Menon struct dm_rproc_uclass_pdata *uc_pdata; 13042392849SNishanth Menon struct ti_powerproc_privdata *priv; 13142392849SNishanth Menon int ret; 13242392849SNishanth Menon 13342392849SNishanth Menon uc_pdata = dev_get_uclass_platdata(dev); 13442392849SNishanth Menon if (!uc_pdata) { 13542392849SNishanth Menon debug("%s: no uc pdata!\n", dev->name); 13642392849SNishanth Menon return -EINVAL; 13742392849SNishanth Menon } 13842392849SNishanth Menon 13942392849SNishanth Menon priv = dev_get_priv(dev); 14042392849SNishanth Menon ret = psc_disable_module(priv->psc_module); 14142392849SNishanth Menon if (ret) { 14242392849SNishanth Menon debug("%s Unable to disable module '%d'(ret=%d)\n", 14342392849SNishanth Menon uc_pdata->name, priv->psc_module, ret); 14442392849SNishanth Menon return ret; 14542392849SNishanth Menon } 14642392849SNishanth Menon 14742392849SNishanth Menon ret = psc_module_release_from_reset(priv->psc_module); 14842392849SNishanth Menon if (ret) { 14942392849SNishanth Menon debug("%s Failed to wait for module '%d'(ret=%d)\n", 15042392849SNishanth Menon uc_pdata->name, priv->psc_module, ret); 15142392849SNishanth Menon return ret; 15242392849SNishanth Menon } 15342392849SNishanth Menon ret = psc_enable_module(priv->psc_module); 15442392849SNishanth Menon if (ret) { 15542392849SNishanth Menon debug("%s Unable to disable module '%d'(ret=%d)\n", 15642392849SNishanth Menon uc_pdata->name, priv->psc_module, ret); 15742392849SNishanth Menon return ret; 15842392849SNishanth Menon } 15942392849SNishanth Menon 16042392849SNishanth Menon return 0; 16142392849SNishanth Menon } 16242392849SNishanth Menon 16342392849SNishanth Menon static const struct dm_rproc_ops ti_powerproc_ops = { 16442392849SNishanth Menon .load = ti_powerproc_load, 16542392849SNishanth Menon .start = ti_powerproc_start, 16642392849SNishanth Menon }; 16742392849SNishanth Menon 16842392849SNishanth Menon static const struct udevice_id ti_powerproc_ids[] = { 16942392849SNishanth Menon {.compatible = "ti,power-processor"}, 17042392849SNishanth Menon {} 17142392849SNishanth Menon }; 17242392849SNishanth Menon 17342392849SNishanth Menon U_BOOT_DRIVER(ti_powerproc) = { 17442392849SNishanth Menon .name = "ti_power_proc", 17542392849SNishanth Menon .of_match = ti_powerproc_ids, 17642392849SNishanth Menon .id = UCLASS_REMOTEPROC, 17742392849SNishanth Menon .ops = &ti_powerproc_ops, 17842392849SNishanth Menon .probe = ti_powerproc_probe, 17942392849SNishanth Menon .priv_auto_alloc_size = sizeof(struct ti_powerproc_privdata), 18042392849SNishanth Menon }; 181