linux/drivers/staging/meilhaus/me4600_di.c
<<
>>
Prefs
   1/**
   2 * @file me4600_di.c
   3 *
   4 * @brief ME-4000 digital input subdevice instance.
   5 * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
   6 * @author Guenter Gebhardt
   7 * @author Krzysztof Gantzke    (k.gantzke@meilhaus.de)
   8 */
   9
  10/*
  11 * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
  12 *
  13 * This file is free software; you can redistribute it and/or modify
  14 * it under the terms of the GNU General Public License as published by
  15 * the Free Software Foundation; either version 2 of the License, or
  16 * (at your option) any later version.
  17 *
  18 * This program is distributed in the hope that it will be useful,
  19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  21 * GNU General Public License for more details.
  22 *
  23 * You should have received a copy of the GNU General Public License
  24 * along with this program; if not, write to the Free Software
  25 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  26 */
  27
  28#ifndef __KERNEL__
  29#  define __KERNEL__
  30#endif
  31
  32/*
  33 * Includes
  34 */
  35#include <linux/module.h>
  36
  37#include <linux/slab.h>
  38#include <linux/spinlock.h>
  39#include <asm/io.h>
  40#include <linux/types.h>
  41
  42#include "medefines.h"
  43#include "meinternal.h"
  44#include "meerror.h"
  45
  46#include "medebug.h"
  47#include "me4600_dio_reg.h"
  48#include "me4600_di.h"
  49
  50/*
  51 * Defines
  52 */
  53
  54/*
  55 * Functions
  56 */
  57
  58static int me4600_di_io_reset_subdevice(struct me_subdevice *subdevice,
  59                                        struct file *filep, int flags)
  60{
  61        me4600_di_subdevice_t *instance;
  62        uint32_t mode;
  63
  64        PDEBUG("executed.\n");
  65
  66        instance = (me4600_di_subdevice_t *) subdevice;
  67
  68        if (flags) {
  69                PERROR("Invalid flag specified.\n");
  70                return ME_ERRNO_INVALID_FLAGS;
  71        }
  72
  73        ME_SUBDEVICE_ENTER;
  74
  75        spin_lock(&instance->subdevice_lock);
  76        spin_lock(instance->ctrl_reg_lock);
  77        mode = inl(instance->ctrl_reg);
  78        mode &= ~(ME4600_DIO_CTRL_BIT_MODE_2 | ME4600_DIO_CTRL_BIT_MODE_3);     //0xFFF3
  79        outl(mode, instance->ctrl_reg);
  80        PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
  81                   instance->ctrl_reg - instance->reg_base, mode);
  82        spin_unlock(instance->ctrl_reg_lock);
  83
  84        outl(0, instance->port_reg);
  85        PDEBUG_REG("port_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
  86                   instance->port_reg - instance->reg_base, 0);
  87        spin_unlock(&instance->subdevice_lock);
  88
  89        ME_SUBDEVICE_EXIT;
  90
  91        return ME_ERRNO_SUCCESS;
  92}
  93
  94static int me4600_di_io_single_config(me_subdevice_t * subdevice,
  95                                      struct file *filep,
  96                                      int channel,
  97                                      int single_config,
  98                                      int ref,
  99                                      int trig_chan,
 100                                      int trig_type, int trig_edge, int flags)
 101{
 102        int err = ME_ERRNO_SUCCESS;
 103        me4600_di_subdevice_t *instance;
 104
 105        PDEBUG("executed.\n");
 106
 107        instance = (me4600_di_subdevice_t *) subdevice;
 108
 109        ME_SUBDEVICE_ENTER;
 110
 111        switch (flags) {
 112        case ME_IO_SINGLE_CONFIG_NO_FLAGS:
 113        case ME_IO_SINGLE_CONFIG_DIO_BYTE:
 114                if (channel == 0) {
 115                        if (single_config == ME_SINGLE_CONFIG_DIO_INPUT) {
 116                        } else {
 117                                PERROR("Invalid port direction specified.\n");
 118                                err = ME_ERRNO_INVALID_SINGLE_CONFIG;
 119                        }
 120                } else {
 121                        PERROR("Invalid channel number.\n");
 122                        err = ME_ERRNO_INVALID_CHANNEL;
 123                }
 124                break;
 125
 126        default:
 127                PERROR("Invalid flags specified.\n");
 128                err = ME_ERRNO_INVALID_FLAGS;
 129        }
 130
 131        ME_SUBDEVICE_EXIT;
 132
 133        return err;
 134}
 135
 136static int me4600_di_io_single_read(me_subdevice_t * subdevice,
 137                                    struct file *filep,
 138                                    int channel,
 139                                    int *value, int time_out, int flags)
 140{
 141        me4600_di_subdevice_t *instance;
 142        int err = ME_ERRNO_SUCCESS;
 143
 144        PDEBUG("executed.\n");
 145
 146        instance = (me4600_di_subdevice_t *) subdevice;
 147
 148        ME_SUBDEVICE_ENTER;
 149
 150        switch (flags) {
 151        case ME_IO_SINGLE_TYPE_DIO_BIT:
 152                if ((channel >= 0) && (channel < 8)) {
 153                        *value = inl(instance->port_reg) & (0x1 << channel);
 154                } else {
 155                        PERROR("Invalid bit number specified.\n");
 156                        err = ME_ERRNO_INVALID_CHANNEL;
 157                }
 158                break;
 159
 160        case ME_IO_SINGLE_NO_FLAGS:
 161        case ME_IO_SINGLE_TYPE_DIO_BYTE:
 162                if (channel == 0) {
 163                        *value = inl(instance->port_reg) & 0xFF;
 164                } else {
 165                        PERROR("Invalid byte number specified.\n");
 166                        err = ME_ERRNO_INVALID_CHANNEL;
 167                }
 168                break;
 169
 170        default:
 171                PERROR("Invalid flags specified.\n");
 172                err = ME_ERRNO_INVALID_FLAGS;
 173        }
 174
 175        ME_SUBDEVICE_EXIT;
 176
 177        return err;
 178}
 179
 180static int me4600_di_query_number_channels(me_subdevice_t * subdevice,
 181                                           int *number)
 182{
 183        PDEBUG("executed.\n");
 184        *number = 8;
 185        return ME_ERRNO_SUCCESS;
 186}
 187
 188static int me4600_di_query_subdevice_type(me_subdevice_t * subdevice,
 189                                          int *type, int *subtype)
 190{
 191        PDEBUG("executed.\n");
 192        *type = ME_TYPE_DI;
 193        *subtype = ME_SUBTYPE_SINGLE;
 194        return ME_ERRNO_SUCCESS;
 195}
 196
 197static int me4600_di_query_subdevice_caps(me_subdevice_t * subdevice, int *caps)
 198{
 199        PDEBUG("executed.\n");
 200        *caps = 0;
 201        return ME_ERRNO_SUCCESS;
 202}
 203
 204me4600_di_subdevice_t *me4600_di_constructor(uint32_t reg_base,
 205                                             spinlock_t * ctrl_reg_lock)
 206{
 207        me4600_di_subdevice_t *subdevice;
 208        int err;
 209
 210        PDEBUG("executed.\n");
 211
 212        /* Allocate memory for subdevice instance */
 213        subdevice = kmalloc(sizeof(me4600_di_subdevice_t), GFP_KERNEL);
 214
 215        if (!subdevice) {
 216                PERROR("Cannot get memory for subdevice instance.\n");
 217                return NULL;
 218        }
 219
 220        memset(subdevice, 0, sizeof(me4600_di_subdevice_t));
 221
 222        /* Initialize subdevice base class */
 223        err = me_subdevice_init(&subdevice->base);
 224
 225        if (err) {
 226                PERROR("Cannot initialize subdevice base class instance.\n");
 227                kfree(subdevice);
 228                return NULL;
 229        }
 230        // Initialize spin locks.
 231        spin_lock_init(&subdevice->subdevice_lock);
 232
 233        subdevice->ctrl_reg_lock = ctrl_reg_lock;
 234
 235        /* Save the subdevice index */
 236        subdevice->port_reg = reg_base + ME4600_DIO_PORT_1_REG;
 237        subdevice->ctrl_reg = reg_base + ME4600_DIO_CTRL_REG;
 238#ifdef MEDEBUG_DEBUG_REG
 239        subdevice->reg_base = reg_base;
 240#endif
 241
 242        /* Overload base class methods. */
 243        subdevice->base.me_subdevice_io_reset_subdevice =
 244            me4600_di_io_reset_subdevice;
 245        subdevice->base.me_subdevice_io_single_config =
 246            me4600_di_io_single_config;
 247        subdevice->base.me_subdevice_io_single_read = me4600_di_io_single_read;
 248        subdevice->base.me_subdevice_query_number_channels =
 249            me4600_di_query_number_channels;
 250        subdevice->base.me_subdevice_query_subdevice_type =
 251            me4600_di_query_subdevice_type;
 252        subdevice->base.me_subdevice_query_subdevice_caps =
 253            me4600_di_query_subdevice_caps;
 254
 255        return subdevice;
 256}
 257
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.