linux/drivers/staging/meilhaus/me8100_do.c
<<
>>
Prefs
   1/**
   2 * @file me8100_do.c
   3 *
   4 * @brief ME-8100 digital 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 "me8100_reg.h"
  48#include "me8100_do_reg.h"
  49#include "me8100_do.h"
  50
  51/*
  52 * Defines
  53 */
  54
  55/*
  56 * Functions
  57 */
  58
  59static int me8100_do_io_reset_subdevice(struct me_subdevice *subdevice,
  60                                        struct file *filep, int flags)
  61{
  62        me8100_do_subdevice_t *instance;
  63        uint16_t ctrl;
  64
  65        PDEBUG("executed.\n");
  66
  67        instance = (me8100_do_subdevice_t *) subdevice;
  68
  69        if (flags) {
  70                PERROR("Invalid flag specified.\n");
  71                return ME_ERRNO_INVALID_FLAGS;
  72        }
  73
  74        ME_SUBDEVICE_ENTER;
  75
  76        spin_lock(&instance->subdevice_lock);
  77        spin_lock(instance->ctrl_reg_lock);
  78        ctrl = inw(instance->ctrl_reg);
  79        ctrl &= ME8100_DIO_CTRL_BIT_INTB_1 | ME8100_DIO_CTRL_BIT_INTB_0;
  80        outw(ctrl, instance->ctrl_reg);
  81        PDEBUG_REG("ctrl_reg outw(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
  82                   instance->ctrl_reg - instance->reg_base, ctrl);
  83        spin_unlock(instance->ctrl_reg_lock);
  84        outw(0, instance->port_reg);
  85        instance->port_reg_mirror = 0;
  86        PDEBUG_REG("port_reg outw(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
  87                   instance->port_reg - instance->reg_base, 0);
  88        spin_unlock(&instance->subdevice_lock);
  89
  90        ME_SUBDEVICE_EXIT;
  91
  92        return ME_ERRNO_SUCCESS;
  93}
  94
  95static int me8100_do_io_single_config(me_subdevice_t * subdevice,
  96                                      struct file *filep,
  97                                      int channel,
  98                                      int single_config,
  99                                      int ref,
 100                                      int trig_chan,
 101                                      int trig_type, int trig_edge, int flags)
 102{
 103        me8100_do_subdevice_t *instance;
 104        int err = ME_ERRNO_SUCCESS;
 105        int config;
 106
 107        PDEBUG("executed.\n");
 108
 109        instance = (me8100_do_subdevice_t *) subdevice;
 110
 111        ME_SUBDEVICE_ENTER;
 112
 113        spin_lock(&instance->subdevice_lock);
 114        spin_lock(instance->ctrl_reg_lock);
 115        config = inw(instance->ctrl_reg);
 116        switch (flags) {
 117        case ME_IO_SINGLE_CONFIG_NO_FLAGS:
 118        case ME_IO_SINGLE_CONFIG_DIO_WORD:
 119                if (channel == 0) {
 120                        if (single_config ==
 121                            ME_SINGLE_CONFIG_DIO_HIGH_IMPEDANCE) {
 122                                config &= ~(ME8100_DIO_CTRL_BIT_ENABLE_DIO);
 123                        } else if (single_config == ME_SINGLE_CONFIG_DIO_SINK) {
 124                                config |= ME8100_DIO_CTRL_BIT_ENABLE_DIO;
 125                                config &= ~ME8100_DIO_CTRL_BIT_SOURCE;
 126                        } else if (single_config == ME_SINGLE_CONFIG_DIO_SOURCE) {
 127                                config |=
 128                                    ME8100_DIO_CTRL_BIT_ENABLE_DIO |
 129                                    ME8100_DIO_CTRL_BIT_SOURCE;
 130                        } else {
 131                                PERROR
 132                                    ("Invalid port configuration specified.\n");
 133                                err = ME_ERRNO_INVALID_SINGLE_CONFIG;
 134                        }
 135                } else {
 136                        PERROR("Invalid word number specified.\n");
 137                        err = ME_ERRNO_INVALID_CHANNEL;
 138                }
 139                break;
 140
 141        default:
 142                PERROR("Invalid flags specified.\n");
 143                err = ME_ERRNO_INVALID_FLAGS;
 144        }
 145
 146        if (!err) {
 147                outw(config, instance->ctrl_reg);
 148                PDEBUG_REG("ctrl_reg outw(0x%lX+0x%lX)=0x%x\n",
 149                           instance->reg_base,
 150                           instance->ctrl_reg - instance->reg_base, config);
 151        }
 152
 153        spin_unlock(instance->ctrl_reg_lock);
 154        spin_unlock(&instance->subdevice_lock);
 155
 156        ME_SUBDEVICE_EXIT;
 157
 158        return err;
 159}
 160
 161static int me8100_do_io_single_read(me_subdevice_t * subdevice,
 162                                    struct file *filep,
 163                                    int channel,
 164                                    int *value, int time_out, int flags)
 165{
 166        me8100_do_subdevice_t *instance;
 167        int err = ME_ERRNO_SUCCESS;
 168
 169        PDEBUG("executed.\n");
 170
 171        instance = (me8100_do_subdevice_t *) subdevice;
 172
 173        ME_SUBDEVICE_ENTER;
 174
 175        spin_lock(&instance->subdevice_lock);
 176        switch (flags) {
 177        case ME_IO_SINGLE_TYPE_DIO_BIT:
 178                if ((channel >= 0) && (channel < 16)) {
 179                        *value = instance->port_reg_mirror & (0x1 << channel);
 180                } else {
 181                        PERROR("Invalid bit number specified.\n");
 182                        err = ME_ERRNO_INVALID_CHANNEL;
 183                }
 184                break;
 185
 186        case ME_IO_SINGLE_TYPE_DIO_BYTE:
 187                if (channel == 0) {
 188                        *value = instance->port_reg_mirror & 0xFF;
 189                } else if (channel == 1) {
 190                        *value = (instance->port_reg_mirror >> 8) & 0xFF;
 191                } else {
 192                        PERROR("Invalid byte number specified.\n");
 193                        err = ME_ERRNO_INVALID_CHANNEL;
 194                }
 195                break;
 196
 197        case ME_IO_SINGLE_NO_FLAGS:
 198        case ME_IO_SINGLE_TYPE_DIO_WORD:
 199                if (channel == 0) {
 200                        *value = instance->port_reg_mirror;
 201                } else {
 202                        PERROR("Invalid word number specified.\n");
 203                        err = ME_ERRNO_INVALID_CHANNEL;
 204                }
 205                break;
 206
 207        default:
 208                PERROR("Invalid flags specified.\n");
 209                err = ME_ERRNO_INVALID_FLAGS;
 210        }
 211        spin_unlock(&instance->subdevice_lock);
 212
 213        ME_SUBDEVICE_EXIT;
 214
 215        return err;
 216}
 217
 218static int me8100_do_io_single_write(me_subdevice_t * subdevice,
 219                                     struct file *filep,
 220                                     int channel,
 221                                     int value, int time_out, int flags)
 222{
 223        me8100_do_subdevice_t *instance;
 224        int err = ME_ERRNO_SUCCESS;
 225
 226        PDEBUG("executed.\n");
 227
 228        instance = (me8100_do_subdevice_t *) subdevice;
 229
 230        ME_SUBDEVICE_ENTER;
 231
 232        spin_lock(&instance->subdevice_lock);
 233        switch (flags) {
 234        case ME_IO_SINGLE_TYPE_DIO_BIT:
 235                if ((channel >= 0) && (channel < 16)) {
 236                        instance->port_reg_mirror =
 237                            value ? (instance->
 238                                     port_reg_mirror | (0x1 << channel))
 239                            : (instance->port_reg_mirror & ~(0x1 << channel));
 240                        outw(instance->port_reg_mirror, instance->port_reg);
 241                        PDEBUG_REG("port_reg outw(0x%lX+0x%lX)=0x%x\n",
 242                                   instance->reg_base,
 243                                   instance->port_reg - instance->reg_base,
 244                                   instance->port_reg_mirror);
 245                } else {
 246                        PERROR("Invalid bit number specified.\n");
 247                        err = ME_ERRNO_INVALID_CHANNEL;
 248                }
 249                break;
 250
 251        case ME_IO_SINGLE_TYPE_DIO_BYTE:
 252                if (channel == 0) {
 253                        instance->port_reg_mirror &= ~0xFF;
 254                        instance->port_reg_mirror |= value & 0xFF;
 255                        outw(instance->port_reg_mirror, instance->port_reg);
 256                        PDEBUG_REG("port_reg outw(0x%lX+0x%lX)=0x%x\n",
 257                                   instance->reg_base,
 258                                   instance->port_reg - instance->reg_base,
 259                                   instance->port_reg_mirror);
 260                } else if (channel == 1) {
 261                        instance->port_reg_mirror &= ~0xFF00;
 262                        instance->port_reg_mirror |= (value << 8) & 0xFF00;
 263                        outw(instance->port_reg_mirror, instance->port_reg);
 264                        PDEBUG_REG("port_reg outw(0x%lX+0x%lX)=0x%x\n",
 265                                   instance->reg_base,
 266                                   instance->port_reg - instance->reg_base,
 267                                   instance->port_reg_mirror);
 268                } else {
 269                        PERROR("Invalid byte number specified.\n");
 270                        err = ME_ERRNO_INVALID_CHANNEL;
 271                }
 272                break;
 273
 274        case ME_IO_SINGLE_NO_FLAGS:
 275        case ME_IO_SINGLE_TYPE_DIO_WORD:
 276                if (channel == 0) {
 277                        instance->port_reg_mirror = value;
 278                        outw(value, instance->port_reg);
 279                        PDEBUG_REG("port_reg outw(0x%lX+0x%lX)=0x%x\n",
 280                                   instance->reg_base,
 281                                   instance->port_reg - instance->reg_base,
 282                                   value);
 283                } else {
 284                        PERROR("Invalid byte number specified.\n");
 285                        err = ME_ERRNO_INVALID_CHANNEL;
 286                }
 287                break;
 288
 289        default:
 290                PERROR("Invalid flags specified.\n");
 291                err = ME_ERRNO_INVALID_FLAGS;
 292        }
 293        spin_unlock(&instance->subdevice_lock);
 294
 295        ME_SUBDEVICE_EXIT;
 296
 297        return err;
 298}
 299
 300static int me8100_do_query_number_channels(me_subdevice_t * subdevice,
 301                                           int *number)
 302{
 303        PDEBUG("executed.\n");
 304        *number = 16;
 305        return ME_ERRNO_SUCCESS;
 306}
 307
 308static int me8100_do_query_subdevice_type(me_subdevice_t * subdevice,
 309                                          int *type, int *subtype)
 310{
 311        PDEBUG("executed.\n");
 312        *type = ME_TYPE_DO;
 313        *subtype = ME_SUBTYPE_SINGLE;
 314        return ME_ERRNO_SUCCESS;
 315}
 316
 317static int me8100_do_query_subdevice_caps(me_subdevice_t * subdevice, int *caps)
 318{
 319        PDEBUG("executed.\n");
 320        *caps = ME_CAPS_DIO_SINK_SOURCE;
 321        return ME_ERRNO_SUCCESS;
 322}
 323
 324me8100_do_subdevice_t *me8100_do_constructor(uint32_t reg_base,
 325                                             unsigned int do_idx,
 326                                             spinlock_t * ctrl_reg_lock)
 327{
 328        me8100_do_subdevice_t *subdevice;
 329        int err;
 330
 331        PDEBUG("executed.\n");
 332
 333        /* Allocate memory for subdevice instance */
 334        subdevice = kmalloc(sizeof(me8100_do_subdevice_t), GFP_KERNEL);
 335
 336        if (!subdevice) {
 337                PERROR("Cannot get memory for subdevice instance.\n");
 338                return NULL;
 339        }
 340
 341        memset(subdevice, 0, sizeof(me8100_do_subdevice_t));
 342
 343        /* Initialize subdevice base class */
 344        err = me_subdevice_init(&subdevice->base);
 345
 346        if (err) {
 347                PERROR("Cannot initialize subdevice base class instance.\n");
 348                kfree(subdevice);
 349                return NULL;
 350        }
 351
 352        /* Initialize registers */
 353        if (do_idx == 0) {
 354                subdevice->port_reg = reg_base + ME8100_DO_REG_A;
 355                subdevice->ctrl_reg = reg_base + ME8100_CTRL_REG_A;
 356        } else if (do_idx == 1) {
 357                subdevice->port_reg = reg_base + ME8100_DO_REG_B;
 358                subdevice->ctrl_reg = reg_base + ME8100_CTRL_REG_B;
 359        } else {
 360                PERROR("Wrong subdevice idx=%d.\n", do_idx);
 361                kfree(subdevice);
 362                return NULL;
 363        }
 364#ifdef MEDEBUG_DEBUG_REG
 365        subdevice->reg_base = reg_base;
 366#endif
 367
 368        // Initialize spin locks.
 369        spin_lock_init(&subdevice->subdevice_lock);
 370        subdevice->ctrl_reg_lock = ctrl_reg_lock;
 371
 372        /* Save the subdevice index */
 373        subdevice->do_idx = do_idx;
 374
 375        /* Overload base class methods. */
 376        subdevice->base.me_subdevice_io_reset_subdevice =
 377            me8100_do_io_reset_subdevice;
 378        subdevice->base.me_subdevice_io_single_config =
 379            me8100_do_io_single_config;
 380        subdevice->base.me_subdevice_io_single_read = me8100_do_io_single_read;
 381        subdevice->base.me_subdevice_io_single_write =
 382            me8100_do_io_single_write;
 383        subdevice->base.me_subdevice_query_number_channels =
 384            me8100_do_query_number_channels;
 385        subdevice->base.me_subdevice_query_subdevice_type =
 386            me8100_do_query_subdevice_type;
 387        subdevice->base.me_subdevice_query_subdevice_caps =
 388            me8100_do_query_subdevice_caps;
 389
 390        return subdevice;
 391}
 392
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.