|
1 /** |
|
2 Network Driver for Beckhoff CCAT communication controller |
|
3 Copyright (C) 2015 Beckhoff Automation GmbH & Co. KG |
|
4 Author: Patrick Bruenn <p.bruenn@beckhoff.com> |
|
5 |
|
6 This program is free software; you can redistribute it and/or modify |
|
7 it under the terms of the GNU General Public License as published by |
|
8 the Free Software Foundation; either version 2 of the License, or |
|
9 (at your option) any later version. |
|
10 |
|
11 This program is distributed in the hope that it will be useful, |
|
12 but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
14 GNU General Public License for more details. |
|
15 |
|
16 You should have received a copy of the GNU General Public License along |
|
17 with this program; if not, write to the Free Software Foundation, Inc., |
|
18 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
|
19 */ |
|
20 |
|
21 #include "module.h" |
|
22 #include <asm/io.h> |
|
23 #include <linux/fs.h> |
|
24 #include <linux/module.h> |
|
25 #include <linux/uaccess.h> |
|
26 |
|
27 #define CCAT_SRAM_DEVICES_MAX 4 |
|
28 |
|
29 static ssize_t __sram_read(struct cdev_buffer *buffer, char __user * buf, |
|
30 size_t len, loff_t * off) |
|
31 { |
|
32 memcpy_fromio(buffer->data, buffer->ccdev->ioaddr + *off, len); |
|
33 if (copy_to_user(buf, buffer->data, len)) |
|
34 return -EFAULT; |
|
35 |
|
36 *off += len; |
|
37 return len; |
|
38 } |
|
39 |
|
40 static ssize_t ccat_sram_read(struct file *const f, char __user * buf, |
|
41 size_t len, loff_t * off) |
|
42 { |
|
43 struct cdev_buffer *buffer = f->private_data; |
|
44 const size_t iosize = buffer->ccdev->iosize; |
|
45 |
|
46 if (*off >= iosize) { |
|
47 return 0; |
|
48 } |
|
49 |
|
50 len = min(len, (size_t) (iosize - *off)); |
|
51 |
|
52 return __sram_read(buffer, buf, len, off); |
|
53 } |
|
54 |
|
55 static ssize_t ccat_sram_write(struct file *const f, const char __user * buf, |
|
56 size_t len, loff_t * off) |
|
57 { |
|
58 struct cdev_buffer *const buffer = f->private_data; |
|
59 |
|
60 if (*off + len > buffer->ccdev->iosize) { |
|
61 return 0; |
|
62 } |
|
63 |
|
64 if (copy_from_user(buffer->data, buf, len)) { |
|
65 return -EFAULT; |
|
66 } |
|
67 |
|
68 memcpy_toio(buffer->ccdev->ioaddr + *off, buffer->data, len); |
|
69 |
|
70 *off += len; |
|
71 return len; |
|
72 } |
|
73 |
|
74 static struct ccat_cdev dev_table[CCAT_SRAM_DEVICES_MAX]; |
|
75 static struct ccat_class cdev_class = { |
|
76 .instances = {0}, |
|
77 .count = CCAT_SRAM_DEVICES_MAX, |
|
78 .devices = dev_table, |
|
79 .name = "ccat_sram", |
|
80 .fops = { |
|
81 .owner = THIS_MODULE, |
|
82 .open = ccat_cdev_open, |
|
83 .release = ccat_cdev_release, |
|
84 .read = ccat_sram_read, |
|
85 .write = ccat_sram_write, |
|
86 }, |
|
87 }; |
|
88 |
|
89 static int ccat_sram_probe(struct ccat_function *func) |
|
90 { |
|
91 static const u8 NO_SRAM_CONNECTED = 0; |
|
92 const u8 type = func->info.sram_width & 0x3; |
|
93 const size_t iosize = (1 << func->info.sram_size); |
|
94 |
|
95 pr_info("%s: 0x%04x rev: 0x%04x\n", __FUNCTION__, func->info.type, |
|
96 func->info.rev); |
|
97 if (type == NO_SRAM_CONNECTED) { |
|
98 return -ENODEV; |
|
99 } |
|
100 return ccat_cdev_probe(func, &cdev_class, iosize); |
|
101 } |
|
102 |
|
103 const struct ccat_driver sram_driver = { |
|
104 .type = CCATINFO_SRAM, |
|
105 .probe = ccat_sram_probe, |
|
106 .remove = ccat_cdev_remove, |
|
107 .cdev_class = &cdev_class, |
|
108 }; |