aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Zhu <r65037@freescale.com>2014-04-11 03:13:58 -0400
committerNitin Garg <nitin.garg@freescale.com>2014-04-16 09:58:22 -0400
commit141a59f4339c9012feb27dc84f490fde09acfafe (patch)
tree973466b4a11bae592a1eca9f1947d60aaa032b97
parentdecf581c1e8dbf8ca0a6964f70cb48f3d446a59a (diff)
ENGR00308382-1 mcc: add a9 linux mcc_demo driver
- based on sema4 driver, mcc stack, add the mcc_demo driver by sysfs. - mcc pingpong demo - mcc can demo NOTE: - rdc should be disabled in m4 mqx side, otherwise, a9 linux would fail to mount rootfs. - add the m4 related clks at linux side, because that the m4's clks would be turned off/on during linux boot up if they are not added at linux clk definitions. Signed-off-by: Richard Zhu <r65037@freescale.com>
-rw-r--r--drivers/char/imx_mcc/Kconfig6
-rw-r--r--drivers/char/imx_mcc/Makefile1
-rw-r--r--drivers/char/imx_mcc/imx_mcc_demo.c295
3 files changed, 302 insertions, 0 deletions
diff --git a/drivers/char/imx_mcc/Kconfig b/drivers/char/imx_mcc/Kconfig
index 1f892f8daccb..d60cf66cd8fd 100644
--- a/drivers/char/imx_mcc/Kconfig
+++ b/drivers/char/imx_mcc/Kconfig
@@ -7,3 +7,9 @@ config IMX_SEMA4
7 depends on SOC_IMX6SX 7 depends on SOC_IMX6SX
8 help 8 help
9 Support for IMX SEMA4 driver, most people should say N here. 9 Support for IMX SEMA4 driver, most people should say N here.
10
11config IMX_MCC_DEMO
12 bool "IMX MCC demo driver"
13 depends on SOC_IMX6SX && IMX_SEMA4
14 help
15 Support for IMX MCC DEMO, most people should say N here.
diff --git a/drivers/char/imx_mcc/Makefile b/drivers/char/imx_mcc/Makefile
index 4e7a91691b39..a0d60f341d07 100644
--- a/drivers/char/imx_mcc/Makefile
+++ b/drivers/char/imx_mcc/Makefile
@@ -3,3 +3,4 @@
3# 3#
4# 4#
5obj-$(CONFIG_IMX_SEMA4) += imx_sema4.o 5obj-$(CONFIG_IMX_SEMA4) += imx_sema4.o
6obj-$(CONFIG_IMX_MCC_DEMO) += imx_mcc_demo.o
diff --git a/drivers/char/imx_mcc/imx_mcc_demo.c b/drivers/char/imx_mcc/imx_mcc_demo.c
new file mode 100644
index 000000000000..6882d81dee8c
--- /dev/null
+++ b/drivers/char/imx_mcc/imx_mcc_demo.c
@@ -0,0 +1,295 @@
1/*
2 * Copyright (C) 2014 Freescale Semiconductor, Inc. All Rights Reserved.
3 */
4
5/*
6 * The code contained herein is licensed under the GNU General Public
7 * License. You may obtain a copy of the GNU General Public License
8 * Version 2 or later at the following locations:
9 *
10 * http://www.opensource.org/licenses/gpl-license.html
11 * http://www.gnu.org/copyleft/gpl.html
12 */
13
14#include <linux/delay.h>
15#include <linux/err.h>
16#include <linux/module.h>
17#include <linux/of.h>
18#include <linux/platform_device.h>
19#include <linux/suspend.h>
20
21#include <linux/imx_sema4.h>
22#include <linux/mcc_common.h>
23#include <linux/mcc_api.h>
24#include <linux/mcc_linux.h>
25#include <linux/mcc_imx6sx.h>
26
27enum {
28 MCC_NODE_A9 = 0,
29 MCC_NODE_M4 = 0,
30
31 MCC_A9_PORT = 1,
32 MCC_M4_PORT = 2,
33};
34
35/* mcc pingpong demo */
36MCC_ENDPOINT mcc_endpoint_a9_pingpong = {0, MCC_NODE_A9, MCC_A9_PORT};
37MCC_ENDPOINT mcc_endpoint_m4_pingpong = {1, MCC_NODE_M4, MCC_M4_PORT};
38/* mcc can demo */
39MCC_ENDPOINT mcc_endpoint_a9_can = {0, MCC_NODE_A9, MCC_A9_PORT};
40
41struct mcc_pp_msg {
42 unsigned int data;
43};
44
45/* Set the max len of the can msg to be 1000 bytes */
46struct mcc_can_msg {
47 char data[MCC_ATTR_BUFFER_SIZE_IN_BYTES - 24];
48};
49
50static ssize_t imx_mcc_can_demo_en(struct device *dev,
51 struct device_attribute *attr,
52 const char *buf, size_t count)
53{
54 u32 can_demo_en;
55 int i = 0, ret = 0;
56 struct mcc_can_msg msg;
57 MCC_MEM_SIZE num_of_received_bytes;
58 MCC_INFO_STRUCT mcc_info;
59
60 sscanf(buf, "%d\n", &can_demo_en);
61
62 if (can_demo_en) {
63 pr_info("imx mcc can communication demo begin.\n");
64 ret = mcc_get_info(MCC_NODE_A9, &mcc_info);
65 if (ret) {
66 pr_err("failed to get mcc info.\n");
67 return -EINVAL;
68 }
69
70 ret = mcc_create_endpoint(&mcc_endpoint_a9_can, MCC_A9_PORT);
71 if (ret) {
72 pr_err("failed to create a9 mcc ep.\n");
73 return -EINVAL;
74 }
75
76 pr_info("\nA9 mcc prepares run, MCC version is %s\n",
77 mcc_info.version_string);
78
79 while (i < 0x10000) {
80 i++;
81 /*
82 * wait for the "sleep" msg from the remote ep.
83 */
84 ret = mcc_recv_copy(&mcc_endpoint_a9_can, &msg,
85 sizeof(struct mcc_can_msg),
86 &num_of_received_bytes, 0xffffffff);
87 pr_info("%s", msg.data);
88 }
89
90 ret = mcc_destroy_endpoint(&mcc_endpoint_a9_can);
91 if (ret) {
92 pr_err("failed to destory a9 mcc ep.\n");
93 return -EINVAL;
94 } else {
95 pr_info("destory a9 mcc ep.\n");
96 }
97 }
98
99 pr_info("imx mcc demo end after %08d times recv tests.\n", i);
100 return count;
101}
102
103static ssize_t imx_mcc_pingpong_en(struct device *dev,
104 struct device_attribute *attr, const char *buf, size_t count)
105{
106 u32 pingpong_en;
107 int i = 0, ret = 0;
108 struct timeval tv1, tv2, tv3;
109 u32 tv_count1 = 0, tv_count2 = 0;
110 struct mcc_pp_msg msg;
111 MCC_MEM_SIZE num_of_received_bytes;
112 MCC_INFO_STRUCT mcc_info;
113
114 sscanf(buf, "%d\n", &pingpong_en);
115 if (pingpong_en) {
116 pr_info("imx mcc pingpong demo begin.\n");
117 ret = mcc_get_info(MCC_NODE_A9, &mcc_info);
118 if (ret) {
119 pr_err("failed to get mcc info.\n");
120 return -EINVAL;
121 }
122
123 ret = mcc_create_endpoint(&mcc_endpoint_a9_pingpong,
124 MCC_A9_PORT);
125 if (ret) {
126 pr_err("failed to create a9 mcc ep.\n");
127 return -EINVAL;
128 }
129
130 pr_info("\nA9 mcc prepares run, MCC version is %s\n",
131 mcc_info.version_string);
132 msg.data = 1;
133 while (i < 0x50000) {
134 i++;
135 i++;
136 /*
137 * wait until the remote endpoint is created by
138 * the other core
139 */
140 if (pingpong_en > 1)
141 do_gettimeofday(&tv1);
142
143 ret = mcc_send(&mcc_endpoint_m4_pingpong, &msg,
144 sizeof(struct mcc_pp_msg),
145 0xffffffff);
146
147 if (pingpong_en > 1) {
148 do_gettimeofday(&tv2);
149 tv_count1 = (tv2.tv_sec - tv1.tv_sec)
150 * USEC_PER_SEC
151 + tv2.tv_usec - tv1.tv_usec;
152 }
153 while (MCC_ERR_ENDPOINT == ret) {
154 pr_err("\n send err ret %d, re-send\n", ret);
155 ret = mcc_send(&mcc_endpoint_m4_pingpong, &msg,
156 sizeof(struct mcc_pp_msg),
157 0xffffffff);
158 msleep(5000);
159 }
160
161 if (pingpong_en > 1)
162 do_gettimeofday(&tv2);
163
164 ret = mcc_recv_copy(&mcc_endpoint_a9_pingpong, &msg,
165 sizeof(struct mcc_pp_msg),
166 &num_of_received_bytes, 0xffffffff);
167
168 if (pingpong_en > 1) {
169 do_gettimeofday(&tv3);
170 tv_count2 = (tv3.tv_sec - tv2.tv_sec)
171 * USEC_PER_SEC
172 + tv3.tv_usec - tv2.tv_usec;
173 pr_info("imx mcc: Data transfer speed tests"
174 "in pingpong. a9 -> m4:%08dus."
175 "a9 <- m4:%08dus.\n",
176 tv_count1, tv_count2);
177 }
178
179 if (MCC_SUCCESS != ret) {
180 pr_err("A9 Main task receive error: %d\n", ret);
181 } else {
182 pr_info("%08x Main task received a msg\n", i);
183 pr_info("Message: Size=0x%08x, data = 0x%08x\n",
184 num_of_received_bytes, msg.data);
185 msg.data++;
186 }
187 }
188 ret = mcc_destroy_endpoint(&mcc_endpoint_a9_pingpong);
189 if (ret) {
190 pr_err("failed to destory a9 mcc ep.\n");
191 return ret;
192 } else {
193 pr_info("destory a9 mcc ep.\n");
194 }
195 pr_info("imx mcc demo end after %08d times tests.\n", i/2);
196 }
197
198 if (ret)
199 return ret;
200 else
201 return count;
202}
203
204static DEVICE_ATTR(pingpong_en, S_IWUGO, NULL, imx_mcc_pingpong_en);
205static DEVICE_ATTR(can_demo_en, S_IWUGO, NULL, imx_mcc_can_demo_en);
206
207static struct attribute *imx_mcc_attrs[] = {
208 &dev_attr_pingpong_en.attr,
209 &dev_attr_can_demo_en.attr,
210 NULL
211};
212
213static struct attribute_group imx_mcc_attrgroup = {
214 .attrs = imx_mcc_attrs,
215};
216
217static int imx_mcc_demo_probe(struct platform_device *pdev)
218{
219 int ret = 0;
220 MCC_INFO_STRUCT mcc_info;
221
222 ret = mcc_initialize(MCC_NODE_A9);
223 if (ret) {
224 pr_err("failed to initialize mcc.\n");
225 ret = -EINVAL;
226 return ret;
227 }
228
229 ret = mcc_get_info(MCC_NODE_A9, &mcc_info);
230 if (ret) {
231 pr_err("failed to get mcc info.\n");
232 ret = -EINVAL;
233 goto out_node;
234 }
235 pr_info("\nA9 mcc prepares run, MCC version is %s\n",
236 mcc_info.version_string);
237
238 if (strcmp(mcc_info.version_string, MCC_VERSION_STRING) != 0) {
239 pr_err("\nError, different versions of the MCC library");
240 pr_err("is used on each core!\n");
241 pr_err("\nApplication is stopped now.\n");
242 ret = -EINVAL;
243 goto out_node;
244 }
245
246 /* add attributes for device. */
247 ret = sysfs_create_group(&pdev->dev.kobj, &imx_mcc_attrgroup);
248 if (ret)
249 goto out_node;
250
251 return ret;
252
253out_node:
254 mcc_destroy(MCC_NODE_A9);
255
256 return ret;
257}
258
259static int imx_mcc_demo_remove(struct platform_device *pdev)
260{
261 return 0;
262}
263
264static const struct of_device_id imx_mcc_demo_dt_ids[] = {
265 { .compatible = "fsl,imx6sx-mcc-demo", },
266 { /* sentinel */ }
267};
268MODULE_DEVICE_TABLE(of, imx_mcc_demo_dt_ids);
269
270static struct platform_driver imx_mcc_demo_driver = {
271 .driver = {
272 .owner = THIS_MODULE,
273 .name = "imx6sx-mcc-demo",
274 .of_match_table = imx_mcc_demo_dt_ids,
275 },
276 .probe = imx_mcc_demo_probe,
277 .remove = imx_mcc_demo_remove,
278};
279
280static int __init imx_mcc_demo_init(void)
281{
282 int ret;
283
284 ret = platform_driver_register(&imx_mcc_demo_driver);
285 if (ret)
286 pr_err("failed to register imx mcc demo driver.\n");
287 else
288 pr_info("imx mcc demo is registered.\n");
289 return ret;
290}
291late_initcall(imx_mcc_demo_init);
292
293MODULE_AUTHOR("Freescale Semiconductor, Inc.");
294MODULE_DESCRIPTION("IMX MCC demo driver");
295MODULE_LICENSE("GPL");