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