linux/drivers/staging/meilhaus/me0600_dio.c
<<
>>
Prefs
   1/**
   2 * @file me0600_dio.c
   3 *
   4 * @brief ME-630 digital input/output 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 "me0600_dio_reg.h"
  48#include "me0600_dio.h"
  49
  50/*
  51 * Defines
  52 */
  53
  54/*
  55 * Functions
  56 */
  57
  58static int me0600_dio_io_reset_subdevice(struct me_subdevice *subdevice,
  59                                         struct file *filep, int flags)
  60{
  61        me0600_dio_subdevice_t *instance;
  62        uint8_t mode;
  63
  64        PDEBUG("executed.\n");
  65
  66        instance = (me0600_dio_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 = inb(instance->ctrl_reg);
  78        mode &= ~(0x3 << (instance->dio_idx * 2));
  79        outb(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        outb(0x00, 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, 0x00);
  87        spin_unlock(&instance->subdevice_lock);
  88
  89        ME_SUBDEVICE_EXIT;
  90
  91        return ME_ERRNO_SUCCESS;
  92}
  93
  94static int me0600_dio_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        me0600_dio_subdevice_t *instance;
 103        int err = ME_ERRNO_SUCCESS;
 104        uint8_t mode;
 105        int size =
 106            flags & (ME_IO_SINGLE_CONFIG_DIO_BIT | ME_IO_SINGLE_CONFIG_DIO_BYTE
 107                     | ME_IO_SINGLE_CONFIG_DIO_WORD |
 108                     ME_IO_SINGLE_CONFIG_DIO_DWORD);
 109
 110        PDEBUG("executed.\n");
 111
 112        instance = (me0600_dio_subdevice_t *) subdevice;
 113
 114        ME_SUBDEVICE_ENTER;
 115
 116        spin_lock(&instance->subdevice_lock);
 117        spin_lock(instance->ctrl_reg_lock);
 118        mode = inb(instance->ctrl_reg);
 119        switch (size) {
 120        case ME_IO_SINGLE_CONFIG_NO_FLAGS:
 121        case ME_IO_SINGLE_CONFIG_DIO_BYTE:
 122                if (channel == 0) {
 123                        if (single_config == ME_SINGLE_CONFIG_DIO_INPUT) {
 124                                mode &=
 125                                    ~((ME0600_DIO_CONFIG_BIT_OUT_0) <<
 126                                      (instance->dio_idx * 2));
 127                        } else if (single_config == ME_SINGLE_CONFIG_DIO_OUTPUT) {
 128                                mode &=
 129                                    ~((ME0600_DIO_CONFIG_BIT_OUT_0) <<
 130                                      (instance->dio_idx * 2));
 131                                mode |=
 132                                    ME0600_DIO_CONFIG_BIT_OUT_0 << (instance->
 133                                                                    dio_idx *
 134                                                                    2);
 135                        } else {
 136                                PERROR
 137                                    ("Invalid port configuration specified.\n");
 138                                err = ME_ERRNO_INVALID_SINGLE_CONFIG;
 139                        }
 140                } else {
 141                        PERROR("Invalid channel number.\n");
 142                        err = ME_ERRNO_INVALID_CHANNEL;
 143                }
 144                break;
 145
 146        default:
 147                PERROR("Invalid flags.\n");
 148                err = ME_ERRNO_INVALID_FLAGS;
 149        }
 150
 151        if (!err) {
 152                outb(mode, instance->ctrl_reg);
 153                PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n",
 154                           instance->reg_base,
 155                           instance->ctrl_reg - instance->reg_base, mode);
 156        }
 157        spin_unlock(instance->ctrl_reg_lock);
 158        spin_unlock(&instance->subdevice_lock);
 159
 160        ME_SUBDEVICE_EXIT;
 161
 162        return err;
 163}
 164
 165static int me0600_dio_io_single_read(me_subdevice_t * subdevice,
 166                                     struct file *filep,
 167                                     int channel,
 168                                     int *value, int time_out, int flags)
 169{
 170        me0600_dio_subdevice_t *instance;
 171        int err = ME_ERRNO_SUCCESS;
 172        uint8_t mode;
 173
 174        PDEBUG("executed.\n");
 175
 176        instance = (me0600_dio_subdevice_t *) subdevice;
 177
 178        ME_SUBDEVICE_ENTER;
 179
 180        spin_lock(&instance->subdevice_lock);
 181        spin_lock(instance->ctrl_reg_lock);
 182        switch (flags) {
 183        case ME_IO_SINGLE_TYPE_DIO_BIT:
 184                if ((channel >= 0) && (channel < 8)) {
 185                        mode =
 186                            inb(instance->
 187                                ctrl_reg) & ((ME0600_DIO_CONFIG_BIT_OUT_0) <<
 188                                             (instance->dio_idx * 2));
 189
 190                        if ((mode ==
 191                             (ME0600_DIO_CONFIG_BIT_OUT_0 <<
 192                              (instance->dio_idx * 2))) || !mode) {
 193                                *value =
 194                                    inb(instance->
 195                                        port_reg) & (0x0001 << channel);
 196                        } else {
 197                                PERROR("Port not in output or input mode.\n");
 198                                err = ME_ERRNO_PREVIOUS_CONFIG;
 199                        }
 200                } else {
 201                        PERROR("Invalid bit number specified.\n");
 202                        err = ME_ERRNO_INVALID_CHANNEL;
 203                }
 204
 205                break;
 206
 207        case ME_IO_SINGLE_NO_FLAGS:
 208        case ME_IO_SINGLE_TYPE_DIO_BYTE:
 209                if (channel == 0) {
 210                        mode =
 211                            inb(instance->
 212                                ctrl_reg) & ((ME0600_DIO_CONFIG_BIT_OUT_0) <<
 213                                             (instance->dio_idx * 2));
 214
 215                        if ((mode ==
 216                             (ME0600_DIO_CONFIG_BIT_OUT_0 <<
 217                              (instance->dio_idx * 2))) || !mode) {
 218                                *value = inb(instance->port_reg) & 0x00FF;
 219                        } else {
 220                                PERROR("Port not in output or input mode.\n");
 221                                err = ME_ERRNO_PREVIOUS_CONFIG;
 222                        }
 223                } else {
 224                        PERROR("Invalid byte number specified.\n");
 225                        err = ME_ERRNO_INVALID_CHANNEL;
 226                }
 227
 228                break;
 229
 230        default:
 231                PERROR("Invalid flags specified.\n");
 232
 233                err = ME_ERRNO_INVALID_FLAGS;
 234
 235                break;
 236        }
 237        spin_unlock(instance->ctrl_reg_lock);
 238        spin_unlock(&instance->subdevice_lock);
 239
 240        ME_SUBDEVICE_EXIT;
 241
 242        return err;
 243}
 244
 245static int me0600_dio_io_single_write(me_subdevice_t * subdevice,
 246                                      struct file *filep,
 247                                      int channel,
 248                                      int value, int time_out, int flags)
 249{
 250        me0600_dio_subdevice_t *instance;
 251        int err = ME_ERRNO_SUCCESS;
 252        uint8_t mode;
 253        uint8_t byte;
 254
 255        PDEBUG("executed.\n");
 256
 257        instance = (me0600_dio_subdevice_t *) subdevice;
 258
 259        ME_SUBDEVICE_ENTER;
 260
 261        spin_lock(&instance->subdevice_lock);
 262        spin_lock(instance->ctrl_reg_lock);
 263        switch (flags) {
 264
 265        case ME_IO_SINGLE_TYPE_DIO_BIT:
 266                if ((channel >= 0) && (channel < 8)) {
 267                        mode =
 268                            inb(instance->
 269                                ctrl_reg) & ((ME0600_DIO_CONFIG_BIT_OUT_0) <<
 270                                             (instance->dio_idx * 2));
 271
 272                        if (mode ==
 273                            (ME0600_DIO_CONFIG_BIT_OUT_0 <<
 274                             (instance->dio_idx * 2))) {
 275                                byte = inb(instance->port_reg);
 276
 277                                if (value)
 278                                        byte |= 0x1 << channel;
 279                                else
 280                                        byte &= ~(0x1 << channel);
 281
 282                                outb(byte, instance->port_reg);
 283                        } else {
 284                                PERROR("Port not in output or input mode.\n");
 285                                err = ME_ERRNO_PREVIOUS_CONFIG;
 286                        }
 287                } else {
 288                        PERROR("Invalid bit number specified.\n");
 289                        err = ME_ERRNO_INVALID_CHANNEL;
 290                }
 291
 292                break;
 293
 294        case ME_IO_SINGLE_NO_FLAGS:
 295        case ME_IO_SINGLE_TYPE_DIO_BYTE:
 296                if (channel == 0) {
 297                        mode =
 298                            inb(instance->
 299                                ctrl_reg) & ((ME0600_DIO_CONFIG_BIT_OUT_0) <<
 300                                             (instance->dio_idx * 2));
 301
 302                        if (mode ==
 303                            (ME0600_DIO_CONFIG_BIT_OUT_0 <<
 304                             (instance->dio_idx * 2))) {
 305                                outb(value, instance->port_reg);
 306                        } else {
 307                                PERROR("Port not in output or input mode.\n");
 308                                err = ME_ERRNO_PREVIOUS_CONFIG;
 309                        }
 310                } else {
 311                        PERROR("Invalid byte number specified.\n");
 312                        err = ME_ERRNO_INVALID_CHANNEL;
 313                }
 314
 315                break;
 316
 317        default:
 318                PERROR("Invalid flags specified.\n");
 319
 320                err = ME_ERRNO_INVALID_FLAGS;
 321
 322                break;
 323        }
 324        spin_unlock(instance->ctrl_reg_lock);
 325        spin_unlock(&instance->subdevice_lock);
 326
 327        ME_SUBDEVICE_EXIT;
 328
 329        return err;
 330}
 331
 332static int me0600_dio_query_number_channels(me_subdevice_t * subdevice,
 333                                            int *number)
 334{
 335        PDEBUG("executed.\n");
 336        *number = 8;
 337        return ME_ERRNO_SUCCESS;
 338}
 339
 340static int me0600_dio_query_subdevice_type(me_subdevice_t * subdevice,
 341                                           int *type, int *subtype)
 342{
 343        PDEBUG("executed.\n");
 344        *type = ME_TYPE_DIO;
 345        *subtype = ME_SUBTYPE_SINGLE;
 346        return ME_ERRNO_SUCCESS;
 347}
 348
 349static int me0600_dio_query_subdevice_caps(me_subdevice_t * subdevice,
 350                                           int *caps)
 351{
 352        PDEBUG("executed.\n");
 353        *caps = ME_CAPS_DIO_DIR_BYTE;
 354        return ME_ERRNO_SUCCESS;
 355}
 356
 357me0600_dio_subdevice_t *me0600_dio_constructor(uint32_t reg_base,
 358                                               unsigned int dio_idx,
 359                                               spinlock_t * ctrl_reg_lock)
 360{
 361        me0600_dio_subdevice_t *subdevice;
 362        int err;
 363
 364        PDEBUG("executed.\n");
 365
 366        /* Allocate memory for subdevice instance */
 367        subdevice = kmalloc(sizeof(me0600_dio_subdevice_t), GFP_KERNEL);
 368
 369        if (!subdevice) {
 370                PERROR("Cannot get memory for subdevice instance.\n");
 371                return NULL;
 372        }
 373
 374        memset(subdevice, 0, sizeof(me0600_dio_subdevice_t));
 375
 376        /* Initialize subdevice base class */
 377        err = me_subdevice_init(&subdevice->base);
 378
 379        if (err) {
 380                PERROR("Cannot initialize subdevice base class instance.\n");
 381                kfree(subdevice);
 382                return NULL;
 383        }
 384        // Initialize spin locks.
 385        spin_lock_init(&subdevice->subdevice_lock);
 386
 387        subdevice->ctrl_reg_lock = ctrl_reg_lock;
 388
 389        /* Save digital i/o index */
 390        subdevice->dio_idx = dio_idx;
 391
 392        /* Save the subdevice index */
 393        subdevice->ctrl_reg = reg_base + ME0600_DIO_CONFIG_REG;
 394        subdevice->port_reg = reg_base + ME0600_DIO_PORT_REG + dio_idx;
 395#ifdef MEDEBUG_DEBUG_REG
 396        subdevice->reg_base = reg_base;
 397#endif
 398
 399        /* Overload base class methods. */
 400        subdevice->base.me_subdevice_io_reset_subdevice =
 401            me0600_dio_io_reset_subdevice;
 402        subdevice->base.me_subdevice_io_single_config =
 403            me0600_dio_io_single_config;
 404        subdevice->base.me_subdevice_io_single_read = me0600_dio_io_single_read;
 405        subdevice->base.me_subdevice_io_single_write =
 406            me0600_dio_io_single_write;
 407        subdevice->base.me_subdevice_query_number_channels =
 408            me0600_dio_query_number_channels;
 409        subdevice->base.me_subdevice_query_subdevice_type =
 410            me0600_dio_query_subdevice_type;
 411        subdevice->base.me_subdevice_query_subdevice_caps =
 412            me0600_dio_query_subdevice_caps;
 413
 414        return subdevice;
 415}
 416
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.