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