This source file includes following definitions.
- glink_subdev_start
- glink_subdev_stop
- qcom_add_glink_subdev
- qcom_remove_glink_subdev
- qcom_register_dump_segments
- smd_subdev_start
- smd_subdev_stop
- qcom_add_smd_subdev
- qcom_remove_smd_subdev
- qcom_register_ssr_notifier
- qcom_unregister_ssr_notifier
- ssr_notify_unprepare
- qcom_add_ssr_subdev
- qcom_remove_ssr_subdev
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  10 #include <linux/firmware.h>
  11 #include <linux/kernel.h>
  12 #include <linux/module.h>
  13 #include <linux/notifier.h>
  14 #include <linux/remoteproc.h>
  15 #include <linux/rpmsg/qcom_glink.h>
  16 #include <linux/rpmsg/qcom_smd.h>
  17 #include <linux/soc/qcom/mdt_loader.h>
  18 
  19 #include "remoteproc_internal.h"
  20 #include "qcom_common.h"
  21 
  22 #define to_glink_subdev(d) container_of(d, struct qcom_rproc_glink, subdev)
  23 #define to_smd_subdev(d) container_of(d, struct qcom_rproc_subdev, subdev)
  24 #define to_ssr_subdev(d) container_of(d, struct qcom_rproc_ssr, subdev)
  25 
  26 static BLOCKING_NOTIFIER_HEAD(ssr_notifiers);
  27 
  28 static int glink_subdev_start(struct rproc_subdev *subdev)
  29 {
  30         struct qcom_rproc_glink *glink = to_glink_subdev(subdev);
  31 
  32         glink->edge = qcom_glink_smem_register(glink->dev, glink->node);
  33 
  34         return PTR_ERR_OR_ZERO(glink->edge);
  35 }
  36 
  37 static void glink_subdev_stop(struct rproc_subdev *subdev, bool crashed)
  38 {
  39         struct qcom_rproc_glink *glink = to_glink_subdev(subdev);
  40 
  41         qcom_glink_smem_unregister(glink->edge);
  42         glink->edge = NULL;
  43 }
  44 
  45 
  46 
  47 
  48 
  49 
  50 void qcom_add_glink_subdev(struct rproc *rproc, struct qcom_rproc_glink *glink)
  51 {
  52         struct device *dev = &rproc->dev;
  53 
  54         glink->node = of_get_child_by_name(dev->parent->of_node, "glink-edge");
  55         if (!glink->node)
  56                 return;
  57 
  58         glink->dev = dev;
  59         glink->subdev.start = glink_subdev_start;
  60         glink->subdev.stop = glink_subdev_stop;
  61 
  62         rproc_add_subdev(rproc, &glink->subdev);
  63 }
  64 EXPORT_SYMBOL_GPL(qcom_add_glink_subdev);
  65 
  66 
  67 
  68 
  69 
  70 
  71 void qcom_remove_glink_subdev(struct rproc *rproc, struct qcom_rproc_glink *glink)
  72 {
  73         if (!glink->node)
  74                 return;
  75 
  76         rproc_remove_subdev(rproc, &glink->subdev);
  77         of_node_put(glink->node);
  78 }
  79 EXPORT_SYMBOL_GPL(qcom_remove_glink_subdev);
  80 
  81 
  82 
  83 
  84 
  85 
  86 
  87 
  88 
  89 
  90 int qcom_register_dump_segments(struct rproc *rproc,
  91                                 const struct firmware *fw)
  92 {
  93         const struct elf32_phdr *phdrs;
  94         const struct elf32_phdr *phdr;
  95         const struct elf32_hdr *ehdr;
  96         int ret;
  97         int i;
  98 
  99         ehdr = (struct elf32_hdr *)fw->data;
 100         phdrs = (struct elf32_phdr *)(ehdr + 1);
 101 
 102         for (i = 0; i < ehdr->e_phnum; i++) {
 103                 phdr = &phdrs[i];
 104 
 105                 if (phdr->p_type != PT_LOAD)
 106                         continue;
 107 
 108                 if ((phdr->p_flags & QCOM_MDT_TYPE_MASK) == QCOM_MDT_TYPE_HASH)
 109                         continue;
 110 
 111                 if (!phdr->p_memsz)
 112                         continue;
 113 
 114                 ret = rproc_coredump_add_segment(rproc, phdr->p_paddr,
 115                                                  phdr->p_memsz);
 116                 if (ret)
 117                         return ret;
 118         }
 119 
 120         return 0;
 121 }
 122 EXPORT_SYMBOL_GPL(qcom_register_dump_segments);
 123 
 124 static int smd_subdev_start(struct rproc_subdev *subdev)
 125 {
 126         struct qcom_rproc_subdev *smd = to_smd_subdev(subdev);
 127 
 128         smd->edge = qcom_smd_register_edge(smd->dev, smd->node);
 129 
 130         return PTR_ERR_OR_ZERO(smd->edge);
 131 }
 132 
 133 static void smd_subdev_stop(struct rproc_subdev *subdev, bool crashed)
 134 {
 135         struct qcom_rproc_subdev *smd = to_smd_subdev(subdev);
 136 
 137         qcom_smd_unregister_edge(smd->edge);
 138         smd->edge = NULL;
 139 }
 140 
 141 
 142 
 143 
 144 
 145 
 146 void qcom_add_smd_subdev(struct rproc *rproc, struct qcom_rproc_subdev *smd)
 147 {
 148         struct device *dev = &rproc->dev;
 149 
 150         smd->node = of_get_child_by_name(dev->parent->of_node, "smd-edge");
 151         if (!smd->node)
 152                 return;
 153 
 154         smd->dev = dev;
 155         smd->subdev.start = smd_subdev_start;
 156         smd->subdev.stop = smd_subdev_stop;
 157 
 158         rproc_add_subdev(rproc, &smd->subdev);
 159 }
 160 EXPORT_SYMBOL_GPL(qcom_add_smd_subdev);
 161 
 162 
 163 
 164 
 165 
 166 
 167 void qcom_remove_smd_subdev(struct rproc *rproc, struct qcom_rproc_subdev *smd)
 168 {
 169         if (!smd->node)
 170                 return;
 171 
 172         rproc_remove_subdev(rproc, &smd->subdev);
 173         of_node_put(smd->node);
 174 }
 175 EXPORT_SYMBOL_GPL(qcom_remove_smd_subdev);
 176 
 177 
 178 
 179 
 180 
 181 
 182 
 183 
 184 
 185 
 186 
 187 int qcom_register_ssr_notifier(struct notifier_block *nb)
 188 {
 189         return blocking_notifier_chain_register(&ssr_notifiers, nb);
 190 }
 191 EXPORT_SYMBOL_GPL(qcom_register_ssr_notifier);
 192 
 193 
 194 
 195 
 196 
 197 void qcom_unregister_ssr_notifier(struct notifier_block *nb)
 198 {
 199         blocking_notifier_chain_unregister(&ssr_notifiers, nb);
 200 }
 201 EXPORT_SYMBOL_GPL(qcom_unregister_ssr_notifier);
 202 
 203 static void ssr_notify_unprepare(struct rproc_subdev *subdev)
 204 {
 205         struct qcom_rproc_ssr *ssr = to_ssr_subdev(subdev);
 206 
 207         blocking_notifier_call_chain(&ssr_notifiers, 0, (void *)ssr->name);
 208 }
 209 
 210 
 211 
 212 
 213 
 214 
 215 
 216 
 217 
 218 
 219 void qcom_add_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr,
 220                          const char *ssr_name)
 221 {
 222         ssr->name = ssr_name;
 223         ssr->subdev.unprepare = ssr_notify_unprepare;
 224 
 225         rproc_add_subdev(rproc, &ssr->subdev);
 226 }
 227 EXPORT_SYMBOL_GPL(qcom_add_ssr_subdev);
 228 
 229 
 230 
 231 
 232 
 233 
 234 void qcom_remove_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr)
 235 {
 236         rproc_remove_subdev(rproc, &ssr->subdev);
 237 }
 238 EXPORT_SYMBOL_GPL(qcom_remove_ssr_subdev);
 239 
 240 MODULE_DESCRIPTION("Qualcomm Remoteproc helper driver");
 241 MODULE_LICENSE("GPL v2");