p@2636: /**
p@2636: Network Driver for Beckhoff CCAT communication controller
p@2636: Copyright (C) 2015 Beckhoff Automation GmbH & Co. KG
p@2636: Author: Patrick Bruenn
p@2636:
p@2636: This program is free software; you can redistribute it and/or modify
p@2636: it under the terms of the GNU General Public License as published by
p@2636: the Free Software Foundation; either version 2 of the License, or
p@2636: (at your option) any later version.
p@2636:
p@2636: This program is distributed in the hope that it will be useful,
p@2636: but WITHOUT ANY WARRANTY; without even the implied warranty of
p@2636: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
p@2636: GNU General Public License for more details.
p@2636:
p@2636: You should have received a copy of the GNU General Public License along
p@2636: with this program; if not, write to the Free Software Foundation, Inc.,
p@2636: 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
p@2636: */
p@2636:
p@2636: #include "module.h"
p@2636: #include
p@2636: #include
p@2636: #include
p@2636: #include
p@2636:
p@2636: #define CCAT_SRAM_DEVICES_MAX 4
p@2636:
p@2636: static ssize_t __sram_read(struct cdev_buffer *buffer, char __user * buf,
p@2636: size_t len, loff_t * off)
p@2636: {
p@2636: memcpy_fromio(buffer->data, buffer->ccdev->ioaddr + *off, len);
p@2636: if (copy_to_user(buf, buffer->data, len))
p@2636: return -EFAULT;
p@2636:
p@2636: *off += len;
p@2636: return len;
p@2636: }
p@2636:
p@2636: static ssize_t ccat_sram_read(struct file *const f, char __user * buf,
p@2636: size_t len, loff_t * off)
p@2636: {
p@2636: struct cdev_buffer *buffer = f->private_data;
p@2636: const size_t iosize = buffer->ccdev->iosize;
p@2636:
p@2636: if (*off >= iosize) {
p@2636: return 0;
p@2636: }
p@2636:
p@2636: len = min(len, (size_t) (iosize - *off));
p@2636:
p@2636: return __sram_read(buffer, buf, len, off);
p@2636: }
p@2636:
p@2636: static ssize_t ccat_sram_write(struct file *const f, const char __user * buf,
p@2636: size_t len, loff_t * off)
p@2636: {
p@2636: struct cdev_buffer *const buffer = f->private_data;
p@2636:
p@2636: if (*off + len > buffer->ccdev->iosize) {
p@2636: return 0;
p@2636: }
p@2636:
p@2636: if (copy_from_user(buffer->data, buf, len)) {
p@2636: return -EFAULT;
p@2636: }
p@2636:
p@2636: memcpy_toio(buffer->ccdev->ioaddr + *off, buffer->data, len);
p@2636:
p@2636: *off += len;
p@2636: return len;
p@2636: }
p@2636:
p@2636: static struct ccat_cdev dev_table[CCAT_SRAM_DEVICES_MAX];
p@2636: static struct ccat_class cdev_class = {
p@2636: .instances = {0},
p@2636: .count = CCAT_SRAM_DEVICES_MAX,
p@2636: .devices = dev_table,
p@2636: .name = "ccat_sram",
p@2636: .fops = {
p@2636: .owner = THIS_MODULE,
p@2636: .open = ccat_cdev_open,
p@2636: .release = ccat_cdev_release,
p@2636: .read = ccat_sram_read,
p@2636: .write = ccat_sram_write,
p@2636: },
p@2636: };
p@2636:
p@2636: static int ccat_sram_probe(struct ccat_function *func)
p@2636: {
p@2636: static const u8 NO_SRAM_CONNECTED = 0;
p@2636: const u8 type = func->info.sram_width & 0x3;
p@2636: const size_t iosize = (1 << func->info.sram_size);
p@2636:
p@2636: pr_info("%s: 0x%04x rev: 0x%04x\n", __FUNCTION__, func->info.type,
p@2636: func->info.rev);
p@2636: if (type == NO_SRAM_CONNECTED) {
p@2636: return -ENODEV;
p@2636: }
p@2636: return ccat_cdev_probe(func, &cdev_class, iosize);
p@2636: }
p@2636:
p@2636: struct ccat_driver sram_driver = {
p@2636: .type = CCATINFO_SRAM,
p@2636: .probe = ccat_sram_probe,
p@2636: .remove = ccat_cdev_remove,
p@2636: .cdev_class = &cdev_class,
p@2636: };