]> rtime.felk.cvut.cz Git - zynq/linux.git/blob - drivers/staging/xroeframer/sysfs_xroe.c
staging: xroeframer: add support for multi-port Ethernet
[zynq/linux.git] / drivers / staging / xroeframer / sysfs_xroe.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) 2018 Xilinx, Inc.
4  *
5  * Vasileios Bimpikas <vasileios.bimpikas@xilinx.com>
6  */
7 #include <linux/init.h>
8 #include <linux/kobject.h>
9 #include <linux/module.h>
10 #include <linux/stat.h>
11 #include <linux/string.h>
12 #include <linux/sysfs.h>
13 #include "xroe_framer.h"
14
15 enum { XROE_SIZE_MAX = 15 };
16 static int xroe_size;
17 static char xroe_tmp[XROE_SIZE_MAX];
18
19 /**
20  * version_show - Returns the block's revision number
21  * @kobj:       The kernel object of the entry
22  * @attr:       The attributes of the kernel object
23  * @buff:       The buffer containing the revision string
24  *
25  * Returns the block's major, minor & version revision numbers
26  * in a %d.%d.%d format
27  *
28  * Return: XROE_SIZE_MAX on success
29  */
30 static ssize_t version_show(struct kobject *kobj, struct kobj_attribute *attr,
31                             char *buff)
32 {
33         u32 major_rev;
34         u32 minor_rev;
35         u32 version_rev;
36
37         major_rev = utils_sysfs_show_wrapper(CFG_MAJOR_REVISION_ADDR,
38                                              CFG_MAJOR_REVISION_OFFSET,
39                                              CFG_MAJOR_REVISION_MASK, kobj);
40         minor_rev = utils_sysfs_show_wrapper(CFG_MINOR_REVISION_ADDR,
41                                              CFG_MINOR_REVISION_OFFSET,
42                                              CFG_MINOR_REVISION_MASK, kobj);
43         version_rev = utils_sysfs_show_wrapper(CFG_VERSION_REVISION_ADDR,
44                                                CFG_VERSION_REVISION_OFFSET,
45                                                CFG_VERSION_REVISION_MASK, kobj);
46         sprintf(buff, "%d.%d.%d\n", major_rev, minor_rev, version_rev);
47         return XROE_SIZE_MAX;
48 }
49
50 /**
51  * version_store - Writes to the framer version sysfs entry (not permitted)
52  * @kobj:       The kernel object of the entry
53  * @attr:       The attributes of the kernel object
54  * @buff:       The buffer containing the revision string
55  * @count:      The number of characters typed by the user
56  *
57  * Writes to the framer version sysfs entry (not permitted)
58  *
59  * Return: 0
60  */
61 static ssize_t version_store(struct  kobject *kobj, struct kobj_attribute *attr,
62                              const char *buff, size_t count)
63 {
64         return 0;
65 }
66
67 /**
68  * enable_show - Returns the framer's enable status
69  * @kobj:       The kernel object of the entry
70  * @attr:       The attributes of the kernel object
71  * @buff:       The buffer containing the enable status
72  *
73  * Reads and writes the framer's enable status to the sysfs entry
74  *
75  * Return: XROE_SIZE_MAX on success
76  */
77 static ssize_t enable_show(struct kobject *kobj, struct kobj_attribute *attr,
78                            char *buff)
79 {
80         u32 enable;
81
82         enable = utils_sysfs_show_wrapper(CFG_MASTER_INT_ENABLE_ADDR,
83                                           CFG_MASTER_INT_ENABLE_OFFSET,
84                                           CFG_MASTER_INT_ENABLE_MASK, kobj);
85         if (enable)
86                 sprintf(buff, "true\n");
87         else
88                 sprintf(buff, "false\n");
89         return XROE_SIZE_MAX;
90 }
91
92 /**
93  * version_store - Writes to the framer's enable status register
94  * @kobj:       The kernel object of the entry
95  * @attr:       The attributes of the kernel object
96  * @buff:       The buffer containing the enable status
97  * @count:      The number of characters typed by the user
98  *
99  * Reads the user input and accordingly writes the framer's enable status
100  * to the sysfs entry
101  *
102  * Return: XROE_SIZE_MAX or the value of "count", if that's lesser, on success
103  */
104 static ssize_t enable_store(struct kobject *kobj, struct kobj_attribute *attr,
105                             const char *buff, size_t count)
106 {
107         u32 enable = 0;
108
109         xroe_size = min_t(size_t, count, (size_t)XROE_SIZE_MAX);
110         strncpy(xroe_tmp, buff, xroe_size);
111         if (strncmp(xroe_tmp, "true", xroe_size) == 0)
112                 enable = 1;
113         else if (strncmp(xroe_tmp, "false", xroe_size) == 0)
114                 enable = 0;
115         utils_sysfs_store_wrapper(CFG_MASTER_INT_ENABLE_ADDR,
116                                   CFG_MASTER_INT_ENABLE_OFFSET,
117                                   CFG_MASTER_INT_ENABLE_MASK, enable, kobj);
118         return xroe_size;
119 }
120
121 /**
122  * framer_restart_show - Returns the framer's restart status
123  * @kobj:       The kernel object of the entry
124  * @attr:       The attributes of the kernel object
125  * @buff:       The buffer containing the restart status
126  *
127  * Reads and writes the framer's restart status to the sysfs entry
128  *
129  * Return: XROE_SIZE_MAX on success
130  */
131 static ssize_t framer_restart_show(struct kobject *kobj,
132                                    struct kobj_attribute *attr, char *buff)
133 {
134         u32 restart;
135
136         restart = utils_sysfs_show_wrapper(FRAM_DISABLE_ADDR,
137                                            FRAM_DISABLE_OFFSET,
138                                            FRAM_DISABLE_MASK, kobj);
139         if (restart)
140                 sprintf(buff, "true\n");
141
142         else
143                 sprintf(buff, "false\n");
144
145         return XROE_SIZE_MAX;
146 }
147
148 /**
149  * framer_restart_store - Writes to the framer's restart status register
150  * @kobj:       The kernel object of the entry
151  * @attr:       The attributes of the kernel object
152  * @buff:       The buffer containing the restart status
153  * @count:      The number of characters typed by the user
154  *
155  * Reads the user input and accordingly writes the framer's restart status
156  * to the sysfs entry
157  *
158  * Return: XROE_SIZE_MAX or the value of "count", if that's lesser, on success
159  */
160 static ssize_t framer_restart_store(struct  kobject *kobj,
161                                     struct kobj_attribute *attr,
162                                     const char *buff, size_t count)
163 {
164         u32 restart = 0;
165
166         xroe_size = min_t(size_t, count, (size_t)XROE_SIZE_MAX);
167         strncpy(xroe_tmp, buff, xroe_size);
168         if (strncmp(xroe_tmp, "true", xroe_size) == 0)
169                 restart = 0x01;
170         else if (strncmp(xroe_tmp, "false", xroe_size) == 0)
171                 restart = 0x00;
172         utils_sysfs_store_wrapper(FRAM_DISABLE_ADDR, FRAM_DISABLE_OFFSET,
173                                   FRAM_DISABLE_MASK, restart, kobj);
174         return xroe_size;
175 }
176
177 /**
178  * deframer_restart_show - Returns the deframer's restart status
179  * @kobj:       The kernel object of the entry
180  * @attr:       The attributes of the kernel object
181  * @buff:       The buffer containing the restart status
182  *
183  * Reads and writes the deframer's restart status to the sysfs entry
184  *
185  * Return: XROE_SIZE_MAX on success
186  */
187 static ssize_t deframer_restart_show(struct kobject *kobj,
188                                      struct kobj_attribute *attr, char *buff)
189 {
190         u32 offset = DEFM_RESTART_OFFSET;
191         u32 mask = DEFM_RESTART_MASK;
192         u32 buffer = 0;
193         u32 restart = 0;
194         void __iomem *working_address = ((u8 *)lp->base_addr
195         + DEFM_RESTART_ADDR);
196
197         buffer = ioread32(working_address);
198         restart = (buffer & mask) >> offset;
199
200         if (restart)
201                 sprintf(buff, "true\n");
202
203         else
204                 sprintf(buff, "false\n");
205
206         return XROE_SIZE_MAX;
207 }
208
209 /**
210  * deframer_restart_store - Writes to the deframer's restart status register
211  * @kobj:       The kernel object of the entry
212  * @attr:       The attributes of the kernel object
213  * @buff:       The buffer containing the restart status
214  * @count:      The number of characters typed by the user
215  *
216  * Reads the user input and accordingly writes the deframer's restart status
217  * to the sysfs entry
218  *
219  * Return: XROE_SIZE_MAX or the value of "count", if that's lesser, on success
220  */
221 static ssize_t deframer_restart_store(struct kobject *kobj,
222                                       struct kobj_attribute *attr,
223                                       const char *buff, size_t count)
224 {
225         u32 offset = DEFM_RESTART_OFFSET;
226         u32 mask = DEFM_RESTART_MASK;
227         void __iomem *working_address = ((u8 *)lp->base_addr
228         + DEFM_RESTART_ADDR);
229         u32 restart = 0;
230
231         xroe_size = min_t(size_t, count, (size_t)XROE_SIZE_MAX);
232         strncpy(xroe_tmp, buff, xroe_size);
233         if (strncmp(xroe_tmp, "true", xroe_size) == 0) {
234                 restart = 0x01;
235                 utils_write32withmask(working_address, restart,
236                                       mask, offset);
237         } else if (strncmp(xroe_tmp, "false", xroe_size) == 0) {
238                 restart = 0x00;
239                 utils_write32withmask(working_address, restart,
240                                       mask, offset);
241         }
242
243         return xroe_size;
244 }
245
246 /**
247  * xxv_reset_show - Returns the XXV's reset status
248  * @kobj:       The kernel object of the entry
249  * @attr:       The attributes of the kernel object
250  * @buff:       The buffer containing the reset status
251  *
252  * Reads and writes the XXV's reset status to the sysfs entry
253  *
254  * Return: XROE_SIZE_MAX on success
255  */
256 static ssize_t xxv_reset_show(struct kobject *kobj, struct kobj_attribute *attr,
257                               char *buff)
258 {
259         u32 offset = CFG_USER_RW_OUT_OFFSET;
260         u32 mask = CFG_USER_RW_OUT_MASK;
261         u32 buffer = 0;
262         u32 restart = 0;
263         void __iomem *working_address = ((u8 *)lp->base_addr +
264         CFG_USER_RW_OUT_ADDR);
265
266         buffer = ioread32(working_address);
267         restart = (buffer & mask) >> offset;
268         if (restart)
269                 sprintf(buff, "true\n");
270         else
271                 sprintf(buff, "false\n");
272         return XROE_SIZE_MAX;
273 }
274
275 /**
276  * xxv_reset_store - Writes to the XXV's reset register
277  * @kobj:       The kernel object of the entry
278  * @attr:       The attributes of the kernel object
279  * @buff:       The buffer containing the reset status
280  * @count:      The number of characters typed by the user
281  *
282  * Reads the user input and accordingly writes the XXV's reset status
283  * to the sysfs entry
284  *
285  * Return: XROE_SIZE_MAX or the value of "count", if that's lesser, on success
286  */
287 static ssize_t xxv_reset_store(struct  kobject *kobj,
288                                struct kobj_attribute *attr,
289                                const char *buff, size_t count)
290 {
291         u32 offset = CFG_USER_RW_OUT_OFFSET;
292         u32 mask = CFG_USER_RW_OUT_MASK;
293         void __iomem *working_address = ((u8 *)lp->base_addr +
294         CFG_USER_RW_OUT_ADDR);
295         u32 restart = 0;
296
297         xroe_size = min_t(size_t, count, (size_t)XROE_SIZE_MAX);
298         strncpy(xroe_tmp, buff, xroe_size);
299
300         if (strncmp(xroe_tmp, "true", xroe_size) == 0) {
301                 restart = 0x01;
302                 utils_write32withmask(working_address, restart,
303                                       mask, offset);
304         } else if (strncmp(xroe_tmp, "false", xroe_size) == 0) {
305                 restart = 0x00;
306                 utils_write32withmask(working_address, restart,
307                                       mask, offset);
308         }
309         return xroe_size;
310 }
311
312 /**
313  * framing_show - Returns the current framing
314  * @kobj:       The kernel object of the entry
315  * @attr:       The attributes of the kernel object
316  * @buff:       The buffer containing the reset status
317  *
318  * Reads and writes the current framing type to the sysfs entry
319  *
320  * Return: XROE_SIZE_MAX on success
321  */
322 static ssize_t framing_show(struct kobject *kobj, struct kobj_attribute *attr,
323                             char *buff)
324 {
325         u32 offset = (DEFM_DATA_PKT_MESSAGE_TYPE_ADDR +
326         DEFM_DATA_PKT_MESSAGE_TYPE_OFFSET);
327         u8 buffer = 0;
328         u8 framing = 0xff;
329         void __iomem *working_address = ((u8 *)lp->base_addr + offset);
330
331         buffer = ioread8(working_address);
332         framing = buffer;
333         if (framing == 0)
334                 sprintf(buff, "eCPRI\n");
335         else if (framing == 1)
336                 sprintf(buff, "1914.3\n");
337         return XROE_SIZE_MAX;
338 }
339
340 /**
341  * framing_store - Writes to the current framing register
342  * @kobj:       The kernel object of the entry
343  * @attr:       The attributes of the kernel object
344  * @buff:       The buffer containing the reset status
345  * @count:      The number of characters typed by the user
346  *
347  * Reads the user input and accordingly writes the current framing
348  * to the sysfs entry
349  *
350  * Return: XROE_SIZE_MAX or the value of "count", if that's lesser, on success
351  */
352 static ssize_t framing_store(struct kobject *kobj, struct kobj_attribute *attr,
353                              const char *buff, size_t count)
354 {
355         u32 offset = (DEFM_DATA_PKT_MESSAGE_TYPE_ADDR +
356         DEFM_DATA_PKT_MESSAGE_TYPE_OFFSET);
357         void __iomem *working_address = ((u8 *)lp->base_addr + offset);
358
359         xroe_size = min_t(size_t, count, (size_t)XROE_SIZE_MAX);
360         strncpy(xroe_tmp, buff, xroe_size);
361         if (strncmp(xroe_tmp, "eCPRI", xroe_size) == 0)
362                 iowrite8(0, working_address);
363         else if (strncmp(xroe_tmp, "1914.3", xroe_size) == 0)
364                 iowrite8(1, working_address);
365         return xroe_size;
366 }
367
368 /* TODO Use DEVICE_ATTR/_RW/_RO macros */
369
370 static struct kobj_attribute version_attribute =
371         __ATTR(version, 0444, version_show, version_store);
372
373 static struct kobj_attribute enable_attribute =
374         __ATTR(enable, 0660, enable_show, enable_store);
375
376 static struct kobj_attribute framer_restart =
377         __ATTR(framer_restart, 0660, framer_restart_show, framer_restart_store);
378
379 static struct kobj_attribute deframer_restart =
380         __ATTR(deframer_restart, 0660, deframer_restart_show,
381                deframer_restart_store);
382
383 static struct kobj_attribute xxv_reset =
384         __ATTR(xxv_reset, 0660, xxv_reset_show, xxv_reset_store);
385
386 static struct kobj_attribute framing_attribute =
387         __ATTR(framing, 0660, framing_show, framing_store);
388
389 static struct attribute *attrs[] = {
390         &version_attribute.attr,
391         &enable_attribute.attr,
392         &framer_restart.attr,
393         &deframer_restart.attr,
394         &xxv_reset.attr,
395         &framing_attribute.attr,
396         NULL,
397 };
398
399 static struct attribute_group attr_group = {
400         .attrs = attrs,
401 };
402
403 struct kobject *root_xroe_kobj;
404
405 /**
406  * xroe_sysfs_init - Creates the xroe sysfs directory and entries
407  *
408  * Return: 0 on success, negative value in case of failure to
409  * create the sysfs group
410  *
411  * Creates the xroe sysfs directory and entries, as well as the
412  * subdirectories for IPv4, IPv6 & UDP
413  */
414 int xroe_sysfs_init(void)
415 {
416         int ret;
417
418         root_xroe_kobj = kobject_create_and_add("xroe", kernel_kobj);
419         if (!root_xroe_kobj)
420                 return -ENOMEM;
421         ret = sysfs_create_group(root_xroe_kobj, &attr_group);
422         if (ret)
423                 kobject_put(root_xroe_kobj);
424         ret = xroe_sysfs_ipv4_init();
425         if (ret)
426                 return ret;
427         ret = xroe_sysfs_ipv6_init();
428         if (ret)
429                 return ret;
430         ret = xroe_sysfs_udp_init();
431         return ret;
432 }
433
434 /**
435  * xroe_sysfs_exit - Deletes the xroe sysfs directory and entries
436  *
437  * Deletes the xroe sysfs directory and entries, as well as the
438  * subdirectories for IPv4, IPv6 & UDP
439  *
440  */
441 void xroe_sysfs_exit(void)
442 {
443         int i;
444
445         xroe_sysfs_ipv4_exit();
446         xroe_sysfs_ipv6_exit();
447         xroe_sysfs_udp_exit();
448         for (i = 0; i < MAX_NUM_ETH_PORTS; i++)
449                 kobject_put(kobj_eth_ports[i]);
450         kobject_put(kobj_framer);
451         kobject_put(root_xroe_kobj);
452 }
453
454 /**
455  * utils_write32withmask - Writes a masked 32-bit value
456  * @working_address:    The starting address to write
457  * @value:                      The value to be written
458  * @mask:                       The mask to be used
459  * @offset:                     The offset from the provided starting address
460  *
461  * Writes a 32-bit value to the provided address with the input mask
462  *
463  * Return: 0 on success
464  */
465 int utils_write32withmask(void __iomem *working_address, u32 value,
466                           u32 mask, u32 offset)
467 {
468         u32 read_register_value = 0;
469         u32 register_value_to_write = 0;
470         u32 delta = 0, buffer = 0;
471
472         read_register_value = ioread32(working_address);
473         buffer = (value << offset);
474         register_value_to_write = read_register_value & ~mask;
475         delta = buffer & mask;
476         register_value_to_write |= delta;
477         iowrite32(register_value_to_write, working_address);
478         return 0;
479 }
480
481 /**
482  * utils_sysfs_path_to_eth_port_num - Get the current ethernet port
483  * @kobj:       The kobject of the entry calling the function
484  *
485  * Extracts the number of the current ethernet port instance
486  *
487  * Return: The number of the ethernet port instance (0 - MAX_NUM_ETH_PORTS) on
488  * success, -1 otherwise
489  */
490 static int utils_sysfs_path_to_eth_port_num(struct kobject *kobj)
491 {
492         char *current_path = NULL;
493         int port;
494         int ret;
495
496         current_path = kobject_get_path(kobj, GFP_KERNEL);
497         ret = sscanf(current_path, "/kernel/xroe/framer/eth_port_%d/", &port);
498         /* if sscanf() returns 0, no fields were assigned, therefore no
499          * adjustments will be made for port number
500          */
501         if (ret == 0)
502                 port = 0;
503 //      printk(KERN_ALERT "current_path: %s port: %d\n", current_path, port);
504         kfree(current_path);
505         return port;
506 }
507
508 /**
509  * utils_sysfs_store_wrapper - Wraps the storing function for sysfs entries
510  * @address:    The address of the register to be written
511  * @offset:     The offset from the address of the register
512  * @mask:       The mask to be used on the value to be written
513  * @value:      The value to be written to the register
514  * @kobj:       The kobject of the entry calling the function
515  *
516  * Wraps the core functionality of all "store" functions of sysfs entries.
517  * After calculating the ethernet port number (in N/A cases, it's 0), the value
518  * is written to the designated register
519  *
520  */
521 void utils_sysfs_store_wrapper(u32 address, u32 offset, u32 mask, u32 value,
522                                struct kobject *kobj)
523 {
524         int port;
525         void __iomem *working_address;
526         u32 buffer;
527
528         port = utils_sysfs_path_to_eth_port_num(kobj);
529         working_address = (void __iomem *)(lp->base_addr +
530                           (address + (0x100 * port)));
531         buffer = ioread32(working_address);
532         utils_write32withmask(working_address, value, mask, offset);
533 }
534
535 /**
536  * utils_sysfs_store_wrapper - Wraps the storing function for sysfs entries
537  * @address:    The address of the register to be read
538  * @offset:     The offset from the address of the register
539  * @mask:       The mask to be used on the value to be read
540  * @kobj:       The kobject of the entry calling the function
541  *
542  * Wraps the core functionality of all "show" functions of sysfs entries.
543  * After calculating the ethernet port number (in N/A cases, it's 0), the value
544  * is read from the designated register and returned.
545  *
546  * Return: The value designated by the address, offset and mask
547  */
548 u32 utils_sysfs_show_wrapper(u32 address, u32 offset, u32 mask,
549                              struct kobject *kobj)
550 {
551         int port;
552         void __iomem *working_address;
553         u32 buffer;
554
555         port = utils_sysfs_path_to_eth_port_num(kobj);
556         working_address = (void __iomem *)(lp->base_addr +
557                           (address + (0x100 * port)));
558         buffer = ioread32(working_address);
559         return (buffer & mask) >> offset;
560 }