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