uboot/drivers/remoteproc/ti_power_proc.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * (C) Copyright 2015-2016
   4 * Texas Instruments Incorporated - http://www.ti.com/
   5 */
   6#define pr_fmt(fmt) "%s: " fmt, __func__
   7#include <common.h>
   8#include <dm.h>
   9#include <errno.h>
  10#include <fdtdec.h>
  11#include <remoteproc.h>
  12#include <mach/psc_defs.h>
  13
  14DECLARE_GLOBAL_DATA_PTR;
  15
  16/**
  17 * struct ti_powerproc_privdata - power processor private data
  18 * @loadaddr:   base address for loading the power processor
  19 * @psc_module: psc module address.
  20 */
  21struct ti_powerproc_privdata {
  22        phys_addr_t loadaddr;
  23        u32 psc_module;
  24};
  25
  26/**
  27 * ti_of_to_priv() - generate private data from device tree
  28 * @dev:        corresponding ti remote processor device
  29 * @priv:       pointer to driver specific private data
  30 *
  31 * Return: 0 if all went ok, else corresponding -ve error
  32 */
  33static int ti_of_to_priv(struct udevice *dev,
  34                         struct ti_powerproc_privdata *priv)
  35{
  36        int node = dev_of_offset(dev);
  37        const void *blob = gd->fdt_blob;
  38        int tmp;
  39
  40        if (!blob) {
  41                debug("'%s' no dt?\n", dev->name);
  42                return -EINVAL;
  43        }
  44
  45        priv->loadaddr = fdtdec_get_addr(blob, node, "reg");
  46        if (priv->loadaddr == FDT_ADDR_T_NONE) {
  47                debug("'%s': no 'reg' property\n", dev->name);
  48                return -EINVAL;
  49        }
  50
  51        tmp = fdtdec_get_int(blob, node, "ti,lpsc_module", -EINVAL);
  52        if (tmp < 0) {
  53                debug("'%s': no 'ti,lpsc_module' property\n", dev->name);
  54                return tmp;
  55        }
  56        priv->psc_module = tmp;
  57
  58        return 0;
  59}
  60
  61/**
  62 * ti_powerproc_probe() - Basic probe
  63 * @dev:        corresponding ti remote processor device
  64 *
  65 * Return: 0 if all went ok, else corresponding -ve error
  66 */
  67static int ti_powerproc_probe(struct udevice *dev)
  68{
  69        struct dm_rproc_uclass_pdata *uc_pdata;
  70        struct ti_powerproc_privdata *priv;
  71        int ret;
  72
  73        uc_pdata = dev_get_uclass_platdata(dev);
  74        priv = dev_get_priv(dev);
  75
  76        ret = ti_of_to_priv(dev, priv);
  77
  78        debug("%s probed with slave_addr=0x%08lX module=%d(%d)\n",
  79              uc_pdata->name, priv->loadaddr, priv->psc_module, ret);
  80
  81        return ret;
  82}
  83
  84/**
  85 * ti_powerproc_load() - Loadup the TI remote processor
  86 * @dev:        corresponding ti remote processor device
  87 * @addr:       Address in memory where image binary is stored
  88 * @size:       Size in bytes of the image binary
  89 *
  90 * Return: 0 if all went ok, else corresponding -ve error
  91 */
  92static int ti_powerproc_load(struct udevice *dev, ulong addr, ulong size)
  93{
  94        struct dm_rproc_uclass_pdata *uc_pdata;
  95        struct ti_powerproc_privdata *priv;
  96        int ret;
  97
  98        uc_pdata = dev_get_uclass_platdata(dev);
  99        if (!uc_pdata) {
 100                debug("%s: no uc pdata!\n", dev->name);
 101                return -EINVAL;
 102        }
 103
 104        priv = dev_get_priv(dev);
 105        ret = psc_module_keep_in_reset_enabled(priv->psc_module, false);
 106        if (ret) {
 107                debug("%s Unable to disable module '%d'(ret=%d)\n",
 108                      uc_pdata->name, priv->psc_module, ret);
 109                return ret;
 110        }
 111
 112        debug("%s: Loading binary from 0x%08lX, size 0x%08lX to 0x%08lX\n",
 113              uc_pdata->name, addr, size, priv->loadaddr);
 114
 115        memcpy((void *)priv->loadaddr, (void *)addr, size);
 116
 117        debug("%s: Complete!\n", uc_pdata->name);
 118        return 0;
 119}
 120
 121/**
 122 * ti_powerproc_start() - (replace: short desc)
 123 * @dev:        corresponding ti remote processor device
 124 *
 125 * Return: 0 if all went ok, else corresponding -ve error
 126 */
 127static int ti_powerproc_start(struct udevice *dev)
 128{
 129        struct dm_rproc_uclass_pdata *uc_pdata;
 130        struct ti_powerproc_privdata *priv;
 131        int ret;
 132
 133        uc_pdata = dev_get_uclass_platdata(dev);
 134        if (!uc_pdata) {
 135                debug("%s: no uc pdata!\n", dev->name);
 136                return -EINVAL;
 137        }
 138
 139        priv = dev_get_priv(dev);
 140        ret = psc_disable_module(priv->psc_module);
 141        if (ret) {
 142                debug("%s Unable to disable module '%d'(ret=%d)\n",
 143                      uc_pdata->name, priv->psc_module, ret);
 144                return ret;
 145        }
 146
 147        ret = psc_module_release_from_reset(priv->psc_module);
 148        if (ret) {
 149                debug("%s Failed to wait for module '%d'(ret=%d)\n",
 150                      uc_pdata->name, priv->psc_module, ret);
 151                return ret;
 152        }
 153        ret = psc_enable_module(priv->psc_module);
 154        if (ret) {
 155                debug("%s Unable to disable module '%d'(ret=%d)\n",
 156                      uc_pdata->name, priv->psc_module, ret);
 157                return ret;
 158        }
 159
 160        return 0;
 161}
 162
 163static const struct dm_rproc_ops ti_powerproc_ops = {
 164        .load = ti_powerproc_load,
 165        .start = ti_powerproc_start,
 166};
 167
 168static const struct udevice_id ti_powerproc_ids[] = {
 169        {.compatible = "ti,power-processor"},
 170        {}
 171};
 172
 173U_BOOT_DRIVER(ti_powerproc) = {
 174        .name = "ti_power_proc",
 175        .of_match = ti_powerproc_ids,
 176        .id = UCLASS_REMOTEPROC,
 177        .ops = &ti_powerproc_ops,
 178        .probe = ti_powerproc_probe,
 179        .priv_auto_alloc_size = sizeof(struct ti_powerproc_privdata),
 180};
 181