blob: 427fd1b56df5540f6a871f31c99c92af4f3edacd [file] [log] [blame]
Pekka Paalanen8b7d89d2008-05-12 21:20:56 +02001/*
Pekka Paalanenfab852a2009-03-01 16:09:14 +02002 * Written by Pekka Paalanen, 2008-2009 <pq@iki.fi>
Pekka Paalanen8b7d89d2008-05-12 21:20:56 +02003 */
4#include <linux/module.h>
Pekka Paalanen970e6fa2008-05-12 21:21:03 +02005#include <linux/io.h>
Pekka Paalanen9e57fb32008-09-16 22:00:34 +03006#include <linux/mmiotrace.h>
Pekka Paalanen8b7d89d2008-05-12 21:20:56 +02007
Pekka Paalanen8b7d89d2008-05-12 21:20:56 +02008#define MODULE_NAME "testmmiotrace"
9
10static unsigned long mmio_address;
11module_param(mmio_address, ulong, 0);
Pekka Paalanen5ff93692009-03-01 16:10:08 +020012MODULE_PARM_DESC(mmio_address, " Start address of the mapping of 16 kB "
13 "(or 8 MB if read_far is non-zero).");
14
15static unsigned long read_far = 0x400100;
16module_param(read_far, ulong, 0);
17MODULE_PARM_DESC(read_far, " Offset of a 32-bit read within 8 MB "
18 "(default: 0x400100).");
Pekka Paalanen8b7d89d2008-05-12 21:20:56 +020019
Pekka Paalanenfab852a2009-03-01 16:09:14 +020020static unsigned v16(unsigned i)
21{
22 return i * 12 + 7;
23}
24
25static unsigned v32(unsigned i)
26{
27 return i * 212371 + 13;
28}
29
Pekka Paalanen8b7d89d2008-05-12 21:20:56 +020030static void do_write_test(void __iomem *p)
31{
32 unsigned int i;
Pekka Paalanen5ff93692009-03-01 16:10:08 +020033 pr_info(MODULE_NAME ": write test.\n");
Pekka Paalanen9e57fb32008-09-16 22:00:34 +030034 mmiotrace_printk("Write test.\n");
Pekka Paalanenfab852a2009-03-01 16:09:14 +020035
Pekka Paalanen8b7d89d2008-05-12 21:20:56 +020036 for (i = 0; i < 256; i++)
37 iowrite8(i, p + i);
Pekka Paalanenfab852a2009-03-01 16:09:14 +020038
Pekka Paalanen8b7d89d2008-05-12 21:20:56 +020039 for (i = 1024; i < (5 * 1024); i += 2)
Pekka Paalanenfab852a2009-03-01 16:09:14 +020040 iowrite16(v16(i), p + i);
41
Pekka Paalanen8b7d89d2008-05-12 21:20:56 +020042 for (i = (5 * 1024); i < (16 * 1024); i += 4)
Pekka Paalanenfab852a2009-03-01 16:09:14 +020043 iowrite32(v32(i), p + i);
Pekka Paalanen8b7d89d2008-05-12 21:20:56 +020044}
45
46static void do_read_test(void __iomem *p)
47{
48 unsigned int i;
Pekka Paalanenfab852a2009-03-01 16:09:14 +020049 unsigned errs[3] = { 0 };
Pekka Paalanen5ff93692009-03-01 16:10:08 +020050 pr_info(MODULE_NAME ": read test.\n");
Pekka Paalanen9e57fb32008-09-16 22:00:34 +030051 mmiotrace_printk("Read test.\n");
Pekka Paalanenfab852a2009-03-01 16:09:14 +020052
Pekka Paalanen8b7d89d2008-05-12 21:20:56 +020053 for (i = 0; i < 256; i++)
Pekka Paalanenfab852a2009-03-01 16:09:14 +020054 if (ioread8(p + i) != i)
55 ++errs[0];
56
Pekka Paalanen8b7d89d2008-05-12 21:20:56 +020057 for (i = 1024; i < (5 * 1024); i += 2)
Pekka Paalanenfab852a2009-03-01 16:09:14 +020058 if (ioread16(p + i) != v16(i))
59 ++errs[1];
60
Pekka Paalanen8b7d89d2008-05-12 21:20:56 +020061 for (i = (5 * 1024); i < (16 * 1024); i += 4)
Pekka Paalanenfab852a2009-03-01 16:09:14 +020062 if (ioread32(p + i) != v32(i))
63 ++errs[2];
64
65 mmiotrace_printk("Read errors: 8-bit %d, 16-bit %d, 32-bit %d.\n",
66 errs[0], errs[1], errs[2]);
Pekka Paalanen8b7d89d2008-05-12 21:20:56 +020067}
68
Pekka Paalanen5ff93692009-03-01 16:10:08 +020069static void do_read_far_test(void __iomem *p)
Pekka Paalanen8b7d89d2008-05-12 21:20:56 +020070{
Pekka Paalanen5ff93692009-03-01 16:10:08 +020071 pr_info(MODULE_NAME ": read far test.\n");
72 mmiotrace_printk("Read far test.\n");
73
74 ioread32(p + read_far);
75}
76
77static void do_test(unsigned long size)
78{
79 void __iomem *p = ioremap_nocache(mmio_address, size);
Pekka Paalanen8b7d89d2008-05-12 21:20:56 +020080 if (!p) {
Pekka Paalanen0fd0e3d2008-05-12 21:20:57 +020081 pr_err(MODULE_NAME ": could not ioremap, aborting.\n");
Pekka Paalanen8b7d89d2008-05-12 21:20:56 +020082 return;
83 }
Pekka Paalanen9e57fb32008-09-16 22:00:34 +030084 mmiotrace_printk("ioremap returned %p.\n", p);
Pekka Paalanen8b7d89d2008-05-12 21:20:56 +020085 do_write_test(p);
86 do_read_test(p);
Pekka Paalanen5ff93692009-03-01 16:10:08 +020087 if (read_far && read_far < size - 4)
88 do_read_far_test(p);
Pekka Paalanend61fc442008-05-12 21:20:57 +020089 iounmap(p);
Pekka Paalanen8b7d89d2008-05-12 21:20:56 +020090}
91
92static int __init init(void)
93{
Pekka Paalanen5ff93692009-03-01 16:10:08 +020094 unsigned long size = (read_far) ? (8 << 20) : (16 << 10);
95
Pekka Paalanen8b7d89d2008-05-12 21:20:56 +020096 if (mmio_address == 0) {
Pekka Paalanen0fd0e3d2008-05-12 21:20:57 +020097 pr_err(MODULE_NAME ": you have to use the module argument "
98 "mmio_address.\n");
99 pr_err(MODULE_NAME ": DO NOT LOAD THIS MODULE UNLESS"
Pekka Paalanen8b7d89d2008-05-12 21:20:56 +0200100 " YOU REALLY KNOW WHAT YOU ARE DOING!\n");
101 return -ENXIO;
102 }
103
Pekka Paalanen5ff93692009-03-01 16:10:08 +0200104 pr_warning(MODULE_NAME ": WARNING: mapping %lu kB @ 0x%08lx in PCI "
105 "address space, and writing 16 kB of rubbish in there.\n",
106 size >> 10, mmio_address);
107 do_test(size);
108 pr_info(MODULE_NAME ": All done.\n");
Pekka Paalanen8b7d89d2008-05-12 21:20:56 +0200109 return 0;
110}
111
112static void __exit cleanup(void)
113{
Pekka Paalanen0fd0e3d2008-05-12 21:20:57 +0200114 pr_debug(MODULE_NAME ": unloaded.\n");
Pekka Paalanen8b7d89d2008-05-12 21:20:56 +0200115}
116
117module_init(init);
118module_exit(cleanup);
119MODULE_LICENSE("GPL");