blob: e974eb59e0cf10071dc59cb8fa0f4426c3656fc5 [file] [log] [blame]
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 */
13
14/*
15 * RPCROUTER SMD XPRT module.
16 */
17
Steve Mucklef132c6c2012-06-06 18:30:57 -070018#include <linux/module.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070019#include <linux/platform_device.h>
20#include <linux/types.h>
Steve Mucklef132c6c2012-06-06 18:30:57 -070021#include <linux/export.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070022
23#include <mach/msm_smd.h>
24#include "smd_rpcrouter.h"
25#include "smd_private.h"
26
27struct rpcrouter_smd_xprt {
28 struct rpcrouter_xprt xprt;
29
30 smd_channel_t *channel;
31};
32
33static struct rpcrouter_smd_xprt smd_remote_xprt;
34#ifdef CONFIG_ARCH_FSM9XXX
35static struct rpcrouter_smd_xprt smd_remote_qdsp_xprt;
36#endif
37
38static int rpcrouter_smd_remote_read_avail(void)
39{
40 return smd_read_avail(smd_remote_xprt.channel);
41}
42
43static int rpcrouter_smd_remote_read(void *data, uint32_t len)
44{
45 return smd_read(smd_remote_xprt.channel, data, len);
46}
47
48static int rpcrouter_smd_remote_write_avail(void)
49{
50 return smd_write_avail(smd_remote_xprt.channel);
51}
52
53static int rpcrouter_smd_remote_write(void *data, uint32_t len, uint32_t type)
54{
55 return smd_write(smd_remote_xprt.channel, data, len);
56}
57
58static int rpcrouter_smd_remote_close(void)
59{
60 smsm_change_state(SMSM_APPS_STATE, SMSM_RPCINIT, 0);
61 return smd_close(smd_remote_xprt.channel);
62}
63
64static void rpcrouter_smd_remote_notify(void *_dev, unsigned event)
65{
66 switch (event) {
67 case SMD_EVENT_DATA:
68 msm_rpcrouter_xprt_notify(&smd_remote_xprt.xprt,
69 RPCROUTER_XPRT_EVENT_DATA);
70 break;
71
72 case SMD_EVENT_OPEN:
73 pr_info("%s: smd opened 0x%p\n", __func__, _dev);
74
75 msm_rpcrouter_xprt_notify(&smd_remote_xprt.xprt,
76 RPCROUTER_XPRT_EVENT_OPEN);
77 break;
78
79 case SMD_EVENT_CLOSE:
80 pr_info("%s: smd closed 0x%p\n", __func__, _dev);
81
82 msm_rpcrouter_xprt_notify(&smd_remote_xprt.xprt,
83 RPCROUTER_XPRT_EVENT_CLOSE);
84 break;
85 }
86}
87
88#ifdef CONFIG_ARCH_FSM9XXX
89static int rpcrouter_smd_remote_qdsp_read_avail(void)
90{
91 return smd_read_avail(smd_remote_qdsp_xprt.channel);
92}
93
94static int rpcrouter_smd_remote_qdsp_read(void *data, uint32_t len)
95{
96 return smd_read(smd_remote_qdsp_xprt.channel, data, len);
97}
98
99static int rpcrouter_smd_remote_qdsp_write_avail(void)
100{
101 return smd_write_avail(smd_remote_qdsp_xprt.channel);
102}
103
104static int rpcrouter_smd_remote_qdsp_write(void *data,
105 uint32_t len, uint32_t type)
106{
107 return smd_write(smd_remote_qdsp_xprt.channel, data, len);
108}
109
110static int rpcrouter_smd_remote_qdsp_close(void)
111{
112 /*
113 * TBD: Implement when we have N way SMSM ported
114 * smsm_change_state(SMSM_APPS_STATE, SMSM_RPCINIT, 0);
115 */
116 return smd_close(smd_remote_qdsp_xprt.channel);
117}
118
119static void rpcrouter_smd_remote_qdsp_notify(void *_dev, unsigned event)
120{
121 switch (event) {
122 case SMD_EVENT_DATA:
123 msm_rpcrouter_xprt_notify(&smd_remote_qdsp_xprt.xprt,
124 RPCROUTER_XPRT_EVENT_DATA);
125 break;
126
127 case SMD_EVENT_OPEN:
128 /* Print log info */
129 pr_debug("%s: smd opened\n", __func__);
130
131 msm_rpcrouter_xprt_notify(&smd_remote_qdsp_xprt.xprt,
132 RPCROUTER_XPRT_EVENT_OPEN);
133 break;
134
135 case SMD_EVENT_CLOSE:
136 /* Print log info */
137 pr_debug("%s: smd closed\n", __func__);
138
139 msm_rpcrouter_xprt_notify(&smd_remote_qdsp_xprt.xprt,
140 RPCROUTER_XPRT_EVENT_CLOSE);
141 break;
142 }
143}
144
145static int rpcrouter_smd_remote_qdsp_probe(struct platform_device *pdev)
146{
147 int rc;
148
149 smd_remote_qdsp_xprt.xprt.name = "rpcrotuer_smd_qdsp_xprt";
150 smd_remote_qdsp_xprt.xprt.read_avail =
151 rpcrouter_smd_remote_qdsp_read_avail;
152 smd_remote_qdsp_xprt.xprt.read = rpcrouter_smd_remote_qdsp_read;
153 smd_remote_qdsp_xprt.xprt.write_avail =
154 rpcrouter_smd_remote_qdsp_write_avail;
155 smd_remote_qdsp_xprt.xprt.write = rpcrouter_smd_remote_qdsp_write;
156 smd_remote_qdsp_xprt.xprt.close = rpcrouter_smd_remote_qdsp_close;
157 smd_remote_qdsp_xprt.xprt.priv = NULL;
158
159 /* Open up SMD channel */
160 rc = smd_named_open_on_edge("RPCCALL_QDSP", SMD_APPS_QDSP,
161 &smd_remote_qdsp_xprt.channel, NULL,
162 rpcrouter_smd_remote_qdsp_notify);
163 if (rc < 0)
164 return rc;
165
166 smd_disable_read_intr(smd_remote_qdsp_xprt.channel);
167
168 return 0;
169}
170
171static struct platform_driver rpcrouter_smd_remote_qdsp_driver = {
172 .probe = rpcrouter_smd_remote_qdsp_probe,
173 .driver = {
174 .name = "RPCCALL_QDSP",
175 .owner = THIS_MODULE,
176 },
177};
178
179static inline int register_smd_remote_qpsp_driver(void)
180{
181 return platform_driver_register(&rpcrouter_smd_remote_qdsp_driver);
182}
183#else /* CONFIG_ARCH_FSM9XXX */
184static inline int register_smd_remote_qpsp_driver(void)
185{
186 return 0;
187}
188#endif
189
190#if defined(CONFIG_MSM_RPC_LOOPBACK_XPRT)
191
192static struct rpcrouter_smd_xprt smd_loopback_xprt;
193
194static int rpcrouter_smd_loopback_read_avail(void)
195{
196 return smd_read_avail(smd_loopback_xprt.channel);
197}
198
199static int rpcrouter_smd_loopback_read(void *data, uint32_t len)
200{
201 return smd_read(smd_loopback_xprt.channel, data, len);
202}
203
204static int rpcrouter_smd_loopback_write_avail(void)
205{
206 return smd_write_avail(smd_loopback_xprt.channel);
207}
208
209static int rpcrouter_smd_loopback_write(void *data, uint32_t len, uint32 type)
210{
211 return smd_write(smd_loopback_xprt.channel, data, len);
212}
213
214static int rpcrouter_smd_loopback_close(void)
215{
216 return smd_close(smd_loopback_xprt.channel);
217}
218
219static void rpcrouter_smd_loopback_notify(void *_dev, unsigned event)
220{
221 switch (event) {
222 case SMD_EVENT_DATA:
223 msm_rpcrouter_xprt_notify(&smd_loopback_xprt.xprt,
224 RPCROUTER_XPRT_EVENT_DATA);
225 break;
226
227 case SMD_EVENT_OPEN:
228 pr_debug("%s: smd loopback opened 0x%p\n", __func__, _dev);
229
230 msm_rpcrouter_xprt_notify(&smd_loopback_xprt.xprt,
231 RPCROUTER_XPRT_EVENT_OPEN);
232 break;
233
234 case SMD_EVENT_CLOSE:
235 pr_debug("%s: smd loopback closed 0x%p\n", __func__, _dev);
236
237 msm_rpcrouter_xprt_notify(&smd_loopback_xprt.xprt,
238 RPCROUTER_XPRT_EVENT_CLOSE);
239 break;
240 }
241}
242
243static int rpcrouter_smd_loopback_probe(struct platform_device *pdev)
244{
245 int rc;
246
247 smd_loopback_xprt.xprt.name = "rpcrouter_loopback_xprt";
248 smd_loopback_xprt.xprt.read_avail = rpcrouter_smd_loopback_read_avail;
249 smd_loopback_xprt.xprt.read = rpcrouter_smd_loopback_read;
250 smd_loopback_xprt.xprt.write_avail = rpcrouter_smd_loopback_write_avail;
251 smd_loopback_xprt.xprt.write = rpcrouter_smd_loopback_write;
252 smd_loopback_xprt.xprt.close = rpcrouter_smd_loopback_close;
253 smd_loopback_xprt.xprt.priv = NULL;
254
255 /* Open up SMD LOOPBACK channel */
256 rc = smd_named_open_on_edge("local_loopback", SMD_LOOPBACK_TYPE,
257 &smd_loopback_xprt.channel, NULL,
258 rpcrouter_smd_loopback_notify);
259 if (rc < 0)
260 return rc;
261
262 smd_disable_read_intr(smd_remote_xprt.channel);
263 return 0;
264}
265
266static struct platform_driver rpcrouter_smd_loopback_driver = {
267 .probe = rpcrouter_smd_loopback_probe,
268 .driver = {
269 .name = "local_loopback",
270 .owner = THIS_MODULE,
271 },
272};
273
274static inline int register_smd_loopback_driver(void)
275{
276 return platform_driver_register(&rpcrouter_smd_loopback_driver);
277}
278#else /* CONFIG_MSM_RPC_LOOPBACK_XPRT */
279static inline int register_smd_loopback_driver(void)
280{
281 return 0;
282}
283#endif
284
285static int rpcrouter_smd_remote_probe(struct platform_device *pdev)
286{
287 int rc;
288
289 smd_remote_xprt.xprt.name = "rpcrotuer_smd_xprt";
290 smd_remote_xprt.xprt.read_avail = rpcrouter_smd_remote_read_avail;
291 smd_remote_xprt.xprt.read = rpcrouter_smd_remote_read;
292 smd_remote_xprt.xprt.write_avail = rpcrouter_smd_remote_write_avail;
293 smd_remote_xprt.xprt.write = rpcrouter_smd_remote_write;
294 smd_remote_xprt.xprt.close = rpcrouter_smd_remote_close;
295 smd_remote_xprt.xprt.priv = NULL;
296
297 /* Open up SMD channel */
298 rc = smd_open("RPCCALL", &smd_remote_xprt.channel, NULL,
299 rpcrouter_smd_remote_notify);
300 if (rc < 0)
301 return rc;
302
303 smd_disable_read_intr(smd_remote_xprt.channel);
304
305 return 0;
306}
307
308static struct platform_driver rpcrouter_smd_remote_driver = {
309 .probe = rpcrouter_smd_remote_probe,
310 .driver = {
311 .name = "RPCCALL",
312 .owner = THIS_MODULE,
313 },
314};
315
316static int __init rpcrouter_smd_init(void)
317{
318 int rc;
319
320 rc = register_smd_loopback_driver();
321 if (rc < 0)
322 return rc;
323
324 rc = register_smd_remote_qpsp_driver();
325 if (rc < 0)
326 return rc;
327
328 return platform_driver_register(&rpcrouter_smd_remote_driver);
329}
330
331module_init(rpcrouter_smd_init);
332MODULE_DESCRIPTION("RPC Router SMD XPRT");
333MODULE_LICENSE("GPL v2");