uboot/drivers/mailbox/mailbox-uclass.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2016, NVIDIA CORPORATION.
   3 *
   4 * SPDX-License-Identifier: GPL-2.0
   5 */
   6
   7#include <common.h>
   8#include <dm.h>
   9#include <mailbox.h>
  10#include <mailbox-uclass.h>
  11
  12DECLARE_GLOBAL_DATA_PTR;
  13
  14static inline struct mbox_ops *mbox_dev_ops(struct udevice *dev)
  15{
  16        return (struct mbox_ops *)dev->driver->ops;
  17}
  18
  19static int mbox_of_xlate_default(struct mbox_chan *chan,
  20                                 struct ofnode_phandle_args *args)
  21{
  22        debug("%s(chan=%p)\n", __func__, chan);
  23
  24        if (args->args_count != 1) {
  25                debug("Invaild args_count: %d\n", args->args_count);
  26                return -EINVAL;
  27        }
  28
  29        chan->id = args->args[0];
  30
  31        return 0;
  32}
  33
  34int mbox_get_by_index(struct udevice *dev, int index, struct mbox_chan *chan)
  35{
  36        struct ofnode_phandle_args args;
  37        int ret;
  38        struct udevice *dev_mbox;
  39        struct mbox_ops *ops;
  40
  41        debug("%s(dev=%p, index=%d, chan=%p)\n", __func__, dev, index, chan);
  42
  43        ret = dev_read_phandle_with_args(dev, "mboxes", "#mbox-cells", 0, index,
  44                                         &args);
  45        if (ret) {
  46                debug("%s: dev_read_phandle_with_args failed: %d\n", __func__,
  47                      ret);
  48                return ret;
  49        }
  50
  51        ret = uclass_get_device_by_ofnode(UCLASS_MAILBOX, args.node, &dev_mbox);
  52        if (ret) {
  53                debug("%s: uclass_get_device_by_of_offset failed: %d\n",
  54                      __func__, ret);
  55                return ret;
  56        }
  57        ops = mbox_dev_ops(dev_mbox);
  58
  59        chan->dev = dev_mbox;
  60        if (ops->of_xlate)
  61                ret = ops->of_xlate(chan, &args);
  62        else
  63                ret = mbox_of_xlate_default(chan, &args);
  64        if (ret) {
  65                debug("of_xlate() failed: %d\n", ret);
  66                return ret;
  67        }
  68
  69        ret = ops->request(chan);
  70        if (ret) {
  71                debug("ops->request() failed: %d\n", ret);
  72                return ret;
  73        }
  74
  75        return 0;
  76}
  77
  78int mbox_get_by_name(struct udevice *dev, const char *name,
  79                     struct mbox_chan *chan)
  80{
  81        int index;
  82
  83        debug("%s(dev=%p, name=%s, chan=%p)\n", __func__, dev, name, chan);
  84
  85        index = dev_read_stringlist_search(dev, "mbox-names", name);
  86        if (index < 0) {
  87                debug("fdt_stringlist_search() failed: %d\n", index);
  88                return index;
  89        }
  90
  91        return mbox_get_by_index(dev, index, chan);
  92}
  93
  94int mbox_free(struct mbox_chan *chan)
  95{
  96        struct mbox_ops *ops = mbox_dev_ops(chan->dev);
  97
  98        debug("%s(chan=%p)\n", __func__, chan);
  99
 100        return ops->free(chan);
 101}
 102
 103int mbox_send(struct mbox_chan *chan, const void *data)
 104{
 105        struct mbox_ops *ops = mbox_dev_ops(chan->dev);
 106
 107        debug("%s(chan=%p, data=%p)\n", __func__, chan, data);
 108
 109        return ops->send(chan, data);
 110}
 111
 112int mbox_recv(struct mbox_chan *chan, void *data, ulong timeout_us)
 113{
 114        struct mbox_ops *ops = mbox_dev_ops(chan->dev);
 115        ulong start_time;
 116        int ret;
 117
 118        debug("%s(chan=%p, data=%p, timeout_us=%ld)\n", __func__, chan, data,
 119              timeout_us);
 120
 121        start_time = timer_get_us();
 122        /*
 123         * Account for partial us ticks, but if timeout_us is 0, ensure we
 124         * still don't wait at all.
 125         */
 126        if (timeout_us)
 127                timeout_us++;
 128
 129        for (;;) {
 130                ret = ops->recv(chan, data);
 131                if (ret != -ENODATA)
 132                        return ret;
 133                if ((timer_get_us() - start_time) >= timeout_us)
 134                        return -ETIMEDOUT;
 135        }
 136}
 137
 138UCLASS_DRIVER(mailbox) = {
 139        .id             = UCLASS_MAILBOX,
 140        .name           = "mailbox",
 141};
 142