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