xref: /rk3399_rockchip-uboot/drivers/mailbox/mailbox-uclass.c (revision 769d52ef0f04812fd65ef2f3ab921ad2e8562ab1)
16238935dSStephen Warren /*
26238935dSStephen Warren  * Copyright (c) 2016, NVIDIA CORPORATION.
36238935dSStephen Warren  *
46238935dSStephen Warren  * SPDX-License-Identifier: GPL-2.0
56238935dSStephen Warren  */
66238935dSStephen Warren 
76238935dSStephen Warren #include <common.h>
86238935dSStephen Warren #include <dm.h>
96238935dSStephen Warren #include <fdtdec.h>
10*769d52efSStephen Warren #include <mailbox.h>
11*769d52efSStephen Warren #include <mailbox-uclass.h>
126238935dSStephen Warren 
136238935dSStephen Warren DECLARE_GLOBAL_DATA_PTR;
146238935dSStephen Warren 
156238935dSStephen Warren static inline struct mbox_ops *mbox_dev_ops(struct udevice *dev)
166238935dSStephen Warren {
176238935dSStephen Warren 	return (struct mbox_ops *)dev->driver->ops;
186238935dSStephen Warren }
196238935dSStephen Warren 
206238935dSStephen Warren static int mbox_of_xlate_default(struct mbox_chan *chan,
216238935dSStephen Warren 				 struct fdtdec_phandle_args *args)
226238935dSStephen Warren {
236238935dSStephen Warren 	debug("%s(chan=%p)\n", __func__, chan);
246238935dSStephen Warren 
256238935dSStephen Warren 	if (args->args_count != 1) {
266238935dSStephen Warren 		debug("Invaild args_count: %d\n", args->args_count);
276238935dSStephen Warren 		return -EINVAL;
286238935dSStephen Warren 	}
296238935dSStephen Warren 
306238935dSStephen Warren 	chan->id = args->args[0];
316238935dSStephen Warren 
326238935dSStephen Warren 	return 0;
336238935dSStephen Warren }
346238935dSStephen Warren 
356238935dSStephen Warren int mbox_get_by_index(struct udevice *dev, int index, struct mbox_chan *chan)
366238935dSStephen Warren {
376238935dSStephen Warren 	struct fdtdec_phandle_args args;
386238935dSStephen Warren 	int ret;
396238935dSStephen Warren 	struct udevice *dev_mbox;
406238935dSStephen Warren 	struct mbox_ops *ops;
416238935dSStephen Warren 
426238935dSStephen Warren 	debug("%s(dev=%p, index=%d, chan=%p)\n", __func__, dev, index, chan);
436238935dSStephen Warren 
446238935dSStephen Warren 	ret = fdtdec_parse_phandle_with_args(gd->fdt_blob, dev->of_offset,
456238935dSStephen Warren 					     "mboxes", "#mbox-cells", 0,
466238935dSStephen Warren 					     index, &args);
476238935dSStephen Warren 	if (ret) {
486238935dSStephen Warren 		debug("%s: fdtdec_parse_phandle_with_args failed: %d\n",
496238935dSStephen Warren 		      __func__, ret);
506238935dSStephen Warren 		return ret;
516238935dSStephen Warren 	}
526238935dSStephen Warren 
536238935dSStephen Warren 	ret = uclass_get_device_by_of_offset(UCLASS_MAILBOX, args.node,
546238935dSStephen Warren 					     &dev_mbox);
556238935dSStephen Warren 	if (ret) {
566238935dSStephen Warren 		debug("%s: uclass_get_device_by_of_offset failed: %d\n",
576238935dSStephen Warren 		      __func__, ret);
586238935dSStephen Warren 		return ret;
596238935dSStephen Warren 	}
606238935dSStephen Warren 	ops = mbox_dev_ops(dev_mbox);
616238935dSStephen Warren 
626238935dSStephen Warren 	chan->dev = dev_mbox;
636238935dSStephen Warren 	if (ops->of_xlate)
646238935dSStephen Warren 		ret = ops->of_xlate(chan, &args);
656238935dSStephen Warren 	else
666238935dSStephen Warren 		ret = mbox_of_xlate_default(chan, &args);
676238935dSStephen Warren 	if (ret) {
686238935dSStephen Warren 		debug("of_xlate() failed: %d\n", ret);
696238935dSStephen Warren 		return ret;
706238935dSStephen Warren 	}
716238935dSStephen Warren 
726238935dSStephen Warren 	ret = ops->request(chan);
736238935dSStephen Warren 	if (ret) {
746238935dSStephen Warren 		debug("ops->request() failed: %d\n", ret);
756238935dSStephen Warren 		return ret;
766238935dSStephen Warren 	}
776238935dSStephen Warren 
786238935dSStephen Warren 	return 0;
796238935dSStephen Warren }
806238935dSStephen Warren 
816238935dSStephen Warren int mbox_get_by_name(struct udevice *dev, const char *name,
826238935dSStephen Warren 		     struct mbox_chan *chan)
836238935dSStephen Warren {
846238935dSStephen Warren 	int index;
856238935dSStephen Warren 
866238935dSStephen Warren 	debug("%s(dev=%p, name=%s, chan=%p)\n", __func__, dev, name, chan);
876238935dSStephen Warren 
886238935dSStephen Warren 	index = fdt_find_string(gd->fdt_blob, dev->of_offset, "mbox-names",
896238935dSStephen Warren 				name);
906238935dSStephen Warren 	if (index < 0) {
916238935dSStephen Warren 		debug("fdt_find_string() failed: %d\n", index);
926238935dSStephen Warren 		return index;
936238935dSStephen Warren 	}
946238935dSStephen Warren 
956238935dSStephen Warren 	return mbox_get_by_index(dev, index, chan);
966238935dSStephen Warren }
976238935dSStephen Warren 
986238935dSStephen Warren int mbox_free(struct mbox_chan *chan)
996238935dSStephen Warren {
1006238935dSStephen Warren 	struct mbox_ops *ops = mbox_dev_ops(chan->dev);
1016238935dSStephen Warren 
1026238935dSStephen Warren 	debug("%s(chan=%p)\n", __func__, chan);
1036238935dSStephen Warren 
1046238935dSStephen Warren 	return ops->free(chan);
1056238935dSStephen Warren }
1066238935dSStephen Warren 
1076238935dSStephen Warren int mbox_send(struct mbox_chan *chan, const void *data)
1086238935dSStephen Warren {
1096238935dSStephen Warren 	struct mbox_ops *ops = mbox_dev_ops(chan->dev);
1106238935dSStephen Warren 
1116238935dSStephen Warren 	debug("%s(chan=%p, data=%p)\n", __func__, chan, data);
1126238935dSStephen Warren 
1136238935dSStephen Warren 	return ops->send(chan, data);
1146238935dSStephen Warren }
1156238935dSStephen Warren 
1166238935dSStephen Warren int mbox_recv(struct mbox_chan *chan, void *data, ulong timeout_us)
1176238935dSStephen Warren {
1186238935dSStephen Warren 	struct mbox_ops *ops = mbox_dev_ops(chan->dev);
1196238935dSStephen Warren 	ulong start_time;
1206238935dSStephen Warren 	int ret;
1216238935dSStephen Warren 
1226238935dSStephen Warren 	debug("%s(chan=%p, data=%p, timeout_us=%ld)\n", __func__, chan, data,
1236238935dSStephen Warren 	      timeout_us);
1246238935dSStephen Warren 
1256238935dSStephen Warren 	start_time = timer_get_us();
1266238935dSStephen Warren 	/*
1276238935dSStephen Warren 	 * Account for partial us ticks, but if timeout_us is 0, ensure we
1286238935dSStephen Warren 	 * still don't wait at all.
1296238935dSStephen Warren 	 */
1306238935dSStephen Warren 	if (timeout_us)
1316238935dSStephen Warren 		timeout_us++;
1326238935dSStephen Warren 
1336238935dSStephen Warren 	for (;;) {
1346238935dSStephen Warren 		ret = ops->recv(chan, data);
1356238935dSStephen Warren 		if (ret != -ENODATA)
1366238935dSStephen Warren 			return ret;
1376238935dSStephen Warren 		if ((timer_get_us() - start_time) >= timeout_us)
1386238935dSStephen Warren 			return -ETIMEDOUT;
1396238935dSStephen Warren 	}
1406238935dSStephen Warren }
1416238935dSStephen Warren 
1426238935dSStephen Warren UCLASS_DRIVER(mailbox) = {
1436238935dSStephen Warren 	.id		= UCLASS_MAILBOX,
1446238935dSStephen Warren 	.name		= "mailbox",
1456238935dSStephen Warren };
146