xref: /rk3399_rockchip-uboot/drivers/mailbox/mailbox-uclass.c (revision 5e1ff6480fbe7cf1b2be1f8a13086b217b2f8578)
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>
9769d52efSStephen Warren #include <mailbox.h>
10769d52efSStephen Warren #include <mailbox-uclass.h>
116238935dSStephen Warren 
126238935dSStephen Warren DECLARE_GLOBAL_DATA_PTR;
136238935dSStephen Warren 
mbox_dev_ops(struct udevice * dev)146238935dSStephen Warren static inline struct mbox_ops *mbox_dev_ops(struct udevice *dev)
156238935dSStephen Warren {
166238935dSStephen Warren 	return (struct mbox_ops *)dev->driver->ops;
176238935dSStephen Warren }
186238935dSStephen Warren 
mbox_of_xlate_default(struct mbox_chan * chan,struct ofnode_phandle_args * args)196238935dSStephen Warren static int mbox_of_xlate_default(struct mbox_chan *chan,
20*5e1ff648SSimon Glass 				 struct ofnode_phandle_args *args)
216238935dSStephen Warren {
226238935dSStephen Warren 	debug("%s(chan=%p)\n", __func__, chan);
236238935dSStephen Warren 
246238935dSStephen Warren 	if (args->args_count != 1) {
256238935dSStephen Warren 		debug("Invaild args_count: %d\n", args->args_count);
266238935dSStephen Warren 		return -EINVAL;
276238935dSStephen Warren 	}
286238935dSStephen Warren 
296238935dSStephen Warren 	chan->id = args->args[0];
306238935dSStephen Warren 
316238935dSStephen Warren 	return 0;
326238935dSStephen Warren }
336238935dSStephen Warren 
mbox_get_by_index(struct udevice * dev,int index,struct mbox_chan * chan)346238935dSStephen Warren int mbox_get_by_index(struct udevice *dev, int index, struct mbox_chan *chan)
356238935dSStephen Warren {
36*5e1ff648SSimon Glass 	struct ofnode_phandle_args args;
376238935dSStephen Warren 	int ret;
386238935dSStephen Warren 	struct udevice *dev_mbox;
396238935dSStephen Warren 	struct mbox_ops *ops;
406238935dSStephen Warren 
416238935dSStephen Warren 	debug("%s(dev=%p, index=%d, chan=%p)\n", __func__, dev, index, chan);
426238935dSStephen Warren 
43*5e1ff648SSimon Glass 	ret = dev_read_phandle_with_args(dev, "mboxes", "#mbox-cells", 0, index,
44*5e1ff648SSimon Glass 					 &args);
456238935dSStephen Warren 	if (ret) {
46*5e1ff648SSimon Glass 		debug("%s: dev_read_phandle_with_args failed: %d\n", __func__,
47*5e1ff648SSimon Glass 		      ret);
486238935dSStephen Warren 		return ret;
496238935dSStephen Warren 	}
506238935dSStephen Warren 
51*5e1ff648SSimon Glass 	ret = uclass_get_device_by_ofnode(UCLASS_MAILBOX, args.node, &dev_mbox);
526238935dSStephen Warren 	if (ret) {
536238935dSStephen Warren 		debug("%s: uclass_get_device_by_of_offset failed: %d\n",
546238935dSStephen Warren 		      __func__, ret);
556238935dSStephen Warren 		return ret;
566238935dSStephen Warren 	}
576238935dSStephen Warren 	ops = mbox_dev_ops(dev_mbox);
586238935dSStephen Warren 
596238935dSStephen Warren 	chan->dev = dev_mbox;
606238935dSStephen Warren 	if (ops->of_xlate)
616238935dSStephen Warren 		ret = ops->of_xlate(chan, &args);
626238935dSStephen Warren 	else
636238935dSStephen Warren 		ret = mbox_of_xlate_default(chan, &args);
646238935dSStephen Warren 	if (ret) {
656238935dSStephen Warren 		debug("of_xlate() failed: %d\n", ret);
666238935dSStephen Warren 		return ret;
676238935dSStephen Warren 	}
686238935dSStephen Warren 
696238935dSStephen Warren 	ret = ops->request(chan);
706238935dSStephen Warren 	if (ret) {
716238935dSStephen Warren 		debug("ops->request() failed: %d\n", ret);
726238935dSStephen Warren 		return ret;
736238935dSStephen Warren 	}
746238935dSStephen Warren 
756238935dSStephen Warren 	return 0;
766238935dSStephen Warren }
776238935dSStephen Warren 
mbox_get_by_name(struct udevice * dev,const char * name,struct mbox_chan * chan)786238935dSStephen Warren int mbox_get_by_name(struct udevice *dev, const char *name,
796238935dSStephen Warren 		     struct mbox_chan *chan)
806238935dSStephen Warren {
816238935dSStephen Warren 	int index;
826238935dSStephen Warren 
836238935dSStephen Warren 	debug("%s(dev=%p, name=%s, chan=%p)\n", __func__, dev, name, chan);
846238935dSStephen Warren 
85*5e1ff648SSimon Glass 	index = dev_read_stringlist_search(dev, "mbox-names", name);
866238935dSStephen Warren 	if (index < 0) {
87b02e4044SSimon Glass 		debug("fdt_stringlist_search() failed: %d\n", index);
886238935dSStephen Warren 		return index;
896238935dSStephen Warren 	}
906238935dSStephen Warren 
916238935dSStephen Warren 	return mbox_get_by_index(dev, index, chan);
926238935dSStephen Warren }
936238935dSStephen Warren 
mbox_free(struct mbox_chan * chan)946238935dSStephen Warren int mbox_free(struct mbox_chan *chan)
956238935dSStephen Warren {
966238935dSStephen Warren 	struct mbox_ops *ops = mbox_dev_ops(chan->dev);
976238935dSStephen Warren 
986238935dSStephen Warren 	debug("%s(chan=%p)\n", __func__, chan);
996238935dSStephen Warren 
1006238935dSStephen Warren 	return ops->free(chan);
1016238935dSStephen Warren }
1026238935dSStephen Warren 
mbox_send(struct mbox_chan * chan,const void * data)1036238935dSStephen Warren int mbox_send(struct mbox_chan *chan, const void *data)
1046238935dSStephen Warren {
1056238935dSStephen Warren 	struct mbox_ops *ops = mbox_dev_ops(chan->dev);
1066238935dSStephen Warren 
1076238935dSStephen Warren 	debug("%s(chan=%p, data=%p)\n", __func__, chan, data);
1086238935dSStephen Warren 
1096238935dSStephen Warren 	return ops->send(chan, data);
1106238935dSStephen Warren }
1116238935dSStephen Warren 
mbox_recv(struct mbox_chan * chan,void * data,ulong timeout_us)1126238935dSStephen Warren int mbox_recv(struct mbox_chan *chan, void *data, ulong timeout_us)
1136238935dSStephen Warren {
1146238935dSStephen Warren 	struct mbox_ops *ops = mbox_dev_ops(chan->dev);
1156238935dSStephen Warren 	ulong start_time;
1166238935dSStephen Warren 	int ret;
1176238935dSStephen Warren 
1186238935dSStephen Warren 	debug("%s(chan=%p, data=%p, timeout_us=%ld)\n", __func__, chan, data,
1196238935dSStephen Warren 	      timeout_us);
1206238935dSStephen Warren 
1216238935dSStephen Warren 	start_time = timer_get_us();
1226238935dSStephen Warren 	/*
1236238935dSStephen Warren 	 * Account for partial us ticks, but if timeout_us is 0, ensure we
1246238935dSStephen Warren 	 * still don't wait at all.
1256238935dSStephen Warren 	 */
1266238935dSStephen Warren 	if (timeout_us)
1276238935dSStephen Warren 		timeout_us++;
1286238935dSStephen Warren 
1296238935dSStephen Warren 	for (;;) {
1306238935dSStephen Warren 		ret = ops->recv(chan, data);
1316238935dSStephen Warren 		if (ret != -ENODATA)
1326238935dSStephen Warren 			return ret;
1336238935dSStephen Warren 		if ((timer_get_us() - start_time) >= timeout_us)
1346238935dSStephen Warren 			return -ETIMEDOUT;
1356238935dSStephen Warren 	}
1366238935dSStephen Warren }
1376238935dSStephen Warren 
1386238935dSStephen Warren UCLASS_DRIVER(mailbox) = {
1396238935dSStephen Warren 	.id		= UCLASS_MAILBOX,
1406238935dSStephen Warren 	.name		= "mailbox",
1416238935dSStephen Warren };
142